OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
InertialKernels.hpp File Reference

Single-source flat kernels for the explicit local-inertial marcher. More...

#include <algorithm>
#include <cmath>
#include "../data/MeshData.hpp"
#include "../data/SolverOptions2D.hpp"
#include "../mesh/VfrClosure.hpp"
#include "../mesh/QuadVfr.hpp"
Include dependency graph for InertialKernels.hpp:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Namespaces

namespace  openswmm
 
namespace  openswmm::twoD
 
namespace  openswmm::twoD::inertial
 

Macros

#define OPENSWMM_2D_NOINLINE
 

Functions

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.
 
OPENSWMM_KERNEL_FN double openswmm::twoD::inertial::qMagnitude (double x, double y) noexcept
 |(x, y)| for the marcher's discharge vectors.
 
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).
 
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).
 
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_*).
 
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).
 
OPENSWMM_2D_NOINLINE void openswmm::twoD::inertial::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 openswmm::twoD::inertial::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 openswmm::twoD::inertial::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 openswmm::twoD::inertial::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 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.
 
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.
 
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.
 
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().
 
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:
 
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.
 
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).
 
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.
 

Variables

constexpr double openswmm::twoD::inertial::kGravity = 9.80665
 matches the existing kernels
 
constexpr double openswmm::twoD::inertial::kEtaDeadband = 1.0e-12
 

Detailed Description

Single-source flat kernels for the explicit local-inertial marcher.

The numerical core of ExplicitInertialSolver (2026-07-29 2D reimplementation plan): the de Almeida & Bates (2013) local-inertial face update on unstructured unique faces, the FLAT/VFR volume→η closure, the Froude clamp, and the CFL step bound. Everything here is a plain inline function over scalars/raw pointers — no owning containers, no allocation, no exceptions — so the same bodies can be annotated for Kokkos in the deferred parallel phase.

Scheme summary (face e between cells L,R; q = unit-width discharge normal to the face, positive cL→cR; SI, g = 9.80665):

h_f = max(η_L, η_R) − max(z_L, z_R) flow depth at face (FACE_RECONSTRUCTION=MEAN; VFR_FACE uses the B&S Eq. 14 wetted-edge depth over the edge's true endpoint beds) S_f = (η_R − η_L) · inv_dx_normal surface slope q̂ = θ·q + (1−θ)·½(q⃗_L + q⃗_R)·n̂ lateral θ-average q* = (q̂ − g·h_f·Δt·S_f) / (1 + g·Δt·n_f²·|q|/h_f^{7/3}) q^{n+1} = clamp(q*, ±Fr_max·h_f·√(g·h_f))

The friction denominator is the exact semi-implicit form used by the ARKODE inertial path (unconditionally stable in friction); θ = 1 recovers Bates et al. (2010). Well-balancedness: at rest η_L = η_R ⇒ S_f = 0 and q stays exactly 0 for any bathymetry; a dry neighbour standing higher gives h_f ≤ 0 ⇒ wall (no uphill creep).

Author
Caleb Buahin caleb.nosp@m..bua.nosp@m.hin@g.nosp@m.mail.nosp@m..com
License
Apache-2.0

Macro Definition Documentation

◆ OPENSWMM_2D_NOINLINE

#define OPENSWMM_2D_NOINLINE