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

Functions

OPENSWMM_KERNEL_FN double momentumBlendFraction (double theta, double dt, double reference_step) noexcept
 Fraction of reconstructed momentum mixed over one physical face step.
 
OPENSWMM_KERNEL_FN double qMagnitude (double x, double y) noexcept
 |(x, y)| for the marcher's discharge vectors.
 
OPENSWMM_KERNEL_FN void etaDepthScalar (double area, double cz, double z1, double z2, double z3, bool vfr, double vfr_min_wet_frac, double V, double &eta, double &depth) noexcept
 Scalar core of the V → (η, depth) closure (device-callable; the MeshData wrapper below loads the geometry and forwards — identical ops and order).
 
OPENSWMM_KERNEL_FN double volumeFromEtaScalar (double area, double cz, double z1, double z2, double z3, bool vfr, double vfr_min_wet_frac, double eta) noexcept
 Scalar core of the η → V inverse (device-callable).
 
OPENSWMM_KERNEL_FN void etaDepthQuadScalar (double area, double cz, const double *zs, double A1, double A2, bool vfr, double vfr_min_wet_frac, double V, double &eta, double &depth) noexcept
 Quad (B&S 2007 two-plane) V → (η, depth) closure core. zs / A1 / A2 are the precomputed quad VFR data (MeshData::quad_vfr_*).
 
OPENSWMM_KERNEL_FN double volumeFromEtaQuadScalar (double area, double cz, const double *zs, double A1, double A2, bool vfr, double vfr_min_wet_frac, double eta) noexcept
 Quad η → V inverse (device-callable).
 
OPENSWMM_2D_NOINLINE void cellEtaDepthQuad (const MeshData &m, const SolverOptions2D &o, int i, double V, double &eta, double &depth) noexcept
 Quad (B&S 2007 two-plane) VFR closure, kept OUT OF LINE on purpose: its safeguarded Newton (QuadVfr.hpp) is large, and inlining it into cellEtaDepth made GCC stop inlining cellEtaDepth itself into the cell kernels — a call per cell per firing on every mesh, quads or not (2D_PERF_REGRESSION_DIAGNOSIS: measured +30 % on Bellinge LI, profile showed cellEtaDepth as a 10 M-call function that used to be inlined).
 
void cellEtaDepth (const MeshData &m, const SolverOptions2D &o, int i, double V, double &eta, double &depth) noexcept
 Volume → (η, depth) closure — the SAME semantics as the CVODE/ARKODE reconstructFromVolume: depth = max(V,0)/A; FLAT η = z_c + depth, VFR η from the Begnudelli–Sanders planar-bed relation (ε-regularized) for triangles and the B&S 2007 two-plane relation for quads.
 
double cellWetArea (const MeshData &m, const SolverOptions2D &o, int i, double volume) noexcept
 Physical planimetric water contact, distinct from the cell-mean depth V/A returned above. The VFR regularization is not a flooded-area floor.
 
double cellVolumeFromEta (const MeshData &m, const SolverOptions2D &o, int i, double eta) noexcept
 Exact inverse of the closure: cell volume holding free surface η — FLAT A·max(0, η − z_c); VFR the regularized B&S forward relation (round-trips with cellEtaDepth). Closure-consistent seeding for tests/hotstart.
 
OPENSWMM_KERNEL_FN double faceFlowDepth (double etaL, double etaR, double zface) noexcept
 Flow depth at a face: the water surface above the higher of the two interface beds. ≤ 0 means the face is a wall this substep. This is the FACE_RECONSTRUCTION = MEAN form; zface is centroid-based (max of the two cell-mean beds), so a thin crest resolved as a line of high VERTICES is diluted by ~⅓ of its height — use the VFR form below to block at the true edge crest.
 
