diff --git a/cime_config/tests.py b/cime_config/tests.py index 3ed0e4d59687..7ef5275f6617 100644 --- a/cime_config/tests.py +++ b/cime_config/tests.py @@ -74,6 +74,14 @@ ) }, + "e3sm_land_mytests" : { + "share" : True, + "time" : "0:45:00", + "tests" : ( + "ERS.ELM_USRDAT.I1850CNPRDCTCBC.elm-arcticpft_codetest_I1850CNPRDCTCBC", + "ERS.ELM_USRDAT.I1850CNPRDCTCBC.elm-arcticpft_onsetgdd_I1850CNPRDCTCBC" + ) + }, "e3sm_land_developer" : { "share" : True, @@ -93,6 +101,8 @@ "SMS_Ly2_P1x1.1x1_smallvilleIA.IELMCNCROP.elm-per_crop", "SMS.r05_r05.IELM.elm-topounit", "ERS.ELM_USRDAT.I1850ELM.elm-usrdat", + "ERS.ELM_USRDAT.I1850CNPRDCTCBC.elm-arcticpft_codetest_I1850CNPRDCTCBC", + "ERS.ELM_USRDAT.I1850CNPRDCTCBC.elm-arcticpft_onsetgdd_I1850CNPRDCTCBC", "ERS.f09_f09.IELM.elm-lnd_rof_2way", "ERS.r05_r05.IELM.elm-V2_ELM_MOSART_features" ) diff --git a/components/elm/bld/namelist_files/namelist_definition.xml b/components/elm/bld/namelist_files/namelist_definition.xml index a113076e22df..16e998dc39f0 100644 --- a/components/elm/bld/namelist_files/namelist_definition.xml +++ b/components/elm/bld/namelist_files/namelist_definition.xml @@ -1801,6 +1801,15 @@ Specifies the method for decomposing CLM grids across processors. pflotran file prefix. + + + + + + Runtime flag to turn on/off stress_deciduous PFT's onset gdd summation end from summer solstice to offset starting. + + diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/arcticpft_codetest_I1850CNPRDCTCBC/clm_params_c211124arctic.nc b/components/elm/cime_config/testdefs/testmods_dirs/elm/arcticpft_codetest_I1850CNPRDCTCBC/clm_params_c211124arctic.nc new file mode 100644 index 000000000000..99d542a8786b Binary files /dev/null and b/components/elm/cime_config/testdefs/testmods_dirs/elm/arcticpft_codetest_I1850CNPRDCTCBC/clm_params_c211124arctic.nc differ diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/arcticpft_codetest_I1850CNPRDCTCBC/shell_commands b/components/elm/cime_config/testdefs/testmods_dirs/elm/arcticpft_codetest_I1850CNPRDCTCBC/shell_commands new file mode 100644 index 000000000000..2f7ff7c8e233 --- /dev/null +++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/arcticpft_codetest_I1850CNPRDCTCBC/shell_commands @@ -0,0 +1,12 @@ +./xmlchange LND_DOMAIN_FILE=domain_42_FLUXNETSITES_simyr1850_c170912.nc +./xmlchange ATM_DOMAIN_FILE=domain_42_FLUXNETSITES_simyr1850_c170912.nc +./xmlchange LND_DOMAIN_PATH="\$DIN_LOC_ROOT/share/domains/domain.clm" +./xmlchange ATM_DOMAIN_PATH="\$DIN_LOC_ROOT/share/domains/domain.clm" +./xmlchange DATM_MODE=CLM1PT +./xmlchange DATM_CLMNCEP_YR_START=1980 +./xmlchange DATM_CLMNCEP_YR_END=2015 +./xmlchange ELM_USRDAT_NAME=42_FLUXNETSITES +./xmlchange NTASKS=6 +echo " + taxmode = 'cycle','extend','extend' +">>user_nl_datm diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/arcticpft_codetest_I1850CNPRDCTCBC/user_nl_elm b/components/elm/cime_config/testdefs/testmods_dirs/elm/arcticpft_codetest_I1850CNPRDCTCBC/user_nl_elm new file mode 100644 index 000000000000..157df24b242c --- /dev/null +++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/arcticpft_codetest_I1850CNPRDCTCBC/user_nl_elm @@ -0,0 +1,12 @@ +fsurdat = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/surfdata_42_FLUXNETSITES_simyr1850_c170912.nc' +! +! below is a new physioloy file example, from Sulman et al 2021, +! by adding a few parameters into default (clm_params_c211124.nc) as following: +! (1) pft-level controls of Nfixation by individual plant NPP: Nfix_NPP_c1, Nfix_NPP_c2 +! (2) MR reduction during dormant seasons: dormant_mr_factor, domant_mr_temp +! (3) pft-level 'lwtop_ann' for live woody tissue turnover: lwtop_pfts +! (4) plant rhizomes added as part of roots for all PFTs incl. graminoids: rhizome_long +! +! but, all with default values (i.e. won't change simualtion results from default) +! NOTE: have to copy this file here to $DIN_LOC_ROOT/lnd/clm2/paramdata/ in your system. + paramfile = '$DIN_LOC_ROOT/lnd/clm2/paramdata/clm_params_c211124arctic.nc' diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/arcticpft_onsetgdd_I1850CNPRDCTCBC/clm_params_c211124arctic.nc b/components/elm/cime_config/testdefs/testmods_dirs/elm/arcticpft_onsetgdd_I1850CNPRDCTCBC/clm_params_c211124arctic.nc new file mode 100644 index 000000000000..99d542a8786b Binary files /dev/null and b/components/elm/cime_config/testdefs/testmods_dirs/elm/arcticpft_onsetgdd_I1850CNPRDCTCBC/clm_params_c211124arctic.nc differ diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/arcticpft_onsetgdd_I1850CNPRDCTCBC/shell_commands b/components/elm/cime_config/testdefs/testmods_dirs/elm/arcticpft_onsetgdd_I1850CNPRDCTCBC/shell_commands new file mode 100644 index 000000000000..20e8b625fc1a --- /dev/null +++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/arcticpft_onsetgdd_I1850CNPRDCTCBC/shell_commands @@ -0,0 +1,16 @@ +./xmlchange LND_DOMAIN_FILE=domain_42_FLUXNETSITES_simyr1850_c170912.nc +./xmlchange ATM_DOMAIN_FILE=domain_42_FLUXNETSITES_simyr1850_c170912.nc +./xmlchange LND_DOMAIN_PATH="\$DIN_LOC_ROOT/share/domains/domain.clm" +./xmlchange ATM_DOMAIN_PATH="\$DIN_LOC_ROOT/share/domains/domain.clm" +./xmlchange DATM_MODE=CLM1PT +./xmlchange DATM_CLMNCEP_YR_START=1980 +./xmlchange DATM_CLMNCEP_YR_END=2015 +./xmlchange ELM_USRDAT_NAME=42_FLUXNETSITES +./xmlchange NTASKS=6 +echo " + taxmode = 'cycle','extend','extend' +">>user_nl_datm +# a long run of test for onset_gdd summation ending in arctic, +# but have to xmlchange the following after ./case.setup called +# ./xmlchange --file env_test.xml STOP_N=200 +# ./xmlchange --file env_test.xml STOP_OPTION=nyears diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/arcticpft_onsetgdd_I1850CNPRDCTCBC/user_nl_elm b/components/elm/cime_config/testdefs/testmods_dirs/elm/arcticpft_onsetgdd_I1850CNPRDCTCBC/user_nl_elm new file mode 100644 index 000000000000..0a4a84841066 --- /dev/null +++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/arcticpft_onsetgdd_I1850CNPRDCTCBC/user_nl_elm @@ -0,0 +1,16 @@ +fsurdat = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/surfdata_42_FLUXNETSITES_simyr1850_c170912.nc' +! +! below is a new physioloy file example, from Sulman et al 2021, +! by adding a few parameters into default (clm_params_c211124.nc) as following: +! (1) pft-level controls of Nfixation by individual plant NPP: Nfix_NPP_c1, Nfix_NPP_c2 +! (2) MR reduction during dormant seasons: dormant_mr_factor, domant_mr_temp +! (3) pft-level 'lwtop_ann' for live woody tissue turnover: lwtop_pfts +! (4) plant rhizomes added as part of roots for all PFTs incl. graminoids: rhizome_long +! +! but, all with default values (i.e. won't change simualtion results from default) +! NOTE: have to copy this file here to $DIN_LOC_ROOT/lnd/clm2/paramdata/ in your system, if not yet. + paramfile = '$DIN_LOC_ROOT/lnd/clm2/paramdata/clm_params_c211124arctic.nc' +! +! and also need to turn on a namelist option. +! use_onset_gdd_ext = .true. + diff --git a/components/elm/src/biogeochem/AllocationMod.F90 b/components/elm/src/biogeochem/AllocationMod.F90 index 20815fee2189..76749fd1eb09 100644 --- a/components/elm/src/biogeochem/AllocationMod.F90 +++ b/components/elm/src/biogeochem/AllocationMod.F90 @@ -832,9 +832,12 @@ subroutine Allocation1_PlantNPDemand (bounds, num_soilc, filter_soilc, num_soilp (f3*(1._r8-f4)*(1._r8+f2))/cpdw else - c_allometry(p) = 1._r8+g1+f1+f1*g1 + c_allometry(p) = 1._r8+g1+f1+f1*g1+f3+f3*g1 ! B Sulman: Let graminoids allocate rhizomes (all livecroot) using stem_leaf parameter n_allometry(p) = 1._r8/cnl + f1/cnfr + if(cnlw>0) n_allometry(p) = n_allometry(p) + f3/cnlw ! Rhizomes p_allometry(p) = 1._r8/cpl + f1/cpfr + if(cplw>0) p_allometry(p) = p_allometry(p) + f3/cplw ! Rhizomes + end if plant_ndemand(p) = availc(p)*(n_allometry(p)/c_allometry(p)) plant_pdemand(p) = availc(p)*(p_allometry(p)/c_allometry(p)) @@ -2589,6 +2592,10 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & 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) + else + ! Assume "stem" allocation in graminoids goes to rhizomes which are all live wood (B Sulman) + cpool_to_livecrootc(p) = nlc * f3 * fcur + cpool_to_livecrootc_storage(p) = nlc * f3 * (1._r8 - fcur) end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops cpool_to_livestemc(p) = nlc * f3 * f4 * fcur @@ -2642,6 +2649,10 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & 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) + elseif (cnlw > 0.0_r8) then + ! Assume "stem" allocation in graminoids goes to rhizomes which are all live wood (B Sulman) + npool_to_livecrootn(p) = (nlc * f3 / cnlw ) * fcur + npool_to_livecrootn_storage(p) = (nlc * f3 / cnlw ) * (1._r8 - fcur) end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops cng = graincn(ivt(p)) @@ -2686,6 +2697,10 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & ppool_to_livecrootp_storage(p) = (nlc * f2 * f3 * f4 / cplw) * (1._r8 -fcur) ppool_to_deadcrootp(p) = (nlc * f2 * f3 * (1._r8 - f4) / cpdw)* fcur ppool_to_deadcrootp_storage(p) = (nlc * f2 * f3 * (1._r8 - f4) / cpdw)* (1._r8 - fcur) + elseif (cplw > 0.0_r8) then + ! Assume "stem" allocation in graminoids goes to rhizomes which are all live wood (B Sulman) + ppool_to_livecrootp(p) = (nlc * f3 / cplw ) * fcur + ppool_to_livecrootp_storage(p) = (nlc * f3 / cplw ) * (1._r8 - fcur) end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops cpg = graincp(ivt(p)) @@ -2711,10 +2726,10 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & ! growth is assigned here. gresp_storage = cpool_to_leafc_storage(p) + cpool_to_frootc_storage(p) - if (woody(ivt(p)) == 1._r8) then + gresp_storage = gresp_storage + cpool_to_livecrootc_storage(p) !Graminoid rhizomes (B Sulman) + if (woody(ivt(p)) >= 1.0_r8) then gresp_storage = gresp_storage + cpool_to_livestemc_storage(p) gresp_storage = gresp_storage + cpool_to_deadstemc_storage(p) - gresp_storage = gresp_storage + cpool_to_livecrootc_storage(p) gresp_storage = gresp_storage + cpool_to_deadcrootc_storage(p) end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops diff --git a/components/elm/src/biogeochem/CarbonIsoFluxMod.F90 b/components/elm/src/biogeochem/CarbonIsoFluxMod.F90 index 9def36df40cc..3a6261fdbf0a 100644 --- a/components/elm/src/biogeochem/CarbonIsoFluxMod.F90 +++ b/components/elm/src/biogeochem/CarbonIsoFluxMod.F90 @@ -131,6 +131,11 @@ subroutine CarbonIsoFlux1(num_soilc, filter_soilc, num_soilp, filter_soilp, & isoveg_cf%livecrootc_to_deadcrootc , veg_cf%livecrootc_to_deadcrootc, & isoveg_cs%livecrootc , veg_cs%livecrootc, & num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CarbonIsoFluxCalc(& + isoveg_cf%livecrootc_to_litter , veg_cf%livecrootc_to_litter, & + isoveg_cs%livecrootc , veg_cs%livecrootc, & + num_soilp , filter_soilp, 1._r8, 0, isotope) call CarbonIsoFluxCalc(& isoveg_cf%leaf_curmr , veg_cf%leaf_curmr, & @@ -937,9 +942,11 @@ subroutine CNCIsoLitterToColumn (num_soilc, filter_soilc, & leaf_prof => cnstate_vars%leaf_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of leaves froot_prof => cnstate_vars%froot_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of fine roots + croot_prof => cnstate_vars%croot_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of coarse roots leafc_to_litter => veg_cf%leafc_to_litter , & ! Input: [real(r8) (:) ] frootc_to_litter => veg_cf%frootc_to_litter , & ! Input: [real(r8) (:) ] + livecrootc_to_litter => veg_cf%livecrootc_to_litter , & ! Input: [real(r8) (:) ] phenology_c_to_litr_met_c => col_cf%phenology_c_to_litr_met_c , & ! InOut: [real(r8) (:,:) ] C fluxes associated with phenology (litterfall and crop) to litter metabolic pool (gC/m3/s) phenology_c_to_litr_cel_c => col_cf%phenology_c_to_litr_cel_c , & ! InOut: [real(r8) (:,:) ] C fluxes associated with phenology (litterfall and crop) to litter cellulose pool (gC/m3/s) phenology_c_to_litr_lig_c => col_cf%phenology_c_to_litr_lig_c & ! InOut: [real(r8) (:,:) ] C fluxes associated with phenology (litterfall and crop) to litter lignin pool (gC/m3/s) @@ -968,6 +975,14 @@ 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) + + ! nonwoody rhizome litter carbon fluxes + phenology_c_to_litr_met_c(c,j) = phenology_c_to_litr_met_c(c,j) & + + livecrootc_to_litter(p) * fr_flab(ivt(p)) * wtcol(p) * croot_prof(p,j) + phenology_c_to_litr_cel_c(c,j) = phenology_c_to_litr_cel_c(c,j) & + + livecrootc_to_litter(p) * fr_fcel(ivt(p)) * wtcol(p) * croot_prof(p,j) + phenology_c_to_litr_lig_c(c,j) = phenology_c_to_litr_lig_c(c,j) & + + livecrootc_to_litter(p) * fr_flig(ivt(p)) * wtcol(p) * croot_prof(p,j) end if end if diff --git a/components/elm/src/biogeochem/CarbonStateUpdate1Mod.F90 b/components/elm/src/biogeochem/CarbonStateUpdate1Mod.F90 index 057fd0e56b6e..ddb6dbe7e4bc 100644 --- a/components/elm/src/biogeochem/CarbonStateUpdate1Mod.F90 +++ b/components/elm/src/biogeochem/CarbonStateUpdate1Mod.F90 @@ -274,13 +274,13 @@ subroutine CarbonStateUpdate1(bounds, & veg_cs%leafc_xfer(p) = veg_cs%leafc_xfer(p) - veg_cf%leafc_xfer_to_leafc(p)*dt veg_cs%frootc(p) = veg_cs%frootc(p) + veg_cf%frootc_xfer_to_frootc(p)*dt veg_cs%frootc_xfer(p) = veg_cs%frootc_xfer(p) - veg_cf%frootc_xfer_to_frootc(p)*dt - if (woody(ivt(p)) == 1._r8) then + veg_cs%livecrootc(p) = veg_cs%livecrootc(p) + veg_cf%livecrootc_xfer_to_livecrootc(p)*dt + veg_cs%livecrootc_xfer(p) = veg_cs%livecrootc_xfer(p) - veg_cf%livecrootc_xfer_to_livecrootc(p)*dt + if (woody(ivt(p)) >= 1.0_r8) then veg_cs%livestemc(p) = veg_cs%livestemc(p) + veg_cf%livestemc_xfer_to_livestemc(p)*dt veg_cs%livestemc_xfer(p) = veg_cs%livestemc_xfer(p) - veg_cf%livestemc_xfer_to_livestemc(p)*dt veg_cs%deadstemc(p) = veg_cs%deadstemc(p) + veg_cf%deadstemc_xfer_to_deadstemc(p)*dt veg_cs%deadstemc_xfer(p) = veg_cs%deadstemc_xfer(p) - veg_cf%deadstemc_xfer_to_deadstemc(p)*dt - veg_cs%livecrootc(p) = veg_cs%livecrootc(p) + veg_cf%livecrootc_xfer_to_livecrootc(p)*dt - veg_cs%livecrootc_xfer(p) = veg_cs%livecrootc_xfer(p) - veg_cf%livecrootc_xfer_to_livecrootc(p)*dt veg_cs%deadcrootc(p) = veg_cs%deadcrootc(p) + veg_cf%deadcrootc_xfer_to_deadcrootc(p)*dt veg_cs%deadcrootc_xfer(p) = veg_cs%deadcrootc_xfer(p) - veg_cf%deadcrootc_xfer_to_deadcrootc(p)*dt end if @@ -297,11 +297,13 @@ subroutine CarbonStateUpdate1(bounds, & veg_cs%frootc(p) = veg_cs%frootc(p) - veg_cf%frootc_to_litter(p)*dt ! livewood turnover fluxes - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1._r8) then veg_cs%livestemc(p) = veg_cs%livestemc(p) - veg_cf%livestemc_to_deadstemc(p)*dt veg_cs%deadstemc(p) = veg_cs%deadstemc(p) + veg_cf%livestemc_to_deadstemc(p)*dt veg_cs%livecrootc(p) = veg_cs%livecrootc(p) - veg_cf%livecrootc_to_deadcrootc(p)*dt veg_cs%deadcrootc(p) = veg_cs%deadcrootc(p) + veg_cf%livecrootc_to_deadcrootc(p)*dt + else ! nonwoody rhizome turnover (B Sulman) + veg_cs%livecrootc(p) = veg_cs%livecrootc(p) - veg_cf%livecrootc_to_litter(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops veg_cs%livestemc(p) = veg_cs%livestemc(p) - veg_cf%livestemc_to_litter(p)*dt @@ -315,9 +317,9 @@ subroutine CarbonStateUpdate1(bounds, & veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_to_xsmrpool(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%leaf_curmr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%froot_curmr(p)*dt - if (woody(ivt(p)) == 1._r8) then - veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%livestem_curmr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%livecroot_curmr(p)*dt + if (woody(ivt(p)) >= 1.0_r8) then + veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%livestem_curmr(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%livestem_curmr(p)*dt @@ -330,12 +332,12 @@ subroutine CarbonStateUpdate1(bounds, & veg_cs%xsmrpool(p) = veg_cs%xsmrpool(p) + veg_cf%cpool_to_xsmrpool(p)*dt veg_cs%xsmrpool(p) = veg_cs%xsmrpool(p) - veg_cf%leaf_xsmr(p)*dt veg_cs%xsmrpool(p) = veg_cs%xsmrpool(p) - veg_cf%froot_xsmr(p)*dt + veg_cs%xsmrpool(p) = veg_cs%xsmrpool(p) - veg_cf%livecroot_xsmr(p)*dt if (nu_com .ne. 'RD') then veg_cs%xsmrpool(p) = veg_cs%xsmrpool(p) - veg_cf%xsmrpool_turnover(p)*dt end if - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_cs%xsmrpool(p) = veg_cs%xsmrpool(p) - veg_cf%livestem_xsmr(p)*dt - veg_cs%xsmrpool(p) = veg_cs%xsmrpool(p) - veg_cf%livecroot_xsmr(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops veg_cs%xsmrpool(p) = veg_cs%xsmrpool(p) - veg_cf%livestem_xsmr(p)*dt @@ -355,7 +357,11 @@ subroutine CarbonStateUpdate1(bounds, & veg_cs%frootc(p) = veg_cs%frootc(p) + veg_cf%cpool_to_frootc(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_to_frootc_storage(p)*dt veg_cs%frootc_storage(p) = veg_cs%frootc_storage(p) + veg_cf%cpool_to_frootc_storage(p)*dt - if (woody(ivt(p)) == 1._r8) then + veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_to_livecrootc(p)*dt + veg_cs%livecrootc(p) = veg_cs%livecrootc(p) + veg_cf%cpool_to_livecrootc(p)*dt + veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_to_livecrootc_storage(p)*dt + veg_cs%livecrootc_storage(p) = veg_cs%livecrootc_storage(p) + veg_cf%cpool_to_livecrootc_storage(p)*dt + if (woody(ivt(p)) >= 1.0_r8) then veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_to_livestemc(p)*dt veg_cs%livestemc(p) = veg_cs%livestemc(p) + veg_cf%cpool_to_livestemc(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_to_livestemc_storage(p)*dt @@ -364,10 +370,6 @@ subroutine CarbonStateUpdate1(bounds, & veg_cs%deadstemc(p) = veg_cs%deadstemc(p) + veg_cf%cpool_to_deadstemc(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_to_deadstemc_storage(p)*dt veg_cs%deadstemc_storage(p) = veg_cs%deadstemc_storage(p) + veg_cf%cpool_to_deadstemc_storage(p)*dt - veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_to_livecrootc(p)*dt - veg_cs%livecrootc(p) = veg_cs%livecrootc(p) + veg_cf%cpool_to_livecrootc(p)*dt - veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_to_livecrootc_storage(p)*dt - veg_cs%livecrootc_storage(p) = veg_cs%livecrootc_storage(p) + veg_cf%cpool_to_livecrootc_storage(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_to_deadcrootc(p)*dt veg_cs%deadcrootc(p) = veg_cs%deadcrootc(p) + veg_cf%cpool_to_deadcrootc(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_to_deadcrootc_storage(p)*dt @@ -387,10 +389,10 @@ subroutine CarbonStateUpdate1(bounds, & ! growth respiration fluxes for current growth veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_leaf_gr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_froot_gr(p)*dt - if (woody(ivt(p)) == 1._r8) then + veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_livecroot_gr(p)*dt + if (woody(ivt(p)) >= 1.0_r8) then veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_livestem_gr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_deadstem_gr(p)*dt - veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_livecroot_gr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_deadcroot_gr(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops @@ -401,10 +403,10 @@ subroutine CarbonStateUpdate1(bounds, & ! growth respiration for transfer growth veg_cs%gresp_xfer(p) = veg_cs%gresp_xfer(p) - veg_cf%transfer_leaf_gr(p)*dt veg_cs%gresp_xfer(p) = veg_cs%gresp_xfer(p) - veg_cf%transfer_froot_gr(p)*dt - if (woody(ivt(p)) == 1._r8) then + veg_cs%gresp_xfer(p) = veg_cs%gresp_xfer(p) - veg_cf%transfer_livecroot_gr(p)*dt + if (woody(ivt(p)) >= 1.0_r8) then veg_cs%gresp_xfer(p) = veg_cs%gresp_xfer(p) - veg_cf%transfer_livestem_gr(p)*dt veg_cs%gresp_xfer(p) = veg_cs%gresp_xfer(p) - veg_cf%transfer_deadstem_gr(p)*dt - veg_cs%gresp_xfer(p) = veg_cs%gresp_xfer(p) - veg_cf%transfer_livecroot_gr(p)*dt veg_cs%gresp_xfer(p) = veg_cs%gresp_xfer(p) - veg_cf%transfer_deadcroot_gr(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops @@ -415,10 +417,10 @@ subroutine CarbonStateUpdate1(bounds, & ! growth respiration at time of storage veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_leaf_storage_gr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_froot_storage_gr(p)*dt - if (woody(ivt(p)) == 1._r8) then + veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_livecroot_storage_gr(p)*dt + if (woody(ivt(p)) >= 1.0_r8) then veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_livestem_storage_gr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_deadstem_storage_gr(p)*dt - veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_livecroot_storage_gr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_deadcroot_storage_gr(p)*dt end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops @@ -435,13 +437,13 @@ subroutine CarbonStateUpdate1(bounds, & veg_cs%leafc_xfer(p) = veg_cs%leafc_xfer(p) + veg_cf%leafc_storage_to_xfer(p)*dt veg_cs%frootc_storage(p) = veg_cs%frootc_storage(p) - veg_cf%frootc_storage_to_xfer(p)*dt veg_cs%frootc_xfer(p) = veg_cs%frootc_xfer(p) + veg_cf%frootc_storage_to_xfer(p)*dt - if (woody(ivt(p)) == 1._r8) then + veg_cs%livecrootc_storage(p) = veg_cs%livecrootc_storage(p)- veg_cf%livecrootc_storage_to_xfer(p)*dt + veg_cs%livecrootc_xfer(p) = veg_cs%livecrootc_xfer(p) + veg_cf%livecrootc_storage_to_xfer(p)*dt + if (woody(ivt(p)) >= 1.0_r8) then veg_cs%livestemc_storage(p) = veg_cs%livestemc_storage(p) - veg_cf%livestemc_storage_to_xfer(p)*dt veg_cs%livestemc_xfer(p) = veg_cs%livestemc_xfer(p) + veg_cf%livestemc_storage_to_xfer(p)*dt veg_cs%deadstemc_storage(p) = veg_cs%deadstemc_storage(p) - veg_cf%deadstemc_storage_to_xfer(p)*dt veg_cs%deadstemc_xfer(p) = veg_cs%deadstemc_xfer(p) + veg_cf%deadstemc_storage_to_xfer(p)*dt - veg_cs%livecrootc_storage(p) = veg_cs%livecrootc_storage(p)- veg_cf%livecrootc_storage_to_xfer(p)*dt - veg_cs%livecrootc_xfer(p) = veg_cs%livecrootc_xfer(p) + veg_cf%livecrootc_storage_to_xfer(p)*dt veg_cs%deadcrootc_storage(p) = veg_cs%deadcrootc_storage(p)- veg_cf%deadcrootc_storage_to_xfer(p)*dt veg_cs%deadcrootc_xfer(p) = veg_cs%deadcrootc_xfer(p) + veg_cf%deadcrootc_storage_to_xfer(p)*dt veg_cs%gresp_storage(p) = veg_cs%gresp_storage(p) - veg_cf%gresp_storage_to_xfer(p)*dt diff --git a/components/elm/src/biogeochem/GrowthRespMod.F90 b/components/elm/src/biogeochem/GrowthRespMod.F90 index f499dedb2e0f..ccd60e1b0156 100644 --- a/components/elm/src/biogeochem/GrowthRespMod.F90 +++ b/components/elm/src/biogeochem/GrowthRespMod.F90 @@ -133,7 +133,13 @@ subroutine GrowthResp(num_soilp, filter_soilp) transfer_froot_gr(p) = frootc_xfer_to_frootc(p) * grperc(ivt(p)) * & (1._r8 - grpnow(ivt(p))) - if (woody(ivt(p)) == 1._r8) then + ! B. Sulman: Moved out of woody to allow graminoid rhizomes + cpool_livecroot_gr(p) = cpool_to_livecrootc(p) * grperc(ivt(p)) + cpool_livecroot_storage_gr(p) = cpool_to_livecrootc_storage(p) * & + grperc(ivt(p)) * grpnow(ivt(p)) + transfer_livecroot_gr(p) = livecrootc_xfer_to_livecrootc(p) * & + grperc(ivt(p)) * (1._r8 - grpnow(ivt(p))) + if (woody(ivt(p)) >= 1.0_r8) then cpool_livestem_gr(p) = cpool_to_livestemc(p) * grperc(ivt(p)) cpool_livestem_storage_gr(p) = cpool_to_livestemc_storage(p) * & grperc(ivt(p)) * grpnow(ivt(p)) @@ -144,11 +150,6 @@ subroutine GrowthResp(num_soilp, filter_soilp) grperc(ivt(p)) * grpnow(ivt(p)) transfer_deadstem_gr(p) = deadstemc_xfer_to_deadstemc(p) * & grperc(ivt(p)) * (1._r8 - grpnow(ivt(p))) - cpool_livecroot_gr(p) = cpool_to_livecrootc(p) * grperc(ivt(p)) - cpool_livecroot_storage_gr(p) = cpool_to_livecrootc_storage(p) * & - grperc(ivt(p)) * grpnow(ivt(p)) - transfer_livecroot_gr(p) = livecrootc_xfer_to_livecrootc(p) * & - grperc(ivt(p)) * (1._r8 - grpnow(ivt(p))) cpool_deadcroot_gr(p) = cpool_to_deadcrootc(p) * grperc(ivt(p)) cpool_deadcroot_storage_gr(p) = cpool_to_deadcrootc_storage(p) * & grperc(ivt(p)) * grpnow(ivt(p)) diff --git a/components/elm/src/biogeochem/MaintenanceRespMod.F90 b/components/elm/src/biogeochem/MaintenanceRespMod.F90 index ef83ca92ff60..67de37a576fa 100644 --- a/components/elm/src/biogeochem/MaintenanceRespMod.F90 +++ b/components/elm/src/biogeochem/MaintenanceRespMod.F90 @@ -34,13 +34,19 @@ module MaintenanceRespMod public :: MaintenanceResp public :: readMaintenanceRespParams - type, private :: MaintenanceRespParamsType - real(r8):: br_mr !base rate for maintenance respiration(gC/gN/s) - end type MaintenanceRespParamsType + type, private :: MaintenanceRespParamsType + real(r8):: br_mr !base rate for maintenance respiration(gC/gN/s) + real(r8):: dormant_mr_temp ! Temperature for dormancy (K) + real(r8):: dormant_mr_factor ! Dormancy multiplier for maint resp (unitless) + end type MaintenanceRespParamsType !type(MaintenanceRespParamsType),private :: MaintenanceRespParamsInst real(r8), public :: br_mr_Inst + real(r8), public :: dormant_mr_temp_Inst + real(r8), public :: dormant_mr_factor_Inst !$acc declare create(br_mr_Inst) + !$acc declare create(dormant_mr_temp_Inst) + !$acc declare create(dormant_mr_factor_Inst) !----------------------------------------------------------------------- contains @@ -70,6 +76,28 @@ subroutine readMaintenanceRespParams ( ncid ) call ncd_io(varname=trim(tString),data=tempr, flag='read', ncid=ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(__FILE__, __LINE__)) br_mr_Inst = tempr + + ! Add parameters for dormant maintenance resp + ! dormant_mr_factor is multiplied by maintenance respiration at temperatures below dormant_mr_temp + + tString='dormant_mr_temp' + call ncd_io(varname=trim(tString),data=tempr, flag='read', ncid=ncid, readvar=readv) + ! Default value: 0 (K), so if it's missing the whole process is turned off + if ( .not. readv ) then + dormant_mr_temp_Inst=0.0_r8 + else + dormant_mr_temp_Inst=tempr + end if + + tString='dormant_mr_factor' + call ncd_io(varname=trim(tString),data=tempr, flag='read', ncid=ncid, readvar=readv) + if ( .not. readv ) then + dormant_mr_factor_Inst=1.0_r8 + else + dormant_mr_factor_Inst=tempr + end if + + end subroutine readMaintenanceRespParams @@ -100,6 +128,8 @@ subroutine MaintenanceResp(bounds, & integer :: fp ! soil filter patch index integer :: fc ! soil filter column index real(r8):: br_mr ! base rate (gC/gN/s) + real(r8):: dormant_mr_temp ! Temperature for dormancy + real(r8):: dormant_mr_factor ! Multiplication factor that is applied to Q10 below dormancy temperature real(r8):: q10 ! temperature dependence real(r8):: tc ! temperature correction, 2m air temp (unitless) real(r8):: tcsoi(bounds%begc:bounds%endc,nlevgrnd) ! temperature correction by soil layer (unitless) @@ -144,7 +174,11 @@ subroutine MaintenanceResp(bounds, & ! set constants br_mr = br_mr_Inst - ! Peter Thornton: 3/13/09 + ! Ben Sulman: Adding dormant maintenance resp + dormant_mr_temp = dormant_mr_temp_Inst + dormant_mr_factor = dormant_mr_factor_Inst + + ! Peter Thornton: 3/13/09 ! Q10 was originally set to 2.0, an arbitrary choice, but reduced to 1.5 as part of the tuning ! to improve seasonal cycle of atmospheric CO2 concentration in global ! simulatoins @@ -159,8 +193,12 @@ subroutine MaintenanceResp(bounds, & ! calculate temperature corrections for each soil layer, for use in ! estimating fine root maintenance respiration with depth + ! Ben Sulman: Adding lower dormant maintenance resp below a certain + ! temperature tcsoi(c,j) = Q10**((t_soisno(c,j)-SHR_CONST_TKFRZ - 20.0_r8)/10.0_r8) - + if (t_soisno(c,j) < dormant_mr_temp) then + tcsoi(c,j) = tcsoi(c,j)*dormant_mr_factor + end if end do end do @@ -172,7 +210,12 @@ subroutine MaintenanceResp(bounds, & ! gC/m2/s for each of the live plant tissues. ! Leaf and live wood MR + ! Ben Sulman: Add dormant MR level below a certain temperature tc = Q10**((t_ref2m(p)-SHR_CONST_TKFRZ - 20.0_r8)/10.0_r8) + if(t_ref2m(p) < dormant_mr_temp) then + tc = tc*dormant_mr_factor + end if + if (frac_veg_nosno(p) == 1) then leaf_mr(p) = lmrsun(p) * laisun(p) * 12.011e-6_r8 + & lmrsha(p) * laisha(p) * 12.011e-6_r8 @@ -188,6 +231,8 @@ subroutine MaintenanceResp(bounds, & else if (ivt(p) >= npcropmin .and. livestemn(p) .gt. 0._r8) then livestem_mr(p) = livestemn(p)*br_mr*tc grain_mr(p) = grainn(p)*br_mr*tc + else ! Graminoid rhizomes + livecroot_mr(p) = livecrootn(p)*br_mr*tc end if if (br_xr(ivt(p)) .gt. 1e-9_r8) then xr(p) = cpool(p) * br_xr(ivt(p)) * tc diff --git a/components/elm/src/biogeochem/NitrogenDynamicsMod.F90 b/components/elm/src/biogeochem/NitrogenDynamicsMod.F90 index d585ffae8492..ece997f5bcc2 100644 --- a/components/elm/src/biogeochem/NitrogenDynamicsMod.F90 +++ b/components/elm/src/biogeochem/NitrogenDynamicsMod.F90 @@ -159,6 +159,7 @@ subroutine NitrogenFixation(bounds, num_soilc, filter_soilc, dayspyr) !$acc routine seq use elm_varcon , only : secspday, spval use elm_instMod , only : alm_fates + use pftvarcon , only : noveg ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -169,11 +170,12 @@ subroutine NitrogenFixation(bounds, num_soilc, filter_soilc, dayspyr) ! ! !LOCAL VARIABLES: - integer :: c,fc ! indices + integer :: c,fc,p ! indices integer :: ic ! clump index integer :: s ! site index (fates only) real(r8) :: t ! temporary real(r8) :: secspyr ! seconds per yr + real(r8) :: total_weight logical :: do_et_bnf = .false. ! Test mutliplier of fixation rate, leave as 1 to use base rates @@ -186,7 +188,10 @@ subroutine NitrogenFixation(bounds, num_soilc, filter_soilc, dayspyr) col_lag_npp => col_cf%lag_npp , & ! Input: [real(r8) (:)] (gC/m2/s) lagged net primary production qflx_tran_veg => col_wf%qflx_tran_veg , & ! col vegetation transpiration (mm H2O/s) (+ = to atm) qflx_evap_veg => col_wf%qflx_evap_veg , & ! col vegetation evaporation (mm H2O/s) (+ = to atm) - nfix_to_sminn => col_nf%nfix_to_sminn & ! Output: [real(r8) (:)] symbiotic/asymbiotic N fixation to soil mineral N (gN/m2/s) + nfix_to_sminn => col_nf%nfix_to_sminn , & ! Output: [real(r8) (:)] symbiotic/asymbiotic N fixation to soil mineral N (gN/m2/s) + + Nfix_NPP_c1 => veg_vp%Nfix_NPP_c1 , & ! Pre-exponential parameter for NPP_based N fixation + Nfix_NPP_c2 => veg_vp%Nfix_NPP_c2 & ! Exponential parameter for NPP_based N fixation ) @@ -219,23 +224,48 @@ subroutine NitrogenFixation(bounds, num_soilc, filter_soilc, dayspyr) ! use exponential relaxation with time constant nfix_timeconst for NPP - NFIX relation ! Loop through columns do fc = 1,num_soilc - c = filter_soilc(fc) - + c = filter_soilc(fc) + ! B. Sulman: Loop through patches. Nfix is weighted average of value for each PFT's parameters + t = 0.0_r8 if (col_lag_npp(c) /= spval) then - ! need to put npp in units of gC/m^2/year here first - t = test_mult*(1.8_r8 * (1._r8 - exp(-0.003_r8 * col_lag_npp(c)*(secspday * dayspyr))))/(secspday * dayspyr) - nfix_to_sminn(c) = max(0._r8,t) + total_weight = 0.0_r8 ! To correct for inactive and unveg cells + do p = col_pp%pfti(c), col_pp%pftf(c) + ! need to put npp in units of gC/m^2/year here first + ! B. Sulman: calculate Nfix value for each patch's parameters, and add to weighted average + if (veg_pp%active(p) .and. (veg_pp%itype(p) .ne. noveg)) then + t = t + max(0._r8,veg_pp%wtcol(p)*(Nfix_NPP_c1(veg_pp%itype(p)) * & + (1._r8 - exp(-Nfix_NPP_c2(veg_pp%itype(p)) * col_lag_npp(c)*(secspday * dayspyr))))/(secspday * dayspyr)) + total_weight = total_weight + veg_pp%wtcol(p) + endif + enddo + if(total_weight>0) then + nfix_to_sminn(c) = max(0._r8,t/total_weight) + else + nfix_to_sminn(c) = 0._r8 + endif else - nfix_to_sminn(c) = 0._r8 + nfix_to_sminn(c) = 0._r8 endif end do else ! use annual-mean values for NPP-NFIX relation do fc = 1,num_soilc c = filter_soilc(fc) - - t = test_mult*(1.8_r8 * (1._r8 - exp(-0.003_r8 * cannsum_npp(c))))/(secspday * dayspyr) - nfix_to_sminn(c) = max(0._r8,t) + ! B. Sulman: Loop through patches. Nfix is weighted average of value for each PFT's parameters + t = 0.0_r8 + total_weight = 0.0_r8 + do p = col_pp%pfti(c), col_pp%pftf(c) + if (veg_pp%active(p) .and. (veg_pp%itype(p) .ne. noveg)) then + t = t + max(0._r8,veg_pp%wtcol(p)*(Nfix_NPP_c1(veg_pp%itype(p)) * & + (1._r8 - exp(-Nfix_NPP_c2(veg_pp%itype(p)) * cannsum_npp(c))))/(secspday * dayspyr)) + total_weight = total_weight + veg_pp%wtcol(p) + endif + enddo + if (total_weight>0) then + nfix_to_sminn(c) = max(0._r8,t/total_weight) + else + nfix_to_sminn(c) = 0.0_r8 + endif end do endif end if diff --git a/components/elm/src/biogeochem/NitrogenStateUpdate1Mod.F90 b/components/elm/src/biogeochem/NitrogenStateUpdate1Mod.F90 index 1eefadd7bead..c9941fe4ba07 100644 --- a/components/elm/src/biogeochem/NitrogenStateUpdate1Mod.F90 +++ b/components/elm/src/biogeochem/NitrogenStateUpdate1Mod.F90 @@ -285,14 +285,14 @@ subroutine NitrogenStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp veg_ns%leafn_xfer(p) = veg_ns%leafn_xfer(p) - veg_nf%leafn_xfer_to_leafn(p)*dt veg_ns%frootn(p) = veg_ns%frootn(p) + veg_nf%frootn_xfer_to_frootn(p)*dt veg_ns%frootn_xfer(p) = veg_ns%frootn_xfer(p) - veg_nf%frootn_xfer_to_frootn(p)*dt + veg_ns%livecrootn(p) = veg_ns%livecrootn(p) + veg_nf%livecrootn_xfer_to_livecrootn(p)*dt + veg_ns%livecrootn_xfer(p) = veg_ns%livecrootn_xfer(p) - veg_nf%livecrootn_xfer_to_livecrootn(p)*dt - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_ns%livestemn(p) = veg_ns%livestemn(p) + veg_nf%livestemn_xfer_to_livestemn(p)*dt veg_ns%livestemn_xfer(p) = veg_ns%livestemn_xfer(p) - veg_nf%livestemn_xfer_to_livestemn(p)*dt veg_ns%deadstemn(p) = veg_ns%deadstemn(p) + veg_nf%deadstemn_xfer_to_deadstemn(p)*dt veg_ns%deadstemn_xfer(p) = veg_ns%deadstemn_xfer(p) - veg_nf%deadstemn_xfer_to_deadstemn(p)*dt - veg_ns%livecrootn(p) = veg_ns%livecrootn(p) + veg_nf%livecrootn_xfer_to_livecrootn(p)*dt - veg_ns%livecrootn_xfer(p) = veg_ns%livecrootn_xfer(p) - veg_nf%livecrootn_xfer_to_livecrootn(p)*dt veg_ns%deadcrootn(p) = veg_ns%deadcrootn(p) + veg_nf%deadcrootn_xfer_to_deadcrootn(p)*dt veg_ns%deadcrootn_xfer(p) = veg_ns%deadcrootn_xfer(p) - veg_nf%deadcrootn_xfer_to_deadcrootn(p)*dt end if @@ -312,7 +312,7 @@ subroutine NitrogenStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp veg_ns%retransn(p) = veg_ns%retransn(p) + veg_nf%leafn_to_retransn(p)*dt ! live wood turnover and retranslocation fluxes - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_ns%livestemn(p) = veg_ns%livestemn(p) - veg_nf%livestemn_to_deadstemn(p)*dt veg_ns%deadstemn(p) = veg_ns%deadstemn(p) + veg_nf%livestemn_to_deadstemn(p)*dt veg_ns%livestemn(p) = veg_ns%livestemn(p) - veg_nf%livestemn_to_retransn(p)*dt @@ -321,6 +321,10 @@ subroutine NitrogenStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp veg_ns%deadcrootn(p) = veg_ns%deadcrootn(p) + veg_nf%livecrootn_to_deadcrootn(p)*dt veg_ns%livecrootn(p) = veg_ns%livecrootn(p) - veg_nf%livecrootn_to_retransn(p)*dt veg_ns%retransn(p) = veg_ns%retransn(p) + veg_nf%livecrootn_to_retransn(p)*dt + else ! Nonwoody rhizome turnover (B Sulman) + veg_ns%livecrootn(p) = veg_ns%livecrootn(p) - veg_nf%livecrootn_to_litter(p)*dt + veg_ns%livecrootn(p) = veg_ns%livecrootn(p) - veg_nf%livecrootn_to_retransn(p)*dt + veg_ns%retransn(p) = veg_ns%retransn(p) + veg_nf%livecrootn_to_retransn(p)*dt end if if (ivt(p) >= npcropmin) then ! Beth adds retrans from froot veg_ns%frootn(p) = veg_ns%frootn(p) - veg_nf%frootn_to_retransn(p)*dt @@ -353,8 +357,12 @@ subroutine NitrogenStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp veg_ns%frootn(p) = veg_ns%frootn(p) + veg_nf%npool_to_frootn(p)*dt veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_frootn_storage(p)*dt veg_ns%frootn_storage(p) = veg_ns%frootn_storage(p) + veg_nf%npool_to_frootn_storage(p)*dt + veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_livecrootn(p)*dt + veg_ns%livecrootn(p) = veg_ns%livecrootn(p) + veg_nf%npool_to_livecrootn(p)*dt + veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_livecrootn_storage(p)*dt + veg_ns%livecrootn_storage(p) = veg_ns%livecrootn_storage(p) + veg_nf%npool_to_livecrootn_storage(p)*dt - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_livestemn(p)*dt veg_ns%livestemn(p) = veg_ns%livestemn(p) + veg_nf%npool_to_livestemn(p)*dt veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_livestemn_storage(p)*dt @@ -363,10 +371,6 @@ subroutine NitrogenStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp veg_ns%deadstemn(p) = veg_ns%deadstemn(p) + veg_nf%npool_to_deadstemn(p)*dt veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_deadstemn_storage(p)*dt veg_ns%deadstemn_storage(p) = veg_ns%deadstemn_storage(p) + veg_nf%npool_to_deadstemn_storage(p)*dt - veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_livecrootn(p)*dt - veg_ns%livecrootn(p) = veg_ns%livecrootn(p) + veg_nf%npool_to_livecrootn(p)*dt - veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_livecrootn_storage(p)*dt - veg_ns%livecrootn_storage(p) = veg_ns%livecrootn_storage(p) + veg_nf%npool_to_livecrootn_storage(p)*dt veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_deadcrootn(p)*dt veg_ns%deadcrootn(p) = veg_ns%deadcrootn(p) + veg_nf%npool_to_deadcrootn(p)*dt veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_deadcrootn_storage(p)*dt @@ -389,14 +393,14 @@ subroutine NitrogenStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp veg_ns%leafn_xfer(p) = veg_ns%leafn_xfer(p) + veg_nf%leafn_storage_to_xfer(p)*dt veg_ns%frootn_storage(p) = veg_ns%frootn_storage(p) - veg_nf%frootn_storage_to_xfer(p)*dt veg_ns%frootn_xfer(p) = veg_ns%frootn_xfer(p) + veg_nf%frootn_storage_to_xfer(p)*dt + veg_ns%livecrootn_storage(p) = veg_ns%livecrootn_storage(p) - veg_nf%livecrootn_storage_to_xfer(p)*dt + veg_ns%livecrootn_xfer(p) = veg_ns%livecrootn_xfer(p) + veg_nf%livecrootn_storage_to_xfer(p)*dt - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_ns%livestemn_storage(p) = veg_ns%livestemn_storage(p) - veg_nf%livestemn_storage_to_xfer(p)*dt veg_ns%livestemn_xfer(p) = veg_ns%livestemn_xfer(p) + veg_nf%livestemn_storage_to_xfer(p)*dt veg_ns%deadstemn_storage(p) = veg_ns%deadstemn_storage(p) - veg_nf%deadstemn_storage_to_xfer(p)*dt veg_ns%deadstemn_xfer(p) = veg_ns%deadstemn_xfer(p) + veg_nf%deadstemn_storage_to_xfer(p)*dt - veg_ns%livecrootn_storage(p) = veg_ns%livecrootn_storage(p) - veg_nf%livecrootn_storage_to_xfer(p)*dt - veg_ns%livecrootn_xfer(p) = veg_ns%livecrootn_xfer(p) + veg_nf%livecrootn_storage_to_xfer(p)*dt veg_ns%deadcrootn_storage(p) = veg_ns%deadcrootn_storage(p) - veg_nf%deadcrootn_storage_to_xfer(p)*dt veg_ns%deadcrootn_xfer(p) = veg_ns%deadcrootn_xfer(p) + veg_nf%deadcrootn_storage_to_xfer(p)*dt end if diff --git a/components/elm/src/biogeochem/PhenologyFluxLimitMod.F90 b/components/elm/src/biogeochem/PhenologyFluxLimitMod.F90 index b6d05460c0bb..7b5df104f847 100644 --- a/components/elm/src/biogeochem/PhenologyFluxLimitMod.F90 +++ b/components/elm/src/biogeochem/PhenologyFluxLimitMod.F90 @@ -75,6 +75,7 @@ module PhenologyFLuxLimitMod integer :: f_livecrootc_xfer_to_livecrootc integer :: f_livecrootc_storage_to_xfer integer :: f_livecrootc_to_deadcrootc + integer :: f_livecrootc_to_litter integer :: f_deadcrootc_xfer_to_deadcrootc integer :: f_deadcrootc_storage_to_xfer integer :: f_grainc_to_food @@ -139,6 +140,7 @@ module PhenologyFLuxLimitMod integer :: f_livecrootn_storage_to_xfer integer :: f_livecrootn_xfer_to_livecrootn integer :: f_livecrootn_to_deadcrootn + integer :: f_livecrootn_to_litter integer :: f_livecrootn_to_retransn integer :: f_deadstemn_storage_to_xfer integer :: f_deadstemn_xfer_to_deadstem @@ -264,6 +266,7 @@ subroutine init_phenofluxl_counters() f_livecrootc_xfer_to_livecrootc= ic_next(id) f_livecrootc_storage_to_xfer = ic_next(id) f_livecrootc_to_deadcrootc = ic_next(id) + f_livecrootc_to_litter = ic_next(id) f_deadcrootc_xfer_to_deadcrootc= ic_next(id) f_deadcrootc_storage_to_xfer = ic_next(id) f_grainc_to_food = ic_next(id) @@ -329,6 +332,7 @@ subroutine init_phenofluxl_counters() f_livestemn_to_retransn = ic_next(id) f_livestemn_to_deadstemn = ic_next(id) f_livecrootn_to_deadcrootn = ic_next(id) + f_livecrootn_to_litter = ic_next(id) f_livecrootn_to_retransn = ic_next(id) f_livecrootn_storage_to_xfer = ic_next(id) f_livecrootn_xfer_to_livecrootn = ic_next(id) @@ -387,6 +391,7 @@ subroutine InitPhenoFluxLimiter() call spm_list_insert(spm_list, -1._r8, f_deadstemc_xfer_to_deadstemc , s_deadstemc_xfer, nelms) call spm_list_insert(spm_list, -1._r8, f_deadstemc_storage_to_xfer , s_deadstemc_storage, nelms) call spm_list_insert(spm_list, -1._r8, f_livecrootc_to_deadcrootc , s_livecrootc, nelms) + call spm_list_insert(spm_list, -1._r8, f_livecrootc_to_litter , s_livecrootc, nelms) call spm_list_insert(spm_list, -1._r8, f_livecrootc_xfer_to_livecrootc, s_livecrootc_xfer, nelms) call spm_list_insert(spm_list, -1._r8, f_livecrootc_storage_to_xfer , s_livecrootc_storage, nelms) call spm_list_insert(spm_list, -1._r8, f_deadcrootc_xfer_to_deadcrootc, s_deadcrootc_xfer, nelms) @@ -630,13 +635,13 @@ subroutine carbon_flux_limiter(bounds, num_soilc, filter_soilc,& ystates(s_frootc) = veg_cs%frootc(p) ystates(s_frootc_xfer) = veg_cs%frootc_xfer(p) ystates(s_frootc_storage) = veg_cs%frootc_storage(p) - if (woody(ivt(p)) == 1._r8) then + ystates(s_livecrootc) = veg_cs%livecrootc(p) + ystates(s_livecrootc_xfer) = veg_cs%livecrootc_xfer(p) + ystates(s_livecrootc_storage) = veg_cs%livecrootc_storage(p) + if (woody(ivt(p)) >= 1.0_r8) then ystates(s_livestemc) = veg_cs%livestemc(p) ystates(s_livestemc_xfer) = veg_cs%livestemc_xfer(p) ystates(s_livestemc_storage) = veg_cs%livestemc_storage(p) - ystates(s_livecrootc) = veg_cs%livecrootc(p) - ystates(s_livecrootc_xfer) = veg_cs%livecrootc_xfer(p) - ystates(s_livecrootc_storage) = veg_cs%livecrootc_storage(p) ystates(s_deadstemc) = veg_cs%deadstemc(p) ystates(s_deadstemc_xfer) = veg_cs%deadstemc_xfer(p) ystates(s_deadstemc_storage) = veg_cs%deadstemc_storage(p) @@ -661,18 +666,18 @@ subroutine carbon_flux_limiter(bounds, num_soilc, filter_soilc,& + veg_cf%cpool_leaf_gr(p) & + veg_cf%cpool_froot_gr(p) & + veg_cf%cpool_leaf_storage_gr(p) & - + veg_cf%cpool_froot_storage_gr(p) - if (woody(ivt(p)) == 1._r8) then + + veg_cf%cpool_froot_storage_gr(p) & + + veg_cf%livecroot_curmr(p) & + + veg_cf%cpool_livecroot_gr(p) & + + veg_cf%cpool_livecroot_storage_gr(p) + if (woody(ivt(p)) >= 1.0_r8) then ar_p = ar_p & + veg_cf%livestem_curmr(p) & - + veg_cf%livecroot_curmr(p) & + veg_cf%cpool_livestem_gr(p) & + veg_cf%cpool_deadstem_gr(p) & - + veg_cf%cpool_livecroot_gr(p) & + veg_cf%cpool_deadcroot_gr(p) & + veg_cf%cpool_livestem_storage_gr(p) & + veg_cf%cpool_deadstem_storage_gr(p) & - + veg_cf%cpool_livecroot_storage_gr(p) & + veg_cf%cpool_deadcroot_storage_gr(p) endif if (ivt(p) >= npcropmin) then @@ -692,13 +697,17 @@ subroutine carbon_flux_limiter(bounds, num_soilc, filter_soilc,& rfluxes(f_cpool_to_xsmrpool) = veg_cf%cpool_to_xsmrpool(p) rfluxes(f_cpool_to_gresp_storage) = veg_cf%cpool_to_gresp_storage(p) rfluxes(f_cpool_to_ar) = ar_p - if (woody(ivt(p)) == 1._r8) then + rfluxes(f_cpool_to_livecrootc) = veg_cf%cpool_to_livecrootc(p) + rfluxes(f_cpool_to_livecrootc_storage) = veg_cf%cpool_to_livecrootc_storage(p) + rfluxes(f_livecrootc_xfer_to_livecrootc)= veg_cf%livecrootc_xfer_to_livecrootc(p) + rfluxes(f_livecrootc_storage_to_xfer) = veg_cf%livecrootc_storage_to_xfer(p) + rfluxes(f_livecrootc_to_deadcrootc) = veg_cf%livecrootc_to_deadcrootc(p) + rfluxes(f_livecrootc_to_litter) = veg_cf%livecrootc_to_litter(p) + if (woody(ivt(p)) >= 1.0_r8) then rfluxes(f_cpool_to_livestemc) = veg_cf%cpool_to_livestemc(p) rfluxes(f_cpool_to_livestemc_storage) = veg_cf%cpool_to_livestemc_storage(p) rfluxes(f_cpool_to_deadstemc) = veg_cf%cpool_to_deadstemc(p) rfluxes(f_cpool_to_deadstemc_storage) = veg_cf%cpool_to_deadstemc_storage(p) - rfluxes(f_cpool_to_livecrootc) = veg_cf%cpool_to_livecrootc(p) - rfluxes(f_cpool_to_livecrootc_storage) = veg_cf%cpool_to_livecrootc_storage(p) rfluxes(f_cpool_to_deadcrootc) = veg_cf%cpool_to_deadcrootc(p) rfluxes(f_cpool_to_deadcrootc_storage) = veg_cf%cpool_to_deadcrootc_storage(p) rfluxes(f_livestemc_to_deadstemc) = veg_cf%livestemc_to_deadstemc(p) @@ -706,9 +715,6 @@ subroutine carbon_flux_limiter(bounds, num_soilc, filter_soilc,& rfluxes(f_livestemc_storage_to_xfer) = veg_cf%livestemc_storage_to_xfer(p) rfluxes(f_deadstemc_xfer_to_deadstemc) = veg_cf%deadstemc_xfer_to_deadstemc(p) rfluxes(f_deadstemc_storage_to_xfer) = veg_cf%deadstemc_storage_to_xfer(p) - rfluxes(f_livecrootc_xfer_to_livecrootc)= veg_cf%livecrootc_xfer_to_livecrootc(p) - rfluxes(f_livecrootc_storage_to_xfer) = veg_cf%livecrootc_storage_to_xfer(p) - rfluxes(f_livecrootc_to_deadcrootc) = veg_cf%livecrootc_to_deadcrootc(p) rfluxes(f_deadcrootc_xfer_to_deadcrootc)= veg_cf%deadcrootc_xfer_to_deadcrootc(p) rfluxes(f_deadcrootc_storage_to_xfer) = veg_cf%deadcrootc_storage_to_xfer(p) rfluxes(f_gresp_storage_to_xfer) = veg_cf%gresp_storage_to_xfer(p) @@ -745,14 +751,18 @@ subroutine carbon_flux_limiter(bounds, num_soilc, filter_soilc,& call fpmax(rfluxes(f_cpool_to_frootc_storage) , veg_cf%cpool_to_frootc_storage(p)) call fpmax(rfluxes(f_cpool_to_xsmrpool) , veg_cf%cpool_to_xsmrpool(p)) call fpmax(rfluxes(f_cpool_to_gresp_storage) , veg_cf%cpool_to_gresp_storage(p)) + call fpmax(rfluxes(f_cpool_to_livecrootc) , veg_cf%cpool_to_livecrootc(p)) + call fpmax(rfluxes(f_cpool_to_livecrootc_storage) , veg_cf%cpool_to_livecrootc_storage(p)) + call fpmax(rfluxes(f_livecrootc_xfer_to_livecrootc), veg_cf%livecrootc_xfer_to_livecrootc(p)) + call fpmax(rfluxes(f_livecrootc_storage_to_xfer) , veg_cf%livecrootc_storage_to_xfer(p)) + call fpmax(rfluxes(f_livecrootc_to_deadcrootc) , veg_cf%livecrootc_to_deadcrootc(p)) + call fpmax(rfluxes(f_livecrootc_to_litter) , veg_cf%livecrootc_to_litter(p)) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then call fpmax(rfluxes(f_cpool_to_livestemc) , veg_cf%cpool_to_livestemc(p)) call fpmax(rfluxes(f_cpool_to_livestemc_storage) , veg_cf%cpool_to_livestemc_storage(p)) call fpmax(rfluxes(f_cpool_to_deadstemc) , veg_cf%cpool_to_deadstemc(p)) call fpmax(rfluxes(f_cpool_to_deadstemc_storage) , veg_cf%cpool_to_deadstemc_storage(p)) - call fpmax(rfluxes(f_cpool_to_livecrootc) , veg_cf%cpool_to_livecrootc(p)) - call fpmax(rfluxes(f_cpool_to_livecrootc_storage) , veg_cf%cpool_to_livecrootc_storage(p)) call fpmax(rfluxes(f_cpool_to_deadcrootc) , veg_cf%cpool_to_deadcrootc(p)) call fpmax(rfluxes(f_cpool_to_deadcrootc_storage) , veg_cf%cpool_to_deadcrootc_storage(p)) call fpmax(rfluxes(f_livestemc_to_deadstemc) , veg_cf%livestemc_to_deadstemc(p)) @@ -760,9 +770,6 @@ subroutine carbon_flux_limiter(bounds, num_soilc, filter_soilc,& call fpmax(rfluxes(f_livestemc_storage_to_xfer) , veg_cf%livestemc_storage_to_xfer(p)) call fpmax(rfluxes(f_deadstemc_xfer_to_deadstemc) , veg_cf%deadstemc_xfer_to_deadstemc(p)) call fpmax(rfluxes(f_deadstemc_storage_to_xfer) , veg_cf%deadstemc_storage_to_xfer(p)) - call fpmax(rfluxes(f_livecrootc_xfer_to_livecrootc), veg_cf%livecrootc_xfer_to_livecrootc(p)) - call fpmax(rfluxes(f_livecrootc_storage_to_xfer) , veg_cf%livecrootc_storage_to_xfer(p)) - call fpmax(rfluxes(f_livecrootc_to_deadcrootc) , veg_cf%livecrootc_to_deadcrootc(p)) call fpmax(rfluxes(f_deadcrootc_xfer_to_deadcrootc), veg_cf%deadcrootc_xfer_to_deadcrootc(p)) call fpmax(rfluxes(f_deadcrootc_storage_to_xfer) , veg_cf%deadcrootc_storage_to_xfer(p)) call fpmax(rfluxes(f_gresp_storage_to_xfer) , veg_cf%gresp_storage_to_xfer(p)) @@ -794,16 +801,16 @@ subroutine carbon_flux_limiter(bounds, num_soilc, filter_soilc,& call ascal(veg_cf%cpool_froot_gr(p) , rscal) call ascal(veg_cf%cpool_leaf_storage_gr(p) , rscal) call ascal(veg_cf%cpool_froot_storage_gr(p) , rscal) - if (woody(ivt(p)) == 1._r8) then + call ascal(veg_cf%livecroot_curmr(p) , rscal) + call ascal(veg_cf%cpool_livecroot_gr(p) , rscal) + call ascal(veg_cf%cpool_livecroot_storage_gr(p), rscal) + if (woody(ivt(p)) >= 1.0_r8) then call ascal(veg_cf%livestem_curmr(p) , rscal) - call ascal(veg_cf%livecroot_curmr(p) , rscal) call ascal(veg_cf%cpool_livestem_gr(p) , rscal) call ascal(veg_cf%cpool_deadstem_gr(p) , rscal) - call ascal(veg_cf%cpool_livecroot_gr(p) , rscal) call ascal(veg_cf%cpool_deadcroot_gr(p) , rscal) call ascal(veg_cf%cpool_livestem_storage_gr(p) , rscal) call ascal(veg_cf%cpool_deadstem_storage_gr(p) , rscal) - call ascal(veg_cf%cpool_livecroot_storage_gr(p), rscal) call ascal(veg_cf%cpool_deadcroot_storage_gr(p), rscal) endif if (ivt(p) >= npcropmin) then @@ -864,16 +871,16 @@ subroutine nitrogen_flux_limiter(bounds, num_soilc, filter_soilc,& ystates(s_frootn) = veg_ns%frootn(p) ystates(s_frootn_xfer) = veg_ns%frootn_xfer(p) ystates(s_frootn_storage) = veg_ns%frootn_storage(p) - if (woody(ivt(p)) == 1.0_r8) then + ystates(s_livecrootn) = veg_ns%livecrootn(p) + ystates(s_livecrootn_xfer) = veg_ns%livecrootn_xfer(p) + ystates(s_livecrootn_storage) = veg_ns%livecrootn_storage(p) + if (woody(ivt(p)) >= 1.0_r8) then ystates(s_livestemn) = veg_ns%livestemn(p) ystates(s_livestemn_xfer) = veg_ns%livestemn_xfer(p) ystates(s_livestemn_storage) = veg_ns%livestemn_storage(p) ystates(s_deadstemn) = veg_ns%deadstemn(p) ystates(s_deadstemn_xfer) = veg_ns%deadstemn_xfer(p) ystates(s_deadstemn_storage) = veg_ns%deadstemn_storage(p) - ystates(s_livecrootn) = veg_ns%livecrootn(p) - ystates(s_livecrootn_xfer) = veg_ns%livecrootn_xfer(p) - ystates(s_livecrootn_storage) = veg_ns%livecrootn_storage(p) ystates(s_deadcrootn) = veg_ns%deadcrootn(p) ystates(s_deadcrootn_xfer) = veg_ns%deadcrootn_xfer(p) ystates(s_deadcrootn_storage) = veg_ns%deadcrootn_storage(p) @@ -894,11 +901,15 @@ subroutine nitrogen_flux_limiter(bounds, num_soilc, filter_soilc,& rfluxes(f_npool_to_leafn_storage) = veg_nf%npool_to_leafn_storage(p) rfluxes(f_npool_to_frootn) = veg_nf%npool_to_frootn(p) rfluxes(f_npool_to_frootn_storage) = veg_nf%npool_to_frootn_storage(p) - if (woody(ivt(p)) == 1.0_r8) then + rfluxes(f_npool_to_livecrootn) = veg_nf%npool_to_livecrootn(p) + rfluxes(f_npool_to_livecrootn_storage) = veg_nf%npool_to_livecrootn_storage(p) + rfluxes(f_livecrootn_to_deadcrootn) = veg_nf%livecrootn_to_deadcrootn(p) + rfluxes(f_livecrootn_to_retransn) = veg_nf%livecrootn_to_retransn(p) + rfluxes(f_livecrootn_storage_to_xfer) = veg_nf%livecrootn_storage_to_xfer(p) + rfluxes(f_livecrootn_xfer_to_livecrootn) = veg_nf%livecrootn_xfer_to_livecrootn(p) + if (woody(ivt(p)) >= 1.0_r8) then rfluxes(f_npool_to_livestemn) = veg_nf%npool_to_livestemn(p) rfluxes(f_npool_to_livestemn_storage) = veg_nf%npool_to_livestemn_storage(p) - rfluxes(f_npool_to_livecrootn) = veg_nf%npool_to_livecrootn(p) - rfluxes(f_npool_to_livecrootn_storage) = veg_nf%npool_to_livecrootn_storage(p) rfluxes(f_npool_to_deadstemn) = veg_nf%npool_to_deadstemn(p) rfluxes(f_npool_to_deadcrootn) = veg_nf%npool_to_deadcrootn(p) rfluxes(f_npool_to_deadstemn_storage) = veg_nf%npool_to_deadstemn_storage(p) @@ -907,10 +918,6 @@ subroutine nitrogen_flux_limiter(bounds, num_soilc, filter_soilc,& rfluxes(f_livestemn_xfer_to_livestemn) = veg_nf%livestemn_xfer_to_livestemn(p) rfluxes(f_livestemn_to_retransn) = veg_nf%livestemn_to_retransn(p) rfluxes(f_livestemn_to_deadstemn) = veg_nf%livestemn_to_deadstemn(p) - rfluxes(f_livecrootn_to_deadcrootn) = veg_nf%livecrootn_to_deadcrootn(p) - rfluxes(f_livecrootn_to_retransn) = veg_nf%livecrootn_to_retransn(p) - rfluxes(f_livecrootn_storage_to_xfer) = veg_nf%livecrootn_storage_to_xfer(p) - rfluxes(f_livecrootn_xfer_to_livecrootn) = veg_nf%livecrootn_xfer_to_livecrootn(p) rfluxes(f_deadstemn_storage_to_xfer) = veg_nf%deadstemn_storage_to_xfer(p) rfluxes(f_deadstemn_xfer_to_deadstem) = veg_nf%deadstemn_xfer_to_deadstemn(p) rfluxes(f_deadcrootn_storage_to_xfer) = veg_nf%deadcrootn_storage_to_xfer(p) @@ -950,11 +957,15 @@ subroutine nitrogen_flux_limiter(bounds, num_soilc, filter_soilc,& call fpmax(rfluxes(f_npool_to_leafn_storage) , veg_nf%npool_to_leafn_storage(p)) call fpmax(rfluxes(f_npool_to_frootn) , veg_nf%npool_to_frootn(p)) call fpmax(rfluxes(f_npool_to_frootn_storage) , veg_nf%npool_to_frootn_storage(p)) - if (woody(ivt(p)) == 1.0_r8) then + call fpmax(rfluxes(f_npool_to_livecrootn) , veg_nf%npool_to_livecrootn(p)) + call fpmax(rfluxes(f_npool_to_livecrootn_storage) , veg_nf%npool_to_livecrootn_storage(p)) + call fpmax(rfluxes(f_livecrootn_to_deadcrootn) , veg_nf%livecrootn_to_deadcrootn(p)) + call fpmax(rfluxes(f_livecrootn_to_retransn) , veg_nf%livecrootn_to_retransn(p)) + call fpmax(rfluxes(f_livecrootn_storage_to_xfer) , veg_nf%livecrootn_storage_to_xfer(p)) + call fpmax(rfluxes(f_livecrootn_xfer_to_livecrootn) , veg_nf%livecrootn_xfer_to_livecrootn(p)) + if (woody(ivt(p)) >= 1.0_r8) then call fpmax(rfluxes(f_npool_to_livestemn) , veg_nf%npool_to_livestemn(p)) call fpmax(rfluxes(f_npool_to_livestemn_storage) , veg_nf%npool_to_livestemn_storage(p)) - call fpmax(rfluxes(f_npool_to_livecrootn) , veg_nf%npool_to_livecrootn(p)) - call fpmax(rfluxes(f_npool_to_livecrootn_storage) , veg_nf%npool_to_livecrootn_storage(p)) call fpmax(rfluxes(f_npool_to_deadstemn) , veg_nf%npool_to_deadstemn(p)) call fpmax(rfluxes(f_npool_to_deadcrootn) , veg_nf%npool_to_deadcrootn(p)) call fpmax(rfluxes(f_npool_to_deadstemn_storage) , veg_nf%npool_to_deadstemn_storage(p)) @@ -963,10 +974,6 @@ subroutine nitrogen_flux_limiter(bounds, num_soilc, filter_soilc,& call fpmax(rfluxes(f_livestemn_xfer_to_livestemn) , veg_nf%livestemn_xfer_to_livestemn(p)) call fpmax(rfluxes(f_livestemn_to_retransn) , veg_nf%livestemn_to_retransn(p)) call fpmax(rfluxes(f_livestemn_to_deadstemn) , veg_nf%livestemn_to_deadstemn(p)) - call fpmax(rfluxes(f_livecrootn_to_deadcrootn) , veg_nf%livecrootn_to_deadcrootn(p)) - call fpmax(rfluxes(f_livecrootn_to_retransn) , veg_nf%livecrootn_to_retransn(p)) - call fpmax(rfluxes(f_livecrootn_storage_to_xfer) , veg_nf%livecrootn_storage_to_xfer(p)) - call fpmax(rfluxes(f_livecrootn_xfer_to_livecrootn) , veg_nf%livecrootn_xfer_to_livecrootn(p)) call fpmax(rfluxes(f_deadstemn_storage_to_xfer) , veg_nf%deadstemn_storage_to_xfer(p)) call fpmax(rfluxes(f_deadstemn_xfer_to_deadstem) , veg_nf%deadstemn_xfer_to_deadstemn(p)) call fpmax(rfluxes(f_deadcrootn_storage_to_xfer) , veg_nf%deadcrootn_storage_to_xfer(p)) @@ -1049,16 +1056,16 @@ subroutine phosphorus_flux_limiter(bounds, num_soilc, filter_soilc,& ystates(s_frootn) = veg_ps%frootp(p) ystates(s_frootn_xfer) = veg_ps%frootp_xfer(p) ystates(s_frootn_storage) = veg_ps%frootp_storage(p) - if (woody(ivt(p)) == 1.0_r8) then + ystates(s_livecrootn) = veg_ps%livecrootp(p) + ystates(s_livecrootn_xfer) = veg_ps%livecrootp_xfer(p) + ystates(s_livecrootn_storage) = veg_ps%livecrootp_storage(p) + if (woody(ivt(p)) >= 1.0_r8) then ystates(s_livestemn) = veg_ps%livestemp(p) ystates(s_livestemn_xfer) = veg_ps%livestemp_xfer(p) ystates(s_livestemn_storage) = veg_ps%livestemp_storage(p) ystates(s_deadstemn) = veg_ps%deadstemp(p) ystates(s_deadstemn_xfer) = veg_ps%deadstemp_xfer(p) ystates(s_deadstemn_storage) = veg_ps%deadstemp_storage(p) - ystates(s_livecrootn) = veg_ps%livecrootp(p) - ystates(s_livecrootn_xfer) = veg_ps%livecrootp_xfer(p) - ystates(s_livecrootn_storage) = veg_ps%livecrootp_storage(p) ystates(s_deadcrootn) = veg_ps%deadcrootp(p) ystates(s_deadcrootn_xfer) = veg_ps%deadcrootp_xfer(p) ystates(s_deadcrootn_storage) = veg_ps%deadcrootp_storage(p) @@ -1079,11 +1086,15 @@ subroutine phosphorus_flux_limiter(bounds, num_soilc, filter_soilc,& rfluxes(f_npool_to_leafn_storage) = veg_pf%ppool_to_leafp_storage(p) rfluxes(f_npool_to_frootn) = veg_pf%ppool_to_frootp(p) rfluxes(f_npool_to_frootn_storage) = veg_pf%ppool_to_frootp_storage(p) - if (woody(ivt(p)) == 1._r8) then + rfluxes(f_npool_to_livecrootn) = veg_pf%ppool_to_livecrootp(p) + rfluxes(f_npool_to_livecrootn_storage) = veg_pf%ppool_to_livecrootp_storage(p) + rfluxes(f_livecrootn_to_deadcrootn) = veg_pf%livecrootp_to_deadcrootp(p) + rfluxes(f_livecrootn_to_retransn) = veg_pf%livecrootp_to_retransp(p) + rfluxes(f_livecrootn_storage_to_xfer) = veg_pf%livecrootp_storage_to_xfer(p) + rfluxes(f_livecrootn_xfer_to_livecrootn) = veg_pf%livecrootp_xfer_to_livecrootp(p) + if (woody(ivt(p)) >= 1.0_r8) then rfluxes(f_npool_to_livestemn) = veg_pf%ppool_to_livestemp(p) rfluxes(f_npool_to_livestemn_storage) = veg_pf%ppool_to_livestemp_storage(p) - rfluxes(f_npool_to_livecrootn) = veg_pf%ppool_to_livecrootp(p) - rfluxes(f_npool_to_livecrootn_storage) = veg_pf%ppool_to_livecrootp_storage(p) rfluxes(f_npool_to_deadstemn) = veg_pf%ppool_to_deadstemp(p) rfluxes(f_npool_to_deadcrootn) = veg_pf%ppool_to_deadcrootp(p) rfluxes(f_npool_to_deadstemn_storage) = veg_pf%ppool_to_deadstemp_storage(p) @@ -1092,10 +1103,6 @@ subroutine phosphorus_flux_limiter(bounds, num_soilc, filter_soilc,& rfluxes(f_livestemn_xfer_to_livestemn) = veg_pf%livestemp_xfer_to_livestemp(p) rfluxes(f_livestemn_to_retransn) = veg_pf%livestemp_to_retransp(p) rfluxes(f_livestemn_to_deadstemn) = veg_pf%livestemp_to_deadstemp(p) - rfluxes(f_livecrootn_to_deadcrootn) = veg_pf%livecrootp_to_deadcrootp(p) - rfluxes(f_livecrootn_to_retransn) = veg_pf%livecrootp_to_retransp(p) - rfluxes(f_livecrootn_storage_to_xfer) = veg_pf%livecrootp_storage_to_xfer(p) - rfluxes(f_livecrootn_xfer_to_livecrootn) = veg_pf%livecrootp_xfer_to_livecrootp(p) rfluxes(f_deadstemn_storage_to_xfer) = veg_pf%deadstemp_storage_to_xfer(p) rfluxes(f_deadstemn_xfer_to_deadstem) = veg_pf%deadstemp_xfer_to_deadstemp(p) rfluxes(f_deadcrootn_storage_to_xfer) = veg_pf%deadcrootp_storage_to_xfer(p) @@ -1135,11 +1142,15 @@ subroutine phosphorus_flux_limiter(bounds, num_soilc, filter_soilc,& call fpmax(rfluxes(f_npool_to_leafn_storage) , veg_pf%ppool_to_leafp_storage(p)) call fpmax(rfluxes(f_npool_to_frootn) , veg_pf%ppool_to_frootp(p)) call fpmax(rfluxes(f_npool_to_frootn_storage) , veg_pf%ppool_to_frootp_storage(p)) - if (woody(ivt(p)) == 1._r8) then + call fpmax(rfluxes(f_npool_to_livecrootn) , veg_pf%ppool_to_livecrootp(p)) + call fpmax(rfluxes(f_npool_to_livecrootn_storage) , veg_pf%ppool_to_livecrootp_storage(p)) + call fpmax(rfluxes(f_livecrootn_to_deadcrootn) , veg_pf%livecrootp_to_deadcrootp(p)) + call fpmax(rfluxes(f_livecrootn_to_retransn) , veg_pf%livecrootp_to_retransp(p)) + call fpmax(rfluxes(f_livecrootn_storage_to_xfer) , veg_pf%livecrootp_storage_to_xfer(p)) + call fpmax(rfluxes(f_livecrootn_xfer_to_livecrootn) , veg_pf%livecrootp_xfer_to_livecrootp(p)) + if (woody(ivt(p)) >= 1.0_r8) then call fpmax(rfluxes(f_npool_to_livestemn) , veg_pf%ppool_to_livestemp(p)) call fpmax(rfluxes(f_npool_to_livestemn_storage) , veg_pf%ppool_to_livestemp_storage(p)) - call fpmax(rfluxes(f_npool_to_livecrootn) , veg_pf%ppool_to_livecrootp(p)) - call fpmax(rfluxes(f_npool_to_livecrootn_storage) , veg_pf%ppool_to_livecrootp_storage(p)) call fpmax(rfluxes(f_npool_to_deadstemn) , veg_pf%ppool_to_deadstemp(p)) call fpmax(rfluxes(f_npool_to_deadcrootn) , veg_pf%ppool_to_deadcrootp(p)) call fpmax(rfluxes(f_npool_to_deadstemn_storage) , veg_pf%ppool_to_deadstemp_storage(p)) @@ -1148,10 +1159,6 @@ subroutine phosphorus_flux_limiter(bounds, num_soilc, filter_soilc,& call fpmax(rfluxes(f_livestemn_xfer_to_livestemn) , veg_pf%livestemp_xfer_to_livestemp(p)) call fpmax(rfluxes(f_livestemn_to_retransn) , veg_pf%livestemp_to_retransp(p)) call fpmax(rfluxes(f_livestemn_to_deadstemn) , veg_pf%livestemp_to_deadstemp(p)) - call fpmax(rfluxes(f_livecrootn_to_deadcrootn) , veg_pf%livecrootp_to_deadcrootp(p)) - call fpmax(rfluxes(f_livecrootn_to_retransn) , veg_pf%livecrootp_to_retransp(p)) - call fpmax(rfluxes(f_livecrootn_storage_to_xfer) , veg_pf%livecrootp_storage_to_xfer(p)) - call fpmax(rfluxes(f_livecrootn_xfer_to_livecrootn) , veg_pf%livecrootp_xfer_to_livecrootp(p)) call fpmax(rfluxes(f_deadstemn_storage_to_xfer) , veg_pf%deadstemp_storage_to_xfer(p)) call fpmax(rfluxes(f_deadstemn_xfer_to_deadstem) , veg_pf%deadstemp_xfer_to_deadstemp(p)) call fpmax(rfluxes(f_deadcrootn_storage_to_xfer) , veg_pf%deadcrootp_storage_to_xfer(p)) diff --git a/components/elm/src/biogeochem/PhenologyMod.F90 b/components/elm/src/biogeochem/PhenologyMod.F90 index 0586044510d9..948cee8aa7db 100644 --- a/components/elm/src/biogeochem/PhenologyMod.F90 +++ b/components/elm/src/biogeochem/PhenologyMod.F90 @@ -531,6 +531,7 @@ subroutine CNEvergreenPhenology (num_soilp, filter_soilp , & integer , intent(in) :: num_soilp ! number of soil patches in filter integer , intent(in) :: filter_soilp(:) ! filter for soil patches type(cnstate_type), intent(inout) :: cnstate_vars + ! ! !LOCAL VARIABLES: real(r8):: dayspyr ! Days per year @@ -547,7 +548,52 @@ subroutine CNEvergreenPhenology (num_soilp, filter_soilp , & bglfr_leaf => cnstate_vars%bglfr_leaf_patch , & ! Output: [real(r8) (:) ] background leaf litterfall rate (1/s) bglfr_froot => cnstate_vars%bglfr_froot_patch, & ! Output: [real(r8) (:) ] background fine root litterfall (1/s) bgtr => cnstate_vars%bgtr_patch , & ! Output: [real(r8) (:) ] background transfer growth rate (1/s) - lgsf => cnstate_vars%lgsf_patch & ! Output: [real(r8) (:) ] long growing season factor [0-1] + lgsf => cnstate_vars%lgsf_patch , & ! Output: [real(r8) (:) ] long growing season factor [0-1] + + woody => veg_vp%woody , & + + leafc_storage => veg_cs%leafc_storage , & ! Input: [real(r8) (:) ] (gC/m2) leaf C storage + frootc_storage => veg_cs%frootc_storage , & ! Input: [real(r8) (:) ] (gC/m2) fine root C storage + livestemc_storage => veg_cs%livestemc_storage , & ! Input: [real(r8) (:) ] (gC/m2) live stem C storage + deadstemc_storage => veg_cs%deadstemc_storage , & ! Input: [real(r8) (:) ] (gC/m2) dead stem C storage + livecrootc_storage => veg_cs%livecrootc_storage , & ! Input: [real(r8) (:) ] (gC/m2) live coarse root C storage + deadcrootc_storage => veg_cs%deadcrootc_storage , & ! Input: [real(r8) (:) ] (gC/m2) dead coarse root C storage + gresp_storage => veg_cs%gresp_storage , & ! Input: [real(r8) (:) ] (gC/m2) growth respiration storage + + leafn_storage => veg_ns%leafn_storage , & ! Input: [real(r8) (:) ] (gN/m2) leaf N storage + frootn_storage => veg_ns%frootn_storage , & ! Input: [real(r8) (:) ] (gN/m2) fine root N storage + livestemn_storage => veg_ns%livestemn_storage , & ! Input: [real(r8) (:) ] (gN/m2) live stem N storage + deadstemn_storage => veg_ns%deadstemn_storage , & ! Input: [real(r8) (:) ] (gN/m2) dead stem N storage + livecrootn_storage => veg_ns%livecrootn_storage , & ! Input: [real(r8) (:) ] (gN/m2) live coarse root N storage + deadcrootn_storage => veg_ns%deadcrootn_storage , & ! Input: [real(r8) (:) ] (gN/m2) dead coarse root N storage + + leafp_storage => veg_ps%leafp_storage , & ! Input: [real(r8) (:) ] (gP/m2) leaf P storage + frootp_storage => veg_ps%frootp_storage , & ! Input: [real(r8) (:) ] (gP/m2) fine root P storage + livestemp_storage => veg_ps%livestemp_storage , & ! Input: [real(r8) (:) ] (gP/m2) live stem P storage + deadstemp_storage => veg_ps%deadstemp_storage , & ! Input: [real(r8) (:) ] (gP/m2) dead stem P storage + livecrootp_storage => veg_ps%livecrootp_storage , & ! Input: [real(r8) (:) ] (gP/m2) live coarse root P storage + deadcrootp_storage => veg_ps%deadcrootp_storage , & ! Input: [real(r8) (:) ] (gP/m2) dead coarse root P storage + + leafc_storage_to_xfer => veg_cf%leafc_storage_to_xfer , & ! Output: [real(r8) (:) ] + frootc_storage_to_xfer => veg_cf%frootc_storage_to_xfer , & ! Output: [real(r8) (:) ] + livestemc_storage_to_xfer => veg_cf%livestemc_storage_to_xfer , & ! Output: [real(r8) (:) ] + deadstemc_storage_to_xfer => veg_cf%deadstemc_storage_to_xfer , & ! Output: [real(r8) (:) ] + livecrootc_storage_to_xfer => veg_cf%livecrootc_storage_to_xfer , & ! Output: [real(r8) (:) ] + deadcrootc_storage_to_xfer => veg_cf%deadcrootc_storage_to_xfer , & ! Output: [real(r8) (:) ] + gresp_storage_to_xfer => veg_cf%gresp_storage_to_xfer , & ! Output: [real(r8) (:) ] + leafn_storage_to_xfer => veg_nf%leafn_storage_to_xfer , & ! Output: [real(r8) (:) ] + frootn_storage_to_xfer => veg_nf%frootn_storage_to_xfer , & ! Output: [real(r8) (:) ] + livestemn_storage_to_xfer => veg_nf%livestemn_storage_to_xfer , & ! Output: [real(r8) (:) ] + deadstemn_storage_to_xfer => veg_nf%deadstemn_storage_to_xfer , & ! Output: [real(r8) (:) ] + livecrootn_storage_to_xfer => veg_nf%livecrootn_storage_to_xfer , & ! Output: [real(r8) (:) ] + deadcrootn_storage_to_xfer => veg_nf%deadcrootn_storage_to_xfer , & ! Output: [real(r8) (:) ] + + leafp_storage_to_xfer => veg_pf%leafp_storage_to_xfer , & ! Output: [real(r8) (:) ] + frootp_storage_to_xfer => veg_pf%frootp_storage_to_xfer , & ! Output: [real(r8) (:) ] + livestemp_storage_to_xfer => veg_pf%livestemp_storage_to_xfer , & ! Output: [real(r8) (:) ] + deadstemp_storage_to_xfer => veg_pf%deadstemp_storage_to_xfer , & ! Output: [real(r8) (:) ] + livecrootp_storage_to_xfer => veg_pf%livecrootp_storage_to_xfer , & ! Output: [real(r8) (:) ] + deadcrootp_storage_to_xfer => veg_pf%deadcrootp_storage_to_xfer & ! Output: [real(r8) (:) ] ) dayspyr = dayspyr_mod @@ -557,8 +603,43 @@ subroutine CNEvergreenPhenology (num_soilp, filter_soilp , & if (evergreen(ivt(p)) == 1._r8) then bglfr_leaf(p) = 1._r8/(leaf_long(ivt(p)) * dayspyr * secspday) bglfr_froot(p) = 1._r8/(froot_long(ivt(p)) * dayspyr * secspday) - bgtr(p) = 0._r8 + ! bgtr(p) = 0._r8 + ! B. Sulman: set background transfer rate based on interpreting fstor2tran as a per-year fraction + ! If bgtr is nonzero, C/N/P will automatically be transferred from xfer to displayed pools in CNOnsetGrowth + bgtr(p) = PhenolParamsInst%fstor2tran/(dayspyr * secspday) lgsf(p) = 0._r8 + + ! B. Sulman: Allow evergreen plants to transfer C/N/P from storage pools to growth, at a constant rate (for now) + leafc_storage_to_xfer(p) = bgtr(p) * leafc_storage(p) + frootc_storage_to_xfer(p) = bgtr(p) * frootc_storage(p) + gresp_storage_to_xfer(p) = bgtr(p) * gresp_storage(p) + livecrootc_storage_to_xfer(p) = bgtr(p) * livecrootc_storage(p) ! For graminoid rhizomes + + if (woody(ivt(p)) == 1.0_r8) then + livestemc_storage_to_xfer(p) = bgtr(p) * livestemc_storage(p) + deadstemc_storage_to_xfer(p) = bgtr(p) * deadstemc_storage(p) + deadcrootc_storage_to_xfer(p) = bgtr(p) * deadcrootc_storage(p) + end if + + ! set nitrogen fluxes for shifting storage pools to transfer pools + leafn_storage_to_xfer(p) = bgtr(p) * leafn_storage(p) + frootn_storage_to_xfer(p) = bgtr(p) * frootn_storage(p) + livecrootn_storage_to_xfer(p) = bgtr(p) * livecrootn_storage(p) + if (woody(ivt(p)) == 1.0_r8) then + livestemn_storage_to_xfer(p) = bgtr(p) * livestemn_storage(p) + deadstemn_storage_to_xfer(p) = bgtr(p) * deadstemn_storage(p) + deadcrootn_storage_to_xfer(p) = bgtr(p) * deadcrootn_storage(p) + end if + + ! set phosphorus fluxes for shifting storage pools to transfer pools + leafp_storage_to_xfer(p) = bgtr(p) * leafp_storage(p) + frootp_storage_to_xfer(p) = bgtr(p) * frootp_storage(p) + livecrootp_storage_to_xfer(p) = bgtr(p) * livecrootp_storage(p) + if (woody(ivt(p)) == 1.0_r8) then + livestemp_storage_to_xfer(p) = bgtr(p) * livestemp_storage(p) + deadstemp_storage_to_xfer(p) = bgtr(p) * deadstemp_storage(p) + deadcrootp_storage_to_xfer(p) = bgtr(p) * deadcrootp_storage(p) + end if end if end do @@ -578,6 +659,7 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp, cnstate_vars) !$acc routine seq use shr_const_mod , only: SHR_CONST_TKFRZ, SHR_CONST_PI use elm_varcon , only: secspday + use elm_varctl , only: onset_gdd_extension ! ! !ARGUMENTS: integer , intent(in) :: num_soilp ! number of soil patches in filter @@ -769,18 +851,18 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp, cnstate_vars) frootn_xfer_to_frootn(p) = 0.0_r8 leafp_xfer_to_leafp(p) = 0.0_r8 frootp_xfer_to_frootp(p) = 0.0_r8 - if (woody(ivt(p)) == 1.0_r8) then + livecrootc_xfer_to_livecrootc(p) = 0.0_r8 ! Graminoid rhizomes + livecrootn_xfer_to_livecrootn(p) = 0.0_r8 + livecrootp_xfer_to_livecrootp(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 livestemp_xfer_to_livestemp(p) = 0.0_r8 deadstemp_xfer_to_deadstemp(p) = 0.0_r8 - livecrootp_xfer_to_livecrootp(p) = 0.0_r8 deadcrootp_xfer_to_deadcrootp(p) = 0.0_r8 end if ! set transfer pools to 0.0 @@ -790,16 +872,16 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp, cnstate_vars) frootc_xfer(p) = 0.0_r8 frootn_xfer(p) = 0.0_r8 frootp_xfer(p) = 0.0_r8 - if (woody(ivt(p)) == 1.0_r8) then + livecrootc_xfer(p) = 0.0_r8 + livecrootn_xfer(p) = 0.0_r8 + livecrootp_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 livestemp_xfer(p) = 0.0_r8 deadstemc_xfer(p) = 0.0_r8 deadstemn_xfer(p) = 0.0_r8 deadstemp_xfer(p) = 0.0_r8 - livecrootc_xfer(p) = 0.0_r8 - livecrootn_xfer(p) = 0.0_r8 - livecrootp_xfer(p) = 0.0_r8 deadcrootc_xfer(p) = 0.0_r8 deadcrootn_xfer(p) = 0.0_r8 deadcrootp_xfer(p) = 0.0_r8 @@ -824,11 +906,27 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp, cnstate_vars) ! In that case, it will take until the next winter solstice ! before the growing degree-day summation starts again. - if (onset_gddflag(p) == 1._r8 .and. ws_flag == 0._r8) then - onset_gddflag(p) = 0._r8 - onset_gdd(p) = 0._r8 + ! A note by F-M Yuan (2020-02-21): when having heavy snow winter, + ! snow melting may be lasting into July in some Arctic area (esp. East Russia) + ! So better to let ONSET stage up to 'offset' starting criteria date, if this feature is on. + + if (onset_gdd_extension) then + if (onset_gddflag(p) == 1._r8 .and. ws_flag == 0._r8 & + .and. dayl(g) < PhenolParamsInst%crit_dayl) then + onset_gddflag(p) = 0._r8 + onset_gdd(p) = 0._r8 + + end if + + else + + if (onset_gddflag(p) == 1._r8 .and. ws_flag == 0._r8) then + onset_gddflag(p) = 0._r8 + onset_gdd(p) = 0._r8 + end if end if + ! if the gdd flag is set, and if the soil is above freezing ! then accumulate growing degree days for onset trigger @@ -853,10 +951,10 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp, cnstate_vars) ! set carbon fluxes for shifting storage pools to transfer pools leafc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * leafc_storage(p)/dt frootc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * frootc_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then + livecrootc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livecrootc_storage(p)/dt + if (woody(ivt(p)) >= 1.0_r8) then livestemc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livestemc_storage(p)/dt deadstemc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * deadstemc_storage(p)/dt - livecrootc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livecrootc_storage(p)/dt deadcrootc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * deadcrootc_storage(p)/dt gresp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * gresp_storage(p)/dt end if @@ -864,20 +962,20 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp, cnstate_vars) ! set nitrogen fluxes for shifting storage pools to transfer pools leafn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * leafn_storage(p)/dt frootn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * frootn_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then + livecrootn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livecrootn_storage(p)/dt + if (woody(ivt(p)) >= 1.0_r8) then livestemn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livestemn_storage(p)/dt deadstemn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * deadstemn_storage(p)/dt - livecrootn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livecrootn_storage(p)/dt deadcrootn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * deadcrootn_storage(p)/dt end if ! set phosphorus fluxes for shifting storage pools to transfer pools leafp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * leafp_storage(p)/dt frootp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * frootp_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then + livecrootp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livecrootp_storage(p)/dt + if (woody(ivt(p)) >= 1.0_r8) then livestemp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livestemp_storage(p)/dt deadstemp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * deadstemp_storage(p)/dt - livecrootp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livecrootp_storage(p)/dt deadcrootp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * deadcrootp_storage(p)/dt end if end if @@ -1114,18 +1212,18 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & frootn_xfer_to_frootn(p) = 0._r8 leafp_xfer_to_leafp(p) = 0._r8 frootp_xfer_to_frootp(p) = 0._r8 - if (woody(ivt(p)) == 1.0_r8) then + livecrootc_xfer_to_livecrootc(p) = 0._r8 + livecrootn_xfer_to_livecrootn(p) = 0._r8 + livecrootp_xfer_to_livecrootp(p) = 0._r8 + if (woody(ivt(p)) >= 1.0_r8) then livestemc_xfer_to_livestemc(p) = 0._r8 deadstemc_xfer_to_deadstemc(p) = 0._r8 - livecrootc_xfer_to_livecrootc(p) = 0._r8 deadcrootc_xfer_to_deadcrootc(p) = 0._r8 livestemn_xfer_to_livestemn(p) = 0._r8 deadstemn_xfer_to_deadstemn(p) = 0._r8 - livecrootn_xfer_to_livecrootn(p) = 0._r8 deadcrootn_xfer_to_deadcrootn(p) = 0._r8 livestemp_xfer_to_livestemp(p) = 0._r8 deadstemp_xfer_to_deadstemp(p) = 0._r8 - livecrootp_xfer_to_livecrootp(p) = 0._r8 deadcrootp_xfer_to_deadcrootp(p) = 0._r8 end if ! set transfer pools to 0.0 @@ -1135,16 +1233,16 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & frootc_xfer(p) = 0._r8 frootn_xfer(p) = 0._r8 frootp_xfer(p) = 0._r8 - if (woody(ivt(p)) == 1.0_r8) then + livecrootc_xfer(p) = 0._r8 + livecrootn_xfer(p) = 0._r8 + livecrootp_xfer(p) = 0._r8 + if (woody(ivt(p)) >= 1.0_r8) then livestemc_xfer(p) = 0._r8 livestemn_xfer(p) = 0._r8 livestemp_xfer(p) = 0._r8 deadstemc_xfer(p) = 0._r8 deadstemn_xfer(p) = 0._r8 deadstemp_xfer(p) = 0._r8 - livecrootc_xfer(p) = 0._r8 - livecrootn_xfer(p) = 0._r8 - livecrootp_xfer(p) = 0._r8 deadcrootc_xfer(p) = 0._r8 deadcrootn_xfer(p) = 0._r8 deadcrootp_xfer(p) = 0._r8 @@ -1227,10 +1325,10 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & ! set carbon fluxes for shifting storage pools to transfer pools leafc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * leafc_storage(p)/dt frootc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * frootc_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then + livecrootc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livecrootc_storage(p)/dt + if (woody(ivt(p)) >= 1.0_r8) then livestemc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livestemc_storage(p)/dt deadstemc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * deadstemc_storage(p)/dt - livecrootc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livecrootc_storage(p)/dt deadcrootc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * deadcrootc_storage(p)/dt gresp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * gresp_storage(p)/dt end if @@ -1238,20 +1336,20 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & ! set nitrogen fluxes for shifting storage pools to transfer pools leafn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * leafn_storage(p)/dt frootn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * frootn_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then + livecrootn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livecrootn_storage(p)/dt + if (woody(ivt(p)) >= 1.0_r8) then livestemn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livestemn_storage(p)/dt deadstemn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * deadstemn_storage(p)/dt - livecrootn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livecrootn_storage(p)/dt deadcrootn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * deadcrootn_storage(p)/dt end if ! set phosphorus fluxes for shifting storage pools to transfer pools leafp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * leafp_storage(p)/dt frootp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * frootp_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then + livecrootp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livecrootp_storage(p)/dt + if (woody(ivt(p)) >= 1.0_r8) then livestemp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livestemp_storage(p)/dt deadstemp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * deadstemp_storage(p)/dt - livecrootp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livecrootp_storage(p)/dt deadcrootp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * deadcrootp_storage(p)/dt end if @@ -1350,10 +1448,10 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & leafc_storage_to_xfer(p) = leafc_storage(p) * bgtr(p) frootc_storage_to_xfer(p) = frootc_storage(p) * bgtr(p) - if (woody(ivt(p)) == 1.0_r8) then + livecrootc_storage_to_xfer(p) = livecrootc_storage(p) * bgtr(p) + if (woody(ivt(p)) >= 1.0_r8) then livestemc_storage_to_xfer(p) = livestemc_storage(p) * bgtr(p) deadstemc_storage_to_xfer(p) = deadstemc_storage(p) * bgtr(p) - livecrootc_storage_to_xfer(p) = livecrootc_storage(p) * bgtr(p) deadcrootc_storage_to_xfer(p) = deadcrootc_storage(p) * bgtr(p) gresp_storage_to_xfer(p) = gresp_storage(p) * bgtr(p) end if @@ -1361,10 +1459,10 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & ! set nitrogen fluxes for shifting storage pools to transfer pools leafn_storage_to_xfer(p) = leafn_storage(p) * bgtr(p) frootn_storage_to_xfer(p) = frootn_storage(p) * bgtr(p) - if (woody(ivt(p)) == 1.0_r8) then + livecrootn_storage_to_xfer(p) = livecrootn_storage(p) * bgtr(p) + if (woody(ivt(p)) >= 1.0_r8) then livestemn_storage_to_xfer(p) = livestemn_storage(p) * bgtr(p) deadstemn_storage_to_xfer(p) = deadstemn_storage(p) * bgtr(p) - livecrootn_storage_to_xfer(p) = livecrootn_storage(p) * bgtr(p) deadcrootn_storage_to_xfer(p) = deadcrootn_storage(p) * bgtr(p) end if @@ -1372,10 +1470,10 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & ! set phosphorus fluxes for shifting storage pools to transfer pools leafp_storage_to_xfer(p) = leafp_storage(p) * bgtr(p) frootp_storage_to_xfer(p) = frootp_storage(p) * bgtr(p) - if (woody(ivt(p)) == 1.0_r8) then + livecrootp_storage_to_xfer(p) = livecrootp_storage(p) * bgtr(p) + if (woody(ivt(p)) >= 1.0_r8) then livestemp_storage_to_xfer(p) = livestemp_storage(p) * bgtr(p) deadstemp_storage_to_xfer(p) = deadstemp_storage(p) * bgtr(p) - livecrootp_storage_to_xfer(p) = livecrootp_storage(p) * bgtr(p) deadcrootp_storage_to_xfer(p) = deadcrootp_storage(p) * bgtr(p) end if end if @@ -2653,19 +2751,19 @@ subroutine CNOnsetGrowth (num_soilp, filter_soilp, & frootn_xfer_to_frootn(p) = t1 * frootn_xfer(p) leafp_xfer_to_leafp(p) = t1 * leafp_xfer(p) frootp_xfer_to_frootp(p) = t1 * frootp_xfer(p) - if (woody(ivt(p)) == 1.0_r8) then + livecrootc_xfer_to_livecrootc(p) = t1 * livecrootc_xfer(p) + livecrootn_xfer_to_livecrootn(p) = t1 * livecrootn_xfer(p) + livecrootp_xfer_to_livecrootp(p) = t1 * livecrootp_xfer(p) + if (woody(ivt(p)) >= 1.0_r8) then livestemc_xfer_to_livestemc(p) = t1 * livestemc_xfer(p) deadstemc_xfer_to_deadstemc(p) = t1 * deadstemc_xfer(p) - livecrootc_xfer_to_livecrootc(p) = t1 * livecrootc_xfer(p) deadcrootc_xfer_to_deadcrootc(p) = t1 * deadcrootc_xfer(p) livestemn_xfer_to_livestemn(p) = t1 * livestemn_xfer(p) deadstemn_xfer_to_deadstemn(p) = t1 * deadstemn_xfer(p) - livecrootn_xfer_to_livecrootn(p) = t1 * livecrootn_xfer(p) deadcrootn_xfer_to_deadcrootn(p) = t1 * deadcrootn_xfer(p) livestemp_xfer_to_livestemp(p) = t1 * livestemp_xfer(p) deadstemp_xfer_to_deadstemp(p) = t1 * deadstemp_xfer(p) - livecrootp_xfer_to_livecrootp(p) = t1 * livecrootp_xfer(p) deadcrootp_xfer_to_deadcrootp(p) = t1 * deadcrootp_xfer(p) end if @@ -2682,18 +2780,18 @@ subroutine CNOnsetGrowth (num_soilp, filter_soilp, & frootn_xfer_to_frootn(p) = frootn_xfer(p) / dt leafp_xfer_to_leafp(p) = leafp_xfer(p) / dt frootp_xfer_to_frootp(p) = frootp_xfer(p) / dt - if (woody(ivt(p)) == 1.0_r8) then + livecrootc_xfer_to_livecrootc(p) = livecrootc_xfer(p) / dt + livecrootn_xfer_to_livecrootn(p) = livecrootn_xfer(p) / dt + livecrootp_xfer_to_livecrootp(p) = livecrootp_xfer(p) / dt + if (woody(ivt(p)) >= 1.0_r8) then livestemc_xfer_to_livestemc(p) = livestemc_xfer(p) / dt deadstemc_xfer_to_deadstemc(p) = deadstemc_xfer(p) / dt - livecrootc_xfer_to_livecrootc(p) = livecrootc_xfer(p) / dt deadcrootc_xfer_to_deadcrootc(p) = deadcrootc_xfer(p) / dt livestemn_xfer_to_livestemn(p) = livestemn_xfer(p) / dt deadstemn_xfer_to_deadstemn(p) = deadstemn_xfer(p) / dt - livecrootn_xfer_to_livecrootn(p) = livecrootn_xfer(p) / dt deadcrootn_xfer_to_deadcrootn(p) = deadcrootn_xfer(p) / dt livestemp_xfer_to_livestemp(p) = livestemp_xfer(p) / dt deadstemp_xfer_to_deadstemp(p) = deadstemp_xfer(p) / dt - livecrootp_xfer_to_livecrootp(p) = livecrootp_xfer(p) / dt deadcrootp_xfer_to_deadcrootp(p) = deadcrootp_xfer(p) / dt end if end if ! end if bgtr @@ -3223,6 +3321,8 @@ subroutine CNLivewoodTurnover (num_soilp, filter_soilp) ! Determines the flux of C and N from live wood to ! dead wood pools, for stem and coarse root. ! add phosphorus flux - X.YANG + use elm_varcon , only : secspday + use elm_time_manager , only : get_days_per_year ! ! !ARGUMENTS: !$acc routine seq @@ -3235,6 +3335,7 @@ subroutine CNLivewoodTurnover (num_soilp, filter_soilp) real(r8):: ctovr ! temporary variable for carbon turnover real(r8):: ntovr ! temporary variable for nitrogen turnover real(r8):: ptovr ! temporary variable for phosphorus turnover + real(r8):: dayspyr ! days per year !----------------------------------------------------------------------- associate( & @@ -3247,6 +3348,8 @@ subroutine CNLivewoodTurnover (num_soilp, filter_soilp) livestemc => veg_cs%livestemc , & ! Input: [real(r8) (:) ] (gC/m2) live stem C livecrootc => veg_cs%livecrootc , & ! Input: [real(r8) (:) ] (gC/m2) live coarse root C + rhizome_long => veg_vp%rhizome_long , & ! Input: [real(r8) (:) ] rhizome longevity (yrs) + livestemn => veg_ns%livestemn , & ! Input: [real(r8) (:) ] (gN/m2) live stem N livecrootn => veg_ns%livecrootn , & ! Input: [real(r8) (:) ] (gN/m2) live coarse root N @@ -3255,26 +3358,37 @@ subroutine CNLivewoodTurnover (num_soilp, filter_soilp) livestemc_to_deadstemc => veg_cf%livestemc_to_deadstemc , & ! Output: [real(r8) (:) ] livecrootc_to_deadcrootc => veg_cf%livecrootc_to_deadcrootc , & ! Output: [real(r8) (:) ] + livecrootc_to_litter => veg_cf%livecrootc_to_litter , & ! Output: [real(r8) (:) ] livestemn_to_deadstemn => veg_nf%livestemn_to_deadstemn , & ! Output: [real(r8) (:) ] livestemn_to_retransn => veg_nf%livestemn_to_retransn , & ! Output: [real(r8) (:) ] livecrootn_to_deadcrootn => veg_nf%livecrootn_to_deadcrootn , & ! Output: [real(r8) (:) ] livecrootn_to_retransn => veg_nf%livecrootn_to_retransn , & ! Output: [real(r8) (:) ] + livecrootn_to_litter => veg_nf%livecrootn_to_litter , & ! Output: [real(r8) (:) ] livewdcp => veg_vp%livewdcp , & ! Input: [real(r8) (:) ] live wood (phloem and ray parenchyma) C:P (gC/gP) deadwdcp => veg_vp%deadwdcp , & ! Input: [real(r8) (:) ] dead wood (xylem and heartwood) C:P (gC/gP) livestemp_to_deadstemp => veg_pf%livestemp_to_deadstemp , & ! Output: [real(r8) (:) ] livestemp_to_retransp => veg_pf%livestemp_to_retransp , & ! Output: [real(r8) (:) ] livecrootp_to_deadcrootp => veg_pf%livecrootp_to_deadcrootp , & ! Output: [real(r8) (:) ] - livecrootp_to_retransp => veg_pf%livecrootp_to_retransp & ! Output: [real(r8) (:) ] + livecrootp_to_retransp => veg_pf%livecrootp_to_retransp , & ! Output: [real(r8) (:) ] + livecrootp_to_litter => veg_pf%livecrootp_to_litter & ! Output: [real(r8) (:) ] ) + + dayspyr = get_days_per_year() + ! patch loop do fp = 1,num_soilp p = filter_soilp(fp) ! only calculate these fluxes for woody types - if (woody(ivt(p)) > 0._r8) then + if (woody(ivt(p)) >= 1.0_r8) then + ! These are only used for nonwoody rhizomes + livecrootc_to_litter(p) = 0.0_r8 + livecrootn_to_litter(p) = 0.0_r8 + livecrootp_to_litter(p) = 0.0_r8 + if ( nu_com .eq. 'RD') then ! live stem to dead stem turnover @@ -3327,6 +3441,26 @@ subroutine CNLivewoodTurnover (num_soilp, filter_soilp) livecrootp_to_retransp(p) = ptovr - livecrootp_to_deadcrootp(p) end if + else ! If not woody, do rhizome turnover + if ( nu_com .eq. 'RD') then + if(rhizome_long(ivt(p))>0.0_r8) then + ctovr = livecrootc(p) / (rhizome_long(ivt(p))*dayspyr*secspday) + ntovr = livecrootn(p) / (rhizome_long(ivt(p))*dayspyr*secspday) + ptovr = livecrootp(p) / (rhizome_long(ivt(p))*dayspyr*secspday) + else + ctovr = 0.0_r8 + ntovr = 0.0_r8 + ptovr = 0.0_r8 + endif + + livecrootc_to_litter(p) = ctovr + livecrootn_to_litter(p) = ntovr ! This assumes no retranslocation + livecrootn_to_retransn(p) = 0.0_r8 + + livecrootp_to_litter(p) = ptovr + livecrootp_to_retransp(p) = 0.0_r8 + + end if end if end do @@ -3371,16 +3505,19 @@ subroutine CNLitterToColumn (num_soilp, filter_soilp, & leaf_prof => cnstate_vars%leaf_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of leaves froot_prof => cnstate_vars%froot_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of fine roots + croot_prof => cnstate_vars%croot_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of coarse roots leafc_to_litter => veg_cf%leafc_to_litter , & ! Input: [real(r8) (:) ] leaf C litterfall (gC/m2/s) frootc_to_litter => veg_cf%frootc_to_litter , & ! Input: [real(r8) (:) ] fine root N litterfall (gN/m2/s) livestemc_to_litter => veg_cf%livestemc_to_litter , & ! Input: [real(r8) (:) ] live stem C litterfall (gC/m2/s) + livecrootc_to_litter => veg_cf%livecrootc_to_litter , & ! Input: [real(r8) (:) ] live coarse root/rhizome C litterfall (gC/m2/s) ! grainc_to_food => veg_cf%grainc_to_food , & ! Input: [real(r8) (:) ] grain C to food (gC/m2/s) phenology_c_to_litr_met_c => col_cf%phenology_c_to_litr_met_c , & ! Output: [real(r8) (:,:) ] C fluxes associated with phenology (litterfall and crop) to litter metabolic pool (gC/m3/s) phenology_c_to_litr_cel_c => col_cf%phenology_c_to_litr_cel_c , & ! Output: [real(r8) (:,:) ] C fluxes associated with phenology (litterfall and crop) to litter cellulose pool (gC/m3/s) phenology_c_to_litr_lig_c => col_cf%phenology_c_to_litr_lig_c , & ! Output: [real(r8) (:,:) ] C fluxes associated with phenology (litterfall and crop) to litter lignin pool (gC/m3/s) livestemn_to_litter => veg_nf%livestemn_to_litter , & ! Input: [real(r8) (:) ] livestem N to litter (gN/m2/s) + livecrootn_to_litter => veg_nf%livecrootn_to_litter , & ! Input: [real(r8) (:) ] livecroot/rhizome N to litter (gN/m2/s) ! grainn_to_food => veg_nf%grainn_to_food , & ! Input: [real(r8) (:) ] grain N to food (gN/m2/s) leafn_to_litter => veg_nf%leafn_to_litter , & ! Input: [real(r8) (:) ] leaf N litterfall (gN/m2/s) frootn_to_litter => veg_nf%frootn_to_litter , & ! Input: [real(r8) (:) ] fine root N litterfall (gN/m2/s) @@ -3389,6 +3526,7 @@ subroutine CNLitterToColumn (num_soilp, filter_soilp, & phenology_n_to_litr_lig_n => col_nf%phenology_n_to_litr_lig_n , & ! Output: [real(r8) (:,:) ] N fluxes associated with phenology (litterfall and crop) to litter lignin pool (gN/m3/s) livestemp_to_litter => veg_pf%livestemp_to_litter , & ! Input: [real(r8) (:) ] livestem P to litter (gP/m2/s) + livecrootp_to_litter => veg_pf%livecrootp_to_litter , & ! Input: [real(r8) (:) ] livecroot/rhizome P to litter (gP/m2/s) ! grainp_to_food => veg_pf%grainp_to_food , & ! Input: [real(r8) (:) ] grain P to food (gP/m2/s) leafp_to_litter => veg_pf%leafp_to_litter , & ! Input: [real(r8) (:) ] leaf P litterfall (gP/m2/s) frootp_to_litter => veg_pf%frootp_to_litter , & ! Input: [real(r8) (:) ] fine root P litterfall (gP/m2/s) @@ -3451,6 +3589,33 @@ subroutine CNLitterToColumn (num_soilp, filter_soilp, & phenology_p_to_litr_lig_p(c,j) = phenology_p_to_litr_lig_p(c,j) & + frootp_to_litter(p) * fr_flig(ivt(p)) * wt_col * froot_prof(p,j) + + ! Rhizome litter carbon fluxes. Assume similar to fine roots (B Sulman) + phenology_c_to_litr_met_c(c,j) = phenology_c_to_litr_met_c(c,j) & + + livecrootc_to_litter(p) * fr_flab(ivt(p)) * wtcol(p) * croot_prof(p,j) + phenology_c_to_litr_cel_c(c,j) = phenology_c_to_litr_cel_c(c,j) & + + livecrootc_to_litter(p) * fr_fcel(ivt(p)) * wtcol(p) * croot_prof(p,j) + phenology_c_to_litr_lig_c(c,j) = phenology_c_to_litr_lig_c(c,j) & + + livecrootc_to_litter(p) * fr_flig(ivt(p)) * wtcol(p) * croot_prof(p,j) + + + ! Rhizome litter nitrogen fluxes + phenology_n_to_litr_met_n(c,j) = phenology_n_to_litr_met_n(c,j) & + + livecrootn_to_litter(p) * fr_flab(ivt(p)) * wtcol(p) * croot_prof(p,j) + phenology_n_to_litr_cel_n(c,j) = phenology_n_to_litr_cel_n(c,j) & + + livecrootn_to_litter(p) * fr_fcel(ivt(p)) * wtcol(p) * croot_prof(p,j) + phenology_n_to_litr_lig_n(c,j) = phenology_n_to_litr_lig_n(c,j) & + + livecrootn_to_litter(p) * fr_flig(ivt(p)) * wtcol(p) * croot_prof(p,j) + + ! Rhizome litter phosphorus fluxes + phenology_p_to_litr_met_p(c,j) = phenology_p_to_litr_met_p(c,j) & + + livecrootp_to_litter(p) * fr_flab(ivt(p)) * wtcol(p) * croot_prof(p,j) + phenology_p_to_litr_cel_p(c,j) = phenology_p_to_litr_cel_p(c,j) & + + livecrootp_to_litter(p) * fr_fcel(ivt(p)) * wtcol(p) * croot_prof(p,j) + phenology_p_to_litr_lig_p(c,j) = phenology_p_to_litr_lig_p(c,j) & + + livecrootp_to_litter(p) * fr_flig(ivt(p)) * wtcol(p) * croot_prof(p,j) + + ! agroibis puts crop stem litter together with leaf litter ! so I've used the leaf lf_f* parameters instead of making ! new ones for now (slevis) diff --git a/components/elm/src/biogeochem/PhosphorusStateUpdate1Mod.F90 b/components/elm/src/biogeochem/PhosphorusStateUpdate1Mod.F90 index 5564b785d205..d6da9695aa3a 100644 --- a/components/elm/src/biogeochem/PhosphorusStateUpdate1Mod.F90 +++ b/components/elm/src/biogeochem/PhosphorusStateUpdate1Mod.F90 @@ -231,13 +231,15 @@ subroutine PhosphorusStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soi veg_ps%frootp(p) = veg_ps%frootp(p) + veg_pf%frootp_xfer_to_frootp(p)*dt veg_ps%frootp_xfer(p) = veg_ps%frootp_xfer(p) - veg_pf%frootp_xfer_to_frootp(p)*dt - if (woody(ivt(p)) == 1.0_r8) then + ! B Sulman: Allow graminoid rhizomes + veg_ps%livecrootp(p) = veg_ps%livecrootp(p) + veg_pf%livecrootp_xfer_to_livecrootp(p)*dt + veg_ps%livecrootp_xfer(p) = veg_ps%livecrootp_xfer(p) - veg_pf%livecrootp_xfer_to_livecrootp(p)*dt + + if (woody(ivt(p)) >= 1.0_r8) then veg_ps%livestemp(p) = veg_ps%livestemp(p) + veg_pf%livestemp_xfer_to_livestemp(p)*dt veg_ps%livestemp_xfer(p) = veg_ps%livestemp_xfer(p) - veg_pf%livestemp_xfer_to_livestemp(p)*dt veg_ps%deadstemp(p) = veg_ps%deadstemp(p) + veg_pf%deadstemp_xfer_to_deadstemp(p)*dt veg_ps%deadstemp_xfer(p) = veg_ps%deadstemp_xfer(p) - veg_pf%deadstemp_xfer_to_deadstemp(p)*dt - veg_ps%livecrootp(p) = veg_ps%livecrootp(p) + veg_pf%livecrootp_xfer_to_livecrootp(p)*dt - veg_ps%livecrootp_xfer(p) = veg_ps%livecrootp_xfer(p) - veg_pf%livecrootp_xfer_to_livecrootp(p)*dt veg_ps%deadcrootp(p) = veg_ps%deadcrootp(p) + veg_pf%deadcrootp_xfer_to_deadcrootp(p)*dt veg_ps%deadcrootp_xfer(p) = veg_ps%deadcrootp_xfer(p) - veg_pf%deadcrootp_xfer_to_deadcrootp(p)*dt end if @@ -266,7 +268,11 @@ subroutine PhosphorusStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soi veg_ps%deadcrootp(p) = veg_ps%deadcrootp(p) + veg_pf%livecrootp_to_deadcrootp(p)*dt veg_ps%livecrootp(p) = veg_ps%livecrootp(p) - veg_pf%livecrootp_to_retransp(p)*dt veg_ps%retransp(p) = veg_ps%retransp(p) + veg_pf%livecrootp_to_retransp(p)*dt - end if + else ! Nonwoody rhizome turnover (B Sulman) + veg_ps%livecrootp(p) = veg_ps%livecrootp(p) - veg_pf%livecrootp_to_litter(p)*dt + veg_ps%livecrootp(p) = veg_ps%livecrootp(p) - veg_pf%livecrootp_to_retransp(p)*dt + veg_ps%retransp(p) = veg_ps%retransp(p) + veg_pf%livecrootp_to_retransp(p)*dt + end if if (ivt(p) >= npcropmin) then ! Beth adds retrans from froot veg_ps%frootp(p) = veg_ps%frootp(p) - veg_pf%frootp_to_retransp(p)*dt veg_ps%retransp(p) = veg_ps%retransp(p) + veg_pf%frootp_to_retransp(p)*dt @@ -298,6 +304,10 @@ subroutine PhosphorusStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soi veg_ps%frootp(p) = veg_ps%frootp(p) + veg_pf%ppool_to_frootp(p)*dt veg_ps%ppool(p) = veg_ps%ppool(p) - veg_pf%ppool_to_frootp_storage(p)*dt veg_ps%frootp_storage(p) = veg_ps%frootp_storage(p) + veg_pf%ppool_to_frootp_storage(p)*dt + veg_ps%ppool(p) = veg_ps%ppool(p) - veg_pf%ppool_to_livecrootp(p)*dt + veg_ps%livecrootp(p) = veg_ps%livecrootp(p) + veg_pf%ppool_to_livecrootp(p)*dt + veg_ps%ppool(p) = veg_ps%ppool(p) - veg_pf%ppool_to_livecrootp_storage(p)*dt + veg_ps%livecrootp_storage(p) = veg_ps%livecrootp_storage(p) + veg_pf%ppool_to_livecrootp_storage(p)*dt if (woody(ivt(p)) == 1._r8) then veg_ps%ppool(p) = veg_ps%ppool(p) - veg_pf%ppool_to_livestemp(p)*dt @@ -308,10 +318,6 @@ subroutine PhosphorusStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soi veg_ps%deadstemp(p) = veg_ps%deadstemp(p) + veg_pf%ppool_to_deadstemp(p)*dt veg_ps%ppool(p) = veg_ps%ppool(p) - veg_pf%ppool_to_deadstemp_storage(p)*dt veg_ps%deadstemp_storage(p) = veg_ps%deadstemp_storage(p) + veg_pf%ppool_to_deadstemp_storage(p)*dt - veg_ps%ppool(p) = veg_ps%ppool(p) - veg_pf%ppool_to_livecrootp(p)*dt - veg_ps%livecrootp(p) = veg_ps%livecrootp(p) + veg_pf%ppool_to_livecrootp(p)*dt - veg_ps%ppool(p) = veg_ps%ppool(p) - veg_pf%ppool_to_livecrootp_storage(p)*dt - veg_ps%livecrootp_storage(p) = veg_ps%livecrootp_storage(p) + veg_pf%ppool_to_livecrootp_storage(p)*dt veg_ps%ppool(p) = veg_ps%ppool(p) - veg_pf%ppool_to_deadcrootp(p)*dt veg_ps%deadcrootp(p) = veg_ps%deadcrootp(p) + veg_pf%ppool_to_deadcrootp(p)*dt veg_ps%ppool(p) = veg_ps%ppool(p) - veg_pf%ppool_to_deadcrootp_storage(p)*dt @@ -334,14 +340,14 @@ subroutine PhosphorusStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soi veg_ps%leafp_xfer(p) = veg_ps%leafp_xfer(p) + veg_pf%leafp_storage_to_xfer(p)*dt veg_ps%frootp_storage(p) = veg_ps%frootp_storage(p) - veg_pf%frootp_storage_to_xfer(p)*dt veg_ps%frootp_xfer(p) = veg_ps%frootp_xfer(p) + veg_pf%frootp_storage_to_xfer(p)*dt + veg_ps%livecrootp_storage(p) = veg_ps%livecrootp_storage(p) - veg_pf%livecrootp_storage_to_xfer(p)*dt + veg_ps%livecrootp_xfer(p) = veg_ps%livecrootp_xfer(p) + veg_pf%livecrootp_storage_to_xfer(p)*dt - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1._r8) then veg_ps%livestemp_storage(p) = veg_ps%livestemp_storage(p) - veg_pf%livestemp_storage_to_xfer(p)*dt veg_ps%livestemp_xfer(p) = veg_ps%livestemp_xfer(p) + veg_pf%livestemp_storage_to_xfer(p)*dt veg_ps%deadstemp_storage(p) = veg_ps%deadstemp_storage(p) - veg_pf%deadstemp_storage_to_xfer(p)*dt veg_ps%deadstemp_xfer(p) = veg_ps%deadstemp_xfer(p) + veg_pf%deadstemp_storage_to_xfer(p)*dt - veg_ps%livecrootp_storage(p) = veg_ps%livecrootp_storage(p) - veg_pf%livecrootp_storage_to_xfer(p)*dt - veg_ps%livecrootp_xfer(p) = veg_ps%livecrootp_xfer(p) + veg_pf%livecrootp_storage_to_xfer(p)*dt veg_ps%deadcrootp_storage(p) = veg_ps%deadcrootp_storage(p) - veg_pf%deadcrootp_storage_to_xfer(p)*dt veg_ps%deadcrootp_xfer(p) = veg_ps%deadcrootp_xfer(p) + veg_pf%deadcrootp_storage_to_xfer(p)*dt end if diff --git a/components/elm/src/biogeophys/SoilStateType.F90 b/components/elm/src/biogeophys/SoilStateType.F90 index 088c68db3f8b..378267578a8a 100644 --- a/components/elm/src/biogeophys/SoilStateType.F90 +++ b/components/elm/src/biogeophys/SoilStateType.F90 @@ -661,7 +661,7 @@ subroutine InitCold(this, bounds) sand = sand3d(g,ti,1) gravel = grvl3d(g,ti,1) om_frac = organic3d(g,ti,1)/organic_max - else if (lev <= nlevsoi) then + else if (lev <= min(nlevbed,nlevsoi)) then do j = 1,nlevsoifl-1 if (zisoi(lev) >= zisoifl(j) .AND. zisoi(lev) < zisoifl(j+1)) then clay = clay3d(g,ti,j+1) @@ -677,7 +677,7 @@ subroutine InitCold(this, bounds) om_frac = 0._r8 endif else - if (lev <= nlevsoi) then ! duplicate clay and sand values from 10th soil layer + if (lev <= min(nlevbed,nlevsoi)) then ! duplicate clay and sand values from 10th soil layer clay = clay3d(g,ti,lev) sand = sand3d(g,ti,lev) gravel = grvl3d(g,ti,lev) @@ -692,7 +692,7 @@ subroutine InitCold(this, bounds) if (lun_pp%itype(l) == istdlak) then - if (lev <= nlevsoi) then + if (lev <= min(nlevbed,nlevsoi)) then this%cellsand_col(c,lev) = sand this%cellclay_col(c,lev) = clay this%cellgrvl_col(c,lev) = gravel @@ -705,7 +705,7 @@ subroutine InitCold(this, bounds) om_frac = 0._r8 ! No organic matter for urban end if - if (lev <= nlevbed) then + if (lev <= min(nlevbed,nlevsoi)) then this%cellsand_col(c,lev) = sand this%cellclay_col(c,lev) = clay this%cellgrvl_col(c,lev) = gravel diff --git a/components/elm/src/biogeophys/SoilWaterMovementMod.F90 b/components/elm/src/biogeophys/SoilWaterMovementMod.F90 index 6d57e7fc0c5d..f3e6009dcc38 100644 --- a/components/elm/src/biogeophys/SoilWaterMovementMod.F90 +++ b/components/elm/src/biogeophys/SoilWaterMovementMod.F90 @@ -1195,7 +1195,7 @@ subroutine Compute_EffecRootFrac_And_VertTranSink_Default(bounds, num_filterc, & do fc = 1, num_filterc c = filterc(fc) nlevbed = nlev2bed(c) - do j = 1, nlevbed + do j = 1, max(nlevbed, nlevsoi) rootr_col(c,j) = 0._r8 end do end do @@ -1298,6 +1298,7 @@ subroutine Compute_EffecRootFrac_And_VertTranSink_HydStress( bounds, & !----------------------------------------------------------------------- associate(& + nlev2bed => col_pp%nlevbed , & ! Input: [integer (:) ] number of layers to bedrock k_soil_root => soilstate_vars%k_soil_root_patch , & ! Input: [real(r8) (:,:) ] ! soil-root interface conductance (mm/s) !qflx_phs_neg_col => waterflux_vars%qflx_phs_neg_col , & ! Input: [real(r8) (:) ] n @@ -1347,7 +1348,7 @@ subroutine Compute_EffecRootFrac_And_VertTranSink_HydStress( bounds, & ! Back out the effective root density if( sum(qflx_rootsoi_col(c,1:nlevsoi))>0.0_r8 ) then - do j = 1, nlevsoi + do j = 1, max(nlev2bed(c), nlevsoi) rootr_col(c,j) = qflx_rootsoi_col(c,j)/sum( qflx_rootsoi_col(c,1:nlevsoi)) end do else diff --git a/components/elm/src/cpl/lnd_import_export.F90 b/components/elm/src/cpl/lnd_import_export.F90 index 4626142e0006..7dab57839d3a 100644 --- a/components/elm/src/cpl/lnd_import_export.F90 +++ b/components/elm/src/cpl/lnd_import_export.F90 @@ -407,7 +407,7 @@ subroutine lnd_import( bounds, x2l, atm2lnd_vars, glc2lnd_vars, lnd2atm_vars) end if ierr = nf90_open(trim(metdata_bypass) // '/' // trim(metdata_fname), NF90_NOWRITE, met_ncids(v)) - if (ierr .ne. 0) call endrun(msg=' ERROR: Failed to open cpl_bypass input meteorology file' ) + if (ierr .ne. 0) call endrun(msg=' ERROR: Failed to open cpl_bypass input meteorology file ' // trim(metdata_bypass) // '/' // trim(metdata_fname)) !get timestep information ierr = nf90_inq_dimid(met_ncids(v), 'DTIME', dimid) diff --git a/components/elm/src/data_types/VegetationDataType.F90 b/components/elm/src/data_types/VegetationDataType.F90 index 5d84cce180bc..7936a20784bd 100644 --- a/components/elm/src/data_types/VegetationDataType.F90 +++ b/components/elm/src/data_types/VegetationDataType.F90 @@ -506,6 +506,7 @@ module VegetationDataType real(r8), pointer :: frootc_to_litter (:) => null() ! fine root C litterfall (gC/m2/s) real(r8), pointer :: livestemc_to_litter (:) => null() ! live stem C litterfall (gC/m2/s) real(r8), pointer :: grainc_to_food (:) => null() ! grain C to food for prognostic crop(gC/m2/s) + real(r8), pointer :: livecrootc_to_litter (:) => null() ! live coarse root C litterfall (gC/m2/s) ! maintenance respiration fluxes real(r8), pointer :: leaf_mr (:) => null() ! leaf maintenance respiration (gC/m2/s) @@ -773,6 +774,7 @@ module VegetationDataType real(r8), pointer :: leafn_to_retransn (:) => null() ! leaf N to retranslocated N pool (gN/m2/s) real(r8), pointer :: frootn_to_retransn (:) => null() ! fine root N to retranslocated N pool (gN/m2/s) real(r8), pointer :: frootn_to_litter (:) => null() ! fine root N litterfall (gN/m2/s) + real(r8), pointer :: livecrootn_to_litter (:) => null() ! live coarse root N litterfall (gN/m2/s) ! allocation fluxes real(r8), pointer :: retransn_to_npool (:) => null() ! deployment of retranslocated N (gN/m2/s) real(r8), pointer :: sminn_to_npool (:) => null() ! deployment of soil mineral N uptake (gN/m2/s) @@ -952,6 +954,7 @@ module VegetationDataType real(r8), pointer :: leafp_to_retransp (:) ! leaf P to retranslocated P pool (gP/m2/s) real(r8), pointer :: frootp_to_retransp (:) ! fine root P to retranslocated P pool (gP/m2/s) real(r8), pointer :: frootp_to_litter (:) ! fine root P litterfall (gP/m2/s) + real(r8), pointer :: livecrootp_to_litter (:) ! live coarse root P litterfall (gP/m2/s) real(r8), pointer :: retransp_to_ppool (:) ! deployment of retranslocated P (gP/m2/s) real(r8), pointer :: sminp_to_ppool (:) ! deployment of soil mineral P uptake (gP/m2/s) real(r8), pointer :: ppool_to_grainp (:) ! allocation to grain P for prognostic crop (gP/m2/s) @@ -5755,6 +5758,7 @@ subroutine veg_cf_init(this, begp, endp, carbon_type) allocate(this%deadcrootc_xfer_to_deadcrootc (begp:endp)) ; this%deadcrootc_xfer_to_deadcrootc (:) = spval allocate(this%leafc_to_litter (begp:endp)) ; this%leafc_to_litter (:) = spval allocate(this%frootc_to_litter (begp:endp)) ; this%frootc_to_litter (:) = spval + allocate(this%livecrootc_to_litter (begp:endp)) ; this%livecrootc_to_litter (:) = spval allocate(this%livestemc_to_litter (begp:endp)) ; this%livestemc_to_litter (:) = spval allocate(this%grainc_to_food (begp:endp)) ; this%grainc_to_food (:) = spval allocate(this%leaf_mr (begp:endp)) ; this%leaf_mr (:) = spval @@ -6294,6 +6298,11 @@ subroutine veg_cf_init(this, begp, endp, carbon_type) call hist_addfld1d (fname='FROOTC_TO_LITTER', units='gC/m^2/s', & avgflag='A', long_name='fine root C litterfall', & ptr_patch=this%frootc_to_litter, default='inactive') + + this%livecrootc_to_litter(begp:endp) = spval + call hist_addfld1d (fname='LIVECROOTC_TO_LITTER', units='gC/m^2/s', & + avgflag='A', long_name='live coarse root C litterfall', & + ptr_patch=this%livecrootc_to_litter, default='inactive') this%leaf_mr(begp:endp) = spval call hist_addfld1d (fname='LEAF_MR', units='gC/m^2/s', & @@ -6956,6 +6965,11 @@ subroutine veg_cf_init(this, begp, endp, carbon_type) avgflag='A', long_name='C13 fine root C litterfall', & ptr_patch=this%frootc_to_litter, default='inactive') + this%livecrootc_to_litter(begp:endp) = spval + call hist_addfld1d (fname='C13_LIVECROOTC_TO_LITTER', units='gC13/m^2/s', & + avgflag='A', long_name='C13 live coarse root C litterfall', & + ptr_patch=this%livecrootc_to_litter, default='inactive') + this%leaf_mr(begp:endp) = spval call hist_addfld1d (fname='C13_LEAF_MR', units='gC13/m^2/s', & avgflag='A', long_name='C13 leaf maintenance respiration', & @@ -7551,6 +7565,11 @@ subroutine veg_cf_init(this, begp, endp, carbon_type) avgflag='A', long_name='C14 fine root C litterfall', & ptr_patch=this%frootc_to_litter, default='inactive') + this%livecrootc_to_litter(begp:endp) = spval + call hist_addfld1d (fname='C14_LIVECROOTC_TO_LITTER', units='gC14/m^2/s', & + avgflag='A', long_name='C14 live coarse root C litterfall', & + ptr_patch=this%livecrootc_to_litter, default='inactive') + this%leaf_mr(begp:endp) = spval call hist_addfld1d (fname='C14_LEAF_MR', units='gC14/m^2/s', & avgflag='A', long_name='C14 leaf maintenance respiration', & @@ -8242,6 +8261,7 @@ subroutine veg_cf_summary(this, bounds, num_soilp, filter_soilp, num_soilc, filt this%litfall(p) = & this%leafc_to_litter(p) + & this%frootc_to_litter(p) + & + this%livecrootc_to_litter(p) + & this%m_leafc_to_litter(p) + & this%m_leafc_storage_to_litter(p) + & this%m_leafc_xfer_to_litter(p) + & @@ -8415,7 +8435,8 @@ subroutine veg_cf_summary(this, bounds, num_soilp, filter_soilp, num_soilc, filt this%hrv_livecrootc_xfer_to_litter(p) + & this%hrv_deadcrootc_to_litter(p) + & this%hrv_deadcrootc_storage_to_litter(p) + & - this%hrv_deadcrootc_xfer_to_litter(p) + this%hrv_deadcrootc_xfer_to_litter(p) + & + this%livecrootc_to_litter(p) ! putting the harvested crop stem and grain in the wood loss bdrewniak if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then this%woodc_loss(p) = & @@ -8694,6 +8715,7 @@ subroutine veg_cf_setvalues ( this, num_patch, filter_patch, value_patch) this%deadcrootc_xfer_to_deadcrootc(i) = value_patch this%leafc_to_litter(i) = value_patch this%frootc_to_litter(i) = value_patch + this%livecrootc_to_litter(i) = value_patch this%leaf_mr(i) = value_patch this%froot_mr(i) = value_patch this%livestem_mr(i) = value_patch @@ -8926,6 +8948,7 @@ subroutine veg_nf_init(this, begp, endp) allocate(this%leafn_to_retransn (begp:endp)) ; this%leafn_to_retransn (:) = spval allocate(this%frootn_to_retransn (begp:endp)) ; this%frootn_to_retransn (:) = spval allocate(this%frootn_to_litter (begp:endp)) ; this%frootn_to_litter (:) = spval + allocate(this%livecrootn_to_litter (begp:endp)) ; this%livecrootn_to_litter (:) = spval allocate(this%retransn_to_npool (begp:endp)) ; this%retransn_to_npool (:) = spval allocate(this%sminn_to_npool (begp:endp)) ; this%sminn_to_npool (:) = spval allocate(this%npool_to_leafn (begp:endp)) ; this%npool_to_leafn (:) = spval @@ -9255,6 +9278,11 @@ subroutine veg_nf_init(this, begp, endp) avgflag='A', long_name='fine root N litterfall', & ptr_patch=this%frootn_to_litter, default='inactive') + this%livecrootn_to_litter(begp:endp) = spval + call hist_addfld1d (fname='LIVECROOTN_TO_LITTER', units='gN/m^2/s', & + avgflag='A', long_name='live coarse root N litterfall', & + ptr_patch=this%livecrootn_to_litter, default='inactive') + this%retransn_to_npool(begp:endp) = spval call hist_addfld1d (fname='RETRANSN_TO_NPOOL', units='gN/m^2/s', & avgflag='A', long_name='deployment of retranslocated N', & @@ -9724,6 +9752,7 @@ subroutine veg_nf_setvalues ( this, num_patch, filter_patch, value_patch) this%leafn_to_litter(i) = value_patch this%leafn_to_retransn(i) = value_patch this%frootn_to_litter(i) = value_patch + this%livecrootn_to_litter(i) = value_patch this%retransn_to_npool(i) = value_patch this%sminn_to_npool(i) = value_patch this%npool_to_leafn(i) = value_patch @@ -9915,7 +9944,8 @@ subroutine veg_nf_summary(this, bounds, num_soilc, filter_soilc, num_soilp, filt else this%sen_nloss_litter(p) = & this%leafn_to_litter(p) + & - this%frootn_to_litter(p) + this%frootn_to_litter(p) + & + this%livecrootn_to_litter(p) end if end do @@ -10057,6 +10087,7 @@ subroutine veg_pf_init(this, begp, endp) allocate(this%leafp_to_retransp (begp:endp)) ; this%leafp_to_retransp (:) = spval allocate(this%frootp_to_retransp (begp:endp)) ; this%frootp_to_retransp (:) = spval allocate(this%frootp_to_litter (begp:endp)) ; this%frootp_to_litter (:) = spval + allocate(this%livecrootp_to_litter (begp:endp)) ; this%livecrootp_to_litter (:) = spval allocate(this%retransp_to_ppool (begp:endp)) ; this%retransp_to_ppool (:) = spval allocate(this%sminp_to_ppool (begp:endp)) ; this%sminp_to_ppool (:) = spval allocate(this%biochem_pmin_to_plant (begp:endp)) ; this%biochem_pmin_to_plant (:) = spval @@ -10379,6 +10410,11 @@ subroutine veg_pf_init(this, begp, endp) avgflag='A', long_name='fine root P litterfall', & ptr_patch=this%frootp_to_litter, default='inactive') + this%livecrootp_to_litter(begp:endp) = spval + call hist_addfld1d (fname='LIVECROOTP_TO_LITTER', units='gP/m^2/s', & + avgflag='A', long_name='live coarse root P litterfall', & + ptr_patch=this%livecrootp_to_litter, default='inactive') + this%retransp_to_ppool(begp:endp) = spval call hist_addfld1d (fname='RETRANSP_TO_PPOOL', units='gP/m^2/s', & avgflag='A', long_name='deployment of retranslocated P', & @@ -10851,6 +10887,7 @@ subroutine veg_pf_setvalues ( this, num_patch, filter_patch, value_patch) this%leafp_to_litter(i) = value_patch this%leafp_to_retransp(i) = value_patch this%frootp_to_litter(i) = value_patch + this%livecrootp_to_litter(i) = value_patch this%retransp_to_ppool(i) = value_patch this%sminp_to_ppool(i) = value_patch this%ppool_to_leafp(i) = value_patch @@ -11036,7 +11073,8 @@ subroutine veg_pf_summary(this, bounds, num_soilc, filter_soilc, num_soilp, filt else this%sen_ploss_litter(p) = & this%leafp_to_litter(p) + & - this%frootp_to_litter(p) + this%frootp_to_litter(p) + & + this%livecrootp_to_litter(p) end if end do diff --git a/components/elm/src/data_types/VegetationPropertiesType.F90 b/components/elm/src/data_types/VegetationPropertiesType.F90 index 2bdc12a9fc30..f5ae770ea2c7 100644 --- a/components/elm/src/data_types/VegetationPropertiesType.F90 +++ b/components/elm/src/data_types/VegetationPropertiesType.F90 @@ -64,6 +64,7 @@ module VegetationPropertiesType real(r8), pointer :: fr_flig (:) => null() ! fine root litter lignin fraction real(r8), pointer :: leaf_long (:) => null() ! leaf longevity (yrs) real(r8), pointer :: froot_long (:) => null() ! fine root longevity (yrs) + real(r8), pointer :: rhizome_long (:) => null() ! nonwoody rhizome longevity (yrs) real(r8), pointer :: evergreen (:) => null() ! binary flag for evergreen leaf habit (0 or 1) real(r8), pointer :: stress_decid (:) => null() ! binary flag for stress-deciduous leaf habit (0 or 1) real(r8), pointer :: season_decid (:) => null() ! binary flag for seasonal-deciduous leaf habit (0 or 1) @@ -93,6 +94,9 @@ module VegetationPropertiesType real(r8), pointer :: deadwdcp (:) => null() ! dead wood (xylem and heartwood) C:P (gC/gP) real(r8), pointer :: graincp (:) => null() ! grain C:P (gC/gP) for prognostic crop model + real(r8), pointer :: Nfix_NPP_c1 (:) => null() ! Pre-exponential parameter in NPP-based N fixation eqn + real(r8), pointer :: Nfix_NPP_c2 (:) => null() ! Exponential parameter in NPP-based N fixation eqn + ! pft dependent parameters for phosphorus for nutrient competition real(r8), pointer :: vmax_plant_nh4(:) => null() ! vmax for plant nh4 uptake real(r8), pointer :: vmax_plant_no3(:) => null() ! vmax for plant no3 uptake @@ -164,10 +168,11 @@ subroutine veg_vp_init(this) use pftvarcon , only : c3psn, slatop, dsladlai, leafcn, flnr, woody use pftvarcon , only : lflitcn, frootcn, livewdcn, deadwdcn, froot_leaf, stem_leaf, croot_stem use pftvarcon , only : flivewd, fcur, lf_flab, lf_fcel, lf_flig, fr_flab, fr_fcel, fr_flig - use pftvarcon , only : leaf_long, froot_long, evergreen, stress_decid, season_decid + use pftvarcon , only : leaf_long, froot_long, rhizome_long, evergreen, stress_decid, season_decid use pftvarcon , only : fertnitro, graincn, fleafcn, ffrootcn, fstemcn, dwood use pftvarcon , only : presharv, convfact, fyield use pftvarcon , only : leafcp,lflitcp, frootcp, livewdcp, deadwdcp,graincp + use pftvarcon , only : Nfix_NPP_c1, Nfix_NPP_c2 use pftvarcon , only : vmax_plant_nh4, vmax_plant_no3, vmax_plant_p, vmax_minsurf_p_vr use pftvarcon , only : km_plant_nh4, km_plant_no3, km_plant_p, km_minsurf_p_vr use pftvarcon , only : km_decomp_nh4, km_decomp_no3, km_decomp_p, km_nit, km_den @@ -229,6 +234,7 @@ subroutine veg_vp_init(this) allocate(this%fr_flig (0:numpft)) ; this%fr_flig (:) =spval allocate(this%leaf_long (0:numpft)) ; this%leaf_long (:) =spval allocate(this%froot_long (0:numpft)) ; this%froot_long (:) =spval + allocate(this%rhizome_long (0:numpft)) ; this%rhizome_long (:) =spval allocate(this%evergreen (0:numpft)) ; this%evergreen (:) =spval allocate(this%stress_decid (0:numpft)) ; this%stress_decid (:) =spval allocate(this%season_decid (0:numpft)) ; this%season_decid (:) =spval @@ -251,6 +257,8 @@ subroutine veg_vp_init(this) allocate(this%livewdcp (0:numpft)) ; this%livewdcp (:) =spval allocate(this%deadwdcp (0:numpft)) ; this%deadwdcp (:) =spval allocate(this%graincp (0:numpft)) ; this%graincp (:) =spval + allocate(this%Nfix_NPP_c1 (0:numpft)) ; this%Nfix_NPP_c1 (:) =spval + allocate(this%Nfix_NPP_c2 (0:numpft)) ; this%Nfix_NPP_c2 (:) =spval allocate( this%alpha_nfix (0:numpft)) ; this%alpha_nfix (:) =spval allocate( this%alpha_ptase (0:numpft)) ; this%alpha_ptase (:) =spval @@ -352,6 +360,7 @@ subroutine veg_vp_init(this) this%fr_flig(m) = fr_flig(m) this%leaf_long(m) = leaf_long(m) this%froot_long(m) = froot_long(m) + this%rhizome_long(m) = rhizome_long(m) this%evergreen(m) = evergreen(m) this%stress_decid(m) = stress_decid(m) this%season_decid(m) = season_decid(m) @@ -393,6 +402,10 @@ subroutine veg_vp_init(this) this%nstor(m) = nstor(m) this%br_xr(m) = br_xr(m) + + this%Nfix_NPP_c1(m) = Nfix_NPP_c1(m) + this%Nfix_NPP_c2(m) = Nfix_NPP_c2(m) + end do do m = 0,numpft diff --git a/components/elm/src/main/controlMod.F90 b/components/elm/src/main/controlMod.F90 index efb0dc540c3e..cba83c6e8aa3 100755 --- a/components/elm/src/main/controlMod.F90 +++ b/components/elm/src/main/controlMod.F90 @@ -285,6 +285,9 @@ subroutine control_init( ) ! bgc & pflotran interface namelist /elm_inparm/ use_elm_interface, use_elm_bgc, use_pflotran + ! onset_gdd_extension in plant phenology + namelist /elm_inparm/ onset_gdd_extension + namelist /elm_inparm/ use_dynroot namelist /elm_inparm/ use_var_soil_thick, use_lake_wat_storage @@ -891,6 +894,9 @@ subroutine control_spmd() call mpi_bcast (use_elm_bgc, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_pflotran, 1, MPI_LOGICAL, 0, mpicom, ier) + ! phenology + call mpi_bcast (onset_gdd_extension, 1, MPI_LOGICAL, 0, mpicom, ier) + !cpl_bypass call mpi_bcast (metdata_type, len(metdata_type), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (metdata_bypass, len(metdata_bypass), MPI_CHARACTER, 0, mpicom, ier) diff --git a/components/elm/src/main/elm_varctl.F90 b/components/elm/src/main/elm_varctl.F90 index 2aa37ce849de..0d3f9fc83593 100644 --- a/components/elm/src/main/elm_varctl.F90 +++ b/components/elm/src/main/elm_varctl.F90 @@ -462,6 +462,15 @@ module elm_varctl !$acc declare copyin(initth_pf2clm) !$acc declare copyin(pf_clmnstep0 ) + !----------------------------------------------------------------------- + ! onset_gdd summation ending switch in phenology + ! by default, onset_gdd will reset to zero passing summer-solstice + ! This may cause non-growing if heavy winter snowing which results in + ! snow-melting passing summer-solstice in arctic. + ! When this switches, it will end by offset critical daylength (i.e. vegetation senescence starts normally in Fall) + logical, public :: onset_gdd_extension = .false. + !$acc declare create(onset_gdd_extension) + ! cpl_bypass character(len=fname_len), public :: metdata_type = ' ' ! metdata type for CPL_BYPASS mode character(len=fname_len), public :: metdata_bypass = ' ' ! met data directory for CPL_BYPASS mode (site, qian, cru_ncep) diff --git a/components/elm/src/main/initVerticalMod.F90 b/components/elm/src/main/initVerticalMod.F90 index 96e064b267a4..1e71b1163444 100755 --- a/components/elm/src/main/initVerticalMod.F90 +++ b/components/elm/src/main/initVerticalMod.F90 @@ -636,7 +636,7 @@ subroutine initVertical(bounds, snow_depth, thick_wall, thick_roof) col_pp%nlevbed(c) = 5 else ! check for near zero DTBs, set minimum value - beddep = max(dtb(g,ti), 0.2_r8) + beddep = max(dtb(g,ti), zsoi(1)) ! better to use first-layer thickness j = 0 zimid = 0._r8 do while (zimid < beddep .and. j < nlevgrnd) @@ -648,7 +648,7 @@ subroutine initVertical(bounds, snow_depth, thick_wall, thick_roof) end if j = j + 1 enddo - nlevbed = max(nlevbed, 5) + nlevbed = max(nlevbed, 1) ! better to use first-layer thickness as the minimal nlevbed = min(nlevbed, nlevgrnd) col_pp%nlevbed(c) = nlevbed col_pp%zibed(c) = zisoi(nlevbed) diff --git a/components/elm/src/main/pftvarcon.F90 b/components/elm/src/main/pftvarcon.F90 index 4f7d411ea15f..8942274e1bec 100644 --- a/components/elm/src/main/pftvarcon.F90 +++ b/components/elm/src/main/pftvarcon.F90 @@ -123,6 +123,10 @@ module pftvarcon real(r8), allocatable :: livewdcp(:) !live wood (phloem and ray parenchyma) C:P (gC/gP) real(r8), allocatable :: deadwdcp(:) !dead wood (xylem and heartwood) C:P (gC/gP) + ! Add user-defined N fixation parameters - B. Sulman + real(r8), allocatable :: Nfix_NPP_c1(:) ! Pre-exponential parameter in NPP-Nfix eqn + real(r8), allocatable :: Nfix_NPP_c2(:) ! Exponential parameter in NPP-Nfix eqn + ! for crop ! These arrays give information about the merge of unused crop types to the types CLM @@ -175,6 +179,7 @@ module pftvarcon real(r8), allocatable :: fr_flig(:) !fine root litter lignin fraction real(r8), allocatable :: leaf_long(:) !leaf longevity (yrs) real(r8), allocatable :: froot_long(:) !fine root longevity(yrs) + real(r8), allocatable :: rhizome_long(:) !nonwoody rhizome longevity(yrs) 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) @@ -444,6 +449,9 @@ subroutine pftconrd allocate( livewdcp (0:mxpft) ) allocate( deadwdcp (0:mxpft) ) + allocate( Nfix_NPP_c1 (0:mxpft) ) + allocate( Nfix_NPP_c2 (0:mxpft) ) + allocate( grperc (0:mxpft) ) allocate( grpnow (0:mxpft) ) allocate( rootprof_beta (0:mxpft) ) @@ -492,6 +500,7 @@ subroutine pftconrd allocate( fr_flig (0:mxpft) ) allocate( leaf_long (0:mxpft) ) allocate( froot_long (0:mxpft) ) + allocate( rhizome_long (0:mxpft) ) allocate( evergreen (0:mxpft) ) allocate( stress_decid (0:mxpft) ) allocate( season_decid (0:mxpft) ) @@ -677,6 +686,10 @@ subroutine pftconrd call ncd_io('deadwdcp',deadwdcp, 'read', ncid, readvar=readv, posNOTonfile=.true.) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(__FILE__, __LINE__)) + call ncd_io('Nfix_NPP_c1',Nfix_NPP_c1, 'read', ncid, readvar=readv, posNOTonfile=.true.) + if ( .not. readv ) Nfix_NPP_c1(:) = 1.8_r8 ! Default value in equation, previously hard-coded + call ncd_io('Nfix_NPP_c2',Nfix_NPP_c2, 'read', ncid, readvar=readv, posNOTonfile=.true.) + if ( .not. readv ) Nfix_NPP_c2(:) = 0.003_r8 ! Default value in equation, previously hard-coded call ncd_io('grperc',grperc, 'read', ncid, readvar=readv, posNOTonfile=.true.) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(__FILE__, __LINE__)) @@ -708,8 +721,9 @@ subroutine pftconrd if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(__FILE__, __LINE__)) call ncd_io('froot_long',froot_long, 'read', ncid, readvar=readv, posNOTonfile=.true.) if (.not. readv) froot_long = leaf_long - !if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(__FILE__, __LINE__)) - call ncd_io('evergreen',evergreen, 'read', ncid, readvar=readv, posNOTonfile=.true.) + call ncd_io('rhizome_long',rhizome_long(0:npft-1), 'read', ncid, readvar=readv, posNOTonfile=.true.) + if (.not. readv) rhizome_long = froot_long + call ncd_io('evergreen',evergreen(0:npft-1), 'read', ncid, readvar=readv, posNOTonfile=.true.) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(__FILE__, __LINE__)) call ncd_io('stress_decid',stress_decid, 'read', ncid, readvar=readv, posNOTonfile=.true.) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(__FILE__, __LINE__))