diff --git a/clm5_params.c171117__FruitTree.nc b/clm5_params.c171117__FruitTree.nc new file mode 100644 index 0000000000..c5cf25c623 Binary files /dev/null and b/clm5_params.c171117__FruitTree.nc differ diff --git a/src/clm5/biogeochem/CNBalanceCheckMod.F90 b/src/clm5/biogeochem/CNBalanceCheckMod.F90 index 8f123cf442..499cad44c7 100644 --- a/src/clm5/biogeochem/CNBalanceCheckMod.F90 +++ b/src/clm5/biogeochem/CNBalanceCheckMod.F90 @@ -105,6 +105,7 @@ subroutine BeginCNBalance(this, bounds, num_soilc, filter_soilc, & c = filter_soilc(fc) col_begcb(c) = totcolc(c) col_begnb(c) = totcoln(c) + end do end associate @@ -161,10 +162,9 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & ! calculate the total column-level carbon storage, for mass conservation check col_endcb(c) = totcolc(c) - ! calculate total column-level inputs col_cinputs = gpp(c) - + ! calculate total column-level outputs ! er = ar + hr, col_fire_closs includes patch-level fire losses col_coutputs = er(c) + col_fire_closs(c) + col_hrv_xsmrpool_to_atm(c) + & @@ -181,7 +181,7 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & ! subtract leaching flux col_coutputs = col_coutputs - som_c_leached(c) - + ! calculate the total column-level carbon balance error for this time step col_errcb(c) = (col_cinputs - col_coutputs)*dt - & (col_endcb(c) - col_begcb(c)) diff --git a/src/clm5/biogeochem/CNCIsoFluxMod.F90 b/src/clm5/biogeochem/CNCIsoFluxMod.F90 index a92ab44e47..63d1796f46 100644 --- a/src/clm5/biogeochem/CNCIsoFluxMod.F90 +++ b/src/clm5/biogeochem/CNCIsoFluxMod.F90 @@ -135,7 +135,7 @@ subroutine CIsoFlux1(num_soilc, filter_soilc, num_soilp, filter_soilp, & iso_cnveg_cf%frootc_to_litter_patch , cnveg_cf%frootc_to_litter_patch, & iso_cnveg_cs%frootc_patch , cnveg_cs%frootc_patch, & num_soilp , filter_soilp, 1._r8, 0, isotope) - + call CIsoFluxCalc(& iso_cnveg_cf%livestemc_to_deadstemc_patch , cnveg_cf%livestemc_to_deadstemc_patch, & iso_cnveg_cs%livestemc_patch , cnveg_cs%livestemc_patch, & @@ -414,6 +414,17 @@ subroutine CIsoFlux1(num_soilc, filter_soilc, num_soilp, filter_soilp, & iso_cnveg_cs%totvegc_patch , cnveg_cs%totvegc_patch, & num_soilp , filter_soilp, 1._r8, 0, isotope) + call CIsoFluxCalc(& + iso_cnveg_cf%crop_seedc_to_froot_patch , cnveg_cf%crop_seedc_to_froot_patch, & + iso_cnveg_cs%totvegc_patch , cnveg_cs%totvegc_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%crop_seedc_to_deadstem_patch , cnveg_cf%crop_seedc_to_deadstem_patch, & + iso_cnveg_cs%totvegc_patch , cnveg_cs%totvegc_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& iso_cnveg_cf%grain_curmr_patch , cnveg_cf%grain_curmr_patch, & iso_cnveg_cs%cpool_patch , cnveg_cs%cpool_patch, & @@ -1222,7 +1233,7 @@ subroutine CNCIsoLitterToColumn (num_soilc, filter_soilc, & + frootc_to_litter(p) * fr_fcel(ivt(p)) * wtcol(p) * froot_prof(p,j) phenology_c_to_litr_lig_c(c,j) = phenology_c_to_litr_lig_c(c,j) & + frootc_to_litter(p) * fr_flig(ivt(p)) * wtcol(p) * froot_prof(p,j) - + !DML if (ivt(p) >= npcropmin) then ! add livestemc to litter ! stem litter carbon fluxes @@ -1492,7 +1503,6 @@ subroutine CNCIsoHarvestPftToColumn (num_soilc, filter_soilc, & hrv_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & hrv_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) - ! storage harvest mortality carbon fluxes harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & hrv_leafc_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) diff --git a/src/clm5/biogeochem/CNCStateUpdate1Mod.F90 b/src/clm5/biogeochem/CNCStateUpdate1Mod.F90 index e1da2f354f..ed96b33192 100644 --- a/src/clm5/biogeochem/CNCStateUpdate1Mod.F90 +++ b/src/clm5/biogeochem/CNCStateUpdate1Mod.F90 @@ -173,7 +173,8 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) - + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types (1=perennial, 0= not perennial) + mulch_pruning => pftcon%mulch_pruning , & ! Input: binary flag for mulching or exporting pruning material (1=mulching, 0=exporting) cascade_donor_pool => decomp_cascade_con%cascade_donor_pool , & ! Input: [integer (:) ] which pool is C taken from for a given decomposition step cascade_receiver_pool => decomp_cascade_con%cascade_receiver_pool , & ! Input: [integer (:) ] which pool is C added to for a given decomposition step @@ -268,10 +269,15 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops ! lines here for consistency; the transfer terms are zero - cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) + cf_veg%livestemc_xfer_to_livestemc_patch(p)*dt - cs_veg%livestemc_xfer_patch(p) = cs_veg%livestemc_xfer_patch(p) - cf_veg%livestemc_xfer_to_livestemc_patch(p)*dt - cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) + cf_veg%grainc_xfer_to_grainc_patch(p)*dt - cs_veg%grainc_xfer_patch(p) = cs_veg%grainc_xfer_patch(p) - cf_veg%grainc_xfer_to_grainc_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) + cf_veg%grainc_xfer_to_grainc_patch(p)*dt + cs_veg%grainc_xfer_patch(p) = cs_veg%grainc_xfer_patch(p) - cf_veg%grainc_xfer_to_grainc_patch(p)*dt + else + cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) + cf_veg%livestemc_xfer_to_livestemc_patch(p)*dt + cs_veg%livestemc_xfer_patch(p) = cs_veg%livestemc_xfer_patch(p) - cf_veg%livestemc_xfer_to_livestemc_patch(p)*dt + cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) + cf_veg%grainc_xfer_to_grainc_patch(p)*dt + cs_veg%grainc_xfer_patch(p) = cs_veg%grainc_xfer_patch(p) - cf_veg%grainc_xfer_to_grainc_patch(p)*dt + end if end if ! phenology: litterfall fluxes @@ -286,12 +292,27 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%deadcrootc_patch(p) = cs_veg%deadcrootc_patch(p) + cf_veg%livecrootc_to_deadcrootc_patch(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) - cf_veg%livestemc_to_litter_patch(p)*dt - cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) & - - (cf_veg%grainc_to_food_patch(p) + cf_veg%grainc_to_seed_patch(p))*dt - cs_veg%cropseedc_deficit_patch(p) = cs_veg%cropseedc_deficit_patch(p) & - - cf_veg%crop_seedc_to_leaf_patch(p) * dt & - + cf_veg%grainc_to_seed_patch(p) * dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) & + - (cf_veg%grainc_to_food_patch(p) + cf_veg%grainc_to_seed_patch(p))*dt + cs_veg%cropseedc_deficit_patch(p) = cs_veg%cropseedc_deficit_patch(p) & + - cf_veg%crop_seedc_to_leaf_patch(p) * dt & + - cf_veg%crop_seedc_to_froot_patch(p) * dt & !(added by O.Dombrowski) + - cf_veg%crop_seedc_to_deadstem_patch(p) * dt & !(added by O.Dombrowski) + + cf_veg%grainc_to_seed_patch(p) * dt + if (mulch_pruning(ivt(p)) == 1._r8) then + ! update stem biomass after pruning + cs_veg%deadstemc_patch(p) = cs_veg%deadstemc_patch(p) - cf_veg%prunec_to_litter_patch(p)*dt + cs_veg%deadstemc_storage_patch(p) = cs_veg%deadstemc_storage_patch(p) - cf_veg%prunec_storage_to_litter_patch(p)*dt + end if + else + cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) - cf_veg%livestemc_to_litter_patch(p)*dt + cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) & + - (cf_veg%grainc_to_food_patch(p) + cf_veg%grainc_to_seed_patch(p))*dt + cs_veg%cropseedc_deficit_patch(p) = cs_veg%cropseedc_deficit_patch(p) & + - cf_veg%crop_seedc_to_leaf_patch(p) * dt & + + cf_veg%grainc_to_seed_patch(p) * dt + end if end if check_cpool = cs_veg%cpool_patch(p)- cf_veg%psnsun_to_cpool_patch(p)*dt-cf_veg%psnshade_to_cpool_patch(p)*dt @@ -302,13 +323,20 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_xsmrpool_patch(p)*dt cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%leaf_curmr_patch(p)*dt cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%froot_curmr_patch(p)*dt - If (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) == 1._r8) then cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%livestem_curmr_patch(p)*dt cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%livecroot_curmr_patch(p)*dt + end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%livestem_curmr_patch(p)*dt - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%grain_curmr_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%grain_curmr_patch(p)*dt + + else + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%livestem_curmr_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%grain_curmr_patch(p)*dt + + end if end if @@ -369,21 +397,31 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%deadcrootc_patch(p) = cs_veg%deadcrootc_patch(p) + cf_veg%cpool_to_deadcrootc_patch(p)*dt cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_deadcrootc_storage_patch(p)*dt cs_veg%deadcrootc_storage_patch(p) = cs_veg%deadcrootc_storage_patch(p) + cf_veg%cpool_to_deadcrootc_storage_patch(p)*dt + end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - if (carbon_resp_opt == 1) then + if (carbon_resp_opt == 1 .and. perennial(ivt(p)) == 0._r8) then !(perennial flag added by O.Dombrowski) cf_veg%cpool_to_livestemc_patch(p) = cf_veg%cpool_to_livestemc_patch(p) - cf_veg%cpool_to_livestemc_resp_patch(p) cf_veg%cpool_to_livestemc_storage_patch(p) = cf_veg%cpool_to_livestemc_storage_patch(p) - & cf_veg%cpool_to_livestemc_storage_resp_patch(p) end if - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_livestemc_patch(p)*dt - cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) + cf_veg%cpool_to_livestemc_patch(p)*dt - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_livestemc_storage_patch(p)*dt - cs_veg%livestemc_storage_patch(p) = cs_veg%livestemc_storage_patch(p) + cf_veg%cpool_to_livestemc_storage_patch(p)*dt - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_grainc_patch(p)*dt - cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) + cf_veg%cpool_to_grainc_patch(p)*dt - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_grainc_storage_patch(p)*dt - cs_veg%grainc_storage_patch(p) = cs_veg%grainc_storage_patch(p) + cf_veg%cpool_to_grainc_storage_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_grainc_patch(p)*dt + cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) + cf_veg%cpool_to_grainc_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_grainc_storage_patch(p)*dt + cs_veg%grainc_storage_patch(p) = cs_veg%grainc_storage_patch(p) + cf_veg%cpool_to_grainc_storage_patch(p)*dt + + else + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_livestemc_patch(p)*dt + cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) + cf_veg%cpool_to_livestemc_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_livestemc_storage_patch(p)*dt + cs_veg%livestemc_storage_patch(p) = cs_veg%livestemc_storage_patch(p) + cf_veg%cpool_to_livestemc_storage_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_grainc_patch(p)*dt + cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) + cf_veg%cpool_to_grainc_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_grainc_storage_patch(p)*dt + cs_veg%grainc_storage_patch(p) = cs_veg%grainc_storage_patch(p) + cf_veg%cpool_to_grainc_storage_patch(p)*dt + + end if end if ! growth respiration fluxes for current growth @@ -397,8 +435,12 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_deadcroot_gr_patch(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_livestem_gr_patch(p)*dt - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_grain_gr_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_grain_gr_patch(p)*dt + else + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_livestem_gr_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_grain_gr_patch(p)*dt + end if end if ! growth respiration for transfer growth @@ -411,8 +453,12 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) - cf_veg%transfer_deadcroot_gr_patch(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) - cf_veg%transfer_livestem_gr_patch(p)*dt - cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) - cf_veg%transfer_grain_gr_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) - cf_veg%transfer_grain_gr_patch(p)*dt + else + cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) - cf_veg%transfer_livestem_gr_patch(p)*dt + cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) - cf_veg%transfer_grain_gr_patch(p)*dt + end if end if ! growth respiration at time of storage @@ -426,10 +472,12 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_deadcroot_storage_gr_patch(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_livestem_storage_gr_patch(p)*dt - - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_grain_storage_gr_patch(p)*dt - + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_grain_storage_gr_patch(p)*dt + else + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_livestem_storage_gr_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_grain_storage_gr_patch(p)*dt + end if end if ! growth respiration stored for release during transfer growth @@ -454,16 +502,25 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) + cf_veg%gresp_storage_to_xfer_patch(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - ! lines here for consistency; the transfer terms are zero - cs_veg%livestemc_storage_patch(p) = cs_veg%livestemc_storage_patch(p) - cf_veg%livestemc_storage_to_xfer_patch(p)*dt - cs_veg%livestemc_xfer_patch(p) = cs_veg%livestemc_xfer_patch(p) + cf_veg%livestemc_storage_to_xfer_patch(p)*dt - cs_veg%grainc_storage_patch(p) = cs_veg%grainc_storage_patch(p) - cf_veg%grainc_storage_to_xfer_patch(p)*dt - cs_veg%grainc_xfer_patch(p) = cs_veg%grainc_xfer_patch(p) + cf_veg%grainc_storage_to_xfer_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%grainc_storage_patch(p) = cs_veg%grainc_storage_patch(p) - cf_veg%grainc_storage_to_xfer_patch(p)*dt + cs_veg%grainc_xfer_patch(p) = cs_veg%grainc_xfer_patch(p) + cf_veg%grainc_storage_to_xfer_patch(p)*dt + else + ! lines here for consistency; the transfer terms are zero + cs_veg%livestemc_storage_patch(p) = cs_veg%livestemc_storage_patch(p) - cf_veg%livestemc_storage_to_xfer_patch(p)*dt + cs_veg%livestemc_xfer_patch(p) = cs_veg%livestemc_xfer_patch(p) + cf_veg%livestemc_storage_to_xfer_patch(p)*dt + cs_veg%grainc_storage_patch(p) = cs_veg%grainc_storage_patch(p) - cf_veg%grainc_storage_to_xfer_patch(p)*dt + cs_veg%grainc_xfer_patch(p) = cs_veg%grainc_xfer_patch(p) + cf_veg%grainc_storage_to_xfer_patch(p)*dt + end if end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%livestem_xsmr_patch(p)*dt - cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%grain_xsmr_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1._r8) then + cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%grain_xsmr_patch(p)*dt + else + cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%livestem_xsmr_patch(p)*dt + cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%grain_xsmr_patch(p)*dt + end if if (harvdate(p) < 999) then ! beginning at harvest, send to atm ! TODO (mv, 11-02-2014) the following lines are why the cf_veg is ! an intent(inout) @@ -491,6 +548,7 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%xsmrpool_patch(p) = 0._r8 cs_veg%cpool_patch(p) = 0._r8 cs_veg%frootc_patch(p) = 0._r8 + end if ! Slowly release xsmrpool to atmosphere @@ -500,6 +558,7 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & ! update xsmrpool loss state cs_veg%xsmrpool_loss_patch(p) = cs_veg%xsmrpool_loss_patch(p) - cf_veg%xsmrpool_to_atm_patch(p) * dt + end if end if diff --git a/src/clm5/biogeochem/CNCStateUpdate2Mod.F90 b/src/clm5/biogeochem/CNCStateUpdate2Mod.F90 index ef1f6f9345..ef0d67dd36 100644 --- a/src/clm5/biogeochem/CNCStateUpdate2Mod.F90 +++ b/src/clm5/biogeochem/CNCStateUpdate2Mod.F90 @@ -178,7 +178,6 @@ subroutine CStateUpdate2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_soil%decomp_cpools_vr_col(c,j,i_lig_lit) + cf_veg%harvest_c_to_litr_lig_c_col(c,j) * dt cs_soil%decomp_cpools_vr_col(c,j,i_cwd) = & cs_soil%decomp_cpools_vr_col(c,j,i_cwd) + cf_veg%harvest_c_to_cwdc_col(c,j) * dt - ! wood to product pools - states updated in CNProducts end do end do @@ -201,7 +200,6 @@ subroutine CStateUpdate2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & - cf_veg%hrv_livecrootc_to_litter_patch(p) * dt cs_veg%deadcrootc_patch(p) = cs_veg%deadcrootc_patch(p) & - cf_veg%hrv_deadcrootc_to_litter_patch(p) * dt - ! xsmrpool cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) & - cf_veg%hrv_xsmrpool_to_atm_patch(p) * dt diff --git a/src/clm5/biogeochem/CNDriverMod.F90 b/src/clm5/biogeochem/CNDriverMod.F90 index 94bc3f3554..43dbcf5c6d 100644 --- a/src/clm5/biogeochem/CNDriverMod.F90 +++ b/src/clm5/biogeochem/CNDriverMod.F90 @@ -352,11 +352,12 @@ subroutine CNDriverNoLeaching(bounds, filter_soilp, num_pcropp, filter_pcropp, & doalb, waterstate_inst, temperature_inst, atm2lnd_inst, & crop_inst, canopystate_inst, soilstate_inst, dgvs_inst, & - cnveg_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & + cnveg_state_inst, soilbiogeochem_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp,1:nlevdecomp_full), & froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp,1:nlevdecomp_full), & + stem_prof_patch=soilbiogeochem_state_inst%stem_prof_patch(begp:endp,1:nlevdecomp_full), & phase=1) call t_stopf('CNPhenology_phase1') @@ -447,22 +448,24 @@ subroutine CNDriverNoLeaching(bounds, filter_soilp, num_pcropp, filter_pcropp, & doalb, waterstate_inst, temperature_inst, atm2lnd_inst, & crop_inst, canopystate_inst, soilstate_inst, dgvs_inst, & - cnveg_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & + cnveg_state_inst,soilbiogeochem_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp,1:nlevdecomp_full), & froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp,1:nlevdecomp_full), & + stem_prof_patch=soilbiogeochem_state_inst%stem_prof_patch(begp:endp,1:nlevdecomp_full), & phase=1) end if call CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & filter_soilp, num_pcropp, filter_pcropp, & doalb, waterstate_inst, temperature_inst, atm2lnd_inst, & crop_inst, canopystate_inst, soilstate_inst, dgvs_inst, & - cnveg_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & + cnveg_state_inst, soilbiogeochem_state_inst,cnveg_carbonstate_inst, cnveg_carbonflux_inst, & cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp,1:nlevdecomp_full), & froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp,1:nlevdecomp_full), & + stem_prof_patch=soilbiogeochem_state_inst%stem_prof_patch(begp:endp,1:nlevdecomp_full), & phase=2) call t_stopf('CNPhenology') diff --git a/src/clm5/biogeochem/CNFUNMod.F90 b/src/clm5/biogeochem/CNFUNMod.F90 index f1adee8f6b..3a97f40223 100644 --- a/src/clm5/biogeochem/CNFUNMod.F90 +++ b/src/clm5/biogeochem/CNFUNMod.F90 @@ -510,6 +510,7 @@ subroutine CNFUN(bounds,num_soilc, filter_soilc,num_soilp& ! -deciduous leaf habit (0 or 1) stress_decid => pftcon%stress_decid , & ! Input: binary flag for stress ! -deciduous leaf habit (0 or 1) + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types (0 or 1) a_fix => pftcon%a_fix , & ! Input: A BNF parameter b_fix => pftcon%b_fix , & ! Input: A BNF parameter c_fix => pftcon%c_fix , & ! Input: A BNF parameter @@ -1194,7 +1195,7 @@ subroutine CNFUN(bounds,num_soilc, filter_soilc,num_soilp& ! Calculate appropriate degree of retranslocation !------------------------------------------------------------------------------- - if(leafc(p).gt.0.0_r8.and.litterfall_n_step(p,istp)* fixerfrac>0.0_r8.and.ivt(p) 0.0_r8.and. (ivt(p) pftcon%leafcn , & ! Input: leaf C:N (gC/gN) frootcn => pftcon%frootcn , & ! Input: fine root C:N (gC/gN) livewdcn => pftcon%livewdcn , & ! Input: live wood (phloem and ray parenchyma) C:N (gC/gN) - + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types (1=perennial, 0=not perennial) + laisun => canopystate_inst%laisun_patch , & ! Input: [real(r8) (:)] sunlit projected leaf area index laisha => canopystate_inst%laisha_patch , & ! Input: [real(r8) (:)] shaded projected leaf area index @@ -147,19 +148,29 @@ subroutine CNGResp(num_soilp, filter_soilp, cnveg_carbonflux_inst, canopystate_i respfact_livestem_storage = 1.0_r8 if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cpool_livestem_gr(p) = cpool_to_livestemc(p) * grperc(ivt(p)) * respfact_livestem + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cpool_grain_gr(p) = cpool_to_grainc(p) * grperc(ivt(p)) - cpool_livestem_storage_gr(p) = cpool_to_livestemc_storage(p) * grperc(ivt(p)) * grpnow(ivt(p)) * & - respfact_livestem_storage + cpool_grain_storage_gr(p) = cpool_to_grainc_storage(p) * grperc(ivt(p)) * grpnow(ivt(p)) - transfer_livestem_gr(p) = livestemc_xfer_to_livestemc(p) * grperc(ivt(p)) * (1._r8 - grpnow(ivt(p))) * & - respfact_livestem_storage + transfer_grain_gr(p) = grainc_xfer_to_grainc(p) * grperc(ivt(p)) * (1._r8 - grpnow(ivt(p))) + + else + cpool_livestem_gr(p) = cpool_to_livestemc(p) * grperc(ivt(p)) * respfact_livestem + + cpool_livestem_storage_gr(p) = cpool_to_livestemc_storage(p) * grperc(ivt(p)) * grpnow(ivt(p)) * & + respfact_livestem_storage + + transfer_livestem_gr(p) = livestemc_xfer_to_livestemc(p) * grperc(ivt(p)) * (1._r8 - grpnow(ivt(p))) * & + respfact_livestem_storage - cpool_grain_gr(p) = cpool_to_grainc(p) * grperc(ivt(p)) + cpool_grain_gr(p) = cpool_to_grainc(p) * grperc(ivt(p)) - cpool_grain_storage_gr(p) = cpool_to_grainc_storage(p) * grperc(ivt(p)) * grpnow(ivt(p)) + cpool_grain_storage_gr(p) = cpool_to_grainc_storage(p) * grperc(ivt(p)) * grpnow(ivt(p)) - transfer_grain_gr(p) = grainc_xfer_to_grainc(p) * grperc(ivt(p)) * (1._r8 - grpnow(ivt(p))) + transfer_grain_gr(p) = grainc_xfer_to_grainc(p) * grperc(ivt(p)) * (1._r8 - grpnow(ivt(p))) + + end if end if ! leaf and fine root growth respiration @@ -203,6 +214,7 @@ subroutine CNGResp(num_soilp, filter_soilp, cnveg_carbonflux_inst, canopystate_i cpool_deadcroot_storage_gr(p) = cpool_to_deadcrootc_storage(p) * grperc(ivt(p)) * grpnow(ivt(p)) transfer_deadcroot_gr(p) = deadcrootc_xfer_to_deadcrootc(p) * grperc(ivt(p)) * (1._r8 - grpnow(ivt(p))) + end if end do diff --git a/src/clm5/biogeochem/CNGapMortalityMod.F90 b/src/clm5/biogeochem/CNGapMortalityMod.F90 index 939d4b52eb..31f6c1627b 100644 --- a/src/clm5/biogeochem/CNGapMortalityMod.F90 +++ b/src/clm5/biogeochem/CNGapMortalityMod.F90 @@ -128,7 +128,8 @@ subroutine CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_so associate( & ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type - woody => pftcon%woody , & ! Input: binary flag for woody lifeform + woody => pftcon%woody , & ! Input: binary flag for woody lifeform + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types greffic => dgvs_inst%greffic_patch , & ! Input: [real(r8) (:) ] heatstress => dgvs_inst%heatstress_patch , & ! Input: [real(r8) (:) ] @@ -235,7 +236,7 @@ subroutine CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_so cnveg_nitrogenflux_inst%m_deadcrootn_to_litter_patch(p) = cnveg_nitrogenstate_inst%deadcrootn_patch(p) * m end if - if (ivt(p) < npcropmin) then + if (ivt(p) < npcropmin .or. perennial(ivt(p)) == 1._r8) then ! perennial flag added by O.Dombrowski cnveg_nitrogenflux_inst%m_retransn_to_litter_patch(p) = cnveg_nitrogenstate_inst%retransn_patch(p) * m end if diff --git a/src/clm5/biogeochem/CNMRespMod.F90 b/src/clm5/biogeochem/CNMRespMod.F90 index 3a7052d0bb..51e5235840 100644 --- a/src/clm5/biogeochem/CNMRespMod.F90 +++ b/src/clm5/biogeochem/CNMRespMod.F90 @@ -176,7 +176,7 @@ subroutine CNMResp(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) - + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types (1=perennial, 0= not perennial) frac_veg_nosno => canopystate_inst%frac_veg_nosno_patch , & ! Input: [integer (:) ] fraction of vegetation not covered by snow (0 OR 1) [-] laisun => canopystate_inst%laisun_patch , & ! Input: [real(r8) (:) ] sunlit projected leaf area index laisha => canopystate_inst%laisha_patch , & ! Input: [real(r8) (:) ] shaded projected leaf area index @@ -264,6 +264,9 @@ subroutine CNMResp(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & if (woody(ivt(p)) == 1) then livestem_mr(p) = livestemn(p)*br*tc livecroot_mr(p) = livecrootn(p)*br_root*tc + if (perennial(ivt(p)) == 1._r8) then ! (added by O.Dombrowski) + grain_mr(p) = grainn(p)*br*tc + end if else if (ivt(p) >= npcropmin) then livestem_mr(p) = livestemn(p)*br*tc grain_mr(p) = grainn(p)*br*tc diff --git a/src/clm5/biogeochem/CNNStateUpdate1Mod.F90 b/src/clm5/biogeochem/CNNStateUpdate1Mod.F90 index 6c1d112029..72fcfca9c2 100644 --- a/src/clm5/biogeochem/CNNStateUpdate1Mod.F90 +++ b/src/clm5/biogeochem/CNNStateUpdate1Mod.F90 @@ -112,7 +112,8 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) - + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types (1=perennial, 0= not perennial) + mulch_pruning => pftcon%mulch_pruning , & ! Input: binary flag for exporting of mulching of pruning material (1=mulching, 0=exporting) nf_veg => cnveg_nitrogenflux_inst , & ! Input: ns_veg => cnveg_nitrogenstate_inst , & ! Output: nf_soil => soilbiogeochem_nitrogenflux_inst & ! Output: @@ -163,14 +164,22 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ns_veg%livecrootn_xfer_patch(p) = ns_veg%livecrootn_xfer_patch(p) - nf_veg%livecrootn_xfer_to_livecrootn_patch(p)*dt ns_veg%deadcrootn_patch(p) = ns_veg%deadcrootn_patch(p) + nf_veg%deadcrootn_xfer_to_deadcrootn_patch(p)*dt ns_veg%deadcrootn_xfer_patch(p) = ns_veg%deadcrootn_xfer_patch(p) - nf_veg%deadcrootn_xfer_to_deadcrootn_patch(p)*dt + end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops ! lines here for consistency; the transfer terms are zero - ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) + nf_veg%livestemn_xfer_to_livestemn_patch(p)*dt - ns_veg%livestemn_xfer_patch(p) = ns_veg%livestemn_xfer_patch(p) - nf_veg%livestemn_xfer_to_livestemn_patch(p)*dt - ns_veg%grainn_patch(p) = ns_veg%grainn_patch(p) + nf_veg%grainn_xfer_to_grainn_patch(p)*dt - ns_veg%grainn_xfer_patch(p) = ns_veg%grainn_xfer_patch(p) - nf_veg%grainn_xfer_to_grainn_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + ns_veg%grainn_patch(p) = ns_veg%grainn_patch(p) + nf_veg%grainn_xfer_to_grainn_patch(p)*dt + ns_veg%grainn_xfer_patch(p) = ns_veg%grainn_xfer_patch(p) - nf_veg%grainn_xfer_to_grainn_patch(p)*dt + + else + ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) + nf_veg%livestemn_xfer_to_livestemn_patch(p)*dt + ns_veg%livestemn_xfer_patch(p) = ns_veg%livestemn_xfer_patch(p) - nf_veg%livestemn_xfer_to_livestemn_patch(p)*dt + ns_veg%grainn_patch(p) = ns_veg%grainn_patch(p) + nf_veg%grainn_xfer_to_grainn_patch(p)*dt + ns_veg%grainn_xfer_patch(p) = ns_veg%grainn_xfer_patch(p) - nf_veg%grainn_xfer_to_grainn_patch(p)*dt + + end if end if ! phenology: litterfall and retranslocation fluxes @@ -189,18 +198,37 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ns_veg%deadcrootn_patch(p) = ns_veg%deadcrootn_patch(p) + nf_veg%livecrootn_to_deadcrootn_patch(p)*dt ns_veg%livecrootn_patch(p) = ns_veg%livecrootn_patch(p) - nf_veg%livecrootn_to_retransn_patch(p)*dt ns_veg%retransn_patch(p) = ns_veg%retransn_patch(p) + nf_veg%livecrootn_to_retransn_patch(p)*dt + end if if (ivt(p) >= npcropmin) then ! Beth adds retrans from froot - ns_veg%frootn_patch(p) = ns_veg%frootn_patch(p) - nf_veg%frootn_to_retransn_patch(p)*dt - ns_veg%retransn_patch(p) = ns_veg%retransn_patch(p) + nf_veg%frootn_to_retransn_patch(p)*dt - ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) - nf_veg%livestemn_to_litter_patch(p)*dt - ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) - nf_veg%livestemn_to_retransn_patch(p)*dt - ns_veg%retransn_patch(p) = ns_veg%retransn_patch(p) + nf_veg%livestemn_to_retransn_patch(p)*dt - ns_veg%grainn_patch(p) = ns_veg%grainn_patch(p) & - - (nf_veg%grainn_to_food_patch(p) + nf_veg%grainn_to_seed_patch(p))*dt - ns_veg%cropseedn_deficit_patch(p) = ns_veg%cropseedn_deficit_patch(p) & - - nf_veg%crop_seedn_to_leaf_patch(p) * dt & - + nf_veg%grainn_to_seed_patch(p) * dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + ns_veg%frootn_patch(p) = ns_veg%frootn_patch(p) - nf_veg%frootn_to_retransn_patch(p)*dt + ns_veg%retransn_patch(p) = ns_veg%retransn_patch(p) + nf_veg%frootn_to_retransn_patch(p)*dt + ns_veg%grainn_patch(p) = ns_veg%grainn_patch(p) & + - (nf_veg%grainn_to_food_patch(p) + nf_veg%grainn_to_seed_patch(p))*dt + ns_veg%cropseedn_deficit_patch(p) = ns_veg%cropseedn_deficit_patch(p) & + - nf_veg%crop_seedn_to_leaf_patch(p) * dt & + - nf_veg%crop_seedn_to_froot_patch(p) * dt & ! added by (O.Dombrowski) + - nf_veg%crop_seedn_to_deadstem_patch(p) * dt & ! added by (O.Dombrowski) + + nf_veg%grainn_to_seed_patch(p) * dt + if (mulch_pruning(ivt(p)) == 1._r8) then + ! update stem N after pruning + ns_veg%deadstemn_patch(p) = ns_veg%deadstemn_patch(p) - nf_veg%prunen_to_litter_patch(p)*dt + ns_veg%deadstemn_storage_patch(p) = ns_veg%deadstemn_storage_patch(p) - nf_veg%prunen_storage_to_litter_patch(p)*dt + end if + else + ns_veg%frootn_patch(p) = ns_veg%frootn_patch(p) - nf_veg%frootn_to_retransn_patch(p)*dt + ns_veg%retransn_patch(p) = ns_veg%retransn_patch(p) + nf_veg%frootn_to_retransn_patch(p)*dt + ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) - nf_veg%livestemn_to_litter_patch(p)*dt + ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) - nf_veg%livestemn_to_retransn_patch(p)*dt + ns_veg%retransn_patch(p) = ns_veg%retransn_patch(p) + nf_veg%livestemn_to_retransn_patch(p)*dt + ns_veg%grainn_patch(p) = ns_veg%grainn_patch(p) & + - (nf_veg%grainn_to_food_patch(p) + nf_veg%grainn_to_seed_patch(p))*dt + ns_veg%cropseedn_deficit_patch(p) = ns_veg%cropseedn_deficit_patch(p) & + - nf_veg%crop_seedn_to_leaf_patch(p) * dt & + + nf_veg%grainn_to_seed_patch(p) * dt + + end if end if ! uptake from soil mineral N pool @@ -240,17 +268,27 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ns_veg%deadcrootn_patch(p) = ns_veg%deadcrootn_patch(p) + nf_veg%npool_to_deadcrootn_patch(p)*dt ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_deadcrootn_storage_patch(p)*dt ns_veg%deadcrootn_storage_patch(p) = ns_veg%deadcrootn_storage_patch(p) + nf_veg%npool_to_deadcrootn_storage_patch(p)*dt + end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_livestemn_patch(p)*dt - ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) + nf_veg%npool_to_livestemn_patch(p)*dt - ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_livestemn_storage_patch(p)*dt - ns_veg%livestemn_storage_patch(p) = ns_veg%livestemn_storage_patch(p) + nf_veg%npool_to_livestemn_storage_patch(p)*dt - ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_grainn_patch(p)*dt - ns_veg%grainn_patch(p) = ns_veg%grainn_patch(p) + nf_veg%npool_to_grainn_patch(p)*dt - ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_grainn_storage_patch(p)*dt - ns_veg%grainn_storage_patch(p) = ns_veg%grainn_storage_patch(p) + nf_veg%npool_to_grainn_storage_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_grainn_patch(p)*dt + ns_veg%grainn_patch(p) = ns_veg%grainn_patch(p) + nf_veg%npool_to_grainn_patch(p)*dt + ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_grainn_storage_patch(p)*dt + ns_veg%grainn_storage_patch(p) = ns_veg%grainn_storage_patch(p) + nf_veg%npool_to_grainn_storage_patch(p)*dt + + else + ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_livestemn_patch(p)*dt + ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) + nf_veg%npool_to_livestemn_patch(p)*dt + ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_livestemn_storage_patch(p)*dt + ns_veg%livestemn_storage_patch(p) = ns_veg%livestemn_storage_patch(p) + nf_veg%npool_to_livestemn_storage_patch(p)*dt + ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_grainn_patch(p)*dt + ns_veg%grainn_patch(p) = ns_veg%grainn_patch(p) + nf_veg%npool_to_grainn_patch(p)*dt + ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_grainn_storage_patch(p)*dt + ns_veg%grainn_storage_patch(p) = ns_veg%grainn_storage_patch(p) + nf_veg%npool_to_grainn_storage_patch(p)*dt + + end if end if ! move storage pools into transfer pools @@ -268,14 +306,22 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ns_veg%livecrootn_xfer_patch(p) = ns_veg%livecrootn_xfer_patch(p) + nf_veg%livecrootn_storage_to_xfer_patch(p)*dt ns_veg%deadcrootn_storage_patch(p) = ns_veg%deadcrootn_storage_patch(p) - nf_veg%deadcrootn_storage_to_xfer_patch(p)*dt ns_veg%deadcrootn_xfer_patch(p) = ns_veg%deadcrootn_xfer_patch(p) + nf_veg%deadcrootn_storage_to_xfer_patch(p)*dt + end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + ns_veg%grainn_storage_patch(p) = ns_veg%grainn_storage_patch(p) - nf_veg%grainn_storage_to_xfer_patch(p)*dt + ns_veg%grainn_xfer_patch(p) = ns_veg%grainn_xfer_patch(p) + nf_veg%grainn_storage_to_xfer_patch(p)*dt + ! lines here for consistency; the transfer terms are zero - ns_veg%livestemn_storage_patch(p) = ns_veg%livestemn_storage_patch(p) - nf_veg%livestemn_storage_to_xfer_patch(p)*dt - ns_veg%livestemn_xfer_patch(p) = ns_veg%livestemn_xfer_patch(p) + nf_veg%livestemn_storage_to_xfer_patch(p)*dt - ns_veg%grainn_storage_patch(p) = ns_veg%grainn_storage_patch(p) - nf_veg%grainn_storage_to_xfer_patch(p)*dt - ns_veg%grainn_xfer_patch(p) = ns_veg%grainn_xfer_patch(p) + nf_veg%grainn_storage_to_xfer_patch(p)*dt + else + ns_veg%livestemn_storage_patch(p) = ns_veg%livestemn_storage_patch(p) - nf_veg%livestemn_storage_to_xfer_patch(p)*dt + ns_veg%livestemn_xfer_patch(p) = ns_veg%livestemn_xfer_patch(p) + nf_veg%livestemn_storage_to_xfer_patch(p)*dt + ns_veg%grainn_storage_patch(p) = ns_veg%grainn_storage_patch(p) - nf_veg%grainn_storage_to_xfer_patch(p)*dt + ns_veg%grainn_xfer_patch(p) = ns_veg%grainn_xfer_patch(p) + nf_veg%grainn_storage_to_xfer_patch(p)*dt + + end if end if end do diff --git a/src/clm5/biogeochem/CNPhenologyMod.F90 b/src/clm5/biogeochem/CNPhenologyMod.F90 index 9d66373085..5e308d0aaa 100644 --- a/src/clm5/biogeochem/CNPhenologyMod.F90 +++ b/src/clm5/biogeochem/CNPhenologyMod.F90 @@ -21,6 +21,7 @@ module CNPhenologyMod use CanopyStateType , only : canopystate_type use CNDVType , only : dgvs_type use CNVegstateType , only : cnveg_state_type + use SoilBiogeochemStateType , only : soilbiogeochem_state_type use CNVegCarbonStateType , only : cnveg_carbonstate_type use CNVegCarbonFluxType , only : cnveg_carbonflux_type use CNVegnitrogenstateType , only : cnveg_nitrogenstate_type @@ -44,12 +45,12 @@ module CNPhenologyMod public :: CNPhenologyreadNML ! Read namelist public :: CNPhenologyInit ! Initialization public :: CNPhenology ! Update - ! + ! ! !PRIVATE DATA MEMBERS: type, private :: params_type real(r8) :: crit_dayl ! critical day length for senescence - real(r8) :: ndays_on ! number of days to complete leaf onset - real(r8) :: ndays_off ! number of days to complete leaf offset + real(r8) :: ndays_on ! number of days to complete leaf onset + real(r8) :: ndays_off ! number of days to complete leaf offset real(r8) :: fstor2tran ! fraction of storage to move to transfer for each onset real(r8) :: crit_onset_fdd ! critical number of freezing days to set gdd counter real(r8) :: crit_onset_swi ! critical number of days > soilpsi_on for onset @@ -57,7 +58,7 @@ module CNPhenologyMod real(r8) :: crit_offset_fdd ! critical number of freezing days to initiate offset real(r8) :: crit_offset_swi ! critical number of water stress days to initiate offset real(r8) :: soilpsi_off ! critical soil water potential for leaf offset - real(r8) :: lwtop ! live wood turnover proportion (annual fraction) + real(r8) :: lwtop ! live wood turnover proportion (annual fraction) end type params_type type(params_type) :: params_inst @@ -89,13 +90,13 @@ module CNPhenologyMod integer, allocatable :: minplantjday(:,:) ! minimum planting julian day integer, allocatable :: maxplantjday(:,:) ! maximum planting julian day + integer, allocatable :: maxharvjday(:,:) ! maximum harvest julian day (added by O.Dombrowski) integer :: jdayyrstart(inSH) ! julian day of start of year real(r8), private :: initial_seed_at_planting = 3._r8 ! Initial seed at planting character(len=*), parameter, private :: sourcefile = & __FILE__ - !----------------------------------------------------------------------- contains @@ -242,10 +243,10 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & filter_soilp, num_pcropp, filter_pcropp, & doalb, waterstate_inst, temperature_inst, atm2lnd_inst, crop_inst, & canopystate_inst, soilstate_inst, dgvs_inst, & - cnveg_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & + cnveg_state_inst, soilbiogeochem_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & - leaf_prof_patch, froot_prof_patch, phase) + leaf_prof_patch, froot_prof_patch,stem_prof_patch, phase) ! !USES: use CNSharedParamsMod, only: use_fun ! @@ -270,6 +271,7 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & type(soilstate_type) , intent(in) :: soilstate_inst type(dgvs_type) , intent(inout) :: dgvs_inst type(cnveg_state_type) , intent(inout) :: cnveg_state_inst + type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst type(cnveg_nitrogenstate_type) , intent(inout) :: cnveg_nitrogenstate_inst @@ -278,12 +280,13 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & type(cnveg_carbonstate_type) , intent(inout) :: c14_cnveg_carbonstate_inst real(r8) , intent(in) :: leaf_prof_patch(bounds%begp:,1:) real(r8) , intent(in) :: froot_prof_patch(bounds%begp:,1:) + real(r8) , intent(in) :: stem_prof_patch(bounds%begp:,1:) integer , intent(in) :: phase !----------------------------------------------------------------------- SHR_ASSERT_ALL((ubound(leaf_prof_patch) == (/bounds%endp,nlevdecomp_full/)), errMsg(sourcefile, __LINE__)) SHR_ASSERT_ALL((ubound(froot_prof_patch) == (/bounds%endp,nlevdecomp_full/)), errMsg(sourcefile, __LINE__)) - + SHR_ASSERT_ALL((ubound(stem_prof_patch) == (/bounds%endp,nlevdecomp_full/)), errMsg(sourcefile, __LINE__)) ! each of the following phenology type routines includes a filter ! to operate only on the relevant patches @@ -308,6 +311,11 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & waterstate_inst, temperature_inst, crop_inst, canopystate_inst, cnveg_state_inst, & cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst) + ! FruitTreePhenology routine has a special filter for deciduous tree crop pfts (added by O.Dombrowski) + call FruitTreePhenology(num_pcropp, filter_pcropp, & + waterstate_inst, temperature_inst, crop_inst, canopystate_inst, cnveg_state_inst, dgvs_inst, & + cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & + c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst) end if else if ( phase == 2 ) then ! the same onset and offset routines are called regardless of @@ -318,7 +326,7 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) call CNOffsetLitterfall(num_soilp, filter_soilp, & - cnveg_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) + crop_inst,cnveg_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) call CNBackgroundLitterfall(num_soilp, filter_soilp, & cnveg_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) @@ -331,10 +339,15 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & ! gather all patch-level litterfall fluxes to the column for litter C and N inputs - call CNLitterToColumn(bounds, num_soilc, filter_soilc, & - cnveg_state_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & + call CNLitterToColumn(bounds, num_soilc, filter_soilc, & + cnveg_state_inst,cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & leaf_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full), & - froot_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full)) + froot_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full), stem_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full)) + + call CNRotationToColumn (num_soilc, filter_soilc, & + cnveg_state_inst, soilbiogeochem_state_inst, crop_inst, cnveg_carbonflux_inst, & + cnveg_nitrogenflux_inst) + else call endrun( 'bad phase' ) end if @@ -525,7 +538,7 @@ subroutine CNEvergreenPhenology (num_soilp, filter_soilp , & integer :: p ! indices integer :: fp ! lake filter patch index - real(r8):: tranr + real(r8):: tranr real(r8):: t1 ! temporary variable !----------------------------------------------------------------------- @@ -538,59 +551,59 @@ subroutine CNEvergreenPhenology (num_soilp, filter_soilp , & woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) leafc_storage => cnveg_carbonstate_inst%leafc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) leaf C storage - frootc_storage => cnveg_carbonstate_inst%frootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) fine root C storage + frootc_storage => cnveg_carbonstate_inst%frootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) fine root C storage livestemc_storage => cnveg_carbonstate_inst%livestemc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) live stem C storage deadstemc_storage => cnveg_carbonstate_inst%deadstemc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) dead stem C storage - livecrootc_storage => cnveg_carbonstate_inst%livecrootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) live coarse root C storage - deadcrootc_storage => cnveg_carbonstate_inst%deadcrootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) dead coarse root C storage - gresp_storage => cnveg_carbonstate_inst%gresp_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) growth respiration storage - leafc_xfer => cnveg_carbonstate_inst%leafc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) leaf C transfer - frootc_xfer => cnveg_carbonstate_inst%frootc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) fine root C transfer - livestemc_xfer => cnveg_carbonstate_inst%livestemc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) live stem C transfer - deadstemc_xfer => cnveg_carbonstate_inst%deadstemc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) dead stem C transfer - livecrootc_xfer => cnveg_carbonstate_inst%livecrootc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) live coarse root C transfer - deadcrootc_xfer => cnveg_carbonstate_inst%deadcrootc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) dead coarse root C transfer - - leafn_storage => cnveg_nitrogenstate_inst%leafn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) leaf N storage - frootn_storage => cnveg_nitrogenstate_inst%frootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) fine root N storage - livestemn_storage => cnveg_nitrogenstate_inst%livestemn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) live stem N storage - deadstemn_storage => cnveg_nitrogenstate_inst%deadstemn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N storage - livecrootn_storage => cnveg_nitrogenstate_inst%livecrootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) live coarse root N storage - deadcrootn_storage => cnveg_nitrogenstate_inst%deadcrootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) dead coarse root N storage - leafn_xfer => cnveg_nitrogenstate_inst%leafn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) leaf N transfer - frootn_xfer => cnveg_nitrogenstate_inst%frootn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) fine root N transfer - livestemn_xfer => cnveg_nitrogenstate_inst%livestemn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) live stem N transfer - deadstemn_xfer => cnveg_nitrogenstate_inst%deadstemn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) dead stem N transfer - livecrootn_xfer => cnveg_nitrogenstate_inst%livecrootn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) live coarse root N transfer - deadcrootn_xfer => cnveg_nitrogenstate_inst%deadcrootn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) dead coarse root N transfer - - leafc_storage_to_xfer => cnveg_carbonflux_inst%leafc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - frootc_storage_to_xfer => cnveg_carbonflux_inst%frootc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - livestemc_storage_to_xfer => cnveg_carbonflux_inst%livestemc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - deadstemc_storage_to_xfer => cnveg_carbonflux_inst%deadstemc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - livecrootc_storage_to_xfer => cnveg_carbonflux_inst%livecrootc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - deadcrootc_storage_to_xfer => cnveg_carbonflux_inst%deadcrootc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - gresp_storage_to_xfer => cnveg_carbonflux_inst%gresp_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - leafc_xfer_to_leafc => cnveg_carbonflux_inst%leafc_xfer_to_leafc_patch , & ! InOut: [real(r8) (:)] - frootc_xfer_to_frootc => cnveg_carbonflux_inst%frootc_xfer_to_frootc_patch , & ! InOut: [real(r8) (:)] - livestemc_xfer_to_livestemc => cnveg_carbonflux_inst%livestemc_xfer_to_livestemc_patch , & ! InOut: [real(r8) (:)] - deadstemc_xfer_to_deadstemc => cnveg_carbonflux_inst%deadstemc_xfer_to_deadstemc_patch , & ! InOut: [real(r8) (:)] - livecrootc_xfer_to_livecrootc => cnveg_carbonflux_inst%livecrootc_xfer_to_livecrootc_patch , & ! InOut: [real(r8) (:)] - deadcrootc_xfer_to_deadcrootc => cnveg_carbonflux_inst%deadcrootc_xfer_to_deadcrootc_patch , & ! InOut: [real(r8) (:)] - - leafn_storage_to_xfer => cnveg_nitrogenflux_inst%leafn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - frootn_storage_to_xfer => cnveg_nitrogenflux_inst%frootn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - livestemn_storage_to_xfer => cnveg_nitrogenflux_inst%livestemn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - deadstemn_storage_to_xfer => cnveg_nitrogenflux_inst%deadstemn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - livecrootn_storage_to_xfer => cnveg_nitrogenflux_inst%livecrootn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - deadcrootn_storage_to_xfer => cnveg_nitrogenflux_inst%deadcrootn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - leafn_xfer_to_leafn => cnveg_nitrogenflux_inst%leafn_xfer_to_leafn_patch , & ! InOut: [real(r8) (:)] - frootn_xfer_to_frootn => cnveg_nitrogenflux_inst%frootn_xfer_to_frootn_patch , & ! InOut: [real(r8) (:)] - livestemn_xfer_to_livestemn => cnveg_nitrogenflux_inst%livestemn_xfer_to_livestemn_patch , & ! InOut: [real(r8) (:)] - deadstemn_xfer_to_deadstemn => cnveg_nitrogenflux_inst%deadstemn_xfer_to_deadstemn_patch , & ! InOut: [real(r8) (:)] - livecrootn_xfer_to_livecrootn => cnveg_nitrogenflux_inst%livecrootn_xfer_to_livecrootn_patch , & ! InOut: [real(r8) (:)] - deadcrootn_xfer_to_deadcrootn => cnveg_nitrogenflux_inst%deadcrootn_xfer_to_deadcrootn_patch , & ! InOut: [real(r8) (:)] - + livecrootc_storage => cnveg_carbonstate_inst%livecrootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) live coarse root C storage + deadcrootc_storage => cnveg_carbonstate_inst%deadcrootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) dead coarse root C storage + gresp_storage => cnveg_carbonstate_inst%gresp_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) growth respiration storage + leafc_xfer => cnveg_carbonstate_inst%leafc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) leaf C transfer + frootc_xfer => cnveg_carbonstate_inst%frootc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) fine root C transfer + livestemc_xfer => cnveg_carbonstate_inst%livestemc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) live stem C transfer + deadstemc_xfer => cnveg_carbonstate_inst%deadstemc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) dead stem C transfer + livecrootc_xfer => cnveg_carbonstate_inst%livecrootc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) live coarse root C transfer + deadcrootc_xfer => cnveg_carbonstate_inst%deadcrootc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) dead coarse root C transfer + + leafn_storage => cnveg_nitrogenstate_inst%leafn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) leaf N storage + frootn_storage => cnveg_nitrogenstate_inst%frootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) fine root N storage + livestemn_storage => cnveg_nitrogenstate_inst%livestemn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) live stem N storage + deadstemn_storage => cnveg_nitrogenstate_inst%deadstemn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N storage + livecrootn_storage => cnveg_nitrogenstate_inst%livecrootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) live coarse root N storage + deadcrootn_storage => cnveg_nitrogenstate_inst%deadcrootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) dead coarse root N storage + leafn_xfer => cnveg_nitrogenstate_inst%leafn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) leaf N transfer + frootn_xfer => cnveg_nitrogenstate_inst%frootn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) fine root N transfer + livestemn_xfer => cnveg_nitrogenstate_inst%livestemn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) live stem N transfer + deadstemn_xfer => cnveg_nitrogenstate_inst%deadstemn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) dead stem N transfer + livecrootn_xfer => cnveg_nitrogenstate_inst%livecrootn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) live coarse root N transfer + deadcrootn_xfer => cnveg_nitrogenstate_inst%deadcrootn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) dead coarse root N transfer + + leafc_storage_to_xfer => cnveg_carbonflux_inst%leafc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + frootc_storage_to_xfer => cnveg_carbonflux_inst%frootc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + livestemc_storage_to_xfer => cnveg_carbonflux_inst%livestemc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + deadstemc_storage_to_xfer => cnveg_carbonflux_inst%deadstemc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + livecrootc_storage_to_xfer => cnveg_carbonflux_inst%livecrootc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + deadcrootc_storage_to_xfer => cnveg_carbonflux_inst%deadcrootc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + gresp_storage_to_xfer => cnveg_carbonflux_inst%gresp_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + leafc_xfer_to_leafc => cnveg_carbonflux_inst%leafc_xfer_to_leafc_patch , & ! InOut: [real(r8) (:)] + frootc_xfer_to_frootc => cnveg_carbonflux_inst%frootc_xfer_to_frootc_patch , & ! InOut: [real(r8) (:)] + livestemc_xfer_to_livestemc => cnveg_carbonflux_inst%livestemc_xfer_to_livestemc_patch , & ! InOut: [real(r8) (:)] + deadstemc_xfer_to_deadstemc => cnveg_carbonflux_inst%deadstemc_xfer_to_deadstemc_patch , & ! InOut: [real(r8) (:)] + livecrootc_xfer_to_livecrootc => cnveg_carbonflux_inst%livecrootc_xfer_to_livecrootc_patch , & ! InOut: [real(r8) (:)] + deadcrootc_xfer_to_deadcrootc => cnveg_carbonflux_inst%deadcrootc_xfer_to_deadcrootc_patch , & ! InOut: [real(r8) (:)] + + leafn_storage_to_xfer => cnveg_nitrogenflux_inst%leafn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + frootn_storage_to_xfer => cnveg_nitrogenflux_inst%frootn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + livestemn_storage_to_xfer => cnveg_nitrogenflux_inst%livestemn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + deadstemn_storage_to_xfer => cnveg_nitrogenflux_inst%deadstemn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + livecrootn_storage_to_xfer => cnveg_nitrogenflux_inst%livecrootn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + deadcrootn_storage_to_xfer => cnveg_nitrogenflux_inst%deadcrootn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + leafn_xfer_to_leafn => cnveg_nitrogenflux_inst%leafn_xfer_to_leafn_patch , & ! InOut: [real(r8) (:)] + frootn_xfer_to_frootn => cnveg_nitrogenflux_inst%frootn_xfer_to_frootn_patch , & ! InOut: [real(r8) (:)] + livestemn_xfer_to_livestemn => cnveg_nitrogenflux_inst%livestemn_xfer_to_livestemn_patch , & ! InOut: [real(r8) (:)] + deadstemn_xfer_to_deadstemn => cnveg_nitrogenflux_inst%deadstemn_xfer_to_deadstemn_patch , & ! InOut: [real(r8) (:)] + livecrootn_xfer_to_livecrootn => cnveg_nitrogenflux_inst%livecrootn_xfer_to_livecrootn_patch , & ! InOut: [real(r8) (:)] + deadcrootn_xfer_to_deadcrootn => cnveg_nitrogenflux_inst%deadcrootn_xfer_to_deadcrootn_patch , & ! InOut: [real(r8) (:)] + bglfr => cnveg_state_inst%bglfr_patch , & ! Output: [real(r8) (:) ] background litterfall rate (1/s) bgtr => cnveg_state_inst%bgtr_patch , & ! Output: [real(r8) (:) ] background transfer growth rate (1/s) lgsf => cnveg_state_inst%lgsf_patch & ! Output: [real(r8) (:) ] long growing season factor [0-1] @@ -706,7 +719,7 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) season_decid => pftcon%season_decid , & ! Input: binary flag for seasonal-deciduous leaf habit (0 or 1) - + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types (0 or 1) t_soisno => temperature_inst%t_soisno_col , & ! Input: [real(r8) (:,:) ] soil temperature (Kelvin) (-nlevsno+1:nlevgrnd) pftmayexist => dgvs_inst%pftmayexist_patch , & ! Output: [logical (:) ] exclude seasonal decid patches from tropics @@ -787,7 +800,7 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & c = patch%column(p) g = patch%gridcell(p) - if (season_decid(ivt(p)) == 1._r8) then + if (season_decid(ivt(p)) == 1._r8 .and. perennial(ivt(p)) == 0._r8) then ! set background litterfall rate, background transfer rate, and ! long growing season factor to 0 for seasonal deciduous types @@ -797,7 +810,6 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & ! onset gdd sum from Biome-BGC, v4.1.2 crit_onset_gdd = exp(4.8_r8 + 0.13_r8*(annavg_t2m(p) - SHR_CONST_TKFRZ)) - ! set flag for solstice period (winter->summer = 1, summer->winter = 0) if (dayl(g) >= prev_dayl(g)) then ws_flag = 1._r8 @@ -1416,6 +1428,700 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & end subroutine CNStressDecidPhenology + !----------------------------------------------------------------------- + subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & + waterstate_inst, temperature_inst, crop_inst, canopystate_inst, cnveg_state_inst, dgvs_inst, & + cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst,& + c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst) + + ! !DESCRIPTION: + ! Code from AgroIBIS adapted for deciduous fruit trees by O. Dombrowski (2022) to determine crop phenology and code from CN to + ! handle CN fluxes during the phenological onset & offset periods. + ! New phenological stages and triggers, as well as management practices typical for fruit orchards are described + + ! !USES: + use shr_const_mod , only : SHR_CONST_TKFRZ + use clm_time_manager , only : get_curr_date, get_curr_calday, get_days_per_year, get_rad_step_size + use pftconMod , only : ncitrus ! the citrus PFT is used for now, separate PFTs for deciduous fruit tree species may be added in the future + use pftconMod , only : nirrig_citrus + use clm_varcon , only : spval, secspday + use clm_varctl , only : use_fertilizer + use clm_varctl , only : use_c13, use_c14 + use clm_varcon , only : c13ratio, c14ratio + ! + ! !ARGUMENTS: + integer , intent(in) :: num_pcropp ! number of prog crop patches in filter + integer , intent(in) :: filter_pcropp(:) ! filter for prognostic crop patches + type(waterstate_type) , intent(in) :: waterstate_inst + type(temperature_type) , intent(in) :: temperature_inst + type(crop_type) , intent(inout) :: crop_inst + type(canopystate_type) , intent(in) :: canopystate_inst + type(cnveg_state_type) , intent(inout) :: cnveg_state_inst + type(dgvs_type) , intent(inout) :: dgvs_inst + type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst + type(cnveg_nitrogenstate_type) , intent(inout) :: cnveg_nitrogenstate_inst + type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst + type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst + type(cnveg_carbonstate_type) , intent(inout) :: c13_cnveg_carbonstate_inst + type(cnveg_carbonstate_type) , intent(inout) :: c14_cnveg_carbonstate_inst + ! + ! LOCAL VARAIBLES: + integer kyr ! current year + integer kmo ! month of year (1, ..., 12) + integer kda ! day of month (1, ..., 31) + integer mcsec ! seconds of day (0, ..., seconds/day) + integer jday ! julian day of the year + integer fp,p ! patch indices + integer c ! column indices + integer g ! gridcell indices + integer h ! hemisphere indices + integer idpp ! number of days past planting + real(r8) :: dtrad ! radiation time step delta t (seconds) + real(r8) dayspyr ! days per year + real(r8) crmcorn ! comparitive relative maturity for corn + real(r8) nfertdays_on ! number of days to fertilize + real(r8):: ws_flag !winter-summer solstice flag (0 or 1) + real(r8):: crit_onset_gdd !critical onset growing degree-day sum + real(r8):: soilt + real(r8) :: Cd !chill day value + real(r8) :: Ca !anti-chill day value + + !------------------------------------------------------------------------ + + associate( & + ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type + dayl => grc%dayl , & ! Input: [real(r8) (:) ] daylength (s) + prev_dayl => grc%prev_dayl , & ! Input: [real(r8) (:) ] daylength from previous time step (s) + leaf_long => pftcon%leaf_long , & ! Input: leaf longevity (yrs) + leafcn => pftcon%leafcn , & ! Input: leaf C:N (gC/gN) + frootcn => pftcon%frootcn , & ! Input: fine root C:N (gC/gN) + livewdcn => pftcon%livewdcn , & ! Input: live wood C:N (gC/gN) + deadwdcn => pftcon%deadwdcn , & ! Input: dead wood C:N (gC/gN) + manunitro => pftcon%manunitro , & ! Input: max manure to be applied in total (kgN/m2) + mxmat => pftcon%mxmat , & ! Input: + minplanttemp => pftcon%minplanttemp , & ! Input: + planttemp => pftcon%planttemp , & ! Input: + gddmin => pftcon%gddmin , & ! Input: + hybgdd => pftcon%hybgdd , & ! Input: + grnfill => pftcon%grnfill , & ! Input: + lfmat => pftcon%lfmat , & ! Input: + grnrp => pftcon%grnrp , & ! Input: + transplant => pftcon%transplant , & ! Input: (O.Dombrowski) + woody => pftcon%woody , & ! Input: (O.Dombrowski) + season_decid => pftcon%season_decid , & ! Input: binary flag for seasonal-deciduous leaf habit (0 or 1) + baset => pftcon%baset , & ! Input: crop base temperature + ndays_stor => pftcon%ndays_stor , & ! Input: length of period for storage growth of fruit tree crops + crit_temp => pftcon%crit_temp , & ! Input: critical temperature to initiate leaf offset for fruit tree crops + crequ => pftcon%crequ , & ! Input: chilling requirements for fruit tree crops + + pftmayexist => dgvs_inst%pftmayexist_patch , & ! Output: [logical (:) ] exlude seasonal decid patches from tropics + + t_soisno => temperature_inst%t_soisno_col , & ! Input: [real(r8) (:,:) ] soil temperature (Kelvin) (-nlevsno+1:nlevgrnd) + + t_ref2m_min => temperature_inst%t_ref2m_min_patch , & ! Input: [real(r8) (:) ] daily minimum of average 2 m height surface air temperature (K) + t_ref2m_max => temperature_inst%t_ref2m_max_patch , & ! Input: [real(r8) (:) ] daily maximum of average 2 m height surface air temperature (K) + t_ref24 => temperature_inst%t_ref24_patch , & ! Input: [real(r8) (:) ] 24-hour averae 2 m air temperature (K) + t10 => temperature_inst%t_a10_patch , & ! Input: [real(r8) (:) ] 10-day running mean of the 2 m temperature (K) + a5tmin => temperature_inst%t_a5min_patch , & ! Input: [real(r8) (:) ] 5-day running mean of min 2-m temperature + a10tmin => temperature_inst%t_a10min_patch , & ! Input: [real(r8) (:) ] 10-day running mean of min 2-m temperature + gdd020 => temperature_inst%gdd020_patch , & ! Input: [real(r8) (:) ] 20 yr mean of gdd0 + gdd820 => temperature_inst%gdd820_patch , & ! Input: [real(r8) (:) ] 20 yr mean of gdd8 + gdd1020 => temperature_inst%gdd1020_patch , & ! Input: [real(r8) (:) ] 20 yr mean of gdd10 + + fertnitro => crop_inst%fertnitro_patch , & ! Input: [real(r8) (:) ] fertilizer nitrogen + hui => crop_inst%gddplant_patch , & ! Input: [real(r8) (:) ] gdd since planting (gddplant) + leafout => crop_inst%gddtsoi_patch , & ! Input: [real(r8) (:) ] gdd from top soil layer temperature + harvdate => crop_inst%harvdate_patch , & ! Output: [integer (:) ] harvest date + croplive => crop_inst%croplive_patch , & ! Output: [logical (:) ] Flag, true if planted, not harvested + cropplant => crop_inst%cropplant_patch , & ! Output: [logical (:) ] Flag, true if crop may be planted + vf => crop_inst%vf_patch , & ! Output: [real(r8) (:) ] vernalization factor + yrop => crop_inst%yrop_patch , & ! Output: [integer (:) ] year of planting (introduced in CLM-Palm (Fan et al. 2015), and adopted here by O.Dombrowski) + peaklai => cnveg_state_inst%peaklai_patch , & ! Output: [integer (:) ] 1: max allowed lai; 0: not at max + tlai => canopystate_inst%tlai_patch , & ! Input: [real(r8) (:) ] one-sided leaf area index, no burying by snow + + idop => cnveg_state_inst%idop_patch , & ! Output: [integer (:) ] date of planting + gddmaturity => cnveg_state_inst%gddmaturity_patch , & ! Output: [real(r8) (:) ] gdd needed to harvest + huileaf => cnveg_state_inst%huileaf_patch , & ! Output: [real(r8) (:) ] heat unit index at leaf emergence + huigrain => cnveg_state_inst%huigrain_patch , & ! Output: [real(r8) (:) ] heat unit index needed to reach start of fruit fill + huilfmat => cnveg_state_inst%huilfmat_patch , & ! Output: [real(r8) (:) ] heat unit index needed to reach canopy maturity (added by O.Dombrowski) + huiripe => cnveg_state_inst%huiripe_patch , & ! Output: [real(r8) (:) ] heat unit index needed to reach start of fruit cell expansion (added by O.Dombrowski) + bglfr => cnveg_state_inst%bglfr_patch , & ! Output: [real(r8) (:) ] background litterfall rate (1/s) + bgtr => cnveg_state_inst%bgtr_patch , & ! Output: [real(r8) (:) ] background transfer growth rate (1/s) + lgsf => cnveg_state_inst%lgsf_patch , & ! Output: [real(r8) (:) ] long growing season factor [0-1] + annavg_t2m => cnveg_state_inst%annavg_t2m_patch , & ! Input: [real(r8) (:) ] annual average 2m air temperature (K) + dormant_flag => cnveg_state_inst%dormant_flag_patch , & ! Output: [real(r8) (:) ] dormancy flag + days_active => cnveg_state_inst%days_active_patch , & ! Output: [real(r8) (:) ] number of days since last dormancy + onset_flag => cnveg_state_inst%onset_flag_patch , & ! Output: [real(r8) (:) ] onset flag + offset_flag => cnveg_state_inst%offset_flag_patch , & ! Output: [real(r8) (:) ] offset flag + offset2_flag => cnveg_state_inst%offset2_flag_patch , & ! Output: [real(r8) (:) ] orchard rotation flag + onset_counter => cnveg_state_inst%onset_counter_patch , & ! Output: [real(r8) (:) ] onset counter + offset_counter => cnveg_state_inst%offset_counter_patch , & ! Output: [real(r8) (:) ] offset counter + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop phenology (1=perennial, 0=not perennial) (introduced in CLM-Palm (Fan et al. 2015), and adopted here by O.Dombrowski) + harvest_flag => cnveg_state_inst%harvest_flag_patch , & ! Output: [real(r8) (:) ] harvest flag (introduced in CLM-Palm (Fan et al. 2015), and adopted here by O.Dombrowski) + prune_flag => cnveg_state_inst%prune_flag_patch , & ! Output: [real(r8) (:) ] pruning flag for perennials (introduced in CLM-Palm (Fan et al. 2015), and adopted here by O.Dombrowski) + storage_flag => cnveg_state_inst%storage_flag_patch , & ! Output: [real(r8) (:) ] flag to switch to storage growth for perennials (added by O.Dombrowski) + onset_gddflag => cnveg_state_inst%onset_gddflag_patch , & ! Output: [real(r8) (:) ] onset freeze flag + onset_gdd => cnveg_state_inst%onset_gdd_patch , & ! Output: [real(r8) (:) ] onset growing degree days + chill_day => cnveg_state_inst%chill_day_patch , & ! Output: [real(r8) (:) ] chilling days required for bud burst of fruit tree crops + anti_chill_day => cnveg_state_inst%anti_chill_day_patch , & ! Output: [real(r8) (:) ] anti-chill days required for bud burst of fruit tree crops + chill_flag => cnveg_state_inst%chill_flag_patch , & ! Output: [real(r8) (:) ] chill flag + + deadstemc => cnveg_carbonstate_inst%deadstemc_patch , & ! Input: [real(r8) (:) ] (gC/m2) deadstem C + leafc_storage => cnveg_carbonstate_inst%leafc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) leaf C storage + frootc_storage => cnveg_carbonstate_inst%frootc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) fine root C storage + livestemc_storage => cnveg_carbonstate_inst%livestemc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) live stem C storage + deadstemc_storage => cnveg_carbonstate_inst%deadstemc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) dead stem C storage + livecrootc_storage => cnveg_carbonstate_inst%livecrootc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) live coarse root C storage + deadcrootc_storage => cnveg_carbonstate_inst%deadcrootc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) dead coarse root C storage + gresp_storage => cnveg_carbonstate_inst%gresp_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) growth respiration storage + leafc_xfer => cnveg_carbonstate_inst%leafc_xfer_patch , & ! Output: [real(r8) (:) ] (gC/m2) leaf C transfer + frootc_xfer => cnveg_carbonstate_inst%frootc_xfer_patch , & ! Output: [real(r8) (:) ] (gC/m2) fine root C transfer + livestemc_xfer => cnveg_carbonstate_inst%livestemc_xfer_patch , & ! Output: [real(r8) (:) ] (gC/m2) live stem C transfer + deadstemc_xfer => cnveg_carbonstate_inst%deadstemc_xfer_patch , & ! Output: [real(r8) (:) ] (gC/m2) dead stem C transfer + livecrootc_xfer => cnveg_carbonstate_inst%livecrootc_xfer_patch , & ! Output: [real(r8) (:) ] (gC/m2) live coarse root C transfer + deadcrootc_xfer => cnveg_carbonstate_inst%deadcrootc_xfer_patch , & ! Output: [real(r8) (:) ] (gC/m2) dead coarse root C transfer + deadstemc_soy => cnveg_carbonstate_inst%deadstemc_soy_patch , & ! Output: [real(r8) (:) ] (gC/m2) dead stem C at start of year + deadstemc_storage_soy => cnveg_carbonstate_inst%deadstemc_storage_soy_patch , & ! Output: [real(r8) (:) ] (gC/m2) dead stem C storage at start of year + + + deadstemn => cnveg_nitrogenstate_inst%deadstemn_patch , & ! Input: [real(r8) (:) ] (gN/m2) deadstem N + leafn_storage => cnveg_nitrogenstate_inst%leafn_storage_patch , & ! Input: [real(r8) (:) ] (gN/m2) leaf N storage + frootn_storage => cnveg_nitrogenstate_inst%frootn_storage_patch , & ! Input: [real(r8) (:) ] (gN/m2) fine root N storage + livestemn_storage => cnveg_nitrogenstate_inst%livestemn_storage_patch , & ! Input: [real(r8) (:) ] (gN/m2) live stem N storage + deadstemn_storage => cnveg_nitrogenstate_inst%deadstemn_storage_patch , & ! Input: [real(r8) (:) ] (gN/m2) dead stem N storage + livecrootn_storage => cnveg_nitrogenstate_inst%livecrootn_storage_patch , & ! Input: [real(r8) (:) ] (gN/m2) live coarse root N storage + deadcrootn_storage => cnveg_nitrogenstate_inst%deadcrootn_storage_patch , & ! Input: [real(r8) (:) ] (gN/m2) dead coarse root N storage + leafn_xfer => cnveg_nitrogenstate_inst%leafn_xfer_patch , & ! Output: [real(r8) (:) ] (gN/m2) leaf N transfer + frootn_xfer => cnveg_nitrogenstate_inst%frootn_xfer_patch , & ! Output: [real(r8) (:) ] (gN/m2) fine root N transfer + livestemn_xfer => cnveg_nitrogenstate_inst%livestemn_xfer_patch , & ! Output: [real(r8) (:) ] (gN/m2) live stem N transfer + deadstemn_xfer => cnveg_nitrogenstate_inst%deadstemn_xfer_patch , & ! Output: [real(r8) (:) ] (gN/m2) dead stem N transfer + livecrootn_xfer => cnveg_nitrogenstate_inst%livecrootn_xfer_patch , & ! Output: [real(r8) (:) ] (gN/m2) live coarse root N transfer + deadcrootn_xfer => cnveg_nitrogenstate_inst%deadcrootn_xfer_patch , & ! Output: [real(r8) (:) ] (gN/m2) dead coarse root N transfer + deadstemn_soy => cnveg_nitrogenstate_inst%deadstemn_soy_patch , & ! Output: [real(r8) (:) ] (gN/m2) dead stem N at start of year + deadstemn_storage_soy => cnveg_nitrogenstate_inst%deadstemn_storage_soy_patch , & ! Output: [real(r8) (:) ] (gN/m2) dead stem N storage at start of year + + + prev_leafc_to_litter => cnveg_carbonflux_inst%prev_leafc_to_litter_patch , & ! Output: [real(r8) (:) ] previous timestep leaf C litterfall flux (gC/m2/s) + prev_frootc_to_litter => cnveg_carbonflux_inst%prev_frootc_to_litter_patch , & ! Output: [real(r8) (:) ] previous timestep froot C litterfall flux (gC/m2/s) + + leafc_xfer_to_leafc => cnveg_carbonflux_inst%leafc_xfer_to_leafc_patch , & ! Output: [real(r8) (:) ] + frootc_xfer_to_frootc => cnveg_carbonflux_inst%frootc_xfer_to_frootc_patch , & ! Output: [real(r8) (:) ] + livestemc_xfer_to_livestemc => cnveg_carbonflux_inst%livestemc_xfer_to_livestemc_patch , & ! Output: [real(r8) (:) ] + deadstemc_xfer_to_deadstemc => cnveg_carbonflux_inst%deadstemc_xfer_to_deadstemc_patch , & ! Output: [real(r8) (:) ] + livecrootc_xfer_to_livecrootc => cnveg_carbonflux_inst%livecrootc_xfer_to_livecrootc_patch , & ! Output: [real(r8) (:) ] + deadcrootc_xfer_to_deadcrootc => cnveg_carbonflux_inst%deadcrootc_xfer_to_deadcrootc_patch , & ! Output: [real(r8) (:) ] + leafc_storage_to_xfer => cnveg_carbonflux_inst%leafc_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + frootc_storage_to_xfer => cnveg_carbonflux_inst%frootc_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + livestemc_storage_to_xfer => cnveg_carbonflux_inst%livestemc_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + deadstemc_storage_to_xfer => cnveg_carbonflux_inst%deadstemc_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + livecrootc_storage_to_xfer => cnveg_carbonflux_inst%livecrootc_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + deadcrootc_storage_to_xfer => cnveg_carbonflux_inst%deadcrootc_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + gresp_storage_to_xfer => cnveg_carbonflux_inst%gresp_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + + leafn_xfer_to_leafn => cnveg_nitrogenflux_inst%leafn_xfer_to_leafn_patch , & ! Output: [real(r8) (:) ] + frootn_xfer_to_frootn => cnveg_nitrogenflux_inst%frootn_xfer_to_frootn_patch , & ! Output: [real(r8) (:) ] + livestemn_xfer_to_livestemn => cnveg_nitrogenflux_inst%livestemn_xfer_to_livestemn_patch , & ! Output: [real(r8) (:) ] + deadstemn_xfer_to_deadstemn => cnveg_nitrogenflux_inst%deadstemn_xfer_to_deadstemn_patch , & ! Output: [real(r8) (:) ] + livecrootn_xfer_to_livecrootn => cnveg_nitrogenflux_inst%livecrootn_xfer_to_livecrootn_patch , & ! Output: [real(r8) (:) ] + deadcrootn_xfer_to_deadcrootn => cnveg_nitrogenflux_inst%deadcrootn_xfer_to_deadcrootn_patch , & ! Output: [real(r8) (:) ] + leafn_storage_to_xfer => cnveg_nitrogenflux_inst%leafn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + frootn_storage_to_xfer => cnveg_nitrogenflux_inst%frootn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + livestemn_storage_to_xfer => cnveg_nitrogenflux_inst%livestemn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + deadstemn_storage_to_xfer => cnveg_nitrogenflux_inst%deadstemn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + livecrootn_storage_to_xfer => cnveg_nitrogenflux_inst%livecrootn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + deadcrootn_storage_to_xfer => cnveg_nitrogenflux_inst%deadcrootn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + + grainc => cnveg_carbonstate_inst%grainc_patch , & ! Input: [real(r8) (:) ] (gC/m2) grain C + + crop_seedc_to_leaf => cnveg_carbonflux_inst%crop_seedc_to_leaf_patch, & ! Output: [real(r8) (:) ] (gC/m2/s) seed source to leaf + crop_seedc_to_froot => cnveg_carbonflux_inst%crop_seedc_to_froot_patch, & ! Output: [real(r8) (:) ] (gC/m2/s) seed source to fine root + crop_seedc_to_deadstem => cnveg_carbonflux_inst%crop_seedc_to_deadstem_patch, & ! Output: [real(r8) (:) ] (gC/m2/s) seed source to deadstem + cropseedc_deficit => cnveg_carbonstate_inst%cropseedc_deficit_patch , & ! Output: [real(r8) (:) ] (gC/m2) crop seed C deficit + crop_seedn_to_leaf => cnveg_nitrogenflux_inst%crop_seedn_to_leaf_patch, & ! Output: [real(r8) (:) ] (gN/m2/s) seed source to leaf + crop_seedn_to_froot => cnveg_nitrogenflux_inst%crop_seedn_to_froot_patch, & ! Output: [real(r8) (:) ] (gN/m2/s) seed source to fine root + crop_seedn_to_deadstem => cnveg_nitrogenflux_inst%crop_seedn_to_deadstem_patch, & ! Output: [real(r8) (:) ] (gN/m2/s) seed source to deadstem + cropseedn_deficit => cnveg_nitrogenstate_inst%cropseedn_deficit_patch , & ! Output: [real(r8) (:) ] (gN/m2) crop seed N deficit + cphase => crop_inst%cphase_patch , & ! Output: [real(r8) (:)] phenology phase + fert_counter => cnveg_nitrogenflux_inst%fert_counter_patch , & ! Output: [real(r8) (:) ] >0 fertilize; <=0 not (seconds) + fert => cnveg_nitrogenflux_inst%fert_patch & ! Output: [real(r8) (:) ] (gN/m2/s) fertilizer applied each timestep + ) + + ! get time info + dayspyr = get_days_per_year() + jday = get_curr_calday() + call get_curr_date(kyr, kmo, kda, mcsec) + dtrad = real( get_rad_step_size(), r8 ) + + if (use_fertilizer) then + nfertdays_on = 20._r8 ! number of days to fertilize + else + nfertdays_on = 0._r8 ! number of days to fertilize + end if + + do fp = 1, num_pcropp + p = filter_pcropp(fp) + c = patch%column(p) + g = patch%gridcell(p) + h = inhemi(p) + + if (perennial(ivt(p)) == 1._r8) then ! flags for perennial crop phenology (added by O.Dombrowski) + + ! prepare planting if .not. croplive + if (.not. croplive(p)) then + cropplant(p) = .false. + idop(p) = NOT_PLANTED + end if + + ! background litterfall and transfer rates; long growing season factor + bglfr(p) = 0._r8 + bgtr(p) = 0._r8 + lgsf(p) = 0._r8 + + if (kmo == 1 .and. kda == 1 .and. mcsec == 0) then + ! get deadstem C and N at the start of the year + deadstemc_soy(p) = deadstemc(p) + deadstemc_storage_soy(p) = deadstemc_storage(p) + deadstemn_soy(p) = deadstemn(p) + deadstemn_storage_soy(p) = deadstemn_storage(p) + + end if + + if (season_decid(ivt(p)) == 1._r8) then + + ! set flag for solstice period (winter->summer = 1, summer->winter =0) + if (dayl(g) >= prev_dayl(g)) then + ws_flag = 1._r8 + else + ws_flag = 0._r8 + end if + + ! base temperature, or critical temperature for chill accumulation + tbase = baset(ivt(p)) + + ! set flag for start of chill period (chill_flag=1), + ! set latest date at which to initiate growing growing season even if chill/heat requirements are not met + if (h == 1) then ! for NH + if (kmo == 11 .and. kda == 1) then + chill_flag(p) = 1._r8 + end if + if (kmo == 7 .and. kda == 1 .and. chill_flag(p) == 1._r8) then + chill_day(p) = crequ(ivt(p)) + anti_chill_day(p) = -chill_day(p) + end if + else if (h == 2) then ! for SH + if (kmo == 5 .and. kda == 1) then + chill_flag(p) = 1._r8 + end if + if (kmo == 1 .and. kda == 1 .and. chill_flag(p) == 1._r8) then + chill_day(p) = crequ(ivt(p)) + anti_chill_day(p) = -chill_day(p) + end if + end if + end if + + ! Phase 1: Planting to leaf emergence + + if ( (.not. croplive(p)) .and. (.not. cropplant(p)) ) then + + if ((t10(p) /= spval.and. a10tmin(p) /= spval .and. & + t10(p) > planttemp(ivt(p)) .and. & + a10tmin(p) > minplanttemp(ivt(p)) .and. & + jday >= minplantjday(ivt(p),h) .and. & + jday <= maxplantjday(ivt(p),h) .and. & + t10(p) /= spval .and. a10tmin(p) /= spval .and. & + gdd820(p) /= spval .and. & + gdd820(p) >= gddmin(ivt(p))) .or. & + (jday == maxplantjday(ivt(p),h) .and. & + gdd820(p) > 0._r8 .and. & + gdd820(p) /= spval )) then + + + ! impose limit on growing season length needed + ! for crop maturity - for cold weather constraints + croplive(p) = .true. + cropplant(p) = .true. + idop(p) = jday + yrop(p) = kyr + harvdate(p) = NOT_Harvested + + ! Fruit trees are usually transplanted from nursery as small trees, code is adapted from the initiation for + ! deciduous trees and the transplanting of seedlings introduced in CLM-Palm (Fan et al. 2015), + ! initial gC m-2 is assigned to leaf, fine root and deadstem + ! (added by O.Dombrowski) + if (transplant(ivt(p)) > 0._r8) then + leafc_xfer(p) = transplant(ivt(p)) + else + leafc_xfer(p) = 1._r8 + end if + + frootc_xfer(p) = leafc_xfer(p) ! assign same amount of leafc to fine roots + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) ! with onset + frootn_xfer(p) = frootc_xfer(p) / frootcn(ivt(p)) + cropseedc_deficit(p) = cropseedc_deficit(p) - leafc_xfer(p) - frootc_xfer(p) + cropseedn_deficit(p) = cropseedn_deficit(p) - leafn_xfer(p) - frootn_xfer(p) + !for woody crops like fruit trees, assign 10% of initial C to deadstem + if (woody(ivt(p)) == 1._r8) then + deadstemc_xfer(p) = 0.1_r8*leafc_xfer(p) + deadstemn_xfer(p) = deadstemc_xfer(p)/deadwdcn(ivt(p)) + cropseedc_deficit(p) = cropseedc_deficit(p) - deadstemc_xfer(p) + cropseedn_deficit(p) = cropseedn_deficit(p) - deadstemn_xfer(p) + end if + end if + + + onset_counter(p) = 0.0_r8 ! CN terminology to trigger certain + offset_counter(p) = 0.0_r8 ! carbon and nitrogen transfers + onset_flag(p) = 0._r8 + offset_flag(p) = 0._r8 + offset2_flag(p) = 0._r8 + dormant_flag(p) = 1._r8 + + ! at planting of orchard, assume that chilling + ! requirements were already met in previous year and only + ! anti chill days need to be reached. + chill_day(p) = crequ(ivt(p)) + anti_chill_day(p) = 0._r8 + chill_flag(p) = 1._r8 + onset_gddflag(p) = 1._r8 + + harvest_flag(p) = 0._r8 ! annual harvest flag for perennial crops + end if ! crop not live nor planted + + ! ---------------------------------- + ! from AgroIBIS subroutine phenocrop + ! ---------------------------------- + + + if (croplive(p)) then + cphase(p) = 1._r8 + ! days past planting determine orchard rotation once maximum lifetime is reached + ! (introduced in CLM-Palm (Fan et al. 2015), and adopted here by O.Dombrowski) + idpp = int(dayspyr)*(kyr-yrop(p)) + jday - idop(p) + if (season_decid(ivt(p)) == 1._r8) then + + ! Test to turn on chill day accumulation. + ! If off, switch on chill day accumulation on + ! October 1st + if (onset_gddflag(p) == 0._r8 .and. chill_flag(p) == 1._r8) then + onset_gddflag(p) = 1._r8 + chill_day(p) = 0._r8 + anti_chill_day(p) = 0._r8 + end if + + ! Test to turn off chill day accumulation, if on. + ! This test resets the chill day accumulation if it gets past + ! May 1st without reaching the chill requirements. + ! In that case, it will take until the next autumn (October 1st) + ! before the chill day accumulation starts again. + + if (onset_gddflag(p) == 1._r8 .and. chill_flag(p) ==0._r8) then + onset_gddflag(p) = 0._r8 + chill_day(p) = 0._r8 + anti_chill_day(p) = 0._r8 + end if + + + ! if the gdd flag is set, and if the chill day + ! accumulation has not reached + ! chill requirements (crequ), accumulate chill days + ! for all equations temperatures must be in + ! degrees (C) + if (onset_gddflag(p) == 1._r8 .and. chill_day(p) > crequ(ivt(p))) then + if (t_ref2m_min(p) < 1.e30_r8) then + if (0._r8 <= tbase .and. tbase <= (t_ref2m_min(p)-tfrz) .and. t_ref2m_min(p)<= t_ref2m_max(p)) then + Cd = 0._r8 + else if (0._r8 <= (t_ref2m_min(p)-tfrz) .and. (t_ref2m_min(p)-tfrz)<= tbase .and. tbase < (t_ref2m_max(p)-tfrz)) then + Cd = -((t_ref24(p)-t_ref2m_min(p))-((t_ref2m_max(p)-tfrz)-tbase)**2/(2*(t_ref2m_max(p)-t_ref2m_min(p)))) + else if (0._r8 <= (t_ref2m_min(p)-tfrz) .and. t_ref2m_min(p) <= t_ref2m_max(p) .and. (t_ref2m_max(p)-tfrz) <= tbase) then + Cd = -(t_ref24(p)-t_ref2m_min(p)) + else if ((t_ref2m_min(p)-tfrz) < 0._r8 .and. 0._r8 <= (t_ref2m_max(p)-tfrz) .and. (t_ref2m_max(p)-tfrz) <= tbase) then + Cd = -((t_ref2m_max(p)-tfrz)**2/(2*(t_ref2m_max(p)-t_ref2m_min(p)))) + else if ((t_ref2m_min(p)-tfrz) < 0._r8 .and. 0._r8 < tbase .and. tbase < (t_ref2m_max(p)-tfrz)) then + Cd = -(t_ref2m_max(p)-tfrz)**2/(2*(t_ref2m_max(p)-t_ref2m_min(p))) - ((t_ref2m_max(p)-tfrz)-tbase)**2/(2*(t_ref2m_max(p)-t_ref2m_min(p))) + else + Cd = 0._r8 + end if + chill_day(p) = chill_day(p)+Cd + end if + end if + + ! if chill day accumulation has reached chill + ! requirements (crequ), accumulate anti chill days + if (onset_gddflag(p) == 1._r8 .and. chill_day(p) <= crequ(ivt(p))) then + if (t_ref2m_min(p) < 1.e30_r8) then + if (0._r8 <= tbase .and. tbase <= (t_ref2m_min(p)-tfrz) .and. t_ref2m_min(p) <= t_ref2m_max(p)) then + Ca = (t_ref24(p)-tfrz) - tbase + else if (0._r8 <= (t_ref2m_min(p)-tfrz) .and. (t_ref2m_min(p)-tfrz) <= tbase .and. tbase < (t_ref2m_max(p)-tfrz)) then + Ca = ((t_ref2m_max(p)-tfrz)-tbase)**2/(2*(t_ref2m_max(p)-t_ref2m_min(p))) + else if (0._r8 <= (t_ref2m_min(p)-tfrz) .and. t_ref2m_min(p) <= t_ref2m_max(p) .and. (t_ref2m_max(p)-tfrz) <= tbase) then + Ca = 0._r8 + else if ((t_ref2m_min(p)-tfrz) < 0._r8 .and. 0._r8 <= (t_ref2m_max(p)-tfrz) .and. (t_ref2m_max(p)-tfrz) <= tbase) then + Ca = 0._r8 + else if ((t_ref2m_min(p)-tfrz) < 0._r8 .and. 0._r8 < tbase .and. tbase < (t_ref2m_max(p)-tfrz)) then + Ca = ((t_ref2m_max(p)-tfrz)-tbase)**2/(2*(t_ref2m_max(p)-t_ref2m_min(p))) + else + Ca = 0._r8 + end if + anti_chill_day(p) = anti_chill_day(p)+Ca + end if + end if + + ! update offset_counter and test for the end of the offset period + if (offset_flag(p) == 1.0_r8) then + ! decrement counter for offset period + offset_counter(p) = offset_counter(p) - dt + prune_flag(p) = 1._r8 + + ! if this is the end of the offset_period, reset phenology + ! flags and indices + if (offset_counter(p) == 0.0_r8) then + offset_flag(p) = 0._r8 + offset_counter(p) = 0._r8 + dormant_flag(p) = 1._r8 + days_active(p) = 0._r8 + harvest_flag(p) = 0._r8 + storage_flag(p) = 0._r8 + if (use_cndv) then + pftmayexist(p) = .true. + end if + + ! reset the previous timestep litterfall flux memory + prev_leafc_to_litter(p) = 0._r8 + prev_frootc_to_litter(p) = 0._r8 + end if + end if + + ! update onset_counter and test for the end of the onset period + if (onset_flag(p) == 1.0_r8) then + ! decrement counter for onset period + onset_counter(p) = onset_counter(p) - dt + + ! if this is the end of the onset period, reset phenology + ! flags and indices + if (onset_counter(p) == 0.0_r8) then + onset_flag(p) = 0.0_r8 + onset_counter(p) = 0.0_r8 + ! set all transfer growth rates to 0.0 + leafc_xfer_to_leafc(p) = 0.0_r8 + frootc_xfer_to_frootc(p) = 0.0_r8 + leafn_xfer_to_leafn(p) = 0.0_r8 + frootn_xfer_to_frootn(p) = 0.0_r8 + if (woody(ivt(p)) == 1.0_r8) then + livestemc_xfer_to_livestemc(p) = 0.0_r8 + deadstemc_xfer_to_deadstemc(p) = 0.0_r8 + livecrootc_xfer_to_livecrootc(p) = 0.0_r8 + deadcrootc_xfer_to_deadcrootc(p) = 0.0_r8 + livestemn_xfer_to_livestemn(p) = 0.0_r8 + deadstemn_xfer_to_deadstemn(p) = 0.0_r8 + livecrootn_xfer_to_livecrootn(p) = 0.0_r8 + deadcrootn_xfer_to_deadcrootn(p) = 0.0_r8 + end if + ! set transfer pools to 0.0 + leafc_xfer(p) = 0.0_r8 + leafn_xfer(p) = 0.0_r8 + frootc_xfer(p) = 0.0_r8 + frootn_xfer(p) = 0.0_r8 + if (woody(ivt(p)) == 1.0_r8) then + livestemc_xfer(p) = 0.0_r8 + livestemn_xfer(p) = 0.0_r8 + deadstemc_xfer(p) = 0.0_r8 + deadstemn_xfer(p) = 0.0_r8 + livecrootc_xfer(p) = 0.0_r8 + livecrootn_xfer(p) = 0.0_r8 + deadcrootc_xfer(p) = 0.0_r8 + deadcrootn_xfer(p) = 0.0_r8 + end if + end if + end if + + ! test for switching from dormant period to growth period + if (dormant_flag(p) == 1._r8) then + ! Test if maximum orchard lifespan is reached and + ! orchard rotation should be initialized (adapted + ! based on CLM-Palm (Fan et al. 2015): + if (idpp >= mxmat(ivt(p))) then + croplive(p) = .false. + cphase(p) = 4._r8 + offset2_flag(p) = 1._r8 + end if + + prune_flag(p) = 0._r8 + + ! set onset_flag if critical growing degree-day sum is exceeded + if (anti_chill_day(p) > 0._r8 .and. anti_chill_day(p) >= (- chill_day(p))) then + cphase(p) = 2.0_r8 + + ! calculate gdd thresholds from bud burst (huileaf) + huileaf(p) = hui(p) + huigrain(p) = huileaf(p) + grnfill(ivt(p)) + huiripe(p) = huileaf(p) + grnrp(ivt(p)) + huilfmat(p) = huileaf(p) + lfmat(ivt(p)) + gddmaturity(p)= huileaf(p) + hybgdd(ivt(p)) + + ! reset parameters for bud burst calculation + chill_day(p) = 0._r8 + anti_chill_day(p) = 0._r8 + chill_flag(p) = 0._r8 + + onset_flag(p) = 1.0_r8 + dormant_flag(p) = 0.0_r8 + onset_gddflag(p) = 0.0_r8 + onset_gdd(p) = 0.0_r8 + onset_counter(p) = ndays_stor(ivt(p)) * secspday + + fert_counter(p) = nfertdays_on * secspday + if (nfertdays_on .gt. 0) then + fert(p) = (manunitro(ivt(p)) * 1000._r8 + fertnitro(p))/ fert_counter(p) + else + fert(p) = 0._r8 + end if + + ! move all the storage pools into transfer pools, + ! where they will be transfered to displayed growth over the onset period. + ! set carbon fluxes for shifting storage pools to transfer pools + leafc_storage_to_xfer(p) = fstor2tran * leafc_storage(p)/dt + frootc_storage_to_xfer(p) = fstor2tran * frootc_storage(p)/dt + if (woody(ivt(p)) == 1.0_r8) then + livestemc_storage_to_xfer(p) = fstor2tran * livestemc_storage(p)/dt + deadstemc_storage_to_xfer(p) = fstor2tran * deadstemc_storage(p)/dt + livecrootc_storage_to_xfer(p) = fstor2tran * livecrootc_storage(p)/dt + deadcrootc_storage_to_xfer(p) = fstor2tran * deadcrootc_storage(p)/dt + gresp_storage_to_xfer(p) = fstor2tran * gresp_storage(p)/dt + end if + + ! set nitrogen fluxes for shifting storage pools to transfer pools + leafn_storage_to_xfer(p) = fstor2tran * leafn_storage(p)/dt + frootn_storage_to_xfer(p) = fstor2tran * frootn_storage(p)/dt + if (woody(ivt(p)) == 1.0_r8) then + livestemn_storage_to_xfer(p) = fstor2tran * livestemn_storage(p)/dt + deadstemn_storage_to_xfer(p) = fstor2tran * deadstemn_storage(p)/dt + livecrootn_storage_to_xfer(p) = fstor2tran * livecrootn_storage(p)/dt + deadcrootn_storage_to_xfer(p) = fstor2tran * deadcrootn_storage(p)/dt + end if + end if + + ! test for switching from growth period to offset period + else if (dormant_flag(p) == 0.0_r8 .and. offset_flag(p) == 0.0_r8) then + if (use_cndv) then + ! If days_active > 355, then remove patch in + ! CNDVEstablishment at the end of the year. + ! days_active > 355 is a symptom of seasonal decid. patches + ! occurring in + ! gridcells where dayl never drops below crit_dayl. + ! This results in TLAI>1e4 in a few gridcells. + days_active(p) = days_active(p) + fracday + if (days_active(p) > 355._r8) pftmayexist(p) = .false. + end if + + ! other crop stages occur outside the dormancy period + if ((hui(p) >= gddmaturity(p) .and. idpp < mxmat(ivt(p))) .or. & + (jday >= maxharvjday(ivt(p),h) .and. idpp < mxmat(ivt(p)))) then + + if (tlai(p) <= 0._r8 .and. harvest_flag(p) == 0._r8) then ! plant never emerged or died + croplive(p) = .false. + if (harvdate(p) >= NOT_Harvested) harvdate(p) = jday + crop_seedc_to_leaf(p) = crop_seedc_to_leaf(p) - leafc_xfer(p)/dt + crop_seedc_to_froot(p) = crop_seedc_to_froot(p) - frootc_xfer(p)/dt + crop_seedn_to_leaf(p) = crop_seedn_to_leaf(p) - leafn_xfer(p)/dt + crop_seedn_to_froot(p) = crop_seedn_to_froot(p) - frootn_xfer(p)/dt + leafc_xfer(p) = 0._r8 ! revert planting transfers + frootc_xfer(p) = 0._r8 + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) + frootn_xfer(p) = frootc_xfer(p) / frootcn(ivt(p)) + if (woody(ivt(p)) == 1._r8) then + crop_seedc_to_deadstem(p) = crop_seedc_to_deadstem(p) - deadstemc_xfer(p)/dt + crop_seedn_to_deadstem(p) = crop_seedn_to_deadstem(p) - deadstemn_xfer(p)/dt + deadstemc_xfer(p) = 0._r8 + deadstemn_xfer(p) = deadstemc_xfer(p) / deadwdcn(ivt(p)) + end if + else if (grainc(p) > 0._r8) then !only harvest when there is positive grainc accumulated during grainfill, adapted based on CLM-Palm (Fan et al. 2015) + harvest_flag(p) = 1._r8 + storage_flag(p) = 1._r8 + end if + else + harvest_flag(p) = 0._r8 + end if + + if (idpp >= mxmat(ivt(p))) then + if (harvdate(p) >= NOT_Harvested) harvdate(p) = jday + croplive(p) = .false. + cphase(p) = 4._r8 + if (tlai(p) > 0._r8) then ! plant had emerged before rotation + offset2_flag(p) = 1._r8 + else ! plant never emerged from ground + crop_seedc_to_leaf(p) = crop_seedc_to_leaf(p) - leafc_xfer(p)/dt + crop_seedc_to_froot(p) = crop_seedc_to_froot(p) - frootc_xfer(p)/dt + crop_seedn_to_leaf(p) = crop_seedn_to_leaf(p) - leafn_xfer(p)/dt + crop_seedn_to_froot(p) = crop_seedn_to_froot(p) - frootn_xfer(p)/dt + leafc_xfer(p) = 0._r8 + frootc_xfer(p) = 0._r8 + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) + frootn_xfer(p) = frootc_xfer(p) / frootcn(ivt(p)) + if (woody(ivt(p)) == 1._r8) then + crop_seedc_to_deadstem(p) = crop_seedc_to_deadstem(p) - deadstemc_xfer(p)/dt + crop_seedn_to_deadstem(p) = crop_seedn_to_deadstem(p) - deadstemn_xfer(p)/dt + deadstemc_xfer(p) = 0._r8 + deadstemn_xfer(p) = deadstemc_xfer(p) / deadwdcn(ivt(p)) + end if + end if + end if ! idpp >=mxmat + + if (fert_counter(p) <= 0._r8) then + fert(p) = 0._r8 + else ! continue same fert application every timestep + fert_counter(p) = fert_counter(p) - dtrad + end if + + ! only begin to test for offset critical temperature once past the summer sol + if (ws_flag == 0._r8 .and. t_ref24(p) < crit_temp(ivt(p))) then + offset_flag(p) = 1._r8 + !storage_flag(p) = 0._r8 + offset_counter(p) = ndays_off * secspday + prev_leafc_to_litter(p) = 0._r8 + prev_frootc_to_litter(p) = 0._r8 + ! harvest grainc if crop not harvested yet + if (grainc(p) > 0._r8) harvest_flag(p) = 1._r8 + end if + end if ! dormant_flag == 1 + end if ! season_decid + + else ! crop not live + dormant_flag(p) = 1._r8 + onset_counter(p) = 0._r8 + ! the next lines conserve mass if leaf*/froot*/deadstem*_xfer > 0 due to interpinic. + ! We subtract from any existing value in crop_seedc_to_* / + ! crop_seedn_to_* in the unlikely event that we enter this block of + ! code in the same time step where the planting transfer originally + ! occurred. + crop_seedc_to_leaf(p) = crop_seedc_to_leaf(p) - leafc_xfer(p)/dt + crop_seedc_to_froot(p) = crop_seedc_to_froot(p) - frootc_xfer(p)/dt + crop_seedn_to_leaf(p) = crop_seedn_to_leaf(p) - leafn_xfer(p)/dt + crop_seedn_to_froot(p) = crop_seedn_to_froot(p) - frootn_xfer(p)/dt + leafc_xfer(p) = 0._r8 + frootc_xfer(p) = 0._r8 + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) + frootn_xfer(p) = frootc_xfer(p) / frootcn(ivt(p)) + if (woody(ivt(p)) == 1._r8) then + crop_seedc_to_deadstem(p) = crop_seedc_to_deadstem(p) - deadstemc_xfer(p)/dt + crop_seedn_to_deadstem(p) = crop_seedn_to_deadstem(p) - deadstemn_xfer(p)/dt + deadstemc_xfer(p) = 0._r8 + deadstemn_xfer(p) = deadstemc_xfer(p) / deadwdcn(ivt(p)) + end if + if (use_c13) then + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 + endif + if (use_c14) then + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 + endif + + end if ! croplive + end if ! end if perennial(ivt(p)) == 1._r8 + end do ! prognostic crops loop + + end associate + + end subroutine FruitTreePhenology + !----------------------------------------------------------------------- subroutine CropPhenology(num_pcropp, filter_pcropp , & waterstate_inst, temperature_inst, crop_inst, canopystate_inst, cnveg_state_inst , & @@ -1483,7 +2189,7 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & hybgdd => pftcon%hybgdd , & ! Input: lfemerg => pftcon%lfemerg , & ! Input: grnfill => pftcon%grnfill , & ! Input: - + perennial => pftcon%perennial , & ! Input: [integer (:) ] binary flag for perennial crop phenology (1=perennial, 0= not perennial) (added by O.Dombrowski) t_ref2m_min => temperature_inst%t_ref2m_min_patch , & ! Input: [real(r8) (:) ] daily minimum of average 2 m height surface air temperature (K) t10 => temperature_inst%t_a10_patch , & ! Input: [real(r8) (:) ] 10-day running mean of the 2 m temperature (K) a5tmin => temperature_inst%t_a5min_patch , & ! Input: [real(r8) (:) ] 5-day running mean of min 2-m temperature @@ -1514,8 +2220,7 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & onset_flag => cnveg_state_inst%onset_flag_patch , & ! Output: [real(r8) (:) ] onset flag offset_flag => cnveg_state_inst%offset_flag_patch , & ! Output: [real(r8) (:) ] offset flag onset_counter => cnveg_state_inst%onset_counter_patch , & ! Output: [real(r8) (:) ] onset counter - offset_counter => cnveg_state_inst%offset_counter_patch , & ! Output: [real(r8) (:) ] offset counter - + offset_counter => cnveg_state_inst%offset_counter_patch , & ! Output: [real(r8) (:) ] offset counter leafc_xfer => cnveg_carbonstate_inst%leafc_xfer_patch , & ! Output: [real(r8) (:) ] (gC/m2) leaf C transfer crop_seedc_to_leaf => cnveg_carbonflux_inst%crop_seedc_to_leaf_patch, & ! Output: [real(r8) (:) ] (gC/m2/s) seed source to leaf @@ -1545,485 +2250,485 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & g = patch%gridcell(p) h = inhemi(p) - ! background litterfall and transfer rates; long growing season factor - - bglfr(p) = 0._r8 ! this value changes later in a crop's life cycle - bgtr(p) = 0._r8 - lgsf(p) = 0._r8 - - ! --------------------------------- - ! from AgroIBIS subroutine planting - ! --------------------------------- - - ! in order to allow a crop to be planted only once each year - ! initialize cropplant = .false., but hold it = .true. through the end of the year - - ! initialize other variables that are calculated for crops - ! on an annual basis in cropresidue subroutine - - if ( jday == jdayyrstart(h) .and. mcsec == 0 )then - - ! make sure variables aren't changed at beginning of the year - ! for a crop that is currently planted, such as - ! WINTER TEMPERATE CEREAL = winter (wheat + barley + rye) - ! represented here by the winter wheat pft - - if (.not. croplive(p)) then - cropplant(p) = .false. - idop(p) = NOT_Planted - - ! keep next for continuous, annual winter temperate cereal crop; - ! if we removed elseif, - ! winter cereal grown continuously would amount to a cereal/fallow - ! rotation because cereal would only be planted every other year - - else if (croplive(p) .and. (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat)) then - cropplant(p) = .false. - ! else ! not possible to have croplive and ivt==cornORsoy? (slevis) - end if - - end if - - if ( (.not. croplive(p)) .and. (.not. cropplant(p)) ) then - - ! gdd needed for * chosen crop and a likely hybrid (for that region) * - ! to reach full physiological maturity - - ! based on accumulated seasonal average growing degree days from - ! April 1 - Sept 30 (inclusive) - ! for corn and soybeans in the United States - - ! decided upon by what the typical average growing season length is - ! and the gdd needed to reach maturity in those regions - - ! first choice is used for spring temperate cereal and/or soybeans and maize - - ! slevis: ibis reads xinpdate in io.f from control.crops.nc variable name 'plantdate' - ! According to Chris Kucharik, the dataset of - ! xinpdate was generated from a previous model run at 0.5 deg resolution - - ! winter temperate cereal : use gdd0 as a limit to plant winter cereal - - if (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat) then - - ! add check to only plant winter cereal after other crops (soybean, maize) - ! have been harvested - - ! *** remember order of planting is crucial - in terms of which crops you want - ! to be grown in what order *** - - ! in this case, corn or soybeans are assumed to be planted before - ! cereal would be in any particular year that both patches are allowed - ! to grow in the same grid cell (e.g., double-cropping) - - ! slevis: harvdate below needs cropplant(p) above to be cropplant(p,ivt(p)) - ! where ivt(p) has rotated to winter cereal because - ! cropplant through the end of the year for a harvested crop. - ! Also harvdate(p) should be harvdate(p,ivt(p)) and should be - ! updated on Jan 1st instead of at harvest (slevis) - if (a5tmin(p) /= spval .and. & - a5tmin(p) <= minplanttemp(ivt(p)) .and. & - jday >= minplantjday(ivt(p),h) .and. & - (gdd020(p) /= spval .and. & - gdd020(p) >= gddmin(ivt(p)))) then - - cumvd(p) = 0._r8 - hdidx(p) = 0._r8 - vf(p) = 0._r8 - croplive(p) = .true. - cropplant(p) = .true. - idop(p) = jday - harvdate(p) = NOT_Harvested - gddmaturity(p) = hybgdd(ivt(p)) - leafc_xfer(p) = initial_seed_at_planting - leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) ! with onset - crop_seedc_to_leaf(p) = leafc_xfer(p)/dt - crop_seedn_to_leaf(p) = leafn_xfer(p)/dt - - ! because leafc_xfer is set above rather than incremneted through the normal process, must also set its isotope - ! pools here. use totvegc_patch as the closest analogue if nonzero, and use initial value otherwise - if (use_c13) then - if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & - c13_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) - else - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c13ratio - endif - endif - if (use_c14) then - if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & - c14_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) - else - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c14ratio - endif - endif - - ! latest possible date to plant winter cereal and after all other - ! crops were harvested for that year - - else if (jday >= maxplantjday(ivt(p),h) .and. & - gdd020(p) /= spval .and. & - gdd020(p) >= gddmin(ivt(p))) then - - cumvd(p) = 0._r8 - hdidx(p) = 0._r8 - vf(p) = 0._r8 - croplive(p) = .true. - cropplant(p) = .true. - idop(p) = jday - harvdate(p) = NOT_Harvested - gddmaturity(p) = hybgdd(ivt(p)) - leafc_xfer(p) = initial_seed_at_planting - leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) ! with onset - crop_seedc_to_leaf(p) = leafc_xfer(p)/dt - crop_seedn_to_leaf(p) = leafn_xfer(p)/dt - - ! because leafc_xfer is set above rather than incremneted through the normal process, must also set its isotope - ! pools here. use totvegc_patch as the closest analogue if nonzero, and use initial value otherwise - if (use_c13) then - if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & - c13_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) - else - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c13ratio - endif - endif - if (use_c14) then - if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & - c14_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) - else - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c14ratio - endif - endif - else - gddmaturity(p) = 0._r8 - end if - - else ! not winter cereal... slevis: added distinction between NH and SH - ! slevis: The idea is that jday will equal idop sooner or later in the year - ! while the gdd part is either true or false for the year. - if (t10(p) /= spval.and. a10tmin(p) /= spval .and. & - t10(p) > planttemp(ivt(p)) .and. & - a10tmin(p) > minplanttemp(ivt(p)) .and. & - jday >= minplantjday(ivt(p),h) .and. & - jday <= maxplantjday(ivt(p),h) .and. & - t10(p) /= spval .and. a10tmin(p) /= spval .and. & - gdd820(p) /= spval .and. & - gdd820(p) >= gddmin(ivt(p))) then - - ! impose limit on growing season length needed - ! for crop maturity - for cold weather constraints - croplive(p) = .true. - cropplant(p) = .true. - idop(p) = jday - harvdate(p) = NOT_Harvested - - ! go a specified amount of time before/after - ! climatological date - if (ivt(p) == ntmp_soybean .or. ivt(p) == nirrig_tmp_soybean .or. & - ivt(p) == ntrp_soybean .or. ivt(p) == nirrig_trp_soybean) then - gddmaturity(p) = min(gdd1020(p), hybgdd(ivt(p))) - end if - if (ivt(p) == ntmp_corn .or. ivt(p) == nirrig_tmp_corn .or. & - ivt(p) == ntrp_corn .or. ivt(p) == nirrig_trp_corn .or. & - ivt(p) == nsugarcane .or. ivt(p) == nirrig_sugarcane) then - gddmaturity(p) = max(950._r8, min(gdd820(p)*0.85_r8, hybgdd(ivt(p)))) - gddmaturity(p) = max(950._r8, min(gddmaturity(p)+150._r8, 1850._r8)) - end if - if (ivt(p) == nswheat .or. ivt(p) == nirrig_swheat .or. & - ivt(p) == ncotton .or. ivt(p) == nirrig_cotton .or. & - ivt(p) == nrice .or. ivt(p) == nirrig_rice) then - gddmaturity(p) = min(gdd020(p), hybgdd(ivt(p))) - end if - - leafc_xfer(p) = initial_seed_at_planting - leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) ! with onset - crop_seedc_to_leaf(p) = leafc_xfer(p)/dt - crop_seedn_to_leaf(p) = leafn_xfer(p)/dt - - ! because leafc_xfer is set above rather than incremneted through the normal process, must also set its isotope - ! pools here. use totvegc_patch as the closest analogue if nonzero, and use initial value otherwise - if (use_c13) then - if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & - c13_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) - else - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c13ratio - endif - endif - if (use_c14) then - if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & - c14_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) - else - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c14ratio - endif - endif - - - ! If hit the max planting julian day -- go ahead and plant - else if (jday == maxplantjday(ivt(p),h) .and. gdd820(p) > 0._r8 .and. & - gdd820(p) /= spval ) then - croplive(p) = .true. - cropplant(p) = .true. - idop(p) = jday - harvdate(p) = NOT_Harvested + if (perennial(ivt(p)) == 0._r8) then + ! background litterfall and transfer rates; long growing season factor + bglfr(p) = 0._r8 ! this value changes later in a crop's life cycle + bgtr(p) = 0._r8 + lgsf(p) = 0._r8 - if (ivt(p) == ntmp_soybean .or. ivt(p) == nirrig_tmp_soybean .or. & - ivt(p) == ntrp_soybean .or. ivt(p) == nirrig_trp_soybean) then - gddmaturity(p) = min(gdd1020(p), hybgdd(ivt(p))) - end if - if (ivt(p) == ntmp_corn .or. ivt(p) == nirrig_tmp_corn .or. & - ivt(p) == ntrp_corn .or. ivt(p) == nirrig_trp_corn .or. & - ivt(p) == nsugarcane .or. ivt(p) == nirrig_sugarcane) then - gddmaturity(p) = max(950._r8, min(gdd820(p)*0.85_r8, hybgdd(ivt(p)))) - end if - if (ivt(p) == nswheat .or. ivt(p) == nirrig_swheat .or. & - ivt(p) == ncotton .or. ivt(p) == nirrig_cotton .or. & - ivt(p) == nrice .or. ivt(p) == nirrig_rice) then - gddmaturity(p) = min(gdd020(p), hybgdd(ivt(p))) - end if - - leafc_xfer(p) = initial_seed_at_planting - leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) ! with onset - crop_seedc_to_leaf(p) = leafc_xfer(p)/dt - crop_seedn_to_leaf(p) = leafn_xfer(p)/dt - - ! because leafc_xfer is set above rather than incremneted through the normal process, must also set its isotope - ! pools here. use totvegc_patch as the closest analogue if nonzero, and use initial value otherwise - if (use_c13) then - if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & - c13_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) - else - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c13ratio - endif - endif - if (use_c14) then - if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & - c14_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) - else - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c14ratio - endif - endif - - else - gddmaturity(p) = 0._r8 - end if - end if ! crop patch distinction - - ! crop phenology (gdd thresholds) controlled by gdd needed for - ! maturity (physiological) which is based on the average gdd - ! accumulation and hybrids in United States from April 1 - Sept 30 - - ! calculate threshold from phase 1 to phase 2: - ! threshold for attaining leaf emergence (based on fraction of - ! gdd(i) -- climatological average) - ! Hayhoe and Dwyer, 1990, Can. J. Soil Sci 70:493-497 - ! Carlson and Gage, 1989, Agric. For. Met., 45: 313-324 - ! J.T. Ritchie, 1991: Modeling Plant and Soil systems - - huileaf(p) = lfemerg(ivt(p)) * gddmaturity(p) ! 3-7% in cereal - - ! calculate threshhold from phase 2 to phase 3: - ! from leaf emergence to beginning of grain-fill period - ! this hypothetically occurs at the end of tassling, not the beginning - ! tassel initiation typically begins at 0.5-0.55 * gddmaturity - - ! calculate linear relationship between huigrain fraction and relative - ! maturity rating for maize - - if (ivt(p) == ntmp_corn .or. ivt(p) == nirrig_tmp_corn .or. & - ivt(p) == ntrp_corn .or. ivt(p) == nirrig_trp_corn .or. & - ivt(p) == nsugarcane .or. ivt(p) == nirrig_sugarcane) then - ! the following estimation of crmcorn from gddmaturity is based on a linear - ! regression using data from Pioneer-brand corn hybrids (Kucharik, 2003, - ! Earth Interactions 7:1-33: fig. 2) - crmcorn = max(73._r8, min(135._r8, (gddmaturity(p)+ 53.683_r8)/13.882_r8)) - - ! the following adjustment of grnfill based on crmcorn is based on a tuning - ! of Agro-IBIS to give reasonable results for max LAI and the seasonal - ! progression of LAI growth (pers. comm. C. Kucharik June 10, 2010) - huigrain(p) = -0.002_r8 * (crmcorn - 73._r8) + grnfill(ivt(p)) - - huigrain(p) = min(max(huigrain(p), grnfill(ivt(p))-0.1_r8), grnfill(ivt(p))) - huigrain(p) = huigrain(p) * gddmaturity(p) ! Cabelguenne et - else - huigrain(p) = grnfill(ivt(p)) * gddmaturity(p) ! al. 1999 - end if + ! --------------------------------- + ! from AgroIBIS subroutine planting + ! --------------------------------- - end if ! crop not live nor planted - - ! ---------------------------------- - ! from AgroIBIS subroutine phenocrop - ! ---------------------------------- - - ! all of the phenology changes are based on the total number of gdd needed - ! to change to the next phase - based on fractions of the total gdd typical - ! for that region based on the April 1 - Sept 30 window of development - - ! crop phenology (gdd thresholds) controlled by gdd needed for - ! maturity (physiological) which is based on the average gdd - ! accumulation and hybrids in United States from April 1 - Sept 30 - - ! Phase 1: Planting to leaf emergence (now in CNAllocation) - ! Phase 2: Leaf emergence to beginning of grain fill (general LAI accumulation) - ! Phase 3: Grain fill to physiological maturity and harvest (LAI decline) - ! Harvest: if gdd past grain fill initiation exceeds limit - ! or number of days past planting reaches a maximum, the crop has - ! reached physiological maturity and plant is harvested; - ! crop could be live or dead at this stage - these limits - ! could lead to reaching physiological maturity or determining - ! a harvest date for a crop killed by an early frost (see next comments) - ! --- --- --- - ! keeping comments without the code (slevis): - ! if minimum temperature, t_ref2m_min <= freeze kill threshold, tkill - ! for 3 consecutive days and lai is above a minimum, - ! plant will be damaged/killed. This function is more for spring freeze events - ! or for early fall freeze events - - ! spring temperate cereal is affected by this, winter cereal kill function - ! is determined in crops.f - is a more elaborate function of - ! cold hardening of the plant - - ! currently simulates too many grid cells killed by freezing temperatures - - ! removed on March 12 2002 - C. Kucharik - ! until it can be a bit more refined, or used at a smaller scale. - ! we really have no way of validating this routine - ! too difficult to implement on 0.5 degree scale grid cells - ! --- --- --- - - onset_flag(p) = 0._r8 ! CN terminology to trigger certain - offset_flag(p) = 0._r8 ! carbon and nitrogen transfers - - if (croplive(p)) then - cphase(p) = 1._r8 - - ! call vernalization if winter temperate cereal planted, living, and the - ! vernalization factor is not 1; - ! vf affects the calculation of gddtsoi & gddplant - - if (t_ref2m_min(p) < 1.e30_r8 .and. vf(p) /= 1._r8 .and. & - (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat)) then - call vernalization(p, & - canopystate_inst, temperature_inst, waterstate_inst, cnveg_state_inst, & - crop_inst) - end if + ! in order to allow a crop to be planted only once each year + ! initialize cropplant = .false., but hold it = .true. through the end of the year - ! days past planting may determine harvest + ! initialize other variables that are calculated for crops + ! on an annual basis in cropresidue subroutine - if (jday >= idop(p)) then - idpp = jday - idop(p) - else - idpp = int(dayspyr) + jday - idop(p) - end if + if ( jday == jdayyrstart(h) .and. mcsec == 0 )then - ! onset_counter initialized to zero when .not. croplive - ! offset_counter relevant only at time step of harvest + ! make sure variables aren't changed at beginning of the year + ! for a crop that is currently planted, such as + ! WINTER TEMPERATE CEREAL = winter (wheat + barley + rye) + ! represented here by the winter wheat pft - onset_counter(p) = onset_counter(p) - dt + if (.not. croplive(p)) then + cropplant(p) = .false. + idop(p) = NOT_Planted - ! enter phase 2 onset for one time step: - ! transfer seed carbon to leaf emergence + ! keep next for continuous, annual winter temperate cereal crop; + ! if we removed elseif, + ! winter cereal grown continuously would amount to a cereal/fallow + ! rotation because cereal would only be planted every other year - if (peaklai(p) >= 1) then - hui(p) = max(hui(p),huigrain(p)) - endif + else if (croplive(p) .and. (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat)) then + cropplant(p) = .false. + ! else ! not possible to have croplive and ivt==cornORsoy? (slevis) + end if - if (leafout(p) >= huileaf(p) .and. hui(p) < huigrain(p) .and. idpp < mxmat(ivt(p))) then - cphase(p) = 2._r8 - if (abs(onset_counter(p)) > 1.e-6_r8) then - onset_flag(p) = 1._r8 - onset_counter(p) = dt - fert_counter(p) = ndays_on * secspday - if (ndays_on .gt. 0) then - fert(p) = (manunitro(ivt(p)) * 1000._r8 + fertnitro(p))/ fert_counter(p) + end if + + if ( (.not. croplive(p)) .and. (.not. cropplant(p)) ) then + + ! gdd needed for * chosen crop and a likely hybrid (for that region) * + ! to reach full physiological maturity + + ! based on accumulated seasonal average growing degree days from + ! April 1 - Sept 30 (inclusive) + ! for corn and soybeans in the United States - + ! decided upon by what the typical average growing season length is + ! and the gdd needed to reach maturity in those regions + + ! first choice is used for spring temperate cereal and/or soybeans and maize + + ! slevis: ibis reads xinpdate in io.f from control.crops.nc variable name 'plantdate' + ! According to Chris Kucharik, the dataset of + ! xinpdate was generated from a previous model run at 0.5 deg resolution + + ! winter temperate cereal : use gdd0 as a limit to plant winter cereal + + if (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat) then + + ! add check to only plant winter cereal after other crops (soybean, maize) + ! have been harvested + + ! *** remember order of planting is crucial - in terms of which crops you want + ! to be grown in what order *** + + ! in this case, corn or soybeans are assumed to be planted before + ! cereal would be in any particular year that both patches are allowed + ! to grow in the same grid cell (e.g., double-cropping) + + ! slevis: harvdate below needs cropplant(p) above to be cropplant(p,ivt(p)) + ! where ivt(p) has rotated to winter cereal because + ! cropplant through the end of the year for a harvested crop. + ! Also harvdate(p) should be harvdate(p,ivt(p)) and should be + ! updated on Jan 1st instead of at harvest (slevis) + if (a5tmin(p) /= spval .and. & + a5tmin(p) <= minplanttemp(ivt(p)) .and. & + jday >= minplantjday(ivt(p),h) .and. & + (gdd020(p) /= spval .and. & + gdd020(p) >= gddmin(ivt(p)))) then + + cumvd(p) = 0._r8 + hdidx(p) = 0._r8 + vf(p) = 0._r8 + croplive(p) = .true. + cropplant(p) = .true. + idop(p) = jday + harvdate(p) = NOT_Harvested + gddmaturity(p) = hybgdd(ivt(p)) + leafc_xfer(p) = initial_seed_at_planting + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) ! with onset + crop_seedc_to_leaf(p) = leafc_xfer(p)/dt + crop_seedn_to_leaf(p) = leafn_xfer(p)/dt + + ! because leafc_xfer is set above rather than incremneted through the normal process, must also set its isotope + ! pools here. use totvegc_patch as the closest analogue if nonzero, and use initial value otherwise + if (use_c13) then + if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & + c13_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) + else + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c13ratio + endif + endif + if (use_c14) then + if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & + c14_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) + else + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c14ratio + endif + endif + + ! latest possible date to plant winter cereal and after all other + ! crops were harvested for that year + + else if (jday >= maxplantjday(ivt(p),h) .and. & + gdd020(p) /= spval .and. & + gdd020(p) >= gddmin(ivt(p))) then + + cumvd(p) = 0._r8 + hdidx(p) = 0._r8 + vf(p) = 0._r8 + croplive(p) = .true. + cropplant(p) = .true. + idop(p) = jday + harvdate(p) = NOT_Harvested + gddmaturity(p) = hybgdd(ivt(p)) + leafc_xfer(p) = initial_seed_at_planting + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) ! with onset + crop_seedc_to_leaf(p) = leafc_xfer(p)/dt + crop_seedn_to_leaf(p) = leafn_xfer(p)/dt + + ! because leafc_xfer is set above rather than incremneted through the normal process, must also set its isotope + ! pools here. use totvegc_patch as the closest analogue if nonzero, and use initial value otherwise + if (use_c13) then + if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & + c13_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) + else + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c13ratio + endif + endif + if (use_c14) then + if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & + c14_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) + else + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c14ratio + endif + endif + else + gddmaturity(p) = 0._r8 + end if + + else ! not winter cereal... slevis: added distinction between NH and SH + ! slevis: The idea is that jday will equal idop sooner or later in the year + ! while the gdd part is either true or false for the year. + if (t10(p) /= spval.and. a10tmin(p) /= spval .and. & + t10(p) > planttemp(ivt(p)) .and. & + a10tmin(p) > minplanttemp(ivt(p)) .and. & + jday >= minplantjday(ivt(p),h) .and. & + jday <= maxplantjday(ivt(p),h) .and. & + t10(p) /= spval .and. a10tmin(p) /= spval .and. & + gdd820(p) /= spval .and. & + gdd820(p) >= gddmin(ivt(p))) then + + ! impose limit on growing season length needed + ! for crop maturity - for cold weather constraints + croplive(p) = .true. + cropplant(p) = .true. + idop(p) = jday + harvdate(p) = NOT_Harvested + + ! go a specified amount of time before/after + ! climatological date + if (ivt(p) == ntmp_soybean .or. ivt(p) == nirrig_tmp_soybean .or. & + ivt(p) == ntrp_soybean .or. ivt(p) == nirrig_trp_soybean) then + gddmaturity(p) = min(gdd1020(p), hybgdd(ivt(p))) + end if + if (ivt(p) == ntmp_corn .or. ivt(p) == nirrig_tmp_corn .or. & + ivt(p) == ntrp_corn .or. ivt(p) == nirrig_trp_corn .or. & + ivt(p) == nsugarcane .or. ivt(p) == nirrig_sugarcane) then + gddmaturity(p) = max(950._r8, min(gdd820(p)*0.85_r8, hybgdd(ivt(p)))) + gddmaturity(p) = max(950._r8, min(gddmaturity(p)+150._r8, 1850._r8)) + end if + if (ivt(p) == nswheat .or. ivt(p) == nirrig_swheat .or. & + ivt(p) == ncotton .or. ivt(p) == nirrig_cotton .or. & + ivt(p) == nrice .or. ivt(p) == nirrig_rice) then + gddmaturity(p) = min(gdd020(p), hybgdd(ivt(p))) + end if + + leafc_xfer(p) = initial_seed_at_planting + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) ! with onset + crop_seedc_to_leaf(p) = leafc_xfer(p)/dt + crop_seedn_to_leaf(p) = leafn_xfer(p)/dt + + ! because leafc_xfer is set above rather than incremneted through the normal process, must also set its isotope + ! pools here. use totvegc_patch as the closest analogue if nonzero, and use initial value otherwise + if (use_c13) then + if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & + c13_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) + else + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c13ratio + endif + endif + if (use_c14) then + if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & + c14_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) + else + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c14ratio + endif + endif + + + ! If hit the max planting julian day -- go ahead and plant + else if (jday == maxplantjday(ivt(p),h) .and. gdd820(p) > 0._r8 .and. & + gdd820(p) /= spval ) then + croplive(p) = .true. + cropplant(p) = .true. + idop(p) = jday + harvdate(p) = NOT_Harvested + + if (ivt(p) == ntmp_soybean .or. ivt(p) == nirrig_tmp_soybean .or. & + ivt(p) == ntrp_soybean .or. ivt(p) == nirrig_trp_soybean) then + gddmaturity(p) = min(gdd1020(p), hybgdd(ivt(p))) + end if + if (ivt(p) == ntmp_corn .or. ivt(p) == nirrig_tmp_corn .or. & + ivt(p) == ntrp_corn .or. ivt(p) == nirrig_trp_corn .or. & + ivt(p) == nsugarcane .or. ivt(p) == nirrig_sugarcane) then + gddmaturity(p) = max(950._r8, min(gdd820(p)*0.85_r8, hybgdd(ivt(p)))) + end if + if (ivt(p) == nswheat .or. ivt(p) == nirrig_swheat .or. & + ivt(p) == ncotton .or. ivt(p) == nirrig_cotton .or. & + ivt(p) == nrice .or. ivt(p) == nirrig_rice) then + gddmaturity(p) = min(gdd020(p), hybgdd(ivt(p))) + end if + + leafc_xfer(p) = initial_seed_at_planting + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) ! with onset + crop_seedc_to_leaf(p) = leafc_xfer(p)/dt + crop_seedn_to_leaf(p) = leafn_xfer(p)/dt + + ! because leafc_xfer is set above rather than incremneted through the normal process, must also set its isotope + ! pools here. use totvegc_patch as the closest analogue if nonzero, and use initial value otherwise + if (use_c13) then + if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & + c13_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) + else + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c13ratio + endif + endif + if (use_c14) then + if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & + c14_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) + else + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c14ratio + endif + endif + + else + gddmaturity(p) = 0._r8 + end if + end if ! crop patch distinction + + ! crop phenology (gdd thresholds) controlled by gdd needed for + ! maturity (physiological) which is based on the average gdd + ! accumulation and hybrids in United States from April 1 - Sept 30 + + ! calculate threshold from phase 1 to phase 2: + ! threshold for attaining leaf emergence (based on fraction of + ! gdd(i) -- climatological average) + ! Hayhoe and Dwyer, 1990, Can. J. Soil Sci 70:493-497 + ! Carlson and Gage, 1989, Agric. For. Met., 45: 313-324 + ! J.T. Ritchie, 1991: Modeling Plant and Soil systems + + huileaf(p) = lfemerg(ivt(p)) * gddmaturity(p) ! 3-7% in cereal + + ! calculate threshhold from phase 2 to phase 3: + ! from leaf emergence to beginning of grain-fill period + ! this hypothetically occurs at the end of tassling, not the beginning + ! tassel initiation typically begins at 0.5-0.55 * gddmaturity + + ! calculate linear relationship between huigrain fraction and relative + ! maturity rating for maize + + if (ivt(p) == ntmp_corn .or. ivt(p) == nirrig_tmp_corn .or. & + ivt(p) == ntrp_corn .or. ivt(p) == nirrig_trp_corn .or. & + ivt(p) == nsugarcane .or. ivt(p) == nirrig_sugarcane) then + ! the following estimation of crmcorn from gddmaturity is based on a linear + ! regression using data from Pioneer-brand corn hybrids (Kucharik, 2003, + ! Earth Interactions 7:1-33: fig. 2) + crmcorn = max(73._r8, min(135._r8, (gddmaturity(p)+ 53.683_r8)/13.882_r8)) + + ! the following adjustment of grnfill based on crmcorn is based on a tuning + ! of Agro-IBIS to give reasonable results for max LAI and the seasonal + ! progression of LAI growth (pers. comm. C. Kucharik June 10, 2010) + huigrain(p) = -0.002_r8 * (crmcorn - 73._r8) + grnfill(ivt(p)) + + huigrain(p) = min(max(huigrain(p), grnfill(ivt(p))-0.1_r8), grnfill(ivt(p))) + huigrain(p) = huigrain(p) * gddmaturity(p) ! Cabelguenne et else - fert(p) = 0._r8 + huigrain(p) = grnfill(ivt(p)) * gddmaturity(p) ! al. 1999 end if - else - ! this ensures no re-entry to onset of phase2 - ! b/c onset_counter(p) = onset_counter(p) - dt - ! at every time step - - onset_counter(p) = dt - end if - ! enter harvest for one time step: - ! - transfer live biomass to litter and to crop yield - ! - send xsmrpool to the atmosphere - ! if onset and harvest needed to last longer than one timestep - ! the onset_counter would change from dt and you'd need to make - ! changes to the offset subroutine below - - else if (hui(p) >= gddmaturity(p) .or. idpp >= mxmat(ivt(p))) then - if (harvdate(p) >= NOT_Harvested) harvdate(p) = jday - croplive(p) = .false. ! no re-entry in greater if-block - cphase(p) = 4._r8 - if (tlai(p) > 0._r8) then ! plant had emerged before harvest - offset_flag(p) = 1._r8 - offset_counter(p) = dt - else ! plant never emerged from the ground - ! Revert planting transfers; this will replenish the crop seed deficit. - ! We subtract from any existing value in crop_seedc_to_leaf / - ! crop_seedn_to_leaf in the unlikely event that we enter this block of - ! code in the same time step where the planting transfer originally - ! occurred. - crop_seedc_to_leaf(p) = crop_seedc_to_leaf(p) - leafc_xfer(p)/dt - crop_seedn_to_leaf(p) = crop_seedn_to_leaf(p) - leafn_xfer(p)/dt - leafc_xfer(p) = 0._r8 - leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) - if (use_c13) then - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 - endif - if (use_c14) then - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 - endif - - end if - - ! enter phase 3 while previous criteria fail and next is true; - ! in terms of order, phase 3 occurs before harvest, but when - ! harvest *can* occur, we want it to have first priority. - ! AgroIBIS uses a complex formula for lai decline. - ! Use CN's simple formula at least as a place holder (slevis) - - else if (hui(p) >= huigrain(p)) then - cphase(p) = 3._r8 - bglfr(p) = 1._r8/(leaf_long(ivt(p))*dayspyr*secspday) - end if + end if ! crop not live nor planted + + ! ---------------------------------- + ! from AgroIBIS subroutine phenocrop + ! ---------------------------------- + + ! all of the phenology changes are based on the total number of gdd needed + ! to change to the next phase - based on fractions of the total gdd typical + ! for that region based on the April 1 - Sept 30 window of development + + ! crop phenology (gdd thresholds) controlled by gdd needed for + ! maturity (physiological) which is based on the average gdd + ! accumulation and hybrids in United States from April 1 - Sept 30 + + ! Phase 1: Planting to leaf emergence (now in CNAllocation) + ! Phase 2: Leaf emergence to beginning of grain fill (general LAI accumulation) + ! Phase 3: Grain fill to physiological maturity and harvest (LAI decline) + ! Harvest: if gdd past grain fill initiation exceeds limit + ! or number of days past planting reaches a maximum, the crop has + ! reached physiological maturity and plant is harvested; + ! crop could be live or dead at this stage - these limits + ! could lead to reaching physiological maturity or determining + ! a harvest date for a crop killed by an early frost (see next comments) + ! --- --- --- + ! keeping comments without the code (slevis): + ! if minimum temperature, t_ref2m_min <= freeze kill threshold, tkill + ! for 3 consecutive days and lai is above a minimum, + ! plant will be damaged/killed. This function is more for spring freeze events + ! or for early fall freeze events + + ! spring temperate cereal is affected by this, winter cereal kill function + ! is determined in crops.f - is a more elaborate function of + ! cold hardening of the plant + + ! currently simulates too many grid cells killed by freezing temperatures + + ! removed on March 12 2002 - C. Kucharik + ! until it can be a bit more refined, or used at a smaller scale. + ! we really have no way of validating this routine + ! too difficult to implement on 0.5 degree scale grid cells + ! --- --- --- + + onset_flag(p) = 0._r8 ! CN terminology to trigger certain + offset_flag(p) = 0._r8 ! carbon and nitrogen transfers + + if (croplive(p)) then + cphase(p) = 1._r8 + + ! call vernalization if winter temperate cereal planted, living, and the + ! vernalization factor is not 1; + ! vf affects the calculation of gddtsoi & gddplant + + if (t_ref2m_min(p) < 1.e30_r8 .and. vf(p) /= 1._r8 .and. & + (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat)) then + call vernalization(p, & + canopystate_inst, temperature_inst, waterstate_inst, cnveg_state_inst, & + crop_inst) + end if - ! continue fertilizer application while in phase 2; - ! assumes that onset of phase 2 took one time step only + ! days past planting may determine harvest - if (fert_counter(p) <= 0._r8) then - fert(p) = 0._r8 - else ! continue same fert application every timestep - fert_counter(p) = fert_counter(p) - dtrad - end if + if (jday >= idop(p)) then + idpp = jday - idop(p) + else + idpp = int(dayspyr) + jday - idop(p) + end if - else ! crop not live - ! next 2 lines conserve mass if leaf*_xfer > 0 due to interpinic. - ! We subtract from any existing value in crop_seedc_to_leaf / - ! crop_seedn_to_leaf in the unlikely event that we enter this block of - ! code in the same time step where the planting transfer originally - ! occurred. - crop_seedc_to_leaf(p) = crop_seedc_to_leaf(p) - leafc_xfer(p)/dt - crop_seedn_to_leaf(p) = crop_seedn_to_leaf(p) - leafn_xfer(p)/dt - onset_counter(p) = 0._r8 - leafc_xfer(p) = 0._r8 - leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) - if (use_c13) then - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 - endif - if (use_c14) then - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 - endif - end if ! croplive + ! onset_counter initialized to zero when .not. croplive + ! offset_counter relevant only at time step of harvest + + onset_counter(p) = onset_counter(p) - dt + + ! enter phase 2 onset for one time step: + ! transfer seed carbon to leaf emergence + + if (peaklai(p) >= 1) then + hui(p) = max(hui(p),huigrain(p)) + endif + + if (leafout(p) >= huileaf(p) .and. hui(p) < huigrain(p) .and. idpp < mxmat(ivt(p))) then + cphase(p) = 2._r8 + if (abs(onset_counter(p)) > 1.e-6_r8) then + onset_flag(p) = 1._r8 + onset_counter(p) = dt + fert_counter(p) = ndays_on * secspday + if (ndays_on .gt. 0) then + fert(p) = (manunitro(ivt(p)) * 1000._r8 + fertnitro(p))/ fert_counter(p) + else + fert(p) = 0._r8 + end if + else + ! this ensures no re-entry to onset of phase2 + ! b/c onset_counter(p) = onset_counter(p) - dt + ! at every time step + + onset_counter(p) = dt + end if + + ! enter harvest for one time step: + ! - transfer live biomass to litter and to crop yield + ! - send xsmrpool to the atmosphere + ! if onset and harvest needed to last longer than one timestep + ! the onset_counter would change from dt and you'd need to make + ! changes to the offset subroutine below + + else if (hui(p) >= gddmaturity(p) .or. idpp >= mxmat(ivt(p))) then + if (harvdate(p) >= NOT_Harvested) harvdate(p) = jday + croplive(p) = .false. ! no re-entry in greater if-block + cphase(p) = 4._r8 + if (tlai(p) > 0._r8) then ! plant had emerged before harvest + offset_flag(p) = 1._r8 + offset_counter(p) = dt + else ! plant never emerged from the ground + ! Revert planting transfers; this will replenish the crop seed deficit. + ! We subtract from any existing value in crop_seedc_to_leaf / + ! crop_seedn_to_leaf in the unlikely event that we enter this block of + ! code in the same time step where the planting transfer originally + ! occurred. + crop_seedc_to_leaf(p) = crop_seedc_to_leaf(p) - leafc_xfer(p)/dt + crop_seedn_to_leaf(p) = crop_seedn_to_leaf(p) - leafn_xfer(p)/dt + leafc_xfer(p) = 0._r8 + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) + if (use_c13) then + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 + endif + if (use_c14) then + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 + endif + + end if + + ! enter phase 3 while previous criteria fail and next is true; + ! in terms of order, phase 3 occurs before harvest, but when + ! harvest *can* occur, we want it to have first priority. + ! AgroIBIS uses a complex formula for lai decline. + ! Use CN's simple formula at least as a place holder (slevis) + + else if (hui(p) >= huigrain(p)) then + cphase(p) = 3._r8 + bglfr(p) = 1._r8/(leaf_long(ivt(p))*dayspyr*secspday) + end if + ! continue fertilizer application while in phase 2; + ! assumes that onset of phase 2 took one time step only + + if (fert_counter(p) <= 0._r8) then + fert(p) = 0._r8 + else ! continue same fert application every timestep + fert_counter(p) = fert_counter(p) - dtrad + end if + + else ! crop not live + ! next 2 lines conserve mass if leaf*_xfer > 0 due to interpinic. + ! We subtract from any existing value in crop_seedc_to_leaf / + ! crop_seedn_to_leaf in the unlikely event that we enter this block of + ! code in the same time step where the planting transfer originally + ! occurred. + crop_seedc_to_leaf(p) = crop_seedc_to_leaf(p) - leafc_xfer(p)/dt + crop_seedn_to_leaf(p) = crop_seedn_to_leaf(p) - leafn_xfer(p)/dt + onset_counter(p) = 0._r8 + leafc_xfer(p) = 0._r8 + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) + if (use_c13) then + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 + endif + if (use_c14) then + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 + endif + end if ! croplive + end if ! not perennial end do ! prognostic crops loop end associate @@ -2051,7 +2756,8 @@ subroutine CropPhenologyInit(bounds) allocate( inhemi(bounds%begp:bounds%endp) ) allocate( minplantjday(0:numpft,inSH)) ! minimum planting julian day - allocate( maxplantjday(0:numpft,inSH)) ! minimum planting julian day + allocate( maxplantjday(0:numpft,inSH)) ! maximum planting julian day + allocate( maxharvjday(0:numpft,inSH)) ! maximum harvest julian day (added by O.Dombrowski) ! Julian day for the start of the year (mid-winter) jdayyrstart(inNH) = 1 @@ -2060,13 +2766,17 @@ subroutine CropPhenologyInit(bounds) ! Convert planting dates into julian day minplantjday(:,:) = huge(1) maxplantjday(:,:) = huge(1) + maxharvjday(:,:) = huge(1) + do n = npcropmin, npcropmax if (pftcon%is_pft_known_to_model(n)) then minplantjday(n, inNH) = int( get_calday( pftcon%mnNHplantdate(n), 0 ) ) maxplantjday(n, inNH) = int( get_calday( pftcon%mxNHplantdate(n), 0 ) ) - + maxharvjday(n, inNH) = int( get_calday( pftcon%mxNHharvdate(n), 0 ) ) minplantjday(n, inSH) = int( get_calday( pftcon%mnSHplantdate(n), 0 ) ) maxplantjday(n, inSH) = int( get_calday( pftcon%mxSHplantdate(n), 0 ) ) + maxharvjday(n, inSH) = int( get_calday( pftcon%mxSHharvdate(n), 0 ) ) + end if end do @@ -2362,7 +3072,7 @@ end subroutine CNOnsetGrowth !----------------------------------------------------------------------- subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & - cnveg_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) + crop_inst,cnveg_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) ! ! !DESCRIPTION: ! Determines the flux of C and N from displayed pools to litter @@ -2371,11 +3081,13 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & ! !USES: use pftconMod , only : npcropmin use CNSharedParamsMod, only : use_fun - use clm_varctl , only : CNratio_floating + use clm_varctl , only : CNratio_floating + use clm_time_manager , only : get_curr_date, get_curr_calday, get_days_per_year, is_beg_curr_year ! ! !ARGUMENTS: integer , intent(in) :: num_soilp ! number of soil patches in filter integer , intent(in) :: filter_soilp(:) ! filter for soil patches + type(crop_type) , intent(inout) :: crop_inst type(cnveg_state_type) , intent(inout) :: cnveg_state_inst type(cnveg_carbonstate_type) , intent(in) :: cnveg_carbonstate_inst type(cnveg_nitrogenstate_type), intent(in) :: cnveg_nitrogenstate_inst @@ -2385,21 +3097,36 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & ! !LOCAL VARIABLES: integer :: p, c ! indices integer :: fp ! lake filter patch index + integer :: kyr, kmo, kda, mcsec ! time info + integer :: dayspyr ! days per year + integer :: idpp ! number of days past planting + integer :: jday ! julian day of year real(r8):: t1 ! temporary variable real(r8):: denom ! temporary variable for divisor real(r8) :: ntovr_leaf real(r8) :: fr_leafn_to_litter ! fraction of the nitrogen turnover that goes to litter; remaining fraction is retranslocated + real(r8) :: pr_fr ! fraction of total stem biomass that is pruned !----------------------------------------------------------------------- associate( & ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type + mxmat => pftcon%mxmat , & ! Input: leafcn => pftcon%leafcn , & ! Input: leaf C:N (gC/gN) lflitcn => pftcon%lflitcn , & ! Input: leaf litter C:N (gC/gN) frootcn => pftcon%frootcn , & ! Input: fine root C:N (gC/gN) graincn => pftcon%graincn , & ! Input: grain C:N (gC/gN) - + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop phenology (added by O.Dombrowski) + mulch_pruning => pftcon%mulch_pruning , & ! Input: binary flag for exporting or mulching of pruning material (added by O.Dombrowski) + prune_fr => pftcon%prune_fr , & ! Input: fraction of deadstem biomass that is pruned (added by O.Dombrowski) + prune_flag => cnveg_state_inst%prune_flag_patch , & ! Input: binary flag for pruning (added by O.Dombrowski) + harvest_flag => cnveg_state_inst%harvest_flag_patch , & ! Input: [real(r8) (:) ] harvest flag (added by O.Dombrowski) + + idop => cnveg_state_inst%idop_patch , & ! Output: [integer (:)] date of planting + yrop => crop_inst%yrop_patch , & ! Output: [integer (:)] year of planting (added by O.Dombrowski) + croplive => crop_inst%croplive_patch , & ! Output: [logical (:) ] Flag, true if planted, not harvested offset_flag => cnveg_state_inst%offset_flag_patch , & ! Input: [real(r8) (:) ] offset flag + offset2_flag => cnveg_state_inst%offset2_flag_patch , & ! Input: [real(r8) (:) ] orchard rotation flag offset_counter => cnveg_state_inst%offset_counter_patch , & ! Input: [real(r8) (:) ] offset days counter leafc => cnveg_carbonstate_inst%leafc_patch , & ! Input: [real(r8) (:) ] (gC/m2) leaf C @@ -2407,8 +3134,51 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & grainc => cnveg_carbonstate_inst%grainc_patch , & ! Input: [real(r8) (:) ] (gC/m2) grain C cropseedc_deficit => cnveg_carbonstate_inst%cropseedc_deficit_patch , & ! Input: [real(r8) (:) ] (gC/m2) crop seed C deficit livestemc => cnveg_carbonstate_inst%livestemc_patch , & ! Input: [real(r8) (:) ] (gC/m2) livestem C + deadstemc => cnveg_carbonstate_inst%deadstemc_patch , & ! Input: [real(r8) (:) ] (gC/m2) deadstem C + deadstemc_soy => cnveg_carbonstate_inst%deadstemc_soy_patch , & ! Input: [real(r8) (:) ] (gC/m2) dead stem C at the start of season + livecrootc => cnveg_carbonstate_inst%livecrootc_patch , & ! Input: [real(r8) (:) ] (gC/m2) live coarse root C + deadcrootc => cnveg_carbonstate_inst%deadcrootc_patch , & ! Input: [real(r8) (:) ] (gC/m2) dead coarse root C + xsmrpool => cnveg_carbonstate_inst%xsmrpool_patch , & ! Input: [real(r8) (:)] (gC/m2) abstract C pool to meet excess MR demand + leafc_storage => cnveg_carbonstate_inst%leafc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) leaf C storage + frootc_storage => cnveg_carbonstate_inst%frootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) fine root C storage + livestemc_storage => cnveg_carbonstate_inst%livestemc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) livestem storage C + deadstemc_storage => cnveg_carbonstate_inst%deadstemc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) deadstem storage C + deadstemc_storage_soy => cnveg_carbonstate_inst%deadstemc_storage_soy_patch , & ! Input: [real(r8) (:) ] (gC/m2) dead stem C storage at the start of season + livecrootc_storage => cnveg_carbonstate_inst%livecrootc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) livecrootc storage C + deadcrootc_storage => cnveg_carbonstate_inst%deadcrootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) dead coarse root C storage + cropseedn_deficit => cnveg_nitrogenstate_inst%cropseedn_deficit_patch , & ! Input: [real(r8) (:) ] (gC/m2) crop seed N deficit - livestemn => cnveg_nitrogenstate_inst%livestemn_patch , & ! Input: [real(r8) (:) ] (gN/m2) livestem N + + gresp_storage => cnveg_carbonstate_inst%gresp_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) growth respiration storage + leafc_xfer => cnveg_carbonstate_inst%leafc_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) leaf C transfer + frootc_xfer => cnveg_carbonstate_inst%frootc_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) fine root C transfer + livestemc_xfer => cnveg_carbonstate_inst%livestemc_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) live stem C transfer + deadstemc_xfer => cnveg_carbonstate_inst%deadstemc_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) dead stem C transfer + livecrootc_xfer => cnveg_carbonstate_inst%livecrootc_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) live coarse root C transfer + deadcrootc_xfer => cnveg_carbonstate_inst%deadcrootc_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) dead coarse root C transfer + gresp_xfer => cnveg_carbonstate_inst%gresp_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) growth respiration transfer + + leafn => cnveg_nitrogenstate_inst%leafn_patch , & ! Input: [real(r8) (:)] (gN/m2) leaf N + frootn => cnveg_nitrogenstate_inst%frootn_patch , & ! Input: [real(r8) (:)] (gN/m2) fine root N + livestemn => cnveg_nitrogenstate_inst%livestemn_patch , & ! Input: [real(r8) (:)] (gN/m2) live stem N + deadstemn => cnveg_nitrogenstate_inst%deadstemn_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N + deadstemn_soy => cnveg_nitrogenstate_inst%deadstemn_soy_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N at the start of season + livecrootn => cnveg_nitrogenstate_inst%livecrootn_patch , & ! Input: [real(r8) (:)] (gN/m2) live coarse root N + deadcrootn => cnveg_nitrogenstate_inst%deadcrootn_patch , & ! Input: [real(r8) (:)] (gN/m2) dead coarse root N + retransn => cnveg_nitrogenstate_inst%retransn_patch , & ! Input: [real(r8) (:)] (gN/m2) plant pool of retranslocated N + leafn_storage => cnveg_nitrogenstate_inst%leafn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) leaf N storage + frootn_storage => cnveg_nitrogenstate_inst%frootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) fine root N storage + livestemn_storage => cnveg_nitrogenstate_inst%livestemn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) live stem N storage + deadstemn_storage => cnveg_nitrogenstate_inst%deadstemn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N storage + deadstemn_storage_soy => cnveg_nitrogenstate_inst%deadstemn_storage_soy_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N storage at the start of season + livecrootn_storage => cnveg_nitrogenstate_inst%livecrootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) live coarse root N storage + deadcrootn_storage => cnveg_nitrogenstate_inst%deadcrootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) dead coarse root N storage + leafn_xfer => cnveg_nitrogenstate_inst%leafn_xfer_patch , & ! Input: [real(r8) (:)] (gN/m2) leaf N transfer + frootn_xfer => cnveg_nitrogenstate_inst%frootn_xfer_patch , & ! Input: [real(r8) (:)] (gN/m2) fine root N transfer + livestemn_xfer => cnveg_nitrogenstate_inst%livestemn_xfer_patch , & ! Input: [real(r8) (:)] (gN/m2) live stem N transfer + deadstemn_xfer => cnveg_nitrogenstate_inst%deadstemn_xfer_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N transfer + livecrootn_xfer => cnveg_nitrogenstate_inst%livecrootn_xfer_patch , & ! Input: [real(r8) (:)] (gN/m2) live coarse root N transfer + deadcrootn_xfer => cnveg_nitrogenstate_inst%deadcrootn_xfer_patch , & ! Input: [real(r8) (:)] (gN/m2) dead coarse root N transfer cpool_to_grainc => cnveg_carbonflux_inst%cpool_to_grainc_patch , & ! Input: [real(r8) (:) ] allocation to grain C (gC/m2/s) npool_to_grainn => cnveg_nitrogenflux_inst%npool_to_grainn_patch , & ! Input: [real(r8) (:) ] allocation to grain N (gN/m2/s) @@ -2416,35 +3186,107 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & cpool_to_livestemc => cnveg_carbonflux_inst%cpool_to_livestemc_patch , & ! Input: [real(r8) (:) ] allocation to live stem C (gC/m2/s) cpool_to_leafc => cnveg_carbonflux_inst%cpool_to_leafc_patch , & ! Input: [real(r8) (:) ] allocation to leaf C (gC/m2/s) cpool_to_frootc => cnveg_carbonflux_inst%cpool_to_frootc_patch , & ! Input: [real(r8) (:) ] allocation to fine root C (gC/m2/s) + cpool_to_livestemc_storage => cnveg_carbonflux_inst%cpool_to_livestemc_storage_patch , & ! Input: [real(r8) (:) ] allocation to live stem storage C (gC/m2/s) + cpool_to_deadstemc_storage => cnveg_carbonflux_inst%cpool_to_deadstemc_storage_patch , & ! Input: [real(r8) (:) ] allocation to dead stem storage C (gC/m2/s) prev_leafc_to_litter => cnveg_carbonflux_inst%prev_leafc_to_litter_patch , & ! Output: [real(r8) (:) ] previous timestep leaf C litterfall flux (gC/m2/s) prev_frootc_to_litter => cnveg_carbonflux_inst%prev_frootc_to_litter_patch , & ! Output: [real(r8) (:) ] previous timestep froot C litterfall flux (gC/m2/s) leafc_to_litter => cnveg_carbonflux_inst%leafc_to_litter_patch , & ! Output: [real(r8) (:) ] leaf C litterfall (gC/m2/s) frootc_to_litter => cnveg_carbonflux_inst%frootc_to_litter_patch , & ! Output: [real(r8) (:) ] fine root C litterfall (gC/m2/s) - livestemc_to_litter => cnveg_carbonflux_inst%livestemc_to_litter_patch , & ! Output: [real(r8) (:) ] live stem C litterfall (gC/m2/s) + livestemc_to_litter => cnveg_carbonflux_inst%livestemc_to_litter_patch , & ! Output: [real(r8) (:) ] live stem C litterfall (gC/m2/s) + prunec_to_litter => cnveg_carbonflux_inst%prunec_to_litter_patch , & ! Output: [real(r8) (:) ] pruning C litterfall (gC/m2/s) + prunec_storage_to_litter => cnveg_carbonflux_inst%prunec_storage_to_litter_patch , & ! Output: [real(r8) (:) ] pruning storage C litterfall (gC/m2/s) + + hrv_leafc_to_litter => cnveg_carbonflux_inst%hrv_leafc_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_frootc_to_litter => cnveg_carbonflux_inst%hrv_frootc_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_livestemc_to_litter => cnveg_carbonflux_inst%hrv_livestemc_to_litter_patch , & ! Output: [real(r8) (:)] + wood_harvestc => cnveg_carbonflux_inst%wood_harvestc_patch , & ! Output: [real(r8) (:)] + hrv_livecrootc_to_litter => cnveg_carbonflux_inst%hrv_livecrootc_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadcrootc_to_litter => cnveg_carbonflux_inst%hrv_deadcrootc_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_xsmrpool_to_atm => cnveg_carbonflux_inst%hrv_xsmrpool_to_atm_patch , & ! Output: [real(r8) (:)] + hrv_leafc_storage_to_litter => cnveg_carbonflux_inst%hrv_leafc_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_frootc_storage_to_litter => cnveg_carbonflux_inst%hrv_frootc_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_livestemc_storage_to_litter => cnveg_carbonflux_inst%hrv_livestemc_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadstemc_storage_to_litter => cnveg_carbonflux_inst%hrv_deadstemc_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_livecrootc_storage_to_litter => cnveg_carbonflux_inst%hrv_livecrootc_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadcrootc_storage_to_litter => cnveg_carbonflux_inst%hrv_deadcrootc_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_gresp_storage_to_litter => cnveg_carbonflux_inst%hrv_gresp_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_leafc_xfer_to_litter => cnveg_carbonflux_inst%hrv_leafc_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_frootc_xfer_to_litter => cnveg_carbonflux_inst%hrv_frootc_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_livestemc_xfer_to_litter => cnveg_carbonflux_inst%hrv_livestemc_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadstemc_xfer_to_litter => cnveg_carbonflux_inst%hrv_deadstemc_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_livecrootc_xfer_to_litter => cnveg_carbonflux_inst%hrv_livecrootc_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadcrootc_xfer_to_litter => cnveg_carbonflux_inst%hrv_deadcrootc_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_gresp_xfer_to_litter => cnveg_carbonflux_inst%hrv_gresp_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + + hrv_leafn_to_litter => cnveg_nitrogenflux_inst%hrv_leafn_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_frootn_to_litter => cnveg_nitrogenflux_inst%hrv_frootn_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_livestemn_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_to_litter_patch , & ! Output: [real(r8) (:)] + wood_harvestn => cnveg_nitrogenflux_inst%wood_harvestn_patch , & ! Output: [real(r8) (:)] + hrv_livecrootn_to_litter => cnveg_nitrogenflux_inst%hrv_livecrootn_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadcrootn_to_litter => cnveg_nitrogenflux_inst%hrv_deadcrootn_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_retransn_to_litter => cnveg_nitrogenflux_inst%hrv_retransn_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_leafn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_leafn_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_frootn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_frootn_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_livestemn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadstemn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_deadstemn_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_livecrootn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_livecrootn_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadcrootn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_deadcrootn_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_leafn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_leafn_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_frootn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_frootn_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_livestemn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadstemn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_deadstemn_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + + + hrv_livecrootn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_livecrootn_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadcrootn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_deadcrootn_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + + grainc_to_food => cnveg_carbonflux_inst%grainc_to_food_patch , & ! Output: [real(r8) (:) ] grain C to food (gC/m2/s) grainc_to_seed => cnveg_carbonflux_inst%grainc_to_seed_patch , & ! Output: [real(r8) (:) ] grain C to seed (gC/m2/s) - leafn => cnveg_nitrogenstate_inst%leafn_patch , & ! Input: [real(r8) (:) ] (gN/m2) leaf N - frootn => cnveg_nitrogenstate_inst%frootn_patch , & ! Input: [real(r8) (:) ] (gN/m2) fine root N livestemn_to_litter => cnveg_nitrogenflux_inst%livestemn_to_litter_patch , & ! Output: [real(r8) (:) ] livestem N to litter (gN/m2/s) + prunen_to_litter => cnveg_nitrogenflux_inst%prunen_to_litter_patch , & ! Output: [real(r8) (:) ] pruning N litterfall (gN/m2/s) + prunen_storage_to_litter => cnveg_nitrogenflux_inst%prunen_storage_to_litter_patch , & ! Output: [real(r8) (:) ] pruning storage N litterfall (gN/m2/s) grainn_to_food => cnveg_nitrogenflux_inst%grainn_to_food_patch , & ! Output: [real(r8) (:) ] grain N to food (gN/m2/s) grainn_to_seed => cnveg_nitrogenflux_inst%grainn_to_seed_patch , & ! Output: [real(r8) (:) ] grain N to seed (gN/m2/s) leafn_to_litter => cnveg_nitrogenflux_inst%leafn_to_litter_patch , & ! Output: [real(r8) (:) ] leaf N litterfall (gN/m2/s) leafn_to_retransn => cnveg_nitrogenflux_inst%leafn_to_retransn_patch , & ! Input: [real(r8) (:) ] leaf N to retranslocated N pool (gN/m2/s) free_retransn_to_npool=> cnveg_nitrogenflux_inst%free_retransn_to_npool_patch , & ! Input: [real(r8) (:) ] free leaf N to retranslocated N pool (gN/m2/s) - paid_retransn_to_npool=> cnveg_nitrogenflux_inst%retransn_to_npool_patch, & ! Input: [real(r8) (:) ] free leaf N to retranslocated N pool (gN/m2/s) + paid_retransn_to_npool=> cnveg_nitrogenflux_inst%retransn_to_npool_patch , & ! Input: [real(r8) (:) ] free leaf N to retranslocated N pool (gN/m2/s) frootn_to_litter => cnveg_nitrogenflux_inst%frootn_to_litter_patch , & ! Output: [real(r8) (:) ] fine root N litterfall (gN/m2/s) leafc_to_litter_fun => cnveg_carbonflux_inst%leafc_to_litter_fun_patch , & ! Output: [real(r8) (:) ] leaf C litterfall used by FUN (gC/m2/s) - leafcn_offset => cnveg_state_inst%leafcn_offset_patch & ! Output: [real(r8) (:) ] Leaf C:N used by FUN + leafcn_offset => cnveg_state_inst%leafcn_offset_patch & ! Output: [real(r8) (:) ] Leaf C:N used by FUN ) + ! get time info + dayspyr = get_days_per_year() + jday = get_curr_calday() + call get_curr_date(kyr, kmo, kda, mcsec) + ! The litterfall transfer rate starts at 0.0 and increases linearly - ! over time, with displayed growth going to 0.0 on the last day of litterfall - + ! over time, with displayed growth going to 0.0 on the last day of litterfall do fp = 1,num_soilp p = filter_soilp(fp) - ! only calculate fluxes during offset period + ! determine days past planting for pruning management + idpp = int(dayspyr)*(kyr-yrop(p)) + jday - idop(p) + !incorporate a one-time harvest: annually for perennial crops (added by O.Dombrowski adopted based on CLM-Palm (Fan et al. 2015)) + !grain flux goes to food + if (harvest_flag(p) == 1._r8)then + if (perennial(ivt(p)) == 1._r8) then + if (grainc(p) > 0._r8) then + t1 = 1.0_r8 / dt + ! replenish seed deficit (needed to balance seedc used for orchard establishment) + grainc_to_seed(p) = t1 * min(-cropseedc_deficit(p), grainc(p)) + grainn_to_seed(p) = t1 * min(-cropseedn_deficit(p), grainn(p)) + ! send remaining grainc to food product pool + grainc_to_food(p) = t1 * grainc(p) + cpool_to_grainc(p) - grainc_to_seed(p) + grainn_to_food(p) = t1 * grainn(p) + npool_to_grainn(p) - grainn_to_seed(p) + + end if + end if + end if + ! only calculate fluxes during offset period (a one time step for crops; multiple days for trees) if (offset_flag(p) == 1._r8) then if (offset_counter(p) == dt) then @@ -2453,7 +3295,9 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & frootc_to_litter(p) = t1 * frootc(p) + cpool_to_frootc(p) ! this assumes that offset_counter == dt for crops ! if this were ever changed, we'd need to add code to the "else" - if (ivt(p) >= npcropmin) then + ! for perennial crops final harvest happens only at rotation + + if (ivt(p) >= npcropmin .and. perennial(ivt(p)) == 0._r8) then ! Replenish the seed deficits from grain, if there is enough ! available grain. (If there is not enough available grain, the seed ! deficits will accumulate until there is eventually enough grain to @@ -2463,9 +3307,35 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & ! Send the remaining grain to the food product pool grainc_to_food(p) = t1 * grainc(p) + cpool_to_grainc(p) - grainc_to_seed(p) grainn_to_food(p) = t1 * grainn(p) + npool_to_grainn(p) - grainn_to_seed(p) - + livestemc_to_litter(p) = t1 * livestemc(p) + cpool_to_livestemc(p) end if + if (prune_flag(p) == 1._r8) then ! perennial fruit tree crops are pruned at the start of the dormancy period + ! young fruit trees are not pruned in the first 3 years after + ! transplanting + if (idpp < 1095._r8) then + pr_fr = 0._r8 + else + pr_fr = prune_fr(ivt(p)) + end if + if (mulch_pruning(ivt(p)) == 0._r8) then ! pruning material is exported + ! carbon fluxes to wood product pool + wood_harvestc(p) = t1 * ((deadstemc(p)-deadstemc_soy(p))*pr_fr) + hrv_deadstemc_storage_to_litter(p) = t1 * ((deadstemc_storage(p)-deadstemc_storage_soy(p))*pr_fr) + ! corresponding nitrogen fluxes + wood_harvestn(p) = t1 * ((deadstemn(p)-deadstemn_soy(p))*pr_fr) + hrv_deadstemn_storage_to_litter(p) = t1 * ((deadstemn_storage(p)-deadstemn_storage_soy(p))*pr_fr) + + else if (mulch_pruning(ivt(p)) == 1._r8) then ! pruning material is mulched into the soil + ! carbon fluxes to wood product pool + prunec_to_litter(p) = t1 * ((deadstemc(p)-deadstemc_soy(p))*pr_fr) + prunec_storage_to_litter(p) = t1 * ((deadstemc_storage(p)-deadstemc_storage_soy(p))*pr_fr) + ! corresponding nitrogen fluxes + prunen_to_litter(p) = t1 * ((deadstemn(p)-deadstemn_soy(p))*pr_fr) + prunen_storage_to_litter(p) = t1 *((deadstemn_storage(p)-deadstemn_storage_soy(p))*pr_fr) + end if + end if + else t1 = dt * 2.0_r8 / (offset_counter(p) * offset_counter(p)) leafc_to_litter(p) = prev_leafc_to_litter(p) + t1*(leafc(p) - prev_leafc_to_litter(p)*offset_counter(p)) @@ -2473,6 +3343,7 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & end if + if ( use_fun ) then if(leafc_to_litter(p)*dt.gt.leafc(p))then leafc_to_litter(p) = leafc(p)/dt + cpool_to_leafc(p) @@ -2506,7 +3377,6 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & else fr_leafn_to_litter = 1.0_r8 end if - else if (CNratio_floating .eqv. .true.) then fr_leafn_to_litter = 0.5_r8 ! assuming 50% of nitrogen turnover goes to litter @@ -2531,9 +3401,9 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & leafn_to_retransn(p) = ntovr_leaf - leafn_to_litter(p) if (frootc(p) == 0.0_r8) then frootn_to_litter(p) = 0.0_r8 - else + else frootn_to_litter(p) = frootc_to_litter(p) * (frootn(p) / frootc(p)) - end if + end if end if if ( use_fun ) then @@ -2541,8 +3411,8 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & frootn_to_litter(p) = frootn(p)/dt endif end if - - if (ivt(p) >= npcropmin) then + + if (ivt(p) >= npcropmin .and. perennial(ivt(p)) == 0._r8) then ! NOTE(slevis, 2014-12) results in -ve livestemn and -ve totpftn !X! livestemn_to_litter(p) = livestemc_to_litter(p) / livewdcn(ivt(p)) ! NOTE(slevis, 2014-12) Beth Drewniak suggested this instead @@ -2554,9 +3424,73 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & prev_frootc_to_litter(p) = frootc_to_litter(p) end if ! end if offset period + ! offset2 is newly implemented for fruit trees, it initializes orchard + ! rotation (complete harvest of all plant organs) after maximum + ! lifespan is reached + ! (introduced in CLM-Palm (Fan et al. 2015), and adopted here by O.Dombrowski) + if (offset2_flag(p) == 1._r8 .and. perennial(ivt(p)) == 1._r8) then + ! Apply all harvest at the start of the year, otherwise will get + ! error because of non zero delta mid-year for dribbler + ! hrv_xsmrpool_to_atm_c + if (is_beg_curr_year()) then + croplive(p) = .false. + t1 = 1.0_r8 / dt + ! clear-cut carbon fluxes, remove all displayed/storage/transfer pools + ! displayed pools + hrv_leafc_to_litter(p) = leafc(p) * t1 + hrv_leafn_to_litter(p) = leafn(p) * t1 + hrv_frootc_to_litter(p) = frootc(p) * t1 + hrv_frootn_to_litter(p) = frootn(p) * t1 + hrv_livestemc_to_litter(p) = livestemc(p) * t1 + hrv_livestemn_to_litter(p) = livestemn(p) * t1 + wood_harvestc(p) = deadstemc(p) * t1 + wood_harvestn(p) = deadstemn(p) * t1 + hrv_livecrootc_to_litter(p) = livecrootc(p) * t1 + hrv_livecrootn_to_litter(p) = livecrootn(p) * t1 + hrv_deadcrootc_to_litter(p) = deadcrootc(p) * t1 + hrv_deadcrootn_to_litter(p) = deadcrootn(p) * t1 + hrv_xsmrpool_to_atm(p) = xsmrpool(p) * t1 + + ! storage pools + hrv_leafc_storage_to_litter(p) = leafc_storage(p) * t1 + hrv_leafn_storage_to_litter(p) = leafn_storage(p) * t1 + hrv_frootc_storage_to_litter(p) = frootc_storage(p) * t1 + hrv_frootn_storage_to_litter(p) = frootn_storage(p) * t1 + hrv_livestemc_storage_to_litter(p) = livestemc_storage(p) * t1 + hrv_livestemn_storage_to_litter(p) = livestemn_storage(p) * t1 + hrv_deadstemc_storage_to_litter(p) = deadstemc_storage(p) * t1 + hrv_deadstemn_storage_to_litter(p) = deadstemn_storage(p) * t1 + hrv_livecrootc_storage_to_litter(p) = livecrootc_storage(p) * t1 + hrv_livecrootn_storage_to_litter(p) = livecrootn_storage(p) * t1 + hrv_deadcrootc_storage_to_litter(p) = deadcrootc_storage(p) * t1 + hrv_deadcrootn_storage_to_litter(p) = deadcrootn_storage(p) * t1 + hrv_gresp_storage_to_litter(p) = gresp_storage(p) * t1 + + ! transfer pools + hrv_leafc_xfer_to_litter(p) = leafc_xfer(p) * t1 + hrv_leafn_xfer_to_litter(p) = leafn_xfer(p) * t1 + hrv_frootc_xfer_to_litter(p) = frootc_xfer(p) * t1 + hrv_frootn_xfer_to_litter(p) = frootn_xfer(p) * t1 + hrv_livestemc_xfer_to_litter(p) = livestemc_xfer(p) * t1 + hrv_livestemn_xfer_to_litter(p) = livestemn_xfer(p) * t1 + hrv_deadstemc_xfer_to_litter(p) = deadstemc_xfer(p) * t1 + hrv_deadstemn_xfer_to_litter(p) = deadstemn_xfer(p) * t1 + hrv_livecrootc_xfer_to_litter(p) = livecrootc_xfer(p) * t1 + hrv_livecrootn_xfer_to_litter(p) = livecrootn_xfer(p) * t1 + hrv_deadcrootc_xfer_to_litter(p) = deadcrootc_xfer(p) * t1 + hrv_deadcrootn_xfer_to_litter(p) = deadcrootn_xfer(p) * t1 + hrv_gresp_xfer_to_litter(p) = gresp_xfer(p) * t1 + + ! retransn pools + hrv_retransn_to_litter(p) = retransn(p) * t1 - end do ! end patch loop + else + croplive(p) = .true. + end if + end if ! end orchard rotation + end do ! end patch loop + end associate end subroutine CNOffsetLitterfall @@ -2855,16 +3789,16 @@ subroutine CNGrainToProductPools(bounds, num_soilp, filter_soilp, num_soilc, fil end subroutine CNGrainToProductPools !----------------------------------------------------------------------- - subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & - cnveg_state_inst,cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & - leaf_prof_patch, froot_prof_patch) + subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & + cnveg_state_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & + leaf_prof_patch, froot_prof_patch, stem_prof_patch) ! ! !DESCRIPTION: ! called at the end of cn_phenology to gather all patch-level litterfall fluxes ! to the column level and assign them to the three litter pools ! ! !USES: - use clm_varpar , only : max_patch_per_col, nlevdecomp + use clm_varpar , only : max_patch_per_col,maxpatch_pft, nlevdecomp use pftconMod , only : npcropmin use clm_varctl , only : use_grainproduct ! @@ -2877,6 +3811,7 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst real(r8) , intent(in) :: leaf_prof_patch(bounds%begp:,1:) real(r8) , intent(in) :: froot_prof_patch(bounds%begp:,1:) + real(r8) , intent(in) :: stem_prof_patch(bounds%begp:,1:) ! ! !LOCAL VARIABLES: integer :: fc,c,pi,p,j ! indices @@ -2884,11 +3819,12 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & SHR_ASSERT_ALL((ubound(leaf_prof_patch) == (/bounds%endp,nlevdecomp_full/)), errMsg(sourcefile, __LINE__)) SHR_ASSERT_ALL((ubound(froot_prof_patch) == (/bounds%endp,nlevdecomp_full/)), errMsg(sourcefile, __LINE__)) + SHR_ASSERT_ALL((ubound(stem_prof_patch) == (/bounds%endp,nlevdecomp_full/)), errMsg(sourcefile, __LINE__)) associate( & leaf_prof => leaf_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of leaves froot_prof => froot_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of fine roots - + stem_prof => stem_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of stems ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type wtcol => patch%wtcol , & ! Input: [real(r8) (:) ] weight (relative to column) for this patch (0-1) @@ -2898,24 +3834,56 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & fr_flab => pftcon%fr_flab , & ! Input: fine root litter labile fraction fr_fcel => pftcon%fr_fcel , & ! Input: fine root litter cellulose fraction fr_flig => pftcon%fr_flig , & ! Input: fine root litter lignin fraction - + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types + mulch_pruning => pftcon%mulch_pruning , & ! Input: binary flag for mulching or exporting of pruning material + prune_flag => cnveg_state_inst%prune_flag_patch , & ! Input: binary flag for pruning of perennial crop types + offset2_flag => cnveg_state_inst%offset2_flag_patch , & ! Input: binary flag for rotation of perennial crop types leafc_to_litter => cnveg_carbonflux_inst%leafc_to_litter_patch , & ! Input: [real(r8) (:) ] leaf C litterfall (gC/m2/s) frootc_to_litter => cnveg_carbonflux_inst%frootc_to_litter_patch , & ! Input: [real(r8) (:) ] fine root N litterfall (gN/m2/s) livestemc_to_litter => cnveg_carbonflux_inst%livestemc_to_litter_patch , & ! Input: [real(r8) (:) ] live stem C litterfall (gC/m2/s) + prunec_to_litter => cnveg_carbonflux_inst%prunec_to_litter_patch , & ! Input: [real(r8) (:) ] pruning C litterfall (gC/m2/s) + prunec_storage_to_litter => cnveg_carbonflux_inst%prunec_storage_to_litter_patch , & ! Input: [real(r8) (:) ] pruning storage C litterfall (gC/m2/s) + grainc_to_food => cnveg_carbonflux_inst%grainc_to_food_patch , & ! Input: [real(r8) (:) ] grain C to food (gC/m2/s) phenology_c_to_litr_met_c => cnveg_carbonflux_inst%phenology_c_to_litr_met_c_col , & ! Output: [real(r8) (:,:) ] C fluxes associated with phenology (litterfall and crop) to litter metabolic pool (gC/m3/s) phenology_c_to_litr_cel_c => cnveg_carbonflux_inst%phenology_c_to_litr_cel_c_col , & ! Output: [real(r8) (:,:) ] C fluxes associated with phenology (litterfall and crop) to litter cellulose pool (gC/m3/s) phenology_c_to_litr_lig_c => cnveg_carbonflux_inst%phenology_c_to_litr_lig_c_col , & ! Output: [real(r8) (:,:) ] C fluxes associated with phenology (litterfall and crop) to litter lignin pool (gC/m3/s) livestemn_to_litter => cnveg_nitrogenflux_inst%livestemn_to_litter_patch , & ! Input: [real(r8) (:) ] livestem N to litter (gN/m2/s) + prunen_to_litter => cnveg_nitrogenflux_inst%prunen_to_litter_patch , & ! Input: [real(r8) (:) ] pruning N litterfall (gN/m2/s) + prunen_storage_to_litter => cnveg_nitrogenflux_inst%prunen_storage_to_litter_patch , & ! Input: [real(r8) (:) ] pruning storage N litterfall (gN/m2/s) grainn_to_food => cnveg_nitrogenflux_inst%grainn_to_food_patch , & ! Input: [real(r8) (:) ] grain N to food (gN/m2/s) + leafn_to_litter => cnveg_nitrogenflux_inst%leafn_to_litter_patch , & ! Input: [real(r8) (:) ] leaf N litterfall (gN/m2/s) frootn_to_litter => cnveg_nitrogenflux_inst%frootn_to_litter_patch , & ! Input: [real(r8) (:) ] fine root N litterfall (gN/m2/s) phenology_n_to_litr_met_n => cnveg_nitrogenflux_inst%phenology_n_to_litr_met_n_col , & ! Output: [real(r8) (:,:) ] N fluxes associated with phenology (litterfall and crop) to litter metabolic pool (gN/m3/s) phenology_n_to_litr_cel_n => cnveg_nitrogenflux_inst%phenology_n_to_litr_cel_n_col , & ! Output: [real(r8) (:,:) ] N fluxes associated with phenology (litterfall and crop) to litter cellulose pool (gN/m3/s) - phenology_n_to_litr_lig_n => cnveg_nitrogenflux_inst%phenology_n_to_litr_lig_n_col & ! Output: [real(r8) (:,:) ] N fluxes associated with phenology (litterfall and crop) to litter lignin pool (gN/m3/s) + phenology_n_to_litr_lig_n => cnveg_nitrogenflux_inst%phenology_n_to_litr_lig_n_col , & ! Output: [real(r8) (:,:) ] N fluxes associated with phenology (litterfall and crop) to litter lignin pool (gN/m3/s) + hrv_livestemc_to_litter => cnveg_carbonflux_inst%hrv_livestemc_to_litter_patch , & ! Input: [real(r8) (:) ] + pwood_harvestc => cnveg_carbonflux_inst%wood_harvestc_patch , & ! Input: [real(r8) (:) ] + hrv_livestemc_storage_to_litter => cnveg_carbonflux_inst%hrv_livestemc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadstemc_storage_to_litter => cnveg_carbonflux_inst%hrv_deadstemc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + cwood_harvestc => cnveg_carbonflux_inst%wood_harvestc_col , & ! InOut: [real(r8) (:) ] + m_deadstemc_to_litter => cnveg_carbonflux_inst%m_deadstemc_to_litter_patch , & ! Input: [real(r8) (:) ] + m_deadstemc_storage_to_litter => cnveg_carbonflux_inst%m_deadstemc_storage_to_litter_patch , & ! Input:[real(r8) (:) ] + harvest_c_to_litr_met_c => cnveg_carbonflux_inst%harvest_c_to_litr_met_c_col , & ! InOut: [real(r8) (:,:) ] C fluxes associated with harvest to litter metabolic pool (gC/m3/s) + harvest_c_to_cwdc => cnveg_carbonflux_inst%harvest_c_to_cwdc_col , & ! InOut: [real(r8) (:,:) ] C fluxes associated with harvest to CWD pool (gC/m3/s) + gap_mortality_c_to_litr_met_c => cnveg_carbonflux_inst%gap_mortality_c_to_litr_met_c_col , & ! Output: [real(r8) (:,:) ] C fluxes associated with gap mortality to litter metabolic pool (gC/m3/s) + gap_mortality_c_to_cwdc => cnveg_carbonflux_inst%gap_mortality_c_to_cwdc_col , & ! Output: [real(r8) (:,:) ] C fluxes associated with gap mortality to CWD pool (gC/m3/s) + hrv_livestemn_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_to_litter_patch , & ! Input: [real(r8) (:) ] + pwood_harvestn => cnveg_nitrogenflux_inst%wood_harvestn_patch , & ! Input: [real(r8) (:) ] + hrv_livestemn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadstemn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_deadstemn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + cwood_harvestn => cnveg_nitrogenflux_inst%wood_harvestn_col , & ! InOut: [real(r8) (:) ] + harvest_n_to_litr_met_n => cnveg_nitrogenflux_inst%harvest_n_to_litr_met_n_col , & ! InOut: [real(r8) (:,:) ] N fluxes associated with harvest to litter metabolic pool (gN/m3/s) + harvest_n_to_cwdn => cnveg_nitrogenflux_inst%harvest_n_to_cwdn_col , & ! InOut: [real(r8) (:,:) ] C fluxes associated with harvest to CWD pool (gC/m3/s) + m_deadstemn_to_litter => cnveg_nitrogenflux_inst%m_deadstemn_to_litter_patch , & ! Input: [real(r8) (:) ] + m_deadstemn_storage_to_litter => cnveg_nitrogenflux_inst%m_deadstemn_storage_to_litter_patch , & ! Input:[real(r8) (:) ] + + gap_mortality_n_to_litr_met_n => cnveg_nitrogenflux_inst%gap_mortality_n_to_litr_met_n_col , & ! Output: [real(r8) (:,:) ] N fluxes associated with gap mortality to litter metabolic pool (gN/m3/s) + gap_mortality_n_to_cwdn => cnveg_nitrogenflux_inst%gap_mortality_n_to_cwdn_col & ! Output: [real(r8) (:,:) ] N fluxes associated with gap mortality to CWD pool (gN/m3/s) ) - + do j = 1, nlevdecomp do pi = 1,max_patch_per_col do fc = 1,num_soilc @@ -2949,6 +3917,7 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & phenology_c_to_litr_lig_c(c,j) = phenology_c_to_litr_lig_c(c,j) & + frootc_to_litter(p) * fr_flig(ivt(p)) * wtcol(p) * froot_prof(p,j) + ! fine root litter nitrogen fluxes phenology_n_to_litr_met_n(c,j) = phenology_n_to_litr_met_n(c,j) & + frootn_to_litter(p) * fr_flab(ivt(p)) * wtcol(p) * froot_prof(p,j) @@ -2962,22 +3931,26 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & ! new ones for now (slevis) ! also for simplicity I've put "food" into the litter pools - if (ivt(p) >= npcropmin) then ! add livestemc to litter - ! stem litter carbon fluxes - phenology_c_to_litr_met_c(c,j) = phenology_c_to_litr_met_c(c,j) & - + livestemc_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) - phenology_c_to_litr_cel_c(c,j) = phenology_c_to_litr_cel_c(c,j) & - + livestemc_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) - phenology_c_to_litr_lig_c(c,j) = phenology_c_to_litr_lig_c(c,j) & - + livestemc_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) - - ! stem litter nitrogen fluxes - phenology_n_to_litr_met_n(c,j) = phenology_n_to_litr_met_n(c,j) & - + livestemn_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) - phenology_n_to_litr_cel_n(c,j) = phenology_n_to_litr_cel_n(c,j) & - + livestemn_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) - phenology_n_to_litr_lig_n(c,j) = phenology_n_to_litr_lig_n(c,j) & - + livestemn_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) + if (ivt(p) >= npcropmin) then + if ( perennial(ivt(p)) == 0._r8) then + ! add livestemc to litter + ! stem litter carbon fluxes + phenology_c_to_litr_met_c(c,j) = phenology_c_to_litr_met_c(c,j) & + + livestemc_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_c_to_litr_cel_c(c,j) = phenology_c_to_litr_cel_c(c,j) & + + livestemc_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_c_to_litr_lig_c(c,j) = phenology_c_to_litr_lig_c(c,j) & + + livestemc_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) + + ! stem litter nitrogen fluxes + phenology_n_to_litr_met_n(c,j) = phenology_n_to_litr_met_n(c,j) & + + livestemn_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_n_to_litr_cel_n(c,j) = phenology_n_to_litr_cel_n(c,j) & + + livestemn_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_n_to_litr_lig_n(c,j) = phenology_n_to_litr_lig_n(c,j) & + + livestemn_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) + + end if if (.not. use_grainproduct) then ! grain litter carbon fluxes @@ -2997,18 +3970,339 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & + grainn_to_food(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) end if + ! calculate pruning litter fluxes added by O.Dombrowski + ! and adapted based on CLM-Palm (Fan et al. 2015) + if ( perennial(ivt(p)) == 1._r8 .and. prune_flag(p) == 1._r8) then + if (mulch_pruning(ivt(p)) == 0._r8) then + ! export pruning material as harvest + ! storage harvest mortality carbon fluxes + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_deadstemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + ! storage harvest mortality nitrogen fluxes + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_deadstemn_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + + ! wood harvest mortality carbon fluxes to product pools + !cwood_harvestc(c) = cwood_harvestc(c) + & + !pwood_harvestc(p) * wtcol(p) + ! wood harvest mortality nitrogen fluxes to product pools + !cwood_harvestn(c) = cwood_harvestn(c) + & + !pwood_harvestn(p) * wtcol(p) + + else if (mulch_pruning(ivt(p)) == 1._r8) then + ! add pruning material to litter + ! pruning carbon fluxes + phenology_c_to_litr_met_c(c,j) = phenology_c_to_litr_met_c(c,j) & + + prunec_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) & + + prunec_storage_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_c_to_litr_cel_c(c,j) = phenology_c_to_litr_cel_c(c,j) & + + prunec_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) & + + prunec_storage_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_c_to_litr_lig_c(c,j) = phenology_c_to_litr_lig_c(c,j) & + + prunec_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) & + + prunec_storage_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) + + ! pruning nitrogen fluxes + phenology_n_to_litr_met_n(c,j) = phenology_n_to_litr_met_n(c,j) & + + prunen_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) & + + prunen_storage_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_n_to_litr_cel_n(c,j) = phenology_n_to_litr_cel_n(c,j) & + + prunen_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) & + + prunen_storage_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_n_to_litr_lig_n(c,j) = phenology_n_to_litr_lig_n(c,j) & + + prunen_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) & + + prunen_storage_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) + end if + end if end if end if end if end do - end do end do - end associate + + do pi = 1,maxpatch_pft + do fc = 1,num_soilc + c = filter_soilc(fc) + + if (pi <= col%npatches(c)) then + p = col%patchi(c) + pi - 1 + if (perennial(ivt(p)) == 1._r8 .and. prune_flag(p) == 1._r8 .and. mulch_pruning(ivt(p)) == 0._r8) then + if (patch%active(p)) then + ! wood harvest mortality carbon fluxes to product pools + cwood_harvestc(c) = cwood_harvestc(c) + & + pwood_harvestc(p) * wtcol(p) + + ! wood harvest mortality nitrogen fluxes to product pools + cwood_harvestn(c) = cwood_harvestn(c) + & + pwood_harvestn(p) * wtcol(p) + end if + end if + end if + + end do + + end do + + end associate end subroutine CNLitterToColumn + !----------------------------------------------------------------------- + subroutine CNRotationToColumn (num_soilc, filter_soilc, & + cnveg_state_inst, soilbiogeochem_state_inst, & + crop_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) + ! + ! !DESCRIPTION: + ! called at the end of CNPhenology to gather all patch-level orchard rotation litterfall + ! fluxes + ! to the column level and assign them to the three litter pools + ! + ! !USES: + use clm_varpar , only : maxpatch_pft, nlevdecomp + use pftconMod , only : npcropmin + ! + ! !ARGUMENTS: + integer , intent(in) :: num_soilc ! number of soil columns in filter + integer , intent(in) :: filter_soilc(:) ! soil column filter + type(crop_type) , intent(inout) :: crop_inst + type(cnveg_state_type) , intent(in) :: cnveg_state_inst + type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst + type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst + type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst + ! + ! !LOCAL VARIABLES: + integer :: fc,c,pi,p,j ! indices + !----------------------------------------------------------------------- + + associate( & + ivt => patch%itype , & ! Input: [integer (:) ] pft vegetation type + wtcol => patch%wtcol , & ! Input: [real(r8) (:) ] pft weight relative to column (0-1) + + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types + lf_flab => pftcon%lf_flab , & ! Input: leaf litter labile fraction + lf_fcel => pftcon%lf_fcel , & ! Input: leaf litter cellulose fraction + lf_flig => pftcon%lf_flig , & ! Input: leaf litter lignin fraction + fr_flab => pftcon%fr_flab , & ! Input: fine root litter labile fraction + fr_fcel => pftcon%fr_fcel , & ! Input: fine root litter cellulose fraction + fr_flig => pftcon%fr_flig , & ! Input: fine root litter lignin fraction + + offset2_flag => cnveg_state_inst%offset2_flag_patch , & ! Input: binary flag for rotation of perennial crop types + croplive => crop_inst%croplive_patch , & ! Output: [logical (:) ] Flag, true if planted, not harvested + + leaf_prof => soilbiogeochem_state_inst%leaf_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of leaves + froot_prof => soilbiogeochem_state_inst%froot_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of fine roots + croot_prof => soilbiogeochem_state_inst%croot_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of coarse roots + stem_prof => soilbiogeochem_state_inst%stem_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of stems + + hrv_leafc_to_litter => cnveg_carbonflux_inst%hrv_leafc_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_frootc_to_litter => cnveg_carbonflux_inst%hrv_frootc_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livestemc_to_litter => cnveg_carbonflux_inst%hrv_livestemc_to_litter_patch , & ! Input: [real(r8) (:) ] + pwood_harvestc => cnveg_carbonflux_inst%wood_harvestc_patch , & ! Input: [real(r8) (:) ] + hrv_livecrootc_to_litter => cnveg_carbonflux_inst%hrv_livecrootc_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadcrootc_to_litter => cnveg_carbonflux_inst%hrv_deadcrootc_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_leafc_storage_to_litter => cnveg_carbonflux_inst%hrv_leafc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_frootc_storage_to_litter => cnveg_carbonflux_inst%hrv_frootc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livestemc_storage_to_litter => cnveg_carbonflux_inst%hrv_livestemc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadstemc_storage_to_litter => cnveg_carbonflux_inst%hrv_deadstemc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livecrootc_storage_to_litter => cnveg_carbonflux_inst%hrv_livecrootc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadcrootc_storage_to_litter => cnveg_carbonflux_inst%hrv_deadcrootc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_gresp_storage_to_litter => cnveg_carbonflux_inst%hrv_gresp_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_leafc_xfer_to_litter => cnveg_carbonflux_inst%hrv_leafc_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_frootc_xfer_to_litter => cnveg_carbonflux_inst%hrv_frootc_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livestemc_xfer_to_litter => cnveg_carbonflux_inst%hrv_livestemc_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadstemc_xfer_to_litter => cnveg_carbonflux_inst%hrv_deadstemc_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livecrootc_xfer_to_litter => cnveg_carbonflux_inst%hrv_livecrootc_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadcrootc_xfer_to_litter => cnveg_carbonflux_inst%hrv_deadcrootc_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_gresp_xfer_to_litter => cnveg_carbonflux_inst%hrv_gresp_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + cwood_harvestc => cnveg_carbonflux_inst%wood_harvestc_col , & ! InOut: [real(r8) (:) ] + harvest_c_to_litr_met_c => cnveg_carbonflux_inst%harvest_c_to_litr_met_c_col , & ! InOut: [real(r8) (:,:) ] C fluxes associated with harvest to litter metabolic pool (gC/m3/s) + harvest_c_to_litr_cel_c => cnveg_carbonflux_inst%harvest_c_to_litr_cel_c_col , & ! InOut: [real(r8) (:,:) ] C fluxes associated with harvest to litter cellulose pool (gC/m3/s) + harvest_c_to_litr_lig_c => cnveg_carbonflux_inst%harvest_c_to_litr_lig_c_col , & ! InOut: [real(r8) (:,:) ] C fluxes associated with harvest to litter lignin pool (gC/m3/s) + harvest_c_to_cwdc => cnveg_carbonflux_inst%harvest_c_to_cwdc_col , & ! InOut: [real(r8) (:,:) ] C fluxes associated with harvest to CWD pool (gC/m3/s) + + hrv_leafn_to_litter => cnveg_nitrogenflux_inst%hrv_leafn_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_frootn_to_litter => cnveg_nitrogenflux_inst%hrv_frootn_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livestemn_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_to_litter_patch , & ! Input: [real(r8) (:) ] + pwood_harvestn => cnveg_nitrogenflux_inst%wood_harvestn_patch , & ! Input: [real(r8) (:) ] + hrv_livecrootn_to_litter => cnveg_nitrogenflux_inst%hrv_livecrootn_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadcrootn_to_litter => cnveg_nitrogenflux_inst%hrv_deadcrootn_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_retransn_to_litter => cnveg_nitrogenflux_inst%hrv_retransn_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_leafn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_leafn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_frootn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_frootn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livestemn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadstemn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_deadstemn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livecrootn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_livecrootn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadcrootn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_deadcrootn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_leafn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_leafn_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_frootn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_frootn_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livestemn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadstemn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_deadstemn_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livecrootn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_livecrootn_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadcrootn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_deadcrootn_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + cwood_harvestn => cnveg_nitrogenflux_inst%wood_harvestn_col , & ! InOut: [real(r8) (:) ] + harvest_n_to_litr_met_n => cnveg_nitrogenflux_inst%harvest_n_to_litr_met_n_col , & ! InOut: [real(r8) (:,:) ] N fluxes associated with harvest to litter metabolic pool (gN/m3/s) + harvest_n_to_litr_cel_n => cnveg_nitrogenflux_inst%harvest_n_to_litr_cel_n_col , & ! InOut: [real(r8) (:,:) ] N fluxes associated with harvest to litter cellulose pool (gN/m3/s) + harvest_n_to_litr_lig_n => cnveg_nitrogenflux_inst%harvest_n_to_litr_lig_n_col , & ! InOut: [real(r8) (:,:) ] N fluxes associated with harvest to litter lignin pool (gN/m3/s) + harvest_n_to_cwdn => cnveg_nitrogenflux_inst%harvest_n_to_cwdn_col & ! InOut: [real(r8) (:,:) ] N fluxes associated with harvest to CWD pool (gN/m3/s) + ) + + do j = 1, nlevdecomp + do pi = 1,maxpatch_pft + do fc = 1,num_soilc + c = filter_soilc(fc) + + if (pi <= col%npatches(c)) then + p = col%patchi(c) + pi - 1 + + if (patch%active(p) .and. (.not. croplive(p)) .and. ivt(p) >= npcropmin .and. perennial(ivt(p)) == 1._r8 .and. offset2_flag(p) == 1._r8) then + + ! leaf harvest mortality carbon fluxes + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_leafc_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) + harvest_c_to_litr_cel_c(c,j) = harvest_c_to_litr_cel_c(c,j) + & + hrv_leafc_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) + harvest_c_to_litr_lig_c(c,j) = harvest_c_to_litr_lig_c(c,j) + & + hrv_leafc_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) + + ! fine root harvest mortality carbon fluxes + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_frootc_to_litter(p) * fr_flab(ivt(p)) * wtcol(p) * froot_prof(p,j) + harvest_c_to_litr_cel_c(c,j) = harvest_c_to_litr_cel_c(c,j) + & + hrv_frootc_to_litter(p) * fr_fcel(ivt(p)) * wtcol(p) * froot_prof(p,j) + harvest_c_to_litr_lig_c(c,j) = harvest_c_to_litr_lig_c(c,j) + & + hrv_frootc_to_litter(p) * fr_flig(ivt(p)) * wtcol(p) * froot_prof(p,j) + + ! wood harvest mortality carbon fluxes + harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & + hrv_livestemc_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & + hrv_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & + hrv_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) + ! storage harvest mortality carbon fluxes + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_leafc_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_frootc_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_livestemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_deadstemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_livecrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_deadcrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_gresp_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + + ! transfer harvest mortality carbon fluxes + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_leafc_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_frootc_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_livestemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_deadstemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_livecrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_deadcrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_gresp_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + + ! leaf harvest mortality nitrogen fluxes + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_leafn_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) + harvest_n_to_litr_cel_n(c,j) = harvest_n_to_litr_cel_n(c,j) + & + hrv_leafn_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) + harvest_n_to_litr_lig_n(c,j) = harvest_n_to_litr_lig_n(c,j) + & + hrv_leafn_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) + + ! fine root litter nitrogen fluxes + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_frootn_to_litter(p) * fr_flab(ivt(p)) * wtcol(p) * froot_prof(p,j) + harvest_n_to_litr_cel_n(c,j) = harvest_n_to_litr_cel_n(c,j) + & + hrv_frootn_to_litter(p) * fr_fcel(ivt(p)) * wtcol(p) * froot_prof(p,j) + harvest_n_to_litr_lig_n(c,j) = harvest_n_to_litr_lig_n(c,j) + & + hrv_frootn_to_litter(p) * fr_flig(ivt(p)) * wtcol(p) * froot_prof(p,j) + + ! wood harvest mortality nitrogen fluxes + harvest_n_to_cwdn(c,j) = harvest_n_to_cwdn(c,j) + & + hrv_livestemn_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_n_to_cwdn(c,j) = harvest_n_to_cwdn(c,j) + & + hrv_livecrootn_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_n_to_cwdn(c,j) = harvest_n_to_cwdn(c,j) + & + hrv_deadcrootn_to_litter(p) * wtcol(p) * croot_prof(p,j) + + ! retranslocated N pool harvest mortality fluxes + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_retransn_to_litter(p) * wtcol(p) * leaf_prof(p,j) + + ! storage harvest mortality nitrogen fluxes + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_leafn_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_frootn_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_livestemn_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_deadstemn_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_livecrootn_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_deadcrootn_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + + ! transfer harvest mortality nitrogen fluxes + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_leafn_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_frootn_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_livestemn_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_deadstemn_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_livecrootn_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_deadcrootn_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + + end if + end if + + end do + + end do + end do + + do pi = 1,maxpatch_pft + do fc = 1,num_soilc + c = filter_soilc(fc) + + if (pi <= col%npatches(c)) then + p = col%patchi(c) + pi - 1 + + if (patch%active(p)) then + ! wood harvest mortality carbon fluxes to product pools + cwood_harvestc(c) = cwood_harvestc(c) + & + pwood_harvestc(p) * wtcol(p) + + ! wood harvest mortality nitrogen fluxes to product pools + cwood_harvestn(c) = cwood_harvestn(c) + & + pwood_harvestn(p) * wtcol(p) + end if + end if + + end do + + end do + + end associate + + end subroutine CNRotationToColumn + end module CNPhenologyMod diff --git a/src/clm5/biogeochem/CNVegCarbonFluxType.F90 b/src/clm5/biogeochem/CNVegCarbonFluxType.F90 index f88c7f5e66..681b394f3e 100644 --- a/src/clm5/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/clm5/biogeochem/CNVegCarbonFluxType.F90 @@ -17,7 +17,7 @@ module CNVegCarbonFluxType use clm_varctl , only : use_grainproduct use clm_varctl , only : iulog use landunit_varcon , only : istsoil, istcrop, istdlak - use pftconMod , only : npcropmin + use pftconMod , only : npcropmin, pftcon use LandunitType , only : lun use ColumnType , only : col use PatchType , only : patch @@ -136,6 +136,10 @@ module CNVegCarbonFluxType real(r8), pointer :: grainc_to_food_patch (:) ! grain C to food for prognostic crop(gC/m2/s) real(r8), pointer :: grainc_to_seed_patch (:) ! grain C to seed for prognostic crop(gC/m2/s) + ! pruning litterfall flux + real(r8), pointer :: prunec_to_litter_patch (:) ! pruning C litterfall (gC/m2/s) + real(r8), pointer :: prunec_storage_to_litter_patch (:) ! pruning storage C litterfall (gC/m2/s) + ! maintenance respiration fluxes real(r8), pointer :: cpool_to_resp_patch (:) ! CNflex excess C maintenance respiration (gC/m2/s) real(r8), pointer :: cpool_to_leafc_resp_patch (:) ! CNflex excess C maintenance respiration (gC/m2/s) @@ -274,6 +278,8 @@ module CNVegCarbonFluxType ! crop fluxes real(r8), pointer :: crop_seedc_to_leaf_patch (:) ! (gC/m2/s) seed source to leaf, for crops + real(r8), pointer :: crop_seedc_to_froot_patch (:) ! (gC/m2/s) seed source to fine roots, for perennial crops (added by O.Dombrowski) + real(r8), pointer :: crop_seedc_to_deadstem_patch (:) ! (gC/m2/s) seed source to deadstem, for perennial crops (added by O.Dombrowski) ! summary (diagnostic) flux variables, not involved in mass balance real(r8), pointer :: gpp_before_downreg_patch (:) ! (gC/m2/s) gross primary production before down regulation @@ -615,6 +621,8 @@ subroutine InitAllocate(this, bounds, carbon_type) allocate(this%leafc_loss_patch (begp:endp)) ; this%leafc_loss_patch (:) = nan allocate(this%woodc_alloc_patch (begp:endp)) ; this%woodc_alloc_patch (:) = nan allocate(this%woodc_loss_patch (begp:endp)) ; this%woodc_loss_patch (:) = nan + allocate(this%prunec_to_litter_patch (begp:endp)) ; this%prunec_to_litter_patch (:) = nan + allocate(this%prunec_storage_to_litter_patch (begp:endp)) ; this%prunec_storage_to_litter_patch (:) = nan allocate(this%phenology_c_to_litr_met_c_col (begc:endc,1:nlevdecomp_full)); this%phenology_c_to_litr_met_c_col (:,:)=nan @@ -654,6 +662,8 @@ subroutine InitAllocate(this, bounds, carbon_type) allocate(this%dwt_crop_productc_gain_patch (begp:endp)) ; this%dwt_crop_productc_gain_patch(:) =nan allocate(this%crop_seedc_to_leaf_patch (begp:endp)) ; this%crop_seedc_to_leaf_patch (:) =nan + allocate(this%crop_seedc_to_froot_patch (begp:endp)) ; this%crop_seedc_to_froot_patch (:) =nan + allocate(this%crop_seedc_to_deadstem_patch (begp:endp)) ; this%crop_seedc_to_deadstem_patch (:) =nan allocate(this%cwdc_hr_col (begc:endc)) ; this%cwdc_hr_col (:) =nan allocate(this%cwdc_loss_col (begc:endc)) ; this%cwdc_loss_col (:) =nan @@ -1264,6 +1274,11 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='live coarse root maintenance respiration', & ptr_patch=this%livecroot_mr_patch, default='inactive') + this%grain_mr_patch(begp:endp) = spval + call hist_addfld1d (fname='GRAIN_MR', units='gC/m^2/s', & + avgflag='A', long_name='grain maintenance respiration', & + ptr_patch=this%grain_mr_patch, default='inactive') + this%psnsun_to_cpool_patch(begp:endp) = spval call hist_addfld1d (fname='PSNSUN_TO_CPOOL', units='gC/m^2/s', & avgflag='A', long_name='C fixation from sunlit canopy', & @@ -2918,6 +2933,16 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='crop seed source to leaf', & ptr_patch=this%crop_seedc_to_leaf_patch, default='inactive') + this%crop_seedc_to_froot_patch(begp:endp) = spval + call hist_addfld1d (fname='CROP_SEEDC_TO_FROOT', units='gC/m^2/s', & + avgflag='A', long_name='crop seed source to fine root', & + ptr_patch=this%crop_seedc_to_froot_patch, default='inactive') + + this%crop_seedc_to_deadstem_patch(begp:endp) = spval + call hist_addfld1d (fname='CROP_SEEDC_TO_DEADSTEM', units='gC/m^2/s', & + avgflag='A', long_name='crop seed source to deadstem', & + ptr_patch=this%crop_seedc_to_deadstem_patch, default='inactive') + this%sr_col(begc:endc) = spval call hist_addfld1d (fname='SR', units='gC/m^2/s', & avgflag='A', long_name='total soil respiration (HR + root resp)', & @@ -3092,6 +3117,16 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C13 crop seed source to leaf', & ptr_patch=this%crop_seedc_to_leaf_patch, default='inactive') + this%crop_seedc_to_froot_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_CROP_SEEDC_TO_FROOT', units='gC13/m^2/s', & + avgflag='A', long_name='C13 crop seed source to fine root', & + ptr_patch=this%crop_seedc_to_froot_patch, default='inactive') + + this%crop_seedc_to_deadstem_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_CROP_SEEDC_TO_DEADSTEM', units='gC13/m^2/s', & + avgflag='A', long_name='C13 crop seed source to deadstem', & + ptr_patch=this%crop_seedc_to_deadstem_patch, default='inactive') + this%sr_col(begc:endc) = spval call hist_addfld1d (fname='C13_SR', units='gC13/m^2/s', & avgflag='A', long_name='C13 total soil respiration (HR + root resp)', & @@ -3248,6 +3283,17 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C14 crop seed source to leaf', & ptr_patch=this%crop_seedc_to_leaf_patch, default='inactive') + this%crop_seedc_to_froot_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_CROP_SEEDC_TO_FROOT', units='gC14/m^2/s', & + avgflag='A', long_name='C14 crop seed source to fine root', & + ptr_patch=this%crop_seedc_to_froot_patch, default='inactive') + + this%crop_seedc_to_deadstem_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_CROP_SEEDC_TO_DEADSTEM', units='gC14/m^2/s', & + avgflag='A', long_name='C14 crop seed source to deadstem', & + ptr_patch=this%crop_seedc_to_deadstem_patch, default='inactive') + + this%sr_col(begc:endc) = spval call hist_addfld1d (fname='C14_SR', units='gC14/m^2/s', & avgflag='A', long_name='C14 total soil respiration (HR + root resp)', & @@ -3521,6 +3567,16 @@ subroutine RestartBulkOnly ( this, bounds, ncid, flag ) long_name='grain C shift storage to transfer', units='gC/m2/s', & interpinic_flag='interp', readvar=readvar, data=this%grainc_storage_to_xfer_patch) + call restartvar(ncid=ncid, flag=flag, varname='prunec_to_litter', xtype=ncd_double, & + dim1name='pft', & + long_name='pruning C litterfall', units='gC/m2/s', & + interpinic_flag='interp', readvar=readvar, data=this%prunec_to_litter_patch) + + call restartvar(ncid=ncid, flag=flag, varname='prunec_storage_to_litter', xtype=ncd_double, & + dim1name='pft', & + long_name='pruning storage C litterfall', units='gC/m2/s', & + interpinic_flag='interp', readvar=readvar, data=this%prunec_storage_to_litter_patch) + end if call restartvar(ncid=ncid, flag=flag, varname='gpp_pepv', xtype=ncd_double, & @@ -3818,6 +3874,8 @@ subroutine SetValues ( this, & this%woodc_loss_patch(i) = value_patch this%crop_seedc_to_leaf_patch(i) = value_patch + this%crop_seedc_to_froot_patch(i) = value_patch + this%crop_seedc_to_deadstem_patch(i) = value_patch this%grainc_to_cropprodc_patch(i) = value_patch end do @@ -3835,6 +3893,8 @@ subroutine SetValues ( this, & this%cpool_grain_storage_gr_patch(i) = value_patch this%transfer_grain_gr_patch(i) = value_patch this%grainc_storage_to_xfer_patch(i) = value_patch + this%prunec_to_litter_patch(i) = value_patch + this%prunec_storage_to_litter_patch(i) = value_patch end do end if @@ -4273,8 +4333,9 @@ subroutine Summary_carbonflux(this, & if ( use_crop .and. patch%itype(p) >= npcropmin )then this%litfall_patch(p) = & this%litfall_patch(p) + & - this%livestemc_to_litter_patch(p) - + this%livestemc_to_litter_patch(p) + & + this%prunec_to_litter_patch(p) + & + this%prunec_storage_to_litter_patch(p) if (.not. use_grainproduct) then this%litfall_patch(p) = & this%litfall_patch(p) + & @@ -4508,8 +4569,7 @@ subroutine Summary_carbonflux(this, & ! total ecosystem respiration, autotrophic + heterotrophic (ER) this%er_col(c) = & this%ar_col(c) + & - soilbiogeochem_hr_col(c) - + soilbiogeochem_hr_col(c) ! coarse woody debris heterotrophic respiration this%cwdc_hr_col(c) = 0._r8 diff --git a/src/clm5/biogeochem/CNVegCarbonStateType.F90 b/src/clm5/biogeochem/CNVegCarbonStateType.F90 index 1d568dc60d..08a273b338 100644 --- a/src/clm5/biogeochem/CNVegCarbonStateType.F90 +++ b/src/clm5/biogeochem/CNVegCarbonStateType.F90 @@ -48,6 +48,8 @@ module CNVegCarbonStateType real(r8), pointer :: deadstemc_patch (:) ! (gC/m2) dead stem C real(r8), pointer :: deadstemc_storage_patch (:) ! (gC/m2) dead stem C storage real(r8), pointer :: deadstemc_xfer_patch (:) ! (gC/m2) dead stem C transfer + real(r8), pointer :: deadstemc_soy_patch (:) ! (gC/m2) dead stem C at the start of year + real(r8), pointer :: deadstemc_storage_soy_patch (:) ! (gC/m2) dead stem C storage at the start of year real(r8), pointer :: livecrootc_patch (:) ! (gC/m2) live coarse root C real(r8), pointer :: livecrootc_storage_patch (:) ! (gC/m2) live coarse root C storage real(r8), pointer :: livecrootc_xfer_patch (:) ! (gC/m2) live coarse root C transfer @@ -234,6 +236,8 @@ subroutine InitAllocate(this, bounds) allocate(this%deadstemc_patch (begp:endp)) ; this%deadstemc_patch (:) = nan allocate(this%deadstemc_storage_patch (begp:endp)) ; this%deadstemc_storage_patch (:) = nan allocate(this%deadstemc_xfer_patch (begp:endp)) ; this%deadstemc_xfer_patch (:) = nan + allocate(this%deadstemc_soy_patch (begp:endp)) ; this%deadstemc_soy_patch (:) = nan + allocate(this%deadstemc_storage_soy_patch (begp:endp)) ; this%deadstemc_storage_soy_patch (:) = nan allocate(this%livecrootc_patch (begp:endp)) ; this%livecrootc_patch (:) = nan allocate(this%livecrootc_storage_patch (begp:endp)) ; this%livecrootc_storage_patch (:) = nan allocate(this%livecrootc_xfer_patch (begp:endp)) ; this%livecrootc_xfer_patch (:) = nan @@ -400,6 +404,16 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='dead stem C transfer', & ptr_patch=this%deadstemc_xfer_patch, default='inactive') + this%deadstemc_soy_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADSTEMC_SOY', units='gC/m^2', & + avgflag='A', long_name='dead stem C at start of year', & + ptr_patch=this%deadstemc_soy_patch, default='inactive') + + this%deadstemc_storage_soy_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADSTEMC_STORAGE_SOY', units='gC/m^2', & + avgflag='A', long_name='dead stem C storage at start of year', & + ptr_patch=this%deadstemc_storage_soy_patch, default='inactive') + this%livecrootc_patch(begp:endp) = spval call hist_addfld1d (fname='LIVECROOTC', units='gC/m^2', & avgflag='A', long_name='live coarse root C', & @@ -941,7 +955,15 @@ subroutine InitCold(this, bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst this%leafc_patch(p) = 0._r8 this%leafc_storage_patch(p) = 0._r8 this%frootc_patch(p) = 0._r8 - this%frootc_storage_patch(p) = 0._r8 + this%frootc_storage_patch(p) = 0._r8 +! if (pftcon%perennial(patch%itype(p)) == 1._r8 .and. pftcon%woody(patch%itype(p)) == 1._r8) then +! this%leafc_patch(p) = 0._r8 +! this%leafc_storage_patch(p) = cnvegcstate_const%initial_vegC * ratio +! this%frootc_patch(p) = 0._r8 +! this%frootc_storage_patch(p) = cnvegcstate_const%initial_vegC * ratio +! this%deadstemc_soy_patch(p) = 0._r8 +! this%deadstemc_storage_soy_patch(p) = 0._r8 +! end if else this%leafc_patch(p) = 0._r8 this%leafc_storage_patch(p) = cnvegcstate_const%initial_vegC * ratio @@ -952,7 +974,6 @@ subroutine InitCold(this, bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst this%leafc_xfer_patch(p) = 0._r8 this%leafc_storage_xfer_acc_patch(p) = 0._r8 this%storage_cdemand_patch(p) = 0._r8 - if (MM_Nuptake_opt .eqv. .false.) then ! if not running in floating CN ratio option this%frootc_patch(p) = 0._r8 this%frootc_storage_patch(p) = 0._r8 @@ -964,7 +985,11 @@ subroutine InitCold(this, bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst this%livestemc_xfer_patch(p) = 0._r8 if (pftcon%woody(patch%itype(p)) == 1._r8) then - this%deadstemc_patch(p) = 0.1_r8 * ratio + if (patch%itype(p) < npcropmin)then ! (added by O.Dombrowski) + this%deadstemc_patch(p) = 0.1_r8 * ratio + else + this%deadstemc_patch(p) = 0._r8 ! (added by O.Dombrowski) + end if else this%deadstemc_patch(p) = 0._r8 end if @@ -1188,6 +1213,14 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%deadstemc_xfer_patch) + call restartvar(ncid=ncid, flag=flag, varname='deadstemc_soy', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemc_soy_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemc_storage_soy', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemc_storage_soy_patch) + call restartvar(ncid=ncid, flag=flag, varname='livecrootc', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%livecrootc_patch) @@ -1379,9 +1412,14 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, !----------------------------------------------- this%leafcmax_patch(i) = 0._r8 - + + if (lun%itype(l) == istcrop .and. pftcon%perennial(patch%itype(i)) == 1._r8) then + this%deadstemc_soy_patch(i) = 0._r8 + this%deadstemc_storage_soy_patch(i) = 0._r8 + end if l = patch%landunit(i) - if (lun%itype(l) == istsoil .or. patch%itype(i) == nc3crop .or. patch%itype(i) == nc3irrig)then + if (lun%itype(l) == istsoil .or. patch%itype(i) == nc3crop .or. patch%itype(i) == nc3irrig) then!.or. & +! (lun%itype(l) == istcrop .and. pftcon%perennial(patch%itype(i)) == 1._r8)) then ! (added by O.Dombrowski) if ( present(num_reseed_patch) ) then num_reseed_patch = num_reseed_patch + 1 filter_reseed_patch(num_reseed_patch) = i @@ -1420,9 +1458,11 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, this%livestemc_xfer_patch(i) = 0._r8 if (pftcon%woody(patch%itype(i)) == 1._r8) then - this%deadstemc_patch(i) = 0.1_r8 * ratio - else - this%deadstemc_patch(i) = 0._r8 + if (patch%itype(p) < npcropmin) then + this%deadstemc_patch(i) = 0.1_r8 * ratio + else + this%deadstemc_patch(i) = 0._r8 + end if end if this%deadstemc_storage_patch(i) = 0._r8 this%deadstemc_xfer_patch(i) = 0._r8 @@ -2367,6 +2407,8 @@ subroutine SetValues ( this, & this%deadstemc_patch(i) = value_patch this%deadstemc_storage_patch(i) = value_patch this%deadstemc_xfer_patch(i) = value_patch + this%deadstemc_soy_patch(i) = value_patch + this%deadstemc_storage_soy_patch(i) = value_patch this%livecrootc_patch(i) = value_patch this%livecrootc_storage_patch(i) = value_patch this%livecrootc_xfer_patch(i) = value_patch @@ -2480,7 +2522,6 @@ subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & this%deadstemc_patch(p) + & this%livecrootc_patch(p) + & this%deadcrootc_patch(p) - ! stored vegetation carbon, excluding cpool (STORVEGC) this%storvegc_patch(p) = & this%cpool_patch(p) + & @@ -2509,18 +2550,16 @@ subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & this%dispvegc_patch(p) + & this%grainc_patch(p) end if - + ! total vegetation carbon, excluding cpool (TOTVEGC) this%totvegc_patch(p) = & this%dispvegc_patch(p) + & this%storvegc_patch(p) - ! total patch-level carbon, including xsmrpool, ctrunc this%totc_patch(p) = & this%totvegc_patch(p) + & this%xsmrpool_patch(p) + & this%ctrunc_patch(p) - if (use_crop) then this%totc_patch(p) = this%totc_patch(p) + this%cropseedc_deficit_patch(p) + & this%xsmrpool_loss_patch(p) @@ -2563,7 +2602,6 @@ subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & soilbiogeochem_totlitc_col(c) + & soilbiogeochem_totsomc_col(c) + & soilbiogeochem_ctrunc_col(c) - end do end subroutine Summary_carbonstate diff --git a/src/clm5/biogeochem/CNVegComputeSeedMod.F90 b/src/clm5/biogeochem/CNVegComputeSeedMod.F90 index 01cf471e20..8ac2b175b2 100644 --- a/src/clm5/biogeochem/CNVegComputeSeedMod.F90 +++ b/src/clm5/biogeochem/CNVegComputeSeedMod.F90 @@ -9,7 +9,7 @@ module CNVegComputeSeedMod use shr_kind_mod , only : r8 => shr_kind_r8 use shr_log_mod , only : errMsg => shr_log_errMsg use decompMod , only : bounds_type - use pftconMod , only : pftcon, noveg + use pftconMod , only : pftcon, noveg, npcropmin use clm_varcon , only : c3_r2, c4_r2, c14ratio use clm_varctl , only : iulog use PatchType , only : patch @@ -133,7 +133,7 @@ subroutine ComputeSeedAmounts(bounds, & if (pft_type /= noveg) then my_leaf_seed = leafc_seed * & SpeciesTypeMultiplier(species, pft_type, COMPONENT_LEAF) - if (pftcon%woody(pft_type) == 1._r8) then + if (pftcon%woody(pft_type) == 1._r8 .and. patch%itype(p) < npcropmin) then my_deadstem_seed = deadstemc_seed * & SpeciesTypeMultiplier(species, pft_type, COMPONENT_DEADWOOD) end if diff --git a/src/clm5/biogeochem/CNVegNitrogenFluxType.F90 b/src/clm5/biogeochem/CNVegNitrogenFluxType.F90 index 47b620bf91..6277d80988 100644 --- a/src/clm5/biogeochem/CNVegNitrogenFluxType.F90 +++ b/src/clm5/biogeochem/CNVegNitrogenFluxType.F90 @@ -137,6 +137,10 @@ module CNVegNitrogenFluxType real(r8), pointer :: frootn_to_retransn_patch (:) ! patch fine root N to retranslocated N pool (gN/m2/s) real(r8), pointer :: frootn_to_litter_patch (:) ! patch fine root N litterfall (gN/m2/s) + ! pruning fluxes + real(r8), pointer :: prunen_to_litter_patch (:) ! patch pruning N to litter (gN/m2/s) + real(r8), pointer :: prunen_storage_to_litter_patch (:) ! patch pruning N to litter (gN/m2/s) + ! allocation fluxes real(r8), pointer :: retransn_to_npool_patch (:) ! patch deployment of retranslocated N (gN/m2/s) real(r8), pointer :: free_retransn_to_npool_patch (:) ! patch deployment of free retranslocated N (gN/m2/s) @@ -206,7 +210,9 @@ module CNVegNitrogenFluxType ! crop fluxes real(r8), pointer :: crop_seedn_to_leaf_patch (:) ! patch (gN/m2/s) seed source to leaf, for crops - + real(r8), pointer :: crop_seedn_to_froot_patch (:) ! patch (gN/m2/s) seed source to fine root, for perennial crops (added by O.Dombrowski) + real(r8), pointer :: crop_seedn_to_deadstem_patch (:) ! patch (gN/m2/s) seed source to deadstem, for perennial crops (added by O.Dombrowski) + ! Misc real(r8), pointer :: plant_ndemand_patch (:) ! N flux required to support initial GPP (gN/m2/s) real(r8), pointer :: avail_retransn_patch (:) ! N flux available from retranslocation pool (gN/m2/s) @@ -419,6 +425,8 @@ subroutine InitAllocate(this, bounds) allocate(this%fert_patch (begp:endp)) ; this%fert_patch (:) = nan allocate(this%fert_counter_patch (begp:endp)) ; this%fert_counter_patch (:) = nan allocate(this%soyfixn_patch (begp:endp)) ; this%soyfixn_patch (:) = nan + allocate(this%prunen_to_litter_patch (begp:endp)) ; this%prunen_to_litter_patch (:) = nan + allocate(this%prunen_storage_to_litter_patch (begp:endp)) ; this%prunen_storage_to_litter_patch (:) = nan allocate(this%grainn_to_cropprodn_patch (begp:endp)) ; this%grainn_to_cropprodn_patch (:) = nan allocate(this%grainn_to_cropprodn_col (begc:endc)) ; this%grainn_to_cropprodn_col (:) = nan @@ -447,7 +455,9 @@ subroutine InitAllocate(this, bounds) allocate(this%dwt_deadcrootn_to_cwdn_col (begc:endc,1:nlevdecomp_full)) ; this%dwt_deadcrootn_to_cwdn_col (:,:) = nan allocate(this%crop_seedn_to_leaf_patch (begp:endp)) ; this%crop_seedn_to_leaf_patch (:) = nan - + allocate(this%crop_seedn_to_froot_patch (begp:endp)) ; this%crop_seedn_to_froot_patch (:) = nan + allocate(this%crop_seedn_to_deadstem_patch (begp:endp)) ; this%crop_seedn_to_deadstem_patch (:) = nan + allocate(this%m_decomp_npools_to_fire_vr_col (begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) allocate(this%m_decomp_npools_to_fire_col (begc:endc,1:ndecomp_pools )) @@ -1063,6 +1073,16 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='crop seed source to leaf', & ptr_patch=this%crop_seedn_to_leaf_patch, default='inactive') + this%crop_seedn_to_froot_patch(begp:endp) = spval + call hist_addfld1d (fname='CROP_SEEDN_TO_FROOT', units='gN/m^2/s', & + avgflag='A', long_name='crop seed source to fine root', & + ptr_patch=this%crop_seedn_to_froot_patch, default='inactive') + + this%crop_seedn_to_deadstem_patch(begp:endp) = spval + call hist_addfld1d (fname='CROP_SEEDN_TO_DEADSTEM', units='gN/m^2/s', & + avgflag='A', long_name='crop seed source to deadstem', & + ptr_patch=this%crop_seedn_to_deadstem_patch, default='inactive') + this%plant_ndemand_patch(begp:endp) = spval call hist_addfld1d (fname='PLANT_NDEMAND', units='gN/m^2/s', & avgflag='A', long_name='N flux required to support initial GPP', & @@ -1392,6 +1412,18 @@ subroutine Restart (this, bounds, ncid, flag ) interpinic_flag='interp', readvar=readvar, data=this%grainn_storage_to_xfer_patch) end if + if (use_crop) then + call restartvar(ncid=ncid, flag=flag, varname='prunen_to_litter', xtype=ncd_double, & + dim1name='pft', & + long_name='pruning N to litterfall', units='gN/m2/s', & + interpinic_flag='interp', readvar=readvar, data=this%prunen_to_litter_patch) + + call restartvar(ncid=ncid, flag=flag, varname='prunen_storage_to_litter', xtype=ncd_double, & + dim1name='pft', & + long_name='pruning storage N to litterfall', units='gN/m2/s', & + interpinic_flag='interp', readvar=readvar, data=this%prunen_storage_to_litter_patch) + end if + call restartvar(ncid=ncid, flag=flag, varname='plant_ndemand', xtype=ncd_double, & dim1name='pft', & long_name='', units='', & @@ -1682,6 +1714,8 @@ subroutine SetValues ( this, & this%fire_nloss_patch(i) = value_patch this%crop_seedn_to_leaf_patch(i) = value_patch + this%crop_seedn_to_froot_patch(i) = value_patch + this%crop_seedn_to_deadstem_patch(i) = value_patch this%grainn_to_cropprodn_patch(i) = value_patch end do @@ -1697,6 +1731,9 @@ subroutine SetValues ( this, & this%grainn_storage_to_xfer_patch(i) = value_patch this%soyfixn_patch(i) = value_patch this%frootn_to_retransn_patch(i) = value_patch + this%prunen_to_litter_patch(i) = value_patch + this%prunen_storage_to_litter_patch(i) = value_patch + end do end if diff --git a/src/clm5/biogeochem/CNVegNitrogenStateType.F90 b/src/clm5/biogeochem/CNVegNitrogenStateType.F90 index 97a5ffaae4..6d2b4d3c90 100644 --- a/src/clm5/biogeochem/CNVegNitrogenStateType.F90 +++ b/src/clm5/biogeochem/CNVegNitrogenStateType.F90 @@ -51,6 +51,8 @@ module CNVegNitrogenStateType real(r8), pointer :: deadstemn_patch (:) ! (gN/m2) dead stem N real(r8), pointer :: deadstemn_storage_patch (:) ! (gN/m2) dead stem N storage real(r8), pointer :: deadstemn_xfer_patch (:) ! (gN/m2) dead stem N transfer + real(r8), pointer :: deadstemn_soy_patch (:) ! (gN/m2) dead stem N at the start of season + real(r8), pointer :: deadstemn_storage_soy_patch (:) ! (gN/m2) dead stem N at the start of season real(r8), pointer :: livecrootn_patch (:) ! (gN/m2) live coarse root N real(r8), pointer :: livecrootn_storage_patch (:) ! (gN/m2) live coarse root N storage real(r8), pointer :: livecrootn_xfer_patch (:) ! (gN/m2) live coarse root N transfer @@ -147,6 +149,8 @@ subroutine InitAllocate(this, bounds) allocate(this%deadstemn_patch (begp:endp)) ; this%deadstemn_patch (:) = nan allocate(this%deadstemn_storage_patch (begp:endp)) ; this%deadstemn_storage_patch (:) = nan allocate(this%deadstemn_xfer_patch (begp:endp)) ; this%deadstemn_xfer_patch (:) = nan + allocate(this%deadstemn_soy_patch (begp:endp)) ; this%deadstemn_soy_patch (:) = nan + allocate(this%deadstemn_storage_soy_patch (begp:endp)) ; this%deadstemn_storage_soy_patch (:) = nan allocate(this%livecrootn_patch (begp:endp)) ; this%livecrootn_patch (:) = nan allocate(this%livecrootn_storage_patch (begp:endp)) ; this%livecrootn_storage_patch (:) = nan allocate(this%livecrootn_xfer_patch (begp:endp)) ; this%livecrootn_xfer_patch (:) = nan @@ -283,6 +287,16 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='dead stem N transfer', & ptr_patch=this%deadstemn_xfer_patch, default='inactive') + this%deadstemn_soy_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADSTEMN_SOY', units='gN/m^2', & + avgflag='A', long_name='dead stem N at start of year', & + ptr_patch=this%deadstemn_soy_patch, default='inactive') + + this%deadstemn_storage_soy_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADSTEMN_STORAGE_SOY', units='gN/m^2', & + avgflag='A', long_name='dead stem N storage at start of year', & + ptr_patch=this%deadstemn_storage_soy_patch, default='inactive') + this%livecrootn_patch(begp:endp) = spval call hist_addfld1d (fname='LIVECROOTN', units='gN/m^2', & avgflag='A', long_name='live coarse root N', & @@ -471,13 +485,19 @@ subroutine InitCold(this, bounds, & ! roughness length is not zero in canopy flux calculation if (pftcon%woody(patch%itype(p)) == 1._r8) then - this%deadstemn_patch(p) = deadstemc_patch(p) / pftcon%deadwdcn(patch%itype(p)) + if (patch%itype(p) < npcropmin) then + this%deadstemn_patch(p) = deadstemc_patch(p) / pftcon%deadwdcn(patch%itype(p)) + else + this%deadstemn_patch(p) = 0._r8 + end if else this%deadstemn_patch(p) = 0._r8 end if this%deadstemn_storage_patch(p) = 0._r8 this%deadstemn_xfer_patch(p) = 0._r8 + this%deadstemn_soy_patch(p) = 0._r8 + this%deadstemn_storage_soy_patch(p) = 0._r8 this%livecrootn_patch(p) = 0._r8 this%livecrootn_storage_patch(p) = 0._r8 this%livecrootn_xfer_patch(p) = 0._r8 @@ -630,6 +650,14 @@ subroutine Restart ( this, bounds, ncid, flag, leafc_patch, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%deadstemn_xfer_patch) + call restartvar(ncid=ncid, flag=flag, varname='deadstemn_soy', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemn_soy_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemn_storage_soy', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemn_storage_soy_patch) + call restartvar(ncid=ncid, flag=flag, varname='livecrootn', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%livecrootn_patch) @@ -781,13 +809,19 @@ subroutine Restart ( this, bounds, ncid, flag, leafc_patch, & ! roughness length is not zero in canopy flux calculation if (pftcon%woody(patch%itype(p)) == 1._r8) then - this%deadstemn_patch(p) = deadstemc_patch(p) / pftcon%deadwdcn(patch%itype(p)) + if (patch%itype(p) < npcropmin) then + this%deadstemn_patch(p) = deadstemc_patch(p) / pftcon%deadwdcn(patch%itype(p)) + else + this%deadstemn_patch(p) = 0._r8 + end if else this%deadstemn_patch(p) = 0._r8 end if this%deadstemn_storage_patch(p) = 0._r8 this%deadstemn_xfer_patch(p) = 0._r8 + this%deadstemn_soy_patch(p) = 0._r8 + this%deadstemn_storage_soy_patch(p) = 0._r8 this%livecrootn_patch(p) = 0._r8 this%livecrootn_storage_patch(p) = 0._r8 this%livecrootn_xfer_patch(p) = 0._r8 @@ -876,6 +910,8 @@ subroutine SetValues ( this, & this%deadstemn_patch(i) = value_patch this%deadstemn_storage_patch(i) = value_patch this%deadstemn_xfer_patch(i) = value_patch + this%deadstemn_soy_patch(i) = value_patch + this%deadstemn_storage_soy_patch(i) = value_patch this%livecrootn_patch(i) = value_patch this%livecrootn_storage_patch(i) = value_patch this%livecrootn_xfer_patch(i) = value_patch diff --git a/src/clm5/biogeochem/CNVegStateType.F90 b/src/clm5/biogeochem/CNVegStateType.F90 index afdfa190aa..2c4f9b5576 100644 --- a/src/clm5/biogeochem/CNVegStateType.F90 +++ b/src/clm5/biogeochem/CNVegStateType.F90 @@ -35,9 +35,15 @@ module CNVegStateType real(r8) , pointer :: cumvd_patch (:) ! patch cumulative vernalization d?ependence? real(r8) , pointer :: gddmaturity_patch (:) ! patch growing degree days (gdd) needed to harvest (ddays) real(r8) , pointer :: huileaf_patch (:) ! patch heat unit index needed from planting to leaf emergence - real(r8) , pointer :: huigrain_patch (:) ! patch heat unit index needed to reach vegetative maturity + real(r8) , pointer :: huigrain_patch (:) ! patch heat unit index needed to reach vegetative maturity/to start fruit fill for perennial crops + real(r8) , pointer :: huilfmat_patch (:) ! patch heat unit index needed to reach canopy maturity (added by O.Dombrowski) + real(r8) , pointer :: huiripe_patch (:) ! patch heat unit index needed to reach fruit cell expansion (ripening) (added by O.Dombrowski) real(r8) , pointer :: aleafi_patch (:) ! patch saved leaf allocation coefficient from phase 2 real(r8) , pointer :: astemi_patch (:) ! patch saved stem allocation coefficient from phase 2 + real(r8) , pointer :: arooti2_patch (:) ! patch saved root allocation coefficient from phase 2 + real(r8) , pointer :: arooti3_patch (:) ! patch saved root allocation coefficient from phase 3 + real(r8) , pointer :: aleafi3_patch (:) ! patch saved leaf allocation coefficient from phase 3 + real(r8) , pointer :: aleaf_patch (:) ! patch leaf allocation coefficient real(r8) , pointer :: astem_patch (:) ! patch stem allocation coefficient real(r8) , pointer :: htmx_patch (:) ! patch max hgt attained by a crop during yr (m) @@ -85,6 +91,7 @@ module CNVegStateType real(r8), pointer :: onset_gdd_patch (:) ! patch onset growing degree days real(r8), pointer :: onset_swi_patch (:) ! patch onset soil water index real(r8), pointer :: offset_flag_patch (:) ! patch offset flag + real(r8), pointer :: offset2_flag_patch (:) ! patch orchard rotation flag real(r8), pointer :: offset_counter_patch (:) ! patch offset days counter real(r8), pointer :: offset_fdd_patch (:) ! patch offset freezing degree days counter real(r8), pointer :: offset_swi_patch (:) ! patch offset soil water index @@ -95,6 +102,13 @@ module CNVegStateType real(r8), pointer :: c_allometry_patch (:) ! patch C allocation index (DIM) real(r8), pointer :: n_allometry_patch (:) ! patch N allocation index (DIM) + real(r8), pointer :: chill_day_patch (:) ! patch chill days requirements for fruit tree crops + real(r8), pointer :: anti_chill_day_patch (:) ! patch anti-chill days requirements for fruit tree crops + real(r8), pointer :: chill_flag_patch (:) ! patch chill requirements flag for fruit tree crops + + real(r8), pointer :: harvest_flag_patch (:) ! patch harvest flag (added by O.Dombrowski) + real(r8), pointer :: prune_flag_patch (:) ! patch pruning flag (added by O.Dombrowski) + real(r8), pointer :: storage_flag_patch (:) ! patch storage growth flag (added by O.Dombrowski) real(r8), pointer :: tempsum_potential_gpp_patch (:) ! patch temporary annual sum of potential GPP real(r8), pointer :: annsum_potential_gpp_patch (:) ! patch annual sum of potential GPP real(r8), pointer :: tempmax_retransn_patch (:) ! patch temporary annual max of retranslocated N pool (gN/m2) @@ -201,7 +215,12 @@ subroutine InitAllocate(this, bounds) allocate(this%gddmaturity_patch (begp:endp)) ; this%gddmaturity_patch (:) = spval allocate(this%huileaf_patch (begp:endp)) ; this%huileaf_patch (:) = nan allocate(this%huigrain_patch (begp:endp)) ; this%huigrain_patch (:) = 0.0_r8 + allocate(this%huilfmat_patch (begp:endp)) ; this%huilfmat_patch (:) = 0.0_r8 + allocate(this%huiripe_patch (begp:endp)) ; this%huiripe_patch (:) = 0.0_r8 allocate(this%aleafi_patch (begp:endp)) ; this%aleafi_patch (:) = nan + allocate(this%arooti2_patch (begp:endp)) ; this%arooti2_patch (:) = nan + allocate(this%arooti3_patch (begp:endp)) ; this%arooti3_patch (:) = nan + allocate(this%aleafi3_patch (begp:endp)) ; this%aleafi3_patch (:) = nan allocate(this%astemi_patch (begp:endp)) ; this%astemi_patch (:) = nan allocate(this%aleaf_patch (begp:endp)) ; this%aleaf_patch (:) = nan allocate(this%astem_patch (begp:endp)) ; this%astem_patch (:) = nan @@ -249,6 +268,7 @@ subroutine InitAllocate(this, bounds) allocate(this%onset_gdd_patch (begp:endp)) ; this%onset_gdd_patch (:) = nan allocate(this%onset_swi_patch (begp:endp)) ; this%onset_swi_patch (:) = nan allocate(this%offset_flag_patch (begp:endp)) ; this%offset_flag_patch (:) = nan + allocate(this%offset2_flag_patch (begp:endp)) ; this%offset2_flag_patch (:) = nan allocate(this%offset_counter_patch (begp:endp)) ; this%offset_counter_patch (:) = nan allocate(this%offset_fdd_patch (begp:endp)) ; this%offset_fdd_patch (:) = nan allocate(this%offset_swi_patch (begp:endp)) ; this%offset_swi_patch (:) = nan @@ -258,6 +278,14 @@ subroutine InitAllocate(this, bounds) allocate(this%bgtr_patch (begp:endp)) ; this%bgtr_patch (:) = nan allocate(this%c_allometry_patch (begp:endp)) ; this%c_allometry_patch (:) = nan allocate(this%n_allometry_patch (begp:endp)) ; this%n_allometry_patch (:) = nan + allocate(this%chill_day_patch (begp:endp)) ; this%chill_day_patch (:) = nan + allocate(this%anti_chill_day_patch (begp:endp)) ; this%anti_chill_day_patch (:) = nan + allocate(this%chill_flag_patch (begp:endp)) ; this%chill_flag_patch (:) = nan + + + allocate(this%harvest_flag_patch (begp:endp)) ; this%harvest_flag_patch (:) = nan + allocate(this%prune_flag_patch (begp:endp)) ; this%prune_flag_patch (:) = nan + allocate(this%storage_flag_patch (begp:endp)) ; this%storage_flag_patch (:) = nan allocate(this%tempsum_potential_gpp_patch (begp:endp)) ; this%tempsum_potential_gpp_patch (:) = nan allocate(this%annsum_potential_gpp_patch (begp:endp)) ; this%annsum_potential_gpp_patch (:) = nan allocate(this%tempmax_retransn_patch (begp:endp)) ; this%tempmax_retransn_patch (:) = nan @@ -321,17 +349,17 @@ subroutine InitHistory(this, bounds) ptr_col=this%nfire_col) this%farea_burned_col(begc:endc) = spval - call hist_addfld1d (fname='FAREA_BURNED', units='s-1', & + call hist_addfld1d (fname='FAREA_BURNED', units='proportion/sec', & avgflag='A', long_name='timestep fractional area burned', & ptr_col=this%farea_burned_col) this%baf_crop_col(begc:endc) = spval - call hist_addfld1d (fname='BAF_CROP', units='s-1', & + call hist_addfld1d (fname='BAF_CROP', units='proportion/sec', & avgflag='A', long_name='fractional area burned for crop', & ptr_col=this%baf_crop_col) this%baf_peatf_col(begc:endc) = spval - call hist_addfld1d (fname='BAF_PEATF', units='s-1', & + call hist_addfld1d (fname='BAF_PEATF', units='proportion/sec', & avgflag='A', long_name='fractional area burned in peatland', & ptr_col=this%baf_peatf_col) @@ -390,6 +418,11 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='offset flag', & ptr_patch=this%offset_flag_patch, default='inactive') + this%offset2_flag_patch(begp:endp) = spval + call hist_addfld1d (fname='OFFSET2_FLAG', units='none', & + avgflag='A', long_name='orchard rotation flag', & + ptr_patch=this%offset2_flag_patch, default='inactive') + this%offset_counter_patch(begp:endp) = spval call hist_addfld1d (fname='OFFSET_COUNTER', units='days', & avgflag='A', long_name='offset days counter', & @@ -430,6 +463,31 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='N allocation index', & ptr_patch=this%n_allometry_patch, default='inactive') + this%chill_day_patch(begp:endp) = spval + call hist_addfld1d (fname='CHILL_DAY', units='days', & + avgflag='A', long_name='Chill days needed for bud break of fruit tree crops', & + ptr_patch=this%chill_day_patch, default='inactive') + + this%anti_chill_day_patch(begp:endp) = spval + call hist_addfld1d (fname='ANTI_CHILL_DAY', units='days', & + avgflag='A', long_name='Anti-chill days needed for bud break of fruit tree crops', & + ptr_patch=this%anti_chill_day_patch, default='inactive') + + this%chill_flag_patch(begp:endp) = spval + call hist_addfld1d (fname='CHILL_FLAG', units='none', & + avgflag='A', long_name='Chill requirements flag for bud break of fruit tree crops', & + ptr_patch=this%chill_flag_patch, default='inactive') + + this%harvest_flag_patch(begp:endp) = spval + call hist_addfld1d (fname='HARVEST_FLAG', units='none', & + avgflag='A', long_name='harvest flag (perennial crops)', & + ptr_patch=this%harvest_flag_patch, default='inactive') + + this%storage_flag_patch(begp:endp) = spval + call hist_addfld1d (fname='STORAGE_FLAG', units='none', & + avgflag='A', long_name='storage growth flag (perennial crops)', & + ptr_patch=this%storage_flag_patch, default='inactive') + this%tempsum_potential_gpp_patch(begp:endp) = spval call hist_addfld1d (fname='TEMPSUM_POTENTIAL_GPP', units='gC/m^2/yr', & avgflag='A', long_name='temporary annual sum of potential GPP', & @@ -464,6 +522,28 @@ subroutine InitHistory(this, bounds) call hist_addfld1d (fname='PLANTCN', units='unitless', & avgflag='A', long_name='Plant C:N used by FUN', & ptr_patch=this%plantCN_patch, default='inactive') + + this%aleaf_patch(begp:endp) = spval + call hist_addfld1d (fname='A_LEAF', units='unitless', & + avgflag='A', long_name='Leaf allocation coefficient', & + ptr_patch=this%aleaf_patch, default='inactive') + +! this%arepr_patch(begp:endp) = spval +! call hist_addfld1d (fname='A_REPR', units='unitless', & +! avgflag='A', long_name='Fruit allocation coefficient', & +! ptr_patch=this%arepr_patch, default='inactive') + + this%astem_patch(begp:endp) = spval + call hist_addfld1d (fname='A_STEM', units='unitless', & + avgflag='A', long_name='Stem allocation coefficient', & + ptr_patch=this%astem_patch, default='inactive') + +! this%aroot_patch(begp:endp) = spval +! call hist_addfld1d (fname='A_ROOT', units='unitless', & +! avgflag='A', long_name='Root allocation coefficient', & +! ptr_patch=this%aroot_patch, default='inactive') + + end subroutine InitHistory !----------------------------------------------------------------------- @@ -607,6 +687,7 @@ subroutine initCold(this, bounds) this%onset_gdd_patch(p) = spval this%onset_swi_patch(p) = spval this%offset_flag_patch(p) = spval + this%offset2_flag_patch(p) = spval this%offset_counter_patch(p) = spval this%offset_fdd_patch(p) = spval this%offset_swi_patch(p) = spval @@ -616,6 +697,12 @@ subroutine initCold(this, bounds) this%bgtr_patch(p) = spval this%c_allometry_patch(p) = spval this%n_allometry_patch(p) = spval + this%chill_day_patch(p) = spval + this%anti_chill_day_patch(p) = spval + this%chill_flag_patch(p) = spval + this%harvest_flag_patch(p) = spval + this%prune_flag_patch(p) = spval + this%storage_flag_patch(p) = spval this%tempsum_potential_gpp_patch(p) = spval this%annsum_potential_gpp_patch(p) = spval this%tempmax_retransn_patch(p) = spval @@ -636,12 +723,19 @@ subroutine initCold(this, bounds) this%onset_gdd_patch(p) = 0._r8 this%onset_swi_patch(p) = 0._r8 this%offset_flag_patch(p) = 0._r8 + this%offset2_flag_patch(p) = 0._r8 this%offset_counter_patch(p) = 0._r8 this%offset_fdd_patch(p) = 0._r8 this%offset_swi_patch(p) = 0._r8 this%lgsf_patch(p) = 0._r8 this%bglfr_patch(p) = 0._r8 this%bgtr_patch(p) = 0._r8 + this%chill_day_patch(p) = 0._r8 + this%anti_chill_day_patch(p) = 0._r8 + this%chill_flag_patch(p) = 0._r8 + this%harvest_flag_patch(p) = 0._r8 + this%prune_flag_patch(p) = 0._r8 + this%storage_flag_patch(p) = 0._r8 this%annavg_t2m_patch(p) = 280._r8 this%tempavg_t2m_patch(p) = 0._r8 this%grain_flag_patch(p) = 0._r8 @@ -746,6 +840,11 @@ subroutine Restart(this, bounds, ncid, flag, cnveg_carbonstate, & long_name='offset flag', units='unitless' , & interpinic_flag='interp', readvar=readvar, data=this%offset_flag_patch) + call restartvar(ncid=ncid, flag=flag, varname='offset2_flag', xtype=ncd_double, & + dim1name='pft', & + long_name='orchard rotation flag', units='unitless' , & + interpinic_flag='interp', readvar=readvar, data=this%offset2_flag_patch) + call restartvar(ncid=ncid, flag=flag, varname='offset_counter', xtype=ncd_double, & dim1name='pft', & long_name='offset days counter', units='sec' , & @@ -875,6 +974,18 @@ subroutine Restart(this, bounds, ncid, flag, cnveg_carbonstate, & dim1name='pft', long_name='Saved leaf allocation coefficient from phase 2', units='', & interpinic_flag='interp', readvar=readvar, data=this%aleafi_patch) + call restartvar(ncid=ncid, flag=flag, varname='arooti2', xtype=ncd_double, & + dim1name='pft', long_name='Saved root allocation coefficient from phase 2', units='', & + interpinic_flag='interp', readvar=readvar, data=this%arooti2_patch) + + call restartvar(ncid=ncid, flag=flag, varname='arooti3', xtype=ncd_double, & + dim1name='pft', long_name='Saved root allocation coefficient from phase 3', units='', & + interpinic_flag='interp', readvar=readvar, data=this%arooti3_patch) + + call restartvar(ncid=ncid, flag=flag, varname='aleafi3', xtype=ncd_double, & + dim1name='pft', long_name='Saved leaf allocation coefficient from phase 3', units='', & + interpinic_flag='interp', readvar=readvar, data=this%aleafi3_patch) + call restartvar(ncid=ncid, flag=flag, varname='astem', xtype=ncd_double, & dim1name='pft', long_name='stem allocation coefficient', units='', & interpinic_flag='interp', readvar=readvar, data=this%astem_patch) @@ -903,9 +1014,44 @@ subroutine Restart(this, bounds, ncid, flag, cnveg_carbonstate, & dim1name='pft', long_name='heat unit index needed to reach vegetative maturity', units='', & interpinic_flag='interp', readvar=readvar, data=this%huigrain_patch) + call restartvar(ncid=ncid, flag=flag, varname='huilfmat', xtype=ncd_double, & + dim1name='pft', long_name='heat unit index needed to reach canopy maturity', units='', & + interpinic_flag='interp', readvar=readvar, data=this%huilfmat_patch) + + call restartvar(ncid=ncid, flag=flag, varname='huiripe', xtype=ncd_double, & + dim1name='pft', long_name='heat unit index needed to reach fruit cell expansion', units='', & + interpinic_flag='interp', readvar=readvar, data=this%huiripe_patch) + call restartvar(ncid=ncid, flag=flag, varname='grain_flag', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%grain_flag_patch) + + call restartvar(ncid=ncid, flag=flag, varname='chill_day', xtype=ncd_double, & + dim1name='pft', long_name='', units='days', & + interpinic_flag='interp', readvar=readvar, data=this%chill_day_patch) + + call restartvar(ncid=ncid, flag=flag, varname='anti_chill_day', xtype=ncd_double, & + dim1name='pft', long_name='', units='days', & + interpinic_flag='interp', readvar=readvar, data=this%anti_chill_day_patch) + + call restartvar(ncid=ncid, flag=flag, varname='chill_flag', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%chill_flag_patch) + + call restartvar(ncid=ncid, flag=flag, varname='harvest_flag', xtype=ncd_double, & + dim1name='pft', long_name='harvest flag (perennial crops)', units='unitless', & + interpinic_flag='interp', readvar=readvar, data=this%harvest_flag_patch) + + call restartvar(ncid=ncid, flag=flag, varname='prune_flag', xtype=ncd_double, & + dim1name='pft', long_name='pruning flag for perenneial crops', units='unitless', & + interpinic_flag='interp', readvar=readvar, data=this%prune_flag_patch) + + call restartvar(ncid=ncid, flag=flag, varname='storage_flag', xtype=ncd_double, & + dim1name='pft', long_name='storage growth flag for perenneial crops', units='unitless', & + interpinic_flag='interp', readvar=readvar, data=this%storage_flag_patch) + + + end if if ( flag == 'read' .and. num_reseed_patch > 0 )then if ( masterproc ) write(iulog, *) 'Reseed dead plants for CNVegState' @@ -921,6 +1067,7 @@ subroutine Restart(this, bounds, ncid, flag, cnveg_carbonstate, & this%onset_gdd_patch(p) = 0._r8 this%onset_swi_patch(p) = 0._r8 this%offset_flag_patch(p) = 0._r8 + this%offset2_flag_patch(p) = 0._r8 this%offset_counter_patch(p) = 0._r8 this%offset_fdd_patch(p) = 0._r8 this%offset_swi_patch(p) = 0._r8 @@ -930,7 +1077,12 @@ subroutine Restart(this, bounds, ncid, flag, cnveg_carbonstate, & this%annavg_t2m_patch(p) = 280._r8 this%tempavg_t2m_patch(p) = 0._r8 this%grain_flag_patch(p) = 0._r8 - + this%harvest_flag_patch(p) = 0._r8 + this%prune_flag_patch(p) = 0._r8 + this%storage_flag_patch(p) = 0._r8 + this%chill_day_patch(p) = 0._r8 + this%anti_chill_day_patch(p) = 0._r8 + this%chill_flag_patch(p) = 0._r8 this%c_allometry_patch(p) = 0._r8 this%n_allometry_patch(p) = 0._r8 this%tempsum_potential_gpp_patch(p) = 0._r8 diff --git a/src/clm5/biogeochem/CNVegStructUpdateMod.F90 b/src/clm5/biogeochem/CNVegStructUpdateMod.F90 index 27b677b04d..fd6c2acfec 100644 --- a/src/clm5/biogeochem/CNVegStructUpdateMod.F90 +++ b/src/clm5/biogeochem/CNVegStructUpdateMod.F90 @@ -63,7 +63,6 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & ! !LOCAL VARIABLES: integer :: p,c,g ! indices integer :: fp ! lake filter indices - real(r8) :: taper ! ratio of height:radius_breast_height (tree allometry) real(r8) :: stocking ! #stems / ha (stocking density) real(r8) :: ol ! thickness of canopy layer covered by snow (m) real(r8) :: fb ! fraction of canopy layer covered by snow @@ -90,6 +89,7 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types slatop => pftcon%slatop , & ! Input: specific leaf area at top of canopy, projected area basis [m^2/gC] dsladlai => pftcon%dsladlai , & ! Input: dSLA/dLAI, projected area basis [m^2/gC] z0mr => pftcon%z0mr , & ! Input: ratio of momentum roughness length to canopy top height (-) @@ -97,7 +97,9 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & dwood => pftcon%dwood , & ! Input: density of wood (gC/m^3) ztopmx => pftcon%ztopmx , & ! Input: laimx => pftcon%laimx , & ! Input: - + nstem => pftcon%nstem , & ! Input: Tree number density (#ind/m2) (introduced by E.Kluzek (2020, unreleased code) and adopted here by O.Dombrowski) + taper => pftcon%taper , & ! Input: ratio of height:radius_breast_height (tree allometry) (introduced by E.Kluzek (2020, unreleased code) and adopted here by O.Dombrowski) + allom2 => dgv_ecophyscon%allom2 , & ! Input: [real(r8) (:) ] ecophys const allom3 => dgv_ecophyscon%allom3 , & ! Input: [real(r8) (:) ] ecophys const @@ -114,7 +116,7 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & farea_burned => cnveg_state_inst%farea_burned_col , & ! Input: [real(r8) (:) ] F. Li and S. Levis htmx => cnveg_state_inst%htmx_patch , & ! Output: [real(r8) (:) ] max hgt attained by a crop during yr (m) peaklai => cnveg_state_inst%peaklai_patch , & ! Output: [integer (:) ] 1: max allowed lai; 0: not at max - + dormant_flag => cnveg_state_inst%dormant_flag_patch , & ! Output: [real(r8) (:) ] dormancy flag harvdate => crop_inst%harvdate_patch , & ! Input: [integer (:) ] harvest date ! *** Key Output from CN*** @@ -129,13 +131,6 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & dt = real( get_rad_step_size(), r8 ) - ! constant allometric parameters - taper = 200._r8 - stocking = 1000._r8 - - ! convert from stems/ha -> stems/m^2 - stocking = stocking / 10000._r8 - ! patch loop do fp = 1,num_soilp p = filter_soilp(fp) @@ -177,25 +172,23 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & if (woody(ivt(p)) == 1._r8) then - ! trees and shrubs - - ! if shrubs have a squat taper - if (ivt(p) >= nbrdlf_evr_shrub .and. ivt(p) <= nbrdlf_dcd_brl_shrub) then - taper = 10._r8 - ! otherwise have a tall taper - else - taper = 200._r8 + if (perennial(ivt(p)) == 1._r8) then + if (dormant_flag(p) == 0._r8) then + if (tlai(p) >= laimx(ivt(p))) peaklai(p) = 1 + else if (dormant_flag(p) == 1._r8) then + peaklai(p) = 0 + end if end if - ! trees and shrubs for now have a very simple allometry, with hard-wired - ! stem taper (height:radius) and hard-wired stocking density (#individuals/area) + ! trees and shrubs for now have a very simple allometry, with + ! stem taper (height:radius) and nstem from PFT parameter file if (use_cndv) then if (fpcgrid(p) > 0._r8 .and. nind(p) > 0._r8) then stocking = nind(p)/fpcgrid(p) !#ind/m2 nat veg area -> #ind/m2 patch area htop(p) = allom2(ivt(p)) * ( (24._r8 * deadstemc(p) / & - (SHR_CONST_PI * stocking * dwood(ivt(p)) * taper))**(1._r8/3._r8) )**allom3(ivt(p)) ! lpj's htop w/ cn's stemdiam + (SHR_CONST_PI * stocking * dwood(ivt(p)) * taper(ivt(p))))**(1._r8/3._r8) )**allom3(ivt(p)) ! lpj's htop w/ cn's stemdiam else htop(p) = 0._r8 @@ -203,12 +196,20 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & else !correct height calculation if doing accelerated spinup - if (spinup_state == 2) then - htop(p) = ((3._r8 * deadstemc(p) * 10._r8 * taper * taper)/ & - (SHR_CONST_PI * stocking * dwood(ivt(p))))**(1._r8/3._r8) + if (spinup_state == 2) then + if (perennial(ivt(p)) == 1._r8 .and. dormant_flag(p) == 1._r8 .and. deadstemc(p)== 0._r8) then + htop(p) = 0.01_r8 + else + htop(p) = ((3._r8 * deadstemc(p) * 10._r8 * taper(ivt(p)) * taper(ivt(p)))/ & + (SHR_CONST_PI * nstem(ivt(p)) * dwood(ivt(p))))**(1._r8/3._r8) + end if else - htop(p) = ((3._r8 * deadstemc(p) * taper * taper)/ & - (SHR_CONST_PI * stocking * dwood(ivt(p))))**(1._r8/3._r8) + if (perennial(ivt(p)) == 1._r8 .and. dormant_flag(p) == 1._r8 .and. deadstemc(p)== 0._r8) then + htop(p) = 0.01_r8 + else + htop(p) = ((3._r8 * deadstemc(p) * taper(ivt(p)) * taper(ivt(p)))/ & + (SHR_CONST_PI * nstem(ivt(p)) * dwood(ivt(p))))**(1._r8/3._r8) + end if end if endif @@ -217,12 +218,15 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & ! Adding test to keep htop from getting too close to forcing height for windspeed ! Also added for grass, below, although it is not likely to ever be an issue. htop(p) = min(htop(p),(forc_hgt_u_patch(p)/(displar(ivt(p))+z0mr(ivt(p))))-3._r8) - ! Peter Thornton, 8/11/2004 ! Adding constraint to keep htop from going to 0.0. ! This becomes an issue when fire mortality is pushing deadstemc ! to 0.0. htop(p) = max(htop(p), 0.01_r8) + ! for fruit trees restrict height to maximum pruned tree height + if (perennial(ivt(p)) == 1._r8) then + htop(p) = min(htop(p), ztopmx(ivt(p))) + end if hbot(p) = max(0._r8, min(3._r8, htop(p)-1._r8)) diff --git a/src/clm5/biogeochem/CropType.F90 b/src/clm5/biogeochem/CropType.F90 index 0b2c0fc1db..da109ddff7 100644 --- a/src/clm5/biogeochem/CropType.F90 +++ b/src/clm5/biogeochem/CropType.F90 @@ -32,6 +32,7 @@ module CropType logical , pointer :: croplive_patch (:) ! patch Flag, true if planted, not harvested logical , pointer :: cropplant_patch (:) ! patch Flag, true if planted integer , pointer :: harvdate_patch (:) ! patch harvest date + integer , pointer :: yrop_patch (:) ! patch year of planting of crop (added by O.Dombrowski) real(r8), pointer :: fertnitro_patch (:) ! patch fertilizer nitrogen real(r8), pointer :: gddplant_patch (:) ! patch accum gdd past planting date for crop (ddays) real(r8), pointer :: gddtsoi_patch (:) ! patch growing degree-days from planting (top two soil layers) (ddays) @@ -192,7 +193,8 @@ subroutine InitAllocate(this, bounds) allocate(this%nyrs_crop_active_patch(begp:endp)) ; this%nyrs_crop_active_patch(:) = 0 allocate(this%croplive_patch (begp:endp)) ; this%croplive_patch (:) = .false. allocate(this%cropplant_patch(begp:endp)) ; this%cropplant_patch(:) = .false. - allocate(this%harvdate_patch (begp:endp)) ; this%harvdate_patch (:) = huge(1) + allocate(this%harvdate_patch (begp:endp)) ; this%harvdate_patch (:) = huge(1) + allocate(this%yrop_patch (begp:endp)) ; this%yrop_patch (:) = huge(1) allocate(this%fertnitro_patch (begp:endp)) ; this%fertnitro_patch (:) = spval allocate(this%gddplant_patch (begp:endp)) ; this%gddplant_patch (:) = spval allocate(this%gddtsoi_patch (begp:endp)) ; this%gddtsoi_patch (:) = spval @@ -497,6 +499,10 @@ subroutine Restart(this, bounds, ncid, flag) dim1name='pft', long_name='harvest date', units='jday', nvalid_range=(/1,366/), & interpinic_flag='interp', readvar=readvar, data=this%harvdate_patch) + call restartvar(ncid=ncid, flag=flag, varname='yrop', xtype=ncd_int, & + dim1name='pft', long_name='year of planting', units='years', nvalid_range=(/1,9999/), & + interpinic_flag='interp', readvar=readvar, data=this%yrop_patch) + call restartvar(ncid=ncid, flag=flag, varname='vf', xtype=ncd_double, & dim1name='pft', long_name='vernalization factor', units='', & interpinic_flag='interp', readvar=readvar, data=this%vf_patch) @@ -527,7 +533,7 @@ subroutine CropUpdateAccVars(this, bounds, t_ref2m_patch, t_soisno_col) use shr_const_mod , only : SHR_CONST_CDAY, SHR_CONST_TKFRZ use clm_time_manager , only : get_step_size, get_nstep use clm_varpar , only : nlevsno, nlevgrnd - use pftconMod , only : nswheat, nirrig_swheat, pftcon + use pftconMod , only : nswheat, nirrig_swheat, ncitrus, nirrig_citrus, pftcon use pftconMod , only : nwwheat, nirrig_wwheat use pftconMod , only : nsugarcane, nirrig_sugarcane use ColumnType , only : col @@ -582,6 +588,7 @@ subroutine CropUpdateAccVars(this, bounds, t_ref2m_patch, t_soisno_col) ivt = patch%itype(p) if ( (trim(this%baset_mapping) == baset_map_latvary) .and. & ((ivt == nswheat) .or. (ivt == nirrig_swheat) .or. & + (ivt == ncitrus) .or. (ivt == nirrig_citrus) .or. & ! added by Olga (ivt == nsugarcane) .or. (ivt == nirrig_sugarcane)) ) then rbufslp(p) = max(0._r8, min(pftcon%mxtmp(ivt), & t_ref2m_patch(p)-(SHR_CONST_TKFRZ + this%latbaset_patch(p)))) & diff --git a/src/clm5/biogeochem/NutrientCompetitionFlexibleCNMod.F90 b/src/clm5/biogeochem/NutrientCompetitionFlexibleCNMod.F90 index f404ac9611..5008ea14d7 100644 --- a/src/clm5/biogeochem/NutrientCompetitionFlexibleCNMod.F90 +++ b/src/clm5/biogeochem/NutrientCompetitionFlexibleCNMod.F90 @@ -25,7 +25,6 @@ module NutrientCompetitionFlexibleCNMod use PatchType , only : patch use NutrientCompetitionMethodMod, only : nutrient_competition_method_type use NutrientCompetitionMethodMod, only : params_inst - use clm_varctl , only : iulog ! implicit none private @@ -98,7 +97,6 @@ subroutine InitAllocate(this, bounds) allocate(this%actual_leafcn(bounds%begp:bounds%endp)) ; this%actual_leafcn(:) = nan allocate(this%actual_storage_leafcn(bounds%begp:bounds%endp)) ; this%actual_storage_leafcn(:) = nan - end subroutine InitAllocate !------------------------------------------------------------------------ @@ -196,7 +194,7 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & use clm_varctl , only : downreg_opt use clm_varctl , only : CN_residual_opt use clm_varctl , only : CN_partition_opt - use clm_time_manager , only : get_step_size + use clm_time_manager , only : get_step_size, get_curr_calday use CNVegStateType , only : cnveg_state_type use CropType , only : crop_type use CanopyStateType , only : canopystate_type @@ -240,7 +238,7 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & real(r8) :: f5 ! grain allocation parameter real(r8) :: cng ! C:N ratio for grain (= cnlw for now; slevis) real(r8) :: dt ! model time step - real(r8):: fsmn(bounds%begp:bounds%endp) ! A emperate variable for adjusting FUN uptakes + real(r8):: fsmn(bounds%begp:bounds%endp) ! A temperate variable for adjusting FUN uptakes real(r8):: frootcn_storage_actual real(r8):: frootcn_actual @@ -323,16 +321,19 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & grperc => pftcon%grperc , & ! Input: growth respiration parameter grpnow => pftcon%grpnow , & ! Input: growth respiration parameter evergreen => pftcon%evergreen , & ! Input: binary flag for evergreen leaf habit (0 or 1) + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop phenology (0 or 1) (added by O.Dombrowski) croplive => crop_inst%croplive_patch , & ! Input: [logical (:) ] flag, true if planted, not harvested - + hui => crop_inst%gddplant_patch , & ! Input: [real(r8) (:) ] =gdd since planting (gddplant) + gddmaturity => cnveg_state_inst%gddmaturity_patch , & ! Input: [real(r8) (:) ] gdd until harvest peaklai => cnveg_state_inst%peaklai_patch , & ! Input: [integer (:) ] 1: max allowed lai; 0: not at max aleaf => cnveg_state_inst%aleaf_patch , & ! Output: [real(r8) (:) ] leaf allocation coefficient astem => cnveg_state_inst%astem_patch , & ! Output: [real(r8) (:) ] stem allocation coefficient c_allometry => cnveg_state_inst%c_allometry_patch , & ! Output: [real(r8) (:) ] C allocation index (DIM) n_allometry => cnveg_state_inst%n_allometry_patch , & ! Output: [real(r8) (:) ] N allocation index (DIM) downreg => cnveg_state_inst%downreg_patch , & ! Output: [real(r8) (:) ] fractional reduction in GPP due to N limitation (DIM) - + harvest_flag => cnveg_state_inst%harvest_flag_patch , & ! Output: [real(r8) (:) ] harvest flag for perennial crops + storage_flag => cnveg_state_inst%storage_flag_patch , & ! Output: [real(r8) (:) ] flag to switch to storage growth for perennials annsum_npp => cnveg_carbonflux_inst%annsum_npp_patch , & ! Input: [real(r8) (:) ] annual sum of NPP, for wood allocation gpp => cnveg_carbonflux_inst%gpp_before_downreg_patch , & ! Output: [real(r8) (:) ] GPP flux before downregulation (gC/m2/s) availc => cnveg_carbonflux_inst%availc_patch , & ! Output: [real(r8) (:) ] C flux available for allocation (gC/m2/s) @@ -402,14 +403,12 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & ! set time steps dt = real( get_step_size(), r8 ) - ! patch loop to distribute the available N between the competing patches ! 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 = patch%column(p) - ! set some local allocation variables f1 = froot_leaf(ivt(p)) f2 = croot_stem(ivt(p)) @@ -518,7 +517,6 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & ! 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 @@ -545,7 +543,35 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & cpool_to_grainc(p) = nlc * f5 * fcur cpool_to_grainc_storage(p) = nlc * f5 * (1._r8 -fcur) end if - + ! allocation for deciduous fruit trees (added by O.Dombrowski) + ! for this crop type, storage growth is considered next to photosynthetic growth + ! after harvest photosynthates are allocated to storage pool for refilling of C reserves + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1._r8) then + if (storage_flag(p) == 0._r8) then + fcur = fcur + else if (storage_flag(p) == 1._r8) then + fcur = 0._r8 + end if + 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) + 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) + if (harvest_flag(p) == 0._r8) then + cpool_to_grainc(p) = nlc * f5 + cpool_to_grainc_storage(p) = nlc * f5 * 0._r8 + else if (harvest_flag(p) == 1._r8) then + cpool_to_grainc(p) = nlc * f5 * 0._r8 + cpool_to_grainc_storage(p) = nlc * f5 * 0._r8 + end if + end if if (downreg_opt) then ! corresponding N fluxes npool_to_leafn(p) = (nlc / cnl) * fcur @@ -575,6 +601,21 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & npool_to_grainn(p) = (nlc * f5 / cng) * fcur npool_to_grainn_storage(p) = (nlc * f5 / cng) * (1._r8 -fcur) end if + ! calculating corresponding N fluxes for deciduous fruit trees + ! (added by O.Dombrowski) + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1._r8) then + cng = graincn(ivt(p)) + 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) + npool_to_grainn(p) = (nlc * f5 / cng) + npool_to_grainn_storage(p) = (nlc * f5 / cng) * (0._r8) + end if end if if (downreg_opt .eqv. .false. .AND. CN_partition_opt == 0) then @@ -735,6 +776,81 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & end if end if + ! calculation of N fluxes for perennial woody croptypes added by + ! O.Dombrowski + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1._r8) then + cng = graincn(ivt(p)) + npool_to_livestemn_demand(p) = (nlc * f3 * f4 / cnlw) * fcur + npool_to_livestemn_supply(p) = npool(p)/dt * fcur - npool_to_frootn(p) + npool_to_livestemn(p) = max(min(npool_to_livestemn_supply(p),npool_to_livestemn_demand(p)),0.0_r8) + + npool_to_livestemn_storage_demand(p) = (nlc * f3 * f4 / cnlw) * (1._r8 - fcur) + npool_to_livestemn_storage_supply(p) = npool(p)/dt * (1._r8 - fcur) - npool_to_frootn_storage(p) + npool_to_livestemn_storage(p) = max(min(npool_to_livestemn_storage_supply(p), & + npool_to_livestemn_storage_demand(p)),0.0_r8) + + npool_to_livecrootn_demand(p) = (nlc * f2 * f3 * f4 / cnlw) * fcur + npool_to_livecrootn_supply(p) = npool(p)/dt * fcur - npool_to_frootn(p) - npool_to_livestemn(p) + npool_to_livecrootn(p) = max(min(npool_to_livecrootn_supply(p),npool_to_livecrootn_demand(p)),0.0_r8) + + npool_to_livecrootn_storage_demand(p) = (nlc * f2 * f3 * f4 / cnlw) * (1._r8 - fcur) + npool_to_livecrootn_storage_supply(p) = npool(p)/dt * (1._r8 - fcur) - npool_to_frootn_storage(p) - & + npool_to_livestemn_storage(p) + npool_to_livecrootn_storage(p) = max(min(npool_to_livecrootn_storage_supply(p), & + npool_to_livecrootn_storage_demand(p)),0.0_r8) + + npool_to_deadstemn_demand(p) = (nlc * f3 * (1._r8 - f4) / cndw) * fcur + npool_to_deadstemn_supply(p) = npool(p)/dt * fcur - npool_to_frootn(p) - npool_to_livestemn(p) - & + npool_to_livecrootn(p) + npool_to_deadstemn(p) = max(min(npool_to_deadstemn_supply(p),npool_to_deadstemn_demand(p)), 0.0_r8) + + npool_to_deadstemn_storage_demand(p) = (nlc * f3 * (1._r8 - f4) / cndw) * (1._r8 - fcur) + npool_to_deadstemn_storage_supply(p) = npool(p)/dt * (1._r8 - fcur) - npool_to_frootn_storage(p) - & + npool_to_livestemn_storage(p) - npool_to_livecrootn_storage(p) + npool_to_deadstemn_storage(p) = max(min(npool_to_deadstemn_storage_supply(p), & + npool_to_deadstemn_storage_demand(p)),0.0_r8) + + npool_to_deadcrootn_demand(p) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * fcur + npool_to_deadcrootn_supply(p) = npool(p)/dt * fcur - npool_to_frootn(p) - npool_to_livestemn(p) - & + npool_to_livecrootn(p) - npool_to_deadstemn(p) + npool_to_deadcrootn(p) = max(min(npool_to_deadcrootn_supply(p), npool_to_deadcrootn_demand(p)), 0.0_r8) + + npool_to_deadcrootn_storage_demand(p) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * (1._r8 - fcur) + npool_to_deadcrootn_storage_supply(p) = npool(p)/dt * (1._r8 - fcur) - npool_to_frootn_storage(p) - & + npool_to_livestemn_storage(p) - npool_to_livecrootn_storage(p) - npool_to_deadstemn_storage(p) + npool_to_deadcrootn_storage(p) = max(min(npool_to_deadcrootn_storage_supply(p), & + npool_to_deadcrootn_storage_demand(p)),0.0_r8) + + npool_to_grainn_demand(p) = (nlc * f5 / cng) + npool_to_grainn_supply(p) = npool(p)/dt - npool_to_frootn(p) - npool_to_livestemn(p) - & + npool_to_livecrootn(p) - npool_to_deadstemn(p) - npool_to_deadcrootn(p) + npool_to_grainn(p) = max(min(npool_to_grainn_supply(p), npool_to_grainn_demand(p)), 0.0_r8) + + npool_to_grainn_storage_demand(p) = (nlc * f5 / cng) * 0._r8 + npool_to_grainn_storage_supply(p) = npool(p)/dt * 0._r8 - npool_to_frootn_storage(p) - & + npool_to_livestemn_storage(p) - npool_to_livecrootn_storage(p) - npool_to_deadstemn_storage(p) - & + npool_to_deadcrootn_storage(p) + npool_to_grainn_storage(p) = max(min(npool_to_grainn_storage_supply(p), npool_to_grainn_storage_demand(p)), & + 0.0_r8) + + npool_to_leafn_demand(p) = (nlc / cnl) * fcur + npool_to_leafn_supply(p) = npool(p)/dt * fcur - npool_to_frootn(p) - npool_to_livestemn(p) - & + npool_to_livecrootn(p) - npool_to_deadstemn(p) - npool_to_deadcrootn(p) - npool_to_grainn(p) + npool_to_leafn(p) = max(min(npool_to_leafn_supply(p), npool_to_leafn_demand(p)), 0.0_r8) + + npool_to_leafn_storage_demand(p) = (nlc / cnl) * (1._r8 - fcur) + npool_to_leafn_storage_supply(p) = npool(p)/dt * (1._r8 - fcur) - npool_to_frootn_storage(p) - & + npool_to_livestemn_storage(p) - npool_to_livecrootn_storage(p) & + - npool_to_deadstemn_storage(p) - npool_to_deadcrootn_storage(p) - npool_to_grainn_storage(p) + npool_to_leafn_storage(p) = max(min(npool_to_leafn_storage_supply(p), npool_to_leafn_storage_demand(p)), & + 0.0_r8) + + if (CN_residual_opt == 1) then + npool_to_leafn(p) = max(npool_to_leafn_supply(p),0.0_r8) + npool_to_leafn_storage(p) = max(npool_to_leafn_storage_supply(p),0.0_r8) + end if + + end if end if @@ -760,9 +876,16 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & gresp_storage = gresp_storage + cpool_to_livestemc_storage(p) gresp_storage = gresp_storage + cpool_to_grainc_storage(p) end if + !recalculate total gresp_storage of vegetation parts for fruit trees (added by O.Dombrowski) + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1._r8) then + gresp_storage = cpool_to_leafc_storage(p) + cpool_to_frootc_storage(p) & + + cpool_to_livestemc_storage(p) & + + cpool_to_deadstemc_storage(p) & + + cpool_to_livecrootc_storage(p) & + + cpool_to_deadcrootc_storage(p) & + + cpool_to_grainc_storage(p) + end if cpool_to_gresp_storage(p) = gresp_storage * g1 * (1._r8 - g2) - - ! computing 1.) fractional N demand and 2.) N allocation after uptake for different plant parts !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! if (downreg_opt .eqv. .false. .AND. CN_partition_opt == 1) then @@ -797,7 +920,22 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & npool_to_grainn_demand(p) = (nlc * f5 / cng) * fcur npool_to_grainn_storage_demand(p) = (nlc * f5 / cng) * (1._r8 -fcur) end if + ! computing nitrogen demand for fruit trees + ! (added by O.Dombrowski) + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1._r8) then + cng = graincn(ivt(p)) + npool_to_livestemn_demand(p) = (nlc * f3 * f4 / cnlw) * fcur + npool_to_livestemn_storage_demand(p) = (nlc * f3 * f4 / cnlw) * (1._r8 - fcur) + npool_to_deadstemn_demand(p) = (nlc * f3 * (1._r8 - f4) / cndw) * fcur + npool_to_deadstemn_storage_demand(p) = (nlc * f3 * (1._r8 - f4) / cndw) * (1._r8 - fcur) + npool_to_livecrootn_demand(p) = (nlc * f2 * f3 * f4 / cnlw) * fcur + npool_to_livecrootn_storage_demand(p) = (nlc * f2 * f3 * f4 / cnlw) * (1._r8 - fcur) + npool_to_deadcrootn_demand(p) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * fcur + npool_to_deadcrootn_storage_demand(p) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * (1._r8 - fcur) + npool_to_grainn_demand(p) = (nlc * f5 / cng) + npool_to_grainn_storage_demand(p) = (nlc * f5 / cng) * 0._r8 + end if ! computing 1.) fractional N demand for different plant parts !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -822,10 +960,11 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & npool_to_deadstemn_storage_demand(p) + & npool_to_livecrootn_demand(p) + npool_to_livecrootn_storage_demand(p) + npool_to_deadcrootn_demand(p) + & npool_to_deadcrootn_storage_demand(p) + & - npool_to_grainn_demand(p) + npool_to_grainn_storage_demand(p) + npool_to_grainn_demand(p) + npool_to_grainn_storage_demand(p) end if + if (total_plant_Ndemand(p) == 0.0_r8) then ! removing division by zero frNdemand_npool_to_leafn(p) = 0.0_r8 @@ -1193,7 +1332,7 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & use clm_varctl , only : use_c13, use_c14 use clm_varctl , only : nscalar_opt, plant_ndemand_opt, substrate_term_opt, temp_scalar_opt use clm_varpar , only : nlevdecomp - use clm_time_manager , only : get_step_size + use clm_time_manager , only : get_step_size,get_curr_calday use CanopyStateType , only : canopystate_type use PhotosynthesisMod , only : photosyns_type use CropType , only : crop_type @@ -1266,6 +1405,7 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types (1=perennial, 0=not perennial) froot_leaf => pftcon%froot_leaf , & ! Input: allocation parameter: new fine root C per new leaf C (gC/gC) croot_stem => pftcon%croot_stem , & ! Input: allocation parameter: new coarse root C per new stem C (gC/gC) stem_leaf => pftcon%stem_leaf , & ! Input: allocation parameter: new stem c per new leaf C (gC/gC) @@ -1281,9 +1421,11 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & bfact => pftcon%bfact , & ! Input: parameter used below aleaff => pftcon%aleaff , & ! Input: parameter used below arootf => pftcon%arootf , & ! Input: parameter used below + arootf2 => pftcon%arootf2 , & ! Input: parameter used below astemf => pftcon%astemf , & ! Input: parameter used below arooti => pftcon%arooti , & ! Input: parameter used below fleafi => pftcon%fleafi , & ! Input: parameter used below + aleafstor => pftcon%aleafstor , & ! Input: parameter used below allconsl => pftcon%allconsl , & ! Input: parameter used below allconss => pftcon%allconss , & ! Input: parameter used below grperc => pftcon%grperc , & ! Input: parameter used below @@ -1307,10 +1449,15 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & gddmaturity => cnveg_state_inst%gddmaturity_patch , & ! Input: [real(r8) (:) ] gdd needed to harvest huileaf => cnveg_state_inst%huileaf_patch , & ! Input: [real(r8) (:) ] heat unit index needed from planting to leaf emergence - huigrain => cnveg_state_inst%huigrain_patch , & ! Input: [real(r8) (:) ] same to reach vegetative maturity + huigrain => cnveg_state_inst%huigrain_patch , & ! Input: [real(r8) (:) ] same to reach vegetative maturity/fruit fill + huilfmat => cnveg_state_inst%huilfmat_patch , & ! Input: [real(r8) (:) ] same to reach canopy maturity + huiripe => cnveg_state_inst%huiripe_patch , & ! Input: [real(r8) (:) ] same to reach fruit cell expansion peaklai => cnveg_state_inst%peaklai_patch , & ! Input: [integer (:) ] 1: max allowed lai; 0: not at max aleafi => cnveg_state_inst%aleafi_patch , & ! Output: [real(r8) (:) ] saved allocation coefficient from phase 2 astemi => cnveg_state_inst%astemi_patch , & ! Output: [real(r8) (:) ] saved allocation coefficient from phase 2 + arooti2 => cnveg_state_inst%arooti2_patch , & ! Output: [real(r8) (:) ] saved allocation coefficient from phase 2 + arooti3 => cnveg_state_inst%arooti3_patch , & ! Output: [real(r8) (:) ] saved allocation coefficient from phase 3 + aleafi3 => cnveg_state_inst%aleafi3_patch , & ! Output: [real(r8) (:) ] saved allocation coefficient from phase 3 aleaf => cnveg_state_inst%aleaf_patch , & ! Output: [real(r8) (:) ] leaf allocation coefficient astem => cnveg_state_inst%astem_patch , & ! Output: [real(r8) (:) ] stem allocation coefficient grain_flag => cnveg_state_inst%grain_flag_patch , & ! Output: [real(r8) (:) ] 1: grain fill stage; 0: not @@ -1320,7 +1467,8 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & tempmax_retransn => cnveg_state_inst%tempmax_retransn_patch , & ! Output: [real(r8) (:) ] temporary annual max of retranslocated N pool (gN/m2) annsum_potential_gpp => cnveg_state_inst%annsum_potential_gpp_patch , & ! Output: [real(r8) (:) ] annual sum of potential GPP annmax_retransn => cnveg_state_inst%annmax_retransn_patch , & ! Output: [real(r8) (:) ] annual max of retranslocated N pool - + dormant_flag => cnveg_state_inst%dormant_flag_patch , & ! Output: [real(r8) (:) ] dormancy flag + harvest_flag => cnveg_state_inst%harvest_flag_patch , & ! Input: [real(r8) (:) ] harvest flag xsmrpool => cnveg_carbonstate_inst%xsmrpool_patch , & ! Input: [real(r8) (:) ] (gC/m2) temporary photosynthate C pool leafc => cnveg_carbonstate_inst%leafc_patch , & ! Input: [real(r8) (:) ] frootc => cnveg_carbonstate_inst%frootc_patch , & ! Input: [real(r8) (:) ] @@ -1413,9 +1561,15 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & mr = leaf_mr(p) + froot_mr(p) if (woody(ivt(p)) == 1.0_r8) then mr = mr + livestem_mr(p) + livecroot_mr(p) + !include all mr terms for woody crop types + if (perennial(ivt(p)) == 1._r8) then + mr = mr + grain_mr(p) + end if else if (ivt(p) >= npcropmin) then if (croplive(p)) mr = mr + livestem_mr(p) + grain_mr(p) end if ! carbon flux available for allocation + + ! carbon flux available for allocation availc(p) = gpp(p) - mr ! new code added for isotope calculations, 7/1/05, PET @@ -1440,13 +1594,11 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & ! 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*secspday) if (xsmrpool_recover(p) < availc(p)) then ! available carbon reduced by amount for xsmrpool recovery @@ -1490,118 +1642,223 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & if (ivt(p) >= npcropmin) then ! skip 2 generic crops if (croplive(p)) then - ! same phases appear in subroutine CropPhenology - - ! Phase 1 completed: - ! ================== - ! if hui is less than the number of gdd needed for filling of grain - ! leaf emergence also has to have taken place for lai changes to occur - ! and carbon assimilation - ! Next phase: leaf emergence to start of leaf decline + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1._r8) then + ! same phases appear in subroutine CropPhenology + if (dormant_flag(p) == 0.0_r8) then + ! Phase 1 completed: + if (leafout(p) >= huileaf(p) .and. hui(p) < huigrain(p)) then + ! allocation rules for crops based on maturity and linear decrease + ! of amount allocated to roots over course of the growing season + + if (peaklai(p) == 1) then ! lai at maximum allowed + arepr(p) = 0._r8 + aleaf(p) = 1.e-5_r8 + astem(p) = astem(p) + aroot(p) = 1._r8 - arepr(p) - aleaf(p) - astem(p) + else + arepr(p) = 0._r8 + aroot(p) = max(0._r8, min(1._r8, arooti(ivt(p)) - & + (arooti(ivt(p)) - arootf(ivt(p))) * & + min(1._r8,(hui(p)-huileaf(p))/(huigrain(p)-huileaf(p))))) + fleaf = fleafi(ivt(p)) * (exp(-bfact(ivt(p))) - & + exp(-bfact(ivt(p))*(hui(p)-huileaf(p))/(huilfmat(p)-huileaf(p)))) / & + (exp(-bfact(ivt(p)))-1) ! fraction alloc to leaf (from J Norman alloc curve) + aleaf(p) = max(0.05_r8, (1._r8 - aroot(p)) * fleaf) + astem(p) = 1._r8 - arepr(p) - aleaf(p) - aroot(p) + end if + + ! AgroIBIS included here an immediate adjustment to aleaf & astem if the + ! predicted lai from the above allocation coefficients exceeded laimx. + ! We have decided to live with lais slightly higher than laimx by + ! enforcing the cap in the following tstep through the peaklai logic above. + astemi(p) = astem(p) ! save for use by equations after shift + aleafi(p) = aleaf(p) ! to reproductive phenology stage begins + arooti2(p) = aroot(p) + grain_flag(p) = 0._r8 ! setting to 0 while in phase 2 + + ! Phase 2 completed: + + else if (hui(p) >= huigrain(p) .and. hui(p) < huiripe(p)) then + + aroot(p) = max(0._r8, min(1._r8, arooti2(p) - & + (arooti2(p) - arootf2(ivt(p))) * min(1._r8, (hui(p)-huileaf(p))/(huiripe(p)-huileaf(p))))) + if (astemi(p) > astemf(ivt(p))) then + astem(p) = max(0._r8, max(astemf(ivt(p)), astem(p) * & + (1._r8 - min(((hui(p)-huileaf(p))- & + (huigrain(p)-huileaf(p)))/(((gddmaturity(p)-huileaf(p))*declfact(ivt(p)))- & + (huigrain(p)-huileaf(p))),1._r8)**allconss(ivt(p)) ))) + end if + ! If crops have hit peaklai, then set leaf allocation to small value + if (peaklai(p) == 1) then + aleaf(p) = 1.e-5_r8 + else if (aleafi(p) > aleaff(ivt(p))) then + fleaf = aleafi(p) * (exp(-bfact(ivt(p))) - & + exp(-bfact(ivt(p))*(hui(p)-huileaf(p))/(huilfmat(p)-huileaf(p)))) / & + (exp(-bfact(ivt(p)))-1) ! fraction alloc to leaf (from J Norman alloc curve) + aleaf(p) = max(1.e-5_r8, (1._r8 - aroot(p)) * fleaf) + end if + + arepr(p) = 1._r8 - aroot(p) - astem(p) - aleaf(p) + arooti3(p) = aroot(p) + aleafi3(p) = aleaf(p) + + else if (hui(p) >= huiripe(p) .and. hui(p) < huilfmat(p)) then + aroot(p) = max(0._r8, min(1._r8, arooti3(p) - & + (arooti3(p) - arootf2(ivt(p))) * min(1._r8, (hui(p)-huileaf(p))/(huilfmat(p)-huileaf(p))))) + if (astemi(p) > astemf(ivt(p))) then + astem(p) = max(0._r8, max(astemf(ivt(p)), astem(p) * & + (1._r8 - min(((hui(p)-huileaf(p))- & + (huiripe(p)-huileaf(p)))/(((gddmaturity(p)-huileaf(p))*declfact(ivt(p)))- & + (huiripe(p)-huileaf(p))),1._r8)**allconss(ivt(p))))) + end if + + ! If crops have hit peaklai, then set leaf allocation to + ! small value + if (peaklai(p) == 1) then + aleaf(p) = 1.e-5_r8 + else if (aleafi3(p) > aleaff(ivt(p))) then + fleaf = fleafi(ivt(p)) * (exp(-bfact(ivt(p))) - & + exp(-bfact(ivt(p))*(hui(p)-huileaf(p))/(huilfmat(p)-huileaf(p)))) / & + (exp(-bfact(ivt(p)))-1) ! fraction alloc to leaf (from J Norman alloc curve) + aleaf(p) = max(1.e-5_r8, (1._r8 - aroot(p)) * fleaf) + end if - if (leafout(p) >= huileaf(p) .and. hui(p) < huigrain(p)) then + arepr(p) = 1._r8 - aroot(p) - astem(p) - aleaf(p) - ! allocation rules for crops based on maturity and linear decrease - ! of amount allocated to roots over course of the growing season + else if (hui(p) >= huilfmat(p) .and. hui(p)< gddmaturity(p)) then + aroot(p) = arootf2(ivt(p)) + if (astemi(p) > astemf(ivt(p))) then + astem(p) = max(0._r8, max(astemf(ivt(p)), astem(p) * & + (1._r8 - min(((hui(p)-huileaf(p))- & + (huilfmat(p)-huileaf(p)))/(((gddmaturity(p)-huileaf(p))*declfact(ivt(p)))- & + (huilfmat(p)-huileaf(p))),1._r8)**allconss(ivt(p))))) + end if + + ! Leaf allocation is set to small value + aleaf(p) = 1.e-5_r8 - if (peaklai(p) == 1) then ! lai at maximum allowed - arepr(p) = 0._r8 - aleaf(p) = 1.e-5_r8 - astem(p) = 0._r8 - aroot(p) = 1._r8 - arepr(p) - aleaf(p) - astem(p) - else - arepr(p) = 0._r8 - aroot(p) = max(0._r8, min(1._r8, arooti(ivt(p)) - & - (arooti(ivt(p)) - arootf(ivt(p))) * & - min(1._r8, hui(p)/gddmaturity(p)))) - fleaf = fleafi(ivt(p)) * (exp(-bfact(ivt(p))) - & - exp(-bfact(ivt(p))*hui(p)/huigrain(p))) / & - (exp(-bfact(ivt(p)))-1) ! fraction alloc to leaf (from J Norman alloc curve) - aleaf(p) = max(1.e-5_r8, (1._r8 - aroot(p)) * fleaf) - astem(p) = 1._r8 - arepr(p) - aleaf(p) - aroot(p) + arepr(p) = 1._r8 - aroot(p) - astem(p) - aleaf(p) + + else if (hui(p) >= gddmaturity(p) .or. harvest_flag(p) == 1._r8) then + arepr(p) = 0._r8 + aleaf(p) = aleafstor(ivt(p)) + astem(p) = (1 - arepr(p) - aleaf(p))/2._r8 + aroot(p) = 1 - arepr(p) - aleaf(p) - astem(p) + end if + else ! when tree is dormant + aleaf(p) = 1.e-5_r8 ! allocation coefficients should be irrelevant + astem(p) = 0._r8 ! because trees have no live carbon pools + aroot(p) = 0._r8 + arepr(p) = 0._r8 + grain_flag(p) = 0._r8 !set to 0 before the next grainfill starts end if + else ! normal crops + ! same phases appear in subroutine CropPhenology - ! AgroIBIS included here an immediate adjustment to aleaf & astem if the - ! predicted lai from the above allocation coefficients exceeded laimx. - ! We have decided to live with lais slightly higher than laimx by - ! enforcing the cap in the following tstep through the peaklai logic above. + ! Phase 1 completed: + ! ================== + ! if hui is less than the number of gdd needed for filling of + ! grain + ! leaf emergence also has to have taken place for lai changes to + ! occur + ! and carbon assimilation + ! Next phase: leaf emergence to start of leaf decline + + if (leafout(p) >= huileaf(p) .and. hui(p) < huigrain(p)) then + + ! allocation rules for crops based on maturity and linear decrease + ! of amount allocated to roots over course of the growing season + + if (peaklai(p) == 1) then ! lai at maximum allowed + arepr(p) = 0._r8 + aleaf(p) = 1.e-5_r8 + astem(p) = 0._r8 + aroot(p) = 1._r8 - arepr(p) - aleaf(p) - astem(p) + else + arepr(p) = 0._r8 + aroot(p) = max(0._r8, min(1._r8, arooti(ivt(p)) - & + (arooti(ivt(p)) - arootf(ivt(p))) * & + min(1._r8, hui(p)/gddmaturity(p)))) + fleaf = fleafi(ivt(p)) * (exp(-bfact(ivt(p))) - & + exp(-bfact(ivt(p))*hui(p)/huigrain(p))) / & + (exp(-bfact(ivt(p)))-1) ! fraction alloc to leaf (from J Norman alloc curve) + aleaf(p) = max(1.e-5_r8, (1._r8 - aroot(p)) * fleaf) + astem(p) = 1._r8 - arepr(p) - aleaf(p) - aroot(p) + end if - astemi(p) = astem(p) ! save for use by equations after shift - aleafi(p) = aleaf(p) ! to reproductive phenology stage begins - grain_flag(p) = 0._r8 ! setting to 0 while in phase 2 + ! AgroIBIS included here an immediate adjustment to aleaf & astem if the + ! predicted lai from the above allocation coefficients exceeded laimx. + ! We have decided to live with lais slightly higher than laimx by + ! enforcing the cap in the following tstep through the peaklai logic above. + + astemi(p) = astem(p) ! save for use by equations after shift + aleafi(p) = aleaf(p) ! to reproductive phenology stage begins + grain_flag(p) = 0._r8 ! setting to 0 while in phase 2 + + ! Phase 2 completed: + ! ================== + ! shift allocation either when enough gdd are accumulated or + ! maximum number + ! of days has elapsed since planting + + else if (hui(p) >= huigrain(p)) then + aroot(p) = max(0._r8, min(1._r8, arooti(ivt(p)) - & + (arooti(ivt(p)) - arootf(ivt(p))) * min(1._r8, hui(p)/gddmaturity(p)))) + if (astemi(p) > astemf(ivt(p))) then + astem(p) = max(0._r8, max(astemf(ivt(p)), astem(p) * & + (1._r8 - min((hui(p)- & + huigrain(p))/((gddmaturity(p)*declfact(ivt(p)))- & + huigrain(p)),1._r8)**allconss(ivt(p)) ))) + end if - ! Phase 2 completed: - ! ================== - ! shift allocation either when enough gdd are accumulated or maximum number - ! of days has elapsed since planting - - else if (hui(p) >= huigrain(p)) then - aroot(p) = max(0._r8, min(1._r8, arooti(ivt(p)) - & - (arooti(ivt(p)) - arootf(ivt(p))) * min(1._r8, hui(p)/gddmaturity(p)))) - if (astemi(p) > astemf(ivt(p))) then - astem(p) = max(0._r8, max(astemf(ivt(p)), astem(p) * & - (1._r8 - min((hui(p)- & - huigrain(p))/((gddmaturity(p)*declfact(ivt(p)))- & - huigrain(p)),1._r8)**allconss(ivt(p)) ))) - end if + ! If crops have hit peaklai, then set leaf allocation to small + ! value + if (peaklai(p) == 1) then + aleaf(p) = 1.e-5_r8 + else if (aleafi(p) > aleaff(ivt(p))) then + aleaf(p) = max(1.e-5_r8, max(aleaff(ivt(p)), aleaf(p) * & + (1._r8 - min((hui(p)- & + huigrain(p))/((gddmaturity(p)*declfact(ivt(p)))- & + huigrain(p)),1._r8)**allconsl(ivt(p)) ))) + end if - ! If crops have hit peaklai, then set leaf allocation to small value - if (peaklai(p) == 1) then - aleaf(p) = 1.e-5_r8 - else if (aleafi(p) > aleaff(ivt(p))) then - aleaf(p) = max(1.e-5_r8, max(aleaff(ivt(p)), aleaf(p) * & - (1._r8 - min((hui(p)- & - huigrain(p))/((gddmaturity(p)*declfact(ivt(p)))- & - huigrain(p)),1._r8)**allconsl(ivt(p)) ))) - end if - !Beth's retranslocation of leafn, stemn, rootn to organ - !Filter excess plant N to retransn pool for organ N - !Only do one time then hold grain_flag till onset next season - - ! slevis: Will astem ever = astemf exactly? - ! Beth's response: ...looks like astem can equal astemf under the right circumstances. - !It might be worth a rewrite to capture what I was trying to do, but the retranslocation for - !corn and wheat begins at the beginning of the grain fill stage, but for soybean I was holding it - !until after the leaf and stem decline were complete. Looking at how astem is calculated, once the - !stem decline is near complete, astem should (usually) be set to astemf. The reason for holding off - !on soybean is that the retranslocation scheme begins at the beginning of the grain phase, when the - !leaf and stem are still growing, but declining. Since carbon is still getting allocated and now - !there is more nitrogen available, the nitrogen can be diverted from grain. For corn and wheat - !the impact was probably enough to boost productivity, but for soybean the nitrogen was better off - !fulfilling the grain fill. It seems that if the peak lai is reached for soybean though that this - !would be bypassed altogether, not the intended outcome. I checked several of my output files and - !they all seemed to be going through the retranslocation loop for soybean - good news. - - if (astem(p) == astemf(ivt(p)) .or. & - (ivt(p) /= ntmp_soybean .and. ivt(p) /= nirrig_tmp_soybean .and.& - ivt(p) /= ntrp_soybean .and. ivt(p) /= nirrig_trp_soybean)) then - if (grain_flag(p) == 0._r8) then - t1 = 1 / dt - leafn_to_retransn(p) = t1 * max(leafn(p)- (leafc(p) / fleafcn(ivt(p))),0._r8) - livestemn_to_retransn(p) = t1 * max(livestemn(p) - (livestemc(p) / fstemcn(ivt(p))),0._r8) - frootn_to_retransn(p) = 0._r8 - if (ffrootcn(ivt(p)) > 0._r8) then - frootn_to_retransn(p) = t1 * max(frootn(p) - (frootc(p) / ffrootcn(ivt(p))),0._r8) + if (astem(p) == astemf(ivt(p)) .or. & + (ivt(p) /= ntmp_soybean .and. ivt(p) /= nirrig_tmp_soybean .and.& + ivt(p) /= ntrp_soybean .and. ivt(p) /= nirrig_trp_soybean)) then + if (grain_flag(p) == 0._r8) then + t1 = 1 / dt + leafn_to_retransn(p) = t1 * max(leafn(p)- (leafc(p) / fleafcn(ivt(p))),0._r8) + livestemn_to_retransn(p) = t1 * max(livestemn(p) - (livestemc(p) / fstemcn(ivt(p))),0._r8) + frootn_to_retransn(p) = 0._r8 + if (ffrootcn(ivt(p)) > 0._r8) then + frootn_to_retransn(p) = t1 * max(frootn(p) - (frootc(p) / ffrootcn(ivt(p))),0._r8) + end if + grain_flag(p) = 1._r8 end if - grain_flag(p) = 1._r8 end if + + arepr(p) = 1._r8 - aroot(p) - astem(p) - aleaf(p) + + else ! pre emergence + aleaf(p) = 1.e-5_r8 ! allocation coefficients should be irrelevant + astem(p) = 0._r8 ! because crops have no live carbon pools; + aroot(p) = 0._r8 ! this applies to this "else" and to the "else" + arepr(p) = 0._r8 ! a few lines down end if - - arepr(p) = 1._r8 - aroot(p) - astem(p) - aleaf(p) - - else ! pre emergence - aleaf(p) = 1.e-5_r8 ! allocation coefficients should be irrelevant - astem(p) = 0._r8 ! because crops have no live carbon pools; - aroot(p) = 0._r8 ! this applies to this "else" and to the "else" - arepr(p) = 0._r8 ! a few lines down - end if + end if ! perennial or normal crop f1 = aroot(p) / aleaf(p) f3 = astem(p) / aleaf(p) f5 = arepr(p) / aleaf(p) g1 = 0.25_r8 - + + if (perennial(ivt(p)) == 1._r8 .and. dormant_flag(p) == 1._r8) then !dormant tree has no allocation to any organs (similar to .not. croplive) + f1 = 0._r8 + f3 = 0._r8 + f5 = 0._r8 + g1 = 0.25_r8 + end if else ! .not croplive f1 = 0._r8 @@ -1615,10 +1872,17 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & ! determine N requirements if(use_fun)then ! In FUN, growth respiration is not part of the allometry calculation. if (woody(ivt(p)) == 1.0_r8) then - c_allometry(p) = (1._r8)*(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 if (ivt(p) >= npcropmin) then ! skip generic crops + if (perennial(ivt(p)) == 1.0_r8) then !(added by O.Dombrowski) + cng = graincn(ivt(p)) + c_allometry(p) = (1._r8)*(1._r8+f1+f5+f3*(1._r8+f2)) + n_allometry(p) = 1._r8/cnl + f1/cnfr + f5/cng + (f3*f4*(1._r8+f2))/cnlw + & + (f3*(1._r8-f4)*(1._r8+f2))/cndw + else + c_allometry(p) = (1._r8)*(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 + end if + else if (ivt(p) >= npcropmin .and. perennial(ivt(p)) == 0.0_r8) then ! skip generic crops cng = graincn(ivt(p)) c_allometry(p) = (1._r8)*(1._r8+f1+f5+f3*(1._r8+f2)) n_allometry(p) = 1._r8/cnl + f1/cnfr + f5/cng + (f3*f4*(1._r8+f2))/cnlw + & @@ -1738,14 +2002,13 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & ! retransn pool has N from leaves, stems, and roots for ! retranslocation - if (ivt(p) >= npcropmin .and. grain_flag(p) == 1._r8) then + if (ivt(p) >= npcropmin .and. grain_flag(p) == 1._r8 .and. perennial(ivt(p)) == 0._r8) then avail_retransn(p) = plant_ndemand(p) - else if (ivt(p) < npcropmin .and. annsum_potential_gpp(p) > 0._r8) then + else if ((ivt(p) < npcropmin .and. annsum_potential_gpp(p) > 0._r8) .or. (perennial(ivt(p)) == 1._r8 .and. annsum_potential_gpp(p) > 0._r8)) then avail_retransn(p) = (annmax_retransn(p)/2._r8)*(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) diff --git a/src/clm5/biogeochem/dynHarvestMod.F90 b/src/clm5/biogeochem/dynHarvestMod.F90 index a9344fd5cf..4119f318a2 100644 --- a/src/clm5/biogeochem/dynHarvestMod.F90 +++ b/src/clm5/biogeochem/dynHarvestMod.F90 @@ -33,7 +33,7 @@ module dynHarvestMod public :: CNHarvest ! harvest mortality routine for CN code ! ! !PRIVATE MEMBER FUNCTIONS: - private :: CNHarvestPftToColumn ! gather patch-level harvest fluxes to the column level + public :: CNHarvestPftToColumn ! gather patch-level harvest fluxes to the column level ! ! !PRIVATE TYPES: @@ -184,7 +184,7 @@ subroutine CNHarvest (num_soilc, filter_soilc, num_soilp, filter_soilp, & ! !USES: use pftconMod , only : noveg, nbrdlf_evr_shrub use clm_varcon , only : secspday - use clm_time_manager, only : get_step_size_real, is_beg_curr_year + use clm_time_manager, only : get_step_size_real, is_beg_curr_year ! ! !ARGUMENTS: integer , intent(in) :: num_soilc ! number of soil columns in filter @@ -330,13 +330,14 @@ subroutine CNHarvest (num_soilc, filter_soilc, num_soilp, filter_soilp, & else m = 0._r8 end if - + ! patch-level harvest carbon fluxes ! displayed pools hrv_leafc_to_litter(p) = leafc(p) * m hrv_frootc_to_litter(p) = frootc(p) * m hrv_livestemc_to_litter(p) = livestemc(p) * m wood_harvestc(p) = deadstemc(p) * m + hrv_livecrootc_to_litter(p) = livecrootc(p) * m hrv_deadcrootc_to_litter(p) = deadcrootc(p) * m hrv_xsmrpool_to_atm(p) = xsmrpool(p) * m @@ -498,7 +499,7 @@ subroutine CNHarvestPftToColumn (num_soilc, filter_soilc, & p = col%patchi(c) + pi - 1 if (patch%active(p)) then - + ! leaf harvest mortality carbon fluxes harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & hrv_leafc_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) @@ -522,7 +523,6 @@ subroutine CNHarvestPftToColumn (num_soilc, filter_soilc, & hrv_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & hrv_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) - ! storage harvest mortality carbon fluxes harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & hrv_leafc_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) @@ -630,7 +630,7 @@ subroutine CNHarvestPftToColumn (num_soilc, filter_soilc, & ! wood harvest mortality carbon fluxes to product pools cwood_harvestc(c) = cwood_harvestc(c) + & pwood_harvestc(p) * wtcol(p) - + ! wood harvest mortality nitrogen fluxes to product pools cwood_harvestn(c) = cwood_harvestn(c) + & pwood_harvestn(p) * wtcol(p) diff --git a/src/clm5/biogeophys/TemperatureType.F90 b/src/clm5/biogeophys/TemperatureType.F90 index 7dfbb5d95f..438734ea8a 100644 --- a/src/clm5/biogeophys/TemperatureType.F90 +++ b/src/clm5/biogeophys/TemperatureType.F90 @@ -87,6 +87,7 @@ module TemperatureType ! being: that way one parameterization is free to change the exact meaning of its ! accumulator without affecting the other). ! + real(r8), pointer :: t_ref24_patch (:) ! patch 24hr average 2 m air temperature (K) real(r8), pointer :: t_veg24_patch (:) ! patch 24hr average vegetation temperature (K) real(r8), pointer :: t_veg240_patch (:) ! patch 240hr average vegetation temperature (Kelvin) real(r8), pointer :: gdd0_patch (:) ! patch growing degree-days base 0C from planting (ddays) @@ -252,6 +253,7 @@ subroutine InitAllocate(this, bounds) allocate(this%t_ref2m_min_inst_u_patch (begp:endp)) ; this%t_ref2m_min_inst_u_patch (:) = nan ! Accumulated fields + allocate(this%t_ref24_patch (begp:endp)) ; this%t_ref24_patch (:) = nan allocate(this%t_veg24_patch (begp:endp)) ; this%t_veg24_patch (:) = nan allocate(this%t_veg240_patch (begp:endp)) ; this%t_veg240_patch (:) = nan allocate(this%gdd0_patch (begp:endp)) ; this%gdd0_patch (:) = spval @@ -456,6 +458,7 @@ subroutine InitHistory(this, bounds, is_simple_buildtemp, is_prog_buildtemp ) else active = "inactive" end if + this%t_a10_patch(begp:endp) = spval call hist_addfld1d (fname='T10', units='K', & avgflag='A', long_name='10-day running mean of 2-m temperature', & @@ -573,6 +576,11 @@ subroutine InitHistory(this, bounds, is_simple_buildtemp, is_prog_buildtemp ) ! Accumulated quantities + this%t_ref24_patch(begp:endp) = spval + call hist_addfld1d (fname='TREF24', units='K', & + avgflag='A', long_name='2 m air temperature (last 24hrs)', & + ptr_patch=this%t_ref24_patch, default='inactive') + this%t_veg24_patch(begp:endp) = spval call hist_addfld1d (fname='TV24', units='K', & avgflag='A', long_name='vegetation temperature (last 24hrs)', & @@ -934,6 +942,10 @@ subroutine Restart(this, bounds, ncid, flag, is_simple_buildtemp, is_prog_buildt long_name='Urban 2m height surface air temperature', units='K', & interpinic_flag='interp', readvar=readvar, data=this%t_ref2m_u_patch) + call restartvar(ncid=ncid, flag=flag, varname='T_REF24', xtype=ncd_double, & + dim1name='pft', & + long_name='daily average 2 m height surface air temperature (K)', units='K', & + interpinic_flag='interp', readvar=readvar, data=this%t_ref24_patch) call restartvar(ncid=ncid, flag=flag, varname='T_REF2M_MIN', xtype=ncd_double, & dim1name='pft', & @@ -1132,6 +1144,10 @@ subroutine InitAccBuffer (this, bounds) dtime = get_step_size() + call init_accum_field (name='T_REF24', units='K', & + desc='24hr average of 2 m air temperature', accum_type='timeavg', accum_period=-1, & + subgrid_type='pft', numlev=1, init_value=0._r8) + this%t_veg24_patch(bounds%begp:bounds%endp) = spval call init_accum_field (name='T_VEG24', units='K', & desc='24hr average of vegetation temperature', accum_type='runmean', accum_period=-1, & @@ -1160,6 +1176,10 @@ subroutine InitAccBuffer (this, bounds) subgrid_type='pft', numlev=1,init_value=SHR_CONST_TKFRZ+20._r8) if ( use_crop )then + call init_accum_field (name='T24', units='K', & + desc='24-hour running mean of 2-m temperature', accum_type='runmean', accum_period=-1, & + subgrid_type='pft', numlev=1,init_value=SHR_CONST_TKFRZ+20._r8) + call init_accum_field (name='TDM10', units='K', & desc='10-day running mean of min 2-m temperature', accum_type='runmean', accum_period=-10, & subgrid_type='pft', numlev=1, init_value=SHR_CONST_TKFRZ) @@ -1235,6 +1255,9 @@ subroutine InitAccVars(this, bounds) ! Determine time step nstep = get_nstep() + call extract_accum_field ('T_REF24', rbufslp, nstep) + this%t_ref24_patch(begp:endp) = rbufslp(begp:endp) + call extract_accum_field ('T_VEG24', rbufslp, nstep) this%t_veg24_patch(begp:endp) = rbufslp(begp:endp) @@ -1245,6 +1268,7 @@ subroutine InitAccVars(this, bounds) this%t_a10_patch(begp:endp) = rbufslp(begp:endp) if (use_crop) then + call extract_accum_field ('TDM10', rbufslp, nstep) this%t_a10min_patch(begp:endp)= rbufslp(begp:endp) @@ -1331,7 +1355,7 @@ subroutine UpdateAccVars (this, bounds) call endrun(msg=errMsg(sourcefile, __LINE__)) endif - ! Accumulate and extract T_VEG24 & T_VEG240 + ! Accumulate and extract T_VEG24 & T_VEG240 do p = begp,endp rbufslp(p) = this%t_veg_patch(p) end do @@ -1340,6 +1364,7 @@ subroutine UpdateAccVars (this, bounds) call update_accum_field ('T_VEG240', rbufslp , nstep) call extract_accum_field ('T_VEG240', this%t_veg240_patch , nstep) + ! Accumulate and extract TREFAV - hourly average 2m air temperature ! Used to compute maximum and minimum of hourly averaged 2m reference ! temperature over a day. Note that "spval" is returned by the call to @@ -1429,6 +1454,11 @@ subroutine UpdateAccVars (this, bounds) call extract_accum_field ('T10', this%t_a10_patch, nstep) if ( use_crop )then + ! Accumulate and extract T_REF24 + + call update_accum_field ('T_REF24' , this%t_ref2m_patch, nstep) + call extract_accum_field ('T_REF24' , this%t_ref24_patch , nstep) + ! Accumulate and extract TDM10 do p = begp,endp diff --git a/src/clm5/main/pftconMod.F90 b/src/clm5/main/pftconMod.F90 index 0efa2053eb..b1a3c14c5c 100644 --- a/src/clm5/main/pftconMod.F90 +++ b/src/clm5/main/pftconMod.F90 @@ -163,9 +163,11 @@ module pftconMod real(r8), allocatable :: bfact (:) ! parameter used in CNAllocation real(r8), allocatable :: aleaff (:) ! parameter used in CNAllocation real(r8), allocatable :: arootf (:) ! parameter used in CNAllocation + real(r8), allocatable :: arootf2 (:) ! parameter used in CNAllocation real(r8), allocatable :: astemf (:) ! parameter used in CNAllocation real(r8), allocatable :: arooti (:) ! parameter used in CNAllocation real(r8), allocatable :: fleafi (:) ! parameter used in CNAllocation + real(r8), allocatable :: aleafstor (:) ! parameter used in CNAllocation real(r8), allocatable :: allconsl (:) ! parameter used in CNAllocation real(r8), allocatable :: allconss (:) ! parameter used in CNAllocation real(r8), allocatable :: ztopmx (:) ! parameter used in CNVegStructUpdate @@ -175,13 +177,21 @@ module pftconMod real(r8), allocatable :: lfemerg (:) ! parameter used in CNPhenology real(r8), allocatable :: grnfill (:) ! parameter used in CNPhenology integer , allocatable :: mxmat (:) ! parameter used in CNPhenology + real(r8), allocatable :: transplant (:) ! parameter used in CNPhenology (added by O.Dombrowski) + real(r8), allocatable :: lfmat (:) ! parameter used in CNPhenology (added by O.Dombrowski) + real(r8), allocatable :: grnrp (:) ! parameter used in CNPhenology (added by O.Dombrowski) + real(r8), allocatable :: crequ (:) ! Chill requirements for fruit tree crops (added by O.Dombrowski) + real(r8), allocatable :: crit_temp (:) ! Critical temperature to initiate leaf offset for fruit tree crops (added by O.Dombrowski) + real(r8), allocatable :: ndays_stor (:) ! Length of period for storage growth for fruit tree crops (added by O.Dombrowski) real(r8), allocatable :: mbbopt (:) ! Ball-Berry equation slope used in Photosynthesis real(r8), allocatable :: medlynslope (:) ! Medlyn equation slope used in Photosynthesis real(r8), allocatable :: medlynintercept(:) ! Medlyn equation intercept used in Photosynthesis integer , allocatable :: mnNHplantdate (:) ! minimum planting date for NorthHemisphere (YYYYMMDD) integer , allocatable :: mxNHplantdate (:) ! maximum planting date for NorthHemisphere (YYYYMMDD) + integer , allocatable :: mxNHharvdate (:) ! maximum harvest date for NorthHemishere (YYYYMMDD) (added by O.Dombrowski) integer , allocatable :: mnSHplantdate (:) ! minimum planting date for SouthHemisphere (YYYYMMDD) integer , allocatable :: mxSHplantdate (:) ! maximum planting date for SouthHemisphere (YYYYMMDD) + integer , allocatable :: mxSHharvdate (:) ! maximum harvest date for SouthHemishere (YYYYMMDD) (added by O.Dombrowski) real(r8), allocatable :: planttemp (:) ! planting temperature used in CNPhenology (K) real(r8), allocatable :: minplanttemp (:) ! mininum planting temperature used in CNPhenology (K) real(r8), allocatable :: froot_leaf (:) ! allocation parameter: new fine root C per new leaf C (gC/gC) @@ -200,11 +210,15 @@ module pftconMod real(r8), allocatable :: evergreen (:) ! binary flag for evergreen leaf habit (0 or 1) real(r8), allocatable :: stress_decid (:) ! binary flag for stress-deciduous leaf habit (0 or 1) real(r8), allocatable :: season_decid (:) ! binary flag for seasonal-deciduous leaf habit (0 or 1) + real(r8), allocatable :: perennial (:) ! binary flag for perennial crop phenology (0 or 1) (added by O.Dombrowski) + real(r8), allocatable :: mulch_pruning (:) ! binary flag for mulching or exporting pruning material (0 or 1) (added by O.Dombrowski) real(r8), allocatable :: pconv (:) ! proportion of deadstem to conversion flux real(r8), allocatable :: pprod10 (:) ! proportion of deadstem to 10-yr product pool real(r8), allocatable :: pprod100 (:) ! proportion of deadstem to 100-yr product pool real(r8), allocatable :: pprodharv10 (:) ! harvest mortality proportion of deadstem to 10-yr pool - + real(r8), allocatable :: prune_fr (:) ! fraction of deadstem that is pruned (added by O.Dombrowski) + real(r8), allocatable :: nstem (:) ! stem density (#/m2) (added by O.Dombrowski) + real(r8), allocatable :: taper (:) ! tapering ratio of height:radius_breast_height (added by O.Dombrowski) ! pft paraemeters for fire code real(r8), allocatable :: cc_leaf (:) real(r8), allocatable :: cc_lstem (:) @@ -372,9 +386,11 @@ subroutine InitAllocate (this) allocate( this%bfact (0:mxpft) ) allocate( this%aleaff (0:mxpft) ) allocate( this%arootf (0:mxpft) ) + allocate( this%arootf2 (0:mxpft) ) allocate( this%astemf (0:mxpft) ) allocate( this%arooti (0:mxpft) ) allocate( this%fleafi (0:mxpft) ) + allocate( this%aleafstor (0:mxpft) ) allocate( this%allconsl (0:mxpft) ) allocate( this%allconss (0:mxpft) ) allocate( this%ztopmx (0:mxpft) ) @@ -386,11 +402,19 @@ subroutine InitAllocate (this) allocate( this%mbbopt (0:mxpft) ) allocate( this%medlynslope (0:mxpft) ) allocate( this%medlynintercept(0:mxpft) ) - allocate( this%mxmat (0:mxpft) ) + allocate( this%mxmat (0:mxpft) ) + allocate( this%transplant (0:mxpft) ) + allocate( this%lfmat (0:mxpft) ) + allocate( this%grnrp (0:mxpft) ) + allocate( this%crequ (0:mxpft) ) + allocate( this%crit_temp (0:mxpft) ) + allocate( this%ndays_stor (0:mxpft) ) allocate( this%mnNHplantdate (0:mxpft) ) allocate( this%mxNHplantdate (0:mxpft) ) + allocate( this%mxNHharvdate (0:mxpft) ) allocate( this%mnSHplantdate (0:mxpft) ) allocate( this%mxSHplantdate (0:mxpft) ) + allocate( this%mxSHharvdate (0:mxpft) ) allocate( this%planttemp (0:mxpft) ) allocate( this%minplanttemp (0:mxpft) ) allocate( this%froot_leaf (0:mxpft) ) @@ -409,6 +433,8 @@ subroutine InitAllocate (this) allocate( this%evergreen (0:mxpft) ) allocate( this%stress_decid (0:mxpft) ) allocate( this%season_decid (0:mxpft) ) + allocate( this%perennial (0:mxpft) ) + allocate( this%mulch_pruning (0:mxpft) ) allocate( this%dwood (0:mxpft) ) allocate( this%root_density (0:mxpft) ) allocate( this%root_radius (0:mxpft) ) @@ -416,6 +442,9 @@ subroutine InitAllocate (this) allocate( this%pprod10 (0:mxpft) ) allocate( this%pprod100 (0:mxpft) ) allocate( this%pprodharv10 (0:mxpft) ) + allocate( this%prune_fr (0:mxpft) ) + allocate( this%nstem (0:mxpft) ) + allocate( this%taper (0:mxpft) ) allocate( this%cc_leaf (0:mxpft) ) allocate( this%cc_lstem (0:mxpft) ) allocate( this%cc_dstem (0:mxpft) ) @@ -739,6 +768,12 @@ subroutine InitRead(this) call ncd_io('season_decid', this%season_decid, 'read', ncid, readvar=readv, posNOTonfile=.true.) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + call ncd_io('perennial', this%perennial, 'read', ncid, readvar=readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('mulch_pruning', this%mulch_pruning, 'read', ncid, readvar=readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + call ncd_io('pftpar20', this%pftpar20, 'read', ncid, readvar=readv, posNOTonfile=.true.) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) @@ -849,6 +884,9 @@ subroutine InitRead(this) call ncd_io('arootf', this%arootf, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('arootf2', this%arootf2, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) call ncd_io('astemf', this%astemf, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) @@ -859,6 +897,9 @@ subroutine InitRead(this) call ncd_io('fleafi', this%fleafi, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + call ncd_io('aleafstor', this%aleafstor, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + call ncd_io('allconsl', this%allconsl, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) @@ -906,6 +947,33 @@ subroutine InitRead(this) call ncd_io('mxmat', this%mxmat, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + call ncd_io('transplant', this%transplant, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('lfmat', this%lfmat, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('grnrp', this%grnrp, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('crequ', this%crequ, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('crit_temp', this%crit_temp, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('ndays_stor', this%ndays_stor, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('prune_fr', this%prune_fr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('nstem', this%nstem, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('taper', this%taper, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + call ncd_io('cc_leaf', this% cc_leaf, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) @@ -960,6 +1028,12 @@ subroutine InitRead(this) call ncd_io('max_NH_planting_date', this%mxNHplantdate, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + call ncd_io('max_NH_harvest_date', this%mxNHharvdate, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('max_SH_harvest_date', this%mxSHharvdate, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + call ncd_io('max_SH_planting_date', this%mxSHplantdate, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) @@ -1287,9 +1361,11 @@ subroutine Clean(this) deallocate( this%bfact) deallocate( this%aleaff) deallocate( this%arootf) + deallocate( this%arootf2) deallocate( this%astemf) deallocate( this%arooti) deallocate( this%fleafi) + deallocate( this%aleafstor) deallocate( this%allconsl) deallocate( this%allconss) deallocate( this%ztopmx) @@ -1302,10 +1378,21 @@ subroutine Clean(this) deallocate( this%medlynslope) deallocate( this%medlynintercept) deallocate( this%mxmat) + deallocate( this%transplant) + deallocate( this%lfmat) + deallocate( this%grnrp) + deallocate( this%crequ) + deallocate( this%crit_temp) + deallocate( this%ndays_stor) + deallocate( this%prune_fr) + deallocate( this%nstem) + deallocate( this%taper) deallocate( this%mnNHplantdate) deallocate( this%mxNHplantdate) + deallocate( this%mxNHharvdate) deallocate( this%mnSHplantdate) deallocate( this%mxSHplantdate) + deallocate( this%mxSHharvdate) deallocate( this%planttemp) deallocate( this%minplanttemp) deallocate( this%froot_leaf) @@ -1324,6 +1411,8 @@ subroutine Clean(this) deallocate( this%evergreen) deallocate( this%stress_decid) deallocate( this%season_decid) + deallocate( this%perennial) + deallocate( this%mulch_pruning) deallocate( this%dwood) deallocate( this%root_density) deallocate( this%root_radius)