Skip to content
Merged
6 changes: 4 additions & 2 deletions doc/.ChangeLog_template
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,10 @@ Changes answers relative to baseline:
changes to state fields usually grow to greater than roundoff as the simulation progresses.

If this tag changes climate list the run(s) done to evaluate the new
climate (from https://github.com/NCAR/LMWG_dev)
- issue number(s):
climate. Preferably in https://github.com/NCAR/LMWG_dev (or give details below)
- LMWG_dev issue number(s):

- details (casename, machine, user, link to plots etc.) [if not in LMWG_dev]

Other details
-------------
Expand Down
90 changes: 90 additions & 0 deletions doc/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,4 +1,94 @@
===============================================================
Tag name: ctsm5.4.014
Originator(s): mvdebolskiy
Date: Thu Jan 29 03:28:03 PM MST 2026
One-line Summary: Fix for xm2 and revise logic for excess ice melt

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

A bug fix in excess ice melt calculation. Previously, we have set
incorrectly xm2=xm-h2osoi_ice after h2osoi_ice has already been updated.
This resulted in extra heat being available to spend on melting excess_ice
since when all h2osoi_ice has been melted (xm2=xm). This fixed now, in
addition Phasechange_beta subroutine in SoilTemperatureMod has been
renamed to Phasechange by swensosc's suggestion.

The changes are generally small and only to a few points, so NOT marking it as a
significant change in answers.

Significant changes to scientifically-supported configurations
--------------------------------------------------------------

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.]

[ ] clm6_0

[ ] clm5_0

[ ] ctsm5_0-nwp

[ ] clm4_5


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

Fixes #3678 -- Logic error in excess ice melt calculation

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

Caveats for users (e.g., need to interpolate initial conditions):
The changes in short simulations are negligible, but a few points can show larger differences if run long enough. The following lists the min and max differences for a 40 year simulation.
https://github.com/ESCOMP/CTSM/pull/3718#issuecomment-3810263334

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

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

[PASS means all tests PASS; OK means tests PASS other than expected fails.]

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

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

If the tag used for baseline comparisons was NOT the previous tag, note that here:


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

Changes answers relative to baseline: Yes! when use_excess_ice is TRUE

Summarize any changes to answers, i.e.,
- any configuration with use_excess_ice=.true.
- larger than roundoff changes in the soil thermal and
moisture state in gridcells where excess ice is present
in the soil at the start of the simulations. Most of the
most of the gridcells will have little differences (1e-6),
however, the difference will grow for longer (>10y) runs.