OPENSWMM_KERNEL_FN double faceDepthFromEta (double eta, double z_lo, double z_hi) noexcept
 Wetted-edge flow depth from a free surface η over an edge with endpoint beds z_lo ≤ z_hi — Begnudelli & Sanders (2007) Eq. 14, the exact cross-sectional water area divided by the full edge length: η ≤ z_lo : 0 (wetting gate: bed above water) z_lo < η ≤ z_hi : (η − z_lo)² / (2(z_hi − z_lo)) (partially submerged) η > z_hi : η − (z_lo + z_hi)/2 (fully submerged: mean depth) The quadratic branch matches value AND slope at both joins (C¹), so overtopping onset is smooth. Single source for the CPU boundary path, the GPU boundary kernels, and the VFR interior-face path — byte-identical to the copies it replaced in SurfaceFluxCalculator.cpp and ExplicitKokkosSurfaceSolver.cpp.
 
OPENSWMM_KERNEL_FN double faceFlowDepthVfr (double etaL, double etaR, double z_lo, double z_hi) noexcept
 Flow depth at an interior face under FACE_RECONSTRUCTION = VFR_FACE: the B&S Eq. 14 wetted-edge depth of the driving surface max(η_L, η_R) over the shared edge's TRUE endpoint beds. Water is blocked until the surface exceeds the edge's low point and overtops smoothly up to full submergence — embankments/levees/road crowns hold to their real crest instead of the centroid-diluted zface. Fully submerged reduces to max(η) − mean edge bed.
 
OPENSWMM_KERNEL_FN double inertialFaceUpdate (double q, double qhat, double hf, double dt, double slope, double n2, double q_mag, double adv=0.0) noexcept
 One local-inertial face update over Δt. q is the current face discharge, qhat the θ-averaged discharge feeding the momentum balance, hf the face flow depth (> 0), slope (η_R−η_L)·inv_dx_normal, n2 the squared face Manning coefficient, q_mag the FLOW-VECTOR magnitude at the face (from the Perot cell reconstruction; pass |q| when unavailable). Friction is semi-implicit: dividing by (1 + g·Δt·n²·q_mag/h^{7/3}) is unconditionally stable — h^{7/3} written as h²·cbrt(h) to avoid pow().
 
OPENSWMM_KERNEL_FN double inertialAdvection (double q_f, double unL, double hL, double unR, double hR, double inv_dx_normal) noexcept
 Convective momentum flux difference ∂(u·q)/∂n at an interior face — [2D_OPTIONS] ADVECTION, the term the pure local-inertial scheme drops. Stelling & Duinmeijer's staggered momentum-conservative upwinding, mapped onto the unstructured layout with the Perot cell vectors standing in for the along-normal neighbour faces a structured grid would have:
 
OPENSWMM_KERNEL_FN double froudeCap (double q, double hf, double fr_max) noexcept
 Froude-number clamp: |q| ≤ Fr_max · h_f · √(g·h_f). The steep-face guard — the local-inertial scheme carries no advection term, so supercritical acceleration must be capped rather than resolved.
 
OPENSWMM_KERNEL_FN double cellCflDt (double alpha, double lchar, double h, double speed) noexcept
 Per-cell CFL stable step: dt = α·L_char/(√(g·h) + |u|), with |u| = |q⃗|/h the cell speed from the Perot reconstruction (pass 0 when unavailable — the gravity-wave celerity dominates in the flows this scheme is valid for).
 
OPENSWMM_KERNEL_FN double positivityScale (double V, double outflow_m3s, double dt, double beta) noexcept
 Positivity scale factor λ for a cell about to export volume: outgoing fluxes (+ explicit sinks) may take at most β·max(V,0) over Δt. Faces leaving the cell are scaled by λ; the identical scaled flux updates both incident cells, so conservation is untouched.
 

Variables

constexpr double kGravity = 9.80665
 matches the existing kernels
 
constexpr double kEtaDeadband = 1.0e-12
 

Function Documentation

◆ cellCflDt()

