OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
openswmm::twoD Namespace Reference

Namespaces

namespace  checkpoint
 
namespace  diffusive
 
namespace  dispersion
 
namespace  exchange
 
namespace  footprint
 
namespace  gpu
 
namespace  inertial
 
namespace  pond
 
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  ChannelGroundContact
 
class  ChannelGroundState
 
class  CommonSourceStage
 
struct  CouplingPoint
 Descriptor for a single coupling point between 2D and 1D. More...
 
struct  CoverageRow2D
 [2D_COVERAGES] — one row = the whole coverage set of its scope. More...
 
struct  CurbRow2D
 [2D_CURB_LENGTH] — curb length per cell, project length units. More...
 
class  EngineSourceResultHistory
 
class  EngineSourceResultStream
 
class  ExplicitInertialSolver
 
class  GpuExecutionOwner
 
struct  GroundColumnAssembly
 
struct  GroundHeatState
 
struct  GroundLidThermalOwner
 
struct  GroundPorewaterColumn
 
struct  GroundThermalCell
 
struct  GwAquiferRow
 
struct  GwBoundaryPulse
 
struct  GwBoundaryQualityRow
 One [GW_BOUNDARY_QUALITY] row — a lateral edge BC. More...
 
struct  GwBoundaryRow
 
struct  GwBoundaryTerm
 
struct  GwInitialQualityRow
 One [GW_INITIAL_QUALITY] row. More...
 
struct  GwLinkRow
 
struct  GwLinkShare
 
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  GwRechargeBackend
 
struct  GwResolvedBoundary
 
struct  GwResolvedSource
 
struct  GwResolvedSourceTerm
 
struct  GwSorptionRow
 One [GW_SORPTION] row: retardation input for one species in one scope. More...
 
struct  GwSourcePulse
 
struct  GwSourceRow
 One [GW_SOURCES] row — a well / point source or sink. More...
 
struct  GwSourceSeries
 
struct  GwSourceSignal
 
struct  GwSourceSpeciesTerm
 One [GW_SOURCES] species term. More...
 
struct  GwSubcatchShare
 
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  LayerTransportMove
 
struct  LayerTransportResult
 
struct  LayerTransportScratch
 
struct  LidNodeThermalGraph
 
struct  LidThermalWaterTransfer
 
struct  LoadingRow2D
 [2D_LOADINGS] — initial buildup, user mass per unit land area. More...
 
struct  MeshAtmosphericFlux
 
struct  MeshData
 SoA storage for 2D mixed triangle/quad mesh geometry and topology. More...
 
struct  MeshHeatState
 
struct  MeshPolylineInterval
 
struct  MeshPolylineMapping
 
class  MomentumPhysics2D
 
struct  NodeData
 Structure-of-Arrays storage for all nodes. More...
 
class  OutfallExchange
 
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  PendingInitialBedQualityRow
 One [2D_INITIAL_BED_QUALITY] row for finite local-bed porewater. More...
 
struct  PendingInitialQualityRow
 One [2D_INITIAL_QUALITY] row (overland transport S1/S2). More...
 
class  PluginSurfaceSolver
 
struct  PorewaterAdvection
 
struct  PorewaterTransportScratch
 
struct  PorousHeatColumn
 
class  RainfallInterpolator
 Builds and applies static rainfall-interpolation weights for the mesh. More...
 
class  ResultHistoryAppend
 
struct  RichardsBedAcceptance
 
struct  RichardsBedBinding
 
struct  RichardsBedOwner
 
struct  RichardsBedReceipt
 
struct  RichardsBedStep
 
struct  RichardsBedStepper
 
struct  RichardsBedTrial
 
struct  Rk2CheckpointBinding
 
struct  RowLayoutLite
 
struct  RuntimeForcing
 
struct  RuntimeForcings
 
struct  RuntimeReceipt
 
struct  RuntimeSource
 
struct  RuntimeSources
 
class  RuntimeWaterCheckpoint
 
struct  RuntimeWaterCheckpointBinding
 
class  RuntimeWaterDriverCheckpoint
 
struct  SigmaPorewaterMap
 
struct  SolverOptions2D
 
class  SourceResultHistory
 
struct  SourceResultTable
 
struct  SqScopeKey
 
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...
 
struct  SubsurfaceTransportState
 Species mass in both aquifer zones, and where mass crossed a boundary. More...
 
struct  SurfaceEtReceipt
 
class  SurfaceExchange
 
struct  SurfaceIntakeActual
 
struct  SurfaceIntakeAward
 
struct  SurfaceIntakeReceipt
 
struct  SurfaceIntakeRequest
 
struct  SurfaceOwnerObject
 
struct  SurfaceOwnerRecord
 
struct  SurfaceOwnerShare
 
struct  SurfaceOwnershipPreview
 
class  SurfaceQuality2D
 The S7 store: authored rows, resolved per-cell coverages and state, and the per-species ledgers. More...
 
struct  SurfaceReturnReceipt
 
class  SurfaceRouter2D
 Top-level orchestrator for the 2D surface routing module. More...
 
struct  SurfaceStateData
 
struct  SurfaceThermalSample
 
struct  SurfaceTransportState
 
struct  ThermalAdvection
 
struct  ThermalBoundary
 
struct  ThermalContact
 
struct  ThermalContactScratch
 
struct  ThermalMaterial
 
struct  ThermalMidpointScratch
 
struct  ThermalSolution
 
struct  ThermalStore
 

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 ,
  NEAREST_NEIGHBOUR = 3
}
 How raingage rainfall is mapped onto the 2D mesh cells. More...
 
enum class  CouplingLaw2D : int8_t {
  ORIFICE = 0 ,
  WEIR_ORIFICE = 1
}
 1D↔2D exchange law at junction coupling points ([2D_OPTIONS] COUPLING_LAW; a node's [2D_NODE_COUPLING] LAW overrides it). More...
 
enum class  CouplingHead2D : int8_t {
  CELL = 0 ,
  VERTEX = 1 ,
  STENCIL_WET_MEAN = 2
}
 Where the 2D head driving a junction exchange is read ([2D_OPTIONS] COUPLING_HEAD). More...
 
enum class  CouplingPondMode2D : int8_t {
  FOOTPRINT = 0 ,
  CHAMBER = 1 ,
  TRACKING = 2
}
 Above-rim storage of a 2D-coupled junction under dynamic wave ([2D_OPTIONS] COUPLING_POND_MODE; plan §4.2). 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  Coriolis2D : int8_t {
  OFF = 0 ,
  LATITUDE = 1 ,
  CONSTANT_F = 2
}
 Configuration for the 2D surface routing solver. More...
 
enum class  Turbulence2D : int8_t {
  NONE = 0 ,
  SMAGORINSKY = 1 ,
  MIXING_LENGTH = 2
}
 
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  SqScope : int8_t {
  GLOBAL = 0 ,
  TAG = 1 ,
  CELL = 2
}
 Row scope — the [2D_INFILTRATION] / [GW_*] ladder. More...
 
enum class  SurfaceEtOwner {
  MESH ,
  PERVIOUS ,
  IMPERVIOUS ,
  LID
}
 
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...
 
enum class  GwLinkMode : int8_t {
  NONE = 0 ,
  AUTO = 1 ,
  TWO_WAY = 2 ,
  DEFAULT = 3
}
 
enum class  SurfaceDonorKind {
  MESH ,
  NON_LID ,
  LID_BOTTOM
}
 
enum class  SurfaceReturnKind {
  NUMERICAL_REFUND ,
  PHYSICAL_DUNNE ,
  COLUMN_EXCESS
}
 

Functions

void resolveExchangeStructure (CouplingPoint &cp, const MeshData &mesh, const SimulationContext &ctx, const SolverOptions2D &opts, int row, NodeCoupling2DType type, double project_len_to_m)
 Resolve a junction point's exchange law, structure and coefficients from its node's [2D_NODE_COUPLING] row, the class preset and the global options (plans/1D2D_FINE_SCALE_COUPLING_PLAN §3.1, §3.4–3.5).
 
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, double dt)
 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::string validateRk2Sources (const RuntimeSources &, int cells, int species, int temperature, int age, const std::vector< uint8_t > *coverage=nullptr)
 Validate copied RK2 source prescriptions and water/heat/species receipt shapes.
 
std::string rk2SurfaceRuntimeProfile (const SurfaceStateData &, const SubsurfaceSolver *ground=nullptr)
 Qualify prepared surface source/weather/snow state for the managed RK2 numerical profile.
 
bool rk2HasSurfaceBoundary (const BoundaryData *)
 Detect any hydraulic boundary use or retained override/receipt history.
 
std::string validateRk2SurfaceBoundary (const MeshData &, const SurfaceStateData &)
 Validate prepared RK2 exterior boundary descriptors, composition and physical receipts.
 
void rk2SurfaceBoundaryArchive (detail::CompletedSourceArchive &a, BoundaryData &b, std::map< int, std::vector< double > > &quality, bool model, int species)
 Archive a matched RK2 boundary model identity or its accepted runtime receipts.
 
void rk2ManagedRuntimeModel (detail::CompletedSourceArchive &a, RuntimeSources &surface, RuntimeSources &ground, RuntimeForcings &forcing, int species, BoundaryData *boundary=nullptr, std::map< int, std::vector< double > > *quality=nullptr)
 Archive copied RK2 source/forcing prescriptions for a managed model binding.
 
std::string validateRk2ReplayIds (const RuntimeSources &, const RuntimeSources &, const RuntimeForcings &, double completed)
 Check provider namespaces, active expiry and last-receipt horizons at a managed boundary.
 
std::vector< PendingBoundaryRow > collectBCRows (const std::vector< PendingBoundaryRow > *pending, const BoundaryData *boundary, bool drained, double flow_to_si_applied=1.0)
 Copy authored boundary rows or reconstruct them from live edge storage.
 
std::vector< PendingEdgeConveyanceRow > collectConveyanceRows (const std::vector< PendingEdgeConveyanceRow > *pending, const MeshData *mesh, bool drained)
 Copy authored conveyance rows or reconstruct unique nondefault mesh edges.
 
const char * turbulenceName (Turbulence2D t) noexcept
 [2D_OPTIONS] TURBULENCE_MODEL token for a closure.
 
std::vector< GwResolvedBoundary > resolveGwBoundaries (SimulationContext &ctx, const MeshData &mesh, const SubsurfaceConfig &config, const GwTransportData &quality, const SubsurfaceState &state, const SubsurfaceTransportState &tr, const std::vector< uint8_t > &coverage, double heat_capacity)
 Resolve authored exterior hydraulic edges and explicit groundwater quality prescriptions.
 
void appendGwBoundaryCuts (const GwResolvedBoundary &b, double start, double end, double head, double bottom, double thickness, std::vector< double > &cuts)
 Append forcing knots and crossings that delimit smooth boundary-integral pieces.
 
GwBoundaryPulse integrateGwBoundary (const GwResolvedBoundary &b, double start, double dt, double head, double bottom, double thickness, double conductivity, int species)
 Integrate a resolved edge's requested water, injection composition and independent fluxes.
 
void integrateGwSource (const GwResolvedSource &s, double t, double dt, double weight, GwSourcePulse &pulse)
 Accumulate signed water and injection/load species forcing over linear intervals.
 
GwSourceSignal resolveGwSignal (SimulationContext &ctx, double value, const std::string &name, std::unordered_map< std::string, GwSourceSignal > &cache, const char *label)
 Resolve a finite constant or copy/share a strictly ordered model time series.
 
std::vector< GwResolvedSource > resolveGwSources (SimulationContext &ctx, const MeshData &mesh, const GwTransportData &gw, const SubsurfaceState &state, const SubsurfaceTransportState &tr)
 Resolve authored groundwater sources to normalized active-cell shares and native signals.
 
const char * gwZoneToken (GwZone z) noexcept
 Borrow the input-section token for an aquifer zone.
 
bool parseGwZone (const std::string &token, GwZone &z) noexcept
 Parse one aquifer zone token without changing state on failure.
 
const char * gwScopeToken (GwScope s) noexcept
 Borrow the input-section token for an aquifer row scope.
 
std::string parseGwTransportOptionsLine (const std::vector< std::string > &tokens, GwTransportOptions &o)
 Apply one groundwater transport/thermal authoring option without resolving physical owners.
 
std::string parseGwParamsLine (const std::vector< std::string > &tokens, std::vector< GwParamsRow > &rows)
 Parse one scoped positional groundwater material/dispersion authoring row.
 
std::string parseGwSorptionLine (const std::vector< std::string > &tokens, std::vector< GwSorptionRow > &rows)
 Parse scoped species partition coefficient and optional decay authoring data.
 
std::string parseGwInitialQualityLine (const std::vector< std::string > &tokens, std::vector< GwInitialQualityRow > &rows, std::string &file)
 Parse a scoped initial native quality row or retain an external file prescription.
 
std::string parseGwBoundaryQualityLine (const std::vector< std::string > &tokens, std::vector< GwBoundaryQualityRow > &rows)
 Parse a lateral groundwater boundary native concentration or flux prescription.
 
std::string parseGwSourcesLine (const std::vector< std::string > &tokens, std::vector< GwSourceRow > &rows)
 Parse one named scoped groundwater injection/extraction and native constituent prescription.
 
void registerGwTransportSections (GwTransportData &gw, input::SectionRegistry &registry)
 Register GW authoring callbacks that append into the borrowed model data.
 
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)
 The single "authored but no kernel" run-time warning (U4's contract). Empty when nothing was authored.
 
std::string buildLidNodeThermalGraph (const LidNodeState &state, double mobile_water_ft3, double water_heat_capacity, const ConductionConfig &material, double initial_celsius, LidNodeThermalGraph &output)
 Build compact active thermal stores and vertical contacts from accepted LID water state.
 
std::string buildLidNodeGroundThermalContact (const LidNodeThermalGraph &graph, std::size_t combined_store_count, int ground_store, double overlap_area, double ground_area, double soil_thickness, double soil_conductivity, double interface_resistance, ThermalContact &output)
 Connect the compact bottom LID store to an appended physical ground store.
 
std::string publishLidNodeThermalEnergy (LidNodeState &state, const LidNodeThermalGraph &graph, const std::vector< double > &energy)
 Replace persisted physical-cell energy with a successful compact graph solution.
 
std::string transferLidNodeThermalEnergy (const LidNodeThermalGraph &graph, std::size_t cell_count, double water_heat_capacity, const std::vector< LidThermalWaterTransfer > &transfers, std::vector< double > &physical_energy, double &external_j, std::vector< double > *transfer_j)
 Stage producer-ordered sensible energy transfers through a fixed physical LID graph.
 
GroundColumnAssembly appendGroundColumnSystem (const MeshData &mesh, const SolverOptions2D &options, GroundHeatState &owner, int i, MeshHeatState *h, double mass, double volume, double evaporated, double dt, double channel_area, std::vector< ThermalStore > &stores, std::vector< ThermalContact > &contacts, std::vector< ThermalBoundary > &boundaries)
 Append one physical column and its finite surface/LID contacts to a shared thermal graph.
 
double commitGroundColumnSystem (GroundColumnAssembly &a, const ThermalSolution &solved) noexcept
 Publish an accepted shared thermal solution into one assembly's canonical owners.
 
std::string initializeMeshHeat (SimulationContext &ctx, const MeshData &mesh, SurfaceStateData &state, const SolverOptions2D &options, GroundHeatState *aquifer, const std::vector< uint8_t > *coverage)
 Prepare optional surface thermal stores, porewater and physical ground ownership.
 
std::string configureGroundLidOwners (SimulationContext &ctx, const MeshData &mesh, GroundHeatState &owner, const std::vector< GwNodeBed > &beds)
 Map persistent Mesh Richards LID thermal owners onto physical ground cells.
 
double applyLocalBedSpecies (const MeshData &mesh, MeshHeatState &h, int i, int r, double mass, double volume, double dt) noexcept
 Exchange one native surface row with finite bed porewater.
 
double applyLocalBedSpeciesEuler (const MeshData &mesh, MeshHeatState &h, int i, int r, double mass, double volume, double dt)
 Exchange one native surface row with finite bed porewater for an Euler RK2 stage.
 
bool ageLocalBedPorewater (MeshHeatState &h, double dt) noexcept
 Advance the local-storage porewater age inventory without altering water volume.
 
void advectStandaloneGround (MeshHeatState &h, int i, double volume, double donor) noexcept
 Carry accepted infiltration heat through a standalone saturated physical soil column.
 
void prepareMeshHeat (SimulationContext &ctx, SurfaceStateData &state, double dt)
 Prepare inherited exchange flags, weather and fresh per-cell thermal interval accounting.
 
double applyMeshHeatCell (const MeshData &mesh, const SolverOptions2D &options, MeshHeatState &h, int i, double mass, double volume, double evaporated, double dt, bool midpoint) noexcept
 Update one mixed surface thermal sample before accepted intensive water sinks.
 
void advanceRemainingGroundColumns (const MeshData &mesh, const SolverOptions2D &options, SurfaceStateData &state, double seconds) noexcept
 Complete each surface-owned physical ground column's unprocessed router interval.
 
PorewaterAdvection advectPorewaterEuler (const std::vector< double > &old_water, const std::vector< double > &retention, const std::vector< double > &mass, const std::vector< double > &change, const std::vector< double > &external_water, const std::vector< double > &external_mass, const std::vector< double > &withdrawal, const std::vector< double > &reserved_water, const std::vector< double > &reserved_mass)
 Compute explicit fixed-layer porewater transport from accepted physical water tangents.
 
PorewaterAdvection & advectPorewaterEuler (const std::vector< double > &old_water, const std::vector< double > &retention, const std::vector< double > &mass, const std::vector< double > &change, const std::vector< double > &external_water, const std::vector< double > &external_mass, const std::vector< double > &withdrawal, const std::vector< double > &reserved_water, const std::vector< double > &reserved_mass, PorewaterTransportScratch &scratch)
 
PorewaterAdvection advectPorewater (const std::vector< double > &old_water, const std::vector< double > &new_water, const std::vector< double > &retention, const std::vector< double > &mass, const std::vector< double > &external_water, const std::vector< double > &external_mass, const std::vector< double > &withdrawal)
 Solve conservative implicit upwind porewater transport on fixed physical layers.
 
PorewaterAdvection & advectPorewater (const std::vector< double > &old_water, const std::vector< double > &new_water, const std::vector< double > &retention, const std::vector< double > &mass, const std::vector< double > &external_water, const std::vector< double > &external_mass, const std::vector< double > &withdrawal, PorewaterTransportScratch &scratch)
 
ThermalSolution solveThermalContacts (const std::vector< ThermalStore > &stores, const std::vector< ThermalContact > &contacts, const std::vector< ThermalBoundary > &boundaries, double dt)
 Solve reciprocal heat contacts by backward Euler and diagonal-preconditioned CG.
 
ThermalSolution & solveThermalContacts (const std::vector< ThermalStore > &stores, const std::vector< ThermalContact > &contacts, const std::vector< ThermalBoundary > &boundaries, double dt, ThermalContactScratch &scratch)
 
ThermalSolution solveThermalContactsRk2 (const std::vector< ThermalStore > &stores, const std::vector< ThermalContact > &contacts, const std::vector< ThermalBoundary > &boundaries, double dt)
 Solve reciprocal heat contacts by bounded implicit-midpoint subdivisions.
 
ThermalSolution & solveThermalContactsRk2 (const std::vector< ThermalStore > &stores, const std::vector< ThermalContact > &contacts, const std::vector< ThermalBoundary > &boundaries, double dt, ThermalMidpointScratch &scratch)
 
ThermalAdvection advectPorousColumn (PorousHeatColumn &column, const std::vector< double > &moisture, const std::vector< double > &external_water, const std::vector< double > &external_j, const std::vector< double > &withdrawal)
 Reconstruct conservative layer water fluxes and apply implicit upwind heat advection.
 
ThermalAdvection advectPorousColumnEuler (PorousHeatColumn &column, const std::vector< double > &moisture, const std::vector< double > &change, const std::vector< double > &external_water, const std::vector< double > &external_j, const std::vector< double > &withdrawal, const std::vector< double > &temperature)
 Apply a conservative explicit heat-advection tangent for one shared RK stage.
 
std::string projectGroundWaterIncrement (const PorousHeatColumn &column, double length, double delta_length, const std::vector< double > &old_water, const std::vector< double > &delta_water, std::vector< double > &output)
 Project a moving hydraulic-layer water tangent onto the fixed thermal grid.
 
std::string projectGroundMoisture (const SubsurfaceState &s, int i, double hg, const std::vector< double > &edges, std::vector< double > &output, std::vector< double > *saturated_water)
 Project accepted hydraulic moisture into a fixed physical thermal depth grid.
 
bool 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.
 
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)
 Number of meaningful positional parameters for method (used by the writer to trim trailing placeholders and by validation).
 
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.
 
std::span< const char *const > current2DOptionKeys ()
 Every current [2D_OPTIONS] key accepted by is2DOptionKey, in documentation order.
 
const std::vector< std::string > & report2DVarTokens ()
 Borrow canonical report-group keyword tokens in defined bit order.
 
std::string parseReport2DVars (const std::string &text, unsigned &mask)
 Parse report-group keyword list/preset through the shared mask grammar.
 
std::string formatReport2DVars (unsigned mask)
 Format a report bitmask using canonical presets or ordered keyword list.
 
std::string format2DOptionValue (const SolverOptions2D &opts, const std::string &key)
 Format a stored 2D option as a canonical authoring/display token.
 
std::string format2DOptionValueEx (const SolverOptions2D &opts, const Infil2D *infil, const std::string &key)
 Format stored 2D policy with optional infiltration/aquifer authoring fallback.
 
std::string format2DOptionValueEx (const SolverOptions2D &opts, const Infil2D *infil, const SubsurfaceConfig *aquifer, const std::string &key)
 Format stored 2D policy with optional infiltration/aquifer authoring fallback.
 
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)
 Parse one scoped initial surface native concentration authoring row.
 
std::string parse2DInitialBedQualityLine (const std::vector< std::string > &tokens, std::vector< SurfaceRouter2D::PendingInitialBedQualityRow > &rows)
 Parse a finite local-bed native concentration seed without resolving a physical bed.
 
std::string parse2DBoundaryQualityLine (const std::vector< std::string > &tokens, std::vector< SurfaceRouter2D::PendingBoundaryQualityRow > &rows)
 Parse one zero-based surface boundary native concentration row.
 
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::PendingInitialBedQualityRow > &pending_ibq_rows, std::vector< SurfaceRouter2D::PendingBoundaryQualityRow > &pending_bq_rows, input::SectionRegistry &registry)
 Register mesh/options/native-quality/boundary/infiltration authoring section handlers.
 
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, std::vector< SurfaceRouter2D::PendingInitialQualityRow > *pending_iq_rows, std::vector< SurfaceRouter2D::PendingInitialBedQualityRow > *pending_ibq_rows, std::vector< SurfaceRouter2D::PendingBoundaryQualityRow > *pending_bq_rows)
 Read a mesh sidecar through a local registry into caller-supplied authoring targets.
 
void prescan2DUnitsHeader (const std::string &inp_path, SolverOptions2D &opts)
 Scan an entire UTF-8 input/mesh file for a recognized SI mesh-units comment marker.
 
void buildMeshTopology (MeshData &mesh)
 Build mesh topology and precompute geometry from raw vertex/triangle data.
 
bool buildMeshTopologyCancellable (MeshData &mesh, const std::function< bool(int)> &progress)
 Cancellable equivalent; progress receives integer percent and returns true to cancel.
 
std::string validateMesh (const MeshData &mesh)
 Validate mesh data for consistency.
 
std::string validateMeshCancellable (const MeshData &mesh, const std::function< bool(int)> &progress, bool &cancelled)
 Cancellable validator. cancelled is set when progress returns true.
 
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
 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).
 
OPENSWMM_KERNEL_FN double quadMeanDepthFromEta (const double *zs, double A1, double A2, double eta, double eps) noexcept
 Regularised cell-mean depth h̄(η) of the quad — the area-weighted sum of the two sub-triangle closures (exact for eps == 0).
 
OPENSWMM_KERNEL_FN double quadMeanDepthSlope (const double *zs, double A1, double A2, double eta, double eps) 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.
 
OPENSWMM_KERNEL_FN double quadEtaFromMeanDepth (const double *zs, double A1, double A2, double mean_depth, double 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).
 
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)
 Cell-shape-aware form: triangle → cellFreeSurfaceElevation over the three vertex beds; quad → the B&S 2007 two-plane closure (mesh/QuadVfr.hpp).
 
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)
 Convenience overload for callers with no persistent scratch (tests, one-shot seeding): allocates the per-cell buffer for the duration of the call.
 
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
 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).
 
OPENSWMM_KERNEL_FN double vfrMeanDepthFromEtaExact (double z1, double z2, double z3, double eta) 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.
 
OPENSWMM_KERNEL_FN double vfrStageAtWetFraction (double z1, double z2, double z3, double eps) noexcept
 Stage η_s at which the wetted-area fraction equals eps (0 < eps < 1). Inputs must be sorted and non-flat (z3 − z1 ≥ kVfrFlatRelief).
 
OPENSWMM_KERNEL_FN double vfrMeanDepthFromEta (double z1, double z2, double z3, double eta, double eps) 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.
 
OPENSWMM_KERNEL_FN double vfrEtaFromMeanDepth (double z1, double z2, double z3, double mean_depth, double eps) noexcept
 Regularized free-surface elevation η(h̄) — the solver closure.
 
OPENSWMM_KERNEL_FN double vfrDryEta (double z1, double z2, double z3, double eps) 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.
 
OPENSWMM_KERNEL_FN double vfrDEtaDMeanDepth (double z1, double z2, double z3, double eta, double eps) 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.
 
std::string formatSqScope (const SqScopeKey &k)
 Scope key ↔ file token ("*", "TAG name", "CELL n" — 1-based).
 
std::string parseSqScope (const std::vector< std::string > &tokens, std::size_t &at, SqScopeKey &key, const char *section)
 Parse a scoped surface-quality row prefix and expose its first payload token.
 
std::string parse2DCoveragesLine (const std::vector< std::string > &tokens, std::vector< CoverageRow2D > &rows)
 Parse one scoped 2D coverage authoring row.
 
std::string parse2DLoadingsLine (const std::vector< std::string > &tokens, std::vector< LoadingRow2D > &rows)
 Parse one scoped 2D loading authoring row.
 
std::string parse2DCurbLengthLine (const std::vector< std::string > &tokens, std::vector< CurbRow2D > &rows)
 Parse one scoped 2D curb authoring row.
 
void registerSurfaceQualitySections (SurfaceQuality2D &sq, input::SectionRegistry &registry)
 Register [2D_COVERAGES], [2D_LOADINGS], [2D_CURB_LENGTH] writing into sq.
 
void rk2SurfaceBoundaryArchive (Archive &a, BoundaryData &b, std::map< int, std::vector< double > > &quality, bool model, int species)
 Archive a matched RK2 boundary model identity or its accepted runtime receipts.
 
void rk2ManagedRuntimeModel (Archive &a, RuntimeSources &surface, RuntimeSources &ground, RuntimeForcings &forcing, int species, BoundaryData *boundary, std::map< int, std::vector< double > > *quality)
 Archive copied RK2 source/forcing prescriptions for a managed model binding.
 
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 diagnostic cell velocity from wetted-edge normal velocities.
 
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 for host boundary queries. Explicit inertial marchers may use their own prognostic stage-boundary update instead.
 
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.
 
GwRechargeBackend makeGwRechargeBackend (const SolverOptions2D &opts, int n_cells)
 Optional stateless host recharge operator. Surface/water/transfer ownership stays with the built-in marcher; absent/unsupported extensions select CPU.
 
double groundwaterZoneConcentration (const SubsurfaceSolver &gw, int cell, int species, bool saturated)
 Derive a reported bulk-zone concentration using the active transport ownership model.
 
LayerTransportResult solveLayerTransport (const std::vector< double > &capacity, const std::vector< double > &rhs, const std::vector< LayerTransportMove > &moves, bool signed_species=false)
 Conservative, positivity-preserving implicit donor transport on a column chain. rhs holds mass after already-paired incoming/outgoing receipts; capacity is the final aqueous+sorption storage coefficient. Dry isolated mass is retained, not divided by an artificial water-volume floor.
 
const LayerTransportResult & solveLayerTransport (const std::vector< double > &capacity, const std::vector< double > &rhs, const std::vector< LayerTransportMove > &moves, LayerTransportScratch &scratch, bool signed_species)
 
LayerTransportResult advanceLayerTransportEuler (const std::vector< double > &capacity, const std::vector< double > &initial, const std::vector< double > &rhs, const std::vector< LayerTransportMove > &moves, bool signed_species=false, const std::vector< double > *donor_available=nullptr)
 Forward-Euler stage evaluated from beginning inventories/storage. All outgoing moves from a donor share one finite beginning-mass budget; incoming receipts never finance another export in the same stage.
 
const LayerTransportResult & advanceLayerTransportEuler (const std::vector< double > &capacity, const std::vector< double > &initial, const std::vector< double > &rhs, const std::vector< LayerTransportMove > &moves, LayerTransportScratch &scratch, bool signed_species, const std::vector< double > *donor_available)
 
RichardsBedTrial trialRichardsBeds (const SubsurfaceSolver &gw, double dt, const std::vector< RichardsBedBinding > &input)
 Freeze actual aquifer budgets and compute a private one-interval Richards exchange trial.
 
RichardsBedAcceptance acceptRichardsBedsAtFiring (SubsurfaceSolver &gw, SurfaceStateData &surface, double start, double end, const std::vector< RichardsBedOwner > &input)
 Accept selected same-horizon Richards owners together with their groundwater cell firing over one interval.
 
RichardsBedAcceptance acceptRichardsBedsAcrossSteps (SubsurfaceSolver &gw, SurfaceStateData &surface, double start, double end, const std::vector< double > &step_ends, const std::vector< RichardsBedOwner > &input, const RichardsBedStepper *stepper=nullptr)
 Accept selected same-horizon Richards owners together with their groundwater cell firing across private short steps.
 
RichardsBedAcceptance acceptRichardsBedsForTier (SubsurfaceSolver &gw, SurfaceStateData &surface, int tier, double start, double end, const std::vector< RichardsBedOwner > &owners)
 Atomically replace one due groundwater tier and its Richards owners over one interval.
 
RichardsBedAcceptance acceptRichardsBedsForTierAcrossSteps (SubsurfaceSolver &gw, SurfaceStateData &surface, int tier, double start, double end, const std::vector< double > &step_ends, const std::vector< RichardsBedOwner > &owners, const RichardsBedStepper *stepper=nullptr)
 Atomically replace one due groundwater tier and its Richards owners across private short steps.
 
const char * soilCharToken (SoilChar s) noexcept
 Return the canonical token for a soil-characteristic law.
 
bool parseSoilChar (const std::string &t, SoilChar &s) noexcept
 Parse a groundwater token after removing whitespace and folding case.
 
const char * gwClosureToken (GwClosure c) noexcept
 Return the canonical token for an unsaturated-zone closure.
 
bool parseGwClosure (const std::string &t, GwClosure &c) noexcept
 Parse a groundwater token after removing whitespace and folding case.
 
std::string parseAquiferOptionsLine (const std::vector< std::string > &tokens, GwOptions &opts)
 Apply one aquifer authoring option without initializing a physical column.
 
std::string parseAquiferLine (const std::vector< std::string > &tokens, std::vector< GwAquiferRow > &rows)
 Parse a scoped aquifer hydraulic authoring row into a local candidate.
 
std::string parseAquiferNodeLine (const std::vector< std::string > &tokens, std::vector< GwNodeBed > &beds, std::vector< std::string > &names)
 Parse one named native-node aquifer bed with explicit cell or deferred location.
 
std::string parseAquiferLinkLine (const std::vector< std::string > &tokens, std::vector< GwLinkRow > &rows, std::vector< std::string > &names)
 Parse named conduit bed coefficient/path and exchange opt-out authoring row.
 
std::string parseAquiferBoundaryLine (const std::vector< std::string > &t, std::vector< GwBoundaryRow > &rows)
 Parse a unique hydraulic aquifer exterior-edge prescription.
 
void registerSubsurfaceSections (SubsurfaceConfig &cfg, std::vector< std::string > &node_names, std::vector< std::string > &link_names, input::SectionRegistry &registry)
 Register aquifer option/cell/node/link/boundary and surface-ownership authoring callbacks.
 
GwUnitFactors gwUnitFactors (const SimulationContext &ctx) noexcept
 Resolve authored aquifer units into SI kernel conversion factors.
 
MeshPolylineMapping mapMeshPolyline (const MeshData &mesh, const std::vector< double > &x, const std::vector< double > &y, const std::function< bool(int)> &progress, std::size_t first_interval, std::size_t max_intervals, bool count_contact_cells)
 Clip a polyline into exact convex-cell chainage intervals with local shared-edge ownership.
 
std::vector< std::string > resolveSubsurface (SimulationContext &ctx, const MeshData &mesh, SubsurfaceConfig &cfg, std::vector< std::string > &names, double node_xy_to_mesh)
 Resolve native-node bed identity/location and optional coordinate-based automatic enrollment.
 
std::vector< GwLinkShare > resolveLinkSeepage (SimulationContext &ctx, const MeshData &mesh, SubsurfaceConfig &cfg, std::vector< std::string > &link_names, double node_xy_to_mesh, int &n_conduits)
 Resolve conduit polylines into normalized aquifer cell shares and vertical contact reaches.
 
