58#ifndef OPENSWMM_ENGINE_FV_CLOSURE_KERNELS_HPP
59#define OPENSWMM_ENGINE_FV_CLOSURE_KERNELS_HPP
66#ifndef OPENSWMM_KERNEL_FN
67#define OPENSWMM_KERNEL_FN inline
111static_assert(std::is_trivially_copyable_v<FvClosure>,
112 "FvClosure must be a plain buffer a device backend can copy");
113static_assert(std::is_standard_layout_v<FvClosure>,
"FvClosure must be standard-layout");
138 double x = h * c.inv_dh;
139 i =
static_cast<int>(x);
144 t = x -
static_cast<double>(i);
167 double& int_dh)
noexcept {
168 const double a0 = c.A[i], a1 = c.A[i + 1];
169 const double m0 = c.M[i] * c.dh, m1 = c.M[i + 1] * c.dh;
170 const double t2 = t * t, t3 = t2 * t;
171 const double h00 = 2.0 * t3 - 3.0 * t2 + 1.0;
172 const double h10 = t3 - 2.0 * t2 + t;
173 const double h01 = -2.0 * t3 + 3.0 * t2;
174 const double h11 = t3 - t2;
175 a = h00 * a0 + h10 * m0 + h01 * a1 + h11 * m1;
176 const double d00 = 6.0 * t2 - 6.0 * t;
177 const double d10 = 3.0 * t2 - 4.0 * t + 1.0;
178 const double d01 = -6.0 * t2 + 6.0 * t;
179 const double d11 = 3.0 * t2 - 2.0 * t;
180 dadh = (d00 * a0 + d10 * m0 + d01 * a1 + d11 * m1) * c.inv_dh;
181 const double t4 = t2 * t2;
182 const double i00 = 0.5 * t4 - t3 + t;
183 const double i10 = 0.25 * t4 - (2.0 / 3.0) * t3 + 0.5 * t2;
184 const double i01 = -0.5 * t4 + t3;
185 const double i11 = 0.25 * t4 - t3 / 3.0;
186 int_dh = (i00 * a0 + i10 * m0 + i01 * a1 + i11 * m1) * c.dh;
208 const double d = h - c.y_full;
209 e.
a = c.a_crown + c.t_slot * d;
211 e.
i1 = c.i1_crown + c.a_crown * d + 0.5 * c.t_slot * d * d;
215 e.
a = (c.c2 * h + c.c1) * h;
216 e.
t = 2.0 * c.c2 * h + c.c1;
217 e.
i1 = (c.c2 * h / 3.0 + 0.5 * c.c1) * h * h;
226 e.
t = (dadh > 0.0) ? dadh : 0.0;
227 e.
i1 = c.I1[i] + idh;
250 const double d = h - c.y_full;
251 e.
a = c.a_crown + c.t_slot * d;
253 e.
i1 = c.i1_crown + c.a_crown * d + 0.5 * c.t_slot * d * d;
257 e.
a = (c.c2 * h + c.c1) * h;
258 const double p = c.p0 + c.p1 * h;
259 radius = (p > 0.0) ? (c.c2 * h + c.c1) * h / p : 0.0;
260 e.
t = 2.0 * c.c2 * h + c.c1;
261 e.
i1 = (c.c2 * h / 3.0 + 0.5 * c.c1) * h * h;
267 radius = c.R[i] + t * (c.R[i + 1] - c.R[i]);
271 e.
t = (dadh > 0.0) ? dadh : 0.0;
272 e.
i1 = c.I1[i] + idh;
293 return c.a_crown + c.t_slot * (h - c.y_full);
295 return (c.c2 * h + c.c1) * h;
323 return 2.0 * c.c2 * h + c.c1;
329 return (dadh > 0.0) ? dadh : 0.0;
369 const double p = c.p0 + c.p1 * h;
370 return (p > 0.0) ? (c.c2 * h + c.c1) * h / p : 0.0;
375 return c.R[i] + t * (c.R[i + 1] - c.R[i]);
398 return c.y_full + (a - c.a_crown) / c.t_slot;
401 return (c.c1 > 0.0) ? a / c.c1 : 0.0;
402 return 2.0 * a / (c.c1 + std::sqrt(c.c1 * c.c1 + 4.0 * c.c2 * a));
405 int k =
static_cast<int>(a * c.inv_a_crown_n);
411 while (i > 0 && c.A[i] > a)
416 const double a0 = c.A[i], a1 = c.A[i + 1];
418 return static_cast<double>(i) * c.dh;
420 return static_cast<double>(i + 1) * c.dh;
422 const double tol = 1.0e-15 * c.y_full * c.inv_dh;
423 double lo = 0.0, hi = 1.0;
424 const double frac = (a - a0) / (a1 - a0);
428 double t = (c.M[i] > 0.0) ? frac : std::sqrt(frac);
429 for (
int it = 0; it < 12; ++it) {
442 const double dadt = dadh * c.dh;
443 double step = (dadt > 0.0) ? -f / dadt : 0.0;
444 if (dadt > 0.0 && std::fabs(step) <= tol)
446 double tn = t + step;
447 if (!(dadt > 0.0) || !(tn > lo && tn < hi))
448 tn = 0.5 * (lo + hi);
451 if (std::fabs(step) <= tol)
454 return static_cast<double>(i) * c.dh + t * c.dh;
#define OPENSWMM_KERNEL_FN
Definition ExplicitKokkosSurfaceSolver.cpp:22
Definition FvClosureKernels.hpp:115
OPENSWMM_KERNEL_FN double closureArea(const FvClosure &c, double h) noexcept
Evaluate the closure flow area.
Definition FvClosureKernels.hpp:289
OPENSWMM_KERNEL_FN double closureWidth(const FvClosure &c, double h) noexcept
Evaluate the closure area derivative used as top width.
Definition FvClosureKernels.hpp:317
OPENSWMM_KERNEL_FN double closureI1(const FvClosure &c, double h) noexcept
Evaluate the closure hydrostatic first moment.
Definition FvClosureKernels.hpp:345
OPENSWMM_KERNEL_FN double closureDepthOfArea(const FvClosure &c, double a) noexcept
Invert aggregate closure area using the same forward geometry.
Definition FvClosureKernels.hpp:394
OPENSWMM_KERNEL_FN void closureHermite(const FvClosure &c, int i, double t, double &a, double &dadh, double &int_dh) noexcept
Evaluate one cubic area panel, its derivative and its partial integral.
Definition FvClosureKernels.hpp:166
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
OPENSWMM_KERNEL_FN double closureHydRad(const FvClosure &c, double h) noexcept
Evaluate the friction hydraulic radius.
Definition FvClosureKernels.hpp:363
Definition AcceptedWaterVolumes.hpp:8
@ kClosureTabulated
Definition FvClosureKernels.hpp:76
@ kClosurePolynomial
Definition FvClosureKernels.hpp:76
constexpr int kClosurePanels
Panels of the closure table, uniform in depth on [0, y_full].
Definition FvClosureKernels.hpp:73
One section's closure. Fixed-size POD: inline arrays, no pointers.
Definition FvClosureKernels.hpp:89
double inv_a_crown_n
kClosurePanels / a_crown
Definition FvClosureKernels.hpp:97
double r_full
R above the crown.
Definition FvClosureKernels.hpp:96
double t_slot
slot top width above the crown
Definition FvClosureKernels.hpp:94
uint8_t kind
Definition FvClosureKernels.hpp:102
int16_t j_of_a[kClosurePanels+1]
Definition FvClosureKernels.hpp:108
double a_crown
A(y_full) incl. the tapered slot = A[N].
Definition FvClosureKernels.hpp:93
double A[kClosurePanels+1]
Definition FvClosureKernels.hpp:104
double inv_dh
Definition FvClosureKernels.hpp:92
double y_full
Definition FvClosureKernels.hpp:90
double i1_crown
I₁(y_full) = I1[N].
Definition FvClosureKernels.hpp:95
double dh
Definition FvClosureKernels.hpp:91
double M[kClosurePanels+1]
Definition FvClosureKernels.hpp:105
double c1
Definition FvClosureKernels.hpp:100
double p1
Definition FvClosureKernels.hpp:100
double I1[kClosurePanels+1]
Definition FvClosureKernels.hpp:106
double R[kClosurePanels+1]
Definition FvClosureKernels.hpp:107
double c2
Definition FvClosureKernels.hpp:100
double p0
Definition FvClosureKernels.hpp:100
A, T and I₁ at one depth, from one panel locate.
Definition FvClosureKernels.hpp:118
double i1
Definition FvClosureKernels.hpp:121
double t
Definition FvClosureKernels.hpp:120
double a
Definition FvClosureKernels.hpp:119