OPENSWMM_KERNEL_FN double openswmm::twoD::inertial::cellCflDt ( double alpha,
double lchar,
double h,
double speed )
noexcept

Per-cell CFL stable step: dt = α·L_char/(√(g·h) + |u|), with |u| = |q⃗|/h the cell speed from the Perot reconstruction (pass 0 when unavailable — the gravity-wave celerity dominates in the flows this scheme is valid for).

Parameters
[in]alphaFinite positive dimensionless Courant factor.
[in]lcharFinite positive characteristic cell length, m.
[in]hFinite nonnegative mean depth, m.
[in]speedFinite nonnegative cell velocity magnitude, m/s; zero when unavailable.
Returns
Gravity/advection CFL bound in seconds; 1e30 s when total celerity is at most 1e-12 m/s.
Note
Pure host/device arithmetic: no allocation, exceptions, retained pointers or model state mutation. Caller supplies finite valid physical inputs; no general validation.
Here is the caller graph for this function:

◆ cellEtaDepth()

void openswmm::twoD::inertial::cellEtaDepth ( const MeshData & m,
const SolverOptions2D & o,
int i,
double V,
double & eta,
double & depth )
inlinenoexcept

Volume → (η, depth) closure — the SAME semantics as the CVODE/ARKODE reconstructFromVolume: depth = max(V,0)/A; FLAT η = z_c + depth, VFR η from the Begnudelli–Sanders planar-bed relation (ε-regularized) for triangles and the B&S 2007 two-plane relation for quads.

Parameters
[in]mBorrowed built SI mixed mesh with valid cell/vertex/quad-VFR arrays.
[in]oBorrowed validated cell-closure options and regularization fraction.
[in]iValid zero-based mixed-cell index; bounds are unchecked.
[in]VSigned cell volume, m3; closure uses its positive part.
[out]etaRequired distinct scalar for free-surface elevation, m.
[out]depthRequired distinct scalar for mean water depth, m.
Note
Read-only mesh/options gather; no ownership transfer, state writes or allocation. Caller guarantees stable valid SI geometry. cellEtaDepthQuad requires an actual quad and always selects VFR.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cellEtaDepthQuad()

OPENSWMM_2D_NOINLINE void openswmm::twoD::inertial::cellEtaDepthQuad ( const MeshData & m,
const SolverOptions2D & o,
int i,
double V,
double & eta,
double & depth )
inlinenoexcept

Quad (B&S 2007 two-plane) VFR closure, kept OUT OF LINE on purpose: its safeguarded Newton (QuadVfr.hpp) is large, and inlining it into cellEtaDepth made GCC stop inlining cellEtaDepth itself into the cell kernels — a call per cell per firing on every mesh, quads or not (2D_PERF_REGRESSION_DIAGNOSIS: measured +30 % on Bellinge LI, profile showed cellEtaDepth as a 10 M-call function that used to be inlined).

Parameters
[in]mBorrowed built SI mixed mesh with valid cell/vertex/quad-VFR arrays.
[in]oBorrowed validated cell-closure options and regularization fraction.
[in]iValid zero-based mixed-cell index; bounds are unchecked.
[in]VSigned cell volume, m3; closure uses its positive part.
[out]etaRequired distinct scalar for free-surface elevation, m.
[out]depthRequired distinct scalar for mean water depth, m.
Note
Read-only mesh/options gather; no ownership transfer, state writes or allocation. Caller guarantees stable valid SI geometry. cellEtaDepthQuad requires an actual quad and always selects VFR.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cellVolumeFromEta()

double openswmm::twoD::inertial::cellVolumeFromEta ( const MeshData & m,
const SolverOptions2D & o,
int i,
double eta )
inlinenoexcept

Exact inverse of the closure: cell volume holding free surface η — FLAT A·max(0, η − z_c); VFR the regularized B&S forward relation (round-trips with cellEtaDepth). Closure-consistent seeding for tests/hotstart.

