ABCD

Implementation

Thomas (1981) ABCD monthly equations; native rationalized root; explicit zero initial stores

  • Time step: monthly

  • Backend: installed Python dependencies

  • Calibrated parameters: 4

  • Temperature required: no

Inspect the exact implementation.

Parameters and initial configuration

Parameter

Supported calibration range

Default

a

0.001 to 1

0.95

b

1 to 2000

250.0

c

0 to 1

0.5

d

0.001 to 1

0.1

soil0

Fixed initial/configuration value

0.0

groundwater0

Fixed initial/configuration value

0.0

Ranges/defaults are implementation contracts, not universal priors or a recommended basin calibration. Consult source comments for parameter units and coupling.

Governing equations

The following source is the exact model kernel used by this adapter. For MARRMoT it includes the state derivative and each referenced flux function; the solver and routing are described above. Original notices and source citations are retained in the files.

"""Native ABCD equations (Thomas 1981), with explicit monthly accounting.

Equations independently implemented from the cited mathematical description;
not copied from a repository without a redistribution license.
"""
import numpy as np
from numba import njit


@njit(cache=True)
def abcd_components(precipitation, pet, a, b, c, d, soil0=0.0, groundwater0=0.0):
    n = len(precipitation)
    q = np.empty(n)
    aet = np.empty(n)
    soil_series = np.empty(n)
    groundwater_series = np.empty(n)
    soil, groundwater = soil0, groundwater0
    for i in range(n):
        available = soil + precipitation[i]
        # Algebraically rationalized root avoids cancellation at a tiny a.
        discriminant = max(0.0, (available + b)**2 - 4*a*b*available)
        y = 2*b*available / (available + b + np.sqrt(discriminant))
        soil = y * np.exp(-pet[i] / b)
        aet[i] = y - soil
        surplus = max(0.0, available - y)
        groundwater = (groundwater + c*surplus) / (1+d)
        q[i] = (1-c)*surplus + d*groundwater
        soil_series[i] = soil
        groundwater_series[i] = groundwater
    return q, aet, soil_series, groundwater_series


def _abcd(basin, parameters):
    return abcd_components(basin.precipitation, basin.pet, *[parameters[name] for name in ["a", "b", "c", "d", "soil0", "groundwater0"]])[0]


def water_balance_registry():
    from .models import Model
    return {"ABCD": Model("ABCD", "monthly", {"a": 0.95, "b": 250.0, "c": 0.5, "d": 0.1, "soil0": 0.0, "groundwater0": 0.0}, {"a": (0.001, 1), "b": (1, 2000), "c": (0, 1), "d": (0.001, 1)}, _abcd, "Thomas (1981) ABCD monthly equations; native rationalized root; explicit zero initial stores")}

Simulation

from basinforge import Basin, get_model

basin = Basin.from_csv("basin.csv", basin_id="A", area_km2=1200,
                       q_unit="m3/s", timestep="monthly")
q_mm = get_model("ABCD").simulate(basin)
q_m3s = basin.to_m3s(q_mm)

Supply your actual data and catchment area; temperature-dependent models require a temperature column. For non-daily models, choose an appropriate warmup in model steps.

See calibration, input requirements, sources and verification limitations.