![]() |
OpenSWMM Engine
6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
|
Namespaces | |
| namespace | diffusive |
| namespace | gpu |
| namespace | inertial |
| namespace | report2d |
| Dataset groups the 2D results writer can emit ([2D_OPTIONS] REPORT_2D_VARIABLES). One bit per group; the tokens are the names below. Unselected groups are NOT created in the file, so readers treat every time-varying dataset as optional. | |
| namespace | sigma |
| namespace | soil |
| namespace | swe |
Classes | |
| struct | BoundaryData |
| SoA storage for per-edge boundary conditions. More... | |
| struct | CouplingPoint |
| Descriptor for a single coupling point between 2D and 1D. More... | |
| class | ExplicitInertialSolver |
| struct | GwAquiferRow |
| struct | GwBoundaryQualityRow |
One [GW_BOUNDARY_QUALITY] row — a lateral edge BC. More... | |
| struct | GwInitialQualityRow |
One [GW_INITIAL_QUALITY] row. More... | |
| struct | GwNodeBed |
| struct | GwOptions |
[2D_AQUIFER_OPTIONS]. Defaults are the plan's starred values. More... | |
| struct | GwParamsRow |
One [GW_TRANSPORT_PARAMS] row: solute + thermal matrix properties. More... | |
| struct | GwSorptionRow |
One [GW_SORPTION] row: retardation input for one species in one scope. More... | |
| struct | GwSourceRow |
One [GW_SOURCES] row — a well / point source or sink. More... | |
| struct | GwSourceSpeciesTerm |
One [GW_SOURCES] species term. More... | |
| struct | GwTransportData |
Every [GW_*] authoring row of one model. More... | |
| struct | GwTransportOptions |
| struct | GwUnitFactors |
| Project-unit → SI multipliers for the four kinds of aquifer number. More... | |
| struct | InertialEdges |
| Canonical unique interior-edge layout + per-cell incidence for the local-inertial scheme. More... | |
| class | Infil2D |
| Owns per-cell infiltration parameters, kernel state and held rates. More... | |
| struct | Infil2DDefault |
| struct | Infil2DOptions |
[2D_INFILTRATION_OPTIONS]. More... | |
| struct | Infil2DOverride |
One [2D_INFILTRATION] per-cell override row. More... | |
| struct | Infil2DRow |
| One infiltration specification: method + positional parameters + destination. More... | |
| class | ISurfaceSolver |
| Abstract time integrator for the 2D surface-routing ODE system. More... | |
| struct | MeshData |
| SoA storage for 2D mixed triangle/quad mesh geometry and topology. More... | |
| struct | NodeData |
| Structure-of-Arrays storage for all nodes. More... | |
| struct | PendingBoundaryQualityRow |
| struct | PendingBoundaryRow |
Per-row buffer for [2D_BOUNDARY_CONDITIONS] parse output. More... | |
| struct | PendingEdgeConveyanceRow |
Per-row buffer for [2D_EDGE_CONVEYANCE] parse output (§11A). More... | |
| struct | PendingInitialQualityRow |
One [2D_INITIAL_QUALITY] row (overland transport S1/S2). More... | |
| class | RainfallInterpolator |
| Builds and applies static rainfall-interpolation weights for the mesh. More... | |
| struct | SolverOptions2D |
| Configuration for the 2D surface routing solver. More... | |
| struct | SubsurfaceConfig |
| Everything the parser fills, before resolution onto cells. More... | |
| class | SubsurfaceSolver |
| The two-zone kernel. Owned by SurfaceRouter2D; driven by the marcher's tier hooks. More... | |
| struct | SubsurfaceState |
| Per-cell resolved parameters and state (SoA). More... | |
| class | SurfaceRouter2D |
| Top-level orchestrator for the 2D surface routing module. More... | |
| struct | SurfaceStateData |
| struct | SurfaceTransportState |
Enumerations | |
| enum class | BoundaryType : int8_t { WALL = 0 , NORMAL_FLOW = 1 , SPECIFIED_STAGE = 2 , SPECIFIED_FLOW = 3 , RATING_CURVE = 4 } |
| Boundary condition types for 2D mesh edges. More... | |
| enum class | CellClosure2D : int8_t { FLAT = 0 , VFR = 1 } |
| Volume → free-surface closure for a 2D cell. More... | |
| enum class | FaceDepth2D : int8_t { MEAN = 0 , VFR_FACE = 1 } |
| Effective conveyance depth at a shared edge for the diffusive-wave flux. More... | |
| enum class | RainfallMode : int8_t { NATURAL_NEIGHBOUR = 0 , SYSTEM = 1 , NONE = 2 } |
| How raingage rainfall is mapped onto the 2D mesh cells. More... | |
| enum class | Backend2D : int8_t { CPU = 0 , AUTO = 1 , OMP = 2 , CUDA = 3 , HIP = 4 , SYCL = 5 } |
| Compute backend for the 2D marcher (mirrors fv::Backend). More... | |
| enum class | Momentum2D : int8_t { LOCAL_INERTIAL = 0 , FULL_SWE = 1 , DIFFUSIVE_WAVE = 2 } |
| Momentum closure of the explicit 2D marcher (2D_FULL_SWE_SHOCK_CAPTURING_PLAN_2026-09-05 §2). More... | |
| enum class | OutputPrecision2D : int8_t { FLOAT32 = 0 , FLOAT64 = 1 } |
| Storage precision of the 2D results file's time-varying datasets ([2D_OPTIONS] OUTPUT_PRECISION). Mesh geometry always stays float64: projected coordinates are O(1e6) m and float32 would lose centimetres there; depth/velocity fields have no such offset. More... | |
| enum class | GwZone : int8_t { SAT = 0 , UNSAT = 1 , LAYER = 2 } |
| Which zone of the two-zone column a row addresses. More... | |
| enum class | GwScope : int8_t { GLOBAL = 0 , TAG = 1 , CELL = 2 } |
| Scope of a per-cell row. More... | |
| enum class | Infil2DDest : int { LOST = 0 , SUBCATCH_AQUIFER = 1 , AQUIFER_2D = 2 } |
| enum class | Infil2DProvenance : std::uint8_t { NONE = 0 , STAR = 1 , TAG = 2 , OVERRIDE = 3 } |
| enum class | SoilChar : int8_t { RUSSO = 0 , GARDNER = 1 , BROOKS_COREY = 2 , VAN_GENUCHTEN = 3 } |
| enum class | GwClosure : int8_t { AUTO = -1 , CLOSED_FORM = 0 , ENSLAVED = 1 , SIGMA = 2 } |
| Unsaturated-zone closure, resolved per cell from AUTO at initialize. More... | |
Functions | |
| double | computeNodeCouplingQ (const CouplingPoint &cp, const MeshData &mesh, const SurfaceStateData &state, const NodeData &nodes, const SolverOptions2D &opts, const double *provisional_vol_m3=nullptr, double h1d_offset_m=0.0) noexcept |
| Live node-coupling orifice flux for ONE non-outfall coupling point. | |
| double | computeNodeCouplingDQdh1d (const CouplingPoint &cp, const MeshData &mesh, const SurfaceStateData &state, const NodeData &nodes, const SolverOptions2D &opts) noexcept |
| Head sensitivity G = −∂Q/∂h_1d ≥ 0 of the coupling orifice at a point (SI: m³/s per m of 1D head, with h_1d in 2D metres). | |
| void | scatterCouplingToYdot (const MeshData &mesh, const SurfaceStateData &state, const CouplingPoint &cp, double Q, double *ydot) noexcept |
| Scatter a signed volumetric exchange Q (m³/s) directly onto the cell derivatives ydot[] of the 2D volume ODE (for the live-RHS path). | |
| std::vector< CouplingPoint > | buildCouplingPoints (const MeshData &mesh, const SimulationContext &ctx) |
| Build the list of coupling points from mesh coupling maps. | |
| void | updateOutfallBoundaries (const std::vector< CouplingPoint > &cps, const MeshData &mesh, const SurfaceStateData &state, SimulationContext &ctx, const SolverOptions2D &opts) |
| Update outfall boundary depths from 2D surface heads. | |
| int | accumulateOutfallDischargeStep (const std::vector< CouplingPoint > &cps, const MeshData &mesh, const SurfaceStateData &state, const SimulationContext &ctx, const SolverOptions2D &opts, double dt, std::vector< double > &accum_m3, std::vector< double > &cell_budget_m3, double *sample_row) |
| Per-routing-step outfall discharge accumulation. | |
| void | injectAccumulatedExchange (const std::vector< CouplingPoint > &cps, const MeshData &mesh, SurfaceStateData &state, const std::vector< double > &accum_m3, double window_dt, double sign, const std::vector< double > *node_conc=nullptr) |
| Inject a per-point accumulated exchange volume into the 2D window source field. | |
| std::vector< PendingBoundaryRow > | collectBCRows (const std::vector< PendingBoundaryRow > *pending, const BoundaryData *boundary, bool drained, double flow_to_si_applied=1.0) |
Collect [2D_BOUNDARY_CONDITIONS]-shaped rows for serialization. | |
| std::vector< PendingEdgeConveyanceRow > | collectConveyanceRows (const std::vector< PendingEdgeConveyanceRow > *pending, const MeshData *mesh, bool drained) |
Collect [2D_EDGE_CONVEYANCE]-shaped rows for serialization. | |
| const char * | gwZoneToken (GwZone z) noexcept |
| bool | parseGwZone (const std::string &token, GwZone &z) noexcept |
| const char * | gwScopeToken (GwScope s) noexcept |
| std::string | parseGwTransportOptionsLine (const std::vector< std::string > &tokens, GwTransportOptions &opts) |
One [GW_TRANSPORT_OPTIONS] line (KEY VALUE [ARG…]). Empty = OK. | |
| std::string | parseGwParamsLine (const std::vector< std::string > &tokens, std::vector< GwParamsRow > &rows) |
| std::string | parseGwSorptionLine (const std::vector< std::string > &tokens, std::vector< GwSorptionRow > &rows) |
One [GW_SORPTION] line: scope, SPECIES, Kd [decay]. Empty = OK. | |
| std::string | parseGwInitialQualityLine (const std::vector< std::string > &tokens, std::vector< GwInitialQualityRow > &rows, std::string &file) |
| std::string | parseGwBoundaryQualityLine (const std::vector< std::string > &tokens, std::vector< GwBoundaryQualityRow > &rows) |
| std::string | parseGwSourcesLine (const std::vector< std::string > &tokens, std::vector< GwSourceRow > &rows) |
| void | registerGwTransportSections (GwTransportData &gw, input::SectionRegistry ®istry) |
Register every [GW_*] handler against registry, writing into gw. | |
| std::vector< std::string > | resolveGwTransport (SimulationContext &ctx, const MeshData &mesh, GwTransportData &gw) |
| Validate the authored rows against the model and the species registry, once the mesh and the species are final. | |
| std::string | gwTransportInertWarning (const GwTransportData &gw) |
| bool | parseInfil2DMethod (const std::string &token, InfilModel &method, bool &has_method) |
| const char * | infil2DMethodToken (const Infil2DRow &row) |
| Inverse of parseInfil2DMethod — the canonical file token. | |
| bool | parseInfil2DDest (const std::string &token, Infil2DDest &dest) |
| Parse a destination token. | |
| const char * | infil2DDestToken (Infil2DDest dest) |
| Inverse of parseInfil2DDest. | |
| int | infil2DParamCount (InfilModel method) |
| std::string | parse2DOptionsLine (const std::vector< std::string > &tokens, SolverOptions2D &opts, std::vector< std::string > *warnings=nullptr) |
| Parse a single line from the [2D_OPTIONS] section. | |
| bool | is2DRetiredOptionKey (const std::string &key) |
True when key (case-insensitive) is a [2D_OPTIONS] parameter retired with the CVODE/ARKODE stack (D2, 2026-07-29). | |
| bool | is2DOptionKey (const std::string &key) |
True when key (case-insensitive) is a [2D_OPTIONS] parameter accepted by parse2DOptionsLine. | |
| const std::vector< std::string > & | report2DVarTokens () |
| Format the current value of a [2D_OPTIONS] parameter as the string token parse2DOptionsLine accepts (round-trip safe). | |
| std::string | parseReport2DVars (const std::string &text, unsigned &mask) |
| std::string | formatReport2DVars (unsigned mask) |
| std::string | format2DOptionValue (const SolverOptions2D &opts, const std::string &key) |
| std::string | format2DOptionValueEx (const SolverOptions2D &opts, const Infil2D *infil, const std::string &key) |
format2DOptionValue with the E2 infiltration keys resolved against the model's [2D_INFILTRATION*] rows: INFIL_STEP falls back to the section value, INFIL_DEFAULT_METHOD to the '*' row's method. INFILTRATION stays AUTO | YES | NO as stored. infil may be null. | |
| std::string | format2DOptionValueEx (const SolverOptions2D &opts, const Infil2D *infil, const SubsurfaceConfig *aquifer, const std::string &key) |
As above, and additionally resolves the groundwater enables against the [2D_AQUIFER*] authoring: GROUNDWATER AUTO reports the YES|NO the kernel will actually take, and GW_ET reads the [2D_AQUIFER_OPTIONS] field that owns it. aquifer may be null. | |
| std::string | parse2DVertexLine (const std::vector< std::string > &tokens, MeshData &mesh) |
| Parse a single line from the [2D_VERTICES] section. | |
| std::string | parse2DTriangleLine (const std::vector< std::string > &tokens, MeshData &mesh) |
| Parse a single line from the [2D_TRIANGLES] section. | |
| std::string | parse2DQuadLine (const std::vector< std::string > &tokens, MeshData &mesh) |
| Parse a single line from the [2D_QUADS] section. | |
| std::string | parse2DInitialVelocityLine (const std::vector< std::string > &tokens, MeshData &mesh) |
| Parse a single line from the [2D_INITIAL_VELOCITY] section. | |
| std::string | parse2DVertexNodeMapLine (const std::vector< std::string > &tokens, MeshData &mesh) |
| Parse a single line from the [2D_VERTEX_NODE_MAP] section. | |
| std::string | parse2DTriangleNodeMapLine (const std::vector< std::string > &tokens, MeshData &mesh) |
| Parse a single line from the [2D_TRIANGLE_NODE_MAP] section. | |
| std::string | parse2DBoundaryConditionsLine (const std::vector< std::string > &tokens, std::vector< SurfaceRouter2D::PendingBoundaryRow > &pending_rows) |
V-E3 — parse a single line from the [2D_BOUNDARY_CONDITIONS] section into a SurfaceRouter2D::PendingBoundaryRow appended to pending_rows. | |
| std::string | parse2DEdgeConveyanceLine (const std::vector< std::string > &tokens, std::vector< SurfaceRouter2D::PendingEdgeConveyanceRow > &pending_rows) |
§11A — parse a single [2D_EDGE_CONVEYANCE] line. | |
| std::string | parse2DInfiltrationOptionsLine (const std::vector< std::string > &tokens, Infil2D &infil) |
§5.5 track I — parse a single [2D_INFILTRATION_OPTIONS] line. | |
| std::string | parse2DInfiltrationDefaultsLine (const std::vector< std::string > &tokens, Infil2D &infil) |
§5.5 track I — parse a single [2D_INFILTRATION_DEFAULTS] line. | |
| std::string | parse2DInfiltrationLine (const std::vector< std::string > &tokens, Infil2D &infil) |
§5.5 track I — parse a single [2D_INFILTRATION] line. | |
| std::string | parse2DInitialQualityLine (const std::vector< std::string > &tokens, std::vector< SurfaceRouter2D::PendingInitialQualityRow > &rows) |
S1/S2 — one [2D_INITIAL_QUALITY] line. Empty string = OK. | |
| std::string | parse2DBoundaryQualityLine (const std::vector< std::string > &tokens, std::vector< SurfaceRouter2D::PendingBoundaryQualityRow > &rows) |
S2 — one [2D_BOUNDARY_QUALITY] line (TRI EDGE SPECIES CONC). Empty = OK. | |
| void | register2DSections (MeshData &mesh, SolverOptions2D &options, std::vector< SurfaceRouter2D::PendingBoundaryRow > &pending_bc_rows, std::vector< SurfaceRouter2D::PendingEdgeConveyanceRow > &pending_ec_rows, std::vector< SurfaceRouter2D::PendingInitialQualityRow > &pending_iq_rows, std::vector< SurfaceRouter2D::PendingBoundaryQualityRow > &pending_bq_rows, input::SectionRegistry ®istry) |
| Register all 2D input section handlers with the section registry. | |
| std::string | load2DMeshExternalFile (MeshData &mesh, SolverOptions2D &opts, std::vector< SurfaceRouter2D::PendingBoundaryRow > &pending_bc_rows, std::vector< SurfaceRouter2D::PendingEdgeConveyanceRow > &pending_ec_rows, Infil2D *infil, const std::string &mesh_file, const std::string &inp_base_dir, std::vector< std::string > *warnings=nullptr, std::vector< SurfaceRouter2D::PendingInitialQualityRow > *pending_iq_rows=nullptr, std::vector< SurfaceRouter2D::PendingBoundaryQualityRow > *pending_bq_rows=nullptr) |
| Load 2D mesh sections from an external file. | |
| void | prescan2DUnitsHeader (const std::string &inp_path, SolverOptions2D &opts) |
Scan inp_path for a ;; UNITS: <value> comment header and set opts.mesh_units_si to true when the value names metres. | |
| void | buildMeshTopology (MeshData &mesh) |
| Build mesh topology and precompute geometry from raw vertex/triangle data. | |
| std::string | validateMesh (const MeshData &mesh) |
| Validate mesh data for consistency. | |
| void | recomputeVertexZDependents (MeshData &mesh, int vidx) |
| Recompute Z-derived per-triangle / per-edge geometry for triangles incident to a vertex whose Z just changed. | |
| void | recomputeAllZDependents (MeshData &mesh) |
Whole-mesh form of recomputeVertexZDependents. | |
| OPENSWMM_KERNEL_FN double | quadWetFraction (const double *zs, double A1, double A2, double eta) noexcept |
| OPENSWMM_KERNEL_FN double | quadMeanDepthFromEta (const double *zs, double A1, double A2, double eta, double eps) noexcept |
| OPENSWMM_KERNEL_FN double | quadMeanDepthSlope (const double *zs, double A1, double A2, double eta, double eps) noexcept |
| OPENSWMM_KERNEL_FN double | quadEtaFromMeanDepth (const double *zs, double A1, double A2, double mean_depth, double eps) noexcept |
| OPENSWMM_KERNEL_FN double | quadDEtaDMeanDepth (const double *zs, double A1, double A2, double eta, double eps) noexcept |
| dη/dh̄ of the regularised quad closure at stage η: 1/max(slope, eps). | |
| int | quadVfrPrecompute (const double *x, const double *y, const double *z, double *zs, double &A1, double &A2) noexcept |
| Choose the B&S 2007 diagonal for a quad and emit its precomputed VFR data. | |
| void | buildVertexStencils (MeshData &mesh) |
| Build pseudo-Laplacian reconstruction stencils for all vertices. | |
| void | reconstructVertexHeads (const MeshData &mesh, SurfaceStateData &state, int nthreads=1) |
| Reconstruct head values at vertices from cell-centred heads. | |
| double | cellFreeSurfaceElevationOf (const MeshData &mesh, int t, double mean_depth) |
| double | cellFreeSurfaceElevation (double mean_depth, double za, double zb, double zc) |
| Free-surface elevation η of one triangular cell from its mean depth (render/output closure). | |
| void | reconstructVertexRenderDepths (const MeshData &mesh, SurfaceStateData &state, double dry_depth, int nthreads, std::vector< double > &eta_scratch) |
| Wet-masked, depth-weighted free-surface reconstruction at vertices for RENDERING/OUTPUT only (writes state.vert_depth_signed). | |
| double | vertexHeadAt (const MeshData &mesh, const SurfaceStateData &state, int v) noexcept |
| Pseudo-Laplacian head at ONE vertex, evaluated on demand from the current cell heads. | |
| void | reconstructVertexRenderDepths (const MeshData &mesh, SurfaceStateData &state, double dry_depth, int nthreads=1) |
| OPENSWMM_KERNEL_FN void | vfrSort3 (double &z1, double &z2, double &z3) noexcept |
| Sort three vertex elevations in place so z1 <= z2 <= z3. | |
| OPENSWMM_KERNEL_FN double | vfrWetFraction (double z1, double z2, double z3, double eta) noexcept |
| OPENSWMM_KERNEL_FN double | vfrMeanDepthFromEtaExact (double z1, double z2, double z3, double eta) noexcept |
| OPENSWMM_KERNEL_FN double | vfrStageAtWetFraction (double z1, double z2, double z3, double eps) noexcept |
| OPENSWMM_KERNEL_FN double | vfrMeanDepthFromEta (double z1, double z2, double z3, double eta, double eps) noexcept |
| OPENSWMM_KERNEL_FN double | vfrEtaFromMeanDepth (double z1, double z2, double z3, double mean_depth, double eps) noexcept |
| OPENSWMM_KERNEL_FN double | vfrDryEta (double z1, double z2, double z3, double eps) noexcept |
| OPENSWMM_KERNEL_FN double | vfrDEtaDMeanDepth (double z1, double z2, double z3, double eta, double eps) noexcept |
| void | computeUnlimitedGradients (const MeshData &mesh, SurfaceStateData &state, int nthreads=1) |
| Compute unlimited gradients for all triangles via Green-Gauss theorem. | |
| void | computeLimitedGradients (const MeshData &mesh, SurfaceStateData &state, double epsilon, int nthreads=1) |
| Apply Jawahar-Kamath slope limiter (Eq. [23]–[24]). | |
| void | computeCellContinuity (const MeshData &mesh, SurfaceStateData &state, const SolverOptions2D &opts, double dt) |
| Compute the per-cell continuity residual (local mass-balance check). | |
| void | computeFaceVelocity (const MeshData &mesh, SurfaceStateData &state, const SolverOptions2D &opts) |
| Reconstruct cell-centred velocity (vx, vy) from edge fluxes (RT0). | |
| double | computeBoundaryEdgeFlux (const MeshData &mesh, const SurfaceStateData &state, const SolverOptions2D &opts, double dh_eps, int i, int idx) noexcept |
Boundary-edge flux for cell i across flat mesh edge slot idx (m³/s, inflow-positive). Exported wrapper over the file-local boundary kernel so non-DW solvers (the explicit marcher) evaluate the identical 5-type boundary math per substep. | |
| double | evapSink (double rate, double depth, double dry_depth) noexcept |
| Depth-limited evaporation sink rate (m/s) for one cell. | |
| double | infilSink (double rate, double depth, double dry_depth) noexcept |
| Depth-limited infiltration sink rate (m/s) for one cell (plan §5.5). | |
| std::unique_ptr< ISurfaceSolver > | makeSurfaceSolver (const SolverOptions2D &opts, std::string *chosen=nullptr, int n_cells=0, bool plugin_capable=true) |
| Construct the 2D surface solver per the runtime backend policy. | |
| const char * | soilCharToken (SoilChar s) noexcept |
| bool | parseSoilChar (const std::string &t, SoilChar &s) noexcept |
| const char * | gwClosureToken (GwClosure c) noexcept |
| bool | parseGwClosure (const std::string &t, GwClosure &c) noexcept |
| std::string | parseAquiferOptionsLine (const std::vector< std::string > &tokens, GwOptions &opts) |
One [2D_AQUIFER_OPTIONS] line (KEY VALUE). Empty return = OK. | |
| std::string | parseAquiferLine (const std::vector< std::string > &tokens, std::vector< GwAquiferRow > &rows) |
One [2D_AQUIFER] line. Empty return = OK. | |
| std::string | parseAquiferNodeLine (const std::vector< std::string > &tokens, std::vector< GwNodeBed > &beds, std::vector< std::string > &names) |
| void | registerSubsurfaceSections (SubsurfaceConfig &cfg, std::vector< std::string > &node_names, input::SectionRegistry ®istry) |
Register the three handlers against registry, writing into cfg. | |
| GwUnitFactors | gwUnitFactors (const SimulationContext &ctx) noexcept |
| The factors for this project's unit system. | |
| std::vector< std::string > | resolveSubsurface (SimulationContext &ctx, const MeshData &mesh, SubsurfaceConfig &cfg, const std::vector< std::string > &names) |
| void | writeSubsurfaceSections (const SubsurfaceConfig &cfg, const std::vector< std::string > &node_names, std::string &out) |
| OPENSWMM_KERNEL_FN double | faceDepthFromEta (double eta, double z_lo, double z_hi) noexcept |
Variables | |
| constexpr int | kMaxCellVerts = 4 |
| constexpr int | kInfil2DMaxParams = 5 |
| constexpr int | kQuadVfrZ = 6 |
| constexpr double | kVfrFlatRelief = 1.0e-9 |
|
strong |
Compute backend for the 2D marcher (mirrors fv::Backend).
AUTO (default) lets SurfaceSolverFactory pick: a device plugin (cuda, hip, sycl) above the device mesh-size floor, the OpenMP plugin above its own (higher) floor, else the built-in CPU marcher. The named values request one backend outright and bypass the size floors; a plugin that is absent or has no usable device falls back to CPU with a stderr notice, never a hard fail. The OPENSWMM_2D_BACKEND environment variable, when set, overrides this option (same precedence as OPENSWMM_FV_BACKEND over FV_BACKEND).
Parsed from [2D_OPTIONS] BACKEND (AUTO|CPU|OMP|CUDA|HIP|SYCL).
|
strong |
Boundary condition types for 2D mesh edges.
SPECIFIED_FLOW (3) and RATING_CURVE (4) added per GUI plan §V V-E4 / V-E5. All five types are enforced at flux time by the explicit marcher via SurfaceFluxCalculator::boundaryEdgeFlux (and the Kokkos backend's device-side equivalent); time-varying values are resolved each step in SurfaceRouter2D::resolveBoundaryValues.
|
strong |
Volume → free-surface closure for a 2D cell.
FLAT (default, legacy) reconstructs η = tri_cz + V/A — exact only for a fully wetted cell. On a partially wet (slope/step-spanning) cell it overstates η by up to two-thirds of the cell relief, which is the driver of the water-climbs-uphill artifact (spurious head pushes thin films upslope; lake-at-rest is not a steady state at shorelines).
VFR reconstructs η from the exact stage–storage relation of the plane bed through the cell's three vertex elevations (Begnudelli & Sanders 2006/2007 volume/free-surface relationships), C¹-regularized by a wetted-area-fraction floor (VFR_MIN_WET_FRAC). Restores the C-property at shorelines. CPU solver only; the Kokkos GPU backends degrade to FLAT with a one-line notice until ported.
Parsed from [2D_OPTIONS] CELL_CLOSURE (FLAT|VFR). See plans/2d/2D_VFR_SOLVER_CLOSURE_PLAN.md.
| Enumerator | |
|---|---|
| FLAT | Legacy flat-cell closure η = tri_cz + V/A (default). |
| VFR | Planar-bed VFR closure (regularized), CPU solvers only. |
|
strong |
Effective conveyance depth at a shared edge for the diffusive-wave flux.
MEAN (default, legacy) uses the upwind cell's MEAN depth V/A — blind to where the waterline sits relative to the edge, so a cell with water pooled in its low corner can discharge across an edge whose bed is entirely above the waterline (uphill creep), and drainage strands water on slopes.
VFR_FACE reconstructs the depth at the edge from the upwind free surface and the edge's two endpoint bed elevations (Begnudelli & Sanders 2007, Eq. 14, adapted as the Manning conveyance depth): zero when the upwind surface is below the whole edge (no flow — the wetting gate), the exact partially-submerged mean when the waterline crosses the edge. C¹ in η.
Scope per solver path: BOUNDARY edges honour the mode in SurfaceFluxCalculator::boundaryEdgeFlux. Under the explicit local-inertial marcher, VFR_FACE also governs INTERIOR faces: the face flow depth becomes faceFlowDepthVfr(η_L, η_R, ze_lo, ze_hi) — the Eq. 14 wetted-edge depth of the driving surface over the shared edge's TRUE endpoint beds — so thin crests (embankments/levees/road crowns resolved as lines of high vertices) block until the water genuinely reaches the crest instead of the centroid-diluted zface (≈ ⅓-height early overtopping). MEAN keeps the legacy centroid zface bit-identical on interior faces.
Parsed from [2D_OPTIONS] FACE_RECONSTRUCTION (MEAN|VFR_FACE). See plans/2d/2D_VFR_SOLVER_CLOSURE_PLAN.md.
| Enumerator | |
|---|---|
| MEAN | Legacy: upwind cell-mean depth (default). |
| VFR_FACE | B&S Eq. 14 face depth + wetting gate. |
|
strong |
|
strong |
|
strong |
|
strong |
Destination of infiltrated water. D-I4 as amended by U3 and G1: LOST and SUBCATCH_AQUIFER are routed, and AQUIFER_2D is accepted once a [2D_AQUIFER] section resolves — without one it is still refused, with a message naming the section to add.
[2D_AQUIFER] present the aquifer OWNS infiltration: every infiltrating cell recharges it and LOST reads as AQUIFER_2D. That is what a user means by putting an aquifer under the mesh, and it keeps the water to one owner. SUBCATCH_AQUIFER is the one destination that cannot coexist with it, for the same one-owner reason the integrated component conflict already states — see SurfaceRouter2D::initialize. | Enumerator | |
|---|---|
| LOST | Leaves the domain; booked to MassBalance2D::infil_out. |
| SUBCATCH_AQUIFER | Legacy subcatchment aquifer (U3 track I-b) |
| AQUIFER_2D | The two-zone 2D kernel (G1 step 11b) |
|
strong |
|
strong |
Momentum closure of the explicit 2D marcher (2D_FULL_SWE_SHOCK_CAPTURING_PLAN_2026-09-05 §2).
Parsed from [2D_OPTIONS] MOMENTUM_EQUATION. One marcher (tiered LTS, active sets, positivity, coupling, transport) with three face laws:
| Enumerator | |
|---|---|
| LOCAL_INERTIAL | |
| FULL_SWE | |
| DIFFUSIVE_WAVE | |
|
strong |
Storage precision of the 2D results file's time-varying datasets ([2D_OPTIONS] OUTPUT_PRECISION). Mesh geometry always stays float64: projected coordinates are O(1e6) m and float32 would lose centimetres there; depth/velocity fields have no such offset.
| Enumerator | |
|---|---|
| FLOAT32 | default — halves the file, ~7 significant digits |
| FLOAT64 | bit-for-bit parity tooling |
|
strong |
How raingage rainfall is mapped onto the 2D mesh cells.
NATURAL_NEIGHBOUR (default) spatially interpolates the located raingages onto every cell centroid — natural-neighbour (Laplace) weights inside the convex hull of the gages, inverse-distance (power 2) extrapolation outside it. The weights are precomputed once in SurfaceRouter2D::initialize() (gage positions are static for a run) and applied each step as a sparse weighted sum.
SYSTEM applies one uniform value to all cells: the arithmetic mean of every gage's current rainfall. It is also the automatic fallback when no gage has a map location (no [SYMBOLS] coordinate), since interpolation is then undefined.
Parsed from [2D_OPTIONS] RAINFALL_MODE; env OPENSWMM_2D_RAINFALL_MODE (natural|system) overrides at initialize().
|
strong |
Soil-characteristic law: how K(ψ) and θ(ψ) are shaped. (Draft plan §2.5. Broadbridge–White is verification-only and is not a production selection — it lives in the test harness, not here.)
| int openswmm::twoD::accumulateOutfallDischargeStep | ( | const std::vector< CouplingPoint > & | cps, |
| const MeshData & | mesh, | ||
| const SurfaceStateData & | state, | ||
| const SimulationContext & | ctx, | ||
| const SolverOptions2D & | opts, | ||
| double | dt, | ||
| std::vector< double > & | accum_m3, | ||
| std::vector< double > & | cell_budget_m3, | ||
| double * | sample_row ) |
Per-routing-step outfall discharge accumulation.
Per-step successor of the retired transferOutfallDischarges: samples the LIVE net outfall exchange (nodes.inflow − nodes.outflow, this routing step) and accumulates Q_net·dt (m³, + = 1D discharge onto the 2D surface, − = surface water drawn back through the outfall) into accum_m3[k]. Withdrawals are capped by the shared per-cell budget so the accumulated window sink cannot overdraw the frozen 2D state.
| sample_row | Optional (nullable): net 2D-source rate row for the interpolated-forcing series — this step's capped Q_net written as +Q_net into sample_row[k] (already source-positive). Junction slots left untouched. |
| std::vector< CouplingPoint > openswmm::twoD::buildCouplingPoints | ( | const MeshData & | mesh, |
| const SimulationContext & | ctx ) |
Build the list of coupling points from mesh coupling maps.
Resolves vertex/triangle → node mappings into CouplingPoint descriptors. Must be called after node names are resolved to indices.
| mesh | Mesh data with coupling maps populated. |
| ctx | Simulation context (for node type and outfall queries). |
| void openswmm::twoD::buildMeshTopology | ( | MeshData & | mesh | ) |
Build mesh topology and precompute geometry from raw vertex/triangle data.
Must be called after parsing is complete and before solver initialization. Populates: tri_nbr*, tri_area, tri_c*, edge_length, edge_n*, edge_m*.
| mesh | The mesh data with vx/vy/vz and tri_v0/v1/v2 already populated. |
| void openswmm::twoD::buildVertexStencils | ( | MeshData & | mesh | ) |
Build pseudo-Laplacian reconstruction stencils for all vertices.
For each vertex, collects all triangles sharing that vertex, computes moments (I_xx, I_yy, I_xy, R_x, R_y), Lagrange multipliers (λ_x, λ_y), and weights. Stores results in mesh.vert_stencil_ptr/idx/wt (CSR format).
| mesh | The mesh (must have topology already built). |
| double openswmm::twoD::cellFreeSurfaceElevation | ( | double | mean_depth, |
| double | za, | ||
| double | zb, | ||
| double | zc ) |
Free-surface elevation η of one triangular cell from its mean depth (render/output closure).
Inverts the stage–storage relation V(η) of a cell whose bed is the plane through its three vertex elevations. For a partially wet cell (η below the highest vertex) this places the free surface over the wetted fraction only, instead of the flat-cell closure η = z̄ + h̄ which overstates η on cells spanning a bed step. Fully wet cells reduce exactly to η = z̄ + h̄ (tri_cz is the vertex-elevation mean), so the closure is continuous and consistent with the solver's conserved volume V = A·h̄.
Piecewise in η with sorted vertex elevations z1 ≤ z2 ≤ z3: z1 < η ≤ z2 : h̄(η) = (η−z1)³ / (3(z2−z1)(z3−z1)) (closed form) z2 < η ≤ z3 : h̄(η) = (η−z̄) + (z3−η)³ / (3(z3−z1)(z3−z2)) (safeguarded Newton) η ≥ z3 : h̄(η) = η − z̄ (flat)
| mean_depth | Cell mean depth h̄ = V/A (m), ≥ 0. |
| za,zb,zc | The cell's three vertex elevations (any order). |
| double openswmm::twoD::cellFreeSurfaceElevationOf | ( | const MeshData & | mesh, |
| int | t, | ||
| double | mean_depth ) |
Cell-shape-aware form: triangle → cellFreeSurfaceElevation over the three vertex beds; quad → the B&S 2007 two-plane closure (mesh/QuadVfr.hpp).
|
inline |
Collect [2D_BOUNDARY_CONDITIONS]-shaped rows for serialization.
| pending | Parse-time pending rows (may be null/empty). |
| boundary | Drained per-edge BC storage (may be null/unsized). |
| drained | SolverOptions2D::pending_rows_drained — true once initialize() moved the pending rows into boundary. |
| flow_to_si_applied | SolverOptions2D::bc_flow_to_si_applied — the display-flow → m³/s factor initialize() scaled the constant SPECIFIED_FLOW values by (1.0 when it has not run). The file contract is display flow units per metre, so constant flows read from boundary are divided by it. Constant STAGE heads need no such treatment: they follow the mesh scaling, and the ;; UNITS: SI (m) header the writer emits covers them. |
|
inline |
Collect [2D_EDGE_CONVEYANCE]-shaped rows for serialization.
| pending | Parse-time pending rows (may be null/empty). |
| mesh | Mesh whose edge_conveyance slots hold the drained values (may be null). |
| drained | SolverOptions2D::pending_rows_drained — true once initialize() moved the pending rows into the mesh slots. |
|
noexcept |
Boundary-edge flux for cell i across flat mesh edge slot idx (m³/s, inflow-positive). Exported wrapper over the file-local boundary kernel so non-DW solvers (the explicit marcher) evaluate the identical 5-type boundary math per substep.
| void openswmm::twoD::computeCellContinuity | ( | const MeshData & | mesh, |
| SurfaceStateData & | state, | ||
| const SolverOptions2D & | opts, | ||
| double | dt ) |
Compute the per-cell continuity residual (local mass-balance check).
Evaluates the discrete semi-discrete balance for each cell: residual_i = (ψ_i − ψ_old_i)·A_i/dt − ( Σ_e F_e + (rainfall_i + coupling_flux_i − evapSink_i − infilSink_i)·A_i ) where F_e = edge_flux[i·3+e] is the inflow-positive volumetric edge flux (m³/s). A perfectly conservative step yields ~0 (first-order diagnostic, not the solver's internal error). Reads old_depth, depth, edge_flux, rainfall, evap_rate, infil_rate, coupling_flux; writes cell_continuity_err (m³/s).
Call AFTER the solver advance, with old_depth holding the start-of-step depths (i.e. after save_state() but before the next save_state()).
| mesh | Mesh geometry (tri_area). |
| state | Surface state (writes cell_continuity_err). |
| opts | Solver options (dry_depth for the evaporation ramp). |
| dt | Step over which old_depth→depth evolved (s). |
| void openswmm::twoD::computeFaceVelocity | ( | const MeshData & | mesh, |
| SurfaceStateData & | state, | ||
| const SolverOptions2D & | opts ) |
Reconstruct cell-centred velocity (vx, vy) from edge fluxes (RT0).
For each wet cell, solves the 3×2 least-squares system N·q ≈ b in closed form via the normal equations (NᵀN)·q = Nᵀb, where each row of N is the outward edge normal and b_e = edge_flux_e / edge_length_e is the depth-integrated normal speed (m²/s). The resulting specific-discharge vector is divided by cell depth to give velocity (m/s). Dry cells (depth < dry_depth) get zero velocity. Mirrors the GUI RT0 reconstruction (swmm2dresultslayer.cpp applyCurrentFlux_) without its scene-space Y-flip.
| mesh | Mesh geometry (edge normals, lengths). |
| state | Surface state (reads edge_flux, depth; writes face_vx/face_vy). |
| opts | Solver options (dry_depth). |
| void openswmm::twoD::computeLimitedGradients | ( | const MeshData & | mesh, |
| SurfaceStateData & | state, | ||
| double | epsilon, | ||
| int | nthreads = 1 ) |
Apply Jawahar-Kamath slope limiter (Eq. [23]–[24]).
Computes continuously differentiable limited gradients from the unlimited gradients of a cell and its neighbours.
| mesh | Mesh geometry (for neighbour lookup). |
| state | Surface state (reads grad_hx/hy, writes grad_hx_lim/hy_lim). |
| epsilon | Limiter epsilon (small positive, typically 1e-6). |
| nthreads | OpenMP thread count for the per-cell loop (1 = serial). |
|
noexcept |
Head sensitivity G = −∂Q/∂h_1d ≥ 0 of the coupling orifice at a point (SI: m³/s per m of 1D head, with h_1d in 2D metres).
Windowless-coupling stabilizer (2026-07-29 plan §5.4): scattered into the dynamic-wave node continuity denominator (sumdqdh) each Picard iteration so the exchange stops being a zero-sensitivity explicit source — the measured fix for drain/spill iteration churn. Gate/ramp derivative terms are dropped to guarantee G ≥ 0 (pure damping; the denominator can only grow).
|
noexcept |
Live node-coupling orifice flux for ONE non-outfall coupling point.
Evaluates the bidirectional capped-pipe orifice exchange Q (m³/s; > 0 drains 2D → 1D, < 0 spills 1D → 2D) from the CURRENT 2D state (head/depth/vert_head, reconstructed live inside the CVODE RHS) against the 1D node head, which is frozen for the duration of a 2D advance() window. Unlike the retired computeCouplingExchange (which pre-computed a HELD flux per window and capped it by available volume / dt to stop a held drain overshooting), this is the continuous form for use inside the RHS: the orifice + capped-pipe gate + the wet/dry Hermite ramp on the LIVE source-side depth make Q self-limit smoothly as the cell drains, so CVODE integrates the stiff coupling implicitly and stably across a large macro-window — no discrete avail/dt cap needed.
Booking/conservation is handled by the caller integrating ∫Q dt (a per-point accumulator carried in the augmented state vector) over the window.
| provisional_vol_m3 | Optional per-cell volume (m³) overriding the 2D state's own depth/head for the driving-head and wet/dry-ramp terms. nullptr on the live-RHS path (CVODE's state is already current). The per-routing-step decoupled path passes the window's remaining withdrawal budget so the exchange self-limits as the surface drains provisionally — without it the frozen window state makes the same full-rate drain repeat every sub-step and the window's total exchange scales with the number of routing steps in it. |
| void openswmm::twoD::computeUnlimitedGradients | ( | const MeshData & | mesh, |
| SurfaceStateData & | state, | ||
| int | nthreads = 1 ) |
Compute unlimited gradients for all triangles via Green-Gauss theorem.
For each triangle, the gradient is the area-weighted average of edge contributions: ∇h_i = (1/A_i) Σ_j h_edge_j * n_j * ξ_j
| mesh | Mesh geometry. |
| state | Surface state (reads head[], writes grad_hx[], grad_hy[]). |
| nthreads | OpenMP thread count for the per-cell loop (1 = serial). |
|
inlinenoexcept |
Depth-limited evaporation sink rate (m/s) for one cell.
Reuses the cubic Hermite wet/dry ramp applied to edge fluxes: the full demand rate applies for depth ≥ dry_depth and shuts off smoothly (C¹) as the cell dries, so evaporation can never drive a depth negative. Negative rates are treated as zero (no condensation source — use rainfall).
| rate | Evaporation demand rate (m/s). |
| depth | Current cell depth (m). |
| dry_depth | Dry-depth threshold (m). |
|
noexcept |
Wetted-edge flow depth from a free surface η over an edge with endpoint beds z_lo ≤ z_hi — Begnudelli & Sanders (2007) Eq. 14, the exact mean depth over the wetted portion of the edge: η ≤ z_lo : 0 (wetting gate: bed above water) z_lo < η ≤ z_hi : (η − z_lo)² / (2(z_hi − z_lo)) (partially submerged) η > z_hi : η − (z_lo + z_hi)/2 (fully submerged: mean depth) The quadratic branch matches value AND slope at both joins (C¹), so overtopping onset is smooth. Single source for the CPU boundary path, the GPU boundary kernels, and the VFR interior-face path — byte-identical to the copies it replaced in SurfaceFluxCalculator.cpp and ExplicitKokkosSurfaceSolver.cpp.
| std::string openswmm::twoD::format2DOptionValue | ( | const SolverOptions2D & | opts, |
| const std::string & | key ) |
| std::string openswmm::twoD::format2DOptionValueEx | ( | const SolverOptions2D & | opts, |
| const Infil2D * | infil, | ||
| const std::string & | key ) |
format2DOptionValue with the E2 infiltration keys resolved against the model's [2D_INFILTRATION*] rows: INFIL_STEP falls back to the section value, INFIL_DEFAULT_METHOD to the '*' row's method. INFILTRATION stays AUTO | YES | NO as stored. infil may be null.
| std::string openswmm::twoD::format2DOptionValueEx | ( | const SolverOptions2D & | opts, |
| const Infil2D * | infil, | ||
| const SubsurfaceConfig * | aquifer, | ||
| const std::string & | key ) |
As above, and additionally resolves the groundwater enables against the [2D_AQUIFER*] authoring: GROUNDWATER AUTO reports the YES|NO the kernel will actually take, and GW_ET reads the [2D_AQUIFER_OPTIONS] field that owns it. aquifer may be null.
| std::string openswmm::twoD::formatReport2DVars | ( | unsigned | mask | ) |
|
noexcept |
|
noexcept |
| std::string openswmm::twoD::gwTransportInertWarning | ( | const GwTransportData & | gw | ) |
The single "authored but no kernel" run-time warning (U4's contract). Empty when nothing was authored.
|
noexcept |
The factors for this project's unit system.
|
noexcept |
| const char * openswmm::twoD::infil2DDestToken | ( | Infil2DDest | dest | ) |
Inverse of parseInfil2DDest.
| const char * openswmm::twoD::infil2DMethodToken | ( | const Infil2DRow & | row | ) |
Inverse of parseInfil2DMethod — the canonical file token.
| int openswmm::twoD::infil2DParamCount | ( | InfilModel | method | ) |
Number of meaningful positional parameters for method (used by the writer to trim trailing placeholders and by validation).
|
inlinenoexcept |
Depth-limited infiltration sink rate (m/s) for one cell (plan §5.5).
Identical contract to evapSink: the held per-cell rate (D-I1, SurfaceStateData::infil_rate) applies in full for depth ≥ dry_depth and shuts off through the same cubic Hermite wet/dry ramp as the cell dries. Negative rates are treated as zero (infiltration is a loss only; exfiltration is not a v1 destination — D-I4).
D-I2 sink ordering: evaporation is taken FIRST with its semantics unchanged, and infiltration is then applied against what is left, so a surface-only project (infil_rate all zero) is bitwise unchanged. Both sinks ramp to zero together as the cell dries, and every call site feeds the sum into a volume update that floors at zero, so the pair cannot leave a cell with negative water.
| rate | Held infiltration rate (m/s). |
| depth | Current cell depth (m). |
| dry_depth | Dry-depth threshold (m). |
| void openswmm::twoD::injectAccumulatedExchange | ( | const std::vector< CouplingPoint > & | cps, |
| const MeshData & | mesh, | ||
| SurfaceStateData & | state, | ||
| const std::vector< double > & | accum_m3, | ||
| double | window_dt, | ||
| double | sign, | ||
| const std::vector< double > * | node_conc = nullptr ) |
Inject a per-point accumulated exchange volume into the 2D window source field.
Window-fire counterpart of the per-step accumulators: converts each accumulated volume to the mean rate over the window (Q_k = accum_m3[k] / window_dt) and scatters it into state.coupling_flux with the given sign convention (+1: accum is already 2D-source-positive, e.g. outfall discharge; −1: accum is 2D→1D-drain-positive, e.g. junction exchange, so the 2D-side source is its negation). coupling_flux is NOT cleared here — callers zero it once before injecting both accumulators.
| node_conc | S3 (nullable): the 1D nodes' published concentrations, flat [node * n_species + s] with the 2D transport stride. When given, each 2D-source volume also scatters transport.coupling_src at the point's node concentration (callers clear coupling_src alongside coupling_flux). |
| bool openswmm::twoD::is2DOptionKey | ( | const std::string & | key | ) |
True when key (case-insensitive) is a [2D_OPTIONS] parameter accepted by parse2DOptionsLine.
Used by the swmm_options_get_ext / swmm_options_set_ext C API to route these keys to the live SolverOptions2D (via SimulationContext::twod_io) instead of the generic ext_options map — that routing is what makes GUI/API edits of 2D options reach the solver and persist through the InpWriter [2D_OPTIONS] emission and the GeoPackage 2D_* option keys.
| bool openswmm::twoD::is2DRetiredOptionKey | ( | const std::string & | key | ) |
True when key (case-insensitive) is a [2D_OPTIONS] parameter retired with the CVODE/ARKODE stack (D2, 2026-07-29).
parse2DOptionsLine hard-errors on these unless given a warnings sink (the file-load path warns and ignores them); swmm_options_set_ext uses this predicate to reject them up front so they can never land in the generic ext_options map (where they would silently persist to the next save).
| std::string openswmm::twoD::load2DMeshExternalFile | ( | MeshData & | mesh, |
| SolverOptions2D & | opts, | ||
| std::vector< SurfaceRouter2D::PendingBoundaryRow > & | pending_bc_rows, | ||
| std::vector< SurfaceRouter2D::PendingEdgeConveyanceRow > & | pending_ec_rows, | ||
| Infil2D * | infil, | ||
| const std::string & | mesh_file, | ||
| const std::string & | inp_base_dir, | ||
| std::vector< std::string > * | warnings = nullptr, | ||
| std::vector< SurfaceRouter2D::PendingInitialQualityRow > * | pending_iq_rows = nullptr, | ||
| std::vector< SurfaceRouter2D::PendingBoundaryQualityRow > * | pending_bq_rows = nullptr ) |
Load 2D mesh sections from an external file.
Opens the file referenced by mesh_file (resolved relative to inp_base_dir if it is a relative path) and parses any [2D_OPTIONS], [2D_VERTICES], [2D_TRIANGLES], [2D_VERTEX_NODE_MAP], [2D_TRIANGLE_NODE_MAP] and [2D_INFILTRATION*] sections found in it.
| mesh | Mesh data to populate. |
| opts | Solver options to populate. |
| mesh_file | Path from the [2D_MESH_FILE] FILE token. |
| inp_base_dir | Directory of the parent .inp file (may be empty). |
| infil | Per-cell infiltration to populate from the sidecar's [2D_INFILTRATION*] sections (plan §5.5.5 — these are per-cell mesh attributes, so they travel with the mesh exactly like [2D_VERTICES]/[2D_TRIANGLES]). The .2dm is parsed against a detached context, so the handlers cannot reach it through ctx.twod_io.infil and it must be passed explicitly. May be null (rows are then dropped). A section present in BOTH files resolves in favour of the sidecar, matching the [2D_MESH_FILE] rule that the external file overrides the inline one; rows are never merged, so nothing is double-counted. |
| warnings | Optional sink for retired-key warnings (see parse2DOptionsLine); pass &ctx.warnings so a legacy external mesh file still loads. |
| std::unique_ptr< ISurfaceSolver > openswmm::twoD::makeSurfaceSolver | ( | const SolverOptions2D & | opts, |
| std::string * | chosen = nullptr, | ||
| int | n_cells = 0, | ||
| bool | plugin_capable = true ) |
Construct the 2D surface solver per the runtime backend policy.
Never throws on plugin absence or load failure — it resolves to the serial CPU solver instead. A successfully loaded GPU plugin is reported on stderr; the default CPU path is silent so ordinary runs produce no extra output.
| opts | Solver options; backend ([2D_OPTIONS] BACKEND) is the model's request, overridden by OPENSWMM_2D_BACKEND when set. |
| chosen | Optional out-param; receives a human-readable backend label (e.g. "cpu (serial CVODE)" or "cuda (NVIDIA A100)"). |
| n_cells | Triangle count of the mesh (0 = unknown). Under the default auto policy a mesh below the parallel-worthwhile threshold (env OPENSWMM_2D_MIN_PARALLEL_CELLS, default 20000) selects the serial CPU solver even when a GPU/OpenMP plugin is present — Kokkos' per-kernel launch overhead makes the accelerated path slower than serial on small meshes. An explicit backend (option or env) always wins (no size gate). |
| std::string openswmm::twoD::parse2DBoundaryConditionsLine | ( | const std::vector< std::string > & | tokens, |
| std::vector< SurfaceRouter2D::PendingBoundaryRow > & | pending_rows ) |
V-E3 — parse a single line from the [2D_BOUNDARY_CONDITIONS] section into a SurfaceRouter2D::PendingBoundaryRow appended to pending_rows.
Format: TRI EDGE TYPE [PARAM_1 [PARAM_2 [GROUP]]] TYPE ∈ WALL / NORMAL_FLOW / SPECIFIED_STAGE / TS_STAGE / SPECIFIED_FLOW / TS_FLOW / RATING_CURVE PARAM_1 = slope / head / TS name / flow / TS name / curve name (by type) PARAM_2 reserved, always "*" GROUP optional named group ("*" = none)
Rows are drained into BoundaryData inside SurfaceRouter2D::initialize() after boundary_.resize() has sized the per-edge slots.
| std::string openswmm::twoD::parse2DBoundaryQualityLine | ( | const std::vector< std::string > & | tokens, |
| std::vector< SurfaceRouter2D::PendingBoundaryQualityRow > & | rows ) |
S2 — one [2D_BOUNDARY_QUALITY] line (TRI EDGE SPECIES CONC). Empty = OK.
| std::string openswmm::twoD::parse2DEdgeConveyanceLine | ( | const std::vector< std::string > & | tokens, |
| std::vector< SurfaceRouter2D::PendingEdgeConveyanceRow > & | pending_rows ) |
§11A — parse a single [2D_EDGE_CONVEYANCE] line.
Format: FROM_VERTEX TO_VERTEX CONVEYANCE FROM_VERTEX, TO_VERTEX : non-negative integer mesh-vertex indices. Must differ. The pair is undirected. CONVEYANCE : double in [0, 1] (strict, clamped at parse).
Rows are accumulated into pending (a scratch buffer on SurfaceRouter2D) and resolved against the mesh topology in SurfaceRouter2D::initialize() after buildMeshTopology populates the neighbour table.
| std::string openswmm::twoD::parse2DInfiltrationDefaultsLine | ( | const std::vector< std::string > & | tokens, |
| Infil2D & | infil ) |
§5.5 track I — parse a single [2D_INFILTRATION_DEFAULTS] line.
Format: TAG|* METHOD [P1 .. P5] [DEST] TAG : [2D_TRIANGLES] TAG to match, or * for the mesh-wide default. METHOD : HORTON / MODIFIED_HORTON / GREEN_AMPT / MODIFIED_GREEN_AMPT / CURVE_NUMBER / CONSTANT / NONE (parseInfil2DMethod). P1..P5 : POSITIONAL parameters in PROJECT UNITS, laid out per method exactly like legacy [INFILTRATION] (see the table on Infil2DRow). - means "unset"; trailing columns a method does not use may be omitted. DEST : LOST / SUBCATCH_AQUIFER / AQUIFER_2D (default LOST). Only LOST is accepted at validation in this release (D-I4).
Rows are appended to infil.defaults() in file order and resolved against the mesh in Infil2D::resolve() (D-I3: override > tag > * > none).
| std::string openswmm::twoD::parse2DInfiltrationLine | ( | const std::vector< std::string > & | tokens, |
| Infil2D & | infil ) |
§5.5 track I — parse a single [2D_INFILTRATION] line.
Format: CELL METHOD [P1 .. P5] [DEST] CELL is the triangle index, 1-BASED in the file and stored 0-based in Infil2DOverride::tri. The upper bound is checked in Infil2D::resolve() — the mesh is not necessarily loaded when this section is read. The remaining columns are identical to [2D_INFILTRATION_DEFAULTS].
Rows are appended to infil.overrides() and take precedence over every default row for that cell.
| std::string openswmm::twoD::parse2DInfiltrationOptionsLine | ( | const std::vector< std::string > & | tokens, |
| Infil2D & | infil ) |
§5.5 track I — parse a single [2D_INFILTRATION_OPTIONS] line.
Format: INFIL_STEP <hh:mm:ss> The only key. Accepts the same duration grammar as WET_STEP/DRY_STEP in [OPTIONS] (hh:mm:ss, hh:mm, or plain seconds) and stores seconds in Infil2DOptions::infil_step. 0 means "use the project WET_STEP" (D-I1).
| std::string openswmm::twoD::parse2DInitialQualityLine | ( | const std::vector< std::string > & | tokens, |
| std::vector< SurfaceRouter2D::PendingInitialQualityRow > & | rows ) |
S1/S2 — one [2D_INITIAL_QUALITY] line. Empty string = OK.
| std::string openswmm::twoD::parse2DInitialVelocityLine | ( | const std::vector< std::string > & | tokens, |
| MeshData & | mesh ) |
Parse a single line from the [2D_INITIAL_VELOCITY] section.
Format: TRI U V (m/s; default 0,0 — rows may cover any subset)
| tokens | Whitespace-split tokens from the line. |
| mesh | Mesh data to update (tri_init_u / tri_init_v). |
| std::string openswmm::twoD::parse2DOptionsLine | ( | const std::vector< std::string > & | tokens, |
| SolverOptions2D & | opts, | ||
| std::vector< std::string > * | warnings = nullptr ) |
Parse a single line from the [2D_OPTIONS] section.
| tokens | Whitespace-split tokens from the line. |
| opts | Output solver options to populate. |
| warnings | When non-null (the .inp file-load path), keys retired with the CVODE/ARKODE stack — and retired INTEGRATOR values — are IGNORED with a WARNING 104 pushed here, so legacy models still open. When null (the programmatic swmm_options_set_ext path), they remain hard errors. |
| std::string openswmm::twoD::parse2DQuadLine | ( | const std::vector< std::string > & | tokens, |
| MeshData & | mesh ) |
Parse a single line from the [2D_QUADS] section.
Format: V1 V2 V3 V4 MANNINGS_N [INIT_DEPTH] [TAG] Quads are appended after every triangle (cell index = n_triangles + j).
| std::string openswmm::twoD::parse2DTriangleLine | ( | const std::vector< std::string > & | tokens, |
| MeshData & | mesh ) |
Parse a single line from the [2D_TRIANGLES] section.
Format: V1 V2 V3 MANNINGS_N [TAG]
| tokens | Whitespace-split tokens from the line. |
| mesh | Mesh data to append triangle to. |
| std::string openswmm::twoD::parse2DTriangleNodeMapLine | ( | const std::vector< std::string > & | tokens, |
| MeshData & | mesh ) |
Parse a single line from the [2D_TRIANGLE_NODE_MAP] section.
Format: TRIANGLE_INDEX_OR_TAG SWMM_NODE_NAME [CD] [AREA]
| tokens | Whitespace-split tokens from the line. |
| mesh | Mesh data to update coupling map. |
| std::string openswmm::twoD::parse2DVertexLine | ( | const std::vector< std::string > & | tokens, |
| MeshData & | mesh ) |
Parse a single line from the [2D_VERTICES] section.
Format: X Y Z [TAG]
| tokens | Whitespace-split tokens from the line. |
| mesh | Mesh data to append vertex to. |
| std::string openswmm::twoD::parse2DVertexNodeMapLine | ( | const std::vector< std::string > & | tokens, |
| MeshData & | mesh ) |
Parse a single line from the [2D_VERTEX_NODE_MAP] section.
Format: VERTEX_INDEX_OR_TAG SWMM_NODE_NAME [CD] [AREA]
| tokens | Whitespace-split tokens from the line. |
| mesh | Mesh data to update coupling map. |
| std::string openswmm::twoD::parseAquiferLine | ( | const std::vector< std::string > & | tokens, |
| std::vector< GwAquiferRow > & | rows ) |
One [2D_AQUIFER] line. Empty return = OK.
| std::string openswmm::twoD::parseAquiferNodeLine | ( | const std::vector< std::string > & | tokens, |
| std::vector< GwNodeBed > & | beds, | ||
| std::vector< std::string > & | names ) |
One [2D_AQUIFER_NODE] line. node is left as a NAME in names until resolveSubsurface maps it to an index. Empty return = OK.
| std::string openswmm::twoD::parseAquiferOptionsLine | ( | const std::vector< std::string > & | tokens, |
| GwOptions & | opts ) |
One [2D_AQUIFER_OPTIONS] line (KEY VALUE). Empty return = OK.
| std::string openswmm::twoD::parseGwBoundaryQualityLine | ( | const std::vector< std::string > & | tokens, |
| std::vector< GwBoundaryQualityRow > & | rows ) |
One [GW_BOUNDARY_QUALITY] line: CELL EDGE SPECIES CONC v | TS n | / MASSFLUX v|n | HEATFLUX v|n. CELL is 1-based in the file, EDGE is 0-based (EDGE 0..nv-1 of that cell). Empty = OK.
|
noexcept |
| std::string openswmm::twoD::parseGwInitialQualityLine | ( | const std::vector< std::string > & | tokens, |
| std::vector< GwInitialQualityRow > & | rows, | ||
| std::string & | file ) |
One [GW_INITIAL_QUALITY] line: scope, SAT|UNSAT|LAYER <j>, SPECIES, VALUE — or FILE <path>. Empty = OK.
| std::string openswmm::twoD::parseGwParamsLine | ( | const std::vector< std::string > & | tokens, |
| std::vector< GwParamsRow > & | rows ) |
One [GW_TRANSPORT_PARAMS] line: * | TAG <t> | CELL <n> then the positional matrix properties (see GwParamsRow). Empty = OK.
| std::string openswmm::twoD::parseGwSorptionLine | ( | const std::vector< std::string > & | tokens, |
| std::vector< GwSorptionRow > & | rows ) |
One [GW_SORPTION] line: scope, SPECIES, Kd [decay]. Empty = OK.
| std::string openswmm::twoD::parseGwSourcesLine | ( | const std::vector< std::string > & | tokens, |
| std::vector< GwSourceRow > & | rows ) |
One [GW_SOURCES] line: NAME (CELL n | TAG t | XY x y) FLOW v|ts / [SPECIES (CONC|MASS) v|ts]…. Empty = OK.
| std::string openswmm::twoD::parseGwTransportOptionsLine | ( | const std::vector< std::string > & | tokens, |
| GwTransportOptions & | o ) |
One [GW_TRANSPORT_OPTIONS] line (KEY VALUE [ARG…]). Empty = OK.
|
noexcept |
| bool openswmm::twoD::parseInfil2DDest | ( | const std::string & | token, |
| Infil2DDest & | dest ) |
Parse a destination token.
| bool openswmm::twoD::parseInfil2DMethod | ( | const std::string & | token, |
| InfilModel & | method, | ||
| bool & | has_method ) |
Parse a method token (HORTON, MODIFIED_HORTON, GREEN_AMPT, MODIFIED_GREEN_AMPT, CURVE_NUMBER, CONSTANT, NONE), case-insensitive.
NONE returns true with has_method set false. | std::string openswmm::twoD::parseReport2DVars | ( | const std::string & | text, |
| unsigned & | mask ) |
|
noexcept |
| void openswmm::twoD::prescan2DUnitsHeader | ( | const std::string & | inp_path, |
| SolverOptions2D & | opts ) |
Scan inp_path for a ;; UNITS: <value> comment header and set opts.mesh_units_si to true when the value names metres.
Recognised SI markers (case-insensitive): SI (m), m, metre, metres, meter, meters. Any other value (or absent header) leaves the flag unchanged.
Safe to call multiple times; e.g. once on the inline .inp and again on the resolved .2dm — the most recent observation wins, which is the intended precedence (external file overrides inline).
Quietly does nothing if the file cannot be opened — the caller already reports the missing-file error via the normal read path.
|
noexcept |
dη/dh̄ of the regularised quad closure at stage η: 1/max(slope, eps).
|
noexcept |
Regularised free-surface elevation η(h̄) of the quad — the solver closure. Monotone inverse of quadMeanDepthFromEta for the same eps; fully wet reduces to the flat closure η = z̄_w + h̄ exactly, where z̄_w is the area-weighted mean of the two sub-triangle mean beds (== the quad's mean bed over its two-plane model).
|
noexcept |
Regularised cell-mean depth h̄(η) of the quad — the area-weighted sum of the two sub-triangle closures (exact for eps == 0).
|
noexcept |
Slope dh̄/dη of the REGULARISED sum at η: each sub-triangle contributes its wet fraction above its switch stage, eps inside its linear tail, and 0 once its tail has reached zero depth. Used by the Newton inverse.
|
inlinenoexcept |
Choose the B&S 2007 diagonal for a quad and emit its precomputed VFR data.
| x,y,z | the four vertices in CYCLIC order (either orientation) |
| zs | out: six elevations — sorted triple of sub-triangle 1, then sorted triple of sub-triangle 2 |
| A1,A2 | out: planimetric areas of the two sub-triangles |
|
noexcept |
Wetted-area fraction of the quad at stage η (dh̄/dη away from the ε-tail). zs: six sorted elevations (z1,z2,z3 of sub-triangle 1, then of 2).
| void openswmm::twoD::recomputeAllZDependents | ( | MeshData & | mesh | ) |
Whole-mesh form of recomputeVertexZDependents.
Recomputes tri_cz and edge_mz for EVERY triangle in one pass, and produces bitwise-identical values to calling the per-vertex form for every vertex in turn (same operands, same operand order, same arithmetic).
This exists because the per-vertex form scans all triangles per call: doing that once per vertex is O(nVertices x nTriangles), which is minutes on a million-cell mesh. swmm_2d_set_vertex_z_bulk writes every Z and then calls this once, making the same work O(nVertices + nTriangles).
| mesh | The mesh; mesh.vz is assumed to already hold the new Zs. |
| void openswmm::twoD::recomputeVertexZDependents | ( | MeshData & | mesh, |
| int | vidx ) |
Recompute Z-derived per-triangle / per-edge geometry for triangles incident to a vertex whose Z just changed.
Updates tri_cz (centroid Z = mean of vertex Zs) and edge_mz (per-edge midpoint Z) for every triangle that references vertex vidx. XY-derived fields (tri_area, tri_cx, tri_cy, edge_length, edge_nx, edge_ny, edge_mx, edge_my) are not affected.
Used by swmm_2d_set_vertex_z and exposed here so tests can verify the recompute logic without spinning up a full engine.
| mesh | The mesh; mesh.vz[vidx] is assumed to already hold the new Z. |
| vidx | Index of the vertex whose Z just changed. |
| void openswmm::twoD::reconstructVertexHeads | ( | const MeshData & | mesh, |
| SurfaceStateData & | state, | ||
| int | nthreads = 1 ) |
Reconstruct head values at vertices from cell-centred heads.
Evaluates: h_vertex[b] = Σ_i ω_i * h_cell[stencil_idx[i]] Uses the CSR stencil built by buildVertexStencils().
| mesh | The mesh (with stencils built). |
| state | Surface state (reads head[], writes vert_head[]). |
| nthreads | OpenMP thread count for the per-vertex loop (1 = serial). |
| void openswmm::twoD::reconstructVertexRenderDepths | ( | const MeshData & | mesh, |
| SurfaceStateData & | state, | ||
| double | dry_depth, | ||
| int | nthreads, | ||
| std::vector< double > & | eta_scratch ) |
Wet-masked, depth-weighted free-surface reconstruction at vertices for RENDERING/OUTPUT only (writes state.vert_depth_signed).
For each vertex, averages the free-surface elevations η_i of incident WET cells (depth ≥ dry_depth) weighted by their depths, then stores the SIGNED vertex depth η_v − z_v. Dry incident cells are excluded, so bed elevations of dry cells can never lift the reconstructed water surface up an adverse slope / bed step (the depth-weighted mean is bounded by the incident wet-cell η's — no-new-maxima). A wet cell additionally votes only where its water actually reaches the corner (wetted-contact gate, η_i > z_v), so a thin film pooled at a cell's base cannot drag the level at the cell's high vertex down to the film (no-new-minima follows from the gate — the mean is bounded below by min η_i > z_v). Consequently the emitted field is either strictly positive or the 0 no-data sentinel; readers should stay tolerant of negatives from files written by older engines. A vertex with no qualifying incident cell gets 0.
Deliberately separate from reconstructVertexHeads(): vert_head is a SOLVER field (gradients/limiters/fluxes and the active-set seed pass rely on dry-cell head = bed elevation) and must keep its semantics.
| mesh | The mesh (with stencil topology built; uses stencil cell lists only, not the pseudo-Laplacian weights). |
| state | Surface state (reads depth[], writes vert_depth_signed[]). |
| dry_depth | Wet/dry threshold (m) — cells below it are excluded. |
| nthreads | OpenMP thread count for the per-vertex loop (1 = serial). |
| eta_scratch | Caller-owned scratch resized to n_triangles(); the per-cell free-surface elevations are evaluated ONCE here and gathered per vertex. Passing a persistent buffer keeps the closure evaluations at O(nt) instead of O(nt x incidence) and avoids a per-call allocation. Bit-identical to the per-incidence evaluation it replaces (same value, same gather order). |
|
inline |
Convenience overload for callers with no persistent scratch (tests, one-shot seeding): allocates the per-cell buffer for the duration of the call.
| void openswmm::twoD::register2DSections | ( | MeshData & | mesh, |
| SolverOptions2D & | options, | ||
| std::vector< SurfaceRouter2D::PendingBoundaryRow > & | pending_bc_rows, | ||
| std::vector< SurfaceRouter2D::PendingEdgeConveyanceRow > & | pending_ec_rows, | ||
| std::vector< SurfaceRouter2D::PendingInitialQualityRow > & | pending_iq_rows, | ||
| std::vector< SurfaceRouter2D::PendingBoundaryQualityRow > & | pending_bq_rows, | ||
| input::SectionRegistry & | registry ) |
Register all 2D input section handlers with the section registry.
Call during input reader setup (conditional on OPENSWMM_HAS_2D). The handlers will populate the mesh and options data in SimulationContext.
| mesh | Mesh data to populate. |
| options | Solver options to populate. |
| registry | Section registry to register handlers into. |
| void openswmm::twoD::registerGwTransportSections | ( | GwTransportData & | gw, |
| input::SectionRegistry & | registry ) |
Register every [GW_*] handler against registry, writing into gw.
| void openswmm::twoD::registerSubsurfaceSections | ( | SubsurfaceConfig & | cfg, |
| std::vector< std::string > & | node_names, | ||
| input::SectionRegistry & | registry ) |
Register the three handlers against registry, writing into cfg.
| const std::vector< std::string > & openswmm::twoD::report2DVarTokens | ( | ) |
Format the current value of a [2D_OPTIONS] parameter as the string token parse2DOptionsLine accepts (round-trip safe).
| opts | Solver options to read. |
| key | Parameter name (case-insensitive). |
Token ↔ bitmask helpers for [2D_OPTIONS] REPORT_2D_VARIABLES.
report2DVarTokens() lists the group tokens in bit order (DEPTH, VELOCITY, EDGE_FLUX, NODE_HEAD, SPECIES, RAINFALL, INFILTRATION, COUPLING, GRADIENTS, CONTINUITY, ENVELOPES). parseReport2DVars() accepts a whitespace/comma-separated list of those tokens or one of the presets DEFAULT | MINIMAL | ALL (case-insensitive); it returns an empty error string on success. formatReport2DVars() writes a preset name when the mask equals one, else the token list.
| std::vector< std::string > openswmm::twoD::resolveGwTransport | ( | SimulationContext & | ctx, |
| const MeshData & | mesh, | ||
| GwTransportData & | gw ) |
Validate the authored rows against the model and the species registry, once the mesh and the species are final.
Cell indices must be on the mesh, EDGE must be 0..nv-1 of ITS cell (cell-generic — a triangle has 3, a quad 4), species must resolve through the one registry (pollutants, reactions species, __WATER_AGE__, __TEMPERATURE__), timeseries names must exist. Returns the diagnostics; empty on success. Also loads the [GW_INITIAL_QUALITY] FILE sidecar (relative to the .inp).
| std::vector< std::string > openswmm::twoD::resolveSubsurface | ( | SimulationContext & | ctx, |
| const MeshData & | mesh, | ||
| SubsurfaceConfig & | cfg, | ||
| const std::vector< std::string > & | names ) |
Resolve node names to indices and each bed's cell to a mesh cell. Returns diagnostics; empty on success.
|
noexcept |
Scatter a signed volumetric exchange Q (m³/s) directly onto the cell derivatives ydot[] of the 2D volume ODE (for the live-RHS path).
Same upwind-HGL stencil distribution as the held-flux scatterCouplingFlux, but adds the per-cell share Q·w (Σw = 1) straight into ydot (m³/s) rather than into a coupling_flux rate, so the exchange is conservative across the stencil. Sign convention matches ydot: positive Q = source INTO the cells, negative = sink OUT of them (so the RHS passes −Q_drain for a 2D → 1D drain).
|
noexcept |
| void openswmm::twoD::updateOutfallBoundaries | ( | const std::vector< CouplingPoint > & | cps, |
| const MeshData & | mesh, | ||
| const SurfaceStateData & | state, | ||
| SimulationContext & | ctx, | ||
| const SolverOptions2D & | opts ) |
Update outfall boundary depths from 2D surface heads.
For each outfall coupled to the 2D domain, sets the outfall depth to max(h_standard, h_2d) to account for dynamic tailwater from 2D flooding. Must be called before 1D routing step.
| cps | Coupling points. |
| mesh | Mesh data. |
| state | 2D surface state. |
| ctx | Simulation context. |
| opts | 2D solver options (for unit-system coupling factors). |
| std::string openswmm::twoD::validateMesh | ( | const MeshData & | mesh | ) |
Validate mesh data for consistency.
Checks: vertex indices in bounds, positive areas, no degenerate triangles.
| mesh | The mesh to validate. |
|
inlinenoexcept |
Pseudo-Laplacian head at ONE vertex, evaluated on demand from the current cell heads.
Same CSR stencil and weights as reconstructVertexHeads(), for callers that need a handful of vertices at the current evaluation state (the coupling points inside the CVODE RHS) without paying the all-vertex pass on every RHS/Jv evaluation. The all-vertex pass still runs once per accepted window so every between-window consumer (output, held-exchange evaluation, outfall boundaries) sees exactly the values it saw when the pass lived in the RHS.
|
noexcept |
dη/dh̄ of the regularized closure at stage eta: 1/max(w(η), eps). Divide by the cell area A to get dη/dV (the preconditioner chain-rule factor; equals 1/A for a fully wet cell, matching the flat closure). Inputs must be sorted.
|
noexcept |
Dry-cell free surface of the regularized closure: η(V = 0). This is the value a dry cell's head must be seeded with under CELL_CLOSURE = VFR so that head → volume seeding (vfrMeanDepthFromEta) returns exactly 0. Inputs must be sorted.
|
noexcept |
Regularized free-surface elevation η(h̄) — the solver closure.
Exact VFR inverse while the wet fraction is ≥ eps; below that, the C¹ tangent-line tail η = η_s − (h̄_s − h̄)/eps, which bounds dη/dh̄ by 1/eps (i.e. dη/dV ≤ 1/(εA)) and lands at η(0) = η_s − h̄_s/eps ∈ (z1, η_s). eps == 0 gives the exact relation with η(h̄ ≤ 0) = z1 (render use). Fully wet (h̄ ≥ z3 − z̄) reduces to the flat closure η = z̄ + h̄ exactly. Inputs must be sorted.
|
noexcept |
Regularized cell-mean depth h̄(η): exact for η ≥ η_s (wet fraction ≥ eps), tangent-line continuation below (slope eps), clamped at 0. eps == 0 gives the exact relation. The EXACT inverse of vfrEtaFromMeanDepth for the same eps, so head ↔ volume seeding round-trips (hotstart, reinitialize). Inputs must be sorted.
|
noexcept |
EXACT cell-mean depth h̄(η) of the planar-bed cell (per unit area; V = A·h̄). Returns 0 for η ≤ z1. Inputs must be sorted.
|
noexcept |
Sort three vertex elevations in place so z1 <= z2 <= z3.
|
noexcept |
Stage η_s at which the wetted-area fraction equals eps (0 < eps < 1). Inputs must be sorted and non-flat (z3 − z1 ≥ kVfrFlatRelief).
|
noexcept |
Wetted-area fraction A_wet/A of the planar-bed cell at stage eta. Piecewise C0, monotone from 0 (η ≤ z1) to 1 (η ≥ z3). This is dh̄/dη. Inputs must be sorted (z1 <= z2 <= z3).
| void openswmm::twoD::writeSubsurfaceSections | ( | const SubsurfaceConfig & | cfg, |
| const std::vector< std::string > & | node_names, | ||
| std::string & | out ) |
Write the three sections back in the project's own units — that is, the authored values verbatim — omitting anything at its default so a round-trip with no edits adds nothing.
|
inlineconstexpr |
Number of positional parameter columns carried per row. Matches the widest legacy [INFILTRATION] method (Horton: f0 fmin decay dry_time Fmax).
|
inlineconstexpr |
Maximum vertices (and therefore edge slots) per cell. The mesh is a mixed triangle / convex-quadrilateral mesh (2D_TRI_QUAD_MESH_PLAN_2026-09-06): every per-cell connectivity and edge SoA is padded to this fixed stride so the flat [cell * kMaxCellVerts + k] addressing the solvers, the C API, the HDF5 layout and the GUI all share stays a plain stride, never a CSR. Slots k ≥ cell_nv[c] are padding (vertex −1, neighbour −2, zero geometry).
|
inlineconstexpr |
Number of doubles of precomputed elevation data per quad cell: two sorted sub-triangle triples.
|
inlineconstexpr |
Relief below which a cell is treated as flat (metres). Matches the guard in the pre-existing render closure (cellFreeSurfaceElevation).