Pollutants#
Note
Engine: OpenSWMM 6 — refactored. Documents
openswmm.engine.Pollutants.
The Pollutants class manages the list of modeled pollutants
and their solute properties (decay rate, rainfall / groundwater /
RDII concentrations, co-pollutant pairing, snow-only flag, molecular
weight). It is also the gateway for injecting pollutant
concentrations into the model at runtime.
For the kinetics — buildup, washoff, treatment, sweeping — see Water quality (landuse, buildup, washoff, treatment).
Reference: openswmm_pollutants.h.
Class signature#
class Pollutants:
def __init__(self, solver: Solver) -> None: ...
Key methods#
Identity#
Method |
Returns |
|---|---|
|
Number of registered pollutants. |
|
Integer index for a string id. |
|
String id for an integer index. |
Pollutant properties (read & write)#
Method |
Action / returns |
|---|---|
|
|
|
First-order decay constant (per day). |
|
Concentration in incoming rainfall. |
|
Concentration in groundwater inflow. |
|
Initial concentration in the system. |
|
Concentration in RDII inflows. |
|
Molecular weight (used by some quality models). |
|
|
|
Pollutant only released by snowmelt. |
Runtime injection#
Method |
Action |
|---|---|
|
Set the concentration of pollutant |
|
Set the concentration of pollutant |
For sticky cross-step injections, use
Forcing.node_quality() (see Advanced forcing). For mass-flux
injection (rather than concentration) at a node, see
Nodes.set_quality_mass_flux() in Nodes.
End-to-end example#
from openswmm.engine import Solver, Pollutants, Nodes
with Solver("water_quality.inp", "wq.rpt", "wq.out") as s:
polls = Pollutants(s)
nodes = Nodes(s)
print(f"{polls.count()} pollutants:")
for i in range(polls.count()):
print(
f" {polls.get_id(i):<10} "
f"k={polls.get_kdecay(i):5.3f}/d "
f"init={polls.get_init_conc(i):6.2f}"
)
tss = polls.get_index("TSS")
outfall = nodes.get_index("OUT1")
history = []
while s.step():
history.append(nodes.get_quality(outfall, tss))
print(f"Mean outfall TSS: {sum(history)/len(history):.2f}")
Common recipes#
Bump a decay constant for sensitivity analysis#
base_k = polls.get_kdecay("TSS")
polls.set_kdecay("TSS", base_k * 1.5)
# ... run ...
polls.set_kdecay("TSS", base_k) # restore for next sweep
Inject a pollutant at a node mid-run#
j1, tss = nodes.get_index("J1"), polls.get_index("TSS")
while s.step():
h = s.elapsed * 24.0
if 1.0 <= h <= 2.0:
polls.set_node_quality(j1, tss, 50.0) # mg/L for one hour
For a persistent injection, prefer Forcing.node_quality().
Set up a co-pollutant relationship#
# Assume TSS is already defined; couple FECAL to TSS
fecal = polls.get_index("FECAL")
tss = polls.get_index("TSS")
polls.set_co_pollutant(fecal, (tss, 0.05)) # FECAL = 5% of TSS
EngineState requirements & exceptions#
Method group |
Required state |
Notes |
|---|---|---|
identity / count |
|
Pollutant count is fixed at parse time. |
property setters |
|
Best applied before |
runtime injection |
|
One-shot per call. |
Common EngineError codes:
INVALID_INDEX— pollutant / node / link index out of range.INVALID_TYPE— calling an injection method on a model with no pollutants.
See also#
Water quality (landuse, buildup, washoff, treatment) — buildup / washoff / treatment kinetics.
Advanced forcing — persistent runtime concentration overrides.
Nodes —
Nodes.set_quality_mass_flux()for mass-flux injection.Output reader (binary .out file) — post-run pollutant time series.