std::vector< GwSubcatchShare > resolveSubcatchInfiltration (const SimulationContext &ctx, const MeshData &mesh, double node_xy_to_mesh, int &n_subcatch)
 Compute normalized polygon-area shares from every subcatchment footprint to mesh cells.
 
std::string parseSurfaceOwnerLine (const std::vector< std::string > &t, std::vector< SurfaceOwnerRecord > &rows)
 Retain one reviewed uniform subcatchment surface-ownership authoring record.
 
SurfaceOwnershipPreview resolveSurfaceOwnership (const SimulationContext &ctx, const MeshData &mesh, const SolverOptions2D &opts, const SubsurfaceConfig &cfg, const std::vector< SurfaceOwnerRecord > &proposed, const std::function< bool(int, int)> &progress)
 Preview reviewed source footprints, receiver shares and weather-area ownership without adoption.
 
void writeSubsurfaceSections (const SubsurfaceConfig &cfg, const std::vector< std::string > &node_names, const std::vector< std::string > &link_names, std::string &out, bool full_precision)
 Append retained aquifer/ownership/boundary authoring sections in project units.
 
OPENSWMM_KERNEL_FN double faceDepthFromEta (double eta, double z_lo, double z_hi) 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 cross-sectional water area divided by the full edge length: η ≤ 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.
 
void meshState (detail::CompletedSourceArchive &, SurfaceStateData &)
 Archive and validate accepted mesh hydraulic, species and optional snow/thermal runtime.
 

Variables

constexpr double runtimeWaterHeatCapacity = 4186000.0
 
constexpr int kMaxCellVerts = 4
 
constexpr int kInfil2DMaxParams = 5
 
constexpr int kQuadVfrZ = 6
 
constexpr double kVfrFlatRelief = 1.0e-9
 

Enumeration Type Documentation

◆ Backend2D

enum class openswmm::twoD::Backend2D : int8_t
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).

Enumerator
CPU 

Built-in marcher (OpenMP-threaded on the host), no plugin.

AUTO 

Default: plugins above their size floors, else CPU.

OMP 

Kokkos OpenMP host plugin.

CUDA 

Kokkos CUDA device plugin (NVIDIA).

HIP 

Kokkos HIP device plugin (AMD).

SYCL 

Kokkos SYCL device plugin (Intel).

◆ BoundaryType

enum class openswmm::twoD::BoundaryType : int8_t
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.

Enumerator
WALL 

Zero-flux wall (default)

NORMAL_FLOW 

Manning outflow using bed slope.

SPECIFIED_STAGE 

Prescribed water surface elevation (constant or TS)

SPECIFIED_FLOW 

Prescribed discharge per metre of edge (constant or TS)

RATING_CURVE 

Stage → flow lookup (curve registry index)

◆ CellClosure2D

enum class openswmm::twoD::CellClosure2D : int8_t
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.

◆ Coriolis2D

enum class openswmm::twoD::Coriolis2D : int8_t
strong

Configuration for the 2D surface routing solver.

Populated from [2D_OPTIONS] input section. Defaults are chosen for typical urban drainage surface routing problems.

Enumerator
OFF 
LATITUDE 
CONSTANT_F 

◆ CouplingHead2D

enum class openswmm::twoD::CouplingHead2D : int8_t
strong

Where the 2D head driving a junction exchange is read ([2D_OPTIONS] COUPLING_HEAD).

CELL (default) is the coupling cell (the lowest-bed cell around a vertex point). VERTEX is the wet-depth-weighted η over the cells around the mapped vertex. STENCIL_WET_MEAN is the wet-depth-weighted η over the cells whose centroid lies within max(structure size, cell size) of the point — the manhole-area average Rubinato et al. (2017) found best in unsteady runs. Both fall back to the coupling cell when every cell is dry.

Enumerator
CELL 
VERTEX 
STENCIL_WET_MEAN 

◆ CouplingLaw2D

enum class openswmm::twoD::CouplingLaw2D : int8_t
strong

1D↔2D exchange law at junction coupling points ([2D_OPTIONS] COUPLING_LAW; a node's [2D_NODE_COUPLING] LAW overrides it).

ORIFICE is the legacy two-way orifice on the map row's CD/AREA (with the rim gate and the AREA→2·AREA ramp). WEIR_ORIFICE is the regime-aware law of coupling/ExchangeLaw.hpp on the node's structure geometry.

Enumerator
ORIFICE 
WEIR_ORIFICE 

◆ CouplingPondMode2D

enum class openswmm::twoD::CouplingPondMode2D : int8_t
strong

Above-rim storage of a 2D-coupled junction under dynamic wave ([2D_OPTIONS] COUPLING_POND_MODE; plan §4.2).

FOOTPRINT (default): the pond spreads over the 2D-cell footprint (the median-dual area of the coupling cells) — the same water the stencil cells hold, so it is stored twice. CHAMBER: the pond is the structure's chamber area only; all ponded water lives on the mesh. TRACKING: the pond area relaxes from the chamber area toward the currently wet footprint over COUPLING_POND_RELAX, conserving the held volume as it changes.

Enumerator
FOOTPRINT 
CHAMBER 
TRACKING 

◆ FaceDepth2D

enum class openswmm::twoD::FaceDepth2D : int8_t
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.

◆ GwClosure

enum class openswmm::twoD::GwClosure : int8_t
strong

Unsaturated-zone closure, resolved per cell from AUTO at initialize.

Enumerator
AUTO 

select from αL at initialize (never stored per cell)

CLOSED_FORM 

closure A: bulk hu + quasi-steady recharge

ENSLAVED 

closure A reduced: hu algebraic in hg (eq. 39)

SIGMA 

closure B: explicit σ column of m layers

◆ GwLinkMode

enum class openswmm::twoD::GwLinkMode : int8_t
strong

G-X4 (2026-09-20): LINK_SEEPAGE mode. AUTO is G-X3's one-way delivery (the conduit's existing [LOSSES] seepage volume is routed to the cells it crosses); TWO_WAY replaces the legacy loss law with the signed MODFLOW-River conductance, so a conduit below the water table GAINS. DEFAULT resolves TWO_WAY on a mesh and one-way in PER_SUBCATCH. Explicit legacy AUTO is retained as one-way and written canonically as ONE_WAY.

Enumerator
NONE 
AUTO 
TWO_WAY 
DEFAULT 

◆ GwScope

enum class openswmm::twoD::GwScope : int8_t
strong

Scope of a per-cell row.

Enumerator
GLOBAL 

the * row

TAG 

every cell carrying tag

CELL 

one cell, by 0-based index (1-based in the file)

◆ GwZone

enum class openswmm::twoD::GwZone : int8_t
strong

Which zone of the two-zone column a row addresses.

Enumerator
SAT 

saturated (lower) zone

UNSAT 

unsaturated (upper) zone

LAYER 

an explicit layer index (layer field)

◆ Infil2DDest

enum class openswmm::twoD::Infil2DDest : int
strong

Ordinary surface-bank destinations. Aquifer ownership is resolved before ordinary defaults: covered cells use an EXTERNAL bank row and the aquifer's receiving capacity. AQUIFER_2D remains parseable for reviewed migration, but is rejected at initialization (R2, 2026-10-05).

Enumerator
LOST 

Leaves the domain; booked to MassBalance2D::infil_out.

SUBCATCH_AQUIFER 

Legacy subcatchment aquifer (U3 track I-b)

AQUIFER_2D 

Obsolete; migrate using the ownership review.

◆ Infil2DProvenance

enum class openswmm::twoD::Infil2DProvenance : std::uint8_t
strong

Where a resolved cell's parameters came from. Retained so the writer emits a compact file (D-I3) instead of N per-cell rows.

Enumerator
NONE 

No model resolved.

STAR 

From the '*' default row.

TAG 

From a tag default row.

OVERRIDE 

From a per-cell [2D_INFILTRATION] row.

◆ Momentum2D

enum class openswmm::twoD::Momentum2D : int8_t
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:

  • LOCAL_INERTIAL de Almeida & Bates face-q update (default; bit-identical to the pre-2026-09 marcher).
  • FULL_SWE conservative shallow-water equations with the convective term: cell (h, hu, hv), hydrostatic reconstruction, rotated HLLC Riemann flux, shock capturing.
  • DIFFUSIVE_WAVE Manning quasi-steady face flux, no inertia (Hunter et al. 2005 explicit diffusive wave; Δt ∝ Δx² per cell, absorbed by the LTS tiers).
Enumerator
LOCAL_INERTIAL 
FULL_SWE 
DIFFUSIVE_WAVE 

◆ OutputPrecision2D

enum class openswmm::twoD::OutputPrecision2D : int8_t
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

◆ RainfallMode

enum class openswmm::twoD::RainfallMode : int8_t
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|nearest|system|none) overrides at initialize().

Enumerator
NATURAL_NEIGHBOUR 

Default: spatial interpolation across all gages.

SYSTEM 

Uniform = mean of all gages.

NONE 

No rain on the mesh. Use when subcatchments already capture the rainfall (runoff → nodes) — rain-on-mesh would double-count the same storm.

NEAREST_NEIGHBOUR 

Closest located gage; ties use first gage order.

◆ SoilChar

enum class openswmm::twoD::SoilChar : int8_t
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.)

Enumerator
RUSSO 

default; Mualem-consistent, same α slot as Gardner

GARDNER 

K = Ks·e^(αψ); the closed form of eq. 22.

BROOKS_COREY 

piecewise about the air-entry pressure

VAN_GENUCHTEN 

Rosetta/UNSODA parameter databases.

◆ SqScope

enum class openswmm::twoD::SqScope : int8_t
strong

Row scope — the [2D_INFILTRATION] / [GW_*] ladder.

Enumerator
GLOBAL 
TAG 
CELL 

◆ SurfaceDonorKind

Enumerator
MESH 
NON_LID 
LID_BOTTOM 

◆ SurfaceEtOwner

enum class openswmm::twoD::SurfaceEtOwner
strong
Enumerator
MESH 
PERVIOUS 
IMPERVIOUS 
LID 

◆ SurfaceReturnKind

Enumerator
NUMERICAL_REFUND 
PHYSICAL_DUNNE 
COLUMN_EXCESS 

◆ Turbulence2D

enum class openswmm::twoD::Turbulence2D : int8_t
strong
Enumerator
NONE 
SMAGORINSKY 
MIXING_LENGTH 

Function Documentation

◆ acceptRichardsBedsAcrossSteps()

RichardsBedAcceptance openswmm::twoD::acceptRichardsBedsAcrossSteps ( SubsurfaceSolver & gw,
SurfaceStateData & surface,
double start,
double end,
const std::vector< double > & step_ends,
const std::vector< RichardsBedOwner > & input,
const RichardsBedStepper * stepper = nullptr )

Accept selected same-horizon Richards owners together with their groundwater cell firing across private short steps.

Accept private Richards trials at the actual due groundwater owner boundary.

Parameters
[in,out]gwInitialized idle qualified water-only spatial groundwater owner with valid joint clock extension and gather_fraction_=1. Candidate hydraulic/receipt/clock state is copied privately.
[in,out]surfaceMatching qualified water-only surface state, including prepared infiltration rates and pending return ownership. Staged with groundwater before live adoption.
[in]startFinite nonnegative elapsed start s, exactly each selected completed groundwater/ reviewed-source owner horizon.
[in]endFinite elapsed end s, strictly after start and matching any completed reviewed-source horizon. Accepted endpoint is installed exactly rather than recomputed by repeated additions.
[in]step_endsNonempty strictly increasing finite elapsed endpoints s in (start,end], ending exactly at end. Each intermediate/final column must satisfy the supplied full hydraulic bounds.
[in]inputBorrowed owner descriptors with distinct nonnull writable column pointers and resolved beds. SI invert/clogging and max_water m3 for every physical cell, including mobile/elastic storage; original and every accepted state must lie within those bounds. All beds sharing a selected cell must be supplied. Input order is independent of node-sorted trial reporting.
[in]stepperOptional synchronous private routing callback between trial endpoints. Must own all routed state privately and keep it alive; supplies per-column revised water plus gross porous withdrawal/bottom-intake claims m3. Claimed original budgets cannot be replenished by opposite/future traffic. Nonempty callback error or caught std::exception rejects the staged window.
Returns
RichardsBedAcceptance with error empty only after live adoption, accepted node-sorted trial/step receipts, combined residual m3 and signed staged routing volume m3. Nonempty error leaves the directly supplied canonical owners unchanged under this qualified pure-water profile.
Note
Freezes full-window directional budgets once, advances private columns through each endpoint and accumulates gross claims without future-water borrowing. Validates matching groundwater closure acceptance, prohibits refund of already accepted node water, checks native owner bounds and combined conservation at relative 1e-10, then publishes with no-throw moves/swaps after allocations finish. Replaces actual due cell firing rather than pinning/refiring at LID cadence. Requires exclusive stable topology/owners and no unsupported native/thermal/external provider side effects. Private routing callback external mutations are not rolled back by this function; staging those resources is its contract. Allocation/uncaught helper exceptions may propagate; no file I/O, automatic mesh activation, generic node queue delivery or engine calendar advancement occurs.

The groundwater/surface references and writable column descriptors must be prepared for the qualified water-only profile and accessed exclusively. start/end are finite elapsed seconds with end>start and exact compatible owner clocks. A tier argument selects one complete due tier; step_ends, when present, strictly cover the same interval ending exactly at end. An optional stepper must own all routing effects privately. Full argument, result, SI buffer/bound and staged publication contracts are documented on the source definition.

Returns
Owned acceptance with empty error only after staged owners pass conservation and adopt; nonempty error preserves supplied canonical water owners under the qualified profile. No mesh activation, generic node delivery, engine calendar update or file write occurs.
Here is the caller graph for this function:

◆ acceptRichardsBedsAtFiring()

RichardsBedAcceptance openswmm::twoD::acceptRichardsBedsAtFiring ( SubsurfaceSolver & gw,
SurfaceStateData & surface,
double start,
double end,
const std::vector< RichardsBedOwner > & input )

Accept selected same-horizon Richards owners together with their groundwater cell firing over one interval.

Accept private Richards trials at the actual due groundwater owner boundary.

Parameters
[in,out]gwInitialized idle qualified water-only spatial groundwater owner with valid joint clock extension and gather_fraction_=1. Candidate hydraulic/receipt/clock state is copied privately.
[in,out]surfaceMatching qualified water-only surface state, including prepared infiltration rates and pending return ownership. Staged with groundwater before live adoption.
[in]startFinite nonnegative elapsed start s, exactly each selected completed groundwater/ reviewed-source owner horizon.
[in]endFinite elapsed end s, strictly after start and matching any completed reviewed-source horizon. Accepted endpoint is installed exactly rather than recomputed by repeated additions.
[in]inputBorrowed owner descriptors with distinct nonnull writable column pointers and resolved beds. SI invert/clogging and max_water m3 for every physical cell, including mobile/elastic storage; original and every accepted state must lie within those bounds. All beds sharing a selected cell must be supplied. Input order is independent of node-sorted trial reporting.
Returns
RichardsBedAcceptance with error empty only after live adoption, accepted node-sorted trial/step receipts, combined residual m3 and signed staged routing volume m3. Nonempty error leaves the directly supplied canonical owners unchanged under this qualified pure-water profile.
Note
Delegates to the across-steps primitive with a single end endpoint and no stepper. Validates matching groundwater closure acceptance, prohibits refund of already accepted node water, checks native owner bounds and combined conservation at relative 1e-10, then publishes with no-throw moves/swaps after allocations finish. Replaces actual due cell firing rather than pinning/refiring at LID cadence. Requires exclusive stable topology/owners and no unsupported native/thermal/external provider side effects. Private routing callback external mutations are not rolled back by this function; staging those resources is its contract. Allocation/uncaught helper exceptions may propagate; no file I/O, automatic mesh activation, generic node queue delivery or engine calendar advancement occurs.

The groundwater/surface references and writable column descriptors must be prepared for the qualified water-only profile and accessed exclusively. start/end are finite elapsed seconds with end>start and exact compatible owner clocks. A tier argument selects one complete due tier; step_ends, when present, strictly cover the same interval ending exactly at end. An optional stepper must own all routing effects privately. Full argument, result, SI buffer/bound and staged publication contracts are documented on the source definition.

Returns
Owned acceptance with empty error only after staged owners pass conservation and adopt; nonempty error preserves supplied canonical water owners under the qualified profile. No mesh activation, generic node delivery, engine calendar update or file write occurs.

◆ acceptRichardsBedsForTier()

RichardsBedAcceptance openswmm::twoD::acceptRichardsBedsForTier ( SubsurfaceSolver & gw,
SurfaceStateData & surface,
int tier,
double start,
double end,
const std::vector< RichardsBedOwner > & owners )

Atomically replace one due groundwater tier and its Richards owners over one interval.

Accept private Richards trials at the actual due groundwater owner boundary.

Parameters
[in,out]gwInitialized idle qualified water-only spatial groundwater owner with valid joint clock extension and gather_fraction_=1. Candidate hydraulic/receipt/clock state is copied privately.
[in,out]surfaceMatching qualified water-only surface state, including prepared infiltration rates and pending return ownership. Staged with groundwater before live adoption.
[in]tierValid due tier with stored cells; every selected cell and source clock must equal start. Every bound Richards bed on this tier must appear in owners. Ordinary cells on the due tier also fire once; other tiers retain their clocks/receipts.
[in]startFinite nonnegative elapsed start s, exactly each selected completed groundwater/ reviewed-source owner horizon.
[in]endFinite elapsed end s, strictly after start and matching any completed reviewed-source horizon. Accepted endpoint is installed exactly rather than recomputed by repeated additions.
[in]ownersBorrowed owner descriptors with distinct nonnull writable column pointers and resolved beds. SI invert/clogging and max_water m3 for every physical cell, including mobile/elastic storage; original and every accepted state must lie within those bounds. All beds sharing a selected cell must be supplied. Input order is independent of node-sorted trial reporting.
Returns
RichardsBedAcceptance with error empty only after live adoption, accepted node-sorted trial/step receipts, combined residual m3 and signed staged routing volume m3. Nonempty error leaves the directly supplied canonical owners unchanged under this qualified pure-water profile.
Note
Delegates to the across-steps primitive with a single end endpoint and no stepper. Validates matching groundwater closure acceptance, prohibits refund of already accepted node water, checks native owner bounds and combined conservation at relative 1e-10, then publishes with no-throw moves/swaps after allocations finish. Includes a late ordinary-cell failure in the same tier transaction. Requires exclusive stable topology/owners and no unsupported native/thermal/external provider side effects. Private routing callback external mutations are not rolled back by this function; staging those resources is its contract. Allocation/uncaught helper exceptions may propagate; no file I/O, automatic mesh activation, generic node queue delivery or engine calendar advancement occurs.

The groundwater/surface references and writable column descriptors must be prepared for the qualified water-only profile and accessed exclusively. start/end are finite elapsed seconds with end>start and exact compatible owner clocks. A tier argument selects one complete due tier; step_ends, when present, strictly cover the same interval ending exactly at end. An optional stepper must own all routing effects privately. Full argument, result, SI buffer/bound and staged publication contracts are documented on the source definition.

Returns
Owned acceptance with empty error only after staged owners pass conservation and adopt; nonempty error preserves supplied canonical water owners under the qualified profile. No mesh activation, generic node delivery, engine calendar update or file write occurs.

◆ acceptRichardsBedsForTierAcrossSteps()

RichardsBedAcceptance openswmm::twoD::acceptRichardsBedsForTierAcrossSteps ( SubsurfaceSolver & gw,
SurfaceStateData & surface,
int tier,
double start,
double end,
const std::vector< double > & step_ends,
const std::vector< RichardsBedOwner > & owners,
const RichardsBedStepper * stepper = nullptr )

Atomically replace one due groundwater tier and its Richards owners across private short steps.

Accept private Richards trials at the actual due groundwater owner boundary.

Parameters
[in,out]gwInitialized idle qualified water-only spatial groundwater owner with valid joint clock extension and gather_fraction_=1. Candidate hydraulic/receipt/clock state is copied privately.
[in,out]surfaceMatching qualified water-only surface state, including prepared infiltration rates and pending return ownership. Staged with groundwater before live adoption.
[in]tierValid due tier with stored cells; every selected cell and source clock must equal start. Every bound Richards bed on this tier must appear in owners. Ordinary cells on the due tier also fire once; other tiers retain their clocks/receipts.
[in]startFinite nonnegative elapsed start s, exactly each selected completed groundwater/ reviewed-source owner horizon.
[in]endFinite elapsed end s, strictly after start and matching any completed reviewed-source horizon. Accepted endpoint is installed exactly rather than recomputed by repeated additions.
[in]step_endsNonempty strictly increasing finite elapsed endpoints s in (start,end], ending exactly at end. Each intermediate/final column must satisfy the supplied full hydraulic bounds.
[in]ownersBorrowed owner descriptors with distinct nonnull writable column pointers and resolved beds. SI invert/clogging and max_water m3 for every physical cell, including mobile/elastic storage; original and every accepted state must lie within those bounds. All beds sharing a selected cell must be supplied. Input order is independent of node-sorted trial reporting.
[in]stepperOptional synchronous private routing callback between trial endpoints. Must own all routed state privately and keep it alive; supplies per-column revised water plus gross porous withdrawal/bottom-intake claims m3. Claimed original budgets cannot be replenished by opposite/future traffic. Nonempty callback error or caught std::exception rejects the staged window.
Returns
RichardsBedAcceptance with error empty only after live adoption, accepted node-sorted trial/step receipts, combined residual m3 and signed staged routing volume m3. Nonempty error leaves the directly supplied canonical owners unchanged under this qualified pure-water profile.
Note
Freezes full-window directional budgets once, advances private columns through each endpoint and accumulates gross claims without future-water borrowing. Validates matching groundwater closure acceptance, prohibits refund of already accepted node water, checks native owner bounds and combined conservation at relative 1e-10, then publishes with no-throw moves/swaps after allocations finish. Includes a late ordinary-cell failure in the same tier transaction. Requires exclusive stable topology/owners and no unsupported native/thermal/external provider side effects. Private routing callback external mutations are not rolled back by this function; staging those resources is its contract. Allocation/uncaught helper exceptions may propagate; no file I/O, automatic mesh activation, generic node queue delivery or engine calendar advancement occurs.

The groundwater/surface references and writable column descriptors must be prepared for the qualified water-only profile and accessed exclusively. start/end are finite elapsed seconds with end>start and exact compatible owner clocks. A tier argument selects one complete due tier; step_ends, when present, strictly cover the same interval ending exactly at end. An optional stepper must own all routing effects privately. Full argument, result, SI buffer/bound and staged publication contracts are documented on the source definition.

Returns
Owned acceptance with empty error only after staged owners pass conservation and adopt; nonempty error preserves supplied canonical water owners under the qualified profile. No mesh activation, generic node delivery, engine calendar update or file write occurs.
Here is the caller graph for this function:

◆ accumulateOutfallDischargeStep()

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.