Parameters
[in]mBorrowed built SI mixed mesh with valid cell/vertex/quad-VFR arrays.
[in]oBorrowed validated cell-closure options and regularization fraction.
[in]iValid zero-based mixed-cell index; bounds are unchecked.
[in]etaFinite free-surface elevation, m in mesh datum.
Returns
Closure-consistent nonnegative water volume in m3; caller must provide valid area and bed arrays.
Note
Read-only mesh/options gather; no ownership transfer, state writes or allocation. Caller guarantees stable valid SI geometry. cellEtaDepthQuad requires an actual quad and always selects VFR.
Here is the call graph for this function:

◆ cellWetArea()

double openswmm::twoD::inertial::cellWetArea ( const MeshData & m,
const SolverOptions2D & o,
int i,
double volume )
inlinenoexcept

Physical planimetric water contact, distinct from the cell-mean depth V/A returned above. The VFR regularization is not a flooded-area floor.

Parameters
[in]mBorrowed built SI mixed mesh with valid cell/vertex/quad-VFR arrays.
[in]oBorrowed validated cell-closure options and regularization fraction.
[in]iValid zero-based mixed-cell index; bounds are unchecked.
[in]volumeSigned cell volume, m3; nonpositive/NaN returns zero contact.
Returns
Physical wetted planimetric area in m2, between zero and cell area for valid inputs. VFR regularization is not used as a wetted-area floor.
Note
Read-only mesh/options gather; no ownership transfer, state writes or allocation. Caller guarantees stable valid SI geometry. cellEtaDepthQuad requires an actual quad and always selects VFR.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ etaDepthQuadScalar()

OPENSWMM_KERNEL_FN void openswmm::twoD::inertial::etaDepthQuadScalar ( double area,
double cz,
const double * zs,
double A1,
double A2,
bool vfr,
double vfr_min_wet_frac,
double V,
double & eta,
double & depth )
noexcept

Quad (B&S 2007 two-plane) V → (η, depth) closure core. zs / A1 / A2 are the precomputed quad VFR data (MeshData::quad_vfr_*).

Parameters
[in]areaFinite positive planimetric cell area, m2.
[in]czFinite cell-mean bed elevation, m.
[in]zsRequired borrowed six-double quad VFR array, two sorted elevation triples in m; valid only for the VFR branch.
[in]A1Finite nonnegative first quad subtriangle area, m2.
[in]A2Finite nonnegative second subtriangle area, m2; A1+A2 > 0.
[in]vfrTrue selects the regularized triangular/two-plane VFR law; false uses flat mean bed.
[in]vfr_min_wet_fracDimensionless regularization fraction in [0,1); zero selects exact storage.
[in]VSigned cell water volume, m3; nonpositive/NaN is treated as zero by this closure without rewriting caller volume.
[out]etaFree-surface elevation in m, including the regularized dry anchor.
[out]depthNonnegative cell-mean depth in m; zero when area <= 1e-30 m2.
Note
Pure host/device closure. Caller retains all storage and supplies distinct eta/depth outputs. Quad storage is dereferenced only in VFR branches; other geometry is unchecked. No allocation or source-state mutation.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ etaDepthScalar()

OPENSWMM_KERNEL_FN void openswmm::twoD::inertial::etaDepthScalar ( double area,
double cz,
double z1,
double z2,
double z3,
bool vfr,
double vfr_min_wet_frac,
double V,
double & eta,
double & depth )
noexcept

Scalar core of the V → (η, depth) closure (device-callable; the MeshData wrapper below loads the geometry and forwards — identical ops and order).

