15aed82e4SJeremy L Thompson // Copyright (c) 2017-2024, Lawrence Livermore National Security, LLC and other CEED contributors. 213fa47b2SJames Wright // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 313fa47b2SJames Wright // 413fa47b2SJames Wright // SPDX-License-Identifier: BSD-2-Clause 513fa47b2SJames Wright // 613fa47b2SJames Wright // This file is part of CEED: http://github.com/ceed 7*509d4af6SJeremy L Thompson #pragma once 813fa47b2SJames Wright 913fa47b2SJames Wright #include <ceed.h> 10c9c2c079SJeremy L Thompson #include <math.h> 1113fa47b2SJames Wright 1213fa47b2SJames Wright #ifndef M_PI 1313fa47b2SJames Wright #define M_PI 3.14159265358979323846 1413fa47b2SJames Wright #endif 1513fa47b2SJames Wright 1613fa47b2SJames Wright CEED_QFUNCTION_HELPER CeedScalar Max(CeedScalar a, CeedScalar b) { return a < b ? b : a; } 1713fa47b2SJames Wright CEED_QFUNCTION_HELPER CeedScalar Min(CeedScalar a, CeedScalar b) { return a < b ? a : b; } 1813fa47b2SJames Wright 19dc9b5c4aSJames Wright CEED_QFUNCTION_HELPER void SwapScalar(CeedScalar *a, CeedScalar *b) { 20dc9b5c4aSJames Wright CeedScalar temp = *a; 21dc9b5c4aSJames Wright *a = *b; 22dc9b5c4aSJames Wright *b = temp; 23dc9b5c4aSJames Wright } 24dc9b5c4aSJames Wright 2513fa47b2SJames Wright CEED_QFUNCTION_HELPER CeedScalar Square(CeedScalar x) { return x * x; } 2613fa47b2SJames Wright CEED_QFUNCTION_HELPER CeedScalar Cube(CeedScalar x) { return x * x * x; } 2713fa47b2SJames Wright 28530ad8c4SKenneth E. Jansen // @brief Scale vector of length N by scalar alpha 29530ad8c4SKenneth E. Jansen CEED_QFUNCTION_HELPER void ScaleN(CeedScalar *u, const CeedScalar alpha, const CeedInt N) { 30a455f92dSJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) u[i] *= alpha; 31a455f92dSJames Wright } 32a455f92dSJames Wright 33a455f92dSJames Wright // @brief Set vector of length N to a value alpha 34a455f92dSJames Wright CEED_QFUNCTION_HELPER void SetValueN(CeedScalar *u, const CeedScalar alpha, const CeedInt N) { 35a455f92dSJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) u[i] = alpha; 36a455f92dSJames Wright } 37a455f92dSJames Wright 38a455f92dSJames Wright // @brief Copy N elements from x to y 39a455f92dSJames 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]; } 40a455f92dSJames Wright 41a455f92dSJames Wright // @brief Copy 3x3 matrix from A to B 42a455f92dSJames Wright CEED_QFUNCTION_HELPER void CopyMat3(const CeedScalar A[3][3], CeedScalar B[3][3]) { CopyN((const CeedScalar *)A, (CeedScalar *)B, 9); } 43a455f92dSJames Wright 44a455f92dSJames Wright // @brief Dot product of vectors with N elements 45a455f92dSJames Wright CEED_QFUNCTION_HELPER CeedScalar DotN(const CeedScalar *u, const CeedScalar *v, const CeedInt N) { 46a455f92dSJames Wright CeedScalar output = 0; 47a455f92dSJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) output += u[i] * v[i]; 48a455f92dSJames Wright return output; 49530ad8c4SKenneth E. Jansen } 50530ad8c4SKenneth E. Jansen 5113fa47b2SJames Wright // @brief Dot product of 3 element vectors 52be91e165SJames 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]; } 5313fa47b2SJames Wright 54a455f92dSJames Wright // @brief Cross product of vectors with 3 elements 55a455f92dSJames Wright CEED_QFUNCTION_HELPER void Cross3(const CeedScalar u[3], const CeedScalar v[3], CeedScalar w[3]) { 56a455f92dSJames Wright w[0] = (u[1] * v[2]) - (u[2] * v[1]); 57a455f92dSJames Wright w[1] = (u[2] * v[0]) - (u[0] * v[2]); 58a455f92dSJames Wright w[2] = (u[0] * v[1]) - (u[1] * v[0]); 59a455f92dSJames Wright } 60a455f92dSJames Wright 61a455f92dSJames Wright // @brief Curl of vector given its gradient 62a455f92dSJames Wright CEED_QFUNCTION_HELPER void Curl3(const CeedScalar gradient[3][3], CeedScalar v[3]) { 63a455f92dSJames Wright v[0] = gradient[2][1] - gradient[1][2]; 64a455f92dSJames Wright v[1] = gradient[0][2] - gradient[2][0]; 65a455f92dSJames Wright v[2] = gradient[1][0] - gradient[0][1]; 66a455f92dSJames Wright } 67a455f92dSJames Wright 68a455f92dSJames Wright // @brief Matrix vector product, b = Ax + b. A is NxM, x is M, b is N 69a455f92dSJames Wright CEED_QFUNCTION_HELPER void MatVecNM(const CeedScalar *A, const CeedScalar *x, const CeedInt N, const CeedInt M, const CeedTransposeMode transpose_A, 70a455f92dSJames Wright CeedScalar *b) { 71a455f92dSJames Wright switch (transpose_A) { 72a455f92dSJames Wright case CEED_NOTRANSPOSE: 73a455f92dSJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) b[i] += DotN(&A[i * M], x, M); 74a455f92dSJames Wright break; 75a455f92dSJames Wright case CEED_TRANSPOSE: 76a455f92dSJames 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]; } 77a455f92dSJames Wright break; 78a455f92dSJames Wright } 79a455f92dSJames Wright } 80a455f92dSJames Wright 81a455f92dSJames Wright // @brief 3x3 Matrix vector product b = Ax + b. 82a455f92dSJames Wright CEED_QFUNCTION_HELPER void MatVec3(const CeedScalar A[3][3], const CeedScalar x[3], const CeedTransposeMode transpose_A, CeedScalar b[3]) { 83a455f92dSJames Wright MatVecNM((const CeedScalar *)A, (const CeedScalar *)x, 3, 3, transpose_A, (CeedScalar *)b); 84a455f92dSJames Wright } 85a455f92dSJames Wright 86a455f92dSJames Wright // @brief Matrix-Matrix product, B = DA + B, where D is diagonal. 87a455f92dSJames 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. 88a455f92dSJames Wright CEED_QFUNCTION_HELPER void MatDiagNM(const CeedScalar *A, const CeedScalar *D, const CeedInt N, const CeedInt M, const CeedTransposeMode transpose_A, 89a455f92dSJames Wright CeedScalar *B) { 90a455f92dSJames Wright switch (transpose_A) { 91a455f92dSJames Wright case CEED_NOTRANSPOSE: 92a455f92dSJames 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]; } 93a455f92dSJames Wright break; 94a455f92dSJames Wright case CEED_TRANSPOSE: 95a455f92dSJames 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]; } 96a455f92dSJames Wright break; 97a455f92dSJames Wright } 98a455f92dSJames Wright } 99a455f92dSJames Wright 100a455f92dSJames Wright // @brief 3x3 Matrix-Matrix product, B = DA + B, where D is diagonal. 101a455f92dSJames Wright // @details Optionally, A may be transposed. 102a455f92dSJames Wright CEED_QFUNCTION_HELPER void MatDiag3(const CeedScalar A[3][3], const CeedScalar D[3], const CeedTransposeMode transpose_A, CeedScalar B[3][3]) { 103a455f92dSJames Wright MatDiagNM((const CeedScalar *)A, (const CeedScalar *)D, 3, 3, transpose_A, (CeedScalar *)B); 104a455f92dSJames Wright } 10598d9a7e6SJames Wright // @brief NxN Matrix-Matrix product, C = AB + C 10698d9a7e6SJames Wright CEED_QFUNCTION_HELPER void MatMatN(const CeedScalar *A, const CeedScalar *B, const CeedInt N, const CeedTransposeMode transpose_A, 10798d9a7e6SJames Wright const CeedTransposeMode transpose_B, CeedScalar *C) { 108a455f92dSJames Wright switch (transpose_A) { 109a455f92dSJames Wright case CEED_NOTRANSPOSE: 110a455f92dSJames Wright switch (transpose_B) { 111a455f92dSJames Wright case CEED_NOTRANSPOSE: 11298d9a7e6SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) { 11398d9a7e6SJames Wright CeedPragmaSIMD for (CeedInt j = 0; j < N; j++) { 11498d9a7e6SJames Wright CeedPragmaSIMD for (CeedInt k = 0; k < N; k++) C[i * N + j] += A[i * N + k] * B[k * N + j]; 11598d9a7e6SJames Wright } 116a455f92dSJames Wright } 117a455f92dSJames Wright break; 118a455f92dSJames Wright case CEED_TRANSPOSE: 11998d9a7e6SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) { 12098d9a7e6SJames Wright CeedPragmaSIMD for (CeedInt j = 0; j < N; j++) { 12198d9a7e6SJames Wright CeedPragmaSIMD for (CeedInt k = 0; k < N; k++) C[i * N + j] += A[i * N + k] * B[j * N + k]; 12298d9a7e6SJames Wright } 123a455f92dSJames Wright } 124a455f92dSJames Wright break; 125a455f92dSJames Wright } 126a455f92dSJames Wright break; 127a455f92dSJames Wright case CEED_TRANSPOSE: 128a455f92dSJames Wright switch (transpose_B) { 129a455f92dSJames Wright case CEED_NOTRANSPOSE: 13098d9a7e6SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) { 13198d9a7e6SJames Wright CeedPragmaSIMD for (CeedInt j = 0; j < N; j++) { 13298d9a7e6SJames Wright CeedPragmaSIMD for (CeedInt k = 0; k < N; k++) C[i * N + j] += A[k * N + i] * B[k * N + j]; 13398d9a7e6SJames Wright } 134a455f92dSJames Wright } 135a455f92dSJames Wright break; 136a455f92dSJames Wright case CEED_TRANSPOSE: 13798d9a7e6SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < N; i++) { 13898d9a7e6SJames Wright CeedPragmaSIMD for (CeedInt j = 0; j < N; j++) { 13998d9a7e6SJames Wright CeedPragmaSIMD for (CeedInt k = 0; k < N; k++) C[i * N + j] += A[k * N + i] * B[j * N + k]; 14098d9a7e6SJames Wright } 141a455f92dSJames Wright } 142a455f92dSJames Wright break; 143a455f92dSJames Wright } 144a455f92dSJames Wright break; 145a455f92dSJames Wright } 146a455f92dSJames Wright } 147a455f92dSJames Wright 14898d9a7e6SJames Wright // @brief 3x3 Matrix-Matrix product, C = AB + C 14998d9a7e6SJames Wright CEED_QFUNCTION_HELPER void MatMat3(const CeedScalar A[3][3], const CeedScalar B[3][3], const CeedTransposeMode transpose_A, 15098d9a7e6SJames Wright const CeedTransposeMode transpose_B, CeedScalar C[3][3]) { 15198d9a7e6SJames Wright MatMatN((const CeedScalar *)A, (const CeedScalar *)B, 3, transpose_A, transpose_B, (CeedScalar *)C); 15298d9a7e6SJames Wright } 15398d9a7e6SJames Wright 15413fa47b2SJames Wright // @brief Unpack Kelvin-Mandel notation symmetric tensor into full tensor 15513fa47b2SJames Wright CEED_QFUNCTION_HELPER void KMUnpack(const CeedScalar v[6], CeedScalar A[3][3]) { 15613fa47b2SJames Wright const CeedScalar weight = 1 / sqrt(2.); 15713fa47b2SJames Wright A[0][0] = v[0]; 15813fa47b2SJames Wright A[1][1] = v[1]; 15913fa47b2SJames Wright A[2][2] = v[2]; 16013fa47b2SJames Wright A[2][1] = A[1][2] = weight * v[3]; 16113fa47b2SJames Wright A[2][0] = A[0][2] = weight * v[4]; 16213fa47b2SJames Wright A[1][0] = A[0][1] = weight * v[5]; 16313fa47b2SJames Wright } 16413fa47b2SJames Wright 165a455f92dSJames Wright // @brief Pack full tensor into Kelvin-Mandel notation symmetric tensor 166a455f92dSJames Wright CEED_QFUNCTION_HELPER void KMPack(const CeedScalar A[3][3], CeedScalar v[6]) { 167a455f92dSJames Wright const CeedScalar weight = sqrt(2.); 168a455f92dSJames Wright v[0] = A[0][0]; 169a455f92dSJames Wright v[1] = A[1][1]; 170a455f92dSJames Wright v[2] = A[2][2]; 171a455f92dSJames Wright v[3] = A[2][1] * weight; 172a455f92dSJames Wright v[4] = A[2][0] * weight; 173a455f92dSJames Wright v[5] = A[1][0] * weight; 174a455f92dSJames Wright } 175a455f92dSJames Wright 176a455f92dSJames Wright // @brief Calculate metric tensor from mapping, g_{ij} = xi_{k,i} xi_{k,j} = dXdx^T dXdx 177a455f92dSJames Wright CEED_QFUNCTION_HELPER void KMMetricTensor(const CeedScalar dXdx[3][3], CeedScalar km_g_ij[6]) { 178a455f92dSJames Wright CeedScalar g_ij[3][3] = {{0.}}; 179a455f92dSJames Wright MatMat3(dXdx, dXdx, CEED_TRANSPOSE, CEED_NOTRANSPOSE, g_ij); 180a455f92dSJames Wright KMPack(g_ij, km_g_ij); 181a455f92dSJames Wright } 182a455f92dSJames Wright 183530ad8c4SKenneth E. Jansen // @brief Linear ramp evaluation 184530ad8c4SKenneth E. Jansen CEED_QFUNCTION_HELPER CeedScalar LinearRampCoefficient(CeedScalar amplitude, CeedScalar length, CeedScalar start, CeedScalar x) { 185530ad8c4SKenneth E. Jansen if (x < start) { 186530ad8c4SKenneth E. Jansen return amplitude; 187530ad8c4SKenneth E. Jansen } else if (x < start + length) { 188530ad8c4SKenneth E. Jansen return amplitude * ((x - start) * (-1 / length) + 1); 189530ad8c4SKenneth E. Jansen } else { 190530ad8c4SKenneth E. Jansen return 0; 191530ad8c4SKenneth E. Jansen } 192530ad8c4SKenneth E. Jansen } 193530ad8c4SKenneth E. Jansen 194f3e15844SJames Wright /** 195f3e15844SJames Wright @brief Pack stored values at quadrature point 196f3e15844SJames Wright 197f3e15844SJames Wright @param[in] Q Number of quadrature points 198f3e15844SJames Wright @param[in] i Current quadrature point 199f3e15844SJames Wright @param[in] start Starting index to store components 200f3e15844SJames Wright @param[in] num_comp Number of components to store 2014e5897fcSJames Wright @param[in] values_at_qpnt Local values for quadrature point i 202f3e15844SJames Wright @param[out] stored Stored values 203f3e15844SJames Wright 204f3e15844SJames Wright @return An error code: 0 - success, otherwise - failure 205f3e15844SJames Wright **/ 2064e5897fcSJames Wright CEED_QFUNCTION_HELPER int StoredValuesPack(CeedInt Q, CeedInt i, CeedInt start, CeedInt num_comp, const CeedScalar *values_at_qpnt, 2074e5897fcSJames Wright CeedScalar *stored) { 2084e5897fcSJames Wright for (CeedInt j = 0; j < num_comp; j++) stored[(start + j) * Q + i] = values_at_qpnt[j]; 209f3e15844SJames Wright 210f3e15844SJames Wright return CEED_ERROR_SUCCESS; 211f3e15844SJames Wright } 212f3e15844SJames Wright 213f3e15844SJames Wright /** 214f3e15844SJames Wright @brief Unpack stored values at quadrature point 215f3e15844SJames Wright 216f3e15844SJames Wright @param[in] Q Number of quadrature points 217f3e15844SJames Wright @param[in] i Current quadrature point 218f3e15844SJames Wright @param[in] start Starting index to store components 219f3e15844SJames Wright @param[in] num_comp Number of components to store 220f3e15844SJames Wright @param[in] stored Stored values 2214e5897fcSJames Wright @param[out] values_at_qpnt Local values for quadrature point i 222f3e15844SJames Wright 223f3e15844SJames Wright @return An error code: 0 - success, otherwise - failure 224f3e15844SJames Wright **/ 2254e5897fcSJames Wright CEED_QFUNCTION_HELPER int StoredValuesUnpack(CeedInt Q, CeedInt i, CeedInt start, CeedInt num_comp, const CeedScalar *stored, 2264e5897fcSJames Wright CeedScalar *values_at_qpnt) { 2274e5897fcSJames Wright for (CeedInt j = 0; j < num_comp; j++) values_at_qpnt[j] = stored[(start + j) * Q + i]; 228f3e15844SJames Wright 229f3e15844SJames Wright return CEED_ERROR_SUCCESS; 230f3e15844SJames Wright } 231f3e15844SJames Wright 232f3e15844SJames Wright /** 233f3e15844SJames Wright @brief Unpack 3D element q_data at quadrature point 234f3e15844SJames Wright 235f3e15844SJames Wright @param[in] Q Number of quadrature points 236f3e15844SJames Wright @param[in] i Current quadrature point 237f3e15844SJames Wright @param[in] q_data Pointer to q_data (generated by `setupgeo.h:Setup`) 238f3e15844SJames Wright @param[out] wdetJ Quadrature weight times determinant of the mapping Jacobian 239f3e15844SJames Wright @param[out] dXdx Inverse of the mapping Jacobian (shape [3][3]) 240f3e15844SJames Wright 241f3e15844SJames Wright @return An error code: 0 - success, otherwise - failure 242f3e15844SJames Wright **/ 243f3e15844SJames Wright CEED_QFUNCTION_HELPER int QdataUnpack_3D(CeedInt Q, CeedInt i, const CeedScalar *q_data, CeedScalar *wdetJ, CeedScalar dXdx[3][3]) { 244f3e15844SJames Wright StoredValuesUnpack(Q, i, 0, 1, q_data, wdetJ); 245f3e15844SJames Wright StoredValuesUnpack(Q, i, 1, 9, q_data, (CeedScalar *)dXdx); 246f3e15844SJames Wright return CEED_ERROR_SUCCESS; 247f3e15844SJames Wright } 248f3e15844SJames Wright 249f3e15844SJames Wright /** 250f3e15844SJames Wright @brief Unpack boundary element q_data for 3D problem at quadrature point 251f3e15844SJames Wright 252f3e15844SJames Wright @param[in] Q Number of quadrature points 253f3e15844SJames Wright @param[in] i Current quadrature point 2541394d07eSJames Wright @param[in] q_data Pointer to q_data (generated by `setupgeo.h:SetupBoundary`) 255f3e15844SJames Wright @param[out] wdetJ Quadrature weight times determinant of the mapping Jacobian, or `NULL` 256f3e15844SJames Wright @param[out] dXdx Inverse of the mapping Jacobian (shape [2][3]), or `NULL` 257f3e15844SJames Wright @param[out] normal Components of the normal vector (shape [3]), or `NULL` 258f3e15844SJames Wright 259f3e15844SJames Wright @return An error code: 0 - success, otherwise - failure 260f3e15844SJames Wright **/ 261f3e15844SJames Wright CEED_QFUNCTION_HELPER int QdataBoundaryUnpack_3D(CeedInt Q, CeedInt i, const CeedScalar *q_data, CeedScalar *wdetJ, CeedScalar dXdx[2][3], 262f3e15844SJames Wright CeedScalar normal[3]) { 263f3e15844SJames Wright if (wdetJ) StoredValuesUnpack(Q, i, 0, 1, q_data, wdetJ); 264f3e15844SJames Wright if (normal) StoredValuesUnpack(Q, i, 1, 3, q_data, normal); 265f3e15844SJames Wright if (dXdx) StoredValuesUnpack(Q, i, 4, 6, q_data, (CeedScalar *)dXdx); 266f3e15844SJames Wright return CEED_ERROR_SUCCESS; 267f3e15844SJames Wright } 268f3e15844SJames Wright 269bf415d3fSJames Wright /** 270bf415d3fSJames Wright @brief Unpack 2D element q_data at quadrature point 271bf415d3fSJames Wright 272bf415d3fSJames Wright @param[in] Q Number of quadrature points 273bf415d3fSJames Wright @param[in] i Current quadrature point 274bf415d3fSJames Wright @param[in] q_data Pointer to q_data (generated by `setupgeo.h:Setup`) 275bf415d3fSJames Wright @param[out] wdetJ Quadrature weight times determinant of the mapping Jacobian 276bf415d3fSJames Wright @param[out] dXdx Inverse of the mapping Jacobian (shape [2][2]) 277bf415d3fSJames Wright 278bf415d3fSJames Wright @return An error code: 0 - success, otherwise - failure 279bf415d3fSJames Wright **/ 280bf415d3fSJames Wright CEED_QFUNCTION_HELPER int QdataUnpack_2D(CeedInt Q, CeedInt i, const CeedScalar *q_data, CeedScalar *wdetJ, CeedScalar dXdx[2][2]) { 281bf415d3fSJames Wright StoredValuesUnpack(Q, i, 0, 1, q_data, wdetJ); 282bf415d3fSJames Wright StoredValuesUnpack(Q, i, 1, 4, q_data, (CeedScalar *)dXdx); 283bf415d3fSJames Wright return CEED_ERROR_SUCCESS; 284bf415d3fSJames Wright } 285bf415d3fSJames Wright 2861394d07eSJames Wright /** 2871394d07eSJames Wright @brief Unpack boundary element q_data for 2D problem at quadrature point 2881394d07eSJames Wright 2891394d07eSJames Wright @param[in] Q Number of quadrature points 2901394d07eSJames Wright @param[in] i Current quadrature point 2911394d07eSJames Wright @param[in] q_data Pointer to q_data (generated by `setupgeo.h:SetupBoundary2d`) 2921394d07eSJames Wright @param[out] wdetJ Quadrature weight times determinant of the mapping Jacobian, or `NULL` 2931394d07eSJames Wright @param[out] normal Components of the normal vector (shape [2]), or `NULL` 2941394d07eSJames Wright 2951394d07eSJames Wright @return An error code: 0 - success, otherwise - failure 2961394d07eSJames Wright **/ 2971394d07eSJames Wright CEED_QFUNCTION_HELPER int QdataBoundaryUnpack_2D(CeedInt Q, CeedInt i, const CeedScalar *q_data, CeedScalar *wdetJ, CeedScalar normal[2]) { 2981394d07eSJames Wright if (wdetJ) StoredValuesUnpack(Q, i, 0, 1, q_data, wdetJ); 2991394d07eSJames Wright if (normal) StoredValuesUnpack(Q, i, 1, 2, q_data, normal); 3001394d07eSJames Wright return CEED_ERROR_SUCCESS; 3011394d07eSJames Wright } 302