From e505dc8e9fc0ed8adc2de84a07897decf99031c5 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Wed, 30 Jul 2025 15:30:24 -0600 Subject: [PATCH 01/16] Add two 1x1 FatesColdPRT2 tests, one with, one without MIMICS PASS ERS_D_Ld30.1x1_brazil.I2000Clm60FatesCrujraRs.derecho_intel.clm-FatesColdPRT2 FAIL ERS_D_Ld30.1x1_brazil.I2000Clm60FatesCrujraRs.derecho_intel.clm-FatesColdPRT2--clm-mimicsFatesCold--clm-nofireemis The latter needs "nofireemis" to work with Fates, but it then dumps core in line 1180 SoilBiogeochemDecompCascadeMIMICSMod.F90 --- cime_config/testdefs/testlist_clm.xml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/cime_config/testdefs/testlist_clm.xml b/cime_config/testdefs/testlist_clm.xml index 478dc59bdd..f591dfa9ff 100644 --- a/cime_config/testdefs/testlist_clm.xml +++ b/cime_config/testdefs/testlist_clm.xml @@ -3703,6 +3703,28 @@ + + + + + + + + + + + + + + + + + + + + + + From 01671b91627dc38617ed285cd52e39e05496539d Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 11 Aug 2025 15:34:48 -0600 Subject: [PATCH 02/16] Uncomment if ( .not. use_fates_sp ) section of clmfates_interfaceMod ...calculating these variables: nf_soil%decomp_npools_sourcesink_col nf_soil%fates_litter_flux --- src/utils/clmfates_interfaceMod.F90 | 38 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/utils/clmfates_interfaceMod.F90 b/src/utils/clmfates_interfaceMod.F90 index 289244ae89..ff33461533 100644 --- a/src/utils/clmfates_interfaceMod.F90 +++ b/src/utils/clmfates_interfaceMod.F90 @@ -1410,23 +1410,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 @@ -1436,16 +1436,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 From 59f9d0937f2e88ed665babe64b96695d31d3ad37 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 12 Aug 2025 16:45:51 -0600 Subject: [PATCH 03/16] Replace plant_ndemand(c) * nuptake_prof(c,j) with plant_ndemand_vr(c,j) --- .../SoilBiogeochemCompetitionMod.F90 | 49 ++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index 57bc82984e..139b19136b 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -228,6 +228,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 @@ -322,7 +323,11 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu 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) + if (use_fates) then + else + plant_ndemand_vr(c,j) = plant_ndemand(c) * nuptake_prof(c,j) + end if + sum_ndemand_vr(c,j) = plant_ndemand_vr(c,j) + potential_immob_vr(c,j) end do end do @@ -337,7 +342,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 ( cnallocate_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 +354,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 @@ -552,8 +557,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 +573,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 +593,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 +624,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 +647,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 +672,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 +686,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 +742,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 From b155e58196bb03142e41d47b0e7bf3707a36949e Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 12 Aug 2025 18:07:40 -0600 Subject: [PATCH 04/16] New use_fates section for plant_ndemand_vr and plant_ndemand from fates --- src/biogeochem/CNDriverMod.F90 | 2 +- .../SoilBiogeochemCompetitionMod.F90 | 59 ++++++++++++++++--- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90 index 9a51d9f616..bef809237f 100644 --- a/src/biogeochem/CNDriverMod.F90 +++ b/src/biogeochem/CNDriverMod.F90 @@ -478,7 +478,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/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index 139b19136b..380565d675 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,10 @@ 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: cnallocate_carbon_only, iulog + use clm_varctl , only: use_fates, cnallocate_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 +208,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(in) :: 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 plant competitors + integer :: ci, s ! used for FATES BC (clump index, site index) + integer :: n_pcomp ! number of plant competitors 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) @@ -320,16 +326,51 @@ 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) - if (use_fates) then - else + num_bgc_soilc: do fc = 1, num_bgc_soilc + c = filter_bgc_soilc(fc) + + use_fates: if (use_fates) 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 + + 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 + + ! [gN/m2/s] + plant_ndemand(c) = plant_ndemand(c) + plant_ndemand_vr(c,j) * dzsoi_decomp(j) + + end do + + else ! not use_fates + + do j = 1, nlevdecomp plant_ndemand_vr(c,j) = plant_ndemand(c) * nuptake_prof(c,j) - end if + end do + + end if use_fates + + 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 num_bgc_soilc do j = 1, nlevdecomp do fc=1,num_bgc_soilc From c79230ce250c2e47d883206842f76c3fe79315b3 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Wed, 13 Aug 2025 16:47:35 -0600 Subject: [PATCH 05/16] New use_fates section to set the FATES N uptake fluxes --- .../SoilBiogeochemCompetitionMod.F90 | 51 ++++++++++++++++--- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index 380565d675..7801d3cd5f 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -215,9 +215,9 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu integer :: c,p,l,pi,j,k ! indices integer :: fc ! filter column index integer :: ft ! FATES functional type index - integer :: f ! loop index for plant competitors + 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) - integer :: n_pcomp ! number of plant competitors 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) @@ -227,6 +227,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) @@ -326,10 +327,10 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu end do end do - num_bgc_soilc: do fc = 1, num_bgc_soilc + bgc_soilc_loop: do fc = 1, num_bgc_soilc c = filter_bgc_soilc(fc) - use_fates: if (use_fates) then + fates: if (use_fates) then ci = bounds%clump_index s = clm_fates%f2hmap(ci)%hsites(c) n_pcomp = clm_fates%fates(ci)%bc_out(s)%num_plant_comps @@ -364,13 +365,13 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu plant_ndemand_vr(c,j) = plant_ndemand(c) * nuptake_prof(c,j) end do - end if use_fates + end if fates do j = 1, nlevdecomp sum_ndemand_vr(c,j) = plant_ndemand_vr(c,j) + potential_immob_vr(c,j) end do - end do num_bgc_soilc + end do bgc_soilc_loop do j = 1, nlevdecomp do fc=1,num_bgc_soilc @@ -1037,6 +1038,44 @@ 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 (use_fates) 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 ( 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 From 98b4b7dfcae668ab4b643af4125df3a2aa2dd219 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Wed, 13 Aug 2025 16:53:05 -0600 Subject: [PATCH 06/16] Change clm_fate from "in" to "inout" argument --- src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index 7801d3cd5f..4d9f855b8f 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -208,7 +208,7 @@ 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(in) :: clm_fates + type(hlm_fates_interface_type), intent(inout) :: clm_fates ! ! ! !LOCAL VARIABLES: From a46a76c8c39922065c629024afbf78865e1a3cda Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Thu, 14 Aug 2025 17:27:42 -0600 Subject: [PATCH 07/16] Replace if (use_fates) with (is_fates(c)) to add flexibility --- .../SoilBiogeochemCompetitionMod.F90 | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index 4d9f855b8f..c809962530 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -176,7 +176,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu soilbiogeochem_nitrogenflux_inst,canopystate_inst, clm_fates) ! ! !USES: - use clm_varctl , only: use_fates, cnallocate_carbon_only, iulog + use clm_varctl , only: fates_parteh_mode, cnallocate_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 @@ -330,7 +330,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu bgc_soilc_loop: do fc = 1, num_bgc_soilc c = filter_bgc_soilc(fc) - fates: if (use_fates) then + fates: 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 @@ -344,15 +344,17 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu do j = 1, nlevdecomp plant_ndemand_vr(c,j) = 0._r8 - do f = 1, n_pcomp - ft = clm_fates%fates(ci)%bc_out(s)%ft_index(f) + if (fates_parteh_mode == 2) 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 + ! [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) @@ -1040,13 +1042,14 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu ! Set the FATES N uptake fluxes - if (use_fates) then + 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 /= 2 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) From f2202fb6e8b27387ad53630f4c7638c3d54e7867 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Fri, 15 Aug 2025 15:40:01 -0600 Subject: [PATCH 08/16] Remove two unhelpful 1x1 FatesColdPRT2 tests that I added earlier --- cime_config/testdefs/testlist_clm.xml | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/cime_config/testdefs/testlist_clm.xml b/cime_config/testdefs/testlist_clm.xml index f591dfa9ff..478dc59bdd 100644 --- a/cime_config/testdefs/testlist_clm.xml +++ b/cime_config/testdefs/testlist_clm.xml @@ -3703,28 +3703,6 @@ - - - - - - - - - - - - - - - - - - - - - - From e96b87ec002e328f59560c6e2e4a35608edc5404 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 26 Aug 2025 11:28:08 -0600 Subject: [PATCH 09/16] New is_fates section for plant_ndemand, now when use_nitrif_denitrif --- .../SoilBiogeochemCompetitionMod.F90 | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index c809962530..0156da6256 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -361,7 +361,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu end do - else ! not use_fates + else ! not is_fates do j = 1, nlevdecomp plant_ndemand_vr(c,j) = plant_ndemand(c) * nuptake_prof(c,j) @@ -594,6 +594,50 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu end do end do + bgc_soilc_loop: do fc = 1, num_bgc_soilc + c = filter_bgc_soilc(fc) + + fates: 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 == 2) 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 fates + + end do bgc_soilc_loop + ! main column/vertical loop do j = 1, nlevdecomp do fc=1,num_bgc_soilc From b24738b8ed738351131e28ba1b44bf6c0bf62327 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 26 Aug 2025 14:43:23 -0600 Subject: [PATCH 10/16] Add (really, uncomment) FATES npp to enable fixation --- src/biogeochem/CNNDynamicsMod.F90 | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/biogeochem/CNNDynamicsMod.F90 b/src/biogeochem/CNNDynamicsMod.F90 index 10c0f5ea38..4e29a3a8e6 100644 --- a/src/biogeochem/CNNDynamicsMod.F90 +++ b/src/biogeochem/CNNDynamicsMod.F90 @@ -239,10 +239,7 @@ 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 / (dayspyr * secspday) else npp = col_lag_npp(c) end if @@ -262,9 +259,7 @@ 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 + npp = clm_fates%fates(clump_index)%bc_out(s)%ema_npp else npp = cannsum_npp(c) end if From 00a332e16756fa9a17ad90f0b165c9f9a6c9543c Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Fri, 19 Sep 2025 17:24:06 -0600 Subject: [PATCH 11/16] Uncomment hrv_deadstem_to_prod* lines in clmfates_interfaceMod ...for fates_parteh_mode == 2 --- src/utils/clmfates_interfaceMod.F90 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/utils/clmfates_interfaceMod.F90 b/src/utils/clmfates_interfaceMod.F90 index ff33461533..5e2b438737 100644 --- a/src/utils/clmfates_interfaceMod.F90 +++ b/src/utils/clmfates_interfaceMod.F90 @@ -2816,13 +2816,13 @@ subroutine wrap_WoodProducts(this, bounds_clump, num_soilc, filter_soilc, & ! If N cycling is on if(fates_parteh_mode == prt_cnp_flex_allom_hyp ) 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 From 2bbdd64bd16adf0a7064ece890e42ffb5a4a8ca1 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Fri, 19 Sep 2025 18:00:44 -0600 Subject: [PATCH 12/16] Add error check about fates_parteh_mode = 2 and suplnitro = suplnAll --- src/main/controlMod.F90 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/controlMod.F90 b/src/main/controlMod.F90 index 6d363a9a6e..9f3619e71f 100644 --- a/src/main/controlMod.F90 +++ b/src/main/controlMod.F90 @@ -498,6 +498,12 @@ subroutine control_init(dtime) call endrun(msg=' ERROR: fates_parteh_mode=1 must have suplnitro set to suplnAll.'//& errMsg(sourcefile, __LINE__)) end if + if (fates_parteh_mode == 2 .and. suplnitro == suplnAll .and. use_fates_bgc )then + write(iulog,*) ' When FATES with fates_parteh_mode == 2 (ie carbon-nitrogen mode),' + write(iulog,*) ' you must have supplemental nitrogen turned off.' + call endrun(msg=' ERROR: fates_parteh_mode=2 must have suplnitro set to suplnNon.'//& + errMsg(sourcefile, __LINE__)) + end if if ( use_cn) then call endrun(msg=' ERROR: use_cn and use_fates cannot both be set to true.'//& From d8bc6ce190baf8085b57c8d3f3c01c6d903c714c Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 22 Sep 2025 16:52:22 -0600 Subject: [PATCH 13/16] Upd. namelist_defaults for suplnitro when parteh_mode == 1 or /= 1 --- bld/CLMBuildNamelist.pm | 24 +++++++++++-------- bld/namelist_files/namelist_defaults_ctsm.xml | 7 +++--- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm index 4cd02532f8..43268d0760 100755 --- a/bld/CLMBuildNamelist.pm +++ b/bld/CLMBuildNamelist.pm @@ -1687,10 +1687,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); @@ -3303,7 +3303,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 @@ -3322,6 +3322,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/) && not &value_is_true( $nl_flags->{'use_fates_sp'}) ) { + $log->fatal_error("supplemental Nitrogen (suplnitro) is NOT set to ALL, FATES is on, " . + "and FATES-SP is not active, but fates_parteh_mode is 1, so Nitrogen is not active. " . + "Change suplnitro back to ALL"); + } + if ( ($parteh_mode == 2) && ($suplnitro !~ /NONE/) && not &value_is_true( $nl_flags->{'use_fates_sp'}) ) { + $log->fatal_error("supplemental Nitrogen (suplnitro) is NOT set to NONE, FATES is on, " . + "and FATES-SP is not active, but fates_parteh_mode is 2, so Nitrogen is active; " . + "change suplnitro back to NONE"); + } } } @@ -4787,14 +4799,6 @@ sub setup_logic_fates { 'use_fates_lupft'=>$nl->get_value('use_fates_lupft'), '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 a435bb3b4a..9f736156c9 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -156,10 +156,6 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .true. 0.0d00 - -NONE -ALL - 0.50,0.30 0.60,0.40 @@ -2467,6 +2463,9 @@ lnd/clm2/surfdata_esmf/NEON/ctsm5.3.0/surfdata_1x1_NEON_TOOL_hist_2000_78pfts_c2 .false. 2,2 + +NONE +ALL From 116b310cd20f29bf5ca07b1d89f9e812f4e94477 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 22 Sep 2025 17:06:26 -0600 Subject: [PATCH 14/16] prt_carbon_allom_hyp -> fates_c_only & prt_cnp_flex_allom_hyp ->fates_cn These variables originate in fates, so this renaming requires the same renaming in fates; I will open the corresponding PR very soon --- src/main/clm_varctl.F90 | 4 ++-- src/main/controlMod.F90 | 15 ++++++++------- .../SoilBiogeochemCompetitionMod.F90 | 7 ++++--- src/utils/clmfates_interfaceMod.F90 | 4 ++-- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/main/clm_varctl.F90 b/src/main/clm_varctl.F90 index 41978ae695..40b25f2f9c 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_cn is C+N (P not enabled) ! 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 9f3619e71f..ca90371a98 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_cn, fates_c_only ! ! !PUBLIC TYPES: implicit none @@ -490,18 +491,18 @@ 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 .and. use_fates_bgc )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 == 2 .and. suplnitro == suplnAll .and. use_fates_bgc )then - write(iulog,*) ' When FATES with fates_parteh_mode == 2 (ie carbon-nitrogen mode),' + if (fates_parteh_mode == fates_cn .and. suplnitro == suplnAll .and. use_fates_bgc )then + write(iulog,*) ' When fates_parteh_mode == fates_cn,' write(iulog,*) ' you must have supplemental nitrogen turned off.' - call endrun(msg=' ERROR: fates_parteh_mode=2 must have suplnitro set to suplnNon.'//& + call endrun(msg=' ERROR: fates_parteh_mode=fates_cn must have suplnitro set to suplnNon.'//& errMsg(sourcefile, __LINE__)) end if diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index 0156da6256..3ae2a72ccc 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -176,6 +176,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu soilbiogeochem_nitrogenflux_inst,canopystate_inst, clm_fates) ! ! !USES: + use PRTGenericMod, only : fates_cn use clm_varctl , only: fates_parteh_mode, cnallocate_carbon_only, iulog use clm_varpar , only: nlevdecomp, ndecomp_cascade_transitions use clm_varpar , only: i_cop_mic, i_oli_mic @@ -344,7 +345,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu do j = 1, nlevdecomp plant_ndemand_vr(c,j) = 0._r8 - if (fates_parteh_mode == 2) then + if (fates_parteh_mode == fates_cn) then do f = 1, n_pcomp ft = clm_fates%fates(ci)%bc_out(s)%ft_index(f) @@ -611,7 +612,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu do j = 1, nlevdecomp plant_ndemand_vr(c,j) = 0._r8 - if (fates_parteh_mode == 2) then + if (fates_parteh_mode == fates_cn) then do f = 1, n_pcomp ft = clm_fates%fates(ci)%bc_out(s)%ft_index(f) @@ -1093,7 +1094,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu s = clm_fates%f2hmap(ci)%hsites(c) n_pcomp = clm_fates%fates(ci)%bc_out(s)%num_plant_comps - ! if fates_parteh_mode /= 2 then plant_ndemand = 0 and this if-statement gets skipped + ! if fates_parteh_mode /= fates_cn 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) diff --git a/src/utils/clmfates_interfaceMod.F90 b/src/utils/clmfates_interfaceMod.F90 index 5e2b438737..1e8de5babd 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_cn use clm_varctl , only : use_fates use clm_varctl , only : fates_spitfire_mode use clm_varctl , only : use_fates_tree_damage @@ -2814,7 +2814,7 @@ 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_cn) then n_products_inst%hrv_deadstem_to_prod10_grc(g) = & n_products_inst%hrv_deadstem_to_prod10_grc(g) + & From ba955b659409d87507977626daa7e5cb08bfbcaf Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 23 Sep 2025 10:52:57 -0600 Subject: [PATCH 15/16] Correction to syntax error caught by gnu and nvhpc, not intel --- .../SoilBiogeochemCompetitionMod.F90 | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index 3ae2a72ccc..2d10e78923 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -328,10 +328,10 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu end do end do - bgc_soilc_loop: do fc = 1, num_bgc_soilc + bgc_soilc_loop1: do fc = 1, num_bgc_soilc c = filter_bgc_soilc(fc) - fates: if (col%is_fates(c)) then + 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 @@ -368,13 +368,13 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu plant_ndemand_vr(c,j) = plant_ndemand(c) * nuptake_prof(c,j) end do - end if fates + 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 bgc_soilc_loop + end do bgc_soilc_loop1 do j = 1, nlevdecomp do fc=1,num_bgc_soilc @@ -595,10 +595,10 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu end do end do - bgc_soilc_loop: do fc = 1, num_bgc_soilc + bgc_soilc_loop2: do fc = 1, num_bgc_soilc c = filter_bgc_soilc(fc) - fates: if (col%is_fates(c)) then + 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 @@ -635,9 +635,9 @@ subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,nu plant_ndemand_vr(c,j) = plant_ndemand(c) * nuptake_prof(c,j) end do - end if fates + end if fates2 - end do bgc_soilc_loop + end do bgc_soilc_loop2 ! main column/vertical loop do j = 1, nlevdecomp From 391a0231f07223a03d0f1f75391253931aefcb03 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 23 Sep 2025 14:26:19 -0600 Subject: [PATCH 16/16] Update fates paramfile var prescribed_puptake to 1 for PRT2 test --- .../testdefs/testmods_dirs/clm/FatesColdPRT2/shell_commands | 4 +--- .../testdefs/testmods_dirs/clm/FatesColdPRT2/user_nl_clm | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/shell_commands index 632b61bf15..7519d1faff 100644 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/shell_commands +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/shell_commands @@ -1,11 +1,9 @@ SRCDIR=`./xmlquery SRCROOT --value` CASEDIR=`./xmlquery CASEROOT --value` FATESDIR=$SRCDIR/src/fates/ -FATESPARAMFILE=$CASEDIR/fates_params_prt2_prescribed_np.nc +FATESPARAMFILE=$CASEDIR/fates_params_prt2_prescribed_p.nc ncgen -o $FATESPARAMFILE $FATESDIR/parameter_files/fates_params_default.cdl -$FATESDIR/tools/modify_fates_paramfile.py --O --fin $FATESPARAMFILE --fout $FATESPARAMFILE --var fates_cnp_prescribed_nuptake --val 1.0 --allpfts - $FATESDIR/tools/modify_fates_paramfile.py --O --fin $FATESPARAMFILE --fout $FATESPARAMFILE --var fates_cnp_prescribed_puptake --val 1.0 --allpfts diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/user_nl_clm index 196d559cb7..d5a24fcf50 100644 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/user_nl_clm @@ -1,4 +1,4 @@ -fates_paramfile = '$CASEROOT/fates_params_prt2_prescribed_np.nc' +fates_paramfile = '$CASEROOT/fates_params_prt2_prescribed_p.nc' 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',