60#ifndef OPENSWMM_ENGINE_FV_KERNELS_HPP
61#define OPENSWMM_ENGINE_FV_KERNELS_HPP
73#ifndef OPENSWMM_KERNEL_FN
74#define OPENSWMM_KERNEL_FN inline
110 if (h <= 0.0)
return 0.0;
111 return g.barrel_scale * g.eval->getAofY(g.xs, (h < g.y_full) ? h : g.y_full);
118 if (h <= 0.0)
return 0.0;
119 return g.barrel_scale * g.eval->getWofY(g.xs, (h < g.y_full) ? h : g.y_full);
126 if (h <= 0.0)
return 0.0;
127 if (h >= g.y_full)
return g.r_full;
128 return g.eval->getRofY(g.xs, h);
139 if (s <= 0.0)
return 0.0;
140 if (s >= 1.0)
return 1.0;
141 return s * s * (3.0 - 2.0 * s);
147 if (s <= 0.0)
return 0.0;
148 if (s >= 1.0)
return s - 0.5;
149 const double s3 = s * s * s;
150 return s3 - 0.5 * s3 * s;
167 if (h <= 0.0)
return 0.0;
168 if (h >= g.y_full)
return g.a_crown + g.t_slot * (h - g.y_full);
169 const double band = g.y_full - g.y_crown;
171 if (band <= 0.0)
return ax;
172 const double s = (h - g.y_crown) / band;
178 if (h <= 0.0)
return 0.0;
179 if (h >= g.y_full)
return g.t_slot;
180 const double band = g.y_full - g.y_crown;
182 if (band <= 0.0)
return wx;
183 const double s = (h - g.y_crown) / band;
189 if (h <= 0.0)
return 0.0;
190 if (h >= g.y_full)
return g.r_full;
206 double area_at_h)
noexcept {
207 if (h <= 0.0)
return 0.0;
209 const double d = h - g.y_full;
210 return g.i1_crown + g.a_crown * d + 0.5 * g.t_slot * d * d;
213 const double dh = g.y_full /
static_cast<double>(n - 1);
214 int i =
static_cast<int>(h / dh);
216 if (i > n - 2) i = n - 2;
217 const double h_i =
static_cast<double>(i) * dh;
220 const double i1_i = g.i1_tbl[
static_cast<std::size_t
>(i)];
221 const double a_i = g.i1_tbl[
static_cast<std::size_t
>(n + i)];
222 return i1_i + 0.5 * (a_i + area_at_h) * (h - h_i);
255 if (a <= 0.0)
return 0.0;
256 if (a >= g.a_crown)
return g.y_full + (a - g.a_crown) / g.t_slot;
259 const double dh = g.y_full /
static_cast<double>(n - 1);
261 int lo = 0, hi = n - 1;
262 while (hi - lo > 1) {
263 const int mid = (lo + hi) / 2;
264 if (g.i1_tbl[
static_cast<std::size_t
>(n + mid)] <= a) lo = mid;
268 double xa =
static_cast<double>(lo) * dh;
269 double xb =
static_cast<double>(hi) * dh;
270 double fa = g.i1_tbl[
static_cast<std::size_t
>(n + lo)] - a;
271 double fb = g.i1_tbl[
static_cast<std::size_t
>(n + hi)] - a;
272 if (fa >= 0.0)
return xa;
273 if (fb <= 0.0)
return xb;
275 for (
int it = 0; it < 40; ++it) {
276 double x = xb - fb * (xb - xa) / (fb - fa);
277 if (!(x > xa && x < xb)) x = 0.5 * (xa + xb);
279 if (f == 0.0)
return x;
280 if (f < 0.0) { xa = x; fa = f; fb *= 0.5; }
281 else { xb = x; fb = f; fa *= 0.5; }
282 if (xb - xa <= 1.0e-15 * g.y_full)
break;
284 return 0.5 * (xa + xb);
324 if (a <= 0.0)
return 0.0;
325 if (a >= g.a_crown)
return g.y_full + (a - g.a_crown) / g.t_slot;
328 const double da = g.a_crown /
static_cast<double>(n - 1);
331 int j =
static_cast<int>(a / da);
333 if (j > n - 3) j = n - 3;
335 double xa = g.h_tbl[
static_cast<std::size_t
>(j - 1)];
336 double xb = g.h_tbl[
static_cast<std::size_t
>(j + 2)];
342 if (fa == 0.0)
return xa;
343 if (fb == 0.0)
return xb;
345 const double tol = 1.0e-15 * g.y_full;
346 double c = xa, fc = fa, d = xb - xa, e = d;
347 for (
int it = 0; it < 60; ++it) {
348 if (fb * fc > 0.0) { c = xa; fc = fa; d = xb - xa; e = d; }
349 if (std::fabs(fc) < std::fabs(fb)) {
350 xa = xb; xb = c; c = xa;
351 fa = fb; fb = fc; fc = fa;
353 const double m = 0.5 * (c - xb);
354 if (std::fabs(m) <= tol || fb == 0.0)
return xb;
356 if (std::fabs(e) < tol || std::fabs(fa) <= std::fabs(fb)) {
359 const double sfb = fb / fa;
365 const double qq = fa / fc;
366 const double r = fb / fc;
367 p = sfb * (2.0 * m * qq * (qq - r) - (xb - xa) * (r - 1.0));
368 q = (qq - 1.0) * (r - 1.0) * (sfb - 1.0);
370 if (p > 0.0) q = -q;
else p = -p;
371 if (2.0 * p < ((3.0 * m * q - std::fabs(tol * q) < std::fabs(e * q))
372 ? 3.0 * m * q - std::fabs(tol * q)
373 : std::fabs(e * q))) {
380 xb += (std::fabs(d) > tol) ? d : ((m > 0.0) ? tol : -tol);
389 if (a <=
kDryArea || t <= 0.0)
return 0.0;
419 double& sl,
double& sr)
noexcept {
423 sl = std::min(L.u - L.c, R.u - R.c);
424 sr = std::max(L.u + L.c, R.u + R.c);
426 sl = R.u - 2.0 * R.c;
430 sr = L.u + 2.0 * L.c;
439 double& fa,
double& fq)
noexcept {
469 double sl = 0.0, sr = 0.0;
474 double fal = 0.0, fql = 0.0, far = 0.0, fqr = 0.0;
478 if (sl >= 0.0) { out.
mass = fal; out.
mom = fql; out.
sstar = sl;
return out; }
479 if (sr <= 0.0) { out.
mass = far; out.
mom = fqr; out.
sstar = sr;
return out; }
481 const double dsr = sr - sl;
482 out.
mass = (sr * fal - sl * far + sl * sr * (R.a - L.a)) / dsr;
483 out.
mom = (sr * fql - sl * fqr + sl * sr * (R.q - L.q)) / dsr;
488 const double den = R.a * (R.u - sr) - L.a * (L.u - sl);
489 if (std::fabs(den) > 1.0e-14) {
490 out.
sstar = (sl * R.a * (R.u - sr) - sr * L.a * (L.u - sl)) / den;
492 const double a_hll = (sr * R.a - sl * L.a - (far - fal)) / dsr;
519 double phi_r,
bool hllc)
noexcept {
520 if (hllc)
return f.mass * ((f.sstar >= 0.0) ? phi_l : phi_r);
525 if (f.sl >= 0.0)
return L.q * phi_l;
526 if (f.sr <= 0.0)
return R.q * phi_r;
527 const double dsr = f.sr - f.sl;
528 return (f.sr * L.q * phi_l - f.sl * R.q * phi_r +
529 f.sl * f.sr * (R.a * phi_r - L.a * phi_l)) / dsr;
545 double dt,
double rough_factor)
noexcept {
546 if (r <= 0.0 || rough_factor <= 0.0)
return q;
547 const double r43 = r * std::cbrt(r);
548 const double den = 1.0 + dt * rough_factor * std::fabs(u) / r43;
561 double dx,
double dt)
noexcept {
562 if (k <= 0.0 || dx <= 0.0)
return q;
563 return q / (1.0 + dt * k * std::fabs(u) / (2.0 * dx));
583 double k3,
double grad_term,
584 double dt)
noexcept {
585 if (k3 <= 0.0 || a <= 0.0)
return q;
594 constexpr double kUfVelFloor = 0.01;
595 if (std::fabs(u_old) < kUfVelFloor && std::fabs(q / a) < kUfVelFloor)
597 double qn = (q + k3 * a * u_old) / (1.0 + k3);
598 qn -= dt * k3 * a * grad_term;
599 const double dq = qn - q;
600 const double cap = 0.5 * std::fabs(q);
601 if (std::fabs(dq) > cap) qn = q + ((dq > 0.0) ? cap : -cap);
622 return g.y_full + (a - g.a_crown) / g.t_slot;
626 return g.a_crown + g.t_slot * (h - g.y_full);
630 return g.i1_crown + g.a_crown * (h - g.y_full);
636 const double s = std::fabs(u) + c;
637 return (s > 1.0e-12) ? cfl * dx / s : 1.0e30;
649 if (outflow <= 0.0 || dt <= 0.0)
return 1.0;
650 const double take = outflow * dt;
651 const double avail = (vol > 0.0) ? vol : 0.0;
652 return (take <= avail) ? 1.0 : avail / take;
#define OPENSWMM_KERNEL_FN
Definition ExplicitKokkosSurfaceSolver.cpp:18
Option struct for the explicit finite-volume 1D network solver.
SoA storage for the 1D finite-volume network mesh and its state.
Definition FvKernels.hpp:77
OPENSWMM_KERNEL_FN FaceFlux riemannFlux(const FaceState &L, const FaceState &R) noexcept
Flux for the conservative St. Venant system, plus the contact speed.
Definition FvKernels.hpp:464
OPENSWMM_KERNEL_FN double frictionUpdate(double q, double u, double r, double dt, double rough_factor) noexcept
Semi-implicit Manning friction — unconditionally stable, so friction imposes no time-step restriction...
Definition FvKernels.hpp:544
OPENSWMM_KERNEL_FN void physicalFlux(const FaceState &S, double &fa, double &fq) noexcept
Physical flux of one state.
Definition FvKernels.hpp:438
OPENSWMM_KERNEL_FN double ufUpdate(double q, double a, double u_old, double k3, double grad_term, double dt) noexcept
Unsteady-friction momentum update (issue #156).
Definition FvKernels.hpp:582
OPENSWMM_KERNEL_FN double widthOfDepth(const FvGeometry &g, double h) noexcept
Top width dA/dh at depth h, INCLUDING the tapered slot.
Definition FvKernels.hpp:177
OPENSWMM_KERNEL_FN double faceCflDt(double cfl, double dx, double u, double c) noexcept
CFL-limited step for one face: α·Δx/(|u| + c).
Definition FvKernels.hpp:634
OPENSWMM_KERNEL_FN double localLossUpdate(double q, double u, double k, double dx, double dt) noexcept
Semi-implicit entrance/exit loss at a node-coupling face.
Definition FvKernels.hpp:560
OPENSWMM_KERNEL_FN void waveSpeeds(const FaceState &L, const FaceState &R, double &sl, double &sr) noexcept
Definition FvKernels.hpp:418
OPENSWMM_KERNEL_FN double positivityScale(double vol, double outflow, double dt) noexcept
Positivity scale for a cell about to export more volume than it holds.
Definition FvKernels.hpp:648
OPENSWMM_KERNEL_FN double hydRadOfDepth(const FvGeometry &g, double h) noexcept
Hydraulic radius at depth h.
Definition FvKernels.hpp:188
OPENSWMM_KERNEL_FN double sectionArea(const FvGeometry &g, double h) noexcept
Definition FvKernels.hpp:109
OPENSWMM_KERNEL_FN double slotRamp(double s) noexcept
Definition FvKernels.hpp:138
constexpr double kDryArea
Area floor paired with kDryDepth for the u = Q/A division.
Definition FvKernels.hpp:89
constexpr double kEtaDeadband
Definition FvKernels.hpp:94
OPENSWMM_KERNEL_FN double tpaDepthOfArea(const FvGeometry &g, double a) noexcept
Definition FvKernels.hpp:621
OPENSWMM_KERNEL_FN double areaOfDepth(const FvGeometry &g, double h) noexcept
Definition FvKernels.hpp:166
OPENSWMM_KERNEL_FN double i1OfDepth(const FvGeometry &g, double h, double area_at_h) noexcept
Hydrostatic first moment I₁(h) = ∫₀ʰ A(η)dη.
Definition FvKernels.hpp:205
OPENSWMM_KERNEL_FN double speciesFlux(const FaceState &L, const FaceState &R, const FaceFlux &f, double phi_l, double phi_r, bool hllc) noexcept
Species flux for the A(phi) component.
Definition FvKernels.hpp:517
OPENSWMM_KERNEL_FN double depthOfAreaBracketed(const FvGeometry &g, double a) noexcept
Invert A → h — the EXACT inverse of areaOfDepth above.
Definition FvKernels.hpp:253
OPENSWMM_KERNEL_FN double slotRampIntegral(double s) noexcept
Definition FvKernels.hpp:146
OPENSWMM_KERNEL_FN double tpaI1OfDepth(const FvGeometry &g, double h) noexcept
Definition FvKernels.hpp:629
OPENSWMM_KERNEL_FN double sectionWidth(const FvGeometry &g, double h) noexcept
Definition FvKernels.hpp:117
OPENSWMM_KERNEL_FN double depthOfArea(const FvGeometry &g, double a) noexcept
Invert A → h. Same root as depthOfAreaBracketed, found far faster.
Definition FvKernels.hpp:323
constexpr double kDryDepth
Definition FvKernels.hpp:86
OPENSWMM_KERNEL_FN double tpaAreaOfDepth(const FvGeometry &g, double h) noexcept
Definition FvKernels.hpp:625
constexpr double kGravity
Definition FvKernels.hpp:81
OPENSWMM_KERNEL_FN double celerity(double a, double t) noexcept
Definition FvKernels.hpp:388
OPENSWMM_KERNEL_FN double sectionHydRad(const FvGeometry &g, double h) noexcept
Definition FvKernels.hpp:125
constexpr int kI1Samples
Definition NetworkMeshData.hpp:61
Cross-section closure for one conduit's cell chain.
Definition NetworkMeshData.hpp:77
Result of a face flux evaluation.
Definition FvKernels.hpp:407
double mom
F[1] — momentum flux (ft⁴/s²)
Definition FvKernels.hpp:409
double sstar
contact-wave speed; sign selects the species upwind
Definition FvKernels.hpp:410
double mass
F[0] — volumetric flux (cfs)
Definition FvKernels.hpp:408
double sr
right signal speed
Definition FvKernels.hpp:412
double sl
left signal speed (kept for the species flux)
Definition FvKernels.hpp:411
One side of a face after hydrostatic reconstruction.
Definition FvKernels.hpp:398
double c
celerity (ft/s)
Definition FvKernels.hpp:402
double i1
hydrostatic first moment at the reconstructed depth
Definition FvKernels.hpp:403
double a
reconstructed flow area (ft²)
Definition FvKernels.hpp:399
double q
reconstructed discharge (cfs) = a·u
Definition FvKernels.hpp:400
double u
velocity (ft/s)
Definition FvKernels.hpp:401