Subcatchments#
Note
Engine: OpenSWMM 6 — refactored.
Subcatchments are the runoff-generating polygons. The shape mirrors
Nodes and Links — a collection on
solver.subcatchments that yields Subcatchment wrappers.
Reference: openswmm_subcatchments.h.
Quickstart#
from openswmm.engine import Solver, InfilModel
with Solver("model.inp") as s:
sc = s.subcatchments["S1"]
print(sc.area, sc.imperv_pct, sc.slope)
# Topology — back-references to Gage / Node wrappers.
print(sc.gage.id, "->", sc.outlet.id)
# Infiltration as a tagged-union view.
print(sc.infiltration.model)
sc.infiltration.set_horton(3.0, 0.5, 4.0, 7.0)
# Coverage as a MutableMapping.
sc.coverage["RESIDENTIAL"] = 0.6
# Runtime state + bulk numpy.
print(sc.runoff, sc.rainfall)
runoffs = s.subcatchments.runoffs
Collection: Subcatchments#
Operation |
What it does |
|---|---|
|
Count. |
|
Returns a |
|
Yields a fresh |
|
Append a subcatchment. |
|
Rename in place. Invalidates wrappers. |
Bulk numpy properties#
Property |
Mode |
Meaning |
|---|---|---|
|
read-only |
Per-subcatchment runoff rate. |
|
read-only |
|
|
read-only |
|
|
read-only |
Infiltration rate. |
|
read-only |
|
|
read-only |
String ids as |
Per-pollutant concentrations:
s.subcatchments.qualities("TSS") # by str or int
Wrapper: Subcatchment#
Property |
Type |
Mode |
Meaning |
|---|---|---|---|
|
|
read-only |
|
|
|
read/write |
|
|
|
read/write |
|
|
|
read/write |
|
|
|
read/write |
Impervious fraction (%). |
|
|
read/write |
Manning’s n. |
|
|
read/write |
Depression storage. |
|
|
read/write |
Rain gage wrapper. |
|
|
read-only |
Whichever outlet target is configured. |
|
|
read-only |
Runtime state. |
|
|
read/write |
Override rainfall (writer is the same property). |
|
|
read-only |
Methods:
Method |
What it does |
|---|---|
|
Route runoff to a |
|
Route runoff to another |
|
Runoff concentration of |
|
Ponded mass balance. |
Infiltration view (tagged union)#
subcatchment.infiltration is a tagged-union view exposing whichever
parameter family matches the active model. Reading the wrong family
raises a BadParamError (which is also a ValueError):
sc = s.subcatchments["S1"]
if sc.infiltration.model in (InfilModel.HORTON, InfilModel.MOD_HORTON):
f0, fmin, decay, dry_time = sc.infiltration.horton
elif sc.infiltration.model in (InfilModel.GREEN_AMPT, InfilModel.MOD_GREEN_AMPT):
suction, ksat, deficit = sc.infiltration.green_ampt
else: # CURVE_NUMBER
cn = sc.infiltration.curve_number
Writers force the model to match:
sc.infiltration.set_horton(3.0, 0.5, 4.0, 7.0)
sc.infiltration.set_green_ampt(3.5, 0.06, 0.26)
sc.infiltration.set_curve_number(85.0)
You can also switch the active model directly without touching its parameters (the per-model sub-arrays are preserved):
sc.infiltration.model = InfilModel.GREEN_AMPT
Groundwater & aquifer assignment#
When a subcatchment drains to an aquifer, three properties expose the
[GROUNDWATER] configuration. Subcatchment.aquifer and
Subcatchment.gw_node return None when unset; assign an index,
a string id, a wrapper, or None to detach:
sc = s.subcatchments["S1"]
sc.aquifer = "Aquifer1" # id, index, or None to detach
sc.gw_node = "J3" # receiving node id / index / Node / None
print(sc.aquifer) # -> aquifer index, or None
print(sc.gw_node) # -> node index, or None
The flow parameters are read as a GroundwaterParams named tuple in
[GROUNDWATER] token order and written with Subcatchment.set_gw_params():
p = sc.gw_params # GroundwaterParams(surf_elev, a1, b1, ...)
print(p.surf_elev, p.a1, p.b1)
sc.set_gw_params(surf_elev=10.0, a1=0.01, b1=1.5,
a2=0.0, b2=0.0, a3=0.0, tw=0.0, hstar=5.0)
Reading gw_params requires an aquifer to be assigned. To inject the
runtime groundwater state (moisture / saturated depth) during a run, use
Subcatchment.set_gw_state() / Subcatchment.get_gw_state().
Coverage view#
subcatchment.coverage is a MutableMapping over landuse ids
→ fractions. Iteration yields landuse ids whose fraction is non-zero:
sc.coverage["RESIDENTIAL"] = 0.6
sc.coverage["COMMERCIAL"] = 0.4
sum(sc.coverage.values()) # ≤ 1.0
for landuse, frac in sc.coverage.items():
print(landuse, frac)
Deletion is not supported (the C side stores a dense per-landuse
array); set the fraction to 0.0 instead.
Statistics sub-view#
Same shape as nodes/links — meaningful after Solver.end():
print(sc.stats.precip) # cumulative precipitation
print(sc.stats.runoff_vol) # cumulative runoff volume
print(sc.stats.max_runoff) # peak runoff rate
Staleness, equality, repr#
Identical contract to Node / Link. Adding, renaming,
or deleting subcatchments invalidates wrappers minted before the
change.
See also#
Running a simulation — Solver — where
s.subcatchmentscomes from.Rain gages —
Subcatchment.gageyields aGage.Nodes —
Subcatchment.outletmay yield aNode.