16 #ifndef GEOS_PHYSICSSOLVERS_RATEANDSTATEKERNELS_HPP_
17 #define GEOS_PHYSICSSOLVERS_RATEANDSTATEKERNELS_HPP_
20 #include "common/GEOS_RAJA_Interface.hpp"
21 #include "constitutive/contact/RateAndStateFriction.hpp"
23 #include "denseLinearAlgebra/denseLASolvers.hpp"
28 namespace rateAndStateKernels
34 static void projectSlipRateBase(
localIndex const k,
35 real64 const frictionCoefficient,
36 real64 const shearImpedance,
37 arrayView2d< real64 const >
const traction,
38 arrayView1d< real64 const >
const slipRate,
39 arrayView2d< real64 >
const slipVelocity )
42 real64 const frictionForce = traction[k][0] * frictionCoefficient;
43 real64 const projectionScaling = 1.0 / ( shearImpedance + frictionForce / slipRate[k] );
44 slipVelocity[k][0] = projectionScaling * traction[k][1];
45 slipVelocity[k][1] = projectionScaling * traction[k][2];
60 constitutive::RateAndStateFriction
const & frictionLaw,
61 real64 const shearImpedance ):
62 m_slipRate( subRegion.
getField< fields::rateAndState::slipRate >() ),
63 m_stateVariable( subRegion.
getField< fields::rateAndState::stateVariable >() ),
64 m_stateVariable_n( subRegion.
getField< fields::rateAndState::stateVariable_n >() ),
65 m_traction( subRegion.
getField< fields::contact::traction >() ),
66 m_slipVelocity( subRegion.
getField< fields::rateAndState::slipVelocity >() ),
67 m_shearImpedance( shearImpedance ),
68 m_frictionLaw( frictionLaw.createKernelUpdates() )
94 real64 const normalTraction = m_traction[k][0];
95 real64 const shearTractionMagnitude = LvArray::math::sqrt( m_traction[k][1] * m_traction[k][1] + m_traction[k][2] * m_traction[k][2] );
97 stack.rhs[0] = shearTractionMagnitude - m_shearImpedance * m_slipRate[k]
98 - normalTraction * m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] );
99 real64 const dFriction[2] = { -normalTraction * m_frictionLaw.dFrictionCoefficient_dStateVariable( k, m_slipRate[k], m_stateVariable[k] ),
100 -m_shearImpedance - normalTraction * m_frictionLaw.dFrictionCoefficient_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) };
103 stack.rhs[1] = (m_stateVariable[k] - m_stateVariable_n[k]) / dt - m_frictionLaw.stateEvolution( k, m_slipRate[k], m_stateVariable[k] );
104 real64 const dStateEvolutionLaw[2] = { 1 / dt - m_frictionLaw.dStateEvolution_dStateVariable( k, m_slipRate[k], m_stateVariable[k] ),
105 -m_frictionLaw.dStateEvolution_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) };
108 stack.jacobian[0][0] = dFriction[0];
109 stack.jacobian[0][1] = dFriction[1];
110 stack.jacobian[1][0] = dStateEvolutionLaw[0];
111 stack.jacobian[1][1] = dStateEvolutionLaw[1];
119 real64 solution[2] = {0.0, 0.0};
120 denseLinearAlgebra::solve< 2 >( stack.jacobian, stack.rhs, solution );
123 m_stateVariable[k] -= solution[0];
124 m_slipRate[k] -= solution[1];
128 void projectSlipRate(
localIndex const k )
const
130 real64 const frictionCoefficient = m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] );
131 projectSlipRateBase( k, frictionCoefficient, m_shearImpedance, m_traction, m_slipRate, m_slipVelocity );
135 camp::tuple< int, real64 > checkConvergence( StackVariables
const & stack,
138 real64 const residualNorm = LvArray::tensorOps::l2Norm< 2 >( stack.rhs );
139 int const converged = residualNorm < tol ? 1 : 0;
140 camp::tuple< int, real64 > result { converged, residualNorm };
146 arrayView1d< real64 >
const m_slipRate;
148 arrayView1d< real64 >
const m_stateVariable;
150 arrayView1d< real64 const >
const m_stateVariable_n;
152 arrayView2d< real64 const >
const m_traction;
154 arrayView2d< real64 >
const m_slipVelocity;
156 real64 const m_shearImpedance;
158 constitutive::RateAndStateFriction::KernelWrapper m_frictionLaw;
174 constitutive::RateAndStateFriction
const & frictionLaw,
175 real64 const shearImpedance ):
176 m_slipRate( subRegion.
getField< fields::rateAndState::slipRate >() ),
177 m_stateVariable( subRegion.
getField< fields::rateAndState::stateVariable >() ),
178 m_traction( subRegion.
getField< fields::contact::traction >() ),
179 m_slipVelocity( subRegion.
getField< fields::rateAndState::slipVelocity >() ),
180 m_shearImpedance( shearImpedance ),
181 m_frictionLaw( frictionLaw.createKernelUpdates() )
207 real64 const normalTraction = m_traction[k][0];
208 real64 const shearTractionMagnitude = LvArray::math::sqrt( m_traction[k][1] * m_traction[k][1] + m_traction[k][2] * m_traction[k][2] );
212 real64 const upperBound = shearTractionMagnitude/m_shearImpedance;
213 real64 const bracketedSlipRate = m_slipRate[k] > upperBound ? 0.5*upperBound : m_slipRate[k];
215 stack.rhs = shearTractionMagnitude - m_shearImpedance *bracketedSlipRate - normalTraction * m_frictionLaw.frictionCoefficient( k, bracketedSlipRate, m_stateVariable[k] );
216 stack.jacobian = -m_shearImpedance - normalTraction * m_frictionLaw.dFrictionCoefficient_dSlipRate( k, bracketedSlipRate, m_stateVariable[k] );
221 StackVariables & stack )
const
223 m_slipRate[k] -= stack.rhs/stack.jacobian;
227 real64 const shearTractionMagnitude = LvArray::math::sqrt( m_traction[k][1] * m_traction[k][1] + m_traction[k][2] * m_traction[k][2] );
228 real64 const upperBound = shearTractionMagnitude/m_shearImpedance;
229 if( m_slipRate[k] > upperBound ) m_slipRate[k] = 0.5*upperBound;
235 camp::tuple< int, real64 > checkConvergence( StackVariables
const & stack,
238 real64 const residualNorm = LvArray::math::abs( stack.rhs );
239 int const converged = residualNorm < tol ? 1 : 0;
240 camp::tuple< int, real64 > result { converged, residualNorm };
245 void projectSlipRate(
localIndex const k )
const
247 real64 const frictionCoefficient = m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] );
248 projectSlipRateBase( k, frictionCoefficient, m_shearImpedance, m_traction, m_slipRate, m_slipVelocity );
253 arrayView1d< real64 >
const m_slipRate;
255 arrayView1d< real64 >
const m_stateVariable;
257 arrayView2d< real64 const >
const m_traction;
259 arrayView2d< real64 >
const m_slipVelocity;
261 real64 const m_shearImpedance;
263 constitutive::RateAndStateFriction::KernelWrapper m_frictionLaw;
273 template<
typename KernelType,
typename POLICY >
275 createAndLaunch( SurfaceElementSubRegion & subRegion,
276 string const & frictionLawNameKey,
277 real64 const shearImpedance,
287 string const & frictionaLawName = subRegion.getReference<
string >( frictionLawNameKey );
288 constitutive::RateAndStateFriction
const & frictionLaw = subRegion.getConstitutiveModel< constitutive::RateAndStateFriction >( frictionaLawName );
289 KernelType kernel( subRegion, frictionLaw, shearImpedance );
292 bool allConverged =
false;
293 for(
integer iter = 0; iter < maxIterNewton; iter++ )
295 RAJA::ReduceMin< parallelDeviceReduce, int > converged( 1 );
296 RAJA::ReduceMax< parallelDeviceReduce, real64 > residualNorm( 0.0 );
299 typename KernelType::StackVariables stack;
300 kernel.setup( k, dt, stack );
301 kernel.solve( k, stack );
302 auto const [elementConverged, elementResidualNorm] = kernel.checkConvergence( stack, newtonTol );
303 converged.min( elementConverged );
304 residualNorm.max( elementResidualNorm );
308 GEOS_LOG_RANK_0( GEOS_FMT(
"-----iter {} : residual = {:.10e} ", iter, maxResidualNorm ) );
310 if( converged.get() )
322 kernel.projectSlipRate( k );
333 integer constexpr
static algHighOrder = 3;
334 integer constexpr
static algLowOrder = 2;
335 integer constexpr
static numStages = 3;
336 real64 const a[2][2] = { { 1.0/2.0, 0.0 },
338 real64 const c[3] = { 0.0, 1.0/2.0, 1.0 };
339 real64 const b[3] = { 1.0/6.0, 4.0/6.0, 1.0/6.0 };
340 real64 const bStar[3] = { 1.0/2.0, 0.0, 1.0/2.0 };
341 real64 constexpr
static FSAL =
false;
349 integer constexpr
static algHighOrder = 3;
350 integer constexpr
static algLowOrder = 2;
351 integer constexpr
static numStages = 4;
352 real64 const a[3][3] = { { 1.0/2.0, 0.0, 0.0 },
353 { 0.0, 3.0/4.0, 0.0 },
354 { 2.0/9.0, 1.0/3.0, 4.0/9.0 } };
355 real64 const c[4] = { 0.0, 1.0/2.0, 3.0/4.0, 1.0 };
356 real64 const b[4] = { 2.0/9.0, 1.0/3.0, 4.0/9.0, 0.0 };
357 real64 const bStar[4] = { 7.0/24.0, 1.0/4.0, 1.0/3.0, 1.0/8.0};
358 bool constexpr
static FSAL =
true;
374 constitutive::RateAndStateFriction
const & frictionLaw,
375 TABLE_TYPE butcherTable ):
376 m_stateVariable( subRegion.
getField< fields::rateAndState::stateVariable >() ),
377 m_stateVariable_n( subRegion.
getField< fields::rateAndState::stateVariable_n >() ),
378 m_slipRate( subRegion.
getField< fields::rateAndState::slipRate >() ),
379 m_slipVelocity( subRegion.
getField< fields::rateAndState::slipVelocity >() ),
380 m_slipVelocity_n( subRegion.
getField< fields::rateAndState::slipVelocity_n >() ),
381 m_deltaSlip( subRegion.
getField< fields::rateAndState::deltaSlip >() ),
382 m_deltaSlip_n( subRegion.
getField< fields::rateAndState::deltaSlip_n >() ),
383 m_dispJump( subRegion.
getField< fields::contact::dispJump >() ),
384 m_dispJump_n( subRegion.
getField< fields::contact::dispJump_n >() ),
385 m_error( subRegion.
getField< fields::rateAndState::error >() ),
386 m_stageRates( subRegion.
getField< fields::rateAndState::rungeKuttaStageRates >() ),
387 m_frictionLaw( frictionLaw.createKernelUpdates() ),
388 m_butcherTable( butcherTable )
397 LvArray::tensorOps::copy< 2 >( m_slipVelocity[k], m_slipVelocity_n[k] );
398 m_slipRate[k] = LvArray::tensorOps::l2Norm< 2 >( m_slipVelocity_n[k] );
399 m_stateVariable[k] = m_stateVariable_n[k];
409 LvArray::tensorOps::copy< 3 >( m_stageRates[k][0], m_stageRates[k][m_butcherTable.numStages-1] );
418 m_stageRates[k][stageIndex][0] = m_slipVelocity[k][0];
419 m_stageRates[k][stageIndex][1] = m_slipVelocity[k][1];
420 m_stageRates[k][stageIndex][2] = m_frictionLaw.stateEvolution( k, m_slipRate[k], m_stateVariable[k] );
430 real64 stateVariableIncrement = 0.0;
431 real64 deltaSlipIncrement[2] = {0.0, 0.0};
433 for(
integer i = 0; i < stageIndex; i++ )
435 deltaSlipIncrement[0] += m_butcherTable.a[stageIndex-1][i] * m_stageRates[k][i][0];
436 deltaSlipIncrement[1] += m_butcherTable.a[stageIndex-1][i] * m_stageRates[k][i][1];
437 stateVariableIncrement += m_butcherTable.a[stageIndex-1][i] * m_stageRates[k][i][2];
439 m_deltaSlip[k][0] = m_deltaSlip_n[k][0] + dt*deltaSlipIncrement[0];
440 m_deltaSlip[k][1] = m_deltaSlip_n[k][1] + dt*deltaSlipIncrement[1];
441 m_stateVariable[k] = m_stateVariable_n[k] + dt*stateVariableIncrement;
443 m_dispJump[k][1] = m_dispJump_n[k][1] + m_deltaSlip[k][0];
444 m_dispJump[k][2] = m_dispJump_n[k][2] + m_deltaSlip[k][1];
455 real64 deltaSlipIncrement[2] = {0.0, 0.0};
456 real64 deltaSlipIncrementLowOrder[2] = {0.0, 0.0};
458 real64 stateVariableIncrement = 0.0;
459 real64 stateVariableIncrementLowOrder = 0.0;
461 for(
localIndex i = 0; i < m_butcherTable.numStages; i++ )
465 deltaSlipIncrement[0] += m_butcherTable.b[i] * m_stageRates[k][i][0];
466 deltaSlipIncrement[1] += m_butcherTable.b[i] * m_stageRates[k][i][1];
467 stateVariableIncrement += m_butcherTable.b[i] * m_stageRates[k][i][2];
470 deltaSlipIncrementLowOrder[0] += m_butcherTable.bStar[i] * m_stageRates[k][i][0];
471 deltaSlipIncrementLowOrder[1] += m_butcherTable.bStar[i] * m_stageRates[k][i][1];
472 stateVariableIncrementLowOrder += m_butcherTable.bStar[i] * m_stageRates[k][i][2];
475 m_deltaSlip[k][0] = m_deltaSlip_n[k][0] + dt * deltaSlipIncrement[0];
476 m_deltaSlip[k][1] = m_deltaSlip_n[k][1] + dt * deltaSlipIncrement[1];
477 m_stateVariable[k] = m_stateVariable_n[k] + dt * stateVariableIncrement;
479 real64 const deltaSlipLowOrder[2] = {m_deltaSlip_n[k][0] + dt * deltaSlipIncrementLowOrder[0],
480 m_deltaSlip_n[k][1] + dt * deltaSlipIncrementLowOrder[1]};
481 real64 const stateVariableLowOrder = m_stateVariable_n[k] + dt * stateVariableIncrementLowOrder;
483 m_dispJump[k][1] = m_dispJump_n[k][1] + m_deltaSlip[k][0];
484 m_dispJump[k][2] = m_dispJump_n[k][2] + m_deltaSlip[k][1];
487 m_error[k][0] =
computeError( m_deltaSlip[k][0], deltaSlipLowOrder[0], absTol, relTol );
488 m_error[k][1] =
computeError( m_deltaSlip[k][1], deltaSlipLowOrder[1], absTol, relTol );
489 m_error[k][2] =
computeError( m_stateVariable[k], stateVariableLowOrder, absTol, relTol );
500 real64 deltaSlipIncrementLowOrder[2] = {0.0, 0.0};
501 real64 stateVariableIncrementLowOrder = 0.0;
503 for(
localIndex i = 0; i < m_butcherTable.numStages; i++ )
508 deltaSlipIncrementLowOrder[0] += m_butcherTable.bStar[i] * m_stageRates[k][i][0];
509 deltaSlipIncrementLowOrder[1] += m_butcherTable.bStar[i] * m_stageRates[k][i][1];
510 stateVariableIncrementLowOrder += m_butcherTable.bStar[i] * m_stageRates[k][i][2];
513 real64 const deltaSlipLowOrder[2] = {m_deltaSlip_n[k][0] + dt * deltaSlipIncrementLowOrder[0],
514 m_deltaSlip_n[k][1] + dt * deltaSlipIncrementLowOrder[1]};
515 real64 const stateVariableLowOrder = m_stateVariable_n[k] + dt * stateVariableIncrementLowOrder;
517 m_dispJump[k][1] = m_dispJump_n[k][1] + m_deltaSlip[k][0];
518 m_dispJump[k][2] = m_dispJump_n[k][2] + m_deltaSlip[k][1];
521 m_error[k][0] =
computeError( m_deltaSlip[k][0], deltaSlipLowOrder[0], absTol, relTol );
522 m_error[k][1] =
computeError( m_deltaSlip[k][1], deltaSlipLowOrder[1], absTol, relTol );
523 m_error[k][2] =
computeError( m_stateVariable[k], stateVariableLowOrder, absTol, relTol );
532 return (highOrderApprox - lowOrderApprox) /
533 ( absTol + relTol * LvArray::math::max( LvArray::math::abs( highOrderApprox ), LvArray::math::abs( lowOrderApprox ) ));
572 constitutive::RateAndStateFriction::KernelWrapper m_frictionLaw;
575 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_ERROR(msg)
Raise a hard error and terminate the program.
#define GEOS_LOG_RANK_0(msg)
Log a message on screen on rank 0.
#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.
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...
GEOS_HOST_DEVICE void solve(localIndex const k, StackVariables &stack) const
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.
static T max(T const &value, MPI_Comm comm=MPI_COMM_GEOS)
Convenience function for a MPI_Allreduce using a MPI_MAX operation.
Butcher table for the BogackiShampine 3(2) method.
Kernel variables located on the stack.
Kernel variables located on the stack.
Butcher table for embedded RK3(2) method using Kuttas third order method for the high-order update,...