#include <misc.h> #include <preproc.h> module CNAllocationMod 3,1 #ifdef CN !----------------------------------------------------------------------- !BOP ! ! !MODULE: CNAllocationMod ! ! !DESCRIPTION: ! Module holding routines used in allocation model for coupled carbon ! nitrogen code. ! ! !USES: use shr_kind_mod, only: r8 => shr_kind_r8 implicit none save private ! !PUBLIC MEMBER FUNCTIONS: public :: CNAllocation ! !PUBLIC DATA MEMBERS: logical, public :: Carbon_only = .false. ! Carbon only mode ! (Nitrogen is prescribed NOT prognostic) ! ! !REVISION HISTORY: ! 8/5/03: Created by Peter Thornton ! !EOP !----------------------------------------------------------------------- contains !----------------------------------------------------------------------- !BOP ! ! !IROUTINE: CNAllocation ! ! !INTERFACE: subroutine CNAllocation (lbp, ubp, lbc, ubc, & 1,7 num_soilc, filter_soilc, num_soilp, filter_soilp) ! ! !DESCRIPTION: ! ! !USES: use clmtype use clm_varctl, only: iulog use shr_sys_mod, only: shr_sys_flush use clm_time_manager, only: get_step_size use pft2colMod, only: p2c ! ! !ARGUMENTS: implicit none integer, intent(in) :: lbp, ubp ! pft-index bounds integer, intent(in) :: lbc, ubc ! column-index bounds integer, intent(in) :: num_soilc ! number of soil columns in filter integer, intent(in) :: filter_soilc(:) ! filter for soil columns integer, intent(in) :: num_soilp ! number of soil pfts in filter integer, intent(in) :: filter_soilp(:) ! filter for soil pfts ! ! !CALLED FROM: ! subroutine CNdecompAlloc in module CNdecompMod.F90 ! ! !REVISION HISTORY: ! 8/5/03: Created by Peter Thornton ! 10/23/03, Peter Thornton: migrated to vector data structures ! ! !LOCAL VARIABLES: ! local pointers to implicit in arrays ! ! pft level integer , pointer :: ivt(:) ! pft vegetation type integer , pointer :: pcolumn(:) ! pft's column index real(r8), pointer :: lgsf(:) ! long growing season factor [0-1] real(r8), pointer :: xsmrpool(:) ! (kgC/m2) temporary photosynthate C pool real(r8), pointer :: retransn(:) ! (kgN/m2) plant pool of retranslocated N real(r8), pointer :: psnsun(:) ! sunlit leaf-level photosynthesis (umol CO2 /m**2/ s) real(r8), pointer :: psnsha(:) ! shaded leaf-level photosynthesis (umol CO2 /m**2/ s) #if (defined C13) real(r8), pointer :: c13_psnsun(:) ! C13 sunlit leaf-level photosynthesis (umol CO2 /m**2/ s) real(r8), pointer :: c13_psnsha(:) ! C13 shaded leaf-level photosynthesis (umol CO2 /m**2/ s) #endif real(r8), pointer :: laisun(:) ! sunlit projected leaf area index real(r8), pointer :: laisha(:) ! shaded projected leaf area index real(r8), pointer :: leaf_mr(:) real(r8), pointer :: froot_mr(:) real(r8), pointer :: livestem_mr(:) real(r8), pointer :: livecroot_mr(:) real(r8), pointer :: leaf_curmr(:) real(r8), pointer :: froot_curmr(:) real(r8), pointer :: livestem_curmr(:) real(r8), pointer :: livecroot_curmr(:) real(r8), pointer :: leaf_xsmr(:) real(r8), pointer :: froot_xsmr(:) real(r8), pointer :: livestem_xsmr(:) real(r8), pointer :: livecroot_xsmr(:) ! column level real(r8), pointer :: sminn(:) ! (kgN/m2) soil mineral N ! ecophysiological constants real(r8), pointer :: woody(:) ! binary flag for woody lifeform (1=woody, 0=not woody) real(r8), pointer :: froot_leaf(:) ! allocation parameter: new fine root C per new leaf C (gC/gC) real(r8), pointer :: croot_stem(:) ! allocation parameter: new coarse root C per new stem C (gC/gC) real(r8), pointer :: stem_leaf(:) ! allocation parameter: new stem c per new leaf C (gC/gC) real(r8), pointer :: flivewd(:) ! allocation parameter: fraction of new wood that is live (phloem and ray parenchyma) (no units) real(r8), pointer :: leafcn(:) ! leaf C:N (gC/gN) real(r8), pointer :: frootcn(:) ! fine root C:N (gC/gN) real(r8), pointer :: livewdcn(:) ! live wood (phloem and ray parenchyma) C:N (gC/gN) real(r8), pointer :: deadwdcn(:) ! dead wood (xylem and heartwood) C:N (gC/gN) real(r8), pointer :: fcur2(:) ! allocation parameter: fraction of allocation that goes to currently displayed growth, remainder to storage integer, pointer :: plandunit(:) ! index into landunit level quantities integer, pointer :: clandunit(:) ! index into landunit level quantities integer , pointer :: itypelun(:) ! landunit type ! ! local pointers to implicit in/out arrays ! ! pft level real(r8), pointer :: gpp(:) ! GPP flux before downregulation (gC/m2/s) real(r8), pointer :: availc(:) ! C flux available for allocation (gC/m2/s) real(r8), pointer :: xsmrpool_recover(:) ! C flux assigned to recovery of negative cpool (gC/m2/s) real(r8), pointer :: c_allometry(:) ! C allocation index (DIM) real(r8), pointer :: n_allometry(:) ! N allocation index (DIM) real(r8), pointer :: plant_ndemand(:) ! N flux required to support initial GPP (gN/m2/s) real(r8), pointer :: tempsum_potential_gpp(:) ! temporary annual sum of potential GPP real(r8), pointer :: tempmax_retransn(:) ! temporary annual max of retranslocated N pool (gN/m2) real(r8), pointer :: annsum_potential_gpp(:) ! annual sum of potential GPP real(r8), pointer :: avail_retransn(:) ! N flux available from retranslocation pool (gN/m2/s) real(r8), pointer :: annmax_retransn(:) ! annual max of retranslocated N pool real(r8), pointer :: plant_nalloc(:) ! total allocated N flux (gN/m2/s) real(r8), pointer :: plant_calloc(:) ! total allocated C flux (gC/m2/s) real(r8), pointer :: excess_cflux(:) ! C flux not allocated due to downregulation (gC/m2/s) real(r8), pointer :: downreg(:) ! fractional reduction in GPP due to N limitation (DIM) real(r8), pointer :: annsum_npp(:) ! annual sum of NPP, for wood allocation real(r8), pointer :: cpool_to_xsmrpool(:) real(r8), pointer :: psnsun_to_cpool(:) real(r8), pointer :: psnshade_to_cpool(:) #if (defined C13) real(r8), pointer :: c13_psnsun_to_cpool(:) real(r8), pointer :: c13_psnshade_to_cpool(:) #endif real(r8), pointer :: cpool_to_leafc(:) real(r8), pointer :: cpool_to_leafc_storage(:) real(r8), pointer :: cpool_to_frootc(:) real(r8), pointer :: cpool_to_frootc_storage(:) real(r8), pointer :: cpool_to_livestemc(:) real(r8), pointer :: cpool_to_livestemc_storage(:) real(r8), pointer :: cpool_to_deadstemc(:) real(r8), pointer :: cpool_to_deadstemc_storage(:) real(r8), pointer :: cpool_to_livecrootc(:) real(r8), pointer :: cpool_to_livecrootc_storage(:) real(r8), pointer :: cpool_to_deadcrootc(:) real(r8), pointer :: cpool_to_deadcrootc_storage(:) real(r8), pointer :: cpool_to_gresp_storage(:) real(r8), pointer :: retransn_to_npool(:) real(r8), pointer :: sminn_to_npool(:) real(r8), pointer :: npool_to_leafn(:) real(r8), pointer :: npool_to_leafn_storage(:) real(r8), pointer :: npool_to_frootn(:) real(r8), pointer :: npool_to_frootn_storage(:) real(r8), pointer :: npool_to_livestemn(:) real(r8), pointer :: npool_to_livestemn_storage(:) real(r8), pointer :: npool_to_deadstemn(:) real(r8), pointer :: npool_to_deadstemn_storage(:) real(r8), pointer :: npool_to_livecrootn(:) real(r8), pointer :: npool_to_livecrootn_storage(:) real(r8), pointer :: npool_to_deadcrootn(:) real(r8), pointer :: npool_to_deadcrootn_storage(:) ! column level real(r8), pointer :: fpi(:) ! fraction of potential immobilization (no units) real(r8), pointer :: fpg(:) ! fraction of potential gpp (no units) real(r8), pointer :: potential_immob(:) real(r8), pointer :: actual_immob(:) real(r8), pointer :: sminn_to_plant(:) real(r8), pointer :: sminn_to_denit_excess(:) real(r8), pointer :: supplement_to_sminn(:) ! ! local pointers to implicit out arrays ! ! ! !OTHER LOCAL VARIABLES: integer :: c,p !indices integer :: fp !lake filter pft index integer :: fc !lake filter column index real(r8):: dt !decomp timestep (seconds) integer :: nlimit !flag for N limitation real(r8), pointer:: col_plant_ndemand(:) !column-level plant N demand real(r8):: dayscrecover !number of days to recover negative cpool real(r8):: mr !maintenance respiration (gC/m2/s) real(r8):: f1,f2,f3,f4,g1,g2 !allocation parameters real(r8):: cnl,cnfr,cnlw,cndw !C:N ratios for leaf, fine root, and wood real(r8):: grperc, grpnow !growth respirarion parameters real(r8):: fcur !fraction of current psn displayed as growth real(r8):: sum_ndemand !total column N demand (gN/m2/s) real(r8):: gresp_storage !temporary variable for growth resp to storage real(r8):: nlc !temporary variable for total new leaf carbon allocation real(r8):: bdnr !bulk denitrification rate (1/s) real(r8):: curmr, curmr_ratio !xsmrpool temporary variables !EOP !----------------------------------------------------------------------- ! Assign local pointers to derived type arrays (in) ivt => clm3%g%l%c%p%itype pcolumn => clm3%g%l%c%p%column plandunit => clm3%g%l%c%p%landunit clandunit => clm3%g%l%c%landunit itypelun => clm3%g%l%itype lgsf => clm3%g%l%c%p%pepv%lgsf xsmrpool => clm3%g%l%c%p%pcs%xsmrpool retransn => clm3%g%l%c%p%pns%retransn psnsun => clm3%g%l%c%p%pcf%psnsun psnsha => clm3%g%l%c%p%pcf%psnsha #if (defined C13) c13_psnsun => clm3%g%l%c%p%pc13f%psnsun c13_psnsha => clm3%g%l%c%p%pc13f%psnsha #endif laisun => clm3%g%l%c%p%pps%laisun laisha => clm3%g%l%c%p%pps%laisha leaf_mr => clm3%g%l%c%p%pcf%leaf_mr froot_mr => clm3%g%l%c%p%pcf%froot_mr livestem_mr => clm3%g%l%c%p%pcf%livestem_mr livecroot_mr => clm3%g%l%c%p%pcf%livecroot_mr leaf_curmr => clm3%g%l%c%p%pcf%leaf_curmr froot_curmr => clm3%g%l%c%p%pcf%froot_curmr livestem_curmr => clm3%g%l%c%p%pcf%livestem_curmr livecroot_curmr => clm3%g%l%c%p%pcf%livecroot_curmr leaf_xsmr => clm3%g%l%c%p%pcf%leaf_xsmr froot_xsmr => clm3%g%l%c%p%pcf%froot_xsmr livestem_xsmr => clm3%g%l%c%p%pcf%livestem_xsmr livecroot_xsmr => clm3%g%l%c%p%pcf%livecroot_xsmr sminn => clm3%g%l%c%cns%sminn woody => pftcon%woody froot_leaf => pftcon%froot_leaf croot_stem => pftcon%croot_stem stem_leaf => pftcon%stem_leaf flivewd => pftcon%flivewd leafcn => pftcon%leafcn frootcn => pftcon%frootcn livewdcn => pftcon%livewdcn deadwdcn => pftcon%deadwdcn fcur2 => pftcon%fcur ! Assign local pointers to derived type arrays (out) gpp => clm3%g%l%c%p%pepv%gpp availc => clm3%g%l%c%p%pepv%availc xsmrpool_recover => clm3%g%l%c%p%pepv%xsmrpool_recover c_allometry => clm3%g%l%c%p%pepv%c_allometry n_allometry => clm3%g%l%c%p%pepv%n_allometry plant_ndemand => clm3%g%l%c%p%pepv%plant_ndemand tempsum_potential_gpp => clm3%g%l%c%p%pepv%tempsum_potential_gpp tempmax_retransn => clm3%g%l%c%p%pepv%tempmax_retransn annsum_potential_gpp => clm3%g%l%c%p%pepv%annsum_potential_gpp avail_retransn => clm3%g%l%c%p%pepv%avail_retransn annmax_retransn => clm3%g%l%c%p%pepv%annmax_retransn plant_nalloc => clm3%g%l%c%p%pepv%plant_nalloc plant_calloc => clm3%g%l%c%p%pepv%plant_calloc excess_cflux => clm3%g%l%c%p%pepv%excess_cflux downreg => clm3%g%l%c%p%pepv%downreg annsum_npp => clm3%g%l%c%p%pepv%annsum_npp cpool_to_xsmrpool => clm3%g%l%c%p%pcf%cpool_to_xsmrpool psnsun_to_cpool => clm3%g%l%c%p%pcf%psnsun_to_cpool psnshade_to_cpool => clm3%g%l%c%p%pcf%psnshade_to_cpool #if (defined C13) c13_psnsun_to_cpool => clm3%g%l%c%p%pc13f%psnsun_to_cpool c13_psnshade_to_cpool => clm3%g%l%c%p%pc13f%psnshade_to_cpool #endif cpool_to_leafc => clm3%g%l%c%p%pcf%cpool_to_leafc cpool_to_leafc_storage => clm3%g%l%c%p%pcf%cpool_to_leafc_storage cpool_to_frootc => clm3%g%l%c%p%pcf%cpool_to_frootc cpool_to_frootc_storage => clm3%g%l%c%p%pcf%cpool_to_frootc_storage cpool_to_livestemc => clm3%g%l%c%p%pcf%cpool_to_livestemc cpool_to_livestemc_storage => clm3%g%l%c%p%pcf%cpool_to_livestemc_storage cpool_to_deadstemc => clm3%g%l%c%p%pcf%cpool_to_deadstemc cpool_to_deadstemc_storage => clm3%g%l%c%p%pcf%cpool_to_deadstemc_storage cpool_to_livecrootc => clm3%g%l%c%p%pcf%cpool_to_livecrootc cpool_to_livecrootc_storage => clm3%g%l%c%p%pcf%cpool_to_livecrootc_storage cpool_to_deadcrootc => clm3%g%l%c%p%pcf%cpool_to_deadcrootc cpool_to_deadcrootc_storage => clm3%g%l%c%p%pcf%cpool_to_deadcrootc_storage cpool_to_gresp_storage => clm3%g%l%c%p%pcf%cpool_to_gresp_storage retransn_to_npool => clm3%g%l%c%p%pnf%retransn_to_npool sminn_to_npool => clm3%g%l%c%p%pnf%sminn_to_npool npool_to_leafn => clm3%g%l%c%p%pnf%npool_to_leafn npool_to_leafn_storage => clm3%g%l%c%p%pnf%npool_to_leafn_storage npool_to_frootn => clm3%g%l%c%p%pnf%npool_to_frootn npool_to_frootn_storage => clm3%g%l%c%p%pnf%npool_to_frootn_storage npool_to_livestemn => clm3%g%l%c%p%pnf%npool_to_livestemn npool_to_livestemn_storage => clm3%g%l%c%p%pnf%npool_to_livestemn_storage npool_to_deadstemn => clm3%g%l%c%p%pnf%npool_to_deadstemn npool_to_deadstemn_storage => clm3%g%l%c%p%pnf%npool_to_deadstemn_storage npool_to_livecrootn => clm3%g%l%c%p%pnf%npool_to_livecrootn npool_to_livecrootn_storage => clm3%g%l%c%p%pnf%npool_to_livecrootn_storage npool_to_deadcrootn => clm3%g%l%c%p%pnf%npool_to_deadcrootn npool_to_deadcrootn_storage => clm3%g%l%c%p%pnf%npool_to_deadcrootn_storage fpi => clm3%g%l%c%cps%fpi fpg => clm3%g%l%c%cps%fpg potential_immob => clm3%g%l%c%cnf%potential_immob actual_immob => clm3%g%l%c%cnf%actual_immob sminn_to_plant => clm3%g%l%c%cnf%sminn_to_plant sminn_to_denit_excess => clm3%g%l%c%cnf%sminn_to_denit_excess supplement_to_sminn => clm3%g%l%c%cnf%supplement_to_sminn ! set time steps dt = real( get_step_size(), r8 ) ! set some space-and-time constant parameters dayscrecover = 30.0_r8 grperc = 0.3_r8 grpnow = 1.0_r8 bdnr = 0.5_r8 * (dt/86400._r8) ! loop over pfts to assess the total plant N demand do fp=1,num_soilp p = filter_soilp(fp) ! get the time step total gross photosynthesis ! this is coming from the canopy fluxes code, and is the ! gpp that is used to control stomatal conductance. ! For the nitrogen downregulation code, this is assumed ! to be the potential gpp, and the actual gpp will be ! reduced due to N limitation. ! Convert psn from umol/m2/s -> gC/m2/s ! The input psn (psnsun and psnsha) are expressed per unit LAI ! in the sunlit and shaded canopy, respectively. These need to be ! scaled by laisun and laisha to get the total gpp for allocation psnsun_to_cpool(p) = psnsun(p) * laisun(p) * 12.011e-6_r8 psnshade_to_cpool(p) = psnsha(p) * laisha(p) * 12.011e-6_r8 #if (defined C13) c13_psnsun_to_cpool(p) = c13_psnsun(p) * laisun(p) * 12.011e-6_r8 c13_psnshade_to_cpool(p) = c13_psnsha(p) * laisha(p) * 12.011e-6_r8 #endif gpp(p) = psnsun_to_cpool(p) + psnshade_to_cpool(p) ! get the time step total maintenance respiration ! These fluxes should already be in gC/m2/s mr = leaf_mr(p) + froot_mr(p) if (woody(ivt(p)) == 1.0_r8) then mr = mr + livestem_mr(p) + livecroot_mr(p) end if ! carbon flux available for allocation availc(p) = gpp(p) - mr ! new code added for isotope calculations, 7/1/05, PET ! If mr > gpp, then some mr comes from gpp, the rest comes from ! cpool (xsmr) curmr_ratio = 1._r8 if (mr > 0._r8 .and. availc(p) < 0._r8) then curmr = gpp(p) curmr_ratio = curmr / mr end if leaf_curmr(p) = leaf_mr(p) * curmr_ratio leaf_xsmr(p) = leaf_mr(p) - leaf_curmr(p) froot_curmr(p) = froot_mr(p) * curmr_ratio froot_xsmr(p) = froot_mr(p) - froot_curmr(p) livestem_curmr(p) = livestem_mr(p) * curmr_ratio livestem_xsmr(p) = livestem_mr(p) - livestem_curmr(p) livecroot_curmr(p) = livecroot_mr(p) * curmr_ratio livecroot_xsmr(p) = livecroot_mr(p) - livecroot_curmr(p) ! no allocation when available c is negative availc(p) = max(availc(p),0.0_r8) ! test for an xsmrpool deficit if (xsmrpool(p) < 0.0_r8) then ! Running a deficit in the xsmrpool, so the first priority is to let ! some availc from this timestep accumulate in xsmrpool. ! Determine rate of recovery for xsmrpool deficit xsmrpool_recover(p) = -xsmrpool(p)/(dayscrecover*86400.0_r8) if (xsmrpool_recover(p) < availc(p)) then ! available carbon reduced by amount for xsmrpool recovery availc(p) = availc(p) - xsmrpool_recover(p) else ! all of the available carbon goes to xsmrpool recovery xsmrpool_recover(p) = availc(p) availc(p) = 0.0_r8 end if cpool_to_xsmrpool(p) = xsmrpool_recover(p) end if f1 = froot_leaf(ivt(p)) f2 = croot_stem(ivt(p)) ! modified wood allocation to be 2.2 at npp=800 gC/m2/yr, 0.2 at npp=0, ! constrained so that it does not go lower than 0.2 (under negative annsum_npp) ! This variable allocation is only for trees. Shrubs have a constant ! allocation as specified in the pft-physiology file. The value is also used ! as a trigger here: -1.0 means to use the dynamic allocation (trees). if (stem_leaf(ivt(p)) == -1._r8) then f3 = (2.7/(1.0+exp(-0.004*(annsum_npp(p) - 300.0)))) - 0.4 else f3 = stem_leaf(ivt(p)) end if f4 = flivewd(ivt(p)) g1 = grperc g2 = grpnow cnl = leafcn(ivt(p)) cnfr = frootcn(ivt(p)) cnlw = livewdcn(ivt(p)) cndw = deadwdcn(ivt(p)) ! based on available C, use constant allometric relationships to ! determine N requirements if (woody(ivt(p)) == 1.0_r8) then c_allometry(p) = (1._r8+g1)*(1._r8+f1+f3*(1._r8+f2)) n_allometry(p) = 1._r8/cnl + f1/cnfr + (f3*f4*(1._r8+f2))/cnlw + & (f3*(1._r8-f4)*(1._r8+f2))/cndw else c_allometry(p) = 1._r8+g1+f1+f1*g1 n_allometry(p) = 1._r8/cnl + f1/cnfr end if plant_ndemand(p) = availc(p)*(n_allometry(p)/c_allometry(p)) ! retranslocated N deployment depends on seasonal cycle of potential GPP ! (requires one year run to accumulate demand) tempsum_potential_gpp(p) = tempsum_potential_gpp(p) + gpp(p) ! Adding the following line to carry max retransn info to CN Annual Update tempmax_retransn(p) = max(tempmax_retransn(p),retransn(p)) if (annsum_potential_gpp(p) > 0.0_r8) then avail_retransn(p) = (annmax_retransn(p)/2.0)*(gpp(p)/annsum_potential_gpp(p))/dt else avail_retransn(p) = 0.0_r8 end if ! make sure available retrans N doesn't exceed storage avail_retransn(p) = min(avail_retransn(p), retransn(p)/dt) ! modify plant N demand according to the availability of ! retranslocated N ! take from retransn pool at most the flux required to meet ! plant ndemand if (plant_ndemand(p) > avail_retransn(p)) then retransn_to_npool(p) = avail_retransn(p) else retransn_to_npool(p) = plant_ndemand(p) end if plant_ndemand(p) = plant_ndemand(p) - retransn_to_npool(p) end do ! end pft loop ! now use the p2c routine to get the column-averaged plant_ndemand allocate(col_plant_ndemand(lbc:ubc)) call p2c(num_soilc,filter_soilc,plant_ndemand,col_plant_ndemand) ! column loop to resolve plant/heterotroph competition for mineral N do fc=1,num_soilc c = filter_soilc(fc) sum_ndemand = col_plant_ndemand(c) + potential_immob(c) if (sum_ndemand*dt < sminn(c)) then ! N availability is not limiting immobilization of plant ! uptake, and both can proceed at their potential rates nlimit = 0 fpi(c) = 1.0_r8 actual_immob(c) = potential_immob(c) sminn_to_plant(c) = col_plant_ndemand(c) ! under conditions of excess N, some proportion is assumed to ! be lost to denitrification, in addition to the constant ! proportion lost in the decomposition pathways sminn_to_denit_excess(c) = bdnr*((sminn(c)/dt) - sum_ndemand) else if ( .not. Carbon_only )then ! N availability can not satisfy the sum of immobilization and ! plant growth demands, so these two demands compete for available ! soil mineral N resource. nlimit = 1 if (sum_ndemand > 0.0_r8) then actual_immob(c) = (sminn(c)/dt)*(potential_immob(c) / sum_ndemand) else actual_immob(c) = 0.0_r8 end if if (potential_immob(c) > 0.0_r8) then fpi(c) = actual_immob(c) / potential_immob(c) else fpi(c) = 0.0_r8 end if sminn_to_plant(c) = (sminn(c)/dt) - actual_immob(c) else ! this code block controls the addition of N to sminn pool ! to eliminate any N limitation, when Carbon_Only is set. This lets the ! model behave essentially as a carbon-only model, but with the ! benefit of keeping trrack of the N additions needed to ! eliminate N limitations, so there is still a diagnostic quantity ! that describes the degree of N limitation at steady-state. nlimit = 1 fpi(c) = 1.0_r8 actual_immob(c) = potential_immob(c) sminn_to_plant(c) = col_plant_ndemand(c) supplement_to_sminn(c) = sum_ndemand - (sminn(c)/dt) end if ! calculate the fraction of potential growth that can be ! acheived with the N available to plants if (col_plant_ndemand(c) > 0.0_r8) then fpg(c) = sminn_to_plant(c) / col_plant_ndemand(c) else fpg(c) = 1.0_r8 end if end do ! end of column loop ! start new pft loop to distribute the available N between the ! competing pfts on the basis of relative demand, and allocate C and N to ! new growth and storage do fp=1,num_soilp p = filter_soilp(fp) c = pcolumn(p) ! set some local allocation variables f1 = froot_leaf(ivt(p)) f2 = croot_stem(ivt(p)) ! modified wood allocation to be 2.2 at npp=800 gC/m2/yr, 0.2 at npp=0, ! constrained so that it does not go lower than 0.2 (under negative annsum_npp) ! There was an error in this formula in previous version, where the coefficient ! was 0.004 instead of 0.0025. ! This variable allocation is only for trees. Shrubs have a constant ! allocation as specified in the pft-physiology file. The value is also used ! as a trigger here: -1.0 means to use the dynamic allocation (trees). if (stem_leaf(ivt(p)) == -1._r8) then f3 = (2.7/(1.0+exp(-0.004*(annsum_npp(p) - 300.0)))) - 0.4 else f3 = stem_leaf(ivt(p)) end if f4 = flivewd(ivt(p)) g1 = grperc g2 = grpnow cnl = leafcn(ivt(p)) cnfr = frootcn(ivt(p)) cnlw = livewdcn(ivt(p)) cndw = deadwdcn(ivt(p)) fcur = fcur2(ivt(p)) ! increase fcur linearly with ndays_active, until fcur reaches 1.0 at ! ndays_active = 365. This prevents the continued storage of C and N. ! turning off this correction (PET, 12/11/03), instead using bgtr in ! phenology algorithm. !fcur = fcur + (1._r8 - fcur)*lgsf(p) sminn_to_npool(p) = plant_ndemand(p) * fpg(c) plant_nalloc(p) = sminn_to_npool(p) + retransn_to_npool(p) ! calculate the associated carbon allocation, and the excess ! carbon flux that must be accounted for through downregulation plant_calloc(p) = plant_nalloc(p) * (c_allometry(p)/n_allometry(p)) excess_cflux(p) = availc(p) - plant_calloc(p) ! reduce gpp fluxes due to N limitation if (gpp(p) > 0.0_r8) then downreg(p) = excess_cflux(p)/gpp(p) psnsun_to_cpool(p) = psnsun_to_cpool(p)*(1._r8 - downreg(p)) psnshade_to_cpool(p) = psnshade_to_cpool(p)*(1._r8 - downreg(p)) #if (defined C13) c13_psnsun_to_cpool(p) = c13_psnsun_to_cpool(p)*(1._r8 - downreg(p)) c13_psnshade_to_cpool(p) = c13_psnshade_to_cpool(p)*(1._r8 - downreg(p)) #endif end if ! calculate the amount of new leaf C dictated by these allocation ! decisions, and calculate the daily fluxes of C and N to current ! growth and storage pools ! fcur is the proportion of this day's growth that is displayed now, ! the remainder going into storage for display next year through the ! transfer pools nlc = plant_calloc(p) / c_allometry(p) cpool_to_leafc(p) = nlc * fcur cpool_to_leafc_storage(p) = nlc * (1._r8 - fcur) cpool_to_frootc(p) = nlc * f1 * fcur cpool_to_frootc_storage(p) = nlc * f1 * (1._r8 - fcur) if (woody(ivt(p)) == 1._r8) then cpool_to_livestemc(p) = nlc * f3 * f4 * fcur cpool_to_livestemc_storage(p) = nlc * f3 * f4 * (1._r8 - fcur) cpool_to_deadstemc(p) = nlc * f3 * (1._r8 - f4) * fcur cpool_to_deadstemc_storage(p) = nlc * f3 * (1._r8 - f4) * (1._r8 - fcur) cpool_to_livecrootc(p) = nlc * f2 * f3 * f4 * fcur cpool_to_livecrootc_storage(p) = nlc * f2 * f3 * f4 * (1._r8 - fcur) cpool_to_deadcrootc(p) = nlc * f2 * f3 * (1._r8 - f4) * fcur cpool_to_deadcrootc_storage(p) = nlc * f2 * f3 * (1._r8 - f4) * (1._r8 - fcur) end if ! corresponding N fluxes npool_to_leafn(p) = (nlc / cnl) * fcur npool_to_leafn_storage(p) = (nlc / cnl) * (1._r8 - fcur) npool_to_frootn(p) = (nlc * f1 / cnfr) * fcur npool_to_frootn_storage(p) = (nlc * f1 / cnfr) * (1._r8 - fcur) if (woody(ivt(p)) == 1._r8) then npool_to_livestemn(p) = (nlc * f3 * f4 / cnlw) * fcur npool_to_livestemn_storage(p) = (nlc * f3 * f4 / cnlw) * (1._r8 - fcur) npool_to_deadstemn(p) = (nlc * f3 * (1._r8 - f4) / cndw) * fcur npool_to_deadstemn_storage(p) = (nlc * f3 * (1._r8 - f4) / cndw) * (1._r8 - fcur) npool_to_livecrootn(p) = (nlc * f2 * f3 * f4 / cnlw) * fcur npool_to_livecrootn_storage(p) = (nlc * f2 * f3 * f4 / cnlw) * (1._r8 - fcur) npool_to_deadcrootn(p) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * fcur npool_to_deadcrootn_storage(p) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * (1._r8 - fcur) end if ! Calculate the amount of carbon that needs to go into growth ! respiration storage to satisfy all of the storage growth demands. ! Allows for the fraction of growth respiration that is released at the ! time of fixation, versus the remaining fraction that is stored for ! release at the time of display. Note that all the growth respiration ! fluxes that get released on a given timestep are calculated in growth_resp(), ! but that the storage of C for growth resp during display of transferred ! growth is assigned here. gresp_storage = cpool_to_leafc_storage(p) + cpool_to_frootc_storage(p) if (woody(ivt(p)) == 1._r8) then gresp_storage = gresp_storage + cpool_to_livestemc_storage(p) gresp_storage = gresp_storage + cpool_to_deadstemc_storage(p) gresp_storage = gresp_storage + cpool_to_livecrootc_storage(p) gresp_storage = gresp_storage + cpool_to_deadcrootc_storage(p) end if cpool_to_gresp_storage(p) = gresp_storage * g1 * (1._r8 - g2) end do ! end pft loop deallocate(col_plant_ndemand) end subroutine CNAllocation #endif end module CNAllocationMod