Parameters
sample_rowOptional (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.
Returns
Number of outfalls whose withdrawal was clamped this step.
Parameters
[in]cpsStable coupling order with valid node/cell/stencil indices.
[in]meshPrepared topology and geometric partition weights.
[in]stateRetained interface argument, unused by this implementation; budget represents current provisional available surface water instead.
[in]ctxLive native node inflow/outflow sampled for each outfall.
[in]optsResolved positive native-flow-to-m3/s conversion.
[in]dtFinite positive routing duration s; nonpositive returns zero, NaN is not rejected.
[in,out]accum_m3At least cps.size() entries; adds signed source-positive accepted m3 to outfall slots, preserving junction entries.
[in,out]cell_budget_m3At least mesh.n_cells() provisional m3; withdrawals draw and discharges credit it, sharing budgets across successive points/steps. Does not mutate canonical state.
Note
sample_row must have cps.size() writable entries when nonnull. A zero-rate outfall leaves its sample slot untouched, as do junctions. Requires serialized bookkeeping and resolved finite physical data; no shape validation or allocation occurs.

◆ advanceLayerTransportEuler() [1/2]

LayerTransportResult openswmm::twoD::advanceLayerTransportEuler ( const std::vector< double > & capacity,
const std::vector< double > & initial,
const std::vector< double > & rhs,
const std::vector< LayerTransportMove > & moves,
bool signed_species = false,
const std::vector< double > * donor_available = nullptr )

Forward-Euler stage evaluated from beginning inventories/storage. All outgoing moves from a donor share one finite beginning-mass budget; incoming receipts never finance another export in the same stage.

Parameters
[in]capacityBorrowed nonempty per-layer aqueous-plus-sorption capacities, finite nonnegative m3-equivalent coefficients.
[in]rhsBorrowed equally sized post-receipt inventories in native concentration*m3; finite and nonnegative unless signed_species is true.
[in]movesBorrowed integrated nonnegative m3 transfer coefficients with valid distinct donor/recipient indices; to == -1 means an external sink.
[in]signed_speciesTrue allows signed concentration/inventory, used for temperature-volume; false enforces nonnegative inventory.
[in]initialBorrowed equally sized beginning-stage inventories, native concentration*m3; concentrations are evaluated from these values and capacity.
[in]donor_availableOptional equally sized finite per-donor inventory reservations; limits export alongside min(initial,rhs) for unsigned species. NULL uses no additional reservation.
Returns
Value-owned result with final mass, BEGINNING concentration, and signed transfer amounts in move order. Nonadjacent internal moves are allowed. Unsigned outgoing budgets are shared; signed species skip positivity scaling.
Note
Always inspect result.error before using arrays: invalid dimensions/data, singular systems or nonfinite results return a message and may leave partially filled result vectors. Inputs remain unchanged. Allocations may throw; no input storage is retained or engine state published.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ advanceLayerTransportEuler() [2/2]

const LayerTransportResult & openswmm::twoD::advanceLayerTransportEuler ( const std::vector< double > & capacity,
const std::vector< double > & initial,
const std::vector< double > & rhs,
const std::vector< LayerTransportMove > & moves,
LayerTransportScratch & scratch,
bool signed_species,
const std::vector< double > * donor_available )

◆ advanceRemainingGroundColumns()

void openswmm::twoD::advanceRemainingGroundColumns ( const MeshData & mesh,
const SolverOptions2D & options,
SurfaceStateData & state,
double seconds )
noexcept

Complete each surface-owned physical ground column's unprocessed router interval.

Parameters
[in]meshPrepared SI cell geometry.
[in]optionsResolved thermal controls.
[in,out]statePrepared surface water/temperature row and thermal owner; replaces each due cell's temperature-volume with applyMeshHeatCell() output and updates its thermal receipts.
[in]secondsPositive completed router duration s; disabled/nonpositive mode returns.
Note
Skips missing volume cells, absent surface temperature row and remainders below relative machine epsilon. Uses max remaining time implicitly by skipping nonpositive remainders; adds no latent evaporation. Without a temperature row the groundwater clock owns conduction. Requires exclusive matching state/owners and finite valid duration; failures are retained in heat diagnostics.
Here is the call graph for this function:

◆ advectPorewater() [1/2]

PorewaterAdvection openswmm::twoD::advectPorewater ( const std::vector< double > & old_water,
const std::vector< double > & new_water,
const std::vector< double > & retention,
const std::vector< double > & mass,
const std::vector< double > & external_water,
const std::vector< double > & external_mass,
const std::vector< double > & withdrawal )

Solve conservative implicit upwind porewater transport on fixed physical layers.

Solve conservative implicit fixed-layer porewater advection without mutating inputs.

Parameters
[in]old_waterFinite nonnegative beginning water m3 per layer.
[in]new_waterFinite nonnegative endpoint water m3 per layer.
[in]retentionFinite nonnegative equilibrium sorption capacity m3 per layer, zero for age.
[in]massNonempty finite nonnegative beginning native_concentration*m3 inventory; defines n.
[in]external_waterFinite signed net accepted external water m3 per layer, including actual physical transfers rather than pure moving-grid handover.
[in]external_massFinite signed paired external inventory, excluding unknown implicit withdrawals. mass+external_mass must be nonnegative for every layer.
[in]withdrawalFinite nonnegative implicit dissolved outgoing volumes m3, n entries.
Returns
Owned result with empty error on success: n final masses/equilibrium concentrations and withdrawn masses, n-1 downward-positive water/mass transfers, net external inventory and bottom water closure residual. Nonempty error reports refusal with no partial solution; inputs remain unchanged. Allocation errors propagate.
Note
All input vectors have n entries. Interior water balance must close within 1e-10 absolute transfer scale + 1e-12 m3. The tridiagonal M-matrix uses new water plus retention and outgoing volumes. A zero-capacity dry layer retains immobile residue conservatively with zero dissolved concentration; a throughflowing zero-end-water layer needs no artificial pore volume.
Argument contract All seven vectors have the same nonzero layer count.
old_water/new_water/retention are finite nonnegative m3 per layer; mass is finite nonnegative native_concentration*m3. external_water is finite signed accepted net water m3 and external_mass its paired signed inventory excluding implicit_withdrawal. That final vector is nonnegative outgoing m3 per layer, solved at the new dissolved concentration. Each initial mass plus external receipt must remain nonnegative.
Returns
Owned final inventories, concentrations, withdrawal/interior receipts and water residual; empty error indicates success. Refusal publishes no partial mass solution. Water balance tolerance is 1e-10 transfer scale plus 1e-12 m3; zero-capacity dry residue remains immobile. Allocation may throw.

◆ advectPorewater() [2/2]

PorewaterAdvection & openswmm::twoD::advectPorewater ( const std::vector< double > & old_water,
const std::vector< double > & new_water,
const std::vector< double > & retention,
const std::vector< double > & mass,
const std::vector< double > & external_water,
const std::vector< double > & external_mass,
const std::vector< double > & withdrawal,
PorewaterTransportScratch & scratch )

◆ advectPorewaterEuler() [1/2]

PorewaterAdvection openswmm::twoD::advectPorewaterEuler ( const std::vector< double > & old_water,
const std::vector< double > & retention,
const std::vector< double > & mass,
const std::vector< double > & change,
const std::vector< double > & external_water,
const std::vector< double > & external_mass,
const std::vector< double > & withdrawal,
const std::vector< double > & reserved_water,
const std::vector< double > & reserved_mass )

Compute explicit fixed-layer porewater transport from accepted physical water tangents.

Compute explicit accepted physical-layer transport with reserved-packet donor budgets.

Parameters
[in]old_waterFinite nonnegative beginning water m3 per layer.
[in]retentionFinite nonnegative sorption capacity m3 per layer, zero for age.
[in]massFinite nonnegative native_concentration*m3 inventory per layer; nonempty and its length defines the common layer count n.
[in]changeFinite signed accepted physical water increment m3 per layer, independent of geometric hydraulic-grid remapping.
[in]external_waterFinite signed net accepted external water m3 per layer.
[in]external_massFinite signed paired external inventory per layer; withdrawal below is excluded from it to avoid double booking.
[in]withdrawalFinite nonnegative accepted outgoing volume m3 per layer; exactly n entries.
[in]reserved_waterOptional n beginning water reservations m3, finite/nonnegative and no greater than old_water. Empty means zero.
[in]reserved_massOptional n canonical mass reservations, finite/nonnegative and no greater than mass; empty means zero. Reserved packets cannot donate to another export.
Returns
Owned result with empty error on success; final n masses, donor/accepted-withdrawal concentrations, n withdrawn masses, n-1 downward-positive interior water/mass receipts, net external mass and bottom water residual m3. On refusal error is nonempty and no partial solution is published. Inputs are always unchanged; allocation errors propagate.
Note
Every required vector has n entries. Reconstructs interior flux by water balance with 1e-10*absolute-volume-scale + 1e-12 m3 closure tolerance. Uses LayerTransportEuler donor limiting; returned concentration reflects accepted withdrawal composition when that budget binds.
Argument contract All required vectors have the same nonzero layer count:
old_water/retention are nonnegative m3, mass nonnegative native_concentration*m3; water_change/external_water are signed accepted m3, external_mass signed paired inventory; withdrawal is nonnegative outgoing m3. Values must be finite. Optional reserved_water/reserved_mass are empty or same-sized, nonnegative and bounded by beginning water/mass, respectively. They remain canonical but cannot supply another export.
Returns
Owned final masses, donor/accepted-withdrawal concentrations, withdrawal/interior receipts, net external inventory and water residual, or a nonempty refusal error with no partial solution. All inputs remain unchanged. Uses beginning-state Euler transport and water closure tolerance 1e-10 transfer scale plus 1e-12 m3. Allocation failures propagate.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ advectPorewaterEuler() [2/2]

PorewaterAdvection & openswmm::twoD::advectPorewaterEuler ( const std::vector< double > & old_water,
const std::vector< double > & retention,
const std::vector< double > & mass,
const std::vector< double > & change,
const std::vector< double > & external_water,
const std::vector< double > & external_mass,
const std::vector< double > & withdrawal,
const std::vector< double > & reserved_water,
const std::vector< double > & reserved_mass,
PorewaterTransportScratch & scratch )
Here is the call graph for this function:

◆ advectPorousColumn()

ThermalAdvection openswmm::twoD::advectPorousColumn ( PorousHeatColumn & column,
const std::vector< double > & moisture,
const std::vector< double > & external_water,
const std::vector< double > & external_j,
const std::vector< double > & withdrawal )

Reconstruct conservative layer water fluxes and apply implicit upwind heat advection.

Parameters
[in,out]columnPrepared nonempty physical column; replaced only after successful solve and finite energy checks. Material water heat capacity is J/(m3 K), energy J and area m2.
[in]moistureEndpoint water fractions per layer; same layer count and valid moisture bounds.
[in]external_waterSigned accepted external water volumes m3 per layer, excluding purely geometric hydraulic-grid remapping. The reconstructed column water balance must close.
[in]external_jSigned paired external sensible energy J per layer.
[in]withdrawalOptional nonnegative finite implicit outgoing volumes m3 per layer; empty means none. Their donor heat is solved at the new implicit layer temperature and subtracted.
Returns
Owned result with empty error on success, n-1 interior downward-positive water/energy receipts m3/J, n donor temperatures degrees C and outgoing energies J, net external energy J and bottom water closure residual m3. On refusal error is nonempty and column is unchanged; other result fields may be partial. Allocation exceptions propagate without publishing the candidate.
Note
The prepared column's existing arrays/geometry must have consistent layer extents. Closure tolerance is 1e-10 times total absolute external/change volume plus 1e-12 m3. This is an integrated accepted-transfer update, not a rate calculation or conductive heat step.
Declaration arguments
  • unnamed column (in,out): Prepared nonempty physical column; replaced only after successful solve and finite energy checks. Material water heat capacity is J/(m3 K), energy J and area m2.
  • new_moisture (in): Endpoint water fractions per layer; same layer count and valid moisture bounds.
  • external_water_m3 (in): Signed accepted external water volumes m3 per layer, excluding purely geometric hydraulic-grid remapping. The reconstructed column water balance must close.
  • external_j (in): Signed paired external sensible energy J per layer.
  • implicit_withdrawal_m3 (in): Optional nonnegative finite implicit outgoing volumes m3 per layer; empty means none. Their donor heat is solved at the new implicit layer temperature and subtracted.
Returns
Owned result with empty error on success, n-1 interior downward-positive water/energy receipts m3/J, n donor temperatures degrees C and outgoing energies J, net external energy J and bottom water closure residual m3. On refusal error is nonempty and column is unchanged; other result fields may be partial. Allocation exceptions propagate without publishing the candidate.
Note
The prepared column's existing arrays/geometry must have consistent layer extents. Closure tolerance is 1e-10 times total absolute external/change volume plus 1e-12 m3. This is an integrated accepted-transfer update, not a rate calculation or conductive heat step.

◆ advectPorousColumnEuler()

ThermalAdvection openswmm::twoD::advectPorousColumnEuler ( PorousHeatColumn & column,
const std::vector< double > & moisture,
const std::vector< double > & change,
const std::vector< double > & external_water,
const std::vector< double > & external_j,
const std::vector< double > & withdrawal,
const std::vector< double > & temperature )

Apply a conservative explicit heat-advection tangent for one shared RK stage.

Parameters
[in,out]columnBeginning-state fixed column, published only after all checks pass.
[in]moistureEndpoint water fractions, used to compute next capacity and conductivity.
[in]changeIntegrated beginning-state physical water tangent m3 per layer; used for flux reconstruction rather than inferring it from endpoint moisture.
[in]external_waterSigned finite accepted external water volume m3 per layer.
[in]external_jSigned finite paired external energy J per layer.
[in]withdrawalOptional nonnegative finite outgoing volume m3 per layer; empty means none.
[in]temperatureFinite beginning-state donor temperatures degrees C per layer, excluding already reserved outgoing water. These are copied into the returned donor-temperature vector.
Returns
Owned receipts with empty error on success; interior n-1 downward-positive flux volumes m3 and energy J, per-layer withdrawal J, net external energy J and closure residual m3. A nonempty error means refusal with column unchanged and no publishable receipts.
Note
All nonoptional vectors have n=column.theta.size() entries; n must be positive. Existing column geometry must be consistent. The water closure tolerance is 1e-10*absolute volume scale plus 1e-12 m3. Allocation failures propagate; moisture, conduction and outside owners are not advanced independently. Supplied donor temperatures are trusted rather than recomputed.
Declaration arguments
  • unnamed column (in,out): Beginning-state fixed column, published only after all checks pass.
  • new_moisture (in): Endpoint water fractions, used to compute next capacity and conductivity.
  • water_change_m3 (in): Integrated beginning-state physical water tangent m3 per layer; used for flux reconstruction rather than inferring it from endpoint moisture.
  • external_water_m3 (in): Signed finite accepted external water volume m3 per layer.
  • external_j (in): Signed finite paired external energy J per layer.
  • withdrawal_m3 (in): Optional nonnegative finite outgoing volume m3 per layer; empty means none.
  • donor_temperature (in): Finite beginning-state donor temperatures degrees C per layer, excluding already reserved outgoing water. These are copied into the returned donor-temperature vector.
Returns
Owned receipts with empty error on success; interior n-1 downward-positive flux volumes m3 and energy J, per-layer withdrawal J, net external energy J and closure residual m3. A nonempty error means refusal with column unchanged and no publishable receipts.
Note
All nonoptional vectors have n=column.theta.size() entries; n must be positive. Existing column geometry must be consistent. The water closure tolerance is 1e-10*absolute volume scale plus 1e-12 m3. Allocation failures propagate; moisture, conduction and outside owners are not advanced independently. Supplied donor temperatures are trusted rather than recomputed.

◆ advectStandaloneGround()

void openswmm::twoD::advectStandaloneGround ( MeshHeatState & h,
int i,
double volume,
double donor )
noexcept

Carry accepted infiltration heat through a standalone saturated physical soil column.

Parameters
[in,out]hPrepared ground-column surface heat owner and per-cell diagnostics.
[in]iValid prepared cell; aquifer-owned cells are skipped. Ownership index is unchecked.
[in]volumePositive accepted water m3; nonpositive/NaN returns without work.
[in]donorFinite producer temperature degC, not the post-withdrawal surface temperature.
Note
Uses downward implicit upwind substitution through fixed-capacity physical layers and equal bottom displacement. Preflights energy arithmetic, flags nonfinite results and leaves physical energy unchanged on that refusal. On success updates layer J, net advective_j and derived bed view. Does not change fixed porewater volume or hydraulic storage; requires exclusive cell access and nonthrowing prepared material dependencies under noexcept.

◆ ageLocalBedPorewater()

bool openswmm::twoD::ageLocalBedPorewater ( MeshHeatState & h,
double dt )
noexcept

Advance the local-storage porewater age inventory without altering water volume.

Parameters
[in,out]hPrepared local bed with row-major mass and per-cell generated-age counters.
[in]dtFinite positive age interval s.
Returns
True for success or disabled/inapplicable mode; false for invalid active interval or any nonfinite resulting age sum. Preflights every cell before writing, so false preserves inventories.
Note
Adds dt*fixed_pore_volume in s*m3 to the age row and generation ledger, including dry surface cells. Physical ground-column age is owned elsewhere. Requires matching allocated arrays and exclusive access; no allocation, water transfer or engine clock change occurs.

◆ appendGroundColumnSystem()

GroundColumnAssembly openswmm::twoD::appendGroundColumnSystem ( const MeshData & mesh,
const SolverOptions2D & options,
GroundHeatState & owner,
int i,
MeshHeatState * h,
double mass,
double volume,
double evaporated,
double dt,
double channel_area,
std::vector< ThermalStore > & stores,
std::vector< ThermalContact > & contacts,
std::vector< ThermalBoundary > & boundaries )

Append one physical column and its finite surface/LID contacts to a shared thermal graph.

Parameters
[in]meshPrepared SI mesh geometry.
[in]optionsResolved water geometry/thermal controls.
[in,out]ownerPrepared canonical physical ground owner. Borrowed in the returned assembly; physical energy is read here and committed later.
[in]iValid cell index with nonempty prepared layers/material arrays.
[in,out]hOptional live surface heat owner; null omits the finite overland water store.
[in]massMixed surface temperature-volume degC*m3.
[in]volumeNonnegative available surface m3; only positive water creates a thermal store.
[in]evaporatedAccepted evaporating volume m3, used for latent flux before water removal.
[in]dtFinite positive duration s.
[in]channel_areaFinite channel footprint m2 in [0,column.area], excluded along with LID footprints from overland/atmospheric ground contact.
[in,out]storesAppended stores with capacity J/K and energy J; existing indices retained.
[in,out]contactsAppended finite W/K links, shifted to global store indices.
[in,out]boundariesAppended temperature/power records, shifted to this graph's stores.
Returns
Assembly retaining borrowed owner pointers, exact index ranges, sampled flux and staged physical LID energy/receipts needed by commitGroundColumnSystem(). It must be used with this graph.
Exceptions
std::runtime_errorInvalid footprint, LID binding/geometry, exhausted active capacity or snow/soil contact setup. Temporary/vector allocation may also throw.
Note
Appends progressively, so failure may leave graph vectors partly extended; callers stage the shared graph. Does not change canonical thermal energy, but reads external LID/snow owners. Requires stable topology, positive active capacities and exclusive graph/owner access through commit.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ appendGwBoundaryCuts()

void openswmm::twoD::appendGwBoundaryCuts ( const GwResolvedBoundary & b,
double start,
double end,
double head,
double bottom,
double thickness,
std::vector< double > & cuts )

Append forcing knots and crossings that delimit smooth boundary-integral pieces.

Append unsorted interior knot and crossing times for a boundary integration interval.

Parameters
[in]bStable resolved boundary with valid linear signals and quality terms.
[in]startInterval start elapsed s.
[in]endInterval end elapsed s, normally greater than start.
[in]headHeld interior groundwater head m.
[in]bottomAquifer bottom elevation m.
[in]thicknessAquifer total thickness m, normally nonnegative.
[in,out]cutsExisting cut times; appends internal hydraulic/quality knots, flux-term zero crossings and hydraulic crossings of head/bottom/top (head boundary) or zero (flow boundary).
Note
Does not clear, sort or deduplicate the destination. Inputs must be finite/prepared; allocation failure can leave a partial appended set. No boundary or groundwater state changes.
Arguments in declaration order Resolved stable boundary; finite start/end elapsed
seconds; held interior head m; aquifer bottom elevation m; nonnegative aquifer thickness m; mutable vector receiving additional cut times. No input state changes, interval checks or deduplication occur. Allocation failure may leave a partially appended destination; the caller sorts and deduplicates before integration.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ applyLocalBedSpecies()

double openswmm::twoD::applyLocalBedSpecies ( const MeshData & mesh,
MeshHeatState & h,
int i,
int r,
double mass,
double volume,
double dt )
noexcept

Exchange one native surface row with finite bed porewater.

Parameters
[in]meshPrepared SI mesh geometry.
[in,out]hPrepared bed/physical-ground owner and per-cell failure/receipt storage.
[in]iValid cell across mesh/material/diagnostic arrays; some failure paths index without guards.
[in]rNative species row (temperature is skipped), matching bed/porewater identity.
[in]massBeginning surface native inventory (concentration*m3), finite nonnegative.
[in]volumeAvailable water m3, finite nonnegative; dry residue does not exchange.
[in]dtFinite positive duration s.
Returns
Updated surface native inventory for caller publication. Physical porewater or local bed inventory changes by the equal opposite accepted amount. Does not transfer water or age species.
Note
Disabled heat/bed, temperature/invalid row or nonpositive duration/water returns mass. GROUND_COLUMN uses a single backward-Euler star solve against physical porewater layers, excluding reserved native exports and channel footprint; stages updates before commit. LOCAL_STORAGE uses the exact finite water/bed pair and records bed_exchange_mass. Invalid physical/result data marks h.failures[i] and returns original mass. Allocations occur inside noexcept and can terminate; this interface does not promise exception recovery. No canonical surface species slot is written.
Here is the call graph for this function:

◆ applyLocalBedSpeciesEuler()

double openswmm::twoD::applyLocalBedSpeciesEuler ( const MeshData & mesh,
MeshHeatState & h,
int i,
int r,
double mass,
double volume,
double dt )

Exchange one native surface row with finite bed porewater for an Euler RK2 stage.

Parameters
[in]meshPrepared SI mesh geometry.
[in,out]hPrepared bed/physical-ground owner and per-cell failure/receipt storage.
[in]iValid cell across mesh/material/diagnostic arrays; some failure paths index without guards.
[in]rNative species row (temperature is skipped), matching bed/porewater identity.
[in]massBeginning surface native inventory (concentration*m3), finite nonnegative.
[in]volumeAvailable water m3, finite nonnegative; dry residue does not exchange.
[in]dtFinite positive duration s.
Returns
Updated surface native inventory for caller publication. Physical porewater or local bed inventory changes by the equal opposite accepted amount. Does not transfer water or age species.
Exceptions
std::runtime_errorInvalid finite porewater contact, overdraw or invalid result; std::out_of_range can propagate for invalid cell geometry. Allocations can also throw.
Note
This Euler path requires an owned active aquifer porewater column. Uses beginning-state donor budgets: incoming soil mass cannot fund an outgoing surface export in the same stage. Caps donor exports and stages porewater updates before commit. No reported failure commits porewater; caller wraps the larger RK2 water/species transaction.
Here is the call graph for this function:

◆ applyMeshHeatCell()

double openswmm::twoD::applyMeshHeatCell ( const MeshData & mesh,
const SolverOptions2D & options,
MeshHeatState & h,
int i,
double mass,
double volume,
double evaporated,
double dt,
bool midpoint )
noexcept

Update one mixed surface thermal sample before accepted intensive water sinks.

Parameters
[in]meshPrepared SI mesh geometry.
[in]optionsResolved wetted-geometry and thermal controls.
[in,out]hPrepared live thermal owner and diagnostics, exclusively accessed for this cell and any coupled LID/snow/ground owners touched by its finite solve.
[in]iValid cell across mesh, heat, material and physical owner arrays, unchecked.
[in]massMixed pre-sink temperature-volume degC*m3; dry residue is retained.
[in]volumeAvailable mixed water m3, nonnegative.
[in]evaporatedAccepted evaporation m3, whose sensible/latent thermal effects apply before the caller removes water, including complete drying.
[in]dtPositive duration s; nonpositive/NaN returns mass. Caller supplies finite controls.
[in]midpointTrue selects midpoint/RK2 only for physical ground-column mode; local bed mode uses its exact affine pair regardless of this flag.
Returns
Updated degC*m3 for caller publication; mass on skipped/refused work. Dry cells can still conduct their bed and update reported dry temperature according to policy.
Note
Physical mode counts attempted interval before solving, catches solve exceptions, flags failure and retains input mass. Commit diagnostics/reciprocal-owner effects may already be changed on a late refusal. Local mode checks finite updates then books bed, atmospheric/deep/water J, component receipts and reported temperature. Does not remove water or write surface transport slots. Unexpected throwing dependencies outside the guarded physical path terminate under noexcept.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ buildCouplingPoints()

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.

Parameters
meshMesh data with coupling maps populated.
ctxSimulation context (for node type and outfall queries).
Returns
Vector of coupling points.
  • Additional argument mesh: Prepared resolved mesh coupling arrays and repeated tri_couplings rows, with consistent vertex/cell shapes and valid nonnegative node IDs into ctx.
  • Additional argument ctx: Matching engine node types/outfall subtype/flap-gate tables, borrowed during call.
    Returns
    Owned coupling vector: vertex points first in vertex order, using the lowest incident cell as representative, then valid authored cell rows in input order. Unattached vertices, negative node IDs and invalid cell rows are skipped; positive node bounds are not guarded.
    Note
    Copies coefficient/area authored flags and outfall gate metadata. Does not resolve final exchange structure, mutate mesh/context, deduplicate repeated points or reserve water. Allocates and can throw; caller preserves mesh/context identity for later use.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ buildLidNodeGroundThermalContact()

std::string openswmm::twoD::buildLidNodeGroundThermalContact ( const LidNodeThermalGraph & graph,
std::size_t combined_store_count,
int ground_store,
double overlap_area,
double ground_area,
double soil_thickness,
double soil_conductivity,
double interface_resistance,
ThermalContact & output )

Connect the compact bottom LID store to an appended physical ground store.

Form the bottom-LID to appended-ground finite conductive contact.

Parameters
[in]graphPrepared consistent LID graph whose last active store is the bottom physical cell.
[in]combined_store_countTotal stores after the ground graph is appended; must exceed the LID store count and fit the int indexing used by the solve.
[in]ground_storeValid appended ground index, at least graph.stores.size().
[in]overlap_areaFinite positive shared footprint m2, no larger than either owner area within relative 1e-12 tolerance (header: overlap_area_m2).
[in]ground_areaFinite positive ground footprint m2 (header: ground_area_m2).
[in]soil_thicknessFinite positive ground layer thickness m (header: ground_layer_thickness_m).
[in]soil_conductivityFinite positive ground conductivity W/(m K) (header: ground_conductivity).
[in]interface_resistanceFinite nonnegative added areal resistance m2 K/W (header: interface_resistance_m2_k_w).
[out]outputReplaced on success by bottom LID/ground store indices and conductance W/K.
Returns
Empty on success, otherwise invalid shape, geometry, owner index or resistance diagnostic.
Note
Uses both half-layer resistances plus the interface term. Does not append stores or mutate owners. Preserves output on refusal; graph numeric physical arrays must already be valid.
  • combined_store_count: Total store count, larger than LID stores and containing ground_store.
  • ground_store: Valid appended ground store index, outside the LID store range.
  • overlap_area_m2: Finite positive overlap m2, bounded by both physical owner footprints.
  • ground_area_m2: Finite positive ground footprint m2.
  • ground_layer_thickness_m: Finite positive receiving layer thickness m.
  • ground_conductivity: Finite positive ground conductivity W/(m K).
  • interface_resistance_m2_k_w: Finite nonnegative additional areal resistance m2 K/W.
    Returns
    Empty after replacing the output contact argument, otherwise validation text with output unchanged. Borrowed graph must end at its physical bottom layer and have consistent SI arrays.
Here is the caller graph for this function:

◆ buildLidNodeThermalGraph()

std::string openswmm::twoD::buildLidNodeThermalGraph ( const LidNodeState & state,
double mobile_water_ft3,
double water_heat_capacity,
const ConductionConfig & material,
double initial_celsius,
LidNodeThermalGraph & output )

Build compact active thermal stores and vertical contacts from accepted LID water state.

Build an SI finite thermal graph from a borrowed accepted physical LID state.

Parameters
[in]stateBorrowed physical LID layers in top-to-bottom contiguous native ft/ft2/ft3 geometry. Richards water is native ft3 per physical cell; other subsurface water is theta*geometric_volume. Existing thermal_energy and optional ground receipts must match physical cells and be finite.
[in]mobile_water_ft3Finite nonnegative water in the separate surface/mobile physical cell, ft3; must not exceed its native geometric volume within tolerance.
[in]water_heat_capacityFinite positive volumetric water capacity J/(m3 K).
[in]materialFinite positive water/sediment conductivity W/(m K), sediment density kg/m3 and specific heat J/(kg K). Nonwater bulk supplies the sediment capacity/conductivity mixture.
[in]initial_celsiusFinite initial degC used only when state.thermal_energy is empty.
[out]outputReplaced on success by SI physical arrays, positive-capacity compact stores with J/K and J, and adjacent active physical-layer conductances W/K. Zero-capacity cells are omitted; no contact bridges an omitted physical layer.
Returns
Empty on success; descriptive shape, geometry, water, material, energy or resistance error.
Note
Stages all output locally, preserving output/state on reported failure. Allocations can throw. Existing layer energy is retained exactly; nonzero energy in a zero-capacity cell is rejected. Does not book heat/water or modify borrowed hydraulic/thermal owners.
  • mobile_water_ft3: Nonnegative native surface/mobile water ft3, bounded by its cell.
  • water_heat_capacity: Finite positive volumetric water capacity J/(m3 K).
  • initial_celsius: Finite initial temperature degC, used if no persisted physical energy.
    Returns
    Empty on success, otherwise validation text; output graph argument is replaced only on success. Physical geometry/material and persistent-energy requirements are detailed in the definition. State is read only; temporary allocations may throw.
Here is the caller graph for this function:

◆ buildMeshTopology()

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*.

Parameters
[in,out]meshThe mesh data with vx/vy/vz and tri_v0/v1/v2 already populated.
Precondition
Mixed-cell connectivity and all per-cell/per-edge arrays are already sized, vertex references are in bounds, and XYZ values are finite in one consistent length unit. This routine is not an input validator.
Postcondition
Replaces neighbor and geometry arrays, retaining triangle/quad cell numbering. Allocates an edge hash map and lazily creates quad VFR data; allocation failures propagate.
Note
Call before stencils/solver initialization, with exclusive mesh access. Geometry lengths/areas retain the mesh's input units.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ buildMeshTopologyCancellable()

bool openswmm::twoD::buildMeshTopologyCancellable ( MeshData & mesh,
const std::function< bool(int)> & progress )

Cancellable equivalent; progress receives integer percent and returns true to cancel.

Parameters
[in,out]meshPre-sized mixed-cell mesh with valid vertex references and finite coordinates, in consistent length units.
[in]progressOptional synchronous percent callback [0,100]; true cancels. It must not mutate the mesh or reenter construction.
Returns
True when all topology/geometry passes complete, false on cancellation.
Postcondition
Cancellation can leave partially rewritten neighbors/geometry; it is not transactional. A caller needing rollback must build a private mesh copy. Allocation/callback exceptions propagate. No callback/storage is retained.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ buildVertexStencils()

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).

Parameters
[in,out]meshThe mesh (must have topology already built).
Precondition
Connectivity, XY cell centroids and vertex arrays are sized and valid in a shared coordinate frame.
Postcondition
Replaces CSR stencil arrays. Degenerate/fully clipped stencils fall back to uniform nonnegative weights; isolated vertices have empty rows. Allocates temporary incidence/weight vectors and may throw.
Note
Run after topology/geometry construction and before solver reads, with exclusive mesh access. No references are retained.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cellFreeSurfaceElevation()

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)

Parameters
[in]mean_depthCell mean depth h̄ = V/A (m), ≥ 0.
[in]za,zb,zcThe cell's three vertex elevations (any order).
Returns
η (m). For mean_depth ≤ 0 returns the lowest vertex elevation.
Note
Elevations must be finite and use the same metre datum. Nonpositive or NaN mean_depth returns the lowest vertex. Delegates to the exact VFR closure, including its finite-iteration inverse; no solver state or input storage is retained.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cellFreeSurfaceElevationOf()

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).

Parameters
[in]meshBorrowed built mixed mesh with vertex beds and quad VFR arrays in metres.
[in]tValid zero-based cell index, not checked here.
[in]mean_depthCell-mean depth V/A, m; nonpositive or NaN selects the lowest bed.
Returns
Shape-aware exact free-surface elevation in m. No geometry/state mutation, allocation, or retained storage.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ collectBCRows()

std::vector< PendingBoundaryRow > openswmm::twoD::collectBCRows ( const std::vector< PendingBoundaryRow > * pending,
const BoundaryData * boundary,
bool drained,
double flow_to_si_applied = 1.0 )
inline

Copy authored boundary rows or reconstruct them from live edge storage.

Parameters
[in]pendingOptional retained authored rows. A nonempty vector wins before draining; after draining it supplies GROUP labels, with the last nonempty label per slot winning.
[in]boundaryOptional live boundary arrays with consistent size() extents. Used after draining, or before draining when pending is null or empty. WALL slots are omitted.
[in]drainedWhether initialization consumed the pending rows into live boundary arrays.
[in]flow_to_si_appliedPositive factor previously applied to constant flow values; reconstruction divides by this factor to recover display flow units per metre. A nonpositive factor uses 1. Stage heads and bed slopes are copied in their current mesh units.
Returns
Independent owned rows, including time-series/curve names where present; an empty vector when no usable source or no non-WALL slots exists. Invalid boundary enum values still produce a row with default parameters; this helper does not validate authored data.
Note
Inputs must remain stable for the call. Allocation failures propagate without mutating them. Live NORMAL_FLOW slopes are copied unchanged, including a zero value; no slope is computed here. The routine walks padded boundary slots rather than validating mesh topology.
See also
collectConveyanceRows()
Here is the call graph for this function:

◆ collectConveyanceRows()

std::vector< PendingEdgeConveyanceRow > openswmm::twoD::collectConveyanceRows ( const std::vector< PendingEdgeConveyanceRow > * pending,
const MeshData * mesh,
bool drained )
inline

Copy authored conveyance rows or reconstruct unique nondefault mesh edges.

Parameters
[in]pendingOptional authored rows; a nonempty vector wins before draining.
[in]meshOptional stable mesh with valid connectivity and vertex indices. Its edge_conveyance array must span n_edge_slots(); absent or undersized storage yields no rows.
[in]drainedWhether initialization consumed pending rows into mesh edge slots.
Returns
Independent owned rows. Reconstruction walks each cell's actual vertex count, sorts endpoint indices, omits factors equal to 1, and emits each undirected edge once. The first encountered nondefault mirror wins; factors are copied without validation or averaging.
Note
Before draining, null/empty pending rows fall back to the mesh. No source is modified; allocation failures propagate. Mixed triangle/quadrilateral connectivity is supported through MeshData::cell_edge_vertices(), rather than assuming a triangle-only local-edge convention.
Here is the call graph for this function:

◆ commitGroundColumnSystem()

double openswmm::twoD::commitGroundColumnSystem ( GroundColumnAssembly & a,
const ThermalSolution & solved )
noexcept

Publish an accepted shared thermal solution into one assembly's canonical owners.

Parameters
[in,out]aLive assembly from appendGroundColumnSystem() against the same graph. Physical LID staging buffers are consumed by swaps; repeated commit is invalid.
[in]solvedSuccessful complete solution with matching graph-indexed energies, temperatures, contact_j and boundary_j arrays. Most bounds/finiteness checks are caller preconditions.
Returns
Updated surface temperature-volume degC*m3, or a.mass for no water/early LID validation failure. That unchanged return does not by itself indicate success; inspect owner failure flags.
Note
Validates staged LID energy/receipt layout, books vertical/ground/snow/water contact J, swaps LID energy/reciprocal receipts, replaces physical soil energy, refreshes bed views and records atmospheric components/temperature/evaporation. Snow refusal flags failure but later commits continue; no blanket rollback. Requires exclusive matching owners and nonthrowing dependencies: an unexpected exception inside this noexcept routine terminates. Does not publish hydraulic water or advance clocks.
Here is the caller graph for this function:

◆ computeBoundaryEdgeFlux()

double openswmm::twoD::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 for host boundary queries. Explicit inertial marchers may use their own prognostic stage-boundary update instead.

Parameters
[in]meshBuilt stable SI mesh; geometry/connectivity arrays span cell i and slot idx.
[in]stateStable surface state with cell depth/head and optional borrowed boundary arrays covering idx. The boundary values must already have their per-step signal resolution applied.
[in]optsValidated face-depth reconstruction options.
[in]dh_epsHead-difference square-root regularization m; nonpositive disables it.
[in]iValid cell index.
[in]idxValid padded local-edge slot belonging to i, normally an exterior edge.
Returns
Inflow-positive volume rate m3/s. WALL, absent boundary data and unknown boundary kind return zero. Specified/rating flow is outward per metre and changes sign after multiplying length. Normal slope is signed; zero slope blocks flow. Stage uses diffusive Manning conductance with regularized head difference and optional VFR face depth, rather than a prognostic inertial update.
Note
No index, array-shape or general finite validation occurs, no signal is sampled and no water budget is applied. Allocation-free, noexcept and read-only with stable borrowed arrays.

◆ computeCellContinuity()

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 = (volume_i − old_volume_i)/dt − ( Σ_e F_e + (rainfall_i + coupling_flux_i − evapSink_i − infilSink_i)·A_i ) where F_e = edge_flux[MeshData::slot(i,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_volume, volume, depth, edge_flux, rainfall, evap_rate, infil_rate, coupling_flux; writes cell_continuity_err (m³/s).

Call AFTER the solver advance, with old_volume holding the start-of-step volumes (i.e. after save_state() but before the next save_state()).

Parameters
meshMesh geometry (tri_area).
stateSurface state (writes cell_continuity_err).
optsSolver options (dry_depth for the evaporation ramp).
dtStep over which old_depth→depth evolved (s).
Note
Uses conserved volume/old_volume in m3, not depth times area; rainfall and evaporation also pass through runtime forcing and snow ownership accessors. It walks actual cell edge counts through MeshData::slot(), including quads. Nonpositive dt clears the entire error vector and returns; finite positive dt is required otherwise. All source/volume/edge/output arrays must be prepared and stable except the exclusively written cell_continuity_err. OpenMP uses opts.num_threads, which must be positive; no allocation or shape/finite validation occurs.
Here is the call graph for this function:

◆ computeFaceVelocity()

void openswmm::twoD::computeFaceVelocity ( const MeshData & mesh,
SurfaceStateData & state,
const SolverOptions2D & opts )

Reconstruct diagnostic cell velocity from wetted-edge normal velocities.

Minimizes sum A_e (n_e.u - Q_e/A_e)^2 over each cell's three/four edges, where A_e is hydraulic depth times edge length and interior transmissivity. Uses VFR endpoint geometry or MEAN depths, including stage-boundary closure rules. Area weights avoid magnifying tiny wet sections. There is no division by cell-average depth, discharge clip or speed cap. FULL_SWE output must use its conserved cell momentum instead of this diagnostic.

Dry cells get zero. Wet cells with rank-deficient normals, nonfinite input, or nonzero flow across a currently dry section get paired NaNs (unavailable). The relative determinant tolerance is 1e-10 * trace^2. API and file readers must retain unavailable values rather than substituting a legacy velocity.

Parameters
meshPrepared SI geometry, topology and interior conveyance.
stateStable depth/head/edge flow and optional boundary state; writes only preallocated face_vx/face_vy. Sign follows internal edge flux.
optsValidated face reconstruction, momentum, dry depth and threads.
Note
Allocation-free O(cells), exclusive per-cell writes, static OpenMP loop.
Here is the call graph for this function:

◆ computeLimitedGradients()

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.

Parameters
meshMesh geometry (for neighbour lookup).
stateSurface state (reads grad_hx/hy, writes grad_hx_lim/hy_lim).
epsilonLimiter epsilon (small positive, typically 1e-6).
nthreadsOpenMP thread count for the per-cell loop (1 = serial).
Note
Uses the cell plus three/four neighboring gradients, mirroring self at exterior edges. The limiter regularization is in dimensionless gradient units; finite nonzero epsilon avoids the zero-norm degeneracy, but its magnitude is squared without range/overflow validation. Input unlimited gradients must already be computed for every cell and remain stable while exclusive limited-gradient output arrays are written. Arrays must span the built mixed mesh; positive nthreads applies when OpenMP is enabled. No allocation or bounds validation occurs.
Here is the call graph for this function:

◆ computeNodeCouplingDQdh1d()

double openswmm::twoD::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).

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).

Parameters
[in]cpValid resolved non-outfall structure and cell/vertex/sampling identity.
[in]meshPrepared SI geometry, valid stencils and fallback weights.
[in]stateMatching live SI cell heads/depths and optional sampling/pond-area buffers.
[in]nodesPrepared 1D node heads/depths/elevations in engine native length units.
[in]optsPositive wet threshold and resolved native-to-SI length conversion.
Note
All selected indices and optional borrowed buffer extents are caller preconditions; no canonical storage, quality, receipts or clock is changed. Passive physical parameters must be finite. Caller serializes reads against live head reconstruction and node mutation.
Returns
Nonnegative stabilizing sensitivity m3/(s m) to SI 1D head; nonpositive/NaN computed sensitivity is returned as zero. Omits gate/ramp/equalization derivatives and the experimental head offset, so this is the documented damping approximation rather than a complete law derivative.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ computeNodeCouplingQ()

double openswmm::twoD::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.

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.

Parameters
provisional_vol_m3Optional 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.
[in]cpValid resolved non-outfall structure and cell/vertex/sampling identity.
[in]meshPrepared SI geometry, valid stencils and fallback weights.
[in]stateMatching live SI cell heads/depths and optional sampling/pond-area buffers.
[in]nodesPrepared 1D node heads/depths/elevations in engine native length units.
[in]optsPositive wet threshold and resolved native-to-SI length conversion.
Note
All selected indices and optional borrowed buffer extents are caller preconditions; no canonical storage, quality, receipts or clock is changed. Passive physical parameters must be finite. Caller serializes reads against live head reconstruction and node mutation.
Parameters
[in]h1d_offset_mFinite added node head m, used by experimental within-window head ramp; zero selects frozen 1D head. It is applied after native-to-SI conversion.
Returns
Signed exchange m3/s, positive surface-to-node. Applies selected law, source-side wetness, legacy crown/area gates where applicable and optional equalization cap. It does not discretely reserve the requested flow or guarantee available water over an arbitrary caller step.
Here is the call graph for this function:

◆ computeUnlimitedGradients()

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

Parameters
meshMesh geometry.
stateSurface state (reads head[], writes grad_hx[], grad_hy[]).
nthreadsOpenMP thread count for the per-cell loop (1 = serial).
Note
Mixed triangles/quadrilaterals are supported. Head is m, edge lengths m and cell area m2, so gradients are dimensionless. All state/geometry arrays must already span the mesh cell/slot counts, and each nonnegative neighbor must be valid. Areas <= 1e-30 produce zero gradients. Boundary heads extrapolate the cell head rather than reading boundary stage signals. Positive nthreads requests that OpenMP thread count when enabled; exclusive output arrays and stable input heads/geometry are required. No allocation, shape validation or synchronization is provided.
Here is the call graph for this function:

◆ configureGroundLidOwners()

std::string openswmm::twoD::configureGroundLidOwners ( SimulationContext & ctx,
const MeshData & mesh,
GroundHeatState & owner,
const std::vector< GwNodeBed > & beds )

Map persistent Mesh Richards LID thermal owners onto physical ground cells.

