hystfit

Fit soil water retention function with hysteresis

View the Project on GitHub or PyPI

Instruction of hystfit

To begin, install Python 3 along with the hystfit library. For installing on Debian system, APT repository is available.

Once installed, create a fitting object f from the hystfit.Fit class, which is a subclass of the unsatfit.Fit class. For more detailed information, refer to the unsatfit documentation.

import math
import numpy as np
import hystfit
f = hystfit.Fit()

Main drying curve

The main drying curve can be modeled using either the van Genuchten (VG) or the Fredlund and Xing (FX) model. Once a model is chosen, parameters can be set in two ways:

(1) Provide given parameters:

(2) Optimize parameters from measured data (h, θ):

As hystfit.Fit is a subclass of unsatfit.Fit, all methods from unsatfit are available in f. You can obtain fitting parameters for the main drying curve using unsatfit methods such as get_init_vg and get_wrf_vg. Note that for the VG function, parameter m should be converted to n=1/(1-m).

Set the water retention data (h, θ) for the main drying curve in f.swrc as described in the unsatfit documentation. After that, to obtain and set VG parameters:

qs, qr, a, m, q = f.get_wrf_vg()
n = 1 / (1 - m)
f.set_vg(qs, qr, a, n)

To obtain and set FX parameters:

f.set_fx(*f.get_wrf_fx())

If θr is equal to 0, you can use the init_hyst method. For instance, for the VG model:

f.model_name = 'VG'
f.init_hyst()
print(f.message)

To use the FX model, simply set f.model_name = 'FX'.

Hysteresis parameters

The hysteresis behavior in soil is determined by the advancing contact angle (γA) and the parameter b. These parameters are collectively set in a single tuple p, defined as p=(cos γA, b). For instance, to set γA = 75° and b = 0.24:

p = (math.cos(math.radians(75)), 0.24)

Please note that in Zhou (2013), the contact angle is denoted by θ; however, we use γ instead to avoid confusion with volumetric water content. A detailed description of Zhou’s model is omitted here; please refer to Zhou’s paper for more information.

The receding contact angle γr is fixed at 0°, and its cosine value is initially set to f.cos_gr = 1. This value remains unchanged unless manually altered by the user.

Predicting change in h from change in θ

The change in h can be predicted from changes in θ using the h method as shown below:

h = f.h(p, theta)

Where:

By default, the initial contact angle γ0 is set at 0°, meaning f.cos_g0 = 1. Since it is the same as the default γR, it indicates that the initial (h,θ) data point is on the main drying curve. After executing the h method, γ0 is updated to the last state, enabling the reproduction of the hysteresis behavior through repeated usage of the h method. γ0 is reset to 0° when set_vg or set_fx methods are called.

To set γ0 to a specific state of (h, θ):

f.cos_g0 = f.contact(h_ini, theta_ini)

Here, h_ini and theta_ini represent the initial values of h and θ, respectively.

Optimizing hysteresis parameters from changes in (h, θ)

To optimize hysteresis parameters based on changes in (h, θ)—for instance, from the main wetting curve—use the opt method. Ensure that each (h, θ) dataset adheres to the data structure conventions of unsatfit, and that the order of the data reflects the sequence of time events. The optimization can be performed with the following code:

f.opt(h, theta)
p = f.hyst
print(f'{f.message} R2 = {f.r2:.3}')

This code obtains the hysteresis parameter p=(cos γA, b) and outputs the result. In the optimization, the residual of ln(h) is used as the cost function. Note that the contact angle γ0 is set at the initial state before optimization and updated to its last state after this operation.