![]() |
OpenSWMM Engine
6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
|
Functions | |
| OPENSWMM_KERNEL_FN double | qMagnitude (double x, double y) noexcept |
| 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 |
| 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 |
| 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 |
| void | cellEtaDepth (const MeshData &m, const SolverOptions2D &o, int i, double V, double &eta, double &depth) noexcept |
| double | cellVolumeFromEta (const MeshData &m, const SolverOptions2D &o, int i, double eta) noexcept |
| OPENSWMM_KERNEL_FN double | faceFlowDepth (double etaL, double etaR, double zface) noexcept |
| OPENSWMM_KERNEL_FN double | faceDepthFromEta (double eta, double z_lo, double z_hi) noexcept |
| OPENSWMM_KERNEL_FN double | faceFlowDepthVfr (double etaL, double etaR, double z_lo, double z_hi) noexcept |
| 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 |
| OPENSWMM_KERNEL_FN double | inertialAdvection (double q_f, double unL, double hL, double unR, double hR, double inv_dx_normal) noexcept |
| OPENSWMM_KERNEL_FN double | froudeCap (double q, double hf, double fr_max) noexcept |
| OPENSWMM_KERNEL_FN double | cellCflDt (double alpha, double lchar, double h, double speed) noexcept |
| OPENSWMM_KERNEL_FN double | positivityScale (double V, double outflow_m3s, double dt, double beta) noexcept |
Variables | |
| constexpr double | kGravity = 9.80665 |
| matches the existing kernels | |
| constexpr double | kEtaDeadband = 1.0e-12 |
|
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).
|
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.
|
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).
|
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.
|
noexcept |
Quad (B&S 2007 two-plane) V → (η, depth) closure core. zs / A1 / A2 are the precomputed quad VFR data (MeshData::quad_vfr_*).
|
noexcept |
Scalar core of the V → (η, depth) closure (device-callable; the MeshData wrapper below loads the geometry and forwards — identical ops and order).
|
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 mean depth over the wetted portion of the edge: η ≤ 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.
|
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.
|
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.
|
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.
|
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.
|
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).
|
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.
|
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.
|
noexcept |
Quad η → V inverse (device-callable).
|
noexcept |
Scalar core of the η → V inverse (device-callable).
|
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.
|
inlineconstexpr |
matches the existing kernels