Parameters
[in]ctxPrepared node subtype/config/state arrays; physical LID geometry is native ft units.
[in]meshSI cell geometry and areas.
[in,out]ownerReplaces lid_owners with a mesh-sized mapping; inactive returns after clearing.
[in]bedsResolved exchange beds with valid zero-based node/cell IDs and optional SI area. Only configured MeshAquifer LIDs participate; invalid/unrelated bindings are skipped.
Returns
Empty on success; diagnostic for duplicate node owners, absent Richards layers, invalid footprint or total LID overlap exceeding the mesh cell area.
Note
Footprint is min(resolved bed area, bottom LID native area converted to m2, mesh area). Sorts each cell's owners by node for deterministic assembly. Does not alter LID energy or water; validation can leave partial mapping and allocation can throw. Caller serializes owner rebuild.
Here is the call graph for this function:

◆ current2DOptionKeys()

std::span< const char *const > openswmm::twoD::current2DOptionKeys ( )

Every current [2D_OPTIONS] key accepted by is2DOptionKey, in documentation order.

Returns
Every current 2D option key in documentation order; process-owned, never empty.

Enumerated by swmm_options_ext_key_count / swmm_options_ext_key_at.

Returns
Process-owned key list; retired keys excluded. No allocation or mutation.
Here is the caller graph for this function:

◆ evapSink()

double openswmm::twoD::evapSink ( double rate,
double depth,
double dry_depth )
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, reducing the instantaneous sink near dryness. Negative rates are treated as zero (no condensation source — use rainfall).

Parameters
rateEvaporation demand rate (m/s).
depthCurrent cell depth (m).
dry_depthDry-depth threshold (m).
Returns
Effective sink rate (m/s, ≥ 0).
Note
Finite rate/depth and positive dry_depth are the intended physical inputs. This function computes only a rate ramp; it has no timestep or available-volume argument and cannot itself bound an explicit step's removed volume. Budget limiting or volume flooring belongs to the caller. A nonpositive rate/depth returns zero; no general NaN/threshold validation occurs.
Here is the caller graph for this function:

◆ faceDepthFromEta()

OPENSWMM_KERNEL_FN double openswmm::twoD::inertial::faceDepthFromEta ( double eta,
double z_lo,
double z_hi )
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 cross-sectional water area divided by the full edge length: η ≤ 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.

Parameters
[in]etaFinite driving free-surface elevation, m.
[in]z_loFinite lower endpoint bed, m.
[in]z_hiFinite upper endpoint bed, m; z_lo <= z_hi.
Returns
Nonnegative edge-averaged hydraulic depth in m; zero below the low endpoint. Near-level relief below 1e-9 m uses the level-edge limit.
Note
Pure host/device arithmetic: no allocation, exceptions, retained pointers or model state mutation. Caller supplies finite valid physical inputs; no general validation.

◆ format2DOptionValue()

std::string openswmm::twoD::format2DOptionValue ( const SolverOptions2D & opts,
const std::string & key )

Format a stored 2D option as a canonical authoring/display token.

Numeric scalars use %.12g, enum/boolean/preset names canonical uppercase, durations shared report step formatting; stored AUTO policy is not resolved to runtime enables. No model or runtime owner mutation/validation; may allocate. This is a display/serialization token, not a source receipt.

Parameters
[in]optsStable retained solver options, not effective runtime owner state.
[in]keyWhole byte-case-insensitive option key.
Returns
Owned value token, or empty for unknown key/unset OUTPUT_FILE. Numeric values use12 significant digits; policy AUTO and configured unit conventions remain stored. No resolution, validation or model mutation; allocation may throw.

Numeric scalars use %.12g, enum/boolean/preset names canonical uppercase, durations shared report step formatting; stored AUTO policy is not resolved to runtime enables. No model or runtime owner mutation/validation; may allocate. This is a display/serialization token, not a source receipt.

  • Argument opts (in): Stable retained solver options, not effective runtime owner state.
  • Argument key (in): Whole byte-case-insensitive option key.
    Returns
    Owned value token, or empty for unknown key/unset OUTPUT_FILE. Numeric values use12 significant digits; policy AUTO and configured unit conventions remain stored. No resolution, validation or model mutation; allocation may throw.
    Format the current value of a [2D_OPTIONS] parameter as the string token parse2DOptionsLine accepts (round-trip safe).
  • Original argument opts: Solver options to read.
  • Original argument key: Parameter name (case-insensitive).
    Returns
    The value token, or an empty string for unknown keys (and for an unset OUTPUT_FILE, whose value token is optional).
Here is the call graph for this function:
Here is the caller graph for this function:

◆ format2DOptionValueEx() [1/2]

std::string openswmm::twoD::format2DOptionValueEx ( const SolverOptions2D & opts,
const Infil2D * infil,
const std::string & key )

Format stored 2D policy with optional infiltration/aquifer authoring fallback.

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.

Parameters
[in]optsStable stored options.
[in]infilOptional borrowed infiltration authoring owner, read only during call.
[in]keyWhole case-insensitive option key.
Returns
Canonical owned value token; unknown key empty. Unset INFIL_STEP uses owner cadence, unset default method uses first '*' row or NONE. No physical/clock mutation; may allocate.

Format a stored option with optional borrowed authoring-owner fallbacks.

  • Argument opts (in): Stable stored solver options.
  • Argument infil (in): Optional stable infiltration authoring owner; consulted only during call.
  • Argument key (in): Whole case-insensitive option key.
    Returns
    Owned canonical token, empty for unknown/unset output path. Unset infiltration cadence uses owner options; unset default method uses first '*' row or NONE. No physics/calendar mutation; may allocate. Does not resolve stored process AUTO to a runtime enable.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ format2DOptionValueEx() [2/2]

std::string openswmm::twoD::format2DOptionValueEx ( const SolverOptions2D & opts,
const Infil2D * infil,
const SubsurfaceConfig * aquifer,
const std::string & key )

Format stored 2D policy with optional infiltration/aquifer authoring fallback.

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.

Parameters
[in]optsStable stored options.
[in]infilOptional borrowed infiltration authoring owner, read only during call.
[in]keyWhole case-insensitive option key.
Returns
Canonical owned value token; unknown key empty. Unset INFIL_STEP uses owner cadence, unset default method uses first '*' row or NONE. No physical/clock mutation; may allocate.
Parameters
[in]aquiferOptional borrowed aquifer authoring owner; unset GW_ET reads its policy or AUTO.
Note
GROUNDWATER AUTO remains stored AUTO; no runtime enable resolution is performed.

Format a stored option with optional borrowed authoring-owner fallbacks.

  • Argument opts (in): Stable stored solver options.
  • Argument infil (in): Optional stable infiltration authoring owner; consulted only during call.
  • Argument key (in): Whole case-insensitive option key.
    Returns
    Owned canonical token, empty for unknown/unset output path. Unset infiltration cadence uses owner options; unset default method uses first '*' row or NONE. No physics/calendar mutation; may allocate. Does not resolve stored process AUTO to a runtime enable.
  • Argument aquifer (in): Optional stable aquifer config; unset GW_ET uses its policy or AUTO.
Here is the call graph for this function:

◆ formatReport2DVars()

std::string openswmm::twoD::formatReport2DVars ( unsigned mask)

Format a report bitmask using canonical presets or ordered keyword list.

Parameters
[in]maskRequested report-group bits.
Returns
Owned canonical preset/list string from formatMask. No model mutation, may allocate.
  • Argument mask (in): Requested report-group bits.
    Returns
    Owned canonical preset/list string from formatMask. No model mutation, may allocate.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ formatSqScope()

std::string openswmm::twoD::formatSqScope ( const SqScopeKey & k)

Scope key ↔ file token ("*", "TAG name", "CELL n" — 1-based).

Parameters
[in]kBorrowed internal zero-based scope key.
Returns
Owned file token text: TAG plus exact name, CELL plus cell+1, otherwise *. Does not quote or validate names/indices; caller supplies a valid resolved key. String allocation may throw.
Here is the caller graph for this function:

◆ groundwaterZoneConcentration()

double openswmm::twoD::groundwaterZoneConcentration ( const SubsurfaceSolver & gw,
int cell,
int species,
bool saturated )
inline

Derive a reported bulk-zone concentration using the active transport ownership model.

Parameters
[in]gwBorrowed initialized aquifer with stable SI water stores, parameters and species arrays.
[in]cellValid zero-based covered cell index, unchecked.
[in]speciesValid zero-based species row, unchecked.
[in]saturatedTrue selects saturated water/inventory; false selects the derived unsaturated bulk sum.
Returns
Native species concentration, age seconds or temperature degrees Celsius; zero when effective capacity is nonpositive. BULK uses water volume only; LAYERED solutes add Kd*rho_b*bulk-soil-volume sorption capacity, with age/temperature always water-only.
Precondition
LAYERED unsat_mass is already refreshed from layer_mass. No finite/bounds checks, allocation, ownership transfer or state mutation; caller serializes with water/mass updates.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ gwClosureToken()

const char * openswmm::twoD::gwClosureToken ( GwClosure c)
noexcept

Return the canonical token for an unsaturated-zone closure.

Parameters
[in]cClosure; an unrecognized enum value falls back to AUTO.
Returns
Borrowed immutable static uppercase string; never null and must not be freed.
Here is the caller graph for this function:

◆ gwScopeToken()

const char * openswmm::twoD::gwScopeToken ( GwScope s)
noexcept

Borrow the input-section token for an aquifer row scope.

Format the canonical groundwater scope keyword.

  • Argument s (in): GwScope enum; unsupported values fall back to GLOBAL.
    Returns
    Process-lifetime immutable literal *, TAG or CELL; do not modify/free it. No allocation or mutation.
    Parameters
    [in]sGLOBAL, TAG or CELL enum.
    Returns
    Static nonowned literal '', TAG or CELL; unknown enum falls back to ''. No mutation.

◆ gwTransportInertWarning()

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.

Parameters
[in]gwStable authoring record; default options alone do not count as authored data.
Returns
Empty when data empty, otherwise owned warning text that authored GW rows have no active aquifer kernel. Caller, not this helper, determines whether the kernel is absent.
Note
Read-only, may allocate; does not validate, disable or mutate authoring/runtime owners.
  • Argument gw (in): Stable authoring record; default options alone do not count as authored data.
    Returns
    Empty when data empty, otherwise owned warning text that authored GW rows have no active aquifer kernel. Caller, not this helper, determines whether the kernel is absent.
    Note
    Read-only, may allocate; does not validate, disable or mutate authoring/runtime owners.
Here is the call graph for this function:

◆ gwUnitFactors()

GwUnitFactors openswmm::twoD::gwUnitFactors ( const SimulationContext & ctx)
noexcept

Resolve authored aquifer units into SI kernel conversion factors.

The factors for this project's unit system.

Parameters
[in]ctxStable flow-unit system selector, read only.
Returns
For US: length .3048 m/ft, rate .0254/3600 m/s per in/hr, inverse-length1/.3048, area .3048^2; metric: length/area/inverse1, rate .001/3600 m/s per mm/hr.
Note
No conversion of actual rows, model mutation, allocation or physical/calendar advance.

Resolve authored aquifer units into SI kernel conversion factors.

  • Argument ctx (in): Stable flow-unit system selector, read only.
    Returns
    For US: length .3048 m/ft, rate .0254/3600 m/s per in/hr, inverse-length1/.3048, area .3048^2; metric: length/area/inverse1, rate .001/3600 m/s per mm/hr.
    Note
    No conversion of actual rows, model mutation, allocation or physical/calendar advance.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ gwZoneToken()

const char * openswmm::twoD::gwZoneToken ( GwZone z)
noexcept

Borrow the input-section token for an aquifer zone.

Format the canonical groundwater zone keyword.

  • Argument z (in): GwZone enum; unsupported values fall back to SAT.
    Returns
    Process-lifetime immutable literal SAT, UNSAT or LAYER; do not modify/free it. No allocation or mutation.
    Parameters
    [in]zSAT, UNSAT or LAYER enum.
    Returns
    Static nonowned null-terminated literal, SAT for unknown enum. No allocation/mutation.

◆ infil2DDestToken()

const char * openswmm::twoD::infil2DDestToken ( Infil2DDest dest)

Inverse of parseInfil2DDest.

Parameters
[in]destAuthored destination enum.
Returns
Borrowed process-lifetime canonical literal, with LOST fallback for an unsupported enum. Do not modify/free it; no allocation or validation of runtime support.

◆ infil2DMethodToken()

const char * openswmm::twoD::infil2DMethodToken ( const Infil2DRow & row)

Inverse of parseInfil2DMethod — the canonical file token.

Parameters
[in]rowBorrowed authored/resolved row.
Returns
Process-lifetime immutable canonical token; NONE when no method or unsupported enum. Do not modify/free the literal; no allocation or mutation.
Here is the caller graph for this function:

◆ infil2DParamCount()

int openswmm::twoD::infil2DParamCount ( InfilModel method)

Number of meaningful positional parameters for method (used by the writer to trim trailing placeholders and by validation).

Parameters
[in]methodEngine infiltration method enum.
Returns
Five for Horton variants, three for Green-Ampt variants/Curve Number, one for Constant, or zero for unsupported method. Counts include the ignored middle Curve Number placeholder. No allocation or mutation.

◆ infilSink()

double openswmm::twoD::infilSink ( double rate,
double depth,
double dry_depth )
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.

Parameters
rateHeld infiltration rate (m/s).
depthCurrent cell depth (m).
dry_depthDry-depth threshold (m).
Returns
Effective sink rate (m/s, ≥ 0).
Note
This is only an instantaneous rate ramp, with the same physical preconditions and lack of timestep/donor-volume limiting as evapSink(). Stable finite inputs and caller-managed water budgets are required; the scalar calculation changes no model state.
Here is the caller graph for this function:

◆ initializeMeshHeat()

std::string openswmm::twoD::initializeMeshHeat ( SimulationContext & ctx,
const MeshData & mesh,
SurfaceStateData & state,
const SolverOptions2D & options,
GroundHeatState * aquifer,
const std::vector< uint8_t > * coverage )

Prepare optional surface thermal stores, porewater and physical ground ownership.

Parameters
[in,out]ctxEngine context with resolved water properties and heat configuration. Heat overrides are resolved here and its physical aquifer may gain surface_owned flags.
[in]meshSI mesh geometry with matching surface cell count/tags.
[in,out]stateSurface owner; clears heat first, allocates cell diagnostics/stores and resets transport.gained_bed when bed species are enabled.
[in]optionsResolved coupled heat and bed model controls; inherited exchange flags come from ctx. Disabled heat or missing surface temperature row leaves empty heat state.
[in,out]aquiferOptional borrowed active porous-equilibrium ground owner, stable/alive through future surface contact solves. Matching populated cells are shared instead of duplicated.
[in]coverageOptional mesh ownership mask; covered hydraulic cells without qualified physical thermal owners are rejected. Null means no explicit hydraulic coverage assertion.
Returns
Empty for success/disabled mode; configuration/material/ownership diagnostic otherwise.
Note
LOCAL_STORAGE is refused over an active aquifer. GROUND_COLUMN creates standalone saturated columns only outside shared aquifer owners. Initializes local-bed porewater at zero native inventory. Initialization mutates progressively; failure/exception can leave partial heat state or external ownership flags. Requires exclusive access and prepared shapes; allocations/forcing parse can throw.
Here is the call graph for this function:

◆ injectAccumulatedExchange()

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.

Parameters
node_concS3 (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).
[in]cpsMatching stable point order and valid cell/vertex identities.
[in]meshPrepared SI geometry/stencils and positive recipient areas.
[in,out]stateAdds coupling_flux m/s and, for positive source rates with valid node tuples, transport.coupling_src native concentration*m/s. Existing rates are retained.
[in]accum_m3Readable vector with at least cps.size() signed accumulated m3 entries.
[in]window_dtFinite positive window duration s; nonpositive returns without work.
[in]signMultiplier, normally +1 source-positive or -1 drain-positive; not validated.
Note
Missing/short node_conc tuples omit species sources for that point. Does not clear/consume accum_m3, change canonical water/mass or reserve donors. Caller clears shared rate arrays once, serializes their scatter and supplies finite values; no allocation occurs.

◆ integrateGwBoundary()

GwBoundaryPulse openswmm::twoD::integrateGwBoundary ( const GwResolvedBoundary & b,
double start,
double dt,
double head,
double bottom,
double thickness,
double conductivity,
int species )

Integrate a resolved edge's requested water, injection composition and independent fluxes.

Integrate requested edge water and species receipts without booking or donor limiting.

Parameters
[in]bPrepared stable boundary with positive finite edge length/distance and valid term rows in [0,species); signals must meet interpolation preconditions.
[in]startFinite elapsed start s.
[in]dtFinite positive duration s; this function does not explicitly validate its sign.
[in]headHeld interior groundwater head m, normally within the aquifer column.
[in]bottomAquifer bottom elevation m.
[in]thicknessNonnegative aquifer thickness m; bounds outside head to [bottom,bottom+thickness].
[in]conductivityFinite nonnegative hydraulic conductivity m/s, used for head boundaries.
[in]speciesNonnegative number of result inventory rows.
Returns
Owned pulse with separately positive requested water input/output m3, incoming advected inventory and signed-flux gross input/output in native_concentration*m3. Temperature inventory uses degrees C*m3. boundary identifier remains its default zero for the caller to assign.
Exceptions
std::runtime_errorIf integrated water or species values are nonfinite.
Note
Uses two-point Gauss quadrature on knot/sign/head-crossing pieces; prescribed linear composition times quadratic head-driven flow is cubic and integrates exactly there. Extraction composition, finite donor limits and state/ledger booking belong to the caller. No input is mutated; invalid term row indices are unchecked, and allocation exceptions propagate.
  • head (in): Held interior hydraulic head m.
  • bottom (in): Aquifer bottom elevation m.
  • thickness (in): Nonnegative aquifer thickness m.
  • conductivity (in): Finite nonnegative hydraulic conductivity m/s.
  • species (in): Nonnegative result row count; every resolved term row must be within it.
    Returns
    Owned pulse of water m3 and native_concentration*m3 species receipts. Throws on nonfinite integrals or allocation failure; does not mutate model/solver state.
    Leading unnamed arguments Stable resolved boundary, finite elapsed start seconds, and
    finite positive duration seconds. Geometry and signals must already be resolved; the consuming solver applies budgets/receipts.
Here is the call graph for this function:

◆ integrateGwSource()

void openswmm::twoD::integrateGwSource ( const GwResolvedSource & s,
double t,
double dt,
double weight,
GwSourcePulse & pulse )
inline

Accumulate signed water and injection/load species forcing over linear intervals.

Parameters
[in]sStable resolved source: flow is total m3/s, positive injection; scale is a positive multiplier. Concentration terms retain native units; massRate terms are native amount/s converted by massScale before accumulation. Signals must satisfy GwSourceSignal::at() preconditions.
[in]tFinite interval start in elapsed simulation seconds.
[in]dtFinite interval duration s. Nonpositive/NaN values return without changing pulse; positive infinity is unsupported rather than explicitly rejected.
[in]weightFinite positive source share, normally a cell fraction. Nonpositive/NaN values or source scale return unchanged; values above one are not clipped or validated.
[in,out]pulseExisting accumulated result. Adds separately nonnegative requested input and extraction water m3. Adds native_concentration*m3 inventory to existing mass entries; invalid species rows are skipped, and this helper never resizes that vector.
Note
Integrates each linear interval exactly, splitting flow sign changes. Concentration enters only with positive injection; extraction composition belongs to the receiving solver. Independent mass loading applies even at zero flow and is not sign-clipped here. No donor/capacity limits or finite-result checks occur. Allocation failure can interrupt after earlier subintervals have already accumulated; this routine provides no rollback or thread synchronization.
Here is the call graph for this function:

◆ is2DOptionKey()

bool openswmm::twoD::is2DOptionKey ( const std::string & key)

True when key (case-insensitive) is a [2D_OPTIONS] parameter accepted by parse2DOptionsLine.

Parameters
[in]keyWhole current option key, byte case-insensitive.
Returns
True for recognized current 2D option key, excluding retired-key list.
Note
Does not validate an option value or its runtime availability; no allocation/mutation.

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.

  • Argument key (in): Whole current option key, byte case-insensitive.
    Returns
    True for recognized current 2D option key, excluding retired-key list.
    Note
    Does not validate an option value or its runtime availability; no allocation/mutation.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ is2DRetiredOptionKey()

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).

Parameters
[in]keyWhole option key, byte case-insensitive.
Returns
True only for recognized retired CVODE/ARKODE keys; no warning or parse side effect.
Note
Allocation-free lookup, no runtime validation or clock change.

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).

  • Argument key (in): Whole option key, byte case-insensitive.
    Returns
    True only for recognized retired CVODE/ARKODE keys; no warning or parse side effect.
    Note
    Allocation-free lookup, no runtime validation or clock change.
Here is the caller graph for this function:

◆ load2DMeshExternalFile()

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,
std::vector< SurfaceRouter2D::PendingInitialQualityRow > * pending_iq_rows,
std::vector< SurfaceRouter2D::PendingInitialBedQualityRow > * pending_ibq_rows,
std::vector< SurfaceRouter2D::PendingBoundaryQualityRow > * pending_bq_rows )

Read a mesh sidecar through a local registry into caller-supplied authoring targets.

Load 2D mesh sections from an external file.

Parameters
[in,out]meshBorrowed mesh append target; caller clears/reconciles inline geometry as needed before this call. This loader does not itself clear mesh or pending boundary stores.
[in,out]optsAuthoring option target and mesh-units marker, may change during partial read.
[in,out]pending_bc_rowsRetained hydraulic boundary rows; sidecar lines append.
[in,out]pending_ec_rowsRetained edge conveyance rows; sidecar lines append.
[in,out]infilOptional target; after successful read, nonempty sidecar defaults/overrides replace corresponding target vectors, positive sidecar cadence replaces options. Empty/zero keeps inline values, including a present section that produces no rows.
[in]mesh_fileUTF-8 absolute or relative sidecar path.
[in]inp_base_dirUTF-8 base directory for relative mesh_file, empty leaves it relative.
[in,out]warningsOptional borrowed retired-option warning sink; null makes those options hard errors. Other row diagnostics return in result.
[in,out]pending_iq_rowsOptional borrowed surface seed target; null omits its handler.
[in,out]pending_ibq_rowsOptional borrowed local-bed seed target; null omits its handler.
[in,out]pending_bq_rowsOptional borrowed boundary-quality target; null omits its handler.
Returns
Empty on successful InputReader read/adoption; otherwise path-qualified parse/read diagnostic.
Note
Registry excludes 2D_MESH_FILE to prevent recursion. Pre-scans SI marker, then uses detached context for reader errors. Mesh/options/pending rows are direct targets, so errors may leave partial append/mutation; only infiltration parses privately before adoption. No unit conversion/topology build/physical advance. Filesystem/allocation/parser exceptions may propagate. Exclusive authoring access; every referenced target must remain stable/alive through synchronous read.

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.

  • Argument mesh: Mesh data to populate.
  • Argument opts: Solver options to populate.
  • Argument mesh_file: Path from the [2D_MESH_FILE] FILE token.
  • Argument inp_base_dir: Directory of the parent .inp file (may be empty).
  • Argument 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.
  • Argument warnings: Optional sink for retired-key warnings (see parse2DOptionsLine); pass &ctx.warnings so a legacy external mesh file still loads.
    Returns
    Empty string on success, or an error description on failure.
    Read a mesh sidecar through a local registry into caller-supplied authoring targets.
  • Additional argument mesh: Borrowed mesh append target; caller clears/reconciles inline geometry as needed before this call. This loader does not itself clear mesh or pending boundary stores.
  • Additional argument opts: Authoring option target and mesh-units marker, may change during partial read.
  • Argument pending_bc_rows (in,out): Retained hydraulic boundary rows; sidecar lines append.
  • Argument pending_ec_rows (in,out): Retained edge conveyance rows; sidecar lines append.
  • Additional argument infil: Optional target; after successful read, nonempty sidecar defaults/overrides replace corresponding target vectors, positive sidecar cadence replaces options. Empty/zero keeps inline values, including a present section that produces no rows.
  • Additional argument mesh_file: UTF-8 absolute or relative sidecar path.
  • Additional argument inp_base_dir: UTF-8 base directory for relative mesh_file, empty leaves it relative.
  • Additional argument warnings: Optional borrowed retired-option warning sink; null makes those options hard errors. Other row diagnostics return in result.
  • Argument pending_iq_rows (in,out): Optional borrowed surface seed target; null omits its handler.
  • Argument pending_ibq_rows (in,out): Optional borrowed local-bed seed target; null omits its handler.
  • Argument pending_bq_rows (in,out): Optional borrowed boundary-quality target; null omits its handler.
    Returns
    Empty on successful InputReader read/adoption; otherwise path-qualified parse/read diagnostic.
    Note
    Registry excludes 2D_MESH_FILE to prevent recursion. Pre-scans SI marker, then uses detached context for reader errors. Mesh/options/pending rows are direct targets, so errors may leave partial append/mutation; only infiltration parses privately before adoption. No unit conversion/topology build/physical advance. Filesystem/allocation/parser exceptions may propagate. Exclusive authoring access; every referenced target must remain stable/alive through synchronous read.
Here is the call graph for this function:

◆ makeGwRechargeBackend()

GwRechargeBackend openswmm::twoD::makeGwRechargeBackend ( const SolverOptions2D & opts,
int n_cells )

Optional stateless host recharge operator. Surface/water/transfer ownership stays with the built-in marcher; absent/unsupported extensions select CPU.

Discover an optional independently scheduled raw-recharge operator.

Parameters
[in]optsBorrowed validated SolverOptions2D, including backend request/session preference. Environment override takes precedence.
[in]n_cellsMesh-cell count, currently unused; no qualified AUTO mesh-size policy is applied.
Returns
Value-owned backend descriptor. Empty evaluate/threads callbacks select scalar CPU and diagnostic explains why. Explicit OMP is required for host-parallel recharge; AUTO remains CPU.
Note
Discovery never transfers groundwater state ownership. Captured execution owner and resident library keep callbacks valid; their array arguments are borrowed synchronously. Callback evaluation exceptions become nonzero failure, while threads callback exceptions can propagate; both execute synchronously on the shared execution owner. Allocation/module-pin exceptions can propagate.

◆ makeSurfaceSolver()

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; AUTO CPU fallback may also report its backend selection rationale.

Parameters
[in]optsSolver options; backend ([2D_OPTIONS] BACKEND) is the model's request, overridden by OPENSWMM_2D_BACKEND when set.
[out]chosenOptional out-param; receives a human-readable backend label (e.g. "cpu (explicit marcher)" or "cuda (NVIDIA A100)").
[in]n_cellsTriangle 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 50000) 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).
Returns
An owned ISurfaceSolver. For a plugin-backed solver the owning shared library is kept resident for the process lifetime.
Parameters
[in]plugin_capableCaller-established compatibility: false forces the built-in marcher for mixed quads, non-local-inertial momentum, transport or other unsupported plugin physics.
Exceptions
std::invalid_argumentFor an unknown OPENSWMM_2D_BACKEND override.
Note
Plugin probing/construction failures are caught and fall back to CPU; allocations for the selected solver/label may still throw. Solver is constructed but not initialized; caller supplies model arrays later.
AUTO uses a default 10000-cell device floor and 50000-cell OpenMP floor, each overridden by its documented environment variable; nonpositive n_cells bypasses size gates. Explicit named backends bypass both. Session auto_backend_cpu applies only to AUTO without an environment override.
Plugin objects are wrapped by a core adapter; the adapter dispatches use/destruction to the resident execution-owner thread. CPU fallback under AUTO may print its selection rationale to stderr.

◆ mapMeshPolyline()

MeshPolylineMapping openswmm::twoD::mapMeshPolyline ( const MeshData & mesh,
const std::vector< double > & x,
const std::vector< double > & y,
const std::function< bool(int)> & progress,
std::size_t first_interval,
std::size_t max_intervals,
bool count_contact_cells )

Clip a polyline into exact convex-cell chainage intervals with local shared-edge ownership.

Exact convex-cell clipping with along-polyline intervals. Shared-edge ownership is divided only over that interval; ordinary interior lengths are not diluted. Reuses the hydraulic locator without changing its path. Invalid points or overlapping mesh interiors return an error and no rows.

Parameters
[in]meshStable validated finite convex CCW topology/geometry, same coordinate frame as x/y. Borrowed only during this call; output retains indices, not mesh references.
[in]xPolyline x coordinates, finite, same extent as y and at least two points; SI m for normal runtime/output chainage convention.
[in]yMatching y coordinates.
[in]progressOptional callback receiving integer percent0..100; true requests cancellation (the ownership preview callback uses the opposite convention). Exceptions propagate.
[in]first_intervalZero-based first generated ownership interval to retain.
[in]max_intervalsMaximum retained interval rows; all intervals still counted/validated.
[in]count_contact_cellsTrue to count distinct contacted cells across all generated intervals, independent of retained page; false leaves contact_cells zero.
Returns
Owned mapping with complete polyline length/covered union length, total interval count, optional distinct-cell count and requested page. Chainage in input coordinate length units; share 1/number-of-coincident-boundary-owners divides ownership without adding covered length. Empty error means geometry accepted unless cancelled. Invalid geometry/overlapping interiors gives error/no rows; other partial metadata can remain on error. Cancellation clears rows/count/contact/covered length and sets cancelled, but may retain traversed full length. Zero-length segments skipped.
Note
No hydraulic/native/clock mutation; constructor/clipping allocates and may throw. Cell edge clipping requires convex CCW prepared mesh; nonfinite/overflow polyline is refused. Serial callback and stable mesh required, no background resources retained.

Clip a polyline into exact convex-cell chainage intervals with local shared-edge ownership.

Note
The unnamed mesh reference is stable validated finite convex CCW geometry in the x/y coordinate frame, borrowed only for this call; output retains indices, not references.
  • Argument x (in): Polyline x coordinates, finite, same extent as y and at least two points; SI m for normal runtime/output chainage convention.
  • Argument y (in): Matching y coordinates.
  • Argument progress (in): Optional callback receiving integer percent0..100; true requests cancellation (the ownership preview callback uses the opposite convention). Exceptions propagate.
  • Argument first_interval (in): Zero-based first generated ownership interval to retain.
  • Argument max_intervals (in): Maximum retained interval rows; all intervals still counted/validated.
  • Argument count_contact_cells (in): True to count distinct contacted cells across all generated intervals, independent of retained page; false leaves contact_cells zero.
Returns
Owned mapping with complete polyline length/covered union length, total interval count, optional distinct-cell count and requested page. Chainage in input coordinate length units; share 1/number-of-coincident-boundary-owners divides ownership without adding covered length. Empty error means geometry accepted unless cancelled. Invalid geometry/overlapping interiors gives error/no rows; other partial metadata can remain on error. Cancellation clears rows/count/contact/covered length and sets cancelled, but may retain traversed full length. Zero-length segments skipped.
Note
No hydraulic/native/clock mutation; constructor/clipping allocates and may throw. Cell edge clipping requires convex CCW prepared mesh; nonfinite/overflow polyline is refused. Serial callback and stable mesh required, no background resources retained.
Here is the caller graph for this function:

◆ meshState()

void openswmm::twoD::checkpoint::meshState ( detail::CompletedSourceArchive & a,
SurfaceStateData & s )

Archive and validate accepted mesh hydraulic, species and optional snow/thermal runtime.

Archive the accepted mesh runtime payload using the shared physical-state validator.

Arguments in order Sequential internal reader/writer archive, then mutable prepared
SurfaceStateData. Read mode requires matching model/profile and preallocated fixed-array extents. Fields retain SI/native solver units; geometry, borrowed owners and provider configuration are handled by the caller.
Exceptions
std::runtime_errorOn unsupported participant profiles, archive shape or invalid finite/water/species/age/bed runtime values. Allocation errors propagate.
Note
Reading can change earlier fields before failure; restore into a private candidate for transactional publication. Saves validate the same canonical state. No model reconstruction, whole-engine framing or ownership transfer occurs here.
Parameters
[in,out]aSequential archive with matching prepared model and fixed extents.
[in,out]sSurface runtime state, progressively decoded on read and validated in both modes.
Exceptions
std::runtime_errorOn unsupported profiles, shape/value or participant errors.
Note
Delegates to meshStateImpl(); no rollback, model reconstruction or pointer ownership transfer occurs. Callers stage private state before publishing a restore.

◆ parse2DBoundaryConditionsLine()

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.

Parameters
[in]tokensEmpty or zero-based TRI EDGE TYPE [PARAM_1 [reserved [GROUP]]]. EDGE checked against max four slots, actual cell shape/upper bound deferred. TYPE wall/normal/stage/flow/series/ rating; '' or missing parameter leaves default. PARAM_1 is dimensionless slope, authored head, display flow per metre, or deferred table name by type. Group copied from sixth token unless ''.
[in,out]pending_rowsExisting rows retained; appends one complete candidate on success.
Returns
Empty on empty/parsed row, otherwise arity/index/type/numeric diagnostic.
Note
No table/mesh/physical finite validation; reserved fifth/surplus tokens ignored. No scaling, activation or clock advance; allocation may throw, exclusive retained authoring access.

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.

  • Argument tokens (in): Empty or zero-based TRI EDGE TYPE [PARAM_1 [reserved [GROUP]]]. EDGE checked against max four slots, actual cell shape/upper bound deferred. TYPE wall/normal/stage/flow/series/ rating; '' or missing parameter leaves default. PARAM_1 is dimensionless slope, authored head, display flow per metre, or deferred table name by type. Group copied from sixth token unless ''.
  • Argument pending_rows (in,out): Existing rows retained; appends one complete candidate on success.
    Returns
    Empty on empty/parsed row, otherwise arity/index/type/numeric diagnostic.
    Note
    No table/mesh/physical finite validation; reserved fifth/surplus tokens ignored. No scaling, activation or clock advance; allocation may throw, exclusive retained authoring access.
