Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
eaddc9b
Spread the DYNBAL water and energy fluxes over many years
billsacks Aug 28, 2026
9681949
Change sign convention for water and energy dynbal fluxes and storage
billsacks Aug 28, 2026
975d410
Make dynbal storage residence time namelist controllable
billsacks Aug 29, 2026
6b44163
Reset dynbal storage pools when reset_dynbal_baselines is true
billsacks Aug 29, 2026
bf025d7
Update tech note for changes on this branch
billsacks Aug 31, 2026
1eee35d
Add a note in namelist definition
billsacks Sep 2, 2026
1475d29
dynbal_storage_residence_time: maintain close to old behavior for clm5_0
billsacks Sep 3, 2026
e5768b9
Don't use hard-coded 365 days per year
billsacks Sep 3, 2026
54ff1fe
Remove a note from namelist definition
billsacks Sep 3, 2026
223b6e7
Add a comment describing clm5 default for dynbal_storage_residence_time
billsacks Sep 3, 2026
3f516e8
More comments on default values for dynbal_storage_residence_time
billsacks Sep 3, 2026
2195552
Move some description out of namelist definition into tech note
billsacks Sep 4, 2026
3fe863a
Move dynbal_storage_residence_time NL read into dynConsBiogeophysMod
billsacks Sep 4, 2026
1e56fd6
Fix test_dyn_cons_biogeophys unit tests
billsacks Sep 4, 2026
cf37d1a
Add some tests to expected fails
billsacks Sep 5, 2026
e10c2e0
Refactor namelist handling
billsacks Sep 5, 2026
d65a988
Merge remote-tracking branch 'escomp/master' into dynbal_temporal_smo…
billsacks Sep 5, 2026
4e3a4e1
Add test back to expected fails list
billsacks Sep 8, 2026
fe49a7e
Remove some tests from expected fails list
billsacks Sep 8, 2026
820370a
Add a test to the expected fails list
billsacks Sep 8, 2026
a5503cf
Update ChangeLog
billsacks Sep 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion bld/CLMBuildNamelist.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1931,6 +1931,11 @@ sub process_namelist_inline_logic {
# namelist group: clm_temperature_inparm #
##########################################
setup_logic_coldstart_temp($opts,$nl_flags, $definition, $defaults, $nl);

##############################################
# namelist group: dyn_cons_biogeophys_inparm #
##############################################
setup_logic_dyn_cons_biogeophys($opts, $nl_flags, $definition, $defaults, $nl);
}

#-------------------------------------------------------------------------------
Expand Down Expand Up @@ -2829,6 +2834,21 @@ sub setup_logic_dynamic_subgrid {
}
}

#-------------------------------------------------------------------------------

sub setup_logic_dyn_cons_biogeophys {
#
# Options controlling conservation of water and energy with dynamic land cover
#
my ($opts, $nl_flags, $definition, $defaults, $nl) = @_;

add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'dynbal_storage_residence_time');
my $dynbal_storage_residence_time = $nl->get_value('dynbal_storage_residence_time');
if ( $dynbal_storage_residence_time <= 0.0 ) {
$log->fatal_error("dynbal_storage_residence_time must be greater than 0");
Comment thread
ekluzek marked this conversation as resolved.
}
}

sub setup_logic_do_transient_pfts {
#
# Set do_transient_pfts default value, and perform error checking on do_transient_pfts
Expand Down Expand Up @@ -5413,7 +5433,8 @@ sub write_output_files {
soil_resis_inparm bgc_shared canopyfluxes_inparm aerosol
clmu_inparm clm_soilstate_inparm clm_nitrogen clm_snowhydrology_inparm hillslope_hydrology_inparm hillslope_properties_inparm
cnprecision_inparm clm_glacier_behavior crop_inparm irrigation_inparm
surfacealbedo_inparm water_tracers_inparm tillage_inparm);
surfacealbedo_inparm water_tracers_inparm tillage_inparm
dyn_cons_biogeophys_inparm);

#@groups = qw(clm_inparm clm_canopyhydrology_inparm clm_soilhydrology_inparm
# finidat_consistency_checks dynpft_consistency_checks);
Expand Down
21 changes: 21 additions & 0 deletions bld/namelist_files/namelist_defaults_ctsm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2750,6 +2750,27 @@ lnd/clm2/surfdata_esmf/NEON/ctsm5.4.0/surfdata_1x1_NEON_TOOL_hist_2000_78pfts_c2
<do_transient_lakes>.false.</do_transient_lakes>
<do_transient_urban>.false.</do_transient_urban>
<reset_dynbal_baselines>.false.</reset_dynbal_baselines>

<!-- Notes regarding the default values for dynbal_storage_residence_time:

