20 #ifndef GEOS_FINITEELEMENT_ELEMENTFORMULATIONS_BBTETRAHEDRON_HPP_
21 #define GEOS_FINITEELEMENT_ELEMENTFORMULATIONS_BBTETRAHEDRON_HPP_
50 static constexpr
int order = ORDER;
128 for(
int i = 0; i < 3; i++ )
130 for(
int j = 0; j < 3; j++ )
132 m[ i ][ j ] = X[ i + 1 ][ j ] - X[ 0 ][ j ];
135 return LvArray::math::abs( LvArray::tensorOps::determinant< 3 >( m ) );
149 int i1 = ( face + 1 ) % 4;
150 int i2 = ( face + 2 ) % 4;
151 int i3 = ( face + 3 ) % 4;
153 real64 ab[3] = { X[ i2 ][ 0 ] - X[ i1 ][ 0 ],
154 X[ i2 ][ 1 ] - X[ i1 ][ 1 ],
155 X[ i2 ][ 2 ] - X[ i1 ][ 2 ] };
156 real64 ac[3] = { X[ i3 ][ 0 ] - X[ i1 ][ 0 ],
157 X[ i3 ][ 1 ] - X[ i1 ][ 1 ],
158 X[ i3 ][ 2 ] - X[ i1 ][ 2 ] };
159 real64 term1 = ab[1] * ac[2] - ab[2] * ac[1];
160 real64 term2 = ab[2] * ac[0] - ab[0] * ac[2];
161 real64 term3 = ab[0] * ac[1] - ab[1] * ac[0];
162 return LvArray::math::sqrt( ( term1 * term1 + term2 * term2 + term3 * term3 ) );
181 GEOS_ERROR(
"Bernstein-Bézier basis is modal, not nodal. No quadrature points are defined." );
199 return calcN( q, N );
214 int limits[ 4 ] = { 1, 1, 1, 1 };
215 for(
int np = 1; np <= ORDER; np++ )
217 prev = np * ( np + 1 ) * ( np + 2 ) / 6 - 1;
218 c = ( np + 1 ) * ( np + 2 ) * ( np + 3 ) / 6 - 1;
219 for(
int i = 0; i < 4; i++ )
221 int denominator = i == 0 ? np : 1;
225 int repetitionCount = i == 0 ? 1 : limits[ i - 1 ];
226 for(
int j = 0; j < limits[ i ]; j++ )
228 if( j - offset >= repetitionCount )
231 offset += repetitionCount;
232 repetitionCount = repetitionCount * c1 / c2;
236 N[ c-- ] = N[ prev - j ] * lambda[ 3 - i ] * ( np + 3 ) / denominator;
239 for(
int i = 1; i < 4; i++ )
241 limits[ i ] += limits[ i - 1 ];
257 real64 const (&coords)[3],
262 for(
int i = 0; i < 3; i++ )
264 for(
int j = 0; j < 3; j++ )
266 m[ i ][ j ] = X[ i + 1 ][ j ] - X[ 0 ][ j ];
269 real64 den = LvArray::math::abs( LvArray::tensorOps::determinant< 3 >( m ) );
270 for(
int i = 0; i < 3; i++ )
272 for(
int j = 0; j < 3; j++ )
274 m[ i ][ j ] = coords[ j ] - X[ 0 ][ j ];
276 lambda[ i + 1 ] = LvArray::math::abs( LvArray::tensorOps::determinant< 3 >( m ) ) / den;
277 for(
int j = 0; j < 3; j++ )
279 m[ i ][ j ] = X[ i + 1 ][ j ] - X[ 0 ][ j ];
282 lambda[ 0 ] = 1.0 - lambda[ 1 ] - lambda[ 2 ] - lambda[ 3 ];
283 return calcN( lambda, N );
299 gradN[ 0 ][ 0 ] = 0.0;
300 gradN[ 0 ][ 1 ] = 0.0;
301 gradN[ 0 ][ 2 ] = 0.0;
302 gradN[ 0 ][ 3 ] = 0.0;
306 int limits[ 4 ] = { 1, 1, 1, 1 };
307 for(
int np = 1; np <= ORDER; np++ )
309 prev = np * ( np + 1 ) * ( np + 2 ) / 6 - 1;
310 c = ( np + 1 ) * ( np + 2 ) * ( np + 3 ) / 6 - 1;
311 for(
int i = 0; i < 4; i++ )
313 int denominator = i == 0 ? np : 1;
317 int repetitionCount = i == 0 ? 1 : limits[ i - 1 ];
318 for(
int j = 0; j < limits[ i ]; j++ )
320 if( j - offset >= repetitionCount )
323 offset += repetitionCount;
324 repetitionCount = repetitionCount * c1 / c2;
328 gradN[ c ][ 0 ] = gradN[ prev - j ][ 0 ] * lambda[ 3 - i ] * ( np + 3 ) / denominator;
329 gradN[ c ][ 1 ] = gradN[ prev - j ][ 1 ] * lambda[ 3 - i ] * ( np + 3 ) / denominator;
330 gradN[ c ][ 2 ] = gradN[ prev - j ][ 2 ] * lambda[ 3 - i ] * ( np + 3 ) / denominator;
331 gradN[ c ][ 3 ] = gradN[ prev - j ][ 3 ] * lambda[ 3 - i ] * ( np + 3 ) / denominator;
332 gradN[ c ][ 3 - i ] += N[ prev - j ] * ( np + 3 ) / denominator;
333 N[ c-- ] = N[ prev - j ] * lambda[ 3 - i ] * ( np + 3 ) / denominator;
336 for(
int i = 1; i < 4; i++ )
338 limits[ i ] += limits[ i - 1 ];
355 real64 const (&coords)[3],
362 for(
int i = 0; i < 3; i++ )
364 for(
int j = 0; j < 3; j++ )
366 m[ i ][ j ] = X[ i + 1 ][ j ] - X[ 0 ][ j ];
369 real64 den = LvArray::math::abs( LvArray::tensorOps::determinant< 3 >( m ) );
370 for(
int i = 0; i < 3; i++ )
372 for(
int j = 0; j < 3; j++ )
374 m[ i ][ j ] = coords[ j ] - X[ 0 ][ j ];
376 lambda[ i + 1 ] = LvArray::math::abs( LvArray::tensorOps::determinant< 3 >( m ) ) / den;
377 for(
int j = 0; j < 3; j++ )
379 m[ i ][ j ] = X[ i + 1 ][ j ] - X[ 0 ][ j ];
382 lambda[ 0 ] = 1.0 - lambda[ 1 ] - lambda[ 2 ] - lambda[ 3 ];
386 for(
int j = 0; j < 3; j++ )
389 ( ( ( 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 ] ) )*
390 ( dNdLambda[ i ][ 1 ] - dNdLambda[ i ][ 0 ] ) +
391 ( ( 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 ]) *
392 ( X[ 3 ][ (j+2)%3 ] - X[ 0 ][ (j+2)%3 ] ) )* ( dNdLambda[ i ][ 2 ] - dNdLambda[ i ][ 0 ] ) +
393 ( ( 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 ]) *
394 ( X[ 1 ][ (j+2)%3 ] - X[ 0 ][ (j+2)%3 ] ) )* ( dNdLambda[ i ][ 3 ] - dNdLambda[ i ][ 0 ] )) / den;
415 gradN[ q ][ 0 ] = 0.0;
416 gradN[ q ][ 1 ] = 0.0;
417 gradN[ q ][ 2 ] = 0.0;
419 GEOS_ERROR(
"Bernstein-Bézier basis is modal, not nodal. No quadrature points are defined." );
457 for(
int i = b; i > 0; i-- )
459 res *= ( (
real64) num ) / i;
462 for(
int i = num; i > 0; i-- )
464 res *= ( (
real64) i ) / den;
467 for(
int i = den; i > 0; i-- )
491 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 )
493 return (i1+j1+k1+l1+dim)* (i2==0 ? 1 : i2) * (j2==0 ? 1 : j2)* (k2==0 ? 1 : k2)* (l2==0 ? 1 : l2);
513 const int i2,
const int j2,
const int k2,
const int l2 )
520 i1+j1+k1+l1+3, i2+j2+k2+l2+3 );
537 const int i2,
const int j2,
const int k2 )
539 return ((i1+k1+j1+3)*(i2+j2+k2+3)*
544 i1+j1+k1+2, i2+j2+k2+2 );
555 template<
int I,
int J,
int K >
563 return ( ORDER - I ) * ( ORDER - I + 1 ) * ( ORDER - I + 2) / 6 +
564 ( ORDER - I - J ) * ( ORDER - I - J + 1 ) / 2 +
565 ( ORDER - I - J - K );
584 return ( ORDER - i ) * ( ORDER - i + 1 ) * ( ORDER - i + 2) / 6 +
585 ( ORDER - i - j ) * ( ORDER - i - j + 1 ) / 2 +
586 ( ORDER - i - j - k );
597 template<
int C,
int VTX >
605 static_assert( VTX >= 0 && VTX < 4 );
607 constexpr
int cc1 = C + 1;
608 constexpr
real64 tetr = cbrt( 3.0 * cc1 + sqrt( 9.0 * cc1 * cc1 - 1.0 / 27.0 ) )
609 + cbrt( 3.0 * cc1 - sqrt( 9.0 * cc1 * cc1 - 1.0 / 27.0 ) ) - 2;
610 constexpr
int i = ORDER - round( tetr * 10.0 ) / 10;
611 constexpr
int cc2 = C - ( ORDER - i ) * ( ORDER - i + 1 ) * ( ORDER - i + 2 ) / 6 + 1;
612 constexpr
real64 trir = ( sqrt( 8.0 * cc2 + 1.0 ) - 1.0 ) / 2.0 - 1;
613 constexpr
int j = ORDER - i - round( trir * 10.0 ) / 10;
614 constexpr
int k = ORDER - i - j - ( C - (ORDER - i ) * ( ORDER - i + 1 ) * ( ORDER - i + 2 ) / 6
615 - ( ORDER - i - j ) * ( ORDER - i - j + 1 ) / 2 );
616 if constexpr ( VTX == 0 )
620 else if constexpr ( VTX == 1)
624 else if constexpr ( VTX == 2)
628 else if constexpr ( VTX == 3)
630 return ORDER - i - j - k;
642 template<
typename FUNC,
int... Is >
645 static constexpr
void loop_impl( FUNC && func, std::integer_sequence< int, Is... > )
647 ( func( std::integral_constant< int, Is >{} ), ... );
657 template<
int N,
typename FUNC >
659 static constexpr
void loop( FUNC
const & func )
663 loop< N - 1 >( func );
664 func( std::integral_constant< int, N - 1 >{} );
675 template<
typename FUNC >
680 loop_impl( std::forward< FUNC >( func ), std::make_integer_sequence< int, 4 >{} );
688 template<
typename FUNC >
693 loop< ORDER + 1 >( [&func] (
auto const iic )
695 constexpr
int i = decltype(iic)::
value;
696 constexpr
int i1 = ORDER - i;
697 loop< ORDER + 1 >( [&func] (
auto const jjc )
699 constexpr
int j = decltype(jjc)::
value;
700 constexpr
int j1 = ORDER - j;
701 if constexpr ( j1 <= ORDER - i1 )
703 loop< ORDER + 1 >( [&func] (
auto const kkc )
705 constexpr
int k = decltype(kkc)::
value;
706 constexpr
int k1 = ORDER - k;
707 if constexpr ( k1 <= (ORDER - i1 - j1) )
709 constexpr
int l1 = ORDER - i1 - j1 - k1;
710 constexpr
int c1 = dofIndex< i1, j1, k1 >();
711 func( std::integral_constant< int, c1 >{},
712 std::integral_constant< int, i1 >{},
713 std::integral_constant< int, j1 >{},
714 std::integral_constant< int, k1 >{},
715 std::integral_constant< int, l1 >{} );
737 template<
int c1,
int i1,
int j1,
int k1,
int l1,
typename F,
int... Is >
742 auto check_i1 = [&](
auto I ) {
743 if constexpr (i1 == decltype(I)::
value) {
744 func( std::integral_constant< int, 0 >{},
745 std::integral_constant< int, i1 >{},
746 std::integral_constant< int, c1 >{},
747 std::integral_constant< int, j1 >{},
748 std::integral_constant< int, k1 >{},
749 std::integral_constant< int, l1 >{} );
752 (check_i1( std::integral_constant< int, Is >{} ), ...);
754 auto check_j1 = [&](
auto I ) {
755 if constexpr (j1 == decltype(I)::
value) {
756 func( std::integral_constant< int, 1 >{},
757 std::integral_constant< int, j1 >{},
758 std::integral_constant< int, c1 >{},
759 std::integral_constant< int, i1 >{},
760 std::integral_constant< int, k1 >{},
761 std::integral_constant< int, l1 >{} );
764 (check_j1( std::integral_constant< int, Is >{} ), ...);
766 auto check_k1 = [&](
auto I ) {
767 if constexpr (k1 == decltype(I)::
value) {
768 func( std::integral_constant< int, 2 >{},
769 std::integral_constant< int, k1 >{},
770 std::integral_constant< int, c1 >{},
771 std::integral_constant< int, i1 >{},
772 std::integral_constant< int, j1 >{},
773 std::integral_constant< int, l1 >{} );
776 (check_k1( std::integral_constant< int, Is >{} ), ...);
778 auto check_l1 = [&](
auto I ) {
779 if constexpr (l1 == decltype(I)::
value) {
780 func( std::integral_constant< int, 3 >{},
781 std::integral_constant< int, l1 >{},
782 std::integral_constant< int, c1 >{},
783 std::integral_constant< int, i1 >{},
784 std::integral_constant< int, j1 >{},
785 std::integral_constant< int, k1 >{} );
788 (check_l1( std::integral_constant< int, Is >{} ), ...);
799 template<
int... Is,
typename FUNC >
803 loop< ORDER + 1 >( [&](
auto const i ) {
804 using i_t = decltype(i);
805 constexpr
int iVal = i_t::value;
806 constexpr
int i1 = ORDER - iVal;
808 loop< ORDER + 1 >( [&](
auto const j ) {
809 using j_t = decltype(j);
810 constexpr
int jVal = j_t::value;
811 constexpr
int j1 = ORDER - jVal;
813 constexpr
bool valid_j1_i1 = (j1 <= iVal);
814 if constexpr (valid_j1_i1) {
816 loop< ORDER + 1 >( [&](
auto const k ) {
817 using k_t = decltype(k);
818 constexpr
int kVal = k_t::value;
819 constexpr
int k1 = ORDER - kVal;
821 constexpr
bool valid_k1 = (k1 <= (ORDER - i1 - j1));
822 if constexpr (valid_k1) {
823 constexpr
int l1 = ORDER - i1 - j1 - k1;
824 constexpr
int c1 = dofIndex< i1, j1, k1 >();
826 call_matching_cases< c1, i1, j1, k1, l1 >( func, std::integer_sequence< int, Is... >{} );
968 template<
typename FUNC >
973 loop< 3 >( std::forward< FUNC >( func ) );
989 basisLoop( [ &m ] (
auto const cc1,
auto const ii1,
auto const jj1,
auto const kk1,
auto const ll1 )
991 constexpr
int c1 = decltype(cc1)::
value;
992 constexpr
int i1 = decltype(ii1)::
value;
993 constexpr
int j1 = decltype(jj1)::
value;
994 constexpr
int k1 = decltype(kk1)::
value;
995 constexpr
int l1 = decltype(ll1)::
value;
998 basisLoop( [ &m ] (
auto const cc2,
auto const ii2,
auto const jj2,
auto const kk2,
auto const ll2 )
1000 constexpr
int c2 = decltype(cc2)::
value;
1001 constexpr
int i2 = decltype(ii2)::
value;
1002 constexpr
int j2 = decltype(jj2)::
value;
1003 constexpr
int k2 = decltype(kk2)::
value;
1004 constexpr
int l2 = decltype(ll2)::
value;
1006 m[ c1 ][ c2 ] = val;
1022 template<
typename DAMPING >
1030 for(
int c1 = 0; c1 <
numNodes; c1++ )
1032 for(
int c2 = 0; c2 <
numNodes; c2++ )
1037 conditionalBasisLoop< 0 >( [&] (
auto const f1,
auto const,
auto const c1,
auto const i1,
auto const j1,
auto const k1 )
1039 conditionalBasisLoop< 0 >( [&] (
auto const f2,
auto const,
auto const c2,
auto const i2,
auto const j2,
auto const k2 )
1041 if constexpr ( f1 == f2 )
1044 if( ( f1 == 0 && face1Damped ) ||
1045 ( f1 == 1 && face2Damped ) ||
1046 ( f1 == 2 && face3Damped ) ||
1047 ( f1 == 3 && face4Damped ) )
1049 d[ c1 ][ c2 ] += val;
1062 template<
typename FUNC >
1092 basisLoop( [&func, &detJ] (
auto cc1,
auto ii1,
auto jj1,
auto kk1,
auto ll1 )
1094 constexpr
int c1 = decltype(cc1)::
value;
1095 constexpr
int i1 = decltype(ii1)::
value;
1096 constexpr
int j1 = decltype(jj1)::
value;
1097 constexpr
int k1 = decltype(kk1)::
value;
1098 constexpr
int l1 = decltype(ll1)::
value;
1101 basisLoop( [&func, &detJ, i1, j1, k1, l1] (
auto c2,
auto ii2,
auto jj2,
auto kk2,
auto ll2 )
1103 constexpr
int c2v = decltype(c2)::
value;
1104 constexpr
int i2 = decltype(ii2)::
value;
1105 constexpr
int j2 = decltype(jj2)::
value;
1106 constexpr
int k2 = decltype(kk2)::
value;
1107 constexpr
int l2 = decltype(ll2)::
value;
1110 func( c1, c2v, val * detJ );
1151 real64 h2 = (el2[1][0]+el2[1][1])-(el2[2][0]+el2[2][1]);
1153 h2 = (4.0 * el2[0][0]*el2[0][1] - h2 * h2)/16.0;
1155 scal = (4.0*h2-detJf1 * detJf1 - detJf2 * detJf2 ) / (2.0 * detJf1 * detJf2);
1159 return scal * detJf1 / detJ;
1169 template<
typename FUNC >
1179 real64 dLambdadX[4][3] = {};
1180 for(
int j = 0; j < 3; j++ )
1183 ( ( 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;
1185 ( ( 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;
1187 ( ( 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;
1188 dLambdadX[0][j] = -dLambdadX[1][j] - dLambdadX[2][j] - dLambdadX[3][j];
1190 basisLoop( [&func, &dLambdadX, &detJ] (
auto const cc1,
auto const ci1,
auto const cj1,
auto const ck1,
auto const cl1 )
1193 constexpr
int c1 = decltype(cc1)::
value;
1194 constexpr
int i1 = decltype(ci1)::
value;
1195 constexpr
int j1 = decltype(cj1)::
value;
1196 constexpr
int k1 = decltype(ck1)::
value;
1197 constexpr
int l1 = decltype(cl1)::
value;
1200 basisLoop( [&func, &dLambdadX, &detJ] (
auto const cc2,
auto const ci2,
auto const cj2,
auto const ck2,
auto const cl2 )
1202 constexpr
int c2 = decltype(cc2)::
value;
1203 constexpr
int i2 = decltype(ci2)::
value;
1204 constexpr
int j2 = decltype(cj2)::
value;
1205 constexpr
int k2 = decltype(ck2)::
value;
1206 constexpr
int l2 = decltype(cl2)::
value;
1211 constexpr
int d1 = decltype(cd1)::
value;
1214 constexpr
int d2 = decltype(cd2)::
value;
1215 constexpr
int ii1 = i1 + ( d1 == 0 ) * ( -1 );
1216 constexpr
int ij1 = j1 + ( d1 == 1 ) * ( -1 );
1217 constexpr
int ik1 = k1 + ( d1 == 2 ) * ( -1 );
1218 constexpr
int il1 = l1 + ( d1 == 3 ) * ( -1 );
1219 constexpr
int ii2 = i2 + ( d2 == 0 ) * ( -1 );
1220 constexpr
int ij2 = j2 + ( d2 == 1 ) * ( -1 );
1221 constexpr
int ik2 = k2 + ( d2 == 2 ) * ( -1 );
1222 constexpr
int il2 = l2 + ( d2 == 3 ) * ( -1 );
1225 if constexpr (ii1 >= 0 && ij1 >= 0 && ik1 >= 0 && il1 >= 0 &&
1226 ii2 >= 0 && ij2 >= 0 && ik2 >= 0 && il2 >= 0)
1229 func( c1, c2, val * detJ * ( dLambdadX[d1][0]*dLambdadX[d2][0] + dLambdadX[d1][1]*dLambdadX[d2][1] + dLambdadX[d1][2]*dLambdadX[d2][2] ) );
1249 real64 const (&X)[4][3] )
1251 real64 ab[3] = { X[ i2 ][ 0 ] - X[ i1 ][ 0 ],
1252 X[ i2 ][ 1 ] - X[ i1 ][ 1 ],
1253 X[ i2 ][ 2 ] - X[ i1 ][ 2 ] };
1254 return ab[0] * ab[0] + ab[1] * ab[1]+ ab[2]*ab[2];
1271 template<
typename FUNCP,
typename FUNCF >
1283 conditionalBasisLoop< 0, 1 >( [&] (
auto const cf1,
auto const cd,
auto const cc1,
auto const ci1,
auto const cj1,
auto const ck1 )
1285 conditionalBasisLoop< 0 >( [&] (
auto const cf2,
auto const,
auto const cc2,
auto const ci2,
auto const cj2,
auto const ck2 )
1287 constexpr
int c1 = decltype(cc1)::
value;
1288 constexpr
int i1 = decltype(ci1)::
value;
1289 constexpr
int j1 = decltype(cj1)::
value;
1290 constexpr
int k1 = decltype(ck1)::
value;
1293 constexpr
int f2 = decltype(cf2)::
value;
1294 constexpr
int c2 = decltype(cc2)::
value;
1295 constexpr
int i2 = decltype(ci2)::
value;
1296 constexpr
int j2 = decltype(cj2)::
value;
1297 constexpr
int k2 = decltype(ck2)::
value;
1302 if constexpr ( std::decay_t< decltype(cf1) >::
value == std::decay_t< decltype(cf2) >::
value)
1305 if constexpr ( std::decay_t< decltype(cd) >::
value == 0 )
1308 funcP( c1, c2, f2, i1, j1, k1, i2, j2, k2, val * detJf[ f2 ] );
1313 if constexpr ( std::decay_t< decltype(cd) >::
value == 1 )
1315 constexpr
real64 derFactor = ( i1 + j1 + k1 + 4 );
1317 funcF( c1, c2, f2, -1, i1, j1, k1, i2, j2, k2, val * detJf[ f2 ] );
1321 else if constexpr ( std::decay_t< decltype(cd) >::
value == 0 )
1325 constexpr
int l = decltype(cl)::
value;
1326 constexpr
int ii1 = i1 + ( l == 0 ) * ( -1 );
1327 constexpr
int ij1 = j1 + ( l == 1 ) * ( -1 );
1328 constexpr
int ik1 = k1 + ( l == 2 ) * ( -1 );
1329 if constexpr (ii1 >= 0 && ij1 >= 0 && ik1 >= 0)
1331 constexpr
real64 derFactor = ( ii1 + ij1 + ik1 + 4 );
1333 constexpr
int f = l >= f2 ? l + 1 : l;
1334 funcF( c1, c2, f2, f, i1, j1, k1, i2, j2, k2, val * detJf[f2] );
#define USING_FINITEELEMENTBASE
Macro to simplify name resolution in derived classes.
#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(msg)
Raise a hard error and terminate the program.
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,...
GEOS_HOST_DEVICE virtual GEOS_FORCE_INLINE localIndex getMaxSupportPoints() const override
Get the maximum number of support points for this element.
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...
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 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 GEOS_FORCE_INLINE real64 edgeLength2(localIndex i1, localIndex i2, real64 const (&X)[4][3])
virtual GEOS_HOST_DEVICE localIndex getNumQuadraturePoints() const override
Virtual getter for the number of quadrature points per element.
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...
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....
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 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 faceBarycentricCoordinateLoop(FUNC &&func)
Helper function for loop over barycentric coordinates of a face.
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE localIndex getNumSupportPoints(StackVariables const &stack)
Get the number of support points.
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.
constexpr static localIndex numNodesPerFace
The number of shape functions per face.
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...
constexpr static localIndex numQuadraturePoints
The number of quadrature points per element.
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.
constexpr static localIndex maxSupportPoints
The maximum number of support points per element.
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 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 void calcN(localIndex const, real64(&N)[numNodes])
Calculate shape functions values for each support point at a quadrature point.
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 GEOS_FORCE_INLINE real64 jacobianDeterminant(real64 const (&X)[4][3])
Returns the determinant of the Jacobian of the element.
static constexpr int order
The order of the finite element.
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...
GEOS_HOST_DEVICE static constexpr GEOS_FORCE_INLINE void barycentricCoordinateLoop(FUNC &&func)
Helper function for loop over barycentric coordinates.
GEOS_HOST_DEVICE static constexpr GEOS_FORCE_INLINE void loop_impl(FUNC &&func, std::integer_sequence< int, Is... >)
Helper function for static for loop.
virtual ~BB_Tetrahedron()=default
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 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 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 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 virtual GEOS_FORCE_INLINE localIndex getNumSupportPoints() const override
Virtual getter for the number of support points per 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 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 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....
GEOS_HOST_DEVICE static constexpr GEOS_FORCE_INLINE int dofIndex()
Computes the local degree of freedom index given the shape function indices (i, j,...
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 basisLoop(FUNC &&func)
Helper function for loop over tet basis functions.
constexpr static localIndex numNodes
The number of shape functions per element.
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.,...
Base class for FEM element implementations.
static GEOS_HOST_DEVICE void value(real64 const (&N)[NUM_SUPPORT_POINTS], real64 const (&var)[NUM_SUPPORT_POINTS], real64 &value)
Compute the interpolated value of a variable.
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 allocated on the stack.