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

The two-zone kernel. Owned by SurfaceRouter2D; driven by the marcher's tier hooks. More...

#include <SubsurfaceSolver.hpp>

Collaboration diagram for openswmm::twoD::SubsurfaceSolver:

Classes

struct  LidBedDiagnostic
 
struct  NodeWaterBudget
 
struct  PendingLidBed
 

Public Member Functions

std::string initialize (const MeshData &mesh, const InertialEdges &edges, const SolverOptions2D &opts, const GwUnitFactors &uf, int n_nodes, SubsurfaceConfig &cfg, std::vector< std::string > &warnings)
 Resolve the authored rows onto cells, seed state, size the accumulators.
 
void bookSurfaceEt (int cell, double dt, double potential_rate, double actual_surface_volume)
 One surface interval: reserve actual pond evaporation first. No forcing refresh resets this budget.
 
void bookAreaEt (int cell, double dt, double potential, double owner_evaporation, double soil_demand)
 SI completed footprint volumes, already paid by their surface/LID owners. Only soil_demand may reach this cell's extraction site; the rest expires.
 
bool active () const noexcept
 Read whether the resolved groundwater kernel is active.
 
void setRechargeBackend (GwRechargeBackend backend)
 Replace the owned optional pure raw-recharge evaluator descriptor.
 
const GwRechargeBackend & rechargeBackend () const noexcept
 Borrow the current optional raw-recharge extension descriptor.
 
uint64_t rechargeBatches () const noexcept
 Read successful validated raw-recharge extension batch evaluations.
 
uint64_t rechargeCells () const noexcept
 Read the cumulative raw-recharge input rows accepted from successful extension batches.
 
int rechargeThreads () const noexcept
 Query the extension's recorded worker-team size when that callback exists.
 
const std::vector< uint8_t > & coverage () const noexcept
 Mesh mode: 1 where a [2D_AQUIFER] row (*, TAG or CELL) covers the cell. An uncovered cell has no aquifer: no storage, no lateral faces, and its infiltration stays with the surface model. All 1 in PER_SUBCATCH mode.
 
bool covers (int cell) const noexcept
 Test resolved aquifer coverage with an index guard.
 
SubsurfaceState & state () noexcept
 Borrow mutable canonical SI hydraulic state and accumulators.
 
const SubsurfaceState & state () const noexcept
 Borrow read-only canonical SI hydraulic state and accumulators.
 
SubsurfaceTransportState & transport () noexcept
 The transported tuple, sized from TransportPolicy at initTransport and inert (active() == false) until then.
 
const SubsurfaceTransportState & transport () const noexcept
 Borrow read-only native species/age/temperature transport inventories and ledgers.
 
GroundHeatState & heat () noexcept
 Borrow mutable prepared physical-layer thermal and porewater owner.
 
const GroundHeatState & heat () const noexcept
 Borrow read-only prepared physical-layer thermal and porewater owner.
 
double pendingHeat (int cell) const noexcept
 Read signed unconsumed lateral physical heat for a cell.
 
std::string initHeat (SimulationContext &, const GwTransportData &)
 Initialize canonical porous thermal layers and paired producer/lateral receipt storage.
 
std::string initPorewater ()
 Initialize canonical native inventories on fixed physical porous thermal layers.
 
std::string refreshSigmaPorewater (int cell)
 Rebuild fixed-depth porewater overlap/reservations from accepted SIGMA state.
 
void refreshSigmaPorewaterReservations (int cell) noexcept
 Refresh one cell's physical/SIGMA outgoing reservation view without propagating exceptions.
 
std::string refreshPorewaterContactLedger ()
 Rebuild the signed soil-side contact receipt from the canonical layer increments after the mesh/channel synchronization has settled.
 
void initTransport (const RowLayoutLite &rows, const GwTransportData *gw, const std::vector< double > &pollut_decay, std::vector< std::string > &warnings)
 Size the rows and seed both stores from [GW_INITIAL_QUALITY]. Separate from initialize because the row layout needs the resolved [GW_*] sections, which the router owns. The layout names follow TransportPolicy order.
 
double satVolume (int cell) const noexcept
 Water volume of one cell's saturated zone (m³) — the denominator for a saturated concentration.
 
double bookLinkGain (int cell, int species, double vol) noexcept
 A gaining conduit draws vol m³ of water from cell: book the mass it carries, at the cell's dissolved saturated concentration, for the cell to debit at its next firing, and return it (native units). The mass is capped at what the cell holds less what is already pending, so a cell whose saturated zone has emptied cannot export residual mass at a concentration divided by a vanishing volume.
 
double unsatVolume (int cell) const noexcept
 …and of its unsaturated column store (m³), whatever closure holds it.
 
void bookInfiltrationMass (int cell, int species, double mass) noexcept
 The surface hands mass down with its infiltration (T7.1 seam): the mass the water it booked through bookInfiltrationFromSurface was carrying, gathered when the GW cell fires.
 
bool sourceReceiptOwnershipBound () const
 Internal reviewed-source ownership. Must bind before pending exchange.
 
std::string configureSourceReceipts (const std::vector< int > &cells)
 Bind exclusive reviewed-source receipt ownership to selected receiver cells.
 
void retainSourceReceipt (const SurfaceIntakeReceipt &)
 Retain intake provenance for a reviewed-source-owned positive receipt.
 
const std::vector< SurfaceIntakeReceipt > & pendingSourceReceipts (int cell) const
 Borrow queued reviewed-source intake provenance for one receiver cell.
 
double sourceCompletedTime (int cell) const
 Read the receiver's completed reviewed-source horizon.
 
const std::vector< SurfaceReturnReceipt > & sourceReturns () const
 Borrow queued source-attributed refunds and physical emergence.
 
void acknowledgeSourceReturns (double completed_through)
 Erase source return receipts whose availability horizon has been adopted.
 
double takeToSurfaceMass (int cell, int species) noexcept
 …and takes back what saturation excess and rejection carried up. Drained by the surface cell in the same call that takes the water.
 
const GwOptions & options () const noexcept
 Borrow the solver's resolved groundwater option copy.
 
