GEOS
SolidMechanicsLagrangeContactKernels.hpp
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_SOLIDMECHANICSLAGRANGECONTACTKERNELS_HPP_
21 #define GEOS_PHYSICSSOLVERS_CONTACT_KERNELS_SOLIDMECHANICSLAGRANGECONTACTKERNELS_HPP_
22 
24 #include "SolidMechanicsConformingContactKernelsBase.hpp"
25 
26 namespace geos
27 {
28 
29 namespace solidMechanicsLagrangeContactKernels
30 {
31 
35 template< typename CONSTITUTIVE_TYPE,
36  typename FE_TYPE >
39  FE_TYPE >
40 {
41 public:
44  FE_TYPE >;
45 
49 
51  static constexpr int numQuadraturePointsPerElem = FE_TYPE::numQuadraturePoints;
52 
53  using Base::numUdofs;
54  using Base::numTdofs;
55  using Base::numBdofs;
56 
58  using Base::m_faceToNodes;
61  using Base::m_dofNumber;
62  using Base::m_bDofNumber;
64  using Base::m_X;
66  using Base::m_dispJump;
67  using Base::m_oldDispJump;
68  using Base::m_matrix;
69  using Base::m_rhs;
70 
75  LagrangeContact( NodeManager const & nodeManager,
76  EdgeManager const & edgeManager,
77  FaceManager const & faceManager,
78  localIndex const targetRegionIndex,
79  FaceElementSubRegion & elementSubRegion,
80  FE_TYPE const & finiteElementSpace,
81  CONSTITUTIVE_TYPE & inputConstitutiveType,
82  arrayView1d< globalIndex const > const uDofNumber,
83  arrayView1d< globalIndex const > const bDofNumber,
84  globalIndex const rankOffset,
86  arrayView1d< real64 > const inputRhs,
87  real64 const inputDt,
88  arrayView1d< localIndex const > const & faceElementList,
89  string const tractionDofKey ):
90  Base( nodeManager,
91  edgeManager,
92  faceManager,
93  targetRegionIndex,
94  elementSubRegion,
95  finiteElementSpace,
96  inputConstitutiveType,
97  uDofNumber,
98  bDofNumber,
99  rankOffset,
100  inputMatrix,
101  inputRhs,
102  inputDt,
103  faceElementList ),
104  m_traction( elementSubRegion.getField< fields::contact::traction >().toViewConst() ),
105  m_tDofNumber( elementSubRegion.getReference< globalIndex_array >( tractionDofKey ).toViewConst() ),
106  m_incrDisp( nodeManager.getField< fields::solidMechanics::incrementalDisplacement >() ),
107  m_incrBubbleDisp( faceManager.getField< fields::solidMechanics::incrementalBubbleDisplacement >() ),
108  m_targetIncrementalJump( elementSubRegion.getField< fields::contact::targetIncrementalJump >().toViewConst() )
109  {}
110 
114  struct StackVariables : public Base::StackVariables
115  {
116 public:
117 
119  StackVariables():
120  Base::StackVariables(),
122  dispColIndices{},
123  bEqnRowIndices{},
124  bColIndices{},
125  tColIndices{},
126  localRu{},
127  localRb{},
128  localRt{},
129  localAtt{ {} },
130  localAut{ {} },
131  localAbt{ {} },
132  duLocal{},
133  dbLocal{}
134  {}
135 
138 
141 
144 
147 
150 
153 
156 
159 
162 
165 
168 
171 
174 
177  };
178 
179  //***************************************************************************
180 
181  //START_kernelLauncher
182  template< typename POLICY,
183  typename KERNEL_TYPE >
184  static
185  real64
186  kernelLaunch( localIndex const numElems,
187  KERNEL_TYPE const & kernelComponent )
188  {
189  return Base::template kernelLaunch< POLICY, KERNEL_TYPE >( numElems, kernelComponent );
190  }
191  //END_kernelLauncher
192 
198  inline
199  void setup( localIndex const k,
200  StackVariables & stack ) const
201  {
202  constexpr int shift = numNodesPerElem * 3;
203 
204  int permutation[numNodesPerElem];
205  m_finiteElementSpace.getPermutation( permutation );
206 
207  localIndex const kf0 = m_elemsToFaces[k][0];
208  localIndex const kf1 = m_elemsToFaces[k][1];
209  for( localIndex a=0; a<numNodesPerElem; ++a )
210  {
211  localIndex const kn0 = m_faceToNodes( kf0, a );
212  localIndex const kn1 = m_faceToNodes( kf1, a );
213 
214  for( int i=0; i<3; ++i )
215  {
216  stack.dispEqnRowIndices[a*3+i] = m_dofNumber[kn0]+i-m_dofRankOffset;
217  stack.dispEqnRowIndices[shift + a*3+i] = m_dofNumber[kn1]+i-m_dofRankOffset;
218  stack.dispColIndices[a*3+i] = m_dofNumber[kn0]+i;
219  stack.dispColIndices[shift + a*3+i] = m_dofNumber[kn1]+i;
220  stack.X[ a ][ i ] = m_X[ m_faceToNodes( kf0, permutation[ a ] ) ][ i ];
221 
222  stack.duLocal[a*3+i] = m_incrDisp[kn0][i];
223  stack.duLocal[shift + a*3+i] = m_incrDisp[kn1][i];
224  }
225  }
226 
227  for( int j=0; j<3; ++j )
228  {
229  for( int i=0; i<3; ++i )
230  {
231  stack.localRotationMatrix[ i ][ j ] = m_rotationMatrix( k, i, j );
232  }
233  }
234 
235  for( int i=0; i<numTdofs; ++i )
236  {
237  stack.dispJumpLocal[i] = m_dispJump( k, i );
238  stack.oldDispJumpLocal[i] = m_oldDispJump( k, i );
239  }
240 
241  for( int i=0; i<3; ++i )
242  {
243  // need to grab the index.
244  stack.bEqnRowIndices[i] = m_bDofNumber[kf0] + i - m_dofRankOffset;
245  stack.bEqnRowIndices[3+i] = m_bDofNumber[kf1] + i - m_dofRankOffset;
246  stack.bColIndices[i] = m_bDofNumber[kf0] + i;
247  stack.bColIndices[3+i] = m_bDofNumber[kf1] + i;
248 
249  stack.dbLocal[ i ] = m_incrBubbleDisp[ kf0 ][i];
250  stack.dbLocal[ 3 + i ] = m_incrBubbleDisp[ kf1 ][i];
251  }
252 
253  for( int i=0; i<3; ++i )
254  {
255  stack.tEqnRowIndices[i] = m_tDofNumber[k] + i - m_dofRankOffset;
256  stack.tColIndices[i] = m_tDofNumber[k] + i;
257  }
258  }
259 
261  inline
262  void quadraturePointKernel( localIndex const k,
263  localIndex const q,
264  StackVariables & stack ) const
265  {
266  Base::quadraturePointKernel( k, q, stack, [ =, &stack ] ( real64 const detJ )
267  {
268  stack.localRt[0] -= detJ * ( m_dispJump[k][0] - m_targetIncrementalJump[k][0] );
269  stack.localRt[1] -= detJ * ( ( m_dispJump[k][1] - m_oldDispJump[k][1] ) - m_targetIncrementalJump[k][1] );
270  stack.localRt[2] -= detJ * ( ( m_dispJump[k][2] - m_oldDispJump[k][2] ) - m_targetIncrementalJump[k][2] );
271  } );
272  }
273 
274 
276  inline
277  real64 complete( localIndex const k,
278  StackVariables & stack ) const
279  {
280  GEOS_UNUSED_VAR( k );
281  real64 tractionR[numUdofs];
282  real64 tractionRb[numBdofs];
283 
284  real64 matRRtAtu[3][numUdofs], matRRtAtb[3][numBdofs];
285 
286  // transp(R) * Atu
287  LvArray::tensorOps::Rij_eq_AkiBkj< 3, numUdofs, 3 >( matRRtAtu, stack.localRotationMatrix, stack.localAtu );
288  // transp(R) * Atb
289  LvArray::tensorOps::Rij_eq_AkiBkj< 3, numBdofs, 3 >( matRRtAtb, stack.localRotationMatrix, stack.localAtb );
290 
291  LvArray::tensorOps::copy< numTdofs, numUdofs >( stack.localAtu, matRRtAtu );
292  LvArray::tensorOps::copy< numTdofs, numBdofs >( stack.localAtb, matRRtAtb );
293 
294  LvArray::tensorOps::scale< numTdofs, numUdofs >( stack.localAtu, -1.0 );
295  LvArray::tensorOps::scale< numTdofs, numBdofs >( stack.localAtb, -1.0 );
296 
297  LvArray::tensorOps::transpose< numUdofs, numTdofs >( stack.localAut, stack.localAtu );
298  LvArray::tensorOps::transpose< numBdofs, numTdofs >( stack.localAbt, stack.localAtb );
299 
300  // Compute the traction contribute of the local residuals
301  LvArray::tensorOps::Ri_eq_AijBj< numUdofs, numTdofs >( tractionR, stack.localAut, m_traction[k] );
302  LvArray::tensorOps::Ri_eq_AijBj< numBdofs, numTdofs >( tractionRb, stack.localAbt, m_traction[k] );
303 
304  // Compute the local residuals
305  // Force Balance for nodal displacement dofs
306  LvArray::tensorOps::scaledAdd< numUdofs >( stack.localRu, tractionR, 1.0 );
307  // Force Balance for the bubble dofs
308  LvArray::tensorOps::scaledAdd< numBdofs >( stack.localRb, tractionRb, 1.0 );
309 
310  fillGlobalMatrix( stack );
311 
312  return 0.0;
313  }
314 
315 protected:
316 
317  arrayView2d< real64 const > const m_traction;
318 
319  arrayView1d< globalIndex const > const m_tDofNumber;
320 
321  arrayView2d< real64 const, nodes::INCR_DISPLACEMENT_USD > const m_incrDisp;
322 
323  arrayView2d< real64 const > const m_incrBubbleDisp;
324 
325  arrayView2d< real64 const > const m_targetIncrementalJump;
326 
333  void updateStickSlipList( DomainPartition const & domain );
334 
340  void createFaceTypeList( DomainPartition const & domain );
341 
347  void createBubbleCellList( DomainPartition & domain ) const;
348 
355  void fillGlobalMatrix( StackVariables & stack ) const
356  {
357 
358  for( localIndex i=0; i < numTdofs; ++i )
359  {
360  localIndex const dof = LvArray::integerConversion< localIndex >( stack.tEqnRowIndices[ i ] );
361 
362  if( dof < 0 || dof >= m_matrix.numRows() ) continue;
363 
364  // TODO: May not need to be an atomic operation
365  RAJA::atomicAdd< parallelDeviceAtomic >( &m_rhs[dof], stack.localRt[i] );
366 
367  // Fill in matrix block Att
368  m_matrix.template addToRowBinarySearchUnsorted< parallelDeviceAtomic >( dof,
369  stack.tColIndices,
370  stack.localAtt[i],
371  numTdofs );
372 
373  // Fill in matrix block Atu
374  m_matrix.template addToRowBinarySearchUnsorted< parallelDeviceAtomic >( dof,
375  stack.dispColIndices,
376  stack.localAtu[i],
377  numUdofs );
378 
379  // Fill in matrix block Atb
380  m_matrix.template addToRowBinarySearchUnsorted< parallelDeviceAtomic >( dof,
381  stack.bColIndices,
382  stack.localAtb[i],
383  numBdofs );
384  }
385 
386  for( localIndex i=0; i < numUdofs; ++i )
387  {
388  localIndex const dof = LvArray::integerConversion< localIndex >( stack.dispEqnRowIndices[ i ] );
389 
390  if( dof < 0 || dof >= m_matrix.numRows() ) continue;
391 
392  // Is it necessary? Each row should be indepenedent
393  RAJA::atomicAdd< parallelDeviceAtomic >( &m_rhs[dof], stack.localRu[i] );
394 
395  // Fill in matrix
396  m_matrix.template addToRowBinarySearchUnsorted< parallelDeviceAtomic >( dof,
397  stack.tColIndices,
398  stack.localAut[i],
399  numTdofs );
400 
401  }
402 
403  for( localIndex i=0; i < numBdofs; ++i )
404  {
405  localIndex const dof = LvArray::integerConversion< localIndex >( stack.bEqnRowIndices[ i ] );
406 
407  if( dof < 0 || dof >= m_matrix.numRows() ) continue;
408 
409  // Is it necessary? Each row should be indepenedent
410  RAJA::atomicAdd< parallelDeviceAtomic >( &m_rhs[dof], stack.localRb[i] );
411 
412  // Fill in matrix
413  m_matrix.template addToRowBinarySearchUnsorted< parallelDeviceAtomic >( dof,
414  stack.tColIndices,
415  stack.localAbt[i],
416  numTdofs );
417  }
418  }
419 
420 };
421 
423 using LagrangeContactFactory = finiteElement::InterfaceKernelFactory< LagrangeContact,
426  globalIndex const,
428  arrayView1d< real64 > const,
429  real64 const,
431  string const >;
432 
433 } // namespace solidMechanicsLagrangeContactKernels
434 
435 } // namespace geos
436 
437 
438 #endif /* GEOS_PHYSICSSOLVERS_CONTACT_KERNELS_SOLIDMECHANICSLAGRANGECONTACTKERNELS_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
Partition of the decomposed physical domain. It also manages the connexion information to its neighbo...
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
Used to forward arguments to a class that implements the InterfaceKernelBase interface.
ArrayOfArraysView< localIndex const > const m_faceToNodes
The array of array containing the face to node map.
static constexpr int numTdofs
The number of lagrange multiplier dofs per element.
arrayView2d< real64 const > const m_oldDispJump
The array containing the displacement jump of previus time step.
arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const m_X
The array containing the nodal position array.
arrayView3d< real64 const > const m_rotationMatrix
The array containing the rotation matrix for each element.
arrayView1d< globalIndex const > const m_bDofNumber
The global degree of freedom number of bubble.
arrayView2d< localIndex const > const m_elemsToFaces
The array of array containing the element to face map.
arrayView2d< real64 > const m_dispJump
The array containing the displacement jump.
Define the base interface for implicit finite element kernels.
static constexpr int numQuadraturePointsPerElem
Compile time value for the number of quadrature points per element.
GEOS_HOST_DEVICE void fillGlobalMatrix(StackVariables &stack) const
Fill global matrix and residual vector.
void createBubbleCellList(DomainPartition &domain) const
Create the list of elements belonging to CellElementSubRegion that are enriched with the bubble basis...
LagrangeContact(NodeManager const &nodeManager, EdgeManager const &edgeManager, FaceManager const &faceManager, localIndex const targetRegionIndex, FaceElementSubRegion &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, arrayView1d< localIndex const > const &faceElementList, string const tractionDofKey)
Constructor.
void updateStickSlipList(DomainPartition const &domain)
Create the list of finite elements of the same type for each FaceElementSubRegion (Triangle or Quadri...
void createFaceTypeList(DomainPartition const &domain)
Create the list of finite elements of the same type for each FaceElementSubRegion (Triangle or Quadri...
GEOS_HOST_DEVICE void setup(localIndex const k, StackVariables &stack) const
Copy global values from primary field to a local stack 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
array1d< globalIndex > globalIndex_array
A 1-dimensional array of geos::globalIndex types.
Definition: DataTypes.hpp:401
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
localIndex bEqnRowIndices[numBdofs]
C-array storage for the element local row degrees of freedom.
localIndex dispEqnRowIndices[numUdofs]
C-array storage for the element local row degrees of freedom.
globalIndex bColIndices[numBdofs]
C-array storage for the element local column degrees of freedom.
real64 dbLocal[numBdofs]
Stack storage for the element local incremental bubble displacement vector.
real64 localRu[numUdofs]
C-array storage for the element local Ru residual vector.
real64 localAtt[numTdofs][numTdofs]
C-array storage for the element local Att matrix.
real64 localAut[numUdofs][numTdofs]
C-array storage for the element local Aut matrix.
real64 localRt[numTdofs]
C-array storage for the element local Rt residual vector.
real64 localRb[numBdofs]
C-array storage for the element local Rb residual vector.
localIndex tEqnRowIndices[numTdofs]
C-array storage for the traction local row degrees of freedom.
real64 localAbt[numBdofs][numTdofs]
C-array storage for the element local Abt matrix.
real64 duLocal[numUdofs]
Stack storage for the element local incremental displacement vector.
globalIndex tColIndices[numTdofs]
C-array storage for the element local column degrees of freedom.
globalIndex dispColIndices[numUdofs]
C-array storage for the element local column degrees of freedom.