Here is the caller graph for this function:

◆ parse2DBoundaryQualityLine()

std::string openswmm::twoD::parse2DBoundaryQualityLine ( const std::vector< std::string > & tokens,
std::vector< SurfaceRouter2D::PendingBoundaryQualityRow > & rows )

Parse one zero-based surface boundary native concentration row.

S2 — one [2D_BOUNDARY_QUALITY] line (TRI EDGE SPECIES CONC). Empty = OK.

Parameters
[in]tokensEmpty or exact TRI EDGE SPECIES CONC. TRI nonnegative zero-based unified cell, EDGE in max four slots; actual cell bound/shape and boundary type checked later. CONC finite nonnegative except case-insensitive TEMPERATURE signed degC; age retained authored hours.
[in,out]rowsAppends one complete candidate on success, retaining earlier rows.
Returns
Empty on empty/success, otherwise count/index/numeric/sign diagnostic.
Note
No table/native-row resolution, scaling, boundary flux, mass or clock change. Allocation can throw; exclusive authoring access, initialization validates actual model identity.

Parse one zero-based surface boundary native concentration row.

  • Argument tokens (in): Empty or exact TRI EDGE SPECIES CONC. TRI nonnegative zero-based unified cell, EDGE in max four slots; actual cell bound/shape and boundary type checked later. CONC finite nonnegative except case-insensitive TEMPERATURE signed degC; age retained authored hours.
  • Argument rows (in,out): Appends one complete candidate on success, retaining earlier rows.
    Returns
    Empty on empty/success, otherwise count/index/numeric/sign diagnostic.
    Note
    No table/native-row resolution, scaling, boundary flux, mass or clock change. Allocation can throw; exclusive authoring access, initialization validates actual model identity.
Here is the caller graph for this function:

◆ parse2DCoveragesLine()

std::string openswmm::twoD::parse2DCoveragesLine ( const std::vector< std::string > & tokens,
std::vector< CoverageRow2D > & rows )

Parse one scoped 2D coverage authoring row.

Parameters
[in]tokensComplete tokenized row beginning *, TAG name or one-based CELL n, followed by LANDUSE/PERCENT pairs, nonnegative percentages summing to at most 100+1e-9. Numeric conversion accepts NaN/infinity where comparison checks do not reject them; upstream input should supply finite representable values. IDs are resolved later.
[in,out]rowsDestination authoring vector. On success erases any earlier identical full scope key then appends the replacement coverage set.
Returns
Empty on success, otherwise parse diagnostic with rows unchanged before append/erase.
Note
Allocation can throw; replacement erasure can precede a failing final allocation. No runtime state or ledger is resolved.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse2DCurbLengthLine()

std::string openswmm::twoD::parse2DCurbLengthLine ( const std::vector< std::string > & tokens,
std::vector< CurbRow2D > & rows )

Parse one scoped 2D curb authoring row.

Parameters
[in]tokensComplete tokenized row beginning *, TAG name or one-based CELL n, followed by one nonnegative length in project length units. Numeric conversion accepts NaN/infinity where comparison checks do not reject them; upstream input should supply finite representable values. IDs are resolved later.
[in,out]rowsDestination authoring vector. Appends on success; duplicate scope/species handling is deferred to ordered resolution.
Returns
Empty on success, otherwise parse diagnostic with rows unchanged before append/erase.
Note
Allocation can throw; ordinary validation failure appends nothing. No runtime state or ledger is resolved.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse2DEdgeConveyanceLine()

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.

Parameters
[in]tokensEmpty or FROM_VERTEX TO_VERTEX CONVEYANCE; distinct nonnegative zero-based int vertex indices, dimensionless multiplier [0,1]. Surplus ignored.
[in,out]pending_rowsAppends one parsed undirected vertex-pair candidate on success.
Returns
Empty on empty/success; arity/index/numeric/out-of-range multiplier diagnostic otherwise.
Note
Range is rejected, not clamped. strtod NaN passes ordinary comparisons, so this is not a complete finite-value validator. Vertex existence/edge topology deferred; no scaling/physical advance. Allocation may throw; exclusive authoring access.

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] (out-of-range values rejected, not clamped).

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.

  • Argument tokens (in): Empty or FROM_VERTEX TO_VERTEX CONVEYANCE; distinct nonnegative zero-based int vertex indices, dimensionless multiplier [0,1]. Surplus ignored.
  • Argument pending_rows (in,out): Appends one parsed undirected vertex-pair candidate on success.
    Returns
    Empty on empty/success; arity/index/numeric/out-of-range multiplier diagnostic otherwise.
    Note
    Range is rejected, not clamped. strtod NaN passes ordinary comparisons, so this is not a complete finite-value validator. Vertex existence/edge topology deferred; no scaling/physical advance. Allocation may throw; exclusive authoring access.
Here is the caller graph for this function:

◆ parse2DInfiltrationDefaultsLine()

std::string openswmm::twoD::parse2DInfiltrationDefaultsLine ( const std::vector< std::string > & tokens,
Infil2D & infil )

§5.5 track I — parse a single [2D_INFILTRATION_DEFAULTS] line.

Parameters
[in]tokensEmpty or TAG|* METHOD [P1..P5] [DEST], method positional parameters in project units; '-' retains zero default, recognized trailing destination optional.
[in,out]infilAppends a complete default/tag row on success; previous rows retained.
Returns
Empty on empty/success, otherwise grammar/method/destination/parameter diagnostic.
Note
Defers tag/exact parameter/physical/ownership validation and unit conversion to resolve(). No runtime rate/cumulative/clock advance; allocation may throw, exclusive authoring access.

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 : retained authoring destination, validated against resolved source ownership. Initialization chooses the supported aquifer/legacy/lost receiver.

Rows are appended to infil.defaults() in file order and resolved against the mesh in Infil2D::resolve() (D-I3: override > tag > * > none).

  • Argument tokens (in): Empty or TAG|* METHOD [P1..P5] [DEST], method positional parameters in project units; '-' retains zero default, recognized trailing destination optional.
  • Argument infil (in,out): Appends a complete default/tag row on success; previous rows retained.
    Returns
    Empty on empty/success, otherwise grammar/method/destination/parameter diagnostic.
    Note
    Defers tag/exact parameter/physical/ownership validation and unit conversion to resolve(). No runtime rate/cumulative/clock advance; allocation may throw, exclusive authoring access.
Here is the caller graph for this function:

◆ parse2DInfiltrationLine()

std::string openswmm::twoD::parse2DInfiltrationLine ( const std::vector< std::string > & tokens,
Infil2D & infil )

§5.5 track I — parse a single [2D_INFILTRATION] line.

Parameters
[in]tokensEmpty or one-based CELL METHOD [P1..P5] [DEST], positional project-unit parameters and optional final destination; '-' retains zero default.
[in,out]infilAppends complete per-cell override with stored zero-based cell on success.
Returns
Empty on empty/success, otherwise cell lower-bound/grammar/method/parameter diagnostic.
Note
Mesh upper bound, physical parameters/ownership and unit conversion deferred to resolve(). Does not alter prepared rate/cumulative/clock state; allocation can throw, exclusive authoring only.

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.

  • Argument tokens (in): Empty or one-based CELL METHOD [P1..P5] [DEST], positional project-unit parameters and optional final destination; '-' retains zero default.
  • Argument infil (in,out): Appends complete per-cell override with stored zero-based cell on success.
    Returns
    Empty on empty/success, otherwise cell lower-bound/grammar/method/parameter diagnostic.
    Note
    Mesh upper bound, physical parameters/ownership and unit conversion deferred to resolve(). Does not alter prepared rate/cumulative/clock state; allocation can throw, exclusive authoring only.
Here is the caller graph for this function:

◆ parse2DInfiltrationOptionsLine()

std::string openswmm::twoD::parse2DInfiltrationOptionsLine ( const std::vector< std::string > & tokens,
Infil2D & infil )

§5.5 track I — parse a single [2D_INFILTRATION_OPTIONS] line.

Parameters
[in]tokensEmpty or INFIL_STEP duration (hh:mm:ss, hh:mm or seconds); surplus ignored.
[in,out]infilReplaces authored cadence seconds on accepted duration, otherwise unchanged.
Returns
Empty on empty/accepted row, otherwise key/arity/negative parsed duration diagnostic.
Note
Zero defers to wet-step resolution. This branch checks <0 without an independent finite check. Does not resolve methods/advance infiltration capacity or clocks; serial authoring only.

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).

  • Argument tokens (in): Empty or INFIL_STEP duration (hh:mm:ss, hh:mm or seconds); surplus ignored.
  • Argument infil (in,out): Replaces authored cadence seconds on accepted duration, otherwise unchanged.
    Returns
    Empty on empty/accepted row, otherwise key/arity/negative parsed duration diagnostic.
    Note
    Zero defers to wet-step resolution. This branch checks <0 without an independent finite check. Does not resolve methods/advance infiltration capacity or clocks; serial authoring only.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse2DInitialBedQualityLine()

std::string openswmm::twoD::parse2DInitialBedQualityLine ( const std::vector< std::string > & tokens,
std::vector< SurfaceRouter2D::PendingInitialBedQualityRow > & rows )

Parse a finite local-bed native concentration seed without resolving a physical bed.

Initial local-bed porewater concentrations; same scope grammar as surface.

Parameters
[in]tokensEmpty or exact global/tag/one-based-CELL SPECIES CONC row, same scope grammar as surface initial quality. CONC finite nonnegative, including any temperature-named token here.
[in,out]rowsExisting retained rows; appends one complete candidate on success.
Returns
Empty on empty/success, otherwise scope/arity/index/value diagnostic.
Note
Bed owner/species support (including later temperature refusal) and mesh/tag/cell lookup are deferred. Native concentration/age authored hours retained without conversion or physical seeding. Allocation may throw, exclusive authoring access; no water/energy/clock advance.

Parse a finite local-bed native concentration seed without resolving a physical bed.

  • Argument tokens (in): Empty or exact global/tag/one-based-CELL SPECIES CONC row, same scope grammar as surface initial quality. CONC finite nonnegative, including any temperature-named token here.
  • Argument rows (in,out): Existing retained rows; appends one complete candidate on success.
    Returns
    Empty on empty/success, otherwise scope/arity/index/value diagnostic.
    Note
    Bed owner/species support (including later temperature refusal) and mesh/tag/cell lookup are deferred. Native concentration/age authored hours retained without conversion or physical seeding. Allocation may throw, exclusive authoring access; no water/energy/clock advance.
Here is the caller graph for this function:

◆ parse2DInitialQualityLine()

std::string openswmm::twoD::parse2DInitialQualityLine ( const std::vector< std::string > & tokens,
std::vector< SurfaceRouter2D::PendingInitialQualityRow > & rows )

Parse one scoped initial surface native concentration authoring row.

S1/S2 — one [2D_INITIAL_QUALITY] line. Empty string = OK.

Parameters
[in]tokensEmpty; '* SPECIES CONC'; 'TAG name SPECIES CONC'; or 'CELL n SPECIES CONC'. Exact arity required, CELL positive one-based stored zero-based. CONC finite nonnegative except case-insensitive TEMPERATURE may be negative. Age retained in authored hours, temperature degC.
[in,out]rowsExisting rows retained; appends one complete candidate on success.
Returns
Empty on empty/success, otherwise scope/count/index/numeric/sign diagnostic.
Note
Species/tag/mesh existence and canonical case/layout, age conversion and mass seeding are separate initialization work. No water/native/clock change; allocation may throw, serial authoring.

Parse one scoped initial surface native concentration authoring row.

  • Argument tokens (in): Empty; '* SPECIES CONC'; 'TAG name SPECIES CONC'; or 'CELL n SPECIES CONC'. Exact arity required, CELL positive one-based stored zero-based. CONC finite nonnegative except case-insensitive TEMPERATURE may be negative. Age retained in authored hours, temperature degC.
  • Argument rows (in,out): Existing rows retained; appends one complete candidate on success.
    Returns
    Empty on empty/success, otherwise scope/count/index/numeric/sign diagnostic.
    Note
    Species/tag/mesh existence and canonical case/layout, age conversion and mass seeding are separate initialization work. No water/native/clock change; allocation may throw, serial authoring.
Here is the caller graph for this function:

◆ parse2DInitialVelocityLine()

std::string openswmm::twoD::parse2DInitialVelocityLine ( const std::vector< std::string > & tokens,
MeshData & mesh )

Parse a single line from the [2D_INITIAL_VELOCITY] section.

TRI is zero-based unified cell index already present; U/V are m/s without project-length conversion. Writes both components only after both numeric syntax checks; no finite check, surplus ignored. Requires tri_init_u/v extents matching mesh. No allocation/physics/clock update; serial edit.

Format: TRI U V (m/s; default 0,0 — rows may cover any subset)

Parameters
tokensWhitespace-split tokens from the line.
meshMesh data to update (tri_init_u / tri_init_v).
Returns
Empty string on success, or error description.

TRI is zero-based unified cell index already present; U/V are m/s without project-length conversion. Writes both components only after both numeric syntax checks; no finite check, surplus ignored. Requires tri_init_u/v extents matching mesh. No allocation/physics/clock update; serial edit.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse2DLoadingsLine()

std::string openswmm::twoD::parse2DLoadingsLine ( const std::vector< std::string > & tokens,
std::vector< LoadingRow2D > & rows )

Parse one scoped 2D loading authoring row.

Parameters
[in]tokensComplete tokenized row beginning *, TAG name or one-based CELL n, followed by SPECIES and nonnegative initial user mass per acre/ha. Numeric conversion accepts NaN/infinity where comparison checks do not reject them; upstream input should supply finite representable values. IDs are resolved later.
[in,out]rowsDestination authoring vector. Appends on success; duplicate scope/species handling is deferred to ordered resolution.
Returns
Empty on success, otherwise parse diagnostic with rows unchanged before append/erase.
Note
Allocation can throw; ordinary validation failure appends nothing. No runtime state or ledger is resolved.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse2DOptionsLine()

std::string openswmm::twoD::parse2DOptionsLine ( const std::vector< std::string > & tokens,
SolverOptions2D & opts,
std::vector< std::string > * warnings )

Parse a single line from the [2D_OPTIONS] section.

Recognizes authoring process/backend/momentum/closure/coupling/report/heat/infiltration policy; options carry their documented SI solver units (s, m, m2/s, dimensionless coefficients). REPORT_2D_VARIABLES/SPECIES consume all value tokens; most other keys use first value and ignore surplus. Enum values/ranges are checked per key, but numeric parsing is not uniformly finite: DISPERSION and report/infil duration explicitly enforce finiteness, while several legacy scalars can retain NaN/Inf or unbounded values for later validation. Some branches assign before returning a diagnostic, so use a copy for transactional edits. Retired keys/INTEGRATOR values append warning and return success only with a nonnull warning sink; otherwise diagnostic failure. No physical owner rebuild or clock advance; allocations can throw after partial options/warnings changes.

Parameters
tokensWhitespace-split tokens from the line.
optsOutput solver options to populate.
warningsWhen 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.
Returns
Empty string on success, or error description.

Recognizes authoring process/backend/momentum/closure/coupling/report/heat/infiltration policy; options carry their documented SI solver units (s, m, m2/s, dimensionless coefficients). REPORT_2D_VARIABLES/SPECIES consume all value tokens; most other keys use first value and ignore surplus. Enum values/ranges are checked per key, but numeric parsing is not uniformly finite: DISPERSION and report/infil duration explicitly enforce finiteness, while several legacy scalars can retain NaN/Inf or unbounded values for later validation. Some branches assign before returning a diagnostic, so use a copy for transactional edits. Retired keys/INTEGRATOR values append warning and return success only with a nonnull warning sink; otherwise diagnostic failure. No physical owner rebuild or clock advance; allocations can throw after partial options/warnings changes.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse2DQuadLine()

std::string openswmm::twoD::parse2DQuadLine ( const std::vector< std::string > & tokens,
MeshData & mesh )

Parse a single line from the [2D_QUADS] section.

Parameters
[in]tokensV1 V2 V3 V4 MANNINGS_N [INIT_DEPTH] [TAG], zero-based int vertex indices in cyclic order. Numeric optional mean depth must be nonnegative; nonnumeric optional token is TAG.
[in,out]meshAppends one four-vertex cell after existing unified cells, retaining authored length/depth units and n coefficient. Earlier rows retained on syntax error.
Returns
Empty on parsed row, otherwise arity/index/numeric/depth diagnostic.
Note
No finite/index-upper-bound/convexity/degeneracy validation; caller keeps all triangles before quads. Surplus ignored. No topology/physical owner rebuild or clock advance occurs. Requires exclusive authoring access; allocation may throw after resizing/appending begins. Numeric helpers accept full strtod/strtol syntax without general finite/range/errno checks; deferred model validation remains necessary.

Format: V1 V2 V3 V4 MANNINGS_N [INIT_DEPTH] [TAG] Quads are appended after every triangle (cell index = n_triangles + j).

  • Argument tokens (in): V1 V2 V3 V4 MANNINGS_N [INIT_DEPTH] [TAG], zero-based int vertex indices in cyclic order. Numeric optional mean depth must be nonnegative; nonnumeric optional token is TAG.
  • Argument mesh (in,out): Appends one four-vertex cell after existing unified cells, retaining authored length/depth units and n coefficient. Earlier rows retained on syntax error.
    Returns
    Empty on parsed row, otherwise arity/index/numeric/depth diagnostic.
    Note
    No finite/index-upper-bound/convexity/degeneracy validation; caller keeps all triangles before quads. Surplus ignored. No topology/physical owner rebuild or clock advance occurs. Requires exclusive authoring access; allocation may throw after resizing/appending begins. Numeric helpers accept full strtod/strtol syntax without general finite/range/errno checks; deferred model validation remains necessary.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse2DTriangleLine()

std::string openswmm::twoD::parse2DTriangleLine ( const std::vector< std::string > & tokens,
MeshData & mesh )

Parse a single line from the [2D_TRIANGLES] section.

Vertex indices are zero-based integer tokens, with mesh range/degeneracy/orientation checked later. INIT_DEPTH optional numeric nonnegative authored mean depth; a nonnumeric fifth token is legacy TAG. Sixth is TAG only with numeric depth. Mannings n is retained without positivity validation. Refuses triangles after any quad to preserve unified cell numbering; surplus ignored. No topology/physical owner rebuild or clock advance occurs. Requires exclusive authoring access; allocation may throw after resizing/appending begins. Numeric helpers accept full strtod/strtol syntax without general finite/range/errno checks; deferred model validation remains necessary.

Format: V1 V2 V3 MANNINGS_N [INIT_DEPTH] [TAG]

Parameters
tokensWhitespace-split tokens from the line.
meshMesh data to append triangle to.
Returns
Empty string on success, or error description.

Vertex indices are zero-based integer tokens, with mesh range/degeneracy/orientation checked later. INIT_DEPTH optional numeric nonnegative authored mean depth; a nonnumeric fifth token is legacy TAG. Sixth is TAG only with numeric depth. Mannings n is retained without positivity validation. Refuses triangles after any quad to preserve unified cell numbering; surplus ignored. No topology/physical owner rebuild or clock advance occurs. Requires exclusive authoring access; allocation may throw after resizing/appending begins. Numeric helpers accept full strtod/strtol syntax without general finite/range/errno checks; deferred model validation remains necessary.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse2DTriangleNodeMapLine()

std::string openswmm::twoD::parse2DTriangleNodeMapLine ( const std::vector< std::string > & tokens,
MeshData & mesh )

Parse a single line from the [2D_TRIANGLE_NODE_MAP] section.

Resolves zero-based unified cell index or exact first matching tag fallback, including out-of-range numeric tags. Every row appends a distinct coupling (multiple nodes per cell) and updates legacy per-cell name/CD/area mirror, last row wins there. Optional malformed CD/area is ignored; no finite/sign/node-name check, retained AREA in project-length2. Array mirrors change before vector append, so allocation failure can leave partial mutation. No runtime owner rebuild or physics/calendar advance; exclusive authoring access and prepared per-cell arrays required.

Format: TRIANGLE_INDEX_OR_TAG SWMM_NODE_NAME [CD] [AREA]

Parameters
tokensWhitespace-split tokens from the line.
meshMesh data to update coupling map.
Returns
Empty string on success, or error description.

Resolves zero-based unified cell index or exact first matching tag fallback, including out-of-range numeric tags. Every row appends a distinct coupling (multiple nodes per cell) and updates legacy per-cell name/CD/area mirror, last row wins there. Optional malformed CD/area is ignored; no finite/sign/node-name check, retained AREA in project-length2. Array mirrors change before vector append, so allocation failure can leave partial mutation. No runtime owner rebuild or physics/calendar advance; exclusive authoring access and prepared per-cell arrays required.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse2DVertexLine()

std::string openswmm::twoD::parse2DVertexLine ( const std::vector< std::string > & tokens,
MeshData & mesh )

Parse a single line from the [2D_VERTICES] section.

Appends a zero-based vertex in input row order; X/Y/Z retain authored project length or sidecar-declared SI units, converted only at initialization. Optional tag copied exactly, surplus ignored. Syntax errors return before resizing, but no finite/geometry/duplicate-tag validation occurs. No topology/physical owner rebuild or clock advance occurs. Requires exclusive authoring access; allocation may throw after resizing/appending begins. Numeric helpers accept full strtod/strtol syntax without general finite/range/errno checks; deferred model validation remains necessary.

Format: X Y Z [TAG]

Parameters
tokensWhitespace-split tokens from the line.
meshMesh data to append vertex to.
Returns
Empty string on success, or error description.

Appends a zero-based vertex in input row order; X/Y/Z retain authored project length or sidecar-declared SI units, converted only at initialization. Optional tag copied exactly, surplus ignored. Syntax errors return before resizing, but no finite/geometry/duplicate-tag validation occurs. No topology/physical owner rebuild or clock advance occurs. Requires exclusive authoring access; allocation may throw after resizing/appending begins. Numeric helpers accept full strtod/strtol syntax without general finite/range/errno checks; deferred model validation remains necessary.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse2DVertexNodeMapLine()

std::string openswmm::twoD::parse2DVertexNodeMapLine ( const std::vector< std::string > & tokens,
MeshData & mesh )

Parse a single line from the [2D_VERTEX_NODE_MAP] section.

Resolves zero-based index first, then exact tag fallback (including out-of-range numeric tags), first matching tag wins. Stores deferred native node name; optional CD dimensionless/AREA project-length2 are applied only when numeric, malformed optional tokens are silently ignored. Valid optional values are not range/finite checked. No node-name lookup yet; surplus ignored. Name allocation can throw; exclusive edit access, later resolution/scaling required.

Format: VERTEX_INDEX_OR_TAG SWMM_NODE_NAME [CD] [AREA]

Parameters
tokensWhitespace-split tokens from the line.
meshMesh data to update coupling map.
Returns
Empty string on success, or error description.

Resolves zero-based index first, then exact tag fallback (including out-of-range numeric tags), first matching tag wins. Stores deferred native node name; optional CD dimensionless/AREA project-length2 are applied only when numeric, malformed optional tokens are silently ignored. Valid optional values are not range/finite checked. No node-name lookup yet; surplus ignored. Name allocation can throw; exclusive edit access, later resolution/scaling required.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ parseAquiferBoundaryLine()

std::string openswmm::twoD::parseAquiferBoundaryLine ( const std::vector< std::string > & t,
std::vector< GwBoundaryRow > & rows )

Parse a unique hydraulic aquifer exterior-edge prescription.

Register the four handlers against registry, writing into cfg.

Parameters
[in]tExactly CELL n EDGE e HEAD|FLOW CONST value|SERIES name. CELL positive one-based stored zero-based; EDGE local zero-based0..3, int-representable. Constant finite signed head in project length or total signed edge flow m3/s, retained for later conversion; series name nonempty.
[in,out]rowsExisting retained prescriptions; appends complete row if cell/edge pair unique.
Returns
Empty on success, otherwise grammar/index/kind/value/duplicate diagnostic.
Note
Defers actual cell shape/exterior/coverage/table/physical checks. No water/native/clock advance; allocation can throw, exclusive authoring access. Declaration calls t tokens.

Parse a unique hydraulic aquifer exterior-edge prescription.

  • Argument tokens (in): Exactly CELL n EDGE e HEAD|FLOW CONST value|SERIES name. CELL positive one-based stored zero-based; EDGE local zero-based0..3, int-representable. Constant finite signed head in project length or total signed edge flow m3/s, retained for later conversion; series name nonempty.
  • Argument rows (in,out): Existing retained prescriptions; appends complete row if cell/edge pair unique.
    Returns
    Empty on success, otherwise grammar/index/kind/value/duplicate diagnostic.
    Note
    Defers actual cell shape/exterior/coverage/table/physical checks. No water/native/clock advance; allocation can throw, exclusive authoring access. Declaration calls t tokens.
Here is the caller graph for this function:

◆ parseAquiferLine()

std::string openswmm::twoD::parseAquiferLine ( const std::vector< std::string > & tokens,
std::vector< GwAquiferRow > & rows )

Parse a scoped aquifer hydraulic authoring row into a local candidate.

One [2D_AQUIFER] line. Empty return = OK.

Parameters
[in]tokensNonempty (*|TAG name|CELL positive-one-based-index) followed by KS ZS THETA_S THETA_R ALPHA and optional key/value law/closure/layer fields. KS/C_LOSS project rainfall units in/hr or mm/hr, ZS/PSI_B/HG0 project length, ALPHA inverse project length, others dimensionless.
[in,out]rowsExisting rows retained, appends one complete candidate only after validation.
Returns
Empty on success, otherwise scope/arity/finite numeric/enum/range diagnostic.
Note
Requires KS/ZS/ALPHA/lambda>0, theta_s(0,1], theta_r[0,theta_s), vg_n>1, psi_b/c_loss>=0, optional layers2..128. Stores CELL zero-based; integer tokens must be int-representable. HG0 and vg_L are finite but not additionally bounded here. Defers mesh/tag/law compatibility and conversion. No physical inventory/clock mutation; allocation may throw, exclusive authoring access.

Parse a scoped aquifer hydraulic authoring row into a local candidate.

  • Argument tokens (in): Nonempty (*|TAG name|CELL positive-one-based-index) followed by KS ZS THETA_S THETA_R ALPHA and optional key/value law/closure/layer fields. KS/C_LOSS project rainfall units in/hr or mm/hr, ZS/PSI_B/HG0 project length, ALPHA inverse project length, others dimensionless.
  • Argument rows (in,out): Existing rows retained, appends one complete candidate only after validation.
    Returns
    Empty on success, otherwise scope/arity/finite numeric/enum/range diagnostic.
    Note
    Requires KS/ZS/ALPHA/lambda>0, theta_s(0,1], theta_r[0,theta_s), vg_n>1, psi_b/c_loss>=0, optional layers2..128. Stores CELL zero-based; integer tokens must be int-representable. HG0 and vg_L are finite but not additionally bounded here. Defers mesh/tag/law compatibility and conversion. No physical inventory/clock mutation; allocation may throw, exclusive authoring access.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parseAquiferLinkLine()

std::string openswmm::twoD::parseAquiferLinkLine ( const std::vector< std::string > & tokens,
std::vector< GwLinkRow > & rows,
std::vector< std::string > & names )

Parse named conduit bed coefficient/path and exchange opt-out authoring row.

One [2D_AQUIFER_LINKS] line (G-X4). link stays a NAME in names until resolveLinkSeepage maps it. Empty return = OK.

Parameters
[in]tokensLINK [KC finite-nonnegative-k] [DC finite-nonnegative-d] [EXCHANGE bool], with KC in project rainfall units and DC project length; omission retains defaults.
[in,out]rowsAppends complete candidate after syntax/value checks.
[in,out]namesAppends exact unresolved link name parallel to rows.
Returns
Empty on success, otherwise empty/keyword/arity/value diagnostic.
Note
Unlike node parser does not require positive DC when KC>0; runtime fallback/path validation is separate. Does not resolve conduit identity/geometry/units or withdraw water. Allocation may leave rows appended before name; exclusive authoring, no physics/calendar advance.

Parse named conduit bed coefficient/path and exchange opt-out authoring row.

  • Argument tokens (in): LINK [KC finite-nonnegative-k] [DC finite-nonnegative-d] [EXCHANGE bool], with KC in project rainfall units and DC project length; omission retains defaults.
  • Argument rows (in,out): Appends complete candidate after syntax/value checks.
  • Argument names (in,out): Appends exact unresolved link name parallel to rows.
    Returns
    Empty on success, otherwise empty/keyword/arity/value diagnostic.
    Note
    Unlike node parser does not require positive DC when KC>0; runtime fallback/path validation is separate. Does not resolve conduit identity/geometry/units or withdraw water. Allocation may leave rows appended before name; exclusive authoring, no physics/calendar advance.
Here is the caller graph for this function:

◆ parseAquiferNodeLine()

std::string openswmm::twoD::parseAquiferNodeLine ( const std::vector< std::string > & tokens,
std::vector< GwNodeBed > & beds,
std::vector< std::string > & names )

Parse one named native-node aquifer bed with explicit cell or deferred location.

One [2D_AQUIFER_NODE] line. node is left as a NAME in names until resolveSubsurface maps it to an index. Empty return = OK.

Parameters
[in]tokensNODE (positive-one-based-CELL|AUTO) [KC k DC d] [AREA a] [EXCHANGE bool]. KC project in/hr or mm/hr; DC project length; AREA project length2. Integers must fit int.
[in,out]bedsAppends complete candidate after syntax/finite/nonnegative checks; positive KC requires positive DC. AUTO records locate=true, explicit CELL stored zero-based.
[in,out]namesAppends exact unresolved node name parallel to beds, not cleared.
Returns
Empty on success, otherwise arity/index/key/value/bed-thickness diagnostic.
Note
Name/cell/ownership resolution is separate. beds append precedes names append, so allocation failure can desynchronize parallel stores; use staged vectors for transactional edits. No physics or clock advance, exclusive authoring access.

Parse one named native-node aquifer bed with explicit cell or deferred location.

  • Argument tokens (in): NODE (positive-one-based-CELL|AUTO) [KC k DC d] [AREA a] [EXCHANGE bool]. KC project in/hr or mm/hr; DC project length; AREA project length2. Integers must fit int.
  • Argument beds (in,out): Appends complete candidate after syntax/finite/nonnegative checks; positive KC requires positive DC. AUTO records locate=true, explicit CELL stored zero-based.
  • Argument names (in,out): Appends exact unresolved node name parallel to beds, not cleared.
    Returns
    Empty on success, otherwise arity/index/key/value/bed-thickness diagnostic.
    Note
    Name/cell/ownership resolution is separate. beds append precedes names append, so allocation failure can desynchronize parallel stores; use staged vectors for transactional edits. No physics or clock advance, exclusive authoring access.
Here is the caller graph for this function:

◆ parseAquiferOptionsLine()

std::string openswmm::twoD::parseAquiferOptionsLine ( const std::vector< std::string > & tokens,
GwOptions & opts )

Apply one aquifer authoring option without initializing a physical column.

One [2D_AQUIFER_OPTIONS] line (KEY VALUE). Empty return = OK.

Parameters
[in]tokensNonempty KEY [VALUE] vector; empty input is outside contract because diagnostic path reads tokens[0]. Success requires at least two; surplus tokens ignored.
[in,out]optsAuthoring defaults/process policies, updated only for recognized valid values.
Returns
Empty on success, otherwise key/value diagnostic.
Note
Parses soil/closure enums, layers2..128, boolean flags, finite C_GW/C_COL(0,1], mode/node eligibility/link-seepage/ET policies and positive project-length wilting suction (AUTO restores implicit150m policy). Integer helper requires int-representable input. No unit conversion/runtime rebuild/physics/clock advance. Allocations can throw, exclusive authoring access required.

Apply one aquifer authoring option without initializing a physical column.

  • Argument tokens (in): Nonempty KEY [VALUE] vector; empty input is outside contract because diagnostic path reads tokens[0]. Success requires at least two; surplus tokens ignored.
  • Argument opts (in,out): Authoring defaults/process policies, updated only for recognized valid values.
    Returns
    Empty on success, otherwise key/value diagnostic.
    Note
    Parses soil/closure enums, layers2..128, boolean flags, finite C_GW/C_COL(0,1], mode/node eligibility/link-seepage/ET policies and positive project-length wilting suction (AUTO restores implicit150m policy). Integer helper requires int-representable input. No unit conversion/runtime rebuild/physics/clock advance. Allocations can throw, exclusive authoring access required.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parseGwBoundaryQualityLine()

std::string openswmm::twoD::parseGwBoundaryQualityLine ( const std::vector< std::string > & tokens,
std::vector< GwBoundaryQualityRow > & rows )

Parse a lateral groundwater boundary native concentration or flux prescription.

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.

Parameters
[in]tokensEmpty or CELL EDGE SPECIES (CONC|TS|MASSFLUX|HEATFLUX) VALUE/NAME. CELL positive one-based becomes zero-based; EDGE nonnegative local zero-based, upper bound deferred. Numeric indices must be int-representable. Surplus tokens ignored.
[in,out]rowsExisting rows retained; appends one complete parsed candidate on success.
Returns
Empty on empty/success, otherwise arity/index/kind diagnostic.
Note
TS always stores name. Other kinds use finite numeric value or treat any nonnumeric token as series name, including nonfinite numeric spellings. Retains prescribed native concentration, mass-flux or W heat-flux conventions without scaling/sign/mesh/species/table validation. Allocation can throw; resolution/physical acceptance are separate, serial authoring only.