Parameters
[in]areaFinite positive planimetric cell area, m2.
[in]czFinite cell-mean bed elevation, m.
[in]z1Finite first triangle vertex bed, m; inputs are sorted on local copies.
[in]z2Finite second triangle vertex bed, m.
[in]z3Finite third triangle vertex bed, m.
[in]vfrTrue selects the regularized triangular/two-plane VFR law; false uses flat mean bed.
[in]vfr_min_wet_fracDimensionless regularization fraction in [0,1); zero selects exact storage.
[in]VSigned cell water volume, m3; nonpositive/NaN is treated as zero by this closure without rewriting caller volume.
[out]etaFree-surface elevation in m, including the regularized dry anchor.
[out]depthNonnegative cell-mean depth in m; zero when area <= 1e-30 m2.
Note
Pure host/device closure. Caller retains all storage and supplies distinct eta/depth outputs. Quad storage is dereferenced only in VFR branches; other geometry is unchecked. No allocation or source-state mutation.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ faceDepthFromEta()

OPENSWMM_KERNEL_FN double openswmm::twoD::inertial::faceDepthFromEta ( double eta,
double z_lo,
double z_hi )
noexcept

Wetted-edge flow depth from a free surface η over an edge with endpoint beds z_lo ≤ z_hi — Begnudelli & Sanders (2007) Eq. 14, the exact cross-sectional water area divided by the full edge length: η ≤ z_lo : 0 (wetting gate: bed above water) z_lo < η ≤ z_hi : (η − z_lo)² / (2(z_hi − z_lo)) (partially submerged) η > z_hi : η − (z_lo + z_hi)/2 (fully submerged: mean depth) The quadratic branch matches value AND slope at both joins (C¹), so overtopping onset is smooth. Single source for the CPU boundary path, the GPU boundary kernels, and the VFR interior-face path — byte-identical to the copies it replaced in SurfaceFluxCalculator.cpp and ExplicitKokkosSurfaceSolver.cpp.

Parameters
[in]etaFinite driving free-surface elevation, m.
[in]z_loFinite lower endpoint bed, m.
[in]z_hiFinite upper endpoint bed, m; z_lo <= z_hi.
Returns
Nonnegative edge-averaged hydraulic depth in m; zero below the low endpoint. Near-level relief below 1e-9 m uses the level-edge limit.
Note
Pure host/device arithmetic: no allocation, exceptions, retained pointers or model state mutation. Caller supplies finite valid physical inputs; no general validation.
Here is the caller graph for this function:

◆ faceFlowDepth()

OPENSWMM_KERNEL_FN double openswmm::twoD::inertial::faceFlowDepth ( double etaL,
double etaR,
double zface )
noexcept

Flow depth at a face: the water surface above the higher of the two interface beds. ≤ 0 means the face is a wall this substep. This is the FACE_RECONSTRUCTION = MEAN form; zface is centroid-based (max of the two cell-mean beds), so a thin crest resolved as a line of high VERTICES is diluted by ~⅓ of its height — use the VFR form below to block at the true edge crest.

Parameters
[in]etaLFinite left free-surface elevation, m.
[in]etaRFinite right free-surface elevation, m.
[in]zfaceFinite higher interface/centroid bed elevation, m.
Returns
Signed flow depth in m; nonpositive means a blocked face.
Note
Pure host/device arithmetic: no allocation, exceptions, retained pointers or model state mutation. Caller supplies finite valid physical inputs; no general validation.
Here is the caller graph for this function:

◆ faceFlowDepthVfr()

OPENSWMM_KERNEL_FN double openswmm::twoD::inertial::faceFlowDepthVfr ( double etaL,
double etaR,
double z_lo,
double z_hi )
noexcept

Flow depth at an interior face under FACE_RECONSTRUCTION = VFR_FACE: the B&S Eq. 14 wetted-edge depth of the driving surface max(η_L, η_R) over the shared edge's TRUE endpoint beds. Water is blocked until the surface exceeds the edge's low point and overtops smoothly up to full submergence — embankments/levees/road crowns hold to their real crest instead of the centroid-diluted zface. Fully submerged reduces to max(η) − mean edge bed.

