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

Classes

struct  NetworkMeshData
 SoA mesh geometry and topology for the FV network solver. More...
 
struct  NetworkStateData
 Mutable solver state — the conserved variables and the node volumes. More...
 
struct  SpeciesKernelView
 Non-owning view over everything the species kernels read and write. More...
 

Enumerations

enum class  Limiter
 Slope limiter used by the second-order (MUSCL) reconstruction. More...
 
enum class  ScalarScheme
 Reconstruction used for the advected scalar field. More...
 

Functions

void reconstructScalars (const SpeciesKernelView &v, double dt)
 Build bounded face-native concentrations and conservative limited scalar fluxes for all rows.
 
void limitSpeciesFluxes (const SpeciesKernelView &v, int species, double dt)
 Assemble the face species fluxes and limit them (Zalesak FCT).
 
void dispersionSolve (const SpeciesKernelView &v, double dt)
 Apply an implicit per-chain longitudinal dispersion solve to every native scalar row.
 
double limitSlope (double a, double b, Limiter lim)
 Slope limiters for the second-order scalar reconstruction. All three are TVD; superbee is the sharpest and can artificially steepen smooth profiles, minmod the most diffusive and most robust. (Moved verbatim from ExplicitFvSolver.cpp; also used by the solver's hydrodynamic reconstructState.)
 

Enumeration Type Documentation

◆ Limiter

enum class openswmm::fv::Limiter : int
strong

Slope limiter used by the second-order (MUSCL) reconstruction.

◆ ScalarScheme

enum class openswmm::fv::ScalarScheme : int
strong

Reconstruction used for the advected scalar field.

Function Documentation

◆ dispersionSolve()

void openswmm::transport::fvkernels::dispersionSolve ( const SpeciesKernelView & v,
double dt )

Apply an implicit per-chain longitudinal dispersion solve to every native scalar row.

Parameters
[in]vNonnull prepared mesh/state; cell_phi extent n_species*n_cells, area n_cells, valid chain CSR/cell indices and positive cell_dx ft. Optional cell_dispersion must cover n_cells with finite nonnegative ft2/s, overriding scalar dispersion of same units. View/pointees borrowed only for call; state scalar rows require exclusive access.
[in]dtFinite nonnegative dispersion duration s chosen by owner.
Note
No rows or nonpositive uniform dispersion with null per-cell field returns. Chains shorter than2 are skipped. Floors cross-sectional area to dry threshold, arithmetic-averages neighboring coefficients/areas, uses zero end coupling and a Thomas solve per species. Updates cell_phi in place, including dry/inactive cells; does not modify water or clock and performs no explicit sign/ finite/pivot validation or result clamp. Allocation of thread-local work arrays may throw after earlier chains changed; no rollback. Thread-local scratch permits disjoint owners on different threads but same-thread reentrancy is unsupported. Implicit stability does not validate arbitrary negative/nonfinite coefficients or imply every nonuniform discretization conservation property.

Implicit longitudinal dispersion (decision D-FV1): one Thomas tridiagonal solve per cell chain per species; unconditionally stable, removes the Δx²/(2·D_L) explicit constraint. E3: honours v.cell_dispersion when set (per-conduit / FISCHER coefficients); scalar v.dispersion otherwise.

Cell coefficient under either model. E3 bitwise-preservation note: each face uses 0.5*(D_i + D_j). With cd == nullptr both operands are v.dispersion, and 0.5*(D + D) == D EXACTLY in binary floating point (the ×2 and ×0.5 are exponent shifts), so the face coefficient — and therefore every downstream product in the same evaluation order — is bit-identical to the pre-E3 v.dispersion * … expression. The FV solver passes cd == nullptr and keeps its bitwise contract (E0 gate).

Here is the call graph for this function:

◆ limitSlope()

double openswmm::transport::fvkernels::limitSlope ( double a,
double b,
Limiter lim )
inline

Slope limiters for the second-order scalar reconstruction. All three are TVD; superbee is the sharpest and can artificially steepen smooth profiles, minmod the most diffusive and most robust. (Moved verbatim from ExplicitFvSolver.cpp; also used by the solver's hydrodynamic reconstructState.)

Limit two one-sided scalar slopes with van Leer, superbee or minmod.

Parameters
[in]aFinite left one-sided concentration gradient in common spatial units.
[in]bFinite right gradient of the same row/units.
[in]limLimiter selection; unknown enum uses minmod.
Returns
Zero for opposite/zero signs, otherwise same-sign TVD-limited slope. No clipping/overflow repair for nonfinite or extreme arithmetic; allocation-free, no mutation.
Here is the caller graph for this function:

◆ limitSpeciesFluxes()

void openswmm::transport::fvkernels::limitSpeciesFluxes ( const SpeciesKernelView & v,
int species,
double dt )

Assemble the face species fluxes and limit them (Zalesak FCT).

Bracketing the reconstructed FACE value between its two cells is necessary but NOT sufficient for the discrete maximum principle: under reversing, unsteady flow with the cell areas evolving underneath the scalar, a face value legitimately inside its bracket can still drain more solute than its donor cell holds. Measured: QUICKEST-ULTIMATE produced −1.3e-3 on a step-function advection case with wall reflections, which is not acceptable in a water-quality model.

The fix has to limit the FLUX, not the result. Clipping the updated concentration would enforce the bound but destroy exact solute conservation (§6.11c) — the two properties trade off, and Zalesak (1979) is the construction that keeps both: blend each face's high-order flux back toward first-order upwind by the largest factor that no incident cell's bound rejects. The SAME limited flux updates both incident cells, so conservation is untouched.

Parameters
[in]vPrepared nonnull borrowed view; f_mass, face state/flux and active face vectors cover n_faces, active cell flags n_cells; old cell_phi and reconstructed face rows cover all species*cell/ face products. Writable f_phi_flux matches row-face layout; all low/anti/td/area/rplus/rminus scratch vectors are distinct and caller-owned. Every active cell's two face indices/sides and chain lengths must be valid, with positive dx; all borrowed owners live and stable through call.
[in]speciesValid zero-based native row below state.n_species; unchecked.
[in]dtPositive finite hydraulic substep s, strictly nonzero for FCT capacity division.
Note
Builds low-order upwind flux from positivity-scaled water and high-order native face flux, predicts active cell area/low-order concentrations, bounds against old/low-order neighbors and uses minimum donor/receiver Zalesak ratios on each shared face. Zero-gradient native node ghosts use interior value; inactive scratch cells retain old state. Native dimensional flux is concentration* ft3/s; area ft2/dx ft. Writes only output flux/scratch, not canonical cell_phi/water/clock. Scratch assign can allocate/throw and earlier outputs remain; no rollback or invalid-state repair. Exclusive scratch/output ownership and one consistent accepted hydraulic face record required.

Assemble the face species fluxes and limit them (Zalesak FCT). See the implementation notes: limits the FLUX, not the result, so the discrete maximum principle and exact solute conservation hold together.

The flux record with the positivity-scaled mass flux substituted in, so the species rides on exactly the water the hydrodynamic update moved. (Formerly ExplicitFvSolver::adjustedFlux.)

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

◆ reconstructScalars()

void openswmm::transport::fvkernels::reconstructScalars ( const SpeciesKernelView & v,
double dt )

Build bounded face-native concentrations and conservative limited scalar fluxes for all rows.

Parameters
[in]vBorrowed view with nonnull mesh/state and all scratch/face/velocity/active-list pointers accessed by reconstruction and limitSpeciesFluxes, even when n_species<=0 because aliases are bound first. Mesh/state dimensions and all indices must be prepared and mutually consistent. cell_phi extent n_species*n_cells; face-native buffers n_species*n_faces; slope n_cells, velocity n_cells, contact-speed n_faces. Caller retains every owner alive/stable and supplies exclusive writable scratch.
[in]dtPositive finite accepted hydraulic substep s, required by Courant/FCT capacity arithmetic.
Note
Uses chain limited MUSCL slopes (zero at ends), UPWIND zero slopes or QUICKEST_ULTIMATE with bounded extra-upstream stencil/MUSCL fallback. Node ghosts use adjacent interior scalar. Clamps higher order face values to neighboring old values and invokes shared FCT per row using positivity-scaled hydraulic water flux. Native conventions: chain length ft, velocity ft/s and flux ft3/s times row concentration (age s, temperature degC where configured). Does not install canonical cell_phi, hydraulic water or engine clock; it writes reconstruction/flux/scratch progressively. Allocations in FCT can throw after earlier row outputs; no local rollback or generic finite/index validation. Not safe to share scratch concurrently or alias unrelated input/output vectors.

Scalar reconstruction — the anti-diffusion layer (FV plan §3.2). Computes limited face values for every species and calls limitSpeciesFluxes to assemble/limit the face species fluxes into f_phi_flux.

Here is the call graph for this function: