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

#include <QualityRouting.hpp>

Collaboration diagram for openswmm::quality::QualitySolver:

Public Member Functions

void init (int n_nodes, int n_links, int n_pollutants)
 Set the solver's pollutant row count for subsequent routing/assembly.
 
void execute (SimulationContext &ctx, double dt)
 Execute one quality routing timestep.
 
FvTransportWater & fvWater () noexcept
 
bool fvTransportAccepted () const noexcept
 
bool hasFvRetainedDryMass () const noexcept
 
std::string fvDryRestartState (const SimulationContext &ctx) const
 
std::string restoreFvDryRestart (SimulationContext &ctx, const std::string &blob, bool apply)
 
std::vector< double > fvRetainedPollutantMass (const SimulationContext &ctx) const
 
std::vector< double > fvRetainedSpeciesMass (const SimulationContext &ctx) const
 
void beginFvWindow () noexcept
 
void assembleExternalLoads (SimulationContext &ctx, double dt)
 Stage 1 of execute() only: reset the assembly arrays and run the external-load adders (runoff/LID, RDII, DWF, GW, interface, direct, coupling and receipts) into nodes.qual_mass_in / qual_vol_in — no mixing, decay, or link update.
 
void addExtInflowLoads (SimulationContext &ctx, double dt)
 Add direct external inflow ([INFLOWS] CONCEN/MASS) pollutant loads, and the direct inflow's water, to the node assembly arrays.
 
void addCouplingLoads (SimulationContext &ctx, double dt)
 Add accepted 2D-to-node coupling carrier volumes, scalar numerators and pollutant rates.
 
void addQualityOnlyInflows (SimulationContext &ctx, double dt)
 review D2 + gaining conduits
 
void addWetWeatherLoads (SimulationContext &ctx, double dt)
 Add subcatchment washoff quality loads to node inflows.
 
void updateLinkQuality (SimulationContext &ctx, double dt)
 Publish link pollutant concentration using shared legacy conduit mixing rules.
 
void applyTreatment (SimulationContext &ctx, double dt, bool full_inflow=true)
 Apply [TREATMENT] at every node that has one.
 

Member Function Documentation

◆ addCouplingLoads()

void openswmm::quality::QualitySolver::addCouplingLoads ( SimulationContext & ctx,
double dt )

Add accepted 2D-to-node coupling carrier volumes, scalar numerators and pollutant rates.

S3: 2D→1D junction drain — its water into qual_vol_in, its species mass (queued by SurfaceRouter2D, drained by assembleLateralInflows) into qual_mass_in. No-op when no 2D coupling is active.

Parameters
[in,out]ctxPrepared completed hydraulic/source state and writable quality/scalar/native species arrays, receipts, ledgers and diagnostics used by this stage.
[in]dtMatching accepted positive finite routing duration s; most stages do not validate it.

Positive water adds q*dt; age/heat use supplied coupling tuple when flagged/covered, otherwise external source configuration. Positive pollutant mass rate is added even if water is nonpositive, and books ex-in mass*dt. Empty carrier returns before pollutant tuple handling. Does not clear coupling receipts; exactly-once after hydraulic drain assembly, prepared full node carrier extent.

Note
Requires matching initialized solver pollutant count, node/link/subtype arrays and writable quality/ledger extents. Carrier volumes use ft3; pollutant rates use concentration*ft3/s and ledger increments concentration*ft3. No implicit litre or user-mass conversion, hydraulic water advance or engine clock change. Caller serializes quality phases; repeat calls can double-book loads.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ addExtInflowLoads()

void openswmm::quality::QualitySolver::addExtInflowLoads ( SimulationContext & ctx,
double dt )

Add direct external inflow ([INFLOWS] CONCEN/MASS) pollutant loads, and the direct inflow's water, to the node assembly arrays.

Add direct external water and signed pollutant/runtime mass-rate forcing.

