# FreezeCurves

`FreezeCurves.AbstractSFCCObjective`

— Type`AbstractSFCCObjective`

Base type for non-linear SFCC optimization objectives.

`FreezeCurves.BrooksCorey`

— Type`BrooksCorey{Twp,Tψₛ,Tλ} <: SWRC`

van Genuchten MT, 1980. A closed-form equation for predicting the hydraulic conductivity of unsaturated soils. Soil Science Society of America Journal, 44(5): 892–898. DOI: 10.2136/sssaj 1980.03615995004400050002x.

`FreezeCurves.DallAmico`

— Type`DallAmico{TFT,Tg,Tswrc<:SWRC} <: SFCC`

Dall'Amico M, 2010. Coupled water and heat transfer in permafrost modeling. Ph.D. Thesis, University of Trento, pp. 43.

`FreezeCurves.DallAmicoSalt`

— Type`DallAmicoSalt{TFT,Tsc,TR,Tg,Tswrc<:SWRC} <: SFCC`

Freeze curve from Dall'Amico (2011) with saline freezing point depression.

Angelopoulos M, Westermann S, Overduin P, Faguet A, Olenchenko V, Grosse G, Grigoriev MN. Heat and salt flow in subsea permafrost modeled with CryoGRID2. Journal of Geophysical Research: Earth Surface. 2019 Apr;124(4):920-37.

`FreezeCurves.FreeWater`

— Type`FreeWater <: FreezeCurve`

"Free water" freeze curve in terms of enthalpy (H), total water content (θtot), and the latent heat of fusion of water (L).

`FreezeCurves.FreezeCurve`

— Type`FreezeCurve`

Base type for freezing characteristic curves which relate temperature or enthalpy to unfrozen water content.

`FreezeCurves.Hu2020`

— Type`Hu2020{TFT,Tvol,Tb} <: SFCC`

Soil freezing characteristic curve formulation of Hu et al. 2020.

Hu G, Zhao L, Zhu X, Wu X, Wu T, Li R, Xie C, Hao J. Review of algorithms and parameterizations to determine unfrozen water content in frozen soil. Geoderma. 2020 Jun 1;368:114277.

`FreezeCurves.LUT`

— Type`LUT{N,T,coordnames,TCoords,TData}`

Generic implementation of an N-dimensional lookup table with support for reverse lookups w.r.t one variable.

`FreezeCurves.Langer`

— Type`Langer{TFT,Tvol,Ta,Tb} <: SFCC`

Langer, M., Westermann, S., Muster, S., Piel, K., & Boike, J. (2011). The surface energy balance of a polygonal tundra site in northern Siberia – Part 2: Winter. The Cryosphere, 5(2), 509–524. https://doi.org/10.5194/tc-5-509-2011

`FreezeCurves.McKenzie`

— Type`McKenzie{TFT,Tvol,Tγ} <: SFCC`

McKenzie JM, Voss CI, Siegel DI, 2007. Groundwater flow with energy transport and water-ice phase change: numerical simulations, benchmarks, and application to freezing in peat bogs. Advances in Water Resources, 30(4): 966–983. DOI: 10.1016/j.advwatres.2006.08.008.

`FreezeCurves.PainterKarra`

— Type`PainterKarra{TFT,Tβ,Tω,Tg,Tswrc<:SWRC} <: SFCC`

Painter SL, Karra S. Constitutive Model for Unfrozen Water Content in Subfreezing Unsaturated Soils. Vadose zone j. 2014 Apr;13(4):1-8.

`FreezeCurves.PowerLaw`

— Type`PowerLaw{Tvol,Tα,Tβ} <: SFCC`

Commonly used power law relation of Lovell (1957).

Lovell, C.: Temperature effects on phase composition and strength of partially frozen soil, Highway Research Board Bulletin, 168, 74–95, 1957.

`FreezeCurves.SFCC`

— Type`SFCC <: FreezeCurve`

