core (src/core, no Qt): the section-preserving input document, the column schemas of EPANET and SWMM sections, the network model used for drawing and editing, feature detection, units, the results model and the .anr results format, readers for EPANET and SWMM binary output, coordinate reference systems (Crs.h: EPSG table, WKT and PROJ parsing, Transverse Mercator, Lambert conformal conic, Albers, Mercator and polar stereographic projections), rasters (Raster.h: GeoTIFF and ESRI ASCII grid readers with lazy, cached block access and bilinear sampling; Inflate.h: the Deflate decoder they use), node elevations from a DEM (Elevation.h), the network graph with upstream, downstream and connected traces and shortest paths (Network.h), element geometry, region selection and geodesic measurement (Geometry.h), query expressions over element properties and results (Query.h), map edits such as splitting a pipe or conduit and reversing a link (Editing.h), and calibration support (Calibration.h: observed-data readers, time alignment, goodness-of-fit metrics and model parameters; Optimizer.h: Dynamically Dimensioned Search and Latin hypercube sampling). It also holds the GIF89a encoder and decoder of the results animation (Gif.h: median-cut palettes, ordered dithering, LZW, changed-rectangle frames) and the page geometry of print layouts with the project and run summaries of report documents (PrintLayout.h). The link between a water and a sewer model (Linkage.h) matches EPANET junctions to SWMM nodes and turns their water use into dry-weather inflows and patterns. Scenarios (Scenario.h) hold row keys, differences between input documents, the application of scenario chains with conflict reports, and the figures of scenario comparisons.
engine (src/engine, no Qt): the Engine interface, the registry with each engine's capability manifest, discovery of engine libraries, compatibility checking and input preparation, and one adapter per engine family.
resilience (src/resilience, no Qt): the five analyses.
interop (src/interop, no Qt): GIS layers, GeoJSON and GeoPackage writers (on the bundled SQLite), WNTR conversion, and importers for shapefiles, DXF and CSV (Import.h) that build network elements with field mapping and snapping. WaterLink.h reads the files a water-sewer link refers to (the EPANET model, its results and service-area polygons).
cli (src/cli): the mirab-cli program. It is both the user's command-line tool and the solver process used by the desktop application. calibrate (Calibrate.cpp) runs the model many times, each run in a child mirab-cli run process, several in parallel. Its --json output (cli.md) is the interface for scripts.
Python package (integrations/python, outside the build): the mirab package for scripts. It calls mirab-cli (model get/model set on the JSON view of core/ModelJson.h, run --machine for runs) and reads .anr files itself, so the application and the CLI never depend on Python. See python.md and cli.md.
app (src/app): the Qt 6 Widgets application: main window and docks, map (MapView, with the Basemap tile layer for XYZ, WMS and WMTS services, MapServices for their capabilities, and RasterLayers for DEM and image layers), reports, data editors, import dialog, the deliverables (print layouts in LayoutDialog, report documents in ReportExport, the results animation in AnimationExport, with map furniture in MapDecorations), the light theme and icon set drawn in code (Theme, Icons), and the interface languages (Language: translators compiled into the program, right-to-left layout, and coreText() for texts of the Qt-free libraries, which stay English inside the libraries and are listed for translation in CoreStrings.cpp). MapView::render() draws the current view and its raster layers into any painter, so the screen, PDF, PNG, printer and GIF frames share one drawing code; painter units are 1/96 inch everywhere.
The input file is the model. Mirab edits .inp files through a document that keeps every line, comment and section order. Only rows the user edits change. Anything Mirab does not model in detail can still be edited in the text view. Settings that engines do not read live in a sidecar JSON file.
Schemas instead of hand-written forms. Each section is described once (columns, units, references, row variants such as inlet types, repeated column groups such as land use coverages). Sections that define named objects (SWMM pollutants, land uses, aquifers, ...) say so in the schema. The property editor, the object editor, renaming, deletion, GIS export and validation all use the same description.
Engines are plug-in libraries. They are loaded with LoadLibraryEx/dlopen and bound by symbol name. EPANET uses the thread-safe EN_ API; EPANET-MSX uses its toolkit plus the legacy API of its companion EPANET library; SWMM uses its stepping API and the binary output file; SWMM5+ uses the swmm5plus-capi interface with a progress callback.
Process isolation. The desktop process never loads an engine; see engines.md.
Scenarios are differences. A scenario stores changes keyed by section, row key and column, relative to the base model or a parent scenario, in the settings file. ProjectDocument keeps the base model and shows the active scenario's model; after each edit it compares that model with the parent's and stores the result as the scenario's changes, so every editor records into scenarios without knowing about them. Undo commands hold the scenario's changes (or the base text) before and after the edit.
Live results. Engines hand each reporting period to a paced frame callback (RunCallbacks::frame) and wait between time steps while paused (RunCallbacks::checkpoint). mirab-cli streams the frames as compact binary events (core/LiveResults.h, file-formats.md); SolverProcess grows an in-memory result set from them that ProjectDocument shows until the saved results replace it.
No Python on the user side. WNTR interoperability is by file format; resilience metrics are native.
QGIS is a neighbour, not a dependency. Mirab writes GeoPackage files and starts QGIS as a separate program.