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
72OPENSWMM_KERNEL_FN double fricSlopeHW(double velocity, double hyd_rad,
73 double c_hw) noexcept {
74 if (c_hw <= 0.0 || hyd_rad <= 0.0) return 0.0;
75 const double v_abs = (velocity < 0.0) ? -velocity : velocity;
76 return std::pow(v_abs / (1.318 * c_hw * std::pow(hyd_rad, 0.63)),
77 1.0 / 0.54);
78}
79
83OPENSWMM_KERNEL_FN double fricSlopeDW(double velocity, double hyd_rad,
84 double roughness) noexcept {
85 if (hyd_rad <= 0.0) return 0.0;
86 const double v_abs = (velocity < 0.0) ? -velocity : velocity;
87 const double diameter = 4.0 * hyd_rad;
88
89 const double re = v_abs * diameter / kViscosity;
90 if (re <= 0.0) return 0.0;
91
92 double f;
93 if (re <= 2000.0) {
94 f = 64.0 / re; // laminar
95 } else {
96 const double e_over_d = roughness / diameter;
97 const double arg = e_over_d / 3.7 + 5.74 / std::pow(re, 0.9);
98 if (arg <= 0.0) return 0.0;
99 const double logarg = std::log10(arg);
100 f = 0.25 / (logarg * logarg);
101 }
102 return f * v_abs * v_abs / (2.0 * kGravity * diameter);
103}
104
105// ===========================================================================
106// Culvert inlet control (FHWA HEC-5)
107// ===========================================================================
108
111 double K = 0.0;
112 double M = 0.0;
113 double C = 0.0;
114 double Y = 0.0;
115};
116
131OPENSWMM_KERNEL_FN double culvertInflow(double q_proposed, double head,
132 double y_full, double a_full,
133 double slope, const CulvertCurve& cc,
134 bool mitered, double& dqdh) noexcept {
135 dqdh = 0.0;
136 if (head <= 0.0 || y_full <= 0.0 || a_full <= 0.0) return q_proposed;
137 if (cc.K == 0.0) return q_proposed;
138
139 const double AD = a_full * std::sqrt(y_full);
140 const double y_norm = head / y_full;
141 const double scf = mitered ? (-7.0 * slope) : (0.5 * slope);
142
143 const double y1_norm = 0.95;
144 double y2_norm = 16.0 * cc.C + cc.Y - scf;
145 if (y2_norm < y1_norm) y2_norm = y1_norm + 0.01;
146
147 double q_inlet;
148 if (y_norm <= y1_norm) {
149 const double arg = y_norm / cc.K;
150 if (arg <= 0.0) return q_proposed;
151 q_inlet = AD * std::pow(arg, 1.0 / cc.M);
152 dqdh = q_inlet / (head * cc.M);
153 } else if (y_norm >= y2_norm) {
154 const double arg = (y_norm - cc.Y + scf) / cc.C;
155 if (arg <= 0.0) return q_proposed;
156 q_inlet = AD * std::sqrt(arg);
157 dqdh = 0.5 * q_inlet / (arg * y_full * cc.C);
158 } else {
159 const double arg1 = y1_norm / cc.K;
160 const double q1 = AD * std::pow(arg1, 1.0 / cc.M);
161 const double arg2 = (y2_norm - cc.Y + scf) / cc.C;
162 const double q2 = (arg2 > 0.0) ? AD * std::sqrt(arg2) : q1;
163
164 const double frac = (y_norm - y1_norm) / (y2_norm - y1_norm);
165 q_inlet = q1 + frac * (q2 - q1);
166 dqdh = (q2 - q1) / ((y2_norm - y1_norm) * y_full);
167 }
168 return (q_inlet < q_proposed) ? q_inlet : q_proposed;
169}
170
171} // namespace openswmm::hydkernels
172
173#endif // OPENSWMM_ENGINE_HYD_CLOSURE_KERNELS_HPP
#define OPENSWMM_KERNEL_FN
Definition ExplicitKokkosSurfaceSolver.cpp:18
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
Inlet-controlled discharge for one culvert.
Definition HydClosureKernels.hpp:131
constexpr double kViscosity
Definition HydClosureKernels.hpp:65
OPENSWMM_KERNEL_FN double fricSlopeHW(double velocity, double hyd_rad, double c_hw) noexcept
Definition HydClosureKernels.hpp:72
OPENSWMM_KERNEL_FN double fricSlopeDW(double velocity, double hyd_rad, double roughness) noexcept
Definition HydClosureKernels.hpp:83
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:110
double M
Definition HydClosureKernels.hpp:112
double Y
Definition HydClosureKernels.hpp:114
double K
Definition HydClosureKernels.hpp:111
double C
Definition HydClosureKernels.hpp:113