diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90
index 7407cf0ca3..094a105c20 100644
--- a/biogeochem/EDCanopyStructureMod.F90
+++ b/biogeochem/EDCanopyStructureMod.F90
@@ -33,7 +33,6 @@ module EDCanopyStructureMod
use FatesInterfaceTypesMod, only : bc_in_type
use FatesPlantHydraulicsMod, only : UpdateH2OVeg,InitHydrCohort, RecruitWaterStorage
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
@@ -41,7 +40,7 @@ module EDCanopyStructureMod
use PRTGenericMod, only : repro_organ
use PRTGenericMod, only : struct_organ
use PRTGenericMod, only : SetState
- use FatesRunningMeanMod, only : ema_lpa
+ use PRTGenericMod, only : carbon12_element
! 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
-
! 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
@@ -321,7 +319,7 @@ subroutine canopy_structure( currentSite , bc_in )
currentCohort => currentCohort%shorter
enddo
endif
-
+
currentPatch => currentPatch%younger
enddo !patch
@@ -629,11 +627,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
@@ -663,24 +661,26 @@ 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()
call InitPRTObject(copyc%prt)
- call InitPRTBoundaryConditions(copyc)
if( hlm_use_planthydro.eq.itrue ) then
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)
-
+ call InitPRTBoundaryConditions(copyc)
+
newarea = currentCohort%c_area - cc_loss
copyc%n = currentCohort%n*newarea/currentCohort%c_area
currentCohort%n = currentCohort%n - copyc%n
@@ -723,6 +723,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
! straight into the fragmenting pools
@@ -834,11 +840,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, &
@@ -1098,11 +1104,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
@@ -1121,11 +1127,17 @@ 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()
call InitPRTObject(copyc%prt)
- call InitPRTBoundaryConditions(copyc)
+
if( hlm_use_planthydro.eq.itrue ) then
call InitHydrCohort(CurrentSite,copyc)
@@ -1138,7 +1150,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)
+
newarea = currentCohort%c_area - cc_gain !new area of existing cohort
call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread, &
@@ -1327,13 +1340,11 @@ subroutine canopy_summarization( nsites, sites, bc_in )
do while(associated(currentCohort))
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
@@ -2168,7 +2179,7 @@ subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, total_canopy_area)
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
diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90
index 4b9dd3058c..70756393d8 100644
--- a/biogeochem/EDCohortDynamicsMod.F90
+++ b/biogeochem/EDCohortDynamicsMod.F90
@@ -19,7 +19,6 @@ Module EDCohortDynamicsMod
use FatesConstantsMod , only : fates_unset_r8
use FatesConstantsMod , only : nearzero
use FatesConstantsMod , only : calloc_abs_error
- use FatesRunningMeanMod , only : ema_lpa
use FatesInterfaceTypesMod , only : hlm_days_per_year
use FatesInterfaceTypesMod , only : nleafage
use SFParamsMod , only : SF_val_CWD_frac
@@ -76,7 +75,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
@@ -97,18 +95,22 @@ 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_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_l2fr
+ 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
+ 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, acnp_bc_in_id_cdamage
- use PRTAllometricCNPMod, only : acnp_bc_out_id_nneed
- use PRTAllometricCNPMod, only : acnp_bc_out_id_pneed
+ use PRTAllometricCNPMod, only : acnp_bc_out_id_pefflux, acnp_bc_out_id_limiter
+ use PRTAllometricCNPMod, only : acnp_bc_in_id_cdamage
use DamageMainMod, only : undamaged_class
- use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=)
+ use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=)
+ use shr_log_mod, only : errMsg => shr_log_errMsg
- ! CIME globals
- use shr_log_mod , only : errMsg => shr_log_errMsg
!
implicit none
private
@@ -214,8 +216,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
!**********************/
@@ -236,6 +237,22 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, &
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)
@@ -302,14 +319,14 @@ 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())
+ 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
@@ -393,8 +410,7 @@ subroutine InitPRTBoundaryConditions(new_cohort)
! value boundary condition.
type(ed_cohort_type), intent(inout), target :: new_cohort
-
-
+
select case(hlm_parteh_mode)
case (prt_carbon_allom_hyp)
@@ -413,21 +429,26 @@ 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_netdp, bc_rval = new_cohort%daily_p_uptake)
+
+ 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_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%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_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)
-
-
+ 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'
@@ -570,23 +591,27 @@ subroutine nan_cohort(cc_p)
! Fluxes from nutrient allocation
currentCohort%daily_nh4_uptake = nan
currentCohort%daily_no3_uptake = nan
- currentCohort%daily_p_uptake = nan
- 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
-
-
+ 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_def = nan ! Maintenance respiration deficit kgC/plant
+ 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
@@ -643,7 +668,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
@@ -688,20 +713,21 @@ 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
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
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
!-------------------------------------------------------------------------------------!
@@ -1047,10 +1073,6 @@ subroutine DeallocateCohort(currentCohort)
type(ed_cohort_type),intent(inout) :: currentCohort
- ! (Keeping as an example)
- ! Remove the running mean structure
- ! deallocate(currentCohort%tveg_lpa)
-
! At this point, nothing should be pointing to current Cohort
if (hlm_use_planthydro.eq.itrue) call DeallocateHydrCohort(currentCohort)
@@ -1106,7 +1128,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
@@ -1217,11 +1240,9 @@ 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)
+
+
! new cohort age is weighted mean of two cohorts
currentCohort%coage = &
(currentCohort%coage * (currentCohort%n/(currentCohort%n + nextc%n))) + &
@@ -1240,6 +1261,9 @@ 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%canopy_trim = (currentCohort%n*currentCohort%canopy_trim &
+ nextc%n*nextc%canopy_trim)/newn
@@ -1305,7 +1329,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in)
call ForceDBH( currentCohort%pft, currentCohort%crowndamage, &
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
!
@@ -1343,7 +1367,8 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in)
call ForceDBH( currentCohort%pft, currentCohort%crowndamage, &
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
!
call carea_allom(currentCohort%dbh,newn,currentSite%spread,currentCohort%pft,&
@@ -1425,11 +1450,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
@@ -1445,31 +1467,43 @@ 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_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 + &
- 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
-
- 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
-
+ ! 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
+
+ ! 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%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 + &
+ 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 + &
@@ -1828,16 +1862,20 @@ subroutine copy_cohort( currentCohort,copyc )
! 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
- ! (Keeping as an example)
! Copy over running means
- ! call n%tveg_lpa%CopyFromDonor(o%tveg_lpa)
+ 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
@@ -1857,14 +1895,17 @@ 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_p_uptake = o%daily_p_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_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
@@ -1875,7 +1916,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
@@ -1936,6 +1977,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
!-------------------------------------------------------------------------------------!
@@ -2004,7 +2048,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
@@ -2094,7 +2138,7 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite)
if( 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,icrowndamage,canopy_trim,sapw_area,target_sapw_c)
@@ -2127,7 +2171,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,icrowndamage, canopy_trim,target_leaf_c)
@@ -2225,7 +2269,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/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90
index 5a72811707..ab0b77b737 100644
--- a/biogeochem/EDLoggingMortalityMod.F90
+++ b/biogeochem/EDLoggingMortalityMod.F90
@@ -57,7 +57,7 @@ module EDLoggingMortalityMod
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
+ 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 2d2061bd17..388d021003 100644
--- a/biogeochem/EDMortalityFunctionsMod.F90
+++ b/biogeochem/EDMortalityFunctionsMod.F90
@@ -23,7 +23,7 @@ module EDMortalityFunctionsMod
use EDLoggingMortalityMod , only : LoggingMortality_frac
use EDParamsMod , only : fates_mortality_disturbance_fraction
- use PRTGenericMod, only : all_carbon_elements
+ use PRTGenericMod, only : carbon12_element
use PRTGenericMod, only : store_organ
use shr_log_mod , only : errMsg => shr_log_errMsg
@@ -167,7 +167,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%crowndamage,cohort_in%canopy_trim,target_leaf_c)
- 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(target_leaf_c, store_c, frac)
if( frac .lt. 1._r8) then
diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90
index 2abc2ee81c..dba1a67d13 100644
--- a/biogeochem/EDPatchDynamicsMod.F90
+++ b/biogeochem/EDPatchDynamicsMod.F90
@@ -72,7 +72,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
@@ -469,6 +468,7 @@ subroutine spawn_patches( currentSite, bc_in)
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
@@ -659,11 +659,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 current disturbance
@@ -3042,7 +3042,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 3ccccc58b3..5eacaf00aa 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 EDTypesMod , only : nclmax
use EDTypesMod , only : AREA,AREA_INV
use EDTypesMod , only : nlevleaf
use EDTypesMod , only : num_vegtemp_mem
@@ -96,7 +97,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
@@ -118,7 +118,7 @@ module EDPhysiologyMod
use SFParamsMod, only : SF_val_CWD_frac
use FatesParameterDerivedMod, only : param_derived
use FatesPlantHydraulicsMod, only : InitHydrCohort
-
+ use PRTInitParamsFatesMod, only : NewRecruitTotalStoichiometry
implicit none
private
@@ -135,7 +135,10 @@ module EDPhysiologyMod
public :: PreDisturbanceIntegrateLitter
public :: GenerateDamageAndLitterFluxes
public :: SeedIn
-
+ public :: UpdateRecruitL2FR
+ public :: UpdateRecruitStoicH
+ public :: SetRecruitL2FR
+
logical, parameter :: debug = .false. ! local debug flag
character(len=*), parameter, private :: sourcefile = &
__FILE__
@@ -642,7 +645,7 @@ subroutine trim_canopy( currentSite )
currentCohort%crowndamage, 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, &
@@ -670,7 +673,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
@@ -1622,7 +1625,7 @@ 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
@@ -1842,15 +1845,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, 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 = 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'
@@ -2037,7 +2041,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)
+ 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)
@@ -2046,7 +2051,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in )
! 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 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)
@@ -2766,5 +2771,152 @@ subroutine CWDOut( litt, fragmentation_scaler, nlev_eff_decomp )
enddo
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
+
+ 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
+
+ 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
+
+ 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)
+ end if
+ end do
+ end do
+
+ return
+ end subroutine UpdateRecruitL2FR
+
+ ! ======================================================================
+
+ 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
+
+ ! 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
+
+ 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
+
+ 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
+
+ return
+ end subroutine UpdateRecruitStoich
+ ! ======================================================================
+
+ subroutine SetRecruitL2FR(csite)
+
+
+ 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
+ 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/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90
index 43497b5b44..1a2b16283e 100644
--- a/biogeochem/FatesAllometryMod.F90
+++ b/biogeochem/FatesAllometryMod.F90
@@ -161,7 +161,7 @@ module FatesAllometryMod
! ============================================================================
subroutine CheckIntegratedAllometries(dbh,ipft,crowndamage, &
- canopy_trim, bl,bfr,bsap,bstore,bdead, &
+ canopy_trim,l2fr, bl,bfr,bsap,bstore,bdead, &
grow_leaf, grow_fr, grow_sap, grow_store, grow_dead, &
max_err, l_pass)
@@ -177,6 +177,7 @@ subroutine CheckIntegratedAllometries(dbh,ipft,crowndamage, &
integer,intent(in) :: ipft ! plant functional type index
integer,intent(in) :: crowndamage ! crowndamage [1: undamaged, >1 damaged]
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]
@@ -220,7 +221,7 @@ subroutine CheckIntegratedAllometries(dbh,ipft,crowndamage, &
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'
@@ -1015,18 +1016,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
@@ -1038,18 +1043,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 = dblmaxdd*l2fr
end if
case DEFAULT
@@ -1161,32 +1168,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 60af4e8f1a..ae01df7c93 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
@@ -38,7 +37,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
@@ -64,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
@@ -89,7 +86,7 @@ module FatesSoilBGCFluxMod
public :: PrepNutrientAquisitionBCs
public :: UnPackNutrientAquisitionBCs
public :: FluxIntoLitterPools
-
+ public :: EffluxIntoLitterPools
logical, parameter :: debug = .false. ! local debug flag
character(len=*), parameter, private :: sourcefile = &
@@ -98,72 +95,6 @@ module FatesSoilBGCFluxMod
contains
- ! =====================================================================================
-
- function GetPlantDemand(ccohort,element_id) result(plant_demand)
-
- ! -----------------------------------------------------------------------------------
- ! This function calculates the plant's demand for a given nutrient
- ! based upon the need to fill its NPP demand and/or the need to
- ! get its tissues to their ideal stoichiometry ratios.
- ! This routine is used for informing BGC competition schemes, and
- ! for generating synthetic upake rates and also for calculating
- ! diagnostics.
- !
- ! THIS ROUTINE IS UNDERGOING MODIFICATIONS WILL CLEAN UP AFTER
- ! A DECENT FIRST HYPOTHESIS MANIFESTS
- ! -----------------------------------------------------------------------------------
-
-
- type(ed_cohort_type),intent(in) :: ccohort
- integer,intent(in) :: element_id ! Should match nitrogen_element or
- ! phosphorus_element
-
- real(r8) :: plant_demand ! Nutrient demand per plant [kg]
- real(r8) :: plant_x ! Total mass for element of interest [kg]
- 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), parameter :: smth_fac = 0.1_r8 ! Smoothing factor for updating
- ! demand.
- real(r8), parameter :: init_demand_frac = 0.1_r8 ! Newly recruited plants
- ! will specify a demand
- ! based on their total nutrient
- ! because they have not history
- ! of need yet
-
-
-
- pft = ccohort%pft
- dbh = ccohort%dbh
-
-
- ! If the cohort has not experienced a day of integration
- ! (and thus any allocation yet), it has no deficit
- ! in its storage to drive any need, so it thus has no demand
- if(ccohort%isnew) then
- plant_demand = 0._r8
- return
- end if
-
-
- ! 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)
-
- 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)
-
- end if
-
- end function GetPlantDemand
! =====================================================================================
@@ -198,27 +129,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
select case (hlm_parteh_mode)
case (prt_carbon_allom_hyp)
@@ -237,24 +150,45 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in)
! then we are not coupling with the soil bgc model.
! In this case, the bc_in structure is meaningless.
! Instead, we give the plants a parameterized fraction
- ! of their demand. Routine GetPlantDemand() returns
- ! the plant demand.
+ ! of their 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
+ fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element)
+ ccohort%daily_n_demand = fnrt_c * &
+ (EDPftvarcon_inst%vmax_nh4(pft)+EDPftvarcon_inst%vmax_no3(pft)) * sec_per_day
+ ccohort%daily_nh4_uptake = fnrt_c*EDPftvarcon_inst%vmax_nh4(pft)*EDPftvarcon_inst%prescribed_nuptake(pft)* sec_per_day
+ ccohort%daily_no3_uptake = fnrt_c*EDPftvarcon_inst%vmax_no3(pft)*EDPftvarcon_inst%prescribed_nuptake(pft)* sec_per_day
+ ccohort => ccohort%shorter
+ end do
+ cpatch => cpatch%younger
+ end do
- 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
-
+ 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
+ pft = ccohort%pft
+ fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element)
+ ccohort%daily_n_demand = fnrt_c * &
+ (EDPftvarcon_inst%vmax_nh4(pft)+EDPftvarcon_inst%vmax_no3(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
@@ -263,151 +197,34 @@ 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
-
+ fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element)
+ ccohort%daily_p_demand = fnrt_c * EDPftvarcon_inst%vmax_p(pft) * sec_per_day
+ ccohort%daily_p_gain = fnrt_c * EDPftvarcon_inst%vmax_p(pft) * sec_per_day * EDPftvarcon_inst%prescribed_nuptake(pft)
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
+ pft = ccohort%pft
+ fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element)
+ ccohort%daily_p_demand = fnrt_c * EDPftvarcon_inst%vmax_p(pft) * sec_per_day
+ ! P Uptake: Convert g/m2/day -> kg/plant/day
+ ccohort%daily_p_gain = 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
@@ -438,6 +255,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]
@@ -448,8 +266,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
@@ -459,6 +279,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
@@ -554,6 +375,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
@@ -561,6 +384,17 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out)
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
end subroutine PrepCH4BCs
@@ -572,8 +406,7 @@ subroutine PrepNutrientAquisitionBCs(csite, bc_in, bc_out)
! This subroutine will generate the appropriate boundary condition output
! structures, depending on:
! 1) Which soil-bgc competition method is active in the HLM
- ! 2) If nitrification/denitrification is turned on
- ! 3) Which competitor scaling type is used
+ ! 2) Which competitor scaling type is used
! -----------------------------------------------------------------------------------
! !ARGUMENTS
@@ -582,307 +415,175 @@ 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 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
-
+
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))
+ 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
- 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) = bc_out%cn_scalar(icomp) + &
- ECACScalar(ccohort, nitrogen_element)
-
- ccohort => ccohort%shorter
- end do
- cpatch => cpatch%younger
- end do
+ subroutine EffluxIntoLitterPools(csite, cpatch, ccohort, bc_in )
- ! 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
+ ! -----------------------------------------------------------------------------------
+ ! 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.
+ ! -----------------------------------------------------------------------------------
- else
+ ! 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
- ! 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
+ ! 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
- 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))
+ select case (element_list(el))
+ case (carbon12_element)
- 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) = bc_out%cp_scalar(icomp) + &
- ECACScalar(ccohort, phosphorus_element)
-
- ccohort => ccohort%shorter
- end do
- cpatch => cpatch%younger
- end do
+ efflux_ptr => ccohort%daily_c_efflux
- 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
+ case (nitrogen_element)
- ! 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
+ efflux_ptr => ccohort%daily_n_efflux
- end if coupled_p_if
-
- elseif(trim(hlm_nu_com).eq.'RD') then
+ case (phosphorus_element)
- ! 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
+ efflux_ptr => ccohort%daily_p_efflux
- 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
+ end select
- 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
+ litt => cpatch%litter(el)
- end if
-
-
- return
- end subroutine PrepNutrientAquisitionBCs
+ 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)
@@ -914,7 +615,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 FatesConstantsMod, only : itrue
@@ -936,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
@@ -1013,21 +711,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
@@ -1035,19 +731,8 @@ 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))
@@ -1118,9 +803,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
@@ -1217,7 +900,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
@@ -1246,103 +929,5 @@ 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 = 25.0_r8 ! logistic function k
- real(r8), parameter :: store_x0 = 1.0_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 :: 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%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
- ! 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/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 4b8d34f664..d313ac9ce2 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
@@ -42,7 +43,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
@@ -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
@@ -227,7 +227,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
@@ -243,6 +243,10 @@ 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) :: 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
real(r8) :: agb_frac ! fraction of biomass aboveground
@@ -280,6 +284,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime)
! (gC/gN/s)
! ------------------------------------------------------------------------
+
! -----------------------------------------------------------------------------------
! Photosynthesis and stomatal conductance parameters, from:
! Bonan et al (2011) JGR, 116, doi:10.1029/2010JG001593
@@ -356,6 +361,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
@@ -410,16 +416,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
@@ -434,7 +440,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
@@ -506,7 +512,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 )
@@ -591,8 +597,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
@@ -641,7 +648,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
! ------------------------------------------------------------------
@@ -656,9 +663,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)
if (hlm_use_tree_damage .eq. itrue) then
@@ -755,12 +761,29 @@ 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
+ 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
+
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
+
+ ! calculate the cost of carbon for N fixation in each soil layer and calculate N fixation rate based on that [kgC / kgN]
+
+ call RootLayerNFixation(bc_in(s)%t_soisno_sl(j),ft,dtime,fnrt_mr_layer,fnrt_mr_nfix_layer,nfix_layer)
+
+ currentCohort%froot_mr = currentCohort%froot_mr + fnrt_mr_nfix_layer + fnrt_mr_layer
+
+ currentCohort%sym_nfix_tstep = currentCohort%sym_nfix_tstep + nfix_layer
+
+
enddo
! Coarse Root MR (kgC/plant/s) (below ground sapwood)
@@ -913,6 +936,64 @@ 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)
+
+
+ ! -------------------------------------------------------------------------------
+ ! Symbiotic N Fixation is handled via Houlton et al 2008 and Fisher et al. 2010
+ !
+ ! A unifying framework for dinitrogen fixation in the terrestrial biosphere
+ ! Benjamin Z. Houlton, Ying-Ping Wang, Peter M. Vitousek & Christopher B. Field
+ ! Nature volume 454, pages327–330 (2008) https://doi.org/10.1038/nature07028
+ !
+ ! Carbon cost of plant nitrogen acquisition: A mechanistic, globally applicable model
+ ! of plant nitrogen uptake, retranslocation, and fixation. J. B. Fisher,S. Sitch,Y.
+ ! Malhi,R. A. Fisher,C. Huntingford,S.-Y. Tan. Global Biogeochemical Cycles. March
+ ! 2010 https://doi.org/10.1029/2009GB003621
+ !
+ ! ------------------------------------------------------------------------------
+
+
+ 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
+
+ return
+end subroutine RootLayerNFixation
+
+
! =======================================================================================
subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in
@@ -1494,14 +1575,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.
@@ -1599,7 +1680,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)
@@ -1626,7 +1707,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:
@@ -1658,7 +1738,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:
@@ -1972,9 +2051,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)
@@ -2042,7 +2118,6 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, &
! ---------------------------------------------------------------------------------
use EDPftvarcon , only : EDPftvarcon_inst
- use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm
! Arguments
! ------------------------------------------------------------------------------
@@ -2125,7 +2200,7 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, &
vcmax = vcmax * btran
return
-end subroutine LeafLayerBiophysicalRates
+ end subroutine LeafLayerBiophysicalRates
subroutine lowstorage_maintresp_reduction(frac, pft, maintresp_reduction_factor)
@@ -2158,7 +2233,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/fire/SFMainMod.F90 b/fire/SFMainMod.F90
index 362593b32b..fdb3501bd2 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
@@ -196,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, all_carbon_elements) + &
- currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + &
- currentCohort%prt%GetState(struct_organ, all_carbon_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
@@ -869,9 +868,9 @@ subroutine crown_scorching ( currentSite )
do while(associated(currentCohort))
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)
- 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 b8697ed6c7..404e08b2ba 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
@@ -177,6 +177,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))
@@ -186,9 +190,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_need_scpf(nlevsclass*numpft))
end do
! Initialize the static soil
@@ -384,6 +385,14 @@ 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
+
+ ! 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
@@ -477,9 +486,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
@@ -807,6 +813,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(pft)
! Assume no damage to begin with - since we assume no damage
! we do not need to initialise branch frac just yet.
@@ -840,7 +847,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%crowndamage, &
diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90
index 681645a71b..025969b07a 100644
--- a/main/EDMainMod.F90
+++ b/main/EDMainMod.F90
@@ -50,8 +50,12 @@ 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 EDPhysiologyMod , only : GenerateDamageAndLitterFluxes
use FatesSoilBGCFluxMod , only : FluxIntoLitterPools
+ use FatesSoilBGCFluxMod , only : EffluxIntoLitterPools
use EDCohortDynamicsMod , only : UpdateCohortBioPhysRates
use FatesSoilBGCFluxMod , only : PrepNutrientAquisitionBCs
use FatesSoilBGCFluxMod , only : PrepCH4BCs
@@ -90,7 +94,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
@@ -100,8 +103,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
@@ -115,6 +116,7 @@ module EDMainMod
! !PUBLIC MEMBER FUNCTIONS:
public :: ed_ecosystem_dynamics
public :: ed_update_site
+
!
! !PRIVATE MEMBER FUNCTIONS:
@@ -150,7 +152,7 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out)
type(ed_patch_type), pointer :: currentPatch
integer :: el ! Loop counter for variables
integer :: do_patch_dynamics ! for some modes, we turn off patch dynamics
-
+
!-----------------------------------------------------------------------
if (debug .and.( hlm_masterproc==itrue)) write(fates_log(),'(A,I4,A,I2.2,A,I2.2)') 'FATES Dynamics: ',&
@@ -167,6 +169,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
@@ -321,7 +325,6 @@ 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 PRTGenericMod , only : all_carbon_elements
use EDCohortDynamicsMod , only : zero_cohort, copy_cohort, insert_cohort
use EDCohortDynamicsMod , only : DeallocateCohort
use FatesPlantHydraulicsMod, only : InitHydrCohort
@@ -362,7 +365,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) :: 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
@@ -372,7 +375,6 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out )
real(r8) :: n_old
real(r8) :: n_recover
- integer :: nleafage
real(r8) :: sapw_c
real(r8) :: leaf_c
real(r8) :: fnrt_c
@@ -401,19 +403,22 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out )
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
site_cmass => currentSite%mass_balance(element_pos(carbon12_element))
- currentPatch => currentSite%youngest_patch
+ ! 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%oldest_patch
do while(associated(currentPatch))
-
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
@@ -506,7 +511,6 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out )
call PRTMaintTurnover(currentCohort%prt,ft,is_drought)
-
! -----------------------------------------------------------------------------------
! Call the routine that advances leaves in age.
! This will move a portion of the leaf mass in each
@@ -514,7 +518,17 @@ 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)
-
+
+ ! 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%sym_nfix_daily
+
+ currentCohort%resp_excess = 0._r8
+
end if if_not_newlyrecovered
! If the current diameter of a plant is somehow less than what is consistent
@@ -525,11 +539,11 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out )
! 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)
! -----------------------------------------------------------------------------
+
! We split the allocation into phases (currently for all hypotheses)
! In phase 1, allocation, we address prioritized allocation that should
@@ -565,93 +579,35 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out )
! 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
+ ! -----------------------------------------------------------------------------
+
+ call EffluxIntoLitterPools(currentSite, currentPatch, currentCohort, bc_in )
+ 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_nh4_uptake+currentCohort%daily_no3_uptake- &
- currentCohort%daily_n_efflux)*currentCohort%n
-
+ (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
-
- ! 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_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(phosphorus_element))%nutrient_need_scpf(iscpf) = &
- currentSite%flux_diags(element_pos(phosphorus_element))%nutrient_need_scpf(iscpf) + &
- currentCohort%daily_p_need*currentCohort%n
-
+ (currentCohort%daily_p_gain-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 = &
+ currentSite%mass_balance(element_pos(carbon12_element))%net_root_uptake - &
+ currentCohort%daily_c_efflux*currentCohort%n
+
! 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)
@@ -702,11 +658,26 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out )
currentCohort => currentCohort%taller
end do
- currentPatch => currentPatch%older
+ currentPatch => currentPatch%younger
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)
+ ! -----------------------------------------------------------------------------
+ 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.
+
+ ! the water balance.
if( hlm_use_planthydro == itrue ) then
currentPatch => currentSite%youngest_patch
@@ -760,6 +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%sym_nfix_daily = 0._r8
currentCohort => currentCohort%taller
enddo
currentPatch => currentPatch%older
@@ -802,6 +774,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
@@ -987,14 +962,15 @@ 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%sym_nfix_daily*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/EDPftvarcon.F90 b/main/EDPftvarcon.F90
index 05a20ec59d..b3ec36ecc7 100644
--- a/main/EDPftvarcon.F90
+++ b/main/EDPftvarcon.F90
@@ -142,10 +142,21 @@ 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 NH4 uptake [gN/gC/s]
+ real(r8), allocatable :: vmax_no3(:) ! maximum production rate for plant NO3 uptake [gN/gC/s]
+ ! For ECA: these rates will be applied separately to
+ ! draw from mineralized nh4 and no3 pools independantly.
+ ! For RD: these rates will be added, to construct a total
+ ! N demand, which will be applied to NH4 and then NO3
+ ! sequentially
+ real(r8), allocatable :: vmax_p(:) ! maximum production rate for plant p uptake [gP/gC/s]
+
+
+
+
! 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,
@@ -153,13 +164,13 @@ 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]
- real(r8), allocatable :: eca_vmax_p(:) ! maximum production rate for plant p uptake [gP/gC/s]
+
real(r8), allocatable :: eca_km_ptase(:) ! half-saturation constant for biochemical P production [gP/m3]
real(r8), allocatable :: eca_vmax_ptase(:) ! maximum production rate for biochemical P prod [gP/gC/s]
real(r8), allocatable :: eca_alpha_ptase(:) ! Fraction of min P generated from ptase activity
@@ -168,9 +179,6 @@ 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
-
-
! Turnover related things
real(r8), allocatable :: phenflush_fraction(:) ! Maximum fraction of storage carbon used to flush leaves
@@ -596,7 +604,6 @@ subroutine Register_PFT(this, fates_params)
! Nutrient competition parameters
-
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)
@@ -605,7 +612,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)
@@ -613,7 +620,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_no3'
+ name = 'fates_cnp_vmax_no3'
call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, &
dimension_names=dim_names, lower_bounds=dim_lower_bound)
@@ -972,18 +979,18 @@ 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, &
data=this%eca_km_no3)
- name = 'fates_cnp_eca_vmax_no3'
+ name = 'fates_cnp_vmax_no3'
call fates_params%RetrieveParameterAllocate(name=name, &
- data=this%eca_vmax_no3)
+ data=this%vmax_no3)
name = 'fates_cnp_eca_km_p'
call fates_params%RetrieveParameterAllocate(name=name, &
@@ -991,7 +998,7 @@ subroutine Receive_PFT(this, fates_params)
name = 'fates_cnp_vmax_p'
call fates_params%RetrieveParameterAllocate(name=name, &
- data=this%eca_vmax_p)
+ data=this%vmax_p)
name = 'fates_cnp_eca_km_ptase'
call fates_params%RetrieveParameterAllocate(name=name, &
@@ -1069,8 +1076,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
!-----------------------------------------------------------------------
@@ -1551,6 +1556,7 @@ subroutine FatesCheckParams(is_master)
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
@@ -1609,9 +1615,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
@@ -1641,13 +1644,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/EDTypesMod.F90 b/main/EDTypesMod.F90
index b68e6ce5e6..4f198d6708 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
@@ -186,6 +186,7 @@ module EDTypesMod
integer, public :: n_uptake_mode
integer, public :: p_uptake_mode
+
!************************************
!** COHORT type structure **
!************************************
@@ -203,6 +204,18 @@ module EDTypesMod
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)
@@ -272,29 +285,35 @@ 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 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) :: daily_p_uptake ! integrated daily uptake of mineralized P through competitive acquisition in soil [kg P / 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_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]
-
+ 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]
- ! 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]
-
! 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
@@ -320,10 +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_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
@@ -369,6 +385,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
@@ -420,8 +439,10 @@ 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
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
@@ -520,10 +541,15 @@ 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:-
+
+
+ ! 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
@@ -606,10 +632,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_need_scpf(:)
contains
@@ -642,7 +664,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
@@ -703,6 +726,16 @@ module EDTypesMod
! Total area of patches in each age bin [m2]
real(r8), allocatable :: area_by_age(:)
+ ! 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
real(r8), allocatable :: sp_tsai(:) ! target TSAI per FATES pft
@@ -860,9 +893,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)
@@ -872,9 +929,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_need_scpf(:) = 0._r8
return
end subroutine ZeroFluxDiags
@@ -1060,13 +1114,13 @@ subroutine dump_cohort(ccohort)
write(fates_log(),*) 'co%hite = ', ccohort%hite
write(fates_log(),*) 'co%crowndamage = ', ccohort%crowndamage
write(fates_log(),*) 'co%coage = ', ccohort%coage
-
- 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(),*) '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
@@ -1091,7 +1145,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/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90
index 0ec836fe0f..ee3bd6cfb3 100644
--- a/main/FatesConstantsMod.F90
+++ b/main/FatesConstantsMod.F90
@@ -46,16 +46,9 @@ module FatesConstantsMod
integer, public, parameter :: prescribed_n_uptake = 1
integer, public, parameter :: coupled_n_uptake = 2
+ integer, public, parameter :: coupled_np_comp_scaling = 1 ! This flag signals that at least 1 chemical element (ie N or P)
- 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 :: 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.
@@ -63,8 +56,8 @@ 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 = 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/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90
index 7c7be86182..db90a49650 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
@@ -52,7 +53,9 @@ module FatesHistoryInterfaceMod
use FatesInterfaceTypesMod , only : nlevcoage
use FatesInterfaceTypesMod , only : hlm_use_nocomp
use FatesAllometryMod , only : CrownDepth
-
+ use FatesAllometryMod , only : bstore_allom
+ use FatesAllometryMod , only : set_root_fraction
+
use EDPftvarcon , only : EDPftvarcon_inst
use PRTParametersMod , only : prt_params
@@ -64,11 +67,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,mol_per_umol
@@ -78,11 +83,12 @@ 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
-
+ use PRTAllometricCNPMod , only : stoich_max,stoich_growth_min
+ use FatesSizeAgeTypeIndicesMod, only : get_layersizetype_class_index
+
implicit none
private ! By default everything is private
@@ -161,56 +167,88 @@ module FatesHistoryInterfaceMod
! Indices to 1D Patch variables
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
+ integer :: ih_fnrtc_sl
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_storentfrac_si
integer :: ih_leafn_si
integer :: ih_sapwn_si
integer :: ih_fnrtn_si
integer :: ih_repron_si
integer :: ih_totvegn_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_storeptfrac_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
- integer,public :: ih_nh4uptake_si
- integer,public :: ih_no3uptake_si
- integer,public :: ih_puptake_si
- integer :: ih_cefflux_si
+ ! These are active if hlm_parteh_mode = prt_cnp_flex_allom_hyp
+ integer :: ih_l2fr_si
+ integer :: ih_l2fr_clscpf
+ integer :: ih_recl2fr_canopy_pf
+ integer :: ih_recl2fr_ustory_pf
+ 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_nefflux_si
integer :: ih_pefflux_si
- integer :: ih_nneed_si
- integer :: ih_pneed_si
-
+ integer :: ih_nefflux_scpf
+ integer :: ih_pefflux_scpf
+ integer :: ih_ndemand_si
+ 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
integer :: ih_area_trees_si
-
+ integer :: ih_litter_in_elem
+ integer :: ih_litter_out_elem
+ integer :: ih_seed_bank_elem
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
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
@@ -220,6 +258,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
@@ -232,41 +271,12 @@ module FatesHistoryInterfaceMod
integer :: ih_lai_canopy_si_scpf
integer :: ih_lai_understory_si_scpf
-
-
- integer :: ih_totvegn_scpf
- integer :: ih_leafn_scpf
- integer :: ih_fnrtn_scpf
- integer :: ih_storen_scpf
- 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_nneed_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_canopy_scpf
- integer :: ih_storeptfrac_understory_scpf
- integer :: ih_sapwp_scpf
- integer,public :: ih_puptake_scpf
- integer :: ih_pefflux_scpf
- integer :: ih_pneed_scpf
-
integer :: ih_bdead_si
integer :: ih_balive_si
integer :: ih_agb_si
@@ -275,6 +285,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
@@ -392,7 +403,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_m3_mortality_canopy_si_scpf
@@ -717,7 +727,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
@@ -729,7 +739,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
@@ -758,7 +769,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
@@ -785,7 +797,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
@@ -793,6 +806,7 @@ module FatesHistoryInterfaceMod
procedure, public :: flush_hvars
procedure, public :: zero_site_hvars
+
end type fates_history_interface_type
@@ -820,9 +834,9 @@ 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
use FatesIODimensionsMod, only : levcdpf, levcdsc, levcdam
-
+
implicit none
class(fates_history_interface_type), intent(inout) :: this
@@ -956,6 +970,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
! ======================================================================
@@ -1072,9 +1091,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
@@ -1089,7 +1108,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
use FatesIOVariableKindMod, only : site_cdpf_r8, site_cdsc_r8, site_cdam_r8
implicit none
@@ -1172,7 +1191,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
! ===================================================================================
@@ -1569,6 +1590,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
! ======================================================================================
@@ -1587,7 +1622,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
@@ -1716,7 +1751,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
use FatesIOVariableKindMod, only : site_cdpf_r8, site_cdsc_r8, site_cdam_r8
implicit none
@@ -1827,17 +1862,207 @@ 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)
+
+ ! 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), 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_si
+ real(r8) :: fnrtc_si
+ real(r8) :: fnrt_c
+
+ associate( &
+ !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_si = 0._r8
+ fnrtc_si = 0._r8
+
+ ! history site index
+ io_si = csite%h_gid
+
+ cpatch => csite%youngest_patch
+ do while(associated(cpatch))
+
+ ccohort => cpatch%shortest
+ do while(associated(ccohort))
+
+ ! If this is a new cohort, do not make diagnostics
+ 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)
+
+ ! unit conversion factor to get x/plant/day -> x/m2/sec
+ uconv = ccohort%n * ha_per_m2 * days_per_sec
+
+
+ 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_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
+ fnrtc_si = fnrtc_si + ccohort%n*fnrt_c
+
+ ! 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
+
+ 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%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%sym_nfix_daily*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_gain*uconv
+
+ fates_hist%hvars(ih_puptake_si)%r81d(io_si) = &
+ fates_hist%hvars(ih_puptake_si)%r81d(io_si) + &
+ ccohort%daily_p_gain*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(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
+
+ return
+ end subroutine update_history_nutrflux
! ====================================================================================
- 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
@@ -1859,6 +2084,7 @@ subroutine update_history_dyn(this,nc,nsites,sites)
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 FatesInterfaceTypesMod , only : nlevdamage
@@ -1868,7 +2094,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_in_type) , intent(in) :: bc_in(nsites)
+
! Locals
type(litter_type), pointer :: litt_c ! Pointer to the carbon12 litter pool
type(litter_type), pointer :: litt ! Generic pointer to any litter pool
@@ -1935,6 +2162,15 @@ subroutine update_history_dyn(this,nc,nsites,sites)
real(r8) :: area_frac
real(r8) :: crown_depth
+ 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)
+ real(r8) :: storec_canopy_scpf(numpft*nlevsclass)
+ real(r8) :: storec_understory_scpf(numpft*nlevsclass)
+
+ integer :: return_code
+
type(ed_patch_type),pointer :: cpatch
type(ed_cohort_type),pointer :: ccohort
@@ -2201,6 +2437,9 @@ 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
! ---------------------------------------------------------------------------------
@@ -2209,6 +2448,14 @@ subroutine update_history_dyn(this,nc,nsites,sites)
io_si = sites(s)%h_gid
+ ! These are weighting factors
+ storen_canopy_scpf(:) = 0._r8
+ 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
+
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, &
@@ -2477,6 +2724,9 @@ 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
+ 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
@@ -2491,10 +2741,13 @@ subroutine update_history_dyn(this,nc,nsites,sites)
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) = &
this%hvars(ih_storec_si)%r81d(io_si) + ccohort%n * &
@@ -2515,6 +2768,20 @@ subroutine update_history_dyn(this,nc,nsites,sites)
this%hvars(ih_totvegc_si)%r81d(io_si)+ ccohort%n * &
total_m / m2_per_ha
+
+ 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
+
+ ! Determine the root carbon biomass in kg/m3
+ ! [kg/m3] = [kg/plant] * [plant/ha] / [m3/ha] * [fraction] / [m]
+
+
+ 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
+
hio_bdead_si(io_si) = hio_bdead_si(io_si) + n_perm2 * struct_m
hio_balive_si(io_si) = hio_balive_si(io_si) + n_perm2 * alive_m
@@ -2545,9 +2812,24 @@ subroutine update_history_dyn(this,nc,nsites,sites)
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)
+ 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 * &
@@ -2571,9 +2853,23 @@ subroutine update_history_dyn(this,nc,nsites,sites)
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)
+ 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 * &
@@ -2597,6 +2893,21 @@ subroutine update_history_dyn(this,nc,nsites,sites)
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
@@ -3248,7 +3559,8 @@ subroutine update_history_dyn(this,nc,nsites,sites)
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
+ ! 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. nearzero) then
hio_lai_si_age(io_si, ipa2) = hio_lai_si_age(io_si, ipa2) / (hio_area_si_age(io_si, ipa2)*AREA)
@@ -3481,12 +3793,14 @@ subroutine update_history_dyn(this,nc,nsites,sites)
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(:,:)) + &
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)
@@ -3539,14 +3853,6 @@ subroutine update_history_dyn(this,nc,nsites,sites)
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
this%hvars(ih_totvegn_scpf)%r82d(io_si,:) = 0._r8
@@ -3554,52 +3860,17 @@ subroutine update_history_dyn(this,nc,nsites,sites)
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,:) = &
- sites(s)%flux_diags(el)%nutrient_efflux_scpf(:) / &
- m2_per_ha / sec_per_day
-
- this%hvars(ih_nneed_scpf)%r82d(io_si,:) = &
- sites(s)%flux_diags(el)%nutrient_need_scpf(:) / &
- m2_per_ha / sec_per_day
-
- this%hvars(ih_nneed_si)%r81d(io_si) = &
- sum(sites(s)%flux_diags(el)%nutrient_need_scpf(:),dim=1) / &
- 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
-
-
+
elseif(element_list(el).eq.phosphorus_element)then
this%hvars(ih_totvegp_scpf)%r82d(io_si,:) = 0._r8
this%hvars(ih_leafp_scpf)%r82d(io_si,:) = 0._r8
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_pefflux_scpf)%r82d(io_si,:) = &
- sites(s)%flux_diags(el)%nutrient_efflux_scpf(:) / &
- m2_per_ha / sec_per_day
-
- this%hvars(ih_pneed_scpf)%r82d(io_si,:) = &
- sites(s)%flux_diags(el)%nutrient_need_scpf(:) / &
- m2_per_ha / sec_per_day
-
- this%hvars(ih_pneed_si)%r81d(io_si) = &
- sum(sites(s)%flux_diags(el)%nutrient_need_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
@@ -3692,7 +3963,7 @@ subroutine update_history_dyn(this,nc,nsites,sites)
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)
+ 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) + &
@@ -3713,17 +3984,9 @@ subroutine update_history_dyn(this,nc,nsites,sites)
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)
+ 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) + &
@@ -3744,14 +4007,6 @@ subroutine update_history_dyn(this,nc,nsites,sites)
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
@@ -3762,9 +4017,34 @@ subroutine update_history_dyn(this,nc,nsites,sites)
end do ! end element loop
- ! Normalize nutrient 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
+
+ do i_pft = 1, numpft
+ do i_scls = 1,nlevsclass
+ i_scpf = (i_pft-1)*nlevsclass + i_scls
+
+ 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
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) / &
@@ -3774,16 +4054,15 @@ subroutine update_history_dyn(this,nc,nsites,sites)
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
@@ -3797,16 +4076,15 @@ subroutine update_history_dyn(this,nc,nsites,sites)
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
@@ -4733,7 +5011,7 @@ subroutine define_history_vars(this, initialize_variables)
use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_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_elem_r8, site_elpft_r8, site_clscpf_r8
use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8
@@ -4773,10 +5051,10 @@ 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 (NOT ACTIVE)
! 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='', &
long='total number of patches per site', use_default='active', &
@@ -4790,13 +5068,16 @@ 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_AREA_PLANTS', units='m2 m-2', &
long='area occupied by all plants per m2 land area', use_default='active', &
avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, &
@@ -5215,7 +5496,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 (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)
@@ -5239,7 +5520,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 (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)
@@ -5283,6 +5564,24 @@ 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_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_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_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 )
+
+
+
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', &
@@ -5307,26 +5606,118 @@ subroutine define_history_vars(this, initialize_variables)
upfreq=1, ivar=ivar, initialize=initialize_variables, &
index = ih_fnrtc_si)
+ 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_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', &
long='total biomass in live plant reproductive tissues in kg carbon per m2', &
use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', &
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=1, 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_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_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_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)
- 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', &
- 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_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_STOREN_TF', units='1', &
+ 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_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, &
+ 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_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, &
+ 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', &
+ 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', &
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)
@@ -5358,29 +5749,56 @@ 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=1, 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=1, 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=1, 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_NNEED', 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, &
- index = ih_nneed_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_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_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_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, &
+ 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
@@ -5429,20 +5847,90 @@ 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_PNEED', units='kg m-2 s-1', &
+ 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, &
- index = ih_pneed_si)
+ 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
@@ -5602,6 +6090,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', &
@@ -7174,171 +7668,6 @@ 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=1, 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_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_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, &
- 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=1, 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, &
- 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, &
- initialize=initialize_variables, index = ih_nefflux_scpf)
-
- call this%set_history_var(vname='FATES_NNEED_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, &
- initialize=initialize_variables, index = ih_nneed_scpf)
-
- 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=1, 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, &
- initialize=initialize_variables, index = ih_pefflux_scpf)
-
- call this%set_history_var(vname='FATES_PNEED_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, &
- initialize=initialize_variables, index = ih_pneed_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', &
diff --git a/main/FatesHistoryVariableType.F90 b/main/FatesHistoryVariableType.F90
index c30d6882e2..5902496a2c 100644
--- a/main/FatesHistoryVariableType.F90
+++ b/main/FatesHistoryVariableType.F90
@@ -15,9 +15,10 @@ module FatesHistoryVariableType
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
+ use FatesIOVariableKindMod, only : iotype_index, site_agefuel_r8, site_clscpf_r8
use shr_log_mod , only : errMsg => shr_log_errMsg
+
implicit none
private ! By default everything is private
@@ -207,6 +208,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),' ?'
@@ -331,6 +336,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'
call endrun(msg=errMsg(sourcefile, __LINE__))
diff --git a/main/FatesIODimensionsMod.F90 b/main/FatesIODimensionsMod.F90
index 97ff3ec49d..92488d00a9 100644
--- a/main/FatesIODimensionsMod.F90
+++ b/main/FatesIODimensionsMod.F90
@@ -26,6 +26,7 @@ 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 :: levclscpf = 'fates_levclscpf'
character(*), parameter, public :: levcdsc = 'fates_levcdsc' ! matches histFileMod
character(*), parameter, public :: levcdpf = 'fates_levcdpf' ! matches histFileMod
character(*), parameter, public :: levcdam = 'fates_levcdam' ! matches histFileMod
@@ -99,6 +100,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
@@ -166,6 +169,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 853122730e..84dd8e692f 100644
--- a/main/FatesIOVariableKindMod.F90
+++ b/main/FatesIOVariableKindMod.F90
@@ -40,7 +40,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/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90
index ccdaf7c86a..c322fc5a6a 100644
--- a/main/FatesInterfaceMod.F90
+++ b/main/FatesInterfaceMod.F90
@@ -63,8 +63,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
@@ -84,10 +84,10 @@ 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
-
! CIME Globals
use shr_log_mod , only : errMsg => shr_log_errMsg
@@ -202,13 +202,13 @@ 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%vmax_no3(numpft))
+ allocate(bc_pconst%vmax_p(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))
- allocate(bc_pconst%eca_vmax_p(numpft))
allocate(bc_pconst%eca_km_ptase(numpft))
allocate(bc_pconst%eca_vmax_ptase(numpft))
allocate(bc_pconst%eca_alpha_ptase(numpft))
@@ -226,24 +226,18 @@ 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%vmax_no3(1:numpft) = EDPftvarcon_inst%vmax_no3(1:numpft)
+ bc_pconst%vmax_p(1:numpft) = EDPftvarcon_inst%vmax_p(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)
- bc_pconst%eca_vmax_p(1:numpft) = EDPftvarcon_inst%eca_vmax_p(1:numpft)
bc_pconst%eca_km_ptase(1:numpft) = EDPftvarcon_inst%eca_km_ptase(1:numpft)
bc_pconst%eca_vmax_ptase(1:numpft) = EDPftvarcon_inst%eca_vmax_ptase(1:numpft)
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
@@ -453,15 +447,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))
@@ -608,15 +596,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
@@ -637,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)
@@ -645,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))
@@ -856,17 +850,32 @@ subroutine SetFatesGlobalElements2(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
! calculate the bin edges for radiative transfer calculations
@@ -977,7 +986,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(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
+
+
return
end subroutine InitTimeAveragingGlobals
@@ -1525,9 +1540,6 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval)
call endrun(msg=errMsg(sourcefile, __LINE__))
end if
- ! TEMPORARY TESTING OVERRIDE !!!!!!!!
- ! hlm_decomp = 'MIMICS'
-
if(trim(hlm_nu_com) .eq. 'unset') then
write(fates_log(),*) 'FATES dimension/parameter unset: hlm_nu_com, exiting'
call endrun(msg=errMsg(sourcefile, __LINE__))
@@ -1935,7 +1947,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/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90
index 5df7fd7abf..dd306e9734 100644
--- a/main/FatesInterfaceTypesMod.F90
+++ b/main/FatesInterfaceTypesMod.F90
@@ -657,10 +657,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]
@@ -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
@@ -742,12 +744,15 @@ 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 :: vmax_no3(:)
+ real(r8), pointer :: vmax_p(:)
+
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(:)
- real(r8), pointer :: eca_vmax_p(:)
+ real(r8), pointer :: eca_km_p(:)
+
real(r8), pointer :: eca_km_ptase(:)
real(r8), pointer :: eca_vmax_ptase(:)
real(r8), pointer :: eca_alpha_ptase(:)
diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90
index 03e04df6c9..a0304f2935 100644
--- a/main/FatesInventoryInitMod.F90
+++ b/main/FatesInventoryInitMod.F90
@@ -1035,7 +1035,9 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, &
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(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, &
diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90
index 5089e09da6..040af0400b 100644
--- a/main/FatesRestartInterfaceMod.F90
+++ b/main/FatesRestartInterfaceMod.F90
@@ -19,6 +19,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 : hlm_use_nocomp, hlm_use_fixed_biogeog
use FatesInterfaceTypesMod, only : fates_maxElementsPerSite
@@ -30,6 +31,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
@@ -101,6 +103,19 @@ module FatesRestartInterfaceMod
integer :: ir_canopy_layer_yesterday_co
integer :: ir_crowndamage_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_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
@@ -113,7 +128,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
@@ -126,16 +141,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_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
- integer :: ir_daily_n_need_co
- integer :: ir_daily_p_need_co
+
!Logging
integer :: ir_lmort_direct_co
@@ -191,6 +197,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
@@ -226,8 +233,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_woodprod_mbal
@@ -731,6 +736,60 @@ 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 )
+
+ 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 )
@@ -782,10 +841,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', &
@@ -802,55 +861,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_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, &
- 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_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', &
@@ -1057,17 +1068,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, &
@@ -1180,7 +1180,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, &
@@ -1821,6 +1825,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
@@ -1882,6 +1887,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites)
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_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, &
@@ -1895,20 +1901,10 @@ 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_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_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_dgmort_co => this%rvars(ir_dgmort_co)%r81d, &
@@ -1931,6 +1927,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, &
@@ -1992,6 +1989,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
@@ -2034,17 +2032,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
this%rvars(ir_woodprod_mbal+el-1)%r81d(io_idx_si) = sites(s)%mass_balance(el)%wood_product
@@ -2111,6 +2098,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%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
if(hlm_use_planthydro==itrue)then
@@ -2130,6 +2131,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites)
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
rio_dbh_co(io_idx_co) = ccohort%dbh
@@ -2144,7 +2146,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
@@ -2154,19 +2156,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites)
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
- 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_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
@@ -2349,7 +2338,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
@@ -2423,6 +2412,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
@@ -2611,7 +2607,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
@@ -2724,6 +2720,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
@@ -2778,6 +2775,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites)
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_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, &
@@ -2791,20 +2789,10 @@ 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_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_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_dgmort_co => this%rvars(ir_dgmort_co)%r81d, &
@@ -2826,6 +2814,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, &
@@ -2877,6 +2866,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
@@ -2929,17 +2919,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)
sites(s)%mass_balance(el)%wood_product = this%rvars(ir_woodprod_mbal+el-1)%r81d(io_idx_si)
@@ -2997,16 +2976,25 @@ 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%crowndamage = rio_crowndamage_co(io_idx_co)
ccohort%canopy_trim = rio_canopy_trim_co(io_idx_co)
+ ccohort%l2fr = rio_l2fr_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%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)
+ 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)
@@ -3020,7 +3008,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)
@@ -3030,18 +3018,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites)
ccohort%dgmort = rio_dgmort_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_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)
- 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)
@@ -3054,9 +3031,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)
call UpdateCohortBioPhysRates(ccohort)
-
! Initialize Plant Hydraulics
if(hlm_use_planthydro==itrue)then
@@ -3225,6 +3202,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 7fa3bfd7cc..a1c51f6abf 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
+ 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
+ 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
@@ -296,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/main/FatesSizeAgeTypeIndicesMod.F90 b/main/FatesSizeAgeTypeIndicesMod.F90
index 66e3edab28..75eef6b6ad 100644
--- a/main/FatesSizeAgeTypeIndicesMod.F90
+++ b/main/FatesSizeAgeTypeIndicesMod.F90
@@ -6,6 +6,7 @@ module FatesSizeAgeTypeIndicesMod
use FatesInterfaceTypesMod, only : nlevage
use FatesInterfaceTypesMod, only : nlevheight
use FatesInterfaceTypesMod, only : nlevcoage
+ use EDTypesMod, only : nclmax
use FatesInterfaceTypesMod, only : nlevdamage
use EDParamsMod, only : ED_val_history_sizeclass_bin_edges
use EDParamsMod, only : ED_val_history_ageclass_bin_edges
@@ -29,7 +30,8 @@ module FatesSizeAgeTypeIndicesMod
public :: coagetype_class_index
public :: get_coage_class_index
public :: get_agefuel_class_index
-
+ public :: get_layersizetype_class_index
+
contains
! =====================================================================================
@@ -47,6 +49,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/parameter_files/archive/api24.2.0_112822_fates_params_default.cdl b/parameter_files/archive/api24.2.0_112822_fates_params_default.cdl
new file mode 100644
index 0000000000..0c89520e40
--- /dev/null
+++ b/parameter_files/archive/api24.2.0_112822_fates_params_default.cdl
@@ -0,0 +1,1537 @@
+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." ;
+ 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" ;
+ 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 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_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.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/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/archive/apichange_24.2to25.xml b/parameter_files/archive/apichange_24.2to25.xml
new file mode 100644
index 0000000000..41d3ea711b
--- /dev/null
+++ b/parameter_files/archive/apichange_24.2to25.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+ 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
+
+
+ fates_cnp_fnrt_adapt_tscale
+
+
+ fates_cnp_eca_vmax_nh4
+
+
+ fates_cnp_rd_vmax_n
+
+
+ fates_cnp_eca_vmax_no3
+
+
+ fates_cnp_vmax_nh4
+ fates_pft
+ gN/gC/s
+ maximum (potential) uptake rate of NH4 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_nh4 for usage)
+ 2.5e-9, 2.5e-9, 2.5e-9, 2.5e-9, 2.5e-9, 2.5e-9, 2.5e-9, 2.5e-9, 2.5e-9, 2.5e-9, 2.5e-9, 2.5e-9
+
+
+ fates_cnp_vmax_no3
+ fates_pft
+ gN/gC/s
+ maximum (potential) uptake rate of NO3 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_no3 for usage)
+ 2.5e-9, 2.5e-9, 2.5e-9, 2.5e-9, 2.5e-9, 2.5e-9, 2.5e-9, 2.5e-9, 2.5e-9, 2.5e-9, 2.5e-9, 2.5e-9
+
+
+ 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 0c89520e40..d1fcd4c9a3 100644
--- a/parameter_files/fates_params_default.cdl
+++ b/parameter_files/fates_params_default.cdl
@@ -188,36 +188,33 @@ 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)" ;
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)" ;
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" ;
@@ -227,6 +224,12 @@ 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 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)" ;
@@ -965,18 +968,9 @@ 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 ;
-
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,
@@ -985,13 +979,17 @@ 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 ;
- 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 =
@@ -1006,6 +1004,12 @@ 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 = 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 ;
diff --git a/parameter_files/patch_default_bciopt224.xml b/parameter_files/patch_default_bciopt224.xml
index c1c7a30e3c..8ab504ed31 100644
--- a/parameter_files/patch_default_bciopt224.xml
+++ b/parameter_files/patch_default_bciopt224.xml
@@ -2,56 +2,55 @@
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_bciopt224_v1_api24.cdl
+ fates_params_opt224_040822_api25.cdl
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
+ 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
+ 0
+ 5e-10
+ 3e-08
+ 0.03991654
+ 0.01995827
+ 0.01303514
+ 0.02955703
+ 3
+ 3
+ 0.04680188
+ 0.001
+ 0.8374751
1,1,3,4
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
diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90
index d640797e6f..9e53e422a6 100644
--- a/parteh/PRTAllometricCNPMod.F90
+++ b/parteh/PRTAllometricCNPMod.F90
@@ -18,14 +18,14 @@ 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
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
@@ -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
@@ -56,6 +57,11 @@ 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
+ use EDPftvarcon, only : EDPftvarcon_inst
implicit none
private
@@ -67,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
@@ -92,8 +96,8 @@ module PRTAllometricCNPMod
! Total number of state variables
integer, parameter :: num_vars = 18
-
-
+
+
! Global identifiers for the two stoichiometry values
integer,public, parameter :: stoich_growth_min = 1 ! Flag for stoichiometry associated with
! minimum needed for growth
@@ -101,7 +105,6 @@ module PRTAllometricCNPMod
! This is deprecated until a reasonable hypothesis is in place (RGK)
integer,public, parameter :: stoich_max = 2 ! Flag for stoichiometry associated with
! maximum for that organ
-
! This is the ordered list of organs used in this module
! -------------------------------------------------------------------------------------
@@ -109,9 +112,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)
@@ -127,6 +132,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,26 +143,30 @@ 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_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 :: 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_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
! -------------------------------------------------------------------------------------
! 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_cdamage = 8 ! Index for the crowndamage 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_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 = 8
+ integer, parameter :: num_bc_in = 7
! -------------------------------------------------------------------------------------
! Output Boundary Indices (These are public)
@@ -165,48 +175,64 @@ 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, public, parameter :: acnp_bc_out_id_limiter = 4 ! The minimum of the Nutrient ratio over c ratio
- integer, parameter :: num_bc_out = 5 ! Total number of
-
+ integer, parameter :: num_bc_out = 4 ! 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 :: intgr_parm_cdamage = 4
+ integer,private, parameter :: num_intgr_parm = 4
! -------------------------------------------------------------------------------------
! 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
-
- real(r8), parameter :: store_overflow_frac = 0.15 ! 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.
+ ! 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
+
+ ! 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
+
+ ! 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
-
- ! Array of pointers are difficult in F90
- ! This structure is a necessary intermediate
- type :: parray_type
- real(r8), pointer :: ptr
- end type parray_type
+ 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.
+
+ ! 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.
! -------------------------------------------------------------------------------------
! This is the core type that holds this specific
! plant reactive transport (PRT) module
! -------------------------------------------------------------------------------------
-
-
type, public, extends(prt_vartypes) :: cnp_allom_prt_vartypes
contains
@@ -218,10 +244,11 @@ module PRTAllometricCNPMod
! Extended functions specific to Allometric CNP
procedure :: CNPPrioritizedReplacement
procedure :: CNPStatureGrowth
+ procedure :: EstimateGrowthNC
+ procedure :: CNPAdjustFRootTargets
procedure :: CNPAllocateRemainder
procedure :: GetDeficit
- procedure :: GrowEquivC
- procedure :: NAndPToMatchC
+ procedure :: TrimFineRoot
end type cnp_allom_prt_vartypes
@@ -247,77 +274,75 @@ 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.
- ! -----------------------------------------------------------------------------------
-
- integer :: nleafage
-
- 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_id = prt_cnp_flex_allom_hyp
-
- 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
-
- 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
-
-
-
- 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_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
-
- ! Have the global generic pointer, point to this hypothesis' object
- prt_global => prt_global_acnp
-
- return
+ ! ----------------------------------------------------------------------------------
+ ! 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
+
+ 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_id = prt_cnp_flex_allom_hyp
+
+ 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
+
+ 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
+
+ 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_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
+
+ ! Have the global generic pointer, point to this hypothesis' object
+ prt_global => prt_global_acnp
+
+ return
end subroutine InitPRTGlobalAllometricCNP
@@ -327,50 +352,43 @@ end subroutine InitPRTGlobalAllometricCNP
subroutine DailyPRTAllometricCNP(this,phase)
class(cnp_allom_prt_vartypes) :: this
- integer,intent(in) :: phase
+ integer,intent(in) :: phase ! the phase splits the routine into parts
+ ! note that phasing is used primarily to
+ ! accomodate the damage module. Damage
+ ! and nutrient cycling are not yet compatable though
+ ! hence, we simply return from any phase but phase 1
+
! 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
- 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 :: crown_damage ! which crown damage clas
-
+ 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)
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
- ! 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]
- integer :: i_org ! organ index
- integer :: i_var ! variable index
-
- ! Agruments for allometry functions, that are not in the target_c array
+ ! 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 :: 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
+ real(r8) :: store_flux
+ integer :: i ! generic organ loop index
+ integer :: i_org ! organ index
+ integer :: i_var ! variable index
! These are daily mass gains, frozen in time, not drawn from, and thus
! these are only used for evaluating mass balancing at the end
@@ -378,24 +396,38 @@ subroutine DailyPRTAllometricCNP(this,phase)
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
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
- ! 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
+ ! Phasing is only used to accomodate the
+ ! damage module. Since this is incompatible with CNP
+ ! Ignore all subsequent calls after the first
+ if (phase.ne.1) return
- if(phase>1)return
+ ! 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
+ 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
! Copy the input only boundary conditions into readable local variables
@@ -403,137 +435,134 @@ subroutine DailyPRTAllometricCNP(this,phase)
! 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
- n_gain = this%bc_in(acnp_bc_in_id_netdnh4)%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
+ 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
-
- ! 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
- 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
-
-
- 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'
- call endrun(msg=errMsg(sourcefile, __LINE__))
+
+ ! 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_r8
end if
+ if(p_uptake_mode.eq.prescribed_p_uptake) then
+ p_gain = 1.e3_r8
+ end if
+
+ n_gain0 = n_gain
+ p_gain0 = p_gain
+ c_gain0 = c_gain
- ! 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))
+ ! 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,crown_damage,canopy_trim,sapw_area,target_c(sapw_id),target_dcdd(sapw_id) )
+ 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_id), ipft, target_c(struct_id), &
- agw_dcdd_target, bgw_dcdd_target, target_dcdd(sapw_id), target_dcdd(struct_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,crown_damage,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)
- state_c0(i_org) = this%variables(i_var)%val(1)
+ 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 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
- i_var = prt_global%sp_organ_map(organ_list(i_org),nitrogen_element)
- state_n(i_org)%ptr => this%variables(i_var)%val(1)
- state_n0(i_org) = this%variables(i_var)%val(1)
+ ! ===================================================================================
+ ! 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.
+ ! ===================================================================================
- 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)
+
+
+ ! Remember the original C,N,P states to help with final
+ ! evaluation of how much was allocated
+ ! -----------------------------------------------------------------------------------
+ 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(i_org,nitrogen_element)
+ state_n0(i_org) = 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
+
+
+ ! 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.
- ! 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())
+ ! Step 0. Transfer all stored nutrient into the daily uptake pool. Also
+ ! transfer C storage that is above the target (ie transfer overflow)
! ===================================================================================
- 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
+ ! 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
- 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
+ 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 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.
! ===================================================================================
-
- 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
-
-
+
! ===================================================================================
- ! 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.
! ===================================================================================
- 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
@@ -543,95 +572,353 @@ subroutine DailyPRTAllometricCNP(this,phase)
! 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)
+ call this%CNPAllocateRemainder(c_gain, n_gain, p_gain, &
+ c_efflux, n_efflux, p_efflux,target_c,target_dcdd)
+
- ! 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(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
+
+ 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 maintenance pay-back and efflux to the "allocated"
- ! pool to make sure everything balances.
-
- allocated_c = (maint_r_def0-maint_r_def) + c_efflux
+ ! we include what is lost through respiration of excess storage
+
+ 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
+ do i = 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))
+ i_org = l2g_organ_list(i)
- 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)
+ 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_n(i_org)%ptr - state_n0(i_org))
-
- allocated_n = allocated_n + (state_n(i_org)%ptr - state_n0(i_org))
+ this%variables(i_var)%net_alloc(1) + (this%variables(i_var)%val(1) - state_c0(i_org))
- i_var = prt_global%sp_organ_map(organ_list(i_org),phosphorus_element)
+ allocated_c = allocated_c + (this%variables(i_var)%val(1) - state_c0(i_org))
+
+ 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_p(i_org)%ptr - state_p0(i_org))
+ this%variables(i_var)%net_alloc(1) + (this%variables(i_var)%val(1) - state_n0(i_org))
- allocated_p = allocated_p + (state_p(i_org)%ptr - state_p0(i_org))
+ allocated_n = allocated_n + (this%variables(i_var)%val(1) - state_n0(i_org))
+
+ 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) + (this%variables(i_var)%val(1) - state_p0(i_org))
+ allocated_p = allocated_p + (this%variables(i_var)%val(1) - 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
+
+ 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(),*) '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
- 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)
- target_p = this%GetNutrientTarget(phosphorus_element,store_organ)
+ ! 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
- 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)
+
+ ! If fine-roots are allocated above their
+ ! target (perhaps with some buffer, but perhaps not)
+ ! then
+ call this%TrimFineRoot()
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 CNPPrioritizedReplacement(this, &
- maint_r_deficit, c_gain, n_gain, p_gain, &
- state_c, state_n, state_p, target_c)
+ 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(:)
+
+ 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) :: 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
+ 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 of the derivative
+ ! 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
+ 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_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
+
+
+ ! 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
+ cn_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)
+
+ 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
+ cp_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)
+
+ 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(cp_ratio)
+ elseif (p_uptake_mode.eq.prescribed_p_uptake) then
+ cx_logratio = SafeLog(cn_ratio)
+ else
+ cx_logratio = SafeLog(max(cp_ratio,cn_ratio))
+ end if
+
+ ! 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( abs(cx_logratio/abs(cx_logratio) - cx0/abs(cx0)) > nearzero ) then
+ cx_int = cx_logratio
+ end if
+ end if
+
+ dcxdt_ratio = cx_logratio-cx0
+
+ ema_dcxdt = pid_drv_wgt*dcxdt_ratio + (1._r8-pid_drv_wgt)*ema_dcxdt
+
+ cx0 = cx_logratio
+
+
+ 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
+
+ ! 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)
+
+ ! 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)
+
+ ! 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 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.
+
+ ! 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)
+
+ ! Find the updated target fineroot biomass
+ call bfineroot(dbh,ipft,canopy_trim, l2fr, 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 )
+
+ if(fnrt_flux_c>nearzero) then
+
+ 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)
+
! -----------------------------------------------------------------------------------
! Alternative allocation hypothesis for the prioritized replacement phase.
@@ -642,56 +929,68 @@ 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
- 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?
- 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]
- 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)
- 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) :: sum_c_demand ! Carbon demanded to bring tissues up to allometry (kg)
+ 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) :: 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
-
-
- c_gain0 = c_gain
+ 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
@@ -701,32 +1000,29 @@ subroutine CNPPrioritizedReplacement(this, &
! 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
@@ -742,39 +1038,30 @@ subroutine CNPPrioritizedReplacement(this, &
! -----------------------------------------------------------------------------------
sum_c_demand = 0._r8
- 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
+ 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
- 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
+ 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
@@ -782,41 +1069,33 @@ 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)
! 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)
- 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,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,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
@@ -826,30 +1105,29 @@ 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
+
+ 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)
-
-
! The flux is the (positive) minimum of all three
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
+ end if
+
! -----------------------------------------------------------------------------------
! If carbon is still available, allocate to remaining high
! carbon balance is guaranteed to be >=0 beyond this point
@@ -857,6 +1135,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
@@ -864,142 +1143,103 @@ 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)
- ! 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
+ ! The priority code associated with this organ
- ! 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
- curpri_org(i) = ii
- end if
- 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
-
- ! 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
- i_org = curpri_org(i)
- 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
- if (sum_c_flux>nearzero) then
- do i = 1, n_curpri_org
-
- 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
-
- ! 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
+ 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. (i_org.eq.leaf_organ)) cycle
+
+ if( priority_code == i_pri ) then
+ i = i + 1
+ 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
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)
+ sum_c_demand = sum_c_demand + deficit_c(i)
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)
+ ! Transfer carbon into pools if there is any
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
+
+ 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
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,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 )
- 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,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, &
+ ! Allocate nutrients at this priority level Nitrogen
+ 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))
end do priority_loop
+
+
+
return
end subroutine CNPPrioritizedReplacement
@@ -1007,34 +1247,29 @@ end subroutine CNPPrioritizedReplacement
! =====================================================================================
- subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, &
- state_c, state_n, state_p, &
- target_c, target_dcdd, cnp_limiter)
+ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, &
+ 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), 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]
- real(r8), intent(in) :: target_c(:)
- real(r8), intent(in) :: target_dcdd(:)
- integer, intent(out) :: cnp_limiter
-
+ 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) :: 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
- real(r8) :: canopy_trim
- real(r8) :: leaf_status
- integer :: crown_damage ! which crown damage clas
-
+ 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)
- 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
+ integer :: i_org ! global organ index
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)
@@ -1042,28 +1277,26 @@ 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
! 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) :: gr_flux ! Growth respiration flux for the current transaction (kgC)
+ real(r8) :: n_flux,p_flux
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
@@ -1094,25 +1327,34 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, 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)
- 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
+ real(r8) :: intgr_params(num_intgr_parm)
+
+
+ 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
+
- 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
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
+ ! 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
- cnp_limiter = 0
+ limiter = 0
! If any of these resources is essentially tapped out,
! then there is no point in performing growth
@@ -1121,22 +1363,24 @@ 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.
+
- 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. &
+ 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
-
- 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)
+ 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
+ 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
@@ -1148,7 +1392,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,
@@ -1156,10 +1402,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?))
@@ -1173,9 +1419,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
@@ -1192,8 +1439,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
@@ -1211,9 +1457,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
@@ -1230,102 +1476,55 @@ 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
+
+ ! 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.
- 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
-
+ if(grow_lim_type == grow_lim_conly) then
+ c_gstature = c_gain
+ limiter = 0
+ elseif (grow_lim_type == grow_lim_estNP) then
- select case(grow_lim_type)
- case(1)
+ call EstimateGrowthNC(this,target_c,target_dcdd,state_mask,avg_nc,avg_pc)
-
- ! 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)
+ neq_cgain = n_gain/avg_nc
+ peq_cgain = p_gain/avg_pc
- 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
+ if(c_gain1._r8 .and. (p_gain/p_match)>1._r8 ) then
- cnp_limiter = c_limited
+ if(c_gain < peq_cgain) then
+ limiter = c_limited
+ c_gstature = c_gain
+ cnp_gain = c_gain
+ else
+ limiter = p_limited
+ c_gstature = peq_cgain
+ cnp_gain = p_gain
+ end if
+
else
- if( n_gain/n_match < p_gain/p_match ) then
- cnp_limiter = n_limited
+ if(neq_cgain < peq_cgain) then
+ limiter = n_limited
+ c_gstature = neq_cgain
+ cnp_gain = n_gain
else
- cnp_limiter = p_limited
+ limiter = p_limited
+ c_gstature = peq_cgain
+ cnp_gain = p_gain
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
+ end if
if_stature_growth: if(c_gstature > nearzero) then
@@ -1345,13 +1544,13 @@ 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.
state_array(dbh_id) = dbh
-
- totalC = c_gstature
do_solve_check: do while( ierr .ne. 0 )
@@ -1377,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,crown_damage,canopy_trim, &
+ 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), &
@@ -1416,8 +1615,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
@@ -1426,13 +1627,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
@@ -1451,14 +1654,16 @@ 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_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)
@@ -1468,7 +1673,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, &
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,fnrt_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)
@@ -1480,8 +1685,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
@@ -1497,18 +1700,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)
@@ -1518,56 +1726,52 @@ 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
+
+ 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(ii) = this%GetDeficit(nitrogen_element,i_org,target_n)
+ sum_n_demand = sum_n_demand+max(0._r8,deficit_n(ii))
+
+ 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
-
+
return
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, &
+ 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
- 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) :: p_gain
real(r8), intent(inout) :: c_efflux
real(r8), intent(inout) :: n_efflux
real(r8), intent(inout) :: p_efflux
-
+ real(r8) :: target_c(:)
+ real(r8) :: target_dcdd(:)
+
integer :: i
real(r8), dimension(num_organs) :: deficit_n
real(r8), dimension(num_organs) :: deficit_p
@@ -1575,17 +1779,18 @@ 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_c_flux ! Flux into storage [kgC]
- integer, dimension(num_organs),parameter :: all_organs = [1,2,3,4,5,6]
real(r8), pointer :: dbh
+ real(r8), pointer :: resp_excess
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
! -----------------------------------------------------------------------------------
@@ -1596,39 +1801,37 @@ 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_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_n = this%GetNutrientTarget(nitrogen_element,l2g_organ_list(i),stoich_growth_min)
+ 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
-
+
! -----------------------------------------------------------------------------------
! Nutrient Fluxes proportionally to each pool (these should be fully actualized)
! (this also removes from the gain pools)
! -----------------------------------------------------------------------------------
! 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)
-
+ call ProportionalNutrAllocation(this,deficit_p(1:num_organs), &
+ p_gain, phosphorus_element, l2g_organ_list(1:num_organs))
- ! 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
-
- n_gain = 0._r8
- p_gain = 0._r8
-
-
+ ! 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
! We will do this last, because we wanted the non-overflow storage
@@ -1637,35 +1840,92 @@ 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,crown_damage,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)))
-
- ! 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
+ 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
+
+ ! Update carbon based allometric targets
+ 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))
+
+ total_c_flux = max(0._r8,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
+ resp_excess = 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,crown_damage,canopy_trim, store_c_target)
+
+ ! Estimate the overflow
+ store_c_target = store_c_target * (1._r8 + prt_params%store_ovrflw_frac(ipft))
+
+ 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
+
+ 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
! -----------------------------------------------------------------------------------
- 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 = n_gain
+ n_gain = 0._r8
+ end if
+
+ if(p_uptake_mode.eq.prescribed_p_uptake) then
+ p_efflux = 0._r8
+ else
+ p_efflux = p_gain
+ p_gain = 0._r8
+ end if
- c_gain = 0.0_r8
-! n_gain = 0.0_r8
-! p_gain = 0.0_r8
+ c_efflux = c_gain
+ c_gain = 0.0_r8
+
+
return
end subroutine CNPAllocateRemainder
@@ -1710,7 +1970,6 @@ function GetDeficit(this,element_id,organ_id,target_m) result(deficit_m)
return
end function GetDeficit
-
! =====================================================================================
@@ -1725,6 +1984,7 @@ 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
integer :: crown_damage
@@ -1732,16 +1992,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) :: 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
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
@@ -1750,7 +2011,7 @@ 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,fnrt_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)
@@ -1767,22 +2028,28 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe
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_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 + prt_params%store_ovrflw_frac(ipft))
+ end if
+
elseif(organ_id == repro_organ) then
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
@@ -1830,7 +2097,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
@@ -1839,19 +2106,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
@@ -1859,8 +2125,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
@@ -1868,11 +2134,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
@@ -1892,192 +2161,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)
@@ -2110,8 +2193,9 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r
! locals
integer :: ipft ! PFT index
- integer :: crown_damage ! Damage class
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)
real(r8) :: sapw_c_target ! target sapwood biomass, dummy var (kgC)
@@ -2127,7 +2211,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
@@ -2147,13 +2230,13 @@ 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))
- crown_damage = int(intgr_params(acnp_bc_in_id_cdamage))
+ 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(intgr_parm_cdamage))
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 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)
@@ -2249,100 +2332,104 @@ 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)
+ ! =====================================================================================
+
+
+ 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, &
+ 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
+ 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_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)
+ 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 * nc_repro
+ avg_pc = avg_pc + repro_w * pc_repro
+ 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
+ avg_nc = avg_nc / total_w
+ avg_pc = avg_pc / total_w
- return
- end subroutine TargetAllometryCheck
+ end associate
+
+ return
+ end subroutine EstimateGrowthNC
-
-
end module PRTAllometricCNPMod
diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90
index be4b2bbdff..91c685fa22 100644
--- a/parteh/PRTAllometricCarbonMod.F90
+++ b/parteh/PRTAllometricCarbonMod.F90
@@ -400,6 +400,9 @@ subroutine DailyPRTAllometricCarbon(this,phase)
real(r8) :: intgr_params(num_bc_in)
+
+ ipft = this%bc_in(ac_bc_in_id_pft)%ival
+
associate( &
leaf_c => this%variables(leaf_c_id)%val, &
@@ -407,7 +410,8 @@ subroutine DailyPRTAllometricCarbon(this,phase)
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(ipft) )
! -----------------------------------------------------------------------------------
@@ -421,7 +425,6 @@ subroutine DailyPRTAllometricCarbon(this,phase)
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
@@ -465,7 +468,7 @@ subroutine DailyPRTAllometricCarbon(this,phase)
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)
+ call bfineroot(dbh,ipft,canopy_trim,l2fr,target_fnrt_c)
! Target storage carbon [kgC,kgC/cm]
call bstore_allom(dbh,ipft,crowndamage,canopy_trim,target_store_c)
@@ -750,7 +753,7 @@ subroutine DailyPRTAllometricCarbon(this,phase)
! we remember the current step size as a good next guess.
call CheckIntegratedAllometries(c_pool_out(dbh_id),ipft,&
- crowndamage, canopy_trim, &
+ crowndamage, 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), &
@@ -917,6 +920,7 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx)
integer :: ipft ! PFT index
integer :: crowndamage ! Damage class
real(r8) :: canopy_trim ! Canopy trimming function (boundary condition [0-1]
+ real(r8) :: l2fr ! Leaf to fine-root 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)
@@ -954,9 +958,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))
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,ct_fnrt,ct_dfnrtdd)
+ 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)
diff --git a/parteh/PRTGenericMod.F90 b/parteh/PRTGenericMod.F90
index 001c617912..2075216da2 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
@@ -100,7 +99,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 +134,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]
@@ -147,6 +145,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
! -------------------------------------------------------------------------------------
!
@@ -1013,44 +1016,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
@@ -1074,43 +1056,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
@@ -1131,43 +1093,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
@@ -1190,42 +1130,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
@@ -1258,9 +1177,9 @@ subroutine DailyPRTBase(this,phase)
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__))
+
+ write(fates_log(),*)'Daily PRT Allocation must be extended'
+ call endrun(msg=errMsg(sourcefile, __LINE__))
end subroutine DailyPRTBase
@@ -1306,12 +1225,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
@@ -1451,10 +1364,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-fnrt-sapw 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 :: 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)
@@ -1467,8 +1382,12 @@ 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 == 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)
@@ -1477,6 +1396,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
@@ -1486,15 +1429,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
diff --git a/parteh/PRTLossFluxesMod.F90 b/parteh/PRTLossFluxesMod.F90
index 7c1a688ebc..f490b0749b 100644
--- a/parteh/PRTLossFluxesMod.F90
+++ b/parteh/PRTLossFluxesMod.F90
@@ -9,7 +9,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
@@ -161,23 +160,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
@@ -225,7 +212,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)
@@ -567,7 +554,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))
@@ -588,7 +575,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
@@ -771,7 +758,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))
diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90
index 23e867a734..0346009745 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
@@ -57,10 +57,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
@@ -77,22 +73,15 @@ 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
! --------------------------------------------------------------------------------------------
! 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 ...
@@ -116,6 +105,8 @@ module PRTParametersMod
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]
+ ! 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")
@@ -140,6 +131,21 @@ 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
+
+ ! PID controller parameters
+ real(r8), allocatable :: pid_kp(:) ! proportion constant in the PID controller for fine-root biomass
+ real(r8), allocatable :: pid_ki(:) ! integral constant in the PID controller for fine-root biomass
+ real(r8), allocatable :: pid_kd(:) ! derivative constant in the PID controller for fine-root biomass
+
+ 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 76558874b7..85521e0370 100644
--- a/parteh/PRTParamsFATESMod.F90
+++ b/parteh/PRTParamsFATESMod.F90
@@ -50,6 +50,7 @@ module PRTInitParamsFatesMod
public :: PRTReceiveParams
public :: PRTCheckParams
public :: PRTDerivedParams
+ public :: NewRecruitTotalStoichiometry
!-----------------------------------------------------------------------
contains
@@ -235,6 +236,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_cnp_pid_kd'
+ call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, &
+ dimension_names=dim_names, lower_bounds=dim_lower_bound)
+
+ name = 'fates_cnp_pid_ki'
+ call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, &
+ dimension_names=dim_names, lower_bounds=dim_lower_bound)
+
+ name = 'fates_cnp_pid_kp'
+ call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, &
+ dimension_names=dim_names, lower_bounds=dim_lower_bound)
+
+ name = 'fates_cnp_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_cnp_nfix1'
+ 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)
@@ -526,6 +547,26 @@ subroutine PRTReceivePFT(fates_params)
call fates_params%RetrieveParameterAllocate(name=name, &
data=prt_params%allom_l2fr)
+ name = 'fates_cnp_pid_kp'
+ call fates_params%RetrieveParameterAllocate(name=name, &
+ data=prt_params%pid_kp)
+
+ name = 'fates_cnp_pid_ki'
+ call fates_params%RetrieveParameterAllocate(name=name, &
+ data=prt_params%pid_ki)
+
+ name = 'fates_cnp_pid_kd'
+ call fates_params%RetrieveParameterAllocate(name=name, &
+ data=prt_params%pid_kd)
+
+ name = 'fates_cnp_store_ovrflw_frac'
+ call fates_params%RetrieveParameterAllocate(name=name, &
+ data=prt_params%store_ovrflw_frac)
+
+ name = 'fates_cnp_nfix1'
+ call fates_params%RetrieveParameterAllocate(name=name, &
+ data=prt_params%nfix_mresp_scfrac)
+
name = 'fates_allom_agb_frac'
call fates_params%RetrieveParameterAllocate(name=name, &
data=prt_params%allom_agb_frac)
@@ -613,7 +654,7 @@ subroutine PRTReceivePFT(fates_params)
name = 'fates_cnp_phos_store_ratio'
call fates_params%RetrieveParameterAllocate(name=name, &
data=prt_params%phos_store_ratio)
-
+
end subroutine PRTReceivePFT
@@ -855,6 +896,10 @@ subroutine FatesReportPFTParams(is_master)
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) 'pid_kp = ',prt_params%pid_kp
+ write(fates_log(),fmt0) 'pid_ki = ',prt_params%pid_ki
+ write(fates_log(),fmt0) 'pid_kd = ',prt_params%pid_kd
+ 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
@@ -909,8 +954,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
@@ -919,18 +962,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
@@ -1007,6 +1038,18 @@ subroutine PRTCheckParams(is_master)
end do
end select
+
+ ! 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
@@ -1347,7 +1390,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
@@ -1361,10 +1404,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]
@@ -1382,7 +1425,7 @@ function NewRecruitTotalStoichiometry(ft,element_id) result(recruit_stoich)
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,c_fnrt)
+ 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)
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