Parse a lateral groundwater boundary native concentration or flux prescription.

  • Argument tokens (in): Empty or CELL EDGE SPECIES (CONC|TS|MASSFLUX|HEATFLUX) VALUE/NAME. CELL positive one-based becomes zero-based; EDGE nonnegative local zero-based, upper bound deferred. Numeric indices must be int-representable. Surplus tokens ignored.
  • Argument rows (in,out): Existing rows retained; appends one complete parsed candidate on success.
    Returns
    Empty on empty/success, otherwise arity/index/kind diagnostic.
    Note
    TS always stores name. Other kinds use finite numeric value or treat any nonnumeric token as series name, including nonfinite numeric spellings. Retains prescribed native concentration, mass-flux or W heat-flux conventions without scaling/sign/mesh/species/table validation. Allocation can throw; resolution/physical acceptance are separate, serial authoring only.
Here is the caller graph for this function:

◆ parseGwClosure()

bool openswmm::twoD::parseGwClosure ( const std::string & t,
GwClosure & c )
noexcept

Parse a groundwater token after removing whitespace and folding case.

Parameters
[in]tToken string; all whitespace is removed, including internal spaces. Accepts AUTO, CLOSED_FORM/CLOSEDFORM/CLOSED-FORM/A, ENSLAVED, or SIGMA/COLUMN/B.
[out]cReplaced on a recognized token; unchanged on false.
Returns
True when recognized, false otherwise.
Note
Normalization allocates despite noexcept; an allocation exception terminates the process. No pointer to t is retained. Character classification follows the current C locale.
Here is the caller graph for this function:

◆ parseGwInitialQualityLine()

std::string openswmm::twoD::parseGwInitialQualityLine ( const std::vector< std::string > & tokens,
std::vector< GwInitialQualityRow > & rows,
std::string & file )

Parse a scoped initial native quality row or retain an external file prescription.

One [GW_INITIAL_QUALITY] line: scope, SAT|UNSAT|LAYER <j>, SPECIES, VALUE — or FILE <path>. Empty = OK.

Parameters
[in]tokensEmpty; FILE path; or scope (SAT|UNSAT|LAYER one-based-layer) SPECIES VALUE. VALUE must be finite; native concentration, age authored hours or temperature degC is retained without unit/sign conversion here. Surplus tokens are ignored.
[in,out]rowsAppends complete inline row only after syntax validation; FILE appends none.
[in,out]fileReplaced by FILE path token only for that branch, otherwise retained.
Returns
Empty on empty/success, otherwise grammar/index/numeric diagnostic.
Note
CELL becomes zero-based, LAYER remains one-based; integer input must be int-representable. Does not open file or resolve mesh/species/sign/layout; use resolveGwTransport and runtime owners. Allocation may throw; no physics/clock update, exclusive authoring access.

Parse a scoped initial native quality row or retain an external file prescription.

  • Argument tokens (in): Empty; FILE path; or scope (SAT|UNSAT|LAYER one-based-layer) SPECIES VALUE. VALUE must be finite; native concentration, age authored hours or temperature degC is retained without unit/sign conversion here. Surplus tokens are ignored.
  • Argument rows (in,out): Appends complete inline row only after syntax validation; FILE appends none.
  • Argument file (in,out): Replaced by FILE path token only for that branch, otherwise retained.
    Returns
    Empty on empty/success, otherwise grammar/index/numeric diagnostic.
    Note
    CELL becomes zero-based, LAYER remains one-based; integer input must be int-representable. Does not open file or resolve mesh/species/sign/layout; use resolveGwTransport and runtime owners. Allocation may throw; no physics/clock update, exclusive authoring access.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parseGwParamsLine()

std::string openswmm::twoD::parseGwParamsLine ( const std::vector< std::string > & tokens,
std::vector< GwParamsRow > & rows )

Parse one scoped positional groundwater material/dispersion authoring row.

One [GW_TRANSPORT_PARAMS] line: * | TAG <t> | CELL <n> then the positional matrix properties (see GwParamsRow). Empty = OK.

Parameters
[in]tokensEmpty or (*|TAG name|CELL one-based-index) followed by up to nine optional properties: rho_s kg/m3, c_s J/(kg*K), lambda_s W/(m*K), a_s m2/kg, alpha_L/alpha_T m, D_m/D_v m2/s and geo_flux W/m2 or configured deep temperature degC. '-' retains struct default.
[in,out]rowsExisting rows retained; appends one complete parsed row on success.
Returns
Empty on empty/success, otherwise scope/count/nonfinite/numeric/negative-property error.
Note
Only ninth property may be negative. Converts CELL to zero-based but defers mesh/tag and physical model validation. Integer tokens must be int-representable; numeric helper casts before its integral check. No unit conversion/owner rebuild; allocation may throw, serial authoring only.

Parse one scoped positional groundwater material/dispersion authoring row.

  • Argument tokens (in): Empty or (*|TAG name|CELL one-based-index) followed by up to nine optional properties: rho_s kg/m3, c_s J/(kg*K), lambda_s W/(m*K), a_s m2/kg, alpha_L/alpha_T m, D_m/D_v m2/s and geo_flux W/m2 or configured deep temperature degC. '-' retains struct default.
  • Argument rows (in,out): Existing rows retained; appends one complete parsed row on success.
    Returns
    Empty on empty/success, otherwise scope/count/nonfinite/numeric/negative-property error.
    Note
    Only ninth property may be negative. Converts CELL to zero-based but defers mesh/tag and physical model validation. Integer tokens must be int-representable; numeric helper casts before its integral check. No unit conversion/owner rebuild; allocation may throw, serial authoring only.
Here is the caller graph for this function:

◆ parseGwSorptionLine()

std::string openswmm::twoD::parseGwSorptionLine ( const std::vector< std::string > & tokens,
std::vector< GwSorptionRow > & rows )

Parse scoped species partition coefficient and optional decay authoring data.

One [GW_SORPTION] line: scope, SPECIES, Kd [decay]. Empty = OK.

Parameters
[in]tokensEmpty or scope SPECIES Kd [decay]; Kd finite nonnegative L/kg, decay finite nonnegative 1/day, '-' or omission retains default fallback to pollutant decay. Surplus ignored.
[in,out]rowsAppends one complete row on success, preserves earlier rows on diagnostic failure.
Returns
Empty on success/empty, otherwise scope/arity/numeric/sign diagnostic.
Note
CELL is authored one-based, stored zero-based, int-representable; species/tag/mesh lookup and kinetic conversion are separate resolution. No physical state mutation; allocation may throw.

Parse scoped species partition coefficient and optional decay authoring data.

  • Argument tokens (in): Empty or scope SPECIES Kd [decay]; Kd finite nonnegative L/kg, decay finite nonnegative 1/day, '-' or omission retains default fallback to pollutant decay. Surplus ignored.
  • Argument rows (in,out): Appends one complete row on success, preserves earlier rows on diagnostic failure.
    Returns
    Empty on success/empty, otherwise scope/arity/numeric/sign diagnostic.
    Note
    CELL is authored one-based, stored zero-based, int-representable; species/tag/mesh lookup and kinetic conversion are separate resolution. No physical state mutation; allocation may throw.
Here is the caller graph for this function:

◆ parseGwSourcesLine()

std::string openswmm::twoD::parseGwSourcesLine ( const std::vector< std::string > & tokens,
std::vector< GwSourceRow > & rows )

Parse one named scoped groundwater injection/extraction and native constituent prescription.

One [GW_SOURCES] line: NAME (CELL n | TAG t | XY x y) FLOW v|ts [SPECIES (CONC|MASS) v|ts]…. Empty = OK.

Parameters
[in]tokensEmpty or NAME (*|GLOBAL|CELL n|TAG name|XY x y) FLOW value/series [SCALE factor] followed by repeated SPECIES (CONC|MASS) value/series. Flow m3/s is signed positive injection; SCALE finite nonnegative multiplies total flow and mass rates, not concentration.
[in,out]rowsAppends one complete local candidate only after all syntax checks succeed.
Returns
Empty on empty/success, otherwise location/arity/scale/species-kind diagnostic.
Note
CELL is int-representable one-based converted to zero-based. XY finite coordinates must be in the centroid frame used at resolution. Numeric/series discrimination defers unknown/nonfinite spellings as names; duplicate source/species/table/coverage/native units are resolved later. No physical source activation or clock advance; vector allocation may throw, exclusive authoring access.

Parse one named scoped groundwater injection/extraction and native constituent prescription.

  • Argument tokens (in): Empty or NAME (*|GLOBAL|CELL n|TAG name|XY x y) FLOW value/series [SCALE factor] followed by repeated SPECIES (CONC|MASS) value/series. Flow m3/s is signed positive injection; SCALE finite nonnegative multiplies total flow and mass rates, not concentration.
  • Argument rows (in,out): Appends one complete local candidate only after all syntax checks succeed.
    Returns
    Empty on empty/success, otherwise location/arity/scale/species-kind diagnostic.
    Note
    CELL is int-representable one-based converted to zero-based. XY finite coordinates must be in the centroid frame used at resolution. Numeric/series discrimination defers unknown/nonfinite spellings as names; duplicate source/species/table/coverage/native units are resolved later. No physical source activation or clock advance; vector allocation may throw, exclusive authoring access.
Here is the caller graph for this function:

◆ parseGwTransportOptionsLine()

std::string openswmm::twoD::parseGwTransportOptionsLine ( const std::vector< std::string > & tokens,
GwTransportOptions & o )

Apply one groundwater transport/thermal authoring option without resolving physical owners.

One [GW_TRANSPORT_OPTIONS] line (KEY VALUE [ARG…]). Empty = OK.

Parameters
[in]tokensTokenized KEY VALUE [ARG...] row; empty is accepted. Most keys ignore surplus tokens; UNSAT_TRANSPORT alone requires exactly two.
[in,out]oMutable authoring options (opts in declaration), including thermal_authored tags.
Returns
Empty on recognized valid row/empty input, otherwise grammar/key/value diagnostic.
Note
Supports transport/conduction/dispersion YES|NO flags, BULK|LAYERED, WATER_ONLY| POROUS_EQUILIBRIUM, thermal layers integer1..128, positive max step s/conductivity W/(m*K)/surface resistance m2*K/W, mixing rules, surface/deep temperature degC or heat flux W/m2/series and optional nonnegative depth m; C_DIFF is finite(0,1]. Stores values/names without scaling or table lookup. Some multi-token thermal branches set fields before validating later values, so diagnostic failure can leave partial options. Allocation can throw. No runtime owner rebuild/physics/clock update; exclusive authoring access required; use a candidate for transactional edits.

Apply one groundwater transport/thermal authoring option without resolving physical owners.

  • Argument tokens (in): Tokenized KEY VALUE [ARG...] row; empty is accepted. Most keys ignore surplus tokens; UNSAT_TRANSPORT alone requires exactly two.
  • Argument opts (in,out): Mutable authoring options (o in the definition), including thermal_authored tags.
    Returns
    Empty on recognized valid row/empty input, otherwise grammar/key/value diagnostic.
    Note
    Supports transport/conduction/dispersion YES|NO flags, BULK|LAYERED, WATER_ONLY| POROUS_EQUILIBRIUM, thermal layers integer1..128, positive max step s/conductivity W/(m*K)/surface resistance m2*K/W, mixing rules, surface/deep temperature degC or heat flux W/m2/series and optional nonnegative depth m; C_DIFF is finite(0,1]. Stores values/names without scaling or table lookup. Some multi-token thermal branches set fields before validating later values, so diagnostic failure can leave partial options. Allocation can throw. No runtime owner rebuild/physics/clock update; exclusive authoring access required; use a candidate for transactional edits.
Here is the caller graph for this function:

◆ parseGwZone()

bool openswmm::twoD::parseGwZone ( const std::string & token,
GwZone & z )
noexcept

Parse one aquifer zone token without changing state on failure.

Parse case-insensitive SAT, UNSAT or LAYER keyword.

  • Argument token (in): Borrowed case-insensitive complete token SAT, UNSAT or LAYER; not whitespace-trimmed here.
  • Argument z (out): Assigned only on success; unchanged for invalid text.
    Returns
    True for a recognized token, otherwise false. No input retention or allocation.
    Parameters
    [in]tokenEntire zone keyword.
    [out]zReplaced on recognized keyword, retained on failure.
    Returns
    True when recognized; no allocation, model mutation or layer-index parsing.
Here is the caller graph for this function:

◆ parseInfil2DDest()

bool openswmm::twoD::parseInfil2DDest ( const std::string & token,
Infil2DDest & dest )

Parse a destination token.

Returns
false if unrecognised.
Parameters
[in]tokenBorrowed complete case-insensitive LOST, SUBCATCH_AQUIFER or AQUIFER_2D token.
[out]destAssigned only on success; unchanged for unknown text.
Note
Parsing accepts obsolete AQUIFER_2D for migration/roundtrip; it does not establish runtime support. No allocation or retained input.

◆ parseInfil2DMethod()

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.

Returns
False if the token is unrecognised. NONE returns true with has_method set false.
Parameters
[in]tokenBorrowed complete case-insensitive method token; no whitespace trimming.
[out]methodAssigned recognized enum, or HORTON for NONE; unchanged on an unknown token.
[out]has_methodTrue for a recognized physical method, false for NONE or unrecognized text.
Note
No input retention, allocation or engine-state mutation. Caller checks the boolean result before using method.

◆ parseReport2DVars()

std::string openswmm::twoD::parseReport2DVars ( const std::string & text,
unsigned & mask )

Parse report-group keyword list/preset through the shared mask grammar.

Parameters
[in]textWhole whitespace/comma-separated group list or DEFAULT|MINIMAL|ALL preset.
[out]maskParsed bitmask on success; delegated parseMask failure contract applies.
Returns
Empty on success, otherwise unknown-token diagnostic; no model/options mutation.
Note
Delegates canonical parser, may allocate; caller explicitly adopts successful mask.
  • Argument text (in): Whole whitespace/comma-separated group list or DEFAULT|MINIMAL|ALL preset.
  • Argument mask (out): Parsed bitmask on success; delegated parseMask failure contract applies.
    Returns
    Empty on success, otherwise unknown-token diagnostic; no model/options mutation.
    Note
    Delegates canonical parser, may allocate; caller explicitly adopts successful mask.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parseSoilChar()

bool openswmm::twoD::parseSoilChar ( const std::string & t,
SoilChar & s )
noexcept

Parse a groundwater token after removing whitespace and folding case.

Parameters
[in]tToken string; all whitespace is removed, including internal spaces. Accepts RUSSO, GARDNER, BROOKS_COREY/BROOKSCOREY/BROOKS-COREY/BC, or VAN_GENUCHTEN/VANGENUCHTEN/VAN-GENUCHTEN/VG.
[out]sReplaced on a recognized token; unchanged on false.
Returns
True when recognized, false otherwise.
Note
Normalization allocates despite noexcept; an allocation exception terminates the process. No pointer to t is retained. Character classification follows the current C locale.
Here is the caller graph for this function:

◆ parseSqScope()

std::string openswmm::twoD::parseSqScope ( const std::vector< std::string > & tokens,
std::size_t & at,
SqScopeKey & key,
const char * section )

Parse a scoped surface-quality row prefix and expose its first payload token.

Parameters
[in]tokensTokenized row, always parsed from tokens[0], independent of initial at.
[out]atSet to the first payload index (1 for *, 2 for TAG/CELL) only on successful scope parse.
[in,out]keyReceives parsed scope plus tag or zero-based cell; unrelated fields retain old values. Failure generally preserves it; no mesh/name resolution occurs.
[in]sectionNonnull terminated section label included in errors.
Returns
Empty on success; diagnostic on empty/unknown/missing/invalid scope. CELL must parse as a positive integral double; representability as int is a caller/input precondition because this parser does not check the conversion range. Allocation can throw; no authoring row is appended.
Here is the caller graph for this function:

◆ parseSurfaceOwnerLine()

std::string openswmm::twoD::parseSurfaceOwnerLine ( const std::vector< std::string > & t,
std::vector< SurfaceOwnerRecord > & rows )

Retain one reviewed uniform subcatchment surface-ownership authoring record.

Parameters
[in]tExactly Subcatchment SUBCATCH UNIFORM, keywords byte case-insensitive.
[in,out]rowsAppends exact subcatchment name only when no case-insensitive duplicate exists.
Returns
Empty on success; unsupported representation/distribution/arity or duplicate diagnostic.
Note
Does not resolve name, geometry, physical ownership or runtime adapter qualification. Allocation may throw; no water/native/clock update, exclusive authoring access.
  • Argument t: Exactly Subcatchment SUBCATCH UNIFORM, keywords byte case-insensitive.
  • Argument rows: Appends exact subcatchment name only when no case-insensitive duplicate exists.
    Returns
    Empty on success; unsupported representation/distribution/arity or duplicate diagnostic.
    Note
    Does not resolve name, geometry, physical ownership or runtime adapter qualification. Allocation may throw; no water/native/clock update, exclusive authoring access.
Here is the caller graph for this function:

◆ prepareMeshHeat()

void openswmm::twoD::prepareMeshHeat ( SimulationContext & ctx,
SurfaceStateData & state,
double dt )

Prepare inherited exchange flags, weather and fresh per-cell thermal interval accounting.

Parameters
[in,out]ctxLive engine context; may update solar forcing when radiation is active.
[in,out]statePrepared surface owner; resets ground_column_seconds, refreshes inherited surface/radiative flags, ground_now and standalone ground boundary cache as applicable.
[in]dtRouter interval s forwarded to solar forcing; caller supplies a finite valid duration.
Note
Disabled heat returns. Does not advance physical energy or clear cumulative J receipts. Standalone prepare() may throw on invalid thermal forcing after earlier cache changes; requires serial access to shared forcing and all prepared heat arrays.
Here is the call graph for this function:

◆ prescan2DUnitsHeader()

void openswmm::twoD::prescan2DUnitsHeader ( const std::string & inp_path,
SolverOptions2D & opts )

Scan an entire UTF-8 input/mesh file for a recognized SI mesh-units comment marker.

Scan inp_path for a ;; UNITS: <value> comment header and set opts.mesh_units_si to true when the value names metres.

Parameters
[in]inp_pathUTF-8 file path, relative paths use process working directory.
[in,out]optsSets mesh_units_si=true on case-insensitive ';; UNITS: SI (m)' or metric synonym; no recognized marker, unknown units or ft leaves current flag unchanged. Never resets false.
Note
Missing/unreadable file silently returns so caller can report normal read errors. Scans to EOF because writer can emit marker inside sections, trims whitespace by borrowed views; does not parse topology or convert coordinates. File/string allocation can throw; exclusive options edit. Multiple markers only enable SI, so later unknown/nonmetric text does not undo an earlier match.

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.

Scan an entire UTF-8 input/mesh file for a recognized SI mesh-units comment marker.

  • Argument inp_path (in): UTF-8 file path, relative paths use process working directory.
  • Argument opts (in,out): Sets mesh_units_si=true on case-insensitive ';; UNITS: SI (m)' or metric synonym; no recognized marker, unknown units or ft leaves current flag unchanged. Never resets false.
    Note
    Missing/unreadable file silently returns so caller can report normal read errors. Scans to EOF because writer can emit marker inside sections, trims whitespace by borrowed views; does not parse topology or convert coordinates. File/string allocation can throw; exclusive options edit. Multiple markers only enable SI, so later unknown/nonmetric text does not undo an earlier match.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ projectGroundMoisture()

std::string openswmm::twoD::projectGroundMoisture ( const SubsurfaceState & s,
int i,
double hg,
const std::vector< double > & edges,
std::vector< double > & output,
std::vector< double > * saturated_water )

Project accepted hydraulic moisture into a fixed physical thermal depth grid.

Parameters
[in]sStable prepared subsurface owner with per-cell arrays sized through n_cells and, for SIGMA, theta_sigma sized m_layers*n_cells in layer-major order.
[in]iCell index in [0,s.n_cells).
[in]hgAccepted saturated thickness m, finite within [0,s.zs[i]].
[in]edgesFinite increasing fixed depths m, from zero to aquifer depth within 1e-12 relative tolerance, with at least two entries. Cell area and depth must be positive.
[out]outputOn success, replaced by one volumetric water fraction per fixed layer; unchanged on refusal. Fractions outside phase bounds by at most 1e-12 are clipped for roundoff.
[out]saturated_waterOptional distinct output for saturated pore-water volume m3 per fixed layer; untouched on failure. It must not alias output if both results are needed.
Returns
Empty on success; diagnostic for invalid target/grid, missing SIGMA layers or moisture outside finite physical bounds. Allocation failures propagate without output publication.
Note
Bulk closures distribute unsaturated water uniformly; SIGMA integrates overlaps of its accepted stretching layers. No hydraulic or heat inventory is changed.
Declaration arguments
  • unnamed subsurface owner (in): Stable prepared subsurface owner with per-cell arrays sized through n_cells and, for SIGMA, theta_sigma sized m_layers*n_cells in layer-major order.
  • cell (in): Cell index in [0,s.n_cells).
  • saturated_thickness (in): Accepted saturated thickness m, finite within [0,s.zs[i]].
  • fixed_depth_edges (in): Finite increasing fixed depths m, from zero to aquifer depth within 1e-12 relative tolerance, with at least two entries. Cell area and depth must be positive.
  • theta (out): On success, replaced by one volumetric water fraction per fixed layer; unchanged on refusal. Fractions outside phase bounds by at most 1e-12 are clipped for roundoff.
  • sat_water (out): Optional distinct output for saturated pore-water volume m3 per fixed layer; untouched on failure. It must not alias output if both results are needed.
Returns
Empty on success; diagnostic for invalid target/grid, missing SIGMA layers or moisture outside finite physical bounds. Allocation failures propagate without output publication.
Note
Bulk closures distribute unsaturated water uniformly; SIGMA integrates overlaps of its accepted stretching layers. No hydraulic or heat inventory is changed.
Here is the caller graph for this function:

◆ projectGroundWaterIncrement()

std::string openswmm::twoD::projectGroundWaterIncrement ( const PorousHeatColumn & column,
double length,
double delta_length,
const std::vector< double > & old_water,
const std::vector< double > & delta_water,
std::vector< double > & output )

Project a moving hydraulic-layer water tangent onto the fixed thermal grid.

Parameters
[in]columnPrepared column with positive finite area m2, finite porosity in [0,1), and strictly increasing fixed depth edges starting at zero.
[in]lengthCurrent unsaturated length m, finite positive and no greater than grid depth.
[in]delta_lengthIntegrated change of unsaturated length m, finite and signed.
[in]old_waterNonempty accepted water depths m per equal stretching hydraulic layer; derived water fraction may exceed [0,porosity] only by the 1e-12 roundoff tolerance.
[in]delta_waterFinite water-depth tangent m per hydraulic layer; old_water.size() entries.
[out]outputReplaced on success with integrated water changes m3 per fixed layer. Remains unchanged on validation refusal or allocation failure.
Returns
Empty on success; diagnostic for invalid geometry, hydraulic moisture or overflow.
Note
Includes moving-interface jump terms. At an aligned fixed-grid boundary, the receiving layer is chosen from movement direction; no heat inventory or input column is changed.
Declaration arguments
  • unnamed column (in): Prepared column with positive finite area m2, finite porosity in [0,1), and strictly increasing fixed depth edges starting at zero.
  • unsaturated_length (in): Current unsaturated length m, finite positive and no greater than grid depth.
  • length_change (in): Integrated change of unsaturated length m, finite and signed.
  • old_water_depth (in): Nonempty accepted water depths m per equal stretching hydraulic layer; derived water fraction may exceed [0,porosity] only by the 1e-12 roundoff tolerance.
  • water_depth_change (in): Finite water-depth tangent m per hydraulic layer; old_water.size() entries.
  • fixed_water_change (out): Replaced on success with integrated water changes m3 per fixed layer. Remains unchanged on validation refusal or allocation failure.
Returns
Empty on success; diagnostic for invalid geometry, hydraulic moisture or overflow.
Note
Includes moving-interface jump terms. At an aligned fixed-grid boundary, the receiving layer is chosen from movement direction; no heat inventory or input column is changed.

◆ publishLidNodeThermalEnergy()

std::string openswmm::twoD::publishLidNodeThermalEnergy ( LidNodeState & state,
const LidNodeThermalGraph & graph,
const std::vector< double > & energy )

Replace persisted physical-cell energy with a successful compact graph solution.

Publish a compact thermal solve into its borrowed LID owner's physical energy layout.

Parameters
[in,out]stateLID owner whose cell count determines the output shape; only thermal_energy is replaced, with omitted zero-capacity physical cells receiving zero J.
[in]graphPrepared compact graph mapping strictly increasing unique physical cell indices to stores; store/cell counts must match energy.
[in]energyFinite signed J per compact thermal store. Temperature below zero degC may yield negative sensible energy; values are not required nonnegative.
Returns
Empty after swapping the staged physical energy, otherwise shape/index/order/finite error.
Note
Refusal preserves owner energy. Allocates a physical-cell vector and can throw; does not publish water, capacity, ground-contact receipts or recompute hydraulic state.
  • energy: Finite signed J per compact store, in exact graph order.
    Returns
    Empty after replacing owner thermal_energy, otherwise diagnostic with owner unchanged. Omitted physical cells receive zero energy. Allocates; no water or contact receipts are changed.

◆ quadDEtaDMeanDepth()

OPENSWMM_KERNEL_FN double openswmm::twoD::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).

Parameters
[in]zsRequired borrowed array of six finite elevations in m: two individually sorted subtriangle triples.
[in]A1First nonnegative planimetric subtriangle area, m2.
[in]A2Second nonnegative planimetric subtriangle area, m2; A1 + A2 > 0.
Precondition
Geometry comes from quadVfrPrecompute(); no pointer/area validation occurs.
Parameters
[in]etaFinite free-surface elevation in the same metre datum as zs.
[in]epsDimensionless regularization fraction in [0,1); nonpositive selects the exact relation.
Returns
Dimensionless inverse slope, with floor max(eps,1e-12) on the denominator.
Note
Read-only host/device calculation; caller retains all storage.
Here is the call graph for this function:

◆ quadEtaFromMeanDepth()

OPENSWMM_KERNEL_FN double openswmm::twoD::quadEtaFromMeanDepth ( const double * zs,
double A1,
double A2,
double mean_depth,
double 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).

Parameters
[in]zsRequired borrowed array of six finite elevations in m: two individually sorted subtriangle triples.
[in]A1First nonnegative planimetric subtriangle area, m2.
[in]A2Second nonnegative planimetric subtriangle area, m2; A1 + A2 > 0.
Precondition
Geometry comes from quadVfrPrecompute(); no pointer/area validation occurs.
Parameters
[in]mean_depthFinite cell-mean depth V/(A1+A2), m; nonpositive selects the lower dry stage.
[in]epsDimensionless regularization fraction in [0,1); nonpositive selects the exact relation.
Returns
Free-surface elevation in m. The partially wet inverse takes at most 80 safeguarded Newton iterations and returns its final iterate without a convergence code.
Note
Read-only host/device calculation; caller retains all storage.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ quadMeanDepthFromEta()

OPENSWMM_KERNEL_FN double openswmm::twoD::quadMeanDepthFromEta ( const double * zs,
double A1,
double A2,
double eta,
double eps )
noexcept

Regularised cell-mean depth h̄(η) of the quad — the area-weighted sum of the two sub-triangle closures (exact for eps == 0).

Parameters
[in]zsRequired borrowed array of six finite elevations in m: two individually sorted subtriangle triples.
[in]A1First nonnegative planimetric subtriangle area, m2.
[in]A2Second nonnegative planimetric subtriangle area, m2; A1 + A2 > 0.
Precondition
Geometry comes from quadVfrPrecompute(); no pointer/area validation occurs.
Parameters
[in]etaFinite free-surface elevation in the same metre datum as zs.
[in]epsDimensionless regularization fraction in [0,1); nonpositive selects the exact relation.
Returns
Area-weighted regularized nonnegative mean depth in m.
Note
Read-only host/device calculation; caller retains all storage.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ quadMeanDepthSlope()

OPENSWMM_KERNEL_FN double openswmm::twoD::quadMeanDepthSlope ( const double * zs,
double A1,
double A2,
double eta,
double eps )
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.

Parameters
[in]zsRequired borrowed array of six finite elevations in m: two individually sorted subtriangle triples.
[in]A1First nonnegative planimetric subtriangle area, m2.
[in]A2Second nonnegative planimetric subtriangle area, m2; A1 + A2 > 0.
Precondition
Geometry comes from quadVfrPrecompute(); no pointer/area validation occurs.
Parameters
[in]etaFinite free-surface elevation in the same metre datum as zs.
[in]epsDimensionless regularization fraction in [0,1); nonpositive selects the exact relation.
Returns
Dimensionless derivative of the regularized mean-depth sum; clamped dry tails contribute zero.
Note
Read-only host/device calculation; caller retains all storage.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ quadVfrPrecompute()

int openswmm::twoD::quadVfrPrecompute ( const double * x,
const double * y,
const double * z,
double * zs,
double & A1,
double & A2 )
inlinenoexcept

Choose the B&S 2007 diagonal for a quad and emit its precomputed VFR data.

Parameters
[in]x,y,zthe four vertices in CYCLIC order (either orientation)
[out]zsout: six elevations — sorted triple of sub-triangle 1, then sorted triple of sub-triangle 2
[out]A1,A2out: planimetric areas of the two sub-triangles
Returns
the case number (1, 2 or 3) — for tests / diagnostics
Precondition
x, y and z each point to four finite cyclic vertices in a consistent metre coordinate frame; zs has six writable doubles. Arrays must not overlap.
Quad geometry has positive total planimetric area, validated upstream.
Postcondition
A1 and A2 contain nonnegative areas in m2; degenerate subtriangles receive zero. No allocation or retained input storage.
Here is the call graph for this function:

◆ quadWetFraction()

OPENSWMM_KERNEL_FN double openswmm::twoD::quadWetFraction ( const double * zs,
double A1,
double A2,
double eta )
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).

Parameters
[in]zsRequired borrowed array of six finite elevations in m: two individually sorted subtriangle triples.
[in]A1First nonnegative planimetric subtriangle area, m2.
[in]A2Second nonnegative planimetric subtriangle area, m2; A1 + A2 > 0.
Precondition
Geometry comes from quadVfrPrecompute(); no pointer/area validation occurs.
Parameters
[in]etaFinite free-surface elevation in the same metre datum as zs.
Returns
Area-weighted wetted fraction, dimensionless [0,1].
Note
Read-only host/device calculation; caller retains all storage.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ recomputeAllZDependents()

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).

Parameters
[in,out]meshThe mesh; mesh.vz is assumed to already hold the new Zs.
Precondition
Mesh topology/derived arrays are already built and sized; updated elevations use the mesh's current length units.
Postcondition
Changes bed centroids, edge-midpoint beds and quad VFR elevations/areas. Does not rewrite hydraulic head/depth, XY geometry, or reconstruction stencils.
Note
Requires exclusive mesh access. Lazy quad side-data allocation may throw; no validation or transactional rollback is provided.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ recomputeVertexZDependents()

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.

Parameters
[in,out]meshThe mesh; mesh.vz[vidx] is assumed to already hold the new Z.
[in]vidxIndex of the vertex whose Z just changed.
Precondition
Mesh topology/derived arrays are already built and sized; updated elevations use the mesh's current length units.
Postcondition
Changes bed centroids, edge-midpoint beds and quad VFR elevations/areas. Does not rewrite hydraulic head/depth, XY geometry, or reconstruction stencils.
Note
Requires exclusive mesh access. Lazy quad side-data allocation may throw; no validation or transactional rollback is provided.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reconstructVertexHeads()

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().

Parameters
[in]meshThe mesh (with stencils built).
[in,out]stateSurface state (reads head[], writes vert_head[]).
[in]nthreadsOpenMP thread count for the per-vertex loop (1 = serial).
Precondition
Head array has at least cell_count entries and vert_head is already sized to vertex_count. CSR indices/offsets are valid; no extents are checked.
Postcondition
Writes only reconstructed vertex heads, in the same length units as cell heads; isolated vertices become zero. No resizing or allocation.
Note
Positive nthreads controls OpenMP; 1 is serial, ignored without OpenMP. Each vertex uses a fixed-order gather; input mesh/head arrays must remain stable and outputs must not be concurrently accessed.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reconstructVertexRenderDepths() [1/2]

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.

Parameters
[in]meshThe mesh (with stencil topology built; uses stencil cell lists only, not the pseudo-Laplacian weights).
[in,out]stateSurface state (reads depth[], writes vert_depth_signed[]).
[in]dry_depthWet/dry threshold (m) — cells below it are excluded.
[in]nthreadsOpenMP thread count for the per-vertex loop (1 = serial).
[in,out]eta_scratchCaller-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).
Precondition
CSR cell incidence and vertex/cell arrays are valid; state.vert_depth_signed is preallocated to vertex_count. dry_depth is finite nonnegative and nthreads positive.
Postcondition
Resizes eta_scratch to cell_count; only qualifying wet cells' scratch values are meaningful. Produces positive render depths or zero no-data, without changing solver head/depth.
Note
OpenMP gathers use fixed per-vertex order. Requires stable inputs and exclusive output/scratch access; resizing may allocate/throw. References are borrowed only during the call.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reconstructVertexRenderDepths() [2/2]

void openswmm::twoD::reconstructVertexRenderDepths ( const MeshData & mesh,
SurfaceStateData & state,
double dry_depth,
int nthreads = 1 )
inline

