From 1bcfffbd548ea499c71c9c6b45e0e344e9b105ab Mon Sep 17 00:00:00 2001 From: Olga Dombrowski Date: Tue, 8 Feb 2022 20:03:30 +0100 Subject: [PATCH 01/13] Implement CLM-FruitTree sub-model for deciduous fruit trees --- src/clm5/biogeochem/CNCIsoFluxMod.F90 | 17 +- src/clm5/biogeochem/CNCStateUpdate1Mod.F90 | 137 +- src/clm5/biogeochem/CNDriverMod.F90 | 9 +- src/clm5/biogeochem/CNFUNMod.F90 | 8 +- src/clm5/biogeochem/CNGRespMod.F90 | 30 +- src/clm5/biogeochem/CNGapMortalityMod.F90 | 5 +- src/clm5/biogeochem/CNMRespMod.F90 | 5 +- src/clm5/biogeochem/CNNStateUpdate1Mod.F90 | 100 +- src/clm5/biogeochem/CNPhenologyMod.F90 | 2181 ++++++++++++----- src/clm5/biogeochem/CNVegCarbonFluxType.F90 | 67 +- src/clm5/biogeochem/CNVegCarbonStateType.F90 | 54 +- src/clm5/biogeochem/CNVegNitrogenFluxType.F90 | 41 +- .../biogeochem/CNVegNitrogenStateType.F90 | 28 + src/clm5/biogeochem/CNVegStateType.F90 | 162 +- src/clm5/biogeochem/CNVegStructUpdateMod.F90 | 15 +- src/clm5/biogeochem/CropType.F90 | 11 +- .../NutrientCompetitionFlexibleCNMod.F90 | 503 +++- src/clm5/biogeochem/dynHarvestMod.F90 | 9 +- src/clm5/biogeophys/TemperatureType.F90 | 32 +- src/clm5/main/pftconMod.F90 | 81 +- 20 files changed, 2677 insertions(+), 818 deletions(-) diff --git a/src/clm5/biogeochem/CNCIsoFluxMod.F90 b/src/clm5/biogeochem/CNCIsoFluxMod.F90 index a92ab44e47..2a5a745ef1 100644 --- a/src/clm5/biogeochem/CNCIsoFluxMod.F90 +++ b/src/clm5/biogeochem/CNCIsoFluxMod.F90 @@ -18,7 +18,7 @@ module CNCIsoFluxMod use SoilBiogeochemCarbonFluxType , only : soilbiogeochem_carbonflux_type use ColumnType , only : col use PatchType , only : patch - use clm_varctl , only : use_crop + use clm_varctl , only : use_crop, iulog use clm_varctl , only : use_grainproduct ! implicit none @@ -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 diff --git a/src/clm5/biogeochem/CNCStateUpdate1Mod.F90 b/src/clm5/biogeochem/CNCStateUpdate1Mod.F90 index e1da2f354f..8f579f7e97 100644 --- a/src/clm5/biogeochem/CNCStateUpdate1Mod.F90 +++ b/src/clm5/biogeochem/CNCStateUpdate1Mod.F90 @@ -83,6 +83,7 @@ subroutine CStateUpdateDynPatch(bounds, num_soilc_with_inactive, filter_soilc_wi do g = bounds%begg, bounds%endg cs_veg%seedc_grc(g) = cs_veg%seedc_grc(g) - cf_veg%dwt_seedc_to_leaf_grc(g) * dt cs_veg%seedc_grc(g) = cs_veg%seedc_grc(g) - cf_veg%dwt_seedc_to_deadstem_grc(g) * dt + write(iulog,*) 'dwt_seedc is calculated',cs_veg%seedc_grc(g) end do end if @@ -173,7 +174,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 +270,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 +293,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 +324,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 +398,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 +436,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 +454,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 +473,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,17 +503,27 @@ 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 + write(iulog,*) 'entering harvdate < 999 in CNCStateUpdate1Mod, date is:', harvdate(p) ! TODO (mv, 11-02-2014) the following lines are why the cf_veg is ! an intent(inout) ! fluxes should not be updated in this module - not sure where @@ -491,6 +550,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 +560,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/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..938e552a77 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,10 @@ 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, & - leaf_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full), & - froot_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full)) + call CNLitterToColumn(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & + cnveg_state_inst,soilbiogeochem_state_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & + cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, leaf_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)) else call endrun( 'bad phase' ) end if @@ -525,7 +533,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 +546,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 +714,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 +795,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 +805,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 +1423,682 @@ 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 (added 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) (added by O.Dombrowski) + harvest_flag => cnveg_state_inst%harvest_flag_patch , & ! Output: [real(r8) (:) ] harvest flag (added by O.Dombrowski) + prune_flag => cnveg_state_inst%prune_flag_patch , & ! Output: [real(r8) (:) ] pruning flag for perennials (added 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 + 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 + 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) + ! 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) + write(iulog,*) 'deadstem C and N in display and storage are:',deadstemc_soy(p),deadstemn_soy(p),deadstemc_storage_soy(p),deadstemn_storage_soy(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/end of chill period (chill_flag=1), + ! no chill period (chill_flag=0) + ! only valid for NH at the moment! + if (kmo == 11 .and. kda == 1) then + chill_flag(p) = 1._r8 + end if + if (kmo == 5 .and. kda == 1 .and. chill_flag(p) == 1._r8) then + chill_flag(p) = 0._r8 + 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, similar to the initiation for + ! deciduous trees, initial gC m-2 is assigned to + ! leaf, fine root and deadstem + 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)) + crop_seedc_to_leaf(c) = crop_seedc_to_leaf(c) + leafc_xfer(p)/dt + crop_seedc_to_froot(c) = crop_seedc_to_froot(c) + frootc_xfer(p)/dt + crop_seedn_to_leaf(c) = crop_seedn_to_leaf(c) + leafn_xfer(p)/dt + crop_seedn_to_froot(c) = crop_seedn_to_froot(c) + frootn_xfer(p)/dt + !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)) + crop_seedc_to_deadstem(c) = crop_seedc_to_deadstem(c) + deadstemc_xfer(p)/dt + crop_seedn_to_deadstem(c) = crop_seedn_to_deadstem(c) + deadstemn_xfer(p)/dt + 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 + 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: + 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 + write(iulog,*) 'WARNING: croplive is set to false and harvdate to jday:',harvdate(p) + crop_seedc_to_leaf(c) = crop_seedc_to_leaf(c) - leafc_xfer(p)/dt + crop_seedc_to_froot(c) = crop_seedc_to_froot(c) - frootc_xfer(p)/dt + crop_seedn_to_leaf(c) = crop_seedn_to_leaf(c) - leafn_xfer(p)/dt + crop_seedn_to_froot(c) = crop_seedn_to_froot(c) - 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(c) = crop_seedc_to_deadstem(c) - deadstemc_xfer(p)/dt + crop_seedn_to_deadstem(c) = crop_seedn_to_deadstem(c) - 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 + 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(c) = crop_seedc_to_froot(c) - frootc_xfer(p)/dt + crop_seedn_to_leaf(p) = crop_seedn_to_leaf(p) - leafn_xfer(p)/dt + crop_seedn_to_froot(c) = crop_seedn_to_froot(c) - 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(c) = crop_seedc_to_deadstem(c) - deadstemc_xfer(p)/dt + crop_seedn_to_deadstem(c) = crop_seedn_to_deadstem(c) - 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 + 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(c) = crop_seedc_to_froot(c) - frootc_xfer(p)/dt + crop_seedn_to_leaf(p) = crop_seedn_to_leaf(p) - leafn_xfer(p)/dt + crop_seedn_to_froot(c) = crop_seedn_to_froot(c) - 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(c) = crop_seedc_to_deadstem(c) - deadstemc_xfer(p)/dt + crop_seedn_to_deadstem(c) = crop_seedn_to_deadstem(c) - 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 +2166,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 +2197,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 +2227,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 + 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 - ! 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 + ! --------------------------------- + ! from AgroIBIS subroutine planting + ! --------------------------------- - if (.not. croplive(p)) then - cropplant(p) = .false. - idop(p) = NOT_Planted + ! 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 - ! 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 + ! initialize other variables that are calculated for crops + ! on an annual basis in cropresidue subroutine - 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 + if ( jday == jdayyrstart(h) .and. mcsec == 0 )then - 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 + ! 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 - ! 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 + ! 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 (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 - - 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 - - ! days past planting may determine harvest - - if (jday >= idop(p)) then - idpp = jday - idop(p) - else - idpp = int(dayspyr) + jday - idop(p) - end if - - ! 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 + 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 +2733,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 +2743,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 +3049,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 +3058,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 ! ! !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 +3074,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) + 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 +3111,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 +3163,105 @@ 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) + !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 + ! send grainc to food product pool, no replenishment of + ! seedpool needed for perennial crops + grainc_to_food(p) = t1 * grainc(p) + cpool_to_grainc(p) + grainn_to_food(p) = t1 * grainn(p) + npool_to_grainn(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 +3270,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 +3282,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 +3318,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 +3352,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 +3376,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 +3386,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,7 +3399,65 @@ 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 (may vary between 25-40 yrs) + ! (O.Dombrowski) + if (offset2_flag(p) == 1._r8 .and. perennial(ivt(p)) == 1._r8) then + 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 if ! end orchard rotation end do ! end patch loop end associate @@ -2855,28 +3758,35 @@ 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, num_soilp, filter_soilp, & + cnveg_state_inst,soilbiogeochem_state_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & + cnveg_carbonstate_inst, cnveg_nitrogenstate_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 + use dynHarvestMod , only: CNHarvestPftToColumn ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds integer , intent(in) :: num_soilc ! number of soil columns in filter integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_soilp ! number of soil patches in filter + integer , intent(in) :: filter_soilp(:) ! patch filter for soil points type(cnveg_state_type) , intent(in) :: cnveg_state_inst type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst + type(cnveg_carbonstate_type) , intent(in) :: cnveg_carbonstate_inst + type(cnveg_nitrogenstate_type) , intent(in) :: cnveg_nitrogenstate_inst + type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_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 +3794,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 +3809,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 +3892,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 +3906,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,17 +3945,88 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & + grainn_to_food(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) end if + 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 + + ! summarize all fuxes at orchard rotation to column level (O. Dombrowski) + if ( perennial(ivt(p)) == 1._r8 .and. offset2_flag(p) == 1._r8) then + call CNHarvestPftToColumn (num_soilc, filter_soilc, & + soilbiogeochem_state_inst, CNVeg_carbonflux_inst, cnveg_nitrogenflux_inst) + end if + + end associate end subroutine CNLitterToColumn diff --git a/src/clm5/biogeochem/CNVegCarbonFluxType.F90 b/src/clm5/biogeochem/CNVegCarbonFluxType.F90 index f88c7f5e66..f27a37595d 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) + & diff --git a/src/clm5/biogeochem/CNVegCarbonStateType.F90 b/src/clm5/biogeochem/CNVegCarbonStateType.F90 index 1d568dc60d..6d08a306ee 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.1_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 .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 @@ -2367,6 +2405,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 +2520,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) + & @@ -2514,13 +2553,11 @@ subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & 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 +2600,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/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..914151581c 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', & @@ -478,6 +492,8 @@ subroutine InitCold(this, bounds, & 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 +646,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) @@ -788,6 +812,8 @@ subroutine Restart ( this, bounds, ncid, flag, leafc_patch, & 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 +902,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..3a828fde0c 100644 --- a/src/clm5/biogeochem/CNVegStructUpdateMod.F90 +++ b/src/clm5/biogeochem/CNVegStructUpdateMod.F90 @@ -90,6 +90,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 (-) @@ -114,7 +115,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*** @@ -132,7 +133,7 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & ! constant allometric parameters taper = 200._r8 stocking = 1000._r8 - + ! convert from stems/ha -> stems/m^2 stocking = stocking / 10000._r8 @@ -182,6 +183,15 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & ! if shrubs have a squat taper if (ivt(p) >= nbrdlf_evr_shrub .and. ivt(p) <= nbrdlf_dcd_brl_shrub) then taper = 10._r8 + ! adapt taper and stocking to orchards (added by O.Dombrowski) + else if (perennial(ivt(p)) == 1._r8) then + taper = 120._r8 + stocking = 3333._r8/10000._r8 + 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 ! otherwise have a tall taper else taper = 200._r8 @@ -217,7 +227,6 @@ 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 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..09d7ce6d70 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 @@ -630,7 +631,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..21147d111f 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,13 @@ 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) ! pft paraemeters for fire code real(r8), allocatable :: cc_leaf (:) real(r8), allocatable :: cc_lstem (:) @@ -372,9 +384,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 +400,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 +431,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 +440,7 @@ 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%cc_leaf (0:mxpft) ) allocate( this%cc_lstem (0:mxpft) ) allocate( this%cc_dstem (0:mxpft) ) @@ -739,6 +764,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 +880,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 +893,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 +943,27 @@ 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('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 +1018,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 +1351,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 +1368,19 @@ 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%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 +1399,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) From 3fe2de2d87527653207bd36c8936a76d81363066 Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Wed, 9 Feb 2022 15:04:38 +0100 Subject: [PATCH 02/13] Update README --- clm5_params.c171117__FruitTree.nc | Bin 0 -> 221240 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 clm5_params.c171117__FruitTree.nc diff --git a/clm5_params.c171117__FruitTree.nc b/clm5_params.c171117__FruitTree.nc new file mode 100644 index 0000000000000000000000000000000000000000..dc7b951c49cbfe76b81c1d18437e4097a959ac7d GIT binary patch literal 221240 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

