Skip to content

Commit 0e70173

Browse files
reedmaxwellReedclaude
authored
Add extended CLM snow parameterization options Feature/clm snow (parflow#698)
## Summary Extends CLM snow parameterizations with new rain-snow partitioning methods, SZA-based melt damping, and configurable fractional snow cover. **New Features:** - **Dai (2008) rain-snow partitioning**: Hyperbolic tangent function fitted to 30 years of global observations - **Jennings (2018) rain-snow partitioning**: Bivariate logistic regression using temperature and relative humidity - **SZA-based snow melt damping**: Reduces melt energy at high solar zenith angles where CLM underestimates albedo - **Configurable fractional snow cover**: Adjustable roughness parameter for frac_sno calculation - **Configurable temperature thresholds**: SnowTCrit, SnowTLow, SnowTHigh, SnowTransitionWidth for existing methods **New Keys (16 total):** - `Solver.CLM.SnowTCrit`, `SnowTLow`, `SnowTHigh`, `SnowTransitionWidth` - `Solver.CLM.DaiCoeffA`, `DaiCoeffB`, `DaiCoeffC`, `DaiCoeffD` - `Solver.CLM.JenningsCoeffA`, `JenningsCoeffB`, `JenningsCoeffG` - `Solver.CLM.SZASnowDamping`, `SZADampingCoszenRef`, `SZADampingCoszenMin` - `Solver.CLM.FracSnoScheme`, `FracSnoRoughness` **References:** - Dai (2008) GRL doi:10.1029/2008GL033295 - Jennings et al. (2018) Nature Communications doi:10.1038/s41467-018-03629-7 - Dang et al. (2019) The Cryosphere doi:10.5194/tc-13-2325-2019 ## Test plan - [x] `clm_snow_dai` - Dai sigmoidal partitioning method - [x] `clm_snow_jennings` - Jennings bivariate logistic method - [x] `clm_snow_sza_damping` - SZA-based melt reduction - [x] All existing CLM snow tests pass Run tests with: `ctest -R clm_snow` 🤖 Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: Reed <rmaxwell@mines.edu> Co-authored-by: Claude <noreply@anthropic.com>
1 parent a221335 commit 0e70173

98 files changed

Lines changed: 2015 additions & 57 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/user_manual/keys.rst

Lines changed: 177 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6357,23 +6357,77 @@ Reference: :cite:p:`Wang2019`.
63576357

63586358
*string* **Solver.CLM.SnowPartition** CLM Selects the method for
63596359
partitioning precipitation into rain and snow. The valid types for
6360-
this key are **CLM**, **WetbulbThreshold**, **WetbulbLinear**.
6360+
this key are **CLM**, **WetbulbThreshold**, **WetbulbLinear**, **Dai**, **Jennings**.
63616361

63626362
**CLM**:
63636363
Standard air temperature threshold with linear transition (default).
6364+
Uses configurable SnowTLow and SnowTHigh thresholds.
63646365

63656366
**WetbulbThreshold**:
63666367
Sharp threshold at wet-bulb temperature. Better for dry mountain climates.
63676368

63686369
**WetbulbLinear**:
63696370
Linear transition around wet-bulb temperature threshold.
6371+
Uses configurable SnowTransitionWidth for transition zone.
6372+
6373+
**Dai**:
6374+
Sigmoidal function of air temperature from :cite:p:`Dai2008`.
6375+
Uses configurable DaiCoeffA/B/C/D coefficients.
6376+
6377+
**Jennings**:
6378+
Bivariate logistic regression with air temperature and relative humidity
6379+
from :cite:p:`Jennings2018`. Uses configurable JenningsCoeffA/B/G coefficients.
6380+
6381+
.. container:: list
6382+
6383+
::
6384+
6385+
pfset Solver.CLM.SnowPartition "Dai" ## TCL syntax
6386+
<runname>.Solver.CLM.SnowPartition = "Dai" ## Python syntax
6387+
6388+
*double* **Solver.CLM.SnowTCrit** 2.5 Initial classification threshold
6389+
above freezing (K) for determining precipitation type in drv_getforce.
6390+
If air temperature exceeds tfrz + SnowTCrit, precipitation is initially
6391+
classified as rain. Default 2.5 K matches the hardcoded CLM value.
6392+
6393+
.. container:: list
6394+
6395+
::
6396+
6397+
pfset Solver.CLM.SnowTCrit 2.5 ## TCL syntax
6398+
<runname>.Solver.CLM.SnowTCrit = 2.5 ## Python syntax
6399+
6400+
*double* **Solver.CLM.SnowTLow** 273.16 CLM method lower temperature
6401+
threshold (K) below which all precipitation is snow. Default 273.16 K (freezing).
63706402

63716403
.. container:: list
63726404

63736405
::
63746406

6375-
pfset Solver.CLM.SnowPartition "WetbulbThreshold" ## TCL syntax
6376-
<runname>.Solver.CLM.SnowPartition = "WetbulbThreshold" ## Python syntax
6407+
pfset Solver.CLM.SnowTLow 273.16 ## TCL syntax
6408+
<runname>.Solver.CLM.SnowTLow = 273.16 ## Python syntax
6409+
6410+
*double* **Solver.CLM.SnowTHigh** 275.16 CLM method upper temperature
6411+
threshold (K) above which the liquid fraction reaches maximum (40%).
6412+
Default 275.16 K (tfrz + 2).
6413+
6414+
.. container:: list
6415+
6416+
::
6417+
6418+
pfset Solver.CLM.SnowTHigh 275.16 ## TCL syntax
6419+
<runname>.Solver.CLM.SnowTHigh = 275.16 ## Python syntax
6420+
6421+
*double* **Solver.CLM.SnowTransitionWidth** 1.0 WetbulbLinear method
6422+
half-width (K) of transition zone. Transition spans threshold +/- this value.
6423+
Default 1.0 K for 2K total range.
6424+
6425+
.. container:: list
6426+
6427+
::
6428+
6429+
pfset Solver.CLM.SnowTransitionWidth 1.0 ## TCL syntax
6430+
<runname>.Solver.CLM.SnowTransitionWidth = 1.0 ## Python syntax
63776431

63786432
*double* **Solver.CLM.WetbulbThreshold** 274.15 Threshold temperature in
63796433
Kelvin for wetbulb partitioning methods. Default 274.15 K (1°C). Only
@@ -6387,6 +6441,48 @@ used when ``Solver.CLM.SnowPartition`` is ``WetbulbThreshold`` or
63876441
pfset Solver.CLM.WetbulbThreshold 274.15 ## TCL syntax
63886442
<runname>.Solver.CLM.WetbulbThreshold = 274.15 ## Python syntax
63896443

6444+
**Dai Coefficients**
6445+
6446+
The Dai (2008) method uses a hyperbolic tangent function fitted to 30 years
6447+
of global weather station observations. Reference: :cite:p:`Dai2008`.
6448+
6449+
Formula: F(%) = a * [tanh(b*(T-c)) - d], where T is in Celsius.
6450+
Defaults are from Table 1a (Land, annual) of Dai (2008).
6451+
6452+
*double* **Solver.CLM.DaiCoeffA** -48.2292 Dai coefficient a (scaling factor, negative).
6453+
6454+
*double* **Solver.CLM.DaiCoeffB** 0.7205 Dai coefficient b (slope at half-frequency T).
6455+
6456+
*double* **Solver.CLM.DaiCoeffC** 1.1662 Dai coefficient c (half-frequency temperature in C,
6457+
where snow probability is ~50%).
6458+
6459+
*double* **Solver.CLM.DaiCoeffD** 1.0223 Dai coefficient d (asymmetry parameter, ~1.0).
6460+
6461+
.. container:: list
6462+
6463+
::
6464+
6465+
pfset Solver.CLM.DaiCoeffA -48.2292 ## TCL syntax
6466+
<runname>.Solver.CLM.DaiCoeffA = -48.2292 ## Python syntax
6467+
6468+
**Jennings Coefficients**
6469+
6470+
The Jennings (2018) method uses bivariate logistic regression:
6471+
psnow = 1 / (1 + exp(a + b*T + g*RH)), where T is in Celsius and RH in percent.
6472+
6473+
*double* **Solver.CLM.JenningsCoeffA** -10.04 Jennings intercept coefficient.
6474+
6475+
*double* **Solver.CLM.JenningsCoeffB** 1.41 Jennings temperature coefficient.
6476+
6477+
*double* **Solver.CLM.JenningsCoeffG** 0.09 Jennings relative humidity coefficient.
6478+
6479+
.. container:: list
6480+
6481+
::
6482+
6483+
pfset Solver.CLM.JenningsCoeffA -10.04 ## TCL syntax
6484+
<runname>.Solver.CLM.JenningsCoeffA = -10.04 ## Python syntax
6485+
63906486
**Thin Snow Damping**
63916487

63926488
Thin early-season snowpacks can experience spurious melt due to warm
@@ -6415,6 +6511,52 @@ threshold in mm below which thin snow damping applies.
64156511
pfset Solver.CLM.ThinSnowThreshold 50.0 ## TCL syntax
64166512
<runname>.Solver.CLM.ThinSnowThreshold = 50.0 ## Python syntax
64176513

6514+
**SZA-Based Snow Damping**
6515+
6516+
CLM's narrowband snow optical parameters are computed assuming a solar
6517+
zenith angle (SZA) of 60 degrees. At higher zenith angles, actual snow
6518+
albedo is higher than CLM assumes, meaning less energy should be available
6519+
for melt. This is particularly relevant for high-latitude sites during
6520+
accumulation season. Reference: :cite:p:`Dang2019`.
6521+
6522+
*double* **Solver.CLM.SZASnowDamping** 1.0 Fraction of melt energy
6523+
retained at high solar zenith angles. A value of 1.0 means no damping
6524+
(default, disabled). A value of 0.8 means 20% energy reduction at high SZA.
6525+
Damping varies linearly with cosine of zenith angle between the reference
6526+
and minimum thresholds.
6527+
6528+
.. container:: list
6529+
6530+
::
6531+
6532+
pfset Solver.CLM.SZASnowDamping 0.8 ## TCL syntax
6533+
<runname>.Solver.CLM.SZASnowDamping = 0.8 ## Python syntax
6534+
6535+
*double* **Solver.CLM.SZADampingCoszenRef** 0.5 Reference cosine of solar
6536+
zenith angle below which SZA damping applies. Default 0.5 corresponds to
6537+
SZA of 60 degrees (matching CLM's assumption for optical parameters).
6538+
6539+
.. container:: list
6540+
6541+
::
6542+
6543+
pfset Solver.CLM.SZADampingCoszenRef 0.5 ## TCL syntax
6544+
<runname>.Solver.CLM.SZADampingCoszenRef = 0.5 ## Python syntax
6545+
6546+
*double* **Solver.CLM.SZADampingCoszenMin** 0.1 Cosine of solar zenith
6547+
angle at which maximum SZA damping applies. Default 0.1 corresponds to
6548+
SZA of approximately 84 degrees. Must be less than SZADampingCoszenRef.
6549+
6550+
.. container:: list
6551+
6552+
::
6553+
6554+
pfset Solver.CLM.SZADampingCoszenMin 0.1 ## TCL syntax
6555+
<runname>.Solver.CLM.SZADampingCoszenMin = 0.1 ## Python syntax
6556+
6557+
Note: Both thin snow damping and SZA damping can be enabled simultaneously.
6558+
When both are active, they combine multiplicatively.
6559+
64186560
**Albedo Schemes**
64196561

64206562
Snow albedo controls the radiation balance and strongly influences melt
@@ -6512,6 +6654,38 @@ snow faster.
65126654
pfset Solver.CLM.AlbedoThawA 0.82 ## TCL syntax
65136655
<runname>.Solver.CLM.AlbedoThawA = 0.82 ## Python syntax
65146656

6657+
**Fractional Snow Cover**
6658+
6659+
The fractional snow covered area (frac_sno) affects surface energy balance
6660+
by weighting snow and bare ground contributions. The CLM formulation uses
6661+
a tanh-like relationship with snow depth and surface roughness.
6662+
6663+
*string* **Solver.CLM.FracSnoScheme** CLM Selects the fractional snow cover
6664+
calculation method. Currently only CLM is available; extensible for future
6665+
formulations.
6666+
6667+
**CLM**:
6668+
Standard formulation: frac_sno = snowdp / (10*roughness + snowdp)
6669+
6670+
.. container:: list
6671+
6672+
::
6673+
6674+
pfset Solver.CLM.FracSnoScheme "CLM" ## TCL syntax
6675+
<runname>.Solver.CLM.FracSnoScheme = "CLM" ## Python syntax
6676+
6677+
*double* **Solver.CLM.FracSnoRoughness** 0.01 Roughness length scale for
6678+
fractional snow cover calculation [m]. Default 0.01 m matches CLM's zlnd
6679+
parameter for backward compatibility. Larger values reduce snow cover
6680+
fraction for a given snow depth.
6681+
6682+
.. container:: list
6683+
6684+
::
6685+
6686+
pfset Solver.CLM.FracSnoRoughness 0.01 ## TCL syntax
6687+
<runname>.Solver.CLM.FracSnoRoughness = 0.01 ## Python syntax
6688+
65156689

65166690
.. _ParFlow NetCDF4 Parallel I/O:
65176691

docs/user_manual/refs.bib

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,16 @@ @article{Cui14
256256
doi = {10.1016/j.cageo.2014.05.005},
257257
}
258258
259+
@article{Dai2008,
260+
author = {Dai, A.},
261+
journal = {Geophysical Research Letters},
262+
pages = {L12802},
263+
title = {Temperature and pressure dependence of the rain-snow phase transition over land and ocean},
264+
volume = {35},
265+
year = {2008},
266+
doi = {10.1029/2008GL033295},
267+
}
268+
259269
@article{Dai03,
260270
author = {Dai, Y. and X. Zeng and R. E. Dickinson and I. Baker and G. B. Bonan and M. G. Bosilovich and A. S. Denning and P. A. Dirmeyer and P. R., G. Niu and K. W. Oleson and C. A. Schlosser and Z. L. Yang},
261271
journal = {The Bulletin of the American Meteorological Society},
@@ -277,6 +287,16 @@ @article{Danesh-Yazdi2018
277287
url = {https://doi.org/10.1002/hyp.11481},
278288
}
279289
290+
@article{Dang2019,
291+
author = {Dang, C. and Zender, C. S. and Flanner, M. G.},
292+
journal = {The Cryosphere},
293+
pages = {2325--2343},
294+
title = {Intercomparison and improvement of two-stream shortwave radiative transfer schemes in Earth system models for a unified treatment of cryospheric surfaces},
295+
volume = {13},
296+
year = {2019},
297+
doi = {10.5194/tc-13-2325-2019},
298+
}
299+
280300
@article{DMC10,
281301
author = {Daniels, M. H. and Maxwell, R. M. and Chow, F. K.},
282302
journal = {Journal of Hydrologic Engineering},
@@ -557,6 +577,16 @@ @article{Jefferson2017
557577
url = {https://doi.org/10.1175/jhm-d-16-0053.1},
558578
}
559579
580+
@article{Jennings2018,
581+
author = {Jennings, K. S. and Winchell, T. S. and Livneh, B. and Molotch, N. P.},
582+
journal = {Nature Communications},
583+
pages = {2831},
584+
title = {Spatial variation of the rain–snow temperature threshold across the Northern Hemisphere},
585+
volume = {9},
586+
year = {2018},
587+
doi = {10.1038/s41467-018-03629-7},
588+
}
589+
560590
@article{Jones-Woodward01,
561591
author = {Jones, J. E. and Woodward, C. S.},
562592
journal = {Advances in Water Resources},

0 commit comments

Comments
 (0)