The mass rates were evaluated by the inflow solver into nodes.ext_qual_mass (CONCEN rows already multiplied by the node's flow). This also folds the direct inflow volume into qual_vol_in, which is the mixing denominator — legacy divides by Node[j].inflow, a total that includes lateral inflow.

See also
Legacy: routing.c addExternalInflows() pollutant portion
Parameters
[in,out]ctxPrepared completed hydraulic/source state and writable quality/scalar/native species arrays, receipts, ledgers and diagnostics used by this stage.
[in]dtMatching accepted positive finite routing duration s; most stages do not validate it.

Positive ext_inflow adds carrier and scalar numerators; negative water is retained only for lateral correction. Signed ext_qual_mass and API user_conc_mass_flux add rates/ledger mass, even with no positive carrier. API mass flux also books forcing ledger and warns once for extraction; actual available-mass clamp occurs during mixing. Requires lateral scratch initialized by assembly; warning allocation can throw after earlier additions. Does not consume persistent forcing.

Note
Requires matching initialized solver pollutant count, node/link/subtype arrays and writable quality/ledger extents. Carrier volumes use ft3; pollutant rates use concentration*ft3/s and ledger increments concentration*ft3. No implicit litre or user-mass conversion, hydraulic water advance or engine clock change. Caller serializes quality phases; repeat calls can double-book loads.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ addQualityOnlyInflows()

void openswmm::quality::QualitySolver::addQualityOnlyInflows ( SimulationContext & ctx,
double dt )

review D2 + gaining conduits

Consume pending surface-outfall and gaining-link quality-only receipts.

Parameters
[in,out]ctxPrepared completed hydraulic/source state and writable quality/scalar/native species arrays, receipts, ledgers and diagnostics used by this stage.
[in]dtMatching accepted positive finite routing duration s; most stages do not validate it.

Adds accepted positive receipt volume directly to node qual_vol_in, divides stored pollutant/native species mass and age/temperature volume numerators by dt to recover rates, books pollutant ex/GW mass, then clears each receipt container. Does not change hydraulic water (already accepted there). Inactive receipt skipped; nonpositive/NaN dt returns before consumption. Native destination shape mismatch resets0. Requires covered receipt scalar/volume arrays; allocation can leave partial receipts.

Note
Requires matching initialized solver pollutant count, node/link/subtype arrays and writable quality/ledger extents. Carrier volumes use ft3; pollutant rates use concentration*ft3/s and ledger increments concentration*ft3. No implicit litre or user-mass conversion, hydraulic water advance or engine clock change. Caller serializes quality phases; repeat calls can double-book loads.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ addWetWeatherLoads()

void openswmm::quality::QualitySolver::addWetWeatherLoads ( SimulationContext & ctx,
double dt )

Add subcatchment washoff quality loads to node inflows.

Add old/new runoff and conventional LID drain mass-rate blends at valid outlet nodes.

For each subcatchment with runoff, adds the washoff concentration × flow as mass inflow to the outlet node. Matches legacy addWetWeatherInflows() in routing.c.

Parameters
[in,out]ctxPrepared completed hydraulic/source state and writable quality/scalar/native species arrays, receipts, ledgers and diagnostics used by this stage.
[in]dtMatching accepted positive finite routing duration s; most stages do not validate it.

Uses runoff_interp_f unbounded: blended positive flow gates carrier/scalar addition, but pollutant rate is blend(q_old*c_old,q_new*c_new), not mean flow times current concentration. Only positive mass rates are added/booked to wet ledger; missing concentration/history uses0. LID carrier and load histories use same blend, prepared layer age/temperature numerators when active else rainfall source scalar. No queue clearing; caller initializes lateral scratch and calls once per routing step.

Note
Requires matching initialized solver pollutant count, node/link/subtype arrays and writable quality/ledger extents. Carrier volumes use ft3; pollutant rates use concentration*ft3/s and ledger increments concentration*ft3. No implicit litre or user-mass conversion, hydraulic water advance or engine clock change. Caller serializes quality phases; repeat calls can double-book loads.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ applyTreatment()

void openswmm::quality::QualitySolver::applyTreatment ( SimulationContext & ctx,
double dt,
bool full_inflow = true )

Apply [TREATMENT] at every node that has one.

Apply compiled treatment to each marked node using its assembled inflow view.

Apply treatment expressions at nodes with treatment defined. Public since E5b: the ARD engine reuses this exact evaluator for treatment interop — it runs on the PUBLISHED nodes.conc after the ARD step and the engine absorbs the treated concentrations back into its node stores (ArdEngine::absorbTreatedNodeConc). Books its own qual_routing_reacted losses.

  • Argument full_inflow: true when the caller assembled the node's COMPLETE inflow (link mass flow plus the external loaders), which is what legacy's Cin means. The EULERIAN_ARD entry runs only assembleExternalLoads, so its accumulators hold the external share alone and it passes false — see the note at the Cin site.
Parameters
[in,out]ctxPrepared completed hydraulic/source state and writable quality/scalar/native species arrays, receipts, ledgers and diagnostics used by this stage.
[in]dtMatching accepted positive finite routing duration s; most stages do not validate it.
[in]full_inflowTrue when assembly includes link plus external inflow; false for external-only ARD seam.

Builds shared treatment cin, then delegates one-node resolver/HRT/ledger work. With full_inflow, cin=mass_rate/(volume/dt); external-only path intentionally uses mass_rate/volume. Thus caller's mode and denominator convention affect removal expressions. No pollutants/no treatments returns; allocations/evaluation can leave earlier nodes treated. Shared scratch makes calls exclusive.

Note
Requires matching initialized solver pollutant count, node/link/subtype arrays and writable quality/ledger extents. Carrier volumes use ft3; pollutant rates use concentration*ft3/s and ledger increments concentration*ft3. No implicit litre or user-mass conversion, hydraulic water advance or engine clock change. Caller serializes quality phases; repeat calls can double-book loads.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ assembleExternalLoads()

void openswmm::quality::QualitySolver::assembleExternalLoads ( SimulationContext & ctx,
double dt )

Stage 1 of execute() only: reset the assembly arrays and run the external-load adders (runoff/LID, RDII, DWF, GW, interface, direct, coupling and receipts) into nodes.qual_mass_in / qual_vol_in — no mixing, decay, or link update.

Reset and assemble all external quality/carrier/scalar sources for this interval.

Split out (behavior-preserving refactor) so the Eulerian ARD engine (QUALITY_SOLVER EULERIAN_ARD) can consume the same source loads while replacing the CSTR transport stages — master plan §4.3 source-attribution seam.

Parameters
[in,out]ctxPrepared completed hydraulic/source state and writable quality/scalar/native species arrays, receipts, ledgers and diagnostics used by this stage.
[in]dtMatching accepted positive finite routing duration s; most stages do not validate it.

Resets node pollutant rates/volumes, age/heat rate numerators and lateral scratch; scalar shape mismatch calls resize (may reset scalar histories). Adds runoff/LID drains, RDII, DWF, GW, interface, direct/runtime, 2D coupling and pending quality-only receipts. Negative lateral components reduce mixing denominator to positive net hydraulic lateral contribution; only negative correction applied. Does not itself clear native msx_ext_mass_in unless a receipt shape mismatch triggers its reset. No consumers returns; callers must pre-evaluate accepted hydraulics and source values. Allocation or warning failures can leave partial assembly and consumed receipts; not transactional.

Note
Requires matching initialized solver pollutant count, node/link/subtype arrays and writable quality/ledger extents. Carrier volumes use ft3; pollutant rates use concentration*ft3/s and ledger increments concentration*ft3. No implicit litre or user-mass conversion, hydraulic water advance or engine clock change. Caller serializes quality phases; repeat calls can double-book loads.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ beginFvWindow()

void openswmm::quality::QualitySolver::beginFvWindow ( )
inlinenoexcept

◆ execute()

void openswmm::quality::QualitySolver::execute ( SimulationContext & ctx,
double dt )

Execute one quality routing timestep.

Route accepted legacy quality, native reaction species, age and heat through one interval.

  1. Accumulate link mass flows → node quality (batch over links)
  2. Complete mixing at nodes: c_new = (c_old*V + W*dt) / (V + Vin)
  3. Apply node treatment/owned native kinetics (node scalar decay is in mixing)
  4. Update link quality, forcing and optional age/heat/bed exchange
  • Argument ctx: Simulation context.
  • Argument dt: Timestep (seconds).
Parameters
[in,out]ctxPrepared completed hydraulic/source state and writable quality/scalar/native species arrays, receipts, ledgers and diagnostics used by this stage.
[in]dtMatching accepted positive finite routing duration s; most stages do not validate it.

Assembles sources, prepares native LID transfers, accumulates links/mixes nodes, advances untreated HRT, routes native MSX, applies treatment/kinetics, updates links/forcing then age/heat and optional bed-solute exchange. With native LID pollutant cells, repeats fixed-point node mixtures up to100 iterations restoring baseline selected ledgers/inventories each time; nonconvergence warns once and retains final iterate (no error result). Accepted outlet phase follows iteration. No pollutants, legacy reactions, age or heat returns even if other external-volume consumers exist. Caller ensures positive finite dt, initial shapes and unique accepted-step ownership; dependency/allocation failures may leave partial transport/ledgers/receipts. No global rollback or engine clock advance.

Note
Requires matching initialized solver pollutant count, node/link/subtype arrays and writable quality/ledger extents. Carrier volumes use ft3; pollutant rates use concentration*ft3/s and ledger increments concentration*ft3. No implicit litre or user-mass conversion, hydraulic water advance or engine clock change. Caller serializes quality phases; repeat calls can double-book loads.
Here is the call graph for this function:

◆ fvDryRestartState()

std::string openswmm::quality::QualitySolver::fvDryRestartState ( const SimulationContext & ctx) const
inline

◆ fvRetainedPollutantMass()

std::vector< double > openswmm::quality::QualitySolver::fvRetainedPollutantMass ( const SimulationContext & ctx) const
inline

◆ fvRetainedSpeciesMass()

std::vector< double > openswmm::quality::QualitySolver::fvRetainedSpeciesMass ( const SimulationContext & ctx) const
inline

◆ fvTransportAccepted()

bool openswmm::quality::QualitySolver::fvTransportAccepted ( ) const
inlinenoexcept

◆ fvWater()

FvTransportWater & openswmm::quality::QualitySolver::fvWater ( )
inlinenoexcept

◆ hasFvRetainedDryMass()

bool openswmm::quality::QualitySolver::hasFvRetainedDryMass ( ) const
inlinenoexcept

◆ init()

void openswmm::quality::QualitySolver::init ( int n_nodes,
int n_links,
int n_pollutants )

Set the solver's pollutant row count for subsequent routing/assembly.

Parameters
[in]n_nodesUnused node count; storage resides on SimulationContext, not this initializer.
[in]n_linksUnused link count.
[in]n_pollutantsPollutant count/flattened stride; caller must keep context arrays consistent.
Note
Does not resize context or reset prior lateral scratch, inventories or clocks; allocation-free.

◆ restoreFvDryRestart()

std::string openswmm::quality::QualitySolver::restoreFvDryRestart ( SimulationContext & ctx,
const std::string & blob,
bool apply )
inline

◆ updateLinkQuality()

void openswmm::quality::QualitySolver::updateLinkQuality ( SimulationContext & ctx,
double dt )

Publish link pollutant concentration using shared legacy conduit mixing rules.

Update link quality using volume-balance mixing with upstream node (DW/KW) or upstream node concentration with exponential decay (STEADY). Public for testing.

Parameters
[in,out]ctxPrepared completed hydraulic/source state and writable quality/scalar/native species arrays, receipts, ledgers and diagnostics used by this stage.
[in]dtMatching accepted positive finite routing duration s; most stages do not validate it.

Non-conduit/DUMMY copies selected upstream/native-LID outlet quality without reaction. STEADY conduit uses geometric node1 concentration, positive exponential decay and signed flow mass booking; other models use old-volume explicit decay then accepted mixing inflow and donor quality. Barrel seep/evaporation modifies pool/ledgers; dry nonsteady conduits book/reset residual. Native reaction ownership suppresses pollutant decay. Requires complete old concentrations, node/subtype geometry and ledgers; caller serializes after node treatment, before final native link kinetics.

Note
Requires matching initialized solver pollutant count, node/link/subtype arrays and writable quality/ledger extents. Carrier volumes use ft3; pollutant rates use concentration*ft3/s and ledger increments concentration*ft3. No implicit litre or user-mass conversion, hydraulic water advance or engine clock change. Caller serializes quality phases; repeat calls can double-book loads.
Here is the call graph for this function:
Here is the caller graph for this function:

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