16 #ifndef GEOS_PHYSICSSOLVERS_INDUCEDSEISMICITY_KERNELS_EXPLICITRATEANDSTATEKERNELS_HPP_
17 #define GEOS_PHYSICSSOLVERS_INDUCEDSEISMICITY_KERNELS_EXPLICITRATEANDSTATEKERNELS_HPP_
19 #include "RateAndStateKernelsBase.hpp"
20 #include "denseLinearAlgebra/denseLASolvers.hpp"
26 namespace rateAndStateKernels
41 constitutive::RateAndStateFriction
const & frictionLaw,
42 real64 const shearImpedance ):
43 m_slipRate( subRegion.
getField< fields::rateAndState::slipRate >() ),
44 m_stateVariable( subRegion.
getField< fields::rateAndState::stateVariable >() ),
45 m_normalTraction( subRegion.
getField< fields::rateAndState::normalTraction >() ),
46 m_shearTraction( subRegion.
getField< fields::rateAndState::shearTraction >() ),
47 m_slipVelocity( subRegion.
getField< fields::rateAndState::slipVelocity >() ),
48 m_shearImpedance( shearImpedance ),
49 m_frictionLaw( frictionLaw.createKernelUpdates() )
73 real64 const normalTraction = m_normalTraction[k];
74 real64 const shearTractionMagnitude = LvArray::tensorOps::l2Norm< 2 >( m_shearTraction[k] );
78 real64 const upperBound = shearTractionMagnitude/m_shearImpedance;
79 real64 const bracketedSlipRate = m_slipRate[k] > upperBound ? 0.5*upperBound : m_slipRate[k];
81 stack.rhs = shearTractionMagnitude - m_shearImpedance *bracketedSlipRate - normalTraction * m_frictionLaw.frictionCoefficient( k, bracketedSlipRate, m_stateVariable[k] );
82 stack.jacobian = -m_shearImpedance - normalTraction * m_frictionLaw.dFrictionCoefficient_dSlipRate( k, bracketedSlipRate, m_stateVariable[k] );
87 StackVariables & stack )
const
89 m_slipRate[k] -= stack.rhs/stack.jacobian;
93 real64 const shearTractionMagnitude = LvArray::tensorOps::l2Norm< 2 >( m_shearTraction[k] );
94 real64 const upperBound = shearTractionMagnitude/m_shearImpedance;
95 if( m_slipRate[k] > upperBound ) m_slipRate[k] = 0.5*upperBound;
101 camp::tuple< int, real64 > checkConvergence( StackVariables
const & stack,
104 real64 const residualNorm = LvArray::math::abs( stack.rhs );
105 int const converged = residualNorm < tol ? 1 : 0;
106 camp::tuple< int, real64 > result { converged, residualNorm };
111 void projectSlipRate(
localIndex const k )
const
113 real64 const frictionCoefficient = m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] );
114 projectSlipRateBase( k, frictionCoefficient, m_shearImpedance, m_normalTraction, m_shearTraction, m_slipRate, m_slipVelocity );
118 void udpateVariables(
localIndex const k )
const
120 projectSlipRate( k );
134 template<
typename POLICY >
144 newtonSolve< POLICY >( subRegion, kernel, dt, maxNewtonIter, newtonTol );
148 kernel.projectSlipRate( k );
165 real64 const m_shearImpedance;
167 constitutive::RateAndStateFriction::KernelWrapper m_frictionLaw;
178 integer constexpr
static algHighOrder = 3;
179 integer constexpr
static algLowOrder = 2;
180 integer constexpr
static numStages = 3;
181 real64 const a[2][2] = { { 1.0/2.0, 0.0 },
183 real64 const c[3] = { 0.0, 1.0/2.0, 1.0 };
184 real64 const b[3] = { 1.0/6.0, 4.0/6.0, 1.0/6.0 };
185 real64 const bStar[3] = { 1.0/2.0, 0.0, 1.0/2.0 };
186 real64 constexpr
static FSAL =
false;
194 integer constexpr
static algHighOrder = 3;
195 integer constexpr
static algLowOrder = 2;
196 integer constexpr
static numStages = 4;
197 real64 const a[3][3] = { { 1.0/2.0, 0.0, 0.0 },
198 { 0.0, 3.0/4.0, 0.0 },
199 { 2.0/9.0, 1.0/3.0, 4.0/9.0 } };
200 real64 const c[4] = { 0.0, 1.0/2.0, 3.0/4.0, 1.0 };
201 real64 const b[4] = { 2.0/9.0, 1.0/3.0, 4.0/9.0, 0.0 };
202 real64 const bStar[4] = { 7.0/24.0, 1.0/4.0, 1.0/3.0, 1.0/8.0};
203 bool constexpr
static FSAL =
true;
214 template<
typename TABLE_TYPE >
220 constitutive::RateAndStateFriction
const & frictionLaw,
221 TABLE_TYPE butcherTable ):
222 m_stateVariable( subRegion.
getField< fields::rateAndState::stateVariable >() ),
223 m_stateVariable_n( subRegion.
getField< fields::rateAndState::stateVariable_n >() ),
224 m_slipRate( subRegion.
getField< fields::rateAndState::slipRate >() ),
225 m_slipVelocity( subRegion.
getField< fields::rateAndState::slipVelocity >() ),
226 m_slipVelocity_n( subRegion.
getField< fields::rateAndState::slipVelocity_n >() ),
227 m_deltaSlip( subRegion.
getField< fields::contact::deltaSlip >() ),
228 m_deltaSlip_n( subRegion.
getField< fields::contact::deltaSlip_n >() ),
229 m_dispJump( subRegion.
getField< fields::contact::dispJump >() ),
230 m_dispJump_n( subRegion.
getField< fields::contact::dispJump_n >() ),
231 m_error( subRegion.
getField< fields::rateAndState::error >() ),
232 m_stageRates( subRegion.
getField< fields::rateAndState::rungeKuttaStageRates >() ),
233 m_frictionLaw( frictionLaw.createKernelUpdates() ),
234 m_butcherTable( butcherTable )
243 LvArray::tensorOps::copy< 2 >( m_slipVelocity[k], m_slipVelocity_n[k] );
244 m_slipRate[k] = LvArray::tensorOps::l2Norm< 2 >( m_slipVelocity_n[k] );
245 m_stateVariable[k] = m_stateVariable_n[k];
255 LvArray::tensorOps::copy< 3 >( m_stageRates[k][0], m_stageRates[k][m_butcherTable.numStages-1] );
264 m_stageRates[k][stageIndex][0] = m_slipVelocity[k][0];
265 m_stageRates[k][stageIndex][1] = m_slipVelocity[k][1];
266 m_stageRates[k][stageIndex][2] = m_frictionLaw.stateEvolution( k, m_slipRate[k], m_stateVariable[k] );
276 real64 stateVariableIncrement = 0.0;
277 real64 deltaSlipIncrement[2] = {0.0, 0.0};
279 for(
integer i = 0; i < stageIndex; i++ )
281 deltaSlipIncrement[0] += m_butcherTable.a[stageIndex-1][i] * m_stageRates[k][i][0];
282 deltaSlipIncrement[1] += m_butcherTable.a[stageIndex-1][i] * m_stageRates[k][i][1];
283 stateVariableIncrement += m_butcherTable.a[stageIndex-1][i] * m_stageRates[k][i][2];
285 m_deltaSlip[k][0] = m_deltaSlip_n[k][0] + dt*deltaSlipIncrement[0];
286 m_deltaSlip[k][1] = m_deltaSlip_n[k][1] + dt*deltaSlipIncrement[1];
287 m_stateVariable[k] = m_stateVariable_n[k] + dt*stateVariableIncrement;
289 m_dispJump[k][1] = m_dispJump_n[k][1] + m_deltaSlip[k][0];
290 m_dispJump[k][2] = m_dispJump_n[k][2] + m_deltaSlip[k][1];
301 real64 deltaSlipIncrement[2] = {0.0, 0.0};
302 real64 deltaSlipIncrementLowOrder[2] = {0.0, 0.0};
304 real64 stateVariableIncrement = 0.0;
305 real64 stateVariableIncrementLowOrder = 0.0;
307 for(
localIndex i = 0; i < m_butcherTable.numStages; i++ )
311 deltaSlipIncrement[0] += m_butcherTable.b[i] * m_stageRates[k][i][0];
312 deltaSlipIncrement[1] += m_butcherTable.b[i] * m_stageRates[k][i][1];
313 stateVariableIncrement += m_butcherTable.b[i] * m_stageRates[k][i][2];
316 deltaSlipIncrementLowOrder[0] += m_butcherTable.bStar[i] * m_stageRates[k][i][0];
317 deltaSlipIncrementLowOrder[1] += m_butcherTable.bStar[i] * m_stageRates[k][i][1];
318 stateVariableIncrementLowOrder += m_butcherTable.bStar[i] * m_stageRates[k][i][2];
321 m_deltaSlip[k][0] = m_deltaSlip_n[k][0] + dt * deltaSlipIncrement[0];
322 m_deltaSlip[k][1] = m_deltaSlip_n[k][1] + dt * deltaSlipIncrement[1];
323 m_stateVariable[k] = m_stateVariable_n[k] + dt * stateVariableIncrement;
325 real64 const deltaSlipLowOrder[2] = {m_deltaSlip_n[k][0] + dt * deltaSlipIncrementLowOrder[0],
326 m_deltaSlip_n[k][1] + dt * deltaSlipIncrementLowOrder[1]};
327 real64 const stateVariableLowOrder = m_stateVariable_n[k] + dt * stateVariableIncrementLowOrder;
329 m_dispJump[k][1] = m_dispJump_n[k][1] + m_deltaSlip[k][0];
330 m_dispJump[k][2] = m_dispJump_n[k][2] + m_deltaSlip[k][1];
333 m_error[k][0] =
computeError( m_deltaSlip[k][0], deltaSlipLowOrder[0], absTol, relTol );
334 m_error[k][1] =
computeError( m_deltaSlip[k][1], deltaSlipLowOrder[1], absTol, relTol );
335 m_error[k][2] =
computeError( m_stateVariable[k], stateVariableLowOrder, absTol, relTol );
346 real64 deltaSlipIncrementLowOrder[2] = {0.0, 0.0};
347 real64 stateVariableIncrementLowOrder = 0.0;
349 for(
localIndex i = 0; i < m_butcherTable.numStages; i++ )
354 deltaSlipIncrementLowOrder[0] += m_butcherTable.bStar[i] * m_stageRates[k][i][0];
355 deltaSlipIncrementLowOrder[1] += m_butcherTable.bStar[i] * m_stageRates[k][i][1];
356 stateVariableIncrementLowOrder += m_butcherTable.bStar[i] * m_stageRates[k][i][2];
359 real64 const deltaSlipLowOrder[2] = {m_deltaSlip_n[k][0] + dt * deltaSlipIncrementLowOrder[0],
360 m_deltaSlip_n[k][1] + dt * deltaSlipIncrementLowOrder[1]};
361 real64 const stateVariableLowOrder = m_stateVariable_n[k] + dt * stateVariableIncrementLowOrder;
363 m_dispJump[k][1] = m_dispJump_n[k][1] + m_deltaSlip[k][0];
364 m_dispJump[k][2] = m_dispJump_n[k][2] + m_deltaSlip[k][1];
367 m_error[k][0] =
computeError( m_deltaSlip[k][0], deltaSlipLowOrder[0], absTol, relTol );
368 m_error[k][1] =
computeError( m_deltaSlip[k][1], deltaSlipLowOrder[1], absTol, relTol );
369 m_error[k][2] =
computeError( m_stateVariable[k], stateVariableLowOrder, absTol, relTol );
378 return (highOrderApprox - lowOrderApprox) /
379 ( absTol + relTol * LvArray::math::max( LvArray::math::abs( highOrderApprox ), LvArray::math::abs( lowOrderApprox ) ));
418 constitutive::RateAndStateFriction::KernelWrapper m_frictionLaw;
421 TABLE_TYPE m_butcherTable;
#define GEOS_HOST_DEVICE
Marks a host-device function.
#define GEOS_UNUSED_VAR(...)
Mark an unused variable and silence compiler warnings.
#define GEOS_MARK_FUNCTION
Mark function with both Caliper and NVTX if enabled.
GEOS_DECLTYPE_AUTO_RETURN getField() const
Get a view to the field associated with a trait from this ObjectManagerBase.
localIndex size() const
Get the "size" of the group, which determines the number of elements in resizable wrappers.
Runge-Kutta method used to time integrate slip and state. Uses of a high order update used to integra...
GEOS_HOST_DEVICE real64 computeError(real64 const highOrderApprox, real64 const lowOrderApprox, real64 const absTol, real64 const relTol) const
Computes the relative error scaled by error tolerances.
GEOS_HOST_DEVICE void updateSolutionAndLocalError(localIndex const k, real64 const dt, real64 const absTol, real64 const relTol) const
Updates slip, state and displacement jump to the next time computes error the local error in the time...
GEOS_HOST_DEVICE void updateStageRates(localIndex const k, integer const stageIndex) const
Updates the stage rates rates (the right-hand-side of the ODEs for slip and state)
GEOS_HOST_DEVICE void updateStageRatesFSAL(localIndex const k) const
Re-uses the last stage rate from the previous time step as the first in the next update....
GEOS_HOST_DEVICE void updateStageValues(localIndex const k, integer const stageIndex, real64 const dt) const
Update stage values (slip, state and displacement jump) to a Runge-Kutta substage.
GEOS_HOST_DEVICE void initialize(localIndex const k) const
Initialize slip and state buffers.
GEOS_HOST_DEVICE void updateSolutionAndLocalErrorFSAL(localIndex const k, real64 const dt, real64 const absTol, real64 const relTol) const
Updates slip, state and displacement jump to the next time computes error the local error in the time...
static real64 solveRateAndStateEquation(SurfaceElementSubRegion &subRegion, ExplicitRateAndStateKernel &kernel, real64 dt, integer const maxNewtonIter, real64 const newtonTol)
Performs the kernel launch.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
double real64
64-bit floating point type.
GEOS_LOCALINDEX_TYPE localIndex
Local index type (for indexing objects within an MPI partition).
std::int32_t integer
Signed integer type.
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
ArrayView< T, 3, USD > arrayView3d
Alias for 3D array view.
Butcher table for the BogackiShampine 3(2) method.
Kernel variables located on the stack.
Butcher table for embedded RK3(2) method using Kuttas third order method for the high-order update,...