Parameters
[in]etaLFinite left free-surface elevation, m.
[in]etaRFinite right free-surface elevation, m.
[in]z_loFinite lower endpoint bed, m.
[in]z_hiFinite upper endpoint bed, m; z_lo <= z_hi.
Returns
Nonnegative edge-averaged hydraulic depth in m; zero below the low endpoint. Near-level relief below 1e-9 m uses the level-edge limit.
Note
Pure host/device arithmetic: no allocation, exceptions, retained pointers or model state mutation. Caller supplies finite valid physical inputs; no general validation.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ froudeCap()

OPENSWMM_KERNEL_FN double openswmm::twoD::inertial::froudeCap ( double q,
double hf,
double fr_max )
noexcept

Froude-number clamp: |q| ≤ Fr_max · h_f · √(g·h_f). The steep-face guard — the local-inertial scheme carries no advection term, so supercritical acceleration must be capped rather than resolved.

Parameters
[in]qFinite signed unit-width discharge, m2/s.
[in]hfFinite nonnegative flow depth, m.
[in]fr_maxFinite nonnegative maximum Froude number.
Returns
Discharge clamped to the symmetric Froude bound in m2/s. Negative hf/fr_max violates the clamp/square-root precondition.
Note
Pure host/device arithmetic: no allocation, exceptions, retained pointers or model state mutation. Caller supplies finite valid physical inputs; no general validation.
Here is the caller graph for this function:

◆ inertialAdvection()

OPENSWMM_KERNEL_FN double openswmm::twoD::inertial::inertialAdvection ( double q_f,
double unL,
double hL,
double unR,
double hR,
double inv_dx_normal )
noexcept

Convective momentum flux difference ∂(u·q)/∂n at an interior face — [2D_OPTIONS] ADVECTION, the term the pure local-inertial scheme drops. Stelling & Duinmeijer's staggered momentum-conservative upwinding, mapped onto the unstructured layout with the Perot cell vectors standing in for the along-normal neighbour faces a structured grid would have:

adv = (u_R·q̂_R − u_L·q̂_L) / Δn u_c = (q⃗_c·n̂)/h_c (cell velocity along the face normal) q̂_L = u_L > 0 ? h_L·u_L : q_f (upwind: the cell's own momentum carries q̂_R = u_R > 0 ? q_f : h_R·u_R in; the face's discharge carries out)

Exactly zero at rest (u = 0) and in uniform flow (u_L = u_R = u, h_L = h_R, q_f = h·u ⇒ both fluxes equal h·u²), so the C-property and steady sheet flow are untouched; upwinding supplies shock dissipation. Units: (m/s)·(m²/s)/m = m²/s², the same as the g·h·∂η/∂n term.

Parameters
[in]q_fFinite current face unit-width discharge, m2/s, positive left-to-right.
[in]unLFinite left normal velocity, m/s, along the left-to-right normal.
[in]hLFinite nonnegative left mean water depth, m.
[in]unRFinite right normal velocity, m/s, in the same orientation.
[in]hRFinite nonnegative right mean depth, m.
[in]inv_dx_normalFinite positive inverse normal cell-center distance, 1/m.
Returns
Upwind convective momentum-flux divergence, m2/s2; zero for rest and consistent uniform-flow states.
Note
Pure host/device arithmetic: no allocation, exceptions, retained pointers or model state mutation. Caller supplies finite valid physical inputs; no general validation.
Here is the caller graph for this function:

◆ inertialFaceUpdate()

OPENSWMM_KERNEL_FN double openswmm::twoD::inertial::inertialFaceUpdate ( double q,
double qhat,
double hf,
double dt,
double slope,
double n2,
double q_mag,
double adv = 0.0 )
noexcept

