From 7d295f20429599361e6bca008d01d7daa2ea79ec Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Mon, 27 Oct 2025 14:07:56 -0600 Subject: [PATCH 01/20] Fix PAR fraction to use relative area in SeedlingParPatch Changesd par_high_frac and par_low_frac to normalize total_canopy_area by area (m2). Previously, using absolute area produced negative values, causing NaNs in seedling light calculations (negative raised to a fractional power). --- main/FatesInterfaceMod.F90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 6982dd700b..db6508890a 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2410,8 +2410,9 @@ subroutine SeedlingParPatch(cpatch, & ! Start with the assumption that there is a single canopy layer seedling_par_high = atm_par_dir+atm_par_dif - par_high_frac = 1._r8-cpatch%total_canopy_area - par_low_frac = cpatch%total_canopy_area + ! RW - edit to make these fractional rather than absolute area [m2] + par_high_frac = 1._r8 - (cpatch%total_canopy_area / cpatch%area) + par_low_frac = cpatch%total_canopy_area / cpatch%area ! Work up through the canopy layers from the bottom layer do cl = cpatch%NCL_p,max(1,cpatch%NCL_p-1),-1 From 2afcc3f7deea6f0314b74f12c57bdb47459f33a7 Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Mon, 27 Oct 2025 14:41:12 -0600 Subject: [PATCH 02/20] Skip first-day update of seedling layer smp and moisture deficit days (mdd). Host model soil matric potential spikes (~negative billions) on day 1. This spike is remembered by running means. When an inflated mdd is passed to the quadratic function to calculate mortality rate from moisture stress, mortality rates > 100%. --- main/FatesInterfaceMod.F90 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index db6508890a..289498acb0 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2335,8 +2335,13 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in, bc_out) endif ! Update the seedling layer smp and mdd running means - call cpatch%sdlng_emerg_smp(pft)%p%UpdateRMean(new_seedling_layer_smp) call cpatch%sdlng_mdd(pft)%p%UpdateRMean(new_seedling_mdd) + ! RW - only update after first model day to avoid adding + ! spike in smp (~negative billions) to running means + if (hlm_model_day > 1.0_r8) then + call cpatch%sdlng_mdd(pft)%p%UpdateRMean(new_seedling_mdd) + call cpatch%sdlng_emerg_smp(pft)%p%UpdateRMean(new_seedling_layer_smp) + endif enddo !end pft loop From 1aa229a008d6b54072184d604784f4a60427a1db Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Mon, 27 Oct 2025 14:41:54 -0600 Subject: [PATCH 03/20] fix typo --- main/FatesInterfaceMod.F90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 289498acb0..320151bde3 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2335,12 +2335,11 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in, bc_out) endif ! Update the seedling layer smp and mdd running means - call cpatch%sdlng_mdd(pft)%p%UpdateRMean(new_seedling_mdd) ! RW - only update after first model day to avoid adding ! spike in smp (~negative billions) to running means if (hlm_model_day > 1.0_r8) then - call cpatch%sdlng_mdd(pft)%p%UpdateRMean(new_seedling_mdd) call cpatch%sdlng_emerg_smp(pft)%p%UpdateRMean(new_seedling_layer_smp) + call cpatch%sdlng_mdd(pft)%p%UpdateRMean(new_seedling_mdd) endif enddo !end pft loop From 006e8a9660e4d0893404ce23ba3f229901adf74d Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Mon, 27 Oct 2025 14:44:02 -0600 Subject: [PATCH 04/20] Fix initial value for sdlng_mort_par, change from temp_init_veg to init_seedling_par --- biogeochem/FatesPatchMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index 2f358cda63..557fcecaa3 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -666,7 +666,7 @@ subroutine InitRunningMeans(this, current_tod, regeneration_model, numpft) call this%seedling_layer_par24%InitRMean(fixed_24hr, & init_value=init_seedling_par, init_offset=real(current_tod, r8)) call this%sdlng_mort_par%InitRMean(ema_sdlng_mort_par, & - init_value=temp_init_veg) + init_value=init_seedling_par) call this%sdlng2sap_par%InitRMean(ema_sdlng2sap_par, & init_value=init_seedling_par) From 0e9f7d8ad7076e4b82281ccf5cdf500943bed7b8 Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Mon, 27 Oct 2025 16:44:02 -0600 Subject: [PATCH 05/20] testing update to seedling layer smp --- biogeochem/EDPhysiologyMod.F90 | 2 +- main/FatesInterfaceMod.F90 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index f509aec000..ed8b9ad2c4 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2317,7 +2317,7 @@ subroutine SeedDecay( litt , currentPatch ) ! Get the current seedling moisture deficit days (tracked as a pft-specific exponential ! average) - seedling_mdds = currentPatch%sdlng_mdd(pft)%p%GetMean() + seedling_mdds = currentPatch%sdlng_mdd(pft)%p%GetMean() ! Calculate seedling mortality as a function of moisture deficit days (mdd) ! If the seedling mmd value is below a critical threshold then moisture-based mortality is zero diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 320151bde3..4a776efc18 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2335,11 +2335,11 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in, bc_out) endif ! Update the seedling layer smp and mdd running means + call cpatch%sdlng_mdd(pft)%p%UpdateRMean(new_seedling_mdd) ! RW - only update after first model day to avoid adding ! spike in smp (~negative billions) to running means if (hlm_model_day > 1.0_r8) then call cpatch%sdlng_emerg_smp(pft)%p%UpdateRMean(new_seedling_layer_smp) - call cpatch%sdlng_mdd(pft)%p%UpdateRMean(new_seedling_mdd) endif enddo !end pft loop From f2c2233661320102a9eb46aed331e33a2c12936f Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Tue, 28 Oct 2025 10:59:37 -0600 Subject: [PATCH 06/20] Fix model day check (must bee > 1.023 to skip 1st model day) --- main/FatesInterfaceMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 4a776efc18..cd7f2c2258 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2335,10 +2335,10 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in, bc_out) endif ! Update the seedling layer smp and mdd running means - call cpatch%sdlng_mdd(pft)%p%UpdateRMean(new_seedling_mdd) ! RW - only update after first model day to avoid adding ! spike in smp (~negative billions) to running means - if (hlm_model_day > 1.0_r8) then + if (hlm_model_day > 1.5_r8) then + call cpatch%sdlng_mdd(pft)%p%UpdateRMean(new_seedling_mdd) call cpatch%sdlng_emerg_smp(pft)%p%UpdateRMean(new_seedling_layer_smp) endif From 408c8cdc56262702a399b0c007e4b58ec3840e22 Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Wed, 29 Oct 2025 17:42:35 -0600 Subject: [PATCH 07/20] Add debugging blocks --- biogeochem/EDPhysiologyMod.F90 | 36 +++++++++++++++++++++++++++++++++- main/FatesInterfaceMod.F90 | 23 ++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index ed8b9ad2c4..2276362760 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2335,7 +2335,21 @@ subroutine SeedDecay( litt , currentPatch ) (litt%seed_germ(pft) * seedling_h2o_mort_rate) + & (litt%seed_germ(pft) * EDPftvarcon_inst%background_seedling_mort(pft) & * years_per_day) - + + ! DEBUG BLOCK START + write(fates_log(),*) '===DEBUG SEED DECAY====' + write(fates_log(),*) 'Model Day = ', hlm_model_day + write(fates_log(),*) 'PFT:', pft, + write(fates_log(),*) 'Seedling par (raw):', currentPatch%sdlng_mort_par%GetMean() + write(fates_log(),*) 'Seedling par (converted):', seedling_layer_par + write(fates_log(),*) 'Seedling light mort rate:', seedling_light_mort_rate + write(fates_log(),*) 'Seedling mdds:', seedling_light_mort_rate + write(fates_log(),*) 'Seedling mdd crit:', EDPftvarcon_inst%seedling_mdd_crit(pft) + write(fates_log(),*) 'Seedling h2o mort rate:', seedling_h2o_mort_rate + write(fates_log(),*) 'Seed germ pool:', litt%seed_germ(pft) + write(fates_log(),*) 'Seed germ decay:',litt%seed_germ_decay(pft) + ! DEBUG BLOCK END + else litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & @@ -2672,6 +2686,19 @@ subroutine recruitment(currentSite, currentPatch, bc_in) EDPftvarcon_inst%seedling_light_rec_a(ft)* & sdlng2sap_par**EDPftvarcon_inst%seedling_light_rec_b(ft) + ! DEBUG BLOCK START + write(fates_log(),*) '=== DEBUG RECRUITMENT TRS ===' + write(fates_log(),*) 'Model day:', hlm_model_day + write(fates_log(),*) 'PFT:', ft + write(fates_log(),*) 'Element:', element_id + write(fates_log(),*) 'sdlng2sap_par (raw GetMean):', currentPatch%sdlng2sap_par%GetMean() + write(fates_log(),*) 'sdlng2sap_par (converted):', sdlng2sap_par + write(fates_log(),*) 'seed_germ before calc:', currentPatch%litter(el)%seed_germ(ft) + write(fates_log(),*) 'seedling_light_rec_a:', EDPftvarcon_inst%seedling_light_rec_a(ft) + write(fates_log(),*) 'seedling_light_rec_b:', EDPftvarcon_inst%seedling_light_rec_b(ft) + write(fates_log(),*) 'currentPatch%area:', currentPatch%area + ! DEBUG BLOCK END + ! If soil moisture is below pft-specific seedling moisture stress threshold the ! recruitment does not occur. ilayer_seedling_root = minloc(abs(bc_in%z_sisl(:) - & @@ -2683,6 +2710,13 @@ subroutine recruitment(currentSite, currentPatch, bc_in) mass_avail = 0.0_r8 end if + ! DEBUG BLOCK START + write(fates_log(),*) 'ilayer_seedling_root', ilayer_seedling_root + write(fates_log(),*) 'seedling_layer_smp', seedling_layer_smp + write(fates_log(),*) 'seedling_psi_crit', EDPftvarcon_inst%seedling_psi_crit(ft) + write(fates_log(),*) 'mass_avail after calc:', mass_avail + ! DEBUG BLOCK END + end if ! End use TRS with seedling dynamics ! update number density if this is the limiting mass diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index cd7f2c2258..4e18dd298a 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2312,6 +2312,13 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in, bc_out) & par_low_frac) new_seedling_layer_par = seedling_par_high*par_high_frac + seedling_par_low*par_low_frac + + ! DEBUG BLOCK START + write(fates_log(),*) '=== Seedling Layer PAR Debug ==== Day:', hlm_model_day + write(fates_log(),*) 'Seedling par high:', seedling_par_high, 'Par frac high:', par_high_frac + write(fates_log(),*) 'Seedling par low:', seedling_par_low, 'Par frac low:', par_low_frac + write(fates_log(),*) 'New seedling layer par', new_seedling_layer_par + ! DEBUG BLOCK END call cpatch%seedling_layer_par24%UpdateRMean(new_seedling_layer_par) call cpatch%sdlng_mort_par%UpdateRMean(new_seedling_layer_par) @@ -2334,6 +2341,22 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in, bc_out) new_seedling_mdd = 0.0_r8 endif + ! === DEBUG BLOCK START === + write(fates_log(),*) '=== MDD DEBUG Day:', hlm_model_day + write(fates_log(),*) 'PFT:', pft, 'Soil layer:', ilayer_seedling_root + write(fates_log(),*) 'Raw SMP from host:', bc_in(s)%smp_sl(ilayer_seedling_root) + write(fates_log(),*) 'new_seedling_layer_smp:', new_seedling_layer_smp + write(fates_log(),*) 'seedling_psi_crit:', EDPftvarcon_inst%seedling_psi_crit(pft) + write(fates_log(),*) 'Deficit check val for check', abs(EDPftvarcon_inst%seedling_psi_crit(pft)) - abs(new_seedling_layer_smp) + write(fates_log(),*) 'new_seedling_mdd (after zero check):', new_seedling_mdd + write(fates_log(),*) 'Current EMA c_mean:', cpatch%sdlng_mdd(pft)%p%c_mean + write(fates_log(),*) 'Current c_index:', cpatch%sdlng_mdd(pft)%p%c_index + write(fates_log(),*) 'n_mem:', cpatch%sdlng_mdd(pft)%p%def_type%n_mem + write(fates_log(),*) 'sdlng_mdd_timescale:', sdlng_mdd_timescale + write(fates_log(),*) '========================' + end if + ! === DEBUG BLOCK END === + ! Update the seedling layer smp and mdd running means ! RW - only update after first model day to avoid adding ! spike in smp (~negative billions) to running means From e047aab49226c81f45daadbed05bff7f9223e7e2 Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Wed, 29 Oct 2025 17:52:44 -0600 Subject: [PATCH 08/20] Fix typo --- biogeochem/EDPhysiologyMod.F90 | 4 ++-- main/FatesInterfaceMod.F90 | 26 ++++++++++++-------------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 2276362760..6abe76cd9d 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2349,7 +2349,7 @@ subroutine SeedDecay( litt , currentPatch ) write(fates_log(),*) 'Seed germ pool:', litt%seed_germ(pft) write(fates_log(),*) 'Seed germ decay:',litt%seed_germ_decay(pft) ! DEBUG BLOCK END - + else litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & @@ -2691,7 +2691,7 @@ subroutine recruitment(currentSite, currentPatch, bc_in) write(fates_log(),*) 'Model day:', hlm_model_day write(fates_log(),*) 'PFT:', ft write(fates_log(),*) 'Element:', element_id - write(fates_log(),*) 'sdlng2sap_par (raw GetMean):', currentPatch%sdlng2sap_par%GetMean() + write(fates_log(),*) 'sdlng2sap_par (raw):', currentPatch%sdlng2sap_par%GetMean() write(fates_log(),*) 'sdlng2sap_par (converted):', sdlng2sap_par write(fates_log(),*) 'seed_germ before calc:', currentPatch%litter(el)%seed_germ(ft) write(fates_log(),*) 'seedling_light_rec_a:', EDPftvarcon_inst%seedling_light_rec_a(ft) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 4e18dd298a..7dd6d8a8c2 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2317,7 +2317,7 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in, bc_out) write(fates_log(),*) '=== Seedling Layer PAR Debug ==== Day:', hlm_model_day write(fates_log(),*) 'Seedling par high:', seedling_par_high, 'Par frac high:', par_high_frac write(fates_log(),*) 'Seedling par low:', seedling_par_low, 'Par frac low:', par_low_frac - write(fates_log(),*) 'New seedling layer par', new_seedling_layer_par + write(fates_log(),*) 'New seedling layer par:', new_seedling_layer_par ! DEBUG BLOCK END call cpatch%seedling_layer_par24%UpdateRMean(new_seedling_layer_par) @@ -2342,19 +2342,17 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in, bc_out) endif ! === DEBUG BLOCK START === - write(fates_log(),*) '=== MDD DEBUG Day:', hlm_model_day - write(fates_log(),*) 'PFT:', pft, 'Soil layer:', ilayer_seedling_root - write(fates_log(),*) 'Raw SMP from host:', bc_in(s)%smp_sl(ilayer_seedling_root) - write(fates_log(),*) 'new_seedling_layer_smp:', new_seedling_layer_smp - write(fates_log(),*) 'seedling_psi_crit:', EDPftvarcon_inst%seedling_psi_crit(pft) - write(fates_log(),*) 'Deficit check val for check', abs(EDPftvarcon_inst%seedling_psi_crit(pft)) - abs(new_seedling_layer_smp) - write(fates_log(),*) 'new_seedling_mdd (after zero check):', new_seedling_mdd - write(fates_log(),*) 'Current EMA c_mean:', cpatch%sdlng_mdd(pft)%p%c_mean - write(fates_log(),*) 'Current c_index:', cpatch%sdlng_mdd(pft)%p%c_index - write(fates_log(),*) 'n_mem:', cpatch%sdlng_mdd(pft)%p%def_type%n_mem - write(fates_log(),*) 'sdlng_mdd_timescale:', sdlng_mdd_timescale - write(fates_log(),*) '========================' - end if + write(fates_log(),*) '=== MDD DEBUG Day:', hlm_model_day + write(fates_log(),*) 'PFT:', pft, 'Soil layer:', ilayer_seedling_root + write(fates_log(),*) 'Raw SMP from host:', bc_in(s)%smp_sl(ilayer_seedling_root) + write(fates_log(),*) 'new_seedling_layer_smp:', new_seedling_layer_smp + write(fates_log(),*) 'seedling_psi_crit:', EDPftvarcon_inst%seedling_psi_crit(pft) + write(fates_log(),*) 'Deficit check val for check', abs(EDPftvarcon_inst%seedling_psi_crit(pft)) - abs(new_seedling_layer_smp) + write(fates_log(),*) 'new_seedling_mdd (after zero check):', new_seedling_mdd + write(fates_log(),*) 'Current EMA c_mean:', cpatch%sdlng_mdd(pft)%p%c_mean + write(fates_log(),*) 'Current c_index:', cpatch%sdlng_mdd(pft)%p%c_index + write(fates_log(),*) 'n_mem:', cpatch%sdlng_mdd(pft)%p%def_type%n_mem + write(fates_log(),*) 'sdlng_mdd_timescale:', sdlng_mdd_timescale ! === DEBUG BLOCK END === ! Update the seedling layer smp and mdd running means From 8477b836b493913ca15ad9a75e50713543929c1f Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Wed, 29 Oct 2025 17:58:45 -0600 Subject: [PATCH 09/20] Fix typo --- biogeochem/EDPhysiologyMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 6abe76cd9d..13b2aad51b 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2339,7 +2339,7 @@ subroutine SeedDecay( litt , currentPatch ) ! DEBUG BLOCK START write(fates_log(),*) '===DEBUG SEED DECAY====' write(fates_log(),*) 'Model Day = ', hlm_model_day - write(fates_log(),*) 'PFT:', pft, + write(fates_log(),*) 'PFT:', pft write(fates_log(),*) 'Seedling par (raw):', currentPatch%sdlng_mort_par%GetMean() write(fates_log(),*) 'Seedling par (converted):', seedling_layer_par write(fates_log(),*) 'Seedling light mort rate:', seedling_light_mort_rate From 5918340982e8165190df2287d61d3f7a2c226791 Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Mon, 3 Nov 2025 14:57:01 -0700 Subject: [PATCH 10/20] Add print statements for debugging: where and how does seed_germ go negative? Check by printing from SeedDecay, SeedGerm, PreDisturbanceIntegrateLiter, and recruitment subroutines --- biogeochem/EDPhysiologyMod.F90 | 86 ++++++++++++++++++++++++---------- 1 file changed, 62 insertions(+), 24 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 13b2aad51b..431e418b03 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -562,6 +562,19 @@ subroutine PreDisturbanceIntegrateLitter(currentPatch) litt%seed_germ_in(pft) - & litt%seed_germ_decay(pft) + ! RW BEBUG BLOCK START + write(fates_log(),*) '=== PreDisturbanceIntegrateLitter DIAGNOSTICS ===' + write(fates_log(),*) 'Model Day:', hlm_model_day + write(fates_log(),*) 'PFT:', pft + write(fates_log(),*) 'seed_germ (before update):', litt%seed_germ(pft) - litt%seed_germ_in(pft) + & + litt%seed_germ_decay(pft) + write(fates_log(),*) 'seed_germ_in:', litt%seed_germ_in(pft) + write(fates_log(),*) 'seed_germ_decay:', litt%seed_germ_decay(pft) + write(fates_log(),*) 'seed_germ (after update):', litt%seed_germ(pft) + write(fates_log(),*) 'Net change:', litt%seed_germ_in(pft) - litt%seed_germ_decay(pft) + write(fates_log(),*) 'Decay exceeds pool?:', litt%seed_germ(pft) < 0.0_r8 + ! RW DEBUG BLOCK END + enddo ! Update the Coarse Woody Debris pools (above and below) @@ -2336,19 +2349,24 @@ subroutine SeedDecay( litt , currentPatch ) (litt%seed_germ(pft) * EDPftvarcon_inst%background_seedling_mort(pft) & * years_per_day) - ! DEBUG BLOCK START - write(fates_log(),*) '===DEBUG SEED DECAY====' + ! RW DEBUG BLOCK START + write(fates_log(),*) '===SEED DECAY DIADNOSTICS====' write(fates_log(),*) 'Model Day = ', hlm_model_day write(fates_log(),*) 'PFT:', pft write(fates_log(),*) 'Seedling par (raw):', currentPatch%sdlng_mort_par%GetMean() write(fates_log(),*) 'Seedling par (converted):', seedling_layer_par - write(fates_log(),*) 'Seedling light mort rate:', seedling_light_mort_rate - write(fates_log(),*) 'Seedling mdds:', seedling_light_mort_rate + write(fates_log(),*) 'Seedling mdds:', currentPatch%sdlng_mdd(pft)%p%GetMean() write(fates_log(),*) 'Seedling mdd crit:', EDPftvarcon_inst%seedling_mdd_crit(pft) - write(fates_log(),*) 'Seedling h2o mort rate:', seedling_h2o_mort_rate - write(fates_log(),*) 'Seed germ pool:', litt%seed_germ(pft) - write(fates_log(),*) 'Seed germ decay:',litt%seed_germ_decay(pft) - ! DEBUG BLOCK END + write(fates_log(),*) 'Seedling light mort rate:', seedling_light_mort_rate + write(fates_log(),*) 'Seedling h2o mort rate:', seedling_h2o_mort_rate + write(fates_log(),*) 'Seed_germ pool (before decay):', litt%seed_germ(pft) + write(fates_log(),*) 'Seed_germ_decay (calculated):', litt%seed_germ_decay(pft) + write(fates_log(),*) 'Background_seedling_mort:', EDPftvarcon_inst%background_seedling_mort(pft) * years_per_day + write(fates_log(),*) 'Total mort rate:', seedling_light_mort_rate + seedling_h2o_mort_rate + & + (EDPftvarcon_inst%background_seedling_mort(pft) * years_per_day) + write(fates_log(),*) 'Does seed decay exceeds pool?:', litt%seed_germ_decay(pft) > litt%seed_germ(pft) + ! RW DEBUG BLOCK END + else @@ -2463,6 +2481,19 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, currentPatch ) ! Step 4. Calculate the amount of carbon germinating out of the seed bank litt%seed_germ_in(pft) = litt%seed(pft) * seedling_emerg_rate + ! RW DEBUG BLOCK START + write(fates_log(),*) '=== SeedGermination DIAGNOSTICS ===' + write(fates_log(),*) 'Model Day:', hlm_model_day + write(fates_log(),*) 'PFT:', pft + write(fates_log(),*) 'seed pool:', litt%seed(pft) + write(fates_log(),*) 'seedling_layer_par:', seedling_layer_par + write(fates_log(),*) 'photoblastic_germ_modifier:', photoblastic_germ_modifier + write(fates_log(),*) 'seedling_layer_smp:', seedling_layer_smp + write(fates_log(),*) 'wetness_index:', wetness_index + write(fates_log(),*) 'seedling_emerg_rate:', seedling_emerg_rate + write(fates_log(),*) 'seed_germ_in (calculated):', litt%seed_germ_in(pft) + ! RW DEBUG BLOCK END + end if if_tfs_or_def select case (prt_params%phen_leaf_habit(pft)) @@ -2685,19 +2716,6 @@ subroutine recruitment(currentSite, currentPatch, bc_in) currentPatch%litter(el)%seed_germ(ft)* & EDPftvarcon_inst%seedling_light_rec_a(ft)* & sdlng2sap_par**EDPftvarcon_inst%seedling_light_rec_b(ft) - - ! DEBUG BLOCK START - write(fates_log(),*) '=== DEBUG RECRUITMENT TRS ===' - write(fates_log(),*) 'Model day:', hlm_model_day - write(fates_log(),*) 'PFT:', ft - write(fates_log(),*) 'Element:', element_id - write(fates_log(),*) 'sdlng2sap_par (raw):', currentPatch%sdlng2sap_par%GetMean() - write(fates_log(),*) 'sdlng2sap_par (converted):', sdlng2sap_par - write(fates_log(),*) 'seed_germ before calc:', currentPatch%litter(el)%seed_germ(ft) - write(fates_log(),*) 'seedling_light_rec_a:', EDPftvarcon_inst%seedling_light_rec_a(ft) - write(fates_log(),*) 'seedling_light_rec_b:', EDPftvarcon_inst%seedling_light_rec_b(ft) - write(fates_log(),*) 'currentPatch%area:', currentPatch%area - ! DEBUG BLOCK END ! If soil moisture is below pft-specific seedling moisture stress threshold the ! recruitment does not occur. @@ -2710,12 +2728,20 @@ subroutine recruitment(currentSite, currentPatch, bc_in) mass_avail = 0.0_r8 end if - ! DEBUG BLOCK START + ! RW DEBUG BLOCK START + write(fates_log(),*) '=== recruitment DIAGNOSTICS ===' + write(fates_log(),*) 'Model Day:', hlm_model_day + write(fates_log(),*) 'PFT:', ft + write(fates_log(),*) 'Element:', element_id + write(fates_log(),*) 'Seed_germ', currentPatch%area* & + currentPatch%litter(el)%seed_germ(ft) + write(fates_log(),*) 'Mass_avail', mass_avail + write(fates_log(),*) 'Mass_demand', mass_demand write(fates_log(),*) 'ilayer_seedling_root', ilayer_seedling_root write(fates_log(),*) 'seedling_layer_smp', seedling_layer_smp write(fates_log(),*) 'seedling_psi_crit', EDPftvarcon_inst%seedling_psi_crit(ft) - write(fates_log(),*) 'mass_avail after calc:', mass_avail - ! DEBUG BLOCK END + write(fates_log(),*) 'sdlng2sap_par', sdlng2sap_par + ! RW DEBUG BLOCK END end if ! End use TRS with seedling dynamics @@ -2814,6 +2840,18 @@ subroutine recruitment(currentSite, currentPatch, bc_in) currentPatch%litter(el)%seed_germ(ft) = & currentPatch%litter(el)%seed_germ(ft) - cohort_n / currentPatch%area * & (m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) + + ! RW DEBUG BLOCK START + write(fates_log(),*) '=== recruitment remove mass DIAGNOSTICS ===' + write(fates_log(),*) 'cohort_n:', cohort_n + write(fates_log(),*) 'currentPatch%area:', currentPatch%area + write(fates_log(),*) 'cohort_n / area:', cohort_n / currentPatch%area + write(fates_log(),*) 'm demand', (m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) + write(fates_log(),*) 'm removed from seed_germ', cohort_n / currentPatch%area * & + (m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) + write(fates_log(),*) 'Is seed_germ negative?:', currentPatch%litter(el)%seed_germ(ft) < 0.0_r8 + ! RW DEBUG BLOCK END + end if end do From fb4f2801d66acb7716374ab76f62f5b1b3fc9ba0 Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Thu, 13 Nov 2025 15:30:45 -0700 Subject: [PATCH 11/20] Update seedling layer smp and mdd running means only after first model day to avoid host model spike in smp at initialization --- main/FatesInterfaceMod.F90 | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 7dd6d8a8c2..66d92cd8ae 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2341,24 +2341,10 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in, bc_out) new_seedling_mdd = 0.0_r8 endif - ! === DEBUG BLOCK START === - write(fates_log(),*) '=== MDD DEBUG Day:', hlm_model_day - write(fates_log(),*) 'PFT:', pft, 'Soil layer:', ilayer_seedling_root - write(fates_log(),*) 'Raw SMP from host:', bc_in(s)%smp_sl(ilayer_seedling_root) - write(fates_log(),*) 'new_seedling_layer_smp:', new_seedling_layer_smp - write(fates_log(),*) 'seedling_psi_crit:', EDPftvarcon_inst%seedling_psi_crit(pft) - write(fates_log(),*) 'Deficit check val for check', abs(EDPftvarcon_inst%seedling_psi_crit(pft)) - abs(new_seedling_layer_smp) - write(fates_log(),*) 'new_seedling_mdd (after zero check):', new_seedling_mdd - write(fates_log(),*) 'Current EMA c_mean:', cpatch%sdlng_mdd(pft)%p%c_mean - write(fates_log(),*) 'Current c_index:', cpatch%sdlng_mdd(pft)%p%c_index - write(fates_log(),*) 'n_mem:', cpatch%sdlng_mdd(pft)%p%def_type%n_mem - write(fates_log(),*) 'sdlng_mdd_timescale:', sdlng_mdd_timescale - ! === DEBUG BLOCK END === - ! Update the seedling layer smp and mdd running means ! RW - only update after first model day to avoid adding - ! spike in smp (~negative billions) to running means - if (hlm_model_day > 1.5_r8) then + ! initialization spike in smp to running means + if (hlm_model_day > 2.0_r8) then call cpatch%sdlng_mdd(pft)%p%UpdateRMean(new_seedling_mdd) call cpatch%sdlng_emerg_smp(pft)%p%UpdateRMean(new_seedling_layer_smp) endif From 735c4cb89441493512eb0294c60977f71026e785 Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Sun, 16 Nov 2025 16:57:28 -0700 Subject: [PATCH 12/20] Fix negative seed pool issue by capping germination flux. Prevent seed_germ_in from exceeding available seed after accounting for inputs and decay --- biogeochem/EDPhysiologyMod.F90 | 58 +++++++++++++++++++++------------- main/FatesInterfaceMod.F90 | 7 ---- 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 431e418b03..87b1542512 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -541,6 +541,7 @@ subroutine PreDisturbanceIntegrateLitter(currentPatch) integer :: nlevsoil ! number of soil layers integer :: ilyr ! soil layer loop counter integer :: dcmpy ! decomposability index + real(r8) :: net_seed_available ! Available seed after inputs and decay do el = 1, num_elements @@ -550,30 +551,42 @@ subroutine PreDisturbanceIntegrateLitter(currentPatch) ! ----------------------------------------------------------------------------------- do pft = 1,numpft - litt%seed(pft) = litt%seed(pft) + & - litt%seed_in_local(pft) + & - litt%seed_in_extern(pft) - & - litt%seed_decay(pft) - & - litt%seed_germ_in(pft) - - ! Note that the recruitment scheme will use seed_germ - ! for its construction costs. - litt%seed_germ(pft) = litt%seed_germ(pft) + & + + ! Calculate net available seed after inputs and decay + net_seed_available = litt%seed(pft) + litt%seed_in_local(pft) + & + litt%seed_in_extern(pft) - litt%seed_decay(pft) + + ! Cap germination at available seed + litt%seed_germ_in(pft) = min(litt%seed_germ_in(pft), net_seed_available) + + ! RW - commenting out for reference + ! litt%seed(pft) = litt%seed(pft) + & + ! litt%seed_in_local(pft) + & + ! litt%seed_in_extern(pft) - & + ! litt%seed_decay(pft) - & + ! litt%seed_germ_in(pft) + + ! Update pools + litt%seed(pft) = net_seed_available - litt%seed_germ_in(pft) + + ! Note that the recruitment scheme will use seed_germ + ! for its construction costs. + litt%seed_germ(pft) = litt%seed_germ(pft) + & litt%seed_germ_in(pft) - & litt%seed_germ_decay(pft) - ! RW BEBUG BLOCK START - write(fates_log(),*) '=== PreDisturbanceIntegrateLitter DIAGNOSTICS ===' - write(fates_log(),*) 'Model Day:', hlm_model_day - write(fates_log(),*) 'PFT:', pft - write(fates_log(),*) 'seed_germ (before update):', litt%seed_germ(pft) - litt%seed_germ_in(pft) + & + ! RW DEBUG BLOCK START + write(fates_log(),*) '=== PreDisturbanceIntegrateLitter DIAGNOSTICS ===' + write(fates_log(),*) 'Model Day:', hlm_model_day + write(fates_log(),*) 'PFT:', pft + write(fates_log(),*) 'seed_germ (before update):', litt%seed_germ(pft) - litt%seed_germ_in(pft) + & litt%seed_germ_decay(pft) - write(fates_log(),*) 'seed_germ_in:', litt%seed_germ_in(pft) - write(fates_log(),*) 'seed_germ_decay:', litt%seed_germ_decay(pft) - write(fates_log(),*) 'seed_germ (after update):', litt%seed_germ(pft) - write(fates_log(),*) 'Net change:', litt%seed_germ_in(pft) - litt%seed_germ_decay(pft) - write(fates_log(),*) 'Decay exceeds pool?:', litt%seed_germ(pft) < 0.0_r8 - ! RW DEBUG BLOCK END + write(fates_log(),*) 'seed_germ_in:', litt%seed_germ_in(pft) + write(fates_log(),*) 'seed_germ_decay:', litt%seed_germ_decay(pft) + write(fates_log(),*) 'seed_germ (after update):', litt%seed_germ(pft) + write(fates_log(),*) 'Net change:', litt%seed_germ_in(pft) - litt%seed_germ_decay(pft) + write(fates_log(),*) 'Decay exceeds pool?:', litt%seed_germ(pft) < 0.0_r8 + ! RW DEBUG BLOCK END enddo @@ -2469,9 +2482,10 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, currentPatch ) ! rate modifier (Step 1). See Eq. 4 of Hanbury-Brown et al., 2022 ! If SMP is below a pft-specific value, then no germination occurs + ! RW - cap emerg rate at 1 if ( seedling_layer_smp .GE. EDPftvarcon_inst%seedling_psi_emerg(pft) ) then - seedling_emerg_rate = photoblastic_germ_modifier * EDPftvarcon_inst%a_emerg(pft) * & - wetness_index**EDPftvarcon_inst%b_emerg(pft) + seedling_emerg_rate = min(1.0_r8, photoblastic_germ_modifier * EDPftvarcon_inst%a_emerg(pft) * & + wetness_index**EDPftvarcon_inst%b_emerg(pft)) else seedling_emerg_rate = 0.0_r8 diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 66d92cd8ae..d9ac05c654 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2312,13 +2312,6 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in, bc_out) & par_low_frac) new_seedling_layer_par = seedling_par_high*par_high_frac + seedling_par_low*par_low_frac - - ! DEBUG BLOCK START - write(fates_log(),*) '=== Seedling Layer PAR Debug ==== Day:', hlm_model_day - write(fates_log(),*) 'Seedling par high:', seedling_par_high, 'Par frac high:', par_high_frac - write(fates_log(),*) 'Seedling par low:', seedling_par_low, 'Par frac low:', par_low_frac - write(fates_log(),*) 'New seedling layer par:', new_seedling_layer_par - ! DEBUG BLOCK END call cpatch%seedling_layer_par24%UpdateRMean(new_seedling_layer_par) call cpatch%sdlng_mort_par%UpdateRMean(new_seedling_layer_par) From 1988d066b541725fcc860a45e96aa7595f3f4482 Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Wed, 10 Dec 2025 11:35:39 -0700 Subject: [PATCH 13/20] remove debug messages for seed germ diagnostics --- biogeochem/EDPhysiologyMod.F90 | 66 +++++++++++++++++----------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 87b1542512..7fdedfec8f 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -576,16 +576,16 @@ subroutine PreDisturbanceIntegrateLitter(currentPatch) litt%seed_germ_decay(pft) ! RW DEBUG BLOCK START - write(fates_log(),*) '=== PreDisturbanceIntegrateLitter DIAGNOSTICS ===' - write(fates_log(),*) 'Model Day:', hlm_model_day - write(fates_log(),*) 'PFT:', pft - write(fates_log(),*) 'seed_germ (before update):', litt%seed_germ(pft) - litt%seed_germ_in(pft) + & - litt%seed_germ_decay(pft) - write(fates_log(),*) 'seed_germ_in:', litt%seed_germ_in(pft) - write(fates_log(),*) 'seed_germ_decay:', litt%seed_germ_decay(pft) - write(fates_log(),*) 'seed_germ (after update):', litt%seed_germ(pft) - write(fates_log(),*) 'Net change:', litt%seed_germ_in(pft) - litt%seed_germ_decay(pft) - write(fates_log(),*) 'Decay exceeds pool?:', litt%seed_germ(pft) < 0.0_r8 + ! write(fates_log(),*) '=== PreDisturbanceIntegrateLitter DIAGNOSTICS ===' + ! write(fates_log(),*) 'Model Day:', hlm_model_day + ! write(fates_log(),*) 'PFT:', pft + ! write(fates_log(),*) 'seed_germ (before update):', litt%seed_germ(pft) - litt%seed_germ_in(pft) + & + ! litt%seed_germ_decay(pft) + ! write(fates_log(),*) 'seed_germ_in:', litt%seed_germ_in(pft) + !write(fates_log(),*) 'seed_germ_decay:', litt%seed_germ_decay(pft) + ! write(fates_log(),*) 'seed_germ (after update):', litt%seed_germ(pft) + ! write(fates_log(),*) 'Net change:', litt%seed_germ_in(pft) - litt%seed_germ_decay(pft) + ! write(fates_log(),*) 'Decay exceeds pool?:', litt%seed_germ(pft) < 0.0_r8 ! RW DEBUG BLOCK END enddo @@ -2363,21 +2363,21 @@ subroutine SeedDecay( litt , currentPatch ) * years_per_day) ! RW DEBUG BLOCK START - write(fates_log(),*) '===SEED DECAY DIADNOSTICS====' - write(fates_log(),*) 'Model Day = ', hlm_model_day - write(fates_log(),*) 'PFT:', pft - write(fates_log(),*) 'Seedling par (raw):', currentPatch%sdlng_mort_par%GetMean() - write(fates_log(),*) 'Seedling par (converted):', seedling_layer_par - write(fates_log(),*) 'Seedling mdds:', currentPatch%sdlng_mdd(pft)%p%GetMean() - write(fates_log(),*) 'Seedling mdd crit:', EDPftvarcon_inst%seedling_mdd_crit(pft) - write(fates_log(),*) 'Seedling light mort rate:', seedling_light_mort_rate - write(fates_log(),*) 'Seedling h2o mort rate:', seedling_h2o_mort_rate - write(fates_log(),*) 'Seed_germ pool (before decay):', litt%seed_germ(pft) - write(fates_log(),*) 'Seed_germ_decay (calculated):', litt%seed_germ_decay(pft) - write(fates_log(),*) 'Background_seedling_mort:', EDPftvarcon_inst%background_seedling_mort(pft) * years_per_day - write(fates_log(),*) 'Total mort rate:', seedling_light_mort_rate + seedling_h2o_mort_rate + & - (EDPftvarcon_inst%background_seedling_mort(pft) * years_per_day) - write(fates_log(),*) 'Does seed decay exceeds pool?:', litt%seed_germ_decay(pft) > litt%seed_germ(pft) + ! write(fates_log(),*) '===SEED DECAY DIADNOSTICS====' + ! write(fates_log(),*) 'Model Day = ', hlm_model_day + ! write(fates_log(),*) 'PFT:', pft + ! write(fates_log(),*) 'Seedling par (raw):', currentPatch%sdlng_mort_par%GetMean() + ! write(fates_log(),*) 'Seedling par (converted):', seedling_layer_par + ! write(fates_log(),*) 'Seedling mdds:', currentPatch%sdlng_mdd(pft)%p%GetMean() + ! write(fates_log(),*) 'Seedling mdd crit:', EDPftvarcon_inst%seedling_mdd_crit(pft) + ! write(fates_log(),*) 'Seedling light mort rate:', seedling_light_mort_rate + ! write(fates_log(),*) 'Seedling h2o mort rate:', seedling_h2o_mort_rate + ! write(fates_log(),*) 'Seed_germ pool (before decay):', litt%seed_germ(pft) + ! write(fates_log(),*) 'Seed_germ_decay (calculated):', litt%seed_germ_decay(pft) + ! write(fates_log(),*) 'Background_seedling_mort:', EDPftvarcon_inst%background_seedling_mort(pft) * years_per_day + ! write(fates_log(),*) 'Total mort rate:', seedling_light_mort_rate + seedling_h2o_mort_rate + & + ! (EDPftvarcon_inst%background_seedling_mort(pft) * years_per_day) + ! write(fates_log(),*) 'Does seed decay exceeds pool?:', litt%seed_germ_decay(pft) > litt%seed_germ(pft) ! RW DEBUG BLOCK END @@ -2856,14 +2856,14 @@ subroutine recruitment(currentSite, currentPatch, bc_in) (m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) ! RW DEBUG BLOCK START - write(fates_log(),*) '=== recruitment remove mass DIAGNOSTICS ===' - write(fates_log(),*) 'cohort_n:', cohort_n - write(fates_log(),*) 'currentPatch%area:', currentPatch%area - write(fates_log(),*) 'cohort_n / area:', cohort_n / currentPatch%area - write(fates_log(),*) 'm demand', (m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) - write(fates_log(),*) 'm removed from seed_germ', cohort_n / currentPatch%area * & - (m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) - write(fates_log(),*) 'Is seed_germ negative?:', currentPatch%litter(el)%seed_germ(ft) < 0.0_r8 + ! write(fates_log(),*) '=== recruitment remove mass DIAGNOSTICS ===' + ! write(fates_log(),*) 'cohort_n:', cohort_n + ! write(fates_log(),*) 'currentPatch%area:', currentPatch%area + ! write(fates_log(),*) 'cohort_n / area:', cohort_n / currentPatch%area + ! write(fates_log(),*) 'm demand', (m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) + ! write(fates_log(),*) 'm removed from seed_germ', cohort_n / currentPatch%area * & + ! (m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) + ! write(fates_log(),*) 'Is seed_germ negative?:', currentPatch%litter(el)%seed_germ(ft) < 0.0_r8 ! RW DEBUG BLOCK END end if From 356b305da0eb367c64768b7bde1d4f6d59c8a05f Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Wed, 10 Dec 2025 12:08:03 -0700 Subject: [PATCH 14/20] Cap seedling h2o mort rate and seed decay rate at 1, add debugging --- biogeochem/EDPhysiologyMod.F90 | 49 +++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 7fdedfec8f..a723ef0da7 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2353,31 +2353,42 @@ subroutine SeedDecay( litt , currentPatch ) seedling_h2o_mort_rate = EDPftvarcon_inst%seedling_h2o_mort_a(pft) * seedling_mdds**2 + & EDPftvarcon_inst%seedling_h2o_mort_b(pft) * seedling_mdds + & EDPftvarcon_inst%seedling_h2o_mort_c(pft) + ! RW: capping h20 mortality rate at 1 + seedling_h2o_mort_rate = min(1.0_r8, seedling_h2o_mort_rate) end if ! mdd threshold check ! Step 3. Sum modes of mortality (including background mortality) and send dead seedlings ! to litter - litt%seed_germ_decay(pft) = (litt%seed_germ(pft) * seedling_light_mort_rate) + & - (litt%seed_germ(pft) * seedling_h2o_mort_rate) + & - (litt%seed_germ(pft) * EDPftvarcon_inst%background_seedling_mort(pft) & - * years_per_day) + ! litt%seed_germ_decay(pft) = (litt%seed_germ(pft) * seedling_light_mort_rate) + & + ! (litt%seed_germ(pft) * seedling_h2o_mort_rate) + & + ! (litt%seed_germ(pft) * EDPftvarcon_inst%background_seedling_mort(pft) & + ! * years_per_day) + + ! RW: capping total mortality rate at 1 + litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & + min(1.0_r8, seedling_light_mort_rate + & + seedling_h2o_mort_rate + & + (EDPftvarcon_inst%background_seedling_mort(pft) * & + years_per_day)) + + ! RW DEBUG BLOCK START - ! write(fates_log(),*) '===SEED DECAY DIADNOSTICS====' - ! write(fates_log(),*) 'Model Day = ', hlm_model_day - ! write(fates_log(),*) 'PFT:', pft - ! write(fates_log(),*) 'Seedling par (raw):', currentPatch%sdlng_mort_par%GetMean() - ! write(fates_log(),*) 'Seedling par (converted):', seedling_layer_par - ! write(fates_log(),*) 'Seedling mdds:', currentPatch%sdlng_mdd(pft)%p%GetMean() - ! write(fates_log(),*) 'Seedling mdd crit:', EDPftvarcon_inst%seedling_mdd_crit(pft) - ! write(fates_log(),*) 'Seedling light mort rate:', seedling_light_mort_rate - ! write(fates_log(),*) 'Seedling h2o mort rate:', seedling_h2o_mort_rate - ! write(fates_log(),*) 'Seed_germ pool (before decay):', litt%seed_germ(pft) - ! write(fates_log(),*) 'Seed_germ_decay (calculated):', litt%seed_germ_decay(pft) - ! write(fates_log(),*) 'Background_seedling_mort:', EDPftvarcon_inst%background_seedling_mort(pft) * years_per_day - ! write(fates_log(),*) 'Total mort rate:', seedling_light_mort_rate + seedling_h2o_mort_rate + & - ! (EDPftvarcon_inst%background_seedling_mort(pft) * years_per_day) - ! write(fates_log(),*) 'Does seed decay exceeds pool?:', litt%seed_germ_decay(pft) > litt%seed_germ(pft) + write(fates_log(),*) '===SEED DECAY DIADNOSTICS====' + write(fates_log(),*) 'Model Day = ', hlm_model_day + write(fates_log(),*) 'PFT:', pft + write(fates_log(),*) 'Seedling par (raw):', currentPatch%sdlng_mort_par%GetMean() + write(fates_log(),*) 'Seedling par (converted):', seedling_layer_par + write(fates_log(),*) 'Seedling mdds:', currentPatch%sdlng_mdd(pft)%p%GetMean() + write(fates_log(),*) 'Seedling mdd crit:', EDPftvarcon_inst%seedling_mdd_crit(pft) + write(fates_log(),*) 'Seedling light mort rate:', seedling_light_mort_rate + write(fates_log(),*) 'Seedling h2o mort rate:', seedling_h2o_mort_rate + write(fates_log(),*) 'Seed_germ pool (before decay):', litt%seed_germ(pft) + write(fates_log(),*) 'Seed_germ_decay (calculated):', litt%seed_germ_decay(pft) + write(fates_log(),*) 'Background_seedling_mort:', EDPftvarcon_inst%background_seedling_mort(pft) * years_per_day + write(fates_log(),*) 'Total mort rate:', seedling_light_mort_rate + seedling_h2o_mort_rate + & + (EDPftvarcon_inst%background_seedling_mort(pft) * years_per_day) + write(fates_log(),*) 'Does seed decay exceeds pool?:', litt%seed_germ_decay(pft) > litt%seed_germ(pft) ! RW DEBUG BLOCK END From c82ba29c59f430ea32a62957028253f1b471f151 Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Mon, 27 Apr 2026 17:54:59 -0600 Subject: [PATCH 15/20] Remove debug print statements from TRS seedling layer subroutines Remove diagnostic blocks from EDPhysiologyMod and FatesInterfaceMod that were added during degubbing of TRS. --- biogeochem/EDPhysiologyMod.F90 | 95 +++------------------------------- main/FatesInterfaceMod.F90 | 3 +- 2 files changed, 7 insertions(+), 91 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index a723ef0da7..5969921254 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -556,16 +556,9 @@ subroutine PreDisturbanceIntegrateLitter(currentPatch) net_seed_available = litt%seed(pft) + litt%seed_in_local(pft) + & litt%seed_in_extern(pft) - litt%seed_decay(pft) - ! Cap germination at available seed + ! Cap germination at available seed to prevent negative seed pool litt%seed_germ_in(pft) = min(litt%seed_germ_in(pft), net_seed_available) - ! RW - commenting out for reference - ! litt%seed(pft) = litt%seed(pft) + & - ! litt%seed_in_local(pft) + & - ! litt%seed_in_extern(pft) - & - ! litt%seed_decay(pft) - & - ! litt%seed_germ_in(pft) - ! Update pools litt%seed(pft) = net_seed_available - litt%seed_germ_in(pft) @@ -575,19 +568,6 @@ subroutine PreDisturbanceIntegrateLitter(currentPatch) litt%seed_germ_in(pft) - & litt%seed_germ_decay(pft) - ! RW DEBUG BLOCK START - ! write(fates_log(),*) '=== PreDisturbanceIntegrateLitter DIAGNOSTICS ===' - ! write(fates_log(),*) 'Model Day:', hlm_model_day - ! write(fates_log(),*) 'PFT:', pft - ! write(fates_log(),*) 'seed_germ (before update):', litt%seed_germ(pft) - litt%seed_germ_in(pft) + & - ! litt%seed_germ_decay(pft) - ! write(fates_log(),*) 'seed_germ_in:', litt%seed_germ_in(pft) - !write(fates_log(),*) 'seed_germ_decay:', litt%seed_germ_decay(pft) - ! write(fates_log(),*) 'seed_germ (after update):', litt%seed_germ(pft) - ! write(fates_log(),*) 'Net change:', litt%seed_germ_in(pft) - litt%seed_germ_decay(pft) - ! write(fates_log(),*) 'Decay exceeds pool?:', litt%seed_germ(pft) < 0.0_r8 - ! RW DEBUG BLOCK END - enddo ! Update the Coarse Woody Debris pools (above and below) @@ -2353,44 +2333,19 @@ subroutine SeedDecay( litt , currentPatch ) seedling_h2o_mort_rate = EDPftvarcon_inst%seedling_h2o_mort_a(pft) * seedling_mdds**2 + & EDPftvarcon_inst%seedling_h2o_mort_b(pft) * seedling_mdds + & EDPftvarcon_inst%seedling_h2o_mort_c(pft) - ! RW: capping h20 mortality rate at 1 + ! Cap h2o mortality rate at 1, quadratic can produce values >1 for large moisture + ! deficit days seedling_h2o_mort_rate = min(1.0_r8, seedling_h2o_mort_rate) end if ! mdd threshold check ! Step 3. Sum modes of mortality (including background mortality) and send dead seedlings ! to litter - ! litt%seed_germ_decay(pft) = (litt%seed_germ(pft) * seedling_light_mort_rate) + & - ! (litt%seed_germ(pft) * seedling_h2o_mort_rate) + & - ! (litt%seed_germ(pft) * EDPftvarcon_inst%background_seedling_mort(pft) & - ! * years_per_day) - - ! RW: capping total mortality rate at 1 + ! Cap total mortality rate at 1 to prevent negative seed pool litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & min(1.0_r8, seedling_light_mort_rate + & seedling_h2o_mort_rate + & (EDPftvarcon_inst%background_seedling_mort(pft) * & years_per_day)) - - - - ! RW DEBUG BLOCK START - write(fates_log(),*) '===SEED DECAY DIADNOSTICS====' - write(fates_log(),*) 'Model Day = ', hlm_model_day - write(fates_log(),*) 'PFT:', pft - write(fates_log(),*) 'Seedling par (raw):', currentPatch%sdlng_mort_par%GetMean() - write(fates_log(),*) 'Seedling par (converted):', seedling_layer_par - write(fates_log(),*) 'Seedling mdds:', currentPatch%sdlng_mdd(pft)%p%GetMean() - write(fates_log(),*) 'Seedling mdd crit:', EDPftvarcon_inst%seedling_mdd_crit(pft) - write(fates_log(),*) 'Seedling light mort rate:', seedling_light_mort_rate - write(fates_log(),*) 'Seedling h2o mort rate:', seedling_h2o_mort_rate - write(fates_log(),*) 'Seed_germ pool (before decay):', litt%seed_germ(pft) - write(fates_log(),*) 'Seed_germ_decay (calculated):', litt%seed_germ_decay(pft) - write(fates_log(),*) 'Background_seedling_mort:', EDPftvarcon_inst%background_seedling_mort(pft) * years_per_day - write(fates_log(),*) 'Total mort rate:', seedling_light_mort_rate + seedling_h2o_mort_rate + & - (EDPftvarcon_inst%background_seedling_mort(pft) * years_per_day) - write(fates_log(),*) 'Does seed decay exceeds pool?:', litt%seed_germ_decay(pft) > litt%seed_germ(pft) - ! RW DEBUG BLOCK END - else @@ -2493,8 +2448,9 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, currentPatch ) ! rate modifier (Step 1). See Eq. 4 of Hanbury-Brown et al., 2022 ! If SMP is below a pft-specific value, then no germination occurs - ! RW - cap emerg rate at 1 if ( seedling_layer_smp .GE. EDPftvarcon_inst%seedling_psi_emerg(pft) ) then + ! Cap emergence rate at 1, rate can exceed 1 for some parameter combinations, + ! leading to negative seed bank seedling_emerg_rate = min(1.0_r8, photoblastic_germ_modifier * EDPftvarcon_inst%a_emerg(pft) * & wetness_index**EDPftvarcon_inst%b_emerg(pft)) else @@ -2506,19 +2462,6 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, currentPatch ) ! Step 4. Calculate the amount of carbon germinating out of the seed bank litt%seed_germ_in(pft) = litt%seed(pft) * seedling_emerg_rate - ! RW DEBUG BLOCK START - write(fates_log(),*) '=== SeedGermination DIAGNOSTICS ===' - write(fates_log(),*) 'Model Day:', hlm_model_day - write(fates_log(),*) 'PFT:', pft - write(fates_log(),*) 'seed pool:', litt%seed(pft) - write(fates_log(),*) 'seedling_layer_par:', seedling_layer_par - write(fates_log(),*) 'photoblastic_germ_modifier:', photoblastic_germ_modifier - write(fates_log(),*) 'seedling_layer_smp:', seedling_layer_smp - write(fates_log(),*) 'wetness_index:', wetness_index - write(fates_log(),*) 'seedling_emerg_rate:', seedling_emerg_rate - write(fates_log(),*) 'seed_germ_in (calculated):', litt%seed_germ_in(pft) - ! RW DEBUG BLOCK END - end if if_tfs_or_def select case (prt_params%phen_leaf_habit(pft)) @@ -2753,21 +2696,6 @@ subroutine recruitment(currentSite, currentPatch, bc_in) mass_avail = 0.0_r8 end if - ! RW DEBUG BLOCK START - write(fates_log(),*) '=== recruitment DIAGNOSTICS ===' - write(fates_log(),*) 'Model Day:', hlm_model_day - write(fates_log(),*) 'PFT:', ft - write(fates_log(),*) 'Element:', element_id - write(fates_log(),*) 'Seed_germ', currentPatch%area* & - currentPatch%litter(el)%seed_germ(ft) - write(fates_log(),*) 'Mass_avail', mass_avail - write(fates_log(),*) 'Mass_demand', mass_demand - write(fates_log(),*) 'ilayer_seedling_root', ilayer_seedling_root - write(fates_log(),*) 'seedling_layer_smp', seedling_layer_smp - write(fates_log(),*) 'seedling_psi_crit', EDPftvarcon_inst%seedling_psi_crit(ft) - write(fates_log(),*) 'sdlng2sap_par', sdlng2sap_par - ! RW DEBUG BLOCK END - end if ! End use TRS with seedling dynamics ! update number density if this is the limiting mass @@ -2866,17 +2794,6 @@ subroutine recruitment(currentSite, currentPatch, bc_in) currentPatch%litter(el)%seed_germ(ft) - cohort_n / currentPatch%area * & (m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) - ! RW DEBUG BLOCK START - ! write(fates_log(),*) '=== recruitment remove mass DIAGNOSTICS ===' - ! write(fates_log(),*) 'cohort_n:', cohort_n - ! write(fates_log(),*) 'currentPatch%area:', currentPatch%area - ! write(fates_log(),*) 'cohort_n / area:', cohort_n / currentPatch%area - ! write(fates_log(),*) 'm demand', (m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) - ! write(fates_log(),*) 'm removed from seed_germ', cohort_n / currentPatch%area * & - ! (m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) - ! write(fates_log(),*) 'Is seed_germ negative?:', currentPatch%litter(el)%seed_germ(ft) < 0.0_r8 - ! RW DEBUG BLOCK END - end if end do diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index d9ac05c654..13422ac3e4 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2335,7 +2335,7 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in, bc_out) endif ! Update the seedling layer smp and mdd running means - ! RW - only update after first model day to avoid adding + ! Only update after first model day to avoid adding ! initialization spike in smp to running means if (hlm_model_day > 2.0_r8) then call cpatch%sdlng_mdd(pft)%p%UpdateRMean(new_seedling_mdd) @@ -2414,7 +2414,6 @@ subroutine SeedlingParPatch(cpatch, & ! Start with the assumption that there is a single canopy layer seedling_par_high = atm_par_dir+atm_par_dif - ! RW - edit to make these fractional rather than absolute area [m2] par_high_frac = 1._r8 - (cpatch%total_canopy_area / cpatch%area) par_low_frac = cpatch%total_canopy_area / cpatch%area From ef6ea7e82b5f7e4dd78677a6d727e2e7161a7d63 Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Tue, 28 Apr 2026 11:21:29 -0600 Subject: [PATCH 16/20] Make rate capping style consistent in SeedGermination seedling_emerg_rate is now calculated and then capped, consistent with the capping of seedling_h2o_mort_rate in SeedDecay --- biogeochem/EDPhysiologyMod.F90 | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 5969921254..e22c93128f 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2340,12 +2340,11 @@ subroutine SeedDecay( litt , currentPatch ) ! Step 3. Sum modes of mortality (including background mortality) and send dead seedlings ! to litter - ! Cap total mortality rate at 1 to prevent negative seed pool - litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & - min(1.0_r8, seedling_light_mort_rate + & - seedling_h2o_mort_rate + & - (EDPftvarcon_inst%background_seedling_mort(pft) * & - years_per_day)) + ! Cap total mortality rate at 1 to prevent negative seedling pool + litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & + min(1.0_r8, seedling_light_mort_rate + & + seedling_h2o_mort_rate + & + (EDPftvarcon_inst%background_seedling_mort(pft) * years_per_day)) else @@ -2449,10 +2448,11 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, currentPatch ) ! If SMP is below a pft-specific value, then no germination occurs if ( seedling_layer_smp .GE. EDPftvarcon_inst%seedling_psi_emerg(pft) ) then + seedling_emerg_rate = photoblastic_germ_modifier * EDPftvarcon_inst%a_emerg(pft) * & + wetness_index**EDPftvarcon_inst%b_emerg(pft) ! Cap emergence rate at 1, rate can exceed 1 for some parameter combinations, ! leading to negative seed bank - seedling_emerg_rate = min(1.0_r8, photoblastic_germ_modifier * EDPftvarcon_inst%a_emerg(pft) * & - wetness_index**EDPftvarcon_inst%b_emerg(pft)) + seedling_emerg_rate = min(1.0_r8, seedling_emerg_rate ) else seedling_emerg_rate = 0.0_r8 @@ -2683,7 +2683,7 @@ subroutine recruitment(currentSite, currentPatch, bc_in) mass_avail = currentPatch%area* & currentPatch%litter(el)%seed_germ(ft)* & EDPftvarcon_inst%seedling_light_rec_a(ft)* & - sdlng2sap_par**EDPftvarcon_inst%seedling_light_rec_b(ft) + sdlng2sap_par**EDPftvarcon_inst%seedling_light_rec_b(ft) ! If soil moisture is below pft-specific seedling moisture stress threshold the ! recruitment does not occur. From 8d7e4ca898e199c57eb2ee2e6b26497408bcd5e8 Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Fri, 22 May 2026 13:22:58 -0600 Subject: [PATCH 17/20] Cap TRS seedling-to-sapling recruitment rate at 1 to prevent negative seed_germ pool Prevent the TRS transition rate factor (seedling_light_rec_a * sdling2sap_par^seedling_light_rec_b) from exceeding 1. A transition rate factor >1 would allow mass_avail to exceed the seed_germ pool, driving seed_germ negative. --- biogeochem/EDPhysiologyMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index e22c93128f..c196e3ccae 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2682,8 +2682,8 @@ subroutine recruitment(currentSite, currentPatch, bc_in) mass_avail = currentPatch%area* & currentPatch%litter(el)%seed_germ(ft)* & - EDPftvarcon_inst%seedling_light_rec_a(ft)* & - sdlng2sap_par**EDPftvarcon_inst%seedling_light_rec_b(ft) + min(1.0_r8, EDPftvarcon_inst%seedling_light_rec_a(ft)* & + sdlng2sap_par**EDPftvarcon_inst%seedling_light_rec_b(ft)) ! If soil moisture is below pft-specific seedling moisture stress threshold the ! recruitment does not occur. From c4f5097ed03c747794faaeaa22383e8b8caa819b Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Fri, 22 May 2026 17:39:47 -0600 Subject: [PATCH 18/20] Log when TRS seedling mortality/transition rates exceed 1 Four TRS rates are capped at 1 (seedling_h2o_mort_rate, total_seedling_mort_rate, seedling_emerg_rate, sdlng2sap_rate) to prevent the TRS construction pool (seed_germ) from going negative. When rates exceed 1, the cap is still enforced but the uncapped value is written to the log --- biogeochem/EDPhysiologyMod.F90 | 46 ++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index c196e3ccae..46af756123 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2259,6 +2259,7 @@ subroutine SeedDecay( litt , currentPatch ) real(r8) :: seedling_light_mort_rate ! daily seedling mortality rate from light stress real(r8) :: seedling_h2o_mort_rate ! daily seedling mortality rate from moisture stress real(r8) :: seedling_mdds ! moisture deficit days accumulated in the seedling layer + real(r8) :: total_seedling_mort_rate ! summed seedling mortality rates !---------------------------------------------------------------------- @@ -2327,6 +2328,7 @@ subroutine SeedDecay( litt , currentPatch ) ! Calculate seedling mortality as a function of moisture deficit days (mdd) ! If the seedling mmd value is below a critical threshold then moisture-based mortality is zero + if (seedling_mdds < EDPftvarcon_inst%seedling_mdd_crit(pft)) then seedling_h2o_mort_rate = 0.0_r8 else @@ -2334,17 +2336,29 @@ subroutine SeedDecay( litt , currentPatch ) EDPftvarcon_inst%seedling_h2o_mort_b(pft) * seedling_mdds + & EDPftvarcon_inst%seedling_h2o_mort_c(pft) ! Cap h2o mortality rate at 1, quadratic can produce values >1 for large moisture - ! deficit days + ! deficit days, if rate exceeds 1 write to fates log + + if (seedling_h2o_mort_rate > 1.0_r8) then + write(fates_log(), *) 'TRS seedling_h2o_mort_rate > 1', & + 'pft=', pft, 'uncapped=', seedling_h2o_mort_rate, 'mdds=', seedling_mdds + end if seedling_h2o_mort_rate = min(1.0_r8, seedling_h2o_mort_rate) end if ! mdd threshold check ! Step 3. Sum modes of mortality (including background mortality) and send dead seedlings ! to litter ! Cap total mortality rate at 1 to prevent negative seedling pool - litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & - min(1.0_r8, seedling_light_mort_rate + & + total_seedling_mort_rate = seedling_light_mort_rate + & seedling_h2o_mort_rate + & - (EDPftvarcon_inst%background_seedling_mort(pft) * years_per_day)) + (EDPftvarcon_inst%background_seedling_mort(pft) * years_per_day) + if (total_seedling_mort_rate > 1.0_r8) then + write(fates_log(), *) 'TRS total seedling mortatliy rate > 1', & + 'pft=', pft, 'uncapped=', total_seedling_mort_rate, & + 'seedling_light_mort_rate=', seedling_light_mort_rate, & + 'seedling_h2o_mort_rate=', seedling_h2o_mort_rate + end if + litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & + min(1.0_r8, total_seedling_mort_rate) else @@ -2451,7 +2465,13 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, currentPatch ) seedling_emerg_rate = photoblastic_germ_modifier * EDPftvarcon_inst%a_emerg(pft) * & wetness_index**EDPftvarcon_inst%b_emerg(pft) ! Cap emergence rate at 1, rate can exceed 1 for some parameter combinations, - ! leading to negative seed bank + ! leading to negative seed bank, write to log if this is the case + if (seedling_emerg_rate > 1.0_r8) then + write(fates_log(),*) 'TRS seedling_emerg_rate > 1' & + 'pft=', pft, 'uncapped=', seedling_emerg_rate, & + 'photoblastic_germ_modifier=', photoblastic_germ_modifier, & + 'wetness_index=', wetness_index + end if seedling_emerg_rate = min(1.0_r8, seedling_emerg_rate ) else @@ -2535,6 +2555,7 @@ subroutine recruitment(currentSite, currentPatch, bc_in) real(r8) :: stem_drop_fraction ! real(r8) :: fnrt_drop_fraction ! real(r8) :: sdlng2sap_par ! running mean of PAR at the seedling layer [MJ/m2/day] + real(r8) :: sdlng2sap_rate ! seedling-to-sapling transition rate factor (unitless) real(r8) :: seedling_layer_smp ! soil matric potential at seedling rooting depth [mm H2O suction] integer, parameter :: recruitstatus = 1 ! whether the newly created cohorts are recruited or initialized integer :: ilayer_seedling_root ! the soil layer at seedling rooting depth @@ -2680,10 +2701,21 @@ subroutine recruitment(currentSite, currentPatch, bc_in) sdlng2sap_par = currentPatch%sdlng2sap_par%GetMean()* & sec_per_day*megajoules_per_joule + sdlng2sap_rate = EDPftvarcon_inst%seedling_light_rec_a(ft)* & + sdlng2sap_par**EDPftvarcon_inst%seedling_light_rec_b(ft) + + ! If the seedling to sapling transition rate exceeds 1, + ! cap at 1 (prevent seed_germ from going negative) and write to fates log + + if (sdlng2sap_rate > 1.0_r8) then + write(fates_log(), *) 'TRS seedling-to-sapling transition rate > 1' & + 'pft=', ft, 'uncapped=', sdlng2sap_rate, + 'sdlng2sap_par=', sdlng2sap_par + end if + mass_avail = currentPatch%area* & currentPatch%litter(el)%seed_germ(ft)* & - min(1.0_r8, EDPftvarcon_inst%seedling_light_rec_a(ft)* & - sdlng2sap_par**EDPftvarcon_inst%seedling_light_rec_b(ft)) + min(1.0_r8, sdlng2sap_rate) ! If soil moisture is below pft-specific seedling moisture stress threshold the ! recruitment does not occur. From 204dcf4c88a6c5c2c10fa865fe6747feb055549c Mon Sep 17 00:00:00 2001 From: Rachel Ward Date: Fri, 22 May 2026 17:44:05 -0600 Subject: [PATCH 19/20] Fix typos --- biogeochem/EDPhysiologyMod.F90 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 46af756123..111ac0d5f3 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2352,7 +2352,7 @@ subroutine SeedDecay( litt , currentPatch ) seedling_h2o_mort_rate + & (EDPftvarcon_inst%background_seedling_mort(pft) * years_per_day) if (total_seedling_mort_rate > 1.0_r8) then - write(fates_log(), *) 'TRS total seedling mortatliy rate > 1', & + write(fates_log(), *) 'TRS total seedling mortality rate > 1', & 'pft=', pft, 'uncapped=', total_seedling_mort_rate, & 'seedling_light_mort_rate=', seedling_light_mort_rate, & 'seedling_h2o_mort_rate=', seedling_h2o_mort_rate @@ -2467,7 +2467,7 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, currentPatch ) ! Cap emergence rate at 1, rate can exceed 1 for some parameter combinations, ! leading to negative seed bank, write to log if this is the case if (seedling_emerg_rate > 1.0_r8) then - write(fates_log(),*) 'TRS seedling_emerg_rate > 1' & + write(fates_log(),*) 'TRS seedling_emerg_rate > 1', & 'pft=', pft, 'uncapped=', seedling_emerg_rate, & 'photoblastic_germ_modifier=', photoblastic_germ_modifier, & 'wetness_index=', wetness_index @@ -2708,11 +2708,11 @@ subroutine recruitment(currentSite, currentPatch, bc_in) ! cap at 1 (prevent seed_germ from going negative) and write to fates log if (sdlng2sap_rate > 1.0_r8) then - write(fates_log(), *) 'TRS seedling-to-sapling transition rate > 1' & - 'pft=', ft, 'uncapped=', sdlng2sap_rate, + write(fates_log(), *) 'TRS seedling-to-sapling transition rate > 1', & + 'pft=', ft, 'uncapped=', sdlng2sap_rate, & 'sdlng2sap_par=', sdlng2sap_par end if - + mass_avail = currentPatch%area* & currentPatch%litter(el)%seed_germ(ft)* & min(1.0_r8, sdlng2sap_rate) From dc31b226840b11f6e15b90ba7fffd1d9d54fe35e Mon Sep 17 00:00:00 2001 From: r-ward Date: Wed, 5 Aug 2026 13:46:40 -0400 Subject: [PATCH 20/20] Remove diagnostic log messages for capped TRS seedling rates --- biogeochem/EDPhysiologyMod.F90 | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 111ac0d5f3..cf0ef1709b 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2336,12 +2336,7 @@ subroutine SeedDecay( litt , currentPatch ) EDPftvarcon_inst%seedling_h2o_mort_b(pft) * seedling_mdds + & EDPftvarcon_inst%seedling_h2o_mort_c(pft) ! Cap h2o mortality rate at 1, quadratic can produce values >1 for large moisture - ! deficit days, if rate exceeds 1 write to fates log - - if (seedling_h2o_mort_rate > 1.0_r8) then - write(fates_log(), *) 'TRS seedling_h2o_mort_rate > 1', & - 'pft=', pft, 'uncapped=', seedling_h2o_mort_rate, 'mdds=', seedling_mdds - end if + ! deficit days seedling_h2o_mort_rate = min(1.0_r8, seedling_h2o_mort_rate) end if ! mdd threshold check @@ -2351,12 +2346,6 @@ subroutine SeedDecay( litt , currentPatch ) total_seedling_mort_rate = seedling_light_mort_rate + & seedling_h2o_mort_rate + & (EDPftvarcon_inst%background_seedling_mort(pft) * years_per_day) - if (total_seedling_mort_rate > 1.0_r8) then - write(fates_log(), *) 'TRS total seedling mortality rate > 1', & - 'pft=', pft, 'uncapped=', total_seedling_mort_rate, & - 'seedling_light_mort_rate=', seedling_light_mort_rate, & - 'seedling_h2o_mort_rate=', seedling_h2o_mort_rate - end if litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & min(1.0_r8, total_seedling_mort_rate) @@ -2465,13 +2454,7 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, currentPatch ) seedling_emerg_rate = photoblastic_germ_modifier * EDPftvarcon_inst%a_emerg(pft) * & wetness_index**EDPftvarcon_inst%b_emerg(pft) ! Cap emergence rate at 1, rate can exceed 1 for some parameter combinations, - ! leading to negative seed bank, write to log if this is the case - if (seedling_emerg_rate > 1.0_r8) then - write(fates_log(),*) 'TRS seedling_emerg_rate > 1', & - 'pft=', pft, 'uncapped=', seedling_emerg_rate, & - 'photoblastic_germ_modifier=', photoblastic_germ_modifier, & - 'wetness_index=', wetness_index - end if + ! leading to negative seed bank seedling_emerg_rate = min(1.0_r8, seedling_emerg_rate ) else @@ -2705,14 +2688,7 @@ subroutine recruitment(currentSite, currentPatch, bc_in) sdlng2sap_par**EDPftvarcon_inst%seedling_light_rec_b(ft) ! If the seedling to sapling transition rate exceeds 1, - ! cap at 1 (prevent seed_germ from going negative) and write to fates log - - if (sdlng2sap_rate > 1.0_r8) then - write(fates_log(), *) 'TRS seedling-to-sapling transition rate > 1', & - 'pft=', ft, 'uncapped=', sdlng2sap_rate, & - 'sdlng2sap_par=', sdlng2sap_par - end if - + ! cap at 1 (prevent seed_germ from going negative) mass_avail = currentPatch%area* & currentPatch%litter(el)%seed_germ(ft)* & min(1.0_r8, sdlng2sap_rate)