19 #ifndef GEOS_PHYSICSSOLVERS_WAVEPROPAGATION_ACOUSTICWAVEEQUATIONDGKERNEL_HPP_
20 #define GEOS_PHYSICSSOLVERS_WAVEPROPAGATION_ACOUSTICWAVEEQUATIONDGKERNEL_HPP_
23 #include "denseLinearAlgebra/interfaces/blaslapack/BlasLapackLA.hpp"
29 namespace AcousticWaveEquationDGKernels
34 using EXEC_POLICY = parallelDevicePolicy< >;
63 template<
typename EXEC_POLICY,
typename FE_TYPE >
90 real64 const center[3] = { elemCenter[k][0],
97 for(
localIndex isrc = 0; isrc < sourceCoordinates.size( 0 ); ++isrc )
99 if( sourceIsAccessible[isrc] == 0 )
101 real64 const coords[3] = { sourceCoordinates[isrc][0],
102 sourceCoordinates[isrc][1],
103 sourceCoordinates[isrc][2] };
104 bool const sourceFound =
105 computationalGeometry::isPointInsideConvexPolyhedronRobust( k,
110 baseNodeLocalToGlobal,
111 elementLocalToGlobal,
117 sourceIsAccessible[isrc] = 1;
118 sourceElem[isrc] = k;
119 sourceRegion[isrc] = regionIndex;
120 real64 Ntest[FE_TYPE::numNodes];
124 constexpr
localIndex numNodesPerElem = FE_TYPE::numNodes;
130 xLocal[a][i] = baseNodeCoords( baseElemsToNodes( k, a ), i );
134 FE_TYPE::calcN( xLocal, coords, Ntest );
136 for(
localIndex a = 0; a < numNodesPerElem; ++a )
138 sourceConstants[isrc][a] = Ntest[a];
147 for(
localIndex ircv = 0; ircv < receiverCoordinates.size( 0 ); ++ircv )
149 if( receiverIsLocal[ircv] == 0 )
151 real64 const coords[3] = { receiverCoordinates[ircv][0],
152 receiverCoordinates[ircv][1],
153 receiverCoordinates[ircv][2] };
155 bool const receiverFound =
156 computationalGeometry::isPointInsideConvexPolyhedronRobust( k,
161 baseNodeLocalToGlobal,
162 elementLocalToGlobal,
166 if( receiverFound && elemGhostRank[k] < 0 )
168 receiverIsLocal[ircv] = 1;
169 receiverElem[ircv] = k;
170 receiverRegion[ircv] = regionIndex;
173 real64 Ntest[FE_TYPE::numNodes];
174 constexpr
localIndex numNodesPerElem = FE_TYPE::numNodes;
181 xLocal[a][i] = baseNodeCoords( baseElemsToNodes( k, a ), i );
184 FE_TYPE::calcN( xLocal, coords, Ntest );
186 for(
localIndex a = 0; a < numNodesPerElem; ++a )
188 receiverConstants[ircv][a] = Ntest[a];
202 using EXEC_POLICY = parallelDevicePolicy< >;
211 template<
typename EXEC_POLICY,
typename FE_TYPE >
224 localIndex vertices[ 4 ] = { elemsToNodes( k1, 0 ), elemsToNodes( k1, 1 ), elemsToNodes( k1, 2 ), elemsToNodes( k1, 3 ) };
225 for(
int i = 0; i < 4; i++ )
229 localIndex faceVertices[ 3 ] = { facesToNodes( f, 0 ), facesToNodes( f, 1 ), facesToNodes( f, 2 ) };
234 k2 = facesToElems( f, 1 );
243 vertex = vertices[k];
245 for(
int j = 0; j < 3; j++ )
247 if( vertex == faceVertices[ j ] )
260 k1OrderedVertices[ count++ ] = vertex;
264 GEOS_ERROR_IF( o1 < 0,
"Topological error in mesh: a face and its adjacent element share all vertices." );
268 elemsToOpposite( k1, indexo1 ) = freeSurfaceFaceIndicator( f ) == 1 ? -2 : -1;
269 elemsToOppositePermutation( k1, indexo1 ) = 0;
273 elemsToOpposite( k1, indexo1 ) = k2;
274 localIndex oppositeElemVertices[ 4 ] = { elemsToNodes( k2, 0 ), elemsToNodes( k2, 1 ), elemsToNodes( k2, 2 ), elemsToNodes( k2, 3 ) };
278 for(
localIndex k2Vertex : oppositeElemVertices )
281 for(
int j = 0; j < 3; j++ )
283 if( k1OrderedVertices[ j ] == k2Vertex )
289 permutation = permutation + c * ( position + 1 );
292 elemsToOppositePermutation( k1, indexo1 ) = permutation;
301 using EXEC_POLICY = parallelDevicePolicy< >;
312 template<
typename EXEC_POLICY >
391 using EXEC_POLICY = parallelDevicePolicy< >;
409 template<
typename FE_TYPE,
typename EXEC_POLICY,
typename ATOMIC_POLICY >
429 real32 const timeSourceFrequency,
430 real32 const timeSourceDelay,
432 bool const useSourceWaveletTables,
438 real64 const rickerValue = useSourceWaveletTables ? 0 : WaveSolverUtils::evaluateRicker( time_n, timeSourceFrequency, timeSourceDelay, rickerOrder );
443 int const order = FE_TYPE::order;
446 int const alpha = 12.0*((order*(order+1)*(order+2))/6);
448 real64 const dt2 = pow( dt, 2 );
450 constexpr
localIndex numNodesPerElem = FE_TYPE::numNodes;
452 real64 pTemp[numNodesPerElem] = {0.0};
453 real64 flowx[numNodesPerElem] = {0.0};
460 xLocal[a][i] = X( elemsToNodes( k, a ), i );
465 real64 const C2 = pow( velocity[k], 2 );
467 real64 const invC2 = 1.0/(C2*density[k]);
469 real64 const det = LvArray::math::abs( FE_TYPE::jacobianDeterminant( xLocal ));
472 FE_TYPE::computeMassTerm( xLocal, [&] (
const int i,
const int j,
const real64 val )
474 pTemp[i] += 2.0*invC2*val*p_n[k][j];
475 pTemp[i] -= val*invC2*p_nm1[k][j];
479 FE_TYPE::computeStiffnessTerm( xLocal, [&] (
const int i,
const int j,
real64 val )
481 flowx[i] -= val*p_n[k][j];
486 FE_TYPE::computeSurfaceTerms( xLocal, [&] (
const int c1,
const int c2,
const int f1,
const int,
const int,
const int,
const int i2,
const int j2,
const int k2,
real64 const val )
490 const localIndex elemNeigh = elemsToOpposite( k, f1 );
498 const int perm = elemsToOppositePermutation( k, f1 );
501 const int p1 = perm%4-1;
502 const int p2 = (perm/4)%4-1;
503 const int p3 = (perm/16)%4-1;
505 const int l2 = order-i2-j2-k2;
506 const int Indices[3] = {i2, j2, k2};
508 const int ii2 = p1 < 0 ? l2 : Indices[p1];
509 const int jj2 = p2 < 0 ? l2 : Indices[p2];
510 const int kk2 = p3 < 0 ? l2 : Indices[p3];
512 const int neighDof2 = FE_TYPE::dofIndex( ii2, jj2, kk2 );
518 real64 const val1 = (alpha/((LvArray::math::min( characteristicSize[k], characteristicSize[elemNeigh] ))))*val*p_n[k][c2];
519 real64 const val2 = (alpha/((LvArray::math::min( characteristicSize[k], characteristicSize[elemNeigh] ))))*val*p_n[elemNeigh][neighDof2];
521 flowx[c1] += -val1+val2;
526 [&] (
const int c1,
const int c2,
const int f1,
const int fNeigh,
const int i1,
const int j1,
const int k1,
const int i2,
const int j2,
const int k2,
533 const int elemNeigh = elemsToOpposite( k, f1 );
538 const int perm = elemsToOppositePermutation( k, f1 );
540 const int p1 = perm%4-1;
541 const int p2 = (perm/4)%4-1;
542 const int p3 = (perm/16)%4-1;
543 const int p4 = (perm/64)%4-1;
548 const int Indices[3] = {i2, j2, k2};
550 const int l2 = order-i2-j2-k2;
552 const int ii2 = p1 < 0 ? l2 : Indices[p1];
553 const int jj2 = p2 < 0 ? l2 : Indices[p2];
554 const int kk2 = p3 < 0 ? l2 : Indices[p3];
556 const int neighDof2 = FE_TYPE::dofIndex( ii2, jj2, kk2 );
558 const int IndicesTranspose[3] = {i1, j1, k1};
560 const int l1 = order-i1-j1-k1;
562 const int ii1 = p1 < 0 ? l1 : IndicesTranspose[p1];
563 const int jj1 = p2 < 0 ? l1 : IndicesTranspose[p2];
564 const int kk1 = p3 < 0 ? l1 : IndicesTranspose[p3];
566 const int neighDof = FE_TYPE::dofIndex( ii1, jj1, kk1 );
592 int o1 = fNeigh < 0 ? f1 : fNeigh;
595 xLocalNeigh[x1][0] = xLocal[x1][0];
596 xLocalNeigh[x1][1] = xLocal[x1][1];
597 xLocalNeigh[x1][2] = xLocal[x1][2];
598 xLocalNeigh[x2][0] = xLocal[x2][0];
599 xLocalNeigh[x2][1] = xLocal[x2][1];
600 xLocalNeigh[x2][2] = xLocal[x2][2];
601 xLocalNeigh[x3][0] = xLocal[x3][0];
602 xLocalNeigh[x3][1] = xLocal[x3][1];
603 xLocalNeigh[x3][2] = xLocal[x3][2];
611 if( IndexPerm[i] ==-1 )
613 xLocalNeigh[f1][0] = X[ elemsToNodes( elemNeigh, i )][0];
614 xLocalNeigh[f1][1] = X[ elemsToNodes( elemNeigh, i )][1];
615 xLocalNeigh[f1][2] = X[ elemsToNodes( elemNeigh, i )][2];
621 real64 corrLocal = FE_TYPE::computeFluxDerivativeFactor( xLocal, x1, x2, o1, o2 );
622 real64 corrNeigh = FE_TYPE::computeFluxDerivativeFactor( xLocalNeigh, x1, x2, o1, o2 );
624 real64 const val1 = 0.5*val*p_n[k][c2]*corrLocal;
625 real64 const val2 = 0.5*val*p_n[elemNeigh][neighDof2]*corrLocal;
627 real64 const val3 = 0.5*val*p_n[k][c1]*corrLocal;
628 real64 const val4 = 0.5*val*p_n[elemNeigh][neighDof]*corrNeigh;
630 flowx[c1] += val1-val2;
631 flowx[c2] += val3-val4;
637 for(
localIndex i = 0; i < numNodesPerElem; i++ )
639 pTemp[i] += dt2*flowx[i];
643 for(
localIndex isrc = 0; isrc < sourceConstants.size( 0 ); ++isrc )
645 if( sourceIsAccessible[isrc] == 1 )
647 if( sourceElem[isrc]==k && sourceRegion[isrc] == regionIndex )
650 real64 const srcValue = useSourceWaveletTables ? sourceWaveletTableWrappers[ isrc ].compute( &time_n ) : rickerValue;
651 for(
localIndex i = 0; i < numNodesPerElem; ++i )
653 pTemp[i]+= dt2*(sourceConstants[isrc][i]*srcValue);
660 for(
localIndex i = 0; i < numNodesPerElem; ++i )
663 for(
localIndex j = 0; j < numNodesPerElem; ++j )
665 fx+= referenceInvMassMatrix( i, j )*pTemp[j];
667 p_np1[k][i]=(C2*density[k]*fx)/det;
#define GEOS_HOST_DEVICE
Marks a host-device function.
#define GEOS_ERROR_IF(EXP, msg)
Conditionally raise a hard error and terminate the program.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
float real32
32-bit floating point type.
LvArray::ArrayOfArraysView< T, INDEX_TYPE const, CONST_SIZES, LvArray::ChaiBuffer > ArrayOfArraysView
View of array of variable-sized arrays. See LvArray::ArrayOfArraysView for details.
double real64
64-bit floating point type.
GEOS_LOCALINDEX_TYPE localIndex
Local index type (for indexing objects within an MPI partition).
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
int integer
Signed integer type.
static void launch(localIndex const size, arrayView2d< localIndex const, cells::NODE_MAP_USD > const &elemsToNodes, arrayView2d< localIndex const > const &elemsToFaces, arrayView2d< localIndex const > const &facesToElems, ArrayOfArraysView< localIndex const > const &facesToNodes, arrayView1d< localIndex const > const &freeSurfaceFaceIndicator, arrayView2d< localIndex > const &elemsToOpposite, arrayView2d< integer > const &elemsToOppositePermutation)
Launches the precomputation of the element neighborhood information needed by DG.
static void launch(localIndex const size, arrayView2d< real32 const, nodes::REFERENCE_POSITION_USD > const nodeCoords, arrayView2d< localIndex const, cells::NODE_MAP_USD > const &elemsToNodes, arrayView1d< real32 > const &characteristicSize)
Launches the precomputation of the geometry term of the penalty coefficient.
static void launch(localIndex const size, localIndex const regionIndex, ArrayOfArraysView< localIndex const > const baseFacesToNodes, arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const baseNodeCoords, arrayView1d< globalIndex const > const baseNodeLocalToGlobal, arrayView1d< globalIndex const > const elementLocalToGlobal, ArrayOfArraysView< localIndex const > const baseNodesToElements, arrayView2d< localIndex const, cells::NODE_MAP_USD > const &baseElemsToNodes, arrayView1d< integer const > const elemGhostRank, arrayView2d< localIndex const > const elemsToFaces, arrayView2d< real64 const > const &elemCenter, arrayView2d< real64 const > const sourceCoordinates, arrayView1d< localIndex > const sourceIsAccessible, arrayView1d< localIndex > const sourceElem, arrayView2d< real64 > const sourceConstants, arrayView1d< localIndex > const sourceRegion, arrayView2d< real64 const > const receiverCoordinates, arrayView1d< localIndex > const receiverIsLocal, arrayView1d< localIndex > const receiverElem, arrayView2d< real64 > const receiverConstants, arrayView1d< localIndex > const receiverRegion)
Launches the precomputation of the source and receiver terms.
static void pressureComputation(localIndex const size, localIndex const regionIndex, arrayView2d< WaveSolverBase::wsCoordType const, nodes::REFERENCE_POSITION_USD > const X, arrayView2d< localIndex const, cells::NODE_MAP_USD > const &elemsToNodes, arrayView1d< real32 const > const velocity, arrayView1d< real32 const > const density, arrayView2d< real32 > const p_n, arrayView2d< real32 const > const p_nm1, arrayView2d< localIndex > const &elemsToOpposite, arrayView2d< integer > const &elemsToOppositePermutation, arrayView2d< real64 >referenceInvMassMatrix, arrayView1d< real32 const > const characteristicSize, arrayView2d< real64 const > const sourceConstants, arrayView1d< localIndex const > const sourceIsAccessible, arrayView1d< localIndex const > const sourceElem, arrayView1d< localIndex const > const sourceRegion, real64 const dt, real64 const time_n, real32 const timeSourceFrequency, real32 const timeSourceDelay, localIndex const rickerOrder, bool const useSourceWaveletTables, arrayView1d< TableFunction::KernelWrapper const > const sourceWaveletTableWrappers, arrayView2d< real32 > const p_np1)
Launches the computation of the pressure for one iteration.
static GEOS_HOST_DEVICE REAL computeReferenceLengthForPenalty(arraySlice1d< localIndex const, cells::NODE_MAP_USD - 1 > const elemsToNodes, arrayView2d< REAL const, nodes::REFERENCE_POSITION_USD > const nodeCoords)
Compute the reference size used for the tetrahederal DG penalty coefficient. This implementation uses...