One local-inertial face update over Δt. q is the current face discharge, qhat the θ-averaged discharge feeding the momentum balance, hf the face flow depth (> 0), slope (η_R−η_L)·inv_dx_normal, n2 the squared face Manning coefficient, q_mag the FLOW-VECTOR magnitude at the face (from the Perot cell reconstruction; pass |q| when unavailable). Friction is semi-implicit: dividing by (1 + g·Δt·n²·q_mag/h^{7/3}) is unconditionally stable — h^{7/3} written as h²·cbrt(h) to avoid pow().

The friction magnitude MUST be the vector magnitude, not |q_n|: Manning friction on the normal component is n²·q_n·|q⃗|/h^{7/3}. With |q_n| the friction a face applies depends on its orientation relative to the flow (a face at 45° to a uniform sheet flow under-damps by √2), so no smooth surface can balance every face of a triangulated slope — the steady state corrugates cell-to-cell (the depth "checkerboarding" observed upstream of the road_culvert embankment under the VFR closure).

Parameters
[in]qCurrent face discharge in m2/s; retained for interface compatibility and not used in this update.
[in]qhatTheta-averaged unit-width discharge in m2/s, positive left-to-right.
[in]hfFinite strictly positive face flow depth, m; no dry guard exists in this kernel.
[in]dtFinite nonnegative face integration interval, s.
[in]slopeSigned dimensionless surface slope, right-minus-left.
[in]n2Finite nonnegative squared Manning roughness, s2/m^(2/3).
[in]q_magFinite nonnegative face discharge-vector magnitude, m2/s.
[in]advFinite convective momentum-gradient contribution, m2/s2; default zero disables advection.
Returns
Uncapped semi-implicit updated unit-width discharge in m2/s; availability/Froude limiting are separate caller steps.
Note
Pure host/device arithmetic: no allocation, exceptions, retained pointers or model state mutation. Caller supplies finite valid physical inputs; no general validation.
Here is the caller graph for this function:

◆ momentumBlendFraction()

OPENSWMM_KERNEL_FN double openswmm::twoD::inertial::momentumBlendFraction ( double theta,
double dt,
double reference_step )
noexcept

Fraction of reconstructed momentum mixed over one physical face step.

Parameters
[in]thetaValid retention in (0,1]; one disables blending.
[in]dtNonnegative actual face interval, seconds.
[in]reference_stepNonnegative reference interval, seconds; zero selects the historical per-firing weight. Positive values retain theta^(dt/reference_step).
Returns
Blend fraction in [0,1]. expm1 avoids cancellation for very small steps.
Note
Pure host/device scalar calculation. Call once per face firing, outside the face loop. Inputs are validated by the option parser/solver owner.
Here is the caller graph for this function:

◆ positivityScale()

OPENSWMM_KERNEL_FN double openswmm::twoD::inertial::positivityScale ( double V,
double outflow_m3s,
double dt,
double beta )
noexcept

Positivity scale factor λ for a cell about to export volume: outgoing fluxes (+ explicit sinks) may take at most β·max(V,0) over Δt. Faces leaving the cell are scaled by λ; the identical scaled flux updates both incident cells, so conservation is untouched.

Parameters
[in]VFinite signed donor-cell volume, m3; only max(V,0) is available.
[in]outflow_m3sFinite total positive export demand, m3/s.
[in]dtFinite step duration, s.
[in]betaFinite availability fraction in [0,1].
Returns
Dimensionless export scale in [0,1] for valid inputs; returns one for nonpositive outflow or step. Does not apply the scale or book any water.
Note
Pure host/device arithmetic: no allocation, exceptions, retained pointers or model state mutation. Caller supplies finite valid physical inputs; no general validation.

◆ qMagnitude()

OPENSWMM_KERNEL_FN double openswmm::twoD::inertial::qMagnitude ( double x,
double y )
noexcept

|(x, y)| for the marcher's discharge vectors.