Convenience overload for callers with no persistent scratch (tests, one-shot seeding): allocates the per-cell buffer for the duration of the call.

Parameters
[in]meshBorrowed valid built mesh and CSR incidence.
[in,out]stateReads cell depths and writes preallocated vertex render depths, m.
[in]dry_depthFinite nonnegative wet/dry threshold, m.
[in]nthreadsPositive OpenMP worker count, 1 for serial; ignored without OpenMP.
Note
Allocates a private cell_count-double temporary buffer, then delegates to the persistent-scratch overload. Output/scratch lifetime does not escape the call; allocation may throw.
Here is the call graph for this function:

◆ register2DSections()

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::PendingInitialBedQualityRow > & pending_ibq_rows,
std::vector< SurfaceRouter2D::PendingBoundaryQualityRow > & pending_bq_rows,
input::SectionRegistry & registry )

Register mesh/options/native-quality/boundary/infiltration authoring section handlers.

Register all 2D input section handlers with the section registry.

Parameters
[in,out]meshStable borrowed mesh target, must outlive callbacks.
[in,out]optionsStable borrowed authoring options, must outlive callbacks.
[in,out]pending_bc_rowsBorrowed retained hydraulic boundary rows, appended by handlers.
[in,out]pending_ec_rowsBorrowed retained undirected edge conveyance rows.
[in,out]pending_iq_rowsBorrowed retained surface initial native quality rows.
[in,out]pending_ibq_rowsBorrowed retained local-bed initial native quality rows.
[in,out]pending_bq_rowsBorrowed retained boundary native quality rows.
[in,out]registryReceives custom handlers; conflict/replacement policy delegated to registry.
Note
Captured references remain externally owned. Infiltration target is taken from callback context twod_io.infil (null skips). Mesh-file handler takes first FILE row only and preserves raw unquoted path spacing. Row handlers tokenize/skip blanks, stop on first diagnostic with context code5/raw line, retaining earlier rows; options receive warning sink for retired-key compatibility. No automatic reset/rollback/model activation/clock advance. Allocation can leave registration partial; callbacks/parsers may throw. Requires serial registry/model lifecycle.

Call during input reader setup (conditional on OPENSWMM_HAS_2D). The handlers will populate the mesh and options data in SimulationContext.

  • Argument mesh: Mesh data to populate.
  • Argument options: Solver options to populate.
  • Argument registry: Section registry to register handlers into.

Register mesh/options/native-quality/boundary/infiltration authoring section handlers.

  • Additional argument mesh: Stable borrowed mesh target, must outlive callbacks.
  • Additional argument options: Stable borrowed authoring options, must outlive callbacks.
  • Argument pending_bc_rows (in,out): Borrowed retained hydraulic boundary rows, appended by handlers.
  • Argument pending_ec_rows (in,out): Borrowed retained undirected edge conveyance rows.
  • Argument pending_iq_rows (in,out): Borrowed retained surface initial native quality rows.
  • Argument pending_ibq_rows (in,out): Borrowed retained local-bed initial native quality rows.
  • Argument pending_bq_rows (in,out): Borrowed retained boundary native quality rows.
  • Additional argument registry: Receives custom handlers; conflict/replacement policy delegated to registry.
    Note
    Captured references remain externally owned. Infiltration target is taken from callback context twod_io.infil (null skips). Mesh-file handler takes first FILE row only and preserves raw unquoted path spacing. Row handlers tokenize/skip blanks, stop on first diagnostic with context code5/raw line, retaining earlier rows; options receive warning sink for retired-key compatibility. No automatic reset/rollback/model activation/clock advance. Allocation can leave registration partial; callbacks/parsers may throw. Requires serial registry/model lifecycle.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ registerGwTransportSections()

void openswmm::twoD::registerGwTransportSections ( GwTransportData & gw,
input::SectionRegistry & registry )

Register GW authoring callbacks that append into the borrowed model data.

Register every [GW_*] handler against registry, writing into gw.

Parameters
[in,out]gwStable model owner captured by reference, must outlive registry callback use.
[in,out]registryReceives handlers for transport options/params/sorption/initial/boundary quality and sources. Existing registry conflict behavior is delegated.
Note
Each handler marks authored, tokenizes nonblank lines, stops on first returned error with ctx.error_code=5 and raw-line diagnostic; prior accepted rows remain. Initial/source edits invalidate derived indexes. Captures no physical runtime owner; no reset/rollback/physics. Allocation/callback exceptions propagate and registration may be partial. Serial registry/model authoring required.

Register GW authoring callbacks that append into the borrowed model data.

  • Argument gw (in,out): Stable model owner captured by reference, must outlive registry callback use.
  • Argument registry (in,out): Receives handlers for transport options/params/sorption/initial/boundary quality and sources. Existing registry conflict behavior is delegated.
    Note
    Each handler marks authored, tokenizes nonblank lines, stops on first returned error with ctx.error_code=5 and raw-line diagnostic; prior accepted rows remain. Initial/source edits invalidate derived indexes. Captures no physical runtime owner; no reset/rollback/physics. Allocation/callback exceptions propagate and registration may be partial. Serial registry/model authoring required.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ registerSubsurfaceSections()

void openswmm::twoD::registerSubsurfaceSections ( SubsurfaceConfig & cfg,
std::vector< std::string > & node_names,
std::vector< std::string > & link_names,
input::SectionRegistry & registry )

Register aquifer option/cell/node/link/boundary and surface-ownership authoring callbacks.

Parameters
[in,out]cfgBorrowed target configuration; must remain stable/alive through callback use.
[in,out]node_namesBorrowed parallel native-node name store.
[in,out]link_namesBorrowed parallel conduit name store.
[in,out]registryReceives six custom section handlers, conflict policy delegated.
Note
Aquifer wrappers mark options.authored, tokenize nonblank lines, stop at first diagnostic with code5/raw line while preserving prior rows. Surface-ownership wrapper omits authored marker and raw-line suffix. No reset/rollback/runtime ownership activation. Allocation/row exceptions can propagate and registration may be partial; serial authoring lifecycle required.
  • Argument cfg (in,out): Borrowed target configuration; must remain stable/alive through callback use.
  • Argument node_names (in,out): Borrowed parallel native-node name store.
  • Argument link_names (in,out): Borrowed parallel conduit name store.
  • Argument registry (in,out): Receives six custom section handlers, conflict policy delegated.
    Note
    Aquifer wrappers mark options.authored, tokenize nonblank lines, stop at first diagnostic with code5/raw line while preserving prior rows. Surface-ownership wrapper omits authored marker and raw-line suffix. No reset/rollback/runtime ownership activation. Allocation/row exceptions can propagate and registration may be partial; serial authoring lifecycle required.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ registerSurfaceQualitySections()

void openswmm::twoD::registerSurfaceQualitySections ( SurfaceQuality2D & sq,
input::SectionRegistry & registry )

Register [2D_COVERAGES], [2D_LOADINGS], [2D_CURB_LENGTH] writing into sq.

Parameters
[in,out]sqAuthoring owner captured by reference in registered callbacks. Must outlive registry callback use; prior rows are retained and new lines append/replace through parsers.
[in,out]registryInstalls custom handlers for the three 2D surface-quality sections.
Note
Handlers skip empty tokens and stop on the first parse error, set context error_code=5 and error_message with the original line. Earlier lines/sections remain applied. Tokenization/string allocation exceptions are not caught here; registration/use require serialized authoring access.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ report2DVarTokens()

const std::vector< std::string > & openswmm::twoD::report2DVarTokens ( )

Borrow canonical report-group keyword tokens in defined bit order.

Token ↔ bitmask helpers for [2D_OPTIONS] REPORT_2D_VARIABLES.

Returns
Process-owned const vector from report2d::tokens; caller must not mutate. No model effect; first construction may allocate, later reads require no owner synchronization.

report2DVarTokens() lists the group tokens in bit order (DEPTH, VELOCITY, EDGE_FLUX, NODE_HEAD, SPECIES, RAINFALL, INFILTRATION, COUPLING, GRADIENTS, CONTINUITY, ENVELOPES, BUILDUP (S7), GROUNDWATER, GW_DETAILED, HEAT (G-O)). 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.

Borrow canonical report-group keyword tokens in defined bit order.

Returns
Process-owned const vector from report2d::tokens; caller must not mutate. No model effect; first construction may allocate, later reads require no owner synchronization.
Here is the call graph for this function:

◆ resolveExchangeStructure()

void openswmm::twoD::resolveExchangeStructure ( CouplingPoint & cp,
const MeshData & mesh,
const SimulationContext & ctx,
const SolverOptions2D & opts,
int row,
NodeCoupling2DType type,
double project_len_to_m )

Resolve a junction point's exchange law, structure and coefficients from its node's [2D_NODE_COUPLING] row, the class preset and the global options (plans/1D2D_FINE_SCALE_COUPLING_PLAN §3.1, §3.4–3.5).

Parameters
[in,out]cpResolved valid non-outfall coupling point, with native node index and either vertex or cell location; map-authored area already m2 and cd dimensionless. Receives SI geometry, coefficients, chamber footprint and equalization policy.
[in]meshPrepared SI vertex elevations/cell centroid beds matching point location.
[in]ctxMatching node rim/surface geometry, optional node coupling parameter row and lookup tables. OPEN geometry lookup may update mutable table cursor through its native helper.
[in]optsPrepared law/preset/equalization defaults and positive native-ft-to-SI conversion.
Note
Chooses node overrides then option presets, applies map-authored CD/area precedence and open-pond/grate/curb geometry rules, scales authored lengths/areas, and resolves crest relative to node rim/mesh bed. ORIFICE returns after law/equalization/chamber selection. No hydraulic water, native inventory or engine clock advance; no general finite/index validation, so authored params and all prepared point/row extents must already qualify. Updates cp progressively; delegated table geometry may throw. Requires exclusive point/table-cache setup access.

Precedence: map-row CD/AREA (when authored) > node row > preset > [2D_OPTIONS]. An authored map-row CD sets both orifice coefficients; an authored map-row AREA sets the orifice area. MANHOLE: L = πD, A = πD²/4 (D default 1.2 m, 4 ft in US units); GRATE / CURB: AREA (else the map-row area, else the manhole area) and PERIMETER (else 4√A); OPEN: AREA (else the storage area at full depth) and PERIMETER (else √(4πA)). LID_OPEN_FRACTION scales L and A. Coefficients come from COEFFS (node, else COUPLING_COEFFS): DEFAULT 0.540 / ⅔·C_w / 0.167 / 0.160, RUBINATO2017 0.540 / 0.056 / 0.167 / 0.160, _LOWER 0.493 / 0.055 / 0.160 / 0.159, _UPPER 0.587 / 0.057 / 0.174 / 0.161; an OPEN node without COEFFS uses 1.0 throughout; CW / CSW / COI / COO override. The crest follows CREST: the node rim (invert + full depth), the coupling bed (vertex z or cell centroid z), or their MAX / MIN.

Parameters
rowThe node's row in ctx.node_coupling_2d, or -1.
typeThe node's effective coupling type.
project_len_to_mProject length unit → metres (authored values).
Here is the call graph for this function:
Here is the caller graph for this function:

◆ resolveGwBoundaries()

std::vector< GwResolvedBoundary > openswmm::twoD::resolveGwBoundaries ( SimulationContext & ctx,
const MeshData & mesh,
const SubsurfaceConfig & config,
const GwTransportData & quality,
const SubsurfaceState & state,
const SubsurfaceTransportState & tr,
const std::vector< uint8_t > & coverage,
double heat_capacity )

Resolve authored exterior hydraulic edges and explicit groundwater quality prescriptions.

Resolve unique active exterior hydraulic edges and their explicit transport composition.

Parameters
[in,out]ctxSimulation context supplying units, model signals and reaction metadata. Signal resolution may open/read file-backed tables; keep the context and tables exclusively available during resolution.
[in]meshPrepared SI mesh with valid cell vertex counts, neighbors, edge lengths and centroid distances. Arrays must span every configured state cell and its padded edge slots.
[in]configAuthored boundary rows. Hydraulic edges require mesh mode, unique exterior (cell,edge) pairs and active aquifer coverage. Head constants/series are project lengths; flow prescriptions are already total SI m3/s.
[in]qualityBoundary species rows matched to hydraulic edges. Species must be enabled; inflow-capable boundaries require explicit concentrations for every transport row.
[in]statePrepared subsurface cell extent.
[in]trPrepared transport identity and species/age/temperature rows.
[in]coverageActive-aquifer mask with at least state.n_cells entries; unchecked extent.
[in]heat_capacityFinite positive volumetric water heat capacity J/(m3 K), required when HEATFLUX terms are present; used with edge length to convert W/m into temperature-volume rate.
Returns
Owned resolved edge vector, with SI hydraulic geometry/signals, shared immutable time series, converted loading scales and zero cumulative receipt arrays per species.
Exceptions
std::runtime_errorOn invalid boundary topology, geometry, coverage, signal/species, duplicate term, missing composition, negative concentration/age, or unresolved native loading units.
Note
Input model rows are not edited. MASSFLUX uses native amount/(s m), converted by .001*edge length to native_concentration*m3/s. HEATFLUX requires the temperature row. Allocation and input signal I/O errors propagate; no partial result is published.
  • coverage (in): Active-aquifer mask, at least the prepared state cell count.
  • heat_capacity (in): Positive finite water heat capacity J/(m3 K) for HEATFLUX conversion.
    Returns
    Owned SI boundary descriptors with zero receipts; throws on invalid rows, composition, geometry or signal resolution. No partial result is returned.
    Positional dependencies The unnamed arguments supply simulation context, prepared SI
    mesh, authored aquifer config, quality config, prepared hydraulic state and transport identity, in that order. They must remain stable and internally consistent. Context signal resolution can perform table I/O; all other inputs are read-only. Full field units and refusal conditions are documented at the definition.
Here is the call graph for this function:

◆ resolveGwSignal()

GwSourceSignal openswmm::twoD::resolveGwSignal ( SimulationContext & ctx,
double value,
const std::string & name,
std::unordered_map< std::string, GwSourceSignal > & cache,
const char * label )

Resolve a finite constant or copy/share a strictly ordered model time series.

Resolve a constant or immutable named series in elapsed simulation seconds.

Parameters
[in,out]ctxContext supplying named time-series tables and absolute simulation start serial. File-backed table cache loading can mutate ctx.tables and perform I/O.
[in]valueFinite constant in caller-defined physical units, used only when name is empty.
[in]nameOptional exact model time-series name. A nonempty name takes precedence over value.
[in,out]cacheCall-scoped named signal cache for this same context/start-date/model. Existing exact-name hits are trusted and copied; newly validated series are inserted only after complete loading and conversion. Do not reuse across differing model identities or edits.
[in]labelNonnull diagnostic section prefix used in exceptions.
Returns
Owned signal value; constants have no time knots, named series share an immutable copied series, with times in elapsed seconds relative to ctx.options.start_date and hasNegative metadata.
Exceptions
std::runtime_errorOn invalid constant, unknown/empty series, nonfinite or nonincreasing knots, multiple value columns, invalid/short cache or file read failure.
Note
Named series ordinate units are unchanged. Allocation failures propagate. A failure can change the context's file cache but does not insert an incomplete named signal into cache. Returned series remain valid independently of future model-table cache replacement.
  • label (in): Nonnull diagnostic prefix, normally the calling input section name.
    Returns
    Owned signal sharing validated copied named ordinates, or a constant. Throws on invalid constant/series, unknown name, I/O or allocation failure.
    Unnamed arguments in order Simulation context (mutable table cache), finite constant in
    caller units, optional series name, and a mutable per-context named-signal cache. Nonempty name wins over the constant. File-backed tables may load cache pages; exact-name cache hits require the same unchanged context/start date.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ resolveGwSources()

std::vector< GwResolvedSource > openswmm::twoD::resolveGwSources ( SimulationContext & ctx,
const MeshData & mesh,
const GwTransportData & gw,
const SubsurfaceState & state,
const SubsurfaceTransportState & tr )

Resolve authored groundwater sources to normalized active-cell shares and native signals.

Resolve authored source scopes, normalized cell areas and transport prescriptions.

Parameters
[in,out]ctxModel units, time-series tables and species metadata; file-backed signal resolution can load/mutate table caches and perform I/O.
[in]meshStable mesh tags; a cell beyond tri_tag.size() cannot match a TAG selector.
[in]gwAuthored source rows, including finite nonnegative SCALE and CELL/TAG/global scopes.
[in]statePrepared hydraulic state; positive cell area and aquifer depth define active receivers. Per-cell area/zs arrays must cover state.n_cells.
[in]trPrepared transport row identity, pollutant count and optional age/temperature rows.
Returns
Owned resolved sources in authored order. Cell shares are normalized by positive matched area; flow is total m3/s, CONC uses row-native concentration/age/temperature units, and pollutant MASS uses native amount/s with .001 conversion to native_concentration*m3/s.
Exceptions
std::runtime_errorOn negative/nonfinite scale, no matched active cell, disabled or duplicate species, unsupported term kind, MASS on non-pollutant rows, invalid signal, or negative concentration/mass rate. Temperature CONC alone may be signed.
Note
Zero scale is valid and later integrates no forcing. Sources need not prescribe every row's composition here; unspecified rows receive no source loading. Model rows are unchanged; local cache shares copied immutable series across sources. Allocation/I/O exceptions propagate before any partial resolved vector is published.
Returns
Owned source vector; throws on invalid scale, unmatched cells, invalid species/signals or unsupported terms. A failed call returns no partial vector and leaves authored rows unchanged.
Arguments in order Simulation context with mutable file-table cache; stable mesh with
tags; authored groundwater transport/source configuration; prepared hydraulic state with positive active-cell area/depth; and prepared transport row identity. Signals are copied/shared, flow is total m3/s, cell shares sum to one per source, and MASS is restricted to pollutants with known native amount units.
Here is the call graph for this function:

◆ resolveGwTransport()

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.

Parameters
[in,out]ctxMatching prepared species registry, series names, input path and model tables; logically read by this resolver.
[in]meshFinal cell count/tags/centroids/local vertex counts, stable and consistently sized.
[in,out]gwAuthoring rows; invalidates caches, loads external initial quality and updates XY source cell assignments while preserving authored location fields.
Returns
All collected file/grammar/cell/tag/species/series/duplicate-source/sign diagnostics; empty when these checks succeed. Does not guarantee complete runtime thermal/native profile qualification.
Note
Resolves sidecar relative to INP directory; comma/semicolon/tab become separators. Removes previous non-LAYER file rows marked -2, ignores malformed physical first line as header, appends other valid rows while collecting errors. LAYER rows lack that marker and are not deduplicated on re-resolve. XY uses nearest centroid, first minimum wins; caller ensures compatible coordinate units. Signed initial age/temperature accepted here, other negative concentration refused. Does not seed native inventories, activate sources, convert units or advance time. Errors may coexist with loaded/ resolved mutations; allocation/file exceptions can propagate. Exclusive authoring/resolve access.

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).

  • Argument ctx (in,out): Matching prepared species registry, series names, input path and model tables; logically read by this resolver.
  • Argument mesh (in): Final cell count/tags/centroids/local vertex counts, stable and consistently sized.
  • Argument gw (in,out): Authoring rows; invalidates caches, loads external initial quality and updates XY source cell assignments while preserving authored location fields.
    Returns
    All collected file/grammar/cell/tag/species/series/duplicate-source/sign diagnostics; empty when these checks succeed. Does not guarantee complete runtime thermal/native profile qualification.
    Note
    Resolves sidecar relative to INP directory; comma/semicolon/tab become separators. Removes previous non-LAYER file rows marked -2, ignores malformed physical first line as header, appends other valid rows while collecting errors. LAYER rows lack that marker and are not deduplicated on re-resolve. XY uses nearest centroid, first minimum wins; caller ensures compatible coordinate units. Signed initial age/temperature accepted here, other negative concentration refused. Does not seed native inventories, activate sources, convert units or advance time. Errors may coexist with loaded/ resolved mutations; allocation/file exceptions can propagate. Exclusive authoring/resolve access.
Here is the call graph for this function:

◆ resolveLinkSeepage()

std::vector< GwLinkShare > openswmm::twoD::resolveLinkSeepage ( SimulationContext & ctx,
const MeshData & mesh,
SubsurfaceConfig & cfg,
std::vector< std::string > & link_names,
double node_xy_to_mesh,
int & n_conduits )

Resolve conduit polylines into normalized aquifer cell shares and vertical contact reaches.

G-X3 (2026-09-19): the length-weighted (conduit, cell) shares for every conduit with a [LOSSES] seepage rate whose polyline crosses the mesh (LINK_SEEPAGE AUTO). n_conduits receives how many conduits got at least one share. Same coordinate factor as resolveSubsurface.

Parameters
[in,out]ctxPrepared link/name/conduit/node/spatial tables; appends warnings for unknown or non-conduit explicit rows.
[in]meshStable validated finite convex CCW cell geometry, consistent with converted map frame.
[in,out]cfgRetained conduit overrides, whose resolved link indices are replaced; exchange opt-out honored. DEFAULT mesh mode chooses two-way coefficient eligibility, legacy AUTO stays one-way.
[in,out]link_namesParallel authored names, read without mutation; absent treated empty.
[in]node_xy_to_meshPositive finite conversion from authored map to mesh coordinate length.
[out]n_conduitsReset zero, incremented for each eligible conduit with positive clipped coverage.
Returns
Owned per-(link,cell) dimensionless shares plus contact fractions and SI endpoint bed-elevation reaches. Denominator=max(total polyline length,sum clipped length) prevents aggregate overbooking when shared edges appear in both cells. Output follows native link order, then candidate discovery.
Note
Eligible positive legacy seepage or two-way authored KC, coordinates and actual conduit subtype are required; missing geometry/ineligible links skipped. Native inverts converted ft to m, optional DC project length subtracted. Does not apply water/native seepage or require aquifer coverage (caller filters that later). No full overlap/nonfinite repair; allocations may throw after name/warning edits. Requires exclusive setup/model identity; no engine/calendar advance.

Resolve conduit polylines into normalized aquifer cell shares and vertical contact reaches.

  • Argument ctx (in,out): Prepared link/name/conduit/node/spatial tables; appends warnings for unknown or non-conduit explicit rows.
  • Argument mesh (in): Stable validated finite convex CCW cell geometry, consistent with converted map frame.
  • Argument cfg (in,out): Retained conduit overrides, whose resolved link indices are replaced; exchange opt-out honored. DEFAULT mesh mode chooses two-way coefficient eligibility, legacy AUTO stays one-way.
  • Argument link_names (in,out): Parallel authored names, read without mutation; absent treated empty.
  • Argument node_xy_to_mesh (in): Positive finite conversion from authored map to mesh coordinate length.
  • Argument n_conduits (out): Reset zero, incremented for each eligible conduit with positive clipped coverage.
    Returns
    Owned per-(link,cell) dimensionless shares plus contact fractions and SI endpoint bed-elevation reaches. Denominator=max(total polyline length,sum clipped length) prevents aggregate overbooking when shared edges appear in both cells. Output follows native link order, then candidate discovery.
    Note
    Eligible positive legacy seepage or two-way authored KC, coordinates and actual conduit subtype are required; missing geometry/ineligible links skipped. Native inverts converted ft to m, optional DC project length subtracted. Does not apply water/native seepage or require aquifer coverage (caller filters that later). No full overlap/nonfinite repair; allocations may throw after name/warning edits. Requires exclusive setup/model identity; no engine/calendar advance.
Here is the call graph for this function:

◆ resolveSubcatchInfiltration()

std::vector< GwSubcatchShare > openswmm::twoD::resolveSubcatchInfiltration ( const SimulationContext & ctx,
const MeshData & mesh,
double node_xy_to_mesh,
int & n_subcatch )

Compute normalized polygon-area shares from every subcatchment footprint to mesh cells.

The area-weighted (subcatchment, cell) shares for every subcatchment whose [Polygons] overlap the mesh. Shares are resolved for all of them; the router skips a subcatchment with a lumped [GROUNDWATER] aquifer at delivery. n_subcatch receives how many subcatchments got at least one share. Same coordinate factor as resolveSubsurface.

Parameters
[in]ctxStable authored subcatchment polygon x/y vectors and count.
[in]meshValid finite convex CCW cell geometry in the converted map frame.
[in]node_xy_to_meshPositive finite authored map to mesh length factor.
[out]n_subcatchReset zero, incremented for each subcatchment with positive clipped coverage.
Returns
Owned (zero-based subcatch,cell,weight) rows with denominator=max(polygon area,sum cell intersection area), so total share<=1. No lumped-aquifer exclusion here; delivery owner chooses scope.
Note
Uses common prefix of mismatched polygon x/y arrays, skips fewer-than3/nonpositive area, stops when a whole polygon entry missing. No full geometry/finite validation beyond assumed prepared inputs. Allocates/clips read-only; no water/native/source ownership activation or clock update.

Compute normalized polygon-area shares from every subcatchment footprint to mesh cells.

  • Argument ctx (in): Stable authored subcatchment polygon x/y vectors and count.
  • Argument mesh (in): Valid finite convex CCW cell geometry in the converted map frame.
  • Argument node_xy_to_mesh (in): Positive finite authored map to mesh length factor.
  • Argument n_subcatch (out): Reset zero, incremented for each subcatchment with positive clipped coverage.
    Returns
    Owned (zero-based subcatch,cell,weight) rows with denominator=max(polygon area,sum cell intersection area), so total share<=1. No lumped-aquifer exclusion here; delivery owner chooses scope.
    Note
    Uses common prefix of mismatched polygon x/y arrays, skips fewer-than3/nonpositive area, stops when a whole polygon entry missing. No full geometry/finite validation beyond assumed prepared inputs. Allocates/clips read-only; no water/native/source ownership activation or clock update.
Here is the call graph for this function:

◆ resolveSubsurface()

std::vector< std::string > openswmm::twoD::resolveSubsurface ( SimulationContext & ctx,
const MeshData & mesh,
SubsurfaceConfig & cfg,
std::vector< std::string > & names,
double node_xy_to_mesh )

Resolve native-node bed identity/location and optional coordinate-based automatic enrollment.

Resolve node names to indices and each bed's cell to a mesh cell; locate CELL AUTO rows and (G-X2, NODE_ENROLMENT AUTO) enrol every node whose [COORDINATES] fall in a cell, appending to cfg.node_beds and names. node_xy_to_mesh converts node coordinates (project map units) into the mesh's coordinates (SI metres once the router has scaled it). Returns diagnostics; empty on success.

Parameters
[in,out]ctxMatching native node-name/coordinate/LID metadata; appends advisory on enrollment.
[in]meshStable prepared cell geometry/vertex indices and consistent finite coordinates.
[in,out]cfgRetained aquifer rows/beds; replaces resolved node/cell on existing beds and may append automatic beds. Authored exchange flags preserved, sealed native LIDs suppress effective checks.
[in,out]namesParallel bed node names, appended with automatic rows; existing entries used for native identity resolution, absent entry treated empty name.
[in]node_xy_to_meshPositive finite project-map-length to mesh-coordinate factor, normally authored ft/m to already SI mesh m.
Returns
All invalid explicit aquifer cells, missing native nodes/coordinates/cells and duplicate node-bed diagnostics; empty on these checks succeeding. Does not fully validate thermal/native profiles.
Note
Empty config returns. AUTO locates first containing cell by binned ray casting. Enrollment runs only if prior checks have no errors and node_auto enabled; explicit opt-out still blocks auto. No row unit conversion/water/clock advance. Resolution can mutate even on diagnostics; allocation may leave parallel appends partly complete. Exclusive authoring/setup access required.

Resolve native-node bed identity/location and optional coordinate-based automatic enrollment.

  • Argument ctx (in,out): Matching native node-name/coordinate/LID metadata; appends advisory on enrollment.
  • Argument mesh (in): Stable prepared cell geometry/vertex indices and consistent finite coordinates.
  • Argument cfg (in,out): Retained aquifer rows/beds; replaces resolved node/cell on existing beds and may append automatic beds. Authored exchange flags preserved, sealed native LIDs suppress effective checks.
  • Argument names (in,out): Parallel bed node names, appended with automatic rows; existing entries used for native identity resolution, absent entry treated empty name.
  • Argument node_xy_to_mesh (in): Positive finite project-map-length to mesh-coordinate factor, normally authored ft/m to already SI mesh m.
    Returns
    All invalid explicit aquifer cells, missing native nodes/coordinates/cells and duplicate node-bed diagnostics; empty on these checks succeeding. Does not fully validate thermal/native profiles.
    Note
    Empty config returns. AUTO locates first containing cell by binned ray casting. Enrollment runs only if prior checks have no errors and node_auto enabled; explicit opt-out still blocks auto. No row unit conversion/water/clock advance. Resolution can mutate even on diagnostics; allocation may leave parallel appends partly complete. Exclusive authoring/setup access required.
Here is the call graph for this function:

◆ resolveSurfaceOwnership()

SurfaceOwnershipPreview openswmm::twoD::resolveSurfaceOwnership ( const SimulationContext & ctx,
const MeshData & mesh,
const SolverOptions2D & opts,
const SubsurfaceConfig & cfg,
const std::vector< SurfaceOwnerRecord > & proposed,
const std::function< bool(int, int)> & progress )

Preview reviewed source footprints, receiver shares and weather-area ownership without adoption.

Parameters
[in]ctxStable complete subcatchment names/area/impervious/lumped/LID/polygon, unit/options and CRS metadata; all parallel vectors must cover declared counts.
[in]meshStable cell/vertex topology and geometry in declared authored or already SI frame.
[in]optsMesh scaling/process flags used to choose geometry conversion/qualification.
[in]cfgStable authored aquifer/process/ownership settings used for profile and fingerprint.
[in]proposedCandidate reviewed subcatchment records, matched by exact model names; no live config mutation occurs.
[in]progressOptional synchronous callback(done,total), total=n_cells+n_subcatches; false requests cancellation (opposite mapMeshPolyline callback convention). May receive repeated total.
Returns
Owned preview with per-source status/reason, SI m2 shares/weather areas, diagnostics, cancellation flag and FNV64 model token on normal completion. Cancellation may return partial objects/shares and no token; errors retain diagnostics/derived preview, never install live ownership.
Note
Validates convex cell geometry, triangulates source polygons, checks declared versus polygon area without renormalizing, subtracts LID/impervious fractions and exact cell intersections, follows connected competing footprints and refuses unreviewed competitors/overlapping polygons. Explicit review requires enabled MODE MESH/routing ownership. Lumped aquifer precedence remains visible. Clamps only tiny weather-area residue after reporting overbooking; no physics/native/source adapter activation or clock advance. Allocations/callback exceptions propagate; stable exclusive lifecycle views required. Token is a change detector, not authentication or full runtime qualification.
  • Argument ctx: Stable complete subcatchment names/area/impervious/lumped/LID/polygon, unit/options and CRS metadata; all parallel vectors must cover declared counts.
  • Argument mesh: Stable cell/vertex topology and geometry in declared authored or already SI frame.
  • Argument opts: Mesh scaling/process flags used to choose geometry conversion/qualification.
  • Argument cfg: Stable authored aquifer/process/ownership settings used for profile and fingerprint.
  • Argument proposed: Candidate reviewed subcatchment records, matched by exact model names; no live config mutation occurs.
  • Argument progress (in): Optional synchronous callback(done,total), total=n_cells+n_subcatches; false requests cancellation (opposite mapMeshPolyline callback convention). May receive repeated total.
    Returns
    Owned preview with per-source status/reason, SI m2 shares/weather areas, diagnostics, cancellation flag and FNV64 model token on normal completion. Cancellation may return partial objects/shares and no token; errors retain diagnostics/derived preview, never install live ownership.
    Note
    Validates convex cell geometry, triangulates source polygons, checks declared versus polygon area without renormalizing, subtracts LID/impervious fractions and exact cell intersections, follows connected competing footprints and refuses unreviewed competitors/overlapping polygons. Explicit review requires enabled MODE MESH/routing ownership. Lumped aquifer precedence remains visible. Clamps only tiny weather-area residue after reporting overbooking; no physics/native/source adapter activation or clock advance. Allocations/callback exceptions propagate; stable exclusive lifecycle views required. Token is a change detector, not authentication or full runtime qualification.
Here is the call graph for this function:

◆ rk2HasSurfaceBoundary()

bool openswmm::twoD::rk2HasSurfaceBoundary ( const BoundaryData * boundary)

Detect any hydraulic boundary use or retained override/receipt history.

Parameters
[in]boundaryOptional stable boundary owner.
Returns
False for null or wall-only arrays with no history; true for any receipts, saved runtime originals or non-WALL current type. This capability test does not validate arrays or descriptors.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rk2ManagedRuntimeModel() [1/2]

void openswmm::twoD::rk2ManagedRuntimeModel ( Archive & a,
RuntimeSources & surface,
RuntimeSources & ground,
RuntimeForcings & forcing,
int species,
BoundaryData * boundary,
std::map< int, std::vector< double > > * quality )

Archive copied RK2 source/forcing prescriptions for a managed model binding.

Parameters
[in,out]aSequential archive; read mode may progressively replace row vectors.
[in,out]surfaceSurface source model rows.
[in,out]groundGroundwater source model rows, including optional boundary-edge/head metadata.
[in,out]forcingCopied forcing model rows, including channel/mode/rate/expiry/owner/composition.
[in]speciesPrepared nonnegative boundary receipt species count.
[in,out]boundaryOptional hydraulic boundary model owner; required for encoded profile v2.
[in,out]qualityOptional boundary composition map; required with v2 boundary profile.
Exceptions
std::runtime_errorOn unsupported v1/v2 profile, missing boundary owner or archive failures.
Note
This archives prescriptions/identity, not complete active runtime: decoding disables every row and clears source/forcing index/cell caches for later reconstruction. Boundary-head sources omit derived flow when their head is finite. Receipts, enabled flags and live external provider programs are not encoded by this helper. Full restored profile/replay validation is separate; use private candidates because failures can leave partial row/model changes.
Here is the call graph for this function:

