SMAP
The Soil Moisture Accounting Procedure (SMAP) is a rainfall-runoff model that simulates the transformation of precipitation into runoff based on conceptual reservoirs representing different states. The formulation follows Lopes (1982).
The MOGESTpy implementation of SMAP includes two versions: a daily timestep version and a monthly timestep version. Both versions are designed to be flexible and can be calibrated to fit observed data for specific catchments.
Daily timestep
The Daily version of SMAP consists of 3 conceptual reservoirs: surface, soil and subsurface. This version can be accessed through the mogestpy.quantity.hydrological.smap.SmapD class.
Daily SMAP Schematic
Mathematical formulation
Mathematical Reservoirs
The daily SMAP model uses three conceptual reservoirs to simulate the hydrological cycle. The water balance equations for each reservoir are:
Where:
\(R_{solo}\) = soil reservoir (aerated zone) (mm)
\(R_{sup}\) = surface reservoir (mm)
\(R_{sub}\) = subsurface reservoir (saturated zone) (mm)
\(P\) = precipitation (mm)
\(Es\) = surface runoff (mm)
\(Ed\) = direct runoff (mm)
\(Er\) = actual evapotranspiration (mm)
\(Rec\) = groundwater recharge (mm)
\(Eb\) = baseflow (mm)
Initialization
The initial conditions for the three reservoirs are set as follows:
Where:
\(Tuin\) = initial soil moisture content (-)
\(Str\) = soil saturation capacity (mm)
\(Ebin\) = initial baseflow discharge (m³/s)
\(Ad\) = drainage area (km²)
\(Kk = 0.5^{(1/kkt)}\) = baseflow recession factor
Transfer Functions
The model uses six transfer functions to compute the fluxes between reservoirs. The surface runoff separation follows the SCS (Soil Conservation Service) method.
1. Surface runoff (Es):
2. Actual evapotranspiration (Er):
3. Groundwater recharge (Rec):
4. Direct runoff (Ed):
5. Baseflow (Eb):
6. Soil moisture (Tu):
Where:
\(P\) = precipitation (mm)
\(Ai\) = initial abstraction (mm)
\(Ep\) = potential evapotranspiration (mm)
\(Crec\) = recharge coefficient (%)
\(Capc\) = field capacity (%)
\(K2 = 0.5^{(1/k2t)}\) = surface runoff recession factor
\(Kk = 0.5^{(1/kkt)}\) = baseflow recession factor
Discharge Calculation
Any overflow from the soil reservoir is converted to surface runoff. The total discharge at the basin outlet is calculated as:
Where:
\(Q\) = discharge (m³/s)
\(Ed\) = direct runoff (mm)
\(Eb\) = baseflow (mm)
\(Ad\) = drainage area (km²)
86.4 is the unit conversion factor (mm·km²/s to m³/s)
The SmapD parameters are described in the table below.
Parameter |
Description |
Range |
Default |
Unit |
|---|---|---|---|---|
Str |
Soil saturation. |
100 - 2000 |
100 |
\(\text{mm}\) |
Crec |
Recession coefficient. |
0 - 20 |
0.0 |
\(\%\) |
Capc |
Field capacity. |
30 - 50 |
40 |
\(\%\) |
kkt |
Base flow recession coefficient. |
30 - 180 |
30 |
\({\text{d}^{-1}}\) |
k2t |
Surface runoff recession coefficient. |
0.2 - 10 |
0.2 |
\({\text{d}^{-1}}\) |
Ad |
Drainage area. |
\(-\) |
1.0 |
\(\text{km}{^2}\) |
Tuin |
Initial soil moisture content. |
0 - 1 |
0.0 |
\(-\) |
Ebin |
Initial base flow. |
\(-\) |
0.0 |
\(\text{m}^3\text{/s}\) |
Ai |
Initial abstraction. |
2 - 5 |
2.5 |
\(\text{mm}\) |
Examples
To use the daily version of SMAP, you can create an instance of the SmapD class and provide the necessary parameters. Here is an example of how to set up and run a simulation using the daily version of SMAP.
from mogestpy.quantity.hydrological.smap import SmapD
model = SmapD(
Str=100,
Crec=19.6125,
Capc=30,
kkt=47.53,
k2t=1.430,
Ai=2,
Tuin=.05,
Ebin=0.1,
Ad=70.2
)
precipitations = [10, 20, 15, 5, 0] # Example precipitation data
evapotranspirations = [2, 3, 1, 0.5, 0] # Example evapotranspiration data
discharges = model.run_to_list(precipitations, evapotranspirations)
The daily model can be calibrated against observed discharge data with the
calibrate method.
from mogestpy.quantity.hydrological.smap import SmapD
model = SmapD() # Initialize with default parameters
result = model.calibrate(
prec_arr=precipitations, # as list/np.array/pd.Series
etp_arr=evapotranspirations, # as list/np.array/pd.Series
eval_arr=observed_discharge, # as list/np.array/pd.Series
variables=["Str", "Crec", "Capc", "kkt", "k2t", "Ai"],
disp=True,
)
print(result.x)
print(result.fun)
By default the calibration uses the Kling-Gupta Efficiency (KGE) as the objective function, but other metrics can be used by specifying the obj_func argument in the calibrate method.
Monthly timestep
The Monthly version of SMAP consists of 2 conceptual reservoirs: soil and subsurface and can be access through the mogestpy.quantity.hydrological.smap.SmapM class. This version is designed for applications where monthly data is more appropriate or available, and it simplifies the model structure while still capturing the essential hydrological processes.
Monthly SMAP Schematic
The monthly SMAP parameters are described in the table below.
Parameter |
Description |
Range |
Default |
Unit |
|---|---|---|---|---|
Str |
Soil saturation. |
400 to 5000 |
1000 |
mm |
Pes |
Exponent for soil evaporation. |
1 to 10 |
1 |
Dimensionless |
Crec |
Recharge coefficient. |
0 to 1 |
0.5 |
Dimensionless |
kkt |
Base flow recession coefficient. |
1 to 6 |
1.5 |
months |
Tuin |
Initial soil moisture content. |
0 to 1 |
0.5 |
Fraction |
Ebin |
Initial base flow. |
No explicit bound |
0.1 |
m^3/s |
Ad |
Drainage area. |
No explicit bound |
1.0 |
km^2 |
Examples
Similarly, to use the monthly version of SMAP, you can create an instance of the SmapM class and provide the necessary parameters. Here is an example of how to set up and run a simulation using the monthly version of SMAP.
from mogestpy.quantity.hydrological.smap import SmapM
model = SmapM(
Str=1000,
Pes=1,
Crec=0.5,
kkt=1.5,
Tuin=0.5,
Ebin=0.1,
Ad=1,
)
precipitations = [100, 200, 150, 50, 0] # Example precipitation data
evapotranspirations = [20, 30, 10, 5, 0] # Example evapotranspiration data
discharges = model.run_to_list(precipitations, evapotranspirations)
The monthly model uses the same calibrate method.
from mogestpy.quantity.hydrological.smap import SmapM
model = SmapM()
result = model.calibrate(
prec_arr=precipitations, # as list/np.array/pd.Series
etp_arr=evapotranspirations, # as list/np.array/pd.Series
eval_arr=observed_discharge, # as list/np.array/pd.Series
variables=["Str", "Pes", "Crec", "kkt"],
disp=True,
)
print(result.x)
print(result.fun)