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

count()

Number of registered pollutants.

get_index(id)()

Integer index for a string id.

get_id(idx)()

String id for an integer index.

Pollutant properties (read & write)#

Method

Action / returns

get_units(idx)()

ConcentrationUnits (mg/L, μg/L, count/L).

get_kdecay() / set_kdecay()

First-order decay constant (per day).

get_rain_conc() / set_rain_conc()

Concentration in incoming rainfall.

get_gw_conc() / set_gw_conc()

Concentration in groundwater inflow.

get_init_conc() / set_init_conc()

Initial concentration in the system.

get_rdii_conc() / set_rdii_conc()

Concentration in RDII inflows.

get_mwt() / set_mwt()

Molecular weight (used by some quality models).

get_co_pollutant() / set_co_pollutant()

(other_pollut_idx, fraction) for a co-pollutant relationship.

get_snow_only() / set_snow_only()

Pollutant only released by snowmelt.

Runtime injection#

Method

Action

set_node_quality(node_idx, p, value)()

Set the concentration of pollutant p at a node (one-shot).

set_link_quality(link_idx, p, value)()

Set the concentration of pollutant p in a link (one-shot).

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, EngineState

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.state == EngineState.RUNNING:
        if s.step() != 0:
            break
        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.state == EngineState.RUNNING:
    if s.step() != 0:
        break
    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

OPENED or later

Pollutant count is fixed at parse time.

property setters

OPENED

Best applied before initialize().

runtime injection

RUNNING

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#