GEOS
H1_Tetrahedron_Lagrange1_Gauss.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_H1TETRAHEDRONLAGRANGE1GAUSS_HPP_
21 #define GEOS_FINITEELEMENT_ELEMENTFORMULATIONS_H1TETRAHEDRONLAGRANGE1GAUSS_HPP_
22 
23 #include "FiniteElementBase.hpp"
24 #include "LagrangeBasis1.hpp"
25 
26 
27 namespace geos
28 {
29 namespace finiteElement
30 {
31 
49 template< typename NUM_Q_POINTS >
51 {
52 public:
53 
55  static_assert( ( NUM_Q_POINTS::value == 1 ||
56  NUM_Q_POINTS::value == 5 ||
57  NUM_Q_POINTS::value == 14 ),
58  "NUM_Q_POINTS::value must be 1, 5, or 14!" );
59 
62 
64  constexpr static localIndex numNodes = 4;
65 
67  constexpr static localIndex numFaces = 4;
68 
70  constexpr static localIndex maxSupportPoints = numNodes;
71 
73  constexpr static localIndex numQuadraturePoints = NUM_Q_POINTS::value;
74 
77 
79  virtual ~H1_Tetrahedron_Lagrange1_Gauss() override
80  {}
81 
83  virtual localIndex getNumQuadraturePoints() const override
84  {
85  return numQuadraturePoints;
86  }
87 
94  static localIndex
96  {
97  GEOS_UNUSED_VAR( stack );
98  return numQuadraturePoints;
99  }
100 
102  virtual localIndex getNumSupportPoints() const override
103  {
104  return numNodes;
105  }
106 
108  virtual localIndex getMaxSupportPoints() const override
109  {
110  return maxSupportPoints;
111  }
112 
120  {
121  GEOS_UNUSED_VAR( stack );
122  return numNodes;
123  }
124 
133  static void getSamplingPointCoordInParentSpace( int const & linearIndex,
134  real64 (& samplingPointCoord)[3] )
135  {
136  int const i0 = linearIndex % numSamplingPointsPerDirection;
137  int const i1 = ( (linearIndex - i0)/numSamplingPointsPerDirection ) % numSamplingPointsPerDirection;
138  int const i2 = ( (linearIndex - i0)/numSamplingPointsPerDirection - i1 ) / numSamplingPointsPerDirection;
139 
140  real64 const step = 1. / ( numSamplingPointsPerDirection - 1 );
141 
142  real64 const r = i0 * step;
143  real64 const s = i1 * step;
144  real64 const t = i2 * step;
145  if( (r+s) <= t )
146  {
147  samplingPointCoord[0] = r;
148  samplingPointCoord[1] = s;
149  samplingPointCoord[2] = t;
150  }
151  else
152  {
153  // if outside of the triangle need to reproject it. Points will be doubled though.
154  samplingPointCoord[0] = 1 - t - r;
155  samplingPointCoord[1] = 1 - t - s;
156  samplingPointCoord[2] = t;
157  }
158  }
159 
169  static void calcN( real64 const (&pointCoord)[3],
170  real64 ( &N )[numNodes] );
171 
180  static void calcN( localIndex const q,
181  real64 ( &N )[numNodes] );
182 
192  inline
193  static void calcN( localIndex const q,
194  StackVariables const & stack,
195  real64 ( &N )[numNodes] );
196 
206  static void calcFaceBubbleN( real64 const (&pointCoord)[3],
207  real64 (& N)[numFaces] )
208  {
209 
210  real64 const r = pointCoord[0];
211  real64 const s = pointCoord[1];
212  real64 const t = pointCoord[2];
213 
214  N[0] = (1 - r - s - t) * r * t;
215  N[1] = (1 - r - s - t) * r * s;
216  N[2] = (1 - r - s - t) * t * s;
217  N[3] = r * s * t;
218  }
219 
228  inline
229  static void calcFaceBubbleN( localIndex const q,
230  real64 (& N)[numFaces] )
231  {
232 
233  real64 const pointCoord[3] = {quadratureParentCoords0( q ),
234  quadratureParentCoords1( q ),
235  quadratureParentCoords2( q )};
236 
237  calcFaceBubbleN( pointCoord, N );
238  }
239 
250  static real64 calcGradN( localIndex const q,
251  real64 const (&X)[numNodes][3],
252  real64 ( &gradN )[numNodes][3] );
253 
265  inline
266  static real64 calcGradN( localIndex const q,
267  real64 const (&X)[numNodes][3],
268  StackVariables const & stack,
269  real64 ( &gradN )[numNodes][3] );
270 
282  real64 const (&X)[numNodes][3],
283  real64 ( &gradN )[numFaces][3] );
284 
294  real64 const (&X)[numNodes][3] );
295 
306  real64 const (&X)[numNodes][3],
307  StackVariables const & stack )
308  { GEOS_UNUSED_VAR( stack ); return transformedQuadratureWeight( q, X ); }
309 
319  static real64 invJacobianTransformation( int const q,
320  real64 const (&X)[numNodes][3],
321  real64 ( & J )[3][3] )
322  {
323  GEOS_UNUSED_VAR( q, X );
324 // jacobianTransformation( q, X, J );
325  return LvArray::tensorOps::invert< 3 >( J );
326  }
327 private:
329  constexpr static real64 parentVolume = 1.0 / 6.0;
330 
332  constexpr static real64 weight = parentVolume;
333  //constexpr static real64 weight = parentVolume / numQuadraturePoints;
334 
341  inline
342  constexpr static real64 quadratureWeight( localIndex const q )
343  {
344  if constexpr (numQuadraturePoints == 1)
345  {
346  real64 const w[numQuadraturePoints] = { 1.0 };
347  return w[q];
348  }
349  else if constexpr (numQuadraturePoints == 5)
350  {
351  real64 const w[numQuadraturePoints] = {-4.0/5.0, 9.0/20.0, 9.0/20.0, 9.0/20.0, 9.0/20.0 };
352  return w[q];
353  }
354  else if constexpr (numQuadraturePoints == 14)
355  {
356  real64 const w[numQuadraturePoints] = { 0.073493043116361949544,
357  0.073493043116361949544,
358  0.073493043116361949544,
359  0.073493043116361949544,
360  0.11268792571801585080,
361  0.11268792571801585080,
362  0.11268792571801585080,
363  0.11268792571801585080,
364  0.042546020777081466438,
365  0.042546020777081466438,
366  0.042546020777081466438,
367  0.042546020777081466438,
368  0.042546020777081466438,
369  0.042546020777081466438 };
370  return w[q];
371  }
372 
373  }
374 
382  inline
383  constexpr static real64 quadratureParentCoords0( localIndex const q )
384  {
385 
386  if constexpr (numQuadraturePoints == 1)
387  {
388  real64 const qCoords[numQuadraturePoints] = { 1.0/4.0 };
389  return qCoords[q];
390  }
391  else if constexpr (numQuadraturePoints == 5)
392  {
393  real64 const qCoords[numQuadraturePoints] = { 1.0/4.0, 1.0/2.0, 1.0/6.0, 1.0/6.0, 1.0/6.0 };
394  return qCoords[q];
395  }
396  else if constexpr (numQuadraturePoints == 14)
397  {
398  real64 const qCoords[numQuadraturePoints] = { 0.72179424906732632079,
399  0.092735250310891226402,
400  0.092735250310891226402,
401  0.092735250310891226402,
402  0.067342242210098170608,
403  0.31088591926330060980,
404  0.31088591926330060980,
405  0.31088591926330060980,
406  0.045503704125649649492,
407  0.045503704125649649492,
408  0.045503704125649649492,
409  0.45449629587435035051,
410  0.45449629587435035051,
411  0.45449629587435035051 };
412  return qCoords[q];
413  }
414 
415  }
416 
424  inline
425  constexpr static real64 quadratureParentCoords1( localIndex const q )
426  {
427 
428  if constexpr (numQuadraturePoints == 1)
429  {
430  real64 const qCoords[numQuadraturePoints] = { 1.0/4.0 };
431  return qCoords[q];
432  }
433  else if constexpr (numQuadraturePoints == 5)
434  {
435  real64 const qCoords[numQuadraturePoints] = { 1.0/4.0, 1.0/6.0, 1.0/2.0, 1.0/6.0, 1.0/6.0 };
436  return qCoords[q];
437  }
438  else if constexpr (numQuadraturePoints == 14)
439  {
440  real64 const qCoords[numQuadraturePoints] = { 0.092735250310891226402,
441  0.72179424906732632079,
442  0.092735250310891226402,
443  0.092735250310891226402,
444  0.31088591926330060980,
445  0.067342242210098170608,
446  0.31088591926330060980,
447  0.31088591926330060980,
448  0.045503704125649649492,
449  0.45449629587435035051,
450  0.45449629587435035051,
451  0.045503704125649649492,
452  0.045503704125649649492,
453  0.45449629587435035051 };
454  return qCoords[q];
455  }
456 
457  }
458 
466  inline
467  constexpr static real64 quadratureParentCoords2( localIndex const q )
468  {
469 
470  if constexpr (numQuadraturePoints == 1)
471  {
472  real64 const qCoords[numQuadraturePoints] = { 1.0/4.0 };
473  return qCoords[q];
474  }
475  else if constexpr (numQuadraturePoints == 5)
476  {
477  real64 const qCoords[numQuadraturePoints] = { 1.0/4.0, 1.0/6.0, 1.0/6.0, 1.0/2.0, 1.0/6.0 };
478  return qCoords[q];
479  }
480  else if constexpr (numQuadraturePoints == 14)
481  {
482  real64 const qCoords[numQuadraturePoints] = { 0.092735250310891226402,
483  0.092735250310891226402,
484  0.72179424906732632079,
485  0.092735250310891226402,
486  0.31088591926330060980,
487  0.31088591926330060980,
488  0.067342242210098170608,
489  0.31088591926330060980,
490  0.45449629587435035051,
491  0.045503704125649649492,
492  0.45449629587435035051,
493  0.045503704125649649492,
494  0.45449629587435035051,
495  0.045503704125649649492 };
496 
497  return qCoords[q];
498  }
499 
500  }
501 
509  static real64 determinantJacobianTransformation( real64 const (&X)[numNodes][3] );
510 
511 };
512 
514 
515 template< typename NUM_Q_POINTS >
517 inline
518 real64
519 H1_Tetrahedron_Lagrange1_Gauss< NUM_Q_POINTS >::
520 determinantJacobianTransformation( real64 const (&X)[numNodes][3] )
521 {
522  return ( X[1][0] - X[0][0] )*( ( X[2][1] - X[0][1] )*( X[3][2] - X[0][2] ) - ( X[3][1] - X[0][1] )*( X[2][2] - X[0][2] ) )
523  + ( X[1][1] - X[0][1] )*( ( X[3][0] - X[0][0] )*( X[2][2] - X[0][2] ) - ( X[2][0] - X[0][0] )*( X[3][2] - X[0][2] ) )
524  + ( X[1][2] - X[0][2] )*( ( X[2][0] - X[0][0] )*( X[3][1] - X[0][1] ) - ( X[3][0] - X[0][0] )*( X[2][1] - X[0][1] ) );
525 }
526 
527 //*************************************************************************************************
528 
529 template< typename NUM_Q_POINTS >
531 inline
532 void
534 calcN( real64 const (&coords)[3],
535  real64 (& N)[numNodes] )
536 {
537  real64 const r = coords[0];
538  real64 const s = coords[1];
539  real64 const t = coords[2];
540 
541  // single quadrature point (centroid), i.e. r = s = t = 1/4
542  N[0] = 1 - r - s - t;
543  N[1] = r;
544  N[2] = s;
545  N[3] = t;
546 }
547 
548 
549 template< typename NUM_Q_POINTS >
551 inline
552 void
554 calcN( localIndex const q,
555  real64 (& N)[numNodes] )
556 {
557  real64 const pointCoord[3] = {quadratureParentCoords0( q ),
558  quadratureParentCoords1( q ),
559  quadratureParentCoords2( q )};
560 
561  calcN( pointCoord, N );
562 }
563 
564 template< typename NUM_Q_POINTS >
566 inline
568 calcN( localIndex const q,
569  StackVariables const & GEOS_UNUSED_PARAM( stack ),
570  real64 ( & N )[numNodes] )
571 {
572  return calcN( q, N );
573 }
574 
575 //*************************************************************************************************
576 
577 template< typename NUM_Q_POINTS >
579 inline
580 real64
582 calcGradN( localIndex const q,
583  real64 const (&X)[numNodes][3],
584  real64 (& gradN)[numNodes][3] )
585 {
586 
587  gradN[0][0] = X[1][1]*( X[3][2] - X[2][2] ) - X[2][1]*( X[3][2] - X[1][2] ) + X[3][1]*( X[2][2] - X[1][2] );
588  gradN[0][1] = -X[1][0]*( X[3][2] - X[2][2] ) + X[2][0]*( X[3][2] - X[1][2] ) - X[3][0]*( X[2][2] - X[1][2] );
589  gradN[0][2] = X[1][0]*( X[3][1] - X[2][1] ) - X[2][0]*( X[3][1] - X[1][1] ) + X[3][0]*( X[2][1] - X[1][1] );
590 
591  gradN[1][0] = -X[0][1]*( X[3][2] - X[2][2] ) + X[2][1]*( X[3][2] - X[0][2] ) - X[3][1]*( X[2][2] - X[0][2] );
592  gradN[1][1] = X[0][0]*( X[3][2] - X[2][2] ) - X[2][0]*( X[3][2] - X[0][2] ) + X[3][0]*( X[2][2] - X[0][2] );
593  gradN[1][2] = -X[0][0]*( X[3][1] - X[2][1] ) + X[2][0]*( X[3][1] - X[0][1] ) - X[3][0]*( X[2][1] - X[0][1] );
594 
595  gradN[2][0] = X[0][1]*( X[3][2] - X[1][2] ) - X[1][1]*( X[3][2] - X[0][2] ) + X[3][1]*( X[1][2] - X[0][2] );
596  gradN[2][1] = -X[0][0]*( X[3][2] - X[1][2] ) + X[1][0]*( X[3][2] - X[0][2] ) - X[3][0]*( X[1][2] - X[0][2] );
597  gradN[2][2] = X[0][0]*( X[3][1] - X[1][1] ) - X[1][0]*( X[3][1] - X[0][1] ) + X[3][0]*( X[1][1] - X[0][1] );
598 
599  gradN[3][0] = -X[0][1]*( X[2][2] - X[1][2] ) + X[1][1]*( X[2][2] - X[0][2] ) - X[2][1]*( X[1][2] - X[0][2] );
600  gradN[3][1] = X[0][0]*( X[2][2] - X[1][2] ) - X[1][0]*( X[2][2] - X[0][2] ) + X[2][0]*( X[1][2] - X[0][2] );
601  gradN[3][2] = -X[0][0]*( X[2][1] - X[1][1] ) + X[1][0]*( X[2][1] - X[0][1] ) - X[2][0]*( X[1][1] - X[0][1] );
602 
603  real64 detJ = determinantJacobianTransformation( X );
604  real64 factor = 1.0 / ( detJ );
605 
606  for( int i = 0; i < numNodes; ++i )
607  {
608  for( int j = 0; j < 3; ++j )
609  {
610  gradN[i][j] *= factor;
611  }
612  }
613 
614  return detJ * weight * quadratureWeight( q );
615 }
616 
617 template< typename NUM_Q_POINTS >
619 inline
621 calcGradN( localIndex const q,
622  real64 const (&X)[numNodes][3],
623  StackVariables const & GEOS_UNUSED_PARAM( stack ),
624  real64 ( & gradN )[numNodes][3] )
625 {
626  return calcGradN( q, X, gradN );
627 }
628 
629 template< typename NUM_Q_POINTS >
631 inline
632 real64
634  real64 const (&X)[numNodes][3],
635  real64 (& gradN)[numFaces][3] )
636 {
637 
638  //real64 detJ = determinantJacobianTransformation( X );
639 
640  real64 J[3][3] = {{0}};
641 
642  J[0][0] = X[1][0] - X[0][0];
643  J[0][1] = X[2][0] - X[0][0];
644  J[0][2] = X[3][0] - X[0][0];
645 
646  J[1][0] = X[1][1] - X[0][1];
647  J[1][1] = X[2][1] - X[0][1];
648  J[1][2] = X[3][1] - X[0][1];
649 
650  J[2][0] = X[1][2] - X[0][2];
651  J[2][1] = X[2][2] - X[0][2];
652  J[2][2] = X[3][2] - X[0][2];
653 
654  real64 const detJ = LvArray::tensorOps::invert< 3 >( J );
655 
656  real64 dNdXi[numFaces][3] = {{0}};
657 
658  real64 const r = quadratureParentCoords0( q );
659  real64 const s = quadratureParentCoords1( q );
660  real64 const t = quadratureParentCoords2( q );
661 
662  dNdXi[0][0] = ( 1 - 2 * r - s - t ) * t; // dN0/dr
663  dNdXi[0][1] = -r * t; // dN0/ds
664  dNdXi[0][2] = ( 1 - r - s - 2 * t ) * r; // dN0/dt
665 
666  dNdXi[1][0] = ( 1 - 2 * r - s - t ) * s; // dN1/dr
667  dNdXi[1][1] = ( 1 - r - 2 * s - t ) * r; // dN1/ds
668  dNdXi[1][2] = -r * s; // dN1/dt
669 
670  dNdXi[2][0] = -t * s; // dN2/dr
671  dNdXi[2][1] = ( 1 - r - 2 * s - t ) * t; // dN2/ds
672  dNdXi[2][2] = ( 1 - r - s - 2 * t ) * s; // dN2/dt
673 
674  dNdXi[3][0] = t * s; // dN3/dr
675  dNdXi[3][1] = r * t; // dN3/ds
676  dNdXi[3][2] = r * s; // dN3/dt
677 
678  for( int fi=0; fi<numFaces; ++fi )
679  {
680  gradN[fi][0] = dNdXi[fi][0] * J[0][0] + dNdXi[fi][1] * J[1][0] + dNdXi[fi][2] * J[2][0];
681  gradN[fi][1] = dNdXi[fi][0] * J[0][1] + dNdXi[fi][1] * J[1][1] + dNdXi[fi][2] * J[2][1];
682  gradN[fi][2] = dNdXi[fi][0] * J[0][2] + dNdXi[fi][1] * J[1][2] + dNdXi[fi][2] * J[2][2];
683  }
684 
685  return detJ * weight * quadratureWeight( q );
686 }
687 
688 //*************************************************************************************************
689 
690 template< typename NUM_Q_POINTS >
692 inline
693 real64
696  real64 const (&X)[numNodes][3] )
697 {
698 
699  real64 detJ = determinantJacobianTransformation( X );
700 
701  return detJ * weight * quadratureWeight( q );
702 }
703 
705 
712 
713 }
714 }
715 
716 #endif //GEOS_FINITEELEMENT_ELEMENTFORMULATIONS_H1TETRAHEDRONLAGRANGE1GAUSS_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 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 void calcN(localIndex const q, real64(&N)[numNodes])
Calculate shape functions values for each support point at a quadrature point.
static GEOS_HOST_DEVICE real64 transformedQuadratureWeight(localIndex const q, real64 const (&X)[numNodes][3])
Calculate the integration weights for a quadrature point.
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE void calcN(real64 const (&pointCoord)[3], real64(&N)[numNodes])
Calculate shape functions values for each support point at a given point in the parent space.
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.
GEOS_HOST_DEVICE static GEOS_FORCE_INLINE void calcFaceBubbleN(real64 const (&pointCoord)[3], real64(&N)[numFaces])
Calculate face bubble functions values for each face at a given point in the parent space.
static GEOS_HOST_DEVICE real64 calcGradFaceBubbleN(localIndex const q, real64 const (&X)[numNodes][3], real64(&gradN)[numFaces][3])
Calculate the bubble function derivatives wrt the physical coordinates.
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 getSamplingPointCoordInParentSpace(int const &linearIndex, real64(&samplingPointCoord)[3])
Get the Sampling Point Coord In the Parent Space.
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.
static GEOS_HOST_DEVICE localIndex getNumQuadraturePoints(StackVariables const &stack)
Get the number of quadrature 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.
static GEOS_HOST_DEVICE localIndex getNumSupportPoints(StackVariables const &stack)
Get the number of support points.
constexpr static localIndex maxSupportPoints
The maximum number of support points per element.
virtual GEOS_HOST_DEVICE localIndex getNumQuadraturePoints() const override
Virtual getter for the number of quadrature points per element.
constexpr static int numSamplingPoints
The number of sampling points per element.
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 real64 calcGradN(localIndex const q, real64 const (&X)[numNodes][3], real64(&gradN)[numNodes][3])
Calculate the shape functions derivatives wrt the physical coordinates.
virtual GEOS_HOST_DEVICE localIndex getNumSupportPoints() const override
Virtual getter for the number of support points per element.
constexpr static localIndex numQuadraturePoints
The number of quadrature points per element.
virtual GEOS_HOST_DEVICE localIndex getMaxSupportPoints() const override
Get the maximum number of support points for this element.
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