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 >{} );
674 template<
typename FUNC >
679 loop_impl( std::forward< FUNC >( func ), std::make_integer_sequence< int, 4 >{} );
687 template<
typename FUNC >
692 loop< ORDER + 1 >( [&func] (
auto const iic )
694 constexpr
int i = decltype(iic)::
value;
695 constexpr
int i1 = ORDER - i;
696 loop< ORDER + 1 >( [&func] (
auto const jjc )
698 constexpr
int j = decltype(jjc)::
value;
699 constexpr
int j1 = ORDER - j;
700 if constexpr ( j1 <= ORDER - i1 )
702 loop< ORDER + 1 >( [&func] (
auto const kkc )
704 constexpr
int k = decltype(kkc)::
value;
705 constexpr
int k1 = ORDER - k;
706 if constexpr ( k1 <= (ORDER - i1 - j1) )
708 constexpr
int l1 = ORDER - i1 - j1 - k1;
709 constexpr
int c1 = dofIndex< i1, j1, k1 >();
710 func( std::integral_constant< int, c1 >{},
711 std::integral_constant< int, i1 >{},
712 std::integral_constant< int, j1 >{},
713 std::integral_constant< int, k1 >{},
714 std::integral_constant< int, l1 >{} );
735 template<
int c1,
int i1,
int j1,
int k1,
int l1,
typename F,
int... Is >
740 auto check_i1 = [&](
auto I ) {
741 if constexpr (i1 == decltype(I)::
value) {
742 func( std::integral_constant< int, 0 >{},
743 std::integral_constant< int, i1 >{},
744 std::integral_constant< int, c1 >{},
745 std::integral_constant< int, j1 >{},
746 std::integral_constant< int, k1 >{},
747 std::integral_constant< int, l1 >{} );
750 (check_i1( std::integral_constant< int, Is >{} ), ...);
752 auto check_j1 = [&](
auto I ) {
753 if constexpr (j1 == decltype(I)::
value) {
754 func( std::integral_constant< int, 1 >{},
755 std::integral_constant< int, j1 >{},
756 std::integral_constant< int, c1 >{},
757 std::integral_constant< int, i1 >{},
758 std::integral_constant< int, k1 >{},
759 std::integral_constant< int, l1 >{} );
762 (check_j1( std::integral_constant< int, Is >{} ), ...);
764 auto check_k1 = [&](
auto I ) {
765 if constexpr (k1 == decltype(I)::
value) {
766 func( std::integral_constant< int, 2 >{},
767 std::integral_constant< int, k1 >{},
768 std::integral_constant< int, c1 >{},
769 std::integral_constant< int, i1 >{},
770 std::integral_constant< int, j1 >{},
771 std::integral_constant< int, l1 >{} );
774 (check_k1( std::integral_constant< int, Is >{} ), ...);
776 auto check_l1 = [&](
auto I ) {
777 if constexpr (l1 == decltype(I)::
value) {
778 func( std::integral_constant< int, 3 >{},
779 std::integral_constant< int, l1 >{},
780 std::integral_constant< int, c1 >{},
781 std::integral_constant< int, i1 >{},
782 std::integral_constant< int, j1 >{},
783 std::integral_constant< int, k1 >{} );
786 (check_l1( std::integral_constant< int, Is >{} ), ...);
797 template<
int... Is,
typename FUNC >
801 loop< ORDER + 1 >( [&](
auto const i ) {
802 using i_t = decltype(i);
803 constexpr
int iVal = i_t::value;
804 constexpr
int i1 = ORDER - iVal;
806 loop< ORDER + 1 >( [&](
auto const j ) {
807 using j_t = decltype(j);
808 constexpr
int jVal = j_t::value;
809 constexpr
int j1 = ORDER - jVal;
811 constexpr
bool valid_j1_i1 = (j1 <= iVal);
812 if constexpr (valid_j1_i1) {
814 loop< ORDER + 1 >( [&](
auto const k ) {
815 using k_t = decltype(k);
816 constexpr
int kVal = k_t::value;
817 constexpr
int k1 = ORDER - kVal;
819 constexpr
bool valid_k1 = (k1 <= (ORDER - i1 - j1));
820 if constexpr (valid_k1) {
821 constexpr
int l1 = ORDER - i1 - j1 - k1;
822 constexpr
int c1 = dofIndex< i1, j1, k1 >();
824 call_matching_cases< c1, i1, j1, k1, l1 >( func, std::integer_sequence< int, Is... >{} );
966 template<
typename FUNC >
971 loop< 3 >( std::forward< FUNC >( func ) );
987 basisLoop( [ &m ] (
auto const cc1,
auto const ii1,
auto const jj1,
auto const kk1,
auto const ll1 )
989 constexpr
int c1 = decltype(cc1)::
value;
990 constexpr
int i1 = decltype(ii1)::
value;
991 constexpr
int j1 = decltype(jj1)::
value;
992 constexpr
int k1 = decltype(kk1)::
value;
993 constexpr
int l1 = decltype(ll1)::
value;
996 basisLoop( [ &m ] (
auto const cc2,
auto const ii2,
auto const jj2,
auto const kk2,
auto const ll2 )
998 constexpr
int c2 = decltype(cc2)::
value;
999 constexpr
int i2 = decltype(ii2)::
value;
1000 constexpr
int j2 = decltype(jj2)::
value;
1001 constexpr
int k2 = decltype(kk2)::
value;
1002 constexpr
int l2 = decltype(ll2)::
value;
1004 m[ c1 ][ c2 ] = val;
1020 template<
typename DAMPING >
1028 for(
int c1 = 0; c1 <
numNodes; c1++ )
1030 for(
int c2 = 0; c2 <
numNodes; c2++ )
1035 conditionalBasisLoop< 0 >( [&] (
auto const f1,
auto const,
auto const c1,
auto const i1,
auto const j1,
auto const k1 )
1037 conditionalBasisLoop< 0 >( [&] (
auto const f2,
auto const,
auto const c2,
auto const i2,
auto const j2,
auto const k2 )
1039 if constexpr ( f1 == f2 )
1042 if( ( f1 == 0 && face1Damped ) ||
1043 ( f1 == 1 && face2Damped ) ||
1044 ( f1 == 2 && face3Damped ) ||
1045 ( f1 == 3 && face4Damped ) )
1047 d[ c1 ][ c2 ] += val;
1060 template<
typename FUNC >
1070 basisLoop( [&func, &detJ] (
auto cc1,
auto ii1,
auto jj1,
auto kk1,
auto ll1 )
1072 constexpr
int c1 = decltype(cc1)::
value;
1073 constexpr
int i1 = decltype(ii1)::
value;
1074 constexpr
int j1 = decltype(jj1)::
value;
1075 constexpr
int k1 = decltype(kk1)::
value;
1076 constexpr
int l1 = decltype(ll1)::
value;
1079 basisLoop( [&func, &detJ, i1, j1, k1, l1] (
auto c2,
auto ii2,
auto jj2,
auto kk2,
auto ll2 )
1081 constexpr
int c2v = decltype(c2)::
value;
1082 constexpr
int i2 = decltype(ii2)::
value;
1083 constexpr
int j2 = decltype(jj2)::
value;
1084 constexpr
int k2 = decltype(kk2)::
value;
1085 constexpr
int l2 = decltype(ll2)::
value;
1088 func( c1, c2v, val * detJ );
1129 real64 h2 = (el2[1][0]+el2[1][1])-(el2[2][0]+el2[2][1]);
1131 h2 = (4.0 * el2[0][0]*el2[0][1] - h2 * h2)/16.0;
1133 scal = (4.0*h2-detJf1 * detJf1 - detJf2 * detJf2 ) / (2.0 * detJf1 * detJf2);
1137 return scal * detJf1 / detJ;
1147 template<
typename FUNC >
1157 real64 dLambdadX[4][3] = {};
1158 for(
int j = 0; j < 3; j++ )
1161 ( ( 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;
1163 ( ( 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;
1165 ( ( 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;
1166 dLambdadX[0][j] = -dLambdadX[1][j] - dLambdadX[2][j] - dLambdadX[3][j];
1168 basisLoop( [&func, &dLambdadX, &detJ] (
auto const cc1,
auto const ci1,
auto const cj1,
auto const ck1,
auto const cl1 )
1171 constexpr
int c1 = decltype(cc1)::
value;
1172 constexpr
int i1 = decltype(ci1)::
value;
1173 constexpr
int j1 = decltype(cj1)::
value;
1174 constexpr
int k1 = decltype(ck1)::
value;
1175 constexpr
int l1 = decltype(cl1)::
value;
1178 basisLoop( [&func, &dLambdadX, &detJ] (
auto const cc2,
auto const ci2,
auto const cj2,
auto const ck2,
auto const cl2 )
1180 constexpr
int c2 = decltype(cc2)::
value;
1181 constexpr
int i2 = decltype(ci2)::
value;
1182 constexpr
int j2 = decltype(cj2)::
value;
1183 constexpr
int k2 = decltype(ck2)::
value;
1184 constexpr
int l2 = decltype(cl2)::
value;
1189 constexpr
int d1 = decltype(cd1)::
value;
1192 constexpr
int d2 = decltype(cd2)::
value;
1193 constexpr
int ii1 = i1 + ( d1 == 0 ) * ( -1 );
1194 constexpr
int ij1 = j1 + ( d1 == 1 ) * ( -1 );
1195 constexpr
int ik1 = k1 + ( d1 == 2 ) * ( -1 );
1196 constexpr
int il1 = l1 + ( d1 == 3 ) * ( -1 );
1197 constexpr
int ii2 = i2 + ( d2 == 0 ) * ( -1 );
1198 constexpr
int ij2 = j2 + ( d2 == 1 ) * ( -1 );
1199 constexpr
int ik2 = k2 + ( d2 == 2 ) * ( -1 );
1200 constexpr
int il2 = l2 + ( d2 == 3 ) * ( -1 );
1203 if constexpr (ii1 >= 0 && ij1 >= 0 && ik1 >= 0 && il1 >= 0 &&
1204 ii2 >= 0 && ij2 >= 0 && ik2 >= 0 && il2 >= 0)
1207 func( c1, c2, val * detJ * ( dLambdadX[d1][0]*dLambdadX[d2][0] + dLambdadX[d1][1]*dLambdadX[d2][1] + dLambdadX[d1][2]*dLambdadX[d2][2] ) );
1227 real64 const (&X)[4][3] )
1229 real64 ab[3] = { X[ i2 ][ 0 ] - X[ i1 ][ 0 ],
1230 X[ i2 ][ 1 ] - X[ i1 ][ 1 ],
1231 X[ i2 ][ 2 ] - X[ i1 ][ 2 ] };
1232 return ab[0] * ab[0] + ab[1] * ab[1]+ ab[2]*ab[2];
1249 template<
typename FUNCP,
typename FUNCF >
1261 conditionalBasisLoop< 0, 1 >( [&] (
auto const cf1,
auto const cd,
auto const cc1,
auto const ci1,
auto const cj1,
auto const ck1 )
1263 conditionalBasisLoop< 0 >( [&] (
auto const cf2,
auto const,
auto const cc2,
auto const ci2,
auto const cj2,
auto const ck2 )
1265 constexpr
int c1 = decltype(cc1)::
value;
1266 constexpr
int i1 = decltype(ci1)::
value;
1267 constexpr
int j1 = decltype(cj1)::
value;
1268 constexpr
int k1 = decltype(ck1)::
value;
1271 constexpr
int f2 = decltype(cf2)::
value;
1272 constexpr
int c2 = decltype(cc2)::
value;
1273 constexpr
int i2 = decltype(ci2)::
value;
1274 constexpr
int j2 = decltype(cj2)::
value;
1275 constexpr
int k2 = decltype(ck2)::
value;
1280 if constexpr ( std::decay_t< decltype(cf1) >::
value == std::decay_t< decltype(cf2) >::
value)
1283 if constexpr ( std::decay_t< decltype(cd) >::
value == 0 )
1286 funcP( c1, c2, f2, i1, j1, k1, i2, j2, k2, val * detJf[ f2 ] );
1291 if constexpr ( std::decay_t< decltype(cd) >::
value == 1 )
1293 constexpr
real64 derFactor = ( i1 + j1 + k1 + 4 );
1295 funcF( c1, c2, f2, -1, i1, j1, k1, i2, j2, k2, val * detJf[ f2 ] );
1299 else if constexpr ( std::decay_t< decltype(cd) >::
value == 0 )
1303 constexpr
int l = decltype(cl)::
value;
1304 constexpr
int ii1 = i1 + ( l == 0 ) * ( -1 );
1305 constexpr
int ij1 = j1 + ( l == 1 ) * ( -1 );
1306 constexpr
int ik1 = k1 + ( l == 2 ) * ( -1 );
1307 if constexpr (ii1 >= 0 && ij1 >= 0 && ik1 >= 0)
1309 constexpr
real64 derFactor = ( ii1 + ij1 + ik1 + 4 );
1311 constexpr
int f = l >= f2 ? l + 1 : l;
1312 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.