![]() |
SWMMVis
6.0.0-alpha.4
Qt6/C++ GIS-based graphical user interface for the SWMMVis engine (6.0.0-alpha.4)
|
Diagnose the problems people actually hit: a project that will not open, layers that do not line up, a basemap that stays blank, a run that fails, a mesh that will not generate, results that never appear, and a window layout you want back.
The Message Logs dock (Ctrl+Alt+7) is the first place to look for anything. The Simulation Status panel (Ctrl+Alt+6) carries per-run detail, and the .rpt status report (Analysis → Report) carries every engine warning and error in full.
The Message Logs dock is a three-column tree — Time, Type, Message — with Information, Warning and Error rows, auto-scrolled to the newest.
There is no on-disk log by default, and no Save Log action. To get the contents out, right-click the view and use Copy (selected rows) or Copy All, which prepends a Time / Type / Message header. Both produce tab-separated text that pastes straight into a spreadsheet or a bug report.
For a persistent log — and on Windows, where the application has no console at all — set SWMM_LOG_FILE before launching:
It appends, is safe across worker threads, flushes every line, and writes each one as hh:mm:ss.zzz <category>: <message>. Add QT_LOGGING_RULES="openswmm.load.*=true" to include the load-path detail (see A4 — Performance and Redraw Policy for the category list).
Check the report and the log first. Parse failures produce numbered engine errors:
| Code | Message |
|---|---|
| 200 | one or more errors in input file. |
| 201 | too many characters in input line. |
| 203 | too few items. |
| 205 | invalid keyword <x>. |
| 207 | duplicate ID name <x>. |
| 209 | undefined object <x>. |
| 211 | invalid number <x>. |
| 213 | invalid date/time <x>. |
| 233 | invalid math expression. |
| 235 | invalid infiltration parameters. |
File-level failures:
| Code | Message |
|---|---|
| 301 | files share same names. |
| 303 | cannot open input file. |
| 305 | cannot open report file. |
| 307 | cannot open binary results file. |
| 308 | amount of output produced will exceed maximum file size. |
| 309 | error writing to binary results file. |
| 311 | error reading from binary results file. |
| 317 | cannot open rainfall data file <x>. |
| 331 | cannot open hot start interface file <x>. |
| 337 | cannot open climate file <x>. |
| 361 | could not open external file used for Time Series <x>. |
Errors 317, 331, 337 and 361 almost always mean a relative path that no longer resolves — see Relative paths and portability below.
Common validation failures once the file parses:
| Code | Message |
|---|---|
| 101 | memory allocation error. |
| 107 | cannot compute a valid time step. |
| 111 | invalid length for Conduit <x>. |
| 112 | elevation drop exceeds length for Conduit <x>. |
| 117 | no cross section defined for Link <x>. |
| 131 | the following links form cyclic loops in the drainage system: |
| 138 | Node <x> has initial depth greater than maximum depth. |
| 140 | Storage node <x> has negative volume at full depth. |
| 141 | Outfall <x> has more than 1 inlet link or an outlet link. |
| 145 | Drainage system has no acceptable outlet nodes. |
| 191 | simulation start date comes after ending date. |
| 195 | reporting time step or duration is less than routing time step. |
If the .inp opens but the styling is gone, the .oswp sidecar is missing or was not found. The .oswp must sit beside the .inp with the same basename. Nothing is lost from the model itself — the .inp is complete on its own.
If map labels, a backdrop image or profile definitions vanished after a save, that is expected: [LABELS], [BACKDROP] and [PROFILE] are parsed and discarded, and nothing writes them back. See A2 — File Formats.
Almost always a CRS problem.
If the project CRS is wrong, Change Coordinate Reference System offers two options under How should the change be applied? — and they are very different:
Picking the first by mistake and then saving is destructive. If in doubt, pick the second.
If nothing reprojects at all, PROJ or GDAL cannot find its data files. SWMMVis locates bundled proj/ and gdal/ directories beside the executable (and inside Contents/Resources/ on macOS) and sets PROJ_DATA and GDAL_DATA itself; if you are running an unpackaged build, set them by hand.
A mesh with no ;; UNITS: header in a US-units project is silently scaled by 0.3048. If a mesh lands a third of the size it should be, that is why. Add ;; UNITS: SI (m) or ;; UNITS: metre to the .2dm (or above the inline 2D sections) and reload.
{s} {z} {x} {y} placeholders must match the provider. Axis order: must be ZXY (standard OSM) for most tile servers and ZYX (ArcGIS REST) for ArcGIS ones — a wrong axis order gives you scrambled or blank tiles rather than an error.Blank-but-no-error is the normal failure mode for tiles. Check the Message Logs and, if you need more, the network activity of the request.
Read the report. A failed run writes a .rpt even when it writes no .out, and that is where the reason is. The GUI's completion messages are:
<path> — success.<path> — the partial .out is still loaded.<message> — <detail>.<path> / The run likely failed during input parsing or setup — see the report file for the cause: <rpt path> — this one almost always means a parse or setup error.Pre-run refusals you may hit:
Engine warnings worth understanding when a run finishes but looks wrong:2D Surface Routing is enabled for this model, but no 2D mesh was found — there is no inline mesh in the .inp and no valid [2D_MESH_FILE] reference. The simulation will run as 1D-only. Generate a mesh (or set one active in Simulation Options → Mesh) to run the 2D solver. Continue with a 1D-only run?
| Code | Meaning |
|---|---|
| 2 | maximum depth increased for a node |
| 5 | minimum slope used for a conduit |
| 8 | elevation drop exceeds length for a conduit |
| 101 | duplicate x values in a curve |
| 102 | boundary regions overlap |
| 103 | a [FILES] entry is not supported by this engine and was ignored |
| 104 | a retired [2D_OPTIONS] key was ignored — see below |
| 105 | an option is accepted but has no effect yet under FLOW_ROUTING FV |
| 106 | a dynamic-wave option does not apply under FLOW_ROUTING FV |
| 107 | unreadable rows were skipped in a rainfall CSV |
| 108 | the Preissmann-slot top-width cap overrode FV_SLOT_CELERITY |
Loading a pre-2026 2D model produces one warning per retired key:
WARNING 104: [2D_OPTIONS] <key> was retired with the CVODE/ARKODE 2D solvers and was ignored; the explicit local-inertial marcher is the only 2D integrator.
The retired keys are MIN_TIMESTEP, REL_TOLERANCE, ABS_TOLERANCE, MAX_CVODE_STEPS, MAX_KRYLOV_DIM, LINEAR_SOLVER, PRECONDITIONER, JACOBIAN, ATOL_AREA_REF, COUPLING_INTERVAL, COUPLING_WINDOW, ACTIVE_SET, ACTIVE_SET_HALO and MOMENTUM, plus any INTEGRATOR value other than EXPLICIT. The replacements are THETA, CFL_NUMBER, LTS_TIERS, H_MOVE, FROUDE_MAX, ADVECTION, MAX_TIMESTEP and COUPLING_AREA.
They are harmless — warn and ignore on file load. To silence them, just save the model from SWMMVis: the Simulation Options dialog writes through the API, which rejects retired keys outright, so they are dropped.
An unknown (as opposed to retired) key is a hard parse error: Unknown 2D_OPTIONS parameter: <key>.
Three [OPTIONS] keys are retired the same way, with a *"… is retired and will be treated as …"* warning: FV_NODE_COUPLING EXPLICIT, FV_NODE_DT NONE and FV_NODE_PICARD. VIRTUAL_JUNCTION_MOMENTUM FULL is retired and is not re-emitted on save.
If Simulation Options has no 2D Surface Routing category at all, the engine you are running was built without the 2D module. The 2D Surface Routing checkbox on the Models / Processes page stays enabled either way, but its tooltip changes to say:
Project-level 2D module flag. Mesh selection tab becomes interactive when checked. The engine 2D solver itself is not compiled in this binary — rebuild with
-DOPENSWMM_BUILD_2D=ONfor end-to-end coupled runs; mesh generation works regardless.
The Mesh category is always present, because mesh management is a pure GUI concern. And the GUI links HDF5 unconditionally for its own results reader, so reading a .2d.h5 and generating a mesh both work even when the engine has no 2D solver.
The Generate 2D Mesh dialog reports the reason directly.
By far the most common: the CRS.
The project CRS (…) has no usable planar linear unit. 2D mesh generation requires a projected or local CRS in metres or feet. Geographic (lat/lon) CRSes are not supported.
Fix: open Project → Change CRS… and pick a projected CRS, or use the 'Local projected' option when the source units are unknown.
Or, more bluntly, No CRS is set for the model.
Geometry failures:
| Message | Cause |
|---|---|
| MeshGenerator: domain is empty. | no boundary polygon and no model extent |
| …no usable boundary polygons (every supplied polygon had < 3 vertices after vertex deduplication). | degenerate boundary layer |
| …all domain boundary segments were degenerate (zero-length after vertex deduplication). | coincident boundary vertices |
| MeshGenerator: cdt: constraint crosses another constraint | constraint segments cross without a shared vertex |
| MeshGenerator: cdt: constraint recovery stalled | constrained edges could not be recovered; check for degenerate or crossing geometry |
| MeshGenerator: no cells were produced — the domain may be smaller than the cell size. | reduce the requested cell size or check the domain geometry |
Non-finite coordinates are rejected explicitly — a NaN coordinate is invisible to duplicate and degeneracy screening, so it is caught up front.
DTM failures: DTM open failed, DTM pixel size is invalid, Terrain thinning failed, DTM sampling failed. With no DTM chosen the dialog logs Using junction rim elevations (no DTM selected)… and carries on.
Minimum cell size conditioning can abandon rather than fail:
The remedy for all three is either a larger minimum cell size or simpler input geometry. The generation log also reports a census — crossings N, duplicate segs N, zero-length N, collinear overlaps N, degenerate rings N — which tells you which of those to go and fix.
Protected slivers: N sub-scale cell(s) are bounded by constrained or coupled geometry and cannot be collapsed — these need a larger minimum cell size or simpler input geometry.
Holes. The Drop holes smaller than one cell checkbox warns that Hole rings narrower than the minimum cell size cannot be meshed around. When checked they are removed, which means THE MESH COVERS THEM — a modelling change, reported in the generation log. Read the log after checking it.
A quality hint you will see often: Min angle is N° — consider 26–28° with a minimum cell size…
Inlet junctions are constrained, and the GUI translates the engine's codes into plain language:
| Code | Message |
|---|---|
| 623 | An inlet junction sits between two STREET conduits (RECT_OPEN or TRAPEZOIDAL for a drop inlet). |
| 625 | The inlet design named on this row does not exist. |
| 627 | The capture node must be an existing node other than the inlet itself, and not a virtual or inlet junction. |
| 629 | An inlet cannot be placed on both conduits of an inlet-junction pair. |
| 631 | Too many items on the [INLET_USAGE] line. |
| 633 | This inlet junction has no inlet design assigned. |
| 635 | The inlet design is not compatible with the host's cross section (gutter inlets need STREET; drop inlets need RECT_OPEN or TRAPEZOIDAL). |
Virtual junctions use the same mechanism with codes 609–621. There is also a 2D-specific error, 617 — Virtual Junction <x> cannot be coupled to a 2D surface mesh.
Other messages you will meet while editing: *"…" is not an inlet junction.*, An inlet junction needs both an inlet …, Click a street conduit to insert an inlet junction at that point. and Could not insert an inlet junction on "…". Deleting one of the paired conduits raises a guard dialog (Delete Inlet Junction or Conduit Belongs to an Inlet Junction).
.out beside the .inp. If the run reported success but produced no output, the failure was during parsing or setup — read the .rpt..out. Only an engine error with no output at all skips the load..2d.h5? Check [2D_OPTIONS] OUTPUT_FILE — an empty value means no 2D output is written — and REPORT_2D. The 2D writer needs no [PLUGINS] entry.qual:<name>) after pollutants changed..out shows no species entries at all in the variable picker. That is not a bug.A4 — Performance and Redraw Policy covers this in full. The short list:
SWMMVIS_LOG_REDRAW=1 and see which channel a gesture dirties. A selection change should dirty Overlay, never Raster.OPENSWMM_2D_RENDER_DEBUG prints the per-paint frame re-grab decision.OPENSWMM_QSG_MESH=0 forces the painter fallback — useful as a diagnosis, not as a fix.One known stale case is on record and not resolved: adding a node with the Add Node tool has been reported not to repaint immediately in some situations. If you see it, a pan or a layer visibility toggle forces the redraw.
Everything SWMMVis writes uses relative paths where it can — the .oswp's layer sources, [2D_MESH_FILE], [PROCESS_COMPONENTS] config=, [FILES] entries and [RAINGAGES] FILE sources are all resolved against the file that names them. That makes a project folder portable, provided you move the whole folder.
What breaks:
.inp without its sidecar configs (.rxn, .ard, .age, .heat) — the components fail to load..inp without its .2dm — the mesh is missing and a 2D run degrades to 1D with the warning above..inp without its rain or climate file — errors 317 and 337.Examples are always copied, never opened in place. Choosing one from the Welcome page asks Choose a folder to copy "…" into first, so that simulation results never land in the bundled baseline. If a copy already exists you get Example copy already exists with Open Existing, Replace and Cancel.
Two separate resets:
| What | Where | Effect |
|---|---|---|
| Preferences | Reset to defaults at the bottom-left of the Preferences dialog | restores compiled-in defaults into the widgets; still needs Apply or OK |
| Window positions | Window → Reset Window Positions | discards saved dialog geometry and gathers open windows back onto the main window's screen |
Reset Window Positions deliberately removes only the geometry key under each saved dialog group — splitter, header, tab, page and toggle state are kept — and clears the main window's saved geometry while leaving the dock and toolbar layout alone.
The legend overlay has its own Reset layout on its context menu.
For a full reset, delete the application's settings store:
| Platform | Location |
|---|---|
| macOS | ~/Library/Preferences/<reversed-domain>.OpenSWMM Stormwater Management Model.plist |
| Windows | HKEY_CURRENT_USER\Software\hydrocouple\OpenSWMM Stormwater Management Model |
| Linux | ~/.config/hydrocouple/OpenSWMM Stormwater Management Model.conf |
The key groups you will find there are SWMMVis/Preferences/…, Dialogs/<dialog>/…, SWMMVis::MainWindow/…, SWMMVis::Shortcuts/… and Window/DialogStacking. Deleting a single group is a targeted reset — for example, dropping SWMMVis::Shortcuts restores every default shortcut.
On macOS, if a dialog stacks behind the main window (or refuses to), override the stacking mode with OPENSWMM_DIALOG_STACKING=qt or =native.
Issues go to https://github.com/HydroCouple/openswmm.engine/issues, which is also the Report an Issue link on the Welcome page.
Include:
SWMM_LOG_FILE=1 and attach the file..rpt is usually decisive..inp plus any sidecars it references, zipped.
SWMM_LOG_FILE before you start.MINIMUM_STEP, MAX_TRIALS, HEAD_TOLERANCE), not an end-of-run surprise. The Simulation Status panel polls it live, so watch it.NORMAL_FLOW 2D boundary with slope 0 behaves as a wall. If water will not leave a boundary you configured, check the slope first..2dm twice produces different bytes each time, because the vertex-node map is written in hash order. That is expected version-control noise, not corruption.