diff --git a/.github/ISSUE_TEMPLATE/01_bug_report.md b/.github/ISSUE_TEMPLATE/01_bug_report.md new file mode 100644 index 0000000000..427217bdfb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/01_bug_report.md @@ -0,0 +1,29 @@ +--- +name: Bug report +about: Report a problem with the code + +--- + +### Brief summary of bug + +[Give a one or two sentence summary. This could be the same as the issue title if you feel that is a sufficient summary.] + +### General bug information + +**CTSM version you are using:** [output of `git describe`] + +**Does this bug cause significantly incorrect results in the model's science?** [Yes / No] + +**Configurations affected:** [Fill this in if known.] + +### Details of bug + +[Fill in details here.] + +### Important details of your setup / configuration so we can reproduce the bug + +[Specify anything relevant: the compset, resolution, machine, compiler, any xml or namelist changes, etc. You don't have to repeat anything that you have already noted above.] + +### Important output or errors that show the problem + +[Fill this in with anything relevant that you haven't already noted; if there is nothing to add, delete this section.] diff --git a/.github/ISSUE_TEMPLATE/02_support_needed.md b/.github/ISSUE_TEMPLATE/02_support_needed.md new file mode 100644 index 0000000000..d3c69aaf6a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/02_support_needed.md @@ -0,0 +1,36 @@ +--- +name: Support needed for model use +about: Ask for help with using CTSM + +--- + +### NOTE: Be sure to read the relevant documentation and user forums + +We have limited staff and ability to provide support. Here are some resources that might provide help: +- User's Guide: https://escomp.github.io/ctsm-docs/doc/build/html/users_guide/index.html +- CLM Forum: https://bb.cgd.ucar.edu/forums/land-modeling-clm +- README files amongst the source code +- GitHub CTSM issues: https://github.com/escomp/ctsm/issues/ +- Also make sure this issue is unique to CTSM and not really an issue with CESM or CIME + +### Details of support request + +[Fill in details here.] + +### Important details of your setup / configuration so we can better assist you + +**CTSM version you are using:** [output of `git describe`] + +**Have you made any modifications to code, xml files, etc.?** [Yes / No] + +[If Yes: Please point us to your modifications. However: In general we can NOT support problems with modified code. Try to show the problem without modifications.] + +**If you are having problems with a specific case: Is your case on a machine accessible to most CTSM developers (e.g., an NCAR machine)?** [Yes / No] + +If Yes: + +- Location of case directory: [Fill this in] + +- Location of run directory: [Fill this in] + +[If No: Please make sure you have included all important input and output needed to understand your issue, either by pasting it into the issue text, or by attaching relevant files. However: We are less likely to be able to reproduce your problem if the issue is NOT on an NCAR machine.] diff --git a/.github/ISSUE_TEMPLATE/03_science_discussion.md b/.github/ISSUE_TEMPLATE/03_science_discussion.md new file mode 100644 index 0000000000..25f47ff601 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/03_science_discussion.md @@ -0,0 +1,7 @@ +--- +name: Science discussion +about: We encourage the use of issues to discuss CTSM science developments + +--- + + diff --git a/.github/ISSUE_TEMPLATE/04_other.md b/.github/ISSUE_TEMPLATE/04_other.md new file mode 100644 index 0000000000..61898d3a75 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/04_other.md @@ -0,0 +1,7 @@ +--- +name: Other +about: Other issues (enhancement, cleanup, documentation, etc.) + +--- + + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000..36a87f49f1 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,20 @@ +### Description of changes + +### Specific notes + +Contributors other than yourself, if any: + +CTSM Issues Fixed (include github issue #): + +Are answers expected to change (and if so in what way)? + +Any User Interface Changes (namelist or namelist defaults changes)? + +Testing performed, if any: +(List what testing you did to show your changes worked as expected) +(This can be manual testing or running of the different test suites) +(Documentation on system testing is here: https://github.com/ESCOMP/ctsm/wiki/System-Testing-Guide) +(aux_clm on cheyenne for gnu/pgi and hobart for gnu/pgi/nag is the standard for tags on master) + +**NOTE: Be sure to check your Coding style against the standard:** +https://github.com/ESCOMP/ctsm/wiki/CTSM-coding-guidelines diff --git a/src/clm5/biogeochem/CNBalanceCheckMod.F90 b/src/clm5/biogeochem/CNBalanceCheckMod.F90 index 8f123cf442..499cad44c7 100644 --- a/src/clm5/biogeochem/CNBalanceCheckMod.F90 +++ b/src/clm5/biogeochem/CNBalanceCheckMod.F90 @@ -105,6 +105,7 @@ subroutine BeginCNBalance(this, bounds, num_soilc, filter_soilc, & c = filter_soilc(fc) col_begcb(c) = totcolc(c) col_begnb(c) = totcoln(c) + end do end associate @@ -161,10 +162,9 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & ! calculate the total column-level carbon storage, for mass conservation check col_endcb(c) = totcolc(c) - ! calculate total column-level inputs col_cinputs = gpp(c) - + ! calculate total column-level outputs ! er = ar + hr, col_fire_closs includes patch-level fire losses col_coutputs = er(c) + col_fire_closs(c) + col_hrv_xsmrpool_to_atm(c) + & @@ -181,7 +181,7 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & ! subtract leaching flux col_coutputs = col_coutputs - som_c_leached(c) - + ! calculate the total column-level carbon balance error for this time step col_errcb(c) = (col_cinputs - col_coutputs)*dt - & (col_endcb(c) - col_begcb(c)) diff --git a/src/clm5/biogeochem/CNCIsoFluxMod.F90 b/src/clm5/biogeochem/CNCIsoFluxMod.F90 index a92ab44e47..63d1796f46 100644 --- a/src/clm5/biogeochem/CNCIsoFluxMod.F90 +++ b/src/clm5/biogeochem/CNCIsoFluxMod.F90 @@ -135,7 +135,7 @@ subroutine CIsoFlux1(num_soilc, filter_soilc, num_soilp, filter_soilp, & iso_cnveg_cf%frootc_to_litter_patch , cnveg_cf%frootc_to_litter_patch, & iso_cnveg_cs%frootc_patch , cnveg_cs%frootc_patch, & num_soilp , filter_soilp, 1._r8, 0, isotope) - + call CIsoFluxCalc(& iso_cnveg_cf%livestemc_to_deadstemc_patch , cnveg_cf%livestemc_to_deadstemc_patch, & iso_cnveg_cs%livestemc_patch , cnveg_cs%livestemc_patch, & @@ -414,6 +414,17 @@ subroutine CIsoFlux1(num_soilc, filter_soilc, num_soilp, filter_soilp, & iso_cnveg_cs%totvegc_patch , cnveg_cs%totvegc_patch, & num_soilp , filter_soilp, 1._r8, 0, isotope) + call CIsoFluxCalc(& + iso_cnveg_cf%crop_seedc_to_froot_patch , cnveg_cf%crop_seedc_to_froot_patch, & + iso_cnveg_cs%totvegc_patch , cnveg_cs%totvegc_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%crop_seedc_to_deadstem_patch , cnveg_cf%crop_seedc_to_deadstem_patch, & + iso_cnveg_cs%totvegc_patch , cnveg_cs%totvegc_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& iso_cnveg_cf%grain_curmr_patch , cnveg_cf%grain_curmr_patch, & iso_cnveg_cs%cpool_patch , cnveg_cs%cpool_patch, & @@ -1222,7 +1233,7 @@ subroutine CNCIsoLitterToColumn (num_soilc, filter_soilc, & + frootc_to_litter(p) * fr_fcel(ivt(p)) * wtcol(p) * froot_prof(p,j) phenology_c_to_litr_lig_c(c,j) = phenology_c_to_litr_lig_c(c,j) & + frootc_to_litter(p) * fr_flig(ivt(p)) * wtcol(p) * froot_prof(p,j) - + !DML if (ivt(p) >= npcropmin) then ! add livestemc to litter ! stem litter carbon fluxes @@ -1492,7 +1503,6 @@ subroutine CNCIsoHarvestPftToColumn (num_soilc, filter_soilc, & hrv_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & hrv_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) - ! storage harvest mortality carbon fluxes harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & hrv_leafc_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) diff --git a/src/clm5/biogeochem/CNCStateUpdate1Mod.F90 b/src/clm5/biogeochem/CNCStateUpdate1Mod.F90 index e1da2f354f..ed96b33192 100644 --- a/src/clm5/biogeochem/CNCStateUpdate1Mod.F90 +++ b/src/clm5/biogeochem/CNCStateUpdate1Mod.F90 @@ -173,7 +173,8 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) - + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types (1=perennial, 0= not perennial) + mulch_pruning => pftcon%mulch_pruning , & ! Input: binary flag for mulching or exporting pruning material (1=mulching, 0=exporting) cascade_donor_pool => decomp_cascade_con%cascade_donor_pool , & ! Input: [integer (:) ] which pool is C taken from for a given decomposition step cascade_receiver_pool => decomp_cascade_con%cascade_receiver_pool , & ! Input: [integer (:) ] which pool is C added to for a given decomposition step @@ -268,10 +269,15 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops ! lines here for consistency; the transfer terms are zero - cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) + cf_veg%livestemc_xfer_to_livestemc_patch(p)*dt - cs_veg%livestemc_xfer_patch(p) = cs_veg%livestemc_xfer_patch(p) - cf_veg%livestemc_xfer_to_livestemc_patch(p)*dt - cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) + cf_veg%grainc_xfer_to_grainc_patch(p)*dt - cs_veg%grainc_xfer_patch(p) = cs_veg%grainc_xfer_patch(p) - cf_veg%grainc_xfer_to_grainc_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) + cf_veg%grainc_xfer_to_grainc_patch(p)*dt + cs_veg%grainc_xfer_patch(p) = cs_veg%grainc_xfer_patch(p) - cf_veg%grainc_xfer_to_grainc_patch(p)*dt + else + cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) + cf_veg%livestemc_xfer_to_livestemc_patch(p)*dt + cs_veg%livestemc_xfer_patch(p) = cs_veg%livestemc_xfer_patch(p) - cf_veg%livestemc_xfer_to_livestemc_patch(p)*dt + cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) + cf_veg%grainc_xfer_to_grainc_patch(p)*dt + cs_veg%grainc_xfer_patch(p) = cs_veg%grainc_xfer_patch(p) - cf_veg%grainc_xfer_to_grainc_patch(p)*dt + end if end if ! phenology: litterfall fluxes @@ -286,12 +292,27 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%deadcrootc_patch(p) = cs_veg%deadcrootc_patch(p) + cf_veg%livecrootc_to_deadcrootc_patch(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) - cf_veg%livestemc_to_litter_patch(p)*dt - cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) & - - (cf_veg%grainc_to_food_patch(p) + cf_veg%grainc_to_seed_patch(p))*dt - cs_veg%cropseedc_deficit_patch(p) = cs_veg%cropseedc_deficit_patch(p) & - - cf_veg%crop_seedc_to_leaf_patch(p) * dt & - + cf_veg%grainc_to_seed_patch(p) * dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) & + - (cf_veg%grainc_to_food_patch(p) + cf_veg%grainc_to_seed_patch(p))*dt + cs_veg%cropseedc_deficit_patch(p) = cs_veg%cropseedc_deficit_patch(p) & + - cf_veg%crop_seedc_to_leaf_patch(p) * dt & + - cf_veg%crop_seedc_to_froot_patch(p) * dt & !(added by O.Dombrowski) + - cf_veg%crop_seedc_to_deadstem_patch(p) * dt & !(added by O.Dombrowski) + + cf_veg%grainc_to_seed_patch(p) * dt + if (mulch_pruning(ivt(p)) == 1._r8) then + ! update stem biomass after pruning + cs_veg%deadstemc_patch(p) = cs_veg%deadstemc_patch(p) - cf_veg%prunec_to_litter_patch(p)*dt + cs_veg%deadstemc_storage_patch(p) = cs_veg%deadstemc_storage_patch(p) - cf_veg%prunec_storage_to_litter_patch(p)*dt + end if + else + cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) - cf_veg%livestemc_to_litter_patch(p)*dt + cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) & + - (cf_veg%grainc_to_food_patch(p) + cf_veg%grainc_to_seed_patch(p))*dt + cs_veg%cropseedc_deficit_patch(p) = cs_veg%cropseedc_deficit_patch(p) & + - cf_veg%crop_seedc_to_leaf_patch(p) * dt & + + cf_veg%grainc_to_seed_patch(p) * dt + end if end if check_cpool = cs_veg%cpool_patch(p)- cf_veg%psnsun_to_cpool_patch(p)*dt-cf_veg%psnshade_to_cpool_patch(p)*dt @@ -302,13 +323,20 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_xsmrpool_patch(p)*dt cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%leaf_curmr_patch(p)*dt cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%froot_curmr_patch(p)*dt - If (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) == 1._r8) then cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%livestem_curmr_patch(p)*dt cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%livecroot_curmr_patch(p)*dt + end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%livestem_curmr_patch(p)*dt - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%grain_curmr_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%grain_curmr_patch(p)*dt + + else + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%livestem_curmr_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%grain_curmr_patch(p)*dt + + end if end if @@ -369,21 +397,31 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%deadcrootc_patch(p) = cs_veg%deadcrootc_patch(p) + cf_veg%cpool_to_deadcrootc_patch(p)*dt cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_deadcrootc_storage_patch(p)*dt cs_veg%deadcrootc_storage_patch(p) = cs_veg%deadcrootc_storage_patch(p) + cf_veg%cpool_to_deadcrootc_storage_patch(p)*dt + end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - if (carbon_resp_opt == 1) then + if (carbon_resp_opt == 1 .and. perennial(ivt(p)) == 0._r8) then !(perennial flag added by O.Dombrowski) cf_veg%cpool_to_livestemc_patch(p) = cf_veg%cpool_to_livestemc_patch(p) - cf_veg%cpool_to_livestemc_resp_patch(p) cf_veg%cpool_to_livestemc_storage_patch(p) = cf_veg%cpool_to_livestemc_storage_patch(p) - & cf_veg%cpool_to_livestemc_storage_resp_patch(p) end if - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_livestemc_patch(p)*dt - cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) + cf_veg%cpool_to_livestemc_patch(p)*dt - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_livestemc_storage_patch(p)*dt - cs_veg%livestemc_storage_patch(p) = cs_veg%livestemc_storage_patch(p) + cf_veg%cpool_to_livestemc_storage_patch(p)*dt - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_grainc_patch(p)*dt - cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) + cf_veg%cpool_to_grainc_patch(p)*dt - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_grainc_storage_patch(p)*dt - cs_veg%grainc_storage_patch(p) = cs_veg%grainc_storage_patch(p) + cf_veg%cpool_to_grainc_storage_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_grainc_patch(p)*dt + cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) + cf_veg%cpool_to_grainc_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_grainc_storage_patch(p)*dt + cs_veg%grainc_storage_patch(p) = cs_veg%grainc_storage_patch(p) + cf_veg%cpool_to_grainc_storage_patch(p)*dt + + else + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_livestemc_patch(p)*dt + cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) + cf_veg%cpool_to_livestemc_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_livestemc_storage_patch(p)*dt + cs_veg%livestemc_storage_patch(p) = cs_veg%livestemc_storage_patch(p) + cf_veg%cpool_to_livestemc_storage_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_grainc_patch(p)*dt + cs_veg%grainc_patch(p) = cs_veg%grainc_patch(p) + cf_veg%cpool_to_grainc_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_grainc_storage_patch(p)*dt + cs_veg%grainc_storage_patch(p) = cs_veg%grainc_storage_patch(p) + cf_veg%cpool_to_grainc_storage_patch(p)*dt + + end if end if ! growth respiration fluxes for current growth @@ -397,8 +435,12 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_deadcroot_gr_patch(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_livestem_gr_patch(p)*dt - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_grain_gr_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_grain_gr_patch(p)*dt + else + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_livestem_gr_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_grain_gr_patch(p)*dt + end if end if ! growth respiration for transfer growth @@ -411,8 +453,12 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) - cf_veg%transfer_deadcroot_gr_patch(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) - cf_veg%transfer_livestem_gr_patch(p)*dt - cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) - cf_veg%transfer_grain_gr_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) - cf_veg%transfer_grain_gr_patch(p)*dt + else + cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) - cf_veg%transfer_livestem_gr_patch(p)*dt + cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) - cf_veg%transfer_grain_gr_patch(p)*dt + end if end if ! growth respiration at time of storage @@ -426,10 +472,12 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_deadcroot_storage_gr_patch(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_livestem_storage_gr_patch(p)*dt - - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_grain_storage_gr_patch(p)*dt - + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_grain_storage_gr_patch(p)*dt + else + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_livestem_storage_gr_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_grain_storage_gr_patch(p)*dt + end if end if ! growth respiration stored for release during transfer growth @@ -454,16 +502,25 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) + cf_veg%gresp_storage_to_xfer_patch(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - ! lines here for consistency; the transfer terms are zero - cs_veg%livestemc_storage_patch(p) = cs_veg%livestemc_storage_patch(p) - cf_veg%livestemc_storage_to_xfer_patch(p)*dt - cs_veg%livestemc_xfer_patch(p) = cs_veg%livestemc_xfer_patch(p) + cf_veg%livestemc_storage_to_xfer_patch(p)*dt - cs_veg%grainc_storage_patch(p) = cs_veg%grainc_storage_patch(p) - cf_veg%grainc_storage_to_xfer_patch(p)*dt - cs_veg%grainc_xfer_patch(p) = cs_veg%grainc_xfer_patch(p) + cf_veg%grainc_storage_to_xfer_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cs_veg%grainc_storage_patch(p) = cs_veg%grainc_storage_patch(p) - cf_veg%grainc_storage_to_xfer_patch(p)*dt + cs_veg%grainc_xfer_patch(p) = cs_veg%grainc_xfer_patch(p) + cf_veg%grainc_storage_to_xfer_patch(p)*dt + else + ! lines here for consistency; the transfer terms are zero + cs_veg%livestemc_storage_patch(p) = cs_veg%livestemc_storage_patch(p) - cf_veg%livestemc_storage_to_xfer_patch(p)*dt + cs_veg%livestemc_xfer_patch(p) = cs_veg%livestemc_xfer_patch(p) + cf_veg%livestemc_storage_to_xfer_patch(p)*dt + cs_veg%grainc_storage_patch(p) = cs_veg%grainc_storage_patch(p) - cf_veg%grainc_storage_to_xfer_patch(p)*dt + cs_veg%grainc_xfer_patch(p) = cs_veg%grainc_xfer_patch(p) + cf_veg%grainc_storage_to_xfer_patch(p)*dt + end if end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%livestem_xsmr_patch(p)*dt - cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%grain_xsmr_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1._r8) then + cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%grain_xsmr_patch(p)*dt + else + cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%livestem_xsmr_patch(p)*dt + cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%grain_xsmr_patch(p)*dt + end if if (harvdate(p) < 999) then ! beginning at harvest, send to atm ! TODO (mv, 11-02-2014) the following lines are why the cf_veg is ! an intent(inout) @@ -491,6 +548,7 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%xsmrpool_patch(p) = 0._r8 cs_veg%cpool_patch(p) = 0._r8 cs_veg%frootc_patch(p) = 0._r8 + end if ! Slowly release xsmrpool to atmosphere @@ -500,6 +558,7 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & ! update xsmrpool loss state cs_veg%xsmrpool_loss_patch(p) = cs_veg%xsmrpool_loss_patch(p) - cf_veg%xsmrpool_to_atm_patch(p) * dt + end if end if diff --git a/src/clm5/biogeochem/CNCStateUpdate2Mod.F90 b/src/clm5/biogeochem/CNCStateUpdate2Mod.F90 index ef1f6f9345..ef0d67dd36 100644 --- a/src/clm5/biogeochem/CNCStateUpdate2Mod.F90 +++ b/src/clm5/biogeochem/CNCStateUpdate2Mod.F90 @@ -178,7 +178,6 @@ subroutine CStateUpdate2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_soil%decomp_cpools_vr_col(c,j,i_lig_lit) + cf_veg%harvest_c_to_litr_lig_c_col(c,j) * dt cs_soil%decomp_cpools_vr_col(c,j,i_cwd) = & cs_soil%decomp_cpools_vr_col(c,j,i_cwd) + cf_veg%harvest_c_to_cwdc_col(c,j) * dt - ! wood to product pools - states updated in CNProducts end do end do @@ -201,7 +200,6 @@ subroutine CStateUpdate2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & - cf_veg%hrv_livecrootc_to_litter_patch(p) * dt cs_veg%deadcrootc_patch(p) = cs_veg%deadcrootc_patch(p) & - cf_veg%hrv_deadcrootc_to_litter_patch(p) * dt - ! xsmrpool cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) & - cf_veg%hrv_xsmrpool_to_atm_patch(p) * dt diff --git a/src/clm5/biogeochem/CNDriverMod.F90 b/src/clm5/biogeochem/CNDriverMod.F90 index 94bc3f3554..43dbcf5c6d 100644 --- a/src/clm5/biogeochem/CNDriverMod.F90 +++ b/src/clm5/biogeochem/CNDriverMod.F90 @@ -352,11 +352,12 @@ subroutine CNDriverNoLeaching(bounds, filter_soilp, num_pcropp, filter_pcropp, & doalb, waterstate_inst, temperature_inst, atm2lnd_inst, & crop_inst, canopystate_inst, soilstate_inst, dgvs_inst, & - cnveg_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & + cnveg_state_inst, soilbiogeochem_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp,1:nlevdecomp_full), & froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp,1:nlevdecomp_full), & + stem_prof_patch=soilbiogeochem_state_inst%stem_prof_patch(begp:endp,1:nlevdecomp_full), & phase=1) call t_stopf('CNPhenology_phase1') @@ -447,22 +448,24 @@ subroutine CNDriverNoLeaching(bounds, filter_soilp, num_pcropp, filter_pcropp, & doalb, waterstate_inst, temperature_inst, atm2lnd_inst, & crop_inst, canopystate_inst, soilstate_inst, dgvs_inst, & - cnveg_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & + cnveg_state_inst,soilbiogeochem_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp,1:nlevdecomp_full), & froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp,1:nlevdecomp_full), & + stem_prof_patch=soilbiogeochem_state_inst%stem_prof_patch(begp:endp,1:nlevdecomp_full), & phase=1) end if call CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & filter_soilp, num_pcropp, filter_pcropp, & doalb, waterstate_inst, temperature_inst, atm2lnd_inst, & crop_inst, canopystate_inst, soilstate_inst, dgvs_inst, & - cnveg_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & + cnveg_state_inst, soilbiogeochem_state_inst,cnveg_carbonstate_inst, cnveg_carbonflux_inst, & cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp,1:nlevdecomp_full), & froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp,1:nlevdecomp_full), & + stem_prof_patch=soilbiogeochem_state_inst%stem_prof_patch(begp:endp,1:nlevdecomp_full), & phase=2) call t_stopf('CNPhenology') diff --git a/src/clm5/biogeochem/CNFUNMod.F90 b/src/clm5/biogeochem/CNFUNMod.F90 index f1adee8f6b..3a97f40223 100644 --- a/src/clm5/biogeochem/CNFUNMod.F90 +++ b/src/clm5/biogeochem/CNFUNMod.F90 @@ -510,6 +510,7 @@ subroutine CNFUN(bounds,num_soilc, filter_soilc,num_soilp& ! -deciduous leaf habit (0 or 1) stress_decid => pftcon%stress_decid , & ! Input: binary flag for stress ! -deciduous leaf habit (0 or 1) + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types (0 or 1) a_fix => pftcon%a_fix , & ! Input: A BNF parameter b_fix => pftcon%b_fix , & ! Input: A BNF parameter c_fix => pftcon%c_fix , & ! Input: A BNF parameter @@ -1194,7 +1195,7 @@ subroutine CNFUN(bounds,num_soilc, filter_soilc,num_soilp& ! Calculate appropriate degree of retranslocation !------------------------------------------------------------------------------- - if(leafc(p).gt.0.0_r8.and.litterfall_n_step(p,istp)* fixerfrac>0.0_r8.and.ivt(p) 0.0_r8.and. (ivt(p) pftcon%leafcn , & ! Input: leaf C:N (gC/gN) frootcn => pftcon%frootcn , & ! Input: fine root C:N (gC/gN) livewdcn => pftcon%livewdcn , & ! Input: live wood (phloem and ray parenchyma) C:N (gC/gN) - + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types (1=perennial, 0=not perennial) + laisun => canopystate_inst%laisun_patch , & ! Input: [real(r8) (:)] sunlit projected leaf area index laisha => canopystate_inst%laisha_patch , & ! Input: [real(r8) (:)] shaded projected leaf area index @@ -147,19 +148,29 @@ subroutine CNGResp(num_soilp, filter_soilp, cnveg_carbonflux_inst, canopystate_i respfact_livestem_storage = 1.0_r8 if (ivt(p) >= npcropmin) then ! skip 2 generic crops - cpool_livestem_gr(p) = cpool_to_livestemc(p) * grperc(ivt(p)) * respfact_livestem + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + cpool_grain_gr(p) = cpool_to_grainc(p) * grperc(ivt(p)) - cpool_livestem_storage_gr(p) = cpool_to_livestemc_storage(p) * grperc(ivt(p)) * grpnow(ivt(p)) * & - respfact_livestem_storage + cpool_grain_storage_gr(p) = cpool_to_grainc_storage(p) * grperc(ivt(p)) * grpnow(ivt(p)) - transfer_livestem_gr(p) = livestemc_xfer_to_livestemc(p) * grperc(ivt(p)) * (1._r8 - grpnow(ivt(p))) * & - respfact_livestem_storage + transfer_grain_gr(p) = grainc_xfer_to_grainc(p) * grperc(ivt(p)) * (1._r8 - grpnow(ivt(p))) + + else + cpool_livestem_gr(p) = cpool_to_livestemc(p) * grperc(ivt(p)) * respfact_livestem + + cpool_livestem_storage_gr(p) = cpool_to_livestemc_storage(p) * grperc(ivt(p)) * grpnow(ivt(p)) * & + respfact_livestem_storage + + transfer_livestem_gr(p) = livestemc_xfer_to_livestemc(p) * grperc(ivt(p)) * (1._r8 - grpnow(ivt(p))) * & + respfact_livestem_storage - cpool_grain_gr(p) = cpool_to_grainc(p) * grperc(ivt(p)) + cpool_grain_gr(p) = cpool_to_grainc(p) * grperc(ivt(p)) - cpool_grain_storage_gr(p) = cpool_to_grainc_storage(p) * grperc(ivt(p)) * grpnow(ivt(p)) + cpool_grain_storage_gr(p) = cpool_to_grainc_storage(p) * grperc(ivt(p)) * grpnow(ivt(p)) - transfer_grain_gr(p) = grainc_xfer_to_grainc(p) * grperc(ivt(p)) * (1._r8 - grpnow(ivt(p))) + transfer_grain_gr(p) = grainc_xfer_to_grainc(p) * grperc(ivt(p)) * (1._r8 - grpnow(ivt(p))) + + end if end if ! leaf and fine root growth respiration @@ -203,6 +214,7 @@ subroutine CNGResp(num_soilp, filter_soilp, cnveg_carbonflux_inst, canopystate_i cpool_deadcroot_storage_gr(p) = cpool_to_deadcrootc_storage(p) * grperc(ivt(p)) * grpnow(ivt(p)) transfer_deadcroot_gr(p) = deadcrootc_xfer_to_deadcrootc(p) * grperc(ivt(p)) * (1._r8 - grpnow(ivt(p))) + end if end do diff --git a/src/clm5/biogeochem/CNGapMortalityMod.F90 b/src/clm5/biogeochem/CNGapMortalityMod.F90 index 939d4b52eb..31f6c1627b 100644 --- a/src/clm5/biogeochem/CNGapMortalityMod.F90 +++ b/src/clm5/biogeochem/CNGapMortalityMod.F90 @@ -128,7 +128,8 @@ subroutine CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_so associate( & ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type - woody => pftcon%woody , & ! Input: binary flag for woody lifeform + woody => pftcon%woody , & ! Input: binary flag for woody lifeform + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types greffic => dgvs_inst%greffic_patch , & ! Input: [real(r8) (:) ] heatstress => dgvs_inst%heatstress_patch , & ! Input: [real(r8) (:) ] @@ -235,7 +236,7 @@ subroutine CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_so cnveg_nitrogenflux_inst%m_deadcrootn_to_litter_patch(p) = cnveg_nitrogenstate_inst%deadcrootn_patch(p) * m end if - if (ivt(p) < npcropmin) then + if (ivt(p) < npcropmin .or. perennial(ivt(p)) == 1._r8) then ! perennial flag added by O.Dombrowski cnveg_nitrogenflux_inst%m_retransn_to_litter_patch(p) = cnveg_nitrogenstate_inst%retransn_patch(p) * m end if diff --git a/src/clm5/biogeochem/CNMRespMod.F90 b/src/clm5/biogeochem/CNMRespMod.F90 index 3a7052d0bb..51e5235840 100644 --- a/src/clm5/biogeochem/CNMRespMod.F90 +++ b/src/clm5/biogeochem/CNMRespMod.F90 @@ -176,7 +176,7 @@ subroutine CNMResp(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) - + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types (1=perennial, 0= not perennial) frac_veg_nosno => canopystate_inst%frac_veg_nosno_patch , & ! Input: [integer (:) ] fraction of vegetation not covered by snow (0 OR 1) [-] laisun => canopystate_inst%laisun_patch , & ! Input: [real(r8) (:) ] sunlit projected leaf area index laisha => canopystate_inst%laisha_patch , & ! Input: [real(r8) (:) ] shaded projected leaf area index @@ -264,6 +264,9 @@ subroutine CNMResp(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & if (woody(ivt(p)) == 1) then livestem_mr(p) = livestemn(p)*br*tc livecroot_mr(p) = livecrootn(p)*br_root*tc + if (perennial(ivt(p)) == 1._r8) then ! (added by O.Dombrowski) + grain_mr(p) = grainn(p)*br*tc + end if else if (ivt(p) >= npcropmin) then livestem_mr(p) = livestemn(p)*br*tc grain_mr(p) = grainn(p)*br*tc diff --git a/src/clm5/biogeochem/CNNDynamicsMod.F90 b/src/clm5/biogeochem/CNNDynamicsMod.F90 index b8796912a2..6fab2c247a 100644 --- a/src/clm5/biogeochem/CNNDynamicsMod.F90 +++ b/src/clm5/biogeochem/CNNDynamicsMod.F90 @@ -304,7 +304,7 @@ subroutine CNSoyfix (bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & ! ! !USES: use pftconMod, only : ntmp_soybean, nirrig_tmp_soybean - use pftconMod, only : ntrp_soybean, nirrig_trp_soybean + !use pftconMod, only : ntrp_soybean, nirrig_trp_soybean ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -362,9 +362,9 @@ subroutine CNSoyfix (bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & if (croplive(p) .and. & (patch%itype(p) == ntmp_soybean .or. & - patch%itype(p) == nirrig_tmp_soybean .or. & - patch%itype(p) == ntrp_soybean .or. & - patch%itype(p) == nirrig_trp_soybean) ) then + patch%itype(p) == nirrig_tmp_soybean)) then !.or. & + !patch%itype(p) == ntrp_soybean .or. & + !patch%itype(p) == nirrig_trp_soybean) ) then ! difference between supply and demand diff --git a/src/clm5/biogeochem/CNNStateUpdate1Mod.F90 b/src/clm5/biogeochem/CNNStateUpdate1Mod.F90 index 6c1d112029..72fcfca9c2 100644 --- a/src/clm5/biogeochem/CNNStateUpdate1Mod.F90 +++ b/src/clm5/biogeochem/CNNStateUpdate1Mod.F90 @@ -112,7 +112,8 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) - + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types (1=perennial, 0= not perennial) + mulch_pruning => pftcon%mulch_pruning , & ! Input: binary flag for exporting of mulching of pruning material (1=mulching, 0=exporting) nf_veg => cnveg_nitrogenflux_inst , & ! Input: ns_veg => cnveg_nitrogenstate_inst , & ! Output: nf_soil => soilbiogeochem_nitrogenflux_inst & ! Output: @@ -163,14 +164,22 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ns_veg%livecrootn_xfer_patch(p) = ns_veg%livecrootn_xfer_patch(p) - nf_veg%livecrootn_xfer_to_livecrootn_patch(p)*dt ns_veg%deadcrootn_patch(p) = ns_veg%deadcrootn_patch(p) + nf_veg%deadcrootn_xfer_to_deadcrootn_patch(p)*dt ns_veg%deadcrootn_xfer_patch(p) = ns_veg%deadcrootn_xfer_patch(p) - nf_veg%deadcrootn_xfer_to_deadcrootn_patch(p)*dt + end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops ! lines here for consistency; the transfer terms are zero - ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) + nf_veg%livestemn_xfer_to_livestemn_patch(p)*dt - ns_veg%livestemn_xfer_patch(p) = ns_veg%livestemn_xfer_patch(p) - nf_veg%livestemn_xfer_to_livestemn_patch(p)*dt - ns_veg%grainn_patch(p) = ns_veg%grainn_patch(p) + nf_veg%grainn_xfer_to_grainn_patch(p)*dt - ns_veg%grainn_xfer_patch(p) = ns_veg%grainn_xfer_patch(p) - nf_veg%grainn_xfer_to_grainn_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + ns_veg%grainn_patch(p) = ns_veg%grainn_patch(p) + nf_veg%grainn_xfer_to_grainn_patch(p)*dt + ns_veg%grainn_xfer_patch(p) = ns_veg%grainn_xfer_patch(p) - nf_veg%grainn_xfer_to_grainn_patch(p)*dt + + else + ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) + nf_veg%livestemn_xfer_to_livestemn_patch(p)*dt + ns_veg%livestemn_xfer_patch(p) = ns_veg%livestemn_xfer_patch(p) - nf_veg%livestemn_xfer_to_livestemn_patch(p)*dt + ns_veg%grainn_patch(p) = ns_veg%grainn_patch(p) + nf_veg%grainn_xfer_to_grainn_patch(p)*dt + ns_veg%grainn_xfer_patch(p) = ns_veg%grainn_xfer_patch(p) - nf_veg%grainn_xfer_to_grainn_patch(p)*dt + + end if end if ! phenology: litterfall and retranslocation fluxes @@ -189,18 +198,37 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ns_veg%deadcrootn_patch(p) = ns_veg%deadcrootn_patch(p) + nf_veg%livecrootn_to_deadcrootn_patch(p)*dt ns_veg%livecrootn_patch(p) = ns_veg%livecrootn_patch(p) - nf_veg%livecrootn_to_retransn_patch(p)*dt ns_veg%retransn_patch(p) = ns_veg%retransn_patch(p) + nf_veg%livecrootn_to_retransn_patch(p)*dt + end if if (ivt(p) >= npcropmin) then ! Beth adds retrans from froot - ns_veg%frootn_patch(p) = ns_veg%frootn_patch(p) - nf_veg%frootn_to_retransn_patch(p)*dt - ns_veg%retransn_patch(p) = ns_veg%retransn_patch(p) + nf_veg%frootn_to_retransn_patch(p)*dt - ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) - nf_veg%livestemn_to_litter_patch(p)*dt - ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) - nf_veg%livestemn_to_retransn_patch(p)*dt - ns_veg%retransn_patch(p) = ns_veg%retransn_patch(p) + nf_veg%livestemn_to_retransn_patch(p)*dt - ns_veg%grainn_patch(p) = ns_veg%grainn_patch(p) & - - (nf_veg%grainn_to_food_patch(p) + nf_veg%grainn_to_seed_patch(p))*dt - ns_veg%cropseedn_deficit_patch(p) = ns_veg%cropseedn_deficit_patch(p) & - - nf_veg%crop_seedn_to_leaf_patch(p) * dt & - + nf_veg%grainn_to_seed_patch(p) * dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + ns_veg%frootn_patch(p) = ns_veg%frootn_patch(p) - nf_veg%frootn_to_retransn_patch(p)*dt + ns_veg%retransn_patch(p) = ns_veg%retransn_patch(p) + nf_veg%frootn_to_retransn_patch(p)*dt + ns_veg%grainn_patch(p) = ns_veg%grainn_patch(p) & + - (nf_veg%grainn_to_food_patch(p) + nf_veg%grainn_to_seed_patch(p))*dt + ns_veg%cropseedn_deficit_patch(p) = ns_veg%cropseedn_deficit_patch(p) & + - nf_veg%crop_seedn_to_leaf_patch(p) * dt & + - nf_veg%crop_seedn_to_froot_patch(p) * dt & ! added by (O.Dombrowski) + - nf_veg%crop_seedn_to_deadstem_patch(p) * dt & ! added by (O.Dombrowski) + + nf_veg%grainn_to_seed_patch(p) * dt + if (mulch_pruning(ivt(p)) == 1._r8) then + ! update stem N after pruning + ns_veg%deadstemn_patch(p) = ns_veg%deadstemn_patch(p) - nf_veg%prunen_to_litter_patch(p)*dt + ns_veg%deadstemn_storage_patch(p) = ns_veg%deadstemn_storage_patch(p) - nf_veg%prunen_storage_to_litter_patch(p)*dt + end if + else + ns_veg%frootn_patch(p) = ns_veg%frootn_patch(p) - nf_veg%frootn_to_retransn_patch(p)*dt + ns_veg%retransn_patch(p) = ns_veg%retransn_patch(p) + nf_veg%frootn_to_retransn_patch(p)*dt + ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) - nf_veg%livestemn_to_litter_patch(p)*dt + ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) - nf_veg%livestemn_to_retransn_patch(p)*dt + ns_veg%retransn_patch(p) = ns_veg%retransn_patch(p) + nf_veg%livestemn_to_retransn_patch(p)*dt + ns_veg%grainn_patch(p) = ns_veg%grainn_patch(p) & + - (nf_veg%grainn_to_food_patch(p) + nf_veg%grainn_to_seed_patch(p))*dt + ns_veg%cropseedn_deficit_patch(p) = ns_veg%cropseedn_deficit_patch(p) & + - nf_veg%crop_seedn_to_leaf_patch(p) * dt & + + nf_veg%grainn_to_seed_patch(p) * dt + + end if end if ! uptake from soil mineral N pool @@ -240,17 +268,27 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ns_veg%deadcrootn_patch(p) = ns_veg%deadcrootn_patch(p) + nf_veg%npool_to_deadcrootn_patch(p)*dt ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_deadcrootn_storage_patch(p)*dt ns_veg%deadcrootn_storage_patch(p) = ns_veg%deadcrootn_storage_patch(p) + nf_veg%npool_to_deadcrootn_storage_patch(p)*dt + end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops - ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_livestemn_patch(p)*dt - ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) + nf_veg%npool_to_livestemn_patch(p)*dt - ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_livestemn_storage_patch(p)*dt - ns_veg%livestemn_storage_patch(p) = ns_veg%livestemn_storage_patch(p) + nf_veg%npool_to_livestemn_storage_patch(p)*dt - ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_grainn_patch(p)*dt - ns_veg%grainn_patch(p) = ns_veg%grainn_patch(p) + nf_veg%npool_to_grainn_patch(p)*dt - ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_grainn_storage_patch(p)*dt - ns_veg%grainn_storage_patch(p) = ns_veg%grainn_storage_patch(p) + nf_veg%npool_to_grainn_storage_patch(p)*dt + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_grainn_patch(p)*dt + ns_veg%grainn_patch(p) = ns_veg%grainn_patch(p) + nf_veg%npool_to_grainn_patch(p)*dt + ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_grainn_storage_patch(p)*dt + ns_veg%grainn_storage_patch(p) = ns_veg%grainn_storage_patch(p) + nf_veg%npool_to_grainn_storage_patch(p)*dt + + else + ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_livestemn_patch(p)*dt + ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) + nf_veg%npool_to_livestemn_patch(p)*dt + ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_livestemn_storage_patch(p)*dt + ns_veg%livestemn_storage_patch(p) = ns_veg%livestemn_storage_patch(p) + nf_veg%npool_to_livestemn_storage_patch(p)*dt + ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_grainn_patch(p)*dt + ns_veg%grainn_patch(p) = ns_veg%grainn_patch(p) + nf_veg%npool_to_grainn_patch(p)*dt + ns_veg%npool_patch(p) = ns_veg%npool_patch(p) - nf_veg%npool_to_grainn_storage_patch(p)*dt + ns_veg%grainn_storage_patch(p) = ns_veg%grainn_storage_patch(p) + nf_veg%npool_to_grainn_storage_patch(p)*dt + + end if end if ! move storage pools into transfer pools @@ -268,14 +306,22 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ns_veg%livecrootn_xfer_patch(p) = ns_veg%livecrootn_xfer_patch(p) + nf_veg%livecrootn_storage_to_xfer_patch(p)*dt ns_veg%deadcrootn_storage_patch(p) = ns_veg%deadcrootn_storage_patch(p) - nf_veg%deadcrootn_storage_to_xfer_patch(p)*dt ns_veg%deadcrootn_xfer_patch(p) = ns_veg%deadcrootn_xfer_patch(p) + nf_veg%deadcrootn_storage_to_xfer_patch(p)*dt + end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1.0_r8) then ! (added by O.Dombrowski) + ns_veg%grainn_storage_patch(p) = ns_veg%grainn_storage_patch(p) - nf_veg%grainn_storage_to_xfer_patch(p)*dt + ns_veg%grainn_xfer_patch(p) = ns_veg%grainn_xfer_patch(p) + nf_veg%grainn_storage_to_xfer_patch(p)*dt + ! lines here for consistency; the transfer terms are zero - ns_veg%livestemn_storage_patch(p) = ns_veg%livestemn_storage_patch(p) - nf_veg%livestemn_storage_to_xfer_patch(p)*dt - ns_veg%livestemn_xfer_patch(p) = ns_veg%livestemn_xfer_patch(p) + nf_veg%livestemn_storage_to_xfer_patch(p)*dt - ns_veg%grainn_storage_patch(p) = ns_veg%grainn_storage_patch(p) - nf_veg%grainn_storage_to_xfer_patch(p)*dt - ns_veg%grainn_xfer_patch(p) = ns_veg%grainn_xfer_patch(p) + nf_veg%grainn_storage_to_xfer_patch(p)*dt + else + ns_veg%livestemn_storage_patch(p) = ns_veg%livestemn_storage_patch(p) - nf_veg%livestemn_storage_to_xfer_patch(p)*dt + ns_veg%livestemn_xfer_patch(p) = ns_veg%livestemn_xfer_patch(p) + nf_veg%livestemn_storage_to_xfer_patch(p)*dt + ns_veg%grainn_storage_patch(p) = ns_veg%grainn_storage_patch(p) - nf_veg%grainn_storage_to_xfer_patch(p)*dt + ns_veg%grainn_xfer_patch(p) = ns_veg%grainn_xfer_patch(p) + nf_veg%grainn_storage_to_xfer_patch(p)*dt + + end if end if end do diff --git a/src/clm5/biogeochem/CNPhenologyMod.F90 b/src/clm5/biogeochem/CNPhenologyMod.F90 index 9d66373085..8e37681836 100644 --- a/src/clm5/biogeochem/CNPhenologyMod.F90 +++ b/src/clm5/biogeochem/CNPhenologyMod.F90 @@ -21,6 +21,7 @@ module CNPhenologyMod use CanopyStateType , only : canopystate_type use CNDVType , only : dgvs_type use CNVegstateType , only : cnveg_state_type + use SoilBiogeochemStateType , only : soilbiogeochem_state_type use CNVegCarbonStateType , only : cnveg_carbonstate_type use CNVegCarbonFluxType , only : cnveg_carbonflux_type use CNVegnitrogenstateType , only : cnveg_nitrogenstate_type @@ -44,12 +45,12 @@ module CNPhenologyMod public :: CNPhenologyreadNML ! Read namelist public :: CNPhenologyInit ! Initialization public :: CNPhenology ! Update - ! + ! ! !PRIVATE DATA MEMBERS: type, private :: params_type real(r8) :: crit_dayl ! critical day length for senescence - real(r8) :: ndays_on ! number of days to complete leaf onset - real(r8) :: ndays_off ! number of days to complete leaf offset + real(r8) :: ndays_on ! number of days to complete leaf onset + real(r8) :: ndays_off ! number of days to complete leaf offset real(r8) :: fstor2tran ! fraction of storage to move to transfer for each onset real(r8) :: crit_onset_fdd ! critical number of freezing days to set gdd counter real(r8) :: crit_onset_swi ! critical number of days > soilpsi_on for onset @@ -57,7 +58,7 @@ module CNPhenologyMod real(r8) :: crit_offset_fdd ! critical number of freezing days to initiate offset real(r8) :: crit_offset_swi ! critical number of water stress days to initiate offset real(r8) :: soilpsi_off ! critical soil water potential for leaf offset - real(r8) :: lwtop ! live wood turnover proportion (annual fraction) + real(r8) :: lwtop ! live wood turnover proportion (annual fraction) end type params_type type(params_type) :: params_inst @@ -89,13 +90,13 @@ module CNPhenologyMod integer, allocatable :: minplantjday(:,:) ! minimum planting julian day integer, allocatable :: maxplantjday(:,:) ! maximum planting julian day + integer, allocatable :: maxharvjday(:,:) ! maximum harvest julian day (added by O.Dombrowski) integer :: jdayyrstart(inSH) ! julian day of start of year real(r8), private :: initial_seed_at_planting = 3._r8 ! Initial seed at planting character(len=*), parameter, private :: sourcefile = & __FILE__ - !----------------------------------------------------------------------- contains @@ -242,10 +243,10 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & filter_soilp, num_pcropp, filter_pcropp, & doalb, waterstate_inst, temperature_inst, atm2lnd_inst, crop_inst, & canopystate_inst, soilstate_inst, dgvs_inst, & - cnveg_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & + cnveg_state_inst, soilbiogeochem_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & - leaf_prof_patch, froot_prof_patch, phase) + leaf_prof_patch, froot_prof_patch,stem_prof_patch, phase) ! !USES: use CNSharedParamsMod, only: use_fun ! @@ -270,6 +271,7 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & type(soilstate_type) , intent(in) :: soilstate_inst type(dgvs_type) , intent(inout) :: dgvs_inst type(cnveg_state_type) , intent(inout) :: cnveg_state_inst + type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst type(cnveg_nitrogenstate_type) , intent(inout) :: cnveg_nitrogenstate_inst @@ -278,12 +280,13 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & type(cnveg_carbonstate_type) , intent(inout) :: c14_cnveg_carbonstate_inst real(r8) , intent(in) :: leaf_prof_patch(bounds%begp:,1:) real(r8) , intent(in) :: froot_prof_patch(bounds%begp:,1:) + real(r8) , intent(in) :: stem_prof_patch(bounds%begp:,1:) integer , intent(in) :: phase !----------------------------------------------------------------------- SHR_ASSERT_ALL((ubound(leaf_prof_patch) == (/bounds%endp,nlevdecomp_full/)), errMsg(sourcefile, __LINE__)) SHR_ASSERT_ALL((ubound(froot_prof_patch) == (/bounds%endp,nlevdecomp_full/)), errMsg(sourcefile, __LINE__)) - + SHR_ASSERT_ALL((ubound(stem_prof_patch) == (/bounds%endp,nlevdecomp_full/)), errMsg(sourcefile, __LINE__)) ! each of the following phenology type routines includes a filter ! to operate only on the relevant patches @@ -308,6 +311,11 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & waterstate_inst, temperature_inst, crop_inst, canopystate_inst, cnveg_state_inst, & cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst) + ! FruitTreePhenology routine has a special filter for deciduous tree crop pfts (added by O.Dombrowski) + call FruitTreePhenology(num_pcropp, filter_pcropp, & + waterstate_inst, temperature_inst, crop_inst, canopystate_inst, cnveg_state_inst, dgvs_inst, & + cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & + c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst) end if else if ( phase == 2 ) then ! the same onset and offset routines are called regardless of @@ -318,7 +326,7 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) call CNOffsetLitterfall(num_soilp, filter_soilp, & - cnveg_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) + crop_inst,cnveg_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) call CNBackgroundLitterfall(num_soilp, filter_soilp, & cnveg_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) @@ -331,10 +339,15 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & ! gather all patch-level litterfall fluxes to the column for litter C and N inputs - call CNLitterToColumn(bounds, num_soilc, filter_soilc, & - cnveg_state_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & + call CNLitterToColumn(bounds, num_soilc, filter_soilc, & + cnveg_state_inst,cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & leaf_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full), & - froot_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full)) + froot_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full), stem_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full)) + + call CNRotationToColumn (num_soilc, filter_soilc, & + cnveg_state_inst, soilbiogeochem_state_inst, crop_inst, cnveg_carbonflux_inst, & + cnveg_nitrogenflux_inst) + else call endrun( 'bad phase' ) end if @@ -525,7 +538,7 @@ subroutine CNEvergreenPhenology (num_soilp, filter_soilp , & integer :: p ! indices integer :: fp ! lake filter patch index - real(r8):: tranr + real(r8):: tranr real(r8):: t1 ! temporary variable !----------------------------------------------------------------------- @@ -538,59 +551,59 @@ subroutine CNEvergreenPhenology (num_soilp, filter_soilp , & woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) leafc_storage => cnveg_carbonstate_inst%leafc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) leaf C storage - frootc_storage => cnveg_carbonstate_inst%frootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) fine root C storage + frootc_storage => cnveg_carbonstate_inst%frootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) fine root C storage livestemc_storage => cnveg_carbonstate_inst%livestemc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) live stem C storage deadstemc_storage => cnveg_carbonstate_inst%deadstemc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) dead stem C storage - livecrootc_storage => cnveg_carbonstate_inst%livecrootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) live coarse root C storage - deadcrootc_storage => cnveg_carbonstate_inst%deadcrootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) dead coarse root C storage - gresp_storage => cnveg_carbonstate_inst%gresp_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) growth respiration storage - leafc_xfer => cnveg_carbonstate_inst%leafc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) leaf C transfer - frootc_xfer => cnveg_carbonstate_inst%frootc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) fine root C transfer - livestemc_xfer => cnveg_carbonstate_inst%livestemc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) live stem C transfer - deadstemc_xfer => cnveg_carbonstate_inst%deadstemc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) dead stem C transfer - livecrootc_xfer => cnveg_carbonstate_inst%livecrootc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) live coarse root C transfer - deadcrootc_xfer => cnveg_carbonstate_inst%deadcrootc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) dead coarse root C transfer - - leafn_storage => cnveg_nitrogenstate_inst%leafn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) leaf N storage - frootn_storage => cnveg_nitrogenstate_inst%frootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) fine root N storage - livestemn_storage => cnveg_nitrogenstate_inst%livestemn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) live stem N storage - deadstemn_storage => cnveg_nitrogenstate_inst%deadstemn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N storage - livecrootn_storage => cnveg_nitrogenstate_inst%livecrootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) live coarse root N storage - deadcrootn_storage => cnveg_nitrogenstate_inst%deadcrootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) dead coarse root N storage - leafn_xfer => cnveg_nitrogenstate_inst%leafn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) leaf N transfer - frootn_xfer => cnveg_nitrogenstate_inst%frootn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) fine root N transfer - livestemn_xfer => cnveg_nitrogenstate_inst%livestemn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) live stem N transfer - deadstemn_xfer => cnveg_nitrogenstate_inst%deadstemn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) dead stem N transfer - livecrootn_xfer => cnveg_nitrogenstate_inst%livecrootn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) live coarse root N transfer - deadcrootn_xfer => cnveg_nitrogenstate_inst%deadcrootn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) dead coarse root N transfer - - leafc_storage_to_xfer => cnveg_carbonflux_inst%leafc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - frootc_storage_to_xfer => cnveg_carbonflux_inst%frootc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - livestemc_storage_to_xfer => cnveg_carbonflux_inst%livestemc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - deadstemc_storage_to_xfer => cnveg_carbonflux_inst%deadstemc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - livecrootc_storage_to_xfer => cnveg_carbonflux_inst%livecrootc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - deadcrootc_storage_to_xfer => cnveg_carbonflux_inst%deadcrootc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - gresp_storage_to_xfer => cnveg_carbonflux_inst%gresp_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - leafc_xfer_to_leafc => cnveg_carbonflux_inst%leafc_xfer_to_leafc_patch , & ! InOut: [real(r8) (:)] - frootc_xfer_to_frootc => cnveg_carbonflux_inst%frootc_xfer_to_frootc_patch , & ! InOut: [real(r8) (:)] - livestemc_xfer_to_livestemc => cnveg_carbonflux_inst%livestemc_xfer_to_livestemc_patch , & ! InOut: [real(r8) (:)] - deadstemc_xfer_to_deadstemc => cnveg_carbonflux_inst%deadstemc_xfer_to_deadstemc_patch , & ! InOut: [real(r8) (:)] - livecrootc_xfer_to_livecrootc => cnveg_carbonflux_inst%livecrootc_xfer_to_livecrootc_patch , & ! InOut: [real(r8) (:)] - deadcrootc_xfer_to_deadcrootc => cnveg_carbonflux_inst%deadcrootc_xfer_to_deadcrootc_patch , & ! InOut: [real(r8) (:)] - - leafn_storage_to_xfer => cnveg_nitrogenflux_inst%leafn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - frootn_storage_to_xfer => cnveg_nitrogenflux_inst%frootn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - livestemn_storage_to_xfer => cnveg_nitrogenflux_inst%livestemn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - deadstemn_storage_to_xfer => cnveg_nitrogenflux_inst%deadstemn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - livecrootn_storage_to_xfer => cnveg_nitrogenflux_inst%livecrootn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - deadcrootn_storage_to_xfer => cnveg_nitrogenflux_inst%deadcrootn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] - leafn_xfer_to_leafn => cnveg_nitrogenflux_inst%leafn_xfer_to_leafn_patch , & ! InOut: [real(r8) (:)] - frootn_xfer_to_frootn => cnveg_nitrogenflux_inst%frootn_xfer_to_frootn_patch , & ! InOut: [real(r8) (:)] - livestemn_xfer_to_livestemn => cnveg_nitrogenflux_inst%livestemn_xfer_to_livestemn_patch , & ! InOut: [real(r8) (:)] - deadstemn_xfer_to_deadstemn => cnveg_nitrogenflux_inst%deadstemn_xfer_to_deadstemn_patch , & ! InOut: [real(r8) (:)] - livecrootn_xfer_to_livecrootn => cnveg_nitrogenflux_inst%livecrootn_xfer_to_livecrootn_patch , & ! InOut: [real(r8) (:)] - deadcrootn_xfer_to_deadcrootn => cnveg_nitrogenflux_inst%deadcrootn_xfer_to_deadcrootn_patch , & ! InOut: [real(r8) (:)] - + livecrootc_storage => cnveg_carbonstate_inst%livecrootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) live coarse root C storage + deadcrootc_storage => cnveg_carbonstate_inst%deadcrootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) dead coarse root C storage + gresp_storage => cnveg_carbonstate_inst%gresp_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) growth respiration storage + leafc_xfer => cnveg_carbonstate_inst%leafc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) leaf C transfer + frootc_xfer => cnveg_carbonstate_inst%frootc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) fine root C transfer + livestemc_xfer => cnveg_carbonstate_inst%livestemc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) live stem C transfer + deadstemc_xfer => cnveg_carbonstate_inst%deadstemc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) dead stem C transfer + livecrootc_xfer => cnveg_carbonstate_inst%livecrootc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) live coarse root C transfer + deadcrootc_xfer => cnveg_carbonstate_inst%deadcrootc_xfer_patch , & ! InOut: [real(r8) (:)] (gC/m2) dead coarse root C transfer + + leafn_storage => cnveg_nitrogenstate_inst%leafn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) leaf N storage + frootn_storage => cnveg_nitrogenstate_inst%frootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) fine root N storage + livestemn_storage => cnveg_nitrogenstate_inst%livestemn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) live stem N storage + deadstemn_storage => cnveg_nitrogenstate_inst%deadstemn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N storage + livecrootn_storage => cnveg_nitrogenstate_inst%livecrootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) live coarse root N storage + deadcrootn_storage => cnveg_nitrogenstate_inst%deadcrootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) dead coarse root N storage + leafn_xfer => cnveg_nitrogenstate_inst%leafn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) leaf N transfer + frootn_xfer => cnveg_nitrogenstate_inst%frootn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) fine root N transfer + livestemn_xfer => cnveg_nitrogenstate_inst%livestemn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) live stem N transfer + deadstemn_xfer => cnveg_nitrogenstate_inst%deadstemn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) dead stem N transfer + livecrootn_xfer => cnveg_nitrogenstate_inst%livecrootn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) live coarse root N transfer + deadcrootn_xfer => cnveg_nitrogenstate_inst%deadcrootn_xfer_patch , & ! InOut: [real(r8) (:)] (gN/m2) dead coarse root N transfer + + leafc_storage_to_xfer => cnveg_carbonflux_inst%leafc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + frootc_storage_to_xfer => cnveg_carbonflux_inst%frootc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + livestemc_storage_to_xfer => cnveg_carbonflux_inst%livestemc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + deadstemc_storage_to_xfer => cnveg_carbonflux_inst%deadstemc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + livecrootc_storage_to_xfer => cnveg_carbonflux_inst%livecrootc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + deadcrootc_storage_to_xfer => cnveg_carbonflux_inst%deadcrootc_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + gresp_storage_to_xfer => cnveg_carbonflux_inst%gresp_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + leafc_xfer_to_leafc => cnveg_carbonflux_inst%leafc_xfer_to_leafc_patch , & ! InOut: [real(r8) (:)] + frootc_xfer_to_frootc => cnveg_carbonflux_inst%frootc_xfer_to_frootc_patch , & ! InOut: [real(r8) (:)] + livestemc_xfer_to_livestemc => cnveg_carbonflux_inst%livestemc_xfer_to_livestemc_patch , & ! InOut: [real(r8) (:)] + deadstemc_xfer_to_deadstemc => cnveg_carbonflux_inst%deadstemc_xfer_to_deadstemc_patch , & ! InOut: [real(r8) (:)] + livecrootc_xfer_to_livecrootc => cnveg_carbonflux_inst%livecrootc_xfer_to_livecrootc_patch , & ! InOut: [real(r8) (:)] + deadcrootc_xfer_to_deadcrootc => cnveg_carbonflux_inst%deadcrootc_xfer_to_deadcrootc_patch , & ! InOut: [real(r8) (:)] + + leafn_storage_to_xfer => cnveg_nitrogenflux_inst%leafn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + frootn_storage_to_xfer => cnveg_nitrogenflux_inst%frootn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + livestemn_storage_to_xfer => cnveg_nitrogenflux_inst%livestemn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + deadstemn_storage_to_xfer => cnveg_nitrogenflux_inst%deadstemn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + livecrootn_storage_to_xfer => cnveg_nitrogenflux_inst%livecrootn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + deadcrootn_storage_to_xfer => cnveg_nitrogenflux_inst%deadcrootn_storage_to_xfer_patch , & ! InOut: [real(r8) (:)] + leafn_xfer_to_leafn => cnveg_nitrogenflux_inst%leafn_xfer_to_leafn_patch , & ! InOut: [real(r8) (:)] + frootn_xfer_to_frootn => cnveg_nitrogenflux_inst%frootn_xfer_to_frootn_patch , & ! InOut: [real(r8) (:)] + livestemn_xfer_to_livestemn => cnveg_nitrogenflux_inst%livestemn_xfer_to_livestemn_patch , & ! InOut: [real(r8) (:)] + deadstemn_xfer_to_deadstemn => cnveg_nitrogenflux_inst%deadstemn_xfer_to_deadstemn_patch , & ! InOut: [real(r8) (:)] + livecrootn_xfer_to_livecrootn => cnveg_nitrogenflux_inst%livecrootn_xfer_to_livecrootn_patch , & ! InOut: [real(r8) (:)] + deadcrootn_xfer_to_deadcrootn => cnveg_nitrogenflux_inst%deadcrootn_xfer_to_deadcrootn_patch , & ! InOut: [real(r8) (:)] + bglfr => cnveg_state_inst%bglfr_patch , & ! Output: [real(r8) (:) ] background litterfall rate (1/s) bgtr => cnveg_state_inst%bgtr_patch , & ! Output: [real(r8) (:) ] background transfer growth rate (1/s) lgsf => cnveg_state_inst%lgsf_patch & ! Output: [real(r8) (:) ] long growing season factor [0-1] @@ -706,7 +719,7 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) season_decid => pftcon%season_decid , & ! Input: binary flag for seasonal-deciduous leaf habit (0 or 1) - + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types (0 or 1) t_soisno => temperature_inst%t_soisno_col , & ! Input: [real(r8) (:,:) ] soil temperature (Kelvin) (-nlevsno+1:nlevgrnd) pftmayexist => dgvs_inst%pftmayexist_patch , & ! Output: [logical (:) ] exclude seasonal decid patches from tropics @@ -787,7 +800,7 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & c = patch%column(p) g = patch%gridcell(p) - if (season_decid(ivt(p)) == 1._r8) then + if (season_decid(ivt(p)) == 1._r8 .and. perennial(ivt(p)) == 0._r8) then ! set background litterfall rate, background transfer rate, and ! long growing season factor to 0 for seasonal deciduous types @@ -797,7 +810,6 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & ! onset gdd sum from Biome-BGC, v4.1.2 crit_onset_gdd = exp(4.8_r8 + 0.13_r8*(annavg_t2m(p) - SHR_CONST_TKFRZ)) - ! set flag for solstice period (winter->summer = 1, summer->winter = 0) if (dayl(g) >= prev_dayl(g)) then ws_flag = 1._r8 @@ -1416,6 +1428,700 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & end subroutine CNStressDecidPhenology + !----------------------------------------------------------------------- + subroutine FruitTreePhenology(num_pcropp, filter_pcropp , & + waterstate_inst, temperature_inst, crop_inst, canopystate_inst, cnveg_state_inst, dgvs_inst, & + cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst,& + c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst) + + ! !DESCRIPTION: + ! Code from AgroIBIS adapted for deciduous fruit trees by O. Dombrowski (2022) to determine crop phenology and code from CN to + ! handle CN fluxes during the phenological onset & offset periods. + ! New phenological stages and triggers, as well as management practices typical for fruit orchards are described + + ! !USES: + use shr_const_mod , only : SHR_CONST_TKFRZ + use clm_time_manager , only : get_curr_date, get_curr_calday, get_days_per_year, get_rad_step_size + use pftconMod , only : napple ! the citrus PFT is used for now, separate PFTs for deciduous fruit tree species may be added in the future + use pftconMod , only : nirrig_apple + 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 , & @@ -1428,10 +2134,10 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & ! !USES: use clm_time_manager , only : get_curr_date, get_curr_calday, get_days_per_year, get_rad_step_size - use pftconMod , only : ntmp_corn, nswheat, nwwheat, ntmp_soybean - use pftconMod , only : nirrig_tmp_corn, nirrig_swheat, nirrig_wwheat, nirrig_tmp_soybean - use pftconMod , only : ntrp_corn, nsugarcane, ntrp_soybean, ncotton, nrice - use pftconMod , only : nirrig_trp_corn, nirrig_sugarcane, nirrig_trp_soybean + use pftconMod , only : ntmp_corn, nswheat, nwwheat, ntmp_soybean, nbarley, nwbarley, nrye, nwrye, ncassava, napple, ncocoa, ncoffee, ncotton, ndatepalm, nfoddergrass, ngrapes, ngroundnuts, nmillet, noilpalm, npotatoes, npulses, nrapeseed, nrice, nsorghum, nsugarbeet, nsunflower, nmiscanthus, nswitchgrass, nc3crop, ncovercrop_1, ncovercrop_2 + use pftconMod , only : nirrig_tmp_corn, nirrig_swheat, nirrig_wwheat, nirrig_tmp_soybean, nirrig_barley, nirrig_wbarley, nirrig_rye, nirrig_wrye, nirrig_cassava, nirrig_apple, nirrig_cocoa, nirrig_coffee, nirrig_cotton, nirrig_datepalm, nirrig_foddergrass, nirrig_grapes, nirrig_groundnuts, nirrig_millet, nirrig_oilpalm, nirrig_potatoes, nirrig_pulses, nirrig_rapeseed, nirrig_rice, nirrig_sorghum, nirrig_sugarbeet, nirrig_sunflower, nirrig_miscanthus, nirrig_switchgrass, nc3irrig + use pftconMod , only : ntrp_corn, nsugarcane, ncotton, nrice + use pftconMod , only : nirrig_trp_corn, nirrig_sugarcane use pftconMod , only : nirrig_cotton, nirrig_rice use clm_varcon , only : spval, secspday use clm_varctl , only : use_fertilizer @@ -1482,8 +2188,9 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & gddmin => pftcon%gddmin , & ! Input: hybgdd => pftcon%hybgdd , & ! Input: lfemerg => pftcon%lfemerg , & ! Input: - grnfill => pftcon%grnfill , & ! 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) + covercrop => pftcon%covercrop , & ! Input: covercrop flag 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,19 +2221,32 @@ 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 + frootc_xfer => cnveg_carbonstate_inst%frootc_xfer_patch , & ! Input: [real(r8) (:) ] (gC/m2) fine root C transfer + frootn_xfer => cnveg_nitrogenstate_inst%frootn_xfer_patch , & ! Input: [real(r8) (:) ] (gN/m2) fine root N transfer + frootcn => pftcon%frootcn , & ! Input: fine root C:N (gC/gN) fert_counter => cnveg_nitrogenflux_inst%fert_counter_patch , & ! Output: [real(r8) (:) ] >0 fertilize; <=0 not (seconds) leafn_xfer => cnveg_nitrogenstate_inst%leafn_xfer_patch , & ! Output: [real(r8) (:) ] (gN/m2) leaf N transfer - 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_leaf=> cnveg_nitrogenflux_inst%crop_seedn_to_leaf_patch, & ! Output: [real(r8) (:) ] (gN/m2/s) seed source to leaf cphase => crop_inst%cphase_patch , & ! Output: [real(r8) (:)] phenology phase - fert => cnveg_nitrogenflux_inst%fert_patch & ! Output: [real(r8) (:) ] (gN/m2/s) fertilizer applied each timestep + fert => cnveg_nitrogenflux_inst%fert_patch , & ! Output: [real(r8) (:) ] (gN/m2/s) fertilizer applied each timestep + lt50 => crop_inst%lt50_patch , & ! Output: [real(r8) (:)] the lethal temperature at which 50% of the individuals are damaged + wdd => crop_inst%wdd_patch , & ! Output: [real(r8) (:)] winter wheat weighted cumulated degree days + rateh => crop_inst%rateh_patch , & ! Output: [real(r8) (:)] increaseof tolerance cuased byhardening + rated => crop_inst%rated_patch , & ! Output: [real(r8) (:)] loss of tolerance cause by dehardening + rates => crop_inst%rates_patch , & ! Output: [real(r8) (:)] loss of tolerance caused by low tempeature + rater => crop_inst%rater_patch , & ! Output: [real(r8) (:)] loss of tolerance caused by respiration under snow + fsurv => crop_inst%fsurv_patch , & ! Output: [real(r8) (:)] winter wheat survival rate + accfsurv => crop_inst%accfsurv_patch , & ! Output: [real(r8) (:)] accumulated winter wheat survival rate + countfsurv => crop_inst%countfsurv_patch & ! Output: [real(r8) (:)] numbers of accumulated winter wheat survival rate ) + !variables for coldtolerance subroutine modified after Lu (2017) (tboas) + ! get time info dayspyr = get_days_per_year() jday = get_curr_calday() @@ -1545,75 +2265,91 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & g = patch%gridcell(p) h = inhemi(p) - ! background litterfall and transfer rates; long growing season factor + 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 - 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 + ! --------------------------------- - ! --------------------------------- - ! 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 - ! 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 - ! initialize other variables that are calculated for crops - ! on an annual basis in cropresidue subroutine + if ( jday == jdayyrstart(h) .and. mcsec == 0 )then - 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 - ! make sure variables aren't changed at beginning of the year - ! for a crop that is currently planted, such as - ! WINTER TEMPERATE CEREAL = winter (wheat + barley + rye) - ! represented here by the winter wheat pft - - if (.not. croplive(p)) then - cropplant(p) = .false. - idop(p) = NOT_Planted + if (.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) + ! (tboas) here, this only prevents the crop to be killed on the + ! first day of a new year and still results in a cereal-fallow + ! rotation + + else if (croplive(p) .and. (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat .or. & + ivt(p) == ncovercrop_1 .or. ivt(p) == ncovercrop_2 .or. & + ivt(p) == nwbarley .or. ivt(p) == nirrig_wbarley .or. & + ivt(p) == nrapeseed .or. ivt(p) == nirrig_rapeseed)) then + cropplant(p) = .true. + ! else ! not possible to have croplive and ivt==cornORsoy? (slevis) end if end if - if ( (.not. croplive(p)) .and. (.not. cropplant(p)) ) then + !(tboas) try to avaoid cereral/fallow rotation + if (.not. croplive(p) .and. jday >= 170._r8 .and. & + (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat)) then + cropplant(p) = .false. + idop(p) = NOT_Planted + 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 + ! 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 + ! 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 + ! 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 + ! 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 + ! winter temperate cereal : use gdd0 as a limit to plant winter cereal - if (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat) then + if (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat .or. & + ivt(p) == ncovercrop_1 .or. ivt(p) == ncovercrop_2 .or. & + ivt(p) == nwbarley .or. ivt(p) == nirrig_wbarley .or. & + ivt(p) == nrapeseed .or. ivt(p) == nirrig_rapeseed) then - ! add check to only plant winter cereal after other crops (soybean, maize) - ! have been harvested + ! 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 *** + ! *** 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) + ! 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 @@ -1625,10 +2361,20 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & jday >= minplantjday(ivt(p),h) .and. & (gdd020(p) /= spval .and. & gdd020(p) >= gddmin(ivt(p)))) then - + write (iulog,*) 'planting winter crop' cumvd(p) = 0._r8 hdidx(p) = 0._r8 vf(p) = 0._r8 + !coldtolerance parameters modified after Lu (2017) (tboas) + lt50(p) = -5._r8 + wdd(p) = 0._r8 + rateh(p) = 0._r8 + rated(p) = 0._r8 + rater(p) = 0._r8 + rates(p) = 0._r8 + fsurv(p) = 1._r8 + accfsurv(p) = 1._r8 + countfsurv(p) = 1._r8 croplive(p) = .true. cropplant(p) = .true. idop(p) = jday @@ -1636,38 +2382,51 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & 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 + frootc_xfer(p) = 0.1_r8 + frootn_xfer(p) = frootc_xfer(p) / frootcn(ivt(p)) ! with onset + crop_seedc_to_leaf(p) = leafc_xfer(p)/dt + frootc_xfer(p)/dt + crop_seedn_to_leaf(p) = leafn_xfer(p)/dt + frootn_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 - + write (iulog,*) 'planting winter crop' cumvd(p) = 0._r8 hdidx(p) = 0._r8 vf(p) = 0._r8 + ! coldtolerance mod. after Lu (2017) (tboas) + rateh(p) = 0._r8 + rated(p) = 0._r8 + rater(p) = 0._r8 + rates(p) = 0._r8 + fsurv(p) = 1._r8 + accfsurv(p) = 1._r8 + countfsurv(p) = 1._r8 + lt50(p) = -5._r8 + wdd(p) = 0._r8 croplive(p) = .true. cropplant(p) = .true. idop(p) = jday @@ -1675,56 +2434,58 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & 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 + frootc_xfer(p) = 0.1_r8 + frootn_xfer(p) = frootc_xfer(p) / frootcn(ivt(p)) ! with onset + crop_seedc_to_leaf(p) = leafc_xfer(p)/dt + frootc_xfer(p)/dt + crop_seedn_to_leaf(p) = leafn_xfer(p)/dt + frootn_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_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 @@ -1732,46 +2493,48 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & 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) == nsugarbeet .or. ivt(p) == nirrig_sugarbeet .or. & + ivt(p) == npotatoes .or. ivt(p) == nirrig_potatoes .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 + 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) then !.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. & @@ -1780,6 +2543,8 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & 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) == nsugarbeet .or. ivt(p) == nirrig_sugarbeet .or. & + ivt(p) == npotatoes .or. ivt(p) == nirrig_potatoes .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))) @@ -1790,180 +2555,225 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & 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 + ! because leafc_xfer is set above rather than incremneted through the normal process, must also set its isotope + ! pools here. use totvegc_patch as the closest analogue if nonzero, and use initial value otherwise + if (use_c13) then + if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & + c13_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) + else + c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c13ratio + endif + endif + if (use_c14) then + if ( cnveg_carbonstate_inst%totvegc_patch(p) .gt. 0._r8) then + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * & + c14_cnveg_carbonstate_inst%totvegc_patch(p) / cnveg_carbonstate_inst%totvegc_patch(p) + else + c14_cnveg_carbonstate_inst%leafc_xfer_patch(p) = leafc_xfer(p) * c14ratio + endif + endif + + else + gddmaturity(p) = 0._r8 + end if + end if ! crop patch distinction + + ! crop phenology (gdd thresholds) controlled by gdd needed for + ! maturity (physiological) which is based on the average gdd + ! accumulation and hybrids in United States from April 1 - Sept 30 + + ! calculate threshold from phase 1 to phase 2: + ! threshold for attaining leaf emergence (based on fraction of + ! gdd(i) -- climatological average) + ! Hayhoe and Dwyer, 1990, Can. J. Soil Sci 70:493-497 + ! Carlson and Gage, 1989, Agric. For. Met., 45: 313-324 + ! J.T. Ritchie, 1991: Modeling Plant and Soil systems + + huileaf(p) = lfemerg(ivt(p)) * gddmaturity(p) ! 3-7% in cereal + + ! calculate threshhold from phase 2 to phase 3: + ! from leaf emergence to beginning of grain-fill period + ! this hypothetically occurs at the end of tassling, not the beginning + ! tassel initiation typically begins at 0.5-0.55 * gddmaturity + + ! calculate linear relationship between huigrain fraction and relative + ! maturity rating for maize + + if (ivt(p) == ntmp_corn .or. ivt(p) == nirrig_tmp_corn .or. & + ivt(p) == ntrp_corn .or. ivt(p) == nirrig_trp_corn .or. & + ivt(p) == nsugarcane .or. ivt(p) == nirrig_sugarcane) then + ! the following estimation of crmcorn from gddmaturity is based on a linear + ! regression using data from Pioneer-brand corn hybrids (Kucharik, 2003, + ! Earth Interactions 7:1-33: fig. 2) + crmcorn = max(73._r8, min(135._r8, (gddmaturity(p)+ 53.683_r8)/13.882_r8)) + + ! the following adjustment of grnfill based on crmcorn is based on a tuning + ! of Agro-IBIS to give reasonable results for max LAI and the seasonal + ! progression of LAI growth (pers. comm. C. Kucharik June 10, 2010) + huigrain(p) = -0.002_r8 * (crmcorn - 73._r8) + grnfill(ivt(p)) + + huigrain(p) = min(max(huigrain(p), grnfill(ivt(p))-0.1_r8), grnfill(ivt(p))) + huigrain(p) = huigrain(p) * gddmaturity(p) ! Cabelguenne et + else + huigrain(p) = grnfill(ivt(p)) * gddmaturity(p) ! al. 1999 + end if - end if ! crop not live nor planted - - ! ---------------------------------- - ! from AgroIBIS subroutine phenocrop - ! ---------------------------------- - - ! all of the phenology changes are based on the total number of gdd needed - ! to change to the next phase - based on fractions of the total gdd typical - ! for that region based on the April 1 - Sept 30 window of development - - ! crop phenology (gdd thresholds) controlled by gdd needed for - ! maturity (physiological) which is based on the average gdd - ! accumulation and hybrids in United States from April 1 - Sept 30 - - ! Phase 1: Planting to leaf emergence (now in CNAllocation) - ! Phase 2: Leaf emergence to beginning of grain fill (general LAI accumulation) - ! Phase 3: Grain fill to physiological maturity and harvest (LAI decline) - ! Harvest: if gdd past grain fill initiation exceeds limit - ! or number of days past planting reaches a maximum, the crop has - ! reached physiological maturity and plant is harvested; - ! crop could be live or dead at this stage - these limits - ! could lead to reaching physiological maturity or determining - ! a harvest date for a crop killed by an early frost (see next comments) - ! --- --- --- - ! keeping comments without the code (slevis): - ! if minimum temperature, t_ref2m_min <= freeze kill threshold, tkill - ! for 3 consecutive days and lai is above a minimum, - ! plant will be damaged/killed. This function is more for spring freeze events - ! or for early fall freeze events - - ! spring temperate cereal is affected by this, winter cereal kill function - ! is determined in crops.f - is a more elaborate function of - ! cold hardening of the plant - - ! currently simulates too many grid cells killed by freezing temperatures - - ! removed on March 12 2002 - C. Kucharik - ! until it can be a bit more refined, or used at a smaller scale. - ! we really have no way of validating this routine - ! too difficult to implement on 0.5 degree scale grid cells - ! --- --- --- - - onset_flag(p) = 0._r8 ! CN terminology to trigger certain - offset_flag(p) = 0._r8 ! carbon and nitrogen transfers + 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) + + ! old vernalization routine inactive + ! 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 .or. & + ! ivt(p) == ncovercrop_1 .or. ivt(p) == ncovercrop_2 .or. & + ! ivt(p) == nwbarley .or. ivt(p) == nirrig_wbarley .or. & + ! ivt(p) == nrapeseed .or. ivt(p) == nirrig_rapeseed)) then + ! write (iulog,*) 'call vernalization old' + ! call vernalization(p, & + ! canopystate_inst, temperature_inst, waterstate_inst, cnveg_state_inst, & + ! crop_inst) + + !new vernalization routine + if (vf(p) /= 1._r8 .and. & + (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat .or. & + ivt(p) == ncovercrop_1 .or. ivt(p) == ncovercrop_2 .or. & + ivt(p) == nwbarley .or. ivt(p) == nirrig_wbarley .or. & + ivt(p) == nrapeseed .or. ivt(p) == nirrig_rapeseed)) then + call vernalization_2(p, & + temperature_inst, waterstate_inst, cnveg_state_inst, & + crop_inst, cnveg_carbonflux_inst) end if - ! days past planting may determine harvest + ! call cold tolerance in cphase 2 + ! if (ivt(p)== nwwheat .or. ivt(p) == nirrig_wwheat .or. & + ! ivt(p) == ncovercrop_1 .or. ivt(p) == ncovercrop_2 .or. & + ! ivt(p) == nwbarley .or. ivt(p) == nirrig_wbarley .or. & + ! ivt(p) == nrapeseed .or. ivt(p) == nirrig_rapeseed) then + ! call coldtolerance(p,canopystate_inst,temperature_inst, & + ! waterstate_inst,cnveg_state_inst, crop_inst, & + ! cnveg_nitrogenflux_inst, cnveg_carbonflux_inst, & + ! cnveg_carbonstate_inst, cnveg_nitrogenstate_inst) + ! end if - if (jday >= idop(p)) then - idpp = jday - idop(p) - else - idpp = int(dayspyr) + jday - idop(p) - end if - ! onset_counter initialized to zero when .not. croplive - ! offset_counter relevant only at time step of harvest + if (jday >= idop(p)) then + idpp = jday - idop(p) + else + idpp = int(dayspyr) + jday - idop(p) + end if + + ! onset_counter initialized to zero when .not. croplive + ! offset_counter relevant only at time step of harvest - onset_counter(p) = onset_counter(p) - dt + onset_counter(p) = onset_counter(p) - dt - ! enter phase 2 onset for one time step: - ! transfer seed carbon to leaf emergence + ! 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 + end if if (leafout(p) >= huileaf(p) .and. hui(p) < huigrain(p) .and. idpp < mxmat(ivt(p))) then - cphase(p) = 2._r8 + cphase(p) = 2._r8 + + if (ivt(p)==nwwheat .or. ivt(p) == nirrig_wwheat .or. & + ivt(p) == ncovercrop_1 .or. ivt(p) == ncovercrop_2 .or. & + ivt(p) == nwbarley .or. ivt(p) == nirrig_wbarley .or. & + ivt(p) == nrapeseed .or. ivt(p) == nirrig_rapeseed) then + call coldtolerance(p,canopystate_inst,temperature_inst, & + waterstate_inst,cnveg_state_inst, crop_inst, & + cnveg_nitrogenflux_inst, cnveg_carbonflux_inst, & + cnveg_carbonstate_inst, cnveg_nitrogenstate_inst) + end if + + 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 + 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 + 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 + ! 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 (harvdate(p) >= NOT_Harvested)then + harvdate(p) = jday + if (covercrop(ivt(p)) == 1) then + call covercropping(p, crop_inst, cnveg_state_inst) + else + croplive(p) = .false. ! no re-entry in greater if-block + cphase(p) = 4._r8 + end if + endif if (tlai(p) > 0._r8) then ! plant had emerged before harvest + write (iulog,*) 'plant emerged' offset_flag(p) = 1._r8 offset_counter(p) = dt else ! plant never emerged from the ground @@ -1972,10 +2782,13 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & ! 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. + !write (iulog,*) 'plant not emerged' 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)) + frootc_xfer(p) = 0._r8 + frootn_xfer(p) = 0._r8 !frootc_xfer(p) / frootcn((ivt)p) ! with onset if (use_c13) then c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 endif @@ -1984,46 +2797,46 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & 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 + 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 +2864,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 +2874,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 @@ -2096,6 +2914,97 @@ subroutine CropPhenologyInit(bounds) end subroutine CropPhenologyInit + !----------------------------------------------------------------------- + subroutine covercropping(p, crop_inst, cnveg_state_inst) + + ! + ! !DESCRIPTION: + ! !Covercropping subroutine allows second onset of phenology for cover crop after harvest of cash crops and immediate rotation to winter cash crop following a summer cash crop + ! * * * only call when covercrop(ivt(p)) == 1 * * * + ! + ! + + ! !USES: + use pftconMod , only : ntmp_corn, nswheat,nwwheat,ntmp_soybean,nbarley, nwbarley, nrye, nwrye, ncassava, napple, ncocoa,ncoffee,ncotton,ndatepalm, nfoddergrass, ngrapes, ngroundnuts, nmillet,noilpalm,npotatoes,npulses, nrapeseed, nrice, nsorghum, nsugarbeet,nsunflower,nmiscanthus,nswitchgrass, nc3crop, ncovercrop_1, ncovercrop_2 + use pftconMod , only : nirrig_tmp_corn,nirrig_swheat,nirrig_wwheat,nirrig_tmp_soybean, nirrig_barley, nirrig_wbarley,nirrig_rye,nirrig_wrye,nirrig_cassava, nirrig_apple, nirrig_cocoa,nirrig_coffee,nirrig_cotton,nirrig_datepalm, nirrig_foddergrass,nirrig_grapes,nirrig_groundnuts,nirrig_millet, nirrig_oilpalm, nirrig_potatoes,nirrig_pulses,nirrig_rapeseed,nirrig_rice, nirrig_sorghum,nirrig_sugarbeet,nirrig_sunflower,nirrig_miscanthus, nirrig_switchgrass,nc3irrig + use pftconMod , only : ntrp_corn, nsugarcane, ncotton, nrice + use pftconMod , only : nirrig_trp_corn, nirrig_sugarcane + use pftconMod , only : nirrig_cotton, nirrig_rice + use clm_varctl , only : use_grainproduct + use clm_time_manager, only: get_curr_calday + + ! !ARGUMENTS: + integer , intent(in) :: p ! PATCH index running over + type(crop_type) , intent(inout) :: crop_inst + type(cnveg_state_type) , intent(inout) :: cnveg_state_inst + + ! + ! LOCAL VARAIBLES: + integer jday ! julian day of the year + integer cashcrop1 ! first cash crop in rotation cycle + integer cashcrop2 ! second cash crop in rotation cycle + integer covercrop1 ! first cover crop in rotation cycle + integer covercrop2 ! second cover crop in rotation cycle + !! list can be extended + + !------------------------------------------------------------------------ + + associate( & + ivt => patch%itype ,& ! Input:[integer (:) ] patch vegetation type + cphase => crop_inst%cphase_patch ,& ! Output:[real(r8) (:)] phenology phase + idop => cnveg_state_inst%idop_patch ,& ! Output:[integer (:) ] date of planting + 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 + harvdate => crop_inst%harvdate_patch & ! Output:[integer (:) ] harvest date + ) + + jday = get_curr_calday() + ! add read in function from .txt file for flexible variable setting + ! define crop rotation: variable assignment can be changes and list can be extended + cashcrop1 = nswheat + cashcrop2 = nsugarbeet + covercrop1 = ncovercrop_1 + covercrop2 = ncovercrop_2 + + if (harvdate(p) >= 150._r8 .and. ivt(p) == cashcrop1) then + ivt(p)= covercrop1 + ! write (iulog,*) 'cft changed to covercrop' + croplive(p) = .false. + cropplant(p) = .false. + idop(p) = NOT_Planted + use_grainproduct = .false. + + else if (harvdate(p) <= 170._r8 .and. ivt(p) == covercrop1) then + ivt(p)= cashcrop2 + ! write (iulog,*) 'cft changed to cashcrop2' + croplive(p) = .false. + cropplant(p) = .false. + idop(p) = NOT_Planted + use_grainproduct = .true. + + else if (harvdate(p) >= 150._r8 .and. ivt(p) == cashcrop2) then + ivt(p)= covercrop2 + ! write (iulog,*) 'cft changed to covercrop2' + croplive(p) = .false. + cropplant(p) = .false. + idop(p) = NOT_Planted + use_grainproduct = .false. + + else if (harvdate(p) <= 170._r8 .and. ivt(p) == covercrop2) then + ivt(p)= cashcrop1 + ! write (iulog,*) 'cft changed back to cashcrop1 - beginning of next + ! rotatoin cycle' + croplive(p) = .false. + cropplant(p) = .false. + idop(p) = NOT_Planted + use_grainproduct = .true. + + end if + + end associate + + end subroutine covercropping + !----------------------------------------------------------------------- subroutine vernalization(p, & canopystate_inst, temperature_inst, waterstate_inst, cnveg_state_inst, crop_inst) @@ -2173,9 +3082,11 @@ subroutine vernalization(p, & cumvd(p) = cumvd(p) - 0.5_r8 * (t_ref2m_max(p) - tfrz - 30._r8) end if cumvd(p) = max(0._r8, cumvd(p)) ! must be > 0 + write(iulog,*)'vernalization_old cumvd(p)=', cumvd(p) vf(p) = 1._r8 - p1v * (50._r8 - cumvd(p)) vf(p) = max(0._r8, min(vf(p), 1._r8)) ! must be between 0 - 1 + write(iulog,*)'vernalization_old vf(p)=', vf(p) end if ! calculate cold hardening of plant @@ -2239,6 +3150,251 @@ subroutine vernalization(p, & end subroutine vernalization + + !----------------------------------------------------------------------- + subroutine vernalization_2(p, & + temperature_inst, waterstate_inst, cnveg_state_inst, crop_inst, cnveg_carbonflux_inst) + + ! + ! !DESCRIPTION: + ! !Alternative vernalization routine tranfered from CLM 4.5 after Lu et al. (2017) (tboas) + ! * * * only call for winter temperate cereal * * * + ! + ! subroutine calculates vernalization and photoperiod effects on + ! gdd accumulation in winter temperate cereal varieties. Thermal time + ! accumulation is reduced in 1st period until plant is fully vernalized. + ! During this time of emergence to spikelet formation, photoperiod can also have a + ! drastic effect on plant development. + + use clm_time_manager, only: get_step_size,get_curr_date + + ! + ! !ARGUMENTS: + integer , intent(in) :: p ! PATCH index running over + type(temperature_type) , intent(in) :: temperature_inst + type(waterstate_type) , intent(in) :: waterstate_inst + type(cnveg_state_type) , intent(inout) :: cnveg_state_inst + type(crop_type) , intent(inout) :: crop_inst + type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst + + + ! + ! LOCAL VARAIBLES: + real(r8) vd, vd1, vd2 ! vernalization dependence + real(r8) vtmin,vtopt,vtmax ! vernalization minimum, optimum, maximumtemperature + real(r8) alpha ! parameter in calculating vernalization rate + real(r8) tc ! t_ref2m in degree C + !real(r8) tcrown ! ? + integer c ! column indices + integer g ! gridcell indices + real(r8) dt ! land model time step (sec) + real(r8) dtime ! convert dt from sec to hour + + associate( & + ivt => patch%itype , & ! Input: [integer (:)] pft vegetation type + cumvd => cnveg_state_inst%cumvd_patch , & ! Output: [real(r8) (:)] cumulative vernalization d?ependence? + vf => crop_inst%vf_patch , & ! Output: [real(r8) (:)] vernalization factor for cereal + t_ref2m => temperature_inst%t_ref2m_patch , & ! Input: [real(r8) (:)] 2 m height surface air temperature (K) + tcrown => crop_inst%tcrown_patch , & ! Output: [real(r8) (:)] crown temperature + snow_depth => waterstate_inst%snow_depth_col , & ! Input: [real(r8) (:)] snow height (m) + 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 + cpool_to_grainc => cnveg_carbonflux_inst%cpool_to_grainc_patch & ! Input: [real(r8) (:) ] allocation to grain C (gC/m2/s) + ) + + c = patch%column(p) + dt=real( get_step_size(), r8 ) + + if (t_ref2m(p) < tfrz) then + tcrown(p) = 2._r8 + (t_ref2m(p) - tfrz) * (0.4_r8 + 0.0018_r8 * & + (min(snow_depth(c)*100._r8, 15._r8) - 15._r8)**2) + else + tcrown(p) = t_ref2m(p) - tfrz + end if + + ! write (iulog,*) 'subroutine vernalization_2' + + ! Vernalization factor calculation + ! if vf(p) = 1. then plant is fully vernalized - and thermal time + ! accumulation in phase 1 will be unaffected + ! refers to gddtsoi & gddplant, defined in the accumulation routines (slevis) + ! reset vf, cumvd, and hdidx to 0 at planting of crop (slevis) + !----------------------------------------------------------------------------- + !----------------------------------------------------------------------------- + ! ylu modified the vernalization function 10/16/15 + ! A generalized vernalization response function for winter wheat (Streck et al.,2003) was used here + ! Streck, N.A., Weiss, A., Baenziger, P.S., 2003. A generalized vernalization response & + ! function for winter wheat. Agron. J. 95 + + vtmin=-1.3_r8 + vtopt=4.9_r8 + vtmax=15.7_r8 + dtime=dt/3600.0_r8 !dtime is the time step in hour + + alpha=log(2._r8)/(log((vtmax-vtmin)/(vtopt-vtmin))) + write(iulog,*) 'alpha=',alpha + write(iulog,*) 'tcrown=',tcrown(p) + !tc = t_ref2m(p)-tfrz + if(tcrown(p) >=vtmin .and. tcrown(p) <= vtmax) then + cumvd(p)=cumvd(p) + ((2._r8*((tcrown(p)-vtmin)**alpha)*(vtopt-vtmin)**alpha & + - (tcrown(p)-vtmin)**(2._r8*alpha))/((vtopt-vtmin)**(2._r8*alpha)))*(dtime/24._r8) + end if + cumvd(p) = max(0._r8, cumvd(p)) ! must be > 0 + + write(iulog,*)'vernalization_2 cumvd(p)=', cumvd(p) + vf(p)=(cumvd(p)**5._r8)/(22.5_r8**5._r8+cumvd(p)**5._r8) + vf(p) = max(0._r8, min(vf(p), 1._r8)) ! must be between 0 - 1 + write(iulog,*)'vernalization_2 vf(p)=', vf(p) + + write(iulog,*)'vernalization_2 cpool_to_grainc(p),hui(p) ',hui(p),cpool_to_grainc(p) + + end associate + + end subroutine vernalization_2 + + !----------------------------------------------------------------------- + subroutine coldtolerance (p,canopystate_inst,temperature_inst, & + waterstate_inst,cnveg_state_inst, crop_inst, & + cnveg_nitrogenflux_inst, cnveg_carbonflux_inst, & + cnveg_carbonstate_inst, cnveg_nitrogenstate_inst) + + ! !DESCRIPTION: + ! !Subroutine for coldtolerance modified after Lu(2017): 'Representing witer wheat in the Community Land Model (version 4.5) (tboas) + ! * * * only call for winter temperate cereal * * * + ! + !the subroutine calculates the lethal temperature at 50% of crop alive, + !survival rate, winter degree days + + + use clm_time_manager, only: get_step_size,get_curr_date + + ! + ! !ARGUMENTS: + !implicit none + integer, intent(in) :: p ! PFT index running over + type(canopystate_type) , intent(in) :: canopystate_inst + type(temperature_type) , intent(in) :: temperature_inst + type(waterstate_type) , intent(in) :: waterstate_inst + type(cnveg_carbonstate_type) , intent(in) :: cnveg_carbonstate_inst + type(cnveg_nitrogenstate_type), intent(in) :: cnveg_nitrogenstate_inst + type(cnveg_state_type) , intent(inout) :: cnveg_state_inst + type(crop_type) , intent(inout) :: crop_inst + type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst + type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst + ! + + ! LOCAL VARAIBLES: + real(r8) tcrown ! crown temperature + logical :: end_cd ! temporary for is_end_curr_day() value + real(r8) tc ! t_ref2m in degree C + real(r8) prevleafc ! previous step leafc + real(r8) tempfsurv ! averaged survival rate + integer c ! column indices + integer g ! gridcell indices + real(r8) dt ! land model time step (sec) + real(r8) dtime ! convert dt from sec to hour + 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) + real(r8), parameter :: Hparam=0.0093 + real(r8), parameter :: Dparam=2.7e-5 + real(r8), parameter :: Sparam=1.9 + real(r8), parameter :: Rparam=0.54 + real(r8), parameter :: T_S_max=12.5 + real(r8), parameter :: lt50max=-23 + !the calculation of frost tolerance is based on Bergjord et al.,(2008),Europ.J.Agronomuy + !the calculation of survival rate and WDD is based on Vico et al.,(2014),Agri and Forest Metero. + + !------------------------------------------------------------------------ + + associate( & + ivt => patch%itype , & ! Input: [integer (:)] pft vegetation type + croplive => crop_inst%croplive_patch , & ! Input: [logical (:)] Flag,true if planted, not harvested + hdidx => cnveg_state_inst%hdidx_patch , & ! Output: [real(r8) (:)] cold hardening index? + rateh => crop_inst%rateh_patch , & ! Output: [real(r8)(:)] increase of tolerance cuased byhardening + rated => crop_inst%rated_patch , & ! Output: [real(r8) (:)] loss of tolerance cause by dehardening + rates => crop_inst%rates_patch , & ! Output: [real(r8) (:)] loss of tolerance caused by low tempeature + rater => crop_inst%rater_patch , & ! Output: [real(r8) (:)] loss of tolerance caused by respiration under snow + lt50 => crop_inst%lt50_patch , & ! Output: [real(r8) (:)] the lethal temperature at which 50% of the individuals are damaged + fsurv => crop_inst%fsurv_patch , & ! Output: [real(r8) (:)] winter wheat survival rate + accfsurv => crop_inst%accfsurv_patch , & ! Output: [real(r8) (:)] accumulated winter wheat survival rate [0 crop_inst%countfsurv_patch , & ! Output: [real(r8) (:)] numbers of accumulated winter wheat survival rate + wdd => crop_inst%wdd_patch , & ! Output: [real(r8) (:)] winter wheat weighted cumulated degree days + ck => crop_inst%ck_patch , & ! Output: [real(r8) (:)] fraction of green leaf area killed + cumvd => cnveg_state_inst%cumvd_patch , & ! Output: [real(r8) (:)] cumulative vernalization d?ependence? + vf => crop_inst%vf_patch , & ! Output: [real(r8) (:)] vernalization factor for cereal + gddmaturity => cnveg_state_inst%gddmaturity_patch , & ! Output: [real(r8) (:)] gdd needed to harvest + huigrain => cnveg_state_inst%huigrain_patch , & ! Output: [real(r8) (:)] heat unit index needed to reach vegetative maturity + leafc_to_litter => cnveg_carbonflux_inst%leafc_to_litter_patch , & ! Output: [real(r8) (:)] leaf C litterfall (gC/m2/s) + leafn_to_litter => cnveg_nitrogenflux_inst%leafn_to_litter_patch , & ! Output: [real(r8) (:)] leaf N litterfall (gN/m2/s) + leafc => cnveg_carbonstate_inst%leafc_patch , & ! Input: [real(r8) (:)] (gC/m2) leaf C + leafcn => pftcon%leafcn , & ! Input: [real(r8) (:)] leaf C:N (gC/gN) + leafn => cnveg_nitrogenstate_inst%leafn_patch , & ! Input: [real(r8)(:)] (gN/m2) leaf N + lflitcn => pftcon%lflitcn , & ! Input: [real(r8) (:)] leaf litter C:N (gC/gN) + tlai => canopystate_inst%tlai_patch , & ! Input: [real(r8) (:)] one-sided leaf area index, no burying by snow + t_ref2m => temperature_inst%t_ref2m_patch , & ! Input: [real(r8) (:)] 2 m height surface air temperature (K) + tcrown => crop_inst%tcrown_patch , & ! Output: [real(r8) (:)] crown temperature + snow_depth => waterstate_inst%snow_depth_col & ! Input: [real(r8) (:)] snow height (m) + ) + + c = patch%column(p) + dt=real( get_step_size(), r8 ) + + if (t_ref2m(p) < tfrz) then !slevis: t_ref2m inst of td=daily avg (K) + tcrown(p) = 2._r8 + (t_ref2m(p) - tfrz) * (0.4_r8 + 0.0018_r8 * & + (min(snow_depth(c)*100._r8, 15._r8) - 15._r8)**2) + else !slevis: snow_depth inst of adsnod=daily average (m) + tcrown(p) = t_ref2m(p) - tfrz + end if + + dtime=dt/3600.0_r8 !dtime is the time step dt in hour + +!frost tolerance and survival rate calculation + + if(tcrown(p) < 10._r8) then + rateh(p)=Hparam*(10._r8-tcrown(p))*(lt50(p)-lt50max) + write(iulog,*) 'rateh=',rateh(p),'lt50=',lt50(p),'tcrown=',tcrown(p) + write(iulog,*) 'snow_depth=',snow_depth(c) + end if + + if((tcrown(p) >=-4._r8 .and. vf(p) == 1._r8) .or. (tcrown(p)>=10._r8 .and. vf(p) <1._r8)) then + rated(p)=Dparam*(-0.6_r8+0.142_r8*lt50max-lt50(p))*(tcrown(p)+4._r8)**3._r8 + end if + + rater(p)=Rparam*(exp(0.84+0.051*tcrown(p))-2._r8)/1.85_r8*(snow_depth(c)*100._r8)/12.5 + rates(p)=(lt50(p)-tcrown(p))/exp(-Sparam*(lt50(p)-tcrown(p))-3.74_r8) + lt50(p)=lt50(p)+(rated(p)+rates(p)+rater(p)-rateh(p))*(dtime/24._r8) + + fsurv(p)=2._r8**(-(abs(tcrown(p))/abs(lt50(p)))**4._r8) + wdd(p)=wdd(p)+(max(tbase-tcrown(p),0._r8)*(1._r8-fsurv(p)))*(dtime/24._r8) + + if(wdd(p) >0._r8) then + accfsurv(p) = accfsurv(p) + fsurv(p) + countfsurv(p) = countfsurv(p) + 1._r8 + end if + + call get_curr_date(kyr, kmo, kda, mcsec) + end_cd = (mcsec == 0) + if( end_cd .and. wdd(p) > 0._r8 .and. vf(p) <0.9_r8 .and. leafc(p) > 10._r8 ) then + leafc_to_litter(p)=leafc_to_litter(p)+5._r8*(1._r8-fsurv(p))/dt + leafn_to_litter(p)=leafn_to_litter(p)+(5._r8*(1._r8-fsurv(p)))/(dt*lflitcn(ivt(p))) + end if + + if(end_cd .and. wdd(p) > 1.0_r8 .and. vf(p)>0.9_r8 ) then + tempfsurv=accfsurv(p)/countfsurv(p) + prevleafc=leafc(p) + leafc_to_litter(p)=leafc_to_litter(p)+prevleafc*(1._r8-tempfsurv)/dt + leafn_to_litter(p)=leafn_to_litter(p)+(prevleafc*(1._r8-tempfsurv))/(dt*lflitcn(ivt(p))) + accfsurv(p) = 1._r8 + countfsurv(p) = 1._r8 + wdd(p) =0._r8 + write (iulog,*) 'subroutine coldtolerance ending' + end if + + end associate + end subroutine coldtolerance + !----------------------------------------------------------------------- subroutine CNOnsetGrowth (num_soilp, filter_soilp, & cnveg_state_inst, & @@ -2298,7 +3454,7 @@ subroutine CNOnsetGrowth (num_soilp, filter_soilp, & 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) (:) ] + deadcrootn_xfer_to_deadcrootn => cnveg_nitrogenflux_inst%deadcrootn_xfer_to_deadcrootn_patch & ! Output: [real(r8) (:) ] ) ! patch loop @@ -2362,7 +3518,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 +3527,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 +3543,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 +3580,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 +3632,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 +3741,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 +3753,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 +3789,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 +3823,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 +3847,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 +3857,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 +3870,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 +4235,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 +4257,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 +4265,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 +4280,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 +4363,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 +4377,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 +4416,339 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & + grainn_to_food(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) end if + ! calculate pruning litter fluxes added by O.Dombrowski + ! and adapted based on CLM-Palm (Fan et al. 2015) + if ( perennial(ivt(p)) == 1._r8 .and. prune_flag(p) == 1._r8) then + if (mulch_pruning(ivt(p)) == 0._r8) then + ! export pruning material as harvest + ! storage harvest mortality carbon fluxes + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_deadstemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + ! storage harvest mortality nitrogen fluxes + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_deadstemn_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + + ! wood harvest mortality carbon fluxes to product pools + !cwood_harvestc(c) = cwood_harvestc(c) + & + !pwood_harvestc(p) * wtcol(p) + ! wood harvest mortality nitrogen fluxes to product pools + !cwood_harvestn(c) = cwood_harvestn(c) + & + !pwood_harvestn(p) * wtcol(p) + + else if (mulch_pruning(ivt(p)) == 1._r8) then + ! add pruning material to litter + ! pruning carbon fluxes + phenology_c_to_litr_met_c(c,j) = phenology_c_to_litr_met_c(c,j) & + + prunec_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) & + + prunec_storage_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_c_to_litr_cel_c(c,j) = phenology_c_to_litr_cel_c(c,j) & + + prunec_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) & + + prunec_storage_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_c_to_litr_lig_c(c,j) = phenology_c_to_litr_lig_c(c,j) & + + prunec_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) & + + prunec_storage_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) + + ! pruning nitrogen fluxes + phenology_n_to_litr_met_n(c,j) = phenology_n_to_litr_met_n(c,j) & + + prunen_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) & + + prunen_storage_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_n_to_litr_cel_n(c,j) = phenology_n_to_litr_cel_n(c,j) & + + prunen_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) & + + prunen_storage_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) + phenology_n_to_litr_lig_n(c,j) = phenology_n_to_litr_lig_n(c,j) & + + prunen_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) & + + prunen_storage_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) + end if + end if end if end if end if end do - end do end do - end associate + + do pi = 1,maxpatch_pft + do fc = 1,num_soilc + c = filter_soilc(fc) + + if (pi <= col%npatches(c)) then + p = col%patchi(c) + pi - 1 + if (perennial(ivt(p)) == 1._r8 .and. prune_flag(p) == 1._r8 .and. mulch_pruning(ivt(p)) == 0._r8) then + if (patch%active(p)) then + ! wood harvest mortality carbon fluxes to product pools + cwood_harvestc(c) = cwood_harvestc(c) + & + pwood_harvestc(p) * wtcol(p) + + ! wood harvest mortality nitrogen fluxes to product pools + cwood_harvestn(c) = cwood_harvestn(c) + & + pwood_harvestn(p) * wtcol(p) + end if + end if + end if + + end do + + end do + + end associate end subroutine CNLitterToColumn + !----------------------------------------------------------------------- + subroutine CNRotationToColumn (num_soilc, filter_soilc, & + cnveg_state_inst, soilbiogeochem_state_inst, & + crop_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) + ! + ! !DESCRIPTION: + ! called at the end of CNPhenology to gather all patch-level orchard rotation litterfall + ! fluxes + ! to the column level and assign them to the three litter pools + ! + ! !USES: + use clm_varpar , only : maxpatch_pft, nlevdecomp + use pftconMod , only : npcropmin + ! + ! !ARGUMENTS: + integer , intent(in) :: num_soilc ! number of soil columns in filter + integer , intent(in) :: filter_soilc(:) ! soil column filter + type(crop_type) , intent(inout) :: crop_inst + type(cnveg_state_type) , intent(in) :: cnveg_state_inst + type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst + type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst + type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst + ! + ! !LOCAL VARIABLES: + integer :: fc,c,pi,p,j ! indices + !----------------------------------------------------------------------- + + associate( & + ivt => patch%itype , & ! Input: [integer (:) ] pft vegetation type + wtcol => patch%wtcol , & ! Input: [real(r8) (:) ] pft weight relative to column (0-1) + + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types + lf_flab => pftcon%lf_flab , & ! Input: leaf litter labile fraction + lf_fcel => pftcon%lf_fcel , & ! Input: leaf litter cellulose fraction + lf_flig => pftcon%lf_flig , & ! Input: leaf litter lignin fraction + fr_flab => pftcon%fr_flab , & ! Input: fine root litter labile fraction + fr_fcel => pftcon%fr_fcel , & ! Input: fine root litter cellulose fraction + fr_flig => pftcon%fr_flig , & ! Input: fine root litter lignin fraction + + offset2_flag => cnveg_state_inst%offset2_flag_patch , & ! Input: binary flag for rotation of perennial crop types + croplive => crop_inst%croplive_patch , & ! Output: [logical (:) ] Flag, true if planted, not harvested + + leaf_prof => soilbiogeochem_state_inst%leaf_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of leaves + froot_prof => soilbiogeochem_state_inst%froot_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of fine roots + croot_prof => soilbiogeochem_state_inst%croot_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of coarse roots + stem_prof => soilbiogeochem_state_inst%stem_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of stems + + hrv_leafc_to_litter => cnveg_carbonflux_inst%hrv_leafc_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_frootc_to_litter => cnveg_carbonflux_inst%hrv_frootc_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livestemc_to_litter => cnveg_carbonflux_inst%hrv_livestemc_to_litter_patch , & ! Input: [real(r8) (:) ] + pwood_harvestc => cnveg_carbonflux_inst%wood_harvestc_patch , & ! Input: [real(r8) (:) ] + hrv_livecrootc_to_litter => cnveg_carbonflux_inst%hrv_livecrootc_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadcrootc_to_litter => cnveg_carbonflux_inst%hrv_deadcrootc_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_leafc_storage_to_litter => cnveg_carbonflux_inst%hrv_leafc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_frootc_storage_to_litter => cnveg_carbonflux_inst%hrv_frootc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livestemc_storage_to_litter => cnveg_carbonflux_inst%hrv_livestemc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadstemc_storage_to_litter => cnveg_carbonflux_inst%hrv_deadstemc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livecrootc_storage_to_litter => cnveg_carbonflux_inst%hrv_livecrootc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadcrootc_storage_to_litter => cnveg_carbonflux_inst%hrv_deadcrootc_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_gresp_storage_to_litter => cnveg_carbonflux_inst%hrv_gresp_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_leafc_xfer_to_litter => cnveg_carbonflux_inst%hrv_leafc_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_frootc_xfer_to_litter => cnveg_carbonflux_inst%hrv_frootc_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livestemc_xfer_to_litter => cnveg_carbonflux_inst%hrv_livestemc_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadstemc_xfer_to_litter => cnveg_carbonflux_inst%hrv_deadstemc_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livecrootc_xfer_to_litter => cnveg_carbonflux_inst%hrv_livecrootc_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadcrootc_xfer_to_litter => cnveg_carbonflux_inst%hrv_deadcrootc_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_gresp_xfer_to_litter => cnveg_carbonflux_inst%hrv_gresp_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + cwood_harvestc => cnveg_carbonflux_inst%wood_harvestc_col , & ! InOut: [real(r8) (:) ] + harvest_c_to_litr_met_c => cnveg_carbonflux_inst%harvest_c_to_litr_met_c_col , & ! InOut: [real(r8) (:,:) ] C fluxes associated with harvest to litter metabolic pool (gC/m3/s) + harvest_c_to_litr_cel_c => cnveg_carbonflux_inst%harvest_c_to_litr_cel_c_col , & ! InOut: [real(r8) (:,:) ] C fluxes associated with harvest to litter cellulose pool (gC/m3/s) + harvest_c_to_litr_lig_c => cnveg_carbonflux_inst%harvest_c_to_litr_lig_c_col , & ! InOut: [real(r8) (:,:) ] C fluxes associated with harvest to litter lignin pool (gC/m3/s) + harvest_c_to_cwdc => cnveg_carbonflux_inst%harvest_c_to_cwdc_col , & ! InOut: [real(r8) (:,:) ] C fluxes associated with harvest to CWD pool (gC/m3/s) + + hrv_leafn_to_litter => cnveg_nitrogenflux_inst%hrv_leafn_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_frootn_to_litter => cnveg_nitrogenflux_inst%hrv_frootn_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livestemn_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_to_litter_patch , & ! Input: [real(r8) (:) ] + pwood_harvestn => cnveg_nitrogenflux_inst%wood_harvestn_patch , & ! Input: [real(r8) (:) ] + hrv_livecrootn_to_litter => cnveg_nitrogenflux_inst%hrv_livecrootn_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadcrootn_to_litter => cnveg_nitrogenflux_inst%hrv_deadcrootn_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_retransn_to_litter => cnveg_nitrogenflux_inst%hrv_retransn_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_leafn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_leafn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_frootn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_frootn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livestemn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadstemn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_deadstemn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livecrootn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_livecrootn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadcrootn_storage_to_litter => cnveg_nitrogenflux_inst%hrv_deadcrootn_storage_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_leafn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_leafn_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_frootn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_frootn_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livestemn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadstemn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_deadstemn_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_livecrootn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_livecrootn_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + hrv_deadcrootn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_deadcrootn_xfer_to_litter_patch , & ! Input: [real(r8) (:) ] + cwood_harvestn => cnveg_nitrogenflux_inst%wood_harvestn_col , & ! InOut: [real(r8) (:) ] + harvest_n_to_litr_met_n => cnveg_nitrogenflux_inst%harvest_n_to_litr_met_n_col , & ! InOut: [real(r8) (:,:) ] N fluxes associated with harvest to litter metabolic pool (gN/m3/s) + harvest_n_to_litr_cel_n => cnveg_nitrogenflux_inst%harvest_n_to_litr_cel_n_col , & ! InOut: [real(r8) (:,:) ] N fluxes associated with harvest to litter cellulose pool (gN/m3/s) + harvest_n_to_litr_lig_n => cnveg_nitrogenflux_inst%harvest_n_to_litr_lig_n_col , & ! InOut: [real(r8) (:,:) ] N fluxes associated with harvest to litter lignin pool (gN/m3/s) + harvest_n_to_cwdn => cnveg_nitrogenflux_inst%harvest_n_to_cwdn_col & ! InOut: [real(r8) (:,:) ] N fluxes associated with harvest to CWD pool (gN/m3/s) + ) + + do j = 1, nlevdecomp + do pi = 1,maxpatch_pft + do fc = 1,num_soilc + c = filter_soilc(fc) + + if (pi <= col%npatches(c)) then + p = col%patchi(c) + pi - 1 + + if (patch%active(p) .and. (.not. croplive(p)) .and. ivt(p) >= npcropmin .and. perennial(ivt(p)) == 1._r8 .and. offset2_flag(p) == 1._r8) then + + ! leaf harvest mortality carbon fluxes + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_leafc_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) + harvest_c_to_litr_cel_c(c,j) = harvest_c_to_litr_cel_c(c,j) + & + hrv_leafc_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) + harvest_c_to_litr_lig_c(c,j) = harvest_c_to_litr_lig_c(c,j) + & + hrv_leafc_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) + + ! fine root harvest mortality carbon fluxes + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_frootc_to_litter(p) * fr_flab(ivt(p)) * wtcol(p) * froot_prof(p,j) + harvest_c_to_litr_cel_c(c,j) = harvest_c_to_litr_cel_c(c,j) + & + hrv_frootc_to_litter(p) * fr_fcel(ivt(p)) * wtcol(p) * froot_prof(p,j) + harvest_c_to_litr_lig_c(c,j) = harvest_c_to_litr_lig_c(c,j) + & + hrv_frootc_to_litter(p) * fr_flig(ivt(p)) * wtcol(p) * froot_prof(p,j) + + ! wood harvest mortality carbon fluxes + harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & + hrv_livestemc_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & + hrv_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & + hrv_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) + ! storage harvest mortality carbon fluxes + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_leafc_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_frootc_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_livestemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_deadstemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_livecrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_deadcrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_gresp_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + + ! transfer harvest mortality carbon fluxes + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_leafc_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_frootc_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_livestemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_deadstemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_livecrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_deadcrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & + hrv_gresp_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + + ! leaf harvest mortality nitrogen fluxes + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_leafn_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) + harvest_n_to_litr_cel_n(c,j) = harvest_n_to_litr_cel_n(c,j) + & + hrv_leafn_to_litter(p) * lf_fcel(ivt(p)) * wtcol(p) * leaf_prof(p,j) + harvest_n_to_litr_lig_n(c,j) = harvest_n_to_litr_lig_n(c,j) + & + hrv_leafn_to_litter(p) * lf_flig(ivt(p)) * wtcol(p) * leaf_prof(p,j) + + ! fine root litter nitrogen fluxes + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_frootn_to_litter(p) * fr_flab(ivt(p)) * wtcol(p) * froot_prof(p,j) + harvest_n_to_litr_cel_n(c,j) = harvest_n_to_litr_cel_n(c,j) + & + hrv_frootn_to_litter(p) * fr_fcel(ivt(p)) * wtcol(p) * froot_prof(p,j) + harvest_n_to_litr_lig_n(c,j) = harvest_n_to_litr_lig_n(c,j) + & + hrv_frootn_to_litter(p) * fr_flig(ivt(p)) * wtcol(p) * froot_prof(p,j) + + ! wood harvest mortality nitrogen fluxes + harvest_n_to_cwdn(c,j) = harvest_n_to_cwdn(c,j) + & + hrv_livestemn_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_n_to_cwdn(c,j) = harvest_n_to_cwdn(c,j) + & + hrv_livecrootn_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_n_to_cwdn(c,j) = harvest_n_to_cwdn(c,j) + & + hrv_deadcrootn_to_litter(p) * wtcol(p) * croot_prof(p,j) + + ! retranslocated N pool harvest mortality fluxes + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_retransn_to_litter(p) * wtcol(p) * leaf_prof(p,j) + + ! storage harvest mortality nitrogen fluxes + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_leafn_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_frootn_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_livestemn_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_deadstemn_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_livecrootn_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_deadcrootn_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + + ! transfer harvest mortality nitrogen fluxes + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_leafn_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_frootn_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_livestemn_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_deadstemn_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_livecrootn_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_n_to_litr_met_n(c,j) = harvest_n_to_litr_met_n(c,j) + & + hrv_deadcrootn_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + + end if + end if + + end do + + end do + end do + + do pi = 1,maxpatch_pft + do fc = 1,num_soilc + c = filter_soilc(fc) + + if (pi <= col%npatches(c)) then + p = col%patchi(c) + pi - 1 + + if (patch%active(p)) then + ! wood harvest mortality carbon fluxes to product pools + cwood_harvestc(c) = cwood_harvestc(c) + & + pwood_harvestc(p) * wtcol(p) + + ! wood harvest mortality nitrogen fluxes to product pools + cwood_harvestn(c) = cwood_harvestn(c) + & + pwood_harvestn(p) * wtcol(p) + end if + end if + + end do + + end do + + end associate + + end subroutine CNRotationToColumn + end module CNPhenologyMod diff --git a/src/clm5/biogeochem/CNVegCarbonFluxType.F90 b/src/clm5/biogeochem/CNVegCarbonFluxType.F90 index f88c7f5e66..681b394f3e 100644 --- a/src/clm5/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/clm5/biogeochem/CNVegCarbonFluxType.F90 @@ -17,7 +17,7 @@ module CNVegCarbonFluxType use clm_varctl , only : use_grainproduct use clm_varctl , only : iulog use landunit_varcon , only : istsoil, istcrop, istdlak - use pftconMod , only : npcropmin + use pftconMod , only : npcropmin, pftcon use LandunitType , only : lun use ColumnType , only : col use PatchType , only : patch @@ -136,6 +136,10 @@ module CNVegCarbonFluxType real(r8), pointer :: grainc_to_food_patch (:) ! grain C to food for prognostic crop(gC/m2/s) real(r8), pointer :: grainc_to_seed_patch (:) ! grain C to seed for prognostic crop(gC/m2/s) + ! pruning litterfall flux + real(r8), pointer :: prunec_to_litter_patch (:) ! pruning C litterfall (gC/m2/s) + real(r8), pointer :: prunec_storage_to_litter_patch (:) ! pruning storage C litterfall (gC/m2/s) + ! maintenance respiration fluxes real(r8), pointer :: cpool_to_resp_patch (:) ! CNflex excess C maintenance respiration (gC/m2/s) real(r8), pointer :: cpool_to_leafc_resp_patch (:) ! CNflex excess C maintenance respiration (gC/m2/s) @@ -274,6 +278,8 @@ module CNVegCarbonFluxType ! crop fluxes real(r8), pointer :: crop_seedc_to_leaf_patch (:) ! (gC/m2/s) seed source to leaf, for crops + real(r8), pointer :: crop_seedc_to_froot_patch (:) ! (gC/m2/s) seed source to fine roots, for perennial crops (added by O.Dombrowski) + real(r8), pointer :: crop_seedc_to_deadstem_patch (:) ! (gC/m2/s) seed source to deadstem, for perennial crops (added by O.Dombrowski) ! summary (diagnostic) flux variables, not involved in mass balance real(r8), pointer :: gpp_before_downreg_patch (:) ! (gC/m2/s) gross primary production before down regulation @@ -615,6 +621,8 @@ subroutine InitAllocate(this, bounds, carbon_type) allocate(this%leafc_loss_patch (begp:endp)) ; this%leafc_loss_patch (:) = nan allocate(this%woodc_alloc_patch (begp:endp)) ; this%woodc_alloc_patch (:) = nan allocate(this%woodc_loss_patch (begp:endp)) ; this%woodc_loss_patch (:) = nan + allocate(this%prunec_to_litter_patch (begp:endp)) ; this%prunec_to_litter_patch (:) = nan + allocate(this%prunec_storage_to_litter_patch (begp:endp)) ; this%prunec_storage_to_litter_patch (:) = nan allocate(this%phenology_c_to_litr_met_c_col (begc:endc,1:nlevdecomp_full)); this%phenology_c_to_litr_met_c_col (:,:)=nan @@ -654,6 +662,8 @@ subroutine InitAllocate(this, bounds, carbon_type) allocate(this%dwt_crop_productc_gain_patch (begp:endp)) ; this%dwt_crop_productc_gain_patch(:) =nan allocate(this%crop_seedc_to_leaf_patch (begp:endp)) ; this%crop_seedc_to_leaf_patch (:) =nan + allocate(this%crop_seedc_to_froot_patch (begp:endp)) ; this%crop_seedc_to_froot_patch (:) =nan + allocate(this%crop_seedc_to_deadstem_patch (begp:endp)) ; this%crop_seedc_to_deadstem_patch (:) =nan allocate(this%cwdc_hr_col (begc:endc)) ; this%cwdc_hr_col (:) =nan allocate(this%cwdc_loss_col (begc:endc)) ; this%cwdc_loss_col (:) =nan @@ -1264,6 +1274,11 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='live coarse root maintenance respiration', & ptr_patch=this%livecroot_mr_patch, default='inactive') + this%grain_mr_patch(begp:endp) = spval + call hist_addfld1d (fname='GRAIN_MR', units='gC/m^2/s', & + avgflag='A', long_name='grain maintenance respiration', & + ptr_patch=this%grain_mr_patch, default='inactive') + this%psnsun_to_cpool_patch(begp:endp) = spval call hist_addfld1d (fname='PSNSUN_TO_CPOOL', units='gC/m^2/s', & avgflag='A', long_name='C fixation from sunlit canopy', & @@ -2918,6 +2933,16 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='crop seed source to leaf', & ptr_patch=this%crop_seedc_to_leaf_patch, default='inactive') + this%crop_seedc_to_froot_patch(begp:endp) = spval + call hist_addfld1d (fname='CROP_SEEDC_TO_FROOT', units='gC/m^2/s', & + avgflag='A', long_name='crop seed source to fine root', & + ptr_patch=this%crop_seedc_to_froot_patch, default='inactive') + + this%crop_seedc_to_deadstem_patch(begp:endp) = spval + call hist_addfld1d (fname='CROP_SEEDC_TO_DEADSTEM', units='gC/m^2/s', & + avgflag='A', long_name='crop seed source to deadstem', & + ptr_patch=this%crop_seedc_to_deadstem_patch, default='inactive') + this%sr_col(begc:endc) = spval call hist_addfld1d (fname='SR', units='gC/m^2/s', & avgflag='A', long_name='total soil respiration (HR + root resp)', & @@ -3092,6 +3117,16 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C13 crop seed source to leaf', & ptr_patch=this%crop_seedc_to_leaf_patch, default='inactive') + this%crop_seedc_to_froot_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_CROP_SEEDC_TO_FROOT', units='gC13/m^2/s', & + avgflag='A', long_name='C13 crop seed source to fine root', & + ptr_patch=this%crop_seedc_to_froot_patch, default='inactive') + + this%crop_seedc_to_deadstem_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_CROP_SEEDC_TO_DEADSTEM', units='gC13/m^2/s', & + avgflag='A', long_name='C13 crop seed source to deadstem', & + ptr_patch=this%crop_seedc_to_deadstem_patch, default='inactive') + this%sr_col(begc:endc) = spval call hist_addfld1d (fname='C13_SR', units='gC13/m^2/s', & avgflag='A', long_name='C13 total soil respiration (HR + root resp)', & @@ -3248,6 +3283,17 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C14 crop seed source to leaf', & ptr_patch=this%crop_seedc_to_leaf_patch, default='inactive') + this%crop_seedc_to_froot_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_CROP_SEEDC_TO_FROOT', units='gC14/m^2/s', & + avgflag='A', long_name='C14 crop seed source to fine root', & + ptr_patch=this%crop_seedc_to_froot_patch, default='inactive') + + this%crop_seedc_to_deadstem_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_CROP_SEEDC_TO_DEADSTEM', units='gC14/m^2/s', & + avgflag='A', long_name='C14 crop seed source to deadstem', & + ptr_patch=this%crop_seedc_to_deadstem_patch, default='inactive') + + this%sr_col(begc:endc) = spval call hist_addfld1d (fname='C14_SR', units='gC14/m^2/s', & avgflag='A', long_name='C14 total soil respiration (HR + root resp)', & @@ -3521,6 +3567,16 @@ subroutine RestartBulkOnly ( this, bounds, ncid, flag ) long_name='grain C shift storage to transfer', units='gC/m2/s', & interpinic_flag='interp', readvar=readvar, data=this%grainc_storage_to_xfer_patch) + call restartvar(ncid=ncid, flag=flag, varname='prunec_to_litter', xtype=ncd_double, & + dim1name='pft', & + long_name='pruning C litterfall', units='gC/m2/s', & + interpinic_flag='interp', readvar=readvar, data=this%prunec_to_litter_patch) + + call restartvar(ncid=ncid, flag=flag, varname='prunec_storage_to_litter', xtype=ncd_double, & + dim1name='pft', & + long_name='pruning storage C litterfall', units='gC/m2/s', & + interpinic_flag='interp', readvar=readvar, data=this%prunec_storage_to_litter_patch) + end if call restartvar(ncid=ncid, flag=flag, varname='gpp_pepv', xtype=ncd_double, & @@ -3818,6 +3874,8 @@ subroutine SetValues ( this, & this%woodc_loss_patch(i) = value_patch this%crop_seedc_to_leaf_patch(i) = value_patch + this%crop_seedc_to_froot_patch(i) = value_patch + this%crop_seedc_to_deadstem_patch(i) = value_patch this%grainc_to_cropprodc_patch(i) = value_patch end do @@ -3835,6 +3893,8 @@ subroutine SetValues ( this, & this%cpool_grain_storage_gr_patch(i) = value_patch this%transfer_grain_gr_patch(i) = value_patch this%grainc_storage_to_xfer_patch(i) = value_patch + this%prunec_to_litter_patch(i) = value_patch + this%prunec_storage_to_litter_patch(i) = value_patch end do end if @@ -4273,8 +4333,9 @@ subroutine Summary_carbonflux(this, & if ( use_crop .and. patch%itype(p) >= npcropmin )then this%litfall_patch(p) = & this%litfall_patch(p) + & - this%livestemc_to_litter_patch(p) - + this%livestemc_to_litter_patch(p) + & + this%prunec_to_litter_patch(p) + & + this%prunec_storage_to_litter_patch(p) if (.not. use_grainproduct) then this%litfall_patch(p) = & this%litfall_patch(p) + & @@ -4508,8 +4569,7 @@ subroutine Summary_carbonflux(this, & ! total ecosystem respiration, autotrophic + heterotrophic (ER) this%er_col(c) = & this%ar_col(c) + & - soilbiogeochem_hr_col(c) - + soilbiogeochem_hr_col(c) ! coarse woody debris heterotrophic respiration this%cwdc_hr_col(c) = 0._r8 diff --git a/src/clm5/biogeochem/CNVegCarbonStateType.F90 b/src/clm5/biogeochem/CNVegCarbonStateType.F90 index 1d568dc60d..08a273b338 100644 --- a/src/clm5/biogeochem/CNVegCarbonStateType.F90 +++ b/src/clm5/biogeochem/CNVegCarbonStateType.F90 @@ -48,6 +48,8 @@ module CNVegCarbonStateType real(r8), pointer :: deadstemc_patch (:) ! (gC/m2) dead stem C real(r8), pointer :: deadstemc_storage_patch (:) ! (gC/m2) dead stem C storage real(r8), pointer :: deadstemc_xfer_patch (:) ! (gC/m2) dead stem C transfer + real(r8), pointer :: deadstemc_soy_patch (:) ! (gC/m2) dead stem C at the start of year + real(r8), pointer :: deadstemc_storage_soy_patch (:) ! (gC/m2) dead stem C storage at the start of year real(r8), pointer :: livecrootc_patch (:) ! (gC/m2) live coarse root C real(r8), pointer :: livecrootc_storage_patch (:) ! (gC/m2) live coarse root C storage real(r8), pointer :: livecrootc_xfer_patch (:) ! (gC/m2) live coarse root C transfer @@ -234,6 +236,8 @@ subroutine InitAllocate(this, bounds) allocate(this%deadstemc_patch (begp:endp)) ; this%deadstemc_patch (:) = nan allocate(this%deadstemc_storage_patch (begp:endp)) ; this%deadstemc_storage_patch (:) = nan allocate(this%deadstemc_xfer_patch (begp:endp)) ; this%deadstemc_xfer_patch (:) = nan + allocate(this%deadstemc_soy_patch (begp:endp)) ; this%deadstemc_soy_patch (:) = nan + allocate(this%deadstemc_storage_soy_patch (begp:endp)) ; this%deadstemc_storage_soy_patch (:) = nan allocate(this%livecrootc_patch (begp:endp)) ; this%livecrootc_patch (:) = nan allocate(this%livecrootc_storage_patch (begp:endp)) ; this%livecrootc_storage_patch (:) = nan allocate(this%livecrootc_xfer_patch (begp:endp)) ; this%livecrootc_xfer_patch (:) = nan @@ -400,6 +404,16 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='dead stem C transfer', & ptr_patch=this%deadstemc_xfer_patch, default='inactive') + this%deadstemc_soy_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADSTEMC_SOY', units='gC/m^2', & + avgflag='A', long_name='dead stem C at start of year', & + ptr_patch=this%deadstemc_soy_patch, default='inactive') + + this%deadstemc_storage_soy_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADSTEMC_STORAGE_SOY', units='gC/m^2', & + avgflag='A', long_name='dead stem C storage at start of year', & + ptr_patch=this%deadstemc_storage_soy_patch, default='inactive') + this%livecrootc_patch(begp:endp) = spval call hist_addfld1d (fname='LIVECROOTC', units='gC/m^2', & avgflag='A', long_name='live coarse root C', & @@ -941,7 +955,15 @@ subroutine InitCold(this, bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst this%leafc_patch(p) = 0._r8 this%leafc_storage_patch(p) = 0._r8 this%frootc_patch(p) = 0._r8 - this%frootc_storage_patch(p) = 0._r8 + this%frootc_storage_patch(p) = 0._r8 +! if (pftcon%perennial(patch%itype(p)) == 1._r8 .and. pftcon%woody(patch%itype(p)) == 1._r8) then +! this%leafc_patch(p) = 0._r8 +! this%leafc_storage_patch(p) = cnvegcstate_const%initial_vegC * ratio +! this%frootc_patch(p) = 0._r8 +! this%frootc_storage_patch(p) = cnvegcstate_const%initial_vegC * ratio +! this%deadstemc_soy_patch(p) = 0._r8 +! this%deadstemc_storage_soy_patch(p) = 0._r8 +! end if else this%leafc_patch(p) = 0._r8 this%leafc_storage_patch(p) = cnvegcstate_const%initial_vegC * ratio @@ -952,7 +974,6 @@ subroutine InitCold(this, bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst this%leafc_xfer_patch(p) = 0._r8 this%leafc_storage_xfer_acc_patch(p) = 0._r8 this%storage_cdemand_patch(p) = 0._r8 - if (MM_Nuptake_opt .eqv. .false.) then ! if not running in floating CN ratio option this%frootc_patch(p) = 0._r8 this%frootc_storage_patch(p) = 0._r8 @@ -964,7 +985,11 @@ subroutine InitCold(this, bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst this%livestemc_xfer_patch(p) = 0._r8 if (pftcon%woody(patch%itype(p)) == 1._r8) then - this%deadstemc_patch(p) = 0.1_r8 * ratio + if (patch%itype(p) < npcropmin)then ! (added by O.Dombrowski) + this%deadstemc_patch(p) = 0.1_r8 * ratio + else + this%deadstemc_patch(p) = 0._r8 ! (added by O.Dombrowski) + end if else this%deadstemc_patch(p) = 0._r8 end if @@ -1188,6 +1213,14 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%deadstemc_xfer_patch) + call restartvar(ncid=ncid, flag=flag, varname='deadstemc_soy', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemc_soy_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemc_storage_soy', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemc_storage_soy_patch) + call restartvar(ncid=ncid, flag=flag, varname='livecrootc', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%livecrootc_patch) @@ -1379,9 +1412,14 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, !----------------------------------------------- this%leafcmax_patch(i) = 0._r8 - + + if (lun%itype(l) == istcrop .and. pftcon%perennial(patch%itype(i)) == 1._r8) then + this%deadstemc_soy_patch(i) = 0._r8 + this%deadstemc_storage_soy_patch(i) = 0._r8 + end if l = patch%landunit(i) - if (lun%itype(l) == istsoil .or. patch%itype(i) == nc3crop .or. patch%itype(i) == nc3irrig)then + if (lun%itype(l) == istsoil .or. patch%itype(i) == nc3crop .or. patch%itype(i) == nc3irrig) then!.or. & +! (lun%itype(l) == istcrop .and. pftcon%perennial(patch%itype(i)) == 1._r8)) then ! (added by O.Dombrowski) if ( present(num_reseed_patch) ) then num_reseed_patch = num_reseed_patch + 1 filter_reseed_patch(num_reseed_patch) = i @@ -1420,9 +1458,11 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, this%livestemc_xfer_patch(i) = 0._r8 if (pftcon%woody(patch%itype(i)) == 1._r8) then - this%deadstemc_patch(i) = 0.1_r8 * ratio - else - this%deadstemc_patch(i) = 0._r8 + if (patch%itype(p) < npcropmin) then + this%deadstemc_patch(i) = 0.1_r8 * ratio + else + this%deadstemc_patch(i) = 0._r8 + end if end if this%deadstemc_storage_patch(i) = 0._r8 this%deadstemc_xfer_patch(i) = 0._r8 @@ -2367,6 +2407,8 @@ subroutine SetValues ( this, & this%deadstemc_patch(i) = value_patch this%deadstemc_storage_patch(i) = value_patch this%deadstemc_xfer_patch(i) = value_patch + this%deadstemc_soy_patch(i) = value_patch + this%deadstemc_storage_soy_patch(i) = value_patch this%livecrootc_patch(i) = value_patch this%livecrootc_storage_patch(i) = value_patch this%livecrootc_xfer_patch(i) = value_patch @@ -2480,7 +2522,6 @@ subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & this%deadstemc_patch(p) + & this%livecrootc_patch(p) + & this%deadcrootc_patch(p) - ! stored vegetation carbon, excluding cpool (STORVEGC) this%storvegc_patch(p) = & this%cpool_patch(p) + & @@ -2509,18 +2550,16 @@ subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & this%dispvegc_patch(p) + & this%grainc_patch(p) end if - + ! total vegetation carbon, excluding cpool (TOTVEGC) this%totvegc_patch(p) = & this%dispvegc_patch(p) + & this%storvegc_patch(p) - ! total patch-level carbon, including xsmrpool, ctrunc this%totc_patch(p) = & this%totvegc_patch(p) + & this%xsmrpool_patch(p) + & this%ctrunc_patch(p) - if (use_crop) then this%totc_patch(p) = this%totc_patch(p) + this%cropseedc_deficit_patch(p) + & this%xsmrpool_loss_patch(p) @@ -2563,7 +2602,6 @@ subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & soilbiogeochem_totlitc_col(c) + & soilbiogeochem_totsomc_col(c) + & soilbiogeochem_ctrunc_col(c) - end do end subroutine Summary_carbonstate diff --git a/src/clm5/biogeochem/CNVegComputeSeedMod.F90 b/src/clm5/biogeochem/CNVegComputeSeedMod.F90 index 01cf471e20..8ac2b175b2 100644 --- a/src/clm5/biogeochem/CNVegComputeSeedMod.F90 +++ b/src/clm5/biogeochem/CNVegComputeSeedMod.F90 @@ -9,7 +9,7 @@ module CNVegComputeSeedMod use shr_kind_mod , only : r8 => shr_kind_r8 use shr_log_mod , only : errMsg => shr_log_errMsg use decompMod , only : bounds_type - use pftconMod , only : pftcon, noveg + use pftconMod , only : pftcon, noveg, npcropmin use clm_varcon , only : c3_r2, c4_r2, c14ratio use clm_varctl , only : iulog use PatchType , only : patch @@ -133,7 +133,7 @@ subroutine ComputeSeedAmounts(bounds, & if (pft_type /= noveg) then my_leaf_seed = leafc_seed * & SpeciesTypeMultiplier(species, pft_type, COMPONENT_LEAF) - if (pftcon%woody(pft_type) == 1._r8) then + if (pftcon%woody(pft_type) == 1._r8 .and. patch%itype(p) < npcropmin) then my_deadstem_seed = deadstemc_seed * & SpeciesTypeMultiplier(species, pft_type, COMPONENT_DEADWOOD) end if diff --git a/src/clm5/biogeochem/CNVegNitrogenFluxType.F90 b/src/clm5/biogeochem/CNVegNitrogenFluxType.F90 index 47b620bf91..6277d80988 100644 --- a/src/clm5/biogeochem/CNVegNitrogenFluxType.F90 +++ b/src/clm5/biogeochem/CNVegNitrogenFluxType.F90 @@ -137,6 +137,10 @@ module CNVegNitrogenFluxType real(r8), pointer :: frootn_to_retransn_patch (:) ! patch fine root N to retranslocated N pool (gN/m2/s) real(r8), pointer :: frootn_to_litter_patch (:) ! patch fine root N litterfall (gN/m2/s) + ! pruning fluxes + real(r8), pointer :: prunen_to_litter_patch (:) ! patch pruning N to litter (gN/m2/s) + real(r8), pointer :: prunen_storage_to_litter_patch (:) ! patch pruning N to litter (gN/m2/s) + ! allocation fluxes real(r8), pointer :: retransn_to_npool_patch (:) ! patch deployment of retranslocated N (gN/m2/s) real(r8), pointer :: free_retransn_to_npool_patch (:) ! patch deployment of free retranslocated N (gN/m2/s) @@ -206,7 +210,9 @@ module CNVegNitrogenFluxType ! crop fluxes real(r8), pointer :: crop_seedn_to_leaf_patch (:) ! patch (gN/m2/s) seed source to leaf, for crops - + real(r8), pointer :: crop_seedn_to_froot_patch (:) ! patch (gN/m2/s) seed source to fine root, for perennial crops (added by O.Dombrowski) + real(r8), pointer :: crop_seedn_to_deadstem_patch (:) ! patch (gN/m2/s) seed source to deadstem, for perennial crops (added by O.Dombrowski) + ! Misc real(r8), pointer :: plant_ndemand_patch (:) ! N flux required to support initial GPP (gN/m2/s) real(r8), pointer :: avail_retransn_patch (:) ! N flux available from retranslocation pool (gN/m2/s) @@ -419,6 +425,8 @@ subroutine InitAllocate(this, bounds) allocate(this%fert_patch (begp:endp)) ; this%fert_patch (:) = nan allocate(this%fert_counter_patch (begp:endp)) ; this%fert_counter_patch (:) = nan allocate(this%soyfixn_patch (begp:endp)) ; this%soyfixn_patch (:) = nan + allocate(this%prunen_to_litter_patch (begp:endp)) ; this%prunen_to_litter_patch (:) = nan + allocate(this%prunen_storage_to_litter_patch (begp:endp)) ; this%prunen_storage_to_litter_patch (:) = nan allocate(this%grainn_to_cropprodn_patch (begp:endp)) ; this%grainn_to_cropprodn_patch (:) = nan allocate(this%grainn_to_cropprodn_col (begc:endc)) ; this%grainn_to_cropprodn_col (:) = nan @@ -447,7 +455,9 @@ subroutine InitAllocate(this, bounds) allocate(this%dwt_deadcrootn_to_cwdn_col (begc:endc,1:nlevdecomp_full)) ; this%dwt_deadcrootn_to_cwdn_col (:,:) = nan allocate(this%crop_seedn_to_leaf_patch (begp:endp)) ; this%crop_seedn_to_leaf_patch (:) = nan - + allocate(this%crop_seedn_to_froot_patch (begp:endp)) ; this%crop_seedn_to_froot_patch (:) = nan + allocate(this%crop_seedn_to_deadstem_patch (begp:endp)) ; this%crop_seedn_to_deadstem_patch (:) = nan + allocate(this%m_decomp_npools_to_fire_vr_col (begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) allocate(this%m_decomp_npools_to_fire_col (begc:endc,1:ndecomp_pools )) @@ -1063,6 +1073,16 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='crop seed source to leaf', & ptr_patch=this%crop_seedn_to_leaf_patch, default='inactive') + this%crop_seedn_to_froot_patch(begp:endp) = spval + call hist_addfld1d (fname='CROP_SEEDN_TO_FROOT', units='gN/m^2/s', & + avgflag='A', long_name='crop seed source to fine root', & + ptr_patch=this%crop_seedn_to_froot_patch, default='inactive') + + this%crop_seedn_to_deadstem_patch(begp:endp) = spval + call hist_addfld1d (fname='CROP_SEEDN_TO_DEADSTEM', units='gN/m^2/s', & + avgflag='A', long_name='crop seed source to deadstem', & + ptr_patch=this%crop_seedn_to_deadstem_patch, default='inactive') + this%plant_ndemand_patch(begp:endp) = spval call hist_addfld1d (fname='PLANT_NDEMAND', units='gN/m^2/s', & avgflag='A', long_name='N flux required to support initial GPP', & @@ -1392,6 +1412,18 @@ subroutine Restart (this, bounds, ncid, flag ) interpinic_flag='interp', readvar=readvar, data=this%grainn_storage_to_xfer_patch) end if + if (use_crop) then + call restartvar(ncid=ncid, flag=flag, varname='prunen_to_litter', xtype=ncd_double, & + dim1name='pft', & + long_name='pruning N to litterfall', units='gN/m2/s', & + interpinic_flag='interp', readvar=readvar, data=this%prunen_to_litter_patch) + + call restartvar(ncid=ncid, flag=flag, varname='prunen_storage_to_litter', xtype=ncd_double, & + dim1name='pft', & + long_name='pruning storage N to litterfall', units='gN/m2/s', & + interpinic_flag='interp', readvar=readvar, data=this%prunen_storage_to_litter_patch) + end if + call restartvar(ncid=ncid, flag=flag, varname='plant_ndemand', xtype=ncd_double, & dim1name='pft', & long_name='', units='', & @@ -1682,6 +1714,8 @@ subroutine SetValues ( this, & this%fire_nloss_patch(i) = value_patch this%crop_seedn_to_leaf_patch(i) = value_patch + this%crop_seedn_to_froot_patch(i) = value_patch + this%crop_seedn_to_deadstem_patch(i) = value_patch this%grainn_to_cropprodn_patch(i) = value_patch end do @@ -1697,6 +1731,9 @@ subroutine SetValues ( this, & this%grainn_storage_to_xfer_patch(i) = value_patch this%soyfixn_patch(i) = value_patch this%frootn_to_retransn_patch(i) = value_patch + this%prunen_to_litter_patch(i) = value_patch + this%prunen_storage_to_litter_patch(i) = value_patch + end do end if diff --git a/src/clm5/biogeochem/CNVegNitrogenStateType.F90 b/src/clm5/biogeochem/CNVegNitrogenStateType.F90 index 97a5ffaae4..6d2b4d3c90 100644 --- a/src/clm5/biogeochem/CNVegNitrogenStateType.F90 +++ b/src/clm5/biogeochem/CNVegNitrogenStateType.F90 @@ -51,6 +51,8 @@ module CNVegNitrogenStateType real(r8), pointer :: deadstemn_patch (:) ! (gN/m2) dead stem N real(r8), pointer :: deadstemn_storage_patch (:) ! (gN/m2) dead stem N storage real(r8), pointer :: deadstemn_xfer_patch (:) ! (gN/m2) dead stem N transfer + real(r8), pointer :: deadstemn_soy_patch (:) ! (gN/m2) dead stem N at the start of season + real(r8), pointer :: deadstemn_storage_soy_patch (:) ! (gN/m2) dead stem N at the start of season real(r8), pointer :: livecrootn_patch (:) ! (gN/m2) live coarse root N real(r8), pointer :: livecrootn_storage_patch (:) ! (gN/m2) live coarse root N storage real(r8), pointer :: livecrootn_xfer_patch (:) ! (gN/m2) live coarse root N transfer @@ -147,6 +149,8 @@ subroutine InitAllocate(this, bounds) allocate(this%deadstemn_patch (begp:endp)) ; this%deadstemn_patch (:) = nan allocate(this%deadstemn_storage_patch (begp:endp)) ; this%deadstemn_storage_patch (:) = nan allocate(this%deadstemn_xfer_patch (begp:endp)) ; this%deadstemn_xfer_patch (:) = nan + allocate(this%deadstemn_soy_patch (begp:endp)) ; this%deadstemn_soy_patch (:) = nan + allocate(this%deadstemn_storage_soy_patch (begp:endp)) ; this%deadstemn_storage_soy_patch (:) = nan allocate(this%livecrootn_patch (begp:endp)) ; this%livecrootn_patch (:) = nan allocate(this%livecrootn_storage_patch (begp:endp)) ; this%livecrootn_storage_patch (:) = nan allocate(this%livecrootn_xfer_patch (begp:endp)) ; this%livecrootn_xfer_patch (:) = nan @@ -283,6 +287,16 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='dead stem N transfer', & ptr_patch=this%deadstemn_xfer_patch, default='inactive') + this%deadstemn_soy_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADSTEMN_SOY', units='gN/m^2', & + avgflag='A', long_name='dead stem N at start of year', & + ptr_patch=this%deadstemn_soy_patch, default='inactive') + + this%deadstemn_storage_soy_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADSTEMN_STORAGE_SOY', units='gN/m^2', & + avgflag='A', long_name='dead stem N storage at start of year', & + ptr_patch=this%deadstemn_storage_soy_patch, default='inactive') + this%livecrootn_patch(begp:endp) = spval call hist_addfld1d (fname='LIVECROOTN', units='gN/m^2', & avgflag='A', long_name='live coarse root N', & @@ -471,13 +485,19 @@ subroutine InitCold(this, bounds, & ! roughness length is not zero in canopy flux calculation if (pftcon%woody(patch%itype(p)) == 1._r8) then - this%deadstemn_patch(p) = deadstemc_patch(p) / pftcon%deadwdcn(patch%itype(p)) + if (patch%itype(p) < npcropmin) then + this%deadstemn_patch(p) = deadstemc_patch(p) / pftcon%deadwdcn(patch%itype(p)) + else + this%deadstemn_patch(p) = 0._r8 + end if else this%deadstemn_patch(p) = 0._r8 end if this%deadstemn_storage_patch(p) = 0._r8 this%deadstemn_xfer_patch(p) = 0._r8 + this%deadstemn_soy_patch(p) = 0._r8 + this%deadstemn_storage_soy_patch(p) = 0._r8 this%livecrootn_patch(p) = 0._r8 this%livecrootn_storage_patch(p) = 0._r8 this%livecrootn_xfer_patch(p) = 0._r8 @@ -630,6 +650,14 @@ subroutine Restart ( this, bounds, ncid, flag, leafc_patch, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%deadstemn_xfer_patch) + call restartvar(ncid=ncid, flag=flag, varname='deadstemn_soy', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemn_soy_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemn_storage_soy', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemn_storage_soy_patch) + call restartvar(ncid=ncid, flag=flag, varname='livecrootn', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%livecrootn_patch) @@ -781,13 +809,19 @@ subroutine Restart ( this, bounds, ncid, flag, leafc_patch, & ! roughness length is not zero in canopy flux calculation if (pftcon%woody(patch%itype(p)) == 1._r8) then - this%deadstemn_patch(p) = deadstemc_patch(p) / pftcon%deadwdcn(patch%itype(p)) + if (patch%itype(p) < npcropmin) then + this%deadstemn_patch(p) = deadstemc_patch(p) / pftcon%deadwdcn(patch%itype(p)) + else + this%deadstemn_patch(p) = 0._r8 + end if else this%deadstemn_patch(p) = 0._r8 end if this%deadstemn_storage_patch(p) = 0._r8 this%deadstemn_xfer_patch(p) = 0._r8 + this%deadstemn_soy_patch(p) = 0._r8 + this%deadstemn_storage_soy_patch(p) = 0._r8 this%livecrootn_patch(p) = 0._r8 this%livecrootn_storage_patch(p) = 0._r8 this%livecrootn_xfer_patch(p) = 0._r8 @@ -876,6 +910,8 @@ subroutine SetValues ( this, & this%deadstemn_patch(i) = value_patch this%deadstemn_storage_patch(i) = value_patch this%deadstemn_xfer_patch(i) = value_patch + this%deadstemn_soy_patch(i) = value_patch + this%deadstemn_storage_soy_patch(i) = value_patch this%livecrootn_patch(i) = value_patch this%livecrootn_storage_patch(i) = value_patch this%livecrootn_xfer_patch(i) = value_patch diff --git a/src/clm5/biogeochem/CNVegStateType.F90 b/src/clm5/biogeochem/CNVegStateType.F90 index afdfa190aa..2c4f9b5576 100644 --- a/src/clm5/biogeochem/CNVegStateType.F90 +++ b/src/clm5/biogeochem/CNVegStateType.F90 @@ -35,9 +35,15 @@ module CNVegStateType real(r8) , pointer :: cumvd_patch (:) ! patch cumulative vernalization d?ependence? real(r8) , pointer :: gddmaturity_patch (:) ! patch growing degree days (gdd) needed to harvest (ddays) real(r8) , pointer :: huileaf_patch (:) ! patch heat unit index needed from planting to leaf emergence - real(r8) , pointer :: huigrain_patch (:) ! patch heat unit index needed to reach vegetative maturity + real(r8) , pointer :: huigrain_patch (:) ! patch heat unit index needed to reach vegetative maturity/to start fruit fill for perennial crops + real(r8) , pointer :: huilfmat_patch (:) ! patch heat unit index needed to reach canopy maturity (added by O.Dombrowski) + real(r8) , pointer :: huiripe_patch (:) ! patch heat unit index needed to reach fruit cell expansion (ripening) (added by O.Dombrowski) real(r8) , pointer :: aleafi_patch (:) ! patch saved leaf allocation coefficient from phase 2 real(r8) , pointer :: astemi_patch (:) ! patch saved stem allocation coefficient from phase 2 + real(r8) , pointer :: arooti2_patch (:) ! patch saved root allocation coefficient from phase 2 + real(r8) , pointer :: arooti3_patch (:) ! patch saved root allocation coefficient from phase 3 + real(r8) , pointer :: aleafi3_patch (:) ! patch saved leaf allocation coefficient from phase 3 + real(r8) , pointer :: aleaf_patch (:) ! patch leaf allocation coefficient real(r8) , pointer :: astem_patch (:) ! patch stem allocation coefficient real(r8) , pointer :: htmx_patch (:) ! patch max hgt attained by a crop during yr (m) @@ -85,6 +91,7 @@ module CNVegStateType real(r8), pointer :: onset_gdd_patch (:) ! patch onset growing degree days real(r8), pointer :: onset_swi_patch (:) ! patch onset soil water index real(r8), pointer :: offset_flag_patch (:) ! patch offset flag + real(r8), pointer :: offset2_flag_patch (:) ! patch orchard rotation flag real(r8), pointer :: offset_counter_patch (:) ! patch offset days counter real(r8), pointer :: offset_fdd_patch (:) ! patch offset freezing degree days counter real(r8), pointer :: offset_swi_patch (:) ! patch offset soil water index @@ -95,6 +102,13 @@ module CNVegStateType real(r8), pointer :: c_allometry_patch (:) ! patch C allocation index (DIM) real(r8), pointer :: n_allometry_patch (:) ! patch N allocation index (DIM) + real(r8), pointer :: chill_day_patch (:) ! patch chill days requirements for fruit tree crops + real(r8), pointer :: anti_chill_day_patch (:) ! patch anti-chill days requirements for fruit tree crops + real(r8), pointer :: chill_flag_patch (:) ! patch chill requirements flag for fruit tree crops + + real(r8), pointer :: harvest_flag_patch (:) ! patch harvest flag (added by O.Dombrowski) + real(r8), pointer :: prune_flag_patch (:) ! patch pruning flag (added by O.Dombrowski) + real(r8), pointer :: storage_flag_patch (:) ! patch storage growth flag (added by O.Dombrowski) real(r8), pointer :: tempsum_potential_gpp_patch (:) ! patch temporary annual sum of potential GPP real(r8), pointer :: annsum_potential_gpp_patch (:) ! patch annual sum of potential GPP real(r8), pointer :: tempmax_retransn_patch (:) ! patch temporary annual max of retranslocated N pool (gN/m2) @@ -201,7 +215,12 @@ subroutine InitAllocate(this, bounds) allocate(this%gddmaturity_patch (begp:endp)) ; this%gddmaturity_patch (:) = spval allocate(this%huileaf_patch (begp:endp)) ; this%huileaf_patch (:) = nan allocate(this%huigrain_patch (begp:endp)) ; this%huigrain_patch (:) = 0.0_r8 + allocate(this%huilfmat_patch (begp:endp)) ; this%huilfmat_patch (:) = 0.0_r8 + allocate(this%huiripe_patch (begp:endp)) ; this%huiripe_patch (:) = 0.0_r8 allocate(this%aleafi_patch (begp:endp)) ; this%aleafi_patch (:) = nan + allocate(this%arooti2_patch (begp:endp)) ; this%arooti2_patch (:) = nan + allocate(this%arooti3_patch (begp:endp)) ; this%arooti3_patch (:) = nan + allocate(this%aleafi3_patch (begp:endp)) ; this%aleafi3_patch (:) = nan allocate(this%astemi_patch (begp:endp)) ; this%astemi_patch (:) = nan allocate(this%aleaf_patch (begp:endp)) ; this%aleaf_patch (:) = nan allocate(this%astem_patch (begp:endp)) ; this%astem_patch (:) = nan @@ -249,6 +268,7 @@ subroutine InitAllocate(this, bounds) allocate(this%onset_gdd_patch (begp:endp)) ; this%onset_gdd_patch (:) = nan allocate(this%onset_swi_patch (begp:endp)) ; this%onset_swi_patch (:) = nan allocate(this%offset_flag_patch (begp:endp)) ; this%offset_flag_patch (:) = nan + allocate(this%offset2_flag_patch (begp:endp)) ; this%offset2_flag_patch (:) = nan allocate(this%offset_counter_patch (begp:endp)) ; this%offset_counter_patch (:) = nan allocate(this%offset_fdd_patch (begp:endp)) ; this%offset_fdd_patch (:) = nan allocate(this%offset_swi_patch (begp:endp)) ; this%offset_swi_patch (:) = nan @@ -258,6 +278,14 @@ subroutine InitAllocate(this, bounds) allocate(this%bgtr_patch (begp:endp)) ; this%bgtr_patch (:) = nan allocate(this%c_allometry_patch (begp:endp)) ; this%c_allometry_patch (:) = nan allocate(this%n_allometry_patch (begp:endp)) ; this%n_allometry_patch (:) = nan + allocate(this%chill_day_patch (begp:endp)) ; this%chill_day_patch (:) = nan + allocate(this%anti_chill_day_patch (begp:endp)) ; this%anti_chill_day_patch (:) = nan + allocate(this%chill_flag_patch (begp:endp)) ; this%chill_flag_patch (:) = nan + + + allocate(this%harvest_flag_patch (begp:endp)) ; this%harvest_flag_patch (:) = nan + allocate(this%prune_flag_patch (begp:endp)) ; this%prune_flag_patch (:) = nan + allocate(this%storage_flag_patch (begp:endp)) ; this%storage_flag_patch (:) = nan allocate(this%tempsum_potential_gpp_patch (begp:endp)) ; this%tempsum_potential_gpp_patch (:) = nan allocate(this%annsum_potential_gpp_patch (begp:endp)) ; this%annsum_potential_gpp_patch (:) = nan allocate(this%tempmax_retransn_patch (begp:endp)) ; this%tempmax_retransn_patch (:) = nan @@ -321,17 +349,17 @@ subroutine InitHistory(this, bounds) ptr_col=this%nfire_col) this%farea_burned_col(begc:endc) = spval - call hist_addfld1d (fname='FAREA_BURNED', units='s-1', & + call hist_addfld1d (fname='FAREA_BURNED', units='proportion/sec', & avgflag='A', long_name='timestep fractional area burned', & ptr_col=this%farea_burned_col) this%baf_crop_col(begc:endc) = spval - call hist_addfld1d (fname='BAF_CROP', units='s-1', & + call hist_addfld1d (fname='BAF_CROP', units='proportion/sec', & avgflag='A', long_name='fractional area burned for crop', & ptr_col=this%baf_crop_col) this%baf_peatf_col(begc:endc) = spval - call hist_addfld1d (fname='BAF_PEATF', units='s-1', & + call hist_addfld1d (fname='BAF_PEATF', units='proportion/sec', & avgflag='A', long_name='fractional area burned in peatland', & ptr_col=this%baf_peatf_col) @@ -390,6 +418,11 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='offset flag', & ptr_patch=this%offset_flag_patch, default='inactive') + this%offset2_flag_patch(begp:endp) = spval + call hist_addfld1d (fname='OFFSET2_FLAG', units='none', & + avgflag='A', long_name='orchard rotation flag', & + ptr_patch=this%offset2_flag_patch, default='inactive') + this%offset_counter_patch(begp:endp) = spval call hist_addfld1d (fname='OFFSET_COUNTER', units='days', & avgflag='A', long_name='offset days counter', & @@ -430,6 +463,31 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='N allocation index', & ptr_patch=this%n_allometry_patch, default='inactive') + this%chill_day_patch(begp:endp) = spval + call hist_addfld1d (fname='CHILL_DAY', units='days', & + avgflag='A', long_name='Chill days needed for bud break of fruit tree crops', & + ptr_patch=this%chill_day_patch, default='inactive') + + this%anti_chill_day_patch(begp:endp) = spval + call hist_addfld1d (fname='ANTI_CHILL_DAY', units='days', & + avgflag='A', long_name='Anti-chill days needed for bud break of fruit tree crops', & + ptr_patch=this%anti_chill_day_patch, default='inactive') + + this%chill_flag_patch(begp:endp) = spval + call hist_addfld1d (fname='CHILL_FLAG', units='none', & + avgflag='A', long_name='Chill requirements flag for bud break of fruit tree crops', & + ptr_patch=this%chill_flag_patch, default='inactive') + + this%harvest_flag_patch(begp:endp) = spval + call hist_addfld1d (fname='HARVEST_FLAG', units='none', & + avgflag='A', long_name='harvest flag (perennial crops)', & + ptr_patch=this%harvest_flag_patch, default='inactive') + + this%storage_flag_patch(begp:endp) = spval + call hist_addfld1d (fname='STORAGE_FLAG', units='none', & + avgflag='A', long_name='storage growth flag (perennial crops)', & + ptr_patch=this%storage_flag_patch, default='inactive') + this%tempsum_potential_gpp_patch(begp:endp) = spval call hist_addfld1d (fname='TEMPSUM_POTENTIAL_GPP', units='gC/m^2/yr', & avgflag='A', long_name='temporary annual sum of potential GPP', & @@ -464,6 +522,28 @@ subroutine InitHistory(this, bounds) call hist_addfld1d (fname='PLANTCN', units='unitless', & avgflag='A', long_name='Plant C:N used by FUN', & ptr_patch=this%plantCN_patch, default='inactive') + + this%aleaf_patch(begp:endp) = spval + call hist_addfld1d (fname='A_LEAF', units='unitless', & + avgflag='A', long_name='Leaf allocation coefficient', & + ptr_patch=this%aleaf_patch, default='inactive') + +! this%arepr_patch(begp:endp) = spval +! call hist_addfld1d (fname='A_REPR', units='unitless', & +! avgflag='A', long_name='Fruit allocation coefficient', & +! ptr_patch=this%arepr_patch, default='inactive') + + this%astem_patch(begp:endp) = spval + call hist_addfld1d (fname='A_STEM', units='unitless', & + avgflag='A', long_name='Stem allocation coefficient', & + ptr_patch=this%astem_patch, default='inactive') + +! this%aroot_patch(begp:endp) = spval +! call hist_addfld1d (fname='A_ROOT', units='unitless', & +! avgflag='A', long_name='Root allocation coefficient', & +! ptr_patch=this%aroot_patch, default='inactive') + + end subroutine InitHistory !----------------------------------------------------------------------- @@ -607,6 +687,7 @@ subroutine initCold(this, bounds) this%onset_gdd_patch(p) = spval this%onset_swi_patch(p) = spval this%offset_flag_patch(p) = spval + this%offset2_flag_patch(p) = spval this%offset_counter_patch(p) = spval this%offset_fdd_patch(p) = spval this%offset_swi_patch(p) = spval @@ -616,6 +697,12 @@ subroutine initCold(this, bounds) this%bgtr_patch(p) = spval this%c_allometry_patch(p) = spval this%n_allometry_patch(p) = spval + this%chill_day_patch(p) = spval + this%anti_chill_day_patch(p) = spval + this%chill_flag_patch(p) = spval + this%harvest_flag_patch(p) = spval + this%prune_flag_patch(p) = spval + this%storage_flag_patch(p) = spval this%tempsum_potential_gpp_patch(p) = spval this%annsum_potential_gpp_patch(p) = spval this%tempmax_retransn_patch(p) = spval @@ -636,12 +723,19 @@ subroutine initCold(this, bounds) this%onset_gdd_patch(p) = 0._r8 this%onset_swi_patch(p) = 0._r8 this%offset_flag_patch(p) = 0._r8 + this%offset2_flag_patch(p) = 0._r8 this%offset_counter_patch(p) = 0._r8 this%offset_fdd_patch(p) = 0._r8 this%offset_swi_patch(p) = 0._r8 this%lgsf_patch(p) = 0._r8 this%bglfr_patch(p) = 0._r8 this%bgtr_patch(p) = 0._r8 + this%chill_day_patch(p) = 0._r8 + this%anti_chill_day_patch(p) = 0._r8 + this%chill_flag_patch(p) = 0._r8 + this%harvest_flag_patch(p) = 0._r8 + this%prune_flag_patch(p) = 0._r8 + this%storage_flag_patch(p) = 0._r8 this%annavg_t2m_patch(p) = 280._r8 this%tempavg_t2m_patch(p) = 0._r8 this%grain_flag_patch(p) = 0._r8 @@ -746,6 +840,11 @@ subroutine Restart(this, bounds, ncid, flag, cnveg_carbonstate, & long_name='offset flag', units='unitless' , & interpinic_flag='interp', readvar=readvar, data=this%offset_flag_patch) + call restartvar(ncid=ncid, flag=flag, varname='offset2_flag', xtype=ncd_double, & + dim1name='pft', & + long_name='orchard rotation flag', units='unitless' , & + interpinic_flag='interp', readvar=readvar, data=this%offset2_flag_patch) + call restartvar(ncid=ncid, flag=flag, varname='offset_counter', xtype=ncd_double, & dim1name='pft', & long_name='offset days counter', units='sec' , & @@ -875,6 +974,18 @@ subroutine Restart(this, bounds, ncid, flag, cnveg_carbonstate, & dim1name='pft', long_name='Saved leaf allocation coefficient from phase 2', units='', & interpinic_flag='interp', readvar=readvar, data=this%aleafi_patch) + call restartvar(ncid=ncid, flag=flag, varname='arooti2', xtype=ncd_double, & + dim1name='pft', long_name='Saved root allocation coefficient from phase 2', units='', & + interpinic_flag='interp', readvar=readvar, data=this%arooti2_patch) + + call restartvar(ncid=ncid, flag=flag, varname='arooti3', xtype=ncd_double, & + dim1name='pft', long_name='Saved root allocation coefficient from phase 3', units='', & + interpinic_flag='interp', readvar=readvar, data=this%arooti3_patch) + + call restartvar(ncid=ncid, flag=flag, varname='aleafi3', xtype=ncd_double, & + dim1name='pft', long_name='Saved leaf allocation coefficient from phase 3', units='', & + interpinic_flag='interp', readvar=readvar, data=this%aleafi3_patch) + call restartvar(ncid=ncid, flag=flag, varname='astem', xtype=ncd_double, & dim1name='pft', long_name='stem allocation coefficient', units='', & interpinic_flag='interp', readvar=readvar, data=this%astem_patch) @@ -903,9 +1014,44 @@ subroutine Restart(this, bounds, ncid, flag, cnveg_carbonstate, & dim1name='pft', long_name='heat unit index needed to reach vegetative maturity', units='', & interpinic_flag='interp', readvar=readvar, data=this%huigrain_patch) + call restartvar(ncid=ncid, flag=flag, varname='huilfmat', xtype=ncd_double, & + dim1name='pft', long_name='heat unit index needed to reach canopy maturity', units='', & + interpinic_flag='interp', readvar=readvar, data=this%huilfmat_patch) + + call restartvar(ncid=ncid, flag=flag, varname='huiripe', xtype=ncd_double, & + dim1name='pft', long_name='heat unit index needed to reach fruit cell expansion', units='', & + interpinic_flag='interp', readvar=readvar, data=this%huiripe_patch) + call restartvar(ncid=ncid, flag=flag, varname='grain_flag', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%grain_flag_patch) + + call restartvar(ncid=ncid, flag=flag, varname='chill_day', xtype=ncd_double, & + dim1name='pft', long_name='', units='days', & + interpinic_flag='interp', readvar=readvar, data=this%chill_day_patch) + + call restartvar(ncid=ncid, flag=flag, varname='anti_chill_day', xtype=ncd_double, & + dim1name='pft', long_name='', units='days', & + interpinic_flag='interp', readvar=readvar, data=this%anti_chill_day_patch) + + call restartvar(ncid=ncid, flag=flag, varname='chill_flag', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%chill_flag_patch) + + call restartvar(ncid=ncid, flag=flag, varname='harvest_flag', xtype=ncd_double, & + dim1name='pft', long_name='harvest flag (perennial crops)', units='unitless', & + interpinic_flag='interp', readvar=readvar, data=this%harvest_flag_patch) + + call restartvar(ncid=ncid, flag=flag, varname='prune_flag', xtype=ncd_double, & + dim1name='pft', long_name='pruning flag for perenneial crops', units='unitless', & + interpinic_flag='interp', readvar=readvar, data=this%prune_flag_patch) + + call restartvar(ncid=ncid, flag=flag, varname='storage_flag', xtype=ncd_double, & + dim1name='pft', long_name='storage growth flag for perenneial crops', units='unitless', & + interpinic_flag='interp', readvar=readvar, data=this%storage_flag_patch) + + + end if if ( flag == 'read' .and. num_reseed_patch > 0 )then if ( masterproc ) write(iulog, *) 'Reseed dead plants for CNVegState' @@ -921,6 +1067,7 @@ subroutine Restart(this, bounds, ncid, flag, cnveg_carbonstate, & this%onset_gdd_patch(p) = 0._r8 this%onset_swi_patch(p) = 0._r8 this%offset_flag_patch(p) = 0._r8 + this%offset2_flag_patch(p) = 0._r8 this%offset_counter_patch(p) = 0._r8 this%offset_fdd_patch(p) = 0._r8 this%offset_swi_patch(p) = 0._r8 @@ -930,7 +1077,12 @@ subroutine Restart(this, bounds, ncid, flag, cnveg_carbonstate, & this%annavg_t2m_patch(p) = 280._r8 this%tempavg_t2m_patch(p) = 0._r8 this%grain_flag_patch(p) = 0._r8 - + this%harvest_flag_patch(p) = 0._r8 + this%prune_flag_patch(p) = 0._r8 + this%storage_flag_patch(p) = 0._r8 + this%chill_day_patch(p) = 0._r8 + this%anti_chill_day_patch(p) = 0._r8 + this%chill_flag_patch(p) = 0._r8 this%c_allometry_patch(p) = 0._r8 this%n_allometry_patch(p) = 0._r8 this%tempsum_potential_gpp_patch(p) = 0._r8 diff --git a/src/clm5/biogeochem/CNVegStructUpdateMod.F90 b/src/clm5/biogeochem/CNVegStructUpdateMod.F90 index 27b677b04d..fd6c2acfec 100644 --- a/src/clm5/biogeochem/CNVegStructUpdateMod.F90 +++ b/src/clm5/biogeochem/CNVegStructUpdateMod.F90 @@ -63,7 +63,6 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & ! !LOCAL VARIABLES: integer :: p,c,g ! indices integer :: fp ! lake filter indices - real(r8) :: taper ! ratio of height:radius_breast_height (tree allometry) real(r8) :: stocking ! #stems / ha (stocking density) real(r8) :: ol ! thickness of canopy layer covered by snow (m) real(r8) :: fb ! fraction of canopy layer covered by snow @@ -90,6 +89,7 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop types slatop => pftcon%slatop , & ! Input: specific leaf area at top of canopy, projected area basis [m^2/gC] dsladlai => pftcon%dsladlai , & ! Input: dSLA/dLAI, projected area basis [m^2/gC] z0mr => pftcon%z0mr , & ! Input: ratio of momentum roughness length to canopy top height (-) @@ -97,7 +97,9 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & dwood => pftcon%dwood , & ! Input: density of wood (gC/m^3) ztopmx => pftcon%ztopmx , & ! Input: laimx => pftcon%laimx , & ! Input: - + nstem => pftcon%nstem , & ! Input: Tree number density (#ind/m2) (introduced by E.Kluzek (2020, unreleased code) and adopted here by O.Dombrowski) + taper => pftcon%taper , & ! Input: ratio of height:radius_breast_height (tree allometry) (introduced by E.Kluzek (2020, unreleased code) and adopted here by O.Dombrowski) + allom2 => dgv_ecophyscon%allom2 , & ! Input: [real(r8) (:) ] ecophys const allom3 => dgv_ecophyscon%allom3 , & ! Input: [real(r8) (:) ] ecophys const @@ -114,7 +116,7 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & farea_burned => cnveg_state_inst%farea_burned_col , & ! Input: [real(r8) (:) ] F. Li and S. Levis htmx => cnveg_state_inst%htmx_patch , & ! Output: [real(r8) (:) ] max hgt attained by a crop during yr (m) peaklai => cnveg_state_inst%peaklai_patch , & ! Output: [integer (:) ] 1: max allowed lai; 0: not at max - + dormant_flag => cnveg_state_inst%dormant_flag_patch , & ! Output: [real(r8) (:) ] dormancy flag harvdate => crop_inst%harvdate_patch , & ! Input: [integer (:) ] harvest date ! *** Key Output from CN*** @@ -129,13 +131,6 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & dt = real( get_rad_step_size(), r8 ) - ! constant allometric parameters - taper = 200._r8 - stocking = 1000._r8 - - ! convert from stems/ha -> stems/m^2 - stocking = stocking / 10000._r8 - ! patch loop do fp = 1,num_soilp p = filter_soilp(fp) @@ -177,25 +172,23 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & if (woody(ivt(p)) == 1._r8) then - ! trees and shrubs - - ! if shrubs have a squat taper - if (ivt(p) >= nbrdlf_evr_shrub .and. ivt(p) <= nbrdlf_dcd_brl_shrub) then - taper = 10._r8 - ! otherwise have a tall taper - else - taper = 200._r8 + if (perennial(ivt(p)) == 1._r8) then + if (dormant_flag(p) == 0._r8) then + if (tlai(p) >= laimx(ivt(p))) peaklai(p) = 1 + else if (dormant_flag(p) == 1._r8) then + peaklai(p) = 0 + end if end if - ! trees and shrubs for now have a very simple allometry, with hard-wired - ! stem taper (height:radius) and hard-wired stocking density (#individuals/area) + ! trees and shrubs for now have a very simple allometry, with + ! stem taper (height:radius) and nstem from PFT parameter file if (use_cndv) then if (fpcgrid(p) > 0._r8 .and. nind(p) > 0._r8) then stocking = nind(p)/fpcgrid(p) !#ind/m2 nat veg area -> #ind/m2 patch area htop(p) = allom2(ivt(p)) * ( (24._r8 * deadstemc(p) / & - (SHR_CONST_PI * stocking * dwood(ivt(p)) * taper))**(1._r8/3._r8) )**allom3(ivt(p)) ! lpj's htop w/ cn's stemdiam + (SHR_CONST_PI * stocking * dwood(ivt(p)) * taper(ivt(p))))**(1._r8/3._r8) )**allom3(ivt(p)) ! lpj's htop w/ cn's stemdiam else htop(p) = 0._r8 @@ -203,12 +196,20 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & else !correct height calculation if doing accelerated spinup - if (spinup_state == 2) then - htop(p) = ((3._r8 * deadstemc(p) * 10._r8 * taper * taper)/ & - (SHR_CONST_PI * stocking * dwood(ivt(p))))**(1._r8/3._r8) + if (spinup_state == 2) then + if (perennial(ivt(p)) == 1._r8 .and. dormant_flag(p) == 1._r8 .and. deadstemc(p)== 0._r8) then + htop(p) = 0.01_r8 + else + htop(p) = ((3._r8 * deadstemc(p) * 10._r8 * taper(ivt(p)) * taper(ivt(p)))/ & + (SHR_CONST_PI * nstem(ivt(p)) * dwood(ivt(p))))**(1._r8/3._r8) + end if else - htop(p) = ((3._r8 * deadstemc(p) * taper * taper)/ & - (SHR_CONST_PI * stocking * dwood(ivt(p))))**(1._r8/3._r8) + if (perennial(ivt(p)) == 1._r8 .and. dormant_flag(p) == 1._r8 .and. deadstemc(p)== 0._r8) then + htop(p) = 0.01_r8 + else + htop(p) = ((3._r8 * deadstemc(p) * taper(ivt(p)) * taper(ivt(p)))/ & + (SHR_CONST_PI * nstem(ivt(p)) * dwood(ivt(p))))**(1._r8/3._r8) + end if end if endif @@ -217,12 +218,15 @@ subroutine CNVegStructUpdate(num_soilp, filter_soilp, & ! Adding test to keep htop from getting too close to forcing height for windspeed ! Also added for grass, below, although it is not likely to ever be an issue. htop(p) = min(htop(p),(forc_hgt_u_patch(p)/(displar(ivt(p))+z0mr(ivt(p))))-3._r8) - ! Peter Thornton, 8/11/2004 ! Adding constraint to keep htop from going to 0.0. ! This becomes an issue when fire mortality is pushing deadstemc ! to 0.0. htop(p) = max(htop(p), 0.01_r8) + ! for fruit trees restrict height to maximum pruned tree height + if (perennial(ivt(p)) == 1._r8) then + htop(p) = min(htop(p), ztopmx(ivt(p))) + end if hbot(p) = max(0._r8, min(3._r8, htop(p)-1._r8)) diff --git a/src/clm5/biogeochem/CropType.F90 b/src/clm5/biogeochem/CropType.F90 index 0b2c0fc1db..1cc42d88f3 100644 --- a/src/clm5/biogeochem/CropType.F90 +++ b/src/clm5/biogeochem/CropType.F90 @@ -28,10 +28,13 @@ module CropType type, public :: crop_type ! Note that cropplant and harvdate could be 2D to facilitate rotation + !!tbo added variables for vernalization and cold tolerance modified after YLu (2017) + integer , pointer :: nyrs_crop_active_patch (:) ! number of years this crop patch has been active (0 for non-crop patches) 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) @@ -41,6 +44,17 @@ module CropType character(len=20) :: baset_mapping real(r8) :: baset_latvary_intercept real(r8) :: baset_latvary_slope + real(r8), pointer :: lt50_patch (:) !lethal temperature at which 50% of the individuals are damaged + real(r8), pointer :: wdd_patch (:) !winter wheat weighted cumulated degree days + real(r8), pointer :: rateh_patch (:) !winter wheat weighted cumulated degree days + real(r8), pointer :: rated_patch (:) !loss of tolerance cause by dehardening + real(r8), pointer :: rates_patch (:) !loss of tolerance caused by low tempeature + real(r8), pointer :: rater_patch (:) !loss of tolerance caused by respiration under snow + real(r8), pointer :: fsurv_patch (:) !winter wheat survival rate + real(r8), pointer :: accfsurv_patch (:) !accumulated winter wheat survival rate + real(r8), pointer :: countfsurv_patch (:) !numbers of accumulated winter wheat survival rate + real(r8), pointer :: ck_patch (:) ! fraction of green leaf area killed + real(r8), pointer :: tcrown_patch (:) ! tcrown contains ! Public routines @@ -186,19 +200,32 @@ subroutine InitAllocate(this, bounds) character(len=*), parameter :: subname = 'InitAllocate' !----------------------------------------------------------------------- + !!tbo added variables for vernalization and cold tolerance modified after !YLu (2017) begp = bounds%begp; endp = bounds%endp 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 allocate(this%vf_patch (begp:endp)) ; this%vf_patch (:) = 0.0_r8 allocate(this%cphase_patch (begp:endp)) ; this%cphase_patch (:) = 0.0_r8 allocate(this%latbaset_patch (begp:endp)) ; this%latbaset_patch (:) = spval + allocate(this%lt50_patch (begp:endp)) ; this%lt50_patch (:) = spval + allocate(this%wdd_patch (begp:endp)) ; this%wdd_patch (:) = spval + allocate(this%rateh_patch (begp:endp)) ; this%rateh_patch (:) = spval + allocate(this%rated_patch (begp:endp)) ; this%rated_patch (:) = spval + allocate(this%rates_patch (begp:endp)) ; this%rates_patch (:) = spval + allocate(this%rater_patch (begp:endp)) ; this%rater_patch (:) = spval + allocate(this%fsurv_patch (begp:endp)) ; this%fsurv_patch (:) = spval + allocate(this%accfsurv_patch (begp:endp)) ; this%accfsurv_patch (:) = spval + allocate(this%countfsurv_patch(begp:endp)) ; this%countfsurv_patch (:) = spval + allocate(this%ck_patch (begp:endp)) ; this%ck_patch (:) = spval + allocate(this%tcrown_patch (begp:endp)) ; this%ck_patch (:) = spval end subroutine InitAllocate @@ -497,6 +524,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,9 +558,12 @@ 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, napple, nirrig_apple, pftcon use pftconMod , only : nwwheat, nirrig_wwheat + use pftconMod , only : nwbarley, nirrig_wbarley + use pftconMod , only : nrapeseed, nirrig_rapeseed use pftconMod , only : nsugarcane, nirrig_sugarcane + use pftconMod , only : ncovercrop_1, ncovercrop_2 use ColumnType , only : col use PatchType , only : patch ! @@ -582,6 +616,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 == napple) .or. (ivt == nirrig_apple) .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)))) & @@ -591,8 +626,11 @@ subroutine CropUpdateAccVars(this, bounds, t_ref2m_patch, t_soisno_col) t_ref2m_patch(p)-(SHR_CONST_TKFRZ + pftcon%baset(ivt)))) & * dtime/SHR_CONST_CDAY end if - if (ivt == nwwheat .or. ivt == nirrig_wwheat) then - rbufslp(p) = rbufslp(p) * this%vf_patch(p) + if (ivt == nwwheat .or. ivt == nirrig_wwheat .or. & + ivt == ncovercrop_1 .or. ivt == ncovercrop_2 .or. & + ivt == nwbarley .or. ivt == nirrig_wbarley .or. & + ivt == nrapeseed .or. ivt == nirrig_rapeseed) then + rbufslp(p) = rbufslp(p) * this%vf_patch(p) end if else rbufslp(p) = accumResetVal @@ -613,8 +651,11 @@ subroutine CropUpdateAccVars(this, bounds, t_ref2m_patch, t_soisno_col) ((t_soisno_col(c,1)*col%dz(c,1) + & t_soisno_col(c,2)*col%dz(c,2))/(col%dz(c,1)+col%dz(c,2))) - & (SHR_CONST_TKFRZ + pftcon%baset(ivt)))) * dtime/SHR_CONST_CDAY - if (ivt == nwwheat .or. ivt == nwwheat) then - rbufslp(p) = rbufslp(p) * this%vf_patch(p) + if (ivt == nwwheat .or. ivt == nwwheat .or. & + ivt == ncovercrop_1 .or. ivt == ncovercrop_2 .or. & + ivt == nwbarley .or. ivt == nirrig_wbarley .or. & + ivt == nrapeseed .or. ivt == nirrig_rapeseed) then + rbufslp(p) = rbufslp(p) * this%vf_patch(p) end if else rbufslp(p) = accumResetVal diff --git a/src/clm5/biogeochem/NutrientCompetitionCLM45defaultMod.F90 b/src/clm5/biogeochem/NutrientCompetitionCLM45defaultMod.F90 index 5d29efbeb5..d427d22ade 100644 --- a/src/clm5/biogeochem/NutrientCompetitionCLM45defaultMod.F90 +++ b/src/clm5/biogeochem/NutrientCompetitionCLM45defaultMod.F90 @@ -498,7 +498,7 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & ! !USES: use pftconMod , only : npcropmin, pftcon use pftconMod , only : ntmp_soybean, nirrig_tmp_soybean - use pftconMod , only : ntrp_soybean, nirrig_trp_soybean + !use pftconMod , only : ntrp_soybean, nirrig_trp_soybean use clm_varcon , only : secspday use clm_varctl , only : use_c13, use_c14 use clm_time_manager , only : get_step_size @@ -855,8 +855,8 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & !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 + (ivt(p) /= ntmp_soybean .and. ivt(p) /= nirrig_tmp_soybean)) then ! .and.& + !ivt(p) /= ntrp_soybean .and. ivt(p) /= nirrig_trp_soybean)) then if (grain_flag(p) == 0._r8)then if(.not.use_fun) then t1 = 1 / dt diff --git a/src/clm5/biogeochem/NutrientCompetitionFlexibleCNMod.F90 b/src/clm5/biogeochem/NutrientCompetitionFlexibleCNMod.F90 index f404ac9611..910dc14daa 100644 --- a/src/clm5/biogeochem/NutrientCompetitionFlexibleCNMod.F90 +++ b/src/clm5/biogeochem/NutrientCompetitionFlexibleCNMod.F90 @@ -25,7 +25,6 @@ module NutrientCompetitionFlexibleCNMod use PatchType , only : patch use NutrientCompetitionMethodMod, only : nutrient_competition_method_type use NutrientCompetitionMethodMod, only : params_inst - use clm_varctl , only : iulog ! implicit none private @@ -98,7 +97,6 @@ subroutine InitAllocate(this, bounds) allocate(this%actual_leafcn(bounds%begp:bounds%endp)) ; this%actual_leafcn(:) = nan allocate(this%actual_storage_leafcn(bounds%begp:bounds%endp)) ; this%actual_storage_leafcn(:) = nan - end subroutine InitAllocate !------------------------------------------------------------------------ @@ -196,7 +194,7 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & use clm_varctl , only : downreg_opt use clm_varctl , only : CN_residual_opt use clm_varctl , only : CN_partition_opt - use clm_time_manager , only : get_step_size + use clm_time_manager , only : get_step_size, get_curr_calday use CNVegStateType , only : cnveg_state_type use CropType , only : crop_type use CanopyStateType , only : canopystate_type @@ -240,7 +238,7 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & real(r8) :: f5 ! grain allocation parameter real(r8) :: cng ! C:N ratio for grain (= cnlw for now; slevis) real(r8) :: dt ! model time step - real(r8):: fsmn(bounds%begp:bounds%endp) ! A emperate variable for adjusting FUN uptakes + real(r8):: fsmn(bounds%begp:bounds%endp) ! A temperate variable for adjusting FUN uptakes real(r8):: frootcn_storage_actual real(r8):: frootcn_actual @@ -323,16 +321,19 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & grperc => pftcon%grperc , & ! Input: growth respiration parameter grpnow => pftcon%grpnow , & ! Input: growth respiration parameter evergreen => pftcon%evergreen , & ! Input: binary flag for evergreen leaf habit (0 or 1) + perennial => pftcon%perennial , & ! Input: binary flag for perennial crop phenology (0 or 1) (added by O.Dombrowski) croplive => crop_inst%croplive_patch , & ! Input: [logical (:) ] flag, true if planted, not harvested - + hui => crop_inst%gddplant_patch , & ! Input: [real(r8) (:) ] =gdd since planting (gddplant) + gddmaturity => cnveg_state_inst%gddmaturity_patch , & ! Input: [real(r8) (:) ] gdd until harvest peaklai => cnveg_state_inst%peaklai_patch , & ! Input: [integer (:) ] 1: max allowed lai; 0: not at max aleaf => cnveg_state_inst%aleaf_patch , & ! Output: [real(r8) (:) ] leaf allocation coefficient astem => cnveg_state_inst%astem_patch , & ! Output: [real(r8) (:) ] stem allocation coefficient c_allometry => cnveg_state_inst%c_allometry_patch , & ! Output: [real(r8) (:) ] C allocation index (DIM) n_allometry => cnveg_state_inst%n_allometry_patch , & ! Output: [real(r8) (:) ] N allocation index (DIM) downreg => cnveg_state_inst%downreg_patch , & ! Output: [real(r8) (:) ] fractional reduction in GPP due to N limitation (DIM) - + harvest_flag => cnveg_state_inst%harvest_flag_patch , & ! Output: [real(r8) (:) ] harvest flag for perennial crops + storage_flag => cnveg_state_inst%storage_flag_patch , & ! Output: [real(r8) (:) ] flag to switch to storage growth for perennials annsum_npp => cnveg_carbonflux_inst%annsum_npp_patch , & ! Input: [real(r8) (:) ] annual sum of NPP, for wood allocation gpp => cnveg_carbonflux_inst%gpp_before_downreg_patch , & ! Output: [real(r8) (:) ] GPP flux before downregulation (gC/m2/s) availc => cnveg_carbonflux_inst%availc_patch , & ! Output: [real(r8) (:) ] C flux available for allocation (gC/m2/s) @@ -402,14 +403,12 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & ! set time steps dt = real( get_step_size(), r8 ) - ! patch loop to distribute the available N between the competing patches ! on the basis of relative demand, and allocate C and N to new growth and storage do fp = 1,num_soilp p = filter_soilp(fp) c = patch%column(p) - ! set some local allocation variables f1 = froot_leaf(ivt(p)) f2 = croot_stem(ivt(p)) @@ -518,7 +517,6 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & ! transfer pools nlc = plant_calloc(p) / c_allometry(p) - cpool_to_leafc(p) = nlc * fcur cpool_to_leafc_storage(p) = nlc * (1._r8 - fcur) cpool_to_frootc(p) = nlc * f1 * fcur @@ -545,7 +543,35 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & cpool_to_grainc(p) = nlc * f5 * fcur cpool_to_grainc_storage(p) = nlc * f5 * (1._r8 -fcur) end if - + ! allocation for deciduous fruit trees (added by O.Dombrowski) + ! for this crop type, storage growth is considered next to photosynthetic growth + ! after harvest photosynthates are allocated to storage pool for refilling of C reserves + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1._r8) then + if (storage_flag(p) == 0._r8) then + fcur = fcur + else if (storage_flag(p) == 1._r8) then + fcur = 0._r8 + end if + cpool_to_leafc(p) = nlc * fcur + cpool_to_leafc_storage(p) = nlc * (1._r8 - fcur) + cpool_to_frootc(p) = nlc * f1 * fcur + cpool_to_frootc_storage(p) = nlc * f1 * (1._r8 - fcur) + cpool_to_livestemc(p) = nlc * f3 * f4 * fcur + cpool_to_livestemc_storage(p) = nlc * f3 * f4 * (1._r8 - fcur) + cpool_to_deadstemc(p) = nlc * f3 * (1._r8 - f4) * fcur + cpool_to_deadstemc_storage(p) = nlc * f3 * (1._r8 - f4) * (1._r8 - fcur) + cpool_to_livecrootc(p) = nlc * f2 * f3 * f4 * fcur + cpool_to_livecrootc_storage(p) = nlc * f2 * f3 * f4 * (1._r8 - fcur) + cpool_to_deadcrootc(p) = nlc * f2 * f3 * (1._r8 - f4) * fcur + cpool_to_deadcrootc_storage(p) = nlc * f2 * f3 * (1._r8 - f4) * (1._r8 - fcur) + if (harvest_flag(p) == 0._r8) then + cpool_to_grainc(p) = nlc * f5 + cpool_to_grainc_storage(p) = nlc * f5 * 0._r8 + else if (harvest_flag(p) == 1._r8) then + cpool_to_grainc(p) = nlc * f5 * 0._r8 + cpool_to_grainc_storage(p) = nlc * f5 * 0._r8 + end if + end if if (downreg_opt) then ! corresponding N fluxes npool_to_leafn(p) = (nlc / cnl) * fcur @@ -575,6 +601,21 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & npool_to_grainn(p) = (nlc * f5 / cng) * fcur npool_to_grainn_storage(p) = (nlc * f5 / cng) * (1._r8 -fcur) end if + ! calculating corresponding N fluxes for deciduous fruit trees + ! (added by O.Dombrowski) + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1._r8) then + cng = graincn(ivt(p)) + npool_to_livestemn(p) = (nlc * f3 * f4 / cnlw) * fcur + npool_to_livestemn_storage(p) = (nlc * f3 * f4 / cnlw) * (1._r8 - fcur) + npool_to_deadstemn(p) = (nlc * f3 * (1._r8 - f4) / cndw) * fcur + npool_to_deadstemn_storage(p) = (nlc * f3 * (1._r8 - f4) / cndw) * (1._r8 - fcur) + npool_to_livecrootn(p) = (nlc * f2 * f3 * f4 / cnlw) * fcur + npool_to_livecrootn_storage(p) = (nlc * f2 * f3 * f4 / cnlw) * (1._r8 - fcur) + npool_to_deadcrootn(p) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * fcur + npool_to_deadcrootn_storage(p) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * (1._r8 - fcur) + npool_to_grainn(p) = (nlc * f5 / cng) + npool_to_grainn_storage(p) = (nlc * f5 / cng) * (0._r8) + end if end if if (downreg_opt .eqv. .false. .AND. CN_partition_opt == 0) then @@ -735,6 +776,81 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & end if end if + ! calculation of N fluxes for perennial woody croptypes added by + ! O.Dombrowski + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1._r8) then + cng = graincn(ivt(p)) + npool_to_livestemn_demand(p) = (nlc * f3 * f4 / cnlw) * fcur + npool_to_livestemn_supply(p) = npool(p)/dt * fcur - npool_to_frootn(p) + npool_to_livestemn(p) = max(min(npool_to_livestemn_supply(p),npool_to_livestemn_demand(p)),0.0_r8) + + npool_to_livestemn_storage_demand(p) = (nlc * f3 * f4 / cnlw) * (1._r8 - fcur) + npool_to_livestemn_storage_supply(p) = npool(p)/dt * (1._r8 - fcur) - npool_to_frootn_storage(p) + npool_to_livestemn_storage(p) = max(min(npool_to_livestemn_storage_supply(p), & + npool_to_livestemn_storage_demand(p)),0.0_r8) + + npool_to_livecrootn_demand(p) = (nlc * f2 * f3 * f4 / cnlw) * fcur + npool_to_livecrootn_supply(p) = npool(p)/dt * fcur - npool_to_frootn(p) - npool_to_livestemn(p) + npool_to_livecrootn(p) = max(min(npool_to_livecrootn_supply(p),npool_to_livecrootn_demand(p)),0.0_r8) + + npool_to_livecrootn_storage_demand(p) = (nlc * f2 * f3 * f4 / cnlw) * (1._r8 - fcur) + npool_to_livecrootn_storage_supply(p) = npool(p)/dt * (1._r8 - fcur) - npool_to_frootn_storage(p) - & + npool_to_livestemn_storage(p) + npool_to_livecrootn_storage(p) = max(min(npool_to_livecrootn_storage_supply(p), & + npool_to_livecrootn_storage_demand(p)),0.0_r8) + + npool_to_deadstemn_demand(p) = (nlc * f3 * (1._r8 - f4) / cndw) * fcur + npool_to_deadstemn_supply(p) = npool(p)/dt * fcur - npool_to_frootn(p) - npool_to_livestemn(p) - & + npool_to_livecrootn(p) + npool_to_deadstemn(p) = max(min(npool_to_deadstemn_supply(p),npool_to_deadstemn_demand(p)), 0.0_r8) + + npool_to_deadstemn_storage_demand(p) = (nlc * f3 * (1._r8 - f4) / cndw) * (1._r8 - fcur) + npool_to_deadstemn_storage_supply(p) = npool(p)/dt * (1._r8 - fcur) - npool_to_frootn_storage(p) - & + npool_to_livestemn_storage(p) - npool_to_livecrootn_storage(p) + npool_to_deadstemn_storage(p) = max(min(npool_to_deadstemn_storage_supply(p), & + npool_to_deadstemn_storage_demand(p)),0.0_r8) + + npool_to_deadcrootn_demand(p) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * fcur + npool_to_deadcrootn_supply(p) = npool(p)/dt * fcur - npool_to_frootn(p) - npool_to_livestemn(p) - & + npool_to_livecrootn(p) - npool_to_deadstemn(p) + npool_to_deadcrootn(p) = max(min(npool_to_deadcrootn_supply(p), npool_to_deadcrootn_demand(p)), 0.0_r8) + + npool_to_deadcrootn_storage_demand(p) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * (1._r8 - fcur) + npool_to_deadcrootn_storage_supply(p) = npool(p)/dt * (1._r8 - fcur) - npool_to_frootn_storage(p) - & + npool_to_livestemn_storage(p) - npool_to_livecrootn_storage(p) - npool_to_deadstemn_storage(p) + npool_to_deadcrootn_storage(p) = max(min(npool_to_deadcrootn_storage_supply(p), & + npool_to_deadcrootn_storage_demand(p)),0.0_r8) + + npool_to_grainn_demand(p) = (nlc * f5 / cng) + npool_to_grainn_supply(p) = npool(p)/dt - npool_to_frootn(p) - npool_to_livestemn(p) - & + npool_to_livecrootn(p) - npool_to_deadstemn(p) - npool_to_deadcrootn(p) + npool_to_grainn(p) = max(min(npool_to_grainn_supply(p), npool_to_grainn_demand(p)), 0.0_r8) + + npool_to_grainn_storage_demand(p) = (nlc * f5 / cng) * 0._r8 + npool_to_grainn_storage_supply(p) = npool(p)/dt * 0._r8 - npool_to_frootn_storage(p) - & + npool_to_livestemn_storage(p) - npool_to_livecrootn_storage(p) - npool_to_deadstemn_storage(p) - & + npool_to_deadcrootn_storage(p) + npool_to_grainn_storage(p) = max(min(npool_to_grainn_storage_supply(p), npool_to_grainn_storage_demand(p)), & + 0.0_r8) + + npool_to_leafn_demand(p) = (nlc / cnl) * fcur + npool_to_leafn_supply(p) = npool(p)/dt * fcur - npool_to_frootn(p) - npool_to_livestemn(p) - & + npool_to_livecrootn(p) - npool_to_deadstemn(p) - npool_to_deadcrootn(p) - npool_to_grainn(p) + npool_to_leafn(p) = max(min(npool_to_leafn_supply(p), npool_to_leafn_demand(p)), 0.0_r8) + + npool_to_leafn_storage_demand(p) = (nlc / cnl) * (1._r8 - fcur) + npool_to_leafn_storage_supply(p) = npool(p)/dt * (1._r8 - fcur) - npool_to_frootn_storage(p) - & + npool_to_livestemn_storage(p) - npool_to_livecrootn_storage(p) & + - npool_to_deadstemn_storage(p) - npool_to_deadcrootn_storage(p) - npool_to_grainn_storage(p) + npool_to_leafn_storage(p) = max(min(npool_to_leafn_storage_supply(p), npool_to_leafn_storage_demand(p)), & + 0.0_r8) + + if (CN_residual_opt == 1) then + npool_to_leafn(p) = max(npool_to_leafn_supply(p),0.0_r8) + npool_to_leafn_storage(p) = max(npool_to_leafn_storage_supply(p),0.0_r8) + end if + + end if end if @@ -760,9 +876,16 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & gresp_storage = gresp_storage + cpool_to_livestemc_storage(p) gresp_storage = gresp_storage + cpool_to_grainc_storage(p) end if + !recalculate total gresp_storage of vegetation parts for fruit trees (added by O.Dombrowski) + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1._r8) then + gresp_storage = cpool_to_leafc_storage(p) + cpool_to_frootc_storage(p) & + + cpool_to_livestemc_storage(p) & + + cpool_to_deadstemc_storage(p) & + + cpool_to_livecrootc_storage(p) & + + cpool_to_deadcrootc_storage(p) & + + cpool_to_grainc_storage(p) + end if cpool_to_gresp_storage(p) = gresp_storage * g1 * (1._r8 - g2) - - ! computing 1.) fractional N demand and 2.) N allocation after uptake for different plant parts !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! if (downreg_opt .eqv. .false. .AND. CN_partition_opt == 1) then @@ -797,7 +920,22 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & npool_to_grainn_demand(p) = (nlc * f5 / cng) * fcur npool_to_grainn_storage_demand(p) = (nlc * f5 / cng) * (1._r8 -fcur) end if + ! computing nitrogen demand for fruit trees + ! (added by O.Dombrowski) + if (perennial(ivt(p)) == 1._r8 .and. woody(ivt(p)) == 1._r8) then + cng = graincn(ivt(p)) + npool_to_livestemn_demand(p) = (nlc * f3 * f4 / cnlw) * fcur + npool_to_livestemn_storage_demand(p) = (nlc * f3 * f4 / cnlw) * (1._r8 - fcur) + npool_to_deadstemn_demand(p) = (nlc * f3 * (1._r8 - f4) / cndw) * fcur + npool_to_deadstemn_storage_demand(p) = (nlc * f3 * (1._r8 - f4) / cndw) * (1._r8 - fcur) + npool_to_livecrootn_demand(p) = (nlc * f2 * f3 * f4 / cnlw) * fcur + npool_to_livecrootn_storage_demand(p) = (nlc * f2 * f3 * f4 / cnlw) * (1._r8 - fcur) + npool_to_deadcrootn_demand(p) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * fcur + npool_to_deadcrootn_storage_demand(p) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * (1._r8 - fcur) + npool_to_grainn_demand(p) = (nlc * f5 / cng) + npool_to_grainn_storage_demand(p) = (nlc * f5 / cng) * 0._r8 + end if ! computing 1.) fractional N demand for different plant parts !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -822,10 +960,11 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & npool_to_deadstemn_storage_demand(p) + & npool_to_livecrootn_demand(p) + npool_to_livecrootn_storage_demand(p) + npool_to_deadcrootn_demand(p) + & npool_to_deadcrootn_storage_demand(p) + & - npool_to_grainn_demand(p) + npool_to_grainn_storage_demand(p) + npool_to_grainn_demand(p) + npool_to_grainn_storage_demand(p) end if + if (total_plant_Ndemand(p) == 0.0_r8) then ! removing division by zero frNdemand_npool_to_leafn(p) = 0.0_r8 @@ -1188,12 +1327,12 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & ! !USES: use pftconMod , only : npcropmin, pftcon use pftconMod , only : ntmp_soybean, nirrig_tmp_soybean - use pftconMod , only : ntrp_soybean, nirrig_trp_soybean + !use pftconMod , only : ntrp_soybean, nirrig_trp_soybean use clm_varcon , only : secspday, dzsoi_decomp use clm_varctl , only : use_c13, use_c14 use clm_varctl , only : 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,92 +1642,190 @@ 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. - - 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: + ! Phase 1 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 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 - ! 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 + ! 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 + + ! 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 + (ivt(p) /= ntmp_soybean .and. ivt(p) /= nirrig_tmp_soybean) ) then !.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) @@ -1590,18 +1840,25 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & 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 + else ! pre emergence + aleaf(p) = 1.e-5_r8 ! allocation coefficients should be irrelevant + astem(p) = 0._r8 ! because crops have no live carbon pools; + aroot(p) = 0._r8 ! this applies to this "else" and to the "else" + arepr(p) = 0._r8 ! a few lines down + end if + end if ! perennial or normal crop f1 = aroot(p) / aleaf(p) f3 = astem(p) / aleaf(p) f5 = arepr(p) / aleaf(p) g1 = 0.25_r8 - + + if (perennial(ivt(p)) == 1._r8 .and. dormant_flag(p) == 1._r8) then !dormant tree has no allocation to any organs (similar to .not. croplive) + f1 = 0._r8 + f3 = 0._r8 + f5 = 0._r8 + g1 = 0.25_r8 + end if else ! .not croplive f1 = 0._r8 @@ -1615,10 +1872,17 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & ! determine N requirements if(use_fun)then ! In FUN, growth respiration is not part of the allometry calculation. if (woody(ivt(p)) == 1.0_r8) then - c_allometry(p) = (1._r8)*(1._r8+f1+f3*(1._r8+f2)) - n_allometry(p) = 1._r8/cnl + f1/cnfr + (f3*f4*(1._r8+f2))/cnlw + & - (f3*(1._r8-f4)*(1._r8+f2))/cndw - else if (ivt(p) >= npcropmin) then ! skip generic crops + if (perennial(ivt(p)) == 1.0_r8) then !(added by O.Dombrowski) + cng = graincn(ivt(p)) + c_allometry(p) = (1._r8)*(1._r8+f1+f5+f3*(1._r8+f2)) + n_allometry(p) = 1._r8/cnl + f1/cnfr + f5/cng + (f3*f4*(1._r8+f2))/cnlw + & + (f3*(1._r8-f4)*(1._r8+f2))/cndw + else + c_allometry(p) = (1._r8)*(1._r8+f1+f3*(1._r8+f2)) + n_allometry(p) = 1._r8/cnl + f1/cnfr + (f3*f4*(1._r8+f2))/cnlw + & + (f3*(1._r8-f4)*(1._r8+f2))/cndw + end if + else if (ivt(p) >= npcropmin .and. perennial(ivt(p)) == 0.0_r8) then ! skip generic crops cng = graincn(ivt(p)) c_allometry(p) = (1._r8)*(1._r8+f1+f5+f3*(1._r8+f2)) n_allometry(p) = 1._r8/cnl + f1/cnfr + f5/cng + (f3*f4*(1._r8+f2))/cnlw + & @@ -1738,14 +2002,13 @@ subroutine calc_plant_nitrogen_demand(this, bounds, num_soilp, filter_soilp, & ! retransn pool has N from leaves, stems, and roots for ! retranslocation - if (ivt(p) >= npcropmin .and. grain_flag(p) == 1._r8) then + if (ivt(p) >= npcropmin .and. grain_flag(p) == 1._r8 .and. perennial(ivt(p)) == 0._r8) then avail_retransn(p) = plant_ndemand(p) - else if (ivt(p) < npcropmin .and. annsum_potential_gpp(p) > 0._r8) then + else if ((ivt(p) < npcropmin .and. annsum_potential_gpp(p) > 0._r8) .or. (perennial(ivt(p)) == 1._r8 .and. annsum_potential_gpp(p) > 0._r8)) then avail_retransn(p) = (annmax_retransn(p)/2._r8)*(gpp(p)/annsum_potential_gpp(p))/dt else avail_retransn(p) = 0.0_r8 end if - ! make sure available retrans N doesn't exceed storage avail_retransn(p) = min(avail_retransn(p), retransn(p)/dt) diff --git a/src/clm5/biogeochem/dynHarvestMod.F90 b/src/clm5/biogeochem/dynHarvestMod.F90 index a9344fd5cf..4119f318a2 100644 --- a/src/clm5/biogeochem/dynHarvestMod.F90 +++ b/src/clm5/biogeochem/dynHarvestMod.F90 @@ -33,7 +33,7 @@ module dynHarvestMod public :: CNHarvest ! harvest mortality routine for CN code ! ! !PRIVATE MEMBER FUNCTIONS: - private :: CNHarvestPftToColumn ! gather patch-level harvest fluxes to the column level + public :: CNHarvestPftToColumn ! gather patch-level harvest fluxes to the column level ! ! !PRIVATE TYPES: @@ -184,7 +184,7 @@ subroutine CNHarvest (num_soilc, filter_soilc, num_soilp, filter_soilp, & ! !USES: use pftconMod , only : noveg, nbrdlf_evr_shrub use clm_varcon , only : secspday - use clm_time_manager, only : get_step_size_real, is_beg_curr_year + use clm_time_manager, only : get_step_size_real, is_beg_curr_year ! ! !ARGUMENTS: integer , intent(in) :: num_soilc ! number of soil columns in filter @@ -330,13 +330,14 @@ subroutine CNHarvest (num_soilc, filter_soilc, num_soilp, filter_soilp, & else m = 0._r8 end if - + ! patch-level harvest carbon fluxes ! displayed pools hrv_leafc_to_litter(p) = leafc(p) * m hrv_frootc_to_litter(p) = frootc(p) * m hrv_livestemc_to_litter(p) = livestemc(p) * m wood_harvestc(p) = deadstemc(p) * m + hrv_livecrootc_to_litter(p) = livecrootc(p) * m hrv_deadcrootc_to_litter(p) = deadcrootc(p) * m hrv_xsmrpool_to_atm(p) = xsmrpool(p) * m @@ -498,7 +499,7 @@ subroutine CNHarvestPftToColumn (num_soilc, filter_soilc, & p = col%patchi(c) + pi - 1 if (patch%active(p)) then - + ! leaf harvest mortality carbon fluxes harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & hrv_leafc_to_litter(p) * lf_flab(ivt(p)) * wtcol(p) * leaf_prof(p,j) @@ -522,7 +523,6 @@ subroutine CNHarvestPftToColumn (num_soilc, filter_soilc, & hrv_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & hrv_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) - ! storage harvest mortality carbon fluxes harvest_c_to_litr_met_c(c,j) = harvest_c_to_litr_met_c(c,j) + & hrv_leafc_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) @@ -630,7 +630,7 @@ subroutine CNHarvestPftToColumn (num_soilc, filter_soilc, & ! wood harvest mortality carbon fluxes to product pools cwood_harvestc(c) = cwood_harvestc(c) + & pwood_harvestc(p) * wtcol(p) - + ! wood harvest mortality nitrogen fluxes to product pools cwood_harvestn(c) = cwood_harvestn(c) + & pwood_harvestn(p) * wtcol(p) diff --git a/src/clm5/biogeophys/TemperatureType.F90 b/src/clm5/biogeophys/TemperatureType.F90 index 7dfbb5d95f..438734ea8a 100644 --- a/src/clm5/biogeophys/TemperatureType.F90 +++ b/src/clm5/biogeophys/TemperatureType.F90 @@ -87,6 +87,7 @@ module TemperatureType ! being: that way one parameterization is free to change the exact meaning of its ! accumulator without affecting the other). ! + real(r8), pointer :: t_ref24_patch (:) ! patch 24hr average 2 m air temperature (K) real(r8), pointer :: t_veg24_patch (:) ! patch 24hr average vegetation temperature (K) real(r8), pointer :: t_veg240_patch (:) ! patch 240hr average vegetation temperature (Kelvin) real(r8), pointer :: gdd0_patch (:) ! patch growing degree-days base 0C from planting (ddays) @@ -252,6 +253,7 @@ subroutine InitAllocate(this, bounds) allocate(this%t_ref2m_min_inst_u_patch (begp:endp)) ; this%t_ref2m_min_inst_u_patch (:) = nan ! Accumulated fields + allocate(this%t_ref24_patch (begp:endp)) ; this%t_ref24_patch (:) = nan allocate(this%t_veg24_patch (begp:endp)) ; this%t_veg24_patch (:) = nan allocate(this%t_veg240_patch (begp:endp)) ; this%t_veg240_patch (:) = nan allocate(this%gdd0_patch (begp:endp)) ; this%gdd0_patch (:) = spval @@ -456,6 +458,7 @@ subroutine InitHistory(this, bounds, is_simple_buildtemp, is_prog_buildtemp ) else active = "inactive" end if + this%t_a10_patch(begp:endp) = spval call hist_addfld1d (fname='T10', units='K', & avgflag='A', long_name='10-day running mean of 2-m temperature', & @@ -573,6 +576,11 @@ subroutine InitHistory(this, bounds, is_simple_buildtemp, is_prog_buildtemp ) ! Accumulated quantities + this%t_ref24_patch(begp:endp) = spval + call hist_addfld1d (fname='TREF24', units='K', & + avgflag='A', long_name='2 m air temperature (last 24hrs)', & + ptr_patch=this%t_ref24_patch, default='inactive') + this%t_veg24_patch(begp:endp) = spval call hist_addfld1d (fname='TV24', units='K', & avgflag='A', long_name='vegetation temperature (last 24hrs)', & @@ -934,6 +942,10 @@ subroutine Restart(this, bounds, ncid, flag, is_simple_buildtemp, is_prog_buildt long_name='Urban 2m height surface air temperature', units='K', & interpinic_flag='interp', readvar=readvar, data=this%t_ref2m_u_patch) + call restartvar(ncid=ncid, flag=flag, varname='T_REF24', xtype=ncd_double, & + dim1name='pft', & + long_name='daily average 2 m height surface air temperature (K)', units='K', & + interpinic_flag='interp', readvar=readvar, data=this%t_ref24_patch) call restartvar(ncid=ncid, flag=flag, varname='T_REF2M_MIN', xtype=ncd_double, & dim1name='pft', & @@ -1132,6 +1144,10 @@ subroutine InitAccBuffer (this, bounds) dtime = get_step_size() + call init_accum_field (name='T_REF24', units='K', & + desc='24hr average of 2 m air temperature', accum_type='timeavg', accum_period=-1, & + subgrid_type='pft', numlev=1, init_value=0._r8) + this%t_veg24_patch(bounds%begp:bounds%endp) = spval call init_accum_field (name='T_VEG24', units='K', & desc='24hr average of vegetation temperature', accum_type='runmean', accum_period=-1, & @@ -1160,6 +1176,10 @@ subroutine InitAccBuffer (this, bounds) subgrid_type='pft', numlev=1,init_value=SHR_CONST_TKFRZ+20._r8) if ( use_crop )then + call init_accum_field (name='T24', units='K', & + desc='24-hour running mean of 2-m temperature', accum_type='runmean', accum_period=-1, & + subgrid_type='pft', numlev=1,init_value=SHR_CONST_TKFRZ+20._r8) + call init_accum_field (name='TDM10', units='K', & desc='10-day running mean of min 2-m temperature', accum_type='runmean', accum_period=-10, & subgrid_type='pft', numlev=1, init_value=SHR_CONST_TKFRZ) @@ -1235,6 +1255,9 @@ subroutine InitAccVars(this, bounds) ! Determine time step nstep = get_nstep() + call extract_accum_field ('T_REF24', rbufslp, nstep) + this%t_ref24_patch(begp:endp) = rbufslp(begp:endp) + call extract_accum_field ('T_VEG24', rbufslp, nstep) this%t_veg24_patch(begp:endp) = rbufslp(begp:endp) @@ -1245,6 +1268,7 @@ subroutine InitAccVars(this, bounds) this%t_a10_patch(begp:endp) = rbufslp(begp:endp) if (use_crop) then + call extract_accum_field ('TDM10', rbufslp, nstep) this%t_a10min_patch(begp:endp)= rbufslp(begp:endp) @@ -1331,7 +1355,7 @@ subroutine UpdateAccVars (this, bounds) call endrun(msg=errMsg(sourcefile, __LINE__)) endif - ! Accumulate and extract T_VEG24 & T_VEG240 + ! Accumulate and extract T_VEG24 & T_VEG240 do p = begp,endp rbufslp(p) = this%t_veg_patch(p) end do @@ -1340,6 +1364,7 @@ subroutine UpdateAccVars (this, bounds) call update_accum_field ('T_VEG240', rbufslp , nstep) call extract_accum_field ('T_VEG240', this%t_veg240_patch , nstep) + ! Accumulate and extract TREFAV - hourly average 2m air temperature ! Used to compute maximum and minimum of hourly averaged 2m reference ! temperature over a day. Note that "spval" is returned by the call to @@ -1429,6 +1454,11 @@ subroutine UpdateAccVars (this, bounds) call extract_accum_field ('T10', this%t_a10_patch, nstep) if ( use_crop )then + ! Accumulate and extract T_REF24 + + call update_accum_field ('T_REF24' , this%t_ref2m_patch, nstep) + call extract_accum_field ('T_REF24' , this%t_ref24_patch , nstep) + ! Accumulate and extract TDM10 do p = begp,endp diff --git a/src/clm5/main/PatchType.F90 b/src/clm5/main/PatchType.F90 index d00f5588b0..e3d558d752 100644 --- a/src/clm5/main/PatchType.F90 +++ b/src/clm5/main/PatchType.F90 @@ -41,8 +41,8 @@ module PatchType ! 32 => irrigated_winter_rye ! 33 => cassava ! 34 => irrigated_cassava - ! 35 => citrus - ! 36 => irrigated_citrus + ! 35 => apple + ! 36 => irrigated_apple ! 37 => cocoa ! 38 => irrigated_cocoa ! 39 => coffee @@ -83,8 +83,8 @@ module PatchType ! 74 => irrigated_switchgrass ! 75 => tropical_corn ! 76 => irrigated_tropical_corn - ! 77 => tropical_soybean - ! 78 => irrigated_tropical_soybean + ! 77 => covercrop_1 + ! 78 => covercrop_2 ! -------------------------------------------------------- ! use shr_kind_mod , only : r8 => shr_kind_r8 diff --git a/src/clm5/main/clm_varpar.F90 b/src/clm5/main/clm_varpar.F90 index d2011dcae4..bd6eb0a5c3 100644 --- a/src/clm5/main/clm_varpar.F90 +++ b/src/clm5/main/clm_varpar.F90 @@ -44,7 +44,7 @@ module clm_varpar integer, parameter :: ndst = 4 ! number of dust size classes (BGC only) integer, parameter :: dst_src_nbr = 3 ! number of size distns in src soil (BGC only) integer, parameter :: sz_nbr = 200 ! number of sub-grid bins in large bin of dust size distribution (BGC only) - integer, parameter :: mxpft = 78 ! maximum number of PFT's for any mode; + integer, parameter :: mxpft = 78 ! maximum number of PFT's for any mode; ! FIX(RF,032414) might we set some of these automatically from reading pft-physiology? integer, parameter :: numveg = 16 ! number of veg types (without specific crop) integer, parameter :: nlayer = 3 ! number of VIC soil layer --Added by AWang @@ -52,7 +52,7 @@ module clm_varpar integer, parameter :: nvariants = 2 ! number of variants of PFT constants integer :: numpft = mxpft ! actual # of pfts (without bare) - integer :: numcft = 64 ! actual # of crops (includes unused CFTs that are merged into other CFTs) + integer :: numcft = 64 ! actual # of crops (includes unused CFTs that are merged into other CFTs) integer :: maxpatch_urb= 5 ! max number of urban patches (columns) in urban landunit integer :: maxpatch_pft ! max number of plant functional types in naturally vegetated landunit (namelist setting) diff --git a/src/clm5/main/findHistFields.pl b/src/clm5/main/findHistFields.pl old mode 100755 new mode 100644 diff --git a/src/clm5/main/pftconMod.F90 b/src/clm5/main/pftconMod.F90 index 0efa2053eb..d992b68c10 100644 --- a/src/clm5/main/pftconMod.F90 +++ b/src/clm5/main/pftconMod.F90 @@ -51,8 +51,8 @@ module pftconMod integer :: nirrig_wrye ! value for winter rye (ir) integer :: ncassava ! ...and so on integer :: nirrig_cassava - integer :: ncitrus - integer :: nirrig_citrus + integer :: napple + integer :: nirrig_apple integer :: ncocoa integer :: nirrig_cocoa integer :: ncoffee @@ -91,14 +91,14 @@ module pftconMod integer :: nirrig_miscanthus integer :: nswitchgrass integer :: nirrig_switchgrass - integer :: ntrp_corn !value for tropical corn (rf) - integer :: nirrig_trp_corn !value for tropical corn (ir) - integer :: ntrp_soybean !value for tropical soybean (rf) - integer :: nirrig_trp_soybean !value for tropical soybean (ir) + integer :: ntrp_corn ! value for tropical corn (rf) + integer :: nirrig_trp_corn ! value for tropical corn (ir) + integer :: ncovercrop_1 ! before value for tropical soybean (rf) + integer :: ncovercrop_2 ! before value for tropical soybean (if) integer :: npcropmax ! value for last prognostic crop in list integer :: nc3crop ! value for generic crop (rf) integer :: nc3irrig ! value for irrigated generic crop (ir) - + ! Number of crop functional types actually used in the model. This includes each CFT for ! which is_pft_known_to_model is true. Note that this includes irrigated crops even if ! irrigation is turned off in this run: it just excludes crop types that aren't handled @@ -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 (:) @@ -255,11 +269,14 @@ module pftconMod real(r8), allocatable :: fun_cn_flex_b (:) ! Parameter b of FUN-flexcn link code (def 200) real(r8), allocatable :: fun_cn_flex_c (:) ! Parameter b of FUN-flexcn link code (def 80) real(r8), allocatable :: FUN_fracfixers(:) ! Fraction of C that can be used for fixation. - + integer , allocatable :: covercrop (:) ! Cover crop flag ! pft parameters for dynamic root code real(r8), allocatable :: root_dmx(:) !maximum root depth + ! pft parameters for cover crop routine + !integer, allocatable :: covercrop(:) !cover crop flag + contains procedure, public :: Init @@ -372,9 +389,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 +405,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 +436,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 +445,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) ) @@ -459,7 +491,7 @@ subroutine InitAllocate (this) allocate( this%fun_cn_flex_b (0:mxpft) ) allocate( this%fun_cn_flex_c (0:mxpft) ) allocate( this%FUN_fracfixers(0:mxpft) ) - + allocate( this%covercrop (0:mxpft) ) end subroutine InitAllocate @@ -535,8 +567,8 @@ subroutine InitRead(this) expected_pftnames(32) = 'irrigated_winter_rye ' expected_pftnames(33) = 'cassava ' expected_pftnames(34) = 'irrigated_cassava ' - expected_pftnames(35) = 'citrus ' - expected_pftnames(36) = 'irrigated_citrus ' + expected_pftnames(35) = 'apple ' + expected_pftnames(36) = 'irrigated_apple ' expected_pftnames(37) = 'cocoa ' expected_pftnames(38) = 'irrigated_cocoa ' expected_pftnames(39) = 'coffee ' @@ -577,10 +609,10 @@ subroutine InitRead(this) expected_pftnames(74) = 'irrigated_switchgrass ' expected_pftnames(75) = 'tropical_corn ' expected_pftnames(76) = 'irrigated_tropical_corn ' - expected_pftnames(77) = 'tropical_soybean ' - expected_pftnames(78) = 'irrigated_tropical_soybean ' - - ! Set specific vegetation type values + expected_pftnames(77) = 'covercrop_1 ' + expected_pftnames(78) = 'covercrop_2 ' + +! Set specific vegetation type values if (masterproc) then write(iulog,*) 'Attempting to read PFT physiological data .....' @@ -739,6 +771,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 +887,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 +900,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 +950,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,9 +1031,20 @@ 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__)) +!Cover crop flag read-in + + call ncd_io('covercrop', this%covercrop, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in cover crop flag'//errMsg(sourcefile, __LINE__)) + ! ! Constants ! @@ -1051,8 +1133,8 @@ subroutine InitRead(this) if ( trim(pftname(i)) == 'irrigated_winter_rye' ) nirrig_wrye = i if ( trim(pftname(i)) == 'cassava' ) ncassava = i if ( trim(pftname(i)) == 'irrigated_cassava' ) nirrig_cassava = i - if ( trim(pftname(i)) == 'citrus' ) ncitrus = i - if ( trim(pftname(i)) == 'irrigated_citrus' ) nirrig_citrus = i + if ( trim(pftname(i)) == 'apple' ) napple = i + if ( trim(pftname(i)) == 'irrigated_apple' ) nirrig_apple = i if ( trim(pftname(i)) == 'cocoa' ) ncocoa = i if ( trim(pftname(i)) == 'irrigated_cocoa' ) nirrig_cocoa = i if ( trim(pftname(i)) == 'coffee' ) ncoffee = i @@ -1093,8 +1175,9 @@ subroutine InitRead(this) if ( trim(pftname(i)) == 'irrigated_switchgrass' ) nirrig_switchgrass = i if ( trim(pftname(i)) == 'tropical_corn' ) ntrp_corn = i if ( trim(pftname(i)) == 'irrigated_tropical_corn' ) nirrig_trp_corn = i - if ( trim(pftname(i)) == 'tropical_soybean' ) ntrp_soybean = i - if ( trim(pftname(i)) == 'irrigated_tropical_soybean' ) nirrig_trp_soybean = i + if ( trim(pftname(i)) == 'covercrop_1' ) ncovercrop_1 = i + if ( trim(pftname(i)) == 'covercrop_2' ) ncovercrop_2 = i + end do ntree = nbrdlf_dcd_brl_tree ! value for last type of tree @@ -1125,7 +1208,7 @@ subroutine InitRead(this) i == nirrig_barley .or. i == nirrig_wbarley .or. & i == nirrig_rye .or. i == nirrig_wrye .or. & i == nirrig_cassava .or. & - i == nirrig_citrus .or. & + i == nirrig_apple .or. & i == nirrig_cocoa .or. i == nirrig_coffee .or. & i == nirrig_cotton .or. & i == nirrig_datepalm .or. & @@ -1139,8 +1222,7 @@ subroutine InitRead(this) i == nirrig_sugarbeet .or. i == nirrig_sugarcane .or. & i == nirrig_sunflower .or. & i == nirrig_miscanthus .or. i == nirrig_switchgrass .or. & - i == nirrig_trp_corn .or. & - i == nirrig_trp_soybean) )then + i == nirrig_trp_corn ) )then ! correct else if ( this%irrigated(i) == 0.0_r8 )then ! correct @@ -1194,6 +1276,16 @@ subroutine set_is_pft_known_to_model(this) ! so we can't handle it in the general loop below. But CLM always uses type 0, so ! handle it specially here. this%is_pft_known_to_model(0) = .true. + this%is_pft_known_to_model(27) = .true. + this%is_pft_known_to_model(28) = .true. + this%is_pft_known_to_model(55) = .true. + this%is_pft_known_to_model(56) = .true. + this%is_pft_known_to_model(59) = .true. + this%is_pft_known_to_model(60) = .true. + this%is_pft_known_to_model(65) = .true. + this%is_pft_known_to_model(66) = .true. + this%is_pft_known_to_model(78) = .true. + this%is_pft_known_to_model(79) = .true. ! NOTE(wjs, 2015-10-04) Currently, mergetoclmpft is only used for crop types. ! However, we handle it more generally here (treating ALL pft types), in case its use @@ -1287,9 +1379,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 +1396,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 +1429,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) @@ -1374,7 +1481,8 @@ subroutine Clean(this) deallocate( this%fun_cn_flex_b) deallocate( this%fun_cn_flex_c) deallocate( this%FUN_fracfixers) - + deallocate( this%covercrop) + end subroutine Clean end module pftconMod diff --git a/src/csm_share/esmf_wrf_timemgr/unittests/go.csh b/src/csm_share/esmf_wrf_timemgr/unittests/go.csh old mode 100755 new mode 100644 diff --git a/src/externals/mct/doc/mct_APIs.tex b/src/externals/mct/doc/mct_APIs.tex old mode 100755 new mode 100644 diff --git a/src/externals/mct/mpi-serial/configure b/src/externals/mct/mpi-serial/configure old mode 100755 new mode 100644 diff --git a/src/externals/mct/mpi-serial/protify.awk b/src/externals/mct/mpi-serial/protify.awk old mode 100755 new mode 100644 diff --git a/src/externals/mct/protex/protex b/src/externals/mct/protex/protex old mode 100755 new mode 100644