Skip to content

Cascade Routing Reference

pywmp.cascade implements the South Florida Water Management District Cascade 2001 storage routing framework: stage-storage basin routing, structure-controlled interbasin transfers, and flexible multi-scenario experimentation.


pywmp.cascade

from pywmp.cascade import (
    # Core simulation
    CascadeSimulation, CascadeBasin, CascadeLink, CascadeResults,
    # Stage-storage
    StageStorageCalculator, StageStorageCurve, LandLakeSubArea,
    # Runoff
    SBUHRunoff, GDCUHRunoff,
    # Structures
    CascadeGravityStructure, CascadeGatedSpillway,
    CascadePumpStation, CascadeDropInlet,
    # Boundary
    OffsiteReceivingBody,
    # Rainfall
    cascade_distribution_hyetograph, convert_rainfall_depth,
    # Flex routing
    BasinConfig, RainfallOverride, run_flex,
    # Experiments
    ExperimentMatrix, Scenario,
    # Seawall
    SeawallModel, SeawallScenario, SeawallSystem,
    # Parser and DSS
    parse_cascade_dat,
    read_dss_timeseries, write_dss_timeseries, list_dss_pathnames,
)

Core simulation

CascadeSimulation

class CascadeSimulation(basins, links, boundary, dt_hr=0.5, units='USC')

Main solver. Iterates stage-storage routing for a network of CascadeBasin objects connected by CascadeLink routing links.

Parameter Type Description
basins list[CascadeBasin] Basin objects with stage-storage curves
links list[CascadeLink] Interbasin routing connections
boundary OffsiteReceivingBody Downstream stage boundary
dt_hr float Routing timestep (hr); default 0.5

Methods

CascadeSimulation.run(rainfall_ts, duration_hr) -> CascadeResults

CascadeBasin

class CascadeBasin(
    name, stage_storage, runoff_model,
    initial_stage=None, area_acres=None
)
Parameter Type Description
name str Basin identifier
stage_storage StageStorageCurve Stage ↔ storage lookup
runoff_model SBUHRunoff | GDCUHRunoff Runoff generation
initial_stage float | None Starting water surface elevation
area_acres float | None Basin area (acres)
class CascadeLink(
    name, upstream, downstream,
    structures, invert_elev=0.0
)

Routing link connecting two basins via one or more outlet structures.

CascadeResults

Container returned by CascadeSimulation.run().

results.stage(basin_name)    -> TimeSeries   # water surface elevation (ft)
results.outflow(link_name)   -> TimeSeries   # flow through link (cfs)
results.storage(basin_name)  -> TimeSeries   # storage (ac·ft)
results.peak_stage()         -> dict         # {basin: peak_stage_ft}
results.to_dataframe()       -> pd.DataFrame
results.plot()

Stage-storage

StageStorageCurve

Lookup table mapping elevation (ft NGVD) to cumulative storage (ac·ft).

curve = StageStorageCurve(
    elevations=[0, 2, 4, 6, 8],
    storages=[0, 12, 35, 72, 130],
)
stor = curve.storage_at(5.2)    # → interpolated ac·ft
elev = curve.elevation_at(50.0) # → interpolated ft

StageStorageCalculator

class StageStorageCalculator(dem, cell_size_ft, basin_mask=None)

Derives a stage-storage curve directly from a DEM by computing the volume of water that would fill the basin from the lowest cell upward.

calc  = StageStorageCalculator(dem_array, cell_size_ft=3.28)
curve = calc.compute(min_elev=5.0, max_elev=12.0, n_steps=50)

LandLakeSubArea

Defines a sub-area storage zone within a basin (e.g. a lake cell or depression that fills before overflowing into the surrounding land cells).

zone = LandLakeSubArea(
    name="Lake_1",
    stage_storage=curve,
    area_acres=120.0,
    connection_elev=8.0,   # elevation at which zone connects to main basin
)

Runoff models

SBUHRunoff

Standard Basin Unit Hydrograph runoff generation using SCS CN.

class SBUHRunoff(cn, area_acres, lag_hr, dt_hr=0.5)