The choice of 20 years is pretty arbitrary. It feels like this is on the longer side
of what's reasonable, and this choice of a relatively long residence time was made to
prioritize reducing annual fluxes, especially in the oscillatory case (where a given
grid cell flips back and forth between two states, as commonly happens at the margin
of the ice sheet).

Regarding the CLM5 default: There is no way to exactly recover the old CLM5 behavior,
which used an annual dribbler to evenly spread the fluxes throughout the following
year. But this CLM5 behavior can be approximated by setting
dynbal_storage_residence_time to something between about 0.5 and 1.0, depending on
the behaviors you want to recover - peak fluxes, effective residence time, etc. The
choice of 0.75 here is a compromise that keeps fluxes not much larger than in CLM5
immediately following landcover change, while still releasing a large fraction of the
conservation correction within the first year after landcover change.
-->
<dynbal_storage_residence_time >20.d00</dynbal_storage_residence_time>
<dynbal_storage_residence_time phys="clm5_0">0.75d00</dynbal_storage_residence_time>

<vars_1dwt_w_time do_transient_pfts=".true.">.true.</vars_1dwt_w_time>
<vars_1dwt_w_time do_transient_crops=".true.">.true.</vars_1dwt_w_time>
<vars_1dwt_w_time do_transient_lakes=".true.">.true.</vars_1dwt_w_time>
Expand Down
28 changes: 28 additions & 0 deletions bld/namelist_files/namelist_definition_ctsm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2878,6 +2878,11 @@ starting a startup or hybrid run from a partially or entirely spun-up
state. This will reset the baseline values based on the state at the
start of this run.

This flag also resets the dynbal storage pools to zero. (These pools hold the
still-to-be-distributed water and energy from earlier dynamic column/landunit area
changes. So resetting these to zero means forgetting about these earlier changes, which is
somewhat analogous to the other resetting done by this flag.)

