swmmrs for Python
Run SWMM from Python, inspect it as it goes, and change a control when the water
has other ideas. swmmrs provides typed access to a native Rust solver, with
each simulation responsible for its own state and files.
Early-stage
Install the published wheel, expect API changes, and validate critical model results against EPA SWMM. See compatibility and limitations.
Solver source access
The native solver source is private. Access starts with a conversation about contributing; read the governance and contribution model.
Start here
- Install and run your first model.
- Choose a run workflow.
- Use the Python user guide for task-oriented workflows.
- Use the API reference for exact types and signatures.
Choose by workflow
| Goal | Guide |
|---|---|
| Discover configured definitions and relationships | Inspect model definitions |
| Configure options, dates, geometry, or initial conditions | Configure a model |
| Run interactively or own the stepping loop | Run a model |
| Apply measured inflow, forecast rain, boundary stages, or controls | Runtime forcings |
| Collect live values, snapshots, quality, or final statistics | Collect results and statistics |
| Resume or branch fuller runtime/resource continuation | Simulation checkpoints and forks |
| Transfer EPA-compatible warm state | EPA hotstarts and chained runs |
| Diagnose and recover from failures | Errors and recovery |
| Port an existing application | Migrating from PySWMM |
Interactive run
from datetime import timedelta
from swmmrs import Simulation
with Simulation("model.inp", "model.rpt", "model.out") as simulation:
node = simulation.nodes["J1"]
gate = simulation.links["OR1"]
simulation.step_advance(timedelta(minutes=5))
for current_time in simulation:
if node.depth > 2.0:
gate.target_setting = 0.5
print(current_time, node.depth, gate.flow)
statistics = simulation.statistics
simulation.end()
simulation.report()
The loop handles the control decisions. Here is who handles the housekeeping:
- iteration owns advancement and finalizes the run;
- the context manager closes the project;
- live views read fresh solver values;
statisticsis an immutable copy that remains valid after closure.
Core behavior
- One owner, one project generation. Reopening invalidates old collections and live views.
- One advancement owner. Do not mix iteration with manual
start(),step(),stride(), orexecute(). - Project units stay unchanged. No automatic SI conversion.
- Host cadence can affect routing cadence. Exact
step_advance()andstride(..., strict=True)boundaries can shorten a routing step;step_advance(..., strict=False)andstride(..., strict=False)preserve ordinary steps and may return after the target. - Live and file-backed results use different interfaces. Collect Live Views and snapshots during routing; use
OutputReaderfor report-period.outqueries after routing stops.
With gratitude to PySWMM
If this feels familiar, PySWMM deserves the
credit. It established a practical way to step through SWMM, inspect results,
and apply controls from Python. swmmrs borrows from that work deliberately.
You will recognize:
- the
Simulationcontext manager and iterator; - object collections and live node/link access;
- step-advance workflows;
- the shape of real-time control loops.
PySWMM remains the mature choice for its broader ecosystem, callbacks, and binary-output tools. See its documentation, repository, and JOSS paper.
Independent project
swmmrs is not affiliated with or endorsed by PySWMM, and it is not a drop-in replacement.
It embeds a different solver implementation with different ownership, lifecycle, errors, and
current capabilities.