OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
ExchangeLaw.hpp
Go to the documentation of this file.
1
48
49#ifndef OPENSWMM_ENGINE_2D_EXCHANGE_LAW_HPP
50#define OPENSWMM_ENGINE_2D_EXCHANGE_LAW_HPP
51
52#include <cmath>
53
54#if defined(KOKKOS_INLINE_FUNCTION)
55#define OPENSWMM_EXCHANGE_HD KOKKOS_INLINE_FUNCTION
56#else
57#define OPENSWMM_EXCHANGE_HD inline
58#endif
59
61
62constexpr double kGravity = 9.80665;
63constexpr double kSigmaBand = 0.1;
64
66struct Geometry {
67 double z_crest = 0.0;
68 double l_weir = 0.0;
69 double a_orif = 0.0;
70};
71
74 double c_w = 0.540;
75 double c_sw = 0.360;
76 double c_oi = 0.167;
77 double c_oo = 0.160;
78 double h_eps = 0.02;
79};
80
89OPENSWMM_EXCHANGE_HD double phi(double x, double eps) {
90 if (!(x > 0.0))
91 return 0.0;
92 if (x >= eps)
93 return std::sqrt(x);
94 const double inv_sqrt_e = 1.0 / std::sqrt(eps);
95 return (1.5 * inv_sqrt_e) * x - (0.5 * inv_sqrt_e / eps) * x * x;
96}
97
108OPENSWMM_EXCHANGE_HD double dphi(double x, double eps) {
109 if (!(x > 0.0))
110 return 1.5 / std::sqrt(eps);
111 if (x >= eps)
112 return 0.5 / std::sqrt(x);
113 const double inv_sqrt_e = 1.0 / std::sqrt(eps);
114 return 1.5 * inv_sqrt_e - (inv_sqrt_e / eps) * x;
115}
116
125 t = t < 0.0 ? 0.0 : (t > 1.0 ? 1.0 : t);
126 return t * t * (3.0 - 2.0 * t);
127}
128
142OPENSWMM_EXCHANGE_HD double softmin(double a, double b, double& wa, double& wb) {
143 wa = wb = 0.0;
144 if (!(a > 0.0) || !(b > 0.0))
145 return 0.0;
146 const bool a_min = a <= b;
147 const double lo = a_min ? a : b;
148 const double r = lo / (a_min ? b : a);
149 double r16 = r * r;
150 r16 *= r16;
151 r16 *= r16;
152 r16 *= r16;
153 const double root = std::sqrt(std::sqrt(std::sqrt(std::sqrt(1.0 + r16))));
154 const double s = 1.0 / root; // Q / min
155 const double q = lo * s;
156 // ∂Q/∂x = (Q/x)^17 for each argument x.
157 double s17 = s * s;
158 s17 *= s17;
159 s17 *= s17;
160 s17 *= s17;
161 s17 *= s;
162 const double rs = r * s;
163 double rs17 = rs * rs;
164 rs17 *= rs17;
165 rs17 *= rs17;
166 rs17 *= rs17;
167 rs17 *= rs;
168 if (a_min) {
169 wa = s17;
170 wb = rs17;
171 } else {
172 wb = s17;
173 wa = rs17;
174 }
175 return q;
176}
177
181struct Result {
182 double q = 0.0;
183 double g = 0.0;
184};
185
199 double h1) {
200 Result r;
201 const double s2g = std::sqrt(2.0 * kGravity);
202 const double z = geo.z_crest;
203 const double eps = c.h_eps;
204
205 if (h2 > h1) {
206 const double hs = h2 - z;
207 if (!(hs > 0.0))
208 return r;
209 const double dh = h2 - h1;
210 const double S = (h1 > z) ? smoothstep((h1 - z) / (kSigmaBand * hs)) : 0.0;
211
212 const double weir_free = (2.0 / 3.0) * c.c_w * geo.l_weir * s2g * hs * phi(hs, eps);
213 const double weir_sub = c.c_sw * geo.l_weir * s2g * hs * phi(dh, eps);
214 const double orif_free = c.c_oi * geo.a_orif * s2g * phi(hs, eps);
215 const double orif_sub = c.c_oi * geo.a_orif * s2g * phi(dh, eps);
216 const double qw = (1.0 - S) * weir_free + S * weir_sub;
217 const double qo = (1.0 - S) * orif_free + S * orif_sub;
218
219 double ww = 0.0, wo = 0.0;
220 r.q = softmin(qw, qo, ww, wo);
221 // Only the submerged forms depend on h1.
222 const double dqw = S * c.c_sw * geo.l_weir * s2g * hs * dphi(dh, eps);
223 const double dqo = S * c.c_oi * geo.a_orif * s2g * dphi(dh, eps);
224 r.g = ww * dqw + wo * dqo;
225 return r;
226 }
227 if (h1 > h2 && h1 > z) {
228 const double head_dry = h1 - z;
229 const double S = (h2 > z) ? smoothstep((h2 - z) / (kSigmaBand * head_dry)) : 0.0;
230 const double k = c.c_oo * geo.a_orif * s2g;
231 r.q = -k * ((1.0 - S) * phi(head_dry, eps) + S * phi(h1 - h2, eps));
232 r.g = k * ((1.0 - S) * dphi(head_dry, eps) + S * dphi(h1 - h2, eps));
233 return r;
234 }
235 return r;
236}
237
238} // namespace openswmm::twoD::exchange
239
240#undef OPENSWMM_EXCHANGE_HD
241
242#endif // OPENSWMM_ENGINE_2D_EXCHANGE_LAW_HPP
#define OPENSWMM_EXCHANGE_HD
Definition ExchangeLaw.hpp:57
Definition ExchangeLaw.hpp:60
OPENSWMM_EXCHANGE_HD Result exchange(const Geometry &geo, const Coefficients &c, double h2, double h1)
Evaluate the bidirectional regularized weir/orifice exchange and damping.
Definition ExchangeLaw.hpp:198
constexpr double kGravity
m/s²
Definition ExchangeLaw.hpp:62
OPENSWMM_EXCHANGE_HD double smoothstep(double t)
Hermite smoothstep of t clamped to [0, 1].
Definition ExchangeLaw.hpp:124
OPENSWMM_EXCHANGE_HD double phi(double x, double eps)
C¹-regularised √x: √x for x ≥ ε, (3/(2√ε))x − x²/(2ε^{3/2}) below.
Definition ExchangeLaw.hpp:89
OPENSWMM_EXCHANGE_HD double softmin(double a, double b, double &wa, double &wb)
p-norm minimum, p = 16: (a^−16 + b^−16)^(−1/16) for a, b > 0, else 0. Evaluated as min / (1 + r^16)^(...
Definition ExchangeLaw.hpp:142
constexpr double kSigmaBand
submergence blend width
Definition ExchangeLaw.hpp:63
OPENSWMM_EXCHANGE_HD double dphi(double x, double eps)
dφ/dx (finite at 0).
Definition ExchangeLaw.hpp:108
Discharge coefficients and the φ regularisation head.
Definition ExchangeLaw.hpp:73
double h_eps
φ regularisation head (m)
Definition ExchangeLaw.hpp:78
double c_sw
submerged weir
Definition ExchangeLaw.hpp:75
double c_oo
orifice, sewer → surface
Definition ExchangeLaw.hpp:77
double c_oi
orifice, surface → sewer
Definition ExchangeLaw.hpp:76
double c_w
free weir
Definition ExchangeLaw.hpp:74
A coupling point's structure, SI.
Definition ExchangeLaw.hpp:66
double a_orif
orifice / open area (m²)
Definition ExchangeLaw.hpp:69
double l_weir
weir crest length (m)
Definition ExchangeLaw.hpp:68
double z_crest
crest / rim elevation (m, 2D frame)
Definition ExchangeLaw.hpp:67
Definition ExchangeLaw.hpp:181
double q
Definition ExchangeLaw.hpp:182
double g
Definition ExchangeLaw.hpp:183