Mallard 0.8.0
Unstructured, GPU accelerated, high-order finite volume CFD solver
Mallard website
Loading...
Searching...
No Matches
common_math.h
Go to the documentation of this file.
1
12#ifndef COMMON_MATH_H
13#define COMMON_MATH_H
14
15#include <array>
16#include <vector>
17#include <limits>
18
19#include <Kokkos_Core.hpp>
20
21#include "common_typedef.h"
22
31template <uint32_t N> KOKKOS_INLINE_FUNCTION
32rtype dot(const rtype * a, const rtype * b) {
33 rtype dot = 0.0;
34 for (uint32_t i = 0; i < N; i++) {
35 dot += a[i] * b[i];
36 }
37 return dot;
38}
39
40// Explicit instantiation for N = 2
41template <> KOKKOS_INLINE_FUNCTION
42rtype dot<2>(const rtype * a, const rtype * b) {
43 return a[0] * b[0] +
44 a[1] * b[1];
45}
46
47// Explicit instantiation for N = 3
48template <> KOKKOS_INLINE_FUNCTION
49rtype dot<3>(const rtype * a, const rtype * b) {
50 return a[0] * b[0] +
51 a[1] * b[1] +
52 a[2] * b[2];
53}
54
61template <uint32_t N> KOKKOS_INLINE_FUNCTION
62rtype norm_2(const rtype * v) {
63 rtype norm = 0.0;
64 for (u_int64_t i = 0; i < N; ++i) {
65 norm += v[i] * v[i];
66 }
67 return Kokkos::sqrt(norm);
68}
69
70// Explicit instantiation for N = 2
71template <> KOKKOS_INLINE_FUNCTION
72rtype norm_2<2>(const rtype * v) {
73 return Kokkos::sqrt(v[0] * v[0] + v[1] * v[1]);
74}
75
76// Explicit instantiation for N = 3
77template <> KOKKOS_INLINE_FUNCTION
78rtype norm_2<3>(const rtype * v) {
79 return Kokkos::sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
80}
81
88template <uint32_t N> KOKKOS_INLINE_FUNCTION
89void unit(const rtype * v, rtype * u) {
90 rtype norm = 0.0;
91 for (u_int64_t i = 0; i < N; ++i) {
92 norm += v[i] * v[i];
93 }
94 norm = Kokkos::sqrt(norm);
95 for (u_int64_t i = 0; i < N; ++i) {
96 u[i] = v[i] / norm;
97 }
98}
99
100// Explicit instantiation for N = 2
101template <> KOKKOS_INLINE_FUNCTION
102void unit<2>(const rtype * v, rtype * u) {
103 const rtype inv_norm = 1 / norm_2<2>(v);
104 u[0] = v[0] * inv_norm;
105 u[1] = v[1] * inv_norm;
106}
107
108// Explicit instantiation for N = 3
109template <> KOKKOS_INLINE_FUNCTION
110void unit<3>(const rtype * v, rtype * u) {
111 const rtype inv_norm = 1 / norm_2<3>(v);
112 u[0] = v[0] * inv_norm;
113 u[1] = v[1] * inv_norm;
114 u[2] = v[2] * inv_norm;
115}
116
127void tangent_basis(const rtype * n, rtype * t1, rtype * t2) {
128 if constexpr (N_DIM == 2) {
129 t1[0] = -n[1];
130 t1[1] = n[0];
131 (void)t2;
132 } else {
133 // Project out of n the coordinate axis least aligned with it
134 const rtype ax = Kokkos::fabs(n[0]), ay = Kokkos::fabs(n[1]), az = Kokkos::fabs(n[2]);
135 const uint8_t k = (ax <= ay && ax <= az) ? 0 : ((ay <= az) ? 1 : 2);
136 rtype v[3];
137 for (uint8_t i = 0; i < 3; i++) v[i] = ((i == k) ? 1.0_r : 0.0_r) - n[k] * n[i];
138 unit<3>(v, t1);
139 t2[0] = n[1] * t1[2] - n[2] * t1[1];
140 t2[1] = n[2] * t1[0] - n[0] * t1[2];
141 t2[2] = n[0] * t1[1] - n[1] * t1[0];
142 }
143}
144
155void transpose(const rtype * A, rtype * AT, const uint16_t m, const uint16_t n) {
156 for (uint16_t i = 0; i < m; i++) {
157 for (uint16_t j = 0; j < n; j++) {
158 AT[j*m + i] = A[i*n + j];
159 }
160 }
161}
162
169template <uint32_t N> KOKKOS_INLINE_FUNCTION
170void invert_matrix(const rtype * A, rtype * A_inv);
171
172// Explicit instantiation for N = 2
173template <> KOKKOS_INLINE_FUNCTION
175 // Calculate determinant
176 const rtype det_A = A[0] * A[3] - A[1] * A[2];
177 if (det_A == 0.0_r) {
178 Kokkos::abort("Matrix is singular.");
179 }
180 const rtype inv_det = 1.0_r / det_A;
181
182 // Store inverse
183 A_inv[0] = A[3] * inv_det;
184 A_inv[1] = -A[1] * inv_det;
185 A_inv[2] = -A[2] * inv_det;
186 A_inv[3] = A[0] * inv_det;
187}
188
189// Explicit instantiation for N = 3
190template <> KOKKOS_INLINE_FUNCTION
192 // Calculate cofactors
193 const rtype c11 = A[4] * A[8] - A[5] * A[7];
194 const rtype c12 = -(A[3] * A[8] - A[5] * A[6]);
195 const rtype c13 = A[3] * A[7] - A[4] * A[6];
196
197 // Calculate determinant using first row
198 const rtype det_A = A[0] * c11 + A[1] * c12 + A[2] * c13;
199 if (det_A == 0.0_r) {
200 Kokkos::abort("Matrix is singular.");
201 }
202 const rtype inv_det = 1.0_r / det_A;
203
204 // Calculate remaining cofactors
205 const rtype c21 = -(A[1] * A[8] - A[2] * A[7]);
206 const rtype c22 = A[0] * A[8] - A[2] * A[6];
207 const rtype c23 = -(A[0] * A[7] - A[1] * A[6]);
208 const rtype c31 = A[1] * A[5] - A[2] * A[4];
209 const rtype c32 = -(A[0] * A[5] - A[2] * A[3]);
210 const rtype c33 = A[0] * A[4] - A[1] * A[3];
211
212 // Store inverse
213 A_inv[0] = c11 * inv_det;
214 A_inv[1] = c21 * inv_det;
215 A_inv[2] = c31 * inv_det;
216 A_inv[3] = c12 * inv_det;
217 A_inv[4] = c22 * inv_det;
218 A_inv[5] = c32 * inv_det;
219 A_inv[6] = c13 * inv_det;
220 A_inv[7] = c23 * inv_det;
221 A_inv[8] = c33 * inv_det;
222}
223
231template <uint32_t N> KOKKOS_INLINE_FUNCTION
232void gemv(const rtype * A, const rtype * x, rtype * y);
233
234// Explicit instantiation for N = 2
235template <> KOKKOS_INLINE_FUNCTION
236void gemv<2>(const rtype * A, const rtype * x, rtype * y) {
237 rtype temp0 = A[0] * x[0] + A[1] * x[1];
238 rtype temp1 = A[2] * x[0] + A[3] * x[1];
239 y[0] = temp0;
240 y[1] = temp1;
241}
242
243// Explicit instantiation for N = 3
244template <> KOKKOS_INLINE_FUNCTION
245void gemv<3>(const rtype * A, const rtype * x, rtype * y) {
246 rtype temp0 = A[0] * x[0] + A[1] * x[1] + A[2] * x[2];
247 rtype temp1 = A[3] * x[0] + A[4] * x[1] + A[5] * x[2];
248 rtype temp2 = A[6] * x[0] + A[7] * x[1] + A[8] * x[2];
249 y[0] = temp0;
250 y[1] = temp1;
251 y[2] = temp2;
252}
253
270void gemm(const rtype * A,
271 const rtype * B,
272 rtype * C,
273 const uint16_t m,
274 const uint16_t n,
275 const uint16_t p,
276 const uint16_t q,
277 const bool tA,
278 const bool tB,
279 const bool print_debug = false) {
280 // Handle in-place multiplication
281 rtype * C_out;
282 if (C == A || C == B) {
283 C_out = new rtype[m*q];
284 } else {
285 C_out = C;
286 }
287
288 // Handle different transpositions
289 if (!tA && !tB) {
290 if (n != p) {
291 Kokkos::abort("Invalid matrix dimensions.");
292 }
293 for (uint16_t i = 0; i < m; i++) {
294 for (uint16_t j = 0; j < q; j++) {
295 rtype sum = 0.0;
296 for (uint16_t k = 0; k < n; k++) {
297 sum += A[i*n + k] * B[k*q + j];
298 }
299 C_out[i*q + j] = sum;
300 }
301 }
302 } else if (tA && !tB) {
303 if (m != p) {
304 Kokkos::abort("Invalid matrix dimensions.");
305 }
306 for (uint16_t i = 0; i < n; i++) {
307 for (uint16_t j = 0; j < q; j++) {
308 rtype sum = 0.0;
309 for (uint16_t k = 0; k < m; k++) {
310 sum += A[k*n + i] * B[k*q + j];
311 }
312 C_out[i*q + j] = sum;
313 }
314 }
315 } else if (!tA && tB) {
316 if (n != q) {
317 Kokkos::abort("Invalid matrix dimensions.");
318 }
319 for (uint16_t i = 0; i < m; i++) {
320 for (uint16_t j = 0; j < p; j++) {
321 rtype sum = 0.0;
322 for (uint16_t k = 0; k < n; k++) {
323 sum += A[i*n + k] * B[j*q + k];
324 }
325 C_out[i*p + j] = sum;
326 }
327 }
328 } else {
329 if (m != q) {
330 Kokkos::abort("Invalid matrix dimensions.");
331 }
332 for (uint16_t i = 0; i < n; i++) {
333 for (uint16_t j = 0; j < p; j++) {
334 rtype sum = 0.0;
335 for (uint16_t k = 0; k < m; k++) {
336 sum += A[k*n + i] * B[j*q + k];
337 }
338 C_out[i*p + j] = sum;
339 }
340 }
341 }
342
343 // Copy result back to C if necessary
344 if (C == A || C == B) {
345 for (uint16_t i = 0; i < m*q; i++) {
346 C[i] = C_out[i];
347 }
348 delete[] C_out;
349 }
350
351 if (print_debug) {
352 printf("A: %d x %d\n", m, n);
353 for (uint16_t i = 0; i < m; i++) {
354 for (uint16_t j = 0; j < n; j++) {
355 printf("%8.3f ", static_cast<double>(A[i*n + j]));
356 }
357 printf("\n");
358 }
359 printf("B: %d x %d\n", p, q);
360 for (uint16_t i = 0; i < p; i++) {
361 for (uint16_t j = 0; j < q; j++) {
362 printf("%8.3f ", static_cast<double>(B[i*q + j]));
363 }
364 printf("\n");
365 }
366 printf("C: %d x %d\n", m, q);
367 for (uint16_t i = 0; i < m; i++) {
368 for (uint16_t j = 0; j < q; j++) {
369 printf("%8.3f ", static_cast<double>(C_out[i*q + j]));
370 }
371 printf("\n");
372 }
373 }
374}
375
386 rtype * R,
387 const uint16_t m,
388 const uint16_t n) {
389 // Copy A into R (m×n)
390 for (uint16_t i = 0; i < m; i++) {
391 for (uint16_t j = 0; j < n; j++) {
392 R[i*n + j] = A[i*n + j];
393 }
394 }
395
396 // Iterate over columns of A
397 rtype * v = new rtype[m];
398 rtype * Q_j = new rtype[m*m];
399 for (uint16_t j = 0; j < n; j++) {
400 // Compute the norm of the first column of the submatrix
401 // The submatrix is taken from R = Q_j-1 ... Q_2 Q_1 A
402 // starting at the j-th column
403 rtype norm_x = 0.0;
404 for (uint16_t i = j; i < m; i++) {
405 norm_x += R[i*n + j] * R[i*n + j];
406 }
407 norm_x = Kokkos::sqrt(norm_x);
408 if (norm_x < 1.0e-15_r) {
409 continue;
410 }
411
412 // Compute Householder vector
413 rtype sign = (R[j*n + j] >= 0.0_r) ? 1.0_r : -1.0_r;
414 rtype alpha = -sign * norm_x;
415 rtype norm_u = 0.0;
416 for (uint16_t k = 0; k < m - j; k++) {
417 v[k] = R[(j+k)*n + j];
418 if (k == 0) {
419 v[k] -= alpha;
420 }
421 norm_u += v[k] * v[k];
422 }
423 norm_u = Kokkos::sqrt(norm_u);
424 for (uint16_t k = 0; k < m - j; k++) {
425 v[k] /= norm_u;
426 }
427
428 // Compute the Q_j matrix
429 // Q_j = I - 2 v v^T
430 for (uint16_t i = 0; i < m; i++) {
431 for (uint16_t k = 0; k < m; k++) {
432 Q_j[i*m + k] = (i == k) ? 1.0 : 0.0;
433 }
434 }
435 for (uint16_t i = j; i < m; i++) {
436 for (uint16_t k = j; k < m; k++) {
437 Q_j[i*m + k] -= 2.0_r * v[i-j] * v[k-j];
438 }
439 }
440
441 // NOTE: Q can be found via
442 // Q = Q_1^T Q_2^T ... Q_n^T
443
444 // Update R by multiplying
445 // R = Q_n ... Q_2 Q_1 A
446 // R is already initialized to A above, so simply multiply
447 gemm(Q_j, R, R, m, m, m, n, false, false);
448 }
449 delete[] v;
450 delete[] Q_j;
451}
452
467 const rtype * B,
468 rtype * X,
469 const uint16_t m,
470 const uint16_t n,
471 const uint16_t p,
472 const bool tL,
473 const bool tB) {
474 for (uint16_t i = 0; i < m; i++) {
475 for (uint16_t j = 0; j < p; j++) {
476 rtype sum = 0.0;
477 for (uint16_t k = 0; k < i; k++) {
478 const int idx_L = tL ? k*m + i : i*n + k;
479 sum += L[idx_L] * X[k*p + j];
480 }
481 const int idx_B = tB ? j*n + i : i*p + j;
482 const int idx_L = tL ? i*m + i : i*n + i;
483 X[i*p + j] = (B[idx_B] - sum) / L[idx_L];
484 }
485 }
486}
487
502 const rtype * B,
503 rtype * X,
504 const uint16_t m,
505 const uint16_t n,
506 const uint16_t p,
507 const bool tU,
508 const bool tB) {
509 for (int i = m - 1; i >= 0; i--) {
510 for (uint16_t j = 0; j < p; j++) {
511 rtype sum = 0.0;
512 uint16_t end = tU ? n : m;
513 for (int k = i + 1; k < end; k++) {
514 const int idx_U = tU ? k*m + i : i*n + k;
515 sum += U[idx_U] * X[k*p + j];
516 }
517 const int idx_B = tB ? j*n + i : i*p + j;
518 const int idx_U = tU ? i*m + i : i*n + i;
519 X[i*p + j] = (B[idx_B] - sum) / U[idx_U];
520 }
521 }
522}
523
532template <uint32_t N> KOKKOS_INLINE_FUNCTION
534 const rtype * v1,
535 const rtype * v2);
536
537// Explicit instantiation for N = 2
538template <> KOKKOS_INLINE_FUNCTION
540 const rtype * v1,
541 const rtype * v2) {
542 return 0.5_r * Kokkos::fabs(v0[0] * (v1[1] - v2[1]) +
543 v1[0] * (v2[1] - v0[1]) +
544 v2[0] * (v0[1] - v1[1]));
545}
546
547// Explicit instantiation for N = 3
548// template <> KOKKOS_INLINE_FUNCTION
549// rtype triangle_area<3>(const rtype * v0,
550// const rtype * v1,
551// const rtype * v2) {
552// }
553
563void triangle_J(const rtype * v0,
564 const rtype * v1,
565 const rtype * v2,
566 rtype * J) {
567 J[0] = v1[0] - v0[0];
568 J[1] = v2[0] - v0[0];
569 J[2] = v1[1] - v0[1];
570 J[3] = v2[1] - v0[1];
571}
572
583void tetrahedron_J(const rtype * v0,
584 const rtype * v1,
585 const rtype * v2,
586 const rtype * v3,
587 rtype * J) {
588 J[0] = v1[0] - v0[0];
589 J[1] = v2[0] - v0[0];
590 J[2] = v3[0] - v0[0];
591 J[3] = v1[1] - v0[1];
592 J[4] = v2[1] - v0[1];
593 J[5] = v3[1] - v0[1];
594 J[6] = v1[2] - v0[2];
595 J[7] = v2[2] - v0[2];
596 J[8] = v3[2] - v0[2];
597}
598
605template <uint32_t N>
606std::array<rtype, N> max_array(Kokkos::View<rtype **> a) {
607 std::array<rtype, N> max;
608 for (uint32_t i = 0; i < N; ++i) {
609 rtype max_i = std::numeric_limits<rtype>::lowest();
610 Kokkos::parallel_reduce(a.extent(0),
612 if (a(j, i) > max_j) {
613 max_j = a(j, i);
614 }
615 },
616 Kokkos::Max<rtype>(max_i));
617 max[i] = max_i;
618 }
619 return max;
620}
621
628template <uint32_t N>
629std::array<rtype, N> min_array(Kokkos::View<rtype **> a) {
630 std::array<rtype, N> min;
631 for (uint32_t i = 0; i < N; ++i) {
632 rtype min_i = std::numeric_limits<rtype>::max();
633 Kokkos::parallel_reduce(a.extent(0),
635 if (a(j, i) < min_j) {
636 min_j = a(j, i);
637 }
638 },
639 Kokkos::Min<rtype>(min_i));
640 min[i] = min_i;
641 }
642 return min;
643}
644
645
646#endif // COMMON_MATH_H
KOKKOS_INLINE_FUNCTION void gemv< 3 >(const rtype *A, const rtype *x, rtype *y)
Definition common_math.h:245
KOKKOS_INLINE_FUNCTION void tetrahedron_J(const rtype *v0, const rtype *v1, const rtype *v2, const rtype *v3, rtype *J)
Get the transformation matrix into a tetrahedron's local coordinates.
Definition common_math.h:583
KOKKOS_INLINE_FUNCTION rtype norm_2(const rtype *v)
Compute the 2-norm of a vector.
Definition common_math.h:62
KOKKOS_INLINE_FUNCTION rtype dot< 2 >(const rtype *a, const rtype *b)
Definition common_math.h:42
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 invert_matrix< 2 >(const rtype *A, rtype *A_inv)
Definition common_math.h:174
KOKKOS_INLINE_FUNCTION rtype norm_2< 2 >(const rtype *v)
Definition common_math.h:72
KOKKOS_INLINE_FUNCTION void unit< 2 >(const rtype *v, rtype *u)
Definition common_math.h:102
KOKKOS_INLINE_FUNCTION void QR_householder_noQ(const rtype *A, rtype *R, const uint16_t m, const uint16_t n)
Compute the R part of the QR decomposition of a matrix.
Definition common_math.h:385
KOKKOS_INLINE_FUNCTION void unit(const rtype *v, rtype *u)
Compute the unit vector of a vector.
Definition common_math.h:89
KOKKOS_INLINE_FUNCTION void forward_substitution(const rtype *L, const rtype *B, rtype *X, const uint16_t m, const uint16_t n, const uint16_t p, const bool tL, const bool tB)
Perform forward substitution to solve a lower triangular system.
Definition common_math.h:466
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
KOKKOS_INLINE_FUNCTION void gemm(const rtype *A, const rtype *B, rtype *C, const uint16_t m, const uint16_t n, const uint16_t p, const uint16_t q, const bool tA, const bool tB, const bool print_debug=false)
General matrix-matrix multiplication. Only intended for use with small matrices within kernels.
Definition common_math.h:270
KOKKOS_INLINE_FUNCTION rtype triangle_area(const rtype *v0, const rtype *v1, const rtype *v2)
Compute the area of a triangle from its vertices.
KOKKOS_INLINE_FUNCTION void invert_matrix(const rtype *A, rtype *A_inv)
Invert a matrix. Will be instantiated for 2x2 and 3x3 matrices.
KOKKOS_INLINE_FUNCTION void transpose(const rtype *A, rtype *AT, const uint16_t m, const uint16_t n)
Transpose a matrix. Only intended for use with small matrices within kernels.
Definition common_math.h:155
KOKKOS_INLINE_FUNCTION void gemv(const rtype *A, const rtype *x, rtype *y)
General matrix-vector multiplication. Will be instantiated for 2x2 and 3x3 matrices.
KOKKOS_INLINE_FUNCTION rtype dot< 3 >(const rtype *a, const rtype *b)
Definition common_math.h:49
KOKKOS_INLINE_FUNCTION void back_substitution(const rtype *U, const rtype *B, rtype *X, const uint16_t m, const uint16_t n, const uint16_t p, const bool tU, const bool tB)
Perform back substitution to solve an upper triangular system.
Definition common_math.h:501
KOKKOS_INLINE_FUNCTION void triangle_J(const rtype *v0, const rtype *v1, const rtype *v2, rtype *J)
Get the transformation matrix into a triangle's local coordinates.
Definition common_math.h:563
KOKKOS_INLINE_FUNCTION rtype triangle_area< 2 >(const rtype *v0, const rtype *v1, const rtype *v2)
Definition common_math.h:539
KOKKOS_INLINE_FUNCTION void invert_matrix< 3 >(const rtype *A, rtype *A_inv)
Definition common_math.h:191
KOKKOS_INLINE_FUNCTION rtype norm_2< 3 >(const rtype *v)
Definition common_math.h:78
std::array< rtype, N > max_array(Kokkos::View< rtype ** > a)
Compute the maximum of each element along the first dimension of a.
Definition common_math.h:606
KOKKOS_INLINE_FUNCTION void unit< 3 >(const rtype *v, rtype *u)
Definition common_math.h:110
std::array< rtype, N > min_array(Kokkos::View< rtype ** > a)
Compute the minimum of each element along the first dimension of a.
Definition common_math.h:629
KOKKOS_INLINE_FUNCTION void gemv< 2 >(const rtype *A, const rtype *x, rtype *y)
Definition common_math.h:236
Typedefs for common types.
float rtype
Definition common_typedef.h:39
#define N_DIM
Definition common_typedef.h:28
SlotArray< double, Space > X
Definition teno_setup.cpp:478
SlotArray< double, Space > A
Definition teno_setup.cpp:478