Turn a SWMM5 model into a SWMM6 solver test in four edits
OpenSWMM's SWMM6 engine keeps EXTRAN's dynamic-wave heart — the same momentum kernel, bit-parity with dwflow.c — and then adds four solver features EXTRAN never had. All four are switched on from the .inp file: three [OPTIONS] lines and one new section. This app shows the exact lines, makes the edits for you, and tells you which engines will accept, warn, error, or crash on the result — because we ran the same six files through all four of them.
What it does
1 · Documents each feature with the exact .inp syntax, engine default, and source-line citation. 2 · Upgrades your pasted SWMM5 .inp with checkboxes and shows a line diff. 3 · Strips a SWMM6 file back to clean SWMM5. 4 · Gives you the four-engine compatibility matrix with the verbatim error messages.
Who uses it
1 · A SWMM5 modeler curious what SWMM6 changes — start on The Four Edits. 2 · Someone building a test file right now — start on Upgrader. 3 · Anyone about to share a SWMM6 file with SWMM5 users — start on Compatibility Matrix. 4 · A reviewer checking whether the features change answers — start on Verified Numbers. 5 · A skeptic — start on Provenance.
What you get out of it
A runnable SWMM6 test file from your own model in under a minute; the knowledge of which engines it will break and how; measured evidence that these switches change real answers (peak flow +13.5% from the Dynamic Preissmann Slot alone on the surcharged demo chain); and a reversible path back to SWMM5.
1 · Dynamic Preissmann Slot — SURCHARGE_METHOD DYNAMIC_SLOT
EXTRAN handles surcharge by switching to a special head-adjustment equation; the classic SLOT method replaces that with a fixed-width Preissmann slot. SWMM6 adds a third method: a dynamic slot whose width follows the Preissmann Number so pressure-wave celerity relaxes toward a target instead of being fixed (Sharior et al. 2023).
[OPTIONS] SURCHARGE_METHOD DYNAMIC_SLOT ;; was EXTRAN (default) or SLOT DPS_CELERITY 25 ;; target pressure celerity, m/s (default 25) DPS_ALPHA 3 ;; shock parameter, dimensionless >= 2 (default 3) DPS_DECAY_TIME 0.5 ;; Preissmann Number decay, seconds (default 0.5)
Lower DPS_CELERITY allows larger timesteps but reduces transient fidelity; larger DPS_ALPHA gives a bigger celerity shock at the mixed-flow transition; shorter DPS_DECAY_TIME reaches the target celerity faster but can oscillate.
Surcharge Method ......... DYNAMIC_SLOT.DPS_* line adds another ERROR 205.Parser: OptionsHandler.cpp:301–315 · defaults: SimulationOptions.hpp:208–231 (surcharge_method=0 EXTRAN, celerity 25.0, alpha 3.0, decay 0.5)
2 · Semi-implicit node continuity — NODE_CONTINUITY SEMI_IMPLICIT
EXTRAN's node depth update is explicit, with a special branch when depth crosses the crown. SWMM6 can replace that branch with one Crank–Nicolson update, dH = dV/(A − dt·Σ∂q/∂h/2) — the same formula through open, transition and surcharged states.
[OPTIONS] NODE_CONTINUITY SEMI_IMPLICIT ;; default is EXPLICIT (legacy behaviour)
Node Continuity .......... SEMI_IMPLICIT.SimulationOptions.hpp:234 sets EXPLICIT and comments it "default (legacy behaviour)". Trust the source — your model behaves the same unless you add this line.Parser: OptionsHandler.cpp:316–320 · default: SimulationOptions.hpp:234
3 · Anderson acceleration — ANDERSON_ACCEL YES
EXTRAN converges node depths by Picard successive approximation. SWMM6 can wrap that loop in depth-2 Anderson mixing; the source claims 25–50% fewer iterations on stiff surcharge problems, falling back to plain Picard for nodes that violate physical bounds. It is clamped to interpolation only (mixing factor in [0,1]) and gated off far from convergence.
[OPTIONS] ANDERSON_ACCEL YES ;; default NO (standard Picard)
Parser: OptionsHandler.cpp:326–329 · default: SimulationOptions.hpp:256
4 · Virtual junctions — the [VIRTUAL_JUNCTIONS] section
EXTRAN puts storage at every node; a pipe broken into segments picks up artificial surface area at every break node. A SWMM6 virtual junction is a zero-storage, momentum-transmitting pipe-break node: move it out of [JUNCTIONS], keep only name and invert, and the engine derives its geometry from the two attached conduits. VIRTUAL_JUNCTION_MOMENTUM FULL adds the cross-junction convective flux correction (dq4_j) — a term with no SWMM5 counterpart.
[JUNCTIONS] ;;J2 removed from here ... [VIRTUAL_JUNCTIONS] ;;Name InvertElev ;; exactly two tokens; a third is a parse error J2 105.0 [OPTIONS] VIRTUAL_JUNCTION_MOMENTUM FULL ;; default BASIC
Parser: NodesHandler.cpp:95 (name + invert only, extra tokens = ERR_VJ_EXTRA_TOKENS) · registration: DefaultInputPlugin.cpp:61 · momentum option: OptionsHandler.cpp:321–325, default BASIC at SimulationOptions.hpp:245 · merged 2026-08-03, PR #115
Where to run the result
The openswmm CLI (new data-oriented engine) takes the same inp rpt out arguments as SWMM5; the legacy EPA tree ships beside it as openswmm-legacy. In the browser, the prebuilt alpha.2 WASM engine accepts the three option-line features today (with one cosmetic bug: DYNAMIC_SLOT echoes as (null) in the report while the solver engages) — but not [VIRTUAL_JUNCTIONS]. Build alpha.3 from source for all four: with GeoPackage, 2D and the GPU plugin switched off it is pure C++20 with no external dependencies.
Input demo loaded
Features to switch on
Diff
Modified file
Engine × feature matrix
| .inp contains… | SWMM6 6.0.0-alpha.3 openswmm CLI @ 1610516 | SWMM6 6.0.0-alpha.2 prebuilt WASM (browser) | Legacy 5.3.0-beta.3 openswmm-legacy, same repo | EPA SWMM 5.2.4 stock, built from v5.2.4 tag |
|---|---|---|---|---|
| nothing new (base SWMM5 file) | runs −0.205% | runs | runs | runs −0.181% |
SURCHARGE_METHOD DYNAMIC_SLOT | runs echoed | runs engages; report label prints (null) | ERROR 205 known key, bad value | ERROR 205 fatal |
DPS_CELERITY / DPS_ALPHA / DPS_DECAY_TIME | runs | runs | WARNING ignored, still runs | ERROR 205 each line |
NODE_CONTINUITY SEMI_IMPLICIT | runs echoed | runs echoed | WARNING ignored | ERROR 205 fatal |
ANDERSON_ACCEL YES | runs echoed | runs echoed | WARNING ignored | ERROR 205 fatal |
[VIRTUAL_JUNCTIONS] section | runs + VJ Summary | CRASH memory access out of bounds | skip → ERROR 209 exits 0 anyway | ERROR 205 at section header |
The verbatim messages
Stock EPA SWMM 5.2.4 — every new keyword is fatal
ERROR 205: invalid keyword DYNAMIC_SLOT at line 26 of [OPTION] section: ERROR 205: invalid keyword DPS_CELERITY at line 27 of [OPTION] section: ERROR 205: invalid keyword NODE_CONTINUITY at line 30 of [OPTION] section: ERROR 205: invalid keyword ANDERSON_ACCEL at line 30 of [OPTION] section: ERROR 205: invalid keyword VIRTUAL_JUNCTION_MOMENTUM at line 30 of [OPTION] section:
5.2.4 has no "unknown option → warn" path: an unrecognized [OPTIONS] keyword and an unrecognized section header both raise ERR_KEYWORD (205) and kill the run (input.c pass 1 and pass 2 both).
Repo legacy 5.3.0-beta.3 — softened, with a trap
WARNING: Unknown option keyword 'NODE_CONTINUITY' in [OPTIONS] section - option will be ignored. WARNING: Unknown section '[VIRTUAL_JUNCTIONS]' at line 39 will be skipped. ERROR 209: undefined object J2 at line 49 of [CONDUIT] section:
Unknown keywords and unknown sections are now warn-and-skip — but skipping [VIRTUAL_JUNCTIONS] erases the node you moved there, so the conduits that reference it fail with ERROR 209. The process still exits 0: check the .rpt, never the exit code.
Prebuilt alpha.2 WASM — the browser trap
callMain(['/m.inp','/m.rpt','/m.out']) → RuntimeError: memory access out of bounds
[VIRTUAL_JUNCTIONS] postdates the alpha.2 build (merged 2026-08-03; alpha.2 shipped to PyPI 2026-07-07). It does not fail gracefully — the WASM instance dies. Any browser runner on that build needs a fresh engine instance per run and should pre-scan for the section.
One feature at a time
| Run | Feature lines added | Routing continuity % | C2 peak flow, cfs | Δ peak vs base |
|---|
Read it like this
DYNAMIC_SLOT moves the answer the most on a surcharged run (+13.5% peak) — expected, since it rewrites how surcharge propagates pressure. SEMI_IMPLICIT shifts the peak −3.9% and flips the continuity sign. ANDERSON leaves the converged peak identical to base — the correct behavior for a convergence accelerator. Virtual junction J2 barely changes this chain's peak (+0.1%) because J2 was already a plain pass-through; its value shows in the new Virtual Junction Summary, which reports the momentum residual EXTRAN silently absorbs into node storage (J2: max 791.64, mean 5.82 cfs·ft/s). All features together: 19.29 cfs, +34.1% — the combination is not additive.
Cross-engine base check
Same base file, no new features: EPA 5.2.4 routing continuity −0.181%, SWMM6 alpha.3 −0.205%. Close, not identical — consistent with the measured 0.000% vs 0.223% routing-continuity gap on an earlier 1-pipe test. State the metric with any parity claim.
How every fact on this page was established
| Item | Method |
|---|---|
| Source tree | github.com/SWMMBobSWMM6/openswmm.engine, branch swmm6_rel, commit 161051639ba93af20e83016e5122dc91a698d20d (2026-08-04) — identical to upstream HydroCouple at the same SHA. Engine version 6.0.0-alpha.3; legacy tier 5.3.0-beta.3. |
| Keyword syntax + defaults | Read directly from src/engine/input/handlers/OptionsHandler.cpp (lines 301–329), NodesHandler.cpp:95, SimulationOptions.hpp (lines 208–256) at that commit. Every card links the lines. |
| SWMM6 alpha.3 behavior | Built the openswmm CLI from that commit (CMake, Release, GeoPackage/2D/GPU off — no external dependencies) and ran all six test files. rc=0 on all; .rpt echoes captured. |
| Legacy 5.3.0-beta.3 behavior | Built openswmm-legacy from the same tree; ran the same files; warnings/errors captured verbatim, including the skip-then-ERROR-209-but-exit-0 chain. |
| EPA 5.2.4 behavior | Built from the v5.2.4 tag of USEPA/Stormwater-Management-Model with gcc (fortify off); every ERROR 205 captured verbatim. Fatality of unknown sections/keywords also confirmed at input.c pass 1 & 2 and project.c. |
| Alpha.2 WASM behavior | Fetched the pinned LocalSWMM build (commit 164beb8d…), SHA-256 d0a8eadd… verified before execution, run in Node via callMain(['/m.inp','/m.rpt','/m.out']). DYNAMIC_SLOT engages (peak 16.33 vs alpha.3's 16.32) while the report label prints (null); [VIRTUAL_JUNCTIONS] throws "memory access out of bounds". |
| Run numbers | Routing continuity and C2 peaks read from the generated .rpt files; the hero "+34%" is recomputed at load from the embedded table and asserted, so it cannot silently go stale. |
| Not measured | Anderson's 25–50% iteration reduction (source comment's claim; .rpt prints no iteration counts). Whether any feature's answer is more accurate — that needs benchmark comparisons this app does not perform. |
App generated 2026-08-08. Demo model embedded below the Upgrader tab as the worked example. Built for Robert Dickinson's SWMM5/SWMM6 enablement work.