sb = SBUHRunoff(cn=75, area_acres=500, lag_hr=1.8)
runoff_ts = sb.compute(rainfall_ts)

GDCUHRunoff

Green-Duan-Chieu UH runoff — a modified unit hydrograph with Green-Ampt infiltration for continuous simulation.

class GDCUHRunoff(cn, area_acres, lag_hr, Ks, psi, theta_i, dt_hr=0.5)

gd = GDCUHRunoff(cn=75, area_acres=500, lag_hr=1.8,
                 Ks=0.5, psi=3.5, theta_i=0.3)
runoff_ts = gd.compute(rainfall_ts)

Outlet structures

All structures are passed as a list to CascadeLink.

Class Formula Key parameters
CascadeGravityStructure Broad-crested weir crest_elev, L, Cw
CascadeGatedSpillway Orifice or gate invert_elev, area, Cd, gate_open
CascadePumpStation Constant flow when above intake intake_elev, capacity_cfs, on_elev, off_elev
CascadeDropInlet Weir + orifice combined crest_elev, L, invert_elev, area
from pywmp.cascade import CascadeGravityStructure, CascadePumpStation

structures = [
    CascadeGravityStructure(crest_elev=7.0, L=30.0),
    CascadePumpStation(intake_elev=2.0, capacity_cfs=15.0,
                       on_elev=5.5, off_elev=4.0),
]
link = CascadeLink("L1", upstream="Basin_A", downstream="Basin_B",
                   structures=structures)

Boundary condition

OffsiteReceivingBody

class OffsiteReceivingBody(name, stage_ts=None, fixed_stage=None)

Downstream stage boundary for the Cascade network. Supply either a TimeSeries of stage or a constant fixed_stage (ft NGVD).


Rainfall helpers

from pywmp.cascade import cascade_distribution_hyetograph, convert_rainfall_depth

# Cascade 2001-style triangular hyetograph
rain_ts = cascade_distribution_hyetograph(
    total_depth_in=5.0, duration_hr=24, dt_hr=0.5,
    peak_ratio=0.375                               # SCS Type II peak at 37.5 %
)

# Unit conversion
depth_mm = convert_rainfall_depth(depth_in=5.0, from_units="in", to_units="mm")

Flex routing

run_flex executes a routing run from a BasinConfig specification, allowing runtime overrides of rainfall without rebuilding the full model.

from pywmp.cascade import BasinConfig, RainfallOverride, run_flex

cfg = BasinConfig.from_dat("project.dat")
override = RainfallOverride(basin_names=["B1", "B2"], scale_factor=1.25)
results  = run_flex(cfg, override=override)

Experiments

from pywmp.cascade import ExperimentMatrix, Scenario

matrix = ExperimentMatrix(
    base_config=cfg,
    scenarios=[
        Scenario("5yr_existing",  rainfall_scale=1.0, cn_delta=0),
        Scenario("100yr_existing",rainfall_scale=2.1, cn_delta=0),
        Scenario("100yr_future",  rainfall_scale=2.1, cn_delta=+5),
    ],
)
all_results = matrix.run()

Seawall integration

from pywmp.cascade import SeawallModel, SeawallScenario, SeawallSystem

seawall = SeawallModel(crest_elev=8.5, length_ft=2400.0, Cw=3.33)
slr_scenario = SeawallScenario(slr_ft=1.5, return_period_yr=100)
system = SeawallSystem(seawall, basin=cascade_basin, scenario=slr_scenario)
results = system.run(rainfall_ts)

Project file parser

from pywmp.cascade import parse_cascade_dat

cfg = parse_cascade_dat("project/BuckCreek.dat")
# cfg.basins, cfg.links, cfg.rainfall, cfg.simulation_control

HEC-DSS I/O

from pywmp.cascade import read_dss_timeseries, write_dss_timeseries, list_dss_pathnames

paths = list_dss_pathnames("output.dss")
ts    = read_dss_timeseries("output.dss", "/BASIN_A/FLOW//1HOUR/RUN1/")
write_dss_timeseries("output.dss", "/BASIN_B/STAGE//1HOUR/RUN1/", stage_ts)