SWMM5 → SWMM6 EXTRAN Features Upgrader

Edit a SWMM5 .inp so the OpenSWMM SWMM6 engine runs its new EXTRAN-heritage dynamic-wave features — every fact on this page verified against four real engines · openswmm.engine swmm6_rel @ 1610516 · 6.0.0-alpha.3

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.

4
EXTRAN-heritage features, .inp-switchable
4
real engines tested with the same files
+34%
peak-flow shift, all features on (verified)
1
hard crash found (alpha.2 WASM + [VIRTUAL_JUNCTIONS])

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.

What this is not. Not a model editor and not a calibration tool. Not a claim that SWMM6 is production-ready — the engine is 6.0.0-alpha.3 and the numbers here are alpha numbers. Not a parity certificate: the demo chain is one small surcharged model, not a corpus. And the crash finding applies to the pinned alpha.2 WASM build; newer builds may differ.

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.

Verified on the demo chain: C2 peak flow 14.38 → 16.32 cfs (+13.5%); routing continuity −0.205% → −0.478%. The .rpt echoes Surcharge Method ......... DYNAMIC_SLOT.
SWMM 5.2.4 dies on this one with ERROR 205: invalid keyword DYNAMIC_SLOT — SURCHARGE_METHOD is a known keyword there, so a bad value is fatal, and each 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)
Verified: C2 peak 14.38 → 13.82 cfs (−3.9%); routing continuity flips sign, −0.205% → +0.705%. Echoed as Node Continuity .......... SEMI_IMPLICIT.
The repo README calls SEMI_IMPLICIT the default. The source disagrees: 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)
Verified: C2 peak 14.38 cfs — identical to the base run, routing continuity −0.203% vs −0.205%. That is the point: acceleration should change the iteration count, not the converged answer. The 25–50% iteration-cut figure is the source's claim (SimulationOptions.hpp:250–256), not measured here — the .rpt does not print iteration counts.

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
Verified: runs clean, and the .rpt gains a Virtual Junction Summary reporting the momentum residual through each virtual node (demo J2: max 791.64, mean 5.82 cfs·ft/s). Only convert junctions with exactly two attached conduits and no local inflows — the Upgrader enforces this.
This is the edit that breaks every other engine, each differently: stock 5.2.4 → fatal ERROR 205 at the section header; the repo's own legacy 5.3.0-beta.3 → warns, skips the section, then fails with ERROR 209 (undefined object J2) while still exiting 0; the pinned alpha.2 WASM build → hard crash, "memory access out of bounds". See the matrix tab.

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

Apply edits to see the 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%runsrunsruns −0.181%
SURCHARGE_METHOD DYNAMIC_SLOTruns echoedruns engages; report label prints (null)ERROR 205 known key, bad valueERROR 205 fatal
DPS_CELERITY / DPS_ALPHA / DPS_DECAY_TIMErunsrunsWARNING ignored, still runsERROR 205 each line
NODE_CONTINUITY SEMI_IMPLICITruns echoedruns echoedWARNING ignoredERROR 205 fatal
ANDERSON_ACCEL YESruns echoedruns echoedWARNING ignoredERROR 205 fatal
[VIRTUAL_JUNCTIONS] sectionruns + VJ SummaryCRASH memory access out of boundsskip → ERROR 209 exits 0 anywayERROR 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.

Practice that falls out of this: keep a SWMM5 twin. The three option-line features strip cleanly (the Upgrader's strip button removes them and restores virtual junctions to [JUNCTIONS] with MaxDepth 0, which SWMM5 raises to the highest connecting crown). Strip before sharing a file with anyone not on alpha.3.

One feature at a time

RunFeature lines addedRouting 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.

Alpha caveat, stated plainly: these deltas are one small model on an alpha engine. They demonstrate the switches engage and change real numbers; they do not tell you which answer is right. That question needs the benchmark corpus, and it is exactly what these switches exist to let you test.

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

ItemMethod
Source treegithub.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 + defaultsRead 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 behaviorBuilt 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 behaviorBuilt 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 behaviorBuilt 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 behaviorFetched 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 numbersRouting 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 measuredAnderson'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.

How to use this app

1. Read The Four Edits — each card is one feature: the lines to add, the default, the verified effect.

2. On Upgrader, paste your SWMM5 .inp (or keep the demo), tick features, hit Apply edits, and download. Eligible virtual-junction nodes are detected for you.

3. Check Compatibility Matrix before sharing the file — three of the four engines out there will reject or crash on parts of it, each differently.

4. Strip back to SWMM5 reverses every edit, restoring virtual junctions to [JUNCTIONS].

5. Verified Numbers and Provenance hold the measured effects and how each fact was established.