Base type for a soil freeze characteristic curve (SFCC) function. Subtypes should be callable structs that implement the freeze curve and contain any necessary additional constants or configuration options. User-specified parameters can either be supplied in the struct or declared as model parameters via the `variables`

method.

`FreezeCurves.SFCCInverseEnthalpyObjective`

— Type`SFCCInverseEnthalpyObjective{TF,Tkwargs<:NamedTuple,Thc,TL,TH,Tsat} <: AbstractSFCCObjective`

Optimization objective for finding a temperature, `T`

, wich resolves the conservation equation:

\[0 = (H - Lθ)/C - T\]

given a fixed enthalpy value `H`

and freeze curve arguments `f_args`

.

`FreezeCurves.SFCCNewtonSolver`

— Type`SFCCNewtonSolver <: SFCCSolver`

Fast, specialized implementation of Newton's method with backtracking line search for resolving the energy conservation law, H = TC + Lθ. Attempts to find the root of the corresponding temperature residual: ϵ = T - (H - Lθ(T)) / C(θ(T)) and uses backtracking to avoid jumping over the solution. This prevents convergence issues that arise due to discontinuities and strong non-linearity in most common soil freeze curves.

`FreezeCurves.SFCCPreSolver`

— Type`SFCCPreSolver{TCache} <: SFCCSolver`

A fast SFCC "solver" which pre-builds an interpolant for the freeze curve in terms of enthalpy, θ(H).

`FreezeCurves.SFCCPreSolverCache1D`

— Type`SFCCPreSolverCache1D{TF} <: AbstractPreSolverCache`

Efficient "presolver" implementation that builds a 1D interpolant for `θw(H)`

over an adaptive range of `H`

values determined based on local approximation error. Note that this presolver implementation is **only valid when all other freeze curve parameters are held constant** and will produce incorrect results otherwise.

`FreezeCurves.SFCCPreSolverCacheND`

— Type`SFCCPreSolverCacheND{N,TF} <: AbstractPreSolverCache`

More general "presolver" implementation that builds a ND lookup-table/interpolant for `θw(H, sat, args...)`

where `args`

is a set of all other freeze curve parameters passed to `initialize!`

. Note that this implementation currently does not perform any error control so there approximation error is not guaranteed.

`FreezeCurves.SFCCSolver`

— Type`SFCCSolver`

Base type representing non-linear solvers for implicit SFCC functions.

`FreezeCurves.SFCCTable`

— Type`SFCCTable{F,I} <: SFCC`

Pre-tabulated soil freezing characteristic curve. See `Tabulated`

and `tabulate`

.

`FreezeCurves.SWRC`

— Type`SWRC`

Base type for soil water retention curves (SWRC) which relate soil water matric potential to water content.

`FreezeCurves.SoilFreezeThawProperties`

— Type`SoilFreezeThawProperties{TTₘ,TLsl}`

Struct containing constants/parameters common to some or all SFCCs.

`FreezeCurves.SoilFreezeThawProperties`

— Method`SoilFreezeThawProperties(f::SFCC)`

Retrieves the default `SoilFreezeThawProperties`

from `f`

; should be defined for all freeze curves.

`FreezeCurves.SoilWaterVolume`

— Type`SoilWaterVolume{Tρw,Tθres,Tθsat}`

Struct containing basic physical constants and propeties related to soil pore water.

`FreezeCurves.SoilWaterVolume`

— Method`SoilWaterVolume(f::SFCC)`

Retrieves the nested `SoilWaterVolume`

from the `SoilFreezeThawProperties`

of the freeze curve `f`

.

`FreezeCurves.SoilWaterVolume`

— Method`SoilWaterVolume(f::SWRC)`

Get the `SoilWaterVolume`

defined for the given `SWRC`

`f`

. Must be implemented for all `SWRC`

types. Default implementation retrieves the field `water`

.

`FreezeCurves.VanGenuchten`

