diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm index 15d92057ee..9074b8368b 100755 --- a/bld/CLMBuildNamelist.pm +++ b/bld/CLMBuildNamelist.pm @@ -1706,10 +1706,10 @@ sub process_namelist_inline_logic { } setup_logic_cnmatrix($opts, $nl_flags, $definition, $defaults, $nl, $envxml_ref); setup_logic_spinup($opts, $nl_flags, $definition, $defaults, $nl); - setup_logic_supplemental_nitrogen($opts, $nl_flags, $definition, $defaults, $nl); setup_logic_c_isotope($opts, $nl_flags, $definition, $defaults, $nl); setup_logic_snowpack($opts, $nl_flags, $definition, $defaults, $nl); setup_logic_fates($opts, $nl_flags, $definition, $defaults, $nl); + setup_logic_supplemental_nitrogen($opts, $nl_flags, $definition, $defaults, $nl); setup_logic_z0param($opts, $nl_flags, $definition, $defaults, $nl); setup_logic_misc($opts, $nl_flags, $definition, $defaults, $nl); @@ -3330,7 +3330,7 @@ sub setup_logic_supplemental_nitrogen { } elsif ( $nl_flags->{'bgc_mode'} eq "fates" && not &value_is_true( $nl_flags->{'use_fates_sp'}) ) { # Or... if its fates but not fates-sp add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, - 'suplnitro', 'use_fates'=>$nl_flags->{'use_fates'}); + 'suplnitro', 'fates_parteh_mode'=>$nl->get_value('fates_parteh_mode')); } # # Error checking for suplnitro @@ -3349,6 +3349,18 @@ sub setup_logic_supplemental_nitrogen { $log->warning("There is no need to use a bgc_spinup mode when supplemental Nitrogen is on for all PFT's, as these modes spinup Nitrogen" ); } } + + my $parteh_mode = $nl->get_value('fates_parteh_mode'); + if ( ($parteh_mode == 1) && ($suplnitro !~ /ALL/) ) { + $log->fatal_error("supplemental Nitrogen (suplnitro) is NOT set to ALL, FATES is on, " . + "and fates_parteh_mode is 1, so Nitrogen is not active; " . + "change suplnitro back to ALL"); + } + if ( ($parteh_mode == 2) && &value_is_true( $nl_flags->{'use_fates_sp'}) ) { + $log->fatal_error("FATES is on, " . + "FATES-SP is active, but fates_parteh_mode is 2, so Nitrogen is active; " . + "change fates_parteh_mode to 1 or do not use FATES-SP"); + } } } @@ -4926,14 +4938,6 @@ sub setup_logic_fates { 'use_fates_managed_fire'=>$nl->get_value('use_fates_managed_fire'), 'use_fates_sp'=>$nl_flags->{'use_fates_sp'} ); - my $suplnitro = $nl->get_value('suplnitro'); - my $parteh_mode = $nl->get_value('fates_parteh_mode'); - if ( ($parteh_mode == 1) && ($suplnitro !~ /ALL/) && not &value_is_true( $nl_flags->{'use_fates_sp'}) ) { - $log->fatal_error("supplemental Nitrogen (suplnitro) is NOT set to ALL, FATES is on, " . - "but and FATES-SP is not active, but fates_parteh_mode is 1, so Nitrogen is not active" . - "Change suplnitro back to ALL"); - } - # For FATES SP mode make sure no-competetiion, and fixed-biogeography are also set # And also check for other settings that can't be trigged on as well # diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml index 9732de325a..1a2ac0df50 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -220,10 +220,6 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .false. 0.0d00 - -NONE -ALL - 0.50,0.30 0.60,0.40 @@ -2689,6 +2685,9 @@ lnd/clm2/surfdata_esmf/NEON/ctsm5.4.0/surfdata_1x1_NEON_TOOL_hist_2000_78pfts_c2 .false. 2,2 + +NONE +ALL diff --git a/cime_config/testdefs/testlist_clm.xml b/cime_config/testdefs/testlist_clm.xml index 9fc44ea70a..53cd078647 100644 --- a/cime_config/testdefs/testlist_clm.xml +++ b/cime_config/testdefs/testlist_clm.xml @@ -3849,7 +3849,27 @@ - + + + + + + + + + + + + + + + + + + + + + diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/user_nl_clm index 65b24d27b2..92ab39ca66 100644 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/user_nl_clm @@ -27,7 +27,7 @@ hist_fincl1 = 'FATES_NCOHORTS', 'FATES_TRIMMING', 'FATES_AREA_PLANTS', 'FATES_DEMOTION_CARBONFLUX', 'FATES_PROMOTION_CARBONFLUX', 'FATES_MORTALITY_CFLUX_CANOPY', 'FATES_MORTALITY_CFLUX_USTORY', 'FATES_NEP', 'FATES_HET_RESP', 'FATES_FIRE_CLOSS', 'FATES_FIRE_FLUX_EL', -'FATES_CBALANCE_ERROR', 'FATES_ERROR_EL', 'FATES_LEAF_ALLOC', +'FATES_CBALANCE_ERROR', 'FATES_LEAF_ALLOC', 'FATES_SEED_ALLOC', 'FATES_STEM_ALLOC', 'FATES_FROOT_ALLOC', 'FATES_CROOT_ALLOC', 'FATES_STORE_ALLOC', 'FATES_PATCHAREA_LU', 'FATES_DISTURBANCE_RATE_MATRIX_LULU', diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/shell_commands index abcfea1425..139be432dd 100644 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/shell_commands +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/shell_commands @@ -1,13 +1,10 @@ SRCDIR=`./xmlquery SRCROOT --value` CASEDIR=`./xmlquery CASEROOT --value` FATESDIR=$SRCDIR/src/fates/ - -FATESPARAMFILE=$CASEDIR/fates_params_prt2_prescribed_np.json +FATESPARAMFILE=$CASEDIR/fates_params_prt2_prescribed_p.json cp $FATESDIR/parameter_files/fates_params_default.json $FATESPARAMFILE -$FATESDIR/tools/modify_fates_paramfile.py --overwrite --fin $FATESPARAMFILE --param fates_cnp_prescribed_nuptake --values 1.0 --indices all - -$FATESDIR/tools/modify_fates_paramfile.py --overwrite --fin $FATESPARAMFILE --param fates_cnp_prescribed_puptake --values 1.0 --indices all +$FATESDIR/tools/modify_fates_paramfile.py --overwrite --fin $FATESPARAMFILE --param fates_cnp_prescribed_puptake --values 10.0 --indices all -echo "fates_paramfile = '$FATESPARAMFILE'" >> $CASEDIR/user_nl_clm \ No newline at end of file +echo "fates_paramfile = '$FATESPARAMFILE'" >> $CASEDIR/user_nl_clm diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2_suplnAll/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2_suplnAll/include_user_mods new file mode 100644 index 0000000000..c55d2e90d7 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2_suplnAll/include_user_mods @@ -0,0 +1,3 @@ +../nofireemis +../cn_conly +../FatesColdPRT2 diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2_synthN/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2_synthN/include_user_mods new file mode 100644 index 0000000000..e781a89ea2 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2_synthN/include_user_mods @@ -0,0 +1,3 @@ +../Fates +../FatesCold +../FatesSetupParamBuild/ diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2_synthN/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2_synthN/shell_commands new file mode 100644 index 0000000000..2ebf250b2d --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2_synthN/shell_commands @@ -0,0 +1,11 @@ +SRCDIR=`./xmlquery SRCROOT --value` +CASEDIR=`./xmlquery CASEROOT --value` +FATESDIR=$SRCDIR/src/fates/ +FATESPARAMFILE=$CASEDIR/fates_params_prt2_prescribed_np.json + +cp $FATESDIR/parameter_files/fates_params_default.json $FATESPARAMFILE + +$FATESDIR/tools/modify_fates_paramfile.py --overwrite --fin $FATESPARAMFILE --param fates_cnp_prescribed_puptake --values 10.0 --indices all +$FATESDIR/tools/modify_fates_paramfile.py --overwrite --fin $FATESPARAMFILE --param fates_cnp_prescribed_nuptake --values 10.0 --indices all + +echo "fates_paramfile = '$FATESPARAMFILE'" >> $CASEDIR/user_nl_clm diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2_synthN/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2_synthN/user_nl_clm new file mode 100644 index 0000000000..679f025b60 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2_synthN/user_nl_clm @@ -0,0 +1,12 @@ +fates_parteh_mode = 2 +hist_fincl1 = 'FATES_L2FR','FATES_L2FR_CANOPY_REC_PF','FATES_L2FR_USTORY_REC_PF', +'FATES_NH4UPTAKE_SZPF','FATES_NO3UPTAKE_SZPF','FATES_NEFFLUX_SZPF', +'FATES_NDEMAND_SZPF','FATES_NFIX_SYM_SZPF','FATES_NH4UPTAKE','FATES_NO3UPTAKE', +'FATES_NEFFLUX','FATES_NDEMAND','FATES_NFIX_SYM','FATES_STOREN','FATES_STOREN_TF', +'FATES_VEGN','FATES_SAPWOODN','FATES_LEAFN','FATES_FROOTN','FATES_REPRON','FATES_VEGN_SZPF', +'FATES_LEAFN_SZPF','FATES_FROOTN_SZPF','FATES_SAPWOODN_SZPF','FATES_STOREN_SZPF','FATES_STOREN_TF_CANOPY_SZPF', +'FATES_STOREN_TF_USTORY_SZPF','FATES_REPRON_SZPF','FATES_STOREP','FATES_STOREP_TF','FATES_VEGP','FATES_SAPWOODP', +'FATES_LEAFP','FATES_FROOTP','FATES_REPROP','FATES_PUPTAKE','FATES_PEFFLUX','FATES_PDEMAND', +'FATES_VEGP_SZPF','FATES_LEAFP_SZPF','FATES_FROOTP_SZPF','FATES_SAPWOODP_SZPF','FATES_STOREP_SZPF', +'FATES_STOREP_TF_CANOPY_SZPF','FATES_STOREP_TF_USTORY_SZPF','FATES_REPROP_SZPF','FATES_PUPTAKE_SZPF', +'FATES_PEFFLUX_SZPF','FATES_PDEMAND_SZPF' diff --git a/src/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90 index d14e619b03..e1252b12ad 100644 --- a/src/biogeochem/CNDriverMod.F90 +++ b/src/biogeochem/CNDriverMod.F90 @@ -479,7 +479,7 @@ subroutine CNDriverNoLeaching(bounds, cnveg_carbonflux_inst,cnveg_nitrogenstate_inst,cnveg_nitrogenflux_inst, & soilbiogeochem_carbonflux_inst,& soilbiogeochem_state_inst,soilbiogeochem_nitrogenstate_inst, & - soilbiogeochem_nitrogenflux_inst,canopystate_inst) + soilbiogeochem_nitrogenflux_inst,canopystate_inst, clm_fates) call t_stopf('soilbiogeochemcompetition') ! distribute the available N between the competing patches on the basis of diff --git a/src/biogeochem/CNNDynamicsMod.F90 b/src/biogeochem/CNNDynamicsMod.F90 index 10c0f5ea38..346a407899 100644 --- a/src/biogeochem/CNNDynamicsMod.F90 +++ b/src/biogeochem/CNNDynamicsMod.F90 @@ -239,17 +239,14 @@ subroutine CNNFixation(num_soilc, filter_soilc, & if(col%is_fates(c))then s = clm_fates%f2hmap(clump_index)%hsites(c) ! %ema_npp is Smoothed [gc/m2/yr] - !npp = clm_fates%fates(clump_index)%bc_out(s)%ema_npp/(dayspyr*secspday) - ! FATES N cycling is not yet active, so runs are supplemented anyway - ! this will be added when FATES N cycling is completed. - npp = 0._r8 + npp = clm_fates%fates(clump_index)%bc_out(s)%ema_npp else - npp = col_lag_npp(c) + ! need to put npp in units of gC/m^2/year here first + npp = col_lag_npp(c) * secspday * dayspyr end if if (npp /= spval) then - ! need to put npp in units of gC/m^2/year here first - t = (1.8_r8 * (1._r8 - exp(-0.003_r8 * npp *(secspday * dayspyr))))/(secspday * dayspyr) + t = (1.8_r8 * (1._r8 - exp(-0.003_r8 * npp))) / (secspday * dayspyr) nfix_to_sminn(c) = max(0._r8,t) else nfix_to_sminn(c) = 0._r8 @@ -262,14 +259,13 @@ subroutine CNNFixation(num_soilc, filter_soilc, & if(col%is_fates(c))then s = clm_fates%f2hmap(clump_index)%hsites(c) - !npp = clm_fates%fates(clump_index)%bc_out(s)%ema_npp - ! See above regarding FATES and N fixation - npp = 0._r8 + ! %ema_npp is Smoothed [gc/m2/yr] + npp = clm_fates%fates(clump_index)%bc_out(s)%ema_npp else npp = cannsum_npp(c) end if - t = (1.8_r8 * (1._r8 - exp(-0.003_r8 * npp)))/(secspday * dayspyr) + t = (1.8_r8 * (1._r8 - exp(-0.003_r8 * npp))) / (secspday * dayspyr) nfix_to_sminn(c) = max(0._r8,t) end do endif diff --git a/src/fates b/src/fates index b8edc4014c..c7e8537129 160000 --- a/src/fates +++ b/src/fates @@ -1 +1 @@ -Subproject commit b8edc4014c08f11b6849847e3f357516a537d1a3 +Subproject commit c7e85371293937650efa6e4c38baa7af05e12c63 diff --git a/src/main/clm_varctl.F90 b/src/main/clm_varctl.F90 index 83133acf2b..efeee0d7e7 100644 --- a/src/main/clm_varctl.F90 +++ b/src/main/clm_varctl.F90 @@ -324,8 +324,8 @@ module clm_varctl integer, public :: fates_seeddisp_cadence = iundef ! 0 => no seed dispersal ! 1, 2, 3 => daily, monthly, or yearly dispersal - integer, public :: fates_parteh_mode = -9 ! 1 => carbon only - ! 2 => C+N+P (not enabled yet) + integer, public :: fates_parteh_mode = -9 ! = 1 indicated by fates_c_only is carbon only + ! = 2 indicated by fates_cnp is C+N+P, though clm cannot enable phosphorus yet, so clm needs fates_cnp_prescribed_puptake > 1 (recommended value 10) in the fates paramfile ! no others enabled integer, public :: fates_spitfire_mode = 0 ! 0 for no fire; 1 for constant ignitions; diff --git a/src/main/controlMod.F90 b/src/main/controlMod.F90 index 089503dc8b..dd33f0dc9c 100644 --- a/src/main/controlMod.F90 +++ b/src/main/controlMod.F90 @@ -42,7 +42,7 @@ module controlMod use CNSharedParamsMod , only: use_fun, use_matrixcn use CIsoAtmTimeseriesMod , only: use_c14_bombspike, atm_c14_filename, use_c13_timeseries, atm_c13_filename use SoilBiogeochemDecompCascadeConType, only : use_soil_matrixcn - use SoilBiogeochemCompetitionMod , only: suplnitro, suplnNon + use SoilBiogeochemCompetitionMod , only: suplnitro, suplnNon, suplnAll use SoilBiogeochemLittVertTranspMod , only: som_adv_flux, max_depth_cryoturb use SoilBiogeochemVerticalProfileMod , only: surfprof_exp use SoilBiogeochemNitrifDenitrifMod , only: no_frozen_nitrif_denitrif @@ -51,6 +51,7 @@ module controlMod use CanopyFluxesMod , only: CanopyFluxesReadNML use shr_drydep_mod , only: n_drydep use clm_varctl + use PRTGenericMod, only : fates_cnp, fates_c_only ! ! !PUBLIC TYPES: implicit none @@ -491,12 +492,19 @@ subroutine control_init(dtime) use_fates_bgc = .true. end if - if (fates_parteh_mode == 1 .and. suplnitro == suplnNon .and. use_fates_bgc )then - write(iulog,*) ' When FATES with fates_parteh_mode == 1 (ie carbon only mode),' + if (fates_parteh_mode == fates_c_only .and. suplnitro == suplnNon)then + write(iulog,*) ' When fates_parteh_mode == fates_c_only,' write(iulog,*) ' you must have supplemental nitrogen turned on, there will be' write(iulog,*) ' no nitrogen dynamics with the plants, and therefore no' write(iulog,*) ' meaningful limitations to nitrogen.' - call endrun(msg=' ERROR: fates_parteh_mode=1 must have suplnitro set to suplnAll.'//& + call endrun(msg=' ERROR: fates_parteh_mode=fates_c_only must have suplnitro set to suplnAll.'//& + errMsg(sourcefile, __LINE__)) + end if + if (fates_parteh_mode == fates_cnp .and. use_fates_sp )then + write(iulog,*) ' When fates_parteh_mode == fates_cnp,' + write(iulog,*) ' you must have use_fates_bgc and not use_fates_sp.' + write(iulog,*) ' When you have use_fates_sp, then fates_parteh_mode should equal fates_c_only.' + call endrun(msg=' ERROR: fates_parteh_mode=fates_cnp and use_fates_sp are inconsistent.'//& errMsg(sourcefile, __LINE__)) end if diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index 041f6ee740..607cdc93b4 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -30,6 +30,7 @@ module SoilBiogeochemCompetitionMod use TemperatureType , only : temperature_type use SoilStateType , only : soilstate_type use CanopyStateType , only : CanopyState_type + use CLMFatesInterfaceMod, only : hlm_fates_interface_type ! implicit none private @@ -172,10 +173,11 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu cnveg_carbonflux_inst,cnveg_nitrogenstate_inst,cnveg_nitrogenflux_inst, & soilbiogeochem_carbonflux_inst, & soilbiogeochem_state_inst, soilbiogeochem_nitrogenstate_inst, & - soilbiogeochem_nitrogenflux_inst,canopystate_inst) + soilbiogeochem_nitrogenflux_inst,canopystate_inst, clm_fates) ! ! !USES: - use clm_varctl , only: allocate_carbon_only, iulog + use PRTGenericMod, only : fates_cnp + use clm_varctl , only: fates_parteh_mode, allocate_carbon_only, iulog use clm_varpar , only: nlevdecomp, ndecomp_cascade_transitions use clm_varpar , only: i_cop_mic, i_oli_mic use clm_varcon , only: nitrif_n2o_loss_frac @@ -207,11 +209,16 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu type(soilbiogeochem_nitrogenstate_type) , intent(inout) :: soilbiogeochem_nitrogenstate_inst type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst type(canopystate_type) , intent(inout) :: canopystate_inst + type(hlm_fates_interface_type), intent(inout) :: clm_fates ! ! ! !LOCAL VARIABLES: integer :: c,p,l,pi,j,k ! indices integer :: fc ! filter column index + integer :: ft ! FATES functional type index + integer :: f ! loop index for FATES plant competitors + integer :: n_pcomp ! number of FATES plant competitors + integer :: ci, s ! used for FATES BC (clump index, site index) logical :: local_use_fun ! local version of use_fun real(r8) :: amnf_immob_vr ! actual mineral N flux from immobilization (gN/m3/s) real(r8) :: n_deficit_vr ! microbial N deficit, vertically resolved (gN/m3/s) @@ -221,6 +228,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu real(r8) :: compet_decomp_nh4 ! (unitless) relative competitiveness of immobilizers for NH4 real(r8) :: compet_denit ! (unitless) relative competitiveness of denitrifiers for NO3 real(r8) :: compet_nit ! (unitless) relative competitiveness of nitrifiers for NH4 + real(r8) :: ndemand ! (gN/m2/s) nitrogen demand per FATES plant competitor f (see local variable f above) real(r8) :: fpi_no3_vr(bounds%begc:bounds%endc,1:nlevdecomp) ! fraction of potential immobilization supplied by no3(no units) real(r8) :: fpi_nh4_vr(bounds%begc:bounds%endc,1:nlevdecomp) ! fraction of potential immobilization supplied by nh4 (no units) real(r8) :: sum_nh4_demand(bounds%begc:bounds%endc,1:nlevdecomp) @@ -228,6 +236,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu real(r8) :: sum_no3_demand(bounds%begc:bounds%endc,1:nlevdecomp) real(r8) :: sum_no3_demand_scaled(bounds%begc:bounds%endc,1:nlevdecomp) real(r8) :: sum_ndemand_vr(bounds%begc:bounds%endc, 1:nlevdecomp) !total column N demand (gN/m3/s) at a given level + real(r8) :: plant_ndemand_vr(bounds%begc:bounds%endc, 1:nlevdecomp) !plant column N demand (gN/m3/s) at a given level real(r8) :: nuptake_prof(bounds%begc:bounds%endc, 1:nlevdecomp) real(r8) :: sminn_tot(bounds%begc:bounds%endc) integer :: nlimit(bounds%begc:bounds%endc,0:nlevdecomp) !flag for N limitation @@ -319,12 +328,53 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu end do end do - do j = 1, nlevdecomp - do fc=1,num_bgc_soilc - c = filter_bgc_soilc(fc) - sum_ndemand_vr(c,j) = plant_ndemand(c) * nuptake_prof(c,j) + potential_immob_vr(c,j) + bgc_soilc_loop1: do fc = 1, num_bgc_soilc + c = filter_bgc_soilc(fc) + + fates1: if (col%is_fates(c)) then + ci = bounds%clump_index + s = clm_fates%f2hmap(ci)%hsites(c) + n_pcomp = clm_fates%fates(ci)%bc_out(s)%num_plant_comps + + ! Overwrite the column level demands, since fates plants are all sharing + ! the same space, in units per the same square meter, we just add demand + ! to scale up to column + plant_ndemand(c) = 0._r8 + + ! We fill the vertically resolved array to simplify some jointly used code + do j = 1, nlevdecomp + plant_ndemand_vr(c,j) = 0._r8 + + if (fates_parteh_mode == fates_cnp) then + do f = 1, n_pcomp + ft = clm_fates%fates(ci)%bc_out(s)%ft_index(f) + + ! [gN/m3/s] = [gC/m3] * [gN/gC/s] + plant_ndemand_vr(c,j) = plant_ndemand_vr(c,j) + & + clm_fates%fates(ci)%bc_out(s)%veg_rootc(f,j) * & + (clm_fates%fates(ci)%bc_pconst%vmax_nh4(ft) + & + clm_fates%fates(ci)%bc_pconst%vmax_no3(ft)) + end do + end if + + ! [gN/m2/s] + plant_ndemand(c) = plant_ndemand(c) + plant_ndemand_vr(c,j) * dzsoi_decomp(j) + + end do + + else ! not is_fates + + do j = 1, nlevdecomp + plant_ndemand_vr(c,j) = plant_ndemand(c) * nuptake_prof(c,j) + end do + + end if fates1 + + do j = 1, nlevdecomp + sum_ndemand_vr(c,j) = plant_ndemand_vr(c,j) + potential_immob_vr(c,j) end do - end do + + end do bgc_soilc_loop1 do j = 1, nlevdecomp do fc=1,num_bgc_soilc @@ -337,7 +387,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu nlimit(c,j) = 0 fpi_vr(c,j) = 1.0_r8 actual_immob_vr(c,j) = potential_immob_vr(c,j) - sminn_to_plant_vr(c,j) = plant_ndemand(c) * nuptake_prof(c,j) + sminn_to_plant_vr(c,j) = plant_ndemand_vr(c,j) else if ( allocate_carbon_only()) then !.or. & ! this code block controls the addition of N to sminn pool ! to eliminate any N limitation, when Carbon_Only is set. This lets the @@ -349,7 +399,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu nlimit(c,j) = 1 fpi_vr(c,j) = 1.0_r8 actual_immob_vr(c,j) = potential_immob_vr(c,j) - sminn_to_plant_vr(c,j) = plant_ndemand(c) * nuptake_prof(c,j) + sminn_to_plant_vr(c,j) = plant_ndemand_vr(c,j) supplement_to_sminn_vr(c,j) = sum_ndemand_vr(c,j) - (sminn_vr(c,j)/dt) else ! N availability can not satisfy the sum of immobilization and @@ -545,6 +595,50 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu end do end do + bgc_soilc_loop2: do fc = 1, num_bgc_soilc + c = filter_bgc_soilc(fc) + + fates2: if (col%is_fates(c)) then + ci = bounds%clump_index + s = clm_fates%f2hmap(ci)%hsites(c) + n_pcomp = clm_fates%fates(ci)%bc_out(s)%num_plant_comps + + ! Overwrite the column level demands, since fates plants are all sharing + ! the same space, in units per the same square meter, we just add demand + ! to scale up to column + plant_ndemand(c) = 0._r8 + + ! We fill the vertically resolved array to simplify some jointly used code + do j = 1, nlevdecomp + plant_ndemand_vr(c,j) = 0._r8 + + if (fates_parteh_mode == fates_cnp) then + do f = 1, n_pcomp + ft = clm_fates%fates(ci)%bc_out(s)%ft_index(f) + + ! [gN/m3/s] = [gC/m3] * [gN/gC/s] + plant_ndemand_vr(c,j) = plant_ndemand_vr(c,j) + & + clm_fates%fates(ci)%bc_out(s)%veg_rootc(f,j) * & + (clm_fates%fates(ci)%bc_pconst%vmax_nh4(ft) + & + clm_fates%fates(ci)%bc_pconst%vmax_no3(ft)) + end do + end if + + ! [gN/m2/s] + plant_ndemand(c) = plant_ndemand(c) + plant_ndemand_vr(c,j) * dzsoi_decomp(j) + + end do + + else ! not is_fates + + do j = 1, nlevdecomp + plant_ndemand_vr(c,j) = plant_ndemand(c) * nuptake_prof(c,j) + end do + + end if fates2 + + end do bgc_soilc_loop2 + ! main column/vertical loop do j = 1, nlevdecomp do fc=1,num_bgc_soilc @@ -552,8 +646,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu l = col%landunit(c) ! first compete for nh4 - sum_nh4_demand(c,j) = plant_ndemand(c) * nuptake_prof(c,j) + potential_immob_vr(c,j) + pot_f_nit_vr(c,j) - sum_nh4_demand_scaled(c,j) = plant_ndemand(c)* nuptake_prof(c,j) * compet_plant_nh4 + & + sum_nh4_demand(c,j) = plant_ndemand_vr(c,j) + potential_immob_vr(c,j) + pot_f_nit_vr(c,j) + sum_nh4_demand_scaled(c,j) = plant_ndemand_vr(c,j) * compet_plant_nh4 + & potential_immob_vr(c,j)*compet_decomp_nh4 + pot_f_nit_vr(c,j)*compet_nit if (sum_nh4_demand(c,j)*dt < smin_nh4_vr(c,j)) then @@ -568,7 +662,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu f_nit_vr(c,j) = pot_f_nit_vr(c,j) if ( .not. local_use_fun ) then - smin_nh4_to_plant_vr(c,j) = plant_ndemand(c) * nuptake_prof(c,j) + smin_nh4_to_plant_vr(c,j) = plant_ndemand_vr(c,j) else smin_nh4_to_plant_vr(c,j) = smin_nh4_vr(c,j)/dt - actual_immob_nh4_vr(c,j) - f_nit_vr(c,j) end if @@ -588,8 +682,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu sum_nh4_demand_scaled(c,j)), pot_f_nit_vr(c,j)) if ( .not. local_use_fun ) then - smin_nh4_to_plant_vr(c,j) = min((smin_nh4_vr(c,j)/dt)*(plant_ndemand(c)* & - nuptake_prof(c,j)*compet_plant_nh4 / sum_nh4_demand_scaled(c,j)), plant_ndemand(c)*nuptake_prof(c,j)) + smin_nh4_to_plant_vr(c,j) = min((smin_nh4_vr(c,j)/dt) * (plant_ndemand_vr(c,j) * & + compet_plant_nh4 / sum_nh4_demand_scaled(c,j)), plant_ndemand_vr(c,j)) else ! RF added new term. send rest of N to plant - which decides whether it should pay or not? @@ -619,15 +713,15 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu end if if(.not.local_use_fun)then - sum_no3_demand(c,j) = (plant_ndemand(c)*nuptake_prof(c,j)-smin_nh4_to_plant_vr(c,j)) + & + sum_no3_demand(c,j) = (plant_ndemand_vr(c,j) - smin_nh4_to_plant_vr(c,j)) + & (potential_immob_vr(c,j)-actual_immob_nh4_vr(c,j)) + pot_f_denit_vr(c,j) - sum_no3_demand_scaled(c,j) = (plant_ndemand(c)*nuptake_prof(c,j) & + sum_no3_demand_scaled(c,j) = (plant_ndemand_vr(c,j) & -smin_nh4_to_plant_vr(c,j))*compet_plant_no3 + & (potential_immob_vr(c,j)-actual_immob_nh4_vr(c,j))*compet_decomp_no3 + pot_f_denit_vr(c,j)*compet_denit else - sum_no3_demand(c,j) = plant_ndemand(c)*nuptake_prof(c,j) + & + sum_no3_demand(c,j) = plant_ndemand_vr(c,j) + & (potential_immob_vr(c,j)-actual_immob_nh4_vr(c,j)) + pot_f_denit_vr(c,j) - sum_no3_demand_scaled(c,j) = (plant_ndemand(c)*nuptake_prof(c,j))*compet_plant_no3 + & + sum_no3_demand_scaled(c,j) = (plant_ndemand_vr(c,j)) * compet_plant_no3 + & (potential_immob_vr(c,j)-actual_immob_nh4_vr(c,j))*compet_decomp_no3 + pot_f_denit_vr(c,j)*compet_denit endif @@ -642,12 +736,12 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu f_denit_vr(c,j) = pot_f_denit_vr(c,j) if(.not.local_use_fun)then - smin_no3_to_plant_vr(c,j) = (plant_ndemand(c)*nuptake_prof(c,j)-smin_nh4_to_plant_vr(c,j)) + smin_no3_to_plant_vr(c,j) = (plant_ndemand_vr(c,j) - smin_nh4_to_plant_vr(c,j)) else ! This restricts the N uptake of a single layer to the value determined from the total demands and the ! hypothetical uptake profile above. Which is a strange thing to do, since that is independent of FUN ! do we need this at all? - smin_no3_to_plant_vr(c,j) = plant_ndemand(c)*nuptake_prof(c,j) + smin_no3_to_plant_vr(c,j) = plant_ndemand_vr(c,j) ! RF added new term. send rest of N to plant - which decides whether it should pay or not? if ( local_use_fun ) then smin_no3_to_plant_vr(c,j) = smin_no3_vr(c,j)/dt - actual_immob_no3_vr(c,j) - f_denit_vr(c,j) @@ -667,9 +761,9 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu actual_immob_nh4_vr(c,j))*compet_decomp_no3 / sum_no3_demand_scaled(c,j)), & potential_immob_vr(c,j)-actual_immob_nh4_vr(c,j)) - smin_no3_to_plant_vr(c,j) = min((smin_no3_vr(c,j)/dt)*((plant_ndemand(c)* & - nuptake_prof(c,j)-smin_nh4_to_plant_vr(c,j))*compet_plant_no3 / sum_no3_demand_scaled(c,j)), & - plant_ndemand(c)*nuptake_prof(c,j)-smin_nh4_to_plant_vr(c,j)) + smin_no3_to_plant_vr(c,j) = min((smin_no3_vr(c,j)/dt) * ((plant_ndemand_vr(c,j) - & + smin_nh4_to_plant_vr(c,j)) * compet_plant_no3 / sum_no3_demand_scaled(c,j)), & + plant_ndemand_vr(c,j) - smin_nh4_to_plant_vr(c,j)) f_denit_vr(c,j) = min((smin_no3_vr(c,j)/dt)*(pot_f_denit_vr(c,j)*compet_denit / & sum_no3_demand_scaled(c,j)), pot_f_denit_vr(c,j)) @@ -681,8 +775,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu f_denit_vr(c,j) = min((smin_no3_vr(c,j)/dt)*(pot_f_denit_vr(c,j)*compet_denit / & sum_no3_demand_scaled(c,j)), pot_f_denit_vr(c,j)) - smin_no3_to_plant_vr(c,j) = (smin_no3_vr(c,j)/dt)*((plant_ndemand(c)* & - nuptake_prof(c,j)-smin_nh4_to_plant_vr(c,j))*compet_plant_no3 / sum_no3_demand_scaled(c,j)) + smin_no3_to_plant_vr(c,j) = (smin_no3_vr(c,j)/dt) * ((plant_ndemand_vr(c,j) - & + smin_nh4_to_plant_vr(c,j)) * compet_plant_no3 / sum_no3_demand_scaled(c,j)) ! RF added new term. send rest of N to plant - which decides whether it should pay or not? smin_no3_to_plant_vr(c,j) = (smin_no3_vr(c,j) / dt) - actual_immob_no3_vr(c,j) - f_denit_vr(c,j) @@ -737,10 +831,10 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu ! update to new values that satisfy demand actual_immob_nh4_vr(c,j) = potential_immob_vr(c,j) - actual_immob_no3_vr(c,j) end if - if ( smin_no3_to_plant_vr(c,j) + smin_nh4_to_plant_vr(c,j) < plant_ndemand(c)*nuptake_prof(c,j) ) then + if ( smin_no3_to_plant_vr(c,j) + smin_nh4_to_plant_vr(c,j) < plant_ndemand_vr(c,j) ) then supplement_to_sminn_vr(c,j) = supplement_to_sminn_vr(c,j) + & - (plant_ndemand(c)*nuptake_prof(c,j) - smin_no3_to_plant_vr(c,j)) - smin_nh4_to_plant_vr(c,j) ! use old values - smin_nh4_to_plant_vr(c,j) = plant_ndemand(c)*nuptake_prof(c,j) - smin_no3_to_plant_vr(c,j) + (plant_ndemand_vr(c,j) - smin_no3_to_plant_vr(c,j)) - smin_nh4_to_plant_vr(c,j) ! use old values + smin_nh4_to_plant_vr(c,j) = plant_ndemand_vr(c,j) - smin_no3_to_plant_vr(c,j) end if sminn_to_plant_vr(c,j) = smin_no3_to_plant_vr(c,j) + smin_nh4_to_plant_vr(c,j) end if @@ -991,6 +1085,45 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu end if end do ! end of column loops + ! Set the FATES N uptake fluxes + + if (col%is_fates(c)) then + do fc=1, num_bgc_soilc + c = filter_bgc_soilc(fc) + ci = bounds%clump_index + s = clm_fates%f2hmap(ci)%hsites(c) + n_pcomp = clm_fates%fates(ci)%bc_out(s)%num_plant_comps + + ! if fates_parteh_mode /= fates_cnp then plant_ndemand = 0 and this if-statement gets skipped + if ( plant_ndemand(c) > tiny(plant_ndemand(c)) ) then + do f = 1, n_pcomp + ft = clm_fates%fates(ci)%bc_out(s)%ft_index(f) + + ! [gN/m2/s] + ndemand = 0._r8 + + do j = 1, nlevdecomp + ndemand = ndemand + clm_fates%fates(ci)%bc_out(s)%veg_rootc(f,j) * & + (clm_fates%fates(ci)%bc_pconst%vmax_nh4(ft) + & + clm_fates%fates(ci)%bc_pconst%vmax_no3(ft)) * dzsoi_decomp(j) + end do + + do j = 1, nlevdecomp + clm_fates%fates(ci)%bc_in(s)%plant_nh4_uptake_flux(f,1) = & + clm_fates%fates(ci)%bc_in(s)%plant_nh4_uptake_flux(f,1) + & + smin_nh4_to_plant_vr(c,j) * dt * dzsoi_decomp(j) * & + (ndemand / plant_ndemand(c)) + + clm_fates%fates(ci)%bc_in(s)%plant_no3_uptake_flux(f,1) = & + clm_fates%fates(ci)%bc_in(s)%plant_no3_uptake_flux(f,1) + & + smin_no3_to_plant_vr(c,j) * dt * dzsoi_decomp(j) * & + (ndemand / plant_ndemand(c)) + end do + end do + end if + end do + end if + end if if_nitrif !end of if_not_use_nitrif_denitrif end associate diff --git a/src/utils/clmfates_interfaceMod.F90 b/src/utils/clmfates_interfaceMod.F90 index e61112674b..f086b24cb6 100644 --- a/src/utils/clmfates_interfaceMod.F90 +++ b/src/utils/clmfates_interfaceMod.F90 @@ -46,7 +46,7 @@ module CLMFatesInterfaceMod use CNProductsMod , only : cn_products_type use clm_varctl , only : iulog use clm_varctl , only : fates_parteh_mode - use PRTGenericMod , only : prt_cnp_flex_allom_hyp + use PRTGenericMod , only : fates_cnp use clm_varctl , only : use_fates use clm_varctl , only : fates_spitfire_mode use clm_varctl , only : use_fates_managed_fire @@ -1405,23 +1405,23 @@ subroutine UpdateNLitterFluxes(this,soilbiogeochem_nitrogenflux_inst,ci,c) if ( .not. use_fates_sp ) then ! (gC/m3/timestep) - !nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_met_lit) = & - ! nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_met_lit) + & - ! this%fates(ci)%bc_out(s)%litt_flux_lab_n_si(1:nlevdecomp)*dtime + nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_met_lit) = & + nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_met_lit) + & + this%fates(ci)%bc_out(s)%litt_flux_lab_n_si(1:nlevdecomp)*dtime ! Used for mass balance checking (gC/m2/s) - !nf_soil%fates_litter_flux(c) = sum(this%fates(ci)%bc_out(s)%litt_flux_lab_n_si(1:nlevdecomp) * & - ! this%fates(ci)%bc_in(s)%dz_decomp_sisl(1:nlevdecomp)) + nf_soil%fates_litter_flux(c) = sum(this%fates(ci)%bc_out(s)%litt_flux_lab_n_si(1:nlevdecomp) * & + this%fates(ci)%bc_in(s)%dz_decomp_sisl(1:nlevdecomp)) - i_cel_lit = i_met_lit + 1 + i_cel_lit = i_met_lit + 1 ! slevis note: in mimics i_cel_lit = i_str_lit = i_met_lit + 1 - !nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_cel_lit) = & - ! nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_cel_lit) + & - ! this%fates(ci)%bc_out(s)%litt_flux_cel_n_si(1:nlevdecomp)*dtime + nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_cel_lit) = & + nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_cel_lit) + & + this%fates(ci)%bc_out(s)%litt_flux_cel_n_si(1:nlevdecomp)*dtime - !nf_soil%fates_litter_flux(c) = nf_soil%fates_litter_flux(c) + & - ! sum(this%fates(ci)%bc_out(s)%litt_flux_cel_n_si(1:nlevdecomp) * & - ! this%fates(ci)%bc_in(s)%dz_decomp_sisl(1:nlevdecomp)) + nf_soil%fates_litter_flux(c) = nf_soil%fates_litter_flux(c) + & + sum(this%fates(ci)%bc_out(s)%litt_flux_cel_n_si(1:nlevdecomp) * & + this%fates(ci)%bc_in(s)%dz_decomp_sisl(1:nlevdecomp)) if (decomp_method == mimics_decomp) then ! Mimics has a structural pool, which is cellulose and lignan @@ -1431,16 +1431,14 @@ subroutine UpdateNLitterFluxes(this,soilbiogeochem_nitrogenflux_inst,ci,c) i_lig_lit = i_cel_lit + 1 end if - !nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_lig_lit) = & - ! nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_lig_lit) + & - ! this%fates(ci)%bc_out(s)%litt_flux_lig_n_si(1:nlevdecomp)*dtime + nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_lig_lit) = & + nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_lig_lit) + & + this%fates(ci)%bc_out(s)%litt_flux_lig_n_si(1:nlevdecomp)*dtime - !nf_soil%fates_litter_flux(c) = nf_soil%fates_litter_flux(c) + & - ! sum(this%fates(ci)%bc_out(s)%litt_flux_lig_n_si(1:nlevdecomp) * & - ! this%fates(ci)%bc_in(s)%dz_decomp_sisl(1:nlevdecomp)) + nf_soil%fates_litter_flux(c) = nf_soil%fates_litter_flux(c) + & + sum(this%fates(ci)%bc_out(s)%litt_flux_lig_n_si(1:nlevdecomp) * & + this%fates(ci)%bc_in(s)%dz_decomp_sisl(1:nlevdecomp)) - nf_soil%fates_litter_flux = 0._r8 - else ! In SP mode their is no mass flux between the two @@ -2811,15 +2809,15 @@ subroutine wrap_WoodProducts(this, bounds_clump, num_soilc, filter_soilc, & this%fates(ci)%bc_out(s)%hrv_deadstemc_to_prod100c ! If N cycling is on - if(fates_parteh_mode == prt_cnp_flex_allom_hyp ) then + if (fates_parteh_mode == fates_cnp) then - !n_products_inst%hrv_deadstem_to_prod10_grc(g) = & - ! n_products_inst%hrv_deadstem_to_prod10_grc(g) + & - ! this%fates(ci)%bc_out(s)%hrv_deadstemc_to_prod10c + n_products_inst%hrv_deadstem_to_prod10_grc(g) = & + n_products_inst%hrv_deadstem_to_prod10_grc(g) + & + this%fates(ci)%bc_out(s)%hrv_deadstemc_to_prod10c - !n_products_inst%hrv_deadstem_to_prod100_grc(g) = & - ! n_products_inst%hrv_deadstem_to_prod100_grc(g) + & - ! this%fates(ci)%bc_out(s)%hrv_deadstemc_to_prod100c + n_products_inst%hrv_deadstem_to_prod100_grc(g) = & + n_products_inst%hrv_deadstem_to_prod100_grc(g) + & + this%fates(ci)%bc_out(s)%hrv_deadstemc_to_prod100c end if