![]() |
OpenSWMM Engine
6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
|
Namespaces | |
| namespace | fvkernels |
| namespace | heat |
Classes | |
| class | ArdEngine |
| struct | Cell |
| struct | ClassEnables |
Allocation-free class enables for one domain — what the engines size from. n_msx is the reactions component's species count when MSX is on for the domain; msx_has_wall tells ARD / 2D that the component declares WALL species (their own fallback / warning). More... | |
| struct | Donors |
| struct | Matrix |
| class | ReactionIntegrator |
| struct | RowLayout |
| struct | RxEvalEnv |
| Evaluation environment: pre-gathered pointers, no lookups. More... | |
| struct | RxExprSpan |
| Compiled expression = span into the shared pool. len 0 ⇒ no expression. More... | |
| struct | RxStepReport |
| struct | RxSymbols |
| struct | RxToken |
| class | RxWorkspace |
| class | Tokenizer |
| Stateless multi-delimiter tokenizer for SWMM input lines. More... | |
Enumerations | |
| enum class | Domain : int { RUNOFF = 0 , GROUNDWATER = 1 , NETWORK_1D = 2 , SURFACE_2D = 3 , COUNT = 4 } |
| Rows of the matrix. Values are the C API's SWMM_TRANSPORT_DOMAIN_* codes. More... | |
| enum class | SpeciesClass : int { POLLUTANTS = 0 , MSX = 1 , AGE = 2 , TEMPERATURE = 3 , COUNT = 4 } |
| Columns of the matrix. Values are the C API's SWMM_TRANSPORT_CLASS_* codes. More... | |
| enum class | CellState : int { ENABLED = 0 , DISABLED_BY_USER = 1 , UNAVAILABLE = 2 } |
| One cell's state. Values are the C API's SWMM_TRANSPORT_* state codes. More... | |
| enum class | RxHydVar |
Functions | |
| void | warnIfFvDispersionKeyIgnored (SimulationContext &ctx) |
| bool | ardBoundariesNeedExternalVolumes (const SimulationContext &ctx) |
| void | resolveArdTransportRows (SimulationContext &ctx, std::vector< std::string > &errors) |
| void | registerArdComponent () |
| void | registerHeatComponent () |
| void | routeLegacyHeat (SimulationContext &ctx, double dt) |
| double | lidLayerHeatCapacity (const SimulationContext &ctx, const lid::LIDGroupSoA &g, std::size_t unit, int layer) noexcept |
| Heat capacity of one layer, J/m²/K over the layer's footprint. | |
| void | initLidLayerTemperature (SimulationContext &ctx, const lid::LIDSolver &solver) |
| void | setLidInflowTemperature (SimulationContext &ctx, int type_index, int unit, int subcatch, double rain_rate, double q_imperv, double q_perv, double q_runon, double lid_area) |
| void | routeLidLayerTemperature (SimulationContext &ctx, const lid::LIDSolver &solver, double dt) |
| void | addRunonTemperature (SimulationContext &ctx, int donor_sc, int receiver_sc, double q) |
Accumulate run-on temperature from donor_sc onto receiver_sc. | |
| void | addRunonTemperatureAt (SimulationContext &ctx, int receiver_sc, double q, double temp_c) |
| Accumulate run-on at an explicitly supplied temperature. | |
| void | routeSubcatchmentTemperature (SimulationContext &ctx, const runoff::RunoffSoA &soa, double dt) |
| Advance ponded subarea temperatures one runoff step. | |
| Donors | donorsFor (lid::LIDType t, bool has_soil) |
| void | layerVolumes (const lid::LIDGroupSoA &g, std::size_t ui, double(&v)[kNL]) |
| std::vector< int > | buildOffsets (const lid::LIDSolver &solver) |
Flat index of each per-type group's first unit; back() == n_units. | |
| void | routeLegacyMsx (SimulationContext &ctx, double dt) |
| bool | ardReactionsActive (const SimulationContext &ctx) |
| bool | ardHasWallSpecies (const SimulationContext &ctx) |
| void | reactArdStage (SimulationContext &ctx, double dt, double *cell_phi, const double *cell_a, const double *cell_dx, int n_cells, double *node_mass, const double *node_vol, int n_nodes, int n_pollut, int ns_total, double min_store_vol, int temp_row=-1) |
| The E4 reaction stage over one routing step. | |
| std::string | compileReactionExpression (const std::string &src, const RxSymbols &symbols, std::vector< RxToken > &pool, RxExprSpan &out, int &error_col) |
Compile src into the shared pool. | |
| double | evalReactionExpression (const std::vector< RxToken > &pool, const RxExprSpan &span, const RxEvalEnv &env) noexcept |
| Tier-1 evaluation: one pass, fixed-depth stack, allocation-free. | |
| int | reactionFunctionCount () |
| Number of built-in functions. | |
| bool | reactionFunctionInfo (int idx, const char **name, int *arity) |
Name + arity of function idx; false when out of range. | |
| int | reactionHydVarCount () |
| Number of built-in hydraulic variables. | |
| bool | reactionHydVarInfo (int idx, const char **name, const char **description) |
Name + one-line description of hydraulic variable idx. | |
| void | ensureMsxState (SimulationContext &ctx) |
| void | reactSpeciesBlock (SimulationContext &ctx, bool tank, double dt, double *species_block, const double *pollut, double hrt_seconds, double temp_c) |
| bool | legacyReactionsActive (const SimulationContext &ctx) |
| void | reactLegacyNodes (SimulationContext &ctx, double dt) |
| void | reactLegacyLinks (SimulationContext &ctx, double dt) |
| void | warnIfLegacyBindingBypassed (SimulationContext &ctx) |
| const std::vector< std::string > & | reactionSectionTags () |
| void | applyReactionSections (SimulationContext &ctx, const components::ComponentConfigSections &config, std::vector< std::string > &errors) |
| void | applyEmbeddedReactionSections (SimulationContext &ctx, bool external_component_registered, std::vector< std::string > &errors) |
| void | registerReactionsComponent () |
| bool | recompileReactionSystem (SimulationContext &ctx, std::vector< std::string > &errors) |
| std::string | serializeReactionSystem (const SimulationContext &ctx) |
| std::string | serializeWaterAgeConfig (const SimulationContext &ctx) |
| void | registerWaterAgeComponent () |
| void | routeLegacyAge (SimulationContext &ctx, double dt) |
| void | initLidLayerAge (SimulationContext &ctx, const lid::LIDSolver &solver) |
| void | setLidInflowAge (SimulationContext &ctx, int type_index, int unit, int subcatch, double rain_rate, double q_imperv, double q_perv, double q_runon, double lid_area) |
| void | routeLidLayerAge (SimulationContext &ctx, const lid::LIDSolver &solver, double dt) |
Advance the per-layer ages one runoff step, after LIDSolver::execute. | |
| void | addRunonAge (SimulationContext &ctx, int donor_sc, int receiver_sc, double q) |
| void | routeSubcatchmentAge (SimulationContext &ctx, const runoff::RunoffSoA &soa, double dt) |
| double | arrivingPrecipRate (const SimulationContext &ctx, std::size_t ui, int subarea) noexcept |
| Net precipitation actually reaching one subarea this step [ft/s]. | |
| double | arrivingMeltFraction (const SimulationContext &ctx, std::size_t ui, int subarea) noexcept |
| Fraction of the arriving water that is MELTWATER, in [0, 1]. | |
| double | arrivingPrecipTemperature (const SimulationContext &ctx, std::size_t ui, int subarea) noexcept |
| Temperature of the water arriving at one subarea [°C] (S2). | |
| double | arrivingPrecipAge (const SimulationContext &ctx, std::size_t ui, int subarea) noexcept |
| Water age of the water arriving at one subarea [seconds] (S2b). | |
| double | initialAgeSecondsFor (const SimulationContext &ctx, bool is_link, int idx, double fallback) |
Per-element initial age (SECONDS) for one node/link, falling back to fallback (normally the INITIAL_STATE global) when no [INITIAL_QUALITY] row targets the element. Later rows win. | |
| double | initialTempFor (const SimulationContext &ctx, bool is_link, int idx, double fallback) |
Per-element initial temperature (degC) for one node/link, falling back to fallback (normally the INITIAL_STATE global). | |
| void | applyInitialAgeOverrides (SimulationContext &ctx) |
| Apply WATER_AGE rows onto water_age_state.node_age/link_age (hours -> seconds). No-op when a hotstart state is loaded (D-IQ7) or the arrays are unsized. | |
| void | applyInitialTempOverrides (SimulationContext &ctx) |
| Apply TEMPERATURE rows onto heat_state.node_temp/link_temp (degC). No-op on unsized arrays. | |
| bool | initialQualityHasMsxRow (const SimulationContext &ctx, bool is_link, int elem_idx, int species) |
| std::vector< std::string > | mirrorInitialQualityMsxRows (SimulationContext &ctx) |
| ClassEnables | network1DEnables (const SimulationContext &ctx) noexcept |
| 1D network enables: LEGACY / ARD / LARD all size from this. | |
| ClassEnables | surface2DEnables (const SimulationContext &ctx) noexcept |
| RowLayout | canonicalRows (const SimulationContext &ctx, const ClassEnables &e) |
| Matrix | resolve (const SimulationContext &ctx) |
| Build the full matrix (states + reasons). Pure: never writes warnings. | |
| const char * | domainName (Domain d) noexcept |
| const char * | speciesClassName (SpeciesClass c) noexcept |
| const char * | cellStateName (CellState s) noexcept |
| std::string | formatReportBlock (const Matrix &m) |
Variables | |
| constexpr int | kNL = LidLayerSpeciesState::kLayerCount |
| constexpr int | kExternal = -1 |
| -1 means "external to the unit"; -2 means "this type has no such layer". | |
| constexpr int | kAbsent = -2 |
| constexpr int | kSurf = static_cast<int>(LidLayer::SURFACE) |
| constexpr int | kPave = static_cast<int>(LidLayer::PAVEMENT) |
| constexpr int | kSoil = static_cast<int>(LidLayer::SOIL) |
| constexpr int | kStor = static_cast<int>(LidLayer::STORAGE) |
| constexpr int | kSubIMPERV0 = 0 |
| constexpr int | kSubIMPERV1 = 1 |
| constexpr int | kSubPERV = 2 |
| constexpr double | kMeltwaterTempC = 0.0 |
| constexpr int | kRxMaxStackDepth |
|
strong |
|
strong |
|
strong |
Hydraulic variables available in reaction expressions (reactions plan §2; engines populate the evaluation environment at R6). Order is the ABI of the evaluator's hydvar array.
|
strong |
| void openswmm::transport::addRunonAge | ( | SimulationContext & | ctx, |
| int | donor_sc, | ||
| int | receiver_sc, | ||
| double | q ) |
Accumulate run-on age-volume from a donor subcatchment to its receiver. Called from the run-on assembly beside the flow it mirrors.
| void openswmm::transport::addRunonTemperature | ( | SimulationContext & | ctx, |
| int | donor_sc, | ||
| int | receiver_sc, | ||
| double | q ) |
Accumulate run-on temperature from donor_sc onto receiver_sc.
The RATE convention every loader uses: donors add q · T, the consumer divides by the total rate. Mirrors addRunonAge, and must be called at every contributor to runon_inflow — the subcatchment cascade, the LID underdrain return, and the outfall return. A3 filled this numerator from one of the three and divided by all three, which produced arriving water younger than anything entering the model. The temperature analogue of that defect is quieter and worse: a missing contributor pulls the arriving temperature toward 0 °C, which is a plausible number.
| q | Volumetric flow rate, ft³/s. |
| void openswmm::transport::addRunonTemperatureAt | ( | SimulationContext & | ctx, |
| int | receiver_sc, | ||
| double | q, | ||
| double | temp_c ) |
Accumulate run-on at an explicitly supplied temperature.
For contributors whose donor is not another subcatchment: the outfall return (which carries heat_state.node_temp) and, from H5b, the LID underdrain. Adds to the numerator and the rate together — the pairing is why this is one function and not two array writes at each call site.
| q | Volumetric flow rate, ft³/s. |
| temp_c | Temperature of that flow, °C. |
| void openswmm::transport::applyEmbeddedReactionSections | ( | SimulationContext & | ctx, |
| bool | external_component_registered, | ||
| std::vector< std::string > & | errors ) |
Embedded fallback (called from SWMMEngine::open after component resolution): if [REACTION_*] sections were found in the legacy .inp, apply them with a style warning — unless an external reactions component was registered, in which case the external file wins wholesale and the embedded sections are reported ignored.
|
inline |
Apply WATER_AGE rows onto water_age_state.node_age/link_age (hours -> seconds). No-op when a hotstart state is loaded (D-IQ7) or the arrays are unsized.
|
inline |
Apply TEMPERATURE rows onto heat_state.node_temp/link_temp (degC). No-op on unsized arrays.
| void openswmm::transport::applyReactionSections | ( | SimulationContext & | ctx, |
| const components::ComponentConfigSections & | config, | ||
| std::vector< std::string > & | errors ) |
Parse + validate a set of reaction sections into ctx.reactions and the species registry. Shared by the component apply hook (external file) and the embedded fallback. Diagnostics are appended to errors (fatal).
| bool openswmm::transport::ardBoundariesNeedExternalVolumes | ( | const SimulationContext & | ctx | ) |
True when the external-load loaders must run even though the model has no pollutants: a [TRANSPORT_BOUNDARIES] row injects qual_vol_in * concentration, and qual_vol_in is accumulated by those loaders. Without this an MSX-ONLY model — the nh2cl shape, and the one E5a exists to enable — assembles no inflow volume and its boundary delivers exactly nothing.
| bool openswmm::transport::ardHasWallSpecies | ( | const SimulationContext & | ctx | ) |
True when any declared MSX species is WALL — unsupported under the ARD engine (no transport semantics for attached species yet); the engine falls back to LEGACY, whose R4 binding runs them element-locally.
| bool openswmm::transport::ardReactionsActive | ( | const SimulationContext & | ctx | ) |
True when the reactions component is active (configured + compiled) — the ARD engine's condition for carrying MSX species on the mesh.
|
noexcept |
Fraction of the arriving water that is MELTWATER, in [0, 1].
Under a pack the arriving water is two different waters: meltwater, and rain that reached the ground through the snow-free fraction. arrivingPrecipRate returns their sum, and a sum cannot say what either is worth — this is the split.
Returns 0 wherever there is no pack, IGNORE_SNOWMELT is on, or nothing arrived, so a caller can blend unconditionally and a bare deck is bit-identical to its pre-S2 behaviour.
|
noexcept |
Water age of the water arriving at one subarea [seconds] (S2b).
The age analogue of arrivingPrecipTemperature, and it uses the same arrivingMeltFraction — not an equivalent expression, the same call. Under a pack the arriving water is meltwater carrying the pack's residence time plus rain that reached the ground through the snow-free fraction carrying the configured WaterAgeSource::RAINFALL age:
a = (1 − f)·a_rain + f·a_pack
If the two tracks ever computed f separately they could drift, and the drift would be invisible: both answers stay inside their brackets, and only a deck comparing arriving age against arriving temperature could see it. One call is what makes that unrepresentable.
snow_melt_age_*, published beside snow_melt_* under the identical area blend. It is NOT the age of the water still in the pack — a pack that empties this step publishes the age its water HAD, which the remaining-water age cannot express because there is none.IGNORE_SNOWMELT is on, nothing arrived, or the pack published no melt — so a caller blends unconditionally and a bare deck is bit-identical to its pre-S2b behaviour.
|
noexcept |
Net precipitation actually reaching one subarea this step [ft/s].
This is the mixing volume, and it is not always the rainfall.
`ctx.subcatches.rainfall` is set once, at `Runoff.cpp:294-295`,
to `rain + SNOWFALL`, and never updated. On a subcatchment with a
snowpack the runoff solver does not use it: it uses
`snow_net_imperv` for IMPERV0/IMPERV1 and `snow_net_perv` for
PERV (`Runoff.cpp:548-552`), each built as
`imelt + rainfall·(1 − asc)` — **melt, plus the rain falling on
the snow-free fraction** (`SWMMEngine.cpp:1608-1616`).
Reading the rainfall field on such a deck is wrong twice over:
- **snowfall is counted as arriving liquid**, so water being
stored in the pack is mixed into the surface as though it had
landed, and
- **snowmelt is not counted at all**, so the water that genuinely
arrives is invisible to the mixing volume and the surface ages
as if nothing arrived.
The second of those is A3's own net-gain failure (lessons 64, 68)
reappearing through a different field: the mixing volume is again
not the arriving volume. They do not cancel — they are displaced
by the whole residence time of the pack, which is precisely the
quantity a snow-aware age model exists to measure.
-1.0 sentinel is the whole guardsnow_net_* initialise to -1.0 (SubcatchData.hpp:642), and the solver's own test is >= 0.0 (Runoff.cpp:551-552). A subcatchment with a pack but no melt this step publishes 0.0, which is a real rate; only the negative sentinel means "no pack, use the gage". This function mirrors that test exactly rather than inventing its own.Runoff.cpp:548's !ctx.options.ignore_snow_melt and legacy subcatch.c:784.| subarea | One of kSubIMPERV0 / kSubIMPERV1 / kSubPERV. |
|
noexcept |
Temperature of the water arriving at one subarea [°C] (S2).
Meltwater is at 0 °C essentially by definition — that is what melting means — so the arriving temperature is the melt fraction blended against the configured HeatSource::RAINFALL value:
T = (1 − f)·T_rain + f·0
On a winter deck this is not a small approximation to make: it is the difference between a stream fed by snowmelt and one fed by rain. Unlike the age half, it needs no pack state at all — the freezing point is not something the pack has to remember.
| std::vector< int > openswmm::transport::buildOffsets | ( | const lid::LIDSolver & | solver | ) |
Flat index of each per-type group's first unit; back() == n_units.
| RowLayout openswmm::transport::canonicalRows | ( | const SimulationContext & | ctx, |
| const ClassEnables & | e ) |
|
noexcept |
| std::string openswmm::transport::compileReactionExpression | ( | const std::string & | src, |
| const RxSymbols & | symbols, | ||
| std::vector< RxToken > & | pool, | ||
| RxExprSpan & | out, | ||
| int & | error_col ) |
Compile src into the shared pool.
| error_col | [out] 1-based column of the offending token on failure. |
|
noexcept |
| Donors openswmm::transport::donorsFor | ( | lid::LIDType | t, |
| bool | has_soil ) |
| void openswmm::transport::ensureMsxState | ( | SimulationContext & | ctx | ) |
Lazily size + seed the MSX element state; warn once about the R4b transport limitation when any RATE MSX species exists in either scope (LEGACY only — under LARD the species ride the segments as of L3).
L3: lazily size + seed the MSX element state (GLOBAL fill + [REACTION_QUALITY] overrides). Shared by the LEGACY dispatch and the LARD engine's init — one seeding spelling for both engines.
|
noexcept |
Tier-1 evaluation: one pass, fixed-depth stack, allocation-free.
| std::string openswmm::transport::formatReportBlock | ( | const Matrix & | m | ) |
The .rpt block: a fixed-width table, one line per domain, one column per class, each cell "on(n)" / "off:KEY" / "n/a:reason". Ends with '
'.
|
inline |
Per-element initial age (SECONDS) for one node/link, falling back to fallback (normally the INITIAL_STATE global) when no [INITIAL_QUALITY] row targets the element. Later rows win.
| bool openswmm::transport::initialQualityHasMsxRow | ( | const SimulationContext & | ctx, |
| bool | is_link, | ||
| int | elem_idx, | ||
| int | species ) |
True when ctx.initial_quality carries an MSX row for (is_link, elem, species) — the ReactionsWriter's "already written elsewhere" test.
|
inline |
Per-element initial temperature (degC) for one node/link, falling back to fallback (normally the INITIAL_STATE global).
| void openswmm::transport::initLidLayerAge | ( | SimulationContext & | ctx, |
| const lid::LIDSolver & | solver ) |
Size the per-layer block against the model's LID units and seed the layers that already hold water at t = 0. Idempotent; safe to call once the LID manager has built its groups.
| void openswmm::transport::initLidLayerTemperature | ( | SimulationContext & | ctx, |
| const lid::LIDSolver & | solver ) |
Size the shared layer block if needed and seed the TEMPERATURE row from HeatSource::INITIAL_STATE. Independent of initLidLayerAge: either may run first, neither wipes the other (LidLayerSpeciesState::ensureSized).
| void openswmm::transport::layerVolumes | ( | const lid::LIDGroupSoA & | g, |
| std::size_t | ui, | ||
| double(&) | v[kNL] ) |
Void-weighted water held in each layer, as a depth per unit area (ft). The four terms are exactly those LIDSolver::storedVolume() sums, so a layer's age is weighted by the same water the mass balance counts.
Void-weighted water held in each layer, as a depth per unit area (ft). The four terms are exactly those LIDSolver::storedVolume() sums.
| bool openswmm::transport::legacyReactionsActive | ( | const SimulationContext & | ctx | ) |
True when the reactions component is active (configured + compiled) — the QualitySolver's branch condition.
|
noexcept |
Heat capacity of one layer, J/m²/K over the layer's footprint.
Exported so a gate can sum a column's heat content and assert conservation WITHOUT restating the water/matrix mixture — a second copy of it in the test would make the gate agree with itself rather than with the code. Zero for an absent layer.
| std::vector< std::string > openswmm::transport::mirrorInitialQualityMsxRows | ( | SimulationContext & | ctx | ) |
Mirror every MSX-kind [INITIAL_QUALITY] row into ctx.reactions.init_elem_* (upsert; a conflicting .rxn row is reported). Returns the diagnostics (empty on success).
|
noexcept |
1D network enables: LEGACY / ARD / LARD all size from this.
| void openswmm::transport::reactArdStage | ( | SimulationContext & | ctx, |
| double | dt, | ||
| double * | cell_phi, | ||
| const double * | cell_a, | ||
| const double * | cell_dx, | ||
| int | n_cells, | ||
| double * | node_mass, | ||
| const double * | node_vol, | ||
| int | n_nodes, | ||
| int | n_pollut, | ||
| int | ns_total, | ||
| double | min_store_vol, | ||
| int | temp_row = -1 ) |
The E4 reaction stage over one routing step.
| cell_phi | ARD cell state, species-major [s * n_cells + c]; rows 0..n_pollut-1 are pollutants, rows n_pollut.. are the MSX species in ReactionData order. |
| cell_a | Cell areas (read-only; dry cells still react — their carried concentration evolves like LEGACY's, and holds negligible mass). |
| cell_dx | Cell lengths (read-only; E5b — with cell_a they give the water volume each kdecay concentration change acts on, so the removed pollutant mass books into the qual_routing_reacted ledger row). |
| node_mass | Node-store species MASS [nd * ns_total + s]. |
| node_vol | Node-store water volume [nd]. |
| n_pollut | Pollutant row count (may be 0 — MSX-only model). |
| ns_total | Total species rows (n_pollut + rx.n_species() when the component is active, else n_pollut). |
| min_store_vol | Below this volume a store has no meaningful concentration: MSX tank integration is skipped there (mass-form kdecay still applies). |
| int openswmm::transport::reactionFunctionCount | ( | ) |
Number of built-in functions.
| bool openswmm::transport::reactionFunctionInfo | ( | int | idx, |
| const char ** | name, | ||
| int * | arity ) |
Name + arity of function idx; false when out of range.
| int openswmm::transport::reactionHydVarCount | ( | ) |
Number of built-in hydraulic variables.
| bool openswmm::transport::reactionHydVarInfo | ( | int | idx, |
| const char ** | name, | ||
| const char ** | description ) |
Name + one-line description of hydraulic variable idx.
| const std::vector< std::string > & openswmm::transport::reactionSectionTags | ( | ) |
The 12 [REACTION_*] tags (upper-case, no brackets) — shared by the embedded-fallback handlers and the config parser.
| void openswmm::transport::reactLegacyLinks | ( | SimulationContext & | ctx, |
| double | dt ) |
Link-side step: exact-exponential pollutant decay + MSX pipe-scope integration. Runs AFTER updateLinkQuality() (whose internal linear decay is zeroed when reactions are active), so the reacted concentrations are not overwritten by the mixing pass.
| void openswmm::transport::reactLegacyNodes | ( | SimulationContext & | ctx, |
| double | dt ) |
Node-side step: exact-exponential pollutant decay + MSX tank-scope integration. Runs where applyDecay() ran (before updateLinkQuality).
| void openswmm::transport::reactSpeciesBlock | ( | SimulationContext & | ctx, |
| bool | tank, | ||
| double | dt, | ||
| double * | species_block, | ||
| const double * | pollut, | ||
| double | hrt_seconds, | ||
| double | temp_c = std::numeric_limits< double >::quiet_NaN() ) |
L3: integrate ONE species block in place over dt through the shared integrator. pollut may be null (no pollutant context); tank selects tank-scope expressions; hrt_seconds feeds RxHydVar::HRT and temp_c feeds RxHydVar::TEMP (NaN ⇒ the [REACTION_OPTIONS] TEMPERATURE constant). On an integrator failure the block is left unchanged and the once-per-run failure warning fires — the reactElements contract.
| bool openswmm::transport::recompileReactionSystem | ( | SimulationContext & | ctx, |
| std::vector< std::string > & | errors ) |
Recompile every reaction expression (terms, pipes, tanks) into a fresh flat token pool from the sources in ctx.reactions (E-C2: the one compile path, shared by the file apply and the CRUD API's eager validation — D-RC4, no second compiler). Returns true and sets rx.compiled on success; on failure appends diagnostics and leaves rx.compiled false (the pool/spans hold the partial result — callers roll back or clear).
| void openswmm::transport::registerArdComponent | ( | ) |
Register org.hydrocouple.openswmm.transport.ard with the process-component registry (idempotent; called from SWMMEngine::open before resolution, next to registerReactionsComponent).
| void openswmm::transport::registerHeatComponent | ( | ) |
Register org.hydrocouple.openswmm.heat with the process-component registry (idempotent; called from SWMMEngine::open before resolution).
| void openswmm::transport::registerReactionsComponent | ( | ) |
Register org.hydrocouple.openswmm.reactions with the process-component registry (idempotent; called from SWMMEngine::open before resolution).
| void openswmm::transport::registerWaterAgeComponent | ( | ) |
Register org.hydrocouple.openswmm.waterage with the process-component registry (idempotent; called from SWMMEngine::open before resolution).
| Matrix openswmm::transport::resolve | ( | const SimulationContext & | ctx | ) |
Build the full matrix (states + reasons). Pure: never writes warnings.
| void openswmm::transport::resolveArdTransportRows | ( | SimulationContext & | ctx, |
| std::vector< std::string > & | errors ) |
E5a: resolve the raw [TRANSPORT_BOUNDARIES]/[TRANSPORT_SOURCES] rows to node/link/species/timeseries indices. Called from SWMMEngine::open AFTER all process components (and the embedded reactions fallback) have applied, because the rows name MSX species and the reactions component may apply before or after transport.ard in file order. Pushes fatal diagnostics into errors; pollutant species are refused (their loading surface is the legacy pathways). Source VALUE rates convert from species mass/s to internal conc·ft³/s here (kLitersPerFt3).
| void openswmm::transport::routeLegacyAge | ( | SimulationContext & | ctx, |
| double | dt ) |
One LEGACY age routing step (call at the END of QualitySolver::execute, after qual_vol_in is fully accumulated). No-op when WATER_AGE is off.
| void openswmm::transport::routeLegacyHeat | ( | SimulationContext & | ctx, |
| double | dt ) |
One LEGACY temperature routing step (call at the END of QualitySolver::execute, after qual_vol_in is fully accumulated). No-op when HEAT_TRANSPORT is off.
| void openswmm::transport::routeLegacyMsx | ( | SimulationContext & | ctx, |
| double | dt ) |
Advect the MSX element state one routing step on the LEGACY CSTR path. No-op unless a reaction system with at least one species is configured.
| void openswmm::transport::routeLidLayerAge | ( | SimulationContext & | ctx, |
| const lid::LIDSolver & | solver, | ||
| double | dt ) |
Advance the per-layer ages one runoff step, after LIDSolver::execute.
| void openswmm::transport::routeLidLayerTemperature | ( | SimulationContext & | ctx, |
| const lid::LIDSolver & | solver, | ||
| double | dt ) |
Advance every LID column one runoff step: advective mixing per layer, then one coupled thermal solve over the stack. Publishes the underdrain temperature, retiring HeatSource::RAINFALL's "(and LID drains until
H5)" marker.
< holds or receives WATER → advection
< has THERMAL MASS → conduction, policy
| void openswmm::transport::routeSubcatchmentAge | ( | SimulationContext & | ctx, |
| const runoff::RunoffSoA & | soa, | ||
| double | dt ) |
One runoff-step update of the subarea ages and the published runoff age. Call immediately AFTER the runoff solver has stepped, so the depths are this step's. No-op when WATER_AGE is off.
| void openswmm::transport::routeSubcatchmentTemperature | ( | SimulationContext & | ctx, |
| const runoff::RunoffSoA & | soa, | ||
| double | dt ) |
Advance ponded subarea temperatures one runoff step.
Per subarea, in order: apply the surface energy balance to the water that was already there, mix in what arrived by GROSS inflow volume, then publish the subcatchment's runoff temperature as the volume-weighted mean of the subareas holding water. Outflow leaves at the subarea's own temperature, so only the inflow is needed — the same complete-mix argument A3 arrived at after its net-gain estimate proved to be a 6.3× defect.
| soa | The solver's own SoA. ctx.subcatches.ponded_depth is declared but written by nobody; reading it would give zeros. |
| dt | Runoff timestep, seconds. |
| std::string openswmm::transport::serializeReactionSystem | ( | const SimulationContext & | ctx | ) |
Canonical .rxn text for the current reaction system (empty system -> a header comment plus an empty [REACTION_SPECIES] shell is NOT emitted; the result is an empty string when nothing is configured).
| std::string openswmm::transport::serializeWaterAgeConfig | ( | const SimulationContext & | ctx | ) |
Render [WATER_AGE_SOURCES] from the live config in FILE units (HOURS, shortest-exact) — the single spelling shared by the ComponentConfigSave hook and swmm_water_age_save (IO3c), the same sharing the reactions component has with serializeReactionSystem. Empty when the component never applied (save DECLINES → the carry-alongside copy runs).
| void openswmm::transport::setLidInflowAge | ( | SimulationContext & | ctx, |
| int | type_index, | ||
| int | unit, | ||
| int | subcatch, | ||
| double | rain_rate, | ||
| double | q_imperv, | ||
| double | q_perv, | ||
| double | q_runon, | ||
| double | lid_area ) |
Flow-weighted age of the water arriving at each LID unit this step, stored into ctx.lid_layer_state.inflow_value. Called where LIDGroupSoA::inflow is assembled, because that is the only place the contributing rates (rain, captured impervious and pervious runoff, whole-subcatchment run-on) exist together.
| void openswmm::transport::setLidInflowTemperature | ( | SimulationContext & | ctx, |
| int | type_index, | ||
| int | unit, | ||
| int | subcatch, | ||
| double | rain_rate, | ||
| double | q_imperv, | ||
| double | q_perv, | ||
| double | q_runon, | ||
| double | lid_area ) |
Temperature of the water arriving at one unit this step, flow-weighted over the same four rates setLidInflowAge weights. Mirrors it exactly, including its hard-won choice to take the SUBCATCHMENT's published runoff value rather than reconstructing a mean from the subarea rows.
|
noexcept |
|
noexcept |
2D surface enables: the 1D rule plus the [2D_OPTIONS] TRANSPORT_* keys. Age and temperature are NOT gated by IGNORE_QUALITY here (pre-E2 rule: "IGNORE_QUALITY turns off the pollutant and MSX rows only").
| void openswmm::transport::warnIfFvDispersionKeyIgnored | ( | SimulationContext & | ctx | ) |
Warn when [OPTIONS] FV_DISPERSION is set under QUALITY_SOLVER EULERIAN_ARD. The component's own bypass warnings only cover models that HAVE a transport.ard file; this is the reverse case — the user spelled dispersion the familiar way, selected the engine that now supports it, and got nothing. FV_DISPERSION reaches no solver today (WARN 105 says so under FLOW_ROUTING FV, and nothing says it under DYNWAVE), so E3's arrival is what makes the silence misleading rather than merely inert.
| void openswmm::transport::warnIfLegacyBindingBypassed | ( | SimulationContext & | ctx | ) |
Warn (once, at open) when a reactions component is configured but no engine will run it this simulation. As of E4/R6 the only remaining bypass is IGNORE_QUALITY — EULERIAN_ARD now runs its own binding (ReactionArdBinding) with MSX species transported on the mesh. Without this a user who wrote a .rxn file gets a run in which nothing reacted and nothing said so.
|
constexpr |
|
constexpr |
-1 means "external to the unit"; -2 means "this type has no such layer".
|
inlineconstexpr |
The temperature meltwater leaves a pack at, °C. Zero, and named rather than written as a literal so a gate can assert against the constant the code uses instead of against a number a reader hopes it uses.
|
constexpr |
|
constexpr |
|
inlineconstexpr |
Maximum operand-stack depth; the compiler rejects deeper expressions so the evaluator's fixed stack can never overflow.
|
constexpr |
|
constexpr |
|
constexpr |
Subarea ordering shared by SubArea (A3) and HeatSubArea (H5a). Both enums are deliberately separate types; this is the ordinal they agree on.
|
constexpr |
|
constexpr |
|
constexpr |