— Type`VanGenuchten{Tvol,Tα,Tn} <: SWRC`

van Genuchten MT, 1980. A closed-form equation for predicting the hydraulic conductivity of unsaturated soils. Soil Science Society of America Journal, 44(5): 892–898. DOI: 10.2136/sssaj 1980.03615995004400050002x.

`FreezeCurves.Westermann`

— Type`Westermann{TFT,Tvol,Tδ} <: SFCC`

Westermann, S., Boike, J., Langer, M., Schuler, T. V., and Etzelmüller, B.: Modeling the impact of wintertime rain events on the thermal regime of permafrost, The Cryosphere, 5, 945–959, https://doi.org/10.5194/tc-5-945-2011, 2011.

`Base.inv`

— Method`Base.inv(f::SWRC)`

Returns a function `(args...) -> f(inv, args...)`

which, when implemented, evaluates the inverse of the soil water retention curve.

`FreezeCurves.Tabulated`

— Method`Tabulated(f; kwargs...)`

Alias for `tabulate`

intended for function types.

`FreezeCurves.Tabulated`

— Method`Tabulated(f::SFCC, args...)`

Produces an `SFCCTable`

function which is a tabulation of `f`

.

`FreezeCurves.adstrip`

— Methodadstrip(x::Number) adstrip(x::ForwardDiff.Dual)

adstrip extracts the underlying numeric value from `x`

if `x`

is a `ForwardDiff.Dual`

number. If `x`

is a non-tracked numeric type, then `adstrip`

simply returns `x`

.

`FreezeCurves.build_lut`

— Method`build_lut(f, coords::Pair{Symbol,<:Union{Number,AbstractVector}}...; f_kwargs...)`

Builds an n-dimensional lookup table `LUT`

by invoking `f`

on the given `coords`

. `f`

should be a function which accepts keyword arguments matching `coords`

as well as any additional constant keyword arguments `f_kwargs`

.

Example:

```
f(; x=1.0, y=1.0) = x + y
lut = build_lut(f, :x => -10.0:10.0, :y=-10.0:10.0)
lut(; x=2.2, y=1.5)
# output
3.7
```

`FreezeCurves.dual`

— Method```
dual(x::Number, ::Type{tag}) where {tag}
dual(x::A, ::Type{tag}) where {N,T,A<:SVector{N,T},tag}
```

Constructs a `ForwardDiff.Dual`

number (or static array thereof) with `tag`

from `x`

.

`FreezeCurves.enthalpy`

— Method`enthalpy(T, C, L, θw)`

Computes the volumetric enthalpy [J/m^3] given T, C, L, θw.

`FreezeCurves.heatcapacity`

— Method`heatcapacity(c_frozen::Number, c_thawed::Number; θtot=1.0)`

Piecewise constant heat capacity function:

\[f(θw,θtot,θsat) = \begin{cases} c_f & θw < θtot \\ c_t & \text{otherwise} \end{cases}\]

`FreezeCurves.heatcapacity`

— Method`heatcapacity(c::Number)`

Heat capacity function `f(θw,θtot,θsat) = c`

where `c`

is a pre-specified constant.

`FreezeCurves.heaviside`

— Method`heaviside(x)`

Differentiable implementation of heaviside step function, i.e:

$h(x) = \begin{cases} 1 & x ≥ 0 \\ 0 & x < 0 \end{cases}$

`FreezeCurves.inflectionpoint`

— Method`inflectionpoint(f::SFCC)`

Returns the analytical inflection point (i.e. where ∂²θ/∂T^2 = 0), if available.

`FreezeCurves.inflectionpoint`

— Method`inflectionpoint(f::SWRC)`

Returns the analytical solution for the inflection point (i.e. where ∂²θ/∂ψ² = 0) of the SWRC, if available.

`FreezeCurves.initialize!`

— Method`initialize!(solver::SFCCSolver, fc::SFCC, hc; fc_kwargs...)`

