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
Max(CeedScalar a,CeedScalar b)14704b8bbeSJames Wright CEED_QFUNCTION_HELPER CeedScalar Max(CeedScalar a, CeedScalar b) { return a < b ? b : a; }
Min(CeedScalar a,CeedScalar b)15704b8bbeSJames Wright CEED_QFUNCTION_HELPER CeedScalar Min(CeedScalar a, CeedScalar b) { return a < b ? a : b; }
16704b8bbeSJames Wright
SwapScalar(CeedScalar * a,CeedScalar * b)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
Square(CeedScalar x)23704b8bbeSJames Wright CEED_QFUNCTION_HELPER CeedScalar Square(CeedScalar x) { return x * x; }
Cube(CeedScalar 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
ScaleN(CeedScalar * u,const CeedScalar alpha,const CeedInt N)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
SetValueN(CeedScalar * u,const CeedScalar alpha,const CeedInt N)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
CopyN(const CeedScalar * x,CeedScalar * y,const CeedInt N)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
CopyMat3(const CeedScalar A[3][3],CeedScalar B[3][3])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
DotN(const CeedScalar * u,const CeedScalar * v,const CeedInt N)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
AXPY(CeedScalar alpha,const CeedScalar * x,CeedScalar * y,CeedInt N)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
Dot3(const CeedScalar * u,const CeedScalar * v)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
Dot2(const CeedScalar * u,const CeedScalar * v)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
Norm3(const CeedScalar * u)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
Norm2(const CeedScalar * u)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
Cross3(const CeedScalar u[3],const CeedScalar v[3],CeedScalar w[3])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
Curl3(const CeedScalar gradient[3][3],CeedScalar v[3])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
MatVecNM(const CeedScalar * A,const CeedScalar * x,const CeedInt N,const CeedInt M,const CeedTransposeMode transpose_A,CeedScalar * b)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.
MatVec3(const CeedScalar A[3][3],const CeedScalar x[3],const CeedTransposeMode transpose_A,CeedScalar b[3])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.
MatVec2(const CeedScalar A[2][2],const CeedScalar x[2],const CeedTransposeMode transpose_A,CeedScalar b[2])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.
MatDiagNM(const CeedScalar * A,const CeedScalar * D,const CeedInt N,const CeedInt M,const CeedTransposeMode transpose_A,CeedScalar * B)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.
MatDiag3(const CeedScalar A[3][3],const CeedScalar D[3],const CeedTransposeMode transpose_A,CeedScalar B[3][3])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
MatMatN(const CeedScalar * A,const CeedScalar * B,const CeedInt N,const CeedTransposeMode transpose_A,const CeedTransposeMode transpose_B,CeedScalar * 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
MatMat3(const CeedScalar A[3][3],const CeedScalar B[3][3],const CeedTransposeMode transpose_A,const CeedTransposeMode transpose_B,CeedScalar C[3][3])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
MatMat2(const CeedScalar A[2][2],const CeedScalar B[2][2],const CeedTransposeMode transpose_A,const CeedTransposeMode transpose_B,CeedScalar C[2][2])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 */
MatInv2(const CeedScalar A[2][2],CeedScalar A_inv[2][2],CeedScalar * detJ_ptr)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 */
MatInv3(const CeedScalar A[3][3],CeedScalar A_inv[3][3],CeedScalar * detJ_ptr)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 **/
MatMatNM(const CeedScalar * mat_A,const CeedScalar * mat_B,CeedScalar * mat_C,CeedInt N,CeedInt M,CeedInt P)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
KMUnpack(const CeedScalar v[6],CeedScalar A[3][3])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
KMPack(const CeedScalar A[3][3],CeedScalar v[6])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
KMMetricTensor(const CeedScalar dXdx[3][3],CeedScalar km_g_ij[6])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
267dc336713SJames Wright /**
268dc336713SJames Wright @brief Linear ramp evaluation from set amplitude to zero
269dc336713SJames Wright
270dc336713SJames Wright ▲
271dc336713SJames Wright │
272dc336713SJames Wright a│-------┬.
273dc336713SJames Wright │ ┊ `-.
274dc336713SJames Wright │ ┊ `-.
275dc336713SJames Wright │ ┊ `-.______
276dc336713SJames Wright └───────┴─────────┴────────> x
277dc336713SJames Wright s s+l
278dc336713SJames Wright
279dc336713SJames Wright where "a" is `amplitude`, "s" is `start`, and "l" is `length`.
280dc336713SJames Wright
281dc336713SJames Wright @param[in] amplitude Maximum value of the ramp
282dc336713SJames Wright @param[in] length Length of the ramp
283dc336713SJames Wright @param[in] start Location where ramp begins to reduce from `amplitude` to 0
284dc336713SJames Wright @param[in] x Input location
285dc336713SJames Wright @return Value of linear ramp function
286dc336713SJames Wright **/
LinearRampCoefficient(CeedScalar amplitude,CeedScalar length,CeedScalar start,CeedScalar x)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 **/
StoredValuesPack(CeedInt Q,CeedInt i,CeedInt start,CeedInt num_comp,const CeedScalar * values_at_qpnt,CeedScalar * stored)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 **/
StoredValuesUnpack(CeedInt Q,CeedInt i,CeedInt start,CeedInt num_comp,const CeedScalar * stored,CeedScalar * values_at_qpnt)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 **/
QdataUnpack_ND(CeedInt dim,CeedInt Q,CeedInt i,const CeedScalar * q_data,CeedScalar * wdetJ,CeedScalar * dXdx)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 **/
QdataBoundaryUnpack_ND(CeedInt dim,CeedInt Q,CeedInt i,const CeedScalar * q_data,CeedScalar * wdetJ,CeedScalar * dXdx,CeedScalar * normal)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 **/
QdataBoundaryGradientUnpack_ND(CeedInt dim,CeedInt Q,CeedInt i,const CeedScalar * q_data,CeedScalar * wdetJ,CeedScalar * dXdx,CeedScalar * normal)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 **/
QdataUnpack_3D(CeedInt Q,CeedInt i,const CeedScalar * q_data,CeedScalar * wdetJ,CeedScalar dXdx[3][3])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 **/
QdataBoundaryUnpack_3D(CeedInt Q,CeedInt i,const CeedScalar * q_data,CeedScalar * wdetJ,CeedScalar dXdx[2][3],CeedScalar normal[3])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 **/
QdataBoundaryGradientUnpack_3D(CeedInt Q,CeedInt i,const CeedScalar * q_data,CeedScalar * wdetJ,CeedScalar dXdx[3][3],CeedScalar normal[3])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 **/
QdataUnpack_2D(CeedInt Q,CeedInt i,const CeedScalar * q_data,CeedScalar * wdetJ,CeedScalar dXdx[2][2])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 **/
QdataBoundaryUnpack_2D(CeedInt Q,CeedInt i,const CeedScalar * q_data,CeedScalar * wdetJ,CeedScalar normal[2])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 **/
QdataBoundaryGradientUnpack_2D(CeedInt Q,CeedInt i,const CeedScalar * q_data,CeedScalar * wdetJ,CeedScalar dXdx[2][2],CeedScalar normal[2])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 **/
GradUnpackND(CeedInt Q,CeedInt i,CeedInt num_comp,CeedInt dim,const CeedScalar * grad,CeedScalar * grad_local)528*22440147SJames Wright CEED_QFUNCTION_HELPER void GradUnpackND(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 **/
GradUnpack3D(CeedInt Q,CeedInt i,CeedInt num_comp,const CeedScalar * grad,CeedScalar (* grad_local)[3])545*22440147SJames Wright CEED_QFUNCTION_HELPER void GradUnpack3D(CeedInt Q, CeedInt i, CeedInt num_comp, const CeedScalar *grad, CeedScalar (*grad_local)[3]) {
546*22440147SJames Wright GradUnpackND(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 **/
GradUnpack2D(CeedInt Q,CeedInt i,CeedInt num_comp,const CeedScalar * grad,CeedScalar (* grad_local)[2])558*22440147SJames Wright CEED_QFUNCTION_HELPER void GradUnpack2D(CeedInt Q, CeedInt i, CeedInt num_comp, const CeedScalar *grad, CeedScalar (*grad_local)[2]) {
559*22440147SJames Wright GradUnpackND(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 **/
DivergenceND(const CeedScalar * grad_qn,const CeedScalar * dXdx,const CeedInt dim,CeedScalar * divergence)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 **/
Divergence3D(const CeedScalar grad_qn[3][3],const CeedScalar dXdx[3][3],CeedScalar * divergence)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