◆ rk2ManagedRuntimeModel() [2/2]

void openswmm::twoD::rk2ManagedRuntimeModel ( detail::CompletedSourceArchive & a,
RuntimeSources & surface,
RuntimeSources & ground,
RuntimeForcings & forcing,
int species,
BoundaryData * boundary = nullptr,
std::map< int, std::vector< double > > * quality = nullptr )

Archive copied RK2 source/forcing prescriptions for a managed model binding.

Parameters
[in,out]aSequential archive; read mode may progressively replace row vectors.
[in,out]surfaceSurface source model rows.
[in,out]groundGroundwater source model rows, including optional boundary-edge/head metadata.
[in,out]forcingCopied forcing model rows, including channel/mode/rate/expiry/owner/composition.
[in]speciesPrepared nonnegative boundary receipt species count.
[in,out]boundaryOptional hydraulic boundary model owner; required for encoded profile v2.
[in,out]qualityOptional boundary composition map; required with v2 boundary profile.
Exceptions
std::runtime_errorOn unsupported v1/v2 profile, missing boundary owner or archive failures.
Note
This archives prescriptions/identity, not complete active runtime: decoding disables every row and clears source/forcing index/cell caches for later reconstruction. Boundary-head sources omit derived flow when their head is finite. Receipts, enabled flags and live external provider programs are not encoded by this helper. Full restored profile/replay validation is separate; use private candidates because failures can leave partial row/model changes.
Here is the caller graph for this function:

◆ rk2SurfaceBoundaryArchive() [1/2]

void openswmm::twoD::rk2SurfaceBoundaryArchive ( Archive & a,
BoundaryData & b,
std::map< int, std::vector< double > > & quality,
bool model,
int species )

Archive a matched RK2 boundary model identity or its accepted runtime receipts.

Parameters
[in,out]aSequential writer/reader; outer framing and final validation belong to the owner.
[in,out]bPrepared matching boundary arrays. Model mode archives fixed descriptors, fallback/owner maps and retained receipt keys; runtime mode fixed cumulative flux and existing receipt values, plus head/flow work values for dynamic signals/curves.
[in,out]qualityRuntime boundary concentration map, archived/rebuilt only in model mode.
[in]modelTrue selects copied/authored/state-dependent/time-dependent/rated model identity; false selects runtime payload against that already prepared exact profile and receipt-key layout.
[in]speciesNonnegative receipt row count used when rebuilding model receipt placeholders.
Exceptions
std::runtime_errorOn profile mismatch, duplicate/unsorted/out-of-range keys, archive shape or decoding failure. Allocation failures propagate; inputs may be partially decoded on failure.
Note
Dynamic work head/flow values are zeroed in writer model identity when supplied by a resolved series/curve. Physical values retain SI/native units. This helper neither validates full boundary physics/species budgets nor serializes referenced model table records; callers stage private copies.
Here is the call graph for this function:

◆ rk2SurfaceBoundaryArchive() [2/2]

void openswmm::twoD::rk2SurfaceBoundaryArchive ( detail::CompletedSourceArchive & a,
BoundaryData & b,
std::map< int, std::vector< double > > & quality,
bool model,
int species )

Archive a matched RK2 boundary model identity or its accepted runtime receipts.

Parameters
[in,out]aSequential writer/reader; outer framing and final validation belong to the owner.
[in,out]bPrepared matching boundary arrays. Model mode archives fixed descriptors, fallback/owner maps and retained receipt keys; runtime mode fixed cumulative flux and existing receipt values, plus head/flow work values for dynamic signals/curves.
[in,out]qualityRuntime boundary concentration map, archived/rebuilt only in model mode.
[in]modelTrue selects copied/authored/state-dependent/time-dependent/rated model identity; false selects runtime payload against that already prepared exact profile and receipt-key layout.
[in]speciesNonnegative receipt row count used when rebuilding model receipt placeholders.
Exceptions
std::runtime_errorOn profile mismatch, duplicate/unsorted/out-of-range keys, archive shape or decoding failure. Allocation failures propagate; inputs may be partially decoded on failure.
Note
Dynamic work head/flow values are zeroed in writer model identity when supplied by a resolved series/curve. Physical values retain SI/native units. This helper neither validates full boundary physics/species budgets nor serializes referenced model table records; callers stage private copies.
Here is the caller graph for this function:

◆ rk2SurfaceRuntimeProfile()

std::string openswmm::twoD::rk2SurfaceRuntimeProfile ( const SurfaceStateData & surface,
const SubsurfaceSolver * ground = nullptr )

Qualify prepared surface source/weather/snow state for the managed RK2 numerical profile.

Parameters
[in]surfaceStable prepared cell/transport/weather/snow state with valid row identities.
[in]groundOptional stable groundwater owner; used for paired infiltration coverage and snow incompatibility with groundwater heat/transport. Null leaves that coverage check deferred.
Returns
Empty on qualified source rows, forcing channels/modes/extents/receipts and accepted-rain pending arrays; otherwise first diagnostic. Does not mutate prescriptions, caches or water state.
Note
Active snow requires its water-only owned context/geometry/catch factors, no heat/transport, no copied weather or pending copied rain, no porous ground-contact mask, finite native weather and valid accepted cover/water/energy ledgers. General forcing channels 1..4 permit value/scale weather modes but no scale on infiltration/concentration; paired infiltration requires local receivers. Held weather has no applied receipts; infiltration uses outward water budget pairing. Allocation for duplicate-key checks can throw. Namespace/replay-time checks are separate.
Here is the call graph for this function:

◆ scatterCouplingToYdot()

void openswmm::twoD::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).

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).

Parameters
[in]meshPrepared SI stencil geometry and partition weights.
[in]stateLive matching heads used only to choose upwind weights.
[in]cpValid resolved cell/vertex coupling; indices are unchecked.
[in]QSigned volumetric source m3/s, positive into cells.
[in,out]ydotNonnull writable derivative buffer with at least mesh.n_cells() entries. Adds shares, retaining existing derivatives; no area division, storage advance or species scatter.
Note
Requires exclusive affected derivative slots and stable reconstruction. Allocation-free; no donor-budget or finite-value validation occurs.
Here is the call graph for this function:

◆ soilCharToken()

const char * openswmm::twoD::soilCharToken ( SoilChar s)
noexcept

Return the canonical token for a soil-characteristic law.

Parameters
[in]sSoil law; an unrecognized enum value falls back to RUSSO.
Returns
Borrowed immutable static uppercase string; never null and must not be freed.
Here is the caller graph for this function:

◆ solveLayerTransport() [1/2]

LayerTransportResult openswmm::twoD::solveLayerTransport ( const std::vector< double > & capacity,
const std::vector< double > & rhs,
const std::vector< LayerTransportMove > & moves,
bool signed_species = false )

Conservative, positivity-preserving implicit donor transport on a column chain. rhs holds mass after already-paired incoming/outgoing receipts; capacity is the final aqueous+sorption storage coefficient. Dry isolated mass is retained, not divided by an artificial water-volume floor.

Parameters
[in]capacityBorrowed nonempty per-layer aqueous-plus-sorption capacities, finite nonnegative m3-equivalent coefficients.
[in]rhsBorrowed equally sized post-receipt inventories in native concentration*m3; finite and nonnegative unless signed_species is true.
[in]movesBorrowed integrated nonnegative m3 transfer coefficients with valid distinct donor/recipient indices; to == -1 means an external sink.
[in]signed_speciesTrue allows signed concentration/inventory, used for temperature-volume; false enforces nonnegative inventory.
Returns
Value-owned result with final mass, final dissolved concentration, and transfers in move order. Internal moves must join adjacent layers; isolated zero-capacity inventories are retained separately rather than divided by a volume floor.
Note
Always inspect result.error before using arrays: invalid dimensions/data, singular systems or nonfinite results return a message and may leave partially filled result vectors. Inputs remain unchanged. Allocations may throw; no input storage is retained or engine state published.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ solveLayerTransport() [2/2]

const LayerTransportResult & openswmm::twoD::solveLayerTransport ( const std::vector< double > & capacity,
const std::vector< double > & rhs,
const std::vector< LayerTransportMove > & moves,
LayerTransportScratch & scratch,
bool signed_species )

◆ solveThermalContacts() [1/2]

ThermalSolution openswmm::twoD::solveThermalContacts ( const std::vector< ThermalStore > & stores,
const std::vector< ThermalContact > & contacts,
const std::vector< ThermalBoundary > & boundaries,
double dt )

Solve reciprocal heat contacts by backward Euler and diagonal-preconditioned CG.

Parameters
[in]storesFinite heat stores: positive finite capacity J/K and finite energy J. Inputs are read-only; temperatures are energy/capacity in degrees C relative to the energy datum.
[in]contactsReciprocal connections with distinct in-range store indices and finite nonnegative conductance W/K. Positive returned contact receipts move from a to b.
[in]boundariesIn-range store indices, finite nonnegative conductance W/K, finite prescribed temperature degrees C and finite signed power W. Positive receipts enter the store.
[in]dtFinite strictly positive interval in seconds; boundaries remain fixed throughout.
Returns
Owned solution with empty error on success, final energy J/temperature degrees C, contact and boundary receipts J in input order, iteration count and equation residual J. On numerical/physical refusal error is nonempty; other fields may be partial and must not be published. Allocation failures propagate. All inputs remain unchanged.
Note
Conjugate-gradient work is bounded by min(4096,4*n+64) iterations, with a 1e-13 relative preconditioned-norm scale. Energies are updated from equal/opposite receipts, then temperatures are recovered from those conservative energies; algebraic_residual measures their solve defect.
Declaration arguments
  • first store vector (in): Finite heat stores: positive finite capacity J/K and finite energy J. Inputs are read-only; temperatures are energy/capacity in degrees C relative to the energy datum.
  • second contact vector (in): Reciprocal connections with distinct in-range store indices and finite nonnegative conductance W/K. Positive returned contact receipts move from a to b.
  • third boundary vector (in): In-range store indices, finite nonnegative conductance W/K, finite prescribed temperature degrees C and finite signed power W. Positive receipts enter the store.
  • seconds (in): Finite strictly positive interval in seconds; boundaries remain fixed throughout.
Returns
Owned solution with empty error on success, final energy J/temperature degrees C, contact and boundary receipts J in input order, iteration count and equation residual J. On numerical/physical refusal error is nonempty; other fields may be partial and must not be published. Allocation failures propagate. All inputs remain unchanged.
Note
Conjugate-gradient work is bounded by min(4096,4*n+64) iterations, with a 1e-13 relative preconditioned-norm scale. Energies are updated from equal/opposite receipts, then temperatures are recovered from those conservative energies; algebraic_residual measures their solve defect.
Here is the caller graph for this function:

◆ solveThermalContacts() [2/2]

ThermalSolution & openswmm::twoD::solveThermalContacts ( const std::vector< ThermalStore > & stores,
const std::vector< ThermalContact > & contacts,
const std::vector< ThermalBoundary > & boundaries,
double dt,
ThermalContactScratch & scratch )

◆ solveThermalContactsRk2() [1/2]

ThermalSolution openswmm::twoD::solveThermalContactsRk2 ( const std::vector< ThermalStore > & stores,
const std::vector< ThermalContact > & contacts,
const std::vector< ThermalBoundary > & boundaries,
double dt )

Solve reciprocal heat contacts by bounded implicit-midpoint subdivisions.

Parameters
[in]storesFinite heat stores: positive finite capacity J/K and finite energy J. Inputs are read-only; temperatures are energy/capacity in degrees C relative to the energy datum.
[in]contactsReciprocal connections with distinct in-range store indices and finite nonnegative conductance W/K. Positive returned contact receipts move from a to b.
[in]boundariesIn-range store indices, finite nonnegative conductance W/K, finite prescribed temperature degrees C and finite signed power W. Positive receipts enter the store.
[in]dtFinite strictly positive interval in seconds; boundaries remain fixed throughout.
Returns
Owned solution with empty error on success, final energy J/temperature degrees C, contact and boundary receipts J in input order, iteration count and equation residual J. On numerical/physical refusal error is nonempty; other fields may be partial and must not be published. Allocation failures propagate. All inputs remain unchanged.
Note
Subdivision enforces dt_sub*sum(conductance)/(2*capacity) <= 1. More than 65536 required subintervals returns interval_limit=true; other refusals leave it false. Each midpoint solve uses backward Euler over half a subinterval, and doubled receipts update energy conservatively. This method advances neither moisture nor external thermal owners.
Declaration arguments
  • first store vector (in): Finite heat stores: positive finite capacity J/K and finite energy J. Inputs are read-only; temperatures are energy/capacity in degrees C relative to the energy datum.
  • second contact vector (in): Reciprocal connections with distinct in-range store indices and finite nonnegative conductance W/K. Positive returned contact receipts move from a to b.
  • third boundary vector (in): In-range store indices, finite nonnegative conductance W/K, finite prescribed temperature degrees C and finite signed power W. Positive receipts enter the store.
  • seconds (in): Finite strictly positive interval in seconds; boundaries remain fixed throughout.
Returns
Owned solution with empty error on success, final energy J/temperature degrees C, contact and boundary receipts J in input order, iteration count and equation residual J. On numerical/physical refusal error is nonempty; other fields may be partial and must not be published. Allocation failures propagate. All inputs remain unchanged.
Note
Subdivision enforces dt_sub*sum(conductance)/(2*capacity) <= 1. More than 65536 required subintervals returns interval_limit=true; other refusals leave it false. Each midpoint solve uses backward Euler over half a subinterval, and doubled receipts update energy conservatively. This method advances neither moisture nor external thermal owners.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ solveThermalContactsRk2() [2/2]

ThermalSolution & openswmm::twoD::solveThermalContactsRk2 ( const std::vector< ThermalStore > & stores,
const std::vector< ThermalContact > & contacts,
const std::vector< ThermalBoundary > & boundaries,
double dt,
ThermalMidpointScratch & scratch )
Here is the call graph for this function:

◆ transferLidNodeThermalEnergy()

std::string openswmm::twoD::transferLidNodeThermalEnergy ( const LidNodeThermalGraph & graph,
std::size_t cell_count,
double water_heat_capacity,
const std::vector< LidThermalWaterTransfer > & transfers,
std::vector< double > & physical_energy,
double & external_j,
std::vector< double > * transfer_j )

Stage producer-ordered sensible energy transfers through a fixed physical LID graph.

Convert accepted ordered water packets into a staged physical-layer energy result.

Parameters
[in]graphPrepared beginning-state stores plus complete SI physical water/matrix arrays. Stored capacities must match the derived beginning capacities; active stores must not be omitted.
[in]cell_countPhysical LID cell count (header: physical_cell_count), matching every graph physical-array extent. Compact cell indices must be strictly increasing and valid.
[in]water_heat_capacityFinite positive volumetric water capacity J/(m3 K).
[in]transfersOrdered accepted water packets: nonnegative finite m3, physical cell indices or -1 for the external owner. A packet must change owner and have at least one physical endpoint. External inflows use source_temperature_c; internal donors use updated pre-packet energy/capacity.
[out]physical_energyReplaced by signed J per physical cell only after every packet validates (header: physical_cell_energy); incoming contents are not used.
[out]external_jReplaced by net J added to the LID from external transfers, signed positive inward. Incoming scalar is not accumulated.
[out]transfer_jOptional vector replaced by signed carried sensible J per packet in original order, including zeros. The sign follows donor temperature, not transfer direction.
Returns
Empty on success; diagnostic for layout/capacity, donor availability, receiver overflow, invalid packet, nonfinite energy or energy remaining without capacity.
Note
Keeps graph/hydraulic owners unchanged and stages outputs until validation completes. Tracks water/capacity after every packet, including matrix replacement by water. Outputs must be distinct buffers and access serialized; temporary allocations can throw. Caller separately publishes accepted water and returned physical energy to matching canonical owners.
  • physical_cell_count: Physical owner cell count matching graph arrays.
  • water_heat_capacity: Finite positive volumetric water capacity J/(m3 K).
  • physical_cell_energy: Replaced with signed J per physical cell on success.
  • external_j: Replaced with net external J into the LID, rather than accumulated.
  • transfer_j: Optional per-packet signed carried J vector, replaced on success.
    Returns
    Empty on success; otherwise descriptive refusal with all outputs unchanged. Requires prepared graph and valid ordered accepted transfers as detailed in the definition. Allocates and may throw; does not modify the graph, water state or canonical LID energy itself.
Here is the caller graph for this function:

◆ trialRichardsBeds()

RichardsBedTrial openswmm::twoD::trialRichardsBeds ( const SubsurfaceSolver & gw,
double dt,
const std::vector< RichardsBedBinding > & input )

Freeze actual aquifer budgets and compute a private one-interval Richards exchange trial.

Evaluate a private one-interval finite aquifer/Richards directional exchange trial.

Parameters
[in]gwStable prepared groundwater owner; read only.
[in]dtFinite positive proposed duration s, called interval in the declaration.
[in]inputBorrowed resolved bed/column bindings, copied and sorted by node. Columns/materials use SI and remain alive/unchanged through the call; max_bottom_water is m3 and clogging dimensionless.
Returns
Owned RichardsBedTrial with error empty only on success. Both proposal/bounded solve work is counted. Private results do not advance canonical columns, aquifer state or clocks.
Note
Delegates to trialBeds() without externally frozen budgets/remaining quotas. Validates identity/geometry/material through the ordinary Richards kernel; allocations or missing referenced state can throw. Caller must separately perform joint qualified acceptance, not blindly copy a trial.
  • Argument interval (in): Finite positive duration s, called dt in source.
    Returns
    Owned trial with error, node-sorted private columns/reports/receipts and frozen SI budgets. The groundwater and binding-vector arguments are borrowed read only; original columns and clocks remain unchanged. Definition documents uniqueness, units, quota limits and exception behavior.
Here is the caller graph for this function:

◆ turbulenceName()

const char * openswmm::twoD::turbulenceName ( Turbulence2D t)
inlinenoexcept

[2D_OPTIONS] TURBULENCE_MODEL token for a closure.

Here is the caller graph for this function:

◆ updateOutfallBoundaries()

void openswmm::twoD::updateOutfallBoundaries ( const std::vector< CouplingPoint > & cps,
const MeshData & mesh,
const SurfaceStateData & state,
SimulationContext & ctx,
const SolverOptions2D & opts,
double dt )

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.

Parameters
cpsCoupling points.
meshMesh data.
state2D surface state.
ctxSimulation context.
opts2D solver options (for unit-system coupling factors).
dtRouting step about to run (s), for TAILWATER_RELAX.
Note
Publishes only cached head_2d (native 1D length) and wet ramp, consumed by later 1D boundary iterations; it does not directly overwrite node head/depth or book water. Vertex wetness uses the deepest live stencil cell; optional sampling range changes stage to a wet-depth mean. Multiple points for one outfall use the last point's target/ramp/relaxation. Positive relaxation time uses min(1,dt/tau) after first initialization. Requires valid resolved indices, positive dry_depth and stable buffers. Allocates staging arrays and may throw after some ramps were written; caller serializes with routing and does not assume a fully atomic boundary-cache update.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ validateMesh()

std::string openswmm::twoD::validateMesh ( const MeshData & mesh)

Validate mesh data for consistency.

Checks: vertex indices in bounds, positive areas, no degenerate triangles.

Parameters
[in]meshThe mesh to validate.
Returns
Empty string if valid, or a description of the first error found.
Precondition
Connectivity and derived geometry arrays are sized consistently; topology construction has already populated cell areas. Invalid outer container sizes are not guarded.
Note
Checks actual triangle/quad vertex bounds, duplicate vertices, positive area and roughness, and quad convexity. It does not exhaustively reject nonfinite geometry or nonmanifold edges. Read-only; formatting errors may allocate/throw.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ validateMeshCancellable()

std::string openswmm::twoD::validateMeshCancellable ( const MeshData & mesh,
const std::function< bool(int)> & progress,
bool & cancelled )

Cancellable validator. cancelled is set when progress returns true.

Parameters
[in]meshBorrowed built mesh; container extents must be consistent before validation.
[in]progressOptional synchronous percent callback [0,100]; true cancels. Must not mutate the mesh.
[out]cancelledReset false on entry, then set true only for callback cancellation.
Returns
First validation error string, or empty for success OR cancellation; always inspect cancelled before treating an empty string as valid.
Note
Read-only validation, with the same checks/limitations as validateMesh(); allocation and callback exceptions propagate. No references/callbacks retained.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ validateRk2ReplayIds()

std::string openswmm::twoD::validateRk2ReplayIds ( const RuntimeSources & surface,
const RuntimeSources & ground,
const RuntimeForcings & forcing,
double completed )

Check provider namespaces, active expiry and last-receipt horizons at a managed boundary.

Parameters
[in]surfaceStable source rows already validated for finite shapes/receipts.
[in]groundStable groundwater source rows under the same prepared model.
[in]forcingStable copied forcing rows already validated by the RK2 profile checks.
[in]completedFinite nonnegative accepted elapsed time s.
Returns
Empty when owners contain no slash/NUL, enabled records expire strictly later, last receipt intervals fit completed/gross water, and nonboundary source IDs match direct/provider local namespaces; otherwise diagnostic. Boundary IDs receive topology-specific validation elsewhere.
Note
Read-only; does not expire rows, rebuild lookups, verify external program state or repeat all finite/shape validation. Prefix/sub-string construction can allocate and throw.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ validateRk2Sources()

std::string openswmm::twoD::validateRk2Sources ( const RuntimeSources & sources,
int cells,
int species,
int temperature,
int age,
const std::vector< uint8_t > * coverage = nullptr )

Validate copied RK2 source prescriptions and water/heat/species receipt shapes.

Parameters
[in]sourcesStable source rows; no live lookup caches or physical state are changed.
[in]cellsPrepared nonnegative cell count.
[in]speciesPrepared nonnegative species count; each row concentration/rate and receipt mass vector must contain exactly this many entries.
[in]temperatureOptional signed temperature row, -1 when absent; nonzero heat requires one.
[in]ageOptional age row, -1 when absent; age/temperature independent mass rates must be zero.
[in]coverageOptional mask of exactly cells entries selecting active groundwater receivers. Its presence permits boundary-edge/head metadata; without it only nonboundary rows are accepted.
Returns
Empty on valid IDs/cells/uniqueness/finite flow+heat/expiry/species and gross/net receipts, otherwise diagnostic. Temperature concentrations may be signed; other concentrations nonnegative. Expiry may be zero or positive infinity here; active completed-time expiry is checked separately.
Note
Does not validate namespace owners, derived lookup caches, boundary edge upper topology, complete time horizons or physical donor availability. Local identity checking allocates and may throw; input rows/receipts remain unchanged.
Here is the caller graph for this function:

◆ validateRk2SurfaceBoundary()

std::string openswmm::twoD::validateRk2SurfaceBoundary ( const MeshData & mesh,
const SurfaceStateData & surface )

Validate prepared RK2 exterior boundary descriptors, composition and physical receipts.

Parameters
[in]meshStable valid mixed mesh; padded slot shape is four times cell count, with valid cell vertex counts and neighbors for exterior-edge tests.
[in]surfaceStable boundary and transport owner. Boundary arrays must have exact slot shape, transport ledgers at least n_species entries and prepared valid row metadata.
Returns
Empty for supported resolved exterior boundaries and exact override-owner/composition layout, finite scalar/species receipts and gross/net pairing; otherwise diagnostic. Without a hydraulic boundary profile, runtime boundary quality must be empty.
Note
Authored quality must belong to a nonwall fallback edge and valid species; concentration may be signed only for temperature. Applied boundary species receipts must match gained-minus- lost physical transport ledgers at 1e-10 scale. Type/series arrangements require resolved indices, but actual table identity/records are checked by model binding elsewhere. This validator is read-only, does not reconstruct caches, and does not reject finite signed bed slopes.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vertexHeadAt()

double openswmm::twoD::vertexHeadAt ( const MeshData & mesh,
const SurfaceStateData & state,
int v )
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.

Parameters
[in]meshBorrowed valid CSR stencils; no topology/extent checks.
[in]stateBorrowed cell heads in metres, stable for the entire gather.
[in]vValid zero-based vertex index with a row in vert_stencil_ptr.
Returns
Weighted head in metres, or zero for an empty stencil. No clipping, allocation, cached vertex-field updates, or retained references.
Here is the caller graph for this function:

◆ vfrDEtaDMeanDepth()

OPENSWMM_KERNEL_FN double openswmm::twoD::vfrDEtaDMeanDepth ( double z1,
double z2,
double z3,
double eta,
double eps )
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.

Parameters
[in]z1Finite minimum vertex elevation, m.
[in]z2Finite middle vertex elevation, m; z1 <= z2 <= z3.
[in]z3Finite maximum vertex elevation, m.
Precondition
Elevations are already sorted; no input validation is performed.
Parameters
[in]etaFinite free-surface elevation, m in the same vertical datum.
[in]epsDimensionless wet-area regularization floor in [0,1); nonpositive selects the exact closure.
Returns
Dimensionless inverse slope; a final wet-fraction floor of 1e-12 caps the value at 1e12 even when eps is zero.
Note
Pure scalar host/device calculation; no allocation, retained storage, or solver state mutation.
Here is the call graph for this function:

◆ vfrDryEta()

OPENSWMM_KERNEL_FN double openswmm::twoD::vfrDryEta ( double z1,
double z2,
double z3,
double eps )
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.

Parameters
[in]z1Finite minimum vertex elevation, m.
[in]z2Finite middle vertex elevation, m; z1 <= z2 <= z3.
[in]z3Finite maximum vertex elevation, m.
Precondition
Elevations are already sorted; no input validation is performed.
Parameters
[in]epsDimensionless wet-area regularization floor in [0,1); nonpositive selects the exact closure.
Returns
Dry regularized stage in m, consistent with zero-volume seeding.
Note
Pure scalar host/device calculation; no allocation, retained storage, or solver state mutation.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vfrEtaFromMeanDepth()

OPENSWMM_KERNEL_FN double openswmm::twoD::vfrEtaFromMeanDepth ( double z1,
double z2,
double z3,
double mean_depth,
double eps )
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.

Parameters
[in]z1Finite minimum vertex elevation, m.
[in]z2Finite middle vertex elevation, m; z1 <= z2 <= z3.
[in]z3Finite maximum vertex elevation, m.
Precondition
Elevations are already sorted; no input validation is performed.
Parameters
[in]mean_depthFinite cell-mean water depth V/A, m; nonpositive values select the dry limit.
[in]epsDimensionless wet-area regularization floor in [0,1); nonpositive selects the exact closure.
Returns
Free surface, m. The upper branch returns the last safeguarded Newton iterate after at most 64 iterations; there is no separate convergence status.
Note
Pure scalar host/device calculation; no allocation, retained storage, or solver state mutation.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vfrMeanDepthFromEta()

OPENSWMM_KERNEL_FN double openswmm::twoD::vfrMeanDepthFromEta ( double z1,
double z2,
double z3,
double eta,
double eps )
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.

Parameters
[in]z1Finite minimum vertex elevation, m.
[in]z2Finite middle vertex elevation, m; z1 <= z2 <= z3.
[in]z3Finite maximum vertex elevation, m.
Precondition
Elevations are already sorted; no input validation is performed.
Parameters
[in]etaFinite free-surface elevation, m in the same vertical datum.
[in]epsDimensionless wet-area regularization floor in [0,1); nonpositive selects the exact closure.
Returns
Nonnegative regularized mean depth, m; values below its dry intercept clamp to zero.
Note
Pure scalar host/device calculation; no allocation, retained storage, or solver state mutation.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vfrMeanDepthFromEtaExact()

OPENSWMM_KERNEL_FN double openswmm::twoD::vfrMeanDepthFromEtaExact ( double z1,
double z2,
double z3,
double eta )
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.

Parameters
[in]z1Finite minimum vertex elevation, m.
[in]z2Finite middle vertex elevation, m; z1 <= z2 <= z3.
[in]z3Finite maximum vertex elevation, m.
Precondition
Elevations are already sorted; no input validation is performed.
Parameters
[in]etaFinite free-surface elevation, m in the same vertical datum.
Returns
Nonnegative cell-mean depth, m, with no regularization.
Note
Pure scalar host/device calculation; no allocation, retained storage, or solver state mutation.
Here is the caller graph for this function:

◆ vfrSort3()

OPENSWMM_KERNEL_FN void openswmm::twoD::vfrSort3 ( double & z1,
double & z2,
double & z3 )
noexcept

Sort three vertex elevations in place so z1 <= z2 <= z3.

Parameters
[in,out]z1First elevation in metres; becomes the minimum.
[in,out]z2Second elevation in metres; becomes the middle value.
[in,out]z3Third elevation in metres; becomes the maximum.
Note
References must refer to distinct finite scalar values. No allocation or shared state.
Here is the caller graph for this function:

◆ vfrStageAtWetFraction()

OPENSWMM_KERNEL_FN double openswmm::twoD::vfrStageAtWetFraction ( double z1,
double z2,
double z3,
double eps )
noexcept

Stage η_s at which the wetted-area fraction equals eps (0 < eps < 1). Inputs must be sorted and non-flat (z3 − z1 ≥ kVfrFlatRelief).

Parameters
[in]z1Finite minimum vertex elevation, m.
[in]z2Finite middle vertex elevation, m; z1 <= z2 <= z3.
[in]z3Finite maximum vertex elevation, m.
Precondition
Elevations are already sorted; no input validation is performed.
Parameters
[in]epsTarget wet fraction strictly in (0,1); requires nonflat relief.
Returns
Stage in m at the requested wet fraction.
Note
Pure scalar host/device calculation; no allocation, retained storage, or solver state mutation.
Here is the caller graph for this function:

◆ vfrWetFraction()

OPENSWMM_KERNEL_FN double openswmm::twoD::vfrWetFraction ( double z1,
double z2,
double z3,
double eta )
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).

Parameters
[in]z1Finite minimum vertex elevation, m.
[in]z2Finite middle vertex elevation, m; z1 <= z2 <= z3.
[in]z3Finite maximum vertex elevation, m.
Precondition
Elevations are already sorted; no input validation is performed.
Parameters
[in]etaFinite free-surface elevation, m in the same vertical datum.
Returns
Dimensionless wetted-area fraction [0,1]; dry/flat thresholds follow kVfrFlatRelief.
Note
Pure scalar host/device calculation; no allocation, retained storage, or solver state mutation.
Here is the caller graph for this function:

◆ writeSubsurfaceSections()

void openswmm::twoD::writeSubsurfaceSections ( const SubsurfaceConfig & cfg,
const std::vector< std::string > & node_names,
const std::vector< std::string > & link_names,
std::string & out,
bool full_precision )

Append retained aquifer/ownership/boundary authoring sections in project units.

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.

Parameters
[in]cfgStable retained authored config, not the converted live kernel copy.
[in]node_namesParallel bed native names; missing authored name emits '?'.
[in]link_namesParallel conduit names; missing name emits '?'.
[in,out]outExisting text retained; sections appended with canonical grammar and spacing.
[in]full_precisionTrue uses %.17g doubles for identity/roundtrip detail; false %.6g for human-readable authoring. Neither performs unit conversion or validation.
Note
Writes ownership/boundaries even before cfg.empty early return. Omits default options, retains explicit nondefault rows, skips automatic node beds so AUTO can re-enroll them later; CELL restored one-based, boundary edge remains zero-based. Allocation can leave appended prefix. No file I/O, physical/native/clock changes; exclusive output buffer and stable authoring views.

Append retained aquifer/ownership/boundary authoring sections in project units.

  • Argument cfg (in): Stable retained authored config, not the converted live kernel copy.
  • Argument node_names (in): Parallel bed native names; missing authored name emits '?'.
  • Argument link_names (in): Parallel conduit names; missing name emits '?'.
  • Argument out (in,out): Existing text retained; sections appended with canonical grammar and spacing.
  • Argument full_precision (in): True uses %.17g doubles for identity/roundtrip detail; false %.6g for human-readable authoring. Neither performs unit conversion or validation.
    Note
    Writes ownership/boundaries even before cfg.empty early return. Omits default options, retains explicit nondefault rows, skips automatic node beds so AUTO can re-enroll them later; CELL restored one-based, boundary edge remains zero-based. Allocation can leave appended prefix. No file I/O, physical/native/clock changes; exclusive output buffer and stable authoring views.
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ kInfil2DMaxParams

int openswmm::twoD::kInfil2DMaxParams = 5
inlineconstexpr

Number of positional parameter columns carried per row. Matches the widest legacy [INFILTRATION] method (Horton: f0 fmin decay dry_time Fmax).

◆ kMaxCellVerts

int openswmm::twoD::kMaxCellVerts = 4
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).

◆ kQuadVfrZ

int openswmm::twoD::kQuadVfrZ = 6
inlineconstexpr

Number of doubles of precomputed elevation data per quad cell: two sorted sub-triangle triples.

◆ kVfrFlatRelief

double openswmm::twoD::kVfrFlatRelief = 1.0e-9
inlineconstexpr

Relief below which a cell is treated as flat (metres). Matches the guard in the pre-existing render closure (cellFreeSurfaceElevation).

◆ runtimeWaterHeatCapacity

double openswmm::twoD::runtimeWaterHeatCapacity = 4186000.0
inlineconstexpr