Note that setting this flag can break water and energy conservation!
Specifically, any water and energy that has previously been added to or
removed from states that contribute to these baselines (currently, (a)
Expand Down Expand Up @@ -2921,6 +2926,29 @@ outcome as vars_1dwt_w_time = .true..
Use this flag if you wish to change FALSE to TRUE when run_has_transient_landcover = .false..
</entry>

<!-- ======================================================================================== -->
<!-- Namelist options related to conservation of water and energy with dynamic land cover -->
<!-- ======================================================================================== -->

<entry id="dynbal_storage_residence_time" type="real" category="physics"
group="dyn_cons_biogeophys_inparm" valid_values="">
Residence time (in years) of the dynbal storage pools.

Dynamic landunit adjustments change a grid cell's total water and energy content with no
associated physical flux. The resulting spurious gain or loss is put in a storage pool for
each of heat (DYNBAL_HEAT_STORAGE), liquid water (DYNBAL_LIQ_STORAGE) and ice
(DYNBAL_ICE_STORAGE); each pool is then released gradually to a corresponding conservation
flux (EFLX_DYNBAL, QFLX_LIQ_DYNBAL and QFLX_ICE_DYNBAL). This setting controls how
gradually: each pool is drained with a turnover rate of 1 / dynbal_storage_residence_time,
so a larger value spreads the correction over a longer period, giving smaller
instantaneous fluxes but also leaving the coupled system further out of balance for
longer.

Must be greater than 0. This can be set to less than 1 year, but should be much longer
than the model time step: if the residence time approaches the length of a time step, the
pools will overshoot and the fluxes will oscillate.
</entry>

<!-- ======================================================================================== -->
<!-- Namelist options related to finidat consistency checks -->
<!-- ======================================================================================== -->
Expand Down
41 changes: 22 additions & 19 deletions cime_config/testdefs/ExpectedTestFails.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,25 +83,6 @@
</test>

<test name="ERP_P64x2_Ld396.f10_f10_mg37.IHistClm60Bgc.derecho_intel.clm-monthly--clm-matrixcnOn_ignore_warnings">
<phase name="BASELINE">
<status>FAIL</status>
<issue>#2619</issue>
<comment>This failure relates to the following REP failure.</comment>
</phase>
</test>
<test name="ERP_D_P64x2_Ld3.f10_f10_mg37.I2000Clm50BgcCru.derecho_intel.clm-noFUN_flexCN--clm-matrixcnOn_ignore_warnings">
<phase name="COMPARE_base_rest">
<status>FAIL</status>
<issue>#2619</issue>
<comment>This failure relates to the following REP failure.</comment>
</phase>
<phase name="BASELINE">
<status>FAIL</status>
<issue>#2619</issue>
<comment>This failure relates to the following REP failure.</comment>
</phase>
</test>
<test name="ERP_D_P64x2_Ld3.f10_f10_mg37.I2000Clm50BgcCru.derecho_intel.clm-flexCN_FUN--clm-matrixcnOn_ignore_warnings">
<phase name="COMPARE_base_rest">
<status>FAIL</status>
<issue>#2619</issue>
Expand Down Expand Up @@ -140,6 +121,23 @@
<status>FAIL</status>
<issue>#3788</issue>
</phase>
<!-- Because the RUN fails, the COMPARE phase has a PEND status -->
<phase name="COMPARE_base_rest">
<status>PEND</status>
<issue>#3788</issue>
</phase>
</test>

<test name="DAE_C2_D_Lh12.f10_f10_mg37.I2000Clm50BgcCrop.derecho_intel.clm-DA_multidrv">
<phase name="RUN">
<status>FAIL</status>
<issue>#4202</issue>
</phase>
<!-- Because the RUN fails, the COMPARE phase has a PEND status -->
<phase name="COMPARE_base_da">
<status>PEND</status>
<issue>#4202</issue>
</phase>
</test>

<test name="ERP_Ly3_P64x2.f10_f10_mg37.IHistClm50BgcCrop.derecho_intel.clm-cropMonthOutput">
Expand Down Expand Up @@ -241,6 +239,11 @@
<status>FAIL</status>
<issue>#2261</issue>
</phase>
<!-- Because the RUN fails, the COMPARE phase has a PEND status -->
<phase name="COMPARE_base_rest">
<status>PEND</status>
<issue>#2261</issue>
</phase>
</test>

<test name="SMS_D_Ld5.5x5_amazon_rHDMA.I2000Clm60SpMizGs.derecho_gnu.mizuroute-default">
Expand Down
125 changes: 125 additions & 0 deletions doc/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,4 +1,129 @@
===============================================================
Tag name: ctsm5.4.055
Originator(s): sacks (Bill Sacks)
Date: Tue Sep 8 16:01:56 MDT 2026
One-line Summary: Add temporal smoothing of DYNBAL conservation correction fluxes

Purpose and description of changes
----------------------------------

Spread the DYNBAL water and energy fluxes over many years: Rather than releasing all of
the DYNBAL fluxes in the year in which they're generated, instead put them in storage
pools that are released with a 20-year residence time (controllable via a new namelist
parameter; the default for CLM50 is set to 0.75 to maintain something closer to the old
behavior). This reduces these fluxes, especially in the oscillatory case that is somewhat
common with a dynamic ice sheet.

The new storage pools are reset when reset_dynbal_baselines is set to .true., since this
feels conceptually similar to the other resetting done by that flag, so it feels
appropriate to do this resetting at the same time.

This tag also changes the sign convention for the DYNBAL fluxes: the previous sign
convention was unintuitively the opposite of the sign convention of other fluxes to
river/atm; while I'm changing these fluxes anyway, I'm also flipping the sign convention
to be more intuitive and hopefully less error-prone.

The motivation for this change is: When subgrid areas change due to dynamic landunits /
columns, fluxes are generated to compensate for changes in gridcell-average water and
energy (QFLX_LIQ_DYNBAL, QFLX_ICE_DYNBAL, EFLX_DYNBAL). These fluxes can (and should) be
reduced via careful setting of reset_dynbal_baselines, but that still doesn't reduce these
fluxes to zero. The previous implementation seems good enough in situations where there is
a gradual change in a given grid cell's subgrid areas over many years. Unfortunately,
though, that is not always the situation when coupling to CISM, as has been seen in recent
CESM3 runs: In grid cells around the ice sheet margin, large fractions of a CTSM grid cell
can blink between mostly-vegetated/bare and mostly-glacier on a 2-year cycle, and this
oscillatory behavior can go on for many years, possibly indefinitely. This can lead to
large dynbal fluxes in each year, even when dribbled throughout the year (as was
previously done). It is problematic for the ocean to get negative dynbal fluxes, but it is
also problematic to remove these negative dynbal fluxes by spreading them globally, as is
currently done, because then regional fluxes that should average to 0 spatially and
temporally (e.g., into the Arctic ocean) end up being biased positive. This PR implements
a relatively easy partial fix, which particularly addresses the oscillatory case that
seems to be a common cause of the observed ice runoff. See
https://github.com/ESCOMP/CTSM/issues/4188 for more details.


Significant changes to scientifically-supported configurations
--------------------------------------------------------------
[Remove entire section if none of the boxes are checked.]

Does this tag change answers significantly for any of the following physics configurations?
(Details of any changes will be given in the "Answer changes" section below.)

[Put an [X] in the box for any configuration with significant answer changes.]

[X] clm6_0

[X] clm5_0

[X] ctsm5_0-nwp

Bugs fixed
----------

List of CTSM issues fixed (include CTSM Issue # and description) [one per line]:
- Partially addresses #4188 - Consider one or more changes to reduce DYNBAL fluxes (dynamic landunit conservation correction fluxes)

Notes of particular relevance for users
---------------------------------------

Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables):
- New namelist variable: dynbal_storage_residence_time

Changes to documentation:
- Updates CLM50_Tech_Note_Transient_Landcover.rst to reflect these changes

Contributors: @billsacks

Notes of particular relevance for developers:
---------------------------------------------

Changes to tests or testing:
- Fixed some expected test fails based on discussions with Erik Kluzek and Sam Levis

Testing summary:
----------------

build-namelist tests (if CLMBuildNamelist.pm has changed):

derecho - OK

regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing):