void refreshDtCell (const MeshData &mesh, const InertialEdges &edges)
 Per-cell stability step min(Δt_g, Δt_u), written into state_.dt_cell. Called once per rebuild; cheap enough to be unconditional (the plan's "they rarely bind").
 
double minDtCell () const noexcept
 G1-c (2026-09-19): the smallest per-cell stability step after refreshDtCell (s), or 1e30 s when no stored value is smaller — the marcher folds it into the ladder's base step so a groundwater cell whose own bound is finer than every active surface cell's does not fire beyond it.
 
void assignTiers (double dt0, int n_tiers)
 Assign tiers from dt_cell against the marcher's dt0 and tier count, and rebuild the per-tier cell/face lists. G-A: no surface quantity enters this.
 
int requiredTiers (double dt0) const noexcept
 Minimum tier count the ladder needs so it reaches the slowest GW cell (K ≥ 1 + ⌈log2(Δt_gw_max/dt0)⌉, G-A point 3). The marcher grows its ladder to this before assigning.
 
void fireGwFaces (int tier, double dt)
 Lateral Darcy on the faces of one tier; books ±ΔV into eacc_L/R.
 
void fireGwCells (int tier, double dt, SurfaceStateData &surf, double time=0.0, double accepted_end=-1.0)
 Gather + closure + node/deep/ET/Dunne for the cells of one tier. accepted_end is the common marcher's exact completed endpoint; owned cells start at their last completed firing, without rounded clock gaps.
 
RuntimeSources & runtimeSources () noexcept
 Borrow mutable copied runtime source prescriptions, receipts and derived lookups.
 
const RuntimeSources & runtimeSources () const noexcept
 Borrow read-only copied runtime source prescriptions, receipts and derived lookups.
 
void setBoundaries (std::vector< GwResolvedBoundary >)
 Replace validated SI exterior boundaries and rebuild their per-cell lookup/stability.
 
const std::vector< GwResolvedBoundary > & boundaries () const noexcept
 Borrow resolved exterior groundwater hydraulic/quality boundary descriptors and receipts.
 
void fireGwRk2Cells (double dt, SurfaceStateData &, double time)
 Run a tier-zero groundwater Euler evaluation within the shared RK2 transaction.
 
void advanceRk2Heat (double seconds, double sample_time)
 Advance independent ground conduction with RK2 at a held thermal forcing sample time.
 
void setSources (std::vector< GwResolvedSource > sources)
 Replace resolved project aquifer sources and rebuild per-cell weighted lookup.
 
void settle (SurfaceStateData &surf)
 Compact drained surface-return bookkeeping before scheduler transitions. Pending edge/node water remains owned until the next paired cell firing.
 
void restorePendingSurface ()
 Rebuild pending-surface cell flags/list from positive xacc_to_surface water.
 
bool tierHasCells (int tier) const noexcept
 True when the tier's cell list is non-empty.
 
bool tierHasFaces (int tier) const noexcept
 Test whether one stored tier has a nonempty firing list.
 
int tierCount () const noexcept
 Read the number of stored groundwater cell-tier lists.
 
const std::vector< long > & tierFirings () const noexcept
 Per-tier firing counts — the G-A telemetry (swmm_gw2d_get_tier_histogram).
 
void bookInfiltrationFromSurface (int cell, double vol_m3) noexcept
 The surface books infiltration it delivered to cell i (m³) at its own (finer) cadence; the GW cell gathers it when it fires.
 
void publishInfiltration (SurfaceStateData &surf, double interval, double time)
 Publish the aquifer's held rate; publication never restores spent storage.
 
double acceptSurfaceInfiltration (int cell, double requested, bool prescribed=false) noexcept
 Reserve and book once, BEFORE the sender removes water (SI m3). Producers for one cell run serially, as for the existing accumulators.
 
double infiltrationHeadroom (int cell) const noexcept
 Compute current unreserved unsaturated receiver capacity.
 
double sourceInfiltrationCapacity (int cell, double pond_m, double interval_s) const noexcept
 Read-only soil/interface rate (m/s) for the actual donor pond head. Group headroom is allocated separately; no front or held rate advances.
 
void bookLinkSeepage (int cell, double vol_m3) noexcept
 G-X3 (2026-09-19): the router books a conduit's seepage volume (m³, SI, its length-weighted share for this cell) at the routing cadence; the GW cell gathers it at its firing as a saturated-zone inflow.
 
void bookLinkContact (int cell, double volume, const std::vector< double > &concentration, double elevation_begin, double elevation_end)
 Accepted leaking reach, with a linear bed elevation over its clipped length. Splits water and producer quality at actual SIGMA interfaces.
 
int contactLayer (int cell, double elevation) const noexcept
 Locate a conduit contact in the current unsaturated SIGMA layers.
 
double takeToSurface (int cell) noexcept
 Volume (m³) the subsurface owes the surface twin — Dunne and exfiltration — drained by the surface at its firing.
 
const std::vector< int > & pendingSurfaceCells () const noexcept
 Cells with pending surface-bound water, so the marcher can pin them active (a dry surface cell above an exfiltrating column must route). Call compactPending() first — takeToSurface clears flags but does not erase from this list, because it runs inside the parallel cell loop.
 
void compactPending () noexcept
 Drop drained cells from pendingSurfaceCells(). Serial; call from the marcher's rebuild, not from a firing.
 
void publishNodeConcentrations (const SimulationContext &ctx)
 T7.4: the node's own species row, [node * n_species + s], published by the router each batch — what a RECHARGING node's water carries down its bed. Null (or a zero row count) means the seam moves water only, which is what every pre-T7.4 deck did.
 
void setNodeRowConc (const double *rows, int n_species) noexcept
 Borrow node-major producer composition for subsequent node/aquifer exchanges.
 
const std::vector< double > & nodeExchangeMass () const noexcept
 T7.4: mass the aquifer owes each 1D node this batch ([s * n_nodes + node], + out of the aquifer), flushed by the router into the node's coupling queues alongside the volume.
 
void bookLinkSeepageMass (int cell, int species, double mass) noexcept
 T7.4: mass a leaking conduit delivered into one cell, at the conduit's own concentration — the species twin of bookLinkSeepage.
 
void sampleNodeExchange (const NodeData *nodes, double dt, double end=-1)
 Node ↔ aquifer exchange, evaluated at tier-0 cadence against the batch-frozen 1D heads and booked into nacc (G-B row 3). The GW cell gathers its share when IT fires — the node is never pinned to the aquifer's tier and the aquifer is never pinned to tier 0.
 
const std::vector< double > & nodeExchangeVolumes () const noexcept
 Per-node exchange volume this advance (m³ SI, + out of the aquifer into the pipe). The router books it into nodes.coupling_volume through the same flow_2d_to_1d factor the surface exchange uses.
 
void resetNodeExchangeVolumes () noexcept
 Zero the per-node ledger at the start of a routing batch.
 
const std::vector< GwNodeBed > & nodeBeds () const noexcept
 G-O: the [2D_AQUIFER_NODE] beds as resolved (cell index filled), in the authored order — parallel to SurfaceRouter2D::aquiferNodeNames().
 
const std::vector< double > & bedExchangeCumulative () const noexcept
 G-O: cumulative exchange per bed (m³, + out of the aquifer into the pipe) since the start — the results-file series behind the GUI's GwExchange plot. Never reset.
 
long drainCapBinds () const noexcept
 Firings on which the aquifer→node drain cap actually clamped Q. Zero means the deck cannot see anything this cap does.
 
long nodeRefunds () const noexcept
 Firings on which a column went short and the node's share of the overdraw was refunded — into the aquifer's books alone, after the router had already paid the node. The defect's signature: 124 before G-W1, 0 after.
 
double specificYieldOf (int cell) const noexcept
 The specific yield the column ACTUALLY uses for cell, from the one definition. Exposed so a test never re-derives it: re-deriving only the CLOSED_FORM branch (as the first version of the G-W1b guard did) silently computes a number the solver never uses under SIGMA or ENSLAVED, and agrees only for as long as every fixture is closure A.
 
double unreservedDrainableWater (int cell) const noexcept
 Compute drainable aquifer water after gross promised exports.
 
double unreservedDrainableWater (int cell, double specific_yield) const noexcept
 
double pendingSaturatedMassExport (int cell, int species) const noexcept
 Sum nonnegative queued saturated native inventory exports.
 
std::string nodeWaterBudget (int cell, double interval, NodeWaterBudget &) const
 Read a validated finite node-trial water budget for one aquifer cell.
 
double cellCompletedTime (int cell) const
 Read one groundwater cell's accepted firing horizon.
 
const std::vector< double > & richardsBedDownCumulative () const noexcept
 Borrow cumulative accepted LID-to-aquifer water per resolved bed.
 
const std::vector< double > & richardsBedUpCumulative () const noexcept
 Borrow cumulative accepted aquifer-to-LID water per resolved bed.
 
std::string configureLidReceipts (const std::vector< int > &beds, const std::vector< int > &mobile={})
 Bind reviewed Richards and mobile-LID water/optional-temperature receipt ownership.
 
std::string retainLidReceipts (double start, double end, const std::vector< RichardsBedReceipt > &)
 Adopt a completed reviewed Richards water/heat receipt interval.
 
std::string completeLidThermalInterval (SimulationContext &)
 Publish persistent LID physical energy for the already accepted paired hydraulic interval.
 
bool lidReceiptsEnabled () const noexcept
 Read whether reviewed LID/aquifer receipt ownership was enabled.
 
double pendingLidDown (int cell) const noexcept
 Sum gross pending LID-to-aquifer water across one cell's beds.
 
double pendingLidUp (int cell) const noexcept
 Sum gross pending aquifer-to-LID water across one cell's beds.
 
double pendingLidWater () const noexcept
 Read signed water stored in reviewed LID receipt queues awaiting groundwater adoption.
 
const std::vector< std::vector< PendingLidBed > > & pendingLidReceipts () const
 Borrow per-bed queued accepted LID/aquifer interval receipts.
 
const std::vector< LidBedDiagnostic > & lidBedDiagnostics () const
 Borrow the latest accepted LID/aquifer request/reservation/settlement samples per bed.
 
double pendingBedDown (int bed) const noexcept
 Sum gross unconsumed LID-to-aquifer water for one bed.
 
double pendingBedUp (int bed) const noexcept
 Sum gross unconsumed aquifer-to-LID water for one bed.
 
void setLidBedClogging (int bed, double factor)
 Replace the multiplier applied to one resolved bed's subsequent node exchange conductance.
 
double storage () const noexcept
 Storage now, for the continuity ledger.
 
void checkpoint (detail::CompletedSourceArchive &, bool model)
 Serialize qualified groundwater identity or completed mutable owner state.
 
void checkpoint (detail::CompletedSourceArchive &, bool model, const double *held_air)
 Serialize qualified groundwater identity or completed mutable owner state.
 
std::string initReactions (SimulationContext &ctx)
 Resolve scoped subsurface expression laws into per-cell saturated/unsaturated reactors.
 
std::string rk2ProfileError () const
 Coupled SSP-RK2: spatial CLOSED_FORM/ENSLAVED/SIGMA water only, authored wells and HEAD/FLOW edges.
 
void blendRk2Water (const SubsurfaceSolver &initial, double end)
 Form the conservative half-beginning/half-two-Euler-state SSP groundwater endpoint.
 
void publishRk2Infiltration (SurfaceStateData &, double dt, double time)
 Publish the current coupled stage's bounded instantaneous intake capacity.
 
bool hasRk2Reactions () const noexcept
 Test whether any scoped reactor or positive first-order native decay is configured.
 
void advanceRk2Reactions (double seconds)
 Apply symmetric reaction/decay composition to every covered coupled groundwater cell.
 
bool needsTransportRestart () const noexcept
 Test whether current transport ownership requires its extended restart payload.
 
std::string transportRestartState () const
 Capture the extended groundwater continuation needed beyond the ordinary hotstart payload.
 
std::string restoreTransportRestart (const std::string &bytes, bool apply)
 Validate or adopt an extended groundwater hotstart against this prepared model identity.
 

Friends

class CommonSourceStage
 
class ExplicitInertialSolver
 
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 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 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 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.
 

Detailed Description

The two-zone kernel. Owned by SurfaceRouter2D; driven by the marcher's tier hooks.

Member Function Documentation

◆ acceptSurfaceInfiltration()

double openswmm::twoD::SubsurfaceSolver::acceptSurfaceInfiltration ( int cell,
double requested,
bool prescribed = false )
noexcept

Reserve and book once, BEFORE the sender removes water (SI m3). Producers for one cell run serially, as for the existing accumulators.

Reserve a valid surface intake against current groundwater receiver headroom.

Parameters
[in]cellPrepared covered receiver cell; inactive/uncovered returns zero.
[in]requestedFinite positive requested water volume m3; invalid returns zero.
[in]prescribedTrue bypasses the conductivity/published-capacity admission gate. False requires both Ks and a finite positive published infil_capacity; the published rate is a gate, not an additional volume-over-time limit in this method.
Returns
min(requested,infiltrationHeadroom(cell)), m3, added to xacc_from_surface and wetting_front as depth. Also refreshes infil_remaining; no canonical storage, native mass or receipt is booked.
Note
Requires positive prepared area and exclusive access to this cell. Caller pairs the accepted water with species/provenance and updates surface storage; no whole coupled transaction occurs.
Here is the call graph for this function:

◆ acknowledgeSourceReturns()

void openswmm::twoD::SubsurfaceSolver::acknowledgeSourceReturns ( double completed_through)

Erase source return receipts whose availability horizon has been adopted.

Parameters
[in]completed_throughInclusive elapsed-time horizon s. Caller supplies a valid completed consumer horizon; no finiteness/sign validation occurs. NaN removes none, positive infinity all.
Note
Caller first delivers every qualifying receipt, then acknowledges serially. Erases matching queue entries and invalidates their views without booking or undoing water/native inventory.

◆ active()

bool openswmm::twoD::SubsurfaceSolver::active ( ) const
inlinenoexcept

Read whether the resolved groundwater kernel is active.

Returns
state_.active; does not validate prepared arrays, pending receipts or transport/heat activation. Default/empty configurations remain inactive; no state change occurs.
Here is the caller graph for this function:

◆ advanceRk2Heat()

void openswmm::twoD::SubsurfaceSolver::advanceRk2Heat ( double seconds,
double sample_time )

Advance independent ground conduction with RK2 at a held thermal forcing sample time.

Parameters
[in]secondsFinite positive solve interval s; inactive/nonpositive returns, positive infinity throws. NaN is skipped by the nonpositive test rather than explicitly rejected.
[in]sample_timeFinite elapsed forcing horizon s, interpolated without changing table cursors.
Note
Samples heat forcing once, conducts every covered unowned physical column and refreshes its derived native views. Surface-owned columns are skipped by conduct(). Refusal throws after earlier cells/caches may have changed; enclosing coupled transaction stages rollback. Allocates thermal work.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ advanceRk2Reactions()

void openswmm::twoD::SubsurfaceSolver::advanceRk2Reactions ( double seconds)

Apply symmetric reaction/decay composition to every covered coupled groundwater cell.

Parameters
[in]secondsFinite positive reaction interval s. Inapplicable/nonpositive/NaN returns; positive nonfinite interval throws.
Note
Without scoped reactors applies full exact exponential decay. Otherwise applies half decay, full reactor solve and half decay so a decaying precursor couples symmetrically to RATE laws. Age/temperature do not decay; physical outgoing native reservations are excluded. Updates canonical mass, reaction ledgers and physical/SIGMA views. Refusal can follow earlier rows/cells; caller stages the coupled transaction. Requires matching stable prepared owners and exclusive shared workspace.
Here is the call graph for this function:

◆ assignTiers()

void openswmm::twoD::SubsurfaceSolver::assignTiers ( double dt0,
int n_tiers )

Assign tiers from dt_cell against the marcher's dt0 and tier count, and rebuild the per-tier cell/face lists. G-A: no surface quantity enters this.

Parameters
[in]dt0Finite positive base duration s. Nonpositive selects tier zero; no general finite validation occurs. Prepared dt_cell values govern floor(log2(dt_cell/dt0)) where usable.
[in]n_tiersRequested tier count, raised to at least one. Must fit stored uint8_t cell/face tiers and caller scheduler shifts; this method does not impose an upper cap.
Note
Inactive returns. Replaces cell/face tier lists, resets tier firing counters, assigns covered cells to bounded binary tiers and covered-covered faces to the finer endpoint tier. Leaves cross- cadence receipts in their stable CSR slots; does not fire or consume them. Allocations can fail after partial list replacement. Requires exclusive access and consistent prepared topology/coverage.
Here is the caller graph for this function:

◆ bedExchangeCumulative()

const std::vector< double > & openswmm::twoD::SubsurfaceSolver::bedExchangeCumulative ( ) const
inlinenoexcept

G-O: cumulative exchange per bed (m³, + out of the aquifer into the pipe) since the start — the results-file series behind the GUI's GwExchange plot. Never reset.

Borrow cumulative signed exchange per resolved node bed.

Returns
Solver-owned const vector in m3, positive out of aquifer. No copy, reset or receipt consumption occurs; initialization/restore/owner bookkeeping can change contents and invalidate element views. Caller keeps the solver stable and uses the matching node/bed/transport identity.

◆ blendRk2Water()

void openswmm::twoD::SubsurfaceSolver::blendRk2Water ( const SubsurfaceSolver & initial,
double end )

Form the conservative half-beginning/half-two-Euler-state SSP groundwater endpoint.

Parameters
[in]initialImmutable beginning-stage solver with identical prepared model, arrays, row and boundary/source identities. Must not alias this mutable solver.
[in]endFinite accepted elapsed endpoint s, strictly after enabled source cells' initial times.
Note
Blends conserved hydraulic/native inventories, reservations and receipts; ENSLAVED inverts blended total equilibrium water, SIGMA blends layer water across changing column length then normalizes only endpoint roundoff. Rebuilds derived layer views and clocks/receipts consistently. Validates profile/shapes/admissibility but mutates progressively and may throw after partial blending; caller stages the complete coupled transaction. Allocations can propagate. Does not average all configuration or borrowed bindings, nor advance canonical 1D owners by itself.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bookAreaEt()

void openswmm::twoD::SubsurfaceSolver::bookAreaEt ( int cell,
double dt,
double potential,
double evaporation,
double soil )

SI completed footprint volumes, already paid by their surface/LID owners. Only soil_demand may reach this cell's extraction site; the rest expires.

Book a completed atmospheric finite-volume owner budget.

Book a completed finite atmospheric owner budget for later groundwater demand.

  • owner_evaporation: Accepted surface/owner evaporation m3 (definition: evaporation).
  • soil_demand: Remaining soil demand m3 (definition: soil).
Parameters
[in]cellCovered prepared cell; inactive, PER_SUBCATCH or uncovered returns without work.
[in]dtFinite positive completed atmospheric interval s; nonpositive/NaN returns before validation, while positive nonfinite values are rejected.
[in]potentialFinite nonnegative potential loss volume m3.
[in]evaporationFinite nonnegative owner evaporation volume m3.
[in]soilFinite nonnegative remaining soil demand m3; evaporation+soil must fit potential within the relative 1e-12 tolerance. Tiny permitted excess is clamped before booking soil demand.
Exceptions
std::invalid_argumentInvalid completed budget, before ledger changes.
Note
Adds soil to et_pending, updates cumulative potential/surface/unused volumes and rates, and advances the ET refresh duration. Requires positive prepared area and serial cell bookkeeping. Does not remove canonical water or book native/thermal transport.
Here is the call graph for this function:

◆ bookInfiltrationFromSurface()

void openswmm::twoD::SubsurfaceSolver::bookInfiltrationFromSurface ( int cell,
double vol_m3 )
noexcept

The surface books infiltration it delivered to cell i (m³) at its own (finer) cadence; the GW cell gathers it when it fires.

Parameters
[in]cellPrepared covered cell; inactive/uncovered returns without booking.
[in]vol_m3Signed pending intake volume m3, added directly without capacity, sign or finite validation. Caller first establishes a physically accepted amount and paired composition.
Note
Changes only this cell's xacc_from_surface. No shared flag, wetting front, native mass or canonical storage is changed. Independent cells can be booked concurrently; competing producers must serialize access to the same slot.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bookInfiltrationMass()

void openswmm::twoD::SubsurfaceSolver::bookInfiltrationMass ( int cell,
int species,
double mass )
noexcept

The surface hands mass down with its infiltration (T7.1 seam): the mass the water it booked through bookInfiltrationFromSurface was carrying, gathered when the GW cell fires.

Parameters
[in]cellPrepared receiver cell index; invalid indices are ignored.
[in]speciesPrepared transport row index; invalid indices or inactive transport are ignored.
[in]massNative row inventory (concentration*m3), signed for signed rows. Zero is ignored; no finite-value or sign validation is performed. Caller supplies an amount consistent with the water receipt and row identity.
Note
Adds to xacc_from_surface only; canonical inventory is gathered later. Does not book water or set the shared pending flag. Requires allocated matching arrays and exclusive access to the addressed cell/row slot; independent slots may be produced separately.
Here is the caller graph for this function:

◆ bookLinkContact()

void openswmm::twoD::SubsurfaceSolver::bookLinkContact ( int cell,
double volume,
const std::vector< double > & concentration,
double elevation_begin,
double elevation_end )

Accepted leaking reach, with a linear bed elevation over its clipped length. Splits water and producer quality at actual SIGMA interfaces.

Parameters
[in]cellPrepared covered receiver; inactive/uncovered returns without work.
[in]volumePositive accepted conduit intake volume m3; nonpositive/NaN returns immediately, positive infinity is rejected by validation.
[in]concentrationBorrowed native concentrations in exact transport row order. Size must match n_species; all values finite and unsigned rows nonnegative. Not retained.
[in]elevation_beginFinite SI elevation m of one end of the conduit contact segment.
[in]elevation_endFinite SI elevation m of the other end; equal elevations are allowed.
Exceptions
std::invalid_argumentInvalid positive receipt volume, composition or endpoint.
Note
Splits the accepted volume at SIGMA layer boundaries, books total link water, then places paired mass/water into layer or saturated contact ledgers. Does not debit the conduit or change canonical groundwater storage. Temporary cuts may allocate before booking. Requires prepared geometry/ledger shapes and serial producer access; receipts are not rolled back by this helper.
Here is the call graph for this function:

◆ bookLinkGain()

double openswmm::twoD::SubsurfaceSolver::bookLinkGain ( int cell,
int species,
double vol )
inlinenoexcept

A gaining conduit draws vol m³ of water from cell: book the mass it carries, at the cell's dissolved saturated concentration, for the cell to debit at its next firing, and return it (native units). The mass is capped at what the cell holds less what is already pending, so a cell whose saturated zone has emptied cannot export residual mass at a concentration divided by a vanishing volume.

Parameters
[in]cellZero-based prepared transport cell; invalid returns zero before booking.
[in]speciesTransport row index; invalid/inactive transport returns zero.
[in]volFinite positive accepted conduit-gain water volume m3; nonpositive/NaN returns zero.
Returns
Booked dissolved native inventory (native_concentration*m3); ordinary unsigned rows are capped against mobile saturated mass less queued exports. Signed rows can return signed values. Zero can still accompany thermal volume/reservation bookkeeping in an active temperature row.
Note
Requires consistent hydraulic/transport/thermal/porewater arrays and serial producer access. Adds outgoing mass to lout_mass for the later cell gather rather than subtracting canonical mass now. Active temperature also books producer-time heat/volume, and physical porewater reservations are updated. Does not book the water volume itself; caller pairs that separately. General finite input/result validation is absent and noexcept callbacks/helpers must not throw.
Here is the call graph for this function:

◆ bookLinkSeepage()

void openswmm::twoD::SubsurfaceSolver::bookLinkSeepage ( int cell,
double vol_m3 )
noexcept

G-X3 (2026-09-19): the router books a conduit's seepage volume (m³, SI, its length-weighted share for this cell) at the routing cadence; the GW cell gathers it at its firing as a saturated-zone inflow.

Parameters
[in]cellPrepared covered cell; inactive/uncovered returns without booking.
[in]vol_m3Signed water volume m3, positive conduit-to-aquifer. No sign, finite-value, availability or headroom validation is performed; caller has accepted and paired the exchange.
Note
Adds lacc, reserves gross layered contact_link_out for negative volumes, and marks shared accumulators pending. Canonical stores/mass are gathered later. Requires serial producer access, including the shared pending flag; not a thread-safe cell-only producer interface.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bookLinkSeepageMass()

void openswmm::twoD::SubsurfaceSolver::bookLinkSeepageMass ( int cell,
int species,
double mass )
noexcept

T7.4: mass a leaking conduit delivered into one cell, at the conduit's own concentration — the species twin of bookLinkSeepage.

Parameters
[in]cellPrepared receiver cell index; invalid indices are ignored.
[in]speciesPrepared transport row index; invalid indices or inactive transport are ignored.
[in]massNative row inventory (concentration*m3), signed for signed rows. Zero is ignored; no finite-value or sign validation is performed. Caller supplies an amount consistent with the water receipt and row identity.
Note
Adds to lacc_mass only; canonical inventory is gathered later. Does not book water or set the shared pending flag. Requires allocated matching arrays and exclusive access to the addressed cell/row slot; independent slots may be produced separately.
Here is the caller graph for this function:

◆ bookSurfaceEt()

void openswmm::twoD::SubsurfaceSolver::bookSurfaceEt ( int cell,
double dt,
double rate,
double surface )

One surface interval: reserve actual pond evaporation first. No forcing refresh resets this budget.

Book unresolved atmospheric soil demand after surface evaporation.

  • potential_rate: Potential atmospheric loss rate m/s (definition: rate).
  • actual_surface_volume: Already accepted surface evaporation m3 (definition: surface).
Parameters
[in]cellCovered prepared cell; inactive, PER_SUBCATCH or uncovered returns without work.
[in]dtPositive elapsed duration s; nonpositive/NaN returns. Caller supplies finite dt and positive cell area because remaining calculations do not validate them.
[in]ratePotential atmospheric loss rate m/s, clamped to nonnegative.
[in]surfaceActual surface evaporation volume m3, clamped into [0,rate*area*dt].
Note
Adds the unmet potential volume to groundwater et_pending, records cumulative potential and surface loss plus latest rates, and advances the cell's ET refresh duration. Does not remove canonical water, book latent heat or native mass. Requires exclusive cell bookkeeping access; this path performs no general finite-value checks.
Here is the call graph for this function:

◆ boundaries()

const std::vector< GwResolvedBoundary > & openswmm::twoD::SubsurfaceSolver::boundaries ( ) const
inlinenoexcept

Borrow resolved exterior groundwater hydraulic/quality boundary descriptors and receipts.

Returns
Solver-owned const vector, in configured order. Geometry is SI, signal time elapsed s, water ledgers m3 and transport inventory native units. setBoundaries(), initialize/restore and firings can replace/change elements; no copy or forcing integration occurs in this getter.

◆ cellCompletedTime()

double openswmm::twoD::SubsurfaceSolver::cellCompletedTime ( int cell) const
inline

Read one groundwater cell's accepted firing horizon.

Parameters
[in]cellValid cell_completed_ index.
Returns
Elapsed completed time s, independent of pending producer/source clocks.
Exceptions
std::out_of_rangeOn invalid cell; no synchronization or firing occurs.

◆ checkpoint() [1/2]

void openswmm::twoD::SubsurfaceSolver::checkpoint ( detail::CompletedSourceArchive & a,
bool model )

Serialize qualified groundwater identity or completed mutable owner state.

Archive groundwater model identity or mutable completed-owner state without a held AIR override.

  • Argument model (in): True writes model identity; false writes/reads mutable state against an externally matched initialized model. The archive reference is borrowed for this call.
    Note
    Physical water/native/heat reservations, source/LID provenance and clocks are preserved and validated on restore. Reads can throw after partial mutation: stage a private copy and finish/ validate the enclosing archive before adoption. Definition details profiles, allowed NaNs and borrowed owner lifetime; no physical firing, file write or engine calendar update occurs.
    Parameters
    [in,out]aCaller-owned CompletedSourceArchive. Model mode writes deterministic identity; state mode writes or restores into an already initialized matching model.
    [in]modelTrue selects identity-only layout, false the mutable physical/receipt state.
    Note
    Delegates to the held-air overload with nullptr, using current native air temperature for qualified AIR model identity. Does not make a staged copy itself; failed state reads can partially mutate this solver. Caller must stage and validate the enclosing whole-engine transaction.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ checkpoint() [2/2]

void openswmm::twoD::SubsurfaceSolver::checkpoint ( detail::CompletedSourceArchive & a,
bool model,
const double * held_air )

Serialize qualified groundwater identity or completed mutable owner state.

Archive qualified groundwater identity or completed hydraulic/native/physical receipt state.

  • Argument model (in): True writes model identity; false writes/reads mutable state against an externally matched initialized model. The archive reference is borrowed for this call.
  • Argument held_air (in): Optional native degF air-temperature override for qualified RK2 AIR identity; null reads current context air. Not retained.
    Note
    Physical water/native/heat reservations, source/LID provenance and clocks are preserved and validated on restore. Reads can throw after partial mutation: stage a private copy and finish/ validate the enclosing archive before adoption. Definition details profiles, allowed NaNs and borrowed owner lifetime; no physical firing, file write or engine calendar update occurs.
    Parameters
    [in,out]aCaller-owned completed-source archive. For model=true use write mode; model identity signal serialization is not a general model reconstruction reader. For model=false read requires identical initialized topology/material/species/forcing identity established externally.
    [in]modelTrue writes physical model, configuration, forcing, thermal/reaction/unit and ownership identity, excluding mutable ledgers; false writes/restores canonical state and receipts.
    [in]held_airOptional readable native engine air temperature degF used only for RK2 porous AIR-boundary model identity. Null samples context climate temperature; pointer is never retained.
    Exceptions
    std::runtime_errorUnsupported restart profile, unqualified Richards ownership, nonfinite/ negative invalid state, mismatched rows/layers/physical reservations/provenance/clocks/tiers or failed physical thermal archive validation. Archive shape/truncation/allocation errors also propagate.
    Note
    State mode includes pending side/native/physical energy packets, staged source/LID receipt queues, per-cell clocks, tier lists/diagnostics and cumulative ledgers; pending water remains paired rather than prematurely settled. Reading resets process-local recharge caches/counters, validates physical/SIGMA owner correspondence and producer reservations, and allows NaN only in designated unpublished diagnostics. Mutable payloads are applied before semantic checks; this routine offers no rollback. Borrowed context/mesh/edges/callbacks remain external and must be live/stable; caller uses a private initialized copy and adopts only after full archive finish/whole-engine validation. No file I/O, water firing, external 1D node mutation or engine calendar advance occurs.
Here is the call graph for this function:

◆ compactPending()

void openswmm::twoD::SubsurfaceSolver::compactPending ( )
noexcept

Drop drained cells from pendingSurfaceCells(). Serial; call from the marcher's rebuild, not from a firing.

Remove pending-surface list entries whose cell flags were cleared by drains.

Note
Serial list maintenance after parallel per-cell takeToSurface() calls. Does not book, consume or recompute water; flagged entries remain. Requires valid prepared cell indices/flags and no concurrent list/flag mutation. Erasure invalidates list element views; no allocation.
Here is the caller graph for this function:

◆ completeLidThermalInterval()

std::string openswmm::twoD::SubsurfaceSolver::completeLidThermalInterval ( SimulationContext & ctx)

Publish persistent LID physical energy for the already accepted paired hydraulic interval.

Apply completed accepted hydraulic transfers to persistent physical Richards LID energy.

Returns
Empty on success/inactive heat, otherwise clock/owner/receipt/transfer diagnostic. The context reference is the writable matching persistent LID owner and producer-temperature source.
Note
Stages every LID before publication, then marks corresponding queue heat receipts adopted. Does not conduct physical layers or advance groundwater water; allocates and may throw. Definition documents native-to-SI conversion, donor order and receipt phase requirements.
Parameters
[in,out]ctxMatching context with persistent Richards storage/quality-transfer/port records, node/link producer temperatures degC and prepared material properties; remains alive during call.
Returns
Empty on success/inactive heat; diagnostic for missing paired owner/clock/receipt, invalid water/thermal geometry/transfer or mismatch of bottom export volume with accepted groundwater receipt.
Note
For every Richards bed, stages a copy beginning at quality_old_water, converts accepted native ft3 packets to m3, computes producer-ordered sensible transfers (network mobile surface remains network-owned), and validates the resulting graph against completed water. After every draft qualifies, swaps physical LID states and updates queued down_j/heat_applied, adding an empty completed marker when no water receipt existed. Already applied interval is rejected. Does not conduct layers, settle groundwater hydraulic water or publish generic network heat receipts. Allocation can throw; staged validation errors precede canonical swaps. Caller serializes all coupled owners and provides valid parallel shapes; exception atomicity of the larger hydraulic transaction belongs to its caller.
Here is the call graph for this function:

◆ configureLidReceipts()

std::string openswmm::twoD::SubsurfaceSolver::configureLidReceipts ( const std::vector< int > & beds,
const std::vector< int > & mobile = {} )

Bind reviewed Richards and mobile-LID water/optional-temperature receipt ownership.

Parameters
[in]bedsZero-based resolved groundwater bed indices owned by persistent Richards LIDs.
[in]mobileZero-based bed indices retaining ordinary mobile-node hydraulic sampling. Lists must be disjoint/duplicate-free, exchange-enabled, resolved and at initial completed time zero, with no pending bed nacc. Empty both returns success without enabling ownership.
Returns
Empty after setting ownership flags/enabled capability; otherwise initialization/profile, bed-identity or finite one-second node-budget diagnostic, before flags are changed.
Note
Requires valid initial groundwater clock and water-only or temperature-only rows; rejects pollutants/MSX/age and already enabled ownership. Uses allocation for duplicate checking/list staging, which may throw. Does not create receipts, book water/heat or advance clocks; exclusive setup access.
Here is the call graph for this function:

◆ configureSourceReceipts()

std::string openswmm::twoD::SubsurfaceSolver::configureSourceReceipts ( const std::vector< int > & cells)

Bind exclusive reviewed-source receipt ownership to selected receiver cells.

Parameters
[in]cellsZero-based receiver cells; duplicates and an empty list are accepted. Every listed cell must be in range and have no pending surface water or native exchange inventory.
Returns
Empty string after binding flags and copying transport row names; otherwise a diagnostic before any flag is set when ownership already exists or a cell fails validation.
Note
Requires prepared ownership/receipt arrays and serial pre-exchange configuration. Does not clear old queues or book water. Copying species metadata may allocate after flags are set, so an allocation exception can leave ownership bound. No whole-call rollback is provided.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ contactLayer()

int openswmm::twoD::SubsurfaceSolver::contactLayer ( int cell,
double elevation ) const
noexcept

Locate a conduit contact in the current unsaturated SIGMA layers.

Parameters
[in]cellCovered prepared cell; invalid/uncovered or nonlayered returns -1.
[in]elevationFinite contact elevation m in the groundwater vertical datum.
Returns
Zero-based unsaturated layer, clamped to [0,n_layers-1], or -1 for elevation at/below the water table, no positive unsaturated length, or invalid input. Elevations above the ground select the top layer. No ledger mutation or allocation occurs.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ coverage()

const std::vector< uint8_t > & openswmm::twoD::SubsurfaceSolver::coverage ( ) const
inlinenoexcept

Mesh mode: 1 where a [2D_AQUIFER] row (*, TAG or CELL) covers the cell. An uncovered cell has no aquifer: no storage, no lateral faces, and its infiltration stays with the surface model. All 1 in PER_SUBCATCH mode.

Returns
Borrowed solver-owned byte mask, one entry per resolved cell; a nonzero value means an authored aquifer receiver covers it. Initialization/replacement invalidates element views. Does not measure current water/activation or rebuild coverage; requires stable solver access.

◆ covers()

bool openswmm::twoD::SubsurfaceSolver::covers ( int cell) const
inlinenoexcept

Test resolved aquifer coverage with an index guard.

Parameters
[in]cellZero-based cell; negative/out-of-range returns false.
Returns
Stored coverage byte is nonzero. Does not test water depth, pending capacity or validate model arrays. Read-only and allocation-free.
Here is the caller graph for this function:

◆ drainCapBinds()

long openswmm::twoD::SubsurfaceSolver::drainCapBinds ( ) const
inlinenoexcept

Firings on which the aquifer→node drain cap actually clamped Q. Zero means the deck cannot see anything this cap does.

Returns
Stored count of node-drain cap binding events since owner initialization. This is direct diagnostic telemetry, not a tolerance-derived estimate; no state or counter reset occurs.

◆ fireGwCells()

void openswmm::twoD::SubsurfaceSolver::fireGwCells ( int tier,
double dt,
SurfaceStateData & surf,
double time = 0.0,
double accepted_end = -1.0 )

Gather + closure + node/deep/ET/Dunne for the cells of one tier. accepted_end is the common marcher's exact completed endpoint; owned cells start at their last completed firing, without rounded clock gaps.

Fire all cells in one due groundwater tier at their accepted ownership horizon.

Parameters
[in]tierStored tier index; inactive/absent tier returns after updating source_firing_end_.
[in]dtFinite positive ordinary firing duration s.
[in,out]surfMatching surface state/recipient, mutated by accepted cell water/species/heat.
[in]timeFinite ordinary start s.
[in]accepted_endNegative selects time+dt, otherwise exact completed end s for reviewed source/LID cells using their own previous completion. Must advance every selected owner.
Exceptions
std::runtime_errorRichards-owned beds lack enabled joint LID receipt acceptance, or a cell/forcing/thermal preflight rejects later work.
Note
Invokes fireGwCellList and increments tier telemetry only after success. Earlier subintervals can remain mutated on failure; caller stages the larger transaction. Requires exclusive prepared solver/coupled-owner access; does not directly advance canonical 1D nodes.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fireGwFaces()

void openswmm::twoD::SubsurfaceSolver::fireGwFaces ( int tier,
double dt )

Lateral Darcy on the faces of one tier; books ±ΔV into eacc_L/R.

Parameters
[in]tierSelected stored face tier; inactive or absent tier returns after any required physical/SIGMA view refresh. Negative/out-of-range tier is handled by tierHasFaces().
[in]dtFinite positive accepted firing duration s; required by caller, not validated here.
Note
Books signed L/R water m3 at donor-thickness Darcy rate with closure-consistent unreserved water caps. Native dissolved upwind inventory and optional tensor dispersion use paired side ledgers; signed temperature avoids a nonnegative-mass cap and porous heat excludes duplicate molecular flux. Also produces lateral heat, physical porewater/thermal outgoing reservations and limiter diagnostics. Canonical cell water/species are gathered later. Reviewed LID budgets/mapping may throw after earlier face reservations/bookings; no whole-list rollback. Requires stable geometry/material/arrays and serial producer access. A thermal owner failure may be flagged instead of thrown; caller checks it.
Here is the call graph for this function:

◆ fireGwRk2Cells()

void openswmm::twoD::SubsurfaceSolver::fireGwRk2Cells ( double dt,
SurfaceStateData & surface,
double time )

Run a tier-zero groundwater Euler evaluation within the shared RK2 transaction.

Evaluate one forward-Euler groundwater stage inside an owned shared RK2 transaction.

  • Argument dt (in): Finite positive stage duration s.
  • Argument time (in): Finite elapsed stage start s.
    Note
    The surface reference is the writable matching staged owner. Requires prevalidated RK2 profile and enclosing rollback/staging; exceptions may follow partial water/species/heat changes. Definition documents source proposal preflight and completion telemetry.
    Parameters
    [in]dtFinite positive stage duration s, caller validated.
    [in,out]surfaceMatching staged surface owner; receives accepted return water/native state.
    [in]timeFinite stage start s.
    Note
    Stores source_firing_end_=time+dt, returns for inactive/no tier-zero cells, prepares recharge, preflights runtime source water/heat/native arithmetic and fires tier-zero cells without extra water substeps. Refreshes physical/SIGMA views and increments tier-zero firings on normal completion. Throws on invalid proposals/thermal mapping/failure. Earlier cells/stage fields remain changed; requires enclosing RK2 staging, compatible prepared layouts and exclusive owner access.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hasRk2Reactions()

bool openswmm::twoD::SubsurfaceSolver::hasRk2Reactions ( ) const
noexcept

Test whether any scoped reactor or positive first-order native decay is configured.

Returns
True for nonempty reactors_ or any tr_.decay rate>0. Does not validate a live reaction binding, active transport or finite/sign validity of other rates. Read-only and allocation-free.
Here is the caller graph for this function:

◆ heat() [1/2]

const GroundHeatState & openswmm::twoD::SubsurfaceSolver::heat ( ) const
inlinenoexcept

Borrow read-only prepared physical-layer thermal and porewater owner.

Returns
Solver-owned const GroundHeatState reference; owner must remain alive/stable during access. Initialization, restore or replacement can replace contents/invalidate element views. No copy, validation, allocation or receipt consumption occurs.

◆ heat() [2/2]

GroundHeatState & openswmm::twoD::SubsurfaceSolver::heat ( )
inlinenoexcept

Borrow mutable prepared physical-layer thermal and porewater owner.

Returns
Solver-owned GroundHeatState reference. Caller retains no ownership and must preserve prepared shapes, identity, receipt phase and matched hydraulic/quality/thermal invariants. Mutations require exclusive solver access and appropriate owner/cache reconstruction before further firings. Initialization, restore or solver replacement can replace contained vectors and invalidate views; this getter performs no validation, allocation or synchronization.
Here is the caller graph for this function:

◆ infiltrationHeadroom()

double openswmm::twoD::SubsurfaceSolver::infiltrationHeadroom ( int cell) const
noexcept

Compute current unreserved unsaturated receiver capacity.

Parameters
[in]cellZero-based receiver cell; inactive or uncovered cells return zero.
Returns
Nonnegative unreserved receiver capacity m3. Uses closure-specific unsaturated storage; SIGMA also limits admission to the top layer's current deficit. Subtracts gross pending surface, link, lateral and LID/node inflows without cancelling outgoing promises against incoming water.
Note
Requires stable prepared cell, edge and bed arrays. Read-only, allocation-free and does not anticipate drainage, future provider receipts or refresh published infiltration rates.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ initHeat()

std::string openswmm::twoD::SubsurfaceSolver::initHeat ( SimulationContext & ctx,
const GwTransportData & config )

Initialize canonical porous thermal layers and paired producer/lateral receipt storage.

Initialize physical porous energy ownership and thermal producer/cross-tier bookkeeping.

Returns
Empty on success/disabled mode, otherwise unsupported ownership/material/contact diagnostic.
Note
Context and groundwater-config reference arguments are borrowed for subsequent forcing; keep them alive/stable. Requires initialized hydraulic/native rows. Clears prior thermal state and can throw or fail after partial mutation; initPorewater() separately initializes non-temperature physical inventories. Definition documents units, ordering and detailed side effects.
Parameters
[in,out]ctxPrepared engine context and matching native species units/names, borrowed by the physical heat owner for later forcing. Must outlive solver uses and retain compatible identity.
[in]configResolved SI groundwater thermal/material controls, borrowed for the physical owner lifetime. Positive valid thermal layer count and phase properties are required.
Returns
Empty on success/inapplicable mode; diagnostic for unsupported PER_SUBCATCH porous heat, physical initialization or lateral-contact geometry failure.
Note
Copies native unit identity, clears old physical heat/reservations/face ledgers, initializes qualified POROUS_EQUILIBRIUM temperature owners, allocates producer-time receipt arrays, refreshes derived temperature views and explicit thermal/CFL limits. Does not initialize non-temperature canonical porewater (initPorewater follows). Changes progressively; allocations/name/forcing errors can throw and leave partial state. Requires exclusive prepared mesh/hydraulic/native owners.
Here is the call graph for this function:

◆ initialize()

std::string openswmm::twoD::SubsurfaceSolver::initialize ( const MeshData & mesh,
const InertialEdges & edges,
const SolverOptions2D & opts,
const GwUnitFactors & uf,
int n_nodes,
SubsurfaceConfig & cfg,
std::vector< std::string > & warnings )

Resolve the authored rows onto cells, seed state, size the accumulators.

Parameters
meshcell areas, centroid elevations and tags
edgesthe marcher's unique interior-edge topology, shared
optsthe 2D solver options (LTS ladder, unit factors)
ufproject-unit → SI multipliers for the authored rows
n_nodes1D node count, to size the node-exchange ledger
cfgthe authored rows — read, never modified
warningsadvisory diagnostics appended here
Returns
a fatal diagnostic; empty on success.
Note
Takes what it needs rather than a SimulationContext. That is not tidiness: it is what lets the numerical gates build a mesh, a soil and a table in twenty lines and check a conservation identity, with no engine, no project file and no units. A kernel that can only be exercised through a full model is a kernel whose failures are found late.
Here is the call graph for this function:

◆ initPorewater()

std::string openswmm::twoD::SubsurfaceSolver::initPorewater ( )

Initialize canonical native inventories on fixed physical porous thermal layers.

Returns
Empty for success/inapplicable mode, otherwise layout/mapping initialization diagnostic or a caught std::exception message. Nonstandard exceptions are not caught.
Note
Requires initialized positive-count physical thermal layers, matching hydraulic/native row identity and SI retention data. Nonlayered mode projects existing SAT/UNSAT native inventories; SIGMA constructs overlap mapping (also for temperature-only geometry) and initial physical mass. Resets outgoing preset/age/contact bookkeeping, refreshes derived transport and temperature initial inventory where applicable. Mutates cell-by-cell and can fail after partial replacement; caller stages initialization. Does not create hydraulic water, change engine clock or take external ownership.
Here is the call graph for this function:

◆ initReactions()

std::string openswmm::twoD::SubsurfaceSolver::initReactions ( SimulationContext & ctx)

Resolve scoped subsurface expression laws into per-cell saturated/unsaturated reactors.

Parameters
[in,out]ctxPrepared compiled reaction system, borrowed through reactions_ on success; compiled token/term/species tables must remain alive and stable throughout solver use.
Returns
Empty for success/no laws, otherwise unsupported/uncompiled/missing-row/layer/scope or duplicate first-order-decay ownership diagnostic.
Note
Clears old reactor binding/identity before validation, allocates reactor forms/spans, applies GLOBAL<TAG<CELL and baseline-before-layer overrides, prepares workspace and serialized identity. Does not execute reactions or alter native mass. Failures can leave partial inactive reactor storage; allocations can throw. Requires valid prepared hydraulic/native model and exclusive initialization.
Here is the call graph for this function:

◆ initTransport()

void openswmm::twoD::SubsurfaceSolver::initTransport ( const RowLayoutLite & rows,
const GwTransportData * gw,
const std::vector< double > & pollut_decay,
std::vector< std::string > & warnings )

Size the rows and seed both stores from [GW_INITIAL_QUALITY]. Separate from initialize because the row layout needs the resolved [GW_*] sections, which the router owns. The layout names follow TransportPolicy order.

Parameters
pollut_decaythe engine's [POLLUTANTS] Kdecay column (1/s), row-aligned with the layout — what a [GW_SORPTION] row with no DECAY of its own falls back to.
[in]rowsResolved row counts, names and age/temperature indices in transport policy order. Counts, metadata and referenced species must be consistent; layout is copied, not retained.
[in]gwOptional resolved SI initial quality, dispersion, sorption and groundwater options. Null selects defaults. Borrowed only during this call; scoped layer overrides require SIGMA cells and are rejected for PER_SUBCATCH. Authored decay overrides are per day, converted to 1/s.
[in,out]warningsReserved shared initialization diagnostics; this implementation does not append to or clear this vector. Resolution warnings are produced by the upstream resolver.
Note
Clears existing transport, heat and related bookkeeping before testing activation. Inactive hydraulics or no rows leaves transport/heat empty. Otherwise allocates stores and node receipts, seeds native concentration times water volume, applies layered retention where configured, and records initial inventory. Caller initializes physical heat/porewater separately afterwards. Requires exclusive access and a prepared hydraulic/mesh identity. Allocation or invalid layered configuration can throw after partial clearing/allocation; this operation is not transactional.
Here is the call graph for this function:

◆ lidBedDiagnostics()

const std::vector< LidBedDiagnostic > & openswmm::twoD::SubsurfaceSolver::lidBedDiagnostics ( ) const
inline

Borrow the latest accepted LID/aquifer request/reservation/settlement samples per bed.

Returns
Solver-owned diagnostic vector: clocks elapsed s, heads m and directional water m3. A sample with end<=start is unavailable. No copy/history append/physical exchange occurs; read only while owner state is stable.

◆ lidReceiptsEnabled()

bool openswmm::twoD::SubsurfaceSolver::lidReceiptsEnabled ( ) const
inlinenoexcept

Read whether reviewed LID/aquifer receipt ownership was enabled.

Returns
Stored capability flag. Does not inspect a specific pending bed, validate a checkpoint or book any exchange; initially false until the owner configures the profile.
Here is the caller graph for this function:

◆ minDtCell()

double openswmm::twoD::SubsurfaceSolver::minDtCell ( ) const
inlinenoexcept

G1-c (2026-09-19): the smallest per-cell stability step after refreshDtCell (s), or 1e30 s when no stored value is smaller — the marcher folds it into the ladder's base step so a groundwater cell whose own bound is finer than every active surface cell's does not fire beyond it.

Returns
Minimum stored dt_cell value below the initial 1e30 s sentinel; NaNs do not reduce the minimum. An empty vector returns 1e30 s, not infinity. Caller refreshes dt_cell first; this getter does not validate signs/finiteness, recompute stability or change any tier.

◆ needsTransportRestart()

bool openswmm::twoD::SubsurfaceSolver::needsTransportRestart ( ) const
inlinenoexcept

Test whether current transport ownership requires its extended restart payload.

Returns
True for layered transport, nonempty age-generation ledger, hydraulic boundaries, reaction reactors, or active transport with any reviewed source-owned cell. False is not a complete checkpoint/profile eligibility check. No state is archived, validated or mutated.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ nodeBeds()

const std::vector< GwNodeBed > & openswmm::twoD::SubsurfaceSolver::nodeBeds ( ) const
inlinenoexcept

G-O: the [2D_AQUIFER_NODE] beds as resolved (cell index filled), in the authored order — parallel to SurfaceRouter2D::aquiferNodeNames().

Borrow resolved authored node/aquifer beds.

Returns
Solver-owned const vector in SI conductivity/thickness/area and zero-based node/cell indices. No copy, reset or receipt consumption occurs; initialization/restore/owner bookkeeping can change contents and invalidate element views. Caller keeps the solver stable and uses the matching node/bed/transport identity.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ nodeExchangeMass()

const std::vector< double > & openswmm::twoD::SubsurfaceSolver::nodeExchangeMass ( ) const
inlinenoexcept

T7.4: mass the aquifer owes each 1D node this batch ([s * n_nodes + node], + out of the aquifer), flushed by the router into the node's coupling queues alongside the volume.

Borrow per-batch node transport export in species-major [species*n_nodes+node] order.

Returns
Solver-owned const vector in native_concentration*m3, signed positive out of the aquifer. No copy, reset or receipt consumption occurs; initialization/restore/owner bookkeeping can change contents and invalidate element views. Caller keeps the solver stable and uses the matching node/bed/transport identity.

◆ nodeExchangeVolumes()

const std::vector< double > & openswmm::twoD::SubsurfaceSolver::nodeExchangeVolumes ( ) const
inlinenoexcept

Per-node exchange volume this advance (m³ SI, + out of the aquifer into the pipe). The router books it into nodes.coupling_volume through the same flow_2d_to_1d factor the surface exchange uses.

Borrow per-batch water exchange per 1D node.

Returns
Solver-owned const vector in m3, signed positive into the 1D node. No copy, reset or receipt consumption occurs; initialization/restore/owner bookkeeping can change contents and invalidate element views. Caller keeps the solver stable and uses the matching node/bed/transport identity.

◆ nodeRefunds()

long openswmm::twoD::SubsurfaceSolver::nodeRefunds ( ) const
inlinenoexcept

Firings on which a column went short and the node's share of the overdraw was refunded — into the aquifer's books alone, after the router had already paid the node. The defect's signature: 124 before G-W1, 0 after.

Returns
Stored count of node-share shortfall refunds since initialization. Reads historical solver diagnostic state only; does not prove all current transfers/balances are valid.

◆ nodeWaterBudget()

std::string openswmm::twoD::SubsurfaceSolver::nodeWaterBudget ( int cell,
double interval,
NodeWaterBudget & out ) const

Read a validated finite node-trial water budget for one aquifer cell.

Preflight a finite aquifer node-trial donor/receiver budget without booking water.

  • Argument cell (in): Prepared active cell ID.
  • Argument interval (in): Finite positive trial duration s.
    Returns
    Empty after replacing the borrowed NodeWaterBudget argument (head m, donor/receiver m3), otherwise diagnostic with output unchanged. Definition documents supported physics/reservations; requires stable prepared ownership and does not book water or advance clocks.
    Parameters
    [in]cellCovered prepared active cell index; rejects invalid/inactive input.
    [in]intervalFinite positive proposed duration s, including interval deep-loss reservation.
    [out]outReplaced only on success by SI head m, unreserved donor m3 and receiver headroom m3.
    Returns
    Empty on success; detailed refusal for material/geometry/storage, unsupported transported rows/wells/live sources, inconsistent equilibrium/SIGMA state or nonfinite pending/result values.
    Note
    Supports water-only or qualified temperature-only aquifers. Donor excludes ET/deep/outgoing link/lateral/LID/node claims; incoming promises do not fund it. ENSLAVED donor uses conserved equilibrium storage rather than an approximate constant yield. Requires prepared consistent arrays; no canonical mutation, reservation, allocation or clock advance. The caller adopts the accepted budget.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ options()

const GwOptions & openswmm::twoD::SubsurfaceSolver::options ( ) const
inlinenoexcept

Borrow the solver's resolved groundwater option copy.

Returns
Const solver-owned GwOptions, replaced on initialization/restore as applicable. Numeric runtime options follow their documented SI conventions; this does not return mutable authored rows or recompute automatic selections. No allocation or state change occurs.

◆ pendingBedDown()

double openswmm::twoD::SubsurfaceSolver::pendingBedDown ( int bed) const
noexcept

Sum gross unconsumed LID-to-aquifer water for one bed.

Parameters
[in]bedValid prepared index into node_pending_down_ and lid_receipts_, unchecked.
Returns
Pending sampled-node down reservation plus every queued reviewed receipt's down volume, m3. No cancellation against the opposite direction, queue drain or canonical mutation occurs. Requires stable producer queues; allocation-free ordinary summation may propagate nonfinite state.

◆ pendingBedUp()

double openswmm::twoD::SubsurfaceSolver::pendingBedUp ( int bed) const
noexcept

Sum gross unconsumed aquifer-to-LID water for one bed.

Parameters
[in]bedValid prepared index into node_pending_up_ and lid_receipts_, unchecked.
Returns
Pending sampled-node up reservation plus every queued reviewed receipt's up volume, m3. No cancellation against the opposite direction, queue drain or canonical mutation occurs. Requires stable producer queues; allocation-free ordinary summation may propagate nonfinite state.

◆ pendingHeat()

double openswmm::twoD::SubsurfaceSolver::pendingHeat ( int i) const
noexcept

Read signed unconsumed lateral physical heat for a cell.

Sum one cell's unconsumed incident physical conductive energy packets.

  • Argument cell (in): Prepared cell index, called i in source; invalid/absent heat mapping returns zero.
    Returns
    Pending inward J, without consuming packets or changing canonical energy. Stable matching edge/physical owner arrays are required; no allocation.
    Parameters
    [in]iPrepared cell index, called cell in the declaration; invalid or absent mapping returns zero.
    Returns
    Signed pending inward J over all incident sides/layers. Ordinary arithmetic can propagate nonfinite state; no receipt is consumed and canonical energy is unchanged. Requires stable matching edge/config/physical shapes; allocation-free.
Here is the caller graph for this function:

◆ pendingLidDown()

double openswmm::twoD::SubsurfaceSolver::pendingLidDown ( int cell) const
noexcept

Sum gross pending LID-to-aquifer water across one cell's beds.

Parameters
[in]cellValid prepared cell_beds_ index, unchecked; bed lookup/receipt shapes must match.
Returns
Sampled-node pending_down plus queued reviewed down m3 over all mapped beds. Retains gross directions independently rather than netting returns. Read-only/no allocation; caller serializes queue producers and must not interpret this as additional unreserved canonical water.

◆ pendingLidReceipts()

const std::vector< std::vector< PendingLidBed > > & openswmm::twoD::SubsurfaceSolver::pendingLidReceipts ( ) const
inline

Borrow per-bed queued accepted LID/aquifer interval receipts.

Returns
Const solver-owned nested vectors, indexed by resolved bed, with elapsed start/end s, gross down/up m3, paired heat J and heat-applied flags. Firings/retention/restore can invalidate entries; no receipt is consumed and opposite directions remain separate gross reservations.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pendingLidUp()

double openswmm::twoD::SubsurfaceSolver::pendingLidUp ( int cell) const
noexcept

Sum gross pending aquifer-to-LID water across one cell's beds.

Parameters
[in]cellValid prepared cell_beds_ index, unchecked; bed lookup/receipt shapes must match.
Returns
Sampled-node pending_up plus queued reviewed up m3 over all mapped beds. Retains gross directions independently rather than netting returns. Read-only/no allocation; caller serializes queue producers and must not interpret this as additional unreserved canonical water.
Here is the caller graph for this function:

◆ pendingLidWater()

double openswmm::twoD::SubsurfaceSolver::pendingLidWater ( ) const
noexcept

Read signed water stored in reviewed LID receipt queues awaiting groundwater adoption.

Returns
Sum(down-up) m3 over queued receipts only. Excludes separate node_pending_down/up ledgers; positive is LID-to-aquifer and negative aquifer-to-LID. Does not consume queues or include canonical soil/LID water. Requires stable queues; allocation-free ordinary arithmetic, no validation.

◆ pendingSaturatedMassExport()

double openswmm::twoD::SubsurfaceSolver::pendingSaturatedMassExport ( int cell,
int species ) const
noexcept

Sum nonnegative queued saturated native inventory exports.

Parameters
[in]cellValid prepared cell with matching edge CSR; unchecked.
[in]speciesValid transport row with consistent edge-major lateral arrays; unchecked.
Returns
Reserved native inventory from lout_mass and this cell's outward lateral side packets. Negative values are excluded from the reservation, including signed-row negative receipts.
Note
Read-only; does not consume mass, include future node exports, or validate array extents. Caller pairs this with the same stable transport/hydraulic producer state.
Here is the caller graph for this function:

◆ pendingSourceReceipts()

const std::vector< SurfaceIntakeReceipt > & openswmm::twoD::SubsurfaceSolver::pendingSourceReceipts ( int cell) const
inline

Borrow queued reviewed-source intake provenance for one receiver cell.

Parameters
[in]cellValid source_receipts_ vector index.
Returns
Const solver-owned receipt vector; water m3, times s, native species inventory. New retention/firing/restore may invalidate elements. No receipt is consumed or copied.
Exceptions
std::out_of_rangeOn an invalid cell; caller provides stable solver access.

◆ pendingSurfaceCells()

const std::vector< int > & openswmm::twoD::SubsurfaceSolver::pendingSurfaceCells ( ) const
inlinenoexcept

Cells with pending surface-bound water, so the marcher can pin them active (a dry surface cell above an exfiltrating column must route). Call compactPending() first — takeToSurface clears flags but does not erase from this list, because it runs inside the parallel cell loop.

Returns
Borrowed solver-owned cell list, potentially containing already drained entries until compactPending(). List mutation/restore/initialization invalidates element views. Water receipts are not consumed by this query; caller serializes list rebuild with firings.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ publishInfiltration()

void openswmm::twoD::SubsurfaceSolver::publishInfiltration ( SurfaceStateData & surf,
double interval,
double time )

Publish the aquifer's held rate; publication never restores spent storage.

Refresh published intake capacity and available volume for every groundwater cell.

Parameters
[in,out]surfSurface state receiving infil_rate where that array covers a cell. Missing surface depths are treated as zero ponding; the remaining groundwater arrays must be prepared.
[in]intervalPositive publication duration s. Inactive solver or nonpositive/NaN duration returns without work; caller supplies a finite value for meaningful volume/rate conversion.
[in]timeElapsed refresh timestamp s, stored without validation.
Note
Updates per-cell infil_remaining, infil_capacity, infil_refresh and infil_interval. Does not accept water or advance either solver. Caller serializes publication with all producers.

◆ publishNodeConcentrations()

void openswmm::twoD::SubsurfaceSolver::publishNodeConcentrations ( const SimulationContext & ctx)

T7.4: the node's own species row, [node * n_species + s], published by the router each batch — what a RECHARGING node's water carries down its bed. Null (or a zero row count) means the seam moves water only, which is what every pre-T7.4 deck did.

Copy current canonical 1D composition into a stable groundwater producer tuple buffer.

Parameters
[in]ctxPrepared matching node pollutant/MSX/age/heat state. MSX is matched by exact row name; missing optional backing entries yield zero. Age remains seconds and temperature degC.
Note
Replaces node_concentrations_ in node-major [node*n_species+row] order, then binds the solver's borrowed node_row_conc_ to this owned buffer. Invalidates prior buffer views. Allocates and can throw before rebinding; caller must not use a stale prior pointer after a failed replacement. Does not advance nodes, book water/native mass or change external context; requires serial producer setup.
Here is the call graph for this function:

◆ publishRk2Infiltration()

void openswmm::twoD::SubsurfaceSolver::publishRk2Infiltration ( SurfaceStateData & surface,
double dt,
double time )

Publish the current coupled stage's bounded instantaneous intake capacity.

Publish one RK2 stage's instantaneous closure-dependent surface intake rate.

  • Argument dt (in): Finite positive stage duration s.
  • Argument time (in): Finite elapsed refresh time s.
    Note
    The surface reference receives matching per-cell m/s rates. Requires validated RK2 profile, prepared arrays and exclusive staged access; can throw after partial publication. Zero-front startup uses a finite integrated rate. Canonical water/native inventories are unchanged.
    Parameters
    [in,out]surfaceMatching prepared surface depth/rate arrays; writes infil_rate for covered cells.
    [in]dtFinite positive stage duration s, required for headroom cap and singular-front startup.
    [in]timeFinite elapsed stage publication timestamp s.
    Note
    Uses SIGMA top-layer capacity or the bulk instantaneous Green-Ampt derivative. At a zero front, uses finite integrated startup rather than claiming second order through the singular event. Caps against unreserved m3/(area*dt), writes capacity/remaining/refresh/interval and throws on inadmissible rate. Earlier cells remain published on failure. No accepted water, native mass or engine clock is advanced; requires prepared stable arrays and exclusive staged state access.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rechargeBackend()

const GwRechargeBackend & openswmm::twoD::SubsurfaceSolver::rechargeBackend ( ) const
inlinenoexcept

Borrow the current optional raw-recharge extension descriptor.

Returns
Solver-owned const callback/capability/diagnostic reference. Stable only while the solver and descriptor are unchanged; evaluation failure can disable its evaluator/update diagnostic. No capability probe, callback or allocation occurs in this getter.

◆ rechargeBatches()

uint64_t openswmm::twoD::SubsurfaceSolver::rechargeBatches ( ) const
inlinenoexcept

Read successful validated raw-recharge extension batch evaluations.

Returns
Cumulative successful nonempty batches since initialize(), excluding rejected/CPU-only batches. Getter does not invoke the extension or reset counters.

◆ rechargeCells()

uint64_t openswmm::twoD::SubsurfaceSolver::rechargeCells ( ) const
inlinenoexcept

Read the cumulative raw-recharge input rows accepted from successful extension batches.

Returns
Processed cell-row count, including repeated cells across firings/batches, since initialize(). It is not unique covered mesh cells and excludes rejected/CPU-fallback batches.

◆ rechargeThreads()

int openswmm::twoD::SubsurfaceSolver::rechargeThreads ( ) const
inlinenoexcept

Query the extension's recorded worker-team size when that callback exists.

Returns
threads() result, otherwise zero for no callback. No positivity/capability validation or parallel execution is performed by this getter. Callback must not throw because this method is noexcept; caller ensures serialized callback/library lifetime.

◆ refreshDtCell()

void openswmm::twoD::SubsurfaceSolver::refreshDtCell ( const MeshData & mesh,
const InertialEdges & edges )

Per-cell stability step min(Δt_g, Δt_u), written into state_.dt_cell. Called once per rebuild; cheap enough to be unconditional (the plan's "they rarely bind").

Recompute each active groundwater cell's explicit water/transport/thermal stability duration.

Parameters
[in]meshStable SI centroids for dispersion gradients, matching prepared hydraulic cells.
[in]edgesMatching saturated-flow CSR/face geometry; PER_SUBCATCH may have no lateral faces.
Note
Inactive returns. Writes dt_cell s from minimum saturated Darcy/boundary/node/deep sink limit, closure-specific unsaturated relaxation/SIGMA bound, optional skew/tensor-dispersion bound and thermal maximum/lateral limits. Uses current moisture/table and previous q0_last for column motion. Does not assign tiers, fire physics, settle receipts or advance clocks. Requires consistent parallel arrays, finite resolved controls and exclusive state access; forcing-series ordinates are borrowed read only.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ refreshPorewaterContactLedger()

std::string openswmm::twoD::SubsurfaceSolver::refreshPorewaterContactLedger ( )

Rebuild the signed soil-side contact receipt from the canonical layer increments after the mesh/channel synchronization has settled.

Returns
Empty after rebuilding native signed gained_contact per species from physical-layer contact_mass (temperature excluded), or diagnostic for incompatible shape/nonfinite increment/sum.
Note
Inactive/absent ledger returns. Layered mode refreshes canonical/derived views first, then zeros and accumulates the ledger. A failure can leave partial views or a partial rebuilt ledger; refreshView() exceptions propagate. Does not consume physical contact receipts, book water or advance clocks. Requires serial stable physical/native owner access.
Here is the call graph for this function:

◆ refreshSigmaPorewater()

std::string openswmm::twoD::SubsurfaceSolver::refreshSigmaPorewater ( int i)

Rebuild fixed-depth porewater overlap/reservations from accepted SIGMA state.

Reconcile the current SIGMA canonical reactors with fixed-depth physical porewater views.

  • Argument cell (in): Valid prepared cell index, called i in the definition.
    Returns
    Empty on success/skip or mapping diagnostic. May allocate/throw after partial canonical or derived publication; requires exclusive matching physical/SIGMA owners. Does not advance water/time.
    Parameters
    [in]iValid prepared cell index, called cell in the declaration; unchecked.
    Returns
    Empty for success/nonlayered/inactive/empty column, otherwise publish/configure diagnostic.
    Note
    Publishes preceding physical contact changes into SIGMA first, builds exact hydraulic/physical overlap water/bulk volumes at the moving table, copies canonical layer/SAT inventories and current saturated export reservations, then configures the overlap map and refreshes physical views. Fixed grain retention is rederived geometrically to preserve model identity. Allocates and may throw; reported failure can follow earlier canonical/derived changes. Requires matching prepared shapes, positive layer counts and exclusive hydraulic/thermal/native access. No water or time advance.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ refreshSigmaPorewaterReservations()

void openswmm::twoD::SubsurfaceSolver::refreshSigmaPorewaterReservations ( int cell)
noexcept

Refresh one cell's physical/SIGMA outgoing reservation view without propagating exceptions.

Parameters
[in]cellValid prepared thermal cell index, unchecked even on failure handling.
Note
Calls refreshSigmaPorewater(); diagnostic or exception marks heat_.cells[cell].failed. A reported diagnostic is copied into error where possible; catch-all only sets failed. Partial refresh changes remain. Caller checks failure before adoption and provides exclusive owner access.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ requiredTiers()

int openswmm::twoD::SubsurfaceSolver::requiredTiers ( double dt0) const
noexcept

Minimum tier count the ladder needs so it reaches the slowest GW cell (K ≥ 1 + ⌈log2(Δt_gw_max/dt0)⌉, G-A point 3). The marcher grows its ladder to this before assigning.

Parameters
[in]dt0Finite positive candidate base step s; inactive/nonpositive returns one.
Returns
max(1,ceil(log2(max(dt_cell)/dt0))+1), enough binary tiers to cover the largest stored limit. Nonfinite maximum or maximum<=dt0 returns one. No maximum cap is applied; representability of the log ratio as int is a caller precondition. Does not refresh limits, assign tiers or mutate state.

◆ resetNodeExchangeVolumes()

void openswmm::twoD::SubsurfaceSolver::resetNodeExchangeVolumes ( )
noexcept

Zero the per-node ledger at the start of a routing batch.

Clear the per-batch node water exchange and held-node-water draw reservations.

Note
Zeros node_exchange_vol_ and node_drawn_gw_ only. Does not clear transport mass, bed accumulators, cumulative diagnostics or canonical storage. Call serially at the batch boundary, before samples that must share the same node draw budget; no allocation occurs.

◆ restorePendingSurface()

void openswmm::twoD::SubsurfaceSolver::restorePendingSurface ( )
inline

Rebuild pending-surface cell flags/list from positive xacc_to_surface water.

Note
Clears prior list and flags, then marks each prepared cell whose queued outward volume is positive. Requires pending_flag_ and xacc_to_surface sized for state_.n_cells. Does not drain water or alter canonical storage. Serial rebuild invalidates list element views; markPendingSurface() is noexcept but its vector push may allocate, so allocation failure there terminates the process.

◆ restoreTransportRestart()

std::string openswmm::twoD::SubsurfaceSolver::restoreTransportRestart ( const std::string & bytes,
bool apply )

Validate or adopt an extended groundwater hotstart against this prepared model identity.

Parameters
[in]bytesBinary envelope from transportRestartState(), borrowed only for the call. Empty is accepted only when this model needs no extended transport/source-clock restart profile.
[in]applyFalse performs full private read/validation only; true move-adopts the validated private solver and rebinds its owned node concentration pointer when present.
Returns
Empty on accepted compatible state, otherwise missing/unknown/mismatched model/profile or caught std::exception diagnostic. Reported validation errors leave this live solver unchanged.
Note
Requires initialized matching mesh, species, units, layers, forcing/reaction/thermal identity and completed owner phase. Verifies complete envelope/payload consumption before adoption; no file I/O, 1D owner restore or engine calendar change occurs. External bindings must stay alive and access serialized. Nonstandard exceptions are not caught; enclosing engine restore coordinates its other canonical owners and publication rather than treating this as a standalone whole-model restart.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ retainLidReceipts()

std::string openswmm::twoD::SubsurfaceSolver::retainLidReceipts ( double start,
double end,
const std::vector< RichardsBedReceipt > & rows )

Adopt a completed reviewed Richards water/heat receipt interval.

Retain one completed paired Richards interval after shared groundwater capacity preflight.

  • Argument start (in): Finite nonnegative start s, matching each bed's previous booked horizon.
  • Argument end (in): Finite end s, greater than start.
    Note
    The receipt-vector argument is borrowed and copied; node/bed/cell identity, gross m3 and J must be paired and within frozen shared budgets. Returns empty on acceptance or diagnostic before ordinary validation adoption. Explicit heat refusal restores staged thermal reservations; allocation exceptions can leave partial publication. Definition documents phase/ownership and detailed effects.
    Parameters
    [in]startFinite nonnegative elapsed interval start s, exactly each bed's prior booked end.
    [in]endFinite elapsed end s, strictly greater than start.
    [in]rowsUnique owned-bed receipts with matching node/cell identity and finite nonnegative accepted down/up m3 plus finite signed sensible J. Zero accepted water requires zero associated J. Both directions retain gross provenance; borrowed data is copied into queues on success.
    Returns
    Empty after adopting receipts/bed clocks/diagnostics/cumulative volumes; diagnostic for stale/unpaired layout/time, unsupported heat, shared donor/receiver budget or physical heat refusal.
    Note
    Validates all rows and aggregate cell budgets before books, derives missing producer J where qualified, and reserves outgoing aquifer sensible heat/capacity at producer time. Stages thermal snapshots and restores them on explicit heat-reservation refusal. Queue allocation occurs before most publication, but active-heat zero-volume push/copy exceptions can still interrupt later booking; no universal exception rollback. Does not settle groundwater table or debit canonical LID water. Requires enabled initial profile, prepared consistent arrays and exclusive coupled-owner access.
Here is the call graph for this function:

◆ retainSourceReceipt()

void openswmm::twoD::SubsurfaceSolver::retainSourceReceipt ( const SurfaceIntakeReceipt & r)

Retain intake provenance for a reviewed-source-owned positive receipt.

Parameters
[in]rReceipt with a valid prepared request.cell index, elapsed times s, volume m3 and matching native row amounts. Cell access is unchecked even when volume is nonpositive.
Note
Owned positive receipts are copied into the cell queue; other receipts are ignored. The copy owns its vector payload and can allocate/throw. Does not book water/mass or validate row identity, time, signs or finiteness. Caller serializes queue access and pairs accepted bookings.
Here is the caller graph for this function:

◆ richardsBedDownCumulative()

const std::vector< double > & openswmm::twoD::SubsurfaceSolver::richardsBedDownCumulative ( ) const
inlinenoexcept

Borrow cumulative accepted LID-to-aquifer water per resolved bed.

Returns
Solver-owned const vector in m3, gross nonnegative down. No copy, reset or receipt consumption occurs; initialization/restore/owner bookkeeping can change contents and invalidate element views. Caller keeps the solver stable and uses the matching node/bed/transport identity.

◆ richardsBedUpCumulative()

const std::vector< double > & openswmm::twoD::SubsurfaceSolver::richardsBedUpCumulative ( ) const
inlinenoexcept

Borrow cumulative accepted aquifer-to-LID water per resolved bed.

Returns
Solver-owned const vector in m3, gross nonnegative up. No copy, reset or receipt consumption occurs; initialization/restore/owner bookkeeping can change contents and invalidate element views. Caller keeps the solver stable and uses the matching node/bed/transport identity.

◆ rk2ProfileError()

std::string openswmm::twoD::SubsurfaceSolver::rk2ProfileError ( ) const

Coupled SSP-RK2: spatial CLOSED_FORM/ENSLAVED/SIGMA water only, authored wells and HEAD/FLOW edges.

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

◆ runtimeSources() [1/2]

const RuntimeSources & openswmm::twoD::SubsurfaceSolver::runtimeSources ( ) const
inlinenoexcept

Borrow read-only copied runtime source prescriptions, receipts and derived lookups.

Returns
Solver-owned const RuntimeSources reference; owner must remain alive/stable during access. Initialization, restore or replacement can replace contents/invalidate element views. No copy, validation, allocation or receipt consumption occurs.

◆ runtimeSources() [2/2]

RuntimeSources & openswmm::twoD::SubsurfaceSolver::runtimeSources ( )
inlinenoexcept

Borrow mutable copied runtime source prescriptions, receipts and derived lookups.

Returns
Solver-owned RuntimeSources reference. Caller retains no ownership and must preserve prepared shapes, identity, receipt phase and matched hydraulic/quality/thermal invariants. Mutations require exclusive solver access and appropriate owner/cache reconstruction before further firings. Initialization, restore or solver replacement can replace contained vectors and invalidate views; this getter performs no validation, allocation or synchronization.
Here is the caller graph for this function:

◆ sampleNodeExchange()

void openswmm::twoD::SubsurfaceSolver::sampleNodeExchange ( const NodeData * nodes,
double dt,
double end = -1 )

Node ↔ aquifer exchange, evaluated at tier-0 cadence against the batch-frozen 1D heads and booked into nacc (G-B row 3). The GW cell gathers its share when IT fires — the node is never pinned to the aquifer's tier and the aquifer is never pinned to tier 0.

Parameters
nodes1D node data, or nullptr when nothing is coupled.
[in]dtFinite positive sampling duration s, required by the caller; no duration validation is performed here. Caps use max(dt,kTiny), whereas accepted volume uses Q*dt directly.
[in]endElapsed sample end time s for mobile-LID diagnostics; a negative value selects the receiver cell's completed time. Does not advance the cell or node clock.
Note
Requires stable, prepared node parallel arrays and solver bed/cell/transport shapes. Node heads/held volume/inflow use the 1D engine units and are converted to SI; producer concentration is borrowed from setNodeRowConc(). Positive water is aquifer-to-node. Reserves gross donor water, receiver capacity and node held-water shares, books nacc and paired incoming native inventory, and updates diagnostics. Canonical aquifer storage and 1D node state are changed by later gathers. Inactive hydraulics, absent beds or null nodes returns without work. Beds owned by Richards are skipped. Caller serializes samples and resets only the appropriate batch ledgers between advances. A rejected reviewed node budget throws std::runtime_error; prior beds' bookings remain applied.
Here is the call graph for this function:

◆ satVolume()

double openswmm::twoD::SubsurfaceSolver::satVolume ( int cell) const
inlinenoexcept

Water volume of one cell's saturated zone (m³) — the denominator for a saturated concentration.

Parameters
[in]cellValid prepared cell index in [0,state_.n_cells); bounds are unchecked.
Returns
hg*theta_s*area in m3, with saturated retained plus drainable water. Does not subtract pending exports or reservations, clamp negative inputs, or validate finite state.
Here is the caller graph for this function:

◆ setBoundaries()

void openswmm::twoD::SubsurfaceSolver::setBoundaries ( std::vector< GwResolvedBoundary > rows)

Replace validated SI exterior boundaries and rebuild their per-cell lookup/stability.

Replace resolved exterior groundwater boundaries and rebuild cell lookup/stability.

Note
The by-value vector is moved into the solver; all row cell indices must be valid prepared IDs. Prior boundary receipts are replaced. Can allocate/throw after partial replacement; requires exclusive access and no pending reconfiguration-sensitive exchange. Definition details its argument.
Parameters
[in]rowsOwned resolved SI boundaries, moved into solver. Every row.cell must be a valid prepared cell and its signal/geometry/quality metadata must be validated before this call.
Note
Replaces boundaries_, allocates cell_boundaries_, then refreshes dt_cell if mesh/edges are bound. Does not validate all row indices, clear existing physical side packets or preserve old boundary cumulative receipts. Allocation/refresh failure can leave partial new mapping. Caller serializes reconfiguration before producer work and preserves model identity across checkpoints.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ setLidBedClogging()

void openswmm::twoD::SubsurfaceSolver::setLidBedClogging ( int bed,
double factor )
inline

Replace the multiplier applied to one resolved bed's subsequent node exchange conductance.

Parameters
[in]bedValid lid_bed_factor_ index.
[in]factorIntended finite nonnegative dimensionless conductance factor; no finite/range check or clipping is performed here.
Exceptions
std::out_of_rangeOn invalid bed. Changes no already accepted water/receipt and performs no ownership activation; caller serializes the update with node sampling.

◆ setNodeRowConc()

void openswmm::twoD::SubsurfaceSolver::setNodeRowConc ( const double * rows,
int n_species )
inlinenoexcept

Borrow node-major producer composition for subsequent node/aquifer exchanges.

Parameters
[in]rowsOptional contiguous buffer [node*n_species+species] covering every referenced 1D node. Values use each row's native concentration, age or temperature units. Null disables pairing.
[in]n_speciesPublished row stride/count; zero disables pairing, otherwise must match the prepared transport identity. Negative values and buffer extents are not validated.
Note
Stores the pointer without copying/ownership. Caller keeps data alive/unchanged until replaced or all consuming node samples complete. No receipts, water or species are booked here.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ setRechargeBackend()

void openswmm::twoD::SubsurfaceSolver::setRechargeBackend ( GwRechargeBackend backend)
inline

Replace the owned optional pure raw-recharge evaluator descriptor.

Parameters
[in]backendOwned callback/capability/diagnostic value moved into the solver. Empty evaluate selects ordinary CPU computation. Captured plugin/library resources must remain valid through every callback; this method performs no probing, ABI validation or output-cache reset itself.
Note
Caller serializes replacement with all firings. Existing batch/cell telemetry is retained; validation/fallback of evaluated results occurs in prepareRechargeBatch().

◆ setSources()

void openswmm::twoD::SubsurfaceSolver::setSources ( std::vector< GwResolvedSource > sources)

Replace resolved project aquifer sources and rebuild per-cell weighted lookup.

Parameters
[in]sourcesOwned resolved SI source definitions, moved into solver. Invalid cell entries are skipped, while source signal/species shapes and weights must already be validated.
Note
Clears runtime_sources_ including callbacks/receipts, replaces sources_ and cell_sources_. Does not clear pending physical water/native packets, recalculate tiers or initialize runtime driver bindings. Allocations may leave a partial mapping; reconfigure serially before new source work.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ settle()

void openswmm::twoD::SubsurfaceSolver::settle ( SurfaceStateData & surf)

Compact drained surface-return bookkeeping before scheduler transitions. Pending edge/node water remains owned until the next paired cell firing.

Parameters
[in,out]surfRetained interface argument, unused; canonical surface state is unchanged.
Note
Compacts the pending surface list and clears accumulators_pending_ only. It deliberately does not turn pending water into table height or consume water/native/heat packets: the paired moving unsaturated/saturated update belongs to fireCell(). Continuity/checkpoints must include outstanding accumulators. Requires serial bookkeeping; no allocation or physical firing occurs.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sourceCompletedTime()

double openswmm::twoD::SubsurfaceSolver::sourceCompletedTime ( int cell) const
inline

Read the receiver's completed reviewed-source horizon.

Parameters
[in]cellValid source_cell_end_ index.
Returns
Elapsed seconds stored for that cell, independent of the global source/engine clock.
Exceptions
std::out_of_rangeOn invalid cell. No queue drain, validation or synchronization occurs.

◆ sourceInfiltrationCapacity()

double openswmm::twoD::SubsurfaceSolver::sourceInfiltrationCapacity ( int i,
double pond,
double interval ) const
noexcept

Read-only soil/interface rate (m/s) for the actual donor pond head. Group headroom is allocated separately; no front or held rate advances.

Compute a closure-dependent ponded intake rate without reserving volume.

  • cell: Covered receiver cell, called i in the definition.
  • pond_m: Finite nonnegative ponding depth m, called pond in the definition.
  • interval_s: Finite positive intake duration s, called interval in the definition.
    Returns
    Nonnegative closure-dependent intake rate m/s, before receiver headroom/reservations. Zero on inactive/uncovered/invalid input or nonfinite result; no mutation occurs.
    Parameters
    [in]iReceiver cell index; inactive or uncovered returns zero.
    [in]pondFinite nonnegative ponding depth m; invalid returns zero.
    [in]intervalFinite positive intake duration s; invalid returns zero.
    Returns
    Finite nonnegative capacity m/s, or zero for invalid geometry/result. SIGMA uses top-layer suction and half-layer length, ENSLAVED uses saturated conductivity and ponding, and bulk closure integrates a wetting front over interval. This rate is not capped by pending receiver headroom.
    Note
    Requires prepared finite material/closure arrays and valid layer count. No booking, clock advance, state mutation or allocation occurs.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sourceReceiptOwnershipBound()

bool openswmm::twoD::SubsurfaceSolver::sourceReceiptOwnershipBound ( ) const
inline

Internal reviewed-source ownership. Must bind before pending exchange.

Returns
True when any reviewed source_owned_ flag is set. An allocated all-false mask is not considered bound. Does not inspect pending receipts or current aquifer activation; no mutation.
Here is the caller graph for this function:

◆ sourceReturns()

const std::vector< SurfaceReturnReceipt > & openswmm::twoD::SubsurfaceSolver::sourceReturns ( ) const
inline

Borrow queued source-attributed refunds and physical emergence.

Returns
Const solver-owned return vector; availability times s, water m3, native transport amounts and donor provenance where relevant. Valid during stable solver access; acknowledgment, firing, retention or restore can change/invalidate elements. No queue consumption occurs.

◆ specificYieldOf()

double openswmm::twoD::SubsurfaceSolver::specificYieldOf ( int cell) const
noexcept

The specific yield the column ACTUALLY uses for cell, from the one definition. Exposed so a test never re-derives it: re-deriving only the CLOSED_FORM branch (as the first version of the G-W1b guard did) silently computes a number the solver never uses under SIGMA or ENSLAVED, and agrees only for as long as every fixture is closure A.

Parameters
[in]cellPrepared hydraulic cell; negative/out-of-range hg index returns zero. Remaining parallel cell/material arrays must have matching extents and valid closure parameters.
Returns
Closure-specific dimensionless specific yield with its positive kSyFloor lower bound, using max(zs-hg,0) as unsaturated length. No receipt reservations are subtracted and no storage, clock or diagnostic changes occur.
Here is the caller graph for this function:

◆ state() [1/2]

const SubsurfaceState & openswmm::twoD::SubsurfaceSolver::state ( ) const
inlinenoexcept

Borrow read-only canonical SI hydraulic state and accumulators.

Returns
Solver-owned const SubsurfaceState reference; owner must remain alive/stable during access. Initialization, restore or replacement can replace contents/invalidate element views. No copy, validation, allocation or receipt consumption occurs.

◆ state() [2/2]

SubsurfaceState & openswmm::twoD::SubsurfaceSolver::state ( )
inlinenoexcept

Borrow mutable canonical SI hydraulic state and accumulators.

Returns
Solver-owned SubsurfaceState reference. Caller retains no ownership and must preserve prepared shapes, identity, receipt phase and matched hydraulic/quality/thermal invariants. Mutations require exclusive solver access and appropriate owner/cache reconstruction before further firings. Initialization, restore or solver replacement can replace contained vectors and invalidate views; this getter performs no validation, allocation or synchronization.
Here is the caller graph for this function:

◆ storage()

double openswmm::twoD::SubsurfaceSolver::storage ( ) const
inlinenoexcept

Storage now, for the continuity ledger.

Returns
state_.storage() in m3: physical saturated plus maintained unsaturated storage, excluding side/pending accumulators. Uses prepared state extents without new validation; for queued holdings/ledger phase distinctions use the corresponding SubsurfaceState helpers.
Here is the caller graph for this function:

◆ takeToSurface()

double openswmm::twoD::SubsurfaceSolver::takeToSurface ( int cell)
noexcept

Volume (m³) the subsurface owes the surface twin — Dunne and exfiltration — drained by the surface at its firing.

Parameters
[in]cellPrepared receiver cell; inactive/invalid returns zero.
Returns
Entire pending outward water volume m3, then zeros xacc_to_surface and clears its pending flag. Does not erase from the shared pending list, modify canonical water or drain native mass.
Note
Independent cells may drain concurrently. Pair once with native mass delivery, then compact the pending list serially; repeated draining returns zero until another producer books water.

◆ takeToSurfaceMass()

double openswmm::twoD::SubsurfaceSolver::takeToSurfaceMass ( int cell,
int species )
noexcept

…and takes back what saturation excess and rejection carried up. Drained by the surface cell in the same call that takes the water.

Parameters
[in]cellReceiver cell; invalid/inactive transport returns zero.
[in]speciesTransport row; invalid returns zero.
Returns
Entire queued xacc_to_surface native inventory, then resets that slot to zero. Signed rows may return signed amounts. No partial gather fraction, bounds validation of prepared arrays, water removal or finite-value check occurs. Pair once with the corresponding surface water drain; independent slots may be drained separately, but competing access to the same slot is unsafe.

◆ tierCount()

int openswmm::twoD::SubsurfaceSolver::tierCount ( ) const
inlinenoexcept

Read the number of stored groundwater cell-tier lists.

Returns
cells_by_tier_.size() converted to int; prepared tier counts must fit int. Does not validate the matching face lists or initialize/retier the solver.

◆ tierFirings()

const std::vector< long > & openswmm::twoD::SubsurfaceSolver::tierFirings ( ) const
inlinenoexcept

Per-tier firing counts — the G-A telemetry (swmm_gw2d_get_tier_histogram).

Returns
Borrowed solver-owned per-tier firing counters in tier order, reset/replaced by owner initialization/tier management. Not wall-clock time or face-count telemetry. Stable read access requires no concurrent firing or retiering; no copy/allocation/reset occurs here.

◆ tierHasCells()

bool openswmm::twoD::SubsurfaceSolver::tierHasCells ( int tier) const
inlinenoexcept

True when the tier's cell list is non-empty.

Test whether one stored tier has a nonempty firing list.

Parameters
[in]tierZero-based tier index; negative/out-of-range returns false.
Returns
Nonempty cells_by_tier_ entry. Does not recompute tiers, validate indices inside the list or imply the tier is currently due; allocation-free and read-only.
Here is the caller graph for this function:

◆ tierHasFaces()

bool openswmm::twoD::SubsurfaceSolver::tierHasFaces ( int tier) const
inlinenoexcept

Test whether one stored tier has a nonempty firing list.

Parameters
[in]tierZero-based tier index; negative/out-of-range returns false.
Returns
Nonempty faces_by_tier_ entry. Does not recompute tiers, validate indices inside the list or imply the tier is currently due; allocation-free and read-only.
Here is the caller graph for this function:

◆ transport() [1/2]

const SubsurfaceTransportState & openswmm::twoD::SubsurfaceSolver::transport ( ) const
inlinenoexcept

Borrow read-only native species/age/temperature transport inventories and ledgers.

Returns
Solver-owned const SubsurfaceTransportState reference; owner must remain alive/stable during access. Initialization, restore or replacement can replace contents/invalidate element views. No copy, validation, allocation or receipt consumption occurs.

◆ transport() [2/2]

SubsurfaceTransportState & openswmm::twoD::SubsurfaceSolver::transport ( )
inlinenoexcept

The transported tuple, sized from TransportPolicy at initTransport and inert (active() == false) until then.

Borrow mutable native species/age/temperature transport inventories and ledgers.

Returns
Solver-owned SubsurfaceTransportState reference. Caller retains no ownership and must preserve prepared shapes, identity, receipt phase and matched hydraulic/quality/thermal invariants. Mutations require exclusive solver access and appropriate owner/cache reconstruction before further firings. Initialization, restore or solver replacement can replace contained vectors and invalidate views; this getter performs no validation, allocation or synchronization.
Here is the caller graph for this function:

◆ transportRestartState()

std::string openswmm::twoD::SubsurfaceSolver::transportRestartState ( ) const

Capture the extended groundwater continuation needed beyond the ordinary hotstart payload.

Returns
Owned binary envelope containing profile, exact model identity and mutable completed state; empty when needsTransportRestart() is false. Not a portable human-readable result/history format.
Note
Copies this solver privately, serializes model/state and includes pending native/physical/ source/LID receipt ownership. Requires a stable completed phase and live external bindings. Does not write files or mutate the live solver; allocation/unsupported-state/archive exceptions propagate. Borrowed callbacks/context/geometry are not independently made durable by these bytes.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unreservedDrainableWater() [1/2]

double openswmm::twoD::SubsurfaceSolver::unreservedDrainableWater ( int cell) const
noexcept

Compute drainable aquifer water after gross promised exports.

Parameters
[in]cellValid prepared cell index, with consistent bed/edge/contact arrays; unchecked.
Returns
max(0,specificYieldOf(cell)*hg*area-reserved), m3. Reservations include outgoing link, lateral and LID/node receipts; layered ledgers preserve gross exports even when net water cancels.
Note
Does not add pending incoming water, consume any reservation or validate physical state. Read-only and allocation-free; requires stable producer ledgers.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unreservedDrainableWater() [2/2]

double openswmm::twoD::SubsurfaceSolver::unreservedDrainableWater ( int cell,
double specific_yield ) const
noexcept
Here is the call graph for this function:

◆ unsatVolume()

double openswmm::twoD::SubsurfaceSolver::unsatVolume ( int cell) const
inlinenoexcept

…and of its unsaturated column store (m³), whatever closure holds it.

Parameters
[in]cellValid prepared cell index; all hu/area arrays must cover it.
Returns
state_.hu[cell]*area[cell] in m3. Uses the maintained bulk/derived hu field directly, including SIGMA's maintained view; it does not integrate theta_sigma or include queued receipts. No index, finite-value or physical-bounds checks occur.
Here is the caller graph for this function:

Friends And Related Symbol Documentation

◆ acceptRichardsBedsAcrossSteps

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

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.

◆ acceptRichardsBedsAtFiring

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

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 acceptRichardsBedsForTier ( SubsurfaceSolver & gw,
SurfaceStateData & surface,
int tier,
double start,
double end,
const std::vector< RichardsBedOwner > & owners )
friend

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

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.

◆ CommonSourceStage

friend class CommonSourceStage
friend

◆ ExplicitInertialSolver

friend class ExplicitInertialSolver
friend

The documentation for this class was generated from the following files: