Skip to content

How the model works (water-balance technical reference)

This page explains what the DSS is actually computing: how water is routed in space, how supply and demand are reconciled per sub-watershed per month, and what each number on the dashboard physically means.

The Flask app does none of this at request time. All hydrological computation happens offline in app/data_prep/prepare_hydrosheds.py, which converts the GeoPackages and Excel from the modelling team into the CSVs and GeoJSONs that the dashboard reads. The app just slices and aggregates those pre-computed tables.


1. The spatial unit: sub-watersheds

The modelled area is partitioned into small drainage cells, one per sub-watershed (1,847 across the 110 modelled WRUAs). Each cell:

  • Is derived from a 30 m SRTM-based DEM via flow accumulation.
  • Has a stable band_id (the sub-watershed polygon identifier).
  • Belongs to exactly one parent WRUA. Water never crosses a WRUA boundary (Rule 1).
  • Has a mean elevation, a polygon area, and an adjacency list (which cells share an edge).
  • The modelled deployment uses a 10000-pixel flow-accumulation threshold (~9 km² per cell, 1847 cells across the 110 modelled WRUAs).

See Modelling unit for per-polygon attribute details.


2. The monthly water balance per sub-watershed

For each sub-watershed i and each month m the model computes a balance:

available(i, m)  = runoff_local(i, m) + inflow_from_upstream(i, m)
demand(i, m)     = CWR(i, m)                          # crop water requirement
gross_deficit    = max(0, demand - available)
surplus          = max(0, available - demand)

The five years of input data (2019 to 2023) are aggregated into a single 12-month climatology that the dashboard plots. The 48-month time series used by the SAT pond simulation preserves the original monthly sequence.

Where each term comes from

Term Source Resolution
runoff_local Model-derived (basin hydrological model), summarized monthly Subbasin, climatology
CWR (crop water requirement) FAO-56 Kc × WaPOR evapotranspiration over cropland 100 m, 2019 to 2023
Cropland mask WaPOR land-cover 100 m
Precipitation CHIRPS 5 km, 2019 to 2023

The gross deficit is the demand the irrigation system has to deliver. The net deficit is what crops actually need at the field gate, before factoring in irrigation losses.

Gross vs net deficit (irrigation efficiency)

The model uses two efficiencies (constant across the basin):

  • Conveyance efficiency Ec = 0.85 (water lost between source and field)
  • Application efficiency Ea = 0.70 (water lost during application to the crop)
  • Overall efficiency E = Ec * Ea = 0.595

So:

vol_deficit_gross_Mm3 = vol_deficit_net_Mm3 / E
                      = vol_deficit_net_Mm3 / 0.595

A 1 Mm³ net crop deficit needs ~1.68 Mm³ of gross water to actually deliver. The map's color ramp keys on total_deficit_Mm3 which is the gross value.


3. Scenario 1: Reallocation (gravity transfer)

Reallocation scenario illustration

Reallocation tries to move surplus water from upstream sub-watersheds to downstream ones using gravity only, with no new infrastructure. The algorithm walks each WRUA top-down by elevation and for every surplus cell decides where its surplus goes.

Routing rules (in priority order)

  1. Stay within the same WRUA. Water never crosses a WRUA boundary, even if a neighbour has surplus to share.
  2. Local reallocation only on slope < 3%. If the donor's mean slope is steeper than 3% (percent grade, not degrees), no local reallocation is attempted; deficit stays accounted for at source.
  3. Flow downhill to adjacent watersheds. Candidate receivers must share a polygon edge with the donor AND lie at lower mean elevation. Uphill transfer is disallowed.
  4. Lowest-friction path. Among eligible downhill neighbours, pick the one with the lowest cumulative friction along the connecting flow path (per-pixel landcover and slope cost surface).
  5. Tie-break by greatest elevation drop. When two candidates tie on friction, the steeper drop wins.

After routing, each sub-watershed has:

inflow_surplus_Mm3        # surplus received from upstream
total_available_Mm3       # = local available + inflow_surplus
deficit_met_gross_Mm3     # how much of gross deficit was closed by transfers
unmet_deficit_gross_Mm3   # residual gross deficit
surplus_transferred_down  # surplus passed further downstream

Across the modelled WRUAs most have small total surplus, so reallocation alone typically closes only single-digit % of the deficit. Reallocation is the cheapest scenario but rarely sufficient.


4. Scenario 2: Storage (SAT farm ponds)

Storage / SAT scenario illustration

SAT = Storage Attenuation Technology. Each pond is a fixed 1000 m³ tank that captures wet-season runoff and releases it during dry-season irrigation.

Pond count per sub-watershed

NP_needed = ceil( max_monthly_deficit_m3 / 1000  *  1.1 )

The 1.1 multiplier is a design factor (over-provision so a pond drained early in the dry season still has buffer). NP_needed is the unconstrained count assuming the basin can absorb all the runoff capture.

Environmental check (the 20% rule)

If every needed pond were built, the basin might capture so much runoff that downstream flows collapse. To prevent this, the model simulates 48 months of pond operation and checks the basin-annual retained fraction:

basin_annual_retained_frac =
   sum(R_captured over all ponds, all months over a year)
   / sum(natural_runoff over the whole basin, same year)

If this fraction exceeds 0.20 (20%), pond counts are scaled down per sub-watershed until the basin-annual cap holds. The resulting count is NP_built. The dashboard always shows both:

  • NP_needed (unconstrained, what the deficit asks for)
  • NP_built (constrained, what passes the 20% environmental check)

The 48-month simulation

For each sub-watershed and each of 48 months the pipeline writes:

Field Meaning
H Pond water level at month end (fraction of pond capacity)
R Runoff inflow into ponds that month
overflow Spillover when ponds reached capacity
balance Net balance (R, ET losses, irrigation withdrawals)
Deficit Residual unmet demand that month, even with ponds operating
retainedfrac Per-watershed annual retained share, recomputed monthly

/api/simulation/<wrua>?scenario=sat returns the timeseries for any WRUA (optionally filtered to a single band_id). The dashboard does not yet plot it, but the data is there.


5. Scenario 3: Combined

Combined scenario illustration

Combined runs reallocation first, then builds ponds only for the residual unmet deficit:

combined_deficit_to_pond = unmet_deficit_after_reallocation
NP_combined = ceil( combined_deficit_to_pond / 1000  *  1.1 )

Typically Combined uses ~40% fewer ponds than pure SAT for the same deficit coverage, because gravity has already done the easy work.


6. What each dashboard chart actually shows

Chart Underlying quantity Aggregation
Map polygon color total_deficit_Mm3 per sub-watershed (annual gross deficit) Single sub-watershed
Monthly Water Balance (right panel bars) vol_surplus_Mm3 (green, up) and vol_deficit_gross_Mm3 (orange, down) Summed across all sub-watersheds in the selected WRUA (or all modelled WRUAs in basin mode)
Deficit Intensity heatmap vol_deficit_gross_Mm3 per (sub-watershed, month) Top 10 sub-watersheds in the WRUA by peak monthly deficit
Recommended Interventions max_deficit_m3 (single-month peak in m³, not Mm³) and NP_needed, NP_built Top 15 sub-watersheds by max_deficit_m3
Comparison view bars Annual total_deficit, deficit_met, unmet, ponds, % addressed Per scenario, per WRUA

7. Constants and assumptions

Constant Value Source
Pond volume 1,000 m³ Reviewer convention; matches typical farm-pond size in Kenya
Pond design factor 1.1× Empirical over-provision
Conveyance efficiency Ec 0.85 Pipeline transmission
Application efficiency Ea 0.70 Surface irrigation
Overall efficiency E 0.595 Ec × Ea
Basin-annual retained-fraction cap 0.20 Environmental flow protection
Local reallocation slope cap 3% Reviewer rule
Years aggregated 2019 to 2023 (5y) Input data window
Simulation length 48 months Reviewer convention

8. What the model does not do

  • It does not route water across WRUA boundaries, even when one WRUA has surplus and a neighbour has deficit. This is a policy choice baked into the rules.
  • It does not account for groundwater. All transfers are surface.
  • It does not model crop choice. CWR is taken as observed from WaPOR ET; the question "what if farmers grew a less thirsty crop?" is out of scope.
  • It does not dynamically recompute as you change scenarios in the UI. Every scenario's outputs are pre-computed offline and stored as static CSV.

9. Where to look in the code

Concern File
Data pipeline (Excel and GPKG → CSV and GeoJSON) app/data_prep/prepare_hydrosheds.py
Authoritative routing rules Reallocation rules
Flask aggregation endpoints app/app.py
Per-WRUA data on disk app/data/reallocation.csv, sat_bands.csv, combined_bands.csv, simulation_*.csv
GeoJSON polygons app/data/elevation_bands.geojson (sub-watershed polygons)