GEOS
ImplicitRateAndStateKernels.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) 2018-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 #ifndef GEOS_PHYSICSSOLVERS_INDUCEDSEISMICITY_KERNELS_IMPLICITRATEANDSTATEKERNELS_HPP_
17 #define GEOS_PHYSICSSOLVERS_INDUCEDSEISMICITY_KERNELS_IMPLICITRATEANDSTATEKERNELS_HPP_
18 
19 #include "RateAndStateKernelsBase.hpp"
20 #include "denseLinearAlgebra/denseLASolvers.hpp"
21 
22 namespace geos
23 {
24 
25 namespace rateAndStateKernels
26 {
27 
36 {
37 public:
38 
40  constitutive::RateAndStateFriction const & frictionLaw,
41  real64 const shearImpedance ):
42  m_slipRate( subRegion.getField< fields::rateAndState::slipRate >() ),
43  m_stateVariable( subRegion.getField< fields::rateAndState::stateVariable >() ),
44  m_stateVariable_n( subRegion.getField< fields::rateAndState::stateVariable_n >() ),
45  m_slipRate_n( subRegion.getField< fields::rateAndState::slipRate_n >() ),
46  m_normalTraction( subRegion.getField< fields::rateAndState::normalTraction >() ),
47  m_shearTraction( subRegion.getField< fields::rateAndState::shearTraction >() ),
48  m_slipVelocity( subRegion.getField< fields::rateAndState::slipVelocity >() ),
49  m_shearImpedance( shearImpedance ),
50  m_frictionLaw( frictionLaw.createKernelUpdates() )
51  {}
52 
58  {
59 public:
60 
61  StackVariables( ) = default;
62 
63  real64 jacobian[2][2]{};
64 
65  real64 rhs[2]{};
66 
67  };
68 
70  void setup( localIndex const k,
71  real64 const dt,
72  StackVariables & stack ) const
73  {
74  real64 const normalTraction = m_normalTraction[k];
75  real64 const shearTractionMagnitude = LvArray::tensorOps::l2Norm< 2 >( m_shearTraction[k] );
76 
77  // Eq 1: Scalar force balance for slipRate and shear traction magnitude
78  stack.rhs[0] = shearTractionMagnitude - m_shearImpedance * m_slipRate[k]
79  - normalTraction * m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] );
80  real64 const dFriction[2] = { -normalTraction * m_frictionLaw.dFrictionCoefficient_dStateVariable( k, m_slipRate[k], m_stateVariable[k] ),
81  -m_shearImpedance - normalTraction * m_frictionLaw.dFrictionCoefficient_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) };
82 
83  // Eq 2: slip law
84  stack.rhs[1] = (m_stateVariable[k] - m_stateVariable_n[k]) / dt - m_frictionLaw.stateEvolution( k, m_slipRate[k], m_stateVariable[k] );
85  real64 const dStateEvolutionLaw[2] = { 1.0 / dt - m_frictionLaw.dStateEvolution_dStateVariable( k, m_slipRate[k], m_stateVariable[k] ),
86  -m_frictionLaw.dStateEvolution_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) };
87 
88  // Assemble Jacobian matrix
89  stack.jacobian[0][0] = dFriction[0]; // derivative of Eq 1 w.r.t. stateVariable
90  stack.jacobian[0][1] = dFriction[1]; // derivative of Eq 1 w.r.t. slipRate
91  stack.jacobian[1][0] = dStateEvolutionLaw[0]; // derivative of Eq 2 w.r.t. stateVariable
92  stack.jacobian[1][1] = dStateEvolutionLaw[1]; // derivative of Eq 2 w.r.t. slipRate
93  }
94 
96  void solve( localIndex const k,
97  StackVariables & stack ) const
98  {
100  real64 solution[2] = {0.0, 0.0};
101  LvArray::tensorOps::scale< 2 >( stack.rhs, -1.0 );
102  denseLinearAlgebra::solve< 2 >( stack.jacobian, stack.rhs, solution );
103 
104  // Slip rate is bracketed between [0, shear traction magnitude / shear impedance]
105  // Check that the update did not end outside of the bracket.
106  real64 const shearTractionMagnitude = LvArray::tensorOps::l2Norm< 2 >( m_shearTraction[k] );
107  real64 const upperBound = shearTractionMagnitude / m_shearImpedance - m_slipRate[k];
108  real64 const lowerBound = -m_slipRate[k];
109 
110  real64 scalingFactor = 1.0;
111  if( solution[1] > upperBound )
112  {
113  scalingFactor = 0.5 * upperBound / solution[1];
114  }
115  else if( solution[1] < lowerBound )
116  {
117  scalingFactor = 0.5 * lowerBound / solution[1];
118  }
119 
120  LvArray::tensorOps::scale< 2 >( solution, scalingFactor );
121 
122  // Update variables
123  m_stateVariable[k] += solution[0];
124  m_slipRate[k] += solution[1];
125  }
126 
128  void projectSlipRate( localIndex const k ) const
129  {
130  real64 const frictionCoefficient = m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] );
131  projectSlipRateBase( k, frictionCoefficient, m_shearImpedance, m_normalTraction, m_shearTraction, m_slipRate, m_slipVelocity );
132  }
133 
135  void udpateVariables( localIndex const k ) const
136  {
137  projectSlipRate( k );
138  m_stateVariable_n[k] = m_stateVariable[k];
139  m_slipRate_n[k] = m_slipRate[k];
140  }
141 
143  camp::tuple< int, real64 > checkConvergence( StackVariables const & stack,
144  real64 const tol ) const
145  {
146  real64 const residualNorm = LvArray::tensorOps::l2Norm< 2 >( stack.rhs );
147  int const converged = residualNorm < tol ? 1 : 0;
148  camp::tuple< int, real64 > result { converged, residualNorm };
149  return result;
150  }
151 
153  void resetState( localIndex const k ) const
154  {
155  m_stateVariable[k] = m_stateVariable_n[k];
156  m_slipRate[k] = m_slipRate_n[k];
157  }
158 
159  template< typename POLICY >
160  static real64 solveRateAndStateEquation( SurfaceElementSubRegion & subRegion,
161  ImplicitFixedStressRateAndStateKernel & kernel,
162  real64 dt,
163  integer const maxNewtonIter,
164  real64 const newtonTol )
165  {
166  bool converged = false;
167  for( integer attempt = 0; attempt < 5; attempt++ )
168  {
169  if( attempt > 0 )
170  {
171  forAll< POLICY >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k )
172  {
173  kernel.resetState( k );
174  } );
175  }
176  GEOS_LOG_RANK_0( GEOS_FMT( " Attempt {} ", attempt ) );
177  converged = newtonSolve< POLICY >( subRegion, kernel, dt, maxNewtonIter, newtonTol );
178  if( converged )
179  {
180  forAll< POLICY >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k )
181  {
182  kernel.udpateVariables( k );
183  } );
184  return dt;
185  }
186  else
187  {
188  GEOS_LOG_RANK_0( GEOS_FMT( " Attempt {} failed. Halving dt and retrying.", attempt ) );
189  dt *= 0.5;
190  }
191  }
192  if( !converged )
193  {
194  GEOS_ERROR( "Maximum number of attempts reached without convergence." );
195  }
196  return dt;
197  }
198 
199 private:
200 
201  arrayView1d< real64 > const m_slipRate;
202 
203  arrayView1d< real64 > const m_stateVariable;
204 
205  arrayView1d< real64 > const m_stateVariable_n;
206 
207  arrayView1d< real64 > const m_slipRate_n;
208 
209  arrayView1d< real64 > const m_normalTraction;
210 
211  arrayView2d< real64 > const m_shearTraction;
212 
213  arrayView2d< real64 > const m_slipVelocity;
214 
215  real64 const m_shearImpedance;
216 
217  constitutive::RateAndStateFriction::KernelWrapper m_frictionLaw;
218 
219 };
220 
221 } /* namespace rateAndStateKernels */
222 
223 } /* namespace geos */
224 
225 #endif /* GEOS_PHYSICSSOLVERS_INDUCEDSEISMICITY_KERNELS_IMPLICITRATEANDSTATEKERNELS_HPP_ */
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
#define GEOS_ERROR(msg)
Raise a hard error and terminate the program.
Definition: Logger.hpp:157
#define GEOS_LOG_RANK_0(msg)
Log a message on screen on rank 0.
Definition: Logger.hpp:101
GEOS_DECLTYPE_AUTO_RETURN getField() const
Get a view to the field associated with a trait from this ObjectManagerBase.
GEOS_HOST_DEVICE void solve(localIndex const k, StackVariables &stack) const
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