From 9fa4d0dfe8ad9a24fa3755aad5fffe06ac4ae313 Mon Sep 17 00:00:00 2001 From: Olga Dombrowski Date: Tue, 8 Feb 2022 20:03:30 +0100 Subject: [PATCH 01/18] Implement CLM-FruitTree sub-model for deciduous fruit trees --- src/biogeochem/CNCIsoFluxMod.F90 | 17 +- src/biogeochem/CNCStateUpdate1Mod.F90 | 137 +- src/biogeochem/CNDriverMod.F90 | 9 +- src/biogeochem/CNFUNMod.F90 | 8 +- src/biogeochem/CNGRespMod.F90 | 30 +- src/biogeochem/CNGapMortalityMod.F90 | 5 +- src/biogeochem/CNMRespMod.F90 | 5 +- src/biogeochem/CNNStateUpdate1Mod.F90 | 100 +- src/biogeochem/CNPhenologyMod.F90 | 2181 ++++++++++++----- src/biogeochem/CNVegCarbonFluxType.F90 | 67 +- src/biogeochem/CNVegCarbonStateType.F90 | 54 +- src/biogeochem/CNVegNitrogenFluxType.F90 | 41 +- src/biogeochem/CNVegNitrogenStateType.F90 | 28 + src/biogeochem/CNVegStateType.F90 | 162 +- src/biogeochem/CNVegStructUpdateMod.F90 | 15 +- src/biogeochem/CropType.F90 | 11 +- .../NutrientCompetitionFlexibleCNMod.F90 | 503 +++- src/biogeochem/dynHarvestMod.F90 | 9 +- src/biogeophys/TemperatureType.F90 | 32 +- src/main/pftconMod.F90 | 81 +- 20 files changed, 2677 insertions(+), 818 deletions(-) diff --git a/src/biogeochem/CNCIsoFluxMod.F90 b/src/biogeochem/CNCIsoFluxMod.F90 index a92ab44e47..2a5a745ef1 100644 --- a/src/biogeochem/CNCIsoFluxMod.F90 +++ b/src/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/biogeochem/CNCStateUpdate1Mod.F90 b/src/biogeochem/CNCStateUpdate1Mod.F90 index e1da2f354f..8f579f7e97 100644 --- a/src/biogeochem/CNCStateUpdate1Mod.F90 +++ b/src/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/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90 index 94bc3f3554..43dbcf5c6d 100644 --- a/src/biogeochem/CNDriverMod.F90 +++ b/src/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/biogeochem/CNFUNMod.F90 b/src/biogeochem/CNFUNMod.F90 index f1adee8f6b..3a97f40223 100644 --- a/src/biogeochem/CNFUNMod.F90 +++ b/src/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/biogeochem/CNGapMortalityMod.F90 b/src/biogeochem/CNGapMortalityMod.F90 index 939d4b52eb..31f6c1627b 100644 --- a/src/biogeochem/CNGapMortalityMod.F90 +++ b/src/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/biogeochem/CNMRespMod.F90 b/src/biogeochem/CNMRespMod.F90 index 3a7052d0bb..51e5235840 100644 --- a/src/biogeochem/CNMRespMod.F90 +++ b/src/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/biogeochem/CNNStateUpdate1Mod.F90 b/src/biogeochem/CNNStateUpdate1Mod.F90 index 6c1d112029..72fcfca9c2 100644 --- a/src/biogeochem/CNNStateUpdate1Mod.F90 +++ b/src/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/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index 9d66373085..938e552a77 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/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/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index f88c7f5e66..f27a37595d 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/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/biogeochem/CNVegCarbonStateType.F90 b/src/biogeochem/CNVegCarbonStateType.F90 index 1d568dc60d..6d08a306ee 100644 --- a/src/biogeochem/CNVegCarbonStateType.F90 +++ b/src/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/biogeochem/CNVegNitrogenFluxType.F90 b/src/biogeochem/CNVegNitrogenFluxType.F90 index 47b620bf91..6277d80988 100644 --- a/src/biogeochem/CNVegNitrogenFluxType.F90 +++ b/src/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/biogeochem/CNVegNitrogenStateType.F90 b/src/biogeochem/CNVegNitrogenStateType.F90 index 97a5ffaae4..914151581c 100644 --- a/src/biogeochem/CNVegNitrogenStateType.F90 +++ b/src/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/biogeochem/CNVegStateType.F90 b/src/biogeochem/CNVegStateType.F90 index afdfa190aa..2c4f9b5576 100644 --- a/src/biogeochem/CNVegStateType.F90 +++ b/src/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/biogeochem/CNVegStructUpdateMod.F90 b/src/biogeochem/CNVegStructUpdateMod.F90 index 27b677b04d..3a828fde0c 100644 --- a/src/biogeochem/CNVegStructUpdateMod.F90 +++ b/src/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/biogeochem/CropType.F90 b/src/biogeochem/CropType.F90 index 0b2c0fc1db..da109ddff7 100644 --- a/src/biogeochem/CropType.F90 +++ b/src/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/biogeochem/NutrientCompetitionFlexibleCNMod.F90 b/src/biogeochem/NutrientCompetitionFlexibleCNMod.F90 index f404ac9611..5008ea14d7 100644 --- a/src/biogeochem/NutrientCompetitionFlexibleCNMod.F90 +++ b/src/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/biogeochem/dynHarvestMod.F90 b/src/biogeochem/dynHarvestMod.F90 index a9344fd5cf..09d7ce6d70 100644 --- a/src/biogeochem/dynHarvestMod.F90 +++ b/src/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/biogeophys/TemperatureType.F90 b/src/biogeophys/TemperatureType.F90 index 5dfc3bc704..674793f9cf 100644 --- a/src/biogeophys/TemperatureType.F90 +++ b/src/biogeophys/TemperatureType.F90 @@ -84,6 +84,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) @@ -246,6 +247,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 @@ -443,6 +445,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', & @@ -560,6 +563,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)', & @@ -921,6 +929,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', & @@ -1119,6 +1131,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, & @@ -1147,6 +1163,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) @@ -1222,6 +1242,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) @@ -1232,6 +1255,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) @@ -1318,7 +1342,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 @@ -1327,6 +1351,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 @@ -1416,6 +1441,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/main/pftconMod.F90 b/src/main/pftconMod.F90 index 0efa2053eb..21147d111f 100644 --- a/src/main/pftconMod.F90 +++ b/src/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 c4f164e92fc47de57f03d6888048df7b0a3ba786 Mon Sep 17 00:00:00 2001 From: odombro <98333860+odombro@users.noreply.github.com> Date: Tue, 8 Feb 2022 21:31:49 +0100 Subject: [PATCH 02/18] Update README --- README | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/README b/README index 92e7a77e81..b7611eb0d1 100644 --- a/README +++ b/README @@ -1,5 +1,47 @@ $CTSMROOT/README 06/08/2018 +################################################################## +Modified Community Land Surface Model (CLM) science version 5.0.0 +Modifications to the model code include: +(1) Addition of a new perennial crop phenology description. +(2) Adaptation of the CN allocation scheme, considering both storage and photosynthetic growth of annual and perennial plant organs of a fruit tree. +(3) Desription of typical management practices associated with fruit orchards. +(4) Parameterization of an apple plant functional type (for now using ncitrus (35) and nirrig_citrus (36)) + +modified src code includes: + +src/biogeochem/CNCIsoFluxMod.F90 +src/biogeochem/CNCStateUpdate1Mod.F90 +src/biogeochem/CNDriverMod.F90 +src/biogeochem/CNFUNMod.F90 +src/biogeochem/CNGapMortalityMod.F90 +src/biogeochem/CNGRespMod.F90 +src/biogeochem/CNMRespMod.F90 +src/biogeochem/CNNStateUpdate1Mod.F90 +src/biogeochem/CNPhenologyMod.F90 +src/biogeochem/CNVegCarbonFluxType.F90 +src/biogeochem/CNVegCarbonStateType.F90 +src/biogeochem/CNVegNitrogenFluxType.F90 +src/biogeochem/CNVegNitrogenStateType.F90 +src/biogeochem/CNVegStateType.F90 +src/biogeochem/CNVegStructUpdateMod.F90 +src/biogeochem/CropType.F90 +src/biogeochem/dynHarvestMod.F90 +src/biogeochem/NutrientCompetitionFlexibleCNMod.F90 +src/main/pftconMod.F90 +src/biogeophys/TemperatureType.F90 + + +For additional information and results please refer to Dombrowski et al. (submitted Feb 2022): + +Dombrowski, O., Brogi, C., HendricksFranssen, H.-J., Zanotelli, D., Bogena, H. (submitted Feb 2022): CLM-FruitTree: A new sub-model for deciduous fruit trees in the Community Land Model (CLM5) + +Abstract: + +The inclusion of perennial, woody crops in land surface models is crucial to address their role in carbon (C) sequestration, food production, and water requirements under climate change. To help quantifying the biogeochemical and biogeophysical processes associated with these agro-ecosystems, we developed and tested a new sub-model, CLM-FruitTree, for deciduous fruit orchards within the framework of the Community Land Model version 5 (CLM5). The model development included (1) a new perennial crop phenology description, (2) an adapted C and nitrogen allocation scheme, considering both storage and photosynthetic growth of annual and perennial plant organs, (3) typical management practices associated with fruit orchards, and (4) the parameterization of an apple plant functional type. CLM-FruitTree was tested using extensive field measurements from an apple orchard in South Tyrol, Italy. Growth and partitioning of biomass to the individual plant components was well represented by CLM-FruitTree and average yield was predicted within 2.3 % of the observed values despite low simulated inter-annual variability compared to observations. The simulated seasonal course of C, energy, and water fluxes was in good agreement with the EC measurements owing to the accurate representation of the prolonged growing season and typical leaf area development of the orchard. We found that gross primary production, net radiation, and latent heat flux were highly correlated (r > 0.94) with EC measurements and showed little bias (< ±5 %). Simulated respiration components, sensible heat, and ground heat flux were less consistent with observations. This was attributed to simplifications in the orchard structure and to the presence of additional management practices that are not yet represented in CLM-FruitTree. Finally, the results suggested that the representation of microbial and autotrophic respiration, and energy partitioning in complex, heterogeneous canopies in CLM5 requires further attention. The new sub-model CLM-FruitTree improved the representation of agricultural systems in CLM5 and can be used to study land surface processes in fruit orchards at the local, regional or larger scale. +######################################################################## + + Community Land Surface Model (CLM) science version 5.0.0 series -- source code, tools, offline-build and test scripts. This gives you everything you need to run CLM with CESM with datm8 to provide CRU NCEP or GSWP3 forcing data in From 2a1f5b91d7d83eafcc29ba96b0e4497e3bf9b288 Mon Sep 17 00:00:00 2001 From: odombro <98333860+odombro@users.noreply.github.com> Date: Wed, 9 Feb 2022 11:24:03 +0100 Subject: [PATCH 03/18] Update README --- README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README b/README index b7611eb0d1..4edac11f9f 100644 --- a/README +++ b/README @@ -1,6 +1,6 @@ $CTSMROOT/README 06/08/2018 -################################################################## +################################################################################### Modified Community Land Surface Model (CLM) science version 5.0.0 Modifications to the model code include: (1) Addition of a new perennial crop phenology description. @@ -39,7 +39,7 @@ Dombrowski, O., Brogi, C., HendricksFranssen, H.-J., Zanotelli, D., Bogena, H. ( Abstract: The inclusion of perennial, woody crops in land surface models is crucial to address their role in carbon (C) sequestration, food production, and water requirements under climate change. To help quantifying the biogeochemical and biogeophysical processes associated with these agro-ecosystems, we developed and tested a new sub-model, CLM-FruitTree, for deciduous fruit orchards within the framework of the Community Land Model version 5 (CLM5). The model development included (1) a new perennial crop phenology description, (2) an adapted C and nitrogen allocation scheme, considering both storage and photosynthetic growth of annual and perennial plant organs, (3) typical management practices associated with fruit orchards, and (4) the parameterization of an apple plant functional type. CLM-FruitTree was tested using extensive field measurements from an apple orchard in South Tyrol, Italy. Growth and partitioning of biomass to the individual plant components was well represented by CLM-FruitTree and average yield was predicted within 2.3 % of the observed values despite low simulated inter-annual variability compared to observations. The simulated seasonal course of C, energy, and water fluxes was in good agreement with the EC measurements owing to the accurate representation of the prolonged growing season and typical leaf area development of the orchard. We found that gross primary production, net radiation, and latent heat flux were highly correlated (r > 0.94) with EC measurements and showed little bias (< ±5 %). Simulated respiration components, sensible heat, and ground heat flux were less consistent with observations. This was attributed to simplifications in the orchard structure and to the presence of additional management practices that are not yet represented in CLM-FruitTree. Finally, the results suggested that the representation of microbial and autotrophic respiration, and energy partitioning in complex, heterogeneous canopies in CLM5 requires further attention. The new sub-model CLM-FruitTree improved the representation of agricultural systems in CLM5 and can be used to study land surface processes in fruit orchards at the local, regional or larger scale. -######################################################################## +############################################################################################################# Community Land Surface Model (CLM) science version 5.0.0 series -- source code, tools, From 7b823206d5858dc57382bb7f90748aaf364c143b Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Wed, 9 Feb 2022 15:04:38 +0100 Subject: [PATCH 04/18] 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 64c8749342b7381ca70fa29807008107425af5ca Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Wed, 9 Feb 2022 15:17:05 +0100 Subject: [PATCH 05/18] Update README --- README | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README b/README index 4edac11f9f..9bab22d7c0 100644 --- a/README +++ b/README @@ -31,6 +31,10 @@ src/biogeochem/NutrientCompetitionFlexibleCNMod.F90 src/main/pftconMod.F90 src/biogeophys/TemperatureType.F90 +new paramater file to be used with the development: + +clm5_params.c171117__FruitTree.nc + For additional information and results please refer to Dombrowski et al. (submitted Feb 2022): From 87b35bed2f0e3c82a85ee501d83fecd092412542 Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Mon, 14 Mar 2022 13:15:11 +0100 Subject: [PATCH 06/18] Correct orchard rotation/replanting trigger --- src/biogeochem/CNPhenologyMod.F90 | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index 938e552a77..2d0ab5a6ae 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/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 093c985b9387006c7c4d756293cb6dda794e408e Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Thu, 5 May 2022 12:47:49 +0200 Subject: [PATCH 07/18] Make taper and nstem PFT parameters to be set in parameter file --- src/biogeochem/CNVegStructUpdateMod.F90 | 39 +++++++------------------ src/main/pftconMod.F90 | 12 ++++++++ 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/biogeochem/CNVegStructUpdateMod.F90 b/src/biogeochem/CNVegStructUpdateMod.F90 index 3a828fde0c..3103882964 100644 --- a/src/biogeochem/CNVegStructUpdateMod.F90 +++ b/src/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/main/pftconMod.F90 b/src/main/pftconMod.F90 index 21147d111f..b1a3c14c5c 100644 --- a/src/main/pftconMod.F90 +++ b/src/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 2a6d95e08e9953078c81919263bfac26bec062da Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Thu, 5 May 2022 15:21:56 +0200 Subject: [PATCH 08/18] 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 57586d70e2c67148526ccd4282d6d03defb8ffee Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Sun, 22 May 2022 07:45:05 +0200 Subject: [PATCH 09/18] added references to CLM-Palm (Fan et al. 2015) --- src/biogeochem/CNPhenologyMod.F90 | 37 +++++++++++++++++-------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index 2d0ab5a6ae..7a8b9e3538 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/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 ad3d25b07b20fa1eac17921e6800247c3d041f94 Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Mon, 30 May 2022 18:58:13 +0200 Subject: [PATCH 10/18] Bug fix in CNPhenology and CNVegStructUpdateMod, and parameter value correction --- clm5_params.c171117__FruitTree.nc | Bin 222872 -> 222872 bytes src/biogeochem/CNPhenologyMod.F90 | 29 ++++++++++++++++-------- src/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 11/18] Included harvest trigger when leaf offset starts --- src/biogeochem/CNPhenologyMod.F90 | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index 9cb0a3b946..7894c2fe81 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/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 17f3e8ae6961e2c7971aefc2f8c566be8699e77f Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Tue, 18 Oct 2022 14:55:01 +0200 Subject: [PATCH 12/18] debug planting of fruit trees, make two more CFTs active --- src/biogeochem/CNPhenologyMod.F90 | 32 +++++++++--------- src/biogeochem/CNVegCarbonFluxType.F90 | 3 +- src/biogeochem/CNVegCarbonStateType.F90 | 33 ++++++++++--------- src/biogeochem/CNVegComputeSeedMod.F90 | 4 +-- src/biogeochem/CNVegNitrogenStateType.F90 | 12 +++++-- src/biogeochem/CNVegStructUpdateMod.F90 | 18 +++++++--- src/biogeochem/CropType.F90 | 3 +- .../NutrientCompetitionFlexibleCNMod.F90 | 7 ++-- 8 files changed, 66 insertions(+), 46 deletions(-) diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index 7894c2fe81..117673da8d 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/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/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index f27a37595d..681b394f3e 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/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/biogeochem/CNVegCarbonStateType.F90 b/src/biogeochem/CNVegCarbonStateType.F90 index 6d08a306ee..30a31a669a 100644 --- a/src/biogeochem/CNVegCarbonStateType.F90 +++ b/src/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/biogeochem/CNVegComputeSeedMod.F90 b/src/biogeochem/CNVegComputeSeedMod.F90 index 01cf471e20..8ac2b175b2 100644 --- a/src/biogeochem/CNVegComputeSeedMod.F90 +++ b/src/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/biogeochem/CNVegNitrogenStateType.F90 b/src/biogeochem/CNVegNitrogenStateType.F90 index 914151581c..6d2b4d3c90 100644 --- a/src/biogeochem/CNVegNitrogenStateType.F90 +++ b/src/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/biogeochem/CNVegStructUpdateMod.F90 b/src/biogeochem/CNVegStructUpdateMod.F90 index 268f658906..fd6c2acfec 100644 --- a/src/biogeochem/CNVegStructUpdateMod.F90 +++ b/src/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/biogeochem/CropType.F90 b/src/biogeochem/CropType.F90 index da109ddff7..ac38275892 100644 --- a/src/biogeochem/CropType.F90 +++ b/src/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/biogeochem/NutrientCompetitionFlexibleCNMod.F90 b/src/biogeochem/NutrientCompetitionFlexibleCNMod.F90 index 5008ea14d7..2c6eaf5aba 100644 --- a/src/biogeochem/NutrientCompetitionFlexibleCNMod.F90 +++ b/src/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 2a21cb01861a492cbf2c23fabc44e3fe30002e39 Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Fri, 4 Nov 2022 14:20:11 +0100 Subject: [PATCH 13/18] Fix orchard rotation carbon balance error --- src/biogeochem/CNCIsoFluxMod.F90 | 3 +- src/biogeochem/CNCStateUpdate1Mod.F90 | 2 -- src/biogeochem/CNCStateUpdate2Mod.F90 | 2 -- src/biogeochem/CNPhenologyMod.F90 | 51 +++++++++++++-------------- src/biogeochem/dynHarvestMod.F90 | 1 - 5 files changed, 25 insertions(+), 34 deletions(-) diff --git a/src/biogeochem/CNCIsoFluxMod.F90 b/src/biogeochem/CNCIsoFluxMod.F90 index 2a5a745ef1..63d1796f46 100644 --- a/src/biogeochem/CNCIsoFluxMod.F90 +++ b/src/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/biogeochem/CNCStateUpdate1Mod.F90 b/src/biogeochem/CNCStateUpdate1Mod.F90 index 8f579f7e97..ed96b33192 100644 --- a/src/biogeochem/CNCStateUpdate1Mod.F90 +++ b/src/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/biogeochem/CNCStateUpdate2Mod.F90 b/src/biogeochem/CNCStateUpdate2Mod.F90 index ef1f6f9345..ef0d67dd36 100644 --- a/src/biogeochem/CNCStateUpdate2Mod.F90 +++ b/src/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/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index 117673da8d..950172127f 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/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/biogeochem/dynHarvestMod.F90 b/src/biogeochem/dynHarvestMod.F90 index 09d7ce6d70..800585166b 100644 --- a/src/biogeochem/dynHarvestMod.F90 +++ b/src/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 a6bd8ded352d4578ffa78fc7376faac1b91835bd Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Tue, 15 Nov 2022 10:45:18 +0100 Subject: [PATCH 14/18] added new subroutine for orchard rotation --- src/biogeochem/CNPhenologyMod.F90 | 376 ++++++++++++++++++++++++------ 1 file changed, 311 insertions(+), 65 deletions(-) diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index 950172127f..37011fa809 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/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 7edde0ba85126d80fc9532bc47e6d28bdadc7833 Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Tue, 15 Nov 2022 16:15:53 +0100 Subject: [PATCH 15/18] cleaned up some scripts, added some crop types to active CFTs --- src/biogeochem/CNBalanceCheckMod.F90 | 6 +++--- src/biogeochem/CNVegCarbonStateType.F90 | 1 - src/biogeochem/CropType.F90 | 3 +-- src/biogeochem/NutrientCompetitionFlexibleCNMod.F90 | 7 ++----- src/biogeochem/dynHarvestMod.F90 | 2 +- 5 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/biogeochem/CNBalanceCheckMod.F90 b/src/biogeochem/CNBalanceCheckMod.F90 index 8f123cf442..499cad44c7 100644 --- a/src/biogeochem/CNBalanceCheckMod.F90 +++ b/src/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/biogeochem/CNVegCarbonStateType.F90 b/src/biogeochem/CNVegCarbonStateType.F90 index 30a31a669a..08a273b338 100644 --- a/src/biogeochem/CNVegCarbonStateType.F90 +++ b/src/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/biogeochem/CropType.F90 b/src/biogeochem/CropType.F90 index ac38275892..da109ddff7 100644 --- a/src/biogeochem/CropType.F90 +++ b/src/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/biogeochem/NutrientCompetitionFlexibleCNMod.F90 b/src/biogeochem/NutrientCompetitionFlexibleCNMod.F90 index 2c6eaf5aba..5008ea14d7 100644 --- a/src/biogeochem/NutrientCompetitionFlexibleCNMod.F90 +++ b/src/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/biogeochem/dynHarvestMod.F90 b/src/biogeochem/dynHarvestMod.F90 index 800585166b..4119f318a2 100644 --- a/src/biogeochem/dynHarvestMod.F90 +++ b/src/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 59b6a30094d1afa810c6be3b2a8feb88c2905875 Mon Sep 17 00:00:00 2001 From: OlgaDom Date: Mon, 17 Jul 2023 11:21:49 +0200 Subject: [PATCH 16/18] Corrected flux assignment from column to patch level --- src/biogeochem/CNPhenologyMod.F90 | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index 37011fa809..5e308d0aaa 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/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 From d4c6a1b9b9dbc93e05fff0f641d806714b35959a Mon Sep 17 00:00:00 2001 From: odombro <98333860+odombro@users.noreply.github.com> Date: Mon, 18 Dec 2023 12:09:10 +0100 Subject: [PATCH 17/18] Update README added missing script to list of modified src code --- README | 1 + 1 file changed, 1 insertion(+) diff --git a/README b/README index 9bab22d7c0..f1158e3158 100644 --- a/README +++ b/README @@ -21,6 +21,7 @@ src/biogeochem/CNNStateUpdate1Mod.F90 src/biogeochem/CNPhenologyMod.F90 src/biogeochem/CNVegCarbonFluxType.F90 src/biogeochem/CNVegCarbonStateType.F90 +src/biogeochem/CNVegComputeSeedMod.F90 src/biogeochem/CNVegNitrogenFluxType.F90 src/biogeochem/CNVegNitrogenStateType.F90 src/biogeochem/CNVegStateType.F90 From 2c1722c9a43601576ac0e3edbca24db08062020a Mon Sep 17 00:00:00 2001 From: odombro <98333860+odombro@users.noreply.github.com> Date: Mon, 18 Dec 2023 12:47:56 +0100 Subject: [PATCH 18/18] Update README --- README | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README b/README index f1158e3158..ff235e8fcd 100644 --- a/README +++ b/README @@ -39,7 +39,8 @@ clm5_params.c171117__FruitTree.nc For additional information and results please refer to Dombrowski et al. (submitted Feb 2022): -Dombrowski, O., Brogi, C., HendricksFranssen, H.-J., Zanotelli, D., Bogena, H. (submitted Feb 2022): CLM-FruitTree: A new sub-model for deciduous fruit trees in the Community Land Model (CLM5) +Dombrowski, O., Brogi, C., Hendricks Franssen, H. J., Zanotelli, D., & Bogena, H. (2022). CLM5-FruitTree: a new sub-model for deciduous fruit trees in the Community Land Model (CLM5). Geoscientific model development, 15(13), 5167-5193. +https://doi.org/10.5194/gmd-15-5167-2022 Abstract: