37#ifndef OPENSWMM_ENGINE_2D_GPU_KOKKOS_SURFACE_KERNELS_HPP
38#define OPENSWMM_ENGINE_2D_GPU_KOKKOS_SURFACE_KERNELS_HPP
40#include <Kokkos_Core.hpp>
68#if defined(OPENSWMM_GPU_EXECSPACE_CUDA)
70#elif defined(OPENSWMM_GPU_EXECSPACE_HIP)
72#elif defined(OPENSWMM_GPU_EXECSPACE_SYCL)
74#elif defined(OPENSWMM_GPU_EXECSPACE_OPENMP)
81using DView = Kokkos::View<double*, MemSpace>;
82using CDView = Kokkos::View<const double*, MemSpace>;
83using IView = Kokkos::View<int*, MemSpace>;
84using CIView = Kokkos::View<const int*, MemSpace>;
125KOKKOS_INLINE_FUNCTION
126double evapSink(
double rate,
double depth,
double dry_depth) {
127 if (rate <= 0.0 || depth <= 0.0)
return 0.0;
128 if (depth >= dry_depth)
return rate;
129 const double t = depth / dry_depth;
130 return rate * t * t * (3.0 - 2.0 * t);
133KOKKOS_INLINE_FUNCTION
double sq(
double x) {
return x * x; }
135KOKKOS_INLINE_FUNCTION
int nbr_of(
int e,
int n0,
int n1,
int n2) {
136 return (e == 0) ? n0 : (e == 1) ? n1 : n2;
145KOKKOS_INLINE_FUNCTION
double regSqrt(
double x,
double eps) {
146 if (eps <= 0.0 || x >= eps)
return Kokkos::sqrt(x);
147 const double inv = 1.0 / Kokkos::sqrt(eps);
148 return (1.5 * inv) * x - (0.5 * inv / eps) * x * x;
161KOKKOS_INLINE_FUNCTION
163 double depth,
double head,
double tri_cz,
double area,
164 double L,
double n,
double dh_eps) {
167 if (slope <= 0.0 || depth <= 0.0 || n <= 0.0)
return 0.0;
168 const double h53 = depth * Kokkos::cbrt(depth * depth);
169 return -(h53 * Kokkos::sqrt(slope) / n) * L;
175 if (n <= 0.0)
return 0.0;
176 const double dh = head - h_bc;
177 const double dx_b = (L > 1.0e-12) ? (2.0 * area) / (3.0 * L) : 0.0;
178 if (dx_b <= 1.0e-12)
return 0.0;
179 const double h_up = (dh > 0.0) ? depth
180 : Kokkos::fmax(h_bc - tri_cz, 0.0);
181 if (h_up <= 0.0)
return 0.0;
182 const double h53 = h_up * Kokkos::cbrt(h_up * h_up);
183 const double sgn = (dh > 0.0) ? 1.0 : (dh < 0.0 ? -1.0 : 0.0);
184 return -h53 * sgn *
regSqrt(Kokkos::fabs(dh), dh_eps) * L
185 / (n * Kokkos::sqrt(dx_b));
199 double dry_depth,
double limiter_eps,
double dh_eps) {
200 const int nt = m.
n_tri;
212 auto head = s.
head;
auto depth = s.
depth;
219 const bool has_bc = (bc_type.extent(0) > 0);
223 Kokkos::parallel_for(
"rhs_unpack", Kokkos::RangePolicy<ExecSpace>(0, nt),
224 KOKKOS_LAMBDA(
int i) {
225 const double A = tri_area(i);
226 const double v =
y(i) > 0.0 ?
y(i) : 0.0;
227 const double d = (A > 1.0e-30) ? v / A : 0.0;
229 head(i) = tri_cz(i) + d;
233 Kokkos::parallel_for(
"rhs_vertex_heads", Kokkos::RangePolicy<ExecSpace>(0, nv),
234 KOKKOS_LAMBDA(
int b) {
235 const int start = v_ptr(b);
236 const int end = v_ptr(b + 1);
238 for (
int k = start; k < end; ++k) h += v_wt(k) * head(v_idx(k));
243 Kokkos::parallel_for(
"rhs_grad_unlimited", Kokkos::RangePolicy<ExecSpace>(0, nt),
244 KOKKOS_LAMBDA(
int i) {
245 const double inv_area = (tri_area(i) > 1.0e-30) ? 1.0 / tri_area(i) : 0.0;
246 const int n0 = nb0(i), n1 = nb1(i), n2 = nb2(i);
247 double ax = 0.0, ay = 0.0;
248 for (
int e = 0; e < 3; ++e) {
249 const int idx = i * 3 + e;
250 const int nbr =
nbr_of(e, n0, n1, n2);
251 const double h_edge = (nbr >= 0) ? 0.5 * (head(i) + head(nbr))
253 ax += h_edge * e_nx(idx) * e_len(idx);
254 ay += h_edge * e_ny(idx) * e_len(idx);
256 gx(i) = ax * inv_area;
257 gy(i) = ay * inv_area;
261 Kokkos::parallel_for(
"rhs_grad_limited", Kokkos::RangePolicy<ExecSpace>(0, nt),
262 KOKKOS_LAMBDA(
int i) {
263 const double eps2 = limiter_eps * limiter_eps;
264 const double q0 =
sq(gx(i)) +
sq(gy(i)) + eps2;
265 const int n0 = nb0(i), n1 = nb1(i), n2 = nb2(i);
266 double q[3], gxn[3], gyn[3];
267 for (
int e = 0; e < 3; ++e) {
268 const int nbr =
nbr_of(e, n0, n1, n2);
270 q[e] =
sq(gx(nbr)) +
sq(gy(nbr)) + eps2;
279 const double m0 = q[0] * q[1] * q[2];
280 const double m1 = q0 * q[1] * q[2];
281 const double m2 = q0 * q[0] * q[2];
282 const double m3 = q0 * q[0] * q[1];
283 const double denom = m0 + m1 + m2 + m3;
284 const double w0 = m0 / denom, w1 = m1 / denom,
285 w2 = m2 / denom, w3 = m3 / denom;
286 gxl(i) = w0 * gx(i) + w1 * gxn[0] + w2 * gxn[1] + w3 * gxn[2];
287 gyl(i) = w0 * gy(i) + w1 * gyn[0] + w2 * gyn[1] + w3 * gyn[2];
291 Kokkos::parallel_for(
"rhs_edge_flux", Kokkos::RangePolicy<ExecSpace>(0, nt),
292 KOKKOS_LAMBDA(
int i) {
293 const int n0 = nb0(i), n1 = nb1(i), n2 = nb2(i);
294 for (
int e = 0; e < 3; ++e) {
295 const int idx = i * 3 + e;
296 const int nbr =
nbr_of(e, n0, n1, n2);
301 bc_head(idx), bc_flow(idx), depth(i), head(i),
302 tri_cz(i), tri_area(i), e_len(idx), mn(i), dh_eps)
307 const double h_L = head(i), h_R = head(nbr);
308 const int up = (h_L >= h_R) ? i : nbr;
309 const double depth_up = depth(up);
310 if (depth_up <= 0.0) { eflux(idx) = 0.0;
continue; }
312 const double dxx = tri_cx(i) - tri_cx(nbr);
313 const double dxy = tri_cy(i) - tri_cy(nbr);
314 const double dx = Kokkos::sqrt(dxx * dxx + dxy * dxy);
315 if (dx < 1.0e-12) { eflux(idx) = 0.0;
continue; }
317 const double dh = h_L - h_R;
318 const double abs_dh = Kokkos::fabs(dh);
319 const double sign_dh = (dh > 0.0) ? 1.0 : (dh < 0.0 ? -1.0 : 0.0);
320 const double h53 = depth_up * Kokkos::cbrt(depth_up * depth_up);
321 const double n_up = mn(up);
322 const double xi = e_len(idx);
324 double F_e = -h53 * sign_dh *
regSqrt(abs_dh, dh_eps) * xi
325 / (n_up * Kokkos::sqrt(dx));
340 Kokkos::parallel_for(
"rhs_assemble", Kokkos::RangePolicy<ExecSpace>(0, nt),
341 KOKKOS_LAMBDA(
int i) {
342 const double area = tri_area(i);
344 for (
int e = 0; e < 3; ++e) fs += eflux(i * 3 + e);
345 ydot(i) = fs + area * (rain(i) + coup(i)
346 -
evapSink(evap(i), depth(i), dry_depth));
356 const int nt = m.
n_tri;
360 Kokkos::parallel_for(
"prec_setup", Kokkos::RangePolicy<ExecSpace>(0, nt),
361 KOKKOS_LAMBDA(
int i) {
362 constexpr double dh_floor = 1.0e-9;
363 const int n0 = nb0(i), n1 = nb1(i), n2 = nb2(i);
365 for (
int e = 0; e < 3; ++e) {
366 const int nbr =
nbr_of(e, n0, n1, n2);
367 if (nbr < 0)
continue;
368 const double dh = Kokkos::fabs(head(i) - head(nbr));
369 const double F = Kokkos::fabs(eflux(i * 3 + e));
370 T_sum += F / Kokkos::fmax(dh, dh_floor);
372 const double inv_area = (tri_area(i) > 1.0e-30) ? 1.0 / tri_area(i) : 0.0;
373 D(i) = -T_sum * inv_area;
379 const int nt =
static_cast<int>(s.
precond_diag.extent(0));
381 Kokkos::parallel_for(
"prec_solve", Kokkos::RangePolicy<ExecSpace>(0, nt),
382 KOKKOS_LAMBDA(
int i) {
383 constexpr double m_floor = 1.0e-12;
384 double mval = 1.0 - gamma * D(i);
385 if (Kokkos::fabs(mval) < m_floor) mval = Kokkos::copysign(m_floor, mval);
Definition ArkodeKokkosSurfaceSolver.cpp:29
Kokkos::View< int *, MemSpace > IView
mutable int array
Definition KokkosSurfaceKernels.hpp:83
@ BC_NORMAL_FLOW
Definition KokkosSurfaceKernels.hpp:153
@ BC_WALL
Definition KokkosSurfaceKernels.hpp:153
@ BC_SPECIFIED_FLOW
Definition KokkosSurfaceKernels.hpp:154
@ BC_SPECIFIED_STAGE
Definition KokkosSurfaceKernels.hpp:153
@ BC_RATING_CURVE
Definition KokkosSurfaceKernels.hpp:154
void evaluateRhs(const MeshViews &m, const StateViews &s, DView y, DView ydot, double dry_depth, double limiter_eps, double dh_eps)
Definition KokkosSurfaceKernels.hpp:197
Kokkos::DefaultExecutionSpace ExecSpace
Definition KokkosSurfaceKernels.hpp:77
KOKKOS_INLINE_FUNCTION double sq(double x)
Definition KokkosSurfaceKernels.hpp:133
Kokkos::View< double *, MemSpace > DView
mutable double array
Definition KokkosSurfaceKernels.hpp:81
ExecSpace::memory_space MemSpace
Definition KokkosSurfaceKernels.hpp:79
Kokkos::View< const double *, MemSpace > CDView
const double array
Definition KokkosSurfaceKernels.hpp:82
Kokkos::View< const int *, MemSpace > CIView
const int array
Definition KokkosSurfaceKernels.hpp:84
void precondSetup(const MeshViews &m, const StateViews &s)
Build the per-cell diagonal D from the most recent edge fluxes/heads.
Definition KokkosSurfaceKernels.hpp:355
KOKKOS_INLINE_FUNCTION double evapSink(double rate, double depth, double dry_depth)
Depth-limited evaporation sink (mirrors evapSink()).
Definition KokkosSurfaceKernels.hpp:126
KOKKOS_INLINE_FUNCTION double boundaryEdgeFlux(int bc, double slope, double h_bc, double q_flow, double depth, double head, double tri_cz, double area, double L, double n, double dh_eps)
Definition KokkosSurfaceKernels.hpp:162
KOKKOS_INLINE_FUNCTION int nbr_of(int e, int n0, int n1, int n2)
Definition KokkosSurfaceKernels.hpp:135
KOKKOS_INLINE_FUNCTION double regSqrt(double x, double eps)
Definition KokkosSurfaceKernels.hpp:145
void precondSolve(const StateViews &s, DView r, DView z, double gamma)
Apply (I − γD)^{-1} element-wise: z = r / (1 − γ·D).
Definition KokkosSurfaceKernels.hpp:378
double * y
Definition odesolve.c:28
Immutable mesh geometry/topology mirrored to device once at initialize().
Definition KokkosSurfaceKernels.hpp:87
int n_vert
Definition KokkosSurfaceKernels.hpp:89
CIView vert_ptr
[n_vert+1]
Definition KokkosSurfaceKernels.hpp:96
CIView tri_nbr1
Definition KokkosSurfaceKernels.hpp:92
CDView tri_area
Definition KokkosSurfaceKernels.hpp:91
CIView tri_nbr2
[n_tri]
Definition KokkosSurfaceKernels.hpp:92
CDView tri_cy
Definition KokkosSurfaceKernels.hpp:91
CDView mannings_n
[n_tri]
Definition KokkosSurfaceKernels.hpp:91
CDView tri_cz
Definition KokkosSurfaceKernels.hpp:91
CDView edge_ny
Definition KokkosSurfaceKernels.hpp:93
int n_tri
Definition KokkosSurfaceKernels.hpp:88
CDView vert_wt
[nnz]
Definition KokkosSurfaceKernels.hpp:98
CIView vert_idx
[nnz]
Definition KokkosSurfaceKernels.hpp:97
CIView tri_nbr0
Definition KokkosSurfaceKernels.hpp:92
CDView edge_nx
Definition KokkosSurfaceKernels.hpp:93
CDView tri_cx
Definition KokkosSurfaceKernels.hpp:91
CDView edge_conveyance
[n_tri*3]
Definition KokkosSurfaceKernels.hpp:93
CDView edge_length
Definition KokkosSurfaceKernels.hpp:93
Mutable per-step state mirrored on device.
Definition KokkosSurfaceKernels.hpp:102
DView grad_hy_lim
[n_tri]
Definition KokkosSurfaceKernels.hpp:104
DView coupling_flux
Definition KokkosSurfaceKernels.hpp:107
DView vert_head
[n_vert]
Definition KokkosSurfaceKernels.hpp:105
DView grad_hy
Definition KokkosSurfaceKernels.hpp:104
DView head
Definition KokkosSurfaceKernels.hpp:103
DView edge_bc_flow
SPECIFIED_FLOW / RATING_CURVE per-metre flow (per step)
Definition KokkosSurfaceKernels.hpp:117
DView precond_diag
[n_tri] Jacobi diag
Definition KokkosSurfaceKernels.hpp:108
IView edge_bc_type
BoundaryType per edge (0=WALL..4=RATING_CURVE)
Definition KokkosSurfaceKernels.hpp:114
DView grad_hx
Definition KokkosSurfaceKernels.hpp:104
DView grad_hx_lim
Definition KokkosSurfaceKernels.hpp:104
DView edge_bed_slope
NORMAL_FLOW bed slope (static)
Definition KokkosSurfaceKernels.hpp:115
DView edge_bc_head
SPECIFIED_STAGE prescribed head (per step)
Definition KokkosSurfaceKernels.hpp:116
DView evap_rate
[n_tri] sources
Definition KokkosSurfaceKernels.hpp:107
DView depth
[n_tri]
Definition KokkosSurfaceKernels.hpp:103
DView edge_flux
[n_tri*3]
Definition KokkosSurfaceKernels.hpp:106
DView rainfall
Definition KokkosSurfaceKernels.hpp:107