diff --git a/README b/README index 92e7a77e81..ff235e8fcd 100644 --- a/README +++ b/README @@ -1,5 +1,53 @@ $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/CNVegComputeSeedMod.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 + +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): + +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: + +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 diff --git a/clm5_params.c171117__FruitTree.nc b/clm5_params.c171117__FruitTree.nc new file mode 100644 index 0000000000..c5cf25c623 Binary files /dev/null and b/clm5_params.c171117__FruitTree.nc differ diff --git a/src/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/CNCIsoFluxMod.F90 b/src/biogeochem/CNCIsoFluxMod.F90 index a92ab44e47..63d1796f46 100644 --- a/src/biogeochem/CNCIsoFluxMod.F90 +++ b/src/biogeochem/CNCIsoFluxMod.F90 @@ -135,7 +135,7 @@ subroutine CIsoFlux1(num_soilc, filter_soilc, num_soilp, filter_soilp, & iso_cnveg_cf%frootc_to_litter_patch , cnveg_cf%frootc_to_litter_patch, & iso_cnveg_cs%frootc_patch , cnveg_cs%frootc_patch, & num_soilp , filter_soilp, 1._r8, 0, isotope) - + call CIsoFluxCalc(& iso_cnveg_cf%livestemc_to_deadstemc_patch , cnveg_cf%livestemc_to_deadstemc_patch, & iso_cnveg_cs%livestemc_patch , cnveg_cs%livestemc_patch, & @@ -414,6 +414,17 @@ subroutine CIsoFlux1(num_soilc, filter_soilc, num_soilp, filter_soilp, & iso_cnveg_cs%totvegc_patch , cnveg_cs%totvegc_patch, & num_soilp , filter_soilp, 1._r8, 0, isotope) + call CIsoFluxCalc(& + iso_cnveg_cf%crop_seedc_to_froot_patch , cnveg_cf%crop_seedc_to_froot_patch, & + iso_cnveg_cs%totvegc_patch , cnveg_cs%totvegc_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%crop_seedc_to_deadstem_patch , cnveg_cf%crop_seedc_to_deadstem_patch, & + iso_cnveg_cs%totvegc_patch , cnveg_cs%totvegc_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& iso_cnveg_cf%grain_curmr_patch , cnveg_cf%grain_curmr_patch, & iso_cnveg_cs%cpool_patch , cnveg_cs%cpool_patch, & @@ -1222,7 +1233,7 @@ subroutine CNCIsoLitterToColumn (num_soilc, filter_soilc, & + frootc_to_litter(p) * fr_fcel(ivt(p)) * wtcol(p) * froot_prof(p,j) phenology_c_to_litr_lig_c(c,j) = phenology_c_to_litr_lig_c(c,j) & + frootc_to_litter(p) * fr_flig(ivt(p)) * wtcol(p) * froot_prof(p,j) - + !DML if (ivt(p) >= npcropmin) then ! add livestemc to litter ! stem litter carbon fluxes @@ -1492,7 +1503,6 @@ subroutine CNCIsoHarvestPftToColumn (num_soilc, filter_soilc, & hrv_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & hrv_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) - ! storage harvest mortality carbon fluxes harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & hrv_leafc_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) diff --git a/src/biogeochem/CNCStateUpdate1Mod.F90 b/src/biogeochem/CNCStateUpdate1Mod.F90 index e1da2f354f..ed96b33192 100644 --- a/src/biogeochem/CNCStateUpdate1Mod.F90 +++ b/src/biogeochem/CNCStateUpdate1Mod.F90 @@ -173,7 +173,8 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) - + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types (1=perennial, 0= not perennial) + mulch_pruning => pftcon%mulch_pruning , & ! Input: binary flag for mulching or exporting pruning material (1=mulching, 0=exporting) cascade_donor_pool => decomp_cascade_con%cascade_donor_pool , & ! Input: [integer (:) ] which pool is C taken from for a given decomposition step cascade_receiver_pool => decomp_cascade_con%cascade_receiver_pool , & ! Input: [integer (:) ] which pool is C added to for a given decomposition step @@ -268,10 +269,15 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops ! lines here for consistency; the transfer terms are zero - cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) + cf_veg%livestemc_xfer_to_livestemc_patch(p)*dt - cs_veg%livestemc_xfer_patch(p) = cs_veg%livestemc_xfer_patch(p) - cf_veg%livestemc_xfer_to_livestemc_patch(p)*dt - cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) + cf_veg%grainc_xfer_to_grainc_patch(p)*dt - cs_veg%grainc_xfer_patch(p) = cs_veg%grainc_xfer_patch(p) - cf_veg%grainc_xfer_to_grainc_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) + cf_veg%grainc_xfer_to_grainc_patch(p)*dt + cs_veg%grainc_xfer_patch(p) = cs_veg%grainc_xfer_patch(p) - cf_veg%grainc_xfer_to_grainc_patch(p)*dt + else + cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) + cf_veg%livestemc_xfer_to_livestemc_patch(p)*dt + cs_veg%livestemc_xfer_patch(p) = cs_veg%livestemc_xfer_patch(p) - cf_veg%livestemc_xfer_to_livestemc_patch(p)*dt + cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) + cf_veg%grainc_xfer_to_grainc_patch(p)*dt + cs_veg%grainc_xfer_patch(p) = cs_veg%grainc_xfer_patch(p) - cf_veg%grainc_xfer_to_grainc_patch(p)*dt + end if end if ! phenology: litterfall fluxes @@ -286,12 +292,27 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%deadcrootc_patch(p) = cs_veg%deadcrootc_patch(p) + cf_veg%livecrootc_to_deadcrootc_patch(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) - cf_veg%livestemc_to_litter_patch(p)*dt - cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) & - - (cf_veg%grainc_to_food_patch(p) + cf_veg%grainc_to_seed_patch(p))*dt - cs_veg%cropseedc_deficit_patch(p) = cs_veg%cropseedc_deficit_patch(p) & - - cf_veg%crop_seedc_to_leaf_patch(p) * dt & - + cf_veg%grainc_to_seed_patch(p) * dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) & + - (cf_veg%grainc_to_food_patch(p) + cf_veg%grainc_to_seed_patch(p))*dt + cs_veg%cropseedc_deficit_patch(p) = cs_veg%cropseedc_deficit_patch(p) & + - cf_veg%crop_seedc_to_leaf_patch(p) * dt & + - cf_veg%crop_seedc_to_froot_patch(p) * dt & !(added by O.Dombrowski) + - cf_veg%crop_seedc_to_deadstem_patch(p) * dt & !(added by O.Dombrowski) + + cf_veg%grainc_to_seed_patch(p) * dt + if (mulch_pruning(ivt(p)) == 1._r8) then + ! update stem biomass after pruning + cs_veg%deadstemc_patch(p) = cs_veg%deadstemc_patch(p) - cf_veg%prunec_to_litter_patch(p)*dt + cs_veg%deadstemc_storage_patch(p) = cs_veg%deadstemc_storage_patch(p) - cf_veg%prunec_storage_to_litter_patch(p)*dt + end if + else + cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) - cf_veg%livestemc_to_litter_patch(p)*dt + cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) & + - (cf_veg%grainc_to_food_patch(p) + cf_veg%grainc_to_seed_patch(p))*dt + cs_veg%cropseedc_deficit_patch(p) = cs_veg%cropseedc_deficit_patch(p) & + - cf_veg%crop_seedc_to_leaf_patch(p) * dt & + + cf_veg%grainc_to_seed_patch(p) * dt + end if end if check_cpool = cs_veg%cpool_patch(p)- cf_veg%psnsun_to_cpool_patch(p)*dt-cf_veg%psnshade_to_cpool_patch(p)*dt @@ -302,13 +323,20 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_xsmrpool_patch(p)*dt cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%leaf_curmr_patch(p)*dt cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%froot_curmr_patch(p)*dt - If (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) == 1._r8) then cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%livestem_curmr_patch(p)*dt cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%livecroot_curmr_patch(p)*dt + end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%livestem_curmr_patch(p)*dt - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%grain_curmr_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%grain_curmr_patch(p)*dt + + else + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%livestem_curmr_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%grain_curmr_patch(p)*dt + + end if end if @@ -369,21 +397,31 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%deadcrootc_patch(p) = cs_veg%deadcrootc_patch(p) + cf_veg%cpool_to_deadcrootc_patch(p)*dt cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_deadcrootc_storage_patch(p)*dt cs_veg%deadcrootc_storage_patch(p) = cs_veg%deadcrootc_storage_patch(p) + cf_veg%cpool_to_deadcrootc_storage_patch(p)*dt + end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - if (carbon_resp_opt == 1) then + if (carbon_resp_opt == 1 .and. perennial(ivt(p)) == 0._r8) then !(perennial flag added by O.Dombrowski) cf_veg%cpool_to_livestemc_patch(p) = cf_veg%cpool_to_livestemc_patch(p) - cf_veg%cpool_to_livestemc_resp_patch(p) cf_veg%cpool_to_livestemc_storage_patch(p) = cf_veg%cpool_to_livestemc_storage_patch(p) - & cf_veg%cpool_to_livestemc_storage_resp_patch(p) end if - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_livestemc_patch(p)*dt - cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) + cf_veg%cpool_to_livestemc_patch(p)*dt - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_livestemc_storage_patch(p)*dt - cs_veg%livestemc_storage_patch(p) = cs_veg%livestemc_storage_patch(p) + cf_veg%cpool_to_livestemc_storage_patch(p)*dt - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_grainc_patch(p)*dt - cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) + cf_veg%cpool_to_grainc_patch(p)*dt - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_grainc_storage_patch(p)*dt - cs_veg%grainc_storage_patch(p) = cs_veg%grainc_storage_patch(p) + cf_veg%cpool_to_grainc_storage_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_grainc_patch(p)*dt + cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) + cf_veg%cpool_to_grainc_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_grainc_storage_patch(p)*dt + cs_veg%grainc_storage_patch(p) = cs_veg%grainc_storage_patch(p) + cf_veg%cpool_to_grainc_storage_patch(p)*dt + + else + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_livestemc_patch(p)*dt + cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) + cf_veg%cpool_to_livestemc_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_livestemc_storage_patch(p)*dt + cs_veg%livestemc_storage_patch(p) = cs_veg%livestemc_storage_patch(p) + cf_veg%cpool_to_livestemc_storage_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_grainc_patch(p)*dt + cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) + cf_veg%cpool_to_grainc_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_grainc_storage_patch(p)*dt + cs_veg%grainc_storage_patch(p) = cs_veg%grainc_storage_patch(p) + cf_veg%cpool_to_grainc_storage_patch(p)*dt + + end if end if ! growth respiration fluxes for current growth @@ -397,8 +435,12 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_deadcroot_gr_patch(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_livestem_gr_patch(p)*dt - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_grain_gr_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_grain_gr_patch(p)*dt + else + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_livestem_gr_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_grain_gr_patch(p)*dt + end if end if ! growth respiration for transfer growth @@ -411,8 +453,12 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) - cf_veg%transfer_deadcroot_gr_patch(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) - cf_veg%transfer_livestem_gr_patch(p)*dt - cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) - cf_veg%transfer_grain_gr_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) - cf_veg%transfer_grain_gr_patch(p)*dt + else + cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) - cf_veg%transfer_livestem_gr_patch(p)*dt + cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) - cf_veg%transfer_grain_gr_patch(p)*dt + end if end if ! growth respiration at time of storage @@ -426,10 +472,12 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_deadcroot_storage_gr_patch(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_livestem_storage_gr_patch(p)*dt - - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_grain_storage_gr_patch(p)*dt - + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_grain_storage_gr_patch(p)*dt + else + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_livestem_storage_gr_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_grain_storage_gr_patch(p)*dt + end if end if ! growth respiration stored for release during transfer growth @@ -454,16 +502,25 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) + cf_veg%gresp_storage_to_xfer_patch(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - ! lines here for consistency; the transfer terms are zero - cs_veg%livestemc_storage_patch(p) = cs_veg%livestemc_storage_patch(p) - cf_veg%livestemc_storage_to_xfer_patch(p)*dt - cs_veg%livestemc_xfer_patch(p) = cs_veg%livestemc_xfer_patch(p) + cf_veg%livestemc_storage_to_xfer_patch(p)*dt - cs_veg%grainc_storage_patch(p) = cs_veg%grainc_storage_patch(p) - cf_veg%grainc_storage_to_xfer_patch(p)*dt - cs_veg%grainc_xfer_patch(p) = cs_veg%grainc_xfer_patch(p) + cf_veg%grainc_storage_to_xfer_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%grainc_storage_patch(p) = cs_veg%grainc_storage_patch(p) - cf_veg%grainc_storage_to_xfer_patch(p)*dt + cs_veg%grainc_xfer_patch(p) = cs_veg%grainc_xfer_patch(p) + cf_veg%grainc_storage_to_xfer_patch(p)*dt + else + ! lines here for consistency; the transfer terms are zero + cs_veg%livestemc_storage_patch(p) = cs_veg%livestemc_storage_patch(p) - cf_veg%livestemc_storage_to_xfer_patch(p)*dt + cs_veg%livestemc_xfer_patch(p) = cs_veg%livestemc_xfer_patch(p) + cf_veg%livestemc_storage_to_xfer_patch(p)*dt + cs_veg%grainc_storage_patch(p) = cs_veg%grainc_storage_patch(p) - cf_veg%grainc_storage_to_xfer_patch(p)*dt + cs_veg%grainc_xfer_patch(p) = cs_veg%grainc_xfer_patch(p) + cf_veg%grainc_storage_to_xfer_patch(p)*dt + end if end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%livestem_xsmr_patch(p)*dt - cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%grain_xsmr_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1._r8) then + cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%grain_xsmr_patch(p)*dt + else + cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%livestem_xsmr_patch(p)*dt + cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%grain_xsmr_patch(p)*dt + end if if (harvdate(p) < 999) then ! beginning at harvest, send to atm ! TODO (mv, 11-02-2014) the following lines are why the cf_veg is ! an intent(inout) @@ -491,6 +548,7 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%xsmrpool_patch(p) = 0._r8 cs_veg%cpool_patch(p) = 0._r8 cs_veg%frootc_patch(p) = 0._r8 + end if ! Slowly release xsmrpool to atmosphere @@ -500,6 +558,7 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & ! update xsmrpool loss state cs_veg%xsmrpool_loss_patch(p) = cs_veg%xsmrpool_loss_patch(p) - cf_veg%xsmrpool_to_atm_patch(p) * dt + end if end if diff --git a/src/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/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..5e308d0aaa 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,15 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & ! gather all patch-level litterfall fluxes to the column for litter C and N inputs - call CNLitterToColumn(bounds, num_soilc, filter_soilc, & - cnveg_state_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & + call CNLitterToColumn(bounds, num_soilc, filter_soilc, & + cnveg_state_inst,cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & leaf_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full), & - froot_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full)) + froot_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full), stem_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full)) + + call CNRotationToColumn (num_soilc, filter_soilc, & + cnveg_state_inst, soilbiogeochem_state_inst, crop_inst, cnveg_carbonflux_inst, & + cnveg_nitrogenflux_inst) + else call endrun( 'bad phase' ) end if @@ -525,7 +538,7 @@ subroutine CNEvergreenPhenology (num_soilp, filter_soilp , & integer :: p ! indices integer :: fp ! lake filter patch index - real(r8):: tranr + real(r8):: tranr real(r8):: t1 ! temporary variable !----------------------------------------------------------------------- @@ -538,59 +551,59 @@ subroutine CNEvergreenPhenology (num_soilp, filter_soilp , & woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) leafc_storage => cnveg_carbonstate_inst%leafc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) leaf C storage - frootc_storage => cnveg_carbonstate_inst%frootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) fine root C storage + frootc_storage => cnveg_carbonstate_inst%frootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) fine root C storage livestemc_storage => cnveg_carbonstate_inst%livestemc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) live stem C storage deadstemc_storage => cnveg_carbonstate_inst%deadstemc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) dead stem C storage - livecrootc_storage => cnveg_carbonstate_inst%livecrootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) live coarse root C storage - deadcrootc_storage => cnveg_carbonstate_inst%deadcrootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) dead coarse root C storage - gresp_storage => cnveg_carbonstate_inst%gresp_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) growth respiration storage - leafc_xfer => cnveg_carbonstate_inst%leafc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) leaf C transfer - frootc_xfer => cnveg_carbonstate_inst%frootc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) fine root C transfer - livestemc_xfer => cnveg_carbonstate_inst%livestemc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) live stem C transfer - deadstemc_xfer => cnveg_carbonstate_inst%deadstemc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) dead stem C transfer - livecrootc_xfer => cnveg_carbonstate_inst%livecrootc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) live coarse root C transfer - deadcrootc_xfer => cnveg_carbonstate_inst%deadcrootc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) dead coarse root C transfer - - leafn_storage => cnveg_nitrogenstate_inst%leafn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) leaf N storage - frootn_storage => cnveg_nitrogenstate_inst%frootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) fine root N storage - livestemn_storage => cnveg_nitrogenstate_inst%livestemn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) live stem N storage - deadstemn_storage => cnveg_nitrogenstate_inst%deadstemn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N storage - livecrootn_storage => cnveg_nitrogenstate_inst%livecrootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) live coarse root N storage - deadcrootn_storage => cnveg_nitrogenstate_inst%deadcrootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) dead coarse root N storage - leafn_xfer => cnveg_nitrogenstate_inst%leafn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) leaf N transfer - frootn_xfer => cnveg_nitrogenstate_inst%frootn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) fine root N transfer - livestemn_xfer => cnveg_nitrogenstate_inst%livestemn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) live stem N transfer - deadstemn_xfer => cnveg_nitrogenstate_inst%deadstemn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) dead stem N transfer - livecrootn_xfer => cnveg_nitrogenstate_inst%livecrootn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) live coarse root N transfer - deadcrootn_xfer => cnveg_nitrogenstate_inst%deadcrootn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) dead coarse root N transfer - - leafc_storage_to_xfer => cnveg_carbonflux_inst%leafc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - frootc_storage_to_xfer => cnveg_carbonflux_inst%frootc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - livestemc_storage_to_xfer => cnveg_carbonflux_inst%livestemc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - deadstemc_storage_to_xfer => cnveg_carbonflux_inst%deadstemc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - livecrootc_storage_to_xfer => cnveg_carbonflux_inst%livecrootc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - deadcrootc_storage_to_xfer => cnveg_carbonflux_inst%deadcrootc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - gresp_storage_to_xfer => cnveg_carbonflux_inst%gresp_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - leafc_xfer_to_leafc => cnveg_carbonflux_inst%leafc_xfer_to_leafc_patch , & ! InOut: [real(r8) (:)] - frootc_xfer_to_frootc => cnveg_carbonflux_inst%frootc_xfer_to_frootc_patch , & ! InOut: [real(r8) (:)] - livestemc_xfer_to_livestemc => cnveg_carbonflux_inst%livestemc_xfer_to_livestemc_patch , & ! InOut: [real(r8) (:)] - deadstemc_xfer_to_deadstemc => cnveg_carbonflux_inst%deadstemc_xfer_to_deadstemc_patch , & ! InOut: [real(r8) (:)] - livecrootc_xfer_to_livecrootc => cnveg_carbonflux_inst%livecrootc_xfer_to_livecrootc_patch , & ! InOut: [real(r8) (:)] - deadcrootc_xfer_to_deadcrootc => cnveg_carbonflux_inst%deadcrootc_xfer_to_deadcrootc_patch , & ! InOut: [real(r8) (:)] - - leafn_storage_to_xfer => cnveg_nitrogenflux_inst%leafn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - frootn_storage_to_xfer => cnveg_nitrogenflux_inst%frootn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - livestemn_storage_to_xfer => cnveg_nitrogenflux_inst%livestemn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - deadstemn_storage_to_xfer => cnveg_nitrogenflux_inst%deadstemn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - livecrootn_storage_to_xfer => cnveg_nitrogenflux_inst%livecrootn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - deadcrootn_storage_to_xfer => cnveg_nitrogenflux_inst%deadcrootn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - leafn_xfer_to_leafn => cnveg_nitrogenflux_inst%leafn_xfer_to_leafn_patch , & ! InOut: [real(r8) (:)] - frootn_xfer_to_frootn => cnveg_nitrogenflux_inst%frootn_xfer_to_frootn_patch , & ! InOut: [real(r8) (:)] - livestemn_xfer_to_livestemn => cnveg_nitrogenflux_inst%livestemn_xfer_to_livestemn_patch , & ! InOut: [real(r8) (:)] - deadstemn_xfer_to_deadstemn => cnveg_nitrogenflux_inst%deadstemn_xfer_to_deadstemn_patch , & ! InOut: [real(r8) (:)] - livecrootn_xfer_to_livecrootn => cnveg_nitrogenflux_inst%livecrootn_xfer_to_livecrootn_patch , & ! InOut: [real(r8) (:)] - deadcrootn_xfer_to_deadcrootn => cnveg_nitrogenflux_inst%deadcrootn_xfer_to_deadcrootn_patch , & ! InOut: [real(r8) (:)] - + livecrootc_storage => cnveg_carbonstate_inst%livecrootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) live coarse root C storage + deadcrootc_storage => cnveg_carbonstate_inst%deadcrootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) dead coarse root C storage + gresp_storage => cnveg_carbonstate_inst%gresp_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) growth respiration storage + leafc_xfer => cnveg_carbonstate_inst%leafc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) leaf C transfer + frootc_xfer => cnveg_carbonstate_inst%frootc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) fine root C transfer + livestemc_xfer => cnveg_carbonstate_inst%livestemc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) live stem C transfer + deadstemc_xfer => cnveg_carbonstate_inst%deadstemc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) dead stem C transfer + livecrootc_xfer => cnveg_carbonstate_inst%livecrootc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) live coarse root C transfer + deadcrootc_xfer => cnveg_carbonstate_inst%deadcrootc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) dead coarse root C transfer + + leafn_storage => cnveg_nitrogenstate_inst%leafn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) leaf N storage + frootn_storage => cnveg_nitrogenstate_inst%frootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) fine root N storage + livestemn_storage => cnveg_nitrogenstate_inst%livestemn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) live stem N storage + deadstemn_storage => cnveg_nitrogenstate_inst%deadstemn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N storage + livecrootn_storage => cnveg_nitrogenstate_inst%livecrootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) live coarse root N storage + deadcrootn_storage => cnveg_nitrogenstate_inst%deadcrootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) dead coarse root N storage + leafn_xfer => cnveg_nitrogenstate_inst%leafn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) leaf N transfer + frootn_xfer => cnveg_nitrogenstate_inst%frootn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) fine root N transfer + livestemn_xfer => cnveg_nitrogenstate_inst%livestemn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) live stem N transfer + deadstemn_xfer => cnveg_nitrogenstate_inst%deadstemn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) dead stem N transfer + livecrootn_xfer => cnveg_nitrogenstate_inst%livecrootn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) live coarse root N transfer + deadcrootn_xfer => cnveg_nitrogenstate_inst%deadcrootn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) dead coarse root N transfer + + leafc_storage_to_xfer => cnveg_carbonflux_inst%leafc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + frootc_storage_to_xfer => cnveg_carbonflux_inst%frootc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + livestemc_storage_to_xfer => cnveg_carbonflux_inst%livestemc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + deadstemc_storage_to_xfer => cnveg_carbonflux_inst%deadstemc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + livecrootc_storage_to_xfer => cnveg_carbonflux_inst%livecrootc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + deadcrootc_storage_to_xfer => cnveg_carbonflux_inst%deadcrootc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + gresp_storage_to_xfer => cnveg_carbonflux_inst%gresp_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + leafc_xfer_to_leafc => cnveg_carbonflux_inst%leafc_xfer_to_leafc_patch , & ! InOut: [real(r8) (:)] + frootc_xfer_to_frootc => cnveg_carbonflux_inst%frootc_xfer_to_frootc_patch , & ! InOut: [real(r8) (:)] + livestemc_xfer_to_livestemc => cnveg_carbonflux_inst%livestemc_xfer_to_livestemc_patch , & ! InOut: [real(r8) (:)] + deadstemc_xfer_to_deadstemc => cnveg_carbonflux_inst%deadstemc_xfer_to_deadstemc_patch , & ! InOut: [real(r8) (:)] + livecrootc_xfer_to_livecrootc => cnveg_carbonflux_inst%livecrootc_xfer_to_livecrootc_patch , & ! InOut: [real(r8) (:)] + deadcrootc_xfer_to_deadcrootc => cnveg_carbonflux_inst%deadcrootc_xfer_to_deadcrootc_patch , & ! InOut: [real(r8) (:)] + + leafn_storage_to_xfer => cnveg_nitrogenflux_inst%leafn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + frootn_storage_to_xfer => cnveg_nitrogenflux_inst%frootn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + livestemn_storage_to_xfer => cnveg_nitrogenflux_inst%livestemn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + deadstemn_storage_to_xfer => cnveg_nitrogenflux_inst%deadstemn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + livecrootn_storage_to_xfer => cnveg_nitrogenflux_inst%livecrootn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + deadcrootn_storage_to_xfer => cnveg_nitrogenflux_inst%deadcrootn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + leafn_xfer_to_leafn => cnveg_nitrogenflux_inst%leafn_xfer_to_leafn_patch , & ! InOut: [real(r8) (:)] + frootn_xfer_to_frootn => cnveg_nitrogenflux_inst%frootn_xfer_to_frootn_patch , & ! InOut: [real(r8) (:)] + livestemn_xfer_to_livestemn => cnveg_nitrogenflux_inst%livestemn_xfer_to_livestemn_patch , & ! InOut: [real(r8) (:)] + deadstemn_xfer_to_deadstemn => cnveg_nitrogenflux_inst%deadstemn_xfer_to_deadstemn_patch , & ! InOut: [real(r8) (:)] + livecrootn_xfer_to_livecrootn => cnveg_nitrogenflux_inst%livecrootn_xfer_to_livecrootn_patch , & ! InOut: [real(r8) (:)] + deadcrootn_xfer_to_deadcrootn => cnveg_nitrogenflux_inst%deadcrootn_xfer_to_deadcrootn_patch , & ! InOut: [real(r8) (:)] + bglfr => cnveg_state_inst%bglfr_patch , & ! Output: [real(r8) (:) ] background litterfall rate (1/s) bgtr => cnveg_state_inst%bgtr_patch , & ! Output: [real(r8) (:) ] background transfer growth rate (1/s) lgsf => cnveg_state_inst%lgsf_patch & ! Output: [real(r8) (:) ] long growing season factor [0-1] @@ -706,7 +719,7 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) season_decid => pftcon%season_decid , & ! Input: binary flag for seasonal-deciduous leaf habit (0 or 1) - + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types (0 or 1) t_soisno => temperature_inst%t_soisno_col , & ! Input: [real(r8) (:,:) ] soil temperature (Kelvin) (-nlevsno+1:nlevgrnd) pftmayexist => dgvs_inst%pftmayexist_patch , & ! Output: [logical (:) ] exclude seasonal decid patches from tropics @@ -787,7 +800,7 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & c = patch%column(p) g = patch%gridcell(p) - if (season_decid(ivt(p)) == 1._r8) then + if (season_decid(ivt(p)) == 1._r8 .and. perennial(ivt(p)) == 0._r8) then ! set background litterfall rate, background transfer rate, and ! long growing season factor to 0 for seasonal deciduous types @@ -797,7 +810,6 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & ! onset gdd sum from Biome-BGC, v4.1.2 crit_onset_gdd = exp(4.8_r8 + 0.13_r8*(annavg_t2m(p) - SHR_CONST_TKFRZ)) - ! set flag for solstice period (winter->summer = 1, summer->winter = 0) if (dayl(g) >= prev_dayl(g)) then ws_flag = 1._r8 @@ -1416,6 +1428,700 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & end subroutine CNStressDecidPhenology + !----------------------------------------------------------------------- + subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & + waterstate_inst, temperature_inst, crop_inst, canopystate_inst, cnveg_state_inst, dgvs_inst, & + cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst,& + c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst) + + ! !DESCRIPTION: + ! Code from AgroIBIS adapted for deciduous fruit trees by O. Dombrowski (2022) to determine crop phenology and code from CN to + ! handle CN fluxes during the phenological onset & offset periods. + ! New phenological stages and triggers, as well as management practices typical for fruit orchards are described + + ! !USES: + use shr_const_mod , only : SHR_CONST_TKFRZ + use clm_time_manager , only : get_curr_date, get_curr_calday, get_days_per_year, get_rad_step_size + use pftconMod , only : ncitrus ! the citrus PFT is used for now, separate PFTs for deciduous fruit tree species may be added in the future + use pftconMod , only : nirrig_citrus + use clm_varcon , only : spval, secspday + use clm_varctl , only : use_fertilizer + use clm_varctl , only : use_c13, use_c14 + use clm_varcon , only : c13ratio, c14ratio + ! + ! !ARGUMENTS: + integer , intent(in) :: num_pcropp ! number of prog crop patches in filter + integer , intent(in) :: filter_pcropp(:) ! filter for prognostic crop patches + type(waterstate_type) , intent(in) :: waterstate_inst + type(temperature_type) , intent(in) :: temperature_inst + type(crop_type) , intent(inout) :: crop_inst + type(canopystate_type) , intent(in) :: canopystate_inst + type(cnveg_state_type) , intent(inout) :: cnveg_state_inst + type(dgvs_type) , intent(inout) :: dgvs_inst + type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst + type(cnveg_nitrogenstate_type) , intent(inout) :: cnveg_nitrogenstate_inst + type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst + type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst + type(cnveg_carbonstate_type) , intent(inout) :: c13_cnveg_carbonstate_inst + type(cnveg_carbonstate_type) , intent(inout) :: c14_cnveg_carbonstate_inst + ! + ! LOCAL VARAIBLES: + integer kyr ! current year + integer kmo ! month of year (1, ..., 12) + integer kda ! day of month (1, ..., 31) + integer mcsec ! seconds of day (0, ..., seconds/day) + integer jday ! julian day of the year + integer fp,p ! patch indices + integer c ! column indices + integer g ! gridcell indices + integer h ! hemisphere indices + integer idpp ! number of days past planting + real(r8) :: dtrad ! radiation time step delta t (seconds) + real(r8) dayspyr ! days per year + real(r8) crmcorn ! comparitive relative maturity for corn + real(r8) nfertdays_on ! number of days to fertilize + real(r8):: ws_flag !winter-summer solstice flag (0 or 1) + real(r8):: crit_onset_gdd !critical onset growing degree-day sum + real(r8):: soilt + real(r8) :: Cd !chill day value + real(r8) :: Ca !anti-chill day value + + !------------------------------------------------------------------------ + + associate( & + ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type + dayl => grc%dayl , & ! Input: [real(r8) (:) ] daylength (s) + prev_dayl => grc%prev_dayl , & ! Input: [real(r8) (:) ] daylength from previous time step (s) + leaf_long => pftcon%leaf_long , & ! Input: leaf longevity (yrs) + leafcn => pftcon%leafcn , & ! Input: leaf C:N (gC/gN) + frootcn => pftcon%frootcn , & ! Input: fine root C:N (gC/gN) + livewdcn => pftcon%livewdcn , & ! Input: live wood C:N (gC/gN) + deadwdcn => pftcon%deadwdcn , & ! Input: dead wood C:N (gC/gN) + manunitro => pftcon%manunitro , & ! Input: max manure to be applied in total (kgN/m2) + mxmat => pftcon%mxmat , & ! Input: + minplanttemp => pftcon%minplanttemp , & ! Input: + planttemp => pftcon%planttemp , & ! Input: + gddmin => pftcon%gddmin , & ! Input: + hybgdd => pftcon%hybgdd , & ! Input: + grnfill => pftcon%grnfill , & ! Input: + lfmat => pftcon%lfmat , & ! Input: + grnrp => pftcon%grnrp , & ! Input: + transplant => pftcon%transplant , & ! Input: (O.Dombrowski) + woody => pftcon%woody , & ! Input: (O.Dombrowski) + season_decid => pftcon%season_decid , & ! Input: binary flag for seasonal-deciduous leaf habit (0 or 1) + baset => pftcon%baset , & ! Input: crop base temperature + ndays_stor => pftcon%ndays_stor , & ! Input: length of period for storage growth of fruit tree crops + crit_temp => pftcon%crit_temp , & ! Input: critical temperature to initiate leaf offset for fruit tree crops + crequ => pftcon%crequ , & ! Input: chilling requirements for fruit tree crops + + pftmayexist => dgvs_inst%pftmayexist_patch , & ! Output: [logical (:) ] exlude seasonal decid patches from tropics + + t_soisno => temperature_inst%t_soisno_col , & ! Input: [real(r8) (:,:) ] soil temperature (Kelvin) (-nlevsno+1:nlevgrnd) + + t_ref2m_min => temperature_inst%t_ref2m_min_patch , & ! Input: [real(r8) (:) ] daily minimum of average 2 m height surface air temperature (K) + t_ref2m_max => temperature_inst%t_ref2m_max_patch , & ! Input: [real(r8) (:) ] daily maximum of average 2 m height surface air temperature (K) + t_ref24 => temperature_inst%t_ref24_patch , & ! Input: [real(r8) (:) ] 24-hour averae 2 m air temperature (K) + t10 => temperature_inst%t_a10_patch , & ! Input: [real(r8) (:) ] 10-day running mean of the 2 m temperature (K) + a5tmin => temperature_inst%t_a5min_patch , & ! Input: [real(r8) (:) ] 5-day running mean of min 2-m temperature + a10tmin => temperature_inst%t_a10min_patch , & ! Input: [real(r8) (:) ] 10-day running mean of min 2-m temperature + gdd020 => temperature_inst%gdd020_patch , & ! Input: [real(r8) (:) ] 20 yr mean of gdd0 + gdd820 => temperature_inst%gdd820_patch , & ! Input: [real(r8) (:) ] 20 yr mean of gdd8 + gdd1020 => temperature_inst%gdd1020_patch , & ! Input: [real(r8) (:) ] 20 yr mean of gdd10 + + fertnitro => crop_inst%fertnitro_patch , & ! Input: [real(r8) (:) ] fertilizer nitrogen + hui => crop_inst%gddplant_patch , & ! Input: [real(r8) (:) ] gdd since planting (gddplant) + leafout => crop_inst%gddtsoi_patch , & ! Input: [real(r8) (:) ] gdd from top soil layer temperature + harvdate => crop_inst%harvdate_patch , & ! Output: [integer (:) ] harvest date + croplive => crop_inst%croplive_patch , & ! Output: [logical (:) ] Flag, true if planted, not harvested + cropplant => crop_inst%cropplant_patch , & ! Output: [logical (:) ] Flag, true if crop may be planted + vf => crop_inst%vf_patch , & ! Output: [real(r8) (:) ] vernalization factor + yrop => crop_inst%yrop_patch , & ! Output: [integer (:) ] year of planting (introduced in CLM-Palm (Fan et al. 2015), and adopted here by O.Dombrowski) + peaklai => cnveg_state_inst%peaklai_patch , & ! Output: [integer (:) ] 1: max allowed lai; 0: not at max + tlai => canopystate_inst%tlai_patch , & ! Input: [real(r8) (:) ] one-sided leaf area index, no burying by snow + + idop => cnveg_state_inst%idop_patch , & ! Output: [integer (:) ] date of planting + gddmaturity => cnveg_state_inst%gddmaturity_patch , & ! Output: [real(r8) (:) ] gdd needed to harvest + huileaf => cnveg_state_inst%huileaf_patch , & ! Output: [real(r8) (:) ] heat unit index at leaf emergence + huigrain => cnveg_state_inst%huigrain_patch , & ! Output: [real(r8) (:) ] heat unit index needed to reach start of fruit fill + huilfmat => cnveg_state_inst%huilfmat_patch , & ! Output: [real(r8) (:) ] heat unit index needed to reach canopy maturity (added by O.Dombrowski) + huiripe => cnveg_state_inst%huiripe_patch , & ! Output: [real(r8) (:) ] heat unit index needed to reach start of fruit cell expansion (added by O.Dombrowski) + bglfr => cnveg_state_inst%bglfr_patch , & ! Output: [real(r8) (:) ] background litterfall rate (1/s) + bgtr => cnveg_state_inst%bgtr_patch , & ! Output: [real(r8) (:) ] background transfer growth rate (1/s) + lgsf => cnveg_state_inst%lgsf_patch , & ! Output: [real(r8) (:) ] long growing season factor [0-1] + annavg_t2m => cnveg_state_inst%annavg_t2m_patch , & ! Input: [real(r8) (:) ] annual average 2m air temperature (K) + dormant_flag => cnveg_state_inst%dormant_flag_patch , & ! Output: [real(r8) (:) ] dormancy flag + days_active => cnveg_state_inst%days_active_patch , & ! Output: [real(r8) (:) ] number of days since last dormancy + onset_flag => cnveg_state_inst%onset_flag_patch , & ! Output: [real(r8) (:) ] onset flag + offset_flag => cnveg_state_inst%offset_flag_patch , & ! Output: [real(r8) (:) ] offset flag + offset2_flag => cnveg_state_inst%offset2_flag_patch , & ! Output: [real(r8) (:) ] orchard rotation flag + onset_counter => cnveg_state_inst%onset_counter_patch , & ! Output: [real(r8) (:) ] onset counter + offset_counter => cnveg_state_inst%offset_counter_patch , & ! Output: [real(r8) (:) ] offset counter + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop phenology (1=perennial, 0=not perennial) (introduced in CLM-Palm (Fan et al. 2015), and adopted here by O.Dombrowski) + harvest_flag => cnveg_state_inst%harvest_flag_patch , & ! Output: [real(r8) (:) ] harvest flag (introduced in CLM-Palm (Fan et al. 2015), and adopted here by O.Dombrowski) + prune_flag => cnveg_state_inst%prune_flag_patch , & ! Output: [real(r8) (:) ] pruning flag for perennials (introduced in CLM-Palm (Fan et al. 2015), and adopted here by O.Dombrowski) + storage_flag => cnveg_state_inst%storage_flag_patch , & ! Output: [real(r8) (:) ] flag to switch to storage growth for perennials (added by O.Dombrowski) + onset_gddflag => cnveg_state_inst%onset_gddflag_patch , & ! Output: [real(r8) (:) ] onset freeze flag + onset_gdd => cnveg_state_inst%onset_gdd_patch , & ! Output: [real(r8) (:) ] onset growing degree days + chill_day => cnveg_state_inst%chill_day_patch , & ! Output: [real(r8) (:) ] chilling days required for bud burst of fruit tree crops + anti_chill_day => cnveg_state_inst%anti_chill_day_patch , & ! Output: [real(r8) (:) ] anti-chill days required for bud burst of fruit tree crops + chill_flag => cnveg_state_inst%chill_flag_patch , & ! Output: [real(r8) (:) ] chill flag + + deadstemc => cnveg_carbonstate_inst%deadstemc_patch , & ! Input: [real(r8) (:) ] (gC/m2) deadstem C + leafc_storage => cnveg_carbonstate_inst%leafc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) leaf C storage + frootc_storage => cnveg_carbonstate_inst%frootc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) fine root C storage + livestemc_storage => cnveg_carbonstate_inst%livestemc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) live stem C storage + deadstemc_storage => cnveg_carbonstate_inst%deadstemc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) dead stem C storage + livecrootc_storage => cnveg_carbonstate_inst%livecrootc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) live coarse root C storage + deadcrootc_storage => cnveg_carbonstate_inst%deadcrootc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) dead coarse root C storage + gresp_storage => cnveg_carbonstate_inst%gresp_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) growth respiration storage + leafc_xfer => cnveg_carbonstate_inst%leafc_xfer_patch , & ! Output: [real(r8) (:) ] (gC/m2) leaf C transfer + frootc_xfer => cnveg_carbonstate_inst%frootc_xfer_patch , & ! Output: [real(r8) (:) ] (gC/m2) fine root C transfer + livestemc_xfer => cnveg_carbonstate_inst%livestemc_xfer_patch , & ! Output: [real(r8) (:) ] (gC/m2) live stem C transfer + deadstemc_xfer => cnveg_carbonstate_inst%deadstemc_xfer_patch , & ! Output: [real(r8) (:) ] (gC/m2) dead stem C transfer + livecrootc_xfer => cnveg_carbonstate_inst%livecrootc_xfer_patch , & ! Output: [real(r8) (:) ] (gC/m2) live coarse root C transfer + deadcrootc_xfer => cnveg_carbonstate_inst%deadcrootc_xfer_patch , & ! Output: [real(r8) (:) ] (gC/m2) dead coarse root C transfer + deadstemc_soy => cnveg_carbonstate_inst%deadstemc_soy_patch , & ! Output: [real(r8) (:) ] (gC/m2) dead stem C at start of year + deadstemc_storage_soy => cnveg_carbonstate_inst%deadstemc_storage_soy_patch , & ! Output: [real(r8) (:) ] (gC/m2) dead stem C storage at start of year + + + deadstemn => cnveg_nitrogenstate_inst%deadstemn_patch , & ! Input: [real(r8) (:) ] (gN/m2) deadstem N + leafn_storage => cnveg_nitrogenstate_inst%leafn_storage_patch , & ! Input: [real(r8) (:) ] (gN/m2) leaf N storage + frootn_storage => cnveg_nitrogenstate_inst%frootn_storage_patch , & ! Input: [real(r8) (:) ] (gN/m2) fine root N storage + livestemn_storage => cnveg_nitrogenstate_inst%livestemn_storage_patch , & ! Input: [real(r8) (:) ] (gN/m2) live stem N storage + deadstemn_storage => cnveg_nitrogenstate_inst%deadstemn_storage_patch , & ! Input: [real(r8) (:) ] (gN/m2) dead stem N storage + livecrootn_storage => cnveg_nitrogenstate_inst%livecrootn_storage_patch , & ! Input: [real(r8) (:) ] (gN/m2) live coarse root N storage + deadcrootn_storage => cnveg_nitrogenstate_inst%deadcrootn_storage_patch , & ! Input: [real(r8) (:) ] (gN/m2) dead coarse root N storage + leafn_xfer => cnveg_nitrogenstate_inst%leafn_xfer_patch , & ! Output: [real(r8) (:) ] (gN/m2) leaf N transfer + frootn_xfer => cnveg_nitrogenstate_inst%frootn_xfer_patch , & ! Output: [real(r8) (:) ] (gN/m2) fine root N transfer + livestemn_xfer => cnveg_nitrogenstate_inst%livestemn_xfer_patch , & ! Output: [real(r8) (:) ] (gN/m2) live stem N transfer + deadstemn_xfer => cnveg_nitrogenstate_inst%deadstemn_xfer_patch , & ! Output: [real(r8) (:) ] (gN/m2) dead stem N transfer + livecrootn_xfer => cnveg_nitrogenstate_inst%livecrootn_xfer_patch , & ! Output: [real(r8) (:) ] (gN/m2) live coarse root N transfer + deadcrootn_xfer => cnveg_nitrogenstate_inst%deadcrootn_xfer_patch , & ! Output: [real(r8) (:) ] (gN/m2) dead coarse root N transfer + deadstemn_soy => cnveg_nitrogenstate_inst%deadstemn_soy_patch , & ! Output: [real(r8) (:) ] (gN/m2) dead stem N at start of year + deadstemn_storage_soy => cnveg_nitrogenstate_inst%deadstemn_storage_soy_patch , & ! Output: [real(r8) (:) ] (gN/m2) dead stem N storage at start of year + + + prev_leafc_to_litter => cnveg_carbonflux_inst%prev_leafc_to_litter_patch , & ! Output: [real(r8) (:) ] previous timestep leaf C litterfall flux (gC/m2/s) + prev_frootc_to_litter => cnveg_carbonflux_inst%prev_frootc_to_litter_patch , & ! Output: [real(r8) (:) ] previous timestep froot C litterfall flux (gC/m2/s) + + leafc_xfer_to_leafc => cnveg_carbonflux_inst%leafc_xfer_to_leafc_patch , & ! Output: [real(r8) (:) ] + frootc_xfer_to_frootc => cnveg_carbonflux_inst%frootc_xfer_to_frootc_patch , & ! Output: [real(r8) (:) ] + livestemc_xfer_to_livestemc => cnveg_carbonflux_inst%livestemc_xfer_to_livestemc_patch , & ! Output: [real(r8) (:) ] + deadstemc_xfer_to_deadstemc => cnveg_carbonflux_inst%deadstemc_xfer_to_deadstemc_patch , & ! Output: [real(r8) (:) ] + livecrootc_xfer_to_livecrootc => cnveg_carbonflux_inst%livecrootc_xfer_to_livecrootc_patch , & ! Output: [real(r8) (:) ] + deadcrootc_xfer_to_deadcrootc => cnveg_carbonflux_inst%deadcrootc_xfer_to_deadcrootc_patch , & ! Output: [real(r8) (:) ] + leafc_storage_to_xfer => cnveg_carbonflux_inst%leafc_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + frootc_storage_to_xfer => cnveg_carbonflux_inst%frootc_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + livestemc_storage_to_xfer => cnveg_carbonflux_inst%livestemc_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + deadstemc_storage_to_xfer => cnveg_carbonflux_inst%deadstemc_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + livecrootc_storage_to_xfer => cnveg_carbonflux_inst%livecrootc_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + deadcrootc_storage_to_xfer => cnveg_carbonflux_inst%deadcrootc_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + gresp_storage_to_xfer => cnveg_carbonflux_inst%gresp_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + + leafn_xfer_to_leafn => cnveg_nitrogenflux_inst%leafn_xfer_to_leafn_patch , & ! Output: [real(r8) (:) ] + frootn_xfer_to_frootn => cnveg_nitrogenflux_inst%frootn_xfer_to_frootn_patch , & ! Output: [real(r8) (:) ] + livestemn_xfer_to_livestemn => cnveg_nitrogenflux_inst%livestemn_xfer_to_livestemn_patch , & ! Output: [real(r8) (:) ] + deadstemn_xfer_to_deadstemn => cnveg_nitrogenflux_inst%deadstemn_xfer_to_deadstemn_patch , & ! Output: [real(r8) (:) ] + livecrootn_xfer_to_livecrootn => cnveg_nitrogenflux_inst%livecrootn_xfer_to_livecrootn_patch , & ! Output: [real(r8) (:) ] + deadcrootn_xfer_to_deadcrootn => cnveg_nitrogenflux_inst%deadcrootn_xfer_to_deadcrootn_patch , & ! Output: [real(r8) (:) ] + leafn_storage_to_xfer => cnveg_nitrogenflux_inst%leafn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + frootn_storage_to_xfer => cnveg_nitrogenflux_inst%frootn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + livestemn_storage_to_xfer => cnveg_nitrogenflux_inst%livestemn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + deadstemn_storage_to_xfer => cnveg_nitrogenflux_inst%deadstemn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + livecrootn_storage_to_xfer => cnveg_nitrogenflux_inst%livecrootn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + deadcrootn_storage_to_xfer => cnveg_nitrogenflux_inst%deadcrootn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + + grainc => cnveg_carbonstate_inst%grainc_patch , & ! Input: [real(r8) (:) ] (gC/m2) grain C + + crop_seedc_to_leaf => cnveg_carbonflux_inst%crop_seedc_to_leaf_patch, & ! Output: [real(r8) (:) ] (gC/m2/s) seed source to leaf + crop_seedc_to_froot => cnveg_carbonflux_inst%crop_seedc_to_froot_patch, & ! Output: [real(r8) (:) ] (gC/m2/s) seed source to fine root + crop_seedc_to_deadstem => cnveg_carbonflux_inst%crop_seedc_to_deadstem_patch, & ! Output: [real(r8) (:) ] (gC/m2/s) seed source to deadstem + cropseedc_deficit => cnveg_carbonstate_inst%cropseedc_deficit_patch , & ! Output: [real(r8) (:) ] (gC/m2) crop seed C deficit + crop_seedn_to_leaf => cnveg_nitrogenflux_inst%crop_seedn_to_leaf_patch, & ! Output: [real(r8) (:) ] (gN/m2/s) seed source to leaf + crop_seedn_to_froot => cnveg_nitrogenflux_inst%crop_seedn_to_froot_patch, & ! Output: [real(r8) (:) ] (gN/m2/s) seed source to fine root + crop_seedn_to_deadstem => cnveg_nitrogenflux_inst%crop_seedn_to_deadstem_patch, & ! Output: [real(r8) (:) ] (gN/m2/s) seed source to deadstem + cropseedn_deficit => cnveg_nitrogenstate_inst%cropseedn_deficit_patch , & ! Output: [real(r8) (:) ] (gN/m2) crop seed N deficit + cphase => crop_inst%cphase_patch , & ! Output: [real(r8) (:)] phenology phase + fert_counter => cnveg_nitrogenflux_inst%fert_counter_patch , & ! Output: [real(r8) (:) ] >0 fertilize; <=0 not (seconds) + fert => cnveg_nitrogenflux_inst%fert_patch & ! Output: [real(r8) (:) ] (gN/m2/s) fertilizer applied each timestep + ) + + ! get time info + dayspyr = get_days_per_year() + jday = get_curr_calday() + call get_curr_date(kyr, kmo, kda, mcsec) + dtrad = real( get_rad_step_size(), r8 ) + + if (use_fertilizer) then + nfertdays_on = 20._r8 ! number of days to fertilize + else + nfertdays_on = 0._r8 ! number of days to fertilize + end if + + do fp = 1, num_pcropp + p = filter_pcropp(fp) + c = patch%column(p) + g = patch%gridcell(p) + h = inhemi(p) + + if (perennial(ivt(p)) == 1._r8) then ! flags for perennial crop phenology (added by O.Dombrowski) + + ! prepare planting if .not. croplive + if (.not. croplive(p)) then + cropplant(p) = .false. + idop(p) = NOT_PLANTED + end if + + ! background litterfall and transfer rates; long growing season factor + bglfr(p) = 0._r8 + bgtr(p) = 0._r8 + lgsf(p) = 0._r8 + + if (kmo == 1 .and. kda == 1 .and. mcsec == 0) then + ! get deadstem C and N at the start of the year + deadstemc_soy(p) = deadstemc(p) + deadstemc_storage_soy(p) = deadstemc_storage(p) + deadstemn_soy(p) = deadstemn(p) + deadstemn_storage_soy(p) = deadstemn_storage(p) + + end if + + if (season_decid(ivt(p)) == 1._r8) then + + ! set flag for solstice period (winter->summer = 1, summer->winter =0) + if (dayl(g) >= prev_dayl(g)) then + ws_flag = 1._r8 + else + ws_flag = 0._r8 + end if + + ! base temperature, or critical temperature for chill accumulation + tbase = baset(ivt(p)) + + ! set flag for start of chill period (chill_flag=1), + ! set latest date at which to initiate growing growing season even if chill/heat requirements are not met + if (h == 1) then ! for NH + if (kmo == 11 .and. kda == 1) then + chill_flag(p) = 1._r8 + end if + if (kmo == 7 .and. kda == 1 .and. chill_flag(p) == 1._r8) then + chill_day(p) = crequ(ivt(p)) + anti_chill_day(p) = -chill_day(p) + end if + else if (h == 2) then ! for SH + if (kmo == 5 .and. kda == 1) then + chill_flag(p) = 1._r8 + end if + if (kmo == 1 .and. kda == 1 .and. chill_flag(p) == 1._r8) then + chill_day(p) = crequ(ivt(p)) + anti_chill_day(p) = -chill_day(p) + end if + end if + end if + + ! Phase 1: Planting to leaf emergence + + if ( (.not. croplive(p)) .and. (.not. cropplant(p)) ) then + + if ((t10(p) /= spval.and. a10tmin(p) /= spval .and. & + t10(p) > planttemp(ivt(p)) .and. & + a10tmin(p) > minplanttemp(ivt(p)) .and. & + jday >= minplantjday(ivt(p),h) .and. & + jday <= maxplantjday(ivt(p),h) .and. & + t10(p) /= spval .and. a10tmin(p) /= spval .and. & + gdd820(p) /= spval .and. & + gdd820(p) >= gddmin(ivt(p))) .or. & + (jday == maxplantjday(ivt(p),h) .and. & + gdd820(p) > 0._r8 .and. & + gdd820(p) /= spval )) then + + + ! impose limit on growing season length needed + ! for crop maturity - for cold weather constraints + croplive(p) = .true. + cropplant(p) = .true. + idop(p) = jday + yrop(p) = kyr + harvdate(p) = NOT_Harvested + + ! Fruit trees are usually transplanted from nursery as small trees, code is adapted from the initiation for + ! deciduous trees and the transplanting of seedlings introduced in CLM-Palm (Fan et al. 2015), + ! initial gC m-2 is assigned to leaf, fine root and deadstem + ! (added by O.Dombrowski) + if (transplant(ivt(p)) > 0._r8) then + leafc_xfer(p) = transplant(ivt(p)) + else + leafc_xfer(p) = 1._r8 + end if + + frootc_xfer(p) = leafc_xfer(p) ! assign same amount of leafc to fine roots + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) ! with onset + frootn_xfer(p) = frootc_xfer(p) / frootcn(ivt(p)) + cropseedc_deficit(p) = cropseedc_deficit(p) - leafc_xfer(p) - frootc_xfer(p) + cropseedn_deficit(p) = cropseedn_deficit(p) - leafn_xfer(p) - frootn_xfer(p) + !for woody crops like fruit trees, assign 10% of initial C to deadstem + if (woody(ivt(p)) == 1._r8) then + deadstemc_xfer(p) = 0.1_r8*leafc_xfer(p) + deadstemn_xfer(p) = deadstemc_xfer(p)/deadwdcn(ivt(p)) + cropseedc_deficit(p) = cropseedc_deficit(p) - deadstemc_xfer(p) + cropseedn_deficit(p) = cropseedn_deficit(p) - deadstemn_xfer(p) + end if + end if + + + onset_counter(p) = 0.0_r8 ! CN terminology to trigger certain + offset_counter(p) = 0.0_r8 ! carbon and nitrogen transfers + onset_flag(p) = 0._r8 + offset_flag(p) = 0._r8 + offset2_flag(p) = 0._r8 + dormant_flag(p) = 1._r8 + + ! at planting of orchard, assume that chilling + ! requirements were already met in previous year and only + ! anti chill days need to be reached. + chill_day(p) = crequ(ivt(p)) + anti_chill_day(p) = 0._r8 + chill_flag(p) = 1._r8 + onset_gddflag(p) = 1._r8 + + harvest_flag(p) = 0._r8 ! annual harvest flag for perennial crops + end if ! crop not live nor planted + + ! ---------------------------------- + ! from AgroIBIS subroutine phenocrop + ! ---------------------------------- + + + if (croplive(p)) then + cphase(p) = 1._r8 + ! days past planting determine orchard rotation once maximum lifetime is reached + ! (introduced in CLM-Palm (Fan et al. 2015), and adopted here by O.Dombrowski) + idpp = int(dayspyr)*(kyr-yrop(p)) + jday - idop(p) + if (season_decid(ivt(p)) == 1._r8) then + + ! Test to turn on chill day accumulation. + ! If off, switch on chill day accumulation on + ! October 1st + if (onset_gddflag(p) == 0._r8 .and. chill_flag(p) == 1._r8) then + onset_gddflag(p) = 1._r8 + chill_day(p) = 0._r8 + anti_chill_day(p) = 0._r8 + end if + + ! Test to turn off chill day accumulation, if on. + ! This test resets the chill day accumulation if it gets past + ! May 1st without reaching the chill requirements. + ! In that case, it will take until the next autumn (October 1st) + ! before the chill day accumulation starts again. + + if (onset_gddflag(p) == 1._r8 .and. chill_flag(p) ==0._r8) then + onset_gddflag(p) = 0._r8 + chill_day(p) = 0._r8 + anti_chill_day(p) = 0._r8 + end if + + + ! if the gdd flag is set, and if the chill day + ! accumulation has not reached + ! chill requirements (crequ), accumulate chill days + ! for all equations temperatures must be in + ! degrees (C) + if (onset_gddflag(p) == 1._r8 .and. chill_day(p) > crequ(ivt(p))) then + if (t_ref2m_min(p) < 1.e30_r8) then + if (0._r8 <= tbase .and. tbase <= (t_ref2m_min(p)-tfrz) .and. t_ref2m_min(p)<= t_ref2m_max(p)) then + Cd = 0._r8 + else if (0._r8 <= (t_ref2m_min(p)-tfrz) .and. (t_ref2m_min(p)-tfrz)<= tbase .and. tbase < (t_ref2m_max(p)-tfrz)) then + Cd = -((t_ref24(p)-t_ref2m_min(p))-((t_ref2m_max(p)-tfrz)-tbase)**2/(2*(t_ref2m_max(p)-t_ref2m_min(p)))) + else if (0._r8 <= (t_ref2m_min(p)-tfrz) .and. t_ref2m_min(p) <= t_ref2m_max(p) .and. (t_ref2m_max(p)-tfrz) <= tbase) then + Cd = -(t_ref24(p)-t_ref2m_min(p)) + else if ((t_ref2m_min(p)-tfrz) < 0._r8 .and. 0._r8 <= (t_ref2m_max(p)-tfrz) .and. (t_ref2m_max(p)-tfrz) <= tbase) then + Cd = -((t_ref2m_max(p)-tfrz)**2/(2*(t_ref2m_max(p)-t_ref2m_min(p)))) + else if ((t_ref2m_min(p)-tfrz) < 0._r8 .and. 0._r8 < tbase .and. tbase < (t_ref2m_max(p)-tfrz)) then + Cd = -(t_ref2m_max(p)-tfrz)**2/(2*(t_ref2m_max(p)-t_ref2m_min(p))) - ((t_ref2m_max(p)-tfrz)-tbase)**2/(2*(t_ref2m_max(p)-t_ref2m_min(p))) + else + Cd = 0._r8 + end if + chill_day(p) = chill_day(p)+Cd + end if + end if + + ! if chill day accumulation has reached chill + ! requirements (crequ), accumulate anti chill days + if (onset_gddflag(p) == 1._r8 .and. chill_day(p) <= crequ(ivt(p))) then + if (t_ref2m_min(p) < 1.e30_r8) then + if (0._r8 <= tbase .and. tbase <= (t_ref2m_min(p)-tfrz) .and. t_ref2m_min(p) <= t_ref2m_max(p)) then + Ca = (t_ref24(p)-tfrz) - tbase + else if (0._r8 <= (t_ref2m_min(p)-tfrz) .and. (t_ref2m_min(p)-tfrz) <= tbase .and. tbase < (t_ref2m_max(p)-tfrz)) then + Ca = ((t_ref2m_max(p)-tfrz)-tbase)**2/(2*(t_ref2m_max(p)-t_ref2m_min(p))) + else if (0._r8 <= (t_ref2m_min(p)-tfrz) .and. t_ref2m_min(p) <= t_ref2m_max(p) .and. (t_ref2m_max(p)-tfrz) <= tbase) then + Ca = 0._r8 + else if ((t_ref2m_min(p)-tfrz) < 0._r8 .and. 0._r8 <= (t_ref2m_max(p)-tfrz) .and. (t_ref2m_max(p)-tfrz) <= tbase) then + Ca = 0._r8 + else if ((t_ref2m_min(p)-tfrz) < 0._r8 .and. 0._r8 < tbase .and. tbase < (t_ref2m_max(p)-tfrz)) then + Ca = ((t_ref2m_max(p)-tfrz)-tbase)**2/(2*(t_ref2m_max(p)-t_ref2m_min(p))) + else + Ca = 0._r8 + end if + anti_chill_day(p) = anti_chill_day(p)+Ca + end if + end if + + ! update offset_counter and test for the end of the offset period + if (offset_flag(p) == 1.0_r8) then + ! decrement counter for offset period + offset_counter(p) = offset_counter(p) - dt + prune_flag(p) = 1._r8 + + ! if this is the end of the offset_period, reset phenology + ! flags and indices + if (offset_counter(p) == 0.0_r8) then + offset_flag(p) = 0._r8 + offset_counter(p) = 0._r8 + dormant_flag(p) = 1._r8 + days_active(p) = 0._r8 + harvest_flag(p) = 0._r8 + storage_flag(p) = 0._r8 + if (use_cndv) then + pftmayexist(p) = .true. + end if + + ! reset the previous timestep litterfall flux memory + prev_leafc_to_litter(p) = 0._r8 + prev_frootc_to_litter(p) = 0._r8 + end if + end if + + ! update onset_counter and test for the end of the onset period + if (onset_flag(p) == 1.0_r8) then + ! decrement counter for onset period + onset_counter(p) = onset_counter(p) - dt + + ! if this is the end of the onset period, reset phenology + ! flags and indices + if (onset_counter(p) == 0.0_r8) then + onset_flag(p) = 0.0_r8 + onset_counter(p) = 0.0_r8 + ! set all transfer growth rates to 0.0 + leafc_xfer_to_leafc(p) = 0.0_r8 + frootc_xfer_to_frootc(p) = 0.0_r8 + leafn_xfer_to_leafn(p) = 0.0_r8 + frootn_xfer_to_frootn(p) = 0.0_r8 + if (woody(ivt(p)) == 1.0_r8) then + livestemc_xfer_to_livestemc(p) = 0.0_r8 + deadstemc_xfer_to_deadstemc(p) = 0.0_r8 + livecrootc_xfer_to_livecrootc(p) = 0.0_r8 + deadcrootc_xfer_to_deadcrootc(p) = 0.0_r8 + livestemn_xfer_to_livestemn(p) = 0.0_r8 + deadstemn_xfer_to_deadstemn(p) = 0.0_r8 + livecrootn_xfer_to_livecrootn(p) = 0.0_r8 + deadcrootn_xfer_to_deadcrootn(p) = 0.0_r8 + end if + ! set transfer pools to 0.0 + leafc_xfer(p) = 0.0_r8 + leafn_xfer(p) = 0.0_r8 + frootc_xfer(p) = 0.0_r8 + frootn_xfer(p) = 0.0_r8 + if (woody(ivt(p)) == 1.0_r8) then + livestemc_xfer(p) = 0.0_r8 + livestemn_xfer(p) = 0.0_r8 + deadstemc_xfer(p) = 0.0_r8 + deadstemn_xfer(p) = 0.0_r8 + livecrootc_xfer(p) = 0.0_r8 + livecrootn_xfer(p) = 0.0_r8 + deadcrootc_xfer(p) = 0.0_r8 + deadcrootn_xfer(p) = 0.0_r8 + end if + end if + end if + + ! test for switching from dormant period to growth period + if (dormant_flag(p) == 1._r8) then + ! Test if maximum orchard lifespan is reached and + ! orchard rotation should be initialized (adapted + ! based on CLM-Palm (Fan et al. 2015): + if (idpp >= mxmat(ivt(p))) then + croplive(p) = .false. + cphase(p) = 4._r8 + offset2_flag(p) = 1._r8 + end if + + prune_flag(p) = 0._r8 + + ! set onset_flag if critical growing degree-day sum is exceeded + if (anti_chill_day(p) > 0._r8 .and. anti_chill_day(p) >= (- chill_day(p))) then + cphase(p) = 2.0_r8 + + ! calculate gdd thresholds from bud burst (huileaf) + huileaf(p) = hui(p) + huigrain(p) = huileaf(p) + grnfill(ivt(p)) + huiripe(p) = huileaf(p) + grnrp(ivt(p)) + huilfmat(p) = huileaf(p) + lfmat(ivt(p)) + gddmaturity(p)= huileaf(p) + hybgdd(ivt(p)) + + ! reset parameters for bud burst calculation + chill_day(p) = 0._r8 + anti_chill_day(p) = 0._r8 + chill_flag(p) = 0._r8 + + onset_flag(p) = 1.0_r8 + dormant_flag(p) = 0.0_r8 + onset_gddflag(p) = 0.0_r8 + onset_gdd(p) = 0.0_r8 + onset_counter(p) = ndays_stor(ivt(p)) * secspday + + fert_counter(p) = nfertdays_on * secspday + if (nfertdays_on .gt. 0) then + fert(p) = (manunitro(ivt(p)) * 1000._r8 + fertnitro(p))/ fert_counter(p) + else + fert(p) = 0._r8 + end if + + ! move all the storage pools into transfer pools, + ! where they will be transfered to displayed growth over the onset period. + ! set carbon fluxes for shifting storage pools to transfer pools + leafc_storage_to_xfer(p) = fstor2tran * leafc_storage(p)/dt + frootc_storage_to_xfer(p) = fstor2tran * frootc_storage(p)/dt + if (woody(ivt(p)) == 1.0_r8) then + livestemc_storage_to_xfer(p) = fstor2tran * livestemc_storage(p)/dt + deadstemc_storage_to_xfer(p) = fstor2tran * deadstemc_storage(p)/dt + livecrootc_storage_to_xfer(p) = fstor2tran * livecrootc_storage(p)/dt + deadcrootc_storage_to_xfer(p) = fstor2tran * deadcrootc_storage(p)/dt + gresp_storage_to_xfer(p) = fstor2tran * gresp_storage(p)/dt + end if + + ! set nitrogen fluxes for shifting storage pools to transfer pools + leafn_storage_to_xfer(p) = fstor2tran * leafn_storage(p)/dt + frootn_storage_to_xfer(p) = fstor2tran * frootn_storage(p)/dt + if (woody(ivt(p)) == 1.0_r8) then + livestemn_storage_to_xfer(p) = fstor2tran * livestemn_storage(p)/dt + deadstemn_storage_to_xfer(p) = fstor2tran * deadstemn_storage(p)/dt + livecrootn_storage_to_xfer(p) = fstor2tran * livecrootn_storage(p)/dt + deadcrootn_storage_to_xfer(p) = fstor2tran * deadcrootn_storage(p)/dt + end if + end if + + ! test for switching from growth period to offset period + else if (dormant_flag(p) == 0.0_r8 .and. offset_flag(p) == 0.0_r8) then + if (use_cndv) then + ! If days_active > 355, then remove patch in + ! CNDVEstablishment at the end of the year. + ! days_active > 355 is a symptom of seasonal decid. patches + ! occurring in + ! gridcells where dayl never drops below crit_dayl. + ! This results in TLAI>1e4 in a few gridcells. + days_active(p) = days_active(p) + fracday + if (days_active(p) > 355._r8) pftmayexist(p) = .false. + end if + + ! other crop stages occur outside the dormancy period + if ((hui(p) >= gddmaturity(p) .and. idpp < mxmat(ivt(p))) .or. & + (jday >= maxharvjday(ivt(p),h) .and. idpp < mxmat(ivt(p)))) then + + if (tlai(p) <= 0._r8 .and. harvest_flag(p) == 0._r8) then ! plant never emerged or died + croplive(p) = .false. + if (harvdate(p) >= NOT_Harvested) harvdate(p) = jday + crop_seedc_to_leaf(p) = crop_seedc_to_leaf(p) - leafc_xfer(p)/dt + crop_seedc_to_froot(p) = crop_seedc_to_froot(p) - frootc_xfer(p)/dt + crop_seedn_to_leaf(p) = crop_seedn_to_leaf(p) - leafn_xfer(p)/dt + crop_seedn_to_froot(p) = crop_seedn_to_froot(p) - frootn_xfer(p)/dt + leafc_xfer(p) = 0._r8 ! revert planting transfers + frootc_xfer(p) = 0._r8 + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) + frootn_xfer(p) = frootc_xfer(p) / frootcn(ivt(p)) + if (woody(ivt(p)) == 1._r8) then + crop_seedc_to_deadstem(p) = crop_seedc_to_deadstem(p) - deadstemc_xfer(p)/dt + crop_seedn_to_deadstem(p) = crop_seedn_to_deadstem(p) - deadstemn_xfer(p)/dt + deadstemc_xfer(p) = 0._r8 + deadstemn_xfer(p) = deadstemc_xfer(p) / deadwdcn(ivt(p)) + end if + else if (grainc(p) > 0._r8) then !only harvest when there is positive grainc accumulated during grainfill, adapted based on CLM-Palm (Fan et al. 2015) + harvest_flag(p) = 1._r8 + storage_flag(p) = 1._r8 + end if + else + harvest_flag(p) = 0._r8 + end if + + if (idpp >= mxmat(ivt(p))) then + if (harvdate(p) >= NOT_Harvested) harvdate(p) = jday + croplive(p) = .false. + cphase(p) = 4._r8 + if (tlai(p) > 0._r8) then ! plant had emerged before rotation + offset2_flag(p) = 1._r8 + else ! plant never emerged from ground + crop_seedc_to_leaf(p) = crop_seedc_to_leaf(p) - leafc_xfer(p)/dt + crop_seedc_to_froot(p) = crop_seedc_to_froot(p) - frootc_xfer(p)/dt + crop_seedn_to_leaf(p) = crop_seedn_to_leaf(p) - leafn_xfer(p)/dt + crop_seedn_to_froot(p) = crop_seedn_to_froot(p) - frootn_xfer(p)/dt + leafc_xfer(p) = 0._r8 + frootc_xfer(p) = 0._r8 + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) + frootn_xfer(p) = frootc_xfer(p) / frootcn(ivt(p)) + if (woody(ivt(p)) == 1._r8) then + crop_seedc_to_deadstem(p) = crop_seedc_to_deadstem(p) - deadstemc_xfer(p)/dt + crop_seedn_to_deadstem(p) = crop_seedn_to_deadstem(p) - deadstemn_xfer(p)/dt + deadstemc_xfer(p) = 0._r8 + deadstemn_xfer(p) = deadstemc_xfer(p) / deadwdcn(ivt(p)) + end if + end if + end if ! idpp >=mxmat + + if (fert_counter(p) <= 0._r8) then + fert(p) = 0._r8 + else ! continue same fert application every timestep + fert_counter(p) = fert_counter(p) - dtrad + end if + + ! only begin to test for offset critical temperature once past the summer sol + if (ws_flag == 0._r8 .and. t_ref24(p) < crit_temp(ivt(p))) then + offset_flag(p) = 1._r8 + !storage_flag(p) = 0._r8 + offset_counter(p) = ndays_off * secspday + prev_leafc_to_litter(p) = 0._r8 + prev_frootc_to_litter(p) = 0._r8 + ! harvest grainc if crop not harvested yet + if (grainc(p) > 0._r8) harvest_flag(p) = 1._r8 + end if + end if ! dormant_flag == 1 + end if ! season_decid + + else ! crop not live + dormant_flag(p) = 1._r8 + onset_counter(p) = 0._r8 + ! the next lines conserve mass if leaf*/froot*/deadstem*_xfer > 0 due to interpinic. + ! We subtract from any existing value in crop_seedc_to_* / + ! crop_seedn_to_* in the unlikely event that we enter this block of + ! code in the same time step where the planting transfer originally + ! occurred. + crop_seedc_to_leaf(p) = crop_seedc_to_leaf(p) - leafc_xfer(p)/dt + crop_seedc_to_froot(p) = crop_seedc_to_froot(p) - frootc_xfer(p)/dt + crop_seedn_to_leaf(p) = crop_seedn_to_leaf(p) - leafn_xfer(p)/dt + crop_seedn_to_froot(p) = crop_seedn_to_froot(p) - frootn_xfer(p)/dt + leafc_xfer(p) = 0._r8 + frootc_xfer(p) = 0._r8 + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) + frootn_xfer(p) = frootc_xfer(p) / frootcn(ivt(p)) + if (woody(ivt(p)) == 1._r8) then + crop_seedc_to_deadstem(p) = crop_seedc_to_deadstem(p) - deadstemc_xfer(p)/dt + crop_seedn_to_deadstem(p) = crop_seedn_to_deadstem(p) - deadstemn_xfer(p)/dt + deadstemc_xfer(p) = 0._r8 + deadstemn_xfer(p) = deadstemc_xfer(p) / deadwdcn(ivt(p)) + end if + if (use_c13) then + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 + endif + if (use_c14) then + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 + endif + + end if ! croplive + end if ! end if perennial(ivt(p)) == 1._r8 + end do ! prognostic crops loop + + end associate + + end subroutine FruitTreePhenology + !----------------------------------------------------------------------- subroutine CropPhenology(num_pcropp, filter_pcropp , & waterstate_inst, temperature_inst, crop_inst, canopystate_inst, cnveg_state_inst , & @@ -1483,7 +2189,7 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & hybgdd => pftcon%hybgdd , & ! Input: lfemerg => pftcon%lfemerg , & ! Input: grnfill => pftcon%grnfill , & ! Input: - + perennial => pftcon%perennial , & ! Input: [integer (:) ] binary flag for perennial crop phenology (1=perennial, 0= not perennial) (added by O.Dombrowski) t_ref2m_min => temperature_inst%t_ref2m_min_patch , & ! Input: [real(r8) (:) ] daily minimum of average 2 m height surface air temperature (K) t10 => temperature_inst%t_a10_patch , & ! Input: [real(r8) (:) ] 10-day running mean of the 2 m temperature (K) a5tmin => temperature_inst%t_a5min_patch , & ! Input: [real(r8) (:) ] 5-day running mean of min 2-m temperature @@ -1514,8 +2220,7 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & onset_flag => cnveg_state_inst%onset_flag_patch , & ! Output: [real(r8) (:) ] onset flag offset_flag => cnveg_state_inst%offset_flag_patch , & ! Output: [real(r8) (:) ] offset flag onset_counter => cnveg_state_inst%onset_counter_patch , & ! Output: [real(r8) (:) ] onset counter - offset_counter => cnveg_state_inst%offset_counter_patch , & ! Output: [real(r8) (:) ] offset counter - + offset_counter => cnveg_state_inst%offset_counter_patch , & ! Output: [real(r8) (:) ] offset counter leafc_xfer => cnveg_carbonstate_inst%leafc_xfer_patch , & ! Output: [real(r8) (:) ] (gC/m2) leaf C transfer crop_seedc_to_leaf => cnveg_carbonflux_inst%crop_seedc_to_leaf_patch, & ! Output: [real(r8) (:) ] (gC/m2/s) seed source to leaf @@ -1545,485 +2250,485 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & g = patch%gridcell(p) h = inhemi(p) - ! background litterfall and transfer rates; long growing season factor - - bglfr(p) = 0._r8 ! this value changes later in a crop's life cycle - bgtr(p) = 0._r8 - lgsf(p) = 0._r8 - - ! --------------------------------- - ! from AgroIBIS subroutine planting - ! --------------------------------- - - ! in order to allow a crop to be planted only once each year - ! initialize cropplant = .false., but hold it = .true. through the end of the year - - ! initialize other variables that are calculated for crops - ! on an annual basis in cropresidue subroutine - - if ( jday == jdayyrstart(h) .and. mcsec == 0 )then - - ! make sure variables aren't changed at beginning of the year - ! for a crop that is currently planted, such as - ! WINTER TEMPERATE CEREAL = winter (wheat + barley + rye) - ! represented here by the winter wheat pft - - if (.not. croplive(p)) then - cropplant(p) = .false. - idop(p) = NOT_Planted - - ! keep next for continuous, annual winter temperate cereal crop; - ! if we removed elseif, - ! winter cereal grown continuously would amount to a cereal/fallow - ! rotation because cereal would only be planted every other year - - else if (croplive(p) .and. (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat)) then - cropplant(p) = .false. - ! else ! not possible to have croplive and ivt==cornORsoy? (slevis) - end if - - end if - - if ( (.not. croplive(p)) .and. (.not. cropplant(p)) ) then - - ! gdd needed for * chosen crop and a likely hybrid (for that region) * - ! to reach full physiological maturity - - ! based on accumulated seasonal average growing degree days from - ! April 1 - Sept 30 (inclusive) - ! for corn and soybeans in the United States - - ! decided upon by what the typical average growing season length is - ! and the gdd needed to reach maturity in those regions - - ! first choice is used for spring temperate cereal and/or soybeans and maize - - ! slevis: ibis reads xinpdate in io.f from control.crops.nc variable name 'plantdate' - ! According to Chris Kucharik, the dataset of - ! xinpdate was generated from a previous model run at 0.5 deg resolution - - ! winter temperate cereal : use gdd0 as a limit to plant winter cereal - - if (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat) then - - ! add check to only plant winter cereal after other crops (soybean, maize) - ! have been harvested - - ! *** remember order of planting is crucial - in terms of which crops you want - ! to be grown in what order *** - - ! in this case, corn or soybeans are assumed to be planted before - ! cereal would be in any particular year that both patches are allowed - ! to grow in the same grid cell (e.g., double-cropping) - - ! slevis: harvdate below needs cropplant(p) above to be cropplant(p,ivt(p)) - ! where ivt(p) has rotated to winter cereal because - ! cropplant through the end of the year for a harvested crop. - ! Also harvdate(p) should be harvdate(p,ivt(p)) and should be - ! updated on Jan 1st instead of at harvest (slevis) - if (a5tmin(p) /= spval .and. & - a5tmin(p) <= minplanttemp(ivt(p)) .and. & - jday >= minplantjday(ivt(p),h) .and. & - (gdd020(p) /= spval .and. & - gdd020(p) >= gddmin(ivt(p)))) then - - cumvd(p) = 0._r8 - hdidx(p) = 0._r8 - vf(p) = 0._r8 - croplive(p) = .true. - cropplant(p) = .true. - idop(p) = jday - harvdate(p) = NOT_Harvested - gddmaturity(p) = hybgdd(ivt(p)) - leafc_xfer(p) = initial_seed_at_planting - leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) ! with onset - crop_seedc_to_leaf(p) = leafc_xfer(p)/dt - crop_seedn_to_leaf(p) = leafn_xfer(p)/dt - - ! because leafc_xfer is set above rather than incremneted through the normal process, must also set its isotope - ! pools here. use totvegc_patch as the closest analogue if nonzero, and use initial value otherwise - if (use_c13) then - if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & - c13_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) - else - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c13ratio - endif - endif - if (use_c14) then - if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & - c14_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) - else - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c14ratio - endif - endif - - ! latest possible date to plant winter cereal and after all other - ! crops were harvested for that year - - else if (jday >= maxplantjday(ivt(p),h) .and. & - gdd020(p) /= spval .and. & - gdd020(p) >= gddmin(ivt(p))) then - - cumvd(p) = 0._r8 - hdidx(p) = 0._r8 - vf(p) = 0._r8 - croplive(p) = .true. - cropplant(p) = .true. - idop(p) = jday - harvdate(p) = NOT_Harvested - gddmaturity(p) = hybgdd(ivt(p)) - leafc_xfer(p) = initial_seed_at_planting - leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) ! with onset - crop_seedc_to_leaf(p) = leafc_xfer(p)/dt - crop_seedn_to_leaf(p) = leafn_xfer(p)/dt - - ! because leafc_xfer is set above rather than incremneted through the normal process, must also set its isotope - ! pools here. use totvegc_patch as the closest analogue if nonzero, and use initial value otherwise - if (use_c13) then - if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & - c13_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) - else - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c13ratio - endif - endif - if (use_c14) then - if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & - c14_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) - else - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c14ratio - endif - endif - else - gddmaturity(p) = 0._r8 - end if - - else ! not winter cereal... slevis: added distinction between NH and SH - ! slevis: The idea is that jday will equal idop sooner or later in the year - ! while the gdd part is either true or false for the year. - if (t10(p) /= spval.and. a10tmin(p) /= spval .and. & - t10(p) > planttemp(ivt(p)) .and. & - a10tmin(p) > minplanttemp(ivt(p)) .and. & - jday >= minplantjday(ivt(p),h) .and. & - jday <= maxplantjday(ivt(p),h) .and. & - t10(p) /= spval .and. a10tmin(p) /= spval .and. & - gdd820(p) /= spval .and. & - gdd820(p) >= gddmin(ivt(p))) then - - ! impose limit on growing season length needed - ! for crop maturity - for cold weather constraints - croplive(p) = .true. - cropplant(p) = .true. - idop(p) = jday - harvdate(p) = NOT_Harvested - - ! go a specified amount of time before/after - ! climatological date - if (ivt(p) == ntmp_soybean .or. ivt(p) == nirrig_tmp_soybean .or. & - ivt(p) == ntrp_soybean .or. ivt(p) == nirrig_trp_soybean) then - gddmaturity(p) = min(gdd1020(p), hybgdd(ivt(p))) - end if - if (ivt(p) == ntmp_corn .or. ivt(p) == nirrig_tmp_corn .or. & - ivt(p) == ntrp_corn .or. ivt(p) == nirrig_trp_corn .or. & - ivt(p) == nsugarcane .or. ivt(p) == nirrig_sugarcane) then - gddmaturity(p) = max(950._r8, min(gdd820(p)*0.85_r8, hybgdd(ivt(p)))) - gddmaturity(p) = max(950._r8, min(gddmaturity(p)+150._r8, 1850._r8)) - end if - if (ivt(p) == nswheat .or. ivt(p) == nirrig_swheat .or. & - ivt(p) == ncotton .or. ivt(p) == nirrig_cotton .or. & - ivt(p) == nrice .or. ivt(p) == nirrig_rice) then - gddmaturity(p) = min(gdd020(p), hybgdd(ivt(p))) - end if - - leafc_xfer(p) = initial_seed_at_planting - leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) ! with onset - crop_seedc_to_leaf(p) = leafc_xfer(p)/dt - crop_seedn_to_leaf(p) = leafn_xfer(p)/dt - - ! because leafc_xfer is set above rather than incremneted through the normal process, must also set its isotope - ! pools here. use totvegc_patch as the closest analogue if nonzero, and use initial value otherwise - if (use_c13) then - if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & - c13_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) - else - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c13ratio - endif - endif - if (use_c14) then - if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & - c14_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) - else - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c14ratio - endif - endif - - - ! If hit the max planting julian day -- go ahead and plant - else if (jday == maxplantjday(ivt(p),h) .and. gdd820(p) > 0._r8 .and. & - gdd820(p) /= spval ) then - croplive(p) = .true. - cropplant(p) = .true. - idop(p) = jday - harvdate(p) = NOT_Harvested + if (perennial(ivt(p)) == 0._r8) then + ! background litterfall and transfer rates; long growing season factor + bglfr(p) = 0._r8 ! this value changes later in a crop's life cycle + bgtr(p) = 0._r8 + lgsf(p) = 0._r8 - if (ivt(p) == ntmp_soybean .or. ivt(p) == nirrig_tmp_soybean .or. & - ivt(p) == ntrp_soybean .or. ivt(p) == nirrig_trp_soybean) then - gddmaturity(p) = min(gdd1020(p), hybgdd(ivt(p))) - end if - if (ivt(p) == ntmp_corn .or. ivt(p) == nirrig_tmp_corn .or. & - ivt(p) == ntrp_corn .or. ivt(p) == nirrig_trp_corn .or. & - ivt(p) == nsugarcane .or. ivt(p) == nirrig_sugarcane) then - gddmaturity(p) = max(950._r8, min(gdd820(p)*0.85_r8, hybgdd(ivt(p)))) - end if - if (ivt(p) == nswheat .or. ivt(p) == nirrig_swheat .or. & - ivt(p) == ncotton .or. ivt(p) == nirrig_cotton .or. & - ivt(p) == nrice .or. ivt(p) == nirrig_rice) then - gddmaturity(p) = min(gdd020(p), hybgdd(ivt(p))) - end if - - leafc_xfer(p) = initial_seed_at_planting - leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) ! with onset - crop_seedc_to_leaf(p) = leafc_xfer(p)/dt - crop_seedn_to_leaf(p) = leafn_xfer(p)/dt - - ! because leafc_xfer is set above rather than incremneted through the normal process, must also set its isotope - ! pools here. use totvegc_patch as the closest analogue if nonzero, and use initial value otherwise - if (use_c13) then - if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & - c13_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) - else - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c13ratio - endif - endif - if (use_c14) then - if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & - c14_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) - else - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c14ratio - endif - endif - - else - gddmaturity(p) = 0._r8 - end if - end if ! crop patch distinction - - ! crop phenology (gdd thresholds) controlled by gdd needed for - ! maturity (physiological) which is based on the average gdd - ! accumulation and hybrids in United States from April 1 - Sept 30 - - ! calculate threshold from phase 1 to phase 2: - ! threshold for attaining leaf emergence (based on fraction of - ! gdd(i) -- climatological average) - ! Hayhoe and Dwyer, 1990, Can. J. Soil Sci 70:493-497 - ! Carlson and Gage, 1989, Agric. For. Met., 45: 313-324 - ! J.T. Ritchie, 1991: Modeling Plant and Soil systems - - huileaf(p) = lfemerg(ivt(p)) * gddmaturity(p) ! 3-7% in cereal - - ! calculate threshhold from phase 2 to phase 3: - ! from leaf emergence to beginning of grain-fill period - ! this hypothetically occurs at the end of tassling, not the beginning - ! tassel initiation typically begins at 0.5-0.55 * gddmaturity - - ! calculate linear relationship between huigrain fraction and relative - ! maturity rating for maize - - if (ivt(p) == ntmp_corn .or. ivt(p) == nirrig_tmp_corn .or. & - ivt(p) == ntrp_corn .or. ivt(p) == nirrig_trp_corn .or. & - ivt(p) == nsugarcane .or. ivt(p) == nirrig_sugarcane) then - ! the following estimation of crmcorn from gddmaturity is based on a linear - ! regression using data from Pioneer-brand corn hybrids (Kucharik, 2003, - ! Earth Interactions 7:1-33: fig. 2) - crmcorn = max(73._r8, min(135._r8, (gddmaturity(p)+ 53.683_r8)/13.882_r8)) - - ! the following adjustment of grnfill based on crmcorn is based on a tuning - ! of Agro-IBIS to give reasonable results for max LAI and the seasonal - ! progression of LAI growth (pers. comm. C. Kucharik June 10, 2010) - huigrain(p) = -0.002_r8 * (crmcorn - 73._r8) + grnfill(ivt(p)) - - huigrain(p) = min(max(huigrain(p), grnfill(ivt(p))-0.1_r8), grnfill(ivt(p))) - huigrain(p) = huigrain(p) * gddmaturity(p) ! Cabelguenne et - else - huigrain(p) = grnfill(ivt(p)) * gddmaturity(p) ! al. 1999 - end if + ! --------------------------------- + ! from AgroIBIS subroutine planting + ! --------------------------------- - end if ! crop not live nor planted - - ! ---------------------------------- - ! from AgroIBIS subroutine phenocrop - ! ---------------------------------- - - ! all of the phenology changes are based on the total number of gdd needed - ! to change to the next phase - based on fractions of the total gdd typical - ! for that region based on the April 1 - Sept 30 window of development - - ! crop phenology (gdd thresholds) controlled by gdd needed for - ! maturity (physiological) which is based on the average gdd - ! accumulation and hybrids in United States from April 1 - Sept 30 - - ! Phase 1: Planting to leaf emergence (now in CNAllocation) - ! Phase 2: Leaf emergence to beginning of grain fill (general LAI accumulation) - ! Phase 3: Grain fill to physiological maturity and harvest (LAI decline) - ! Harvest: if gdd past grain fill initiation exceeds limit - ! or number of days past planting reaches a maximum, the crop has - ! reached physiological maturity and plant is harvested; - ! crop could be live or dead at this stage - these limits - ! could lead to reaching physiological maturity or determining - ! a harvest date for a crop killed by an early frost (see next comments) - ! --- --- --- - ! keeping comments without the code (slevis): - ! if minimum temperature, t_ref2m_min <= freeze kill threshold, tkill - ! for 3 consecutive days and lai is above a minimum, - ! plant will be damaged/killed. This function is more for spring freeze events - ! or for early fall freeze events - - ! spring temperate cereal is affected by this, winter cereal kill function - ! is determined in crops.f - is a more elaborate function of - ! cold hardening of the plant - - ! currently simulates too many grid cells killed by freezing temperatures - - ! removed on March 12 2002 - C. Kucharik - ! until it can be a bit more refined, or used at a smaller scale. - ! we really have no way of validating this routine - ! too difficult to implement on 0.5 degree scale grid cells - ! --- --- --- - - onset_flag(p) = 0._r8 ! CN terminology to trigger certain - offset_flag(p) = 0._r8 ! carbon and nitrogen transfers - - if (croplive(p)) then - cphase(p) = 1._r8 - - ! call vernalization if winter temperate cereal planted, living, and the - ! vernalization factor is not 1; - ! vf affects the calculation of gddtsoi & gddplant - - if (t_ref2m_min(p) < 1.e30_r8 .and. vf(p) /= 1._r8 .and. & - (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat)) then - call vernalization(p, & - canopystate_inst, temperature_inst, waterstate_inst, cnveg_state_inst, & - crop_inst) - end if + ! in order to allow a crop to be planted only once each year + ! initialize cropplant = .false., but hold it = .true. through the end of the year - ! days past planting may determine harvest + ! initialize other variables that are calculated for crops + ! on an annual basis in cropresidue subroutine - if (jday >= idop(p)) then - idpp = jday - idop(p) - else - idpp = int(dayspyr) + jday - idop(p) - end if + if ( jday == jdayyrstart(h) .and. mcsec == 0 )then - ! onset_counter initialized to zero when .not. croplive - ! offset_counter relevant only at time step of harvest + ! make sure variables aren't changed at beginning of the year + ! for a crop that is currently planted, such as + ! WINTER TEMPERATE CEREAL = winter (wheat + barley + rye) + ! represented here by the winter wheat pft - onset_counter(p) = onset_counter(p) - dt + if (.not. croplive(p)) then + cropplant(p) = .false. + idop(p) = NOT_Planted - ! enter phase 2 onset for one time step: - ! transfer seed carbon to leaf emergence + ! keep next for continuous, annual winter temperate cereal crop; + ! if we removed elseif, + ! winter cereal grown continuously would amount to a cereal/fallow + ! rotation because cereal would only be planted every other year - if (peaklai(p) >= 1) then - hui(p) = max(hui(p),huigrain(p)) - endif + else if (croplive(p) .and. (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat)) then + cropplant(p) = .false. + ! else ! not possible to have croplive and ivt==cornORsoy? (slevis) + end if - if (leafout(p) >= huileaf(p) .and. hui(p) < huigrain(p) .and. idpp < mxmat(ivt(p))) then - cphase(p) = 2._r8 - if (abs(onset_counter(p)) > 1.e-6_r8) then - onset_flag(p) = 1._r8 - onset_counter(p) = dt - fert_counter(p) = ndays_on * secspday - if (ndays_on .gt. 0) then - fert(p) = (manunitro(ivt(p)) * 1000._r8 + fertnitro(p))/ fert_counter(p) + end if + + if ( (.not. croplive(p)) .and. (.not. cropplant(p)) ) then + + ! gdd needed for * chosen crop and a likely hybrid (for that region) * + ! to reach full physiological maturity + + ! based on accumulated seasonal average growing degree days from + ! April 1 - Sept 30 (inclusive) + ! for corn and soybeans in the United States - + ! decided upon by what the typical average growing season length is + ! and the gdd needed to reach maturity in those regions + + ! first choice is used for spring temperate cereal and/or soybeans and maize + + ! slevis: ibis reads xinpdate in io.f from control.crops.nc variable name 'plantdate' + ! According to Chris Kucharik, the dataset of + ! xinpdate was generated from a previous model run at 0.5 deg resolution + + ! winter temperate cereal : use gdd0 as a limit to plant winter cereal + + if (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat) then + + ! add check to only plant winter cereal after other crops (soybean, maize) + ! have been harvested + + ! *** remember order of planting is crucial - in terms of which crops you want + ! to be grown in what order *** + + ! in this case, corn or soybeans are assumed to be planted before + ! cereal would be in any particular year that both patches are allowed + ! to grow in the same grid cell (e.g., double-cropping) + + ! slevis: harvdate below needs cropplant(p) above to be cropplant(p,ivt(p)) + ! where ivt(p) has rotated to winter cereal because + ! cropplant through the end of the year for a harvested crop. + ! Also harvdate(p) should be harvdate(p,ivt(p)) and should be + ! updated on Jan 1st instead of at harvest (slevis) + if (a5tmin(p) /= spval .and. & + a5tmin(p) <= minplanttemp(ivt(p)) .and. & + jday >= minplantjday(ivt(p),h) .and. & + (gdd020(p) /= spval .and. & + gdd020(p) >= gddmin(ivt(p)))) then + + cumvd(p) = 0._r8 + hdidx(p) = 0._r8 + vf(p) = 0._r8 + croplive(p) = .true. + cropplant(p) = .true. + idop(p) = jday + harvdate(p) = NOT_Harvested + gddmaturity(p) = hybgdd(ivt(p)) + leafc_xfer(p) = initial_seed_at_planting + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) ! with onset + crop_seedc_to_leaf(p) = leafc_xfer(p)/dt + crop_seedn_to_leaf(p) = leafn_xfer(p)/dt + + ! because leafc_xfer is set above rather than incremneted through the normal process, must also set its isotope + ! pools here. use totvegc_patch as the closest analogue if nonzero, and use initial value otherwise + if (use_c13) then + if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & + c13_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) + else + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c13ratio + endif + endif + if (use_c14) then + if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & + c14_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) + else + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c14ratio + endif + endif + + ! latest possible date to plant winter cereal and after all other + ! crops were harvested for that year + + else if (jday >= maxplantjday(ivt(p),h) .and. & + gdd020(p) /= spval .and. & + gdd020(p) >= gddmin(ivt(p))) then + + cumvd(p) = 0._r8 + hdidx(p) = 0._r8 + vf(p) = 0._r8 + croplive(p) = .true. + cropplant(p) = .true. + idop(p) = jday + harvdate(p) = NOT_Harvested + gddmaturity(p) = hybgdd(ivt(p)) + leafc_xfer(p) = initial_seed_at_planting + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) ! with onset + crop_seedc_to_leaf(p) = leafc_xfer(p)/dt + crop_seedn_to_leaf(p) = leafn_xfer(p)/dt + + ! because leafc_xfer is set above rather than incremneted through the normal process, must also set its isotope + ! pools here. use totvegc_patch as the closest analogue if nonzero, and use initial value otherwise + if (use_c13) then + if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & + c13_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) + else + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c13ratio + endif + endif + if (use_c14) then + if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & + c14_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) + else + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c14ratio + endif + endif + else + gddmaturity(p) = 0._r8 + end if + + else ! not winter cereal... slevis: added distinction between NH and SH + ! slevis: The idea is that jday will equal idop sooner or later in the year + ! while the gdd part is either true or false for the year. + if (t10(p) /= spval.and. a10tmin(p) /= spval .and. & + t10(p) > planttemp(ivt(p)) .and. & + a10tmin(p) > minplanttemp(ivt(p)) .and. & + jday >= minplantjday(ivt(p),h) .and. & + jday <= maxplantjday(ivt(p),h) .and. & + t10(p) /= spval .and. a10tmin(p) /= spval .and. & + gdd820(p) /= spval .and. & + gdd820(p) >= gddmin(ivt(p))) then + + ! impose limit on growing season length needed + ! for crop maturity - for cold weather constraints + croplive(p) = .true. + cropplant(p) = .true. + idop(p) = jday + harvdate(p) = NOT_Harvested + + ! go a specified amount of time before/after + ! climatological date + if (ivt(p) == ntmp_soybean .or. ivt(p) == nirrig_tmp_soybean .or. & + ivt(p) == ntrp_soybean .or. ivt(p) == nirrig_trp_soybean) then + gddmaturity(p) = min(gdd1020(p), hybgdd(ivt(p))) + end if + if (ivt(p) == ntmp_corn .or. ivt(p) == nirrig_tmp_corn .or. & + ivt(p) == ntrp_corn .or. ivt(p) == nirrig_trp_corn .or. & + ivt(p) == nsugarcane .or. ivt(p) == nirrig_sugarcane) then + gddmaturity(p) = max(950._r8, min(gdd820(p)*0.85_r8, hybgdd(ivt(p)))) + gddmaturity(p) = max(950._r8, min(gddmaturity(p)+150._r8, 1850._r8)) + end if + if (ivt(p) == nswheat .or. ivt(p) == nirrig_swheat .or. & + ivt(p) == ncotton .or. ivt(p) == nirrig_cotton .or. & + ivt(p) == nrice .or. ivt(p) == nirrig_rice) then + gddmaturity(p) = min(gdd020(p), hybgdd(ivt(p))) + end if + + leafc_xfer(p) = initial_seed_at_planting + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) ! with onset + crop_seedc_to_leaf(p) = leafc_xfer(p)/dt + crop_seedn_to_leaf(p) = leafn_xfer(p)/dt + + ! because leafc_xfer is set above rather than incremneted through the normal process, must also set its isotope + ! pools here. use totvegc_patch as the closest analogue if nonzero, and use initial value otherwise + if (use_c13) then + if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & + c13_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) + else + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c13ratio + endif + endif + if (use_c14) then + if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & + c14_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) + else + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c14ratio + endif + endif + + + ! If hit the max planting julian day -- go ahead and plant + else if (jday == maxplantjday(ivt(p),h) .and. gdd820(p) > 0._r8 .and. & + gdd820(p) /= spval ) then + croplive(p) = .true. + cropplant(p) = .true. + idop(p) = jday + harvdate(p) = NOT_Harvested + + if (ivt(p) == ntmp_soybean .or. ivt(p) == nirrig_tmp_soybean .or. & + ivt(p) == ntrp_soybean .or. ivt(p) == nirrig_trp_soybean) then + gddmaturity(p) = min(gdd1020(p), hybgdd(ivt(p))) + end if + if (ivt(p) == ntmp_corn .or. ivt(p) == nirrig_tmp_corn .or. & + ivt(p) == ntrp_corn .or. ivt(p) == nirrig_trp_corn .or. & + ivt(p) == nsugarcane .or. ivt(p) == nirrig_sugarcane) then + gddmaturity(p) = max(950._r8, min(gdd820(p)*0.85_r8, hybgdd(ivt(p)))) + end if + if (ivt(p) == nswheat .or. ivt(p) == nirrig_swheat .or. & + ivt(p) == ncotton .or. ivt(p) == nirrig_cotton .or. & + ivt(p) == nrice .or. ivt(p) == nirrig_rice) then + gddmaturity(p) = min(gdd020(p), hybgdd(ivt(p))) + end if + + leafc_xfer(p) = initial_seed_at_planting + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) ! with onset + crop_seedc_to_leaf(p) = leafc_xfer(p)/dt + crop_seedn_to_leaf(p) = leafn_xfer(p)/dt + + ! because leafc_xfer is set above rather than incremneted through the normal process, must also set its isotope + ! pools here. use totvegc_patch as the closest analogue if nonzero, and use initial value otherwise + if (use_c13) then + if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & + c13_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) + else + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c13ratio + endif + endif + if (use_c14) then + if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & + c14_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) + else + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c14ratio + endif + endif + + else + gddmaturity(p) = 0._r8 + end if + end if ! crop patch distinction + + ! crop phenology (gdd thresholds) controlled by gdd needed for + ! maturity (physiological) which is based on the average gdd + ! accumulation and hybrids in United States from April 1 - Sept 30 + + ! calculate threshold from phase 1 to phase 2: + ! threshold for attaining leaf emergence (based on fraction of + ! gdd(i) -- climatological average) + ! Hayhoe and Dwyer, 1990, Can. J. Soil Sci 70:493-497 + ! Carlson and Gage, 1989, Agric. For. Met., 45: 313-324 + ! J.T. Ritchie, 1991: Modeling Plant and Soil systems + + huileaf(p) = lfemerg(ivt(p)) * gddmaturity(p) ! 3-7% in cereal + + ! calculate threshhold from phase 2 to phase 3: + ! from leaf emergence to beginning of grain-fill period + ! this hypothetically occurs at the end of tassling, not the beginning + ! tassel initiation typically begins at 0.5-0.55 * gddmaturity + + ! calculate linear relationship between huigrain fraction and relative + ! maturity rating for maize + + if (ivt(p) == ntmp_corn .or. ivt(p) == nirrig_tmp_corn .or. & + ivt(p) == ntrp_corn .or. ivt(p) == nirrig_trp_corn .or. & + ivt(p) == nsugarcane .or. ivt(p) == nirrig_sugarcane) then + ! the following estimation of crmcorn from gddmaturity is based on a linear + ! regression using data from Pioneer-brand corn hybrids (Kucharik, 2003, + ! Earth Interactions 7:1-33: fig. 2) + crmcorn = max(73._r8, min(135._r8, (gddmaturity(p)+ 53.683_r8)/13.882_r8)) + + ! the following adjustment of grnfill based on crmcorn is based on a tuning + ! of Agro-IBIS to give reasonable results for max LAI and the seasonal + ! progression of LAI growth (pers. comm. C. Kucharik June 10, 2010) + huigrain(p) = -0.002_r8 * (crmcorn - 73._r8) + grnfill(ivt(p)) + + huigrain(p) = min(max(huigrain(p), grnfill(ivt(p))-0.1_r8), grnfill(ivt(p))) + huigrain(p) = huigrain(p) * gddmaturity(p) ! Cabelguenne et else - fert(p) = 0._r8 + huigrain(p) = grnfill(ivt(p)) * gddmaturity(p) ! al. 1999 end if - else - ! this ensures no re-entry to onset of phase2 - ! b/c onset_counter(p) = onset_counter(p) - dt - ! at every time step - - onset_counter(p) = dt - end if - ! enter harvest for one time step: - ! - transfer live biomass to litter and to crop yield - ! - send xsmrpool to the atmosphere - ! if onset and harvest needed to last longer than one timestep - ! the onset_counter would change from dt and you'd need to make - ! changes to the offset subroutine below - - else if (hui(p) >= gddmaturity(p) .or. idpp >= mxmat(ivt(p))) then - if (harvdate(p) >= NOT_Harvested) harvdate(p) = jday - croplive(p) = .false. ! no re-entry in greater if-block - cphase(p) = 4._r8 - if (tlai(p) > 0._r8) then ! plant had emerged before harvest - offset_flag(p) = 1._r8 - offset_counter(p) = dt - else ! plant never emerged from the ground - ! Revert planting transfers; this will replenish the crop seed deficit. - ! We subtract from any existing value in crop_seedc_to_leaf / - ! crop_seedn_to_leaf in the unlikely event that we enter this block of - ! code in the same time step where the planting transfer originally - ! occurred. - crop_seedc_to_leaf(p) = crop_seedc_to_leaf(p) - leafc_xfer(p)/dt - crop_seedn_to_leaf(p) = crop_seedn_to_leaf(p) - leafn_xfer(p)/dt - leafc_xfer(p) = 0._r8 - leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) - if (use_c13) then - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 - endif - if (use_c14) then - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 - endif - - end if - - ! enter phase 3 while previous criteria fail and next is true; - ! in terms of order, phase 3 occurs before harvest, but when - ! harvest *can* occur, we want it to have first priority. - ! AgroIBIS uses a complex formula for lai decline. - ! Use CN's simple formula at least as a place holder (slevis) - - else if (hui(p) >= huigrain(p)) then - cphase(p) = 3._r8 - bglfr(p) = 1._r8/(leaf_long(ivt(p))*dayspyr*secspday) - end if + end if ! crop not live nor planted + + ! ---------------------------------- + ! from AgroIBIS subroutine phenocrop + ! ---------------------------------- + + ! all of the phenology changes are based on the total number of gdd needed + ! to change to the next phase - based on fractions of the total gdd typical + ! for that region based on the April 1 - Sept 30 window of development + + ! crop phenology (gdd thresholds) controlled by gdd needed for + ! maturity (physiological) which is based on the average gdd + ! accumulation and hybrids in United States from April 1 - Sept 30 + + ! Phase 1: Planting to leaf emergence (now in CNAllocation) + ! Phase 2: Leaf emergence to beginning of grain fill (general LAI accumulation) + ! Phase 3: Grain fill to physiological maturity and harvest (LAI decline) + ! Harvest: if gdd past grain fill initiation exceeds limit + ! or number of days past planting reaches a maximum, the crop has + ! reached physiological maturity and plant is harvested; + ! crop could be live or dead at this stage - these limits + ! could lead to reaching physiological maturity or determining + ! a harvest date for a crop killed by an early frost (see next comments) + ! --- --- --- + ! keeping comments without the code (slevis): + ! if minimum temperature, t_ref2m_min <= freeze kill threshold, tkill + ! for 3 consecutive days and lai is above a minimum, + ! plant will be damaged/killed. This function is more for spring freeze events + ! or for early fall freeze events + + ! spring temperate cereal is affected by this, winter cereal kill function + ! is determined in crops.f - is a more elaborate function of + ! cold hardening of the plant + + ! currently simulates too many grid cells killed by freezing temperatures + + ! removed on March 12 2002 - C. Kucharik + ! until it can be a bit more refined, or used at a smaller scale. + ! we really have no way of validating this routine + ! too difficult to implement on 0.5 degree scale grid cells + ! --- --- --- + + onset_flag(p) = 0._r8 ! CN terminology to trigger certain + offset_flag(p) = 0._r8 ! carbon and nitrogen transfers + + if (croplive(p)) then + cphase(p) = 1._r8 + + ! call vernalization if winter temperate cereal planted, living, and the + ! vernalization factor is not 1; + ! vf affects the calculation of gddtsoi & gddplant + + if (t_ref2m_min(p) < 1.e30_r8 .and. vf(p) /= 1._r8 .and. & + (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat)) then + call vernalization(p, & + canopystate_inst, temperature_inst, waterstate_inst, cnveg_state_inst, & + crop_inst) + end if - ! continue fertilizer application while in phase 2; - ! assumes that onset of phase 2 took one time step only + ! days past planting may determine harvest - if (fert_counter(p) <= 0._r8) then - fert(p) = 0._r8 - else ! continue same fert application every timestep - fert_counter(p) = fert_counter(p) - dtrad - end if + if (jday >= idop(p)) then + idpp = jday - idop(p) + else + idpp = int(dayspyr) + jday - idop(p) + end if - else ! crop not live - ! next 2 lines conserve mass if leaf*_xfer > 0 due to interpinic. - ! We subtract from any existing value in crop_seedc_to_leaf / - ! crop_seedn_to_leaf in the unlikely event that we enter this block of - ! code in the same time step where the planting transfer originally - ! occurred. - crop_seedc_to_leaf(p) = crop_seedc_to_leaf(p) - leafc_xfer(p)/dt - crop_seedn_to_leaf(p) = crop_seedn_to_leaf(p) - leafn_xfer(p)/dt - onset_counter(p) = 0._r8 - leafc_xfer(p) = 0._r8 - leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) - if (use_c13) then - c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 - endif - if (use_c14) then - c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 - endif - end if ! croplive + ! onset_counter initialized to zero when .not. croplive + ! offset_counter relevant only at time step of harvest + + onset_counter(p) = onset_counter(p) - dt + + ! enter phase 2 onset for one time step: + ! transfer seed carbon to leaf emergence + + if (peaklai(p) >= 1) then + hui(p) = max(hui(p),huigrain(p)) + endif + + if (leafout(p) >= huileaf(p) .and. hui(p) < huigrain(p) .and. idpp < mxmat(ivt(p))) then + cphase(p) = 2._r8 + if (abs(onset_counter(p)) > 1.e-6_r8) then + onset_flag(p) = 1._r8 + onset_counter(p) = dt + fert_counter(p) = ndays_on * secspday + if (ndays_on .gt. 0) then + fert(p) = (manunitro(ivt(p)) * 1000._r8 + fertnitro(p))/ fert_counter(p) + else + fert(p) = 0._r8 + end if + else + ! this ensures no re-entry to onset of phase2 + ! b/c onset_counter(p) = onset_counter(p) - dt + ! at every time step + + onset_counter(p) = dt + end if + + ! enter harvest for one time step: + ! - transfer live biomass to litter and to crop yield + ! - send xsmrpool to the atmosphere + ! if onset and harvest needed to last longer than one timestep + ! the onset_counter would change from dt and you'd need to make + ! changes to the offset subroutine below + + else if (hui(p) >= gddmaturity(p) .or. idpp >= mxmat(ivt(p))) then + if (harvdate(p) >= NOT_Harvested) harvdate(p) = jday + croplive(p) = .false. ! no re-entry in greater if-block + cphase(p) = 4._r8 + if (tlai(p) > 0._r8) then ! plant had emerged before harvest + offset_flag(p) = 1._r8 + offset_counter(p) = dt + else ! plant never emerged from the ground + ! Revert planting transfers; this will replenish the crop seed deficit. + ! We subtract from any existing value in crop_seedc_to_leaf / + ! crop_seedn_to_leaf in the unlikely event that we enter this block of + ! code in the same time step where the planting transfer originally + ! occurred. + crop_seedc_to_leaf(p) = crop_seedc_to_leaf(p) - leafc_xfer(p)/dt + crop_seedn_to_leaf(p) = crop_seedn_to_leaf(p) - leafn_xfer(p)/dt + leafc_xfer(p) = 0._r8 + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) + if (use_c13) then + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 + endif + if (use_c14) then + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 + endif + + end if + + ! enter phase 3 while previous criteria fail and next is true; + ! in terms of order, phase 3 occurs before harvest, but when + ! harvest *can* occur, we want it to have first priority. + ! AgroIBIS uses a complex formula for lai decline. + ! Use CN's simple formula at least as a place holder (slevis) + + else if (hui(p) >= huigrain(p)) then + cphase(p) = 3._r8 + bglfr(p) = 1._r8/(leaf_long(ivt(p))*dayspyr*secspday) + end if + ! continue fertilizer application while in phase 2; + ! assumes that onset of phase 2 took one time step only + + if (fert_counter(p) <= 0._r8) then + fert(p) = 0._r8 + else ! continue same fert application every timestep + fert_counter(p) = fert_counter(p) - dtrad + end if + + else ! crop not live + ! next 2 lines conserve mass if leaf*_xfer > 0 due to interpinic. + ! We subtract from any existing value in crop_seedc_to_leaf / + ! crop_seedn_to_leaf in the unlikely event that we enter this block of + ! code in the same time step where the planting transfer originally + ! occurred. + crop_seedc_to_leaf(p) = crop_seedc_to_leaf(p) - leafc_xfer(p)/dt + crop_seedn_to_leaf(p) = crop_seedn_to_leaf(p) - leafn_xfer(p)/dt + onset_counter(p) = 0._r8 + leafc_xfer(p) = 0._r8 + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) + if (use_c13) then + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 + endif + if (use_c14) then + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 + endif + end if ! croplive + end if ! not perennial end do ! prognostic crops loop end associate @@ -2051,7 +2756,8 @@ subroutine CropPhenologyInit(bounds) allocate( inhemi(bounds%begp:bounds%endp) ) allocate( minplantjday(0:numpft,inSH)) ! minimum planting julian day - allocate( maxplantjday(0:numpft,inSH)) ! minimum planting julian day + allocate( maxplantjday(0:numpft,inSH)) ! maximum planting julian day + allocate( maxharvjday(0:numpft,inSH)) ! maximum harvest julian day (added by O.Dombrowski) ! Julian day for the start of the year (mid-winter) jdayyrstart(inNH) = 1 @@ -2060,13 +2766,17 @@ subroutine CropPhenologyInit(bounds) ! Convert planting dates into julian day minplantjday(:,:) = huge(1) maxplantjday(:,:) = huge(1) + maxharvjday(:,:) = huge(1) + do n = npcropmin, npcropmax if (pftcon%is_pft_known_to_model(n)) then minplantjday(n, inNH) = int( get_calday( pftcon%mnNHplantdate(n), 0 ) ) maxplantjday(n, inNH) = int( get_calday( pftcon%mxNHplantdate(n), 0 ) ) - + maxharvjday(n, inNH) = int( get_calday( pftcon%mxNHharvdate(n), 0 ) ) minplantjday(n, inSH) = int( get_calday( pftcon%mnSHplantdate(n), 0 ) ) maxplantjday(n, inSH) = int( get_calday( pftcon%mxSHplantdate(n), 0 ) ) + maxharvjday(n, inSH) = int( get_calday( pftcon%mxSHharvdate(n), 0 ) ) + end if end do @@ -2362,7 +3072,7 @@ end subroutine CNOnsetGrowth !----------------------------------------------------------------------- subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & - cnveg_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) + crop_inst,cnveg_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) ! ! !DESCRIPTION: ! Determines the flux of C and N from displayed pools to litter @@ -2371,11 +3081,13 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & ! !USES: use pftconMod , only : npcropmin use CNSharedParamsMod, only : use_fun - use clm_varctl , only : CNratio_floating + use clm_varctl , only : CNratio_floating + use clm_time_manager , only : get_curr_date, get_curr_calday, get_days_per_year, is_beg_curr_year ! ! !ARGUMENTS: integer , intent(in) :: num_soilp ! number of soil patches in filter integer , intent(in) :: filter_soilp(:) ! filter for soil patches + type(crop_type) , intent(inout) :: crop_inst type(cnveg_state_type) , intent(inout) :: cnveg_state_inst type(cnveg_carbonstate_type) , intent(in) :: cnveg_carbonstate_inst type(cnveg_nitrogenstate_type), intent(in) :: cnveg_nitrogenstate_inst @@ -2385,21 +3097,36 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & ! !LOCAL VARIABLES: integer :: p, c ! indices integer :: fp ! lake filter patch index + integer :: kyr, kmo, kda, mcsec ! time info + integer :: dayspyr ! days per year + integer :: idpp ! number of days past planting + integer :: jday ! julian day of year real(r8):: t1 ! temporary variable real(r8):: denom ! temporary variable for divisor real(r8) :: ntovr_leaf real(r8) :: fr_leafn_to_litter ! fraction of the nitrogen turnover that goes to litter; remaining fraction is retranslocated + real(r8) :: pr_fr ! fraction of total stem biomass that is pruned !----------------------------------------------------------------------- associate( & ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type + mxmat => pftcon%mxmat , & ! Input: leafcn => pftcon%leafcn , & ! Input: leaf C:N (gC/gN) lflitcn => pftcon%lflitcn , & ! Input: leaf litter C:N (gC/gN) frootcn => pftcon%frootcn , & ! Input: fine root C:N (gC/gN) graincn => pftcon%graincn , & ! Input: grain C:N (gC/gN) - + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop phenology (added by O.Dombrowski) + mulch_pruning => pftcon%mulch_pruning , & ! Input: binary flag for exporting or mulching of pruning material (added by O.Dombrowski) + prune_fr => pftcon%prune_fr , & ! Input: fraction of deadstem biomass that is pruned (added by O.Dombrowski) + prune_flag => cnveg_state_inst%prune_flag_patch , & ! Input: binary flag for pruning (added by O.Dombrowski) + harvest_flag => cnveg_state_inst%harvest_flag_patch , & ! Input: [real(r8) (:) ] harvest flag (added by O.Dombrowski) + + idop => cnveg_state_inst%idop_patch , & ! Output: [integer (:)] date of planting + yrop => crop_inst%yrop_patch , & ! Output: [integer (:)] year of planting (added by O.Dombrowski) + croplive => crop_inst%croplive_patch , & ! Output: [logical (:) ] Flag, true if planted, not harvested offset_flag => cnveg_state_inst%offset_flag_patch , & ! Input: [real(r8) (:) ] offset flag + offset2_flag => cnveg_state_inst%offset2_flag_patch , & ! Input: [real(r8) (:) ] orchard rotation flag offset_counter => cnveg_state_inst%offset_counter_patch , & ! Input: [real(r8) (:) ] offset days counter leafc => cnveg_carbonstate_inst%leafc_patch , & ! Input: [real(r8) (:) ] (gC/m2) leaf C @@ -2407,8 +3134,51 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & grainc => cnveg_carbonstate_inst%grainc_patch , & ! Input: [real(r8) (:) ] (gC/m2) grain C cropseedc_deficit => cnveg_carbonstate_inst%cropseedc_deficit_patch , & ! Input: [real(r8) (:) ] (gC/m2) crop seed C deficit livestemc => cnveg_carbonstate_inst%livestemc_patch , & ! Input: [real(r8) (:) ] (gC/m2) livestem C + deadstemc => cnveg_carbonstate_inst%deadstemc_patch , & ! Input: [real(r8) (:) ] (gC/m2) deadstem C + deadstemc_soy => cnveg_carbonstate_inst%deadstemc_soy_patch , & ! Input: [real(r8) (:) ] (gC/m2) dead stem C at the start of season + livecrootc => cnveg_carbonstate_inst%livecrootc_patch , & ! Input: [real(r8) (:) ] (gC/m2) live coarse root C + deadcrootc => cnveg_carbonstate_inst%deadcrootc_patch , & ! Input: [real(r8) (:) ] (gC/m2) dead coarse root C + xsmrpool => cnveg_carbonstate_inst%xsmrpool_patch , & ! Input: [real(r8) (:)] (gC/m2) abstract C pool to meet excess MR demand + leafc_storage => cnveg_carbonstate_inst%leafc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) leaf C storage + frootc_storage => cnveg_carbonstate_inst%frootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) fine root C storage + livestemc_storage => cnveg_carbonstate_inst%livestemc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) livestem storage C + deadstemc_storage => cnveg_carbonstate_inst%deadstemc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) deadstem storage C + deadstemc_storage_soy => cnveg_carbonstate_inst%deadstemc_storage_soy_patch , & ! Input: [real(r8) (:) ] (gC/m2) dead stem C storage at the start of season + livecrootc_storage => cnveg_carbonstate_inst%livecrootc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) livecrootc storage C + deadcrootc_storage => cnveg_carbonstate_inst%deadcrootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) dead coarse root C storage + cropseedn_deficit => cnveg_nitrogenstate_inst%cropseedn_deficit_patch , & ! Input: [real(r8) (:) ] (gC/m2) crop seed N deficit - livestemn => cnveg_nitrogenstate_inst%livestemn_patch , & ! Input: [real(r8) (:) ] (gN/m2) livestem N + + gresp_storage => cnveg_carbonstate_inst%gresp_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) growth respiration storage + leafc_xfer => cnveg_carbonstate_inst%leafc_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) leaf C transfer + frootc_xfer => cnveg_carbonstate_inst%frootc_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) fine root C transfer + livestemc_xfer => cnveg_carbonstate_inst%livestemc_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) live stem C transfer + deadstemc_xfer => cnveg_carbonstate_inst%deadstemc_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) dead stem C transfer + livecrootc_xfer => cnveg_carbonstate_inst%livecrootc_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) live coarse root C transfer + deadcrootc_xfer => cnveg_carbonstate_inst%deadcrootc_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) dead coarse root C transfer + gresp_xfer => cnveg_carbonstate_inst%gresp_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) growth respiration transfer + + leafn => cnveg_nitrogenstate_inst%leafn_patch , & ! Input: [real(r8) (:)] (gN/m2) leaf N + frootn => cnveg_nitrogenstate_inst%frootn_patch , & ! Input: [real(r8) (:)] (gN/m2) fine root N + livestemn => cnveg_nitrogenstate_inst%livestemn_patch , & ! Input: [real(r8) (:)] (gN/m2) live stem N + deadstemn => cnveg_nitrogenstate_inst%deadstemn_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N + deadstemn_soy => cnveg_nitrogenstate_inst%deadstemn_soy_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N at the start of season + livecrootn => cnveg_nitrogenstate_inst%livecrootn_patch , & ! Input: [real(r8) (:)] (gN/m2) live coarse root N + deadcrootn => cnveg_nitrogenstate_inst%deadcrootn_patch , & ! Input: [real(r8) (:)] (gN/m2) dead coarse root N + retransn => cnveg_nitrogenstate_inst%retransn_patch , & ! Input: [real(r8) (:)] (gN/m2) plant pool of retranslocated N + leafn_storage => cnveg_nitrogenstate_inst%leafn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) leaf N storage + frootn_storage => cnveg_nitrogenstate_inst%frootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) fine root N storage + livestemn_storage => cnveg_nitrogenstate_inst%livestemn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) live stem N storage + deadstemn_storage => cnveg_nitrogenstate_inst%deadstemn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N storage + deadstemn_storage_soy => cnveg_nitrogenstate_inst%deadstemn_storage_soy_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N storage at the start of season + livecrootn_storage => cnveg_nitrogenstate_inst%livecrootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) live coarse root N storage + deadcrootn_storage => cnveg_nitrogenstate_inst%deadcrootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) dead coarse root N storage + leafn_xfer => cnveg_nitrogenstate_inst%leafn_xfer_patch , & ! Input: [real(r8) (:)] (gN/m2) leaf N transfer + frootn_xfer => cnveg_nitrogenstate_inst%frootn_xfer_patch , & ! Input: [real(r8) (:)] (gN/m2) fine root N transfer + livestemn_xfer => cnveg_nitrogenstate_inst%livestemn_xfer_patch , & ! Input: [real(r8) (:)] (gN/m2) live stem N transfer + deadstemn_xfer => cnveg_nitrogenstate_inst%deadstemn_xfer_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N transfer + livecrootn_xfer => cnveg_nitrogenstate_inst%livecrootn_xfer_patch , & ! Input: [real(r8) (:)] (gN/m2) live coarse root N transfer + deadcrootn_xfer => cnveg_nitrogenstate_inst%deadcrootn_xfer_patch , & ! Input: [real(r8) (:)] (gN/m2) dead coarse root N transfer cpool_to_grainc => cnveg_carbonflux_inst%cpool_to_grainc_patch , & ! Input: [real(r8) (:) ] allocation to grain C (gC/m2/s) npool_to_grainn => cnveg_nitrogenflux_inst%npool_to_grainn_patch , & ! Input: [real(r8) (:) ] allocation to grain N (gN/m2/s) @@ -2416,35 +3186,107 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & cpool_to_livestemc => cnveg_carbonflux_inst%cpool_to_livestemc_patch , & ! Input: [real(r8) (:) ] allocation to live stem C (gC/m2/s) cpool_to_leafc => cnveg_carbonflux_inst%cpool_to_leafc_patch , & ! Input: [real(r8) (:) ] allocation to leaf C (gC/m2/s) cpool_to_frootc => cnveg_carbonflux_inst%cpool_to_frootc_patch , & ! Input: [real(r8) (:) ] allocation to fine root C (gC/m2/s) + cpool_to_livestemc_storage => cnveg_carbonflux_inst%cpool_to_livestemc_storage_patch , & ! Input: [real(r8) (:) ] allocation to live stem storage C (gC/m2/s) + cpool_to_deadstemc_storage => cnveg_carbonflux_inst%cpool_to_deadstemc_storage_patch , & ! Input: [real(r8) (:) ] allocation to dead stem storage C (gC/m2/s) prev_leafc_to_litter => cnveg_carbonflux_inst%prev_leafc_to_litter_patch , & ! Output: [real(r8) (:) ] previous timestep leaf C litterfall flux (gC/m2/s) prev_frootc_to_litter => cnveg_carbonflux_inst%prev_frootc_to_litter_patch , & ! Output: [real(r8) (:) ] previous timestep froot C litterfall flux (gC/m2/s) leafc_to_litter => cnveg_carbonflux_inst%leafc_to_litter_patch , & ! Output: [real(r8) (:) ] leaf C litterfall (gC/m2/s) frootc_to_litter => cnveg_carbonflux_inst%frootc_to_litter_patch , & ! Output: [real(r8) (:) ] fine root C litterfall (gC/m2/s) - livestemc_to_litter => cnveg_carbonflux_inst%livestemc_to_litter_patch , & ! Output: [real(r8) (:) ] live stem C litterfall (gC/m2/s) + livestemc_to_litter => cnveg_carbonflux_inst%livestemc_to_litter_patch , & ! Output: [real(r8) (:) ] live stem C litterfall (gC/m2/s) + prunec_to_litter => cnveg_carbonflux_inst%prunec_to_litter_patch , & ! Output: [real(r8) (:) ] pruning C litterfall (gC/m2/s) + prunec_storage_to_litter => cnveg_carbonflux_inst%prunec_storage_to_litter_patch , & ! Output: [real(r8) (:) ] pruning storage C litterfall (gC/m2/s) + + hrv_leafc_to_litter => cnveg_carbonflux_inst%hrv_leafc_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_frootc_to_litter => cnveg_carbonflux_inst%hrv_frootc_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_livestemc_to_litter => cnveg_carbonflux_inst%hrv_livestemc_to_litter_patch , & ! Output: [real(r8) (:)] + wood_harvestc => cnveg_carbonflux_inst%wood_harvestc_patch , & ! Output: [real(r8) (:)] + hrv_livecrootc_to_litter => cnveg_carbonflux_inst%hrv_livecrootc_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadcrootc_to_litter => cnveg_carbonflux_inst%hrv_deadcrootc_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_xsmrpool_to_atm => cnveg_carbonflux_inst%hrv_xsmrpool_to_atm_patch , & ! Output: [real(r8) (:)] + hrv_leafc_storage_to_litter => cnveg_carbonflux_inst%hrv_leafc_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_frootc_storage_to_litter => cnveg_carbonflux_inst%hrv_frootc_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_livestemc_storage_to_litter => cnveg_carbonflux_inst%hrv_livestemc_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadstemc_storage_to_litter => cnveg_carbonflux_inst%hrv_deadstemc_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_livecrootc_storage_to_litter => cnveg_carbonflux_inst%hrv_livecrootc_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadcrootc_storage_to_litter => cnveg_carbonflux_inst%hrv_deadcrootc_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_gresp_storage_to_litter => cnveg_carbonflux_inst%hrv_gresp_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_leafc_xfer_to_litter => cnveg_carbonflux_inst%hrv_leafc_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_frootc_xfer_to_litter => cnveg_carbonflux_inst%hrv_frootc_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_livestemc_xfer_to_litter => cnveg_carbonflux_inst%hrv_livestemc_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadstemc_xfer_to_litter => cnveg_carbonflux_inst%hrv_deadstemc_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_livecrootc_xfer_to_litter => cnveg_carbonflux_inst%hrv_livecrootc_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadcrootc_xfer_to_litter => cnveg_carbonflux_inst%hrv_deadcrootc_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_gresp_xfer_to_litter => cnveg_carbonflux_inst%hrv_gresp_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + + hrv_leafn_to_litter => cnveg_nitrogenflux_inst%hrv_leafn_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_frootn_to_litter => cnveg_nitrogenflux_inst%hrv_frootn_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_livestemn_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_to_litter_patch , & ! Output: [real(r8) (:)] + wood_harvestn => cnveg_nitrogenflux_inst%wood_harvestn_patch , & ! Output: [real(r8) (:)] + hrv_livecrootn_to_litter => cnveg_nitrogenflux_inst%hrv_livecrootn_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadcrootn_to_litter => cnveg_nitrogenflux_inst%hrv_deadcrootn_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_retransn_to_litter => cnveg_nitrogenflux_inst%hrv_retransn_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_leafn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_leafn_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_frootn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_frootn_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_livestemn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadstemn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_deadstemn_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_livecrootn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_livecrootn_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadcrootn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_deadcrootn_storage_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_leafn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_leafn_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_frootn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_frootn_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_livestemn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadstemn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_deadstemn_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + + + hrv_livecrootn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_livecrootn_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + hrv_deadcrootn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_deadcrootn_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + + grainc_to_food => cnveg_carbonflux_inst%grainc_to_food_patch , & ! Output: [real(r8) (:) ] grain C to food (gC/m2/s) grainc_to_seed => cnveg_carbonflux_inst%grainc_to_seed_patch , & ! Output: [real(r8) (:) ] grain C to seed (gC/m2/s) - leafn => cnveg_nitrogenstate_inst%leafn_patch , & ! Input: [real(r8) (:) ] (gN/m2) leaf N - frootn => cnveg_nitrogenstate_inst%frootn_patch , & ! Input: [real(r8) (:) ] (gN/m2) fine root N livestemn_to_litter => cnveg_nitrogenflux_inst%livestemn_to_litter_patch , & ! Output: [real(r8) (:) ] livestem N to litter (gN/m2/s) + prunen_to_litter => cnveg_nitrogenflux_inst%prunen_to_litter_patch , & ! Output: [real(r8) (:) ] pruning N litterfall (gN/m2/s) + prunen_storage_to_litter => cnveg_nitrogenflux_inst%prunen_storage_to_litter_patch , & ! Output: [real(r8) (:) ] pruning storage N litterfall (gN/m2/s) grainn_to_food => cnveg_nitrogenflux_inst%grainn_to_food_patch , & ! Output: [real(r8) (:) ] grain N to food (gN/m2/s) grainn_to_seed => cnveg_nitrogenflux_inst%grainn_to_seed_patch , & ! Output: [real(r8) (:) ] grain N to seed (gN/m2/s) leafn_to_litter => cnveg_nitrogenflux_inst%leafn_to_litter_patch , & ! Output: [real(r8) (:) ] leaf N litterfall (gN/m2/s) leafn_to_retransn => cnveg_nitrogenflux_inst%leafn_to_retransn_patch , & ! Input: [real(r8) (:) ] leaf N to retranslocated N pool (gN/m2/s) free_retransn_to_npool=> cnveg_nitrogenflux_inst%free_retransn_to_npool_patch , & ! Input: [real(r8) (:) ] free leaf N to retranslocated N pool (gN/m2/s) - paid_retransn_to_npool=> cnveg_nitrogenflux_inst%retransn_to_npool_patch, & ! Input: [real(r8) (:) ] free leaf N to retranslocated N pool (gN/m2/s) + paid_retransn_to_npool=> cnveg_nitrogenflux_inst%retransn_to_npool_patch , & ! Input: [real(r8) (:) ] free leaf N to retranslocated N pool (gN/m2/s) frootn_to_litter => cnveg_nitrogenflux_inst%frootn_to_litter_patch , & ! Output: [real(r8) (:) ] fine root N litterfall (gN/m2/s) leafc_to_litter_fun => cnveg_carbonflux_inst%leafc_to_litter_fun_patch , & ! Output: [real(r8) (:) ] leaf C litterfall used by FUN (gC/m2/s) - leafcn_offset => cnveg_state_inst%leafcn_offset_patch & ! Output: [real(r8) (:) ] Leaf C:N used by FUN + leafcn_offset => cnveg_state_inst%leafcn_offset_patch & ! Output: [real(r8) (:) ] Leaf C:N used by FUN ) + ! get time info + dayspyr = get_days_per_year() + jday = get_curr_calday() + call get_curr_date(kyr, kmo, kda, mcsec) + ! The litterfall transfer rate starts at 0.0 and increases linearly - ! over time, with displayed growth going to 0.0 on the last day of litterfall - + ! over time, with displayed growth going to 0.0 on the last day of litterfall do fp = 1,num_soilp p = filter_soilp(fp) - ! only calculate fluxes during offset period + ! determine days past planting for pruning management + idpp = int(dayspyr)*(kyr-yrop(p)) + jday - idop(p) + !incorporate a one-time harvest: annually for perennial crops (added by O.Dombrowski adopted based on CLM-Palm (Fan et al. 2015)) + !grain flux goes to food + if (harvest_flag(p) == 1._r8)then + if (perennial(ivt(p)) == 1._r8) then + if (grainc(p) > 0._r8) then + t1 = 1.0_r8 / dt + ! replenish seed deficit (needed to balance seedc used for orchard establishment) + grainc_to_seed(p) = t1 * min(-cropseedc_deficit(p), grainc(p)) + grainn_to_seed(p) = t1 * min(-cropseedn_deficit(p), grainn(p)) + ! send remaining grainc to food product pool + grainc_to_food(p) = t1 * grainc(p) + cpool_to_grainc(p) - grainc_to_seed(p) + grainn_to_food(p) = t1 * grainn(p) + npool_to_grainn(p) - grainn_to_seed(p) + + end if + end if + end if + ! only calculate fluxes during offset period (a one time step for crops; multiple days for trees) if (offset_flag(p) == 1._r8) then if (offset_counter(p) == dt) then @@ -2453,7 +3295,9 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & frootc_to_litter(p) = t1 * frootc(p) + cpool_to_frootc(p) ! this assumes that offset_counter == dt for crops ! if this were ever changed, we'd need to add code to the "else" - if (ivt(p) >= npcropmin) then + ! for perennial crops final harvest happens only at rotation + + if (ivt(p) >= npcropmin .and. perennial(ivt(p)) == 0._r8) then ! Replenish the seed deficits from grain, if there is enough ! available grain. (If there is not enough available grain, the seed ! deficits will accumulate until there is eventually enough grain to @@ -2463,9 +3307,35 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & ! Send the remaining grain to the food product pool grainc_to_food(p) = t1 * grainc(p) + cpool_to_grainc(p) - grainc_to_seed(p) grainn_to_food(p) = t1 * grainn(p) + npool_to_grainn(p) - grainn_to_seed(p) - + livestemc_to_litter(p) = t1 * livestemc(p) + cpool_to_livestemc(p) end if + if (prune_flag(p) == 1._r8) then ! perennial fruit tree crops are pruned at the start of the dormancy period + ! young fruit trees are not pruned in the first 3 years after + ! transplanting + if (idpp < 1095._r8) then + pr_fr = 0._r8 + else + pr_fr = prune_fr(ivt(p)) + end if + if (mulch_pruning(ivt(p)) == 0._r8) then ! pruning material is exported + ! carbon fluxes to wood product pool + wood_harvestc(p) = t1 * ((deadstemc(p)-deadstemc_soy(p))*pr_fr) + hrv_deadstemc_storage_to_litter(p) = t1 * ((deadstemc_storage(p)-deadstemc_storage_soy(p))*pr_fr) + ! corresponding nitrogen fluxes + wood_harvestn(p) = t1 * ((deadstemn(p)-deadstemn_soy(p))*pr_fr) + hrv_deadstemn_storage_to_litter(p) = t1 * ((deadstemn_storage(p)-deadstemn_storage_soy(p))*pr_fr) + + else if (mulch_pruning(ivt(p)) == 1._r8) then ! pruning material is mulched into the soil + ! carbon fluxes to wood product pool + prunec_to_litter(p) = t1 * ((deadstemc(p)-deadstemc_soy(p))*pr_fr) + prunec_storage_to_litter(p) = t1 * ((deadstemc_storage(p)-deadstemc_storage_soy(p))*pr_fr) + ! corresponding nitrogen fluxes + prunen_to_litter(p) = t1 * ((deadstemn(p)-deadstemn_soy(p))*pr_fr) + prunen_storage_to_litter(p) = t1 *((deadstemn_storage(p)-deadstemn_storage_soy(p))*pr_fr) + end if + end if + else t1 = dt * 2.0_r8 / (offset_counter(p) * offset_counter(p)) leafc_to_litter(p) = prev_leafc_to_litter(p) + t1*(leafc(p) - prev_leafc_to_litter(p)*offset_counter(p)) @@ -2473,6 +3343,7 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & end if + if ( use_fun ) then if(leafc_to_litter(p)*dt.gt.leafc(p))then leafc_to_litter(p) = leafc(p)/dt + cpool_to_leafc(p) @@ -2506,7 +3377,6 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & else fr_leafn_to_litter = 1.0_r8 end if - else if (CNratio_floating .eqv. .true.) then fr_leafn_to_litter = 0.5_r8 ! assuming 50% of nitrogen turnover goes to litter @@ -2531,9 +3401,9 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & leafn_to_retransn(p) = ntovr_leaf - leafn_to_litter(p) if (frootc(p) == 0.0_r8) then frootn_to_litter(p) = 0.0_r8 - else + else frootn_to_litter(p) = frootc_to_litter(p) * (frootn(p) / frootc(p)) - end if + end if end if if ( use_fun ) then @@ -2541,8 +3411,8 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & frootn_to_litter(p) = frootn(p)/dt endif end if - - if (ivt(p) >= npcropmin) then + + if (ivt(p) >= npcropmin .and. perennial(ivt(p)) == 0._r8) then ! NOTE(slevis, 2014-12) results in -ve livestemn and -ve totpftn !X! livestemn_to_litter(p) = livestemc_to_litter(p) / livewdcn(ivt(p)) ! NOTE(slevis, 2014-12) Beth Drewniak suggested this instead @@ -2554,9 +3424,73 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & prev_frootc_to_litter(p) = frootc_to_litter(p) end if ! end if offset period + ! offset2 is newly implemented for fruit trees, it initializes orchard + ! rotation (complete harvest of all plant organs) after maximum + ! lifespan is reached + ! (introduced in CLM-Palm (Fan et al. 2015), and adopted here by O.Dombrowski) + if (offset2_flag(p) == 1._r8 .and. perennial(ivt(p)) == 1._r8) then + ! Apply all harvest at the start of the year, otherwise will get + ! error because of non zero delta mid-year for dribbler + ! hrv_xsmrpool_to_atm_c + if (is_beg_curr_year()) then + croplive(p) = .false. + t1 = 1.0_r8 / dt + ! clear-cut carbon fluxes, remove all displayed/storage/transfer pools + ! displayed pools + hrv_leafc_to_litter(p) = leafc(p) * t1 + hrv_leafn_to_litter(p) = leafn(p) * t1 + hrv_frootc_to_litter(p) = frootc(p) * t1 + hrv_frootn_to_litter(p) = frootn(p) * t1 + hrv_livestemc_to_litter(p) = livestemc(p) * t1 + hrv_livestemn_to_litter(p) = livestemn(p) * t1 + wood_harvestc(p) = deadstemc(p) * t1 + wood_harvestn(p) = deadstemn(p) * t1 + hrv_livecrootc_to_litter(p) = livecrootc(p) * t1 + hrv_livecrootn_to_litter(p) = livecrootn(p) * t1 + hrv_deadcrootc_to_litter(p) = deadcrootc(p) * t1 + hrv_deadcrootn_to_litter(p) = deadcrootn(p) * t1 + hrv_xsmrpool_to_atm(p) = xsmrpool(p) * t1 + + ! storage pools + hrv_leafc_storage_to_litter(p) = leafc_storage(p) * t1 + hrv_leafn_storage_to_litter(p) = leafn_storage(p) * t1 + hrv_frootc_storage_to_litter(p) = frootc_storage(p) * t1 + hrv_frootn_storage_to_litter(p) = frootn_storage(p) * t1 + hrv_livestemc_storage_to_litter(p) = livestemc_storage(p) * t1 + hrv_livestemn_storage_to_litter(p) = livestemn_storage(p) * t1 + hrv_deadstemc_storage_to_litter(p) = deadstemc_storage(p) * t1 + hrv_deadstemn_storage_to_litter(p) = deadstemn_storage(p) * t1 + hrv_livecrootc_storage_to_litter(p) = livecrootc_storage(p) * t1 + hrv_livecrootn_storage_to_litter(p) = livecrootn_storage(p) * t1 + hrv_deadcrootc_storage_to_litter(p) = deadcrootc_storage(p) * t1 + hrv_deadcrootn_storage_to_litter(p) = deadcrootn_storage(p) * t1 + hrv_gresp_storage_to_litter(p) = gresp_storage(p) * t1 + + ! transfer pools + hrv_leafc_xfer_to_litter(p) = leafc_xfer(p) * t1 + hrv_leafn_xfer_to_litter(p) = leafn_xfer(p) * t1 + hrv_frootc_xfer_to_litter(p) = frootc_xfer(p) * t1 + hrv_frootn_xfer_to_litter(p) = frootn_xfer(p) * t1 + hrv_livestemc_xfer_to_litter(p) = livestemc_xfer(p) * t1 + hrv_livestemn_xfer_to_litter(p) = livestemn_xfer(p) * t1 + hrv_deadstemc_xfer_to_litter(p) = deadstemc_xfer(p) * t1 + hrv_deadstemn_xfer_to_litter(p) = deadstemn_xfer(p) * t1 + hrv_livecrootc_xfer_to_litter(p) = livecrootc_xfer(p) * t1 + hrv_livecrootn_xfer_to_litter(p) = livecrootn_xfer(p) * t1 + hrv_deadcrootc_xfer_to_litter(p) = deadcrootc_xfer(p) * t1 + hrv_deadcrootn_xfer_to_litter(p) = deadcrootn_xfer(p) * t1 + hrv_gresp_xfer_to_litter(p) = gresp_xfer(p) * t1 + + ! retransn pools + hrv_retransn_to_litter(p) = retransn(p) * t1 - end do ! end patch loop + else + croplive(p) = .true. + end if + end if ! end orchard rotation + end do ! end patch loop + end associate end subroutine CNOffsetLitterfall @@ -2855,16 +3789,16 @@ subroutine CNGrainToProductPools(bounds, num_soilp, filter_soilp, num_soilc, fil end subroutine CNGrainToProductPools !----------------------------------------------------------------------- - subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & - cnveg_state_inst,cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & - leaf_prof_patch, froot_prof_patch) + subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & + cnveg_state_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & + leaf_prof_patch, froot_prof_patch, stem_prof_patch) ! ! !DESCRIPTION: ! called at the end of cn_phenology to gather all patch-level litterfall fluxes ! to the column level and assign them to the three litter pools ! ! !USES: - use clm_varpar , only : max_patch_per_col, nlevdecomp + use clm_varpar , only : max_patch_per_col,maxpatch_pft, nlevdecomp use pftconMod , only : npcropmin use clm_varctl , only : use_grainproduct ! @@ -2877,6 +3811,7 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst real(r8) , intent(in) :: leaf_prof_patch(bounds%begp:,1:) real(r8) , intent(in) :: froot_prof_patch(bounds%begp:,1:) + real(r8) , intent(in) :: stem_prof_patch(bounds%begp:,1:) ! ! !LOCAL VARIABLES: integer :: fc,c,pi,p,j ! indices @@ -2884,11 +3819,12 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & SHR_ASSERT_ALL((ubound(leaf_prof_patch) == (/bounds%endp,nlevdecomp_full/)), errMsg(sourcefile, __LINE__)) SHR_ASSERT_ALL((ubound(froot_prof_patch) == (/bounds%endp,nlevdecomp_full/)), errMsg(sourcefile, __LINE__)) + SHR_ASSERT_ALL((ubound(stem_prof_patch) == (/bounds%endp,nlevdecomp_full/)), errMsg(sourcefile, __LINE__)) associate( & leaf_prof => leaf_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of leaves froot_prof => froot_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of fine roots - + stem_prof => stem_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of stems ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type wtcol => patch%wtcol , & ! Input: [real(r8) (:) ] weight (relative to column) for this patch (0-1) @@ -2898,24 +3834,56 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & fr_flab => pftcon%fr_flab , & ! Input: fine root litter labile fraction fr_fcel => pftcon%fr_fcel , & ! Input: fine root litter cellulose fraction fr_flig => pftcon%fr_flig , & ! Input: fine root litter lignin fraction - + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types + mulch_pruning => pftcon%mulch_pruning , & ! Input: binary flag for mulching or exporting of pruning material + prune_flag => cnveg_state_inst%prune_flag_patch , & ! Input: binary flag for pruning of perennial crop types + offset2_flag => cnveg_state_inst%offset2_flag_patch , & ! Input: binary flag for rotation of perennial crop types leafc_to_litter => cnveg_carbonflux_inst%leafc_to_litter_patch , & ! Input: [real(r8) (:) ] leaf C litterfall (gC/m2/s) frootc_to_litter => cnveg_carbonflux_inst%frootc_to_litter_patch , & ! Input: [real(r8) (:) ] fine root N litterfall (gN/m2/s) livestemc_to_litter => cnveg_carbonflux_inst%livestemc_to_litter_patch , & ! Input: [real(r8) (:) ] live stem C litterfall (gC/m2/s) + prunec_to_litter => cnveg_carbonflux_inst%prunec_to_litter_patch , & ! Input: [real(r8) (:) ] pruning C litterfall (gC/m2/s) + prunec_storage_to_litter => cnveg_carbonflux_inst%prunec_storage_to_litter_patch , & ! Input: [real(r8) (:) ] pruning storage C litterfall (gC/m2/s) + grainc_to_food => cnveg_carbonflux_inst%grainc_to_food_patch , & ! Input: [real(r8) (:) ] grain C to food (gC/m2/s) phenology_c_to_litr_met_c => cnveg_carbonflux_inst%phenology_c_to_litr_met_c_col , & ! Output: [real(r8) (:,:) ] C fluxes associated with phenology (litterfall and crop) to litter metabolic pool (gC/m3/s) phenology_c_to_litr_cel_c => cnveg_carbonflux_inst%phenology_c_to_litr_cel_c_col , & ! Output: [real(r8) (:,:) ] C fluxes associated with phenology (litterfall and crop) to litter cellulose pool (gC/m3/s) phenology_c_to_litr_lig_c => cnveg_carbonflux_inst%phenology_c_to_litr_lig_c_col , & ! Output: [real(r8) (:,:) ] C fluxes associated with phenology (litterfall and crop) to litter lignin pool (gC/m3/s) livestemn_to_litter => cnveg_nitrogenflux_inst%livestemn_to_litter_patch , & ! Input: [real(r8) (:) ] livestem N to litter (gN/m2/s) + prunen_to_litter => cnveg_nitrogenflux_inst%prunen_to_litter_patch , & ! Input: [real(r8) (:) ] pruning N litterfall (gN/m2/s) + prunen_storage_to_litter => cnveg_nitrogenflux_inst%prunen_storage_to_litter_patch , & ! Input: [real(r8) (:) ] pruning storage N litterfall (gN/m2/s) grainn_to_food => cnveg_nitrogenflux_inst%grainn_to_food_patch , & ! Input: [real(r8) (:) ] grain N to food (gN/m2/s) + leafn_to_litter => cnveg_nitrogenflux_inst%leafn_to_litter_patch , & ! Input: [real(r8) (:) ] leaf N litterfall (gN/m2/s) frootn_to_litter => cnveg_nitrogenflux_inst%frootn_to_litter_patch , & ! Input: [real(r8) (:) ] fine root N litterfall (gN/m2/s) phenology_n_to_litr_met_n => cnveg_nitrogenflux_inst%phenology_n_to_litr_met_n_col , & ! Output: [real(r8) (:,:) ] N fluxes associated with phenology (litterfall and crop) to litter metabolic pool (gN/m3/s) phenology_n_to_litr_cel_n => cnveg_nitrogenflux_inst%phenology_n_to_litr_cel_n_col , & ! Output: [real(r8) (:,:) ] N fluxes associated with phenology (litterfall and crop) to litter cellulose pool (gN/m3/s) - phenology_n_to_litr_lig_n => cnveg_nitrogenflux_inst%phenology_n_to_litr_lig_n_col & ! Output: [real(r8) (:,:) ] N fluxes associated with phenology (litterfall and crop) to litter lignin pool (gN/m3/s) + phenology_n_to_litr_lig_n => cnveg_nitrogenflux_inst%phenology_n_to_litr_lig_n_col , & ! Output: [real(r8) (:,:) ] N fluxes associated with phenology (litterfall and crop) to litter lignin pool (gN/m3/s) + hrv_livestemc_to_litter => cnveg_carbonflux_inst%hrv_livestemc_to_litter_patch , & ! Input: [real(r8) (:) ] + pwood_harvestc => cnveg_carbonflux_inst%wood_harvestc_patch , & ! Input: [real(r8) (:) ] + hrv_livestemc_storage_to_litter => cnveg_carbonflux_inst%hrv_livestemc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadstemc_storage_to_litter => cnveg_carbonflux_inst%hrv_deadstemc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + cwood_harvestc => cnveg_carbonflux_inst%wood_harvestc_col , & ! InOut: [real(r8) (:) ] + m_deadstemc_to_litter => cnveg_carbonflux_inst%m_deadstemc_to_litter_patch , & ! Input: [real(r8) (:) ] + m_deadstemc_storage_to_litter => cnveg_carbonflux_inst%m_deadstemc_storage_to_litter_patch , & ! Input:[real(r8) (:) ] + harvest_c_to_litr_met_c => cnveg_carbonflux_inst%harvest_c_to_litr_met_c_col , & ! InOut: [real(r8) (:,:) ] C fluxes associated with harvest to litter metabolic pool (gC/m3/s) + harvest_c_to_cwdc => cnveg_carbonflux_inst%harvest_c_to_cwdc_col , & ! InOut: [real(r8) (:,:) ] C fluxes associated with harvest to CWD pool (gC/m3/s) + gap_mortality_c_to_litr_met_c => cnveg_carbonflux_inst%gap_mortality_c_to_litr_met_c_col , & ! Output: [real(r8) (:,:) ] C fluxes associated with gap mortality to litter metabolic pool (gC/m3/s) + gap_mortality_c_to_cwdc => cnveg_carbonflux_inst%gap_mortality_c_to_cwdc_col , & ! Output: [real(r8) (:,:) ] C fluxes associated with gap mortality to CWD pool (gC/m3/s) + hrv_livestemn_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_to_litter_patch , & ! Input: [real(r8) (:) ] + pwood_harvestn => cnveg_nitrogenflux_inst%wood_harvestn_patch , & ! Input: [real(r8) (:) ] + hrv_livestemn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadstemn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_deadstemn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + cwood_harvestn => cnveg_nitrogenflux_inst%wood_harvestn_col , & ! InOut: [real(r8) (:) ] + harvest_n_to_litr_met_n => cnveg_nitrogenflux_inst%harvest_n_to_litr_met_n_col , & ! InOut: [real(r8) (:,:) ] N fluxes associated with harvest to litter metabolic pool (gN/m3/s) + harvest_n_to_cwdn => cnveg_nitrogenflux_inst%harvest_n_to_cwdn_col , & ! InOut: [real(r8) (:,:) ] C fluxes associated with harvest to CWD pool (gC/m3/s) + m_deadstemn_to_litter => cnveg_nitrogenflux_inst%m_deadstemn_to_litter_patch , & ! Input: [real(r8) (:) ] + m_deadstemn_storage_to_litter => cnveg_nitrogenflux_inst%m_deadstemn_storage_to_litter_patch , & ! Input:[real(r8) (:) ] + + gap_mortality_n_to_litr_met_n => cnveg_nitrogenflux_inst%gap_mortality_n_to_litr_met_n_col , & ! Output: [real(r8) (:,:) ] N fluxes associated with gap mortality to litter metabolic pool (gN/m3/s) + gap_mortality_n_to_cwdn => cnveg_nitrogenflux_inst%gap_mortality_n_to_cwdn_col & ! Output: [real(r8) (:,:) ] N fluxes associated with gap mortality to CWD pool (gN/m3/s) ) - + do j = 1, nlevdecomp do pi = 1,max_patch_per_col do fc = 1,num_soilc @@ -2949,6 +3917,7 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & phenology_c_to_litr_lig_c(c,j) = phenology_c_to_litr_lig_c(c,j) & + frootc_to_litter(p) * fr_flig(ivt(p)) * wtcol(p) * froot_prof(p,j) + ! fine root litter nitrogen fluxes phenology_n_to_litr_met_n(c,j) = phenology_n_to_litr_met_n(c,j) & + frootn_to_litter(p) * fr_flab(ivt(p)) * wtcol(p) * froot_prof(p,j) @@ -2962,22 +3931,26 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & ! new ones for now (slevis) ! also for simplicity I've put "food" into the litter pools - if (ivt(p) >= npcropmin) then ! add livestemc to litter - ! stem litter carbon fluxes - phenology_c_to_litr_met_c(c,j) = phenology_c_to_litr_met_c(c,j) & - + livestemc_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) - phenology_c_to_litr_cel_c(c,j) = phenology_c_to_litr_cel_c(c,j) & - + livestemc_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) - phenology_c_to_litr_lig_c(c,j) = phenology_c_to_litr_lig_c(c,j) & - + livestemc_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) - - ! stem litter nitrogen fluxes - phenology_n_to_litr_met_n(c,j) = phenology_n_to_litr_met_n(c,j) & - + livestemn_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) - phenology_n_to_litr_cel_n(c,j) = phenology_n_to_litr_cel_n(c,j) & - + livestemn_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) - phenology_n_to_litr_lig_n(c,j) = phenology_n_to_litr_lig_n(c,j) & - + livestemn_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) + if (ivt(p) >= npcropmin) then + if ( perennial(ivt(p)) == 0._r8) then + ! add livestemc to litter + ! stem litter carbon fluxes + phenology_c_to_litr_met_c(c,j) = phenology_c_to_litr_met_c(c,j) & + + livestemc_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_c_to_litr_cel_c(c,j) = phenology_c_to_litr_cel_c(c,j) & + + livestemc_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_c_to_litr_lig_c(c,j) = phenology_c_to_litr_lig_c(c,j) & + + livestemc_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) + + ! stem litter nitrogen fluxes + phenology_n_to_litr_met_n(c,j) = phenology_n_to_litr_met_n(c,j) & + + livestemn_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_n_to_litr_cel_n(c,j) = phenology_n_to_litr_cel_n(c,j) & + + livestemn_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_n_to_litr_lig_n(c,j) = phenology_n_to_litr_lig_n(c,j) & + + livestemn_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) + + end if if (.not. use_grainproduct) then ! grain litter carbon fluxes @@ -2997,18 +3970,339 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & + grainn_to_food(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) end if + ! calculate pruning litter fluxes added by O.Dombrowski + ! and adapted based on CLM-Palm (Fan et al. 2015) + if ( perennial(ivt(p)) == 1._r8 .and. prune_flag(p) == 1._r8) then + if (mulch_pruning(ivt(p)) == 0._r8) then + ! export pruning material as harvest + ! storage harvest mortality carbon fluxes + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_deadstemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + ! storage harvest mortality nitrogen fluxes + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_deadstemn_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + + ! wood harvest mortality carbon fluxes to product pools + !cwood_harvestc(c) = cwood_harvestc(c) + & + !pwood_harvestc(p) * wtcol(p) + ! wood harvest mortality nitrogen fluxes to product pools + !cwood_harvestn(c) = cwood_harvestn(c) + & + !pwood_harvestn(p) * wtcol(p) + + else if (mulch_pruning(ivt(p)) == 1._r8) then + ! add pruning material to litter + ! pruning carbon fluxes + phenology_c_to_litr_met_c(c,j) = phenology_c_to_litr_met_c(c,j) & + + prunec_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) & + + prunec_storage_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_c_to_litr_cel_c(c,j) = phenology_c_to_litr_cel_c(c,j) & + + prunec_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) & + + prunec_storage_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_c_to_litr_lig_c(c,j) = phenology_c_to_litr_lig_c(c,j) & + + prunec_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) & + + prunec_storage_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) + + ! pruning nitrogen fluxes + phenology_n_to_litr_met_n(c,j) = phenology_n_to_litr_met_n(c,j) & + + prunen_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) & + + prunen_storage_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_n_to_litr_cel_n(c,j) = phenology_n_to_litr_cel_n(c,j) & + + prunen_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) & + + prunen_storage_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_n_to_litr_lig_n(c,j) = phenology_n_to_litr_lig_n(c,j) & + + prunen_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) & + + prunen_storage_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) + end if + end if end if end if end if end do - end do end do - end associate + + do pi = 1,maxpatch_pft + do fc = 1,num_soilc + c = filter_soilc(fc) + + if (pi <= col%npatches(c)) then + p = col%patchi(c) + pi - 1 + if (perennial(ivt(p)) == 1._r8 .and. prune_flag(p) == 1._r8 .and. mulch_pruning(ivt(p)) == 0._r8) then + if (patch%active(p)) then + ! wood harvest mortality carbon fluxes to product pools + cwood_harvestc(c) = cwood_harvestc(c) + & + pwood_harvestc(p) * wtcol(p) + + ! wood harvest mortality nitrogen fluxes to product pools + cwood_harvestn(c) = cwood_harvestn(c) + & + pwood_harvestn(p) * wtcol(p) + end if + end if + end if + + end do + + end do + + end associate end subroutine CNLitterToColumn + !----------------------------------------------------------------------- + subroutine CNRotationToColumn (num_soilc, filter_soilc, & + cnveg_state_inst, soilbiogeochem_state_inst, & + crop_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) + ! + ! !DESCRIPTION: + ! called at the end of CNPhenology to gather all patch-level orchard rotation litterfall + ! fluxes + ! to the column level and assign them to the three litter pools + ! + ! !USES: + use clm_varpar , only : maxpatch_pft, nlevdecomp + use pftconMod , only : npcropmin + ! + ! !ARGUMENTS: + integer , intent(in) :: num_soilc ! number of soil columns in filter + integer , intent(in) :: filter_soilc(:) ! soil column filter + type(crop_type) , intent(inout) :: crop_inst + type(cnveg_state_type) , intent(in) :: cnveg_state_inst + type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst + type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst + type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst + ! + ! !LOCAL VARIABLES: + integer :: fc,c,pi,p,j ! indices + !----------------------------------------------------------------------- + + associate( & + ivt => patch%itype , & ! Input: [integer (:) ] pft vegetation type + wtcol => patch%wtcol , & ! Input: [real(r8) (:) ] pft weight relative to column (0-1) + + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types + lf_flab => pftcon%lf_flab , & ! Input: leaf litter labile fraction + lf_fcel => pftcon%lf_fcel , & ! Input: leaf litter cellulose fraction + lf_flig => pftcon%lf_flig , & ! Input: leaf litter lignin fraction + fr_flab => pftcon%fr_flab , & ! Input: fine root litter labile fraction + fr_fcel => pftcon%fr_fcel , & ! Input: fine root litter cellulose fraction + fr_flig => pftcon%fr_flig , & ! Input: fine root litter lignin fraction + + offset2_flag => cnveg_state_inst%offset2_flag_patch , & ! Input: binary flag for rotation of perennial crop types + croplive => crop_inst%croplive_patch , & ! Output: [logical (:) ] Flag, true if planted, not harvested + + leaf_prof => soilbiogeochem_state_inst%leaf_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of leaves + froot_prof => soilbiogeochem_state_inst%froot_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of fine roots + croot_prof => soilbiogeochem_state_inst%croot_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of coarse roots + stem_prof => soilbiogeochem_state_inst%stem_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of stems + + hrv_leafc_to_litter => cnveg_carbonflux_inst%hrv_leafc_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_frootc_to_litter => cnveg_carbonflux_inst%hrv_frootc_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livestemc_to_litter => cnveg_carbonflux_inst%hrv_livestemc_to_litter_patch , & ! Input: [real(r8) (:) ] + pwood_harvestc => cnveg_carbonflux_inst%wood_harvestc_patch , & ! Input: [real(r8) (:) ] + hrv_livecrootc_to_litter => cnveg_carbonflux_inst%hrv_livecrootc_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadcrootc_to_litter => cnveg_carbonflux_inst%hrv_deadcrootc_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_leafc_storage_to_litter => cnveg_carbonflux_inst%hrv_leafc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_frootc_storage_to_litter => cnveg_carbonflux_inst%hrv_frootc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livestemc_storage_to_litter => cnveg_carbonflux_inst%hrv_livestemc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadstemc_storage_to_litter => cnveg_carbonflux_inst%hrv_deadstemc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livecrootc_storage_to_litter => cnveg_carbonflux_inst%hrv_livecrootc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadcrootc_storage_to_litter => cnveg_carbonflux_inst%hrv_deadcrootc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_gresp_storage_to_litter => cnveg_carbonflux_inst%hrv_gresp_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_leafc_xfer_to_litter => cnveg_carbonflux_inst%hrv_leafc_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_frootc_xfer_to_litter => cnveg_carbonflux_inst%hrv_frootc_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livestemc_xfer_to_litter => cnveg_carbonflux_inst%hrv_livestemc_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadstemc_xfer_to_litter => cnveg_carbonflux_inst%hrv_deadstemc_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livecrootc_xfer_to_litter => cnveg_carbonflux_inst%hrv_livecrootc_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadcrootc_xfer_to_litter => cnveg_carbonflux_inst%hrv_deadcrootc_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_gresp_xfer_to_litter => cnveg_carbonflux_inst%hrv_gresp_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + cwood_harvestc => cnveg_carbonflux_inst%wood_harvestc_col , & ! InOut: [real(r8) (:) ] + harvest_c_to_litr_met_c => cnveg_carbonflux_inst%harvest_c_to_litr_met_c_col , & ! InOut: [real(r8) (:,:) ] C fluxes associated with harvest to litter metabolic pool (gC/m3/s) + harvest_c_to_litr_cel_c => cnveg_carbonflux_inst%harvest_c_to_litr_cel_c_col , & ! InOut: [real(r8) (:,:) ] C fluxes associated with harvest to litter cellulose pool (gC/m3/s) + harvest_c_to_litr_lig_c => cnveg_carbonflux_inst%harvest_c_to_litr_lig_c_col , & ! InOut: [real(r8) (:,:) ] C fluxes associated with harvest to litter lignin pool (gC/m3/s) + harvest_c_to_cwdc => cnveg_carbonflux_inst%harvest_c_to_cwdc_col , & ! InOut: [real(r8) (:,:) ] C fluxes associated with harvest to CWD pool (gC/m3/s) + + hrv_leafn_to_litter => cnveg_nitrogenflux_inst%hrv_leafn_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_frootn_to_litter => cnveg_nitrogenflux_inst%hrv_frootn_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livestemn_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_to_litter_patch , & ! Input: [real(r8) (:) ] + pwood_harvestn => cnveg_nitrogenflux_inst%wood_harvestn_patch , & ! Input: [real(r8) (:) ] + hrv_livecrootn_to_litter => cnveg_nitrogenflux_inst%hrv_livecrootn_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadcrootn_to_litter => cnveg_nitrogenflux_inst%hrv_deadcrootn_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_retransn_to_litter => cnveg_nitrogenflux_inst%hrv_retransn_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_leafn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_leafn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_frootn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_frootn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livestemn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadstemn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_deadstemn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livecrootn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_livecrootn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadcrootn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_deadcrootn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_leafn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_leafn_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_frootn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_frootn_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livestemn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadstemn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_deadstemn_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livecrootn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_livecrootn_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadcrootn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_deadcrootn_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + cwood_harvestn => cnveg_nitrogenflux_inst%wood_harvestn_col , & ! InOut: [real(r8) (:) ] + harvest_n_to_litr_met_n => cnveg_nitrogenflux_inst%harvest_n_to_litr_met_n_col , & ! InOut: [real(r8) (:,:) ] N fluxes associated with harvest to litter metabolic pool (gN/m3/s) + harvest_n_to_litr_cel_n => cnveg_nitrogenflux_inst%harvest_n_to_litr_cel_n_col , & ! InOut: [real(r8) (:,:) ] N fluxes associated with harvest to litter cellulose pool (gN/m3/s) + harvest_n_to_litr_lig_n => cnveg_nitrogenflux_inst%harvest_n_to_litr_lig_n_col , & ! InOut: [real(r8) (:,:) ] N fluxes associated with harvest to litter lignin pool (gN/m3/s) + harvest_n_to_cwdn => cnveg_nitrogenflux_inst%harvest_n_to_cwdn_col & ! InOut: [real(r8) (:,:) ] N fluxes associated with harvest to CWD pool (gN/m3/s) + ) + + do j = 1, nlevdecomp + do pi = 1,maxpatch_pft + do fc = 1,num_soilc + c = filter_soilc(fc) + + if (pi <= col%npatches(c)) then + p = col%patchi(c) + pi - 1 + + if (patch%active(p) .and. (.not. croplive(p)) .and. ivt(p) >= npcropmin .and. perennial(ivt(p)) == 1._r8 .and. offset2_flag(p) == 1._r8) then + + ! leaf harvest mortality carbon fluxes + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_leafc_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) + harvest_c_to_litr_cel_c(c,j) = harvest_c_to_litr_cel_c(c,j) + & + hrv_leafc_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) + harvest_c_to_litr_lig_c(c,j) = harvest_c_to_litr_lig_c(c,j) + & + hrv_leafc_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) + + ! fine root harvest mortality carbon fluxes + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_frootc_to_litter(p) * fr_flab(ivt(p)) * wtcol(p) * froot_prof(p,j) + harvest_c_to_litr_cel_c(c,j) = harvest_c_to_litr_cel_c(c,j) + & + hrv_frootc_to_litter(p) * fr_fcel(ivt(p)) * wtcol(p) * froot_prof(p,j) + harvest_c_to_litr_lig_c(c,j) = harvest_c_to_litr_lig_c(c,j) + & + hrv_frootc_to_litter(p) * fr_flig(ivt(p)) * wtcol(p) * froot_prof(p,j) + + ! wood harvest mortality carbon fluxes + harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & + hrv_livestemc_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & + hrv_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & + hrv_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) + ! storage harvest mortality carbon fluxes + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_leafc_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_frootc_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_livestemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_deadstemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_livecrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_deadcrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_gresp_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + + ! transfer harvest mortality carbon fluxes + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_leafc_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_frootc_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_livestemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_deadstemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_livecrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_deadcrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_gresp_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + + ! leaf harvest mortality nitrogen fluxes + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_leafn_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) + harvest_n_to_litr_cel_n(c,j) = harvest_n_to_litr_cel_n(c,j) + & + hrv_leafn_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) + harvest_n_to_litr_lig_n(c,j) = harvest_n_to_litr_lig_n(c,j) + & + hrv_leafn_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) + + ! fine root litter nitrogen fluxes + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_frootn_to_litter(p) * fr_flab(ivt(p)) * wtcol(p) * froot_prof(p,j) + harvest_n_to_litr_cel_n(c,j) = harvest_n_to_litr_cel_n(c,j) + & + hrv_frootn_to_litter(p) * fr_fcel(ivt(p)) * wtcol(p) * froot_prof(p,j) + harvest_n_to_litr_lig_n(c,j) = harvest_n_to_litr_lig_n(c,j) + & + hrv_frootn_to_litter(p) * fr_flig(ivt(p)) * wtcol(p) * froot_prof(p,j) + + ! wood harvest mortality nitrogen fluxes + harvest_n_to_cwdn(c,j) = harvest_n_to_cwdn(c,j) + & + hrv_livestemn_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_n_to_cwdn(c,j) = harvest_n_to_cwdn(c,j) + & + hrv_livecrootn_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_n_to_cwdn(c,j) = harvest_n_to_cwdn(c,j) + & + hrv_deadcrootn_to_litter(p) * wtcol(p) * croot_prof(p,j) + + ! retranslocated N pool harvest mortality fluxes + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_retransn_to_litter(p) * wtcol(p) * leaf_prof(p,j) + + ! storage harvest mortality nitrogen fluxes + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_leafn_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_frootn_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_livestemn_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_deadstemn_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_livecrootn_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_deadcrootn_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + + ! transfer harvest mortality nitrogen fluxes + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_leafn_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_frootn_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_livestemn_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_deadstemn_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_livecrootn_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_deadcrootn_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + + end if + end if + + end do + + end do + end do + + do pi = 1,maxpatch_pft + do fc = 1,num_soilc + c = filter_soilc(fc) + + if (pi <= col%npatches(c)) then + p = col%patchi(c) + pi - 1 + + if (patch%active(p)) then + ! wood harvest mortality carbon fluxes to product pools + cwood_harvestc(c) = cwood_harvestc(c) + & + pwood_harvestc(p) * wtcol(p) + + ! wood harvest mortality nitrogen fluxes to product pools + cwood_harvestn(c) = cwood_harvestn(c) + & + pwood_harvestn(p) * wtcol(p) + end if + end if + + end do + + end do + + end associate + + end subroutine CNRotationToColumn + end module CNPhenologyMod diff --git a/src/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index f88c7f5e66..681b394f3e 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) + & @@ -4508,8 +4569,7 @@ subroutine Summary_carbonflux(this, & ! total ecosystem respiration, autotrophic + heterotrophic (ER) this%er_col(c) = & this%ar_col(c) + & - soilbiogeochem_hr_col(c) - + soilbiogeochem_hr_col(c) ! coarse woody debris heterotrophic respiration this%cwdc_hr_col(c) = 0._r8 diff --git a/src/biogeochem/CNVegCarbonStateType.F90 b/src/biogeochem/CNVegCarbonStateType.F90 index 1d568dc60d..08a273b338 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._r8 ! (added by O.Dombrowski) + end if else this%deadstemc_patch(p) = 0._r8 end if @@ -1188,6 +1213,14 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%deadstemc_xfer_patch) + call restartvar(ncid=ncid, flag=flag, varname='deadstemc_soy', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemc_soy_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemc_storage_soy', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemc_storage_soy_patch) + call restartvar(ncid=ncid, flag=flag, varname='livecrootc', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%livecrootc_patch) @@ -1379,9 +1412,14 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, !----------------------------------------------- this%leafcmax_patch(i) = 0._r8 - + + if (lun%itype(l) == istcrop .and. pftcon%perennial(patch%itype(i)) == 1._r8) then + this%deadstemc_soy_patch(i) = 0._r8 + this%deadstemc_storage_soy_patch(i) = 0._r8 + end if l = patch%landunit(i) - if (lun%itype(l) == istsoil .or. patch%itype(i) == nc3crop .or. patch%itype(i) == nc3irrig)then + if (lun%itype(l) == istsoil .or. patch%itype(i) == nc3crop .or. patch%itype(i) == nc3irrig) then!.or. & +! (lun%itype(l) == istcrop .and. pftcon%perennial(patch%itype(i)) == 1._r8)) then ! (added by O.Dombrowski) if ( present(num_reseed_patch) ) then num_reseed_patch = num_reseed_patch + 1 filter_reseed_patch(num_reseed_patch) = i @@ -1420,9 +1458,11 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, this%livestemc_xfer_patch(i) = 0._r8 if (pftcon%woody(patch%itype(i)) == 1._r8) then - this%deadstemc_patch(i) = 0.1_r8 * ratio - else - this%deadstemc_patch(i) = 0._r8 + if (patch%itype(p) < npcropmin) then + this%deadstemc_patch(i) = 0.1_r8 * ratio + else + this%deadstemc_patch(i) = 0._r8 + end if end if this%deadstemc_storage_patch(i) = 0._r8 this%deadstemc_xfer_patch(i) = 0._r8 @@ -2367,6 +2407,8 @@ subroutine SetValues ( this, & this%deadstemc_patch(i) = value_patch this%deadstemc_storage_patch(i) = value_patch this%deadstemc_xfer_patch(i) = value_patch + this%deadstemc_soy_patch(i) = value_patch + this%deadstemc_storage_soy_patch(i) = value_patch this%livecrootc_patch(i) = value_patch this%livecrootc_storage_patch(i) = value_patch this%livecrootc_xfer_patch(i) = value_patch @@ -2480,7 +2522,6 @@ subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & this%deadstemc_patch(p) + & this%livecrootc_patch(p) + & this%deadcrootc_patch(p) - ! stored vegetation carbon, excluding cpool (STORVEGC) this%storvegc_patch(p) = & this%cpool_patch(p) + & @@ -2509,18 +2550,16 @@ subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & this%dispvegc_patch(p) + & this%grainc_patch(p) end if - + ! total vegetation carbon, excluding cpool (TOTVEGC) this%totvegc_patch(p) = & this%dispvegc_patch(p) + & this%storvegc_patch(p) - ! total patch-level carbon, including xsmrpool, ctrunc this%totc_patch(p) = & this%totvegc_patch(p) + & this%xsmrpool_patch(p) + & this%ctrunc_patch(p) - if (use_crop) then this%totc_patch(p) = this%totc_patch(p) + this%cropseedc_deficit_patch(p) + & this%xsmrpool_loss_patch(p) @@ -2563,7 +2602,6 @@ subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & soilbiogeochem_totlitc_col(c) + & soilbiogeochem_totsomc_col(c) + & soilbiogeochem_ctrunc_col(c) - end do end subroutine Summary_carbonstate diff --git a/src/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/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..6d2b4d3c90 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', & @@ -471,13 +485,19 @@ subroutine InitCold(this, bounds, & ! roughness length is not zero in canopy flux calculation if (pftcon%woody(patch%itype(p)) == 1._r8) then - this%deadstemn_patch(p) = deadstemc_patch(p) / pftcon%deadwdcn(patch%itype(p)) + if (patch%itype(p) < npcropmin) then + this%deadstemn_patch(p) = deadstemc_patch(p) / pftcon%deadwdcn(patch%itype(p)) + else + this%deadstemn_patch(p) = 0._r8 + end if else this%deadstemn_patch(p) = 0._r8 end if this%deadstemn_storage_patch(p) = 0._r8 this%deadstemn_xfer_patch(p) = 0._r8 + this%deadstemn_soy_patch(p) = 0._r8 + this%deadstemn_storage_soy_patch(p) = 0._r8 this%livecrootn_patch(p) = 0._r8 this%livecrootn_storage_patch(p) = 0._r8 this%livecrootn_xfer_patch(p) = 0._r8 @@ -630,6 +650,14 @@ subroutine Restart ( this, bounds, ncid, flag, leafc_patch, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%deadstemn_xfer_patch) + call restartvar(ncid=ncid, flag=flag, varname='deadstemn_soy', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemn_soy_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemn_storage_soy', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemn_storage_soy_patch) + call restartvar(ncid=ncid, flag=flag, varname='livecrootn', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%livecrootn_patch) @@ -781,13 +809,19 @@ subroutine Restart ( this, bounds, ncid, flag, leafc_patch, & ! roughness length is not zero in canopy flux calculation if (pftcon%woody(patch%itype(p)) == 1._r8) then - this%deadstemn_patch(p) = deadstemc_patch(p) / pftcon%deadwdcn(patch%itype(p)) + if (patch%itype(p) < npcropmin) then + this%deadstemn_patch(p) = deadstemc_patch(p) / pftcon%deadwdcn(patch%itype(p)) + else + this%deadstemn_patch(p) = 0._r8 + end if else this%deadstemn_patch(p) = 0._r8 end if this%deadstemn_storage_patch(p) = 0._r8 this%deadstemn_xfer_patch(p) = 0._r8 + this%deadstemn_soy_patch(p) = 0._r8 + this%deadstemn_storage_soy_patch(p) = 0._r8 this%livecrootn_patch(p) = 0._r8 this%livecrootn_storage_patch(p) = 0._r8 this%livecrootn_xfer_patch(p) = 0._r8 @@ -876,6 +910,8 @@ subroutine SetValues ( this, & this%deadstemn_patch(i) = value_patch this%deadstemn_storage_patch(i) = value_patch this%deadstemn_xfer_patch(i) = value_patch + this%deadstemn_soy_patch(i) = value_patch + this%deadstemn_storage_soy_patch(i) = value_patch this%livecrootn_patch(i) = value_patch this%livecrootn_storage_patch(i) = value_patch this%livecrootn_xfer_patch(i) = value_patch diff --git a/src/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..fd6c2acfec 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 @@ -90,6 +89,7 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types slatop => pftcon%slatop , & ! Input: specific leaf area at top of canopy, projected area basis [m^2/gC] dsladlai => pftcon%dsladlai , & ! Input: dSLA/dLAI, projected area basis [m^2/gC] z0mr => pftcon%z0mr , & ! Input: ratio of momentum roughness length to canopy top height (-) @@ -97,7 +97,9 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & dwood => pftcon%dwood , & ! Input: density of wood (gC/m^3) ztopmx => pftcon%ztopmx , & ! Input: laimx => pftcon%laimx , & ! Input: - + nstem => pftcon%nstem , & ! Input: Tree number density (#ind/m2) (introduced by E.Kluzek (2020, unreleased code) and adopted here by O.Dombrowski) + taper => pftcon%taper , & ! Input: ratio of height:radius_breast_height (tree allometry) (introduced by E.Kluzek (2020, unreleased code) and adopted here by O.Dombrowski) + allom2 => dgv_ecophyscon%allom2 , & ! Input: [real(r8) (:) ] ecophys const allom3 => dgv_ecophyscon%allom3 , & ! Input: [real(r8) (:) ] ecophys const @@ -114,7 +116,7 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & farea_burned => cnveg_state_inst%farea_burned_col , & ! Input: [real(r8) (:) ] F. Li and S. Levis htmx => cnveg_state_inst%htmx_patch , & ! Output: [real(r8) (:) ] max hgt attained by a crop during yr (m) peaklai => cnveg_state_inst%peaklai_patch , & ! Output: [integer (:) ] 1: max allowed lai; 0: not at max - + dormant_flag => cnveg_state_inst%dormant_flag_patch , & ! Output: [real(r8) (:) ] dormancy flag harvdate => crop_inst%harvdate_patch , & ! Input: [integer (:) ] harvest date ! *** Key Output from CN*** @@ -129,13 +131,6 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & dt = real( get_rad_step_size(), r8 ) - ! constant allometric parameters - taper = 200._r8 - stocking = 1000._r8 - - ! convert from stems/ha -> stems/m^2 - stocking = stocking / 10000._r8 - ! patch loop do fp = 1,num_soilp p = filter_soilp(fp) @@ -177,25 +172,23 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & if (woody(ivt(p)) == 1._r8) then - ! trees and shrubs - - ! if shrubs have a squat taper - if (ivt(p) >= nbrdlf_evr_shrub .and. ivt(p) <= nbrdlf_dcd_brl_shrub) then - taper = 10._r8 - ! otherwise have a tall taper - else - taper = 200._r8 + if (perennial(ivt(p)) == 1._r8) then + if (dormant_flag(p) == 0._r8) then + if (tlai(p) >= laimx(ivt(p))) peaklai(p) = 1 + else if (dormant_flag(p) == 1._r8) then + peaklai(p) = 0 + end if end if - ! trees and shrubs for now have a very simple allometry, with hard-wired - ! stem taper (height:radius) and hard-wired stocking density (#individuals/area) + ! trees and shrubs for now have a very simple allometry, with + ! stem taper (height:radius) and nstem from PFT parameter file if (use_cndv) then if (fpcgrid(p) > 0._r8 .and. nind(p) > 0._r8) then stocking = nind(p)/fpcgrid(p) !#ind/m2 nat veg area -> #ind/m2 patch area htop(p) = allom2(ivt(p)) * ( (24._r8 * deadstemc(p) / & - (SHR_CONST_PI * stocking * dwood(ivt(p)) * taper))**(1._r8/3._r8) )**allom3(ivt(p)) ! lpj's htop w/ cn's stemdiam + (SHR_CONST_PI * stocking * dwood(ivt(p)) * taper(ivt(p))))**(1._r8/3._r8) )**allom3(ivt(p)) ! lpj's htop w/ cn's stemdiam else htop(p) = 0._r8 @@ -203,12 +196,20 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & else !correct height calculation if doing accelerated spinup - if (spinup_state == 2) then - htop(p) = ((3._r8 * deadstemc(p) * 10._r8 * taper * taper)/ & - (SHR_CONST_PI * stocking * dwood(ivt(p))))**(1._r8/3._r8) + if (spinup_state == 2) then + if (perennial(ivt(p)) == 1._r8 .and. dormant_flag(p) == 1._r8 .and. deadstemc(p)== 0._r8) then + htop(p) = 0.01_r8 + else + htop(p) = ((3._r8 * deadstemc(p) * 10._r8 * taper(ivt(p)) * taper(ivt(p)))/ & + (SHR_CONST_PI * nstem(ivt(p)) * dwood(ivt(p))))**(1._r8/3._r8) + end if else - htop(p) = ((3._r8 * deadstemc(p) * taper * taper)/ & - (SHR_CONST_PI * stocking * dwood(ivt(p))))**(1._r8/3._r8) + if (perennial(ivt(p)) == 1._r8 .and. dormant_flag(p) == 1._r8 .and. deadstemc(p)== 0._r8) then + htop(p) = 0.01_r8 + else + htop(p) = ((3._r8 * deadstemc(p) * taper(ivt(p)) * taper(ivt(p)))/ & + (SHR_CONST_PI * nstem(ivt(p)) * dwood(ivt(p))))**(1._r8/3._r8) + end if end if endif @@ -217,12 +218,15 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & ! Adding test to keep htop from getting too close to forcing height for windspeed ! Also added for grass, below, although it is not likely to ever be an issue. htop(p) = min(htop(p),(forc_hgt_u_patch(p)/(displar(ivt(p))+z0mr(ivt(p))))-3._r8) - ! Peter Thornton, 8/11/2004 ! Adding constraint to keep htop from going to 0.0. ! This becomes an issue when fire mortality is pushing deadstemc ! to 0.0. htop(p) = max(htop(p), 0.01_r8) + ! for fruit trees restrict height to maximum pruned tree height + if (perennial(ivt(p)) == 1._r8) then + htop(p) = min(htop(p), ztopmx(ivt(p))) + end if hbot(p) = max(0._r8, min(3._r8, htop(p)-1._r8)) diff --git a/src/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..4119f318a2 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 @@ -498,7 +499,7 @@ subroutine CNHarvestPftToColumn (num_soilc, filter_soilc, & p = col%patchi(c) + pi - 1 if (patch%active(p)) then - + ! leaf harvest mortality carbon fluxes harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & hrv_leafc_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) @@ -522,7 +523,6 @@ subroutine CNHarvestPftToColumn (num_soilc, filter_soilc, & hrv_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & hrv_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) - ! storage harvest mortality carbon fluxes harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & hrv_leafc_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) @@ -630,7 +630,7 @@ subroutine CNHarvestPftToColumn (num_soilc, filter_soilc, & ! wood harvest mortality carbon fluxes to product pools cwood_harvestc(c) = cwood_harvestc(c) + & pwood_harvestc(p) * wtcol(p) - + ! wood harvest mortality nitrogen fluxes to product pools cwood_harvestn(c) = cwood_harvestn(c) + & pwood_harvestn(p) * wtcol(p) diff --git a/src/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..b1a3c14c5c 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,15 @@ module pftconMod real(r8), allocatable :: evergreen (:) ! binary flag for evergreen leaf habit (0 or 1) real(r8), allocatable :: stress_decid (:) ! binary flag for stress-deciduous leaf habit (0 or 1) real(r8), allocatable :: season_decid (:) ! binary flag for seasonal-deciduous leaf habit (0 or 1) + real(r8), allocatable :: perennial (:) ! binary flag for perennial crop phenology (0 or 1) (added by O.Dombrowski) + real(r8), allocatable :: mulch_pruning (:) ! binary flag for mulching or exporting pruning material (0 or 1) (added by O.Dombrowski) real(r8), allocatable :: pconv (:) ! proportion of deadstem to conversion flux real(r8), allocatable :: pprod10 (:) ! proportion of deadstem to 10-yr product pool real(r8), allocatable :: pprod100 (:) ! proportion of deadstem to 100-yr product pool real(r8), allocatable :: pprodharv10 (:) ! harvest mortality proportion of deadstem to 10-yr pool - + real(r8), allocatable :: prune_fr (:) ! fraction of deadstem that is pruned (added by O.Dombrowski) + real(r8), allocatable :: nstem (:) ! stem density (#/m2) (added by O.Dombrowski) + real(r8), allocatable :: taper (:) ! tapering ratio of height:radius_breast_height (added by O.Dombrowski) ! pft paraemeters for fire code real(r8), allocatable :: cc_leaf (:) real(r8), allocatable :: cc_lstem (:) @@ -372,9 +386,11 @@ subroutine InitAllocate (this) allocate( this%bfact (0:mxpft) ) allocate( this%aleaff (0:mxpft) ) allocate( this%arootf (0:mxpft) ) + allocate( this%arootf2 (0:mxpft) ) allocate( this%astemf (0:mxpft) ) allocate( this%arooti (0:mxpft) ) allocate( this%fleafi (0:mxpft) ) + allocate( this%aleafstor (0:mxpft) ) allocate( this%allconsl (0:mxpft) ) allocate( this%allconss (0:mxpft) ) allocate( this%ztopmx (0:mxpft) ) @@ -386,11 +402,19 @@ subroutine InitAllocate (this) allocate( this%mbbopt (0:mxpft) ) allocate( this%medlynslope (0:mxpft) ) allocate( this%medlynintercept(0:mxpft) ) - allocate( this%mxmat (0:mxpft) ) + allocate( this%mxmat (0:mxpft) ) + allocate( this%transplant (0:mxpft) ) + allocate( this%lfmat (0:mxpft) ) + allocate( this%grnrp (0:mxpft) ) + allocate( this%crequ (0:mxpft) ) + allocate( this%crit_temp (0:mxpft) ) + allocate( this%ndays_stor (0:mxpft) ) allocate( this%mnNHplantdate (0:mxpft) ) allocate( this%mxNHplantdate (0:mxpft) ) + allocate( this%mxNHharvdate (0:mxpft) ) allocate( this%mnSHplantdate (0:mxpft) ) allocate( this%mxSHplantdate (0:mxpft) ) + allocate( this%mxSHharvdate (0:mxpft) ) allocate( this%planttemp (0:mxpft) ) allocate( this%minplanttemp (0:mxpft) ) allocate( this%froot_leaf (0:mxpft) ) @@ -409,6 +433,8 @@ subroutine InitAllocate (this) allocate( this%evergreen (0:mxpft) ) allocate( this%stress_decid (0:mxpft) ) allocate( this%season_decid (0:mxpft) ) + allocate( this%perennial (0:mxpft) ) + allocate( this%mulch_pruning (0:mxpft) ) allocate( this%dwood (0:mxpft) ) allocate( this%root_density (0:mxpft) ) allocate( this%root_radius (0:mxpft) ) @@ -416,6 +442,9 @@ subroutine InitAllocate (this) allocate( this%pprod10 (0:mxpft) ) allocate( this%pprod100 (0:mxpft) ) allocate( this%pprodharv10 (0:mxpft) ) + allocate( this%prune_fr (0:mxpft) ) + allocate( this%nstem (0:mxpft) ) + allocate( this%taper (0:mxpft) ) allocate( this%cc_leaf (0:mxpft) ) allocate( this%cc_lstem (0:mxpft) ) allocate( this%cc_dstem (0:mxpft) ) @@ -739,6 +768,12 @@ subroutine InitRead(this) call ncd_io('season_decid', this%season_decid, 'read', ncid, readvar=readv, posNOTonfile=.true.) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + call ncd_io('perennial', this%perennial, 'read', ncid, readvar=readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('mulch_pruning', this%mulch_pruning, 'read', ncid, readvar=readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + call ncd_io('pftpar20', this%pftpar20, 'read', ncid, readvar=readv, posNOTonfile=.true.) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) @@ -849,6 +884,9 @@ subroutine InitRead(this) call ncd_io('arootf', this%arootf, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('arootf2', this%arootf2, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) call ncd_io('astemf', this%astemf, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) @@ -859,6 +897,9 @@ subroutine InitRead(this) call ncd_io('fleafi', this%fleafi, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + call ncd_io('aleafstor', this%aleafstor, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + call ncd_io('allconsl', this%allconsl, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) @@ -906,6 +947,33 @@ subroutine InitRead(this) call ncd_io('mxmat', this%mxmat, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + call ncd_io('transplant', this%transplant, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('lfmat', this%lfmat, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('grnrp', this%grnrp, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('crequ', this%crequ, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('crit_temp', this%crit_temp, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('ndays_stor', this%ndays_stor, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('prune_fr', this%prune_fr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('nstem', this%nstem, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('taper', this%taper, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + call ncd_io('cc_leaf', this% cc_leaf, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) @@ -960,6 +1028,12 @@ subroutine InitRead(this) call ncd_io('max_NH_planting_date', this%mxNHplantdate, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + call ncd_io('max_NH_harvest_date', this%mxNHharvdate, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('max_SH_harvest_date', this%mxSHharvdate, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + call ncd_io('max_SH_planting_date', this%mxSHplantdate, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) @@ -1287,9 +1361,11 @@ subroutine Clean(this) deallocate( this%bfact) deallocate( this%aleaff) deallocate( this%arootf) + deallocate( this%arootf2) deallocate( this%astemf) deallocate( this%arooti) deallocate( this%fleafi) + deallocate( this%aleafstor) deallocate( this%allconsl) deallocate( this%allconss) deallocate( this%ztopmx) @@ -1302,10 +1378,21 @@ subroutine Clean(this) deallocate( this%medlynslope) deallocate( this%medlynintercept) deallocate( this%mxmat) + deallocate( this%transplant) + deallocate( this%lfmat) + deallocate( this%grnrp) + deallocate( this%crequ) + deallocate( this%crit_temp) + deallocate( this%ndays_stor) + deallocate( this%prune_fr) + deallocate( this%nstem) + deallocate( this%taper) deallocate( this%mnNHplantdate) deallocate( this%mxNHplantdate) + deallocate( this%mxNHharvdate) deallocate( this%mnSHplantdate) deallocate( this%mxSHplantdate) + deallocate( this%mxSHharvdate) deallocate( this%planttemp) deallocate( this%minplanttemp) deallocate( this%froot_leaf) @@ -1324,6 +1411,8 @@ subroutine Clean(this) deallocate( this%evergreen) deallocate( this%stress_decid) deallocate( this%season_decid) + deallocate( this%perennial) + deallocate( this%mulch_pruning) deallocate( this%dwood) deallocate( this%root_density) deallocate( this%root_radius)