Collatz → SWMM5
.inpgenerator with a real EPA SWMM 5.2.x WebAssembly engine that runs in the browser. Written from the repository source (src/lib/collatz.ts,src/lib/swmm/*,package.json).
Collatz Wave Maker turns the Collatz (3n+1) conjecture into a runnable EPA SWMM5 stormwater model entirely in the browser. It generates Collatz sequences, assembles them into a tree, maps that tree onto a SWMM drainage network, runs a real WebAssembly build of the SWMM5 engine, and plots the resulting hydraulic time series as animated "waves."
The pipeline is:
- Collatz math – for every seed up to
maxSeed, repeatedly applyn -> n/2(even) orn -> 3n+1(odd) until reaching 1, building a tree where every number flows toward 1. - Network mapping – each number becomes a SWMM junction, each Collatz step
n -> next(n)becomes a conduit directed toward 1 (the outfall). Distance from 1 sets node depth/invert. .inpgeneration – a complete SWMM5 input file is written with[JUNCTIONS],[CONDUITS],[DWF],[INFLOWS],[TIMESERIES],[RAINGAGES],[SUBCATCHMENTS], coordinates, and more.- Simulation – a real Emscripten-compiled SWMM5 engine
(
/public/wasm/swmm5.js, which embeds the.wasmbinary as a base64 data URI, so no separateswmm5.wasmfile ships) runs the model in-browser inside a Web Worker. There is no fallback solver: if the engine cannot start, the run fails loudly rather than returning made-up numbers. - Visualization – SWMM binary output is parsed into per-node and per-link time series (depth, inflow, flow, velocity) and rendered as charts with Recharts, plus an animated hydraulic grade line and a longitudinal profile.
This project is part of the SWMMEnablement collection.
| Area | What the app does |
|---|---|
| Generator | Collatz tree up to N = 5,000 seeds, radial/symmetric/manual layouts, live "Holy Tree" canvas with pan, zoom and shift-drag area selection |
| INP output | Full SWMM5 .inp text preview, download, and a validator that flags structural problems before you run |
| Engine | EPA SWMM 5.2.x WASM in a Web Worker: progress bar, cancel button, run metrics (continuity error, flooded nodes, max surcharge), status classification |
| Results | Node depth/inflow and conduit flow hydrographs, filtered to the area you marquee-selected on the diagram |
| HGL | Hydraulic grade line animated over the 12-hour run using real SWMM depths, with flooding/surcharge highlights |
| Profile | Longitudinal geometry profile: invert, crown, rim, depth bars, max-HGL envelope, flooding markers, conduit flow |
| Inflow | User-defined DWF at every node plus a 12-hour trapezoidal storm hydrograph with presets; inflow scope selectable (seeds / leaves / all nodes) |
| Rainfall | Rain gauges, design storms (uniform, SCS type II, alternating block) and auto-generated subcatchments with a blunt-area note |
| Sizing | Hydraulic auto-sizing over standard diameters with live per-attempt streaming, cancel, resume, and a one-click uniform vs √upstream diameter comparison |
| Regression lab | Deterministic fixtures (N = 10 / 27 / 100 / 1000) run across solver presets, with a results matrix and a divergence heatmap |
| History & compare | Last 30 runs in localStorage, side-by-side comparison of two runs (metric deltas, flooded/surcharged node set differences), export and re-import of a comparison |
| Provenance | SHA-256 of the WASM asset, engine version, and a downloadable deterministic run manifest (manifest.json) |
| Export | .inp, .rpt, .out, summary.json, manifest.json, GeoJSON, comparison CSV/JSON |
| Thresholds | Configurable continuity / flooding / surcharge limits that colour the run status |
| Theme | Light and dark mode |
| Path | Description |
|---|---|
src/lib/collatz.ts |
Core math: nextCollatz, sequence(seed), pathToOne, and buildTree(maxSeed) (nodes, edges, BFS depth from 1), plus overflow/truncation diagnostics |
src/lib/swmm/inp.ts |
buildInp(opts) – writes the SWMM5 .inp file from the Collatz tree and InpOptions; storm hyetograph and trapezoid presets |
src/lib/swmm/layout.ts |
Computes node coordinates for the network (layoutFor, LayoutMode) |
src/lib/swmm/engine.ts |
runEngine / startEngine – runs the WASM SWMM5 engine in a worker; defines NodeSeries / LinkSeries / SystemSeries |
src/lib/swmm/engine.worker.ts |
Worker entry; installs a minimal Node shim so the Node-targeted Emscripten build loads in a browser worker |
src/lib/swmm/outfile.ts |
Parses the SWMM binary output file into time series (parseSwmmOut) |
src/lib/swmm/rpt.ts |
Extracts run metrics from the text .rpt report |
src/lib/swmm/validate.ts |
Structural INP validator |
src/lib/swmm/sizing.ts |
Iterative diameter search (autoSizeUniform, compareDiameterModes) with abort + streaming callbacks |
src/lib/swmm/manifest.ts |
Deterministic run manifest builder |
src/lib/swmm/provenance.ts |
SHA-256 hash of the vendored WASM asset |
src/lib/swmm/geojson.ts |
GeoJSON export of nodes and conduits |
src/lib/runHistory.ts |
Run history store (last 30 runs, localStorage) |
src/lib/thresholds.ts |
Configurable pass/fail limits |
src/lib/theme.tsx |
Light/dark theme provider |
src/components/ |
UI panels: GeneratorForm, HolyTreeCanvas, InpPreview, HglView, ProfileView, EngineRunner, SizingPanel, RegressionLab, RunHistoryPanel, ComparePanel, BatchRunner, ThresholdsPanel, DocsView |
src/routes/ |
TanStack Start route/page components (index.tsx is the app, github-sync.tsx the repo view) |
public/wasm/ |
Emscripten-compiled swmm5.js (WASM binary embedded as a data URI) |
Defined in src/lib/swmm/inp.ts:
| Option | Meaning |
|---|---|
maxSeed |
Largest Collatz seed; controls how many junctions/conduits the network has |
flowUnits |
SWMM flow units: CFS, LPS, or CMS |
baseInvert |
Invert elevation of the outfall/base node |
invertDrop |
Elevation drop applied per depth step toward the outfall |
maxDepth |
Maximum node depth |
conduitLength |
Length assigned to each conduit |
roughness |
Manning's roughness for conduits |
diameter |
Conduit diameter |
layoutMode |
Layout algorithm used to place nodes |
dwfBaseflow |
Dry Weather Flow – average baseflow assigned to each junction |
dwfPattern |
Optional DWF time pattern name ("" = none) |
inflowScope |
Which nodes receive inflow: seeds, leaves, or all |
endTimeSec |
Simulation duration in seconds (minimum 12 h = 43200) |
peakInflow |
Peak of the trapezoidal inflow hydrograph at each junction |
trapRiseFrac / trapPlateauFrac / trapFallFrac |
Trapezoid shape, also settable from a preset |
stormType |
Rainfall design storm: none, uniform, scs-type-ii, alt-block |
coordScale |
Multiplier applied to all node x/y coordinates |
Solver settings are fixed by default and overridable for the regression lab:
FLOW_ROUTING = DYNWAVE, ROUTING_STEP = 10 s, LENGTHENING_STEP = 5 s.
Collatz trajectories are computed with BigInt and only converted back to
JavaScript numbers when they stay inside Number.MAX_SAFE_INTEGER (2^53 − 1).
A seed whose trajectory exceeds that limit is reported in the sidebar
diagnostics instead of being silently rounded, and every seed is capped at
ITERATION_CAP_PER_SEED = 100_000 steps.
Scripts are defined in package.json:
# Install dependencies
bun install
# Start the dev server
bun run dev # vite dev
# Production build / preview
bun run build # vite build
bun run preview # vite preview
# Lint / format
bun run lint # eslint .
bun run format # prettier --write .Then open the local URL printed by Vite in your browser.
- The SWMM5 engine runs client-side via WebAssembly inside a Web Worker; no server is required for simulation.
- The vendored
swmm5.jswas built by Emscripten for Node only, soengine.worker.tsinstalls a small Node shim (aprocessobject withversions.nodeandhrtime,Buffer.from(..., "base64")backed byatobfor the embedded binary, and stubs forpath/fs/crypto) before loading it. Seepublic/wasm/README.md. - Run history, selected comparison runs and thresholds live in
localStorage. - This is an experimental / educational project connecting number theory (Collatz) to hydraulic modeling (SWMM5).
MIT — see LICENSE.