20 #ifndef GEOS_FINITEELEMENT_ELEMENTFORMULATIONS_BBTETRAHEDRON_HPP_
21 #define GEOS_FINITEELEMENT_ELEMENTFORMULATIONS_BBTETRAHEDRON_HPP_
36 constexpr
int BB_Tetrahedron_NumNodes = ( ORDER + 1 ) * ( ORDER + 2 ) * ( ORDER + 3 ) / 6;
53 BB_Tetrahedron_NumNodes< ORDER > >
59 BB_Tetrahedron_NumNodes< ORDER > >;
65 template<
typename SubregionType >
78 static constexpr
int order = ORDER;
143 for(
int i = 0; i < 3; i++ )
145 for(
int j = 0; j < 3; j++ )
147 m[ i ][ j ] = X[ i + 1 ][ j ] - X[ 0 ][ j ];
150 return LvArray::math::abs( LvArray::tensorOps::determinant< 3 >( m ) );
164 int i1 = ( face + 1 ) % 4;
165 int i2 = ( face + 2 ) % 4;
166 int i3 = ( face + 3 ) % 4;
168 real64 ab[3] = { X[ i2 ][ 0 ] - X[ i1 ][ 0 ],
169 X[ i2 ][ 1 ] - X[ i1 ][ 1 ],
170 X[ i2 ][ 2 ] - X[ i1 ][ 2 ] };
171 real64 ac[3] = { X[ i3 ][ 0 ] - X[ i1 ][ 0 ],
172 X[ i3 ][ 1 ] - X[ i1 ][ 1 ],
173 X[ i3 ][ 2 ] - X[ i1 ][ 2 ] };
174 real64 term1 = ab[1] * ac[2] - ab[2] * ac[1];
175 real64 term2 = ab[2] * ac[0] - ab[0] * ac[2];
176 real64 term3 = ab[0] * ac[1] - ab[1] * ac[0];
177 return LvArray::math::sqrt( ( term1 * term1 + term2 * term2 + term3 * term3 ) );
196 GEOS_ERROR(
"Bernstein-Bézier basis is modal, not nodal. No quadrature points are defined." );
214 return calcN( q, N );
229 int limits[ 4 ] = { 1, 1, 1, 1 };
230 for(
int np = 1; np <= ORDER; np++ )
232 prev = np * ( np + 1 ) * ( np + 2 ) / 6 - 1;
233 c = ( np + 1 ) * ( np + 2 ) * ( np + 3 ) / 6 - 1;
234 for(
int i = 0; i < 4; i++ )
236 int denominator = i == 0 ? np : 1;
240 int repetitionCount = i == 0 ? 1 : limits[ i - 1 ];
241 for(
int j = 0; j < limits[ i ]; j++ )
243 if( j - offset >= repetitionCount )
246 offset += repetitionCount;
247 repetitionCount = repetitionCount * c1 / c2;
251 N[ c-- ] = N[ prev - j ] * lambda[ 3 - i ] * ( np + 3 ) / denominator;
254 for(
int i = 1; i < 4; i++ )
256 limits[ i ] += limits[ i - 1 ];
272 real64 const (&coords)[3],
277 for(
int i = 0; i < 3; i++ )
279 for(
int j = 0; j < 3; j++ )
281 m[ i ][ j ] = X[ i + 1 ][ j ] - X[ 0 ][ j ];
284 real64 den = LvArray::math::abs( LvArray::tensorOps::determinant< 3 >( m ) );
285 for(
int i = 0; i < 3; i++ )
287 for(
int j = 0; j < 3; j++ )
289 m[ i ][ j ] = coords[ j ] - X[ 0 ][ j ];
291 lambda[ i + 1 ] = LvArray::math::abs( LvArray::tensorOps::determinant< 3 >( m ) ) / den;
292 for(
int j = 0; j < 3; j++ )
294 m[ i ][ j ] = X[ i + 1 ][ j ] - X[ 0 ][ j ];
297 lambda[ 0 ] = 1.0 - lambda[ 1 ] - lambda[ 2 ] - lambda[ 3 ];
298 return calcN( lambda, N );
314 gradN[ 0 ][ 0 ] = 0.0;
315 gradN[ 0 ][ 1 ] = 0.0;
316 gradN[ 0 ][ 2 ] = 0.0;
317 gradN[ 0 ][ 3 ] = 0.0;
321 int limits[ 4 ] = { 1, 1, 1, 1 };
322 for(
int np = 1; np <= ORDER; np++ )
324 prev = np * ( np + 1 ) * ( np + 2 ) / 6 - 1;
325 c = ( np + 1 ) * ( np + 2 ) * ( np + 3 ) / 6 - 1;
326 for(
int i = 0; i < 4; i++ )
328 int denominator = i == 0 ? np : 1;
332 int repetitionCount = i == 0 ? 1 : limits[ i - 1 ];
333 for(
int j = 0; j < limits[ i ]; j++ )
335 if( j - offset >= repetitionCount )
338 offset += repetitionCount;
339 repetitionCount = repetitionCount * c1 / c2;
343 gradN[ c ][ 0 ] = gradN[ prev - j ][ 0 ] * lambda[ 3 - i ] * ( np + 3 ) / denominator;
344 gradN[ c ][ 1 ] = gradN[ prev - j ][ 1 ] * lambda[ 3 - i ] * ( np + 3 ) / denominator;
345 gradN[ c ][ 2 ] = gradN[ prev - j ][ 2 ] * lambda[ 3 - i ] * ( np + 3 ) / denominator;
346 gradN[ c ][ 3 ] = gradN[ prev - j ][ 3 ] * lambda[ 3 - i ] * ( np + 3 ) / denominator;
347 gradN[ c ][ 3 - i ] += N[ prev - j ] * ( np + 3 ) / denominator;
348 N[ c-- ] = N[ prev - j ] * lambda[ 3 - i ] * ( np + 3 ) / denominator;
351 for(
int i = 1; i < 4; i++ )
353 limits[ i ] += limits[ i - 1 ];
370 real64 const (&coords)[3],
377 for(
int i = 0; i < 3; i++ )
379 for(
int j = 0; j < 3; j++ )
381 m[ i ][ j ] = X[ i + 1 ][ j ] - X[ 0 ][ j ];
384 real64 den = LvArray::math::abs( LvArray::tensorOps::determinant< 3 >( m ) );
385 for(
int i = 0; i < 3; i++ )
387 for(
int j = 0; j < 3; j++ )
389 m[ i ][ j ] = coords[ j ] - X[ 0 ][ j ];
391 lambda[ i + 1 ] = LvArray::math::abs( LvArray::tensorOps::determinant< 3 >( m ) ) / den;
392 for(
int j = 0; j < 3; j++ )
394 m[ i ][ j ] = X[ i + 1 ][ j ] - X[ 0 ][ j ];
397 lambda[ 0 ] = 1.0 - lambda[ 1 ] - lambda[ 2 ] - lambda[ 3 ];
401 for(
int j = 0; j < 3; j++ )
404 ( ( ( X[ 2 ][ (j+1)%3 ] - X[ 0 ][ (j+1)%3 ]) * ( X[ 3 ][ (j+2)%3 ] - X[ 0 ][ (j+2)%3 ] ) - ( X[ 3 ][ (j+1)%3 ] - X[ 0 ][ (j+1)%3 ]) * ( X[ 2 ][ (j+2)%3 ] - X[ 0 ][ (j+2)%3 ] ) )*
405 ( dNdLambda[ i ][ 1 ] - dNdLambda[ i ][ 0 ] ) +
406 ( ( X[ 3 ][ (j+1)%3 ] - X[ 0 ][ (j+1)%3 ]) * ( X[ 1 ][ (j+2)%3 ] - X[ 0 ][ (j+2)%3 ] ) - ( X[ 1 ][ (j+1)%3 ] - X[ 0 ][ (j+1)%3 ]) *
407 ( X[ 3 ][ (j+2)%3 ] - X[ 0 ][ (j+2)%3 ] ) )* ( dNdLambda[ i ][ 2 ] - dNdLambda[ i ][ 0 ] ) +
408 ( ( X[ 1 ][ (j+1)%3 ] - X[ 0 ][ (j+1)%3 ]) * ( X[ 2 ][ (j+2)%3 ] - X[ 0 ][ (j+2)%3 ] ) - ( X[ 2 ][ (j+1)%3 ] - X[ 0 ][ (j+1)%3 ]) *
409 ( X[ 1 ][ (j+2)%3 ] - X[ 0 ][ (j+2)%3 ] ) )* ( dNdLambda[ i ][ 3 ] - dNdLambda[ i ][ 0 ] )) / den;
428 for(
int i = 0; i < 3; ++i )
430 for(
int j = 0; j < 3; ++j )
436 for(
int i = 0; i < 3; i++ )
438 for(
int j = 0; j < 3; j++ )
440 m[ i ][ j ] = X[ i + 1 ][ j ] - X[ 0 ][ j ];
443 real64 const detJ = LvArray::math::abs( LvArray::tensorOps::determinant< 3 >( m ) );
481 gradN[ q ][ 0 ] = 0.0;
482 gradN[ q ][ 1 ] = 0.0;
483 gradN[ q ][ 2 ] = 0.0;
485 GEOS_ERROR(
"Bernstein-Bézier basis is modal, not nodal. No quadrature points are defined." );
523 for(
int i = b; i > 0; i-- )
525 res *= ( (
real64) num ) / i;
528 for(
int i = num; i > 0; i-- )
530 res *= ( (
real64) i ) / den;
533 for(
int i = den; i > 0; i-- )
557 static constexpr
real64 correctionFactorDerivative(
int const i1,
int const j1,
int const k1,
int const l1,
int const i2,
int const j2,
int const k2,
int const l2,
int const dim )
559 return (i1+j1+k1+l1+dim)* (i2==0 ? 1 : i2) * (j2==0 ? 1 : j2)* (k2==0 ? 1 : k2)* (l2==0 ? 1 : l2);
579 const int i2,
const int j2,
const int k2,
const int l2 )
586 i1+j1+k1+l1+3, i2+j2+k2+l2+3 );
603 const int i2,
const int j2,
const int k2 )
605 return ((i1+k1+j1+3)*(i2+j2+k2+3)*
610 i1+j1+k1+2, i2+j2+k2+2 );
621 template<
int I,
int J,
int K >
629 return ( ORDER - I ) * ( ORDER - I + 1 ) * ( ORDER - I + 2) / 6 +
630 ( ORDER - I - J ) * ( ORDER - I - J + 1 ) / 2 +
631 ( ORDER - I - J - K );
650 return ( ORDER - i ) * ( ORDER - i + 1 ) * ( ORDER - i + 2) / 6 +
651 ( ORDER - i - j ) * ( ORDER - i - j + 1 ) / 2 +
652 ( ORDER - i - j - k );
663 template<
int C,
int VTX >
671 static_assert( VTX >= 0 && VTX < 4 );
673 constexpr
int cc1 = C + 1;
674 constexpr
real64 tetr = cbrt( 3.0 * cc1 + sqrt( 9.0 * cc1 * cc1 - 1.0 / 27.0 ) )
675 + cbrt( 3.0 * cc1 - sqrt( 9.0 * cc1 * cc1 - 1.0 / 27.0 ) ) - 2;
676 constexpr
int i = ORDER - round( tetr * 10.0 ) / 10;
677 constexpr
int cc2 = C - ( ORDER - i ) * ( ORDER - i + 1 ) * ( ORDER - i + 2 ) / 6 + 1;
678 constexpr
real64 trir = ( sqrt( 8.0 * cc2 + 1.0 ) - 1.0 ) / 2.0 - 1;
679 constexpr
int j = ORDER - i - round( trir * 10.0 ) / 10;
680 constexpr
int k = ORDER - i - j - ( C - (ORDER - i ) * ( ORDER - i + 1 ) * ( ORDER - i + 2 ) / 6
681 - ( ORDER - i - j ) * ( ORDER - i - j + 1 ) / 2 );
682 if constexpr ( VTX == 0 )
686 else if constexpr ( VTX == 1)
690 else if constexpr ( VTX == 2)
694 else if constexpr ( VTX == 3)
696 return ORDER - i - j - k;
708 template<
typename FUNC,
int... Is >
711 static constexpr
void loop_impl( FUNC && func, std::integer_sequence< int, Is... > )
713 ( func( std::integral_constant< int, Is >{} ), ... );
723 template<
int N,
typename FUNC >
725 static constexpr
void loop( FUNC
const & func )
729 loop< N - 1 >( func );
730 func( std::integral_constant< int, N - 1 >{} );
740 template<
typename FUNC >
745 loop_impl( std::forward< FUNC >( func ), std::make_integer_sequence< int, 4 >{} );
753 template<
typename FUNC >
758 loop< ORDER + 1 >( [&func] (
auto const iic )
760 constexpr
int i = decltype(iic)::value;
761 constexpr
int i1 = ORDER - i;
762 loop< ORDER + 1 >( [&func] (
auto const jjc )
764 constexpr
int j = decltype(jjc)::value;
765 constexpr
int j1 = ORDER - j;
766 if constexpr ( j1 <= ORDER - i1 )
768 loop< ORDER + 1 >( [&func] (
auto const kkc )
770 constexpr
int k = decltype(kkc)::value;
771 constexpr
int k1 = ORDER - k;
772 if constexpr ( k1 <= (ORDER - i1 - j1) )
774 constexpr
int l1 = ORDER - i1 - j1 - k1;
775 constexpr
int c1 = dofIndex< i1, j1, k1 >();
776 func( std::integral_constant< int, c1 >{},
777 std::integral_constant< int, i1 >{},
778 std::integral_constant< int, j1 >{},
779 std::integral_constant< int, k1 >{},
780 std::integral_constant< int, l1 >{} );
801 template<
int c1,
int i1,
int j1,
int k1,
int l1,
typename F,
int... Is >
806 auto check_i1 = [&](
auto I ) {
807 if constexpr (i1 == decltype(I)::value) {
808 func( std::integral_constant< int, 0 >{},
809 std::integral_constant< int, i1 >{},
810 std::integral_constant< int, c1 >{},
811 std::integral_constant< int, j1 >{},
812 std::integral_constant< int, k1 >{},
813 std::integral_constant< int, l1 >{} );
816 (check_i1( std::integral_constant< int, Is >{} ), ...);
818 auto check_j1 = [&](
auto I ) {
819 if constexpr (j1 == decltype(I)::value) {
820 func( std::integral_constant< int, 1 >{},
821 std::integral_constant< int, j1 >{},
822 std::integral_constant< int, c1 >{},
823 std::integral_constant< int, i1 >{},
824 std::integral_constant< int, k1 >{},
825 std::integral_constant< int, l1 >{} );
828 (check_j1( std::integral_constant< int, Is >{} ), ...);
830 auto check_k1 = [&](
auto I ) {
831 if constexpr (k1 == decltype(I)::value) {
832 func( std::integral_constant< int, 2 >{},
833 std::integral_constant< int, k1 >{},
834 std::integral_constant< int, c1 >{},
835 std::integral_constant< int, i1 >{},
836 std::integral_constant< int, j1 >{},
837 std::integral_constant< int, l1 >{} );
840 (check_k1( std::integral_constant< int, Is >{} ), ...);
842 auto check_l1 = [&](
auto I ) {
843 if constexpr (l1 == decltype(I)::value) {
844 func( std::integral_constant< int, 3 >{},
845 std::integral_constant< int, l1 >{},
846 std::integral_constant< int, c1 >{},
847 std::integral_constant< int, i1 >{},
848 std::integral_constant< int, j1 >{},
849 std::integral_constant< int, k1 >{} );
852 (check_l1( std::integral_constant< int, Is >{} ), ...);
863 template<
int... Is,
typename FUNC >
867 loop< ORDER + 1 >( [&](
auto const i ) {
868 using i_t = decltype(i);
869 constexpr
int iVal = i_t::value;
870 constexpr
int i1 = ORDER - iVal;
872 loop< ORDER + 1 >( [&](
auto const j ) {
873 using j_t = decltype(j);
874 constexpr
int jVal = j_t::value;
875 constexpr
int j1 = ORDER - jVal;
877 constexpr
bool valid_j1_i1 = (j1 <= iVal);
878 if constexpr (valid_j1_i1) {
880 loop< ORDER + 1 >( [&](
auto const k ) {
881 using k_t = decltype(k);
882 constexpr
int kVal = k_t::value;
883 constexpr
int k1 = ORDER - kVal;
885 constexpr
bool valid_k1 = (k1 <= (ORDER - i1 - j1));
886 if constexpr (valid_k1) {
887 constexpr
int l1 = ORDER - i1 - j1 - k1;
888 constexpr
int c1 = dofIndex< i1, j1, k1 >();
890 call_matching_cases< c1, i1, j1, k1, l1 >( func, std::integer_sequence< int, Is... >{} );
1032 template<
typename FUNC >
1037 loop< 3 >( std::forward< FUNC >( func ) );
1053 basisLoop( [ &m ] (
auto const cc1,
auto const ii1,
auto const jj1,
auto const kk1,
auto const ll1 )
1055 constexpr
int c1 = decltype(cc1)::value;
1056 constexpr
int i1 = decltype(ii1)::value;
1057 constexpr
int j1 = decltype(jj1)::value;
1058 constexpr
int k1 = decltype(kk1)::value;
1059 constexpr
int l1 = decltype(ll1)::value;
1062 basisLoop( [ &m ] (
auto const cc2,
auto const ii2,
auto const jj2,
auto const kk2,
auto const ll2 )
1064 constexpr
int c2 = decltype(cc2)::value;
1065 constexpr
int i2 = decltype(ii2)::value;
1066 constexpr
int j2 = decltype(jj2)::value;
1067 constexpr
int k2 = decltype(kk2)::value;
1068 constexpr
int l2 = decltype(ll2)::value;
1070 m[ c1 ][ c2 ] = val;
1086 template<
typename DAMPING >
1094 for(
int c1 = 0; c1 <
numNodes; c1++ )
1096 for(
int c2 = 0; c2 <
numNodes; c2++ )
1101 conditionalBasisLoop< 0 >( [&] (
auto const f1,
auto const,
auto const c1,
auto const i1,
auto const j1,
auto const k1 )
1103 conditionalBasisLoop< 0 >( [&] (
auto const f2,
auto const,
auto const c2,
auto const i2,
auto const j2,
auto const k2 )
1105 if constexpr ( f1 == f2 )
1108 if( ( f1 == 0 && face1Damped ) ||
1109 ( f1 == 1 && face2Damped ) ||
1110 ( f1 == 2 && face3Damped ) ||
1111 ( f1 == 3 && face4Damped ) )
1113 d[ c1 ][ c2 ] += val;
1126 template<
typename FUNC >
1136 basisLoop( [&func, &detJ] (
auto cc1,
auto ii1,
auto jj1,
auto kk1,
auto ll1 )
1138 constexpr
int c1 = decltype(cc1)::value;
1139 constexpr
int i1 = decltype(ii1)::value;
1140 constexpr
int j1 = decltype(jj1)::value;
1141 constexpr
int k1 = decltype(kk1)::value;
1142 constexpr
int l1 = decltype(ll1)::value;
1145 basisLoop( [&func, &detJ, i1, j1, k1, l1] (
auto c2,
auto ii2,
auto jj2,
auto kk2,
auto ll2 )
1147 constexpr
int c2v = decltype(c2)::value;
1148 constexpr
int i2 = decltype(ii2)::value;
1149 constexpr
int j2 = decltype(jj2)::value;
1150 constexpr
int k2 = decltype(kk2)::value;
1151 constexpr
int l2 = decltype(ll2)::value;
1154 func( c1, c2v, val * detJ );
1195 real64 h2 = (el2[1][0]+el2[1][1])-(el2[2][0]+el2[2][1]);
1197 h2 = (4.0 * el2[0][0]*el2[0][1] - h2 * h2)/16.0;
1199 scal = (4.0*h2-detJf1 * detJf1 - detJf2 * detJf2 ) / (2.0 * detJf1 * detJf2);
1203 return scal * detJf1 / detJ;
1213 template<
typename FUNC >
1223 real64 dLambdadX[4][3] = {};
1224 for(
int j = 0; j < 3; j++ )
1227 ( ( X[ 2 ][ (j+1)%3 ] - X[ 0 ][ (j+1)%3 ]) * ( X[ 3 ][ (j+2)%3 ] - X[ 0 ][ (j+2)%3 ] ) - ( X[ 3 ][ (j+1)%3 ] - X[ 0 ][ (j+1)%3 ]) * ( X[ 2 ][ (j+2)%3 ] - X[ 0 ][ (j+2)%3 ] ) ) / detJ;
1229 ( ( X[ 3 ][ (j+1)%3 ] - X[ 0 ][ (j+1)%3 ]) * ( X[ 1 ][ (j+2)%3 ] - X[ 0 ][ (j+2)%3 ] ) - ( X[ 1 ][ (j+1)%3 ] - X[ 0 ][ (j+1)%3 ]) * ( X[ 3 ][ (j+2)%3 ] - X[ 0 ][ (j+2)%3 ] ) ) / detJ;
1231 ( ( X[ 1 ][ (j+1)%3 ] - X[ 0 ][ (j+1)%3 ]) * ( X[ 2 ][ (j+2)%3 ] - X[ 0 ][ (j+2)%3 ] ) - ( X[ 2 ][ (j+1)%3 ] - X[ 0 ][ (j+1)%3 ]) * ( X[ 1 ][ (j+2)%3 ] - X[ 0 ][ (j+2)%3 ] ) ) / detJ;
1232 dLambdadX[0][j] = -dLambdadX[1][j] - dLambdadX[2][j] - dLambdadX[3][j];
1234 basisLoop( [&func, &dLambdadX, &detJ] (
auto const cc1,
auto const ci1,
auto const cj1,
auto const ck1,
auto const cl1 )
1237 constexpr
int c1 = decltype(cc1)::value;
1238 constexpr
int i1 = decltype(ci1)::value;
1239 constexpr
int j1 = decltype(cj1)::value;
1240 constexpr
int k1 = decltype(ck1)::value;
1241 constexpr
int l1 = decltype(cl1)::value;
1244 basisLoop( [&func, &dLambdadX, &detJ] (
auto const cc2,
auto const ci2,
auto const cj2,
auto const ck2,
auto const cl2 )
1246 constexpr
int c2 = decltype(cc2)::value;
1247 constexpr
int i2 = decltype(ci2)::value;
1248 constexpr
int j2 = decltype(cj2)::value;
1249 constexpr
int k2 = decltype(ck2)::value;
1250 constexpr
int l2 = decltype(cl2)::value;
1255 constexpr
int d1 = decltype(cd1)::value;
1258 constexpr
int d2 = decltype(cd2)::value;
1259 constexpr
int ii1 = i1 + ( d1 == 0 ) * ( -1 );
1260 constexpr
int ij1 = j1 + ( d1 == 1 ) * ( -1 );
1261 constexpr
int ik1 = k1 + ( d1 == 2 ) * ( -1 );
1262 constexpr
int il1 = l1 + ( d1 == 3 ) * ( -1 );
1263 constexpr
int ii2 = i2 + ( d2 == 0 ) * ( -1 );
1264 constexpr
int ij2 = j2 + ( d2 == 1 ) * ( -1 );
1265 constexpr
int ik2 = k2 + ( d2 == 2 ) * ( -1 );
1266 constexpr
int il2 = l2 + ( d2 == 3 ) * ( -1 );
1269 if constexpr (ii1 >= 0 && ij1 >= 0 && ik1 >= 0 && il1 >= 0 &&
1270 ii2 >= 0 && ij2 >= 0 && ik2 >= 0 && il2 >= 0)
1273 func( c1, c2, val * detJ * ( dLambdadX[d1][0]*dLambdadX[d2][0] + dLambdadX[d1][1]*dLambdadX[d2][1] + dLambdadX[d1][2]*dLambdadX[d2][2] ) );
1293 real64 const (&X)[4][3] )
1295 real64 ab[3] = { X[ i2 ][ 0 ] - X[ i1 ][ 0 ],
1296 X[ i2 ][ 1 ] - X[ i1 ][ 1 ],
1297 X[ i2 ][ 2 ] - X[ i1 ][ 2 ] };
1298 return ab[0] * ab[0] + ab[1] * ab[1]+ ab[2]*ab[2];
1315 template<
typename FUNCP,
typename FUNCF >
1327 conditionalBasisLoop< 0, 1 >( [&] (
auto const cf1,
auto const cd,
auto const cc1,
auto const ci1,
auto const cj1,
auto const ck1 )
1329 conditionalBasisLoop< 0 >( [&] (
auto const cf2,
auto const,
auto const cc2,
auto const ci2,
auto const cj2,
auto const ck2 )
1331 constexpr
int c1 = decltype(cc1)::value;
1332 constexpr
int i1 = decltype(ci1)::value;
1333 constexpr
int j1 = decltype(cj1)::value;
1334 constexpr
int k1 = decltype(ck1)::value;
1337 constexpr
int f2 = decltype(cf2)::value;
1338 constexpr
int c2 = decltype(cc2)::value;
1339 constexpr
int i2 = decltype(ci2)::value;
1340 constexpr
int j2 = decltype(cj2)::value;
1341 constexpr
int k2 = decltype(ck2)::value;
1346 if constexpr ( std::decay_t< decltype(cf1) >::value == std::decay_t< decltype(cf2) >::value)
1349 if constexpr ( std::decay_t< decltype(cd) >::value == 0 )
1352 funcP( c1, c2, f2, i1, j1, k1, i2, j2, k2, val * detJf[ f2 ] );
1357 if constexpr ( std::decay_t< decltype(cd) >::value == 1 )
1359 constexpr
real64 derFactor = ( i1 + j1 + k1 + 4 );
1361 funcF( c1, c2, f2, -1, i1, j1, k1, i2, j2, k2, val * detJf[ f2 ] );
1365 else if constexpr ( std::decay_t< decltype(cd) >::value == 0 )
1369 constexpr
int l = decltype(cl)::value;
1370 constexpr
int ii1 = i1 + ( l == 0 ) * ( -1 );
1371 constexpr
int ij1 = j1 + ( l == 1 ) * ( -1 );
1372 constexpr
int ik1 = k1 + ( l == 2 ) * ( -1 );
1373 if constexpr (ii1 >= 0 && ij1 >= 0 && ik1 >= 0)
1375 constexpr
real64 derFactor = ( ii1 + ij1 + ik1 + 4 );
1377 constexpr
int f = l >= f2 ? l + 1 : l;
1378 funcF( c1, c2, f2, f, i1, j1, k1, i2, j2, k2, val * detJf[f2] );
1390 template<
int ORDER >
1406 #pragma nv_diag_suppress 20012
1420 return static_cast< ImplType *
>(
this);
1429 return static_cast< ImplType const *
>(
this);
#define GEOS_HOST_DEVICE
Marks a host-device function.
#define GEOS_UNUSED_VAR(...)
Mark an unused variable and silence compiler warnings.
#define GEOS_FORCE_INLINE
Marks a function or lambda for inlining.
#define GEOS_ERROR(...)
Raise a hard error and terminate the program.
GEOS_HOST_DEVICE static constexpr GEOS_FORCE_INLINE real64 computeFluxDerivativeFactor(real64 const (&X)[4][3], int x1, int x2, int o1, int o2)
Function to compute the factor for the flux derivative term.
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE localIndex getMaxSupportPoints()
Get the maximum number of support points.
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE void calcNandGradN(real64 const (&lambda)[4], real64 const (&N)[numNodes], real64(&gradN)[numNodes][4])
Calculate the values and derivatives of shape functions with respect to barycentric coordinates at a ...
GEOS_HOST_DEVICE constexpr static GEOS_FORCE_INLINE real64 integralTerm(const int a, const int b, const int c)
Computes a! / ( b! * c! ) with b + c >= a >= b, c.
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE localIndex getNumQuadraturePoints(StackVariables const &stack)
Get the number of quadrature points.
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE real64 jacobianDeterminant(real64 const (&X)[4][3])
Returns the determinant of the Jacobian of the element.
GEOS_HOST_DEVICE static constexpr GEOS_FORCE_INLINE int indexToIJKL()
Computes the local degree of freedom index given the shape function indices for each vertex.
GEOS_HOST_DEVICE static constexpr GEOS_FORCE_INLINE void computeStiffnessTerm(real64 const (&X)[4][3], FUNC &&func)
Computes the non-zero contributions inside the element of the stiffness matrix R, i....
static constexpr int order
The order of the finite element.
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE void computeReferenceMassMatrix(arraySlice2d< real64 > const &m)
Computes the reference mass matrix, i.e., the superposition matrix of the shape functions in barycent...
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE void calcN(localIndex const, real64(&N)[numNodes])
Calculate shape functions values for each support point at a quadrature point.
typename Base::template MeshData< SubregionType > MeshData
Mesh data structure for the element.
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE void calcN(localIndex const q, StackVariables const &stack, real64(&N)[numNodes])
Calculate shape functions values for each support point at a quadrature point.
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE real64 edgeLength2(localIndex i1, localIndex i2, real64 const (&X)[4][3])
GEOS_HOST_DEVICE static constexpr GEOS_FORCE_INLINE void computeSurfaceTerms(real64 const (&X)[4][3], FUNCP &&funcP, FUNCF &&funcF)
Computes the non-zero contributions inside the element of the surface terms, including the value of t...
static constexpr GEOS_HOST_DEVICE void conditionalBasisLoop(FUNC const &func)
Helper function for loop over tet basis functions that have one index in a given set of indices....
static constexpr GEOS_HOST_DEVICE void loop(FUNC const &func)
Helper function for static for loop.
GEOS_HOST_DEVICE static constexpr GEOS_FORCE_INLINE void computeMassTerm(real64 const (&X)[4][3], FUNC &&func)
Computes the non-zero contributions inside the element of the mass matrix M, i.e.,...
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE real64 calcGradN(localIndex const q, real64 const (&X)[numNodes][3], StackVariables const &stack, real64(&gradN)[numNodes][3])
Calculate the shape functions derivatives wrt the physical coordinates.
GEOS_HOST_DEVICE static constexpr GEOS_FORCE_INLINE void basisLoop(FUNC &&func)
Helper function for loop over tet basis functions.
static GEOS_HOST_DEVICE localIndex getNumQuadraturePoints()
Get the number of quadrature points.
static constexpr GEOS_HOST_DEVICE void call_matching_cases(F &&func, std::integer_sequence< int, Is... >)
Helper function for loop over tet basis functions that have one index in a given set of indices....
GEOS_HOST_DEVICE static constexpr GEOS_FORCE_INLINE void barycentricCoordinateLoop(FUNC &&func)
Helper function for loop over barycentric coordinates.
GEOS_HOST_DEVICE constexpr static GEOS_FORCE_INLINE real64 computeFaceSuperpositionIntegral(const int i1, const int j1, const int k1, const int i2, const int j2, const int k2)
Computes the superposition integral over a face between Bernstein-Bézier functions whose indices are ...
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE localIndex getNumSupportPoints()
Get the number of support points.
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE void calcN(real64 const (&X)[4][3], real64 const (&coords)[3], real64(&N)[numNodes])
Calculate shape functions values at a single point, given the coordinates of the tetrahedron vertices...
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE void calcNandGradN(real64 const (&X)[4][3], real64 const (&coords)[3], real64(&N)[numNodes], real64(&gradN)[numNodes][4])
Calculate the shape functions values and derivatives at a single point, given the coorginates of the ...
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE real64 faceJacobianDeterminant(localIndex face, real64 const (&X)[4][3])
Calculate the determinant of the jacobian on the face opposite to the given vertex.
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE real64 calcJacobian(localIndex const q, real64 const (&X)[numNodes][3], StackVariables const &stack, real64(&J)[3][3])
Calculate the Jacobian matrix at a quadrature point.
GEOS_HOST_DEVICE static constexpr GEOS_FORCE_INLINE int dofIndex()
Computes the local degree of freedom index given the shape function indices (i, j,...
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE localIndex getNumSupportPoints(StackVariables const &stack)
Get the number of support points.
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE void calcN(real64 const (&lambda)[4], real64(&N)[numNodes])
Calculate shape functions values at a single point using De Casteljau's algorithm.
GEOS_HOST_DEVICE static constexpr GEOS_FORCE_INLINE void loop_impl(FUNC &&func, std::integer_sequence< int, Is... >)
Helper function for static for loop.
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE void computeReferenceDampingMatrix(real64(&d)[numNodes][numNodes], bool const face1Damped, bool const face2Damped, bool const face3Damped, bool const face4Damped)
Computes the reference damping matrix, i.e., the superposition matrix of the shape functions in baryc...
GEOS_HOST_DEVICE static constexpr GEOS_FORCE_INLINE void faceBarycentricCoordinateLoop(FUNC &&func)
Helper function for loop over barycentric coordinates of a face.
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE real64 calcJacobian(localIndex const q, real64 const (&X)[numNodes][3], real64(&J)[3][3])
Calculate the Jacobian matrix at a quadrature point.
GEOS_HOST_DEVICE static constexpr GEOS_FORCE_INLINE int dofIndex(const int i, const int j, const int k)
Computes the local degree of freedom index given the shape function indices (i, j,...
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE real64 calcGradN(localIndex const q, real64 const (&X)[numNodes][3], real64(&gradN)[numNodes][3])
Calculate the shape functions derivatives wrt the physical coordinates.
GEOS_HOST_DEVICE static constexpr GEOS_FORCE_INLINE real64 correctionFactorDerivative(int const i1, int const j1, int const k1, int const l1, int const i2, int const j2, int const k2, int const l2, int const dim)
Computes the correction factor for the superposition integral in case a function has been derived onc...
constexpr static localIndex numNodesPerFace
The number of shape functions per face.
GEOS_HOST_DEVICE static constexpr GEOS_FORCE_INLINE real64 computeSuperpositionIntegral(const int i1, const int j1, const int k1, const int l1, const int i2, const int j2, const int k2, const int l2)
Computes the superposition integral between Bernstein-Bézier functions indexed by (i1,...
ImplType * getImpl()
Get the device-compatible implementation type.
ImplType const * getImpl() const
Get the device-compatible implementation type.
Device-compatible (non virtual) Base class for all finite element formulations.
constexpr static localIndex numQuadraturePoints
The number of quadrature points per element.
constexpr static localIndex maxSupportPoints
The maximum number of support points per element.
constexpr static localIndex numNodes
The number of nodes per element.
Base class for FEM element implementations.
ArraySlice< T, 2, USD > arraySlice2d
Alias for 2D array slice.
double real64
64-bit floating point type.
GEOS_LOCALINDEX_TYPE localIndex
Local index type (for indexing objects within an MPI partition).
Kernel variables (dof numbers, jacobian and residual) located on the stack.