OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
ImplicitWetKernels.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Caleb Buahin
3
12
13#pragma once
14#include "FvKernels.hpp"
15#include <array>
16
18// Native forward directional arithmetic. Five local variables at most: two
19// cell (h,Q) pairs and one node head. No global seeds, allocation or inner solve.
20struct Jet {
21 double v = 0.0;
22 std::array<double, 5> d{};
26 Jet() = default;
35 Jet(double value) : v(value) {}
43 static Jet seed(double value, int column) {
44 Jet x(value);
45 x.d[column] = 1.0;
46 return x;
47 }
48};
49
58inline Jet operator+(const Jet& a, const Jet& b) {
59 Jet r(a.v + b.v);
60 for (int i = 0; i < 5; ++i)
61 r.d[i] = a.d[i] + b.d[i];
62 return r;
63}
64
73inline Jet operator-(const Jet& a, const Jet& b) {
74 Jet r(a.v - b.v);
75 for (int i = 0; i < 5; ++i)
76 r.d[i] = a.d[i] - b.d[i];
77 return r;
78}
79
88inline Jet operator*(const Jet& a, const Jet& b) {
89 Jet r(a.v * b.v);
90 for (int i = 0; i < 5; ++i)
91 r.d[i] = a.d[i] * b.v + a.v * b.d[i];
92 return r;
93}
94
103inline Jet operator/(const Jet& a, const Jet& b) {
104 Jet r(a.v / b.v);
105 for (int i = 0; i < 5; ++i)
106 r.d[i] = (a.d[i] - r.v * b.d[i]) / b.v;
107 return r;
108}
109
117inline Jet mapped(double value, double slope, const Jet& x) {
118 Jet r(value);
119 for (int i = 0; i < 5; ++i)
120 r.d[i] = slope * x.d[i];
121 return r;
122}
123
133inline Jet minimum(const Jet& a, const Jet& b) {
134 return b.v < a.v ? b : a;
135}
136
145inline Jet maximum(const Jet& a, const Jet& b) {
146 return a.v < b.v ? b : a;
147}
148
154inline bool finite(const Jet& x) {
155 return std::isfinite(x.v) &&
156 std::all_of(x.d.begin(), x.d.end(), [](double d) { return std::isfinite(d); });
157}
158struct Closure {
160};
161
175inline Closure closure(const FvClosure& c, const Jet& h) {
176 const auto e = kernels::closureEval(c, h.v);
177 double second = 0.0;
178 if (h.v < c.y_full) {
179 if (c.kind == kClosurePolynomial)
180 second = 2.0 * c.c2;
181 else {
182 int i;
183 double t;
184 kernels::closureLocate(c, h.v, i, t);
185 second = ((12 * t - 6) * c.A[i] + (6 * t - 4) * c.M[i] * c.dh +
186 (-12 * t + 6) * c.A[i + 1] + (6 * t - 2) * c.M[i + 1] * c.dh) *
187 c.inv_dh * c.inv_dh;
188 }
189 }
190 return {mapped(e.a, e.t, h), mapped(e.t, second, h), mapped(e.i1, e.a, h)};
191}
192
203inline double radiusSlope(const FvClosure& c, double h) {
204 if (h >= c.y_full)
205 return 0.0;
206 if (c.kind == kClosurePolynomial) {
207 const auto e = kernels::closureEval(c, h);
208 const double p = c.p0 + c.p1 * h;
209 return (e.t * p - e.a * c.p1) / (p * p);
210 }
211 int i;
212 double t;
213 kernels::closureLocate(c, h, i, t);
214 return (c.R[i + 1] - c.R[i]) * c.inv_dh;
215}
216struct State {
217 Jet a, q, u, c, i1;
218 uint8_t press = 0;
219};
220
234inline State state(const FvClosure& table, const Jet& h, const Jet& velocity, uint8_t press) {
235 const auto e = closure(table, h);
236 const double speed = kernels::celerity(e.area.v, e.width.v);
237 Jet c(speed);
238 for (int i = 0; i < 5; ++i)
239 c.d[i] = .5 * speed * (e.area.d[i] / e.area.v - e.width.d[i] / e.width.v);
240 return {e.area, e.area * velocity, velocity, c, e.moment, press};
241}
242struct Flux {
244};
245// Differentiate exactly the wet branch of kernels::waveSpeeds/riemannFlux.
246// Branches are selected at the current state, including RH min/max bounds;
247// their numerical values (celerity, jump speed, pressure) are NOT frozen.
248// At ties use the same first-operand choice as std::min/std::max. Residual
249// evaluation still calls the shared kernels, and tests enforce primal parity.
265inline Flux flux(const State& l, const State& r) {
266 auto sl = minimum(l.u - l.c, r.u - r.c), sr = maximum(l.u + l.c, r.u + r.c);
267 if (l.press != r.press && l.press < 2 && r.press < 2) {
268 if (l.press) {
269 const auto da = l.a - r.a;
270 const auto w = da.v > 0.0 ? (l.q - r.q) / da : sr;
271 sr = maximum(r.u + r.c, minimum(sr, w));
272 } else {
273 const auto da = r.a - l.a;
274 const auto w = da.v > 0.0 ? (r.q - l.q) / da : sl;
275 sl = minimum(l.u - l.c, maximum(sl, w));
276 }
277 }
278 const auto fl = l.q * l.u + kernels::kGravity * l.i1, fr = r.q * r.u + kernels::kGravity * r.i1;
279 if (sl.v >= 0.0)
280 return {l.q, fl};
281 if (sr.v <= 0.0)
282 return {r.q, fr};
283 return {(sr * l.q - sl * r.q + sl * sr * (r.a - l.a)) / (sr - sl),
284 (sr * fl - sl * fr + sl * sr * (r.q - l.q)) / (sr - sl)};
285}
286} // namespace openswmm::fv::implicit_wet
Single-source scalar kernels for the explicit FV 1D network solver.
Definition ImplicitWetKernels.hpp:17
double radiusSlope(const FvClosure &c, double h)
Evaluate the active wet friction-radius derivative with respect to depth.
Definition ImplicitWetKernels.hpp:203
bool finite(const Jet &x)
Check a primal value and every directional derivative for finite arithmetic.
Definition ImplicitWetKernels.hpp:154
Jet operator-(const Jet &a, const Jet &b)
Subtract two forward-mode values.
Definition ImplicitWetKernels.hpp:73
Flux flux(const State &l, const State &r)
Differentiate the active wet HLL hydraulic flux and pressure-bore bounds.
Definition ImplicitWetKernels.hpp:265
Jet operator/(const Jet &a, const Jet &b)
Divide two forward-mode values using the quotient rule.
Definition ImplicitWetKernels.hpp:103
Jet mapped(double value, double slope, const Jet &x)
Lift a known scalar function value and slope through an input jet.
Definition ImplicitWetKernels.hpp:117
Jet maximum(const Jet &a, const Jet &b)
Select the local maximum branch and preserve that branch derivative.
Definition ImplicitWetKernels.hpp:145
Closure closure(const FvClosure &c, const Jet &h)
Differentiate wet closure area, width and pressure integral with respect to depth.
Definition ImplicitWetKernels.hpp:175
State state(const FvClosure &table, const Jet &h, const Jet &velocity, uint8_t press)
Construct a differentiated wet face state from depth and velocity.
Definition ImplicitWetKernels.hpp:234
Jet operator*(const Jet &a, const Jet &b)
Multiply two forward-mode values using the product rule.
Definition ImplicitWetKernels.hpp:88
Jet operator+(const Jet &a, const Jet &b)
Add two forward-mode values.
Definition ImplicitWetKernels.hpp:58
Jet minimum(const Jet &a, const Jet &b)
Select the local minimum branch and preserve that branch derivative.
Definition ImplicitWetKernels.hpp:133
OPENSWMM_KERNEL_FN void closureLocate(const FvClosure &c, double h, int &i, double &t) noexcept
Locate a uniform depth panel and its clamped local coordinate.
Definition FvClosureKernels.hpp:137
OPENSWMM_KERNEL_FN ClosureEval closureEval(const FvClosure &c, double h) noexcept
Evaluate area, top width and cumulative hydrostatic integral together.
Definition FvClosureKernels.hpp:203
constexpr double kGravity
Definition FvKernels.hpp:81
OPENSWMM_KERNEL_FN double celerity(double a, double t) noexcept
Compute the gravity-wave speed from aggregate area and top width.
Definition FvKernels.hpp:234
@ kClosurePolynomial
Definition FvClosureKernels.hpp:76
One section's closure. Fixed-size POD: inline arrays, no pointers.
Definition FvClosureKernels.hpp:89
uint8_t kind
Definition FvClosureKernels.hpp:102
double A[kClosurePanels+1]
Definition FvClosureKernels.hpp:104
double inv_dh
Definition FvClosureKernels.hpp:92
double y_full
Definition FvClosureKernels.hpp:90
double dh
Definition FvClosureKernels.hpp:91
double M[kClosurePanels+1]
Definition FvClosureKernels.hpp:105
double p1
Definition FvClosureKernels.hpp:100
double R[kClosurePanels+1]
Definition FvClosureKernels.hpp:107
double c2
Definition FvClosureKernels.hpp:100
double p0
Definition FvClosureKernels.hpp:100
Definition ImplicitWetKernels.hpp:158
Jet area
Definition ImplicitWetKernels.hpp:159
Jet moment
Definition ImplicitWetKernels.hpp:159
Jet width
Definition ImplicitWetKernels.hpp:159
Definition ImplicitWetKernels.hpp:242
Jet momentum
Definition ImplicitWetKernels.hpp:243
Jet mass
Definition ImplicitWetKernels.hpp:243
Definition ImplicitWetKernels.hpp:20
std::array< double, 5 > d
Definition ImplicitWetKernels.hpp:22
Jet()=default
Construct a zero primal value with all five directional derivatives zero.
Jet(double value)
Lift a scalar constant into five-direction forward arithmetic.
Definition ImplicitWetKernels.hpp:35
static Jet seed(double value, int column)
Create one local independent variable for forward differentiation.
Definition ImplicitWetKernels.hpp:43
double v
Definition ImplicitWetKernels.hpp:21
Definition ImplicitWetKernels.hpp:216
Jet a
Definition ImplicitWetKernels.hpp:217
Jet c
Definition ImplicitWetKernels.hpp:217
Jet q
Definition ImplicitWetKernels.hpp:217
Jet i1
Definition ImplicitWetKernels.hpp:217
Jet u
Definition ImplicitWetKernels.hpp:217
uint8_t press
Definition ImplicitWetKernels.hpp:218