calculate_soil_water() — Calculation of soil water balance


 from swb import calculate_soil_water

 results = calculate_soil_water(

See the reference section below for what all this means.



This module provides the calculate_soil_water() function, which calculates soil water content.

The soil is, so to speak, full of water when it is at field capacity and empty when it is at wilting point.

The field capacity is below saturation point. When the soil is saturated, any excess water runs off immediately; when it is between field capacity and saturation, the soil drains downward, usually in 2-3 days; when the soil is at or below field capacity, water is lost only through evapotranspiration. The field capacity is roughly the amount of water that the soil can keep indefinitely without percolation. It is a property of the soil.

The wilting point (also called “permanent wilting point”) is the amount of water needed for plants to not wilt. It is a property of the soil.

We are interested only in the topmost part of the soil, which is called the root zone. It is the part of the soil that contains plant roots. The depth of the root zone is a property of the crop.

The depletion (more precisely the “root zone depletion”) is the amount of water missing from the soil (more precisely the root zone). When the soil is “full” (at field capacity) the depletion is zero. When it is “half-empty”, the depletion is the amount of water that would be needed to “fill it up”; that is, the amount of water that is needed to reach field capacity. The depletion is normally measured in mm.

This is the relation between depletion Dr and water content θ:

Dr = (θfc - θ) Zr

(FAO56, p. 170 eq. 87)


  • θ is the water content. It is a proper number (m3/m3).
  • θfc is the water content at field capacity.
  • Zr is the root zone depth.

Often Zr is in meters and depletion in mm, so the equation becomes

Dr = (θfc - θ) × Zr × 1000

(In the rest of this text, we call 1000 the “root depth factor” or zr_factor).

As we said, the soil is “full” at field capacity and “empty” at wilting point. The difference between these two is the total available water or TAW. In other words, if the soil was a reservoir, the TAW would be its capacity. The TAW is normally measured in mm.

TAW = (θfc - θwp) × Zr × zr_factor

(FAO56, p. 162 eq. 82)

Since saturation is above field capacity, the soil can be “overfull”, so to speak, in which case depletion is negative. The drain time is the time the soil needs to go from saturation (θs) to field capacity (θfc) solely because of downward movement (percolation) (i.e. if evapotranspiration is zero).

Although plants can theoretically survive whenever the water content is above wilting point, there’s a threshold below which they are stressed. This is different from crop to crop. The difference between field capacity and this threshold is the readily available water:


(FAO56, p. 162 eq. 83)

The factor p, called “soil water depletion fraction for no stress”, is a property of the crop.

When the water content is above the threshold (Dr < RAW), the crop evapotranspiration is Kc × ET0, where ET0 the reference evapotranspiration and Kc the crop coefficient. When the water content is below the threshold (Dr > RAW), the crop is stressed and decreases the amount of evapotranspiration to Ks × Kc × ET0 where Ks is the water stress coefficient:

Ks = (TAW - Dr) / (TAW - RAW) = (TAW - Dr) / ((1-p) TAW)

(FAO56, p. 169 eq. 84)

When the water content reaches the threshold (i.e. when Dr reaches RAW), we need to irrigate. Normally the amount of water we irrigate with is RAW. But sometimes we prefer to throw in a fraction of that amount. This will result in more frequent irrigations thereafter and is beneficial in some cases. TEIEP (2014, p. 92) confusingly calls this fraction the “irrigation optimizer”, but we are going to call it the malamos irrigation fraction or mif.

Calculation of depletion

The basis for the calculation is this formula:

Dr,i = Dr,i-1 - (Pi - ROi) - IRn,i - CRi + ETc,i + DPi

(FAO56, p. 170 eq. 85)


  • i is the current time period (i.e. the current day).
  • Dr,i is the root zone depletion at the end of time period i.
  • Pi is the effective precipitation (see below).
  • ROi is the runoff (see below).
  • IRn,i is the net irrigation depth (see below).
  • CRi is the capillary rise.
  • ETc,i is the crop evapotranspiration.
  • DPi is the water loss through deep percolation.

subject to this constraint:

Dr,i ≤ TAW

(FAO56, p. 170 eq. 86. That equation also has the constraint Dr,i ≥ 0; however we allow Dr,i to have negative values, because water content can actually exceed field capacity and reach saturation.)

CRi is ignored and considered zero.

The evapotranspiration ETc,i is the reference evapotranspiration multiplied by the crop coefficient Kc.

The runoff is the amount of water that exceeds saturation after heavy rainfall:

ROi = Pi + (θi-1 - θs) Zr when larger than zero

(Malamos et al., 2016, eq. 5)

The effective precipitation is the precipitation that actually falls on the soil. It is essentially the total precipitation minus the amount that is held by the leaves. swb does not contain any model that converts total precipitation to effective precipitation; you need to make this conversion and call calculate_soil_water() with the effective precipitation. (A trivial model that you can use is multiply total precipitation by a factor, peff, usually 0.8; it’s quite crude, but it’s better than nothing.)

The net irrigation depth is the amount of water that reaches the soil during irrigation. It is the total amount of water consumed for irrigation minus losses. swb does not convert between total and net irrigation; it accepts net irrigation as input (and includes net irrigation in its output).

The deep percolation is zero if we are at or below field capacity. If we are above field capacity (θfc < θ < θs) it is this:

DPi = (θ - θfc) * Zr / draintime

If θ > θs (which technically can’t happen, but θ can have this value as calculated in the previous step, notably if there has been too much irrigation) then θs is used instead of θ in the above equation.



Calculates soil water balance. Example:

results = calculate_soil_water(
  • theta_s (float) – Water content at saturation.
  • theta_fc (float) – Water content at field capacity.
  • theta_wp (float) – Water content at wilting point.
  • zr (float) – The root depth.
  • zr_factor (float) – If the root depth is in a different unit than the water depth variables (such as evapotranspiration, precipitation, irrigation and depletion) zr_factor is used to convert it. If the root depth is in metres and the water depth variables are in mm, specify zr_factor=1000.
  • p (float) – The soil water depletion fraction for no stress.
  • draintime (float) – The time, in days, needed for the soil to drain from saturation to field capacity.
  • timeseries (dataframe) –

    A pandas dataframe indexed by date, containing two or three columns with input time series. The dataframe and its time series must be continuous and have no missing values. The columns are “crop_evapotranspiration”, “effective_precipitation” and “actual_net_irrigation”. All time series should be in mm; more precisely, in the same unit as the resulting depletion.

    The “crop_evapotranspiration” is the potential crop evapotranspiration (that is, the reference evapotranspiration multiplied by the crop coefficient Kc).

    The “actual_net_irrigation” is the applied net irrigation (that is, the total applied irrigation multiplied by the irrigation efficiency).

    If in a day it is known that we irrigated but not how much, “applied_net_irrigation” may simply be the boolean True for that day. In this case, it is assumed that we irrigated with the recommended amount that was calculated by the model.

  • theta_init (float) – The initial water content (that is, the water content at the first date of the time series).
  • mif (float) – The Malamos irrigation fraction.
Return type:



A dictionary with the results. It contains the following items:

raw:The readily available water.
taw:The total available water.
timeseries:The original dataframe with additional columns added, namely dr for depletion, theta for soil moisture, ks for the water stress coefficient, and recommended_net_irrigation for the calculated recommended net irrigation. The original dataframe is changed in place (so the caller doesn’t really need it returned), but the original columns and index are untouched.


R. G. Allen, L. S. Pereira, D. Raes, and M. Smith, Crop evapotranspiration - Guidelines for computing crop water requirements, FAO Irrigation and drainage paper no. 56, 1998.

N. Malamos, I. L. Tsirogiannis, and A. Christofides, Modelling irrigation management services: the IRMA_SYS case, International Journal of Sustainable Agricultural Management and Informatics, 2 (1), 1–18, 2016.

TEIEP (Technological Educational Institute of Epirus), Deliverable 5.3.1: Detailed plan regarding the information system setup, for project Development of an Irrigation Information System for the plain of Arta (IRMA_SYS Arta), 2014. Available at