OdA8TDCOCw8)7 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

{CL18 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 literal 0 HcmV?d00001 From 50fddc1208646b6faada5d8dcc9a314b7ea32081 Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Mon, 14 Mar 2022 13:15:11 +0100 Subject: [PATCH 03/13] Correct orchard rotation/replanting trigger --- src/clm5/biogeochem/CNPhenologyMod.F90 | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/clm5/biogeochem/CNPhenologyMod.F90 b/src/clm5/biogeochem/CNPhenologyMod.F90 index 938e552a77..2d0ab5a6ae 100644 --- a/src/clm5/biogeochem/CNPhenologyMod.F90 +++ b/src/clm5/biogeochem/CNPhenologyMod.F90 @@ -1658,6 +1658,13 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & 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 @@ -3059,7 +3066,7 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & use pftconMod , only : npcropmin use CNSharedParamsMod, only : use_fun use clm_varctl , only : CNratio_floating - use clm_time_manager , only : get_curr_date, get_curr_calday, get_days_per_year + 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 @@ -3101,7 +3108,7 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & 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 @@ -3404,8 +3411,17 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & ! lifespan is reached (may vary between 25-40 yrs) ! (O.Dombrowski) if (offset2_flag(p) == 1._r8 .and. perennial(ivt(p)) == 1._r8) then - t1 = 1.0_r8 / dt - + + ! 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 = .false. + t1 = 1.0_r8 / dt + else + croplive = .true. + t1 = 0._r8 + end if ! clear-cut carbon fluxes, remove all displayed/storage/transfer pools From 99dca29bcfa1c16f0aeee125b077a11c04e08d28 Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Thu, 5 May 2022 12:47:49 +0200 Subject: [PATCH 04/13] Make taper and nstem PFT parameters to be set in parameter file --- src/clm5/biogeochem/CNVegStructUpdateMod.F90 | 39 ++++++-------------- src/clm5/main/pftconMod.F90 | 12 ++++++ 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/clm5/biogeochem/CNVegStructUpdateMod.F90 b/src/clm5/biogeochem/CNVegStructUpdateMod.F90 index 3a828fde0c..3103882964 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 @@ -98,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 @@ -130,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) @@ -178,34 +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 - ! adapt taper and stocking to orchards (added by O.Dombrowski) - else if (perennial(ivt(p)) == 1._r8) then - taper = 120._r8 - stocking = 3333._r8/10000._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 - ! otherwise have a tall taper - else - taper = 200._r8 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 @@ -214,11 +197,11 @@ 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) + 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) else - htop(p) = ((3._r8 * deadstemc(p) * taper * taper)/ & - (SHR_CONST_PI * stocking * dwood(ivt(p))))**(1._r8/3._r8) + 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 endif diff --git a/src/clm5/main/pftconMod.F90 b/src/clm5/main/pftconMod.F90 index 21147d111f..b1a3c14c5c 100644 --- a/src/clm5/main/pftconMod.F90 +++ b/src/clm5/main/pftconMod.F90 @@ -217,6 +217,8 @@ module pftconMod 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 (:) @@ -441,6 +443,8 @@ subroutine InitAllocate (this) 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) ) @@ -964,6 +968,12 @@ subroutine InitRead(this) 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__)) @@ -1375,6 +1385,8 @@ subroutine Clean(this) 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) From 3eef0a65bb9e1585381be3f6bfadd7147bcdbb31 Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Thu, 5 May 2022 15:21:56 +0200 Subject: [PATCH 05/13] Update parameter file with taper and nstem parameters --- clm5_params.c171117__FruitTree.nc | Bin 221240 -> 222872 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/clm5_params.c171117__FruitTree.nc b/clm5_params.c171117__FruitTree.nc index dc7b951c49cbfe76b81c1d18437e4097a959ac7d..6e9585bc00ab09b59e784fa0c9cb6836ddd9b0b4 100644 GIT binary patch delta 2851 zcmb7GeRR|170!M6Xqprjp_G6fq_ismN(rS%V4b9sL4b9?1_dH3kTKw7({bVkp2(bbP^IqlctAdL*TKbnq;XfK+ybVmH$fub?=H*qHh{aD7B6@wq8TjFj6w`KgN z8K=`3KM7&y_vyH}XGFm`IxFs(&_9k2ik=`^$CFDuFhHZDyXpr>OV9A2mU&@qQDC8zs& zm#X~Rxu`3nJly#qJtM{|B})OfOPwL}98zIh>-a{q?LVTQt26rtto3&HfRdvhr%fVD z0srH4S7a&So=f{gb|W+6*=4 zWOq5$CdaU|7t!tQXf8(@C+?fyN@* zAy&nZ@+8|=ThS(CaRl?0u-#@xWC_<~v%vZk*I*B$SH?0Ed=@@EWoDEu<TAhE^QT+9>XRlt)#C3+L6f#Ye}u0`x= zj_lRJvxY13awZ!cNb(xwh*hvRal}t-WD{N^%q2X7UK6gD@U(c%Fxkna@>wxQL*Nng=HSIIQ@w;(8EKm*HqrhCwbp7p#wtiaYP#-kpjSJM^sv0f&X zR9#VB>BfhJJouw)Xq9Mpz*)oc9*;p=%ezllaazVx5y?_VV@aGbquR;mD;Sb`oV1Zd zFf5h1WEsy6hOeHto-@JV=8Ni_89i<$c+P@`4NUx;6-68QXrGTDwvp}Uqi}9wzwq>#UfhV^s724-`Yganjp5u^RS@1m1_RA$m z-@+PPjUupx{jbKLYviH4+Ku-bd9<(gqVWYDimUxldii@;0bc@@lJb`{oJ3dy?N)BW zH6LzorOo1o0@iIT*85iUZsWWA{eA>qG!pmC($3$|V@`a6-_jxy|Is4k=RI*h zjJug#oIALiNyG!l-y_@G(7uO{P`m@iy_#4QVfPj0VIKXhd17{N03}R@rWbbH9uh^zCN}A6l{V0OQvY zWWCBL%;=PHa0n{`+`A+r`U5;+NhUPC#`YvLat_LC3&M=aNmgb#$W>Pg+ccVlz(q>N z{?}=xNGd_!>nu-_1J#FEj%2=h4l|}$(SDeklZHol^R1U{Np^zWBlkn&f}4;MCV(4m8NSF6l$FHbpu!FgSTiRE_6_l80SOE z36?iQftC}TGeZg8NuG)f4I(G`8pzN}ZKo)gM5Z6n)0`ulABVTuFVwLKmVdVpa#bLoDzdy|nWkQjwU;ukt0jAPW7k{(-&{^OUf5@qwM+ zh?L88Mr}^Klj~fyF6V%7b1%~vXs+taHf%R2 zD|hM&*-%-#PUo__E9-Q16*@}$FxuM=x>MFO_yKMtT*jJG`Wstp14pm$4 zF0c76)UcH0yw;VK*Vb3MpG9aIr4G)VR+9(+t29}Z>9%VkBxxc-??=cZl4nBYLrh5c`+V!v7hWpt~o6nz?@+7hHOO+xTx$_Oj6b E0CJ?}H~;_u delta 2593 zcmXw5eRPxM74LnZkTj+1AVTD;p~SU77YcM3u}DC$5jzOuD-$s32PM!_LK{oO3hxjl zW2g~oe}NSiJ}i+Hs91Re7R)Mk5s?#}AK3;jGLB@2syUu|)-4>}eZ&0gci!i@_qq4} z?(ezJ>;GU_C_GH+qPIrSJ?I`mpAL=YW@Kb!R$%UUnuWh;X}kEyD=)i;_LBG{1BsDz zS^bHMO|mL#>+#JE8R$sXzeDVB$_1D#V|~!LqcuBrODJP)Ml)nqM!x+Q#ebt6+4R*v_boG z1syn+Mkh*)v_q&}2pMUwPN>bE@*~g{N4t_dzv{$yWR2@H84uL$Z~oY4^E| zTJ%k4gB&lKXHb*K@u7bPADH8Zr-ZhNoB#$&II)}{{J)^9;-`8zXHt(C;YZQ^OxuV6 zKE9t$X+{K<+N$f;R@8vrxqtDOJmY}agBrOEdy(Q53C74ExCj(Ui;h z577;g?}vL19T4~BBG*jMivlnFW>(7N43y60^&$^qbD1P#60UjlxtQjJ^1?)lWNGDSIxs%9guPNapcWt0!&0xA&?T9Ew+A2&OU&PSL6vkA5`#(ABs7OrtY zAv!G7t|<$obF5$QZn(?Hu1Bd>EYzX@QRcJUhn9sLYq1K&k1;NhaOE*NBbE+8DyQ9I zg$vogZCPtY>8}{q zMW9{E`y0&YNTUVwm(gXh!HV4FoOE3Tq2=7qO=dK&V7tvBXjd}2i_x)?<1__PVqNMRCQ!YLQ|vS5QNi6lcr9wf4pt zD6XW3@k0gQN-2TDO2sINwn{EU8i1pU3xC!HQ#BLvf)(1eT<}W~#1-7jMAUFWEg>|o zW8tG1*-iybXmfJV{hiRS=QP_25mN9_0M-qh?qMDJHt_dRA9mI7$+52ZDiMTQ53s*P@RjR&&>&*i=+8TPW)T~5)i9RbXy~t;N9g*EH(LxdfL453pS6MfqV=rH!lo_UdTxH6F?tOd}Q&y~Qp$#HsL!?DnccA!Q1Rq>l`$)Uj#sI5=r9L6W;QC%yAfO3d4>&h;$}O2D}EA3>^RTc;XE&c zOqezb>ua2fHirJ!xD+ib_5`P(O~|@GD)P`KQP{zq8RbNF7W@g^jMpO?OA>H>arp7dxq3jME|eb*4AZ2mk9FGtUqG z8CFGJ0MRo%2J(V(@C`DO$k!v*#W4*0IK0V*h5+uo$*~PVxX#iJjiHlc3~^UHX>Y`Y zrF@U4hNuWjWtu1qA$VkNg&~YPX^cP$F~x=`bmtfgEa+5lQW%!=j728I&vO~ZPPDzn z*UT6~Q8$-u45K5B5fokE{{mxFZo9ymRvBX)TX^b_GlpA}S4){lT;v?5S>bw{iq38qpQrM!$V1X*!8D;a$>)BugKPLf`)Y{V}ns From 9e8401d629cb55ce71bf0ad3e17fd75c4e30c00b Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Sun, 22 May 2022 07:45:05 +0200 Subject: [PATCH 06/13] added references to CLM-Palm (Fan et al. 2015) --- src/clm5/biogeochem/CNPhenologyMod.F90 | 37 ++++++++++++++------------ 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/clm5/biogeochem/CNPhenologyMod.F90 b/src/clm5/biogeochem/CNPhenologyMod.F90 index 2d0ab5a6ae..7a8b9e3538 100644 --- a/src/clm5/biogeochem/CNPhenologyMod.F90 +++ b/src/clm5/biogeochem/CNPhenologyMod.F90 @@ -1530,7 +1530,7 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & 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 (added by O.Dombrowski) + 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 @@ -1551,9 +1551,9 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & 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) (added by O.Dombrowski) - harvest_flag => cnveg_state_inst%harvest_flag_patch , & ! Output: [real(r8) (:) ] harvest flag (added by O.Dombrowski) - prune_flag => cnveg_state_inst%prune_flag_patch , & ! Output: [real(r8) (:) ] pruning flag for perennials (added by O.Dombrowski) + 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 @@ -1697,7 +1697,7 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & if (kmo == 11 .and. kda == 1) then chill_flag(p) = 1._r8 end if - if (kmo == 5 .and. kda == 1 .and. chill_flag(p) == 1._r8) then + if (kmo == 7 .and. kda == 1 .and. chill_flag(p) == 1._r8) then chill_flag(p) = 0._r8 end if @@ -1727,10 +1727,10 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & yrop(p) = kyr harvdate(p) = NOT_Harvested - ! Fruit trees are usually transplanted from nursery - ! as small trees, similar to the initiation for - ! deciduous trees, initial gC m-2 is assigned to - ! leaf, fine root and deadstem + ! 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 @@ -1780,8 +1780,8 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & if (croplive(p)) then cphase(p) = 1._r8 - ! days past planting determine orchard rotation once maximum - ! lifetime is reached + ! 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 @@ -1923,7 +1923,8 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & ! 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: + ! 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 @@ -2020,7 +2021,7 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & 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 + 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 @@ -3254,7 +3255,7 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & ! 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) + !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 @@ -3408,8 +3409,8 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & 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 (may vary between 25-40 yrs) - ! (O.Dombrowski) + ! 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 @@ -3961,6 +3962,8 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, num_soilp, filter_ + 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 @@ -4036,7 +4039,7 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, num_soilp, filter_ end do - ! summarize all fuxes at orchard rotation to column level (O. Dombrowski) + ! summarize all fuxes at orchard rotation to column level (added by O. Dombrowski adapted based on CLM-Palm (Fan et al.(2015)) if ( perennial(ivt(p)) == 1._r8 .and. offset2_flag(p) == 1._r8) then call CNHarvestPftToColumn (num_soilc, filter_soilc, & soilbiogeochem_state_inst, CNVeg_carbonflux_inst, cnveg_nitrogenflux_inst) From 27db3e6049be5b10c3e78c58604e572fe35f4536 Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Mon, 30 May 2022 18:58:13 +0200 Subject: [PATCH 07/13] Bug fix in CNPhenology and CNVegStructUpdateMod, and parameter value correction --- clm5_params.c171117__FruitTree.nc | Bin 222872 -> 222872 bytes src/clm5/biogeochem/CNPhenologyMod.F90 | 29 ++++++++++++------- src/clm5/biogeochem/CNVegStructUpdateMod.F90 | 4 +++ 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/clm5_params.c171117__FruitTree.nc b/clm5_params.c171117__FruitTree.nc index 6e9585bc00ab09b59e784fa0c9cb6836ddd9b0b4..c5cf25c623d013f978f465e0ad4bcec7523e8fcb 100644 GIT binary patch delta 51 zcmbPnmUqTk-i8*&7N#xCCoTAS&VayK2Pi$A@e-rL^n! Date: Wed, 17 Aug 2022 17:11:05 +0200 Subject: [PATCH 08/13] Included harvest trigger when leaf offset starts --- src/clm5/biogeochem/CNPhenologyMod.F90 | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/clm5/biogeochem/CNPhenologyMod.F90 b/src/clm5/biogeochem/CNPhenologyMod.F90 index 9cb0a3b946..7894c2fe81 100644 --- a/src/clm5/biogeochem/CNPhenologyMod.F90 +++ b/src/clm5/biogeochem/CNPhenologyMod.F90 @@ -2042,7 +2042,7 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & 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 + if (deadstemc(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 @@ -2070,6 +2070,12 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & ! 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 + ! harvest crop if maturity has not been reached by + ! now + if (grainc(p) > 0._r8) then + harvest_flag(p) = 1._r8 + storage_flag(p) = 1._r8 + end if offset_flag(p) = 1._r8 !storage_flag(p) = 0._r8 offset_counter(p) = ndays_off * secspday From cbf5e76d52b408f51a69d25998b513534c48c736 Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Tue, 18 Oct 2022 14:55:01 +0200 Subject: [PATCH 09/13] debug planting of fruit trees, make two more CFTs active --- src/clm5/biogeochem/CNPhenologyMod.F90 | 32 +++++++++--------- src/clm5/biogeochem/CNVegCarbonFluxType.F90 | 3 +- src/clm5/biogeochem/CNVegCarbonStateType.F90 | 33 ++++++++++--------- src/clm5/biogeochem/CNVegComputeSeedMod.F90 | 4 +-- .../biogeochem/CNVegNitrogenStateType.F90 | 12 +++++-- src/clm5/biogeochem/CNVegStructUpdateMod.F90 | 18 +++++++--- src/clm5/biogeochem/CropType.F90 | 3 +- .../NutrientCompetitionFlexibleCNMod.F90 | 7 ++-- 8 files changed, 66 insertions(+), 46 deletions(-) diff --git a/src/clm5/biogeochem/CNPhenologyMod.F90 b/src/clm5/biogeochem/CNPhenologyMod.F90 index 7894c2fe81..117673da8d 100644 --- a/src/clm5/biogeochem/CNPhenologyMod.F90 +++ b/src/clm5/biogeochem/CNPhenologyMod.F90 @@ -1631,9 +1631,11 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & 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 @@ -1676,7 +1678,7 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & deadstemc_storage_soy(p) = deadstemc_storage(p) deadstemn_soy(p) = deadstemn(p) deadstemn_storage_soy(p) = deadstemn_storage(p) - write(iulog,*) 'deadstem C and N in display and storage are:',deadstemc_soy(p),deadstemn_soy(p),deadstemc_storage_soy(p),deadstemn_storage_soy(p) + end if if (season_decid(ivt(p)) == 1._r8) then @@ -1728,6 +1730,7 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & 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. @@ -1749,18 +1752,15 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & 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)) - crop_seedc_to_leaf(c) = crop_seedc_to_leaf(c) + leafc_xfer(p)/dt - crop_seedc_to_froot(c) = crop_seedc_to_froot(c) + frootc_xfer(p)/dt - crop_seedn_to_leaf(c) = crop_seedn_to_leaf(c) + leafn_xfer(p)/dt - crop_seedn_to_froot(c) = crop_seedn_to_froot(c) + frootn_xfer(p)/dt + 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)) - crop_seedc_to_deadstem(c) = crop_seedc_to_deadstem(c) + deadstemc_xfer(p)/dt - crop_seedn_to_deadstem(c) = crop_seedn_to_deadstem(c) + deadstemn_xfer(p)/dt + cropseedc_deficit(p) = cropseedc_deficit(p) - deadstemc_xfer(p) + cropseedn_deficit(p) = cropseedn_deficit(p) - deadstemn_xfer(p) end if - end if @@ -2042,7 +2042,7 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & if (harvdate(p) >= NOT_Harvested) harvdate(p) = jday croplive(p) = .false. cphase(p) = 4._r8 - if (deadstemc(p) > 0._r8) then ! plant had emerged before rotation + 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 @@ -2070,17 +2070,13 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & ! 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 - ! harvest crop if maturity has not been reached by - ! now - if (grainc(p) > 0._r8) then - harvest_flag(p) = 1._r8 - storage_flag(p) = 1._r8 - end if 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 @@ -3276,8 +3272,10 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & if (perennial(ivt(p)) == 1._r8) then if (grainc(p) > 0._r8) then t1 = 1.0_r8 / dt - ! send grainc to food product pool, no replenishment of - ! seedpool needed for perennial crops + ! 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) grainn_to_food(p) = t1 * grainn(p) + npool_to_grainn(p) diff --git a/src/clm5/biogeochem/CNVegCarbonFluxType.F90 b/src/clm5/biogeochem/CNVegCarbonFluxType.F90 index f27a37595d..681b394f3e 100644 --- a/src/clm5/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/clm5/biogeochem/CNVegCarbonFluxType.F90 @@ -4569,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 6d08a306ee..30a31a669a 100644 --- a/src/clm5/biogeochem/CNVegCarbonStateType.F90 +++ b/src/clm5/biogeochem/CNVegCarbonStateType.F90 @@ -956,14 +956,14 @@ subroutine InitCold(this, bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst this%leafc_storage_patch(p) = 0._r8 this%frootc_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 +! 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 @@ -988,7 +988,7 @@ subroutine InitCold(this, bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst if (patch%itype(p) < npcropmin)then ! (added by O.Dombrowski) this%deadstemc_patch(p) = 0.1_r8 * ratio else - this%deadstemc_patch(p) = 0.1_r8 ! (added by O.Dombrowski) + this%deadstemc_patch(p) = 0._r8 ! (added by O.Dombrowski) end if else this%deadstemc_patch(p) = 0._r8 @@ -1418,8 +1418,8 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, 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 .or. & - (lun%itype(l) == istcrop .and. pftcon%perennial(patch%itype(i)) == 1._r8)) then ! (added by O.Dombrowski) + 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 @@ -1458,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 @@ -2548,7 +2550,7 @@ 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) + & @@ -2600,6 +2602,7 @@ 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/CNVegNitrogenStateType.F90 b/src/clm5/biogeochem/CNVegNitrogenStateType.F90 index 914151581c..6d2b4d3c90 100644 --- a/src/clm5/biogeochem/CNVegNitrogenStateType.F90 +++ b/src/clm5/biogeochem/CNVegNitrogenStateType.F90 @@ -485,7 +485,11 @@ 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 @@ -805,7 +809,11 @@ 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 diff --git a/src/clm5/biogeochem/CNVegStructUpdateMod.F90 b/src/clm5/biogeochem/CNVegStructUpdateMod.F90 index 268f658906..fd6c2acfec 100644 --- a/src/clm5/biogeochem/CNVegStructUpdateMod.F90 +++ b/src/clm5/biogeochem/CNVegStructUpdateMod.F90 @@ -196,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(ivt(p)) * taper(ivt(p)))/ & - (SHR_CONST_PI * nstem(ivt(p)) * 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(ivt(p)) * taper(ivt(p)))/ & - (SHR_CONST_PI * nstem(ivt(p)) * 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 diff --git a/src/clm5/biogeochem/CropType.F90 b/src/clm5/biogeochem/CropType.F90 index da109ddff7..ac38275892 100644 --- a/src/clm5/biogeochem/CropType.F90 +++ b/src/clm5/biogeochem/CropType.F90 @@ -533,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, ncitrus, nirrig_citrus, pftcon + use pftconMod , only : nswheat, nirrig_swheat, ncitrus, nirrig_citrus, ngrapes, nirrig_grapes, pftcon use pftconMod , only : nwwheat, nirrig_wwheat use pftconMod , only : nsugarcane, nirrig_sugarcane use ColumnType , only : col @@ -589,6 +589,7 @@ subroutine CropUpdateAccVars(this, bounds, t_ref2m_patch, t_soisno_col) 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 == ngrapes) .or. (ivt == nirrig_grapes) .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 5008ea14d7..2c6eaf5aba 100644 --- a/src/clm5/biogeochem/NutrientCompetitionFlexibleCNMod.F90 +++ b/src/clm5/biogeochem/NutrientCompetitionFlexibleCNMod.F90 @@ -1329,7 +1329,7 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & use pftconMod , only : ntmp_soybean, nirrig_tmp_soybean use pftconMod , only : ntrp_soybean, nirrig_trp_soybean use clm_varcon , only : secspday, dzsoi_decomp - use clm_varctl , only : use_c13, use_c14 + use clm_varctl , only : iulog, 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,get_curr_calday @@ -1651,6 +1651,7 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & ! of amount allocated to roots over course of the growing season if (peaklai(p) == 1) then ! lai at maximum allowed + write(iulog,*) 'hit peaklai, allocation to leaf is set to small value' arepr(p) = 0._r8 aleaf(p) = 1.e-5_r8 astem(p) = astem(p) @@ -1689,7 +1690,8 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & (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 + if (peaklai(p) == 1) then + write(iulog,*) 'hit peaklai, allocation to leaf is set to small value' aleaf(p) = 1.e-5_r8 else if (aleafi(p) > aleaff(ivt(p))) then fleaf = aleafi(p) * (exp(-bfact(ivt(p))) - & @@ -1716,6 +1718,7 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & ! small value if (peaklai(p) == 1) then aleaf(p) = 1.e-5_r8 + write(iulog,*) 'hit peaklai, allocation to leaf is set to small value' 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)))) / & From 1dbab6aebefe43a4ab17d8ef9adac07501431112 Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Fri, 4 Nov 2022 14:20:11 +0100 Subject: [PATCH 10/13] Fix orchard rotation carbon balance error --- src/clm5/biogeochem/CNCIsoFluxMod.F90 | 3 +- src/clm5/biogeochem/CNCStateUpdate1Mod.F90 | 2 - src/clm5/biogeochem/CNCStateUpdate2Mod.F90 | 2 - src/clm5/biogeochem/CNPhenologyMod.F90 | 51 ++++++++++------------ src/clm5/biogeochem/dynHarvestMod.F90 | 1 - 5 files changed, 25 insertions(+), 34 deletions(-) diff --git a/src/clm5/biogeochem/CNCIsoFluxMod.F90 b/src/clm5/biogeochem/CNCIsoFluxMod.F90 index 2a5a745ef1..63d1796f46 100644 --- a/src/clm5/biogeochem/CNCIsoFluxMod.F90 +++ b/src/clm5/biogeochem/CNCIsoFluxMod.F90 @@ -18,7 +18,7 @@ module CNCIsoFluxMod use SoilBiogeochemCarbonFluxType , only : soilbiogeochem_carbonflux_type use ColumnType , only : col use PatchType , only : patch - use clm_varctl , only : use_crop, iulog + use clm_varctl , only : use_crop use clm_varctl , only : use_grainproduct ! implicit none @@ -1503,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 8f579f7e97..ed96b33192 100644 --- a/src/clm5/biogeochem/CNCStateUpdate1Mod.F90 +++ b/src/clm5/biogeochem/CNCStateUpdate1Mod.F90 @@ -83,7 +83,6 @@ subroutine CStateUpdateDynPatch(bounds, num_soilc_with_inactive, filter_soilc_wi do g = bounds%begg, bounds%endg cs_veg%seedc_grc(g) = cs_veg%seedc_grc(g) - cf_veg%dwt_seedc_to_leaf_grc(g) * dt cs_veg%seedc_grc(g) = cs_veg%seedc_grc(g) - cf_veg%dwt_seedc_to_deadstem_grc(g) * dt - write(iulog,*) 'dwt_seedc is calculated',cs_veg%seedc_grc(g) end do end if @@ -523,7 +522,6 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & 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 - write(iulog,*) 'entering harvdate < 999 in CNCStateUpdate1Mod, date is:', harvdate(p) ! TODO (mv, 11-02-2014) the following lines are why the cf_veg is ! an intent(inout) ! fluxes should not be updated in this module - not sure where 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/CNPhenologyMod.F90 b/src/clm5/biogeochem/CNPhenologyMod.F90 index 117673da8d..950172127f 100644 --- a/src/clm5/biogeochem/CNPhenologyMod.F90 +++ b/src/clm5/biogeochem/CNPhenologyMod.F90 @@ -326,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, & - crop_inst,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,soilbiogeochem_state_inst,num_soilc, filter_soilc) call CNBackgroundLitterfall(num_soilp, filter_soilp, & cnveg_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) @@ -339,9 +339,9 @@ 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, num_soilp, filter_soilp, & - cnveg_state_inst,soilbiogeochem_state_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & - cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, leaf_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full), & + 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), stem_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full)) else call endrun( 'bad phase' ) @@ -2015,7 +2015,6 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & 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 - write(iulog,*) 'WARNING: croplive is set to false and harvdate to jday:',harvdate(p) crop_seedc_to_leaf(c) = crop_seedc_to_leaf(c) - leafc_xfer(p)/dt crop_seedc_to_froot(c) = crop_seedc_to_froot(c) - frootc_xfer(p)/dt crop_seedn_to_leaf(c) = crop_seedn_to_leaf(c) - leafn_xfer(p)/dt @@ -3068,7 +3067,7 @@ end subroutine CNOnsetGrowth !----------------------------------------------------------------------- subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & - crop_inst,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, soilbiogeochem_state_inst,num_soilc,filter_soilc) ! ! !DESCRIPTION: ! Determines the flux of C and N from displayed pools to litter @@ -3079,6 +3078,7 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & use CNSharedParamsMod, only : use_fun 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 + use dynHarvestMod , only : CNHarvestPftToColumn ! ! !ARGUMENTS: integer , intent(in) :: num_soilp ! number of soil patches in filter @@ -3089,6 +3089,9 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & type(cnveg_nitrogenstate_type), intent(in) :: cnveg_nitrogenstate_inst type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst + type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst + integer , intent(in) :: num_soilc ! number of soil columns in filter + integer , intent(in) :: filter_soilc(:) ! filter for soil columns ! ! !LOCAL VARIABLES: integer :: p, c ! indices @@ -3272,12 +3275,12 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & 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 + ! 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) - grainn_to_food(p) = t1 * grainn(p) + npool_to_grainn(p) + 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 @@ -3425,15 +3428,14 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & ! 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 = .false. + croplive(p) = .false. t1 = 1.0_r8 / dt else - croplive = .true. + croplive(p) = .true. t1 = 0._r8 end if ! clear-cut carbon fluxes, remove all displayed/storage/transfer pools @@ -3487,6 +3489,13 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & ! retransn pools hrv_retransn_to_litter(p) = retransn(p) * t1 + ! summarize all fuxes at orchard rotation to column level (added by O. Dombrowski adapted based on CLM-Palm (Fan et al.(2015)) + if (.not. croplive(p)) then + call CNHarvestPftToColumn (num_soilc, filter_soilc, & + soilbiogeochem_state_inst, CNVeg_carbonflux_inst, cnveg_nitrogenflux_inst) + end if + + end if ! end orchard rotation end do ! end patch loop @@ -3788,9 +3797,9 @@ subroutine CNGrainToProductPools(bounds, num_soilp, filter_soilp, num_soilc, fil end subroutine CNGrainToProductPools !----------------------------------------------------------------------- - subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_state_inst,soilbiogeochem_state_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & - cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, leaf_prof_patch, froot_prof_patch, stem_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 @@ -3800,20 +3809,14 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, num_soilp, filter_ use clm_varpar , only : max_patch_per_col,maxpatch_pft, nlevdecomp use pftconMod , only : npcropmin use clm_varctl , only : use_grainproduct - use dynHarvestMod , only: CNHarvestPftToColumn ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds integer , intent(in) :: num_soilc ! number of soil columns in filter integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! patch filter for soil points type(cnveg_state_type) , intent(in) :: cnveg_state_inst type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst - type(cnveg_carbonstate_type) , intent(in) :: cnveg_carbonstate_inst - type(cnveg_nitrogenstate_type) , intent(in) :: cnveg_nitrogenstate_inst - type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_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:) @@ -4052,12 +4055,6 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, num_soilp, filter_ end do - ! summarize all fuxes at orchard rotation to column level (added by O. Dombrowski adapted based on CLM-Palm (Fan et al.(2015)) - if ( perennial(ivt(p)) == 1._r8 .and. offset2_flag(p) == 1._r8) then - call CNHarvestPftToColumn (num_soilc, filter_soilc, & - soilbiogeochem_state_inst, CNVeg_carbonflux_inst, cnveg_nitrogenflux_inst) - end if - end associate end subroutine CNLitterToColumn diff --git a/src/clm5/biogeochem/dynHarvestMod.F90 b/src/clm5/biogeochem/dynHarvestMod.F90 index 09d7ce6d70..800585166b 100644 --- a/src/clm5/biogeochem/dynHarvestMod.F90 +++ b/src/clm5/biogeochem/dynHarvestMod.F90 @@ -523,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) From be24b9368c624883051b1067e7176b850dfab52d Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Tue, 15 Nov 2022 10:45:18 +0100 Subject: [PATCH 11/13] added new subroutine for orchard rotation --- src/clm5/biogeochem/CNPhenologyMod.F90 | 376 ++++++++++++++++++++----- 1 file changed, 311 insertions(+), 65 deletions(-) diff --git a/src/clm5/biogeochem/CNPhenologyMod.F90 b/src/clm5/biogeochem/CNPhenologyMod.F90 index 950172127f..37011fa809 100644 --- a/src/clm5/biogeochem/CNPhenologyMod.F90 +++ b/src/clm5/biogeochem/CNPhenologyMod.F90 @@ -326,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, & - crop_inst,cnveg_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst,soilbiogeochem_state_inst,num_soilc, filter_soilc) + 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) @@ -343,6 +343,11 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & 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), 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 @@ -3067,7 +3072,7 @@ end subroutine CNOnsetGrowth !----------------------------------------------------------------------- subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & - crop_inst,cnveg_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, soilbiogeochem_state_inst,num_soilc,filter_soilc) + 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 @@ -3077,8 +3082,7 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & use pftconMod , only : npcropmin use CNSharedParamsMod, only : use_fun 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 - use dynHarvestMod , only : CNHarvestPftToColumn + 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 @@ -3089,9 +3093,6 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & type(cnveg_nitrogenstate_type), intent(in) :: cnveg_nitrogenstate_inst type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst - type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns ! ! !LOCAL VARIABLES: integer :: p, c ! indices @@ -3434,71 +3435,62 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & if (is_beg_curr_year()) then croplive(p) = .false. t1 = 1.0_r8 / dt - else - croplive(p) = .true. - t1 = 0._r8 - end if - ! 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 + ! 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 + ! 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 + ! retransn pools + hrv_retransn_to_litter(p) = retransn(p) * t1 - ! summarize all fuxes at orchard rotation to column level (added by O. Dombrowski adapted based on CLM-Palm (Fan et al.(2015)) - if (.not. croplive(p)) then - call CNHarvestPftToColumn (num_soilc, filter_soilc, & - soilbiogeochem_state_inst, CNVeg_carbonflux_inst, cnveg_nitrogenflux_inst) + else + croplive(p) = .true. end if - end if ! end orchard rotation end do ! end patch loop - + end associate end subroutine CNOffsetLitterfall @@ -4059,4 +4051,258 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & 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 From 1d07087dc2aac43d6c072621b036633aecabd4ce Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Tue, 15 Nov 2022 16:15:53 +0100 Subject: [PATCH 12/13] cleaned up some scripts, added some crop types to active CFTs --- src/clm5/biogeochem/CNBalanceCheckMod.F90 | 6 +++--- src/clm5/biogeochem/CNVegCarbonStateType.F90 | 1 - src/clm5/biogeochem/CropType.F90 | 3 +-- src/clm5/biogeochem/NutrientCompetitionFlexibleCNMod.F90 | 7 ++----- src/clm5/biogeochem/dynHarvestMod.F90 | 2 +- 5 files changed, 7 insertions(+), 12 deletions(-) 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/CNVegCarbonStateType.F90 b/src/clm5/biogeochem/CNVegCarbonStateType.F90 index 30a31a669a..08a273b338 100644 --- a/src/clm5/biogeochem/CNVegCarbonStateType.F90 +++ b/src/clm5/biogeochem/CNVegCarbonStateType.F90 @@ -2602,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/CropType.F90 b/src/clm5/biogeochem/CropType.F90 index ac38275892..da109ddff7 100644 --- a/src/clm5/biogeochem/CropType.F90 +++ b/src/clm5/biogeochem/CropType.F90 @@ -533,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, ncitrus, nirrig_citrus, ngrapes, nirrig_grapes, 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 @@ -589,7 +589,6 @@ subroutine CropUpdateAccVars(this, bounds, t_ref2m_patch, t_soisno_col) 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 == ngrapes) .or. (ivt == nirrig_grapes) .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 2c6eaf5aba..5008ea14d7 100644 --- a/src/clm5/biogeochem/NutrientCompetitionFlexibleCNMod.F90 +++ b/src/clm5/biogeochem/NutrientCompetitionFlexibleCNMod.F90 @@ -1329,7 +1329,7 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & use pftconMod , only : ntmp_soybean, nirrig_tmp_soybean use pftconMod , only : ntrp_soybean, nirrig_trp_soybean use clm_varcon , only : secspday, dzsoi_decomp - use clm_varctl , only : iulog, use_c13, use_c14 + 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,get_curr_calday @@ -1651,7 +1651,6 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & ! of amount allocated to roots over course of the growing season if (peaklai(p) == 1) then ! lai at maximum allowed - write(iulog,*) 'hit peaklai, allocation to leaf is set to small value' arepr(p) = 0._r8 aleaf(p) = 1.e-5_r8 astem(p) = astem(p) @@ -1690,8 +1689,7 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & (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 - write(iulog,*) 'hit peaklai, allocation to leaf is set 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))) - & @@ -1718,7 +1716,6 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & ! small value if (peaklai(p) == 1) then aleaf(p) = 1.e-5_r8 - write(iulog,*) 'hit peaklai, allocation to leaf is set to small value' 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)))) / & diff --git a/src/clm5/biogeochem/dynHarvestMod.F90 b/src/clm5/biogeochem/dynHarvestMod.F90 index 800585166b..4119f318a2 100644 --- a/src/clm5/biogeochem/dynHarvestMod.F90 +++ b/src/clm5/biogeochem/dynHarvestMod.F90 @@ -499,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) From acf0b4cbc0ac5e8b58e749b29f085c93d6eb5d4d Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Mon, 17 Jul 2023 11:21:49 +0200 Subject: [PATCH 13/13] Corrected flux assignment from column to patch level --- src/clm5/biogeochem/CNPhenologyMod.F90 | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/clm5/biogeochem/CNPhenologyMod.F90 b/src/clm5/biogeochem/CNPhenologyMod.F90 index 37011fa809..5e308d0aaa 100644 --- a/src/clm5/biogeochem/CNPhenologyMod.F90 +++ b/src/clm5/biogeochem/CNPhenologyMod.F90 @@ -2020,17 +2020,17 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & 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(c) = crop_seedc_to_leaf(c) - leafc_xfer(p)/dt - crop_seedc_to_froot(c) = crop_seedc_to_froot(c) - frootc_xfer(p)/dt - crop_seedn_to_leaf(c) = crop_seedn_to_leaf(c) - leafn_xfer(p)/dt - crop_seedn_to_froot(c) = crop_seedn_to_froot(c) - frootn_xfer(p)/dt + 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(c) = crop_seedc_to_deadstem(c) - deadstemc_xfer(p)/dt - crop_seedn_to_deadstem(c) = crop_seedn_to_deadstem(c) - deadstemn_xfer(p)/dt + 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 @@ -2050,16 +2050,16 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & 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(c) = crop_seedc_to_froot(c) - frootc_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(c) = crop_seedn_to_froot(c) - frootn_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(c) = crop_seedc_to_deadstem(c) - deadstemc_xfer(p)/dt - crop_seedn_to_deadstem(c) = crop_seedn_to_deadstem(c) - deadstemn_xfer(p)/dt + 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 @@ -2094,16 +2094,16 @@ subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & ! 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(c) = crop_seedc_to_froot(c) - frootc_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(c) = crop_seedn_to_froot(c) - frootn_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(c) = crop_seedc_to_deadstem(c) - deadstemc_xfer(p)/dt - crop_seedn_to_deadstem(c) = crop_seedn_to_deadstem(c) - deadstemn_xfer(p)/dt + 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