1ae2b091fSJames Wright // SPDX-FileCopyrightText: Copyright (c) 2017-2024, HONEE contributors. 2ae2b091fSJames Wright // SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause 3c7ece6efSJeremy L Thompson #pragma once 4704b8bbeSJames Wright 53e17a7a1SJames Wright #include <ceed/types.h> 63e17a7a1SJames Wright #ifndef CEED_RUNNING_JIT_PASS 7d0cce58aSJeremy L Thompson #include <math.h> 83e17a7a1SJames Wright #endif 9704b8bbeSJames Wright 10704b8bbeSJames Wright #ifndef M_PI 11704b8bbeSJames Wright #define M_PI 3.14159265358979323846 12704b8bbeSJames Wright #endif 13704b8bbeSJames Wright 14704b8bbeSJames Wright CEED_QFUNCTION_HELPER CeedScalar Max(CeedScalar a, CeedScalar b) { return a < b ? b : a; } 15704b8bbeSJames Wright CEED_QFUNCTION_HELPER CeedScalar Min(CeedScalar a, CeedScalar b) { return a < b ? a : b; } 16704b8bbeSJames Wright 17bfa7851aSJames Wright CEED_QFUNCTION_HELPER void SwapScalar(CeedScalar *a, CeedScalar *b) { 18bfa7851aSJames Wright CeedScalar temp = *a; 19bfa7851aSJames Wright *a = *b; 20bfa7851aSJames Wright *b = temp; 21bfa7851aSJames Wright } 22bfa7851aSJames Wright 23704b8bbeSJames Wright CEED_QFUNCTION_HELPER CeedScalar Square(CeedScalar x) { return x * x; } 24704b8bbeSJames Wright CEED_QFUNCTION_HELPER CeedScalar Cube(CeedScalar x) { return x * x * x; } 25704b8bbeSJames Wright 26e7754af5SKenneth E. Jansen // @brief Scale vector of length N by scalar alpha 27e7754af5SKenneth E. Jansen CEED_QFUNCTION_HELPER void ScaleN(CeedScalar *u, const CeedScalar alpha, const CeedInt N) { 288e5e3595SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) u[i] *= alpha; 298e5e3595SJames Wright } 308e5e3595SJames Wright 318e5e3595SJames Wright // @brief Set vector of length N to a value alpha 328e5e3595SJames Wright CEED_QFUNCTION_HELPER void SetValueN(CeedScalar *u, const CeedScalar alpha, const CeedInt N) { 338e5e3595SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) u[i] = alpha; 348e5e3595SJames Wright } 358e5e3595SJames Wright 368e5e3595SJames Wright // @brief Copy N elements from x to y 378e5e3595SJames Wright CEED_QFUNCTION_HELPER void CopyN(const CeedScalar *x, CeedScalar *y, const CeedInt N) { CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) y[i] = x[i]; } 388e5e3595SJames Wright 398e5e3595SJames Wright // @brief Copy 3x3 matrix from A to B 408e5e3595SJames Wright CEED_QFUNCTION_HELPER void CopyMat3(const CeedScalar A[3][3], CeedScalar B[3][3]) { CopyN((const CeedScalar *)A, (CeedScalar *)B, 9); } 418e5e3595SJames Wright 428e5e3595SJames Wright // @brief Dot product of vectors with N elements 438e5e3595SJames Wright CEED_QFUNCTION_HELPER CeedScalar DotN(const CeedScalar *u, const CeedScalar *v, const CeedInt N) { 448e5e3595SJames Wright CeedScalar output = 0; 458e5e3595SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) output += u[i] * v[i]; 468e5e3595SJames Wright return output; 47e7754af5SKenneth E. Jansen } 48e7754af5SKenneth E. Jansen 497787ef7fSJames Wright // @brief y = \alpha x + y 507787ef7fSJames Wright CEED_QFUNCTION_HELPER void AXPY(CeedScalar alpha, const CeedScalar *x, CeedScalar *y, CeedInt N) { 517787ef7fSJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) y[i] += alpha * x[i]; 527787ef7fSJames Wright } 537787ef7fSJames Wright 54704b8bbeSJames Wright // @brief Dot product of 3 element vectors 558fff8293SJames Wright CEED_QFUNCTION_HELPER CeedScalar Dot3(const CeedScalar *u, const CeedScalar *v) { return u[0] * v[0] + u[1] * v[1] + u[2] * v[2]; } 56704b8bbeSJames Wright 572a28a40bSJames Wright // @brief Dot product of 2 element vectors 582a28a40bSJames Wright CEED_QFUNCTION_HELPER CeedScalar Dot2(const CeedScalar *u, const CeedScalar *v) { return u[0] * v[0] + u[1] * v[1]; } 592a28a40bSJames Wright 6064667825SJames Wright // @brief \ell^2 norm of 3 element vectors 6164667825SJames Wright CEED_QFUNCTION_HELPER CeedScalar Norm3(const CeedScalar *u) { return sqrt(u[0] * u[0] + u[1] * u[1] + u[2] * u[2]); } 6264667825SJames Wright 6383c0b726SJames Wright // @brief \ell^2 norm of 2 element vectors 6483c0b726SJames Wright CEED_QFUNCTION_HELPER CeedScalar Norm2(const CeedScalar *u) { return sqrt(u[0] * u[0] + u[1] * u[1]); } 6583c0b726SJames Wright 668e5e3595SJames Wright // @brief Cross product of vectors with 3 elements 678e5e3595SJames Wright CEED_QFUNCTION_HELPER void Cross3(const CeedScalar u[3], const CeedScalar v[3], CeedScalar w[3]) { 688e5e3595SJames Wright w[0] = (u[1] * v[2]) - (u[2] * v[1]); 698e5e3595SJames Wright w[1] = (u[2] * v[0]) - (u[0] * v[2]); 708e5e3595SJames Wright w[2] = (u[0] * v[1]) - (u[1] * v[0]); 718e5e3595SJames Wright } 728e5e3595SJames Wright 738e5e3595SJames Wright // @brief Curl of vector given its gradient 748e5e3595SJames Wright CEED_QFUNCTION_HELPER void Curl3(const CeedScalar gradient[3][3], CeedScalar v[3]) { 758e5e3595SJames Wright v[0] = gradient[2][1] - gradient[1][2]; 768e5e3595SJames Wright v[1] = gradient[0][2] - gradient[2][0]; 778e5e3595SJames Wright v[2] = gradient[1][0] - gradient[0][1]; 788e5e3595SJames Wright } 798e5e3595SJames Wright 808e5e3595SJames Wright // @brief Matrix vector product, b = Ax + b. A is NxM, x is M, b is N 818e5e3595SJames Wright CEED_QFUNCTION_HELPER void MatVecNM(const CeedScalar *A, const CeedScalar *x, const CeedInt N, const CeedInt M, const CeedTransposeMode transpose_A, 828e5e3595SJames Wright CeedScalar *b) { 838e5e3595SJames Wright switch (transpose_A) { 848e5e3595SJames Wright case CEED_NOTRANSPOSE: 858e5e3595SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) b[i] += DotN(&A[i * M], x, M); 868e5e3595SJames Wright break; 878e5e3595SJames Wright case CEED_TRANSPOSE: 888e5e3595SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < M; i++) { CeedPragmaSIMD for (CeedInt j = 0; j < N; j++) b[i] += A[j * M + i] * x[j]; } 898e5e3595SJames Wright break; 908e5e3595SJames Wright } 918e5e3595SJames Wright } 928e5e3595SJames Wright 938e5e3595SJames Wright // @brief 3x3 Matrix vector product b = Ax + b. 948e5e3595SJames Wright CEED_QFUNCTION_HELPER void MatVec3(const CeedScalar A[3][3], const CeedScalar x[3], const CeedTransposeMode transpose_A, CeedScalar b[3]) { 958e5e3595SJames Wright MatVecNM((const CeedScalar *)A, (const CeedScalar *)x, 3, 3, transpose_A, (CeedScalar *)b); 968e5e3595SJames Wright } 978e5e3595SJames Wright 982a28a40bSJames Wright // @brief 2x2 Matrix vector product b = Ax + b. 992a28a40bSJames Wright CEED_QFUNCTION_HELPER void MatVec2(const CeedScalar A[2][2], const CeedScalar x[2], const CeedTransposeMode transpose_A, CeedScalar b[2]) { 1002a28a40bSJames Wright MatVecNM((const CeedScalar *)A, (const CeedScalar *)x, 2, 2, transpose_A, (CeedScalar *)b); 1012a28a40bSJames Wright } 1022a28a40bSJames Wright 1038e5e3595SJames Wright // @brief Matrix-Matrix product, B = DA + B, where D is diagonal. 1048e5e3595SJames Wright // @details A is NxM, D is diagonal NxN, represented by a vector of length N, and B is NxM. Optionally, A may be transposed. 1058e5e3595SJames Wright CEED_QFUNCTION_HELPER void MatDiagNM(const CeedScalar *A, const CeedScalar *D, const CeedInt N, const CeedInt M, const CeedTransposeMode transpose_A, 1068e5e3595SJames Wright CeedScalar *B) { 1078e5e3595SJames Wright switch (transpose_A) { 1088e5e3595SJames Wright case CEED_NOTRANSPOSE: 1098e5e3595SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) { CeedPragmaSIMD for (CeedInt j = 0; j < M; j++) B[i * M + j] += D[i] * A[i * M + j]; } 1108e5e3595SJames Wright break; 1118e5e3595SJames Wright case CEED_TRANSPOSE: 1128e5e3595SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < M; i++) { CeedPragmaSIMD for (CeedInt j = 0; j < N; j++) B[i * N + j] += D[i] * A[j * M + i]; } 1138e5e3595SJames Wright break; 1148e5e3595SJames Wright } 1158e5e3595SJames Wright } 1168e5e3595SJames Wright 1178e5e3595SJames Wright // @brief 3x3 Matrix-Matrix product, B = DA + B, where D is diagonal. 1188e5e3595SJames Wright // @details Optionally, A may be transposed. 1198e5e3595SJames Wright CEED_QFUNCTION_HELPER void MatDiag3(const CeedScalar A[3][3], const CeedScalar D[3], const CeedTransposeMode transpose_A, CeedScalar B[3][3]) { 1208e5e3595SJames Wright MatDiagNM((const CeedScalar *)A, (const CeedScalar *)D, 3, 3, transpose_A, (CeedScalar *)B); 1218e5e3595SJames Wright } 122e975cfccSJames Wright // @brief NxN Matrix-Matrix product, C = AB + C 123e975cfccSJames Wright CEED_QFUNCTION_HELPER void MatMatN(const CeedScalar *A, const CeedScalar *B, const CeedInt N, const CeedTransposeMode transpose_A, 124e975cfccSJames Wright const CeedTransposeMode transpose_B, CeedScalar *C) { 1258e5e3595SJames Wright switch (transpose_A) { 1268e5e3595SJames Wright case CEED_NOTRANSPOSE: 1278e5e3595SJames Wright switch (transpose_B) { 1288e5e3595SJames Wright case CEED_NOTRANSPOSE: 129e975cfccSJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) { 130e975cfccSJames Wright CeedPragmaSIMD for (CeedInt j = 0; j < N; j++) { 131e975cfccSJames Wright CeedPragmaSIMD for (CeedInt k = 0; k < N; k++) C[i * N + j] += A[i * N + k] * B[k * N + j]; 132e975cfccSJames Wright } 1338e5e3595SJames Wright } 1348e5e3595SJames Wright break; 1358e5e3595SJames Wright case CEED_TRANSPOSE: 136e975cfccSJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) { 137e975cfccSJames Wright CeedPragmaSIMD for (CeedInt j = 0; j < N; j++) { 138e975cfccSJames Wright CeedPragmaSIMD for (CeedInt k = 0; k < N; k++) C[i * N + j] += A[i * N + k] * B[j * N + k]; 139e975cfccSJames Wright } 1408e5e3595SJames Wright } 1418e5e3595SJames Wright break; 1428e5e3595SJames Wright } 1438e5e3595SJames Wright break; 1448e5e3595SJames Wright case CEED_TRANSPOSE: 1458e5e3595SJames Wright switch (transpose_B) { 1468e5e3595SJames Wright case CEED_NOTRANSPOSE: 147e975cfccSJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) { 148e975cfccSJames Wright CeedPragmaSIMD for (CeedInt j = 0; j < N; j++) { 149e975cfccSJames Wright CeedPragmaSIMD for (CeedInt k = 0; k < N; k++) C[i * N + j] += A[k * N + i] * B[k * N + j]; 150e975cfccSJames Wright } 1518e5e3595SJames Wright } 1528e5e3595SJames Wright break; 1538e5e3595SJames Wright case CEED_TRANSPOSE: 154e975cfccSJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) { 155e975cfccSJames Wright CeedPragmaSIMD for (CeedInt j = 0; j < N; j++) { 156e975cfccSJames Wright CeedPragmaSIMD for (CeedInt k = 0; k < N; k++) C[i * N + j] += A[k * N + i] * B[j * N + k]; 157e975cfccSJames Wright } 1588e5e3595SJames Wright } 1598e5e3595SJames Wright break; 1608e5e3595SJames Wright } 1618e5e3595SJames Wright break; 1628e5e3595SJames Wright } 1638e5e3595SJames Wright } 1648e5e3595SJames Wright 165e975cfccSJames Wright // @brief 3x3 Matrix-Matrix product, C = AB + C 166e975cfccSJames Wright CEED_QFUNCTION_HELPER void MatMat3(const CeedScalar A[3][3], const CeedScalar B[3][3], const CeedTransposeMode transpose_A, 167e975cfccSJames Wright const CeedTransposeMode transpose_B, CeedScalar C[3][3]) { 168e975cfccSJames Wright MatMatN((const CeedScalar *)A, (const CeedScalar *)B, 3, transpose_A, transpose_B, (CeedScalar *)C); 169e975cfccSJames Wright } 170e975cfccSJames Wright 1712a28a40bSJames Wright // @brief 2x2 Matrix-Matrix product, C = AB + C 1722a28a40bSJames Wright CEED_QFUNCTION_HELPER void MatMat2(const CeedScalar A[2][2], const CeedScalar B[2][2], const CeedTransposeMode transpose_A, 1732a28a40bSJames Wright const CeedTransposeMode transpose_B, CeedScalar C[2][2]) { 1742a28a40bSJames Wright MatMatN((const CeedScalar *)A, (const CeedScalar *)B, 2, transpose_A, transpose_B, (CeedScalar *)C); 1752a28a40bSJames Wright } 1762a28a40bSJames Wright 17706f0a019SJames Wright /** 178d8667e38SJames Wright * @brief Calculate inverse of 2x2 matrix 179d8667e38SJames Wright * 180d8667e38SJames Wright * @param[in] A Input matrix 181d8667e38SJames Wright * @param[out] detJ_ptr Determinate of A, may be NULL is not desired 182d8667e38SJames Wright * @param[out] A_inv Output matrix inverse 183d8667e38SJames Wright */ 184d8667e38SJames Wright CEED_QFUNCTION_HELPER void MatInv2(const CeedScalar A[2][2], CeedScalar A_inv[2][2], CeedScalar *detJ_ptr) { 185d8667e38SJames Wright const CeedScalar detJ = A[0][0] * A[1][1] - A[1][0] * A[0][1]; 186d8667e38SJames Wright 187d8667e38SJames Wright A_inv[0][0] = A[1][1] / detJ; 188d8667e38SJames Wright A_inv[0][1] = -A[0][1] / detJ; 189d8667e38SJames Wright A_inv[1][0] = -A[1][0] / detJ; 190d8667e38SJames Wright A_inv[1][1] = A[0][0] / detJ; 191d8667e38SJames Wright if (detJ_ptr) *detJ_ptr = detJ; 192d8667e38SJames Wright } 193d8667e38SJames Wright 194d8667e38SJames Wright /** 195d8667e38SJames Wright * @brief Calculate inverse of 3x3 matrix 196d8667e38SJames Wright * 197d8667e38SJames Wright * @param[in] A Input matrix 198d8667e38SJames Wright * @param[out] detJ_ptr Determinate of A, may be NULL is not desired 199d8667e38SJames Wright * @param[out] A_inv Output matrix inverse 200d8667e38SJames Wright */ 201d8667e38SJames Wright CEED_QFUNCTION_HELPER void MatInv3(const CeedScalar A[3][3], CeedScalar A_inv[3][3], CeedScalar *detJ_ptr) { 202d8667e38SJames Wright // Compute Adjugate of dxdX 203d8667e38SJames Wright A_inv[0][0] = A[1][1] * A[2][2] - A[1][2] * A[2][1]; 204d8667e38SJames Wright A_inv[0][1] = A[0][2] * A[2][1] - A[0][1] * A[2][2]; 205d8667e38SJames Wright A_inv[0][2] = A[0][1] * A[1][2] - A[0][2] * A[1][1]; 206d8667e38SJames Wright A_inv[1][0] = A[1][2] * A[2][0] - A[1][0] * A[2][2]; 207d8667e38SJames Wright A_inv[1][1] = A[0][0] * A[2][2] - A[0][2] * A[2][0]; 208d8667e38SJames Wright A_inv[1][2] = A[0][2] * A[1][0] - A[0][0] * A[1][2]; 209d8667e38SJames Wright A_inv[2][0] = A[1][0] * A[2][1] - A[1][1] * A[2][0]; 210d8667e38SJames Wright A_inv[2][1] = A[0][1] * A[2][0] - A[0][0] * A[2][1]; 211d8667e38SJames Wright A_inv[2][2] = A[0][0] * A[1][1] - A[0][1] * A[1][0]; 212d8667e38SJames Wright 213d8667e38SJames Wright const CeedScalar detJ = A[0][0] * A_inv[0][0] + A[1][0] * A_inv[0][1] + A[2][0] * A_inv[0][2]; 214d8667e38SJames Wright ScaleN((CeedScalar *)A_inv, 1 / detJ, 9); 215d8667e38SJames Wright if (detJ_ptr) *detJ_ptr = detJ; 216d8667e38SJames Wright } 217d8667e38SJames Wright 218d8667e38SJames Wright /** 21906f0a019SJames Wright @brief MxN Matrix-Matrix product, C = AB + C 22006f0a019SJames Wright 22106f0a019SJames Wright C is NxM, A is NxP, B is PxM 22206f0a019SJames Wright 22306f0a019SJames Wright @param[in] mat_A Row-major matrix `A` 22406f0a019SJames Wright @param[in] mat_B Row-major matrix `B` 22506f0a019SJames Wright @param[out] mat_C Row-major output matrix `C` 22606f0a019SJames Wright @param[in] N Number of rows of `C` 22706f0a019SJames Wright @param[in] M Number of columns of `C` 22806f0a019SJames Wright @param[in] P Number of columns of `A`/rows of `B` 22906f0a019SJames Wright **/ 23006f0a019SJames Wright CEED_QFUNCTION_HELPER void MatMatNM(const CeedScalar *mat_A, const CeedScalar *mat_B, CeedScalar *mat_C, CeedInt N, CeedInt M, CeedInt P) { 23106f0a019SJames Wright for (CeedInt i = 0; i < N; i++) { 23206f0a019SJames Wright for (CeedInt j = 0; j < M; j++) { 23306f0a019SJames Wright for (CeedInt k = 0; k < P; k++) mat_C[i * M + j] += mat_A[i * P + k] * mat_B[k * M + j]; 23406f0a019SJames Wright } 23506f0a019SJames Wright } 23606f0a019SJames Wright } 23706f0a019SJames Wright 238704b8bbeSJames Wright // @brief Unpack Kelvin-Mandel notation symmetric tensor into full tensor 239704b8bbeSJames Wright CEED_QFUNCTION_HELPER void KMUnpack(const CeedScalar v[6], CeedScalar A[3][3]) { 240704b8bbeSJames Wright const CeedScalar weight = 1 / sqrt(2.); 241704b8bbeSJames Wright A[0][0] = v[0]; 242704b8bbeSJames Wright A[1][1] = v[1]; 243704b8bbeSJames Wright A[2][2] = v[2]; 244704b8bbeSJames Wright A[2][1] = A[1][2] = weight * v[3]; 245704b8bbeSJames Wright A[2][0] = A[0][2] = weight * v[4]; 246704b8bbeSJames Wright A[1][0] = A[0][1] = weight * v[5]; 247704b8bbeSJames Wright } 248704b8bbeSJames Wright 2498e5e3595SJames Wright // @brief Pack full tensor into Kelvin-Mandel notation symmetric tensor 2508e5e3595SJames Wright CEED_QFUNCTION_HELPER void KMPack(const CeedScalar A[3][3], CeedScalar v[6]) { 2518e5e3595SJames Wright const CeedScalar weight = sqrt(2.); 2528e5e3595SJames Wright v[0] = A[0][0]; 2538e5e3595SJames Wright v[1] = A[1][1]; 2548e5e3595SJames Wright v[2] = A[2][2]; 2558e5e3595SJames Wright v[3] = A[2][1] * weight; 2568e5e3595SJames Wright v[4] = A[2][0] * weight; 2578e5e3595SJames Wright v[5] = A[1][0] * weight; 2588e5e3595SJames Wright } 2598e5e3595SJames Wright 2608e5e3595SJames Wright // @brief Calculate metric tensor from mapping, g_{ij} = xi_{k,i} xi_{k,j} = dXdx^T dXdx 2618e5e3595SJames Wright CEED_QFUNCTION_HELPER void KMMetricTensor(const CeedScalar dXdx[3][3], CeedScalar km_g_ij[6]) { 2628e5e3595SJames Wright CeedScalar g_ij[3][3] = {{0.}}; 2638e5e3595SJames Wright MatMat3(dXdx, dXdx, CEED_TRANSPOSE, CEED_NOTRANSPOSE, g_ij); 2648e5e3595SJames Wright KMPack(g_ij, km_g_ij); 2658e5e3595SJames Wright } 2668e5e3595SJames Wright 267*dc336713SJames Wright /** 268*dc336713SJames Wright @brief Linear ramp evaluation from set amplitude to zero 269*dc336713SJames Wright 270*dc336713SJames Wright ▲ 271*dc336713SJames Wright │ 272*dc336713SJames Wright a│-------┬. 273*dc336713SJames Wright │ ┊ `-. 274*dc336713SJames Wright │ ┊ `-. 275*dc336713SJames Wright │ ┊ `-.______ 276*dc336713SJames Wright └───────┴─────────┴────────> x 277*dc336713SJames Wright s s+l 278*dc336713SJames Wright 279*dc336713SJames Wright where "a" is `amplitude`, "s" is `start`, and "l" is `length`. 280*dc336713SJames Wright 281*dc336713SJames Wright @param[in] amplitude Maximum value of the ramp 282*dc336713SJames Wright @param[in] length Length of the ramp 283*dc336713SJames Wright @param[in] start Location where ramp begins to reduce from `amplitude` to 0 284*dc336713SJames Wright @param[in] x Input location 285*dc336713SJames Wright @return Value of linear ramp function 286*dc336713SJames Wright **/ 287e7754af5SKenneth E. Jansen CEED_QFUNCTION_HELPER CeedScalar LinearRampCoefficient(CeedScalar amplitude, CeedScalar length, CeedScalar start, CeedScalar x) { 288e7754af5SKenneth E. Jansen if (x < start) { 289e7754af5SKenneth E. Jansen return amplitude; 290e7754af5SKenneth E. Jansen } else if (x < start + length) { 291e7754af5SKenneth E. Jansen return amplitude * ((x - start) * (-1 / length) + 1); 292e7754af5SKenneth E. Jansen } else { 293e7754af5SKenneth E. Jansen return 0; 294e7754af5SKenneth E. Jansen } 295e7754af5SKenneth E. Jansen } 296e7754af5SKenneth E. Jansen 297ade49511SJames Wright /** 298ade49511SJames Wright @brief Pack stored values at quadrature point 299ade49511SJames Wright 300ade49511SJames Wright @param[in] Q Number of quadrature points 301ade49511SJames Wright @param[in] i Current quadrature point 302ade49511SJames Wright @param[in] start Starting index to store components 303ade49511SJames Wright @param[in] num_comp Number of components to store 3046764667bSJames Wright @param[in] values_at_qpnt Local values for quadrature point i 305ade49511SJames Wright @param[out] stored Stored values 306ade49511SJames Wright 307ade49511SJames Wright @return An error code: 0 - success, otherwise - failure 308ade49511SJames Wright **/ 3096764667bSJames Wright CEED_QFUNCTION_HELPER int StoredValuesPack(CeedInt Q, CeedInt i, CeedInt start, CeedInt num_comp, const CeedScalar *values_at_qpnt, 3106764667bSJames Wright CeedScalar *stored) { 3116764667bSJames Wright for (CeedInt j = 0; j < num_comp; j++) stored[(start + j) * Q + i] = values_at_qpnt[j]; 312ade49511SJames Wright 313ade49511SJames Wright return CEED_ERROR_SUCCESS; 314ade49511SJames Wright } 315ade49511SJames Wright 316ade49511SJames Wright /** 317ade49511SJames Wright @brief Unpack stored values at quadrature point 318ade49511SJames Wright 319ade49511SJames Wright @param[in] Q Number of quadrature points 320ade49511SJames Wright @param[in] i Current quadrature point 321ade49511SJames Wright @param[in] start Starting index to store components 322ade49511SJames Wright @param[in] num_comp Number of components to store 323ade49511SJames Wright @param[in] stored Stored values 3246764667bSJames Wright @param[out] values_at_qpnt Local values for quadrature point i 325ade49511SJames Wright 326ade49511SJames Wright @return An error code: 0 - success, otherwise - failure 327ade49511SJames Wright **/ 3286764667bSJames Wright CEED_QFUNCTION_HELPER int StoredValuesUnpack(CeedInt Q, CeedInt i, CeedInt start, CeedInt num_comp, const CeedScalar *stored, 3296764667bSJames Wright CeedScalar *values_at_qpnt) { 3306764667bSJames Wright for (CeedInt j = 0; j < num_comp; j++) values_at_qpnt[j] = stored[(start + j) * Q + i]; 331ade49511SJames Wright 332ade49511SJames Wright return CEED_ERROR_SUCCESS; 333ade49511SJames Wright } 334ade49511SJames Wright 335ade49511SJames Wright /** 336e1bedf8cSJames Wright @brief Unpack N-D element q_data at quadrature point 337e1bedf8cSJames Wright 338e1bedf8cSJames Wright @param[in] dim Dimension of the element 339e1bedf8cSJames Wright @param[in] Q Number of quadrature points 340e1bedf8cSJames Wright @param[in] i Current quadrature point 341e1bedf8cSJames Wright @param[in] q_data Pointer to q_data (generated by `setupgeo.h:Setup`) 342e1bedf8cSJames Wright @param[out] wdetJ Quadrature weight times determinant of the mapping Jacobian, or `NULL` 343e1bedf8cSJames Wright @param[out] dXdx Inverse of the mapping Jacobian (shape [dim][dim]), or `NULL` 344e77831d2SJames Wright 345e77831d2SJames Wright @return An error code: 0 - success, otherwise - failure 346e1bedf8cSJames Wright **/ 347e77831d2SJames Wright CEED_QFUNCTION_HELPER int QdataUnpack_ND(CeedInt dim, CeedInt Q, CeedInt i, const CeedScalar *q_data, CeedScalar *wdetJ, CeedScalar *dXdx) { 348e1bedf8cSJames Wright switch (dim) { 349e1bedf8cSJames Wright case 2: 350e1bedf8cSJames Wright if (wdetJ) StoredValuesUnpack(Q, i, 0, 1, q_data, wdetJ); 351e1bedf8cSJames Wright if (dXdx) StoredValuesUnpack(Q, i, 1, 4, q_data, dXdx); 352e1bedf8cSJames Wright break; 353e1bedf8cSJames Wright case 3: 354e1bedf8cSJames Wright if (wdetJ) StoredValuesUnpack(Q, i, 0, 1, q_data, wdetJ); 355e1bedf8cSJames Wright if (dXdx) StoredValuesUnpack(Q, i, 1, 9, q_data, dXdx); 356e1bedf8cSJames Wright break; 357e1bedf8cSJames Wright } 358e77831d2SJames Wright return CEED_ERROR_SUCCESS; 359e1bedf8cSJames Wright } 360e1bedf8cSJames Wright 361e1bedf8cSJames Wright /** 362e1bedf8cSJames Wright @brief Unpack boundary element q_data for N-D problem at quadrature point 363e1bedf8cSJames Wright 364e77831d2SJames Wright @param[in] dim Dimension of the element 365e1bedf8cSJames Wright @param[in] Q Number of quadrature points 366e1bedf8cSJames Wright @param[in] i Current quadrature point 367e1bedf8cSJames Wright @param[in] q_data Pointer to q_data (generated by `setupgeo.h:SetupBoundary`) 368e1bedf8cSJames Wright @param[out] wdetJ Quadrature weight times determinant of the mapping Jacobian, or `NULL` 369e1bedf8cSJames Wright @param[out] dXdx Inverse of the mapping Jacobian (shape [dim - 1][dim]), or `NULL` 370e1bedf8cSJames Wright @param[out] normal Components of the normal vector (shape [dim]), or `NULL` 371e77831d2SJames Wright 372e77831d2SJames Wright @return An error code: 0 - success, otherwise - failure 373e1bedf8cSJames Wright **/ 374e77831d2SJames Wright CEED_QFUNCTION_HELPER int QdataBoundaryUnpack_ND(CeedInt dim, CeedInt Q, CeedInt i, const CeedScalar *q_data, CeedScalar *wdetJ, CeedScalar *dXdx, 375e1bedf8cSJames Wright CeedScalar *normal) { 376e1bedf8cSJames Wright switch (dim) { 377e1bedf8cSJames Wright case 2: 378e1bedf8cSJames Wright if (wdetJ) StoredValuesUnpack(Q, i, 0, 1, q_data, wdetJ); 379e1bedf8cSJames Wright if (normal) StoredValuesUnpack(Q, i, 1, 2, q_data, normal); 380e1bedf8cSJames Wright break; 381e1bedf8cSJames Wright case 3: 382e1bedf8cSJames Wright if (wdetJ) StoredValuesUnpack(Q, i, 0, 1, q_data, wdetJ); 383e1bedf8cSJames Wright if (normal) StoredValuesUnpack(Q, i, 1, 3, q_data, normal); 384e1bedf8cSJames Wright if (dXdx) StoredValuesUnpack(Q, i, 4, 6, q_data, (CeedScalar *)dXdx); 385e1bedf8cSJames Wright break; 386e1bedf8cSJames Wright } 387e77831d2SJames Wright return CEED_ERROR_SUCCESS; 388e1bedf8cSJames Wright } 389e1bedf8cSJames Wright 390e1bedf8cSJames Wright /** 391da8b59d6SJames Wright @brief Unpack boundary element q_data for N-D problem at quadrature point 392da8b59d6SJames Wright 393da8b59d6SJames Wright @param[in] dim Dimension of the element 394da8b59d6SJames Wright @param[in] Q Number of quadrature points 395da8b59d6SJames Wright @param[in] i Current quadrature point 396da8b59d6SJames Wright @param[in] q_data Pointer to q_data (generated by `setupgeo.h:SetupBoundaryGradient`) 397da8b59d6SJames Wright @param[out] wdetJ Quadrature weight times determinant of the mapping Jacobian, or `NULL` 398da8b59d6SJames Wright @param[out] dXdx Inverse of the mapping Jacobian (shape [dim][dim]), or `NULL` 399da8b59d6SJames Wright @param[out] normal Components of the normal vector (shape [dim]), or `NULL` 400da8b59d6SJames Wright 401da8b59d6SJames Wright @return An error code: 0 - success, otherwise - failure 402da8b59d6SJames Wright **/ 403da8b59d6SJames Wright CEED_QFUNCTION_HELPER int QdataBoundaryGradientUnpack_ND(CeedInt dim, CeedInt Q, CeedInt i, const CeedScalar *q_data, CeedScalar *wdetJ, 404da8b59d6SJames Wright CeedScalar *dXdx, CeedScalar *normal) { 405da8b59d6SJames Wright switch (dim) { 406da8b59d6SJames Wright case 2: 407da8b59d6SJames Wright if (wdetJ) StoredValuesUnpack(Q, i, 0, 1, q_data, wdetJ); 408da8b59d6SJames Wright if (dXdx) StoredValuesUnpack(Q, i, 1, 4, q_data, dXdx); 409da8b59d6SJames Wright if (normal) StoredValuesUnpack(Q, i, 5, 2, q_data, normal); 410da8b59d6SJames Wright break; 411da8b59d6SJames Wright case 3: 412da8b59d6SJames Wright if (wdetJ) StoredValuesUnpack(Q, i, 0, 1, q_data, wdetJ); 413da8b59d6SJames Wright if (dXdx) StoredValuesUnpack(Q, i, 1, 9, q_data, dXdx); 414da8b59d6SJames Wright if (normal) StoredValuesUnpack(Q, i, 10, 3, q_data, normal); 415da8b59d6SJames Wright break; 416da8b59d6SJames Wright } 417da8b59d6SJames Wright return CEED_ERROR_SUCCESS; 418da8b59d6SJames Wright } 419da8b59d6SJames Wright 420da8b59d6SJames Wright /** 421ade49511SJames Wright @brief Unpack 3D element q_data at quadrature point 422ade49511SJames Wright 423ade49511SJames Wright @param[in] Q Number of quadrature points 424ade49511SJames Wright @param[in] i Current quadrature point 425ade49511SJames Wright @param[in] q_data Pointer to q_data (generated by `setupgeo.h:Setup`) 426ade49511SJames Wright @param[out] wdetJ Quadrature weight times determinant of the mapping Jacobian 427ade49511SJames Wright @param[out] dXdx Inverse of the mapping Jacobian (shape [3][3]) 428ade49511SJames Wright 429ade49511SJames Wright @return An error code: 0 - success, otherwise - failure 430ade49511SJames Wright **/ 431ade49511SJames Wright CEED_QFUNCTION_HELPER int QdataUnpack_3D(CeedInt Q, CeedInt i, const CeedScalar *q_data, CeedScalar *wdetJ, CeedScalar dXdx[3][3]) { 432e77831d2SJames Wright return QdataUnpack_ND(3, Q, i, q_data, wdetJ, (CeedScalar *)dXdx); 433ade49511SJames Wright } 434ade49511SJames Wright 435ade49511SJames Wright /** 436ade49511SJames Wright @brief Unpack boundary element q_data for 3D problem at quadrature point 437ade49511SJames Wright 438ade49511SJames Wright @param[in] Q Number of quadrature points 439ade49511SJames Wright @param[in] i Current quadrature point 4402c512a7bSJames Wright @param[in] q_data Pointer to q_data (generated by `setupgeo.h:SetupBoundary`) 441ade49511SJames Wright @param[out] wdetJ Quadrature weight times determinant of the mapping Jacobian, or `NULL` 442ade49511SJames Wright @param[out] dXdx Inverse of the mapping Jacobian (shape [2][3]), or `NULL` 443ade49511SJames Wright @param[out] normal Components of the normal vector (shape [3]), or `NULL` 444ade49511SJames Wright 445ade49511SJames Wright @return An error code: 0 - success, otherwise - failure 446ade49511SJames Wright **/ 447ade49511SJames Wright CEED_QFUNCTION_HELPER int QdataBoundaryUnpack_3D(CeedInt Q, CeedInt i, const CeedScalar *q_data, CeedScalar *wdetJ, CeedScalar dXdx[2][3], 448ade49511SJames Wright CeedScalar normal[3]) { 449e77831d2SJames Wright return QdataBoundaryUnpack_ND(3, Q, i, q_data, wdetJ, (CeedScalar *)dXdx, normal); 450ade49511SJames Wright } 451ade49511SJames Wright 452baadde1fSJames Wright /** 45315c15616SJames Wright @brief Unpack boundary element q_data for 3D problem at quadrature point 45415c15616SJames Wright 45515c15616SJames Wright @param[in] Q Number of quadrature points 45615c15616SJames Wright @param[in] i Current quadrature point 45715c15616SJames Wright @param[in] q_data Pointer to q_data (generated by `setupgeo.h:SetupBoundary`) 45815c15616SJames Wright @param[out] wdetJ Quadrature weight times determinant of the mapping Jacobian, or `NULL` 459e77831d2SJames Wright @param[out] dXdx Inverse of the mapping Jacobian (shape [3][3]), or `NULL` 46015c15616SJames Wright @param[out] normal Components of the normal vector (shape [3]), or `NULL` 46115c15616SJames Wright 46215c15616SJames Wright @return An error code: 0 - success, otherwise - failure 46315c15616SJames Wright **/ 464e77831d2SJames Wright CEED_QFUNCTION_HELPER int QdataBoundaryGradientUnpack_3D(CeedInt Q, CeedInt i, const CeedScalar *q_data, CeedScalar *wdetJ, CeedScalar dXdx[3][3], 46515c15616SJames Wright CeedScalar normal[3]) { 466da8b59d6SJames Wright return QdataBoundaryGradientUnpack_ND(3, Q, i, q_data, wdetJ, (CeedScalar *)dXdx, normal); 46715c15616SJames Wright } 46815c15616SJames Wright 46915c15616SJames Wright /** 470baadde1fSJames Wright @brief Unpack 2D element q_data at quadrature point 471baadde1fSJames Wright 472baadde1fSJames Wright @param[in] Q Number of quadrature points 473baadde1fSJames Wright @param[in] i Current quadrature point 474baadde1fSJames Wright @param[in] q_data Pointer to q_data (generated by `setupgeo.h:Setup`) 475baadde1fSJames Wright @param[out] wdetJ Quadrature weight times determinant of the mapping Jacobian 476baadde1fSJames Wright @param[out] dXdx Inverse of the mapping Jacobian (shape [2][2]) 477baadde1fSJames Wright 478baadde1fSJames Wright @return An error code: 0 - success, otherwise - failure 479baadde1fSJames Wright **/ 480baadde1fSJames Wright CEED_QFUNCTION_HELPER int QdataUnpack_2D(CeedInt Q, CeedInt i, const CeedScalar *q_data, CeedScalar *wdetJ, CeedScalar dXdx[2][2]) { 481e1bedf8cSJames Wright QdataUnpack_ND(2, Q, i, q_data, wdetJ, (CeedScalar *)dXdx); 482baadde1fSJames Wright return CEED_ERROR_SUCCESS; 483baadde1fSJames Wright } 484baadde1fSJames Wright 4852c512a7bSJames Wright /** 4862c512a7bSJames Wright @brief Unpack boundary element q_data for 2D problem at quadrature point 4872c512a7bSJames Wright 4882c512a7bSJames Wright @param[in] Q Number of quadrature points 4892c512a7bSJames Wright @param[in] i Current quadrature point 4902c512a7bSJames Wright @param[in] q_data Pointer to q_data (generated by `setupgeo.h:SetupBoundary2d`) 4912c512a7bSJames Wright @param[out] wdetJ Quadrature weight times determinant of the mapping Jacobian, or `NULL` 4922c512a7bSJames Wright @param[out] normal Components of the normal vector (shape [2]), or `NULL` 4932c512a7bSJames Wright 4942c512a7bSJames Wright @return An error code: 0 - success, otherwise - failure 4952c512a7bSJames Wright **/ 4962c512a7bSJames Wright CEED_QFUNCTION_HELPER int QdataBoundaryUnpack_2D(CeedInt Q, CeedInt i, const CeedScalar *q_data, CeedScalar *wdetJ, CeedScalar normal[2]) { 497e1bedf8cSJames Wright QdataBoundaryUnpack_ND(3, Q, i, q_data, wdetJ, NULL, normal); 4982c512a7bSJames Wright return CEED_ERROR_SUCCESS; 4992c512a7bSJames Wright } 50006f0a019SJames Wright 50106f0a019SJames Wright /** 502da8b59d6SJames Wright @brief Unpack boundary element q_data for 2D problem at quadrature point 503da8b59d6SJames Wright 504da8b59d6SJames Wright @param[in] Q Number of quadrature points 505da8b59d6SJames Wright @param[in] i Current quadrature point 506da8b59d6SJames Wright @param[in] q_data Pointer to q_data (generated by `setupgeo.h:SetupBoundary`) 507da8b59d6SJames Wright @param[out] wdetJ Quadrature weight times determinant of the mapping Jacobian, or `NULL` 508da8b59d6SJames Wright @param[out] dXdx Inverse of the mapping Jacobian (shape [2][2]), or `NULL` 509da8b59d6SJames Wright @param[out] normal Components of the normal vector (shape [2]), or `NULL` 510da8b59d6SJames Wright 511da8b59d6SJames Wright @return An error code: 0 - success, otherwise - failure 512da8b59d6SJames Wright **/ 513da8b59d6SJames Wright CEED_QFUNCTION_HELPER int QdataBoundaryGradientUnpack_2D(CeedInt Q, CeedInt i, const CeedScalar *q_data, CeedScalar *wdetJ, CeedScalar dXdx[2][2], 514da8b59d6SJames Wright CeedScalar normal[2]) { 515da8b59d6SJames Wright return QdataBoundaryGradientUnpack_ND(2, Q, i, q_data, wdetJ, (CeedScalar *)dXdx, normal); 516da8b59d6SJames Wright } 517da8b59d6SJames Wright 518da8b59d6SJames Wright /** 51906f0a019SJames Wright @brief Unpack `CEED_EVAL_GRAD` QF input into quadrature-point local array 52006f0a019SJames Wright 52106f0a019SJames Wright @param[in] Q Number of quadrature points 52206f0a019SJames Wright @param[in] i Current quadrature point 52306f0a019SJames Wright @param[in] num_comp Number of components of the input 52406f0a019SJames Wright @param[in] dim Topological dimension of the element (ie. number of derivative terms per component) 52506f0a019SJames Wright @param[in] grad QF gradient input, shape `[dim][num_comp][Q]` 526db7fbcd2SJames Wright @param[out] grad_local Gradient array at quadrature point Q, shape `[num_comp][dim]` 52706f0a019SJames Wright **/ 528db7fbcd2SJames Wright CEED_QFUNCTION_HELPER void GradUnpackN(CeedInt Q, CeedInt i, CeedInt num_comp, CeedInt dim, const CeedScalar *grad, CeedScalar *grad_local) { 52906f0a019SJames Wright for (CeedInt d = 0; d < dim; d++) { 53006f0a019SJames Wright for (CeedInt c = 0; c < num_comp; c++) { 531db7fbcd2SJames Wright grad_local[dim * c + d] = grad[(Q * num_comp) * d + Q * c + i]; 53206f0a019SJames Wright } 53306f0a019SJames Wright } 53406f0a019SJames Wright } 53506f0a019SJames Wright 53606f0a019SJames Wright /** 53706f0a019SJames Wright @brief Unpack `CEED_EVAL_GRAD` QF input into quadrature-point local array for 3D elements 53806f0a019SJames Wright 53906f0a019SJames Wright @param[in] Q Number of quadrature points 54006f0a019SJames Wright @param[in] i Current quadrature point 54106f0a019SJames Wright @param[in] num_comp Number of components of the input 54283c0b726SJames Wright @param[in] grad QF gradient input, shape `[3][num_comp][Q]` 543db7fbcd2SJames Wright @param[out] grad_local Gradient array at quadrature point Q, shape `[num_comp][3]` 54406f0a019SJames Wright **/ 545db7fbcd2SJames Wright CEED_QFUNCTION_HELPER void GradUnpack3(CeedInt Q, CeedInt i, CeedInt num_comp, const CeedScalar *grad, CeedScalar (*grad_local)[3]) { 546db7fbcd2SJames Wright GradUnpackN(Q, i, num_comp, 3, grad, (CeedScalar *)grad_local); 54706f0a019SJames Wright } 5488c85b835SJames Wright 5498c85b835SJames Wright /** 55083c0b726SJames Wright @brief Unpack `CEED_EVAL_GRAD` QF input into quadrature-point local array for 2D elements 55183c0b726SJames Wright 55283c0b726SJames Wright @param[in] Q Number of quadrature points 55383c0b726SJames Wright @param[in] i Current quadrature point 55483c0b726SJames Wright @param[in] num_comp Number of components of the input 55583c0b726SJames Wright @param[in] grad QF gradient input, shape `[2][num_comp][Q]` 556db7fbcd2SJames Wright @param[out] grad_local Gradient array at quadrature point Q, shape `[num_comp][2]` 55783c0b726SJames Wright **/ 558db7fbcd2SJames Wright CEED_QFUNCTION_HELPER void GradUnpack2(CeedInt Q, CeedInt i, CeedInt num_comp, const CeedScalar *grad, CeedScalar (*grad_local)[2]) { 559db7fbcd2SJames Wright GradUnpackN(Q, i, num_comp, 2, grad, (CeedScalar *)grad_local); 56083c0b726SJames Wright } 56183c0b726SJames Wright 56283c0b726SJames Wright /** 5638c85b835SJames Wright @brief Calculate divergence from reference gradient 5648c85b835SJames Wright 5658c85b835SJames Wright Given gradient array G_{ij} and inverse element mapping X_{ij}, then the divergence is 5668c85b835SJames Wright 5678c85b835SJames Wright G_{ij} X{ji} 5688c85b835SJames Wright 5698c85b835SJames Wright @param[in] grad_qn Gradient array, orientation [vector component][gradient direction] 5708c85b835SJames Wright @param[in] dXdx Inverse of the mapping Jacobian (shape [dim][dim]) 5718c85b835SJames Wright @param[in] dim Dimension of the problem 5728c85b835SJames Wright @param[out] divergence The divergence 5738c85b835SJames Wright **/ 5748c85b835SJames Wright CEED_QFUNCTION_HELPER void DivergenceND(const CeedScalar *grad_qn, const CeedScalar *dXdx, const CeedInt dim, CeedScalar *divergence) { 5758c85b835SJames Wright for (CeedInt i = 0; i < dim; i++) { 5768c85b835SJames Wright for (CeedInt j = 0; j < dim; j++) { 5778c85b835SJames Wright *divergence += grad_qn[i * dim + j] * dXdx[j * dim + i]; 5788c85b835SJames Wright } 5798c85b835SJames Wright } 5808c85b835SJames Wright } 5818c85b835SJames Wright 5828c85b835SJames Wright /** 5838c85b835SJames Wright @brief Calculate divergence from reference gradient for 3D problem 5848c85b835SJames Wright 5858c85b835SJames Wright Given gradient array G_{ij} and inverse element mapping X_{ij}, then the divergence is 5868c85b835SJames Wright 5878c85b835SJames Wright G_{ij} X{ji} 5888c85b835SJames Wright 5898c85b835SJames Wright @param[in] grad_qn Gradient array, orientation [vector component][gradient direction] 5908c85b835SJames Wright @param[in] dXdx Inverse of the mapping Jacobian (shape [3][3]) 5918c85b835SJames Wright @param[out] divergence The divergence 5928c85b835SJames Wright **/ 5938c85b835SJames Wright CEED_QFUNCTION_HELPER void Divergence3D(const CeedScalar grad_qn[3][3], const CeedScalar dXdx[3][3], CeedScalar *divergence) { 5948c85b835SJames Wright DivergenceND((const CeedScalar *)grad_qn, (const CeedScalar *)dXdx, 3, divergence); 5958c85b835SJames Wright } 596