OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
HydClosureKernels.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2//
3// Copyright 2026 Caleb Buahin
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
43
44#ifndef OPENSWMM_ENGINE_HYD_CLOSURE_KERNELS_HPP
45#define OPENSWMM_ENGINE_HYD_CLOSURE_KERNELS_HPP
46
47#include <cmath>
48
49// Same convention as InertialKernels.hpp:45 / FvKernels.hpp: host builds get
50// plain `inline`; a device build defines this to KOKKOS_INLINE_FUNCTION before
51// including the header.
52#ifndef OPENSWMM_KERNEL_FN
53#define OPENSWMM_KERNEL_FN inline
54#endif
55
57
58// ===========================================================================
59// Force-main friction
60// ===========================================================================
61
65inline constexpr double kViscosity = 1.1e-5;
66
68inline constexpr double kGravity = 32.2;
69
80OPENSWMM_KERNEL_FN double fricSlopeHW(double velocity, double hyd_rad, double c_hw) noexcept {
81 if (c_hw <= 0.0 || hyd_rad <= 0.0)
82 return 0.0;
83 const double v_abs = (velocity < 0.0) ? -velocity : velocity;
84 return std::pow(v_abs / (1.318 * c_hw * std::pow(hyd_rad, 0.63)), 1.0 / 0.54);
85}
86
99OPENSWMM_KERNEL_FN double fricSlopeDW(double velocity, double hyd_rad, double roughness) noexcept {
100 if (hyd_rad <= 0.0)
101 return 0.0;
102 const double v_abs = (velocity < 0.0) ? -velocity : velocity;
103 const double diameter = 4.0 * hyd_rad;
104
105 const double re = v_abs * diameter / kViscosity;
106 if (re <= 0.0)
107 return 0.0;
108
109 double f;
110 if (re <= 2000.0) {
111 f = 64.0 / re; // laminar
112 } else {
113 const double e_over_d = roughness / diameter;
114 const double arg = e_over_d / 3.7 + 5.74 / std::pow(re, 0.9);
115 if (arg <= 0.0)
116 return 0.0;
117 const double logarg = std::log10(arg);
118 f = 0.25 / (logarg * logarg);
119 }
120 return f * v_abs * v_abs / (2.0 * kGravity * diameter);
121}
122
123// ===========================================================================
124// Culvert inlet control (FHWA HEC-5)
125// ===========================================================================
126
129 double K = 0.0;
130 double M = 0.0;
131 double C = 0.0;
132 double Y = 0.0;
133};
134
154OPENSWMM_KERNEL_FN double culvertInflow(double q_proposed, double head, double y_full,
155 double a_full, double slope, const CulvertCurve& cc,
156 bool mitered, double& dqdh) noexcept {
157 dqdh = 0.0;
158 if (head <= 0.0 || y_full <= 0.0 || a_full <= 0.0)
159 return q_proposed;
160 if (cc.K == 0.0)
161 return q_proposed;
162
163 const double AD = a_full * std::sqrt(y_full);
164 const double y_norm = head / y_full;
165 const double scf = mitered ? (-7.0 * slope) : (0.5 * slope);
166
167 const double y1_norm = 0.95;
168 double y2_norm = 16.0 * cc.C + cc.Y - scf;
169 if (y2_norm < y1_norm)
170 y2_norm = y1_norm + 0.01;
171
172 double q_inlet;
173 if (y_norm <= y1_norm) {
174 const double arg = y_norm / cc.K;
175 if (arg <= 0.0)
176 return q_proposed;
177 q_inlet = AD * std::pow(arg, 1.0 / cc.M);
178 dqdh = q_inlet / (head * cc.M);
179 } else if (y_norm >= y2_norm) {
180 const double arg = (y_norm - cc.Y + scf) / cc.C;
181 if (arg <= 0.0)
182 return q_proposed;
183 q_inlet = AD * std::sqrt(arg);
184 dqdh = 0.5 * q_inlet / (arg * y_full * cc.C);
185 } else {
186 const double arg1 = y1_norm / cc.K;
187 const double q1 = AD * std::pow(arg1, 1.0 / cc.M);
188 const double arg2 = (y2_norm - cc.Y + scf) / cc.C;
189 const double q2 = (arg2 > 0.0) ? AD * std::sqrt(arg2) : q1;
190
191 const double frac = (y_norm - y1_norm) / (y2_norm - y1_norm);
192 q_inlet = q1 + frac * (q2 - q1);
193 dqdh = (q2 - q1) / ((y2_norm - y1_norm) * y_full);
194 }
195 return (q_inlet < q_proposed) ? q_inlet : q_proposed;
196}
197
198} // namespace openswmm::hydkernels
199
200#endif // OPENSWMM_ENGINE_HYD_CLOSURE_KERNELS_HPP
#define OPENSWMM_KERNEL_FN
Definition ExplicitKokkosSurfaceSolver.cpp:22
Definition HydClosureKernels.hpp:56
OPENSWMM_KERNEL_FN double culvertInflow(double q_proposed, double head, double y_full, double a_full, double slope, const CulvertCurve &cc, bool mitered, double &dqdh) noexcept
Limit proposed culvert flow by a three-regime inlet-control curve.
Definition HydClosureKernels.hpp:154
constexpr double kViscosity
Definition HydClosureKernels.hpp:65
OPENSWMM_KERNEL_FN double fricSlopeHW(double velocity, double hyd_rad, double c_hw) noexcept
Compute Hazen-Williams friction slope from velocity and hydraulic radius.
Definition HydClosureKernels.hpp:80
OPENSWMM_KERNEL_FN double fricSlopeDW(double velocity, double hyd_rad, double roughness) noexcept
Compute Darcy-Weisbach slope with laminar or Swamee-Jain friction factor.
Definition HydClosureKernels.hpp:99
constexpr double kGravity
Gravity in internal units, matching constants::GRAVITY.
Definition HydClosureKernels.hpp:68
Inlet-control curve coefficients for one culvert type code.
Definition HydClosureKernels.hpp:128
double M
Definition HydClosureKernels.hpp:130
double Y
Definition HydClosureKernels.hpp:132
double K
Definition HydClosureKernels.hpp:129
double C
Definition HydClosureKernels.hpp:131