Initializes `solver`

(if necessary) for the freeze curve function `fc`

with arguments `fc_kwargs`

and heat capacity function `hc`

. Default implementation does nothing.

`FreezeCurves.initialize!`

— Method`initialize!(solver::SFCCPreSolver{<:SFCCPreSolverCache1D}, fc::SFCC, hc::F; fc_kwargs...)`

Initializes this `SFCCPreSolver`

by building interpolants for `fc`

and its derivatives. `θtot`

and `θsat`

are assumed fixed. `hc`

must be heat capacity as a function of liquid water content.

`FreezeCurves.normalize_temperature`

— Method```
normalize_temperature(x)
normalize_temperature(x::TemperatureQuantity)
```

Converts temperature `x`

to Kelvin. If `x`

has units, `uconvert`

is used. Otherwise, if `x`

a general numeric type, does a heuristic check `x <= 200`

and assumes the given temperature is in celsius if the condition is satisfied.

`FreezeCurves.sfccsolve`

— Method`sfccsolve(obj::AbstractSFCCObjective, solver::SFCCSolver, x₀, ::Val{return_all}=Val{true}()) where {return_all}`

Solve the given objective `obj`

using `solver`

and initial guess `x₀`

. If `return_all=true`

, then `sfccsolve`

should return a named tuple with at least the temperature solution `T`

, the liquid water content `θw`

, the heat capacity `C`

, and the liquid water content deriviative `∂θw∂T`

defined. Solver-specific additional values may also be included.

`FreezeCurves.sfccsolve`

— Method`sfccsolve(obj::SFCCInverseEnthalpyObjective, solver::SFCCNewtonSolver, T₀::Number, ::Val{return_all}=Val{true}(); error_when_not_converged=true)`

Solves `obj`

using the specialized Newton `solver`

and returns the result. If `return_all`

is `true`

, a named tuple `(;T, Tres, θw, C, itercount)`

is returned; otherwise (by default), only the temperature solution is returned.

`FreezeCurves.swrc`

— Method`swrc(::SFCC)`

Retrieves the `SWRC`

embedded within this `SFCC`

, if defined. The default value for freeze curve functions without an associated soil-water retention curve is `nothing`

.

`FreezeCurves.tabulate`

— Method`tabulate(f; kwargs...)`

Tabulates the given function `f`

using a linear, multi-dimensional interpolant. Knots should be given as keyword arguments `arg = A`

where `A`

is a `StepRange`

or `Vector`

of input values (knots) at which to evaluate the function. `A`

may also be a `Number`

, in which case a pseudo-point interpolant will be used (i.e valid on `[A,A+ϵ]`

). Note that all arguments to `f`

must be accepted as keyword arguments.

`FreezeCurves.temperature_residual`

— Method`temperature_residual(f::F, hc, L, H, T, sat; θsat=SoilWaterVolume(f).θsat, f_kwargs...) where {F<:SFCC}`

Helper function for updating θw, C, and the residual. `hc`

should be a function `(θw,θtot,θsat) -> C`

which computes the heat capacity from the unfrozen, total, and maximum (saturated) water contents respectively.

`FreezeCurves.waterpotential`

— Method`waterpotential(f::SWRC, θ; θsat=f.vol.θsat, θres=f.vol.θres, kwargs...)`

Returns the water potential at volumetric water content `θ`

by evaluating the inverse of `f`

.

`RecipesBase.apply_recipe`

— Method`plot(T, fc::SFCC)`

Simple plotting recipe for `SFCC`

which takes care of stripping units.

`RecipesBase.apply_recipe`

— Method`plot(Ts, fc::SFCC)`

Simple plotting recipe for `SWRC`

which takes care of stripping units.

`Unitful.ustrip`

— Method`ustrip(x)`

Reconstructs the type or function `x`

with all numerical quantities stripped of units. All units are first converted to preferred SI units before being stripped.