Fix bugs in the Tree Recruitment Scheme with seedling dynamics - #1572
Fix bugs in the Tree Recruitment Scheme with seedling dynamics#1572r-ward wants to merge 20 commits into
Conversation
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).
… (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%.
…egative? Check by printing from SeedDecay, SeedGerm, PreDisturbanceIntegrateLiter, and recruitment subroutines
…l day to avoid host model spike in smp at initialization
…d_germ_in from exceeding available seed after accounting for inputs and decay
Remove diagnostic blocks from EDPhysiologyMod and FatesInterfaceMod that were added during degubbing of TRS.
seedling_emerg_rate is now calculated and then capped, consistent with the capping of seedling_h2o_mort_rate in SeedDecay
… 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.
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
| litt%seed_in_extern(pft) - litt%seed_decay(pft) | ||
|
|
||
| ! Cap germination at available seed to prevent negative seed pool | ||
| litt%seed_germ_in(pft) = min(litt%seed_germ_in(pft), net_seed_available) |
There was a problem hiding this comment.
@r-ward , I'm wondering if this seed_germ_in could potentially be negative. I don't think it can since seed decay is the only negative term in net_seed_available, and it is by definition a fraction of seed mass. Can you verify this?
There was a problem hiding this comment.
Correct, seed_germ_in is never negative. Although, I guess it is possible for the flux to go negative if fates_recruit_seed_germination_rate or fates_trs_seedling_a_emerg were erroneously set as negative values. Maybe there should be a check on this in FatesCheckParams (I see for example a check against values of seed_dispersal_fraction < 0). I could add something similar. What do you think?
| ! 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', & |
There was a problem hiding this comment.
logging messages that don't have terminations associated with them are most helpful in my experience while actively debugging. Another alternative is to use FatesWarn() which will count the times this situation triggers and summarize at the end of a run. Another alternative would be create a history variable that tracks the mort rate in this situation.
There was a problem hiding this comment.
Makes sense, will remove. I'm working on a separate PR to add history variables for some TRS-specific output; I'll add history variables or FatesWarn() messages there.
| 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', & |
| ! 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) |
There was a problem hiding this comment.
We want to make sure that hlm_model_day is continuous across restarts. If for some reason someone is running two day restarts, and hlm_model_day is resetting each time, this running mean will never increment with meaningful data.
While I don't think SMP spikes are unexpected at the beginning of a simulation, and your move to ignore them makes sense. But I also wanted to check in regarding frozen soils. I think there was some discussion of it here:
SHould we apply some filters to prevent calculations when soils are frozen?
There was a problem hiding this comment.
Ok, I see. Re: frozen soils - I think you're right that we need some conditionality, but I don't think we should stop calculations when soils are frozen. We could do something analogous to the phenology code (https://github.com/r-ward/fates/blob/3b58472a513e39fcb8d0dafc7bc0ae31b91f6e95/biogeochem/EDPhysiologyMod.F90#L1222)) and use a lower bound value similar to smp_lwr_bound for cases where check_layer_water finds no liquid water. Frozen conditions are physiologically dry, so I think that makes sense (although really we should implement behavior dependent on moisture and chilling degree days for temperate/boreal forest uses of TRS).
In the tropics, though, using an smp_lwr_bound during the SMP initialization spike suppresses germination and inflates seedling mortality for weeks/months, so this fix alone doesn't work.
Can we differentiate real frozen soils from initialization/erroneous freezing by adding a check on soil temperature? If soil temperature is warm and there is no liquid water, skip the calculations. If soil temperature is freezing, and there is no liquid water, use an smp_lwr_bound. @lmkueppers - what do you think?
Description:
Fixes several bugs that cause the model to crash when running FATES with the Tree Recruitment Scheme (TRS; namelist option
fates_regeneration_model = 'trs').Bug fixes:
#1499 - Fix PAR fraction calculations (normalization by patch area was previously missing, causing NaN errors)
#1500 - Skip updating seedling layer SMP running mean on first model day (host model SMP spike leads to 100% seedling mortality; the host model spike itself is a separate issue: ESCOMP/CTSM#3584 (comment))
#1501 - Fix initial value for
sdlng_mort_par(was set totemp_init_veg, should beinit_seedling_par)#1504 - Add rate caps for TRS seedling emergence and decay rates so that they cannot exceed 1; rates > 1 unrealistically drive the TRS seedling pool negative, eventually crashing the model
Collaborators:
@rgknox @glemieux
Expectation of Answer Changes:
Results using other regeneration models (
default,trs_no_seed_dyn) are unchanged, results will differ when usingfates_regeneration_model='trs'(model previously crashed)Description of generative AI usage (as necessary)
None
Checklist
If this is your first time contributing, please read the CONTRIBUTING document.
All checklist items must be checked to enable merging this pull request:
Contributor
Integrator
If satellite phenology regressions are not b4b, please hold merge and notify the FATES development team.
Documentation
Test Results:
CTSM (or) E3SM (specify which) test hash-tag:
CTSM (or) E3SM (specify which) baseline hash-tag:
FATES baseline hash-tag:
Test Output: