GEOS
ExplicitMPM.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 
16 
21 #ifndef GEOS_PHYSICSSOLVERS_CONTACT_EXPLICITMPM_HPP_
22 #define GEOS_PHYSICSSOLVERS_CONTACT_EXPLICITMPM_HPP_
23 
24 #include "constitutive/solid/SolidUtilities.hpp"
26 #include "physicsSolvers/solidMechanics/MPMSolverFields.hpp"
27 
28 namespace geos
29 {
30 
31 namespace solidMechanicsMPMKernels
32 {
33 
34 // A helper function to calculate polar decomposition. TODO: Previously this was an LvArray method, hopefully it will be again someday.
36 static inline void polarDecomposition( real64 (& R)[3][3],
37  real64 const (&matrix)[3][3] )
38 {
39  // Initialize
40  LvArray::tensorOps::copy< 3, 3 >( R, matrix );
41  real64 RInverse[3][3] = { {0} },
42  RInverseTranspose[3][3] = { {0} },
43  RRTMinusI[3][3] = { {0} };
44 
45  // Higham Algorithm
46  real64 errorSquared = 1.0;
47  real64 tolerance = 10 * LvArray::NumericLimits< real64 >::epsilon;
48  int iter = 0;
49  while( errorSquared > tolerance * tolerance && iter < 100 )
50  {
51  iter++;
52  errorSquared = 0.0;
53 
54  // Average the current R with its inverse tranpose
55  LvArray::tensorOps::internal::SquareMatrixOps< 3 >::invert( RInverse, R );
56  LvArray::tensorOps::transpose< 3, 3 >( RInverseTranspose, RInverse );
57  LvArray::tensorOps::add< 3, 3 >( R, RInverseTranspose );
58  LvArray::tensorOps::scale< 3, 3 >( R, 0.5 );
59 
60  // Determine how close R is to being orthogonal using L2Norm(R.R^T-I)
61  real64 copyR[3][3];
62  LvArray::tensorOps::copy< 3, 3 >( copyR, R );
63  LvArray::tensorOps::Rij_eq_AikBjk< 3, 3, 3 >( RRTMinusI, R, copyR );
64  LvArray::tensorOps::addIdentity< 3 >( RRTMinusI, -1.0 );
65  for( std::ptrdiff_t i = 0; i < 3; i++ )
66  {
67  for( std::ptrdiff_t j = 0; j < 3; j++ )
68  {
69  errorSquared += RRTMinusI[i][j] * RRTMinusI[i][j];
70  }
71  }
72  }
73  if( iter == 100 )
74  {
75  GEOS_LOG_RANK( "Polar decomposition did not converge in 100 iterations!" );
76  }
77 }
78 
79 
84 {
95  template< typename POLICY, typename CONSTITUTIVE_WRAPPER >
96  static void launch( SortedArrayView< localIndex const > const indices,
97  CONSTITUTIVE_WRAPPER const & constitutiveWrapper,
98  real64 dt,
99  arrayView3d< real64 const > const deformationGradient,
100  arrayView3d< real64 const > const fDot,
101  arrayView3d< real64 const > const velocityGradient,
102  arrayView2d< real64 > const particleStress )
103  {
104  arrayView3d< real64, solid::STRESS_USD > const oldStress = constitutiveWrapper.m_oldStress;
105  // arrayView3d< real64, solid::STRESS_USD > const newStress = constitutiveWrapper.m_newStress;
106 
107  // Perform constitutive call
108  forAll< POLICY >( indices.size(), [=] GEOS_HOST_DEVICE ( localIndex const k )
109  {
110  // Particle index
111  localIndex const p = indices[k];
112 
113  // Copy the beginning-of-step particle stress into the constitutive model's m_oldStress - this fixes the MPI sync issue on Lassen for
114  // some reason
115  #if defined(GEOS_USE_CUDA)
116  LvArray::tensorOps::copy< 6 >( oldStress[p][0], particleStress[p] );
117  #endif
118 
119  // Determine the strain increment in Voigt notation
120  real64 strainIncrement[6];
121  strainIncrement[0] = velocityGradient[p][0][0] * dt;
122  strainIncrement[1] = velocityGradient[p][1][1] * dt;
123  strainIncrement[2] = velocityGradient[p][2][2] * dt;
124  strainIncrement[3] = (velocityGradient[p][1][2] + velocityGradient[p][2][1]) * dt;
125  strainIncrement[4] = (velocityGradient[p][0][2] + velocityGradient[p][2][0]) * dt;
126  strainIncrement[5] = (velocityGradient[p][0][1] + velocityGradient[p][1][0]) * dt;
127 
128  // Get old F by incrementing backwards
129  real64 fOld[3][3] = { {0} };
130  real64 fNew[3][3] = { {0} };
131  LvArray::tensorOps::copy< 3, 3 >( fNew, deformationGradient[p] );
132  LvArray::tensorOps::copy< 3, 3 >( fOld, deformationGradient[p] );
133  LvArray::tensorOps::scaledAdd< 3, 3 >( fOld, fDot[p], -dt );
134 
135  // Polar decompositions
136  real64 rotBeginning[3][3] = { {0} };
137  real64 rotEnd[3][3] = { {0} };
138  polarDecomposition( rotBeginning, fOld );
139  polarDecomposition( rotEnd, fNew );
140 
141  // Call stress update
142  real64 stress[6] = { 0 };
143  constitutive::SolidUtilities::hypoUpdate2_StressOnly( constitutiveWrapper, // the constitutive model
144  p, // particle local index
145  0, // particles have 1 quadrature point
146  dt, // time step size
147  strainIncrement, // particle strain increment
148  rotBeginning, // beginning-of-step rotation matrix
149  rotEnd, // end-of-step rotation matrix
150  stress ); // final updated stress
151 
152  // Copy the updated stress into particleStress
153  LvArray::tensorOps::copy< 6 >( particleStress[p], stress );
154 
155  // Copy m_newStress into m_oldStress
156  constitutiveWrapper.saveConvergedState( p, 0 );
157  } );
158  }
159 };
160 
161 } // namespace solidMechanicsMPMKernels
162 
163 } // namespace geos
164 
165 
166 #endif /* GEOS_PHYSICSSOLVERS_CONTACT_EXPLICITMPM_HPP_ */
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
#define GEOS_LOG_RANK(msg)
Log a message to the rank output stream.
Definition: Logger.hpp:126
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
LvArray::SortedArrayView< T, localIndex, LvArray::ChaiBuffer > SortedArrayView
A sorted array view of local indices.
Definition: DataTypes.hpp:271
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
Definition: DataTypes.hpp:196
ArrayView< T, 3, USD > arrayView3d
Alias for 3D array view.
Definition: DataTypes.hpp:212
A struct to update particle stresses.
Definition: ExplicitMPM.hpp:84
static void launch(SortedArrayView< localIndex const > const indices, CONSTITUTIVE_WRAPPER const &constitutiveWrapper, real64 dt, arrayView3d< real64 const > const deformationGradient, arrayView3d< real64 const > const fDot, arrayView3d< real64 const > const velocityGradient, arrayView2d< real64 > const particleStress)
Launch the kernel function doing constitutive updates.
Definition: ExplicitMPM.hpp:96