GEOS
SolidMechanicsContactFaceBubbleKernels.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_PHYSICSSOLVERS_CONTACT_KERNELS_SOLIDMECHANICSCONTACTFACEBUBBLEKERNELS_HPP_
21 #define GEOS_PHYSICSSOLVERS_CONTACT_KERNELS_SOLIDMECHANICSCONTACTFACEBUBBLEKERNELS_HPP_
22 
25 
26 // TODO: Use the bilinear form utilities
27 //#include "finiteElement/BilinearFormUtilities.hpp"
28 
29 namespace geos
30 {
31 
32 namespace solidMechanicsConformingContactKernels
33 {
34 
40 template< typename SUBREGION_TYPE,
41  typename CONSTITUTIVE_TYPE,
42  typename FE_TYPE >
45  CONSTITUTIVE_TYPE,
46  FE_TYPE >
47 {
48 public:
51  CONSTITUTIVE_TYPE,
52  FE_TYPE >;
53 
57 
59  static constexpr int numFacesPerElem = FE_TYPE::numFaces;
60 
62  static constexpr int numQuadraturePointsPerElem = FE_TYPE::numQuadraturePoints;
63 
64  using Base::m_X;
68  using Base::m_dofNumber;
70  using Base::m_matrix;
71  using Base::m_rhs;
72  using Base::m_disp;
73 
78  FaceBubbleKernels( NodeManager const & nodeManager,
79  EdgeManager const & edgeManager,
80  FaceManager const & faceManager,
81  localIndex const targetRegionIndex,
82  SUBREGION_TYPE const & elementSubRegion,
83  FE_TYPE const & finiteElementSpace,
84  CONSTITUTIVE_TYPE & inputConstitutiveType,
85  arrayView1d< globalIndex const > const uDofNumber,
86  arrayView1d< globalIndex const > const bDofNumber,
87  globalIndex const rankOffset,
89  arrayView1d< real64 > const inputRhs,
90  real64 const inputDt,
91  real64 const (&inputGravityVector)[3] ):
92  Base( nodeManager,
93  edgeManager,
94  faceManager,
95  targetRegionIndex,
96  elementSubRegion,
97  finiteElementSpace,
98  inputConstitutiveType,
99  uDofNumber,
100  rankOffset,
101  inputMatrix,
102  inputRhs,
103  inputDt,
104  inputGravityVector ),
105  m_bubbleDisp( faceManager.getField< fields::solidMechanics::totalBubbleDisplacement >().toViewConst() ),
106  m_bDofNumber( bDofNumber ),
107  m_bubbleElems( elementSubRegion.bubbleElementsList() ),
108  m_elemsToFaces( elementSubRegion.faceElementsList() )
109  {}
110 
111  //***************************************************************************
112 
117  {
118 public:
120  static constexpr int numUdofs = numNodesPerElem * 3;
121 
123  static constexpr int numBubbleUdofs = numFacesPerElem * 3;
124 
131  dispColIndices{},
132  bEqnRowIndices{},
133  bColIndices{},
134  localRu{},
135  localRb{},
136  localAbb{ {} },
137  localAbu{ {} },
138  localAub{ {} },
139  bLocal{},
140  uLocal{},
141  X{ {} },
142  constitutiveStiffness{ {} }
143  {}
144 
146  globalIndex dispEqnRowIndices[numUdofs];
147 
149  globalIndex dispColIndices[numUdofs];
150 
152  globalIndex bEqnRowIndices[3];
153 
155  globalIndex bColIndices[3];
156 
158  real64 localRu[numUdofs];
159 
161  real64 localRb[numBubbleUdofs];
162 
164  real64 localAbb[numBubbleUdofs][numBubbleUdofs];
165 
167  real64 localAbu[numBubbleUdofs][numUdofs];
168 
170  real64 localAub[numUdofs][numBubbleUdofs];
171 
173  real64 bLocal[3];
174 
176  real64 uLocal[numUdofs];
177 
180 
182  real64 constitutiveStiffness[ 6 ][ 6 ];
183 
184  };
185 
186  //***************************************************************************
187 
195  //START_kernelLauncher
196  template< typename POLICY,
197  typename KERNEL_TYPE >
198  static
199  real64
200  kernelLaunch( localIndex const numElems,
201  KERNEL_TYPE const & kernelComponent )
202  {
203 
205  GEOS_UNUSED_VAR( numElems );
206 
207  // Define a RAJA reduction variable to get the maximum residual contribution.
208  RAJA::ReduceMax< ReducePolicy< POLICY >, real64 > maxResidual( 0 );
209 
210  forAll< POLICY >( kernelComponent.m_bubbleElems.size(),
211  [=] GEOS_HOST_DEVICE ( localIndex const i )
212  {
213  typename KERNEL_TYPE::StackVariables stack;
214 
215  kernelComponent.setup( i, stack );
216  for( integer q=0; q<numQuadraturePointsPerElem; ++q )
217  {
218  kernelComponent.quadraturePointKernel( i, q, stack );
219  }
220  maxResidual.max( kernelComponent.complete( i, stack ) );
221  } );
222 
223  return maxResidual.get();
224  }
225  //END_kernelLauncher
226 
228  inline
229  void setup( localIndex const kk,
230  StackVariables & stack ) const
231  {
232 
233  localIndex k = m_bubbleElems[kk];
234 
235  for( localIndex a=0; a<numNodesPerElem; ++a )
236  {
237  localIndex const localNodeIndex = m_elemsToNodes( k, a );
238 
239  for( int i=0; i<3; ++i )
240  {
241  stack.dispEqnRowIndices[a*3+i] = m_dofNumber[localNodeIndex]+i-m_dofRankOffset;
242  stack.dispColIndices[a*3+i] = m_dofNumber[localNodeIndex]+i;
243  stack.X[ a ][ i ] = m_X[ localNodeIndex ][ i ];
244  stack.uLocal[ a*3 + i ] = m_disp[localNodeIndex][i];
245  }
246  }
247 
248  localIndex const localFaceIndex = m_elemsToFaces[kk][0];
249 
250  for( int i=0; i<3; ++i )
251  {
252  // need to grab the index.
253  stack.bEqnRowIndices[i] = m_bDofNumber[localFaceIndex] + i - m_dofRankOffset;
254  stack.bColIndices[i] = m_bDofNumber[localFaceIndex] + i;
255  stack.bLocal[ i ] = m_bubbleDisp[ localFaceIndex ][i];
256  }
257  }
258 
259 
261  inline
262  void quadraturePointKernel( localIndex const kk,
263  localIndex const q,
264  StackVariables & stack ) const
265  {
266 
267  localIndex k = m_bubbleElems[kk];
268  constexpr int nUdof = numNodesPerElem*3;
269  constexpr int nBubbleUdof = numFacesPerElem*3;
270 
271  real64 dBubbleNdX[ numFacesPerElem ][ 3 ];
272  // Next line is needed because I only inserted a placeholder for calcGradFaceBubbleN in some finite elements
273  LvArray::tensorOps::fill< numFacesPerElem, 3 >( dBubbleNdX, 0 ); //make 0
274 
275  real64 detJ = m_finiteElementSpace.calcGradFaceBubbleN( q, stack.X, dBubbleNdX );
276 
277  real64 dNdX[ numNodesPerElem ][ 3 ];
278  detJ = m_finiteElementSpace.calcGradN( q, stack.X, dNdX );
279 
280  m_constitutiveUpdate.getElasticStiffness( k, q, stack.constitutiveStiffness );
281 
282  real64 strainMatrix[6][nUdof];
283  solidMechanicsConformingContactKernelsHelper::assembleStrainOperator< 6, nUdof, numNodesPerElem >( strainMatrix, dNdX );
284 
285  real64 strainBubbleMatrix[6][nBubbleUdof];
286  solidMechanicsConformingContactKernelsHelper::assembleStrainOperator< 6, nBubbleUdof, numFacesPerElem >( strainBubbleMatrix, dBubbleNdX );
287 
288  // TODO: It would be nice use BilinearFormUtilities::compute
289 
290  real64 matBD[nBubbleUdof][6];
291  real64 Abb_gauss[nBubbleUdof][nBubbleUdof], Abu_gauss[nBubbleUdof][nUdof], Aub_gauss[nUdof][nBubbleUdof];
292 
293  // transp(Bb)D
294  LvArray::tensorOps::Rij_eq_AkiBkj< nBubbleUdof, 6, 6 >( matBD, strainBubbleMatrix, stack.constitutiveStiffness );
295 
296  // transp(Bb)DB
297  LvArray::tensorOps::Rij_eq_AikBkj< nBubbleUdof, nUdof, 6 >( Abu_gauss, matBD, strainMatrix );
298 
299  // transp(Bb)DBb
300  LvArray::tensorOps::Rij_eq_AikBkj< nBubbleUdof, nBubbleUdof, 6 >( Abb_gauss, matBD, strainBubbleMatrix );
301 
302  // transp(B)DBb
303  LvArray::tensorOps::transpose< nUdof, nBubbleUdof >( Aub_gauss, Abu_gauss );
304 
305  // multiply by determinant and add to element matrix
306  LvArray::tensorOps::scaledAdd< nBubbleUdof, nBubbleUdof >( stack.localAbb, Abb_gauss, -detJ );
307  LvArray::tensorOps::scaledAdd< nBubbleUdof, nUdof >( stack.localAbu, Abu_gauss, -detJ );
308  LvArray::tensorOps::scaledAdd< nUdof, nBubbleUdof >( stack.localAub, Aub_gauss, -detJ );
309 
310  // Compute the initial stress
311  // The following block assumes a linear elastic constitutive model
312  real64 rb_gauss[nBubbleUdof]{};
313  real64 strain[6] = {0};
314  LvArray::tensorOps::Ri_eq_AijBj< 6, nUdof >( strain, strainMatrix, stack.uLocal );
315 
316  real64 initStressLocal[ 6 ] = {0};
317  LvArray::tensorOps::Ri_eq_AijBj< 6, 6 >( initStressLocal, stack.constitutiveStiffness, strain );
318  for( localIndex c = 0; c < 6; ++c )
319  {
320  initStressLocal[ c ] -= m_constitutiveUpdate.m_newStress( k, q, c );
321  }
322 
323  LvArray::tensorOps::Ri_eq_AjiBj< nBubbleUdof, 6 >( rb_gauss, strainBubbleMatrix, initStressLocal );
324  LvArray::tensorOps::scaledAdd< nBubbleUdof >( stack.localRb, rb_gauss, detJ );
325 
326  }
327 
329  inline
330  real64 complete( localIndex const kk,
331  StackVariables & stack ) const
332  {
333 
334  real64 maxForce = 0;
335  constexpr int nUdof = numNodesPerElem*3;
336 
337  localIndex const parentFaceIndex = m_elemsToFaces[kk][1];
338 
339  // Extract only the submatrix and known term corresponding to the index of the local face
340  // on which the bubble function was applied.
341  real64 localAub[nUdof][3];
342  real64 localAbu[3][nUdof];
343  real64 localAbb[3][3];
344  real64 localRb[3];
345  for( localIndex i = 0; i < 3; ++i )
346  {
347  for( localIndex j = 0; j < nUdof; ++j )
348  {
349  localAub[j][i] = stack.localAub[j][parentFaceIndex*3+i];
350  }
351  for( localIndex j = 0; j < 3; ++j )
352  {
353  localAbb[j][i] = stack.localAbb[parentFaceIndex*3+j][parentFaceIndex*3+i];
354  }
355  localRb[i] = stack.localRb[parentFaceIndex*3+i];
356  }
357 
358  for( localIndex j = 0; j < nUdof; ++j )
359  {
360  for( localIndex i = 0; i < 3; ++i )
361  {
362  localAbu[i][j] = stack.localAbu[parentFaceIndex*3+i][j];
363  }
364  }
365 
366  // Compute the local residuals
367  LvArray::tensorOps::Ri_add_AijBj< 3, 3 >( localRb, localAbb, stack.bLocal );
368  LvArray::tensorOps::Ri_add_AijBj< 3, nUdof >( localRb, localAbu, stack.uLocal );
369  LvArray::tensorOps::Ri_add_AijBj< nUdof, 3 >( stack.localRu, localAub, stack.bLocal );
370 
371  for( localIndex i = 0; i < nUdof; ++i )
372  {
373  localIndex const dof = LvArray::integerConversion< localIndex >( stack.dispEqnRowIndices[ i ] );
374  if( dof < 0 || dof >= m_matrix.numRows() ) continue;
375 
376  RAJA::atomicAdd< parallelDeviceAtomic >( &m_rhs[dof], stack.localRu[i] );
377 
378  // fill in matrix
379  m_matrix.template addToRowBinarySearchUnsorted< parallelDeviceAtomic >( dof,
380  stack.bColIndices,
381  localAub[i],
382  3 );
383 
384  }
385 
386  for( localIndex i=0; i < 3; ++i )
387  {
388  localIndex const dof = LvArray::integerConversion< localIndex >( stack.bEqnRowIndices[ i ] );
389 
390  if( dof < 0 || dof >= m_matrix.numRows() ) continue;
391 
392  RAJA::atomicAdd< parallelDeviceAtomic >( &m_rhs[dof], localRb[i] );
393 
394  // fill in matrix
395  m_matrix.template addToRowBinarySearchUnsorted< parallelDeviceAtomic >( dof,
396  stack.bColIndices,
397  localAbb[i],
398  3 );
399 
400  m_matrix.template addToRowBinarySearchUnsorted< parallelDeviceAtomic >( dof,
401  stack.dispColIndices,
402  localAbu[i],
403  numNodesPerElem*3 );
404  }
405 
406  return maxForce;
407  }
408 
409 protected:
410 
413 
416 
419 
424 
425 };
426 
431  globalIndex const,
433  arrayView1d< real64 > const,
434  real64 const,
435  real64 const (&) [3] >;
436 
437 } // namespace SolidMechanicsContactFaceBubbleKernels
438 
439 } // namespace geos
440 
441 
442 #endif /* GEOS_PHYSICSSOLVERS_CONTACT_KERNELS_SOLIDMECHANICSCONTACTFACEBUBBLEKERNELS_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_MARK_FUNCTION
Mark function with both Caliper and NVTX if enabled.
This class provides an interface to ObjectManagerBase in order to manage edge data.
Definition: EdgeManager.hpp:43
The FaceManager class provides an interface to ObjectManagerBase in order to manage face data.
Definition: FaceManager.hpp:44
The NodeManager class provides an interface to ObjectManagerBase in order to manage node data.
Definition: NodeManager.hpp:46
traits::ViewTypeConst< typename SUBREGION_TYPE::NodeMapType::base_type > const m_elemsToNodes
The element to nodes map.
Definition: KernelBase.hpp:257
CRSMatrixView< real64, globalIndex const > const m_matrix
The global Jacobian matrix.
arrayView1d< globalIndex const > const m_dofNumber
The global degree of freedom number.
CONSTITUTIVE_TYPE::KernelWrapper const m_constitutiveUpdate
Definition: KernelBase.hpp:264
Used to forward arguments to a class that implements the KernelBase interface.
Definition: KernelBase.hpp:282
arrayView1d< globalIndex const > const m_bDofNumber
The global degree of freedom number of bubble.
arrayView1d< localIndex const > const m_bubbleElems
The array containing the list of bubble elements.
FaceBubbleKernels(NodeManager const &nodeManager, EdgeManager const &edgeManager, FaceManager const &faceManager, localIndex const targetRegionIndex, SUBREGION_TYPE const &elementSubRegion, FE_TYPE const &finiteElementSpace, CONSTITUTIVE_TYPE &inputConstitutiveType, arrayView1d< globalIndex const > const uDofNumber, arrayView1d< globalIndex const > const bDofNumber, globalIndex const rankOffset, CRSMatrixView< real64, globalIndex const > const inputMatrix, arrayView1d< real64 > const inputRhs, real64 const inputDt, real64 const (&inputGravityVector)[3])
Constructor.
static real64 kernelLaunch(localIndex const numElems, KERNEL_TYPE const &kernelComponent)
Kernel Launcher.
static constexpr int numQuadraturePointsPerElem
Compile time value for the number of quadrature points per element.
static constexpr int numFacesPerElem
Compile time value for the number of faces per element.
arrayView2d< real64 const > const m_bubbleDisp
The array containing the bubble displacement.
arrayView2d< real64 const, nodes::TOTAL_DISPLACEMENT_USD > const m_disp
The rank-global displacement array.
arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const m_X
The array containing the nodal position array.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:180
LvArray::CRSMatrixView< T, COL_INDEX, localIndex const, LvArray::ChaiBuffer > CRSMatrixView
Alias for CRS Matrix View.
Definition: DataTypes.hpp:310
GEOS_GLOBALINDEX_TYPE globalIndex
Global index type (for indexing objects across MPI partitions).
Definition: DataTypes.hpp:88
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
std::int32_t integer
Signed integer type.
Definition: DataTypes.hpp:82
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
Definition: DataTypes.hpp:196
real64 localAbb[numBubbleUdofs][numBubbleUdofs]
C-array storage for the element local Abb matrix.
real64 localRu[numUdofs]
C-array storage for the element local Ru residual vector.
globalIndex dispEqnRowIndices[numUdofs]
C-array storage for the element local row degrees of freedom.
globalIndex bEqnRowIndices[3]
C-array storage for the element local row degrees of freedom.
globalIndex dispColIndices[numUdofs]
C-array storage for the element local column degrees of freedom.
globalIndex bColIndices[3]
C-array storage for the element local column degrees of freedom.
real64 localRb[numBubbleUdofs]
C-array storage for the element local Rb residual vector.