std::hypot's overflow/underflow safety costs ~10x a plain sqrt and buys nothing here: the arguments are unit-width discharges (m^2/s), which the Froude cap and the positivity limiter already bound to O(1..10). It was measured at ~8% of the marcher's runtime. Values differ from std::hypot by at most 1 ulp — and the Kokkos face kernel had ALREADY taken this liberty while the serial marcher had not, so routing every backend through this helper closes a real cross-backend bit-difference instead of opening one.

Parameters
[in]xFinite X unit-width discharge, m2/s.
[in]yFinite Y unit-width discharge, m2/s.
Returns
Euclidean discharge magnitude, m2/s. Direct squaring can overflow for unbounded inputs; caller-provided hydraulic limits keep this kernel in range.
Note
Pure host/device arithmetic: no allocation, exceptions, retained pointers or model state mutation. Caller supplies finite valid physical inputs; no general validation.
Here is the caller graph for this function:

◆ volumeFromEtaQuadScalar()

OPENSWMM_KERNEL_FN double openswmm::twoD::inertial::volumeFromEtaQuadScalar ( double area,
double cz,
const double * zs,
double A1,
double A2,
bool vfr,
double vfr_min_wet_frac,
double eta )
noexcept

Quad η → V inverse (device-callable).

Parameters
[in]areaFinite positive planimetric cell area, m2.
[in]czFinite cell-mean bed elevation, m.
[in]zsRequired borrowed six-double quad VFR array, two sorted elevation triples in m; valid only for the VFR branch.
[in]A1Finite nonnegative first quad subtriangle area, m2.
[in]A2Finite nonnegative second subtriangle area, m2; A1+A2 > 0.
[in]vfrTrue selects the regularized triangular/two-plane VFR law; false uses flat mean bed.
[in]vfr_min_wet_fracDimensionless regularization fraction in [0,1); zero selects exact storage.
[in]etaFinite free-surface elevation in m, in the bed datum.
Returns
Cell volume in m3; nonpositive flat depth returns zero. Area is not validated here.
Note
Pure host/device closure. Caller retains all storage and supplies distinct eta/depth outputs. Quad storage is dereferenced only in VFR branches; other geometry is unchecked. No allocation or source-state mutation.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ volumeFromEtaScalar()

OPENSWMM_KERNEL_FN double openswmm::twoD::inertial::volumeFromEtaScalar ( double area,
double cz,
double z1,
double z2,
double z3,
bool vfr,
double vfr_min_wet_frac,
double eta )
noexcept

Scalar core of the η → V inverse (device-callable).

Parameters
[in]areaFinite positive planimetric cell area, m2.
[in]czFinite cell-mean bed elevation, m.
[in]z1Finite first triangle vertex bed, m; inputs are sorted on local copies.
[in]z2Finite second triangle vertex bed, m.
[in]z3Finite third triangle vertex bed, m.
[in]vfrTrue selects the regularized triangular/two-plane VFR law; false uses flat mean bed.
[in]vfr_min_wet_fracDimensionless regularization fraction in [0,1); zero selects exact storage.
[in]etaFinite free-surface elevation in m, in the bed datum.
Returns
Cell volume in m3; nonpositive flat depth returns zero. Area is not validated here.
Note
Pure host/device closure. Caller retains all storage and supplies distinct eta/depth outputs. Quad storage is dereferenced only in VFR branches; other geometry is unchecked. No allocation or source-state mutation.
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ kEtaDeadband

double openswmm::twoD::inertial::kEtaDeadband = 1.0e-12
inlineconstexpr

Free-surface difference below which a face slope is numerical zero (m). Without it, the local-inertial q integrates even 1-ulp closure round-trip noise up to its Manning equilibrium (√-amplification: Δη ~ 1e-16 sustains q ~ 1e-6 m²/s), so lake-at-rest would drift measurably. 1e-12 m is far below any physical head; with the slope zeroed the friction denominator decays q geometrically and rest states are exact.

◆ kGravity

double openswmm::twoD::inertial::kGravity = 9.80665
inlineconstexpr

matches the existing kernels