![]() |
OpenSWMM Engine
6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
|
Species mass in both aquifer zones, and where mass crossed a boundary. More...
#include <SubsurfaceTransportState.hpp>
Public Member Functions | |
| bool | signedRow (int s) const noexcept |
| A row whose mass may legitimately be negative — the temperature row (°C·m³ below zero is a state, not an error), so no clamp applies. | |
| int | rowIndex (std::string_view name) const noexcept |
Row index of a species by name, or −1 — the [GW_*] sections address species by name and resolve through this. | |
| std::size_t | layerIdx (int s, int j, int c) const noexcept |
| < layerIdx | |
| void | refreshUnsat (int s, int c) noexcept |
| Refresh one derived unsaturated bulk inventory from canonical layers. | |
| double | dissolvedFraction (int s, int c, double theta) const noexcept |
The share of a cell's stored mass that is DISSOLVED and therefore mobile: 1 / R with the retardation factor R = 1 + ρ_b·K_d/θ. Age and temperature never sorb — they are properties of the water, not solutes — so they are always fully mobile. | |
| bool | active () const noexcept |
| Test whether the subsurface transport layout is nonempty. | |
| std::size_t | idx (int s, int c) const noexcept |
| Map a species/cell pair into bulk species-major storage. | |
| std::size_t | lateralIndex (int species, std::size_t edge) const noexcept |
| Index a lateral species packet in edge-major owned storage. Requires valid species/edge indices and coherent model-derived extents. No ordering, inventory, allocation or validation side effect. | |
| void | resize (int n_spec, int n_cell, int n_edges) |
| Allocate/reset the core two-zone transport arrays and ledgers. | |
| void | clear () |
| Reset the complete subsurface transport state to empty defaults. | |
| double | inFlight1D (int s) const noexcept |
T7.4: mass in flight on the two 1D seams — booked by the producer, not yet taken by the owner. Part of storage, for the same reason the surface accumulators are. | |
| double | storage (int s) const noexcept |
Everything the aquifer HOLDS of one species, including mass in flight in a side accumulator (the water's liveStorage rule). | |
| double | ledgeredStorage (int s) const noexcept |
The storage the LEDGER can account for: holdings less the two surface accumulators, which are always one firing out of phase with gained_infil (booked when the cell gathers) and lost_dunne (booked when the cell pushes). The water side's ledgeredStorage makes the identical exclusion for the identical reason — the two pending terms cancel on both sides of the balance. | |
| double | continuityDenominator (int s) const noexcept |
T7.4 (2026-09-21): the scale a residual is judged against — what the aquifer started with plus every route mass can arrive by. It lives here, beside residual(), because the two must name the same channels: T7.4 added the node and link seams as routes and the .rpt block's own copy of this sum was not updated, so a deck fed only through its beds divided a machine-precision residual by a machine-precision denominator and printed 6 198 889.840 % beside an exact balance. One definition, one place to add a channel to. | |
| double | residual (int s) const noexcept |
T7.1's conservation statement, the twin of SurfaceTransportState::totalIncludingLedgers: what the aquifer holds now, plus everything that left, minus everything that arrived, equals what it started with. Zero to machine precision for a conserving kernel — GW plan gate 6's stub. | |
Public Attributes | |
| double | c_diff = 0.4 |
| explicit solute diffusion safety factor | |
| int | n_species = 0 |
| int | n_cells = 0 |
| int | n_pollut = 0 |
| int | n_msx = 0 |
| int | age_row = -1 |
| int | temp_row = -1 |
| std::vector< std::string > | row_names |
| std::vector< double > | sat_mass |
| [s*n_cells+c] in the saturated water | |
| std::vector< double > | unsat_mass |
| [s*n_cells+c] in the column store | |
| int | n_layers = 0 |
| std::vector< double > | layer_mass |
| [(s*n_cells+c)*n_layers+j] | |
| std::vector< double > | contact_water |
| [j*n_cells+c], SI m3 | |
| std::vector< double > | contact_node_out |
| std::vector< double > | contact_link_out |
| gross promised water, per bed/cell | |
| std::vector< double > | contact_node_mass |
| std::vector< double > | contact_link_mass |
| std::vector< double > | alpha_L |
[GW_TRANSPORT_PARAMS] per cell, after * < TAG < CELL resolution. | |
| std::vector< double > | alpha_T |
| transverse dispersivity (m) | |
| std::vector< double > | D_m |
| molecular diffusivity (m²/s) | |
| std::vector< double > | rho_b |
| std::vector< double > | kd |
| std::vector< double > | decay |
| bool | dispersion_on = true |
Whether dispersion runs at all ([GW_TRANSPORT_OPTIONS] DISPERSION). | |
| long | dispersion_limiter_binds = 0 |
| std::vector< double > | sacc_L |
| std::vector< double > | sacc_R |
| std::vector< double > | xacc_from_surface |
| std::vector< double > | xacc_to_surface |
| std::vector< double > | nacc_mass |
| std::vector< double > | lacc_mass |
| std::vector< double > | lout_mass |
| std::vector< double > | link_gain_shortfall |
| std::vector< double > | node_out_mass |
| std::vector< double > | lost_deep |
| deep percolation | |
| std::vector< double > | lost_node |
| to a 1D node through its bed | |
| std::vector< double > | lost_link |
| to a gaining conduit (G-X4) | |
| std::vector< double > | lost_dunne |
| saturation excess + rejection, to the surface | |
| std::vector< double > | lost_et |
| the intensive rows ET carried off | |
| std::vector< double > | gained_infil |
| from the surface's infiltration | |
| std::vector< double > | gained_node |
| from a recharging node (T7.4 seam) | |
| std::vector< double > | gained_link |
| from a leaking conduit (T7.4 seam) | |
| std::vector< double > | net_lateral |
| net across the domain edge (0 on a closed mesh) | |
| std::vector< double > | gained_source |
| std::vector< double > | lost_source |
| wells, native concentration x m3 | |
| std::vector< double > | boundary_in |
| std::vector< double > | boundary_out |
| std::vector< double > | boundary_flux_in |
| std::vector< double > | boundary_flux_out |
| gross split of net_lateral | |
| std::vector< double > | lost_reaction |
| T7.2: first-order decay. | |
| std::vector< double > | generated_age |
| std::vector< double > | gained_contact |
| std::vector< double > | init_mass |
| std::vector< double > | internal_recharge |
Species mass in both aquifer zones, and where mass crossed a boundary.
|
inlinenoexcept |
Test whether the subsurface transport layout is nonempty.
|
inline |
Reset the complete subsurface transport state to empty defaults.
|
inlinenoexcept |
T7.4 (2026-09-21): the scale a residual is judged against — what the aquifer started with plus every route mass can arrive by. It lives here, beside residual(), because the two must name the same channels: T7.4 added the node and link seams as routes and the .rpt block's own copy of this sum was not updated, so a deck fed only through its beds divided a machine-precision residual by a machine-precision denominator and printed 6 198 889.840 % beside an exact balance. One definition, one place to add a channel to.
| [in] | s | Valid zero-based species row with coherently sized mandatory and enabled optional arrays. |
|
inlinenoexcept |
The share of a cell's stored mass that is DISSOLVED and therefore mobile: 1 / R with the retardation factor R = 1 + ρ_b·K_d/θ. Age and temperature never sorb — they are properties of the water, not solutes — so they are always fully mobile.
| [in] | s | Valid zero-based species row, unchecked. |
| [in] | c | Valid zero-based cell with rho_b and kd storage when sorption is active. |
| [in] | theta | Finite volumetric water content, dimensionless. |
|
inlinenoexcept |
Map a species/cell pair into bulk species-major storage.
| [in] | s | Valid nonnegative species row in [0,n_species). |
| [in] | c | Valid nonnegative cell in [0,n_cells). |
|
inlinenoexcept |
T7.4: mass in flight on the two 1D seams — booked by the producer, not yet taken by the owner. Part of storage, for the same reason the surface accumulators are.
| [in] | s | Valid zero-based species row with coherently sized mandatory and enabled optional arrays. |
|
inlinenoexcept |
Index a lateral species packet in edge-major owned storage. Requires valid species/edge indices and coherent model-derived extents. No ordering, inventory, allocation or validation side effect.
|
inlinenoexcept |
< layerIdx
Map a species/layer/cell triple into owned species/cell/layer storage. Layer mass and its paired node/link contact masses share this index.
| [in] | s | Valid zero-based species row. |
| [in] | j | Valid zero-based unsaturated layer in [0,n_layers), surface first. |
| [in] | c | Valid zero-based cell in [0,n_cells). |
|
inlinenoexcept |
The storage the LEDGER can account for: holdings less the two surface accumulators, which are always one firing out of phase with gained_infil (booked when the cell gathers) and lost_dunne (booked when the cell pushes). The water side's ledgeredStorage makes the identical exclusion for the identical reason — the two pending terms cancel on both sides of the balance.
| [in] | s | Valid zero-based species row with coherently sized mandatory and enabled optional arrays. |
|
inlinenoexcept |
Refresh one derived unsaturated bulk inventory from canonical layers.
| [in] | s | Valid zero-based species row. |
| [in] | c | Valid zero-based cell index. |
|
inlinenoexcept |
T7.1's conservation statement, the twin of SurfaceTransportState::totalIncludingLedgers: what the aquifer holds now, plus everything that left, minus everything that arrived, equals what it started with. Zero to machine precision for a conserving kernel — GW plan gate 6's stub.
| [in] | s | Valid zero-based species row with coherently sized mandatory and enabled optional arrays. |
|
inline |
Allocate/reset the core two-zone transport arrays and ledgers.
| [in] | n_spec | Requested species count; nonpositive clamps to zero. |
| [in] | n_cell | Requested cell count; nonpositive clamps to zero. |
| [in] | n_edges | Requested lateral-face count; nonpositive clamps to zero. |
|
inlinenoexcept |
Row index of a species by name, or −1 — the [GW_*] sections address species by name and resolve through this.
| [in] | name | Borrowed nonowning exact species name view, not retained. |
|
inlinenoexcept |
A row whose mass may legitimately be negative — the temperature row (°C·m³ below zero is a state, not an error), so no clamp applies.
| [in] | s | Valid zero-based species index; caller excludes the -1 unset sentinel. |
|
inlinenoexcept |
Everything the aquifer HOLDS of one species, including mass in flight in a side accumulator (the water's liveStorage rule).
| [in] | s | Valid zero-based species row with coherently sized mandatory and enabled optional arrays. |
| int openswmm::twoD::SubsurfaceTransportState::age_row = -1 |
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::alpha_L |
[GW_TRANSPORT_PARAMS] per cell, after * < TAG < CELL resolution.
longitudinal dispersivity (m)
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::alpha_T |
transverse dispersivity (m)
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::boundary_flux_in |
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::boundary_flux_out |
gross split of net_lateral
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::boundary_in |
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::boundary_out |
| double openswmm::twoD::SubsurfaceTransportState::c_diff = 0.4 |
explicit solute diffusion safety factor
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::contact_link_mass |
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::contact_link_out |
gross promised water, per bed/cell
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::contact_node_mass |
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::contact_node_out |
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::contact_water |
[j*n_cells+c], SI m3
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::D_m |
molecular diffusivity (m²/s)
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::decay |
| long openswmm::twoD::SubsurfaceTransportState::dispersion_limiter_binds = 0 |
T7.2 telemetry: faces whose dispersive exchange hit the limiter. A bind is not an error — it is the face telling the modeller the dispersion is under-resolved at this Δt, which is the surface's rule too (dispersion_limiter_binds).
| bool openswmm::twoD::SubsurfaceTransportState::dispersion_on = true |
Whether dispersion runs at all ([GW_TRANSPORT_OPTIONS] DISPERSION).
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::gained_contact |
explicit finite-porewater model only; empty in compatibility mode
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::gained_infil |
from the surface's infiltration
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::gained_link |
from a leaking conduit (T7.4 seam)
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::gained_node |
from a recharging node (T7.4 seam)
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::gained_source |
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::generated_age |
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::init_mass |
Mass in both stores at the start of the run — the conservation gate's reference (the aquifer is seeded from [GW_INITIAL_QUALITY]).
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::internal_recharge |
Internal, informational: the unsaturated ⇄ saturated handover. Not in the balance — both ends are inside the same cell.
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::kd |
[GW_SORPTION] per cell and species, [s*n_cells+c]: the linear partition coefficient (m³/kg — the row is L/kg and converts once) and the first-order decay constant (1/s).
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::lacc_mass |
[s * n_cells + c] mass a LEAKING conduit delivered, at the conduit's own concentration — the twin of the water's lacc.
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::layer_mass |
[(s*n_cells+c)*n_layers+j]
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::link_gain_shortfall |
[s] informational: gain mass the 1D received that the cell could not supply at its firing (its store had already been drawn below it).
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::lost_deep |
deep percolation
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::lost_dunne |
saturation excess + rejection, to the surface
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::lost_et |
the intensive rows ET carried off
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::lost_link |
to a gaining conduit (G-X4)
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::lost_node |
to a 1D node through its bed
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::lost_reaction |
T7.2: first-order decay.
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::lost_source |
wells, native concentration x m3
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::lout_mass |
[s * n_cells + c] mass a GAINING conduit already delivered to its end nodes (review, 2026-10-15), debited from the saturated store when the cell fires — the twin of the water's negative lacc. Booked into lost_link at that debit, so the aquifer ledger is unchanged in form.
| int openswmm::twoD::SubsurfaceTransportState::n_cells = 0 |
| int openswmm::twoD::SubsurfaceTransportState::n_layers = 0 |
| int openswmm::twoD::SubsurfaceTransportState::n_msx = 0 |
| int openswmm::twoD::SubsurfaceTransportState::n_pollut = 0 |
| int openswmm::twoD::SubsurfaceTransportState::n_species = 0 |
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::nacc_mass |
[s * n_beds + b] mass a RECHARGING node pushed down its bed, sampled at the node's own concentration at tier-0 cadence and gathered by the cell when it fires — the twin of the water's nacc.
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::net_lateral |
net across the domain edge (0 on a closed mesh)
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::node_out_mass |
[s * n_nodes] mass the aquifer owes each 1D node, booked at the cell's firing and flushed by the router into the node's coupling queues. Reset per routing batch, exactly as node_exchange_vol_ is.
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::rho_b |
bulk density ρ_s(1 − θ_s) (kg/m³)
| std::vector<std::string> openswmm::twoD::SubsurfaceTransportState::row_names |
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::sacc_L |
Lateral Darcy face sides, [e*n_species + s] — the twin of eacc_L/eacc_R, gathered by the owning cell at ITS firing (GW plan §3.1).
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::sacc_R |
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::sat_mass |
[s*n_cells+c] in the saturated water
| int openswmm::twoD::SubsurfaceTransportState::temp_row = -1 |
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::unsat_mass |
[s*n_cells+c] in the column store
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::xacc_from_surface |
[s*n_cells+c] mass the SURFACE handed down with its infiltration, gathered when the GW cell fires — the twin of xacc_from_surface.
| std::vector<double> openswmm::twoD::SubsurfaceTransportState::xacc_to_surface |
…and the mass owed back to the surface with saturation excess and column rejection — the twin of xacc_to_surface, drained by the surface cell.