GEOS
H1_Wedge_Lagrange1_Gauss6.hpp
Go to the documentation of this file.
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2024 TotalEnergies
7  * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
8  * Copyright (c) 2023-2024 Chevron
9  * Copyright (c) 2019- GEOS/GEOSX Contributors
10  * All rights reserved
11  *
12  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
13  * ------------------------------------------------------------------------------------------------------------
14  */
15 
20 #ifndef GEOS_FINITEELEMENT_ELEMENTFORMULATIONS_H1WEDGELAGRANGE1GAUSS6_HPP_
21 #define GEOS_FINITEELEMENT_ELEMENTFORMULATIONS_H1WEDGELAGRANGE1GAUSS6_HPP_
22 
23 #include "FiniteElementBase.hpp"
24 #include "LagrangeBasis1.hpp"
25 
26 
27 namespace geos
28 {
29 namespace finiteElement
30 {
31 
56 {
57 public:
58 
61 
63  constexpr static localIndex numNodes = 6;
64 
66  constexpr static localIndex numFaces = 5;
67 
69  constexpr static localIndex maxSupportPoints = numNodes;
70 
72  constexpr static localIndex numQuadraturePoints = 6;
73 
76 
78  virtual ~H1_Wedge_Lagrange1_Gauss6() override
79  {}
80 
82  virtual localIndex getNumQuadraturePoints() const override
83  {
84  return numQuadraturePoints;
85  }
86 
94  {
95  GEOS_UNUSED_VAR( stack );
96  return numQuadraturePoints;
97  }
98 
100  virtual localIndex getNumSupportPoints() const override
101  {
102  return numNodes;
103  }
104 
106  virtual localIndex getMaxSupportPoints() const override
107  {
108  return maxSupportPoints;
109  }
110 
118  {
119  GEOS_UNUSED_VAR( stack );
120  return numNodes;
121  }
122 
131  static void getSamplingPointCoordInParentSpace( int const & linearIndex,
132  real64 (& samplingPointCoord)[3] )
133  {
134  int const i0 = linearIndex % numSamplingPointsPerDirection;
135  int const i1 = ( (linearIndex - i0)/numSamplingPointsPerDirection ) % numSamplingPointsPerDirection;
136  int const i2 = ( (linearIndex - i0)/numSamplingPointsPerDirection - i1 ) / numSamplingPointsPerDirection;
137 
138  real64 const step = 1. / ( numSamplingPointsPerDirection - 1 );
139 
140  real64 const r = i0 * step;
141  real64 const s = i1 * step;
142  real64 const t = i2 * 2 * step;
143  if( (r+s) <= 1 )
144  {
145  samplingPointCoord[0] = r;
146  samplingPointCoord[1] = s;
147  samplingPointCoord[2] = t;
148  }
149  else
150  {
151  // if outside of the triangle need to reproject it. Points will be doubled though.
152  samplingPointCoord[0] = 1 - r;
153  samplingPointCoord[1] = 1 - s;
154  samplingPointCoord[2] = t;
155  }
156  }
157 
164  inline
165  static void calcN( real64 const (&coords)[3],
166  real64 ( &N )[numNodes] );
167 
168 
177  static void calcN( localIndex const q,
178  real64 ( &N )[numNodes] );
179 
189  inline
190  static void calcN( localIndex const q,
191  StackVariables const & stack,
192  real64 ( &N )[numNodes] );
193 
203  static void calcFaceBubbleN( real64 const (&pointCoord)[3],
204  real64 (& N)[numFaces] )
205  {
206 
207  real64 const r = pointCoord[0];
208  real64 const s = pointCoord[1];
209  real64 const xi = pointCoord[2];
210 
211  N[0] = 4.0 * (1.0 - r - s) * s * LagrangeBasis1::valueBubble( xi );
212  N[1] = 4.0 * (1.0 - r - s) * r * LagrangeBasis1::valueBubble( xi );
213  N[2] = (1.0 - r - s) * r * s * LagrangeBasis1::value( 0, xi );
214  N[3] = (1.0 - r - s) * r * s * LagrangeBasis1::value( 1, xi );
215  N[4] = 4.0 * r * s * LagrangeBasis1::valueBubble( xi );
216 
217  }
218 
227  inline
228  static void calcFaceBubbleN( localIndex const q,
229  real64 (& N)[numFaces] )
230  {
231 
232  real64 const pointCoord[3] = {quadratureParentCoords0( q ),
233  quadratureParentCoords1( q ),
234  quadratureParentCoords2( q )};
235 
236  calcFaceBubbleN( pointCoord, N );
237  }
238 
249  static real64 calcGradN( localIndex const q,
250  real64 const (&X)[numNodes][3],
251  real64 ( &gradN )[numNodes][3] );
252 
264  inline
265  static real64 calcGradN( localIndex const q,
266  real64 const (&X)[numNodes][3],
267  StackVariables const & stack,
268  real64 ( &gradN )[numNodes][3] );
269 
281  real64 const (&X)[numNodes][3],
282  real64 ( &gradN )[numFaces][3] );
283 
293  real64 const (&X)[numNodes][3] );
294 
305  real64 const (&X)[numNodes][3],
306  StackVariables const & stack )
307  { GEOS_UNUSED_VAR( stack ); return transformedQuadratureWeight( q, X ); }
308 
318  static real64 invJacobianTransformation( int const q,
319  real64 const (&X)[numNodes][3],
320  real64 ( & J )[3][3] )
321  {
322  jacobianTransformation( q, X, J );
323  return LvArray::tensorOps::invert< 3 >( J );
324  }
325 
326 
327 private:
329  constexpr static real64 parentVolume = 1.0;
330 
332  constexpr static real64 weight = parentVolume / numQuadraturePoints;
333 
336  constexpr static real64 quadratureCrossSectionCoord = 1.0 / 6.0;
337 
341  constexpr static real64 quadratureLongitudinalCoord = 1.0 / 1.732050807568877293528;
342 
350  template< typename T >
352  inline
353  constexpr static T linearMap( T const indexT, T const indexL )
354  {
355  return 2 * indexT + indexL;
356  }
357 
365  inline
366  constexpr static real64 parentCoords0( localIndex const a )
367  {
368  return 0.5 * ( a & 2 );
369  }
370 
378  inline
379  constexpr static real64 parentCoords1( localIndex const a )
380  {
381  return 0.25 * ( a & 4 );
382  }
383 
391  inline
392  constexpr static real64 parentCoords2( localIndex const a )
393  {
394  return -1.0 + 2 * ( a & 1 );
395  }
396 
404  inline
405  constexpr static real64 quadratureParentCoords0( localIndex const q )
406  {
407  return quadratureCrossSectionCoord + 0.5 * parentCoords0( q );
408  }
409 
417  inline
418  constexpr static real64 quadratureParentCoords1( localIndex const q )
419  {
420  return quadratureCrossSectionCoord + 0.5 * parentCoords1( q );
421  }
422 
430  inline
431  constexpr static real64 quadratureParentCoords2( localIndex const q )
432  {
433  return parentCoords2( q ) * quadratureLongitudinalCoord;
434  }
435 
443  static void jacobianTransformation( int const q,
444  real64 const (&X)[numNodes][3],
445  real64 ( &J )[3][3] );
446 
457  static void
458  applyJacobianTransformationToShapeFunctionsDerivatives( int const q,
459  real64 const ( &invJ )[3][3],
460  real64 ( &gradN )[numNodes][3] );
461 
462 };
463 
465 
467 inline
468 void
469 H1_Wedge_Lagrange1_Gauss6::
470  jacobianTransformation( int const q,
471  real64 const (&X)[numNodes][3],
472  real64 ( & J )[3][3] )
473 {
474  real64 const r = quadratureParentCoords0( q );
475  real64 const s = quadratureParentCoords1( q );
476  real64 const xi = quadratureParentCoords2( q );
477 
478  real64 const psiTRI[3] = { 1.0 - r - s, r, s };
479  real64 const psiLIN[2] = { 0.5 - 0.5*xi, 0.5 + 0.5*xi };
480  constexpr real64 dpsiTRI[2][3] = { { -1.0, 1.0, 0.0 }, { -1.0, 0.0, 1.0 } };
481  constexpr real64 dpsiLIN[2] = { -0.5, 0.5 };
482 
483  for( localIndex a=0; a<3; ++a )
484  {
485  for( localIndex b=0; b<2; ++b )
486  {
487  real64 const dNdXi[3] = { dpsiTRI[0][a] * psiLIN[b],
488  dpsiTRI[1][a] * psiLIN[b],
489  psiTRI[a] * dpsiLIN[b] };
490  localIndex const nodeIndex = linearMap( a, b );
491  for( int i = 0; i < 3; ++i )
492  {
493  for( int j = 0; j < 3; ++j )
494  {
495  J[i][j] = J[i][j] + dNdXi[ j ] * X[nodeIndex][i];
496  }
497  }
498  }
499  }
500 }
501 
502 //*************************************************************************************************
503 
505 inline
506 void
507 H1_Wedge_Lagrange1_Gauss6::
508  applyJacobianTransformationToShapeFunctionsDerivatives( int const q,
509  real64 const ( &invJ )[3][3],
510  real64 (& gradN)[numNodes][3] )
511 {
512  real64 const r = quadratureParentCoords0( q );
513  real64 const s = quadratureParentCoords1( q );
514  real64 const xi = quadratureParentCoords2( q );
515 
516  real64 const psiTRI[3] = { 1.0 - r - s, r, s };
517  real64 const psiLIN[2] = { 0.5 - 0.5*xi, 0.5 + 0.5*xi };
518  constexpr real64 dpsiTRI[2][3] = { { -1.0, 1.0, 0.0 }, { -1.0, 0.0, 1.0 } };
519  constexpr real64 dpsiLIN[2] = { -0.5, 0.5 };
520 
521  for( localIndex a=0; a<3; ++a )
522  {
523  for( localIndex b=0; b<2; ++b )
524  {
525  real64 const dNdXi[3] = { dpsiTRI[0][a] * psiLIN[b],
526  dpsiTRI[1][a] * psiLIN[b],
527  psiTRI[a] * dpsiLIN[b] };
528  localIndex const nodeIndex = linearMap( a, b );
529  for( int i = 0; i < 3; ++i )
530  {
531  gradN[nodeIndex][i] = 0.0;
532  for( int j = 0; j < 3; ++j )
533  {
534  gradN[nodeIndex][i] = gradN[nodeIndex][i] + dNdXi[ j ] * invJ[j][i];
535  }
536  }
537  }
538  }
539 }
540 
541 //*************************************************************************************************
542 
544 inline
545 void
546 H1_Wedge_Lagrange1_Gauss6::calcN( real64 const (&coords)[3],
547  real64 (& N)[numNodes] )
548 {
549  real64 const r = coords[0];
550  real64 const s = coords[1];
551  real64 const xi = coords[2];
552 
553  N[0] = 0.5*( 1.0 - r - s ) * ( 1.0 - xi );
554  N[1] = 0.5*( 1.0 - r - s ) * ( 1.0 + xi );
555  N[2] = 0.5* r * ( 1.0 - xi );
556  N[3] = 0.5* r * ( 1.0 + xi );
557  N[4] = 0.5* s * ( 1.0 - xi );
558  N[5] = 0.5* s * ( 1.0 + xi );
559 
560 }
561 
562 
564 inline
565 void
567  calcN( localIndex const q,
568  real64 (& N)[numNodes] )
569 {
570  real64 const pointCoord[3] = {quadratureParentCoords0( q ),
571  quadratureParentCoords1( q ),
572  quadratureParentCoords2( q )};
573 
574  calcN( pointCoord, N );
575 }
576 
578 inline
580  calcN( localIndex const q,
581  StackVariables const & GEOS_UNUSED_PARAM( stack ),
582  real64 ( & N )[numNodes] )
583 {
584  return calcN( q, N );
585 }
586 
587 //*************************************************************************************************
588 
590 inline
591 real64
593  calcGradN( localIndex const q,
594  real64 const (&X)[numNodes][3],
595  real64 (& gradN)[numNodes][3] )
596 {
597  real64 J[3][3] = {{0}};
598 
599  jacobianTransformation( q, X, J );
600 
601  real64 const detJ = LvArray::tensorOps::invert< 3 >( J );
602 
603  applyJacobianTransformationToShapeFunctionsDerivatives( q, J, gradN );
604 
605  return detJ * weight;
606 }
607 
609 inline
611  calcGradN( localIndex const q,
612  real64 const (&X)[numNodes][3],
613  StackVariables const & GEOS_UNUSED_PARAM( stack ),
614  real64 ( & gradN )[numNodes][3] )
615 {
616  return calcGradN( q, X, gradN );
617 }
618 
620 inline
621 real64
623  real64 const (&X)[numNodes][3],
624  real64 (& gradN)[numFaces][3] )
625 {
626 
627  real64 J[3][3] = {{0}};
628 
629  jacobianTransformation( q, X, J );
630 
631  real64 const detJ = LvArray::tensorOps::invert< 3 >( J );
632 
633  real64 dNdXi[numFaces][3] = {{0}};
634 
635  real64 const r = quadratureParentCoords0( q );
636  real64 const s = quadratureParentCoords1( q );
637  real64 const xi = quadratureParentCoords2( q );
638 
639  dNdXi[0][0] = -4.0 * s * LagrangeBasis1::valueBubble( xi ); // dN0/dr
640  dNdXi[0][1] = 4.0 * (1.0 - r - 2.0 * s) * LagrangeBasis1::valueBubble( xi ); // dN0/ds
641  dNdXi[0][2] = 4.0 *(1 - r - s) * s * LagrangeBasis1::gradientBubble( xi ); // dN0/dxi
642 
643  dNdXi[1][0] = 4.0 * (1.0 - 2.0 * r - s) * LagrangeBasis1::valueBubble( xi ); // dN1/dr
644  dNdXi[1][1] = -4.0 * r * LagrangeBasis1::valueBubble( xi ); // dN1/ds
645  dNdXi[1][2] = 4.0 * (1 - r - s) * r * LagrangeBasis1::gradientBubble( xi ); // dN1/dxi
646 
647  dNdXi[2][0] = (1.0 - 2.0 * r - s) * s * LagrangeBasis1::value( 0, xi ); // dN2/dr
648  dNdXi[2][1] = (1.0 - r - 2.0 * s) * r * LagrangeBasis1::value( 0, xi ); // dN2/ds
649  dNdXi[2][2] = (1 - r - s) * r * s * LagrangeBasis1::gradient( 0, xi ); // dN2/dxi
650 
651  dNdXi[3][0] = (1.0 - 2.0 * r - s) * s * LagrangeBasis1::value( 1, xi ); // dN3/dr
652  dNdXi[3][1] = (1.0 - r - 2.0 * s) * r * LagrangeBasis1::value( 1, xi ); // dN3/ds
653  dNdXi[3][2] = (1 - r - s) * r * s * LagrangeBasis1::gradient( 1, xi ); // dN3/dxi
654 
655  dNdXi[4][0] = 4.0 * s * LagrangeBasis1::valueBubble( xi ); // dN4/dr
656  dNdXi[4][1] = 4.0 * r * LagrangeBasis1::valueBubble( xi ); // dN4/ds
657  dNdXi[4][2] = 4.0 * r * s * LagrangeBasis1::gradientBubble( xi ); // dN4/dxi
658 
659  for( int fi=0; fi<numFaces; ++fi )
660  {
661  gradN[fi][0] = dNdXi[fi][0] * J[0][0] + dNdXi[fi][1] * J[1][0] + dNdXi[fi][2] * J[2][0];
662  gradN[fi][1] = dNdXi[fi][0] * J[0][1] + dNdXi[fi][1] * J[1][1] + dNdXi[fi][2] * J[2][1];
663  gradN[fi][2] = dNdXi[fi][0] * J[0][2] + dNdXi[fi][1] * J[1][2] + dNdXi[fi][2] * J[2][2];
664  }
665 
666  return detJ * weight;
667 }
668 
669 //*************************************************************************************************
670 
672 inline
673 real64
676  real64 const (&X)[numNodes][3] )
677 {
678  real64 J[3][3] = {{0}};
679 
680  jacobianTransformation( q, X, J );
681 
682  return LvArray::tensorOps::determinant< 3 >( J ) * weight;
683 }
684 
686 
687 }
688 }
689 
690 #endif //GEOS_FINITEELEMENT_ELEMENTFORMULATIONS_H1WEDGELAGRANGE1GAUSS6_HPP_
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
#define GEOS_UNUSED_VAR(...)
Mark an unused variable and silence compiler warnings.
Definition: GeosxMacros.hpp:84
#define GEOS_FORCE_INLINE
Marks a function or lambda for inlining.
Definition: GeosxMacros.hpp:51
#define GEOS_UNUSED_PARAM(X)
Mark an unused argument and silence compiler warnings.
Definition: GeosxMacros.hpp:72
Base class for FEM element implementations.
constexpr static int numSamplingPointsPerDirection
Number of sampling points.
static GEOS_HOST_DEVICE void calcFaceBubbleN(localIndex const q, real64(&N)[numFaces])
Calculate face bubble functions values for each face at a quadrature point.
virtual GEOS_HOST_DEVICE localIndex getNumSupportPoints() const override
Virtual getter for the number of support points per element.
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE void getSamplingPointCoordInParentSpace(int const &linearIndex, real64(&samplingPointCoord)[3])
Get the Sampling Point Coord In the Parent Space.
constexpr static localIndex numNodes
The number of nodes/support points per element.
constexpr static localIndex numFaces
The number of faces/support points per element.
static GEOS_HOST_DEVICE localIndex getNumQuadraturePoints(StackVariables const &stack)
Get the number of quadrature points.
constexpr static localIndex numQuadraturePoints
The number of quadrature points per element.
static GEOS_HOST_DEVICE real64 calcGradFaceBubbleN(localIndex const q, real64 const (&X)[numNodes][3], real64(&gradN)[numFaces][3])
Calculate the shape bubble function derivatives wrt the physical coordinates.
virtual GEOS_HOST_DEVICE localIndex getNumQuadraturePoints() const override
Virtual getter for the number of quadrature points per element.
static GEOS_HOST_DEVICE void calcN(localIndex const q, StackVariables const &stack, real64(&N)[numNodes])
Calculate shape functions values for each support point at a quadrature point.
static GEOS_HOST_DEVICE localIndex getNumSupportPoints(StackVariables const &stack)
Get the number of support points.
constexpr static int numSamplingPoints
The number of sampling points per element.
static GEOS_HOST_DEVICE real64 transformedQuadratureWeight(localIndex const q, real64 const (&X)[numNodes][3])
Calculate the integration weights for a quadrature point.
static GEOS_HOST_DEVICE void calcN(localIndex const q, real64(&N)[numNodes])
Calculate shape functions values for each support point at a quadrature point.
static GEOS_HOST_DEVICE void calcN(real64 const (&coords)[3], real64(&N)[numNodes])
Calculate shape functions values at a single point.
static GEOS_HOST_DEVICE real64 calcGradN(localIndex const q, real64 const (&X)[numNodes][3], real64(&gradN)[numNodes][3])
Calculate the shape functions derivatives wrt the physical coordinates.
static GEOS_HOST_DEVICE real64 transformedQuadratureWeight(localIndex const q, real64 const (&X)[numNodes][3], StackVariables const &stack)
Calculate the integration weights for a quadrature point.
virtual GEOS_HOST_DEVICE localIndex getMaxSupportPoints() const override
Get the maximum number of support points for this element.
constexpr static localIndex maxSupportPoints
The maximum number of support points per element.
static GEOS_HOST_DEVICE real64 invJacobianTransformation(int const q, real64 const (&X)[numNodes][3], real64(&J)[3][3])
Calculates the isoparametric "Jacobian" transformation matrix/mapping from the parent space to the ph...
static GEOS_HOST_DEVICE 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 void calcFaceBubbleN(real64 const (&pointCoord)[3], real64(&N)[numFaces])
Calculate shape functions values for each support face at a given point in the parent space.
GEOS_HOST_DEVICE constexpr static GEOS_FORCE_INLINE real64 gradientBubble(const real64 xi)
The gradient of the bubble basis function for support point 1 evaluated at a point along the axes.
GEOS_HOST_DEVICE constexpr static GEOS_FORCE_INLINE real64 valueBubble(const real64 xi)
The value of the bubble basis function.
GEOS_HOST_DEVICE constexpr static GEOS_FORCE_INLINE real64 gradient(const int index, const real64 xi)
The gradient of the basis function for a support point evaluated at a point along the axes.
GEOS_HOST_DEVICE constexpr static GEOS_FORCE_INLINE real64 value(const int index, const real64 xi)
The value of the basis function for a support point evaluated at a point along the axes.
double real64
64-bit floating point type.
Definition: DataTypes.hpp:99
GEOS_LOCALINDEX_TYPE localIndex
Local index type (for indexing objects within an MPI partition).
Definition: DataTypes.hpp:85