derecho ----- OK
izumi ------- OK

Answer changes
--------------

Changes answers relative to baseline:

Summarize any changes to answers, i.e.,
- what code configurations:
- Transient cases (Hist, SSP)
- Cases with an evolving ice sheet (active CISM)
- FATES cases
- Cases that start mid-year from a restart file that had non-zero values in the old dribblers
- what platforms/compilers: all
- nature of change (roundoff; larger than roundoff/same climate; new climate):
- larger than roundoff
- same vs. new climate depends on the configuration and what variables are of interest

Non-BGC I compset cases have diffs only in limited variables: This PR only directly
affects sensible heat, liquid and ice runoff fluxes, so the only changes are in these
fluxes and related ROF variables. However, some BGC cases have more extensive diffs, I
think due to the feedback of ROF on CH4. For a few long BGC tests with extensive diffs, I
verified that, by changing the compset to one using SROF, the set of variables with diffs
became small (similar to the set of variables with diffs in non-BGC cases).


Other details
-------------

Pull Requests that document the changes (include PR ids): https://github.com/ESCOMP/CTSM/pull/4189

===============================================================
===============================================================
Tag name: ctsm5.4.054
Originator(s): erik (Erik Kluzek,UCAR/TSS,303-497-1326)
Date: Mon Aug 31 05:35:20 AM MDT 2026
Expand Down
1 change: 1 addition & 0 deletions doc/ChangeSum
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Tag Who Date Summary
============================================================================================================================
ctsm5.4.055 sacks 09/08/2026 Add temporal smoothing of DYNBAL conservation correction fluxes
ctsm5.4.054 erik 08/31/2026 Update submodules to the latest needed for cesm3_0_alpha10a
ctsm5.4.053 oleson 08/18/2026 Resolve problems with running PLUMBER2 sites
ctsm5.4.052 slevis 08/17/2026 Merge b4b-dev to master
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ When subgrid areas change, the water and energy states remain unchanged on a per

For example, consider a gridcell with two columns: column 1 has a water mass of 1 kg m\ :sup:`-2` and column 2 has a water mass of 2 kg m\ :sup:`-2` for a given water state variable, where these are expressed per unit column area. If column 1 increases in area at the expense of column 2, then column 1 will still have a water mass of 1 kg m\ :sup:`-2`, but now expressed over the new column area. This results in a decrease in the total gridcell water content.

Water and energy are conserved by summing up the total water and energy content of each gridcell before and after a change in area. Differences in liquid and ice water content are balanced by liquid and ice runoff terms, which can be either positive or negative. (Negative runoff is effectively a withdrawal of water from the ocean.) Differences in energy content are balanced by a sensible heat flux term, which again can be either positive or negative. These balancing fluxes are spread evenly throughout the following year.
Water and energy are conserved by summing up the total water and energy content of each gridcell before and after a change in area. Differences in liquid and ice water content are balanced by liquid and ice runoff terms, which can be either positive or negative. (Negative runoff is effectively a withdrawal of water from the ocean.) Differences in energy content are balanced by a sensible heat flux term, which again can be either positive or negative. These balancing fluxes are released gradually from temporary storage pools with 20-year residence times (with separate storage pools for each of heat, liquid water and ice). CLM's water and energy budgets close every time step because the storage pools are counted as part of each grid cell's total water and energy. What is deferred is the compensating exchange with real, physical state variables: at any moment, the coupled system carries an outstanding imbalance equal to the current contents of the storage pools. Since the pools only approach 0 asymptotically, this is only fully settled in the limit as time goes to infinity.

There is a special case when a given crop column type newly comes into existence - for example, when temperate corn first comes into existence in a gridcell. In this case, the column's below-ground temperature and water states are copied from the natural vegetated column in its gridcell, so that these state variables begin in a close-to-spun-up state. Other state variables (most of which spin up relatively quickly) begin at their cold start initialization values. This initialization is not necessary for the two other land unit types that currently can grow - natural vegetation and glacier: Those land unit types are always active, even when they have zero area on the gridcell, so their state variables will be spun up immediately when they come into existence. After this initialization, the conservation code described above takes effect.

Expand Down
Loading
Loading