Mallard 0.8.0
Unstructured, GPU accelerated, high-order finite volume CFD solver
Mallard website
Loading...
Searching...
No Matches
teno.h
Go to the documentation of this file.
1
12#ifndef TENO_H
13#define TENO_H
14
15#include <Kokkos_Core.hpp>
16
17#include "common.h"
18
19namespace teno {
20
21constexpr uint8_t MAX_DEGREE = 5;
22
27constexpr uint8_t n_dof(const uint8_t r) {
28 if constexpr (N_DIM == 2) {
29 return static_cast<uint8_t>((r + 1) * (r + 2) / 2 - 1);
30 } else {
31 return static_cast<uint8_t>((r + 1) * (r + 2) * (r + 3) / 6 - 1);
32 }
33}
34
35constexpr uint8_t MAX_NK = n_dof(MAX_DEGREE); // non-constant dofs
36constexpr uint8_t NK_SMALL = n_dof(2); // degree-2 dofs
37constexpr uint8_t MAX_FACES = (N_DIM == 2) ? 4 : 6;
38constexpr uint8_t MAX_FACE_QUAD = (N_DIM == 2) ? 4 : 9;
39
45constexpr uint16_t upper_index(const uint8_t l, const uint8_t m, const uint8_t n) {
46 return static_cast<uint16_t>(l * n - l * (l - 1) / 2 + (m - l));
47}
48
55 Kokkos::SpaceAccessibility<Kokkos::DefaultExecutionSpace, Kokkos::HostSpace>::accessible ? 0 : 5;
56
67 Kokkos::View<uint64_t *> slice_start; // (slice): first slot of the slice
68 Kokkos::View<int32_t *> cells;
69 Kokkos::View<int32_t *> faces;
70 Kokkos::View<rtype *> pinv;
73 bool single = false;
74
77 static size_t pinv_elements(const size_t n, const bool single) {
78 return single ? (n * sizeof(float) + sizeof(rtype) - 1) / sizeof(rtype) : n;
79 }
80
82 template <typename T>
83 struct RowT {
84 const T * pinv_;
85 const int32_t * cells_;
86 const int32_t * faces_;
88
90 int32_t cell(const uint32_t s) const { return cells_[s << shift]; }
91
93 int32_t face(const uint32_t s) const { return faces_[s << shift]; }
94
96 template <uint8_t WIDTH>
98 rtype pinv(const uint32_t s, const uint32_t l) const { return rtype(pinv_[(s * WIDTH + l) << shift]); }
99 };
101
102 // The arrays are single allocations whose base pointers reach the kernels
103 // as parameters: pointers loaded from device memory (e.g. a table of
104 // separately allocated chunks) compile to generic loads, which made the
105 // reconstruction up to 30% slower
106 // T: float if single, else rtype
107 template <typename T = rtype>
109 RowT<T> row(const uint32_t c) const {
110 const uint64_t start = slice_start(c >> shift);
111 const uint32_t lane = c & ((1u << shift) - 1);
112 return RowT<T>{reinterpret_cast<const T *>(pinv.data()) + ((start * width) << shift) + lane,
113 cells.data() + (start << shift) + lane, faces.data() + (start << shift) + lane, shift};
114 }
115};
116
118using Moments = Kokkos::View<double **, Kokkos::LayoutRight>;
119
127 Kokkos::View<uint32_t *> start;
128 Kokkos::View<uint32_t *> term;
129
136 template <uint32_t G>
138 void entries(const uint32_t e0, const uint32_t n, const double * moments, rtype * out) const {
139 uint32_t t[G], end[G];
140 double sum[G];
141 uint32_t longest = 0;
142 for (uint32_t g = 0; g < G; g++) {
143 const bool in = e0 + g < n;
144 t[g] = in ? start(e0 + g) : 0;
145 end[g] = in ? start(e0 + g + 1) : 0;
146 sum[g] = 0.0;
147 longest = (end[g] - t[g]) > longest ? end[g] - t[g] : longest;
148 }
149 for (uint32_t k = 0; k < longest; k++) {
150 for (uint32_t g = 0; g < G; g++) {
151 if (t[g] + k < end[g]) {
152 const uint32_t w = term(t[g] + k);
153 sum[g] = add_product_rn(sum[g], double(w >> 16), moments[w & 0xFFFFu]);
154 }
155 }
156 }
157 for (uint32_t g = 0; g < G; g++) {
158 if (e0 + g < n) out[e0 + g] = rtype(sum[g]);
159 }
160 }
161
164 static double add_product_rn(const double s, const double a, const double b) {
165#if defined(KOKKOS_ENABLE_CUDA) || defined(KOKKOS_ENABLE_HIP)
166 KOKKOS_IF_ON_DEVICE((return __dadd_rn(s, __dmul_rn(a, b));))
167 KOKKOS_IF_ON_HOST((const volatile double p = a * b; return s + p;))
168#else
169 const volatile double p = a * b;
170 return s + p;
171#endif
172 }
173};
174
180void exponents(const uint8_t l, uint8_t & a, uint8_t & b) {
181 uint8_t d = 1;
182 uint8_t first = 0;
183 while (l >= first + d + 1) {
184 first = static_cast<uint8_t>(first + d + 1);
185 d++;
186 }
187 a = static_cast<uint8_t>(d - (l - first));
188 b = static_cast<uint8_t>(l - first);
189}
190
197void exponents(const uint8_t l, uint8_t & a, uint8_t & b, uint8_t & c) {
198 uint8_t idx = 0;
199 for (uint8_t d = 1;; d++) {
200 for (int i = d; i >= 0; i--) {
201 for (int j = d - i; j >= 0; j--) {
202 if (idx == l) {
203 a = static_cast<uint8_t>(i);
204 b = static_cast<uint8_t>(j);
205 c = static_cast<uint8_t>(d - i - j);
206 return;
207 }
208 idx++;
209 }
210 }
211 }
212}
213
214template <typename T> KOKKOS_INLINE_FUNCTION
215T ipow(const T x, const uint8_t n) {
216 T result = 1;
217 for (uint8_t i = 0; i < n; i++) result *= x;
218 return result;
219}
220
224template <typename T> KOKKOS_INLINE_FUNCTION
225void monomials(const uint8_t r, const T xi, const T eta, T * phi) {
226 const uint8_t nk = n_dof(r);
227 for (uint8_t l = 0; l < nk; l++) {
228 uint8_t a, b;
229 exponents(l, a, b);
230 phi[l] = ipow(xi, a) * ipow(eta, b);
231 }
232}
233
238template <typename T> KOKKOS_INLINE_FUNCTION
239void monomial_gradients(const uint8_t r, const T xi, const T eta, T * d_xi, T * d_eta) {
240 const uint8_t nk = n_dof(r);
241 for (uint8_t l = 0; l < nk; l++) {
242 uint8_t a, b;
243 exponents(l, a, b);
244 d_xi[l] = a > 0 ? T(a) * ipow(xi, a - 1) * ipow(eta, b) : T(0);
245 d_eta[l] = b > 0 ? T(b) * ipow(xi, a) * ipow(eta, b - 1) : T(0);
246 }
247}
248
252template <typename T> KOKKOS_INLINE_FUNCTION
253void monomials(const uint8_t r, const T xi, const T eta, const T zeta, T * phi) {
254 uint8_t l = 0;
255 for (uint8_t d = 1; d <= r; d++) {
256 for (int i = d; i >= 0; i--) {
257 for (int j = d - i; j >= 0; j--) {
258 phi[l++] = ipow(xi, static_cast<uint8_t>(i)) * ipow(eta, static_cast<uint8_t>(j)) *
259 ipow(zeta, static_cast<uint8_t>(d - i - j));
260 }
261 }
262 }
263}
264
268template <typename T> KOKKOS_INLINE_FUNCTION
269void monomials(const uint8_t r, const T * x, T * phi) {
270 if constexpr (N_DIM == 2) {
271 monomials(r, x[0], x[1], phi);
272 } else {
273 monomials(r, x[0], x[1], x[2], phi);
274 }
275}
276
284void eigenvectors(const rtype * W, const rtype * n, const rtype gamma,
287 constexpr uint8_t E = N_DIM + 1;
288 const rtype * u = W + 1;
289 const rtype a = Kokkos::sqrt(gamma * W[E] / W[0]);
290 const rtype q2 = dot<N_DIM>(u, u);
291 const rtype H = a * a / (gamma - 1.0_r) + 0.5_r * q2;
292 const rtype qn = dot<N_DIM>(u, n);
293 rtype t[N_DIM - 1][N_DIM];
294 tangent_basis(n, t[0], t[N_DIM - 2]);
295 const rtype b1 = (gamma - 1.0_r) / (a * a);
296 const rtype b2 = 0.5_r * b1 * q2;
297
298 R[0][0] = 1.0; R[0][1] = 1.0; R[0][2] = 1.0;
299 R[E][0] = H - a * qn; R[E][1] = 0.5_r * q2; R[E][2] = H + a * qn;
300 L[0][0] = 0.5_r * (b2 + qn / a); L[0][E] = 0.5_r * b1;
301 L[1][0] = 1.0_r - b2; L[1][E] = -b1;
302 L[2][0] = 0.5_r * (b2 - qn / a); L[2][E] = 0.5_r * b1;
303 FOR_I_DIM {
304 R[1 + i][0] = u[i] - a * n[i];
305 R[1 + i][1] = u[i];
306 R[1 + i][2] = u[i] + a * n[i];
307 L[0][1 + i] = 0.5_r * (-b1 * u[i] - n[i] / a);
308 L[1][1 + i] = b1 * u[i];
309 L[2][1 + i] = 0.5_r * (-b1 * u[i] + n[i] / a);
310 }
311 for (uint8_t k = 0; k < N_DIM - 1; k++) {
312 const uint8_t c = 3 + k;
313 R[0][c] = 0.0;
314 R[E][c] = dot<N_DIM>(u, t[k]);
315 L[c][0] = -R[E][c];
316 L[c][E] = 0.0;
317 FOR_I_DIM {
318 R[1 + i][c] = t[k][i];
319 L[c][1 + i] = t[k][i];
320 }
321 }
322}
323
332void primitive_eigenvectors(const rtype * W, const rtype a, const rtype * n,
335 constexpr uint8_t E = N_DIM + 1;
336 const rtype rho = W[0];
337 rtype t[N_DIM - 1][N_DIM];
338 tangent_basis(n, t[0], t[N_DIM - 2]);
339 for (uint8_t r = 0; r < N_CONSERVATIVE; r++) {
340 for (uint8_t c = 0; c < N_CONSERVATIVE; c++) {
341 L[r][c] = 0.0_r;
342 R[r][c] = 0.0_r;
343 }
344 }
345 // Acoustic waves r = [1, -+a n / rho, a^2], entropy r = [1, 0, 0], shear r = [0, t, 0]
346 R[0][0] = 1.0_r;
347 R[0][1] = 1.0_r;
348 R[0][2] = 1.0_r;
349 R[E][0] = a * a;
350 R[E][2] = a * a;
351 L[0][E] = 0.5_r / (a * a);
352 L[2][E] = 0.5_r / (a * a);
353 L[1][0] = 1.0_r;
354 L[1][E] = -1.0_r / (a * a);
355 FOR_I_DIM {
356 R[1 + i][0] = -a * n[i] / rho;
357 R[1 + i][2] = a * n[i] / rho;
358 L[0][1 + i] = -0.5_r * rho * n[i] / a;
359 L[2][1 + i] = 0.5_r * rho * n[i] / a;
360 }
361 for (uint8_t k = 0; k < N_DIM - 1; k++) {
362 FOR_I_DIM {
363 R[1 + i][3 + k] = t[k][i];
364 L[3 + k][1 + i] = t[k][i];
365 }
366 }
367}
368
374rtype adaptive_CT(const rtype sigma, const rtype sigma_L, const rtype sigma_U) {
375 const rtype m = (sigma >= sigma_U) ? 1.0_r : Kokkos::fmin(1.0_r, Kokkos::fmax(0.0_r, (sigma - sigma_L) / (sigma_U - sigma_L)));
376 const rtype g = (1.0_r - m) * (1.0_r - m) * (1.0_r + 2.0_r * m);
377 const rtype psi = 10.0_r - 4.0_r * (1.0_r - g);
378 return Kokkos::pow(10.0_r, -Kokkos::floor(psi));
379}
380
381} // namespace teno
382
383#endif // TENO_H
Common header file.
KOKKOS_INLINE_FUNCTION rtype dot(const rtype *a, const rtype *b)
Compute the dot product of two arrays.
Definition common_math.h:32
KOKKOS_INLINE_FUNCTION void tangent_basis(const rtype *n, rtype *t1, rtype *t2)
Unit tangents completing the unit normal n to an orthonormal, right-handed basis: (n,...
Definition common_math.h:127
float rtype
Definition common_typedef.h:39
#define N_DIM
Definition common_typedef.h:28
#define N_CONSERVATIVE
Definition common_typedef.h:29
#define FOR_I_DIM
Definition common_typedef.h:32
Definition teno.h:19
constexpr uint8_t SLICE_SHIFT
log2 of the cells per slice of PackedStencils: 32 on GPUs, so that a warp reads consecutive words,...
Definition teno.h:54
KOKKOS_INLINE_FUNCTION rtype adaptive_CT(const rtype sigma, const rtype sigma_L, const rtype sigma_U)
Adaptive cutoff C_T from the troubled-cell measure sigma (Liang, Shyy & Fu 2025): 1e-10 near sigma_L,...
Definition teno.h:374
constexpr uint8_t MAX_FACES
Definition teno.h:37
constexpr uint8_t NK_SMALL
Definition teno.h:36
KOKKOS_INLINE_FUNCTION void exponents(const uint8_t l, uint8_t &a, uint8_t &b)
Exponents (a, b) of the l-th monomial xi^a eta^b, ordered by total degree: (1,0), (0,...
Definition teno.h:180
constexpr uint8_t MAX_DEGREE
Definition teno.h:21
Kokkos::View< double **, Kokkos::LayoutRight > Moments
(cell, k): central moments of each cell, mean of ((x - x_c) / h_c)^a ... (3D).
Definition teno.h:118
KOKKOS_INLINE_FUNCTION void monomial_gradients(const uint8_t r, const T xi, const T eta, T *d_xi, T *d_eta)
Derivatives with respect to xi and eta of all monomials of degree 1..r at (xi, eta).
Definition teno.h:239
KOKKOS_INLINE_FUNCTION void monomials(const uint8_t r, const T xi, const T eta, T *phi)
Evaluate all monomials of degree 1..r at (xi, eta).
Definition teno.h:225
KOKKOS_INLINE_FUNCTION constexpr uint8_t n_dof(const uint8_t r)
Number of non-constant N_DIM-variate monomials of total degree <= r.
Definition teno.h:27
KOKKOS_INLINE_FUNCTION T ipow(const T x, const uint8_t n)
Definition teno.h:215
KOKKOS_INLINE_FUNCTION void primitive_eigenvectors(const rtype *W, const rtype a, const rtype *n, rtype L[N_CONSERVATIVE][N_CONSERVATIVE], rtype R[N_CONSERVATIVE][N_CONSERVATIVE])
Left (L) and right (R) eigenvectors of the Euler equations in primitive variables W = [rho,...
Definition teno.h:332
constexpr uint8_t MAX_NK
Definition teno.h:35
constexpr uint8_t MAX_FACE_QUAD
Definition teno.h:38
KOKKOS_INLINE_FUNCTION void eigenvectors(const rtype *W, const rtype *n, const rtype gamma, rtype L[N_CONSERVATIVE][N_CONSERVATIVE], rtype R[N_CONSERVATIVE][N_CONSERVATIVE])
Left (L) and right (R) eigenvectors of the Euler flux Jacobian in direction n for conservative variab...
Definition teno.h:284
KOKKOS_INLINE_FUNCTION constexpr uint16_t upper_index(const uint8_t l, const uint8_t m, const uint8_t n)
Index of entry (l, m), l <= m, of a symmetric n x n matrix stored as its upper triangle,...
Definition teno.h:45
One cell's stencil, resolved once per cell, for pseudo-inverse entries of type T.
Definition teno.h:83
const T * pinv_
Definition teno.h:84
const int32_t * faces_
Definition teno.h:86
KOKKOS_INLINE_FUNCTION int32_t cell(const uint32_t s) const
Definition teno.h:90
KOKKOS_INLINE_FUNCTION rtype pinv(const uint32_t s, const uint32_t l) const
Entry l of slot s, for pseudo-inverses of WIDTH entries per slot.
Definition teno.h:98
const int32_t * cells_
Definition teno.h:85
uint8_t shift
Definition teno.h:87
KOKKOS_INLINE_FUNCTION int32_t face(const uint32_t s) const
Definition teno.h:93
Per-cell stencils of different sizes, stored without padding to the largest one in the mesh....
Definition teno.h:66
uint8_t width
Definition teno.h:72
bool single
Definition teno.h:73
Kokkos::View< rtype * > pinv
Definition teno.h:70
Kokkos::View< uint64_t * > slice_start
Definition teno.h:67
Kokkos::View< int32_t * > faces
Definition teno.h:69
uint8_t shift
Definition teno.h:71
Kokkos::View< int32_t * > cells
Definition teno.h:68
static KOKKOS_INLINE_FUNCTION size_t pinv_elements(const size_t n, const bool single)
Elements of pinv that hold n entries.
Definition teno.h:77
KOKKOS_INLINE_FUNCTION RowT< T > row(const uint32_t c) const
Definition teno.h:109
The terms of the smoothness-indicator matrix (3D): entry e (upper_index(l, m)) is sum_t weight(t) mom...
Definition teno.h:126
Kokkos::View< uint32_t * > start
Definition teno.h:127
KOKKOS_INLINE_FUNCTION void entries(const uint32_t e0, const uint32_t n, const double *moments, rtype *out) const
Entries [e0, e0 + G) below n from one cell's moments into out, each summed in term order and rounded ...
Definition teno.h:138
static KOKKOS_INLINE_FUNCTION double add_product_rn(const double s, const double a, const double b)
s + a b, each rounded, never fused.
Definition teno.h:164
Kokkos::View< uint32_t * > term
Definition teno.h:128
SlotArray< double, Space > psi
Definition teno_setup.cpp:478
CellSetup< ExecSpace > c
Definition teno_setup.cpp:1810
TableBatchT< Space > out
Definition teno_setup.cpp:681
uint8_t r
Definition teno_setup.cpp:687
R< double ** > moments
Definition teno_setup.cpp:406
Geometry< Space > g
Definition teno_setup.cpp:678
uint8_t nk
Definition teno_setup.cpp:687