If this tag changes climate list the run(s) done to evaluate the new
climate (from https://github.com/NCAR/LMWG_dev)
- issue number(s):
- NCAR/LMWG_dev#140

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

Pull Requests that document the changes (include PR ids):

https://github.com/ESCOMP/CTSM/pull/3718

===============================================================
===============================================================
Tag name: ctsm5.4.013
Originator(s): erik (Erik Kluzek,UCAR/TSS,303-497-1326)
Date: Wed Jan 28 12:24:02 AM MST 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.014 mvdebols 01/29/2026 Fix for xm2 and revise logic for excess ice melt
ctsm5.4.013 erik 01/28/2026 Patch the Greenland snow hole with initial conditions for ne30 and tweak the C14 isotope latitudes
ctsm5.4.012 slevis 01/26/2026 Fix C-balance error for partly emerged crops
ctsm5.4.011 slevis 01/22/2026 Merge b4b-dev to master
Expand Down
35 changes: 17 additions & 18 deletions src/biogeophys/SoilTemperatureMod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ module SoilTemperatureMod
! !PRIVATE MEMBER FUNCTIONS:
private :: SoilThermProp ! Set therm conduct. and heat cap of snow/soil layers
private :: PhaseChangeH2osfc ! When surface water freezes move ice to bottom snow layer
private :: PhaseChange_beta ! Calculation of the phase change within snow and soil layers
private :: PhaseChange ! Calculation of the phase change within snow and soil layers
private :: BuildingHAC ! Building Heating and Cooling for simpler method (introduced in CLM4.5)

real(r8), private, parameter :: thin_sfclayer = 1.0e-6_r8 ! Threshold for thin surface layer
Expand Down Expand Up @@ -517,7 +517,7 @@ subroutine SoilTemperature(bounds, num_urbanl, filter_urbanl, num_urbanc, filter
dhsdT(bounds%begc:bounds%endc), &
waterstatebulk_inst, waterdiagnosticbulk_inst, waterfluxbulk_inst, temperature_inst,energyflux_inst)

call Phasechange_beta (bounds, num_nolakec, filter_nolakec, &
call Phasechange (bounds, num_nolakec, filter_nolakec, &
dhsdT(bounds%begc:bounds%endc), &
soilstate_inst, waterstatebulk_inst, waterdiagnosticbulk_inst, waterfluxbulk_inst, energyflux_inst, temperature_inst)

Expand Down Expand Up @@ -1130,7 +1130,7 @@ subroutine PhaseChangeH2osfc (bounds, num_nolakec, filter_nolakec, &
end subroutine PhaseChangeH2osfc

!-----------------------------------------------------------------------
subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, &
subroutine Phasechange (bounds, num_nolakec, filter_nolakec, dhsdT, &
soilstate_inst, waterstatebulk_inst, waterdiagnosticbulk_inst, waterfluxbulk_inst, energyflux_inst, temperature_inst)
!
! !DESCRIPTION:
Expand Down Expand Up @@ -1186,7 +1186,7 @@ subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, &

!-----------------------------------------------------------------------

call t_startf( 'PhaseChangebeta' )
call t_startf( 'PhaseChange' )

! Enforce expected array sizes
SHR_ASSERT_ALL_FL((ubound(dhsdT) == (/bounds%endc/)), sourcefile, __LINE__)
Expand Down Expand Up @@ -1279,7 +1279,6 @@ subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, &
! If ice exists above melt point, melt some to liquid.
if (h2osoi_ice(c,j) > 0._r8 .and. t_soisno(c,j) > tfrz) then
imelt(c,j) = 1
! tinc(c,j) = t_soisno(c,j) - tfrz
tinc(c,j) = tfrz - t_soisno(c,j)
t_soisno(c,j) = tfrz
endif
Expand All @@ -1288,7 +1287,6 @@ subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, &
! If liquid exists below melt point, freeze some to ice.
if (h2osoi_liq(c,j) > 0._r8 .AND. t_soisno(c,j) < tfrz) then
imelt(c,j) = 2
! tinc(c,j) = t_soisno(c,j) - tfrz
tinc(c,j) = tfrz - t_soisno(c,j)
t_soisno(c,j) = tfrz
endif
Expand All @@ -1310,7 +1308,6 @@ subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, &

if (h2osoi_ice(c,j) > 0. .AND. t_soisno(c,j) > tfrz) then
imelt(c,j) = 1
! tinc(c,j) = t_soisno(c,j) - tfrz
tinc(c,j) = tfrz - t_soisno(c,j)
t_soisno(c,j) = tfrz
endif
Expand All @@ -1334,7 +1331,6 @@ subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, &

if (h2osoi_liq(c,j) > supercool(c,j) .AND. t_soisno(c,j) < tfrz) then
imelt(c,j) = 2
! tinc(c,j) = t_soisno(c,j) - tfrz
tinc(c,j) = tfrz - t_soisno(c,j)
t_soisno(c,j) = tfrz
endif
Expand All @@ -1343,7 +1339,6 @@ subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, &
if (h2osno_no_layers(c) > 0._r8 .AND. j == 1) then
if (t_soisno(c,j) > tfrz) then
imelt(c,j) = 1
! tincc,j) = t_soisno(c,j) - tfrz
tinc(c,j) = tfrz - t_soisno(c,j)
t_soisno(c,j) = tfrz
endif
Expand Down Expand Up @@ -1438,14 +1433,18 @@ subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, &
heatr = 0._r8
if (xm(c,j) > 0._r8) then !if there is excess heat to melt the ice
h2osoi_ice(c,j) = max(0._r8, wice0(c,j)-xm(c,j))
heatr = hm(c,j) - hfus*(wice0(c,j)-h2osoi_ice(c,j))/dtime
xm2(c,j) = xm(c,j) - h2osoi_ice(c,j) !excess ice melting
if (h2osoi_ice(c,j) == 0._r8) then ! this might be redundant
if (excess_ice(c,j) >= 0._r8 .and. xm2(c,j)>0._r8 .and. j>=2) then ! if there is excess ice to melt
excess_ice(c,j) = max(0._r8,wexice0(c,j) - xm2(c,j))
heatr = hm(c,j) - hfus * (wexice0(c,j)-excess_ice(c,j)+wice0(c,j)-h2osoi_ice(c,j)) / dtime
! If xm > wice0, then all soil ice melts,
! and the remaining heat (xm2) is used to melt excess ice
xm2(c,j) = xm(c,j) - wice0(c,j)
if (j>=1) then ! soil
if (excess_ice(c,j) >= 0._r8 .and. xm2(c,j)>0._r8) then ! if there is excess ice to melt
excess_ice(c,j) = max(0._r8,wexice0(c,j) - xm2(c,j))
endif
endif !end of excess ice block
heatr = hm(c,j) - hfus * (wexice0(c,j)-excess_ice(c,j)+ &
wice0(c,j)-h2osoi_ice(c,j)) / dtime
else !snow
heatr = hm(c,j) - hfus * (wice0(c,j)-h2osoi_ice(c,j)) / dtime
endif
else if (xm(c,j) < 0._r8) then
if (j <= 0) then
h2osoi_ice(c,j) = min(wmass0(c,j), wice0(c,j)-xm(c,j)) ! snow
Expand Down Expand Up @@ -1535,10 +1534,10 @@ subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, &
end if
end do

call t_stopf( 'PhaseChangebeta' )
call t_stopf( 'PhaseChange' )
end associate

end subroutine Phasechange_beta
end subroutine Phasechange

!-----------------------------------------------------------------------
subroutine ComputeGroundHeatFluxAndDeriv(bounds, &
Expand Down