From 6246dedcf4d24fbf0297890f05f2b5cbe7f5efd5 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Mon, 12 Aug 2024 16:10:32 -0700 Subject: [PATCH 01/53] feat: add rate- and state-dependent friction model. --- .../contact/RateAndStateFriction.hpp | 214 ++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 src/coreComponents/constitutive/contact/RateAndStateFriction.hpp diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp new file mode 100644 index 00000000000..fc8dbc6b426 --- /dev/null +++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp @@ -0,0 +1,214 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file RateAndStateFriction.hpp + */ + +#ifndef GEOS_CONSTITUTIVE_CONTACT_RATEANDSTATEFRICTION_HPP_ +#define GEOS_CONSTITUTIVE_CONTACT_RATEANDSTATEFRICTION_HPP_ + +#include "FrictionBase.hpp" + +namespace geos +{ + +namespace constitutive +{ + +/** + * @class RateAndStateFrictionUpdates + * + * This class is used for in-kernel contact relation updates + */ +class RateAndStateFrictionUpdates : public FrictionBaseUpdates +{ +public: + RateAndStateFrictionUpdates( real64 const & displacementJumpThreshold, + real64 const & shearStiffness, + real64 const & cohesion, + real64 const & frictionCoefficient, + arrayView2d< real64 > const & elasticSlip ) + : FrictionBaseUpdates( displacementJumpThreshold ), + m_shearStiffness( shearStiffness ), + m_cohesion( cohesion ), + m_frictionCoefficient( frictionCoefficient ), + m_elasticSlip( elasticSlip ) + {} + + /// Default copy constructor + RateAndStateFrictionUpdates( RateAndStateFrictionUpdates const & ) = default; + + /// Default move constructor + RateAndStateFrictionUpdates( RateAndStateFrictionUpdates && ) = default; + + /// Deleted default constructor + RateAndStateFrictionUpdates() = delete; + + /// Deleted copy assignment operator + RateAndStateFrictionUpdates & operator=( RateAndStateFrictionUpdates const & ) = delete; + + /// Deleted move assignment operator + RateAndStateFrictionUpdates & operator=( RateAndStateFrictionUpdates && ) = delete; + + /** + * @brief Evaluate the limit tangential traction norm and return the derivative wrt normal traction + * @param[in] normalTraction the normal traction + * @param[out] dLimitTangentialTractionNorm_dTraction the derivative of the limit tangential traction norm wrt normal traction + * @return the limit tangential traction norm + */ + GEOS_HOST_DEVICE + inline + virtual real64 computeLimitTangentialTractionNorm( real64 const & normalTraction, + real64 & dLimitTangentialTractionNorm_dTraction ) const override final; + + GEOS_HOST_DEVICE + inline + virtual void computeShearTraction( localIndex const k, + arraySlice1d< real64 const > const & oldDispJump, + arraySlice1d< real64 const > const & dispJump, + integer const & fractureState, + arraySlice1d< real64 > const & tractionVector, + arraySlice2d< real64 > const & dTractionVector_dJump ) const override final; + + GEOS_HOST_DEVICE + inline + virtual void updateFractureState( localIndex const k, + arraySlice1d< real64 const > const & dispJump, + arraySlice1d< real64 const > const & tractionVector, + integer & fractureState ) const override final; + +private: + /// The friction coefficient for each upper level dimension (i.e. cell) of *this + real64 m_frictionCoefficient; +}; + + +/** + * @class RateAndStateFriction + * + * Class to provide a RateAndStateFriction friction model. + */ +class RateAndStateFriction : public FrictionBase +{ +public: + + /** + * constructor + * @param[in] name name of the instance in the catalog + * @param[in] parent the group which contains this instance + */ + RateAndStateFriction( string const & name, Group * const parent ); + + /** + * Default Destructor + */ + virtual ~RateAndStateFriction() override; + + static string catalogName() { return "RateAndStateFriction"; } + + virtual string getCatalogName() const override { return catalogName(); } + + ///@} + + virtual void allocateConstitutiveData( dataRepository::Group & parent, + localIndex const numConstitutivePointsPerParentIndex ) override final; + + /** + * @brief Const accessor for friction angle + * @return A const reference to arrayView1d containing the + * friction coefficient (at every element). + */ + real64 const & frictionCoefficient() const { return m_frictionCoefficient; } + + /// Type of kernel wrapper for in-kernel update + using KernelWrapper = RateAndStateFrictionUpdates; + + /** + * @brief Create an update kernel wrapper. + * @return the wrapper + */ + KernelWrapper createKernelWrapper() const; + +private: + + virtual void postInputInitialization() override; + + /// The friction coefficient for each upper level dimension (i.e. cell) of *this + array1d< real64 > m_frictionCoefficient; + + /// Rate and State coefficient a + array1d< real64 > m_a; + + /// Rate and State coefficient b + array1d< real64 > m_b; + + /// Rate and State reference velocity + array1d< real64 > m_V0; + +/** + * @struct Set of "char const *" and keys for data specified in this class. + */ + struct viewKeyStruct : public FrictionBase::viewKeyStruct + { + /// string/key for friction coefficient + static constexpr char const * frictionCoefficientString() { return "frictionCoefficient"; } + }; + +}; + + +GEOS_HOST_DEVICE +real64 RateAndStateFrictionUpdates::computeLimitTangentialTractionNorm( real64 const & normalTraction, + real64 & dLimitTangentialTractionNorm_dTraction ) const +{ + dLimitTangentialTractionNorm_dTraction = m_frictionCoefficient; + return ( m_cohesion - normalTraction * m_frictionCoefficient ); +} + + +GEOS_HOST_DEVICE +inline void RateAndStateFrictionUpdates::computeShearTraction( localIndex const k, + arraySlice1d< real64 const > const & oldDispJump, + arraySlice1d< real64 const > const & dispJump, + integer const & fractureState, + arraySlice1d< real64 > const & tractionVector, + arraySlice2d< real64 > const & dTractionVector_dJump ) const +{ + +} + +GEOS_HOST_DEVICE +inline void RateAndStateFrictionUpdates::updateFractureState( localIndex const k, + arraySlice1d< real64 const > const & dispJump, + arraySlice1d< real64 const > const & tractionVector, + integer & fractureState ) const +{ + using namespace fields::contact; + + if( dispJump[0] > -m_displacementJumpThreshold ) + { + fractureState = FractureState::Open; + } else + { + fractureState = FractureState::Slip; + } +} + +} /* namespace constitutive */ + +} /* namespace geos */ + +#endif /* GEOS_CONSTITUTIVE_CONTACT_RATEANDSTATEFRICTION_HPP_ */ From 2dc8e16c066350a0ee7ac68ddeda2f8137dacc19 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Tue, 13 Aug 2024 09:26:45 -0700 Subject: [PATCH 02/53] wip rate and state impl. --- .../contact/RateAndStateFriction.hpp | 72 +++++-------------- 1 file changed, 17 insertions(+), 55 deletions(-) diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp index fc8dbc6b426..b900e37e253 100644 --- a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp +++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp @@ -36,16 +36,10 @@ namespace constitutive class RateAndStateFrictionUpdates : public FrictionBaseUpdates { public: - RateAndStateFrictionUpdates( real64 const & displacementJumpThreshold, - real64 const & shearStiffness, - real64 const & cohesion, - real64 const & frictionCoefficient, - arrayView2d< real64 > const & elasticSlip ) + RateAndStateFrictionUpdates( real64 const displacementJumpThreshold, + arrayView1d< real64 > const frictionCoefficient ) : FrictionBaseUpdates( displacementJumpThreshold ), - m_shearStiffness( shearStiffness ), - m_cohesion( cohesion ), - m_frictionCoefficient( frictionCoefficient ), - m_elasticSlip( elasticSlip ) + m_frictionCoefficient( frictionCoefficient ) {} /// Default copy constructor @@ -63,26 +57,6 @@ class RateAndStateFrictionUpdates : public FrictionBaseUpdates /// Deleted move assignment operator RateAndStateFrictionUpdates & operator=( RateAndStateFrictionUpdates && ) = delete; - /** - * @brief Evaluate the limit tangential traction norm and return the derivative wrt normal traction - * @param[in] normalTraction the normal traction - * @param[out] dLimitTangentialTractionNorm_dTraction the derivative of the limit tangential traction norm wrt normal traction - * @return the limit tangential traction norm - */ - GEOS_HOST_DEVICE - inline - virtual real64 computeLimitTangentialTractionNorm( real64 const & normalTraction, - real64 & dLimitTangentialTractionNorm_dTraction ) const override final; - - GEOS_HOST_DEVICE - inline - virtual void computeShearTraction( localIndex const k, - arraySlice1d< real64 const > const & oldDispJump, - arraySlice1d< real64 const > const & dispJump, - integer const & fractureState, - arraySlice1d< real64 > const & tractionVector, - arraySlice2d< real64 > const & dTractionVector_dJump ) const override final; - GEOS_HOST_DEVICE inline virtual void updateFractureState( localIndex const k, @@ -91,8 +65,17 @@ class RateAndStateFrictionUpdates : public FrictionBaseUpdates integer & fractureState ) const override final; private: - /// The friction coefficient for each upper level dimension (i.e. cell) of *this - real64 m_frictionCoefficient; + /// The friction coefficient + arrayView1d< real64 > m_frictionCoefficient; + + /// Rate and State coefficient a + arrayView1d< real64 const > m_a; + + /// Rate and State coefficient b + arrayView1d< real64 const > m_b; + + /// Rate and State reference velocity + arrayView1d< real64 const > m_V0; }; @@ -169,32 +152,11 @@ class RateAndStateFriction : public FrictionBase }; - -GEOS_HOST_DEVICE -real64 RateAndStateFrictionUpdates::computeLimitTangentialTractionNorm( real64 const & normalTraction, - real64 & dLimitTangentialTractionNorm_dTraction ) const -{ - dLimitTangentialTractionNorm_dTraction = m_frictionCoefficient; - return ( m_cohesion - normalTraction * m_frictionCoefficient ); -} - - -GEOS_HOST_DEVICE -inline void RateAndStateFrictionUpdates::computeShearTraction( localIndex const k, - arraySlice1d< real64 const > const & oldDispJump, - arraySlice1d< real64 const > const & dispJump, - integer const & fractureState, - arraySlice1d< real64 > const & tractionVector, - arraySlice2d< real64 > const & dTractionVector_dJump ) const -{ - -} - GEOS_HOST_DEVICE inline void RateAndStateFrictionUpdates::updateFractureState( localIndex const k, - arraySlice1d< real64 const > const & dispJump, - arraySlice1d< real64 const > const & tractionVector, - integer & fractureState ) const + arraySlice1d< real64 const > const & dispJump, + arraySlice1d< real64 const > const & tractionVector, + integer & fractureState ) const { using namespace fields::contact; From 02c09180f3e28960ce56c7e9b334b143b7692bba Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Wed, 14 Aug 2024 17:01:59 -0700 Subject: [PATCH 03/53] WiP: implemented several rs functions. --- .../contact/RateAndStateFriction.hpp | 229 ++++++++++++++---- .../inducedSeismicity/CMakeLists.txt | 2 +- .../inducedSeismicity/SeismicityRate.cpp | 2 +- .../SeismicityRateKernels.hpp | 202 --------------- .../inducedSeismicityFields.hpp | 1 - 5 files changed, 181 insertions(+), 255 deletions(-) delete mode 100644 src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRateKernels.hpp diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp index b900e37e253..3c89d3a1f3d 100644 --- a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp +++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp @@ -33,50 +33,6 @@ namespace constitutive * * This class is used for in-kernel contact relation updates */ -class RateAndStateFrictionUpdates : public FrictionBaseUpdates -{ -public: - RateAndStateFrictionUpdates( real64 const displacementJumpThreshold, - arrayView1d< real64 > const frictionCoefficient ) - : FrictionBaseUpdates( displacementJumpThreshold ), - m_frictionCoefficient( frictionCoefficient ) - {} - - /// Default copy constructor - RateAndStateFrictionUpdates( RateAndStateFrictionUpdates const & ) = default; - - /// Default move constructor - RateAndStateFrictionUpdates( RateAndStateFrictionUpdates && ) = default; - - /// Deleted default constructor - RateAndStateFrictionUpdates() = delete; - - /// Deleted copy assignment operator - RateAndStateFrictionUpdates & operator=( RateAndStateFrictionUpdates const & ) = delete; - - /// Deleted move assignment operator - RateAndStateFrictionUpdates & operator=( RateAndStateFrictionUpdates && ) = delete; - - GEOS_HOST_DEVICE - inline - virtual void updateFractureState( localIndex const k, - arraySlice1d< real64 const > const & dispJump, - arraySlice1d< real64 const > const & tractionVector, - integer & fractureState ) const override final; - -private: - /// The friction coefficient - arrayView1d< real64 > m_frictionCoefficient; - - /// Rate and State coefficient a - arrayView1d< real64 const > m_a; - - /// Rate and State coefficient b - arrayView1d< real64 const > m_b; - - /// Rate and State reference velocity - arrayView1d< real64 const > m_V0; -}; /** @@ -116,8 +72,99 @@ class RateAndStateFriction : public FrictionBase */ real64 const & frictionCoefficient() const { return m_frictionCoefficient; } - /// Type of kernel wrapper for in-kernel update - using KernelWrapper = RateAndStateFrictionUpdates; + +class KernelWrapper : public FrictionBaseUpdates +{ +public: + KernelWrapper( real64 const displacementJumpThreshold, + arrayView1d< real64 > const frictionCoefficient, + arrayView1d< real64 > m_frictionCoefficient, + arrayView1d< real64 const > a, + arrayView1d< real64 const > b, + arrayView1d< real64 const > Dc, + arrayView1d< real64 const > V0 ) + : FrictionBaseUpdates( displacementJumpThreshold ), + m_frictionCoefficient( frictionCoefficient ) + m_a( a ), + m_b( b ), + m_Dc( Dc ), + m_V0( V0 ) + {} + + /// Default copy constructor + KernelWrapper( RateAndStateFrictionUpdates const & ) = default; + + /// Default move constructor + KernelWrapper( RateAndStateFrictionUpdates && ) = default; + + /// Deleted default constructor + KernelWrapper() = delete; + + /// Deleted copy assignment operator + KernelWrapper & operator=( KernelWrapper const & ) = delete; + + /// Deleted move assignment operator + KernelWrapper & operator=( KernelWrapper && ) = delete; + + GEOS_HOST_DEVICE + inline + virtual void updateFractureState( localIndex const k, + arraySlice1d< real64 const > const & dispJump, + arraySlice1d< real64 const > const & tractionVector, + integer & fractureState ) const override final; + +GEOS_HOST_DEVICE +inline std::tuple< real64, real64[2] > +computeShearTraction( real64 const normalTraction, + real64 const slipRate, + real64 const stateVariable ) const; + +GEOS_HOST_DEVICE +inline real64 frictionCoefficient( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const; + +GEOS_HOST_DEVICE +inline real64 dfrictionCoefficient_dSlipRate( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const; + +GEOS_HOST_DEVICE +inline real64 dfrictionCoefficient_dStateVariable( localIndex const k, + real64 const slipRate, + real64 const stateVariable) const; + +GEOS_HOST_DEVICE +inline real64 dStateVariabledT( localIndex const k, + real64 const slipRate, + real64 const stateVariable) const; + +GEOS_HOST_DEVICE +inline real64 dStateVariabledT_dStateVariable( localIndex const k, + real64 const slipRate, + real64 const stateVariable) const; + +GEOS_HOST_DEVICE +inline real64 dStateVariabledT_dSlipRate( localIndex const k, + real64 const slipRate, + real64 const stateVariable) const; +private: + /// The friction coefficient + arrayView1d< real64 > m_frictionCoefficient; + + /// Rate and State coefficient a + arrayView1d< real64 const > m_a; + + /// Rate and State coefficient b + arrayView1d< real64 const > m_b; + + /// Rate and State characteristic length + arrayView1d< real64 const > m_Dc; + + /// Rate and State reference velocity + arrayView1d< real64 const > m_V0; +}; + /** * @brief Create an update kernel wrapper. @@ -137,6 +184,9 @@ class RateAndStateFriction : public FrictionBase /// Rate and State coefficient b array1d< real64 > m_b; + + /// Rate and State characteristic length + array1d< real64 > m_Dc; /// Rate and State reference velocity array1d< real64 > m_V0; @@ -153,10 +203,10 @@ class RateAndStateFriction : public FrictionBase }; GEOS_HOST_DEVICE -inline void RateAndStateFrictionUpdates::updateFractureState( localIndex const k, - arraySlice1d< real64 const > const & dispJump, - arraySlice1d< real64 const > const & tractionVector, - integer & fractureState ) const +inline void RateAndStateFriction::KernelWrapper::updateFractureState( localIndex const k, + arraySlice1d< real64 const > const & dispJump, + arraySlice1d< real64 const > const & tractionVector, + integer & fractureState ) const { using namespace fields::contact; @@ -169,6 +219,85 @@ inline void RateAndStateFrictionUpdates::updateFractureState( localIndex const k } } +GEOS_HOST_DEVICE +inline std::tuple< real64, real64[2] > +RateAndStateFriction::KernelWrapper::computeShearTraction( real64 const normalTraction, + real64 const slipRate, + real64 const stateVariable ) const +{ + real64 const shearTraction = 0.0; + real64 const dTauFriction = {0.0, 0.0}; + + return std::make_tuple( shearTraction, dTauFriction ); +} + +GEOS_HOST_DEVICE +inline real64 RateAndStateFriction::KernelWrapper::frictionCoefficient( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const +{ + real64 const arg = ( slipRate / (2 * m_V0[k]) ) * LvArray::math::exp( stateVariable / m_a[k] ); + real64 const frictionCoefficient = m_a[k] * LvArray::math::asinh( arg ); + + m_frictionCoefficient[k] = frictionCoefficient; + + return frictionCoefficient; +} + +GEOS_HOST_DEVICE +inline real64 RateAndStateFriction::KernelWrapper::dfrictionCoefficient_dSlipRate( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const +{ + + real64 const inner_expression = ( slip_velocity / (2 * m_V0[k]) ) * LvArray::math::exp( theta / m_a[k] ) + + return (m_a[k] / LvArray::math::sqrt(1 + inner_expression**2)) * (1 / (2 * m_V0[k])) * LvArray::math::exp( theta / m_a[k] ); +} + +GEOS_HOST_DEVICE +inline real64 dfrictionCoefficient_dStateVariable( localIndex const k, + real64 const slipRate, + real64 const stateVariable) const +{ + + real64 const arg = (slipRate / (2 * m_V0[k])) * LvArray::math::exp(stateVariable / m_a[k]); + + return (slipRate / (2 * m_V0[k])) * LvArray::math::exp(stateVariable / m_a[k]) / LvArray::math::sqrt(arg**2 + 1); +} + +GEOS_HOST_DEVICE +inline real64 RateAndStateFriction::KernelWrapper::dStateVariabledT( localIndex const k, + real64 const slipRate, + real64 const stateVariable) const +{ + real64 const mu = frictionCoefficient(k, slipRate, stateVariable); + + return -slipRate / m_Dc * (mu - m_mu0 + (m_b - m_a) * LvArray::math::log(slipRate / m_V0)) ; +} + +GEOS_HOST_DEVICE +inline real64 RateAndStateFriction::KernelWrapper::dStateVariabledT_dStateVariable( localIndex const k, + real64 const slipRate, + real64 const stateVariable) const +{ + return -slipRate /m_Dc[k] * dfrictionCoefficient_dStateVariable( k, slipRate, stateVariable ); +} + +GEOS_HOST_DEVICE +inline real64 RateAndStateFriction::KernelWrapper::dStateVariabledT_dSlipRate( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const +{ + real64 const dfrictionCoefficient_dSlipRate = dfrictionCoefficient_dSlipRate(k, slipRate, stateVariable); + + real64 const part1 = - 1.0 / m_Dc[k] * (frictionCoefficient(slipRate, stateVariable) - m_mu0[k] + (m_b[k] - m_a[k]) * LvArray::math::log(slipRate / m_V0[k])) + + real64 const part2 = - slipRate / m_Dc[k] * (dfrictionCoefficient_dSlipRate + (m_b[k] - m_a[k]) / slipRate) + + return part1 + part2; +} + } /* namespace constitutive */ } /* namespace geos */ diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/CMakeLists.txt b/src/coreComponents/physicsSolvers/inducedSeismicity/CMakeLists.txt index e4a805314ac..0341bba8df9 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/CMakeLists.txt +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/CMakeLists.txt @@ -3,7 +3,7 @@ set( physicsSolvers_headers ${physicsSolvers_headers} inducedSeismicity/inducedSeismicityFields.hpp inducedSeismicity/SeismicityRate.hpp - inducedSeismicity/SeismicityRateKernels.hpp + inducedSeismicity/kernels/SeismicityRateKernels.hpp PARENT_SCOPE ) # Specify solver sources diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.cpp index 14ae9707b43..6405fdb2d67 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.cpp @@ -23,7 +23,7 @@ #include "mainInterface/GeosxState.hpp" #include "mesh/mpiCommunications/CommunicationTools.hpp" #include "physicsSolvers/solidMechanics/SolidMechanicsLagrangianFEM.hpp" -#include "SeismicityRateKernels.hpp" +#include "kernels/SeismicityRateKernels.hpp" namespace geos { diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRateKernels.hpp deleted file mode 100644 index 9dfcd31d210..00000000000 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRateKernels.hpp +++ /dev/null @@ -1,202 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * SPDX-License-Identifier: LGPL-2.1-only - * - * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 Total, S.A - * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University - * Copyright (c) 2018-2024 Chevron - * Copyright (c) 2019- GEOS/GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -#ifndef GEOS_PHYSICSSOLVERS_SEISMICITYRATEKERNELS_HPP_ -#define GEOS_PHYSICSSOLVERS_SEISMICITYRATEKERNELS_HPP_ - -#include "common/DataTypes.hpp" -#include "common/GEOS_RAJA_Interface.hpp" -#include "physicsSolvers/inducedSeismicity/inducedSeismicityFields.hpp" -#include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" - -namespace geos -{ - -namespace seismicityRateKernels -{ -/** - * @class DieterichSeismicityRate - * - * @brief Solving the ODE for seismicity rate from Dieterich, 1994 - * - * @details This solver finds a solution R(x, t) - the seismicity rate - to the ordinary differential equation (ODE) - * formulated by Dieterich, 1994 given a certain stressing history. The stressing history can consist - * of mechanical stresses and pore pressure. The solver class includes a member variable - * pointing to the stress solver that is specified in the XML file. SolverStep for the - * stress solver is then called in the SolverStep function for the seismicity rate, to take - * the updated stress history as the input. - * - * Solving the ODE is currently implemented by computing the closed-form integral solution - * to the ODE which involves numerical calculation of an integral of a stress functional. - * We initially solve for the log of the seismicity rate in order to avoid overflow that - * typically occurs in the exponential of the stress history. - */ -class SeismicityRateKernel -{ -public: - - SeismicityRateKernel( ElementSubRegionBase & subRegion ): - m_R( subRegion.getField< fields::inducedSeismicity::seismicityRate >() ), - m_logDenom( subRegion.getField< fields::inducedSeismicity::logDenom >() ), - m_sigma_0( subRegion.getField< fields::inducedSeismicity::initialProjectedNormalTraction >() ), - m_sigma_n( subRegion.getField< fields::inducedSeismicity::projectedNormalTraction_n >() ), - m_sigma( subRegion.getField< fields::inducedSeismicity::projectedNormalTraction >() ), - m_tau_0( subRegion.getField< fields::inducedSeismicity::initialProjectedShearTraction >() ), - m_tau_n( subRegion.getField< fields::inducedSeismicity::projectedShearTraction_n >() ), - m_tau( subRegion.getField< fields::inducedSeismicity::projectedShearTraction >() ) - {} - - /** - * @struct StackVariables - * @brief Kernel variables located on the stack - */ - struct StackVariables - { -public: - - GEOS_HOST_DEVICE - StackVariables( real64 const directEffect, - real64 const backgroundStressingRate ): - directEffectValue( directEffect ), - backgroundStressingRateValue( backgroundStressingRate ), - effectiveNormalTraction_0( 0.0 ), - effectiveNormalTraction_n( 0.0 ), - effectiveNormalTraction( 0.0 ) - {} - - real64 const directEffectValue; - - real64 const backgroundStressingRateValue; - - real64 effectiveNormalTraction_0; - - real64 effectiveNormalTraction_n; - - real64 effectiveNormalTraction; - }; - - GEOS_HOST_DEVICE - void setup( localIndex const k, - StackVariables & stack ) const - { - stack.effectiveNormalTraction_0 = -m_sigma_0[k]; - stack.effectiveNormalTraction_n = -m_sigma_n[k]; - stack.effectiveNormalTraction = -m_sigma[k]; - } - - GEOS_HOST_DEVICE - void computeSeismicityRate( localIndex const k, - real64 const & time_n, - real64 const & dt, - StackVariables & stack ) const - { - - // arguments of stress exponential at current and previous time step - real64 const g = ( m_tau[k] + stack.backgroundStressingRateValue*(time_n+dt))/(stack.directEffectValue*stack.effectiveNormalTraction ) - - m_tau_0[k]/(stack.directEffectValue * stack.effectiveNormalTraction_0 ); - - real64 const g_n = ( m_tau_n[k] + stack.backgroundStressingRateValue*time_n)/(stack.directEffectValue*stack.effectiveNormalTraction_n ) - - m_tau_0[k]/(stack.directEffectValue*stack.effectiveNormalTraction_0); - - // Compute the difference of the log of the denominator of closed for integral solution. - // This avoids directly computing the exponential of the current stress state which is more prone to overflow. - m_logDenom[k] += std::log( 1 + dt/(2*(stack.directEffectValue*stack.effectiveNormalTraction_0/stack.backgroundStressingRateValue)) - *(std::exp( g - m_logDenom[k] ) + std::exp( g_n - m_logDenom[k] ) )); - - // Convert log seismicity rate to raw value - m_R[k] = LvArray::math::exp( g - m_logDenom[k] ); - } - -protected: - - arrayView1d< real64 > m_R; - - arrayView1d< real64 > m_logDenom; - - arrayView1d< real64 const > m_sigma_0; - - arrayView1d< real64 const > m_sigma_n; - - arrayView1d< real64 const > m_sigma; - - arrayView1d< real64 const > m_tau_0; - - arrayView1d< real64 const > m_tau_n; - - arrayView1d< real64 const > m_tau; -}; - - -class SeismicityRateKernelPoroelastic : public SeismicityRateKernel -{ - -public: - - SeismicityRateKernelPoroelastic( ElementSubRegionBase & subRegion ): - SeismicityRateKernel( subRegion ), - m_pressure_0( subRegion.getField< fields::flow::initialPressure >() ), - m_pressure_n( subRegion.getField< fields::flow::pressure_n >() ), - m_pressure( subRegion.getField< fields::flow::pressure >() ) - {} - - GEOS_HOST_DEVICE - void setup( localIndex const k, - StackVariables & stack ) const - { - stack.effectiveNormalTraction_0 = -m_sigma_0[k] - m_pressure_0[k]; - stack.effectiveNormalTraction_n = -m_sigma_n[k] - m_pressure_n[k]; - stack.effectiveNormalTraction = -m_sigma[k] - m_pressure[k]; - } - -private: - - arrayView1d< real64 const > m_pressure_0; - - arrayView1d< real64 const > m_pressure_n; - - arrayView1d< real64 const > m_pressure; -}; - - -/** - * @brief Performs the kernel launch - * @tparam POLICY the policy used in the RAJA kernels - */ -template< typename POLICY, bool ISPORO > -static void -createAndLaunch( ElementSubRegionBase & subRegion, - real64 const time_n, - real64 const dt, - real64 const directEffectValue, - real64 const backgroundStressingRateValue ) -{ - GEOS_MARK_FUNCTION; - - using kernelType = std::conditional_t< ISPORO, SeismicityRateKernelPoroelastic, SeismicityRateKernel >; - kernelType kernel( subRegion ); - - forAll< POLICY >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) - { - typename kernelType::StackVariables stack( directEffectValue, backgroundStressingRateValue ); - kernel.setup( k, stack ); - kernel.computeSeismicityRate( k, time_n, dt, stack ); - } ); -} - -} /* namespace seismicityRateKernels */ - -}/* namespace geos */ - -#endif /* GEOS_PHYSICSSOLVERS_SEISMICITYRATEKERNELS_HPP_ */ diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/inducedSeismicityFields.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/inducedSeismicityFields.hpp index 1b6433bc1b4..f0b7513403b 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/inducedSeismicityFields.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/inducedSeismicityFields.hpp @@ -95,7 +95,6 @@ DECLARE_FIELD( logDenom, LEVEL_2, WRITE_AND_READ, "Log of the denominator of the integral form of the seismicity rate" ); - } } From e959ca6dcdf3bead4e8b596188027fd0ea9d22a5 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Thu, 15 Aug 2024 13:56:17 -0700 Subject: [PATCH 04/53] add TwoByTwo dense solver. --- .../denseLinearAlgebra/denseLASolvers.hpp | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/coreComponents/denseLinearAlgebra/denseLASolvers.hpp diff --git a/src/coreComponents/denseLinearAlgebra/denseLASolvers.hpp b/src/coreComponents/denseLinearAlgebra/denseLASolvers.hpp new file mode 100644 index 00000000000..d01016d1327 --- /dev/null +++ b/src/coreComponents/denseLinearAlgebra/denseLASolvers.hpp @@ -0,0 +1,75 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file denseLASolvers.hpp + */ +#ifndef GEOS_DENSELINEARALGEBRA_DENSELASOLVERS_HPP_ +#define GEOS_DENSELINEARALGEBRA_DENSELASOLVERS_HPP_ + +#include "common/DataTypes.hpp" +#include "denseLinearAlgebra/common/layouts.hpp" + +#include + +namespace geos +{ + +namespace denseLinearAlgebra +{ +/** + * @brief Solves a 2x2 linear system A * x = b. + * + * This function solves a linear system of the form A * x = b, where A is a 2x2 matrix, + * b is a 2x1 vector, and x is the solution vector. The function checks the sizes + * of the inputs to ensure they conform to the expected dimensions. It also checks that + * the determinant of matrix A is not near zero to avoid solving a singular system. + * + * @tparam MATRIX_TYPE The type of the matrix A. Must support indexing with `A[i][j]`. + * @tparam RHS_TYPE The type of the right-hand side vector b. Must support indexing with `b[i]`. + * @tparam SOL_TYPE The type of the solution vector x. Must support indexing with `x[i]`. + * + * @param[in] A The 2x2 matrix representing the system of equations. Must have size 2x2. + * @param[in] b The 2-element vector representing the right-hand side of the equation. + * @param[out] x The 2-element vector that will store the solution to the system. + */ +template< typename MATRIX_TYPE, + typename RHS_TYPE, + typename SOL_TYPE > +GEOS_HOST_DEVICE +inline +void solveTwoByTwoSystem( MATRIX_TYPE const & A, RHS_TYPE const & b, SOL_TYPE && x) +{ + LvArray::tensorOps::internal::checkSizes< 2, 2 >( A ); + LvArray::tensorOps::internal::checkSizes< 2 >( b ); + LvArray::tensorOps::internal::checkSizes< 2 >( x ); + + real64 const detA = A[0][0] * A[1][1] - A[0][1] * A[1][0]; + + GEOS_ERROR_IF_LT_MSG( LvArray::math::abs(detA), LvArray::NumericLimits< real64 >::epsilon;, "Singular system." ); + + real64 const A_inv[2][2] = { { A[1][1] / detA, -A[0][1] / detA }, + { -A[1][0] / detA, A[0][0] / detA } }; + + x[0] = A_inv[0][0] * b[0] + A_inv[0][1] * b[1]; + x[1] = A_inv[1][0] * b[0] + A_inv[1][1] * b[1]; +} + +}; + +}; + + +#endif /*GEOS_DENSELINEARALGEBRA_DENSELASOLVERS_HPP_*/ From 634ee68922e4e8aa8cc8c3a888cf9bf4c0b033d7 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Thu, 15 Aug 2024 13:57:41 -0700 Subject: [PATCH 05/53] add solver and kernels. --- .../inducedSeismicity/RateAndStateSolver.cpp | 99 +++++++++ .../inducedSeismicity/RateAndStateSolver.hpp | 162 ++++++++++++++ .../kernels/RateAndStateKernels.hpp | 163 ++++++++++++++ .../kernels/SeismicityRateKernels.hpp | 202 ++++++++++++++++++ .../inducedSeismicity/rateAndStateFields.hpp | 58 +++++ 5 files changed, 684 insertions(+) create mode 100644 src/coreComponents/physicsSolvers/inducedSeismicity/RateAndStateSolver.cpp create mode 100644 src/coreComponents/physicsSolvers/inducedSeismicity/RateAndStateSolver.hpp create mode 100644 src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp create mode 100644 src/coreComponents/physicsSolvers/inducedSeismicity/kernels/SeismicityRateKernels.hpp create mode 100644 src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/RateAndStateSolver.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/RateAndStateSolver.cpp new file mode 100644 index 00000000000..ace55b1b1f6 --- /dev/null +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/RateAndStateSolver.cpp @@ -0,0 +1,99 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file RateAndState.cpp + */ + +#include "RateAndState.hpp" + +#include "dataRepository/InputFlags.hpp" +#include "mainInterface/GeosxState.hpp" +#include "mesh/mpiCommunications/CommunicationTools.hpp" +#include "rateAndStateFields.hpp" + + +namespace geos +{ + +using namespace dataRepository; +using namespace constitutive; + +RateAndState::RateAndState( const string & name, + Group * const parent ): + SolverBase( name, parent ), + m_stressSolver( nullptr ) +{ + +} + +void RateAndState::postInputInitialization() +{ + + SolverBase::postInputInitialization(); +} + +RateAndState::~RateAndState() +{ + // TODO Auto-generated destructor stub +} + +void RateAndState::registerDataOnMesh( Group & meshBodies ) +{ + SolverBase::registerDataOnMesh( meshBodies ); + + forDiscretizationOnMeshTargets( meshBodies, [&] ( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + ElementRegionManager & elemManager = mesh.getElemManager(); + + elemManager.forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) + { + subRegion.registerField< fields::rateAndState::slipRate >( getName() ); + + subRegion.registerField< fields::rateAndState::stateVariable >( getName() ); + } ); + } ); +} + +real64 RateAndState::solverStep( real64 const & time_n, + real64 const & dt, + const int cycleNumber, + DomainPartition & domain ) +{ + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + ElementRegionManager & elemManager = mesh.getElemManager(); + elemManager.forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) + { + + + + } ); + } ) ; + + + return dt; +} + +REGISTER_CATALOG_ENTRY( SolverBase, RateAndState, string const &, dataRepository::Group * const ) +} // namespace geos diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/RateAndStateSolver.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/RateAndStateSolver.hpp new file mode 100644 index 00000000000..e48424050ac --- /dev/null +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/RateAndStateSolver.hpp @@ -0,0 +1,162 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +#ifndef GEOS_PHYSICSSOLVERS_INDUCED_SEISMICITY_SEISMICITYRATE_HPP +#define GEOS_PHYSICSSOLVERS_INDUCED_SEISMICITY_SEISMICITYRATE_HPP + +#include "codingUtilities/EnumStrings.hpp" // facilities for enum-string conversion (for reading enum values from XML input) +#include "physicsSolvers/SolverBase.hpp" // an abstraction class shared by all physics solvers +#include "fieldSpecification/FieldSpecificationManager.hpp" // a manager that can access and set values on the discretized domain + +#include "physicsSolvers/inducedSeismicity/inducedSeismicityFields.hpp" + +#include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" + +namespace geos +{ + +class RateAndState : public SolverBase +{ +public: + /// The default nullary constructor is disabled to avoid compiler auto-generation: + RateAndState() = delete; + + /// The constructor needs a user-defined "name" and a parent Group (to place this instance in the tree structure of classes) + RateAndState( const string & name, + Group * const parent ); + + /// Destructor + virtual ~RateAndState() override; + + static string catalogName() { return "RateAndState"; } + + /** + * @return Get the final class Catalog name + */ + virtual string getCatalogName() const override { return catalogName(); } + + /// This method ties properties with their supporting mesh + virtual void registerDataOnMesh( Group & meshBodies ) override; + + struct viewKeyStruct : public SolverBase::viewKeyStruct + { + static constexpr char const * stressSolverNameString() { return "stressSolverName"; } + static constexpr char const * initialFaultNormalTractionString() { return "initialFaultNormalTraction"; } + static constexpr char const * initialFaultShearTractionString() { return "initialFaultShearTraction"; } + static constexpr char const * faultNormalDirectionString() { return "faultNormalDirection"; } + static constexpr char const * faultShearDirectionString() { return "faultShearDirection"; } + static constexpr char const * directEffectString() { return "directEffect"; } + static constexpr char const * backgroundStressingRateString() { return "backgroundStressingRate"; } + }; + + virtual real64 solverStep( real64 const & time_n, + real64 const & dt, + integer const cycleNumber, + DomainPartition & domain ) override final; + + /** + * @brief single step advance in computing the seismicity rate based on + * stress history according to closed form integral solution (Heimisson & Segall, 2018) + * to the ODE formulated by Dieterich, 1994 + * @param time_n time at previous converged step + * @param dt time step size + * @param subRegion ElementSubRegionBase to compute the solution in + */ + void integralSolverStep( real64 const & time_n, + real64 const & dt, + ElementSubRegionBase & subRegion ); + + /** + * @brief called in SolverStep after member stress solver is called to + * project the stress state to pre-defined fault orientations + * @param subRegion The ElementSubRegionBase that will have the stress information + */ + void updateFaultTraction( ElementSubRegionBase & subRegion ) const; + + /** + * @brief save the old state + * @param subRegion + */ + void saveOldState( ElementSubRegionBase & subRegion ) const; + + /** + * @brief + * @param biotCoefficient + * @param pres + * @param sig + * @param tau + */ + void computeTotalStressOnFault( arrayView1d< real64 const > const biotCoefficient, + arrayView1d< real64 const > const pres, + real64 const (&faultNormalProjectionTensor)[6], + real64 const (&faultShearProjectionTensor)[6], + arrayView1d< real64 > const sig, + arrayView1d< real64 > const tau ) const; + + /** + * @brief called in SolverStep before member stress solver is called to + * project the initial stress state to pre-defined fault orientations, + * only when cycleNumber == 0 + * @param cycleNumber current cycle number + * @param domain The DomainPartition of the problem + */ + void initializeFaultTraction( real64 const time_n, + integer const cycleNumber, + DomainPartition & domain ) const; + + +protected: + + /** + * @brief update the stresses either by asking the stressSolver or by applying b.c. + * @param time_n the current time + * @param dt the current time step + * @param cycleNumber the cycle number + * @param domain the DomainPartion group + */ + real64 updateStresses( real64 const & time_n, + real64 const & dt, + const int cycleNumber, + DomainPartition & domain ) const; + + + + void constructFaultStressProjectionTensors( real64 ( &faultNormalProjectionTensor )[6], + real64 ( &faultShearProjectionTensor )[6] ) const; + + virtual void postInputInitialization() override; + + /// pointer to stress solver + SolverBase * m_stressSolver; + + /// stress solver name string + string m_stressSolverName; + + /// fault orientation: normal direction + R1Tensor m_faultNormalDirection; + + /// fault orientation: shear direction + R1Tensor m_faultShearDirection; + + /// direct effect coefficient + real64 m_directEffect; + + /// bacground stressing rate + real64 m_backgroundStressingRate; +}; + +} /* namespace geos */ + +#endif /* GEOS_PHYSICSSOLVERS_INDUCED_SEISMICITY_SEISMICITYRATE_HPP */ diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp new file mode 100644 index 00000000000..194d145e717 --- /dev/null +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -0,0 +1,163 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +#ifndef GEOS_PHYSICSSOLVERS_RATEANDSTATEKERNELS_HPP_ +#define GEOS_PHYSICSSOLVERS_RATEANDSTATEKERNELS_HPP_ + +#include "common/DataTypes.hpp" +#include "common/GEOS_RAJA_Interface.hpp" +#include "physicsSolvers/inducedSeismicity/rateAndStateFields.hpp" +#include "denseLinearAlgebra/denseLASolvers.hpp" + +namespace geos +{ + +namespace rateAndStateKernels +{ +/** + * @class DieterichSeismicityRate + * + * @brief + * + * @details + */ +class RateAndStateKernel +{ +public: + + RateAndStateKernel( SurfaceElementSubRegion & subRegion ): + {} + + /** + * @struct StackVariables + * @brief Kernel variables located on the stack + */ + struct StackVariables + { +public: + + GEOS_HOST_DEVICE + StackVariables( ) + {} + + jacobian[2][2]{}; + + rhs[2]{}; + + }; + + GEOS_HOST_DEVICE + void setup( localIndex const k, + StackVariables & stack ) const + { + + // Eq 1: shear stress balance + real64 tauFriction = 0.0; + real64 dTauFriction = {0.0, 0.0}; + + frictionLaw.computeShearTraction( m_normalTraction[k], + m_slipRate[k], + m_stateVariable[k], + tauFriction, + dTauFriction ); + + stack.rhs[0] = m_shearTraction[k] - tauFriction; + + // Eq 2: slip law + stack.rhs[1] = (theta - theta_n) / dt - m_frictionLaw.dStateVariabledT( m_slipRate[k], m_stateVariable[k] ) + real64 const dStateEvolutionLaw[0] = 1 / dt - m_frictionLaw.dStateVariabledT_dtheta( m_slipRate[k], m_stateVariable[k] ) + real64 const dStateEvolutionLaw[1] = - m_frictionLaw.dStateVariabledT_dSlipRate( m_slipRate[k], m_stateVariable[k] ) + + // Assemble Jacobian matrix + // derivative shear stress balance w.r.t. theta + stack.jacobian[0][0] = - dTauFriction[0] + // derivative shear stress balance w.r.t. slip_velocity + stack.jacobian[0][1] = - dTauFriction[1] + // derivative slip law w.r.t. theta + stack.jacobian[1][0] = dStateEvolutionLaw[0] + // derivative slip law w.r.t. slip_velocity + stack.jacobian[1][1] = dStateEvolutionLaw[1] + } + + GEOS_HOST_DEVICE + void solve( localIndex const k, + StackVariables & stack ) const + { + /// Solve 2x2 system + real64 const solution = {0.0, 0.0}; + + denseLinearAlgebra::solveTwoByTwoSystem( stack.jacobian, stack.rhs, solution ); + + /// Update variables + m_stateVariable[k] += soluiton[0]; + m_slipRate[k] += soluiton[1]; + } + +private: + + arrayView1d< real64 > const m_slipRate; + + arrayView1d< real64 > const m_stateVariable; + + arrayView1d< real64 const > const m_normalTraction; + + arrayView1d< real64 const > const m_shearTraction; + + RateAndStateFriction::KernelWrapper m_frictionLaw; + +}; + + + +/** + * @brief Performs the kernel launch + * @tparam POLICY the policy used in the RAJA kernels + */ +template< typename POLICY > +static void +createAndLaunch( SurfaceElementSubRegionBase & subRegion, + integer const maxNewtonIter, + real64 const time_n, + real64 const dt ) +{ + GEOS_MARK_FUNCTION; + + using kernelType ; + kernelType kernel( subRegion ); + + // Newton loops outside of the kernel launch + for( integer iter = 0; iter < maxNewtonIter; iter++ ) + { + /// Kernel 1: Do a solver for all non converged elements + forAll< POLICY >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + typename kernelType::StackVariables stack(); + kernel.setup( k, stack ); + kernel.( k, time_n, dt, stack ); + } ); + + /// Kernel 2: Update set of non-converged elements + // forAll< POLICY >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + // { + + // } ); + } +} + +} /* namespace rateAndStateKernels */ + +}/* namespace geos */ + +#endif /* GEOS_PHYSICSSOLVERS_RATEANDSTATEKERNELS_HPP_ */ diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/SeismicityRateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/SeismicityRateKernels.hpp new file mode 100644 index 00000000000..9dfcd31d210 --- /dev/null +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/SeismicityRateKernels.hpp @@ -0,0 +1,202 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +#ifndef GEOS_PHYSICSSOLVERS_SEISMICITYRATEKERNELS_HPP_ +#define GEOS_PHYSICSSOLVERS_SEISMICITYRATEKERNELS_HPP_ + +#include "common/DataTypes.hpp" +#include "common/GEOS_RAJA_Interface.hpp" +#include "physicsSolvers/inducedSeismicity/inducedSeismicityFields.hpp" +#include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" + +namespace geos +{ + +namespace seismicityRateKernels +{ +/** + * @class DieterichSeismicityRate + * + * @brief Solving the ODE for seismicity rate from Dieterich, 1994 + * + * @details This solver finds a solution R(x, t) - the seismicity rate - to the ordinary differential equation (ODE) + * formulated by Dieterich, 1994 given a certain stressing history. The stressing history can consist + * of mechanical stresses and pore pressure. The solver class includes a member variable + * pointing to the stress solver that is specified in the XML file. SolverStep for the + * stress solver is then called in the SolverStep function for the seismicity rate, to take + * the updated stress history as the input. + * + * Solving the ODE is currently implemented by computing the closed-form integral solution + * to the ODE which involves numerical calculation of an integral of a stress functional. + * We initially solve for the log of the seismicity rate in order to avoid overflow that + * typically occurs in the exponential of the stress history. + */ +class SeismicityRateKernel +{ +public: + + SeismicityRateKernel( ElementSubRegionBase & subRegion ): + m_R( subRegion.getField< fields::inducedSeismicity::seismicityRate >() ), + m_logDenom( subRegion.getField< fields::inducedSeismicity::logDenom >() ), + m_sigma_0( subRegion.getField< fields::inducedSeismicity::initialProjectedNormalTraction >() ), + m_sigma_n( subRegion.getField< fields::inducedSeismicity::projectedNormalTraction_n >() ), + m_sigma( subRegion.getField< fields::inducedSeismicity::projectedNormalTraction >() ), + m_tau_0( subRegion.getField< fields::inducedSeismicity::initialProjectedShearTraction >() ), + m_tau_n( subRegion.getField< fields::inducedSeismicity::projectedShearTraction_n >() ), + m_tau( subRegion.getField< fields::inducedSeismicity::projectedShearTraction >() ) + {} + + /** + * @struct StackVariables + * @brief Kernel variables located on the stack + */ + struct StackVariables + { +public: + + GEOS_HOST_DEVICE + StackVariables( real64 const directEffect, + real64 const backgroundStressingRate ): + directEffectValue( directEffect ), + backgroundStressingRateValue( backgroundStressingRate ), + effectiveNormalTraction_0( 0.0 ), + effectiveNormalTraction_n( 0.0 ), + effectiveNormalTraction( 0.0 ) + {} + + real64 const directEffectValue; + + real64 const backgroundStressingRateValue; + + real64 effectiveNormalTraction_0; + + real64 effectiveNormalTraction_n; + + real64 effectiveNormalTraction; + }; + + GEOS_HOST_DEVICE + void setup( localIndex const k, + StackVariables & stack ) const + { + stack.effectiveNormalTraction_0 = -m_sigma_0[k]; + stack.effectiveNormalTraction_n = -m_sigma_n[k]; + stack.effectiveNormalTraction = -m_sigma[k]; + } + + GEOS_HOST_DEVICE + void computeSeismicityRate( localIndex const k, + real64 const & time_n, + real64 const & dt, + StackVariables & stack ) const + { + + // arguments of stress exponential at current and previous time step + real64 const g = ( m_tau[k] + stack.backgroundStressingRateValue*(time_n+dt))/(stack.directEffectValue*stack.effectiveNormalTraction ) + - m_tau_0[k]/(stack.directEffectValue * stack.effectiveNormalTraction_0 ); + + real64 const g_n = ( m_tau_n[k] + stack.backgroundStressingRateValue*time_n)/(stack.directEffectValue*stack.effectiveNormalTraction_n ) + - m_tau_0[k]/(stack.directEffectValue*stack.effectiveNormalTraction_0); + + // Compute the difference of the log of the denominator of closed for integral solution. + // This avoids directly computing the exponential of the current stress state which is more prone to overflow. + m_logDenom[k] += std::log( 1 + dt/(2*(stack.directEffectValue*stack.effectiveNormalTraction_0/stack.backgroundStressingRateValue)) + *(std::exp( g - m_logDenom[k] ) + std::exp( g_n - m_logDenom[k] ) )); + + // Convert log seismicity rate to raw value + m_R[k] = LvArray::math::exp( g - m_logDenom[k] ); + } + +protected: + + arrayView1d< real64 > m_R; + + arrayView1d< real64 > m_logDenom; + + arrayView1d< real64 const > m_sigma_0; + + arrayView1d< real64 const > m_sigma_n; + + arrayView1d< real64 const > m_sigma; + + arrayView1d< real64 const > m_tau_0; + + arrayView1d< real64 const > m_tau_n; + + arrayView1d< real64 const > m_tau; +}; + + +class SeismicityRateKernelPoroelastic : public SeismicityRateKernel +{ + +public: + + SeismicityRateKernelPoroelastic( ElementSubRegionBase & subRegion ): + SeismicityRateKernel( subRegion ), + m_pressure_0( subRegion.getField< fields::flow::initialPressure >() ), + m_pressure_n( subRegion.getField< fields::flow::pressure_n >() ), + m_pressure( subRegion.getField< fields::flow::pressure >() ) + {} + + GEOS_HOST_DEVICE + void setup( localIndex const k, + StackVariables & stack ) const + { + stack.effectiveNormalTraction_0 = -m_sigma_0[k] - m_pressure_0[k]; + stack.effectiveNormalTraction_n = -m_sigma_n[k] - m_pressure_n[k]; + stack.effectiveNormalTraction = -m_sigma[k] - m_pressure[k]; + } + +private: + + arrayView1d< real64 const > m_pressure_0; + + arrayView1d< real64 const > m_pressure_n; + + arrayView1d< real64 const > m_pressure; +}; + + +/** + * @brief Performs the kernel launch + * @tparam POLICY the policy used in the RAJA kernels + */ +template< typename POLICY, bool ISPORO > +static void +createAndLaunch( ElementSubRegionBase & subRegion, + real64 const time_n, + real64 const dt, + real64 const directEffectValue, + real64 const backgroundStressingRateValue ) +{ + GEOS_MARK_FUNCTION; + + using kernelType = std::conditional_t< ISPORO, SeismicityRateKernelPoroelastic, SeismicityRateKernel >; + kernelType kernel( subRegion ); + + forAll< POLICY >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + typename kernelType::StackVariables stack( directEffectValue, backgroundStressingRateValue ); + kernel.setup( k, stack ); + kernel.computeSeismicityRate( k, time_n, dt, stack ); + } ); +} + +} /* namespace seismicityRateKernels */ + +}/* namespace geos */ + +#endif /* GEOS_PHYSICSSOLVERS_SEISMICITYRATEKERNELS_HPP_ */ diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp new file mode 100644 index 00000000000..6179a0e5cf2 --- /dev/null +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp @@ -0,0 +1,58 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file inducedSeismicityFields.hpp + */ + +#ifndef GEOS_PHYSICSSOLVERS_INDUCEDSEISMICITY_INDUCEDSEISMICITYFIELDS_HPP_ +#define GEOS_PHYSICSSOLVERS_INDUCEDSEISMICITY_INDUCEDSEISMICITYFIELDS_HPP_ + +#include "common/DataLayouts.hpp" +#include "mesh/MeshFields.hpp" + +namespace geos +{ + +namespace fields +{ + +namespace rateAndState +{ + +DECLARE_FIELD( slipRate, + "slipRate", + array1d< real64 >, + 1.0e-6, + LEVEL_0, + WRITE_AND_READ, + "Slip rate" ); + +DECLARE_FIELD( stateVariable, + "stateVariable", + array1d< real64 >, + 0.6, + LEVEL_0, + WRITE_AND_READ, + "Rate- and state-dependent friction state variable" ); + + +} + +} + +} + +#endif // GEOS_PHYSICSSOLVERS_INDUCEDSEISMICITY_INDUCEDSEISMICITYFIELDS_HPP_ From 933f289392102cc6479b9a8e4baba5c337d34e0f Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Tue, 20 Aug 2024 16:45:51 -0700 Subject: [PATCH 06/53] wip. --- .../constitutive/CMakeLists.txt | 2 + .../constitutive/contact/CoulombFriction.hpp | 14 -- .../contact/RateAndStateFriction.hpp | 79 ++++---- .../denseLinearAlgebra/CMakeLists.txt | 1 + .../denseLinearAlgebra/denseLASolvers.hpp | 188 +++++++++++++++++- .../inducedSeismicity/CMakeLists.txt | 4 + .../inducedSeismicity/RateAndStateSolver.cpp | 99 --------- .../inducedSeismicity/RateAndStateSolver.hpp | 162 --------------- .../kernels/RateAndStateKernels.hpp | 40 ++-- .../inducedSeismicity/rateAndStateFields.hpp | 6 +- 10 files changed, 265 insertions(+), 330 deletions(-) delete mode 100644 src/coreComponents/physicsSolvers/inducedSeismicity/RateAndStateSolver.cpp delete mode 100644 src/coreComponents/physicsSolvers/inducedSeismicity/RateAndStateSolver.hpp diff --git a/src/coreComponents/constitutive/CMakeLists.txt b/src/coreComponents/constitutive/CMakeLists.txt index 38304adc24c..960221bf9bd 100644 --- a/src/coreComponents/constitutive/CMakeLists.txt +++ b/src/coreComponents/constitutive/CMakeLists.txt @@ -25,6 +25,7 @@ set( constitutive_headers contact/HydraulicApertureBase.hpp contact/HydraulicApertureRelationSelector.hpp contact/HydraulicApertureTable.hpp + contact/RateAndStateFriction.hpp diffusion/ConstantDiffusion.hpp diffusion/DiffusionBase.hpp diffusion/DiffusionFields.hpp @@ -198,6 +199,7 @@ set( constitutive_sources contact/FrictionlessContact.cpp contact/HydraulicApertureBase.cpp contact/HydraulicApertureTable.cpp + contact/RateAndStateFriction.cpp diffusion/ConstantDiffusion.cpp diffusion/DiffusionBase.cpp dispersion/DispersionBase.cpp diff --git a/src/coreComponents/constitutive/contact/CoulombFriction.hpp b/src/coreComponents/constitutive/contact/CoulombFriction.hpp index e2cd87f024f..49b9c5cd5a6 100644 --- a/src/coreComponents/constitutive/contact/CoulombFriction.hpp +++ b/src/coreComponents/constitutive/contact/CoulombFriction.hpp @@ -134,20 +134,6 @@ class CoulombFriction : public FrictionBase virtual void allocateConstitutiveData( dataRepository::Group & parent, localIndex const numConstitutivePointsPerParentIndex ) override final; - /** - * @brief Const accessor for cohesion - * @return A const reference to arrayView1d containing the - * cohesions (at every element). - */ - real64 const & cohesion() const { return m_cohesion; } - - /** - * @brief Const accessor for friction angle - * @return A const reference to arrayView1d containing the - * friction coefficient (at every element). - */ - real64 const & frictionCoefficient() const { return m_frictionCoefficient; } - /// Type of kernel wrapper for in-kernel update using KernelWrapper = CoulombFrictionUpdates; diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp index 3c89d3a1f3d..8905cd75247 100644 --- a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp +++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp @@ -65,37 +65,31 @@ class RateAndStateFriction : public FrictionBase virtual void allocateConstitutiveData( dataRepository::Group & parent, localIndex const numConstitutivePointsPerParentIndex ) override final; - /** - * @brief Const accessor for friction angle - * @return A const reference to arrayView1d containing the - * friction coefficient (at every element). - */ - real64 const & frictionCoefficient() const { return m_frictionCoefficient; } - class KernelWrapper : public FrictionBaseUpdates { public: KernelWrapper( real64 const displacementJumpThreshold, - arrayView1d< real64 > const frictionCoefficient, - arrayView1d< real64 > m_frictionCoefficient, - arrayView1d< real64 const > a, - arrayView1d< real64 const > b, - arrayView1d< real64 const > Dc, - arrayView1d< real64 const > V0 ) + arrayView1d< real64 > frictionCoefficient, + arrayView1d< real64 const > a, + arrayView1d< real64 const > b, + arrayView1d< real64 const > Dc, + arrayView1d< real64 const > V0, + arrayView1d< real64 const > mu0 ) : FrictionBaseUpdates( displacementJumpThreshold ), - m_frictionCoefficient( frictionCoefficient ) + m_frictionCoefficient( frictionCoefficient ), m_a( a ), m_b( b ), m_Dc( Dc ), - m_V0( V0 ) + m_V0( V0 ), + m_mu0( mu0 ) {} /// Default copy constructor - KernelWrapper( RateAndStateFrictionUpdates const & ) = default; + KernelWrapper( KernelWrapper const & ) = default; /// Default move constructor - KernelWrapper( RateAndStateFrictionUpdates && ) = default; + KernelWrapper( KernelWrapper && ) = default; /// Deleted default constructor KernelWrapper() = delete; @@ -114,7 +108,7 @@ class KernelWrapper : public FrictionBaseUpdates integer & fractureState ) const override final; GEOS_HOST_DEVICE -inline std::tuple< real64, real64[2] > +inline std::tuple< real64, real64, real64 > computeShearTraction( real64 const normalTraction, real64 const slipRate, real64 const stateVariable ) const; @@ -163,6 +157,9 @@ inline real64 dStateVariabledT_dSlipRate( localIndex const k, /// Rate and State reference velocity arrayView1d< real64 const > m_V0; + + /// Rate and State reference friction coefficient + arrayView1d< real64 const > m_mu0; }; @@ -191,6 +188,9 @@ inline real64 dStateVariabledT_dSlipRate( localIndex const k, /// Rate and State reference velocity array1d< real64 > m_V0; + /// Rate and State reference friction coefficient + array1d< real64 > m_mu0; + /** * @struct Set of "char const *" and keys for data specified in this class. */ @@ -198,6 +198,16 @@ inline real64 dStateVariabledT_dSlipRate( localIndex const k, { /// string/key for friction coefficient static constexpr char const * frictionCoefficientString() { return "frictionCoefficient"; } + /// string/key for friction coefficient + static constexpr char const * aCoefficientString() { return "a"; } + /// string/key for friction coefficient + static constexpr char const * bCoefficientString() { return "b"; } + /// string/key for friction coefficient + static constexpr char const * DcCoefficientString() { return "Dc"; } + /// string/key for friction coefficient + static constexpr char const * referenceVelocityString() { return "referenceVelocity"; } + /// string/key for friction coefficient + static constexpr char const * referenceFrictionCoefficientString() { return "referenceFrictionCoefficient"; } }; }; @@ -208,6 +218,8 @@ inline void RateAndStateFriction::KernelWrapper::updateFractureState( localIndex arraySlice1d< real64 const > const & tractionVector, integer & fractureState ) const { + + GEOS_UNUSED_VAR(tractionVector, k); using namespace fields::contact; if( dispJump[0] > -m_displacementJumpThreshold ) @@ -220,15 +232,16 @@ inline void RateAndStateFriction::KernelWrapper::updateFractureState( localIndex } GEOS_HOST_DEVICE -inline std::tuple< real64, real64[2] > +inline std::tuple< real64, real64, real64 > RateAndStateFriction::KernelWrapper::computeShearTraction( real64 const normalTraction, real64 const slipRate, real64 const stateVariable ) const { - real64 const shearTraction = 0.0; - real64 const dTauFriction = {0.0, 0.0}; + GEOS_UNUSED_VAR(normalTraction, slipRate, stateVariable); + real64 shearTraction = 0.0; + real64 dTauFriction[2] = {0.0, 0.0}; - return std::make_tuple( shearTraction, dTauFriction ); + return std::make_tuple( shearTraction, dTauFriction[0], dTauFriction[1] ); } GEOS_HOST_DEVICE @@ -237,7 +250,7 @@ inline real64 RateAndStateFriction::KernelWrapper::frictionCoefficient( localInd real64 const stateVariable ) const { real64 const arg = ( slipRate / (2 * m_V0[k]) ) * LvArray::math::exp( stateVariable / m_a[k] ); - real64 const frictionCoefficient = m_a[k] * LvArray::math::asinh( arg ); + real64 const frictionCoefficient = m_a[k] * LvArray::math::asin( arg ); //TODO: change!! asinh m_frictionCoefficient[k] = frictionCoefficient; @@ -250,20 +263,20 @@ inline real64 RateAndStateFriction::KernelWrapper::dfrictionCoefficient_dSlipRat real64 const stateVariable ) const { - real64 const inner_expression = ( slip_velocity / (2 * m_V0[k]) ) * LvArray::math::exp( theta / m_a[k] ) + real64 const inner_expression = ( slipRate / (2 * m_V0[k]) ) * LvArray::math::exp( stateVariable / m_a[k] ); - return (m_a[k] / LvArray::math::sqrt(1 + inner_expression**2)) * (1 / (2 * m_V0[k])) * LvArray::math::exp( theta / m_a[k] ); + return (m_a[k] / LvArray::math::sqrt(1 + inner_expression*inner_expression )) * (1 / (2 * m_V0[k])) * LvArray::math::exp( stateVariable / m_a[k] ); } GEOS_HOST_DEVICE -inline real64 dfrictionCoefficient_dStateVariable( localIndex const k, +inline real64 RateAndStateFriction::KernelWrapper::dfrictionCoefficient_dStateVariable( localIndex const k, real64 const slipRate, real64 const stateVariable) const { real64 const arg = (slipRate / (2 * m_V0[k])) * LvArray::math::exp(stateVariable / m_a[k]); - return (slipRate / (2 * m_V0[k])) * LvArray::math::exp(stateVariable / m_a[k]) / LvArray::math::sqrt(arg**2 + 1); + return ( slipRate / (2 * m_V0[k])) * LvArray::math::exp(stateVariable / m_a[k]) / LvArray::math::sqrt(arg * arg + 1); } GEOS_HOST_DEVICE @@ -273,7 +286,7 @@ inline real64 RateAndStateFriction::KernelWrapper::dStateVariabledT( localIndex { real64 const mu = frictionCoefficient(k, slipRate, stateVariable); - return -slipRate / m_Dc * (mu - m_mu0 + (m_b - m_a) * LvArray::math::log(slipRate / m_V0)) ; + return -slipRate / m_Dc[k] * (mu - m_mu0[k] + (m_b[k] - m_a[k]) * LvArray::math::log(slipRate / m_V0[k])) ; } GEOS_HOST_DEVICE @@ -281,19 +294,17 @@ inline real64 RateAndStateFriction::KernelWrapper::dStateVariabledT_dStateVariab real64 const slipRate, real64 const stateVariable) const { - return -slipRate /m_Dc[k] * dfrictionCoefficient_dStateVariable( k, slipRate, stateVariable ); + return -slipRate / m_Dc[k] * dfrictionCoefficient_dStateVariable( k, slipRate, stateVariable ); } GEOS_HOST_DEVICE inline real64 RateAndStateFriction::KernelWrapper::dStateVariabledT_dSlipRate( localIndex const k, real64 const slipRate, real64 const stateVariable ) const -{ - real64 const dfrictionCoefficient_dSlipRate = dfrictionCoefficient_dSlipRate(k, slipRate, stateVariable); - - real64 const part1 = - 1.0 / m_Dc[k] * (frictionCoefficient(slipRate, stateVariable) - m_mu0[k] + (m_b[k] - m_a[k]) * LvArray::math::log(slipRate / m_V0[k])) +{ + real64 const part1 = - 1.0 / m_Dc[k] * (frictionCoefficient(k, slipRate, stateVariable) - m_mu0[k] + (m_b[k] - m_a[k]) * LvArray::math::log(slipRate / m_V0[k])); - real64 const part2 = - slipRate / m_Dc[k] * (dfrictionCoefficient_dSlipRate + (m_b[k] - m_a[k]) / slipRate) + real64 const part2 = - slipRate / m_Dc[k] * (dfrictionCoefficient_dSlipRate(k, slipRate, stateVariable) + (m_b[k] - m_a[k]) / slipRate); return part1 + part2; } diff --git a/src/coreComponents/denseLinearAlgebra/CMakeLists.txt b/src/coreComponents/denseLinearAlgebra/CMakeLists.txt index 791767bc5c6..aa71e7ad349 100644 --- a/src/coreComponents/denseLinearAlgebra/CMakeLists.txt +++ b/src/coreComponents/denseLinearAlgebra/CMakeLists.txt @@ -1,5 +1,6 @@ # Specify all headers set( denseLinearAlgebra_headers + denseLASolvers.hpp common/layouts.hpp interfaces/blaslapack/BlasLapackFunctions.h interfaces/blaslapack/BlasLapackLA.hpp ) diff --git a/src/coreComponents/denseLinearAlgebra/denseLASolvers.hpp b/src/coreComponents/denseLinearAlgebra/denseLASolvers.hpp index d01016d1327..793820cd779 100644 --- a/src/coreComponents/denseLinearAlgebra/denseLASolvers.hpp +++ b/src/coreComponents/denseLinearAlgebra/denseLASolvers.hpp @@ -29,6 +29,9 @@ namespace geos namespace denseLinearAlgebra { + +namespace internal +{ /** * @brief Solves a 2x2 linear system A * x = b. * @@ -60,11 +63,188 @@ void solveTwoByTwoSystem( MATRIX_TYPE const & A, RHS_TYPE const & b, SOL_TYPE && GEOS_ERROR_IF_LT_MSG( LvArray::math::abs(detA), LvArray::NumericLimits< real64 >::epsilon;, "Singular system." ); - real64 const A_inv[2][2] = { { A[1][1] / detA, -A[0][1] / detA }, - { -A[1][0] / detA, A[0][0] / detA } }; + x[0] = (A[1][1] * b[0] - A[0][1] * b[1] ) / detA; + x[1] = (A[0][0] * b[1] - A[1][0] * b[0] ) / detA; +} - x[0] = A_inv[0][0] * b[0] + A_inv[0][1] * b[1]; - x[1] = A_inv[1][0] * b[0] + A_inv[1][1] * b[1]; +/** + * @brief Solves a 3x3 linear system A * x = b. + * + * This function solves a linear system of the form A * x = b, where A is a 3x3 matrix, + * b is a 3x1 vector, and x is the solution vector. The function checks the sizes + * of the inputs to ensure they conform to the expected dimensions. It also checks that + * the determinant of matrix A is not near zero to avoid solving a singular system. + * + * @tparam MATRIX_TYPE The type of the matrix A. Must support indexing with `A[i][j]`. + * @tparam RHS_TYPE The type of the right-hand side vector b. Must support indexing with `b[i]`. + * @tparam SOL_TYPE The type of the solution vector x. Must support indexing with `x[i]`. + * + * @param[in] A The 3x3 matrix representing the system of equations. Must have size 3x3. + * @param[in] b The 3-element vector representing the right-hand side of the equation. + * @param[out] x The 3-element vector that will store the solution to the system. + */ +template< typename MATRIX_TYPE, + typename RHS_TYPE, + typename SOL_TYPE > +GEOS_HOST_DEVICE +inline +void solveThreeByThreeSystem( MATRIX_TYPE const & A, RHS_TYPE const & b, SOL_TYPE && x) +{ + LvArray::tensorOps::internal::checkSizes< 3, 3 >( A ); + LvArray::tensorOps::internal::checkSizes< 3 >( b ); + LvArray::tensorOps::internal::checkSizes< 3 >( x ); + + real64 const detA = A[0][0] * (A[1][1] * A[2][2] - A[1][2] * A[2][1]) - + A[0][1] * (A[1][0] * A[2][2] - A[1][2] * A[2][0]) + + A[0][2] * (A[1][0] * A[2][1] - A[1][1] * A[2][0]); + + GEOS_ERROR_IF_LT_MSG( LvArray::math::abs(detA), LvArray::NumericLimits< real64 >::epsilon;, "Singular system." ); + + real64 const detX0 = b[0] * (A[1][1] * A[2][2] - A[1][2] * A[2][1]) - + b[1] * (A[0][1] * A[2][2] - A[0][2] * A[2][1]) + + b[2] * (A[0][1] * A[1][2] - A[0][2] * A[1][1]); + + real64 const detX1 = A[0][0] * (b[1] * A[2][2] - b[2] * A[2][1]) - + A[0][1] * (b[0] * A[2][2] - b[2] * A[2][0]) + + A[0][2] * (b[0] * A[1][2] - b[1] * A[1][0]); + + real64 const detX2 = A[0][0] * (A[1][1] * b[2] - A[1][2] * b[1]) - + A[0][1] * (A[1][0] * b[2] - A[1][2] * b[0]) + + A[0][2] * (A[1][0] * b[1] - A[1][1] * b[0]); + + x[0] = detX0 / detA; + x[1] = detX1 / detA; + x[2] = detX2 / detA; +} + + +template< std::ptrdiff_t N, + typename MATRIX_TYPE, + typename RHS_TYPE, + typename SOL_TYPE > +void solveUpperTriangularSystem( MATRIX_TYPE const & A, RHS_TYPE & b, SOL_TYPE && x ) +{ + for (std::ptrdiff_t i = N - 1; i >= 0; --i) + { + real64 sum = b[i]; + for (std::ptrdiff_t j = i + 1; j < N; ++j) + { + sum -= A[i][j] * x[j]; + } + x[i] = sum / A[i][i]; + } +} + +template< std::ptrdiff_t N, + typename MATRIX_TYPE, + typename RHS_TYPE, + typename SOL_TYPE > +GEOS_HOST_DEVICE +inline +void solveGaussianElimination( MATRIX_TYPE & A, RHS_TYPE & b, SOL_TYPE && x ) +{ + static_assert( N > 0, "N must be greater than 0." ); + internal::checkSizes< N, N >( matrix ); + internal::checkSizes< N >( b ); + internal::checkSizes< N >( x ); + + + // Step 1: Transform into an upper triangular matrix + + // 1.a. Find the pivot + for (std::ptrdiff_t i = 0; i < N; ++i) + { + std::ptrdiff_t max_row = i; + for (std::ptrdiff_t k = i + 1; k < N; ++k) + { + if (std::abs(A[k][i]) > std::abs(A[max_row][i])) + { + max_row = k; + } + } + + // 1.b. Swap rows + for (std::ptrdiff_t k = i; k < N; ++k) + { + std::swap(A[i][k], A[max_row][k]); + } + std::swap(b[i], b[max_row]); + + GEOS_ERROR_IF_LT_MSG( LvArray::math::abs(A[i][i]), LvArray::NumericLimits< real64 >::epsilon, "Singular matrix." ); + + // 1.c Eliminate entries below the pivot + for (std::ptrdiff_t k = i + 1; k < N; ++k) + { + real64 const scaling = A[k][i] / A[i][i]; + for (std::ptrdiff_t j = i; j < N; ++j) + { + A[k][j] -= scaling * A[i][j]; + } + b[k] -= scaling * b[i]; + } + } + + // Step 2: Backward substitution + solveUpperTriangularSystem( A, b, std::forward(x) ) +} + +/** + * Const version of the function + */ +template< std::ptrdiff_t N, + typename MATRIX_TYPE, + typename RHS_TYPE, + typename SOL_TYPE > +GEOS_HOST_DEVICE +inline +void solveGaussianElimination( MATRIX_TYPE const & A, RHS_TYPE const & b, SOL_TYPE && x ) +{ + real64[N][N] A_copy{}; + real64[N] b_copy{}; + + for(std::ptrdiff_t i=0; i < N; ++j) + { + b_copy[i] = b[i]; + for( std::ptrdiff_t j=0; j < N; ++j ) + { + A_copy[i][j] = A[i][j]; + }; + }; + + solveGaussianElimination( A_copy, b_copy, std::forward(x) ); +} + +}; // internal namespace + + +/** + * + */ +template< std::ptrdiff_t N, + typename MATRIX_TYPE, + typename RHS_TYPE, + typename SOL_TYPE > +GEOS_HOST_DEVICE +inline +void solve( MATRIX_TYPE const & A, RHS_TYPE const & b, SOL_TYPE && x ) +{ + static_assert( N > 0, "N must be greater than 0." ); + internal::checkSizes< N, N >( A ); + internal::checkSizes< N >( b ); + internal::checkSizes< N >( x ); + + if constexpr ( N == 2 ) + { + internal::solveTwoByTwoSystem( A, b, std::forward(x) ); + } + else if constexpr( N == 3 ) + { + internal::solveThreeByThreeSystem( A, b, std::forward(x) ); + } + else + { + internal::solveGaussianElimination< N >( A, b, std::forward(x) ); + } } }; diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/CMakeLists.txt b/src/coreComponents/physicsSolvers/inducedSeismicity/CMakeLists.txt index 0341bba8df9..aaa15658069 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/CMakeLists.txt +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/CMakeLists.txt @@ -2,12 +2,16 @@ set( physicsSolvers_headers ${physicsSolvers_headers} inducedSeismicity/inducedSeismicityFields.hpp + inducedSeismicity/rateAndStateFields.hpp + inducedSeismicity/RateAndState.hpp inducedSeismicity/SeismicityRate.hpp + inducedSeismicity/kernels/RateAndStateKernels.hpp inducedSeismicity/kernels/SeismicityRateKernels.hpp PARENT_SCOPE ) # Specify solver sources set( physicsSolvers_sources ${physicsSolvers_sources} + inducedSeismicity/RateAndState.cpp inducedSeismicity/SeismicityRate.cpp PARENT_SCOPE ) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/RateAndStateSolver.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/RateAndStateSolver.cpp deleted file mode 100644 index ace55b1b1f6..00000000000 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/RateAndStateSolver.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * SPDX-License-Identifier: LGPL-2.1-only - * - * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 Total, S.A - * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University - * Copyright (c) 2018-2024 Chevron - * Copyright (c) 2019- GEOS/GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file RateAndState.cpp - */ - -#include "RateAndState.hpp" - -#include "dataRepository/InputFlags.hpp" -#include "mainInterface/GeosxState.hpp" -#include "mesh/mpiCommunications/CommunicationTools.hpp" -#include "rateAndStateFields.hpp" - - -namespace geos -{ - -using namespace dataRepository; -using namespace constitutive; - -RateAndState::RateAndState( const string & name, - Group * const parent ): - SolverBase( name, parent ), - m_stressSolver( nullptr ) -{ - -} - -void RateAndState::postInputInitialization() -{ - - SolverBase::postInputInitialization(); -} - -RateAndState::~RateAndState() -{ - // TODO Auto-generated destructor stub -} - -void RateAndState::registerDataOnMesh( Group & meshBodies ) -{ - SolverBase::registerDataOnMesh( meshBodies ); - - forDiscretizationOnMeshTargets( meshBodies, [&] ( string const &, - MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) - { - ElementRegionManager & elemManager = mesh.getElemManager(); - - elemManager.forElementSubRegions< SurfaceElementSubRegion >( regionNames, - [&]( localIndex const, - SurfaceElementSubRegion & subRegion ) - { - subRegion.registerField< fields::rateAndState::slipRate >( getName() ); - - subRegion.registerField< fields::rateAndState::stateVariable >( getName() ); - } ); - } ); -} - -real64 RateAndState::solverStep( real64 const & time_n, - real64 const & dt, - const int cycleNumber, - DomainPartition & domain ) -{ - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) - { - ElementRegionManager & elemManager = mesh.getElemManager(); - elemManager.forElementSubRegions< SurfaceElementSubRegion >( regionNames, - [&]( localIndex const, - SurfaceElementSubRegion & subRegion ) - { - - - - } ); - } ) ; - - - return dt; -} - -REGISTER_CATALOG_ENTRY( SolverBase, RateAndState, string const &, dataRepository::Group * const ) -} // namespace geos diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/RateAndStateSolver.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/RateAndStateSolver.hpp deleted file mode 100644 index e48424050ac..00000000000 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/RateAndStateSolver.hpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * SPDX-License-Identifier: LGPL-2.1-only - * - * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 Total, S.A - * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University - * Copyright (c) 2018-2024 Chevron - * Copyright (c) 2019- GEOS/GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -#ifndef GEOS_PHYSICSSOLVERS_INDUCED_SEISMICITY_SEISMICITYRATE_HPP -#define GEOS_PHYSICSSOLVERS_INDUCED_SEISMICITY_SEISMICITYRATE_HPP - -#include "codingUtilities/EnumStrings.hpp" // facilities for enum-string conversion (for reading enum values from XML input) -#include "physicsSolvers/SolverBase.hpp" // an abstraction class shared by all physics solvers -#include "fieldSpecification/FieldSpecificationManager.hpp" // a manager that can access and set values on the discretized domain - -#include "physicsSolvers/inducedSeismicity/inducedSeismicityFields.hpp" - -#include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" - -namespace geos -{ - -class RateAndState : public SolverBase -{ -public: - /// The default nullary constructor is disabled to avoid compiler auto-generation: - RateAndState() = delete; - - /// The constructor needs a user-defined "name" and a parent Group (to place this instance in the tree structure of classes) - RateAndState( const string & name, - Group * const parent ); - - /// Destructor - virtual ~RateAndState() override; - - static string catalogName() { return "RateAndState"; } - - /** - * @return Get the final class Catalog name - */ - virtual string getCatalogName() const override { return catalogName(); } - - /// This method ties properties with their supporting mesh - virtual void registerDataOnMesh( Group & meshBodies ) override; - - struct viewKeyStruct : public SolverBase::viewKeyStruct - { - static constexpr char const * stressSolverNameString() { return "stressSolverName"; } - static constexpr char const * initialFaultNormalTractionString() { return "initialFaultNormalTraction"; } - static constexpr char const * initialFaultShearTractionString() { return "initialFaultShearTraction"; } - static constexpr char const * faultNormalDirectionString() { return "faultNormalDirection"; } - static constexpr char const * faultShearDirectionString() { return "faultShearDirection"; } - static constexpr char const * directEffectString() { return "directEffect"; } - static constexpr char const * backgroundStressingRateString() { return "backgroundStressingRate"; } - }; - - virtual real64 solverStep( real64 const & time_n, - real64 const & dt, - integer const cycleNumber, - DomainPartition & domain ) override final; - - /** - * @brief single step advance in computing the seismicity rate based on - * stress history according to closed form integral solution (Heimisson & Segall, 2018) - * to the ODE formulated by Dieterich, 1994 - * @param time_n time at previous converged step - * @param dt time step size - * @param subRegion ElementSubRegionBase to compute the solution in - */ - void integralSolverStep( real64 const & time_n, - real64 const & dt, - ElementSubRegionBase & subRegion ); - - /** - * @brief called in SolverStep after member stress solver is called to - * project the stress state to pre-defined fault orientations - * @param subRegion The ElementSubRegionBase that will have the stress information - */ - void updateFaultTraction( ElementSubRegionBase & subRegion ) const; - - /** - * @brief save the old state - * @param subRegion - */ - void saveOldState( ElementSubRegionBase & subRegion ) const; - - /** - * @brief - * @param biotCoefficient - * @param pres - * @param sig - * @param tau - */ - void computeTotalStressOnFault( arrayView1d< real64 const > const biotCoefficient, - arrayView1d< real64 const > const pres, - real64 const (&faultNormalProjectionTensor)[6], - real64 const (&faultShearProjectionTensor)[6], - arrayView1d< real64 > const sig, - arrayView1d< real64 > const tau ) const; - - /** - * @brief called in SolverStep before member stress solver is called to - * project the initial stress state to pre-defined fault orientations, - * only when cycleNumber == 0 - * @param cycleNumber current cycle number - * @param domain The DomainPartition of the problem - */ - void initializeFaultTraction( real64 const time_n, - integer const cycleNumber, - DomainPartition & domain ) const; - - -protected: - - /** - * @brief update the stresses either by asking the stressSolver or by applying b.c. - * @param time_n the current time - * @param dt the current time step - * @param cycleNumber the cycle number - * @param domain the DomainPartion group - */ - real64 updateStresses( real64 const & time_n, - real64 const & dt, - const int cycleNumber, - DomainPartition & domain ) const; - - - - void constructFaultStressProjectionTensors( real64 ( &faultNormalProjectionTensor )[6], - real64 ( &faultShearProjectionTensor )[6] ) const; - - virtual void postInputInitialization() override; - - /// pointer to stress solver - SolverBase * m_stressSolver; - - /// stress solver name string - string m_stressSolverName; - - /// fault orientation: normal direction - R1Tensor m_faultNormalDirection; - - /// fault orientation: shear direction - R1Tensor m_faultShearDirection; - - /// direct effect coefficient - real64 m_directEffect; - - /// bacground stressing rate - real64 m_backgroundStressingRate; -}; - -} /* namespace geos */ - -#endif /* GEOS_PHYSICSSOLVERS_INDUCED_SEISMICITY_SEISMICITYRATE_HPP */ diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index 194d145e717..3129b63954f 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -18,6 +18,7 @@ #include "common/DataTypes.hpp" #include "common/GEOS_RAJA_Interface.hpp" +#include "constitutive/contact/RateAndStateFriction.hpp" #include "physicsSolvers/inducedSeismicity/rateAndStateFields.hpp" #include "denseLinearAlgebra/denseLASolvers.hpp" @@ -37,7 +38,14 @@ class RateAndStateKernel { public: - RateAndStateKernel( SurfaceElementSubRegion & subRegion ): + RateAndStateKernel( SurfaceElementSubRegion & subRegion, + RateAndStateFriction const & frictionLaw ): + m_slipRate( subRegion.getField< fields::rateAndState::slipRate >() ), + m_stateVariable( subRegion.getField< fields::rateAndState::stateVariable >() ), + m_stateVariable_n( subRegion.getField< fields::rateAndState::stateVariable >() ), + m_normalTraction( subRegion.getField< fields::rateAndState::slipRate >() ), + m_shearTraction( subRegion.getField< fields::rateAndState::slipRate >() ), + m_frictionLaw( frictionLaw.createKernelWrapper() ) {} /** @@ -52,20 +60,21 @@ class RateAndStateKernel StackVariables( ) {} - jacobian[2][2]{}; + real64 jacobian[2][2]{}; - rhs[2]{}; + real64 rhs[2]{}; }; GEOS_HOST_DEVICE void setup( localIndex const k, + real64 const dt, StackVariables & stack ) const { // Eq 1: shear stress balance real64 tauFriction = 0.0; - real64 dTauFriction = {0.0, 0.0}; + real64 dTauFriction[2] = {0.0, 0.0}; frictionLaw.computeShearTraction( m_normalTraction[k], m_slipRate[k], @@ -76,7 +85,7 @@ class RateAndStateKernel stack.rhs[0] = m_shearTraction[k] - tauFriction; // Eq 2: slip law - stack.rhs[1] = (theta - theta_n) / dt - m_frictionLaw.dStateVariabledT( m_slipRate[k], m_stateVariable[k] ) + stack.rhs[1] = (m_stateVariable[k] - m_stateVariable_n[k]) / dt - m_frictionLaw.dStateVariabledT( m_slipRate[k], m_stateVariable[k] ) real64 const dStateEvolutionLaw[0] = 1 / dt - m_frictionLaw.dStateVariabledT_dtheta( m_slipRate[k], m_stateVariable[k] ) real64 const dStateEvolutionLaw[1] = - m_frictionLaw.dStateVariabledT_dSlipRate( m_slipRate[k], m_stateVariable[k] ) @@ -96,13 +105,13 @@ class RateAndStateKernel StackVariables & stack ) const { /// Solve 2x2 system - real64 const solution = {0.0, 0.0}; + real64 const solution[2] = {0.0, 0.0}; denseLinearAlgebra::solveTwoByTwoSystem( stack.jacobian, stack.rhs, solution ); /// Update variables - m_stateVariable[k] += soluiton[0]; - m_slipRate[k] += soluiton[1]; + m_stateVariable[k] += solution[0]; + m_slipRate[k] += solution[1]; } private: @@ -111,6 +120,8 @@ class RateAndStateKernel arrayView1d< real64 > const m_stateVariable; + arrayView1d< real64 const > const m_stateVariable_n; + arrayView1d< real64 const > const m_normalTraction; arrayView1d< real64 const > const m_shearTraction; @@ -127,15 +138,16 @@ class RateAndStateKernel */ template< typename POLICY > static void -createAndLaunch( SurfaceElementSubRegionBase & subRegion, +createAndLaunch( SurfaceElementSubRegion & subRegion, + string const & frictionLawName, integer const maxNewtonIter, real64 const time_n, real64 const dt ) { GEOS_MARK_FUNCTION; - using kernelType ; - kernelType kernel( subRegion ); + RateAndStateFrction const & frictionLaw = subRegion.getConstitutiveModel( frictionaLawName ); + RateAndStateKernel kernel( subRegion, frictionLaw ); // Newton loops outside of the kernel launch for( integer iter = 0; iter < maxNewtonIter; iter++ ) @@ -143,9 +155,9 @@ createAndLaunch( SurfaceElementSubRegionBase & subRegion, /// Kernel 1: Do a solver for all non converged elements forAll< POLICY >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { - typename kernelType::StackVariables stack(); - kernel.setup( k, stack ); - kernel.( k, time_n, dt, stack ); + RateAndStateKernel::StackVariables stack(); + kernel.setup( k, dt, stack ); + kernel.solve( k, stack ); } ); /// Kernel 2: Update set of non-converged elements diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp index 6179a0e5cf2..3a054f6b95c 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp @@ -14,11 +14,11 @@ */ /** - * @file inducedSeismicityFields.hpp + * @file rateAndStateFields.hpp */ -#ifndef GEOS_PHYSICSSOLVERS_INDUCEDSEISMICITY_INDUCEDSEISMICITYFIELDS_HPP_ -#define GEOS_PHYSICSSOLVERS_INDUCEDSEISMICITY_INDUCEDSEISMICITYFIELDS_HPP_ +#ifndef GEOS_PHYSICSSOLVERS_INDUCEDSEISMICITY_RATEANDSTATEFIELDS_HPP_ +#define GEOS_PHYSICSSOLVERS_INDUCEDSEISMICITY_RATEANDSTATEFIELDS_HPP_ #include "common/DataLayouts.hpp" #include "mesh/MeshFields.hpp" From 4e16608653ecc60e3fb76815b3e9937b98920570 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Mon, 26 Aug 2024 15:03:52 -0700 Subject: [PATCH 07/53] remove solvers. --- src/coreComponents/LvArray | 2 +- .../denseLinearAlgebra/CMakeLists.txt | 1 - .../denseLinearAlgebra/denseLASolvers.hpp | 255 ------------------ 3 files changed, 1 insertion(+), 257 deletions(-) delete mode 100644 src/coreComponents/denseLinearAlgebra/denseLASolvers.hpp diff --git a/src/coreComponents/LvArray b/src/coreComponents/LvArray index 02ce362c009..69948929ca4 160000 --- a/src/coreComponents/LvArray +++ b/src/coreComponents/LvArray @@ -1 +1 @@ -Subproject commit 02ce362c009f11ddb2ade0286df23408d7334c4f +Subproject commit 69948929ca40acf490143fc020f72cd12d331f37 diff --git a/src/coreComponents/denseLinearAlgebra/CMakeLists.txt b/src/coreComponents/denseLinearAlgebra/CMakeLists.txt index aa71e7ad349..791767bc5c6 100644 --- a/src/coreComponents/denseLinearAlgebra/CMakeLists.txt +++ b/src/coreComponents/denseLinearAlgebra/CMakeLists.txt @@ -1,6 +1,5 @@ # Specify all headers set( denseLinearAlgebra_headers - denseLASolvers.hpp common/layouts.hpp interfaces/blaslapack/BlasLapackFunctions.h interfaces/blaslapack/BlasLapackLA.hpp ) diff --git a/src/coreComponents/denseLinearAlgebra/denseLASolvers.hpp b/src/coreComponents/denseLinearAlgebra/denseLASolvers.hpp deleted file mode 100644 index 793820cd779..00000000000 --- a/src/coreComponents/denseLinearAlgebra/denseLASolvers.hpp +++ /dev/null @@ -1,255 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * SPDX-License-Identifier: LGPL-2.1-only - * - * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 Total, S.A - * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University - * Copyright (c) 2018-2024 Chevron - * Copyright (c) 2019- GEOS/GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file denseLASolvers.hpp - */ -#ifndef GEOS_DENSELINEARALGEBRA_DENSELASOLVERS_HPP_ -#define GEOS_DENSELINEARALGEBRA_DENSELASOLVERS_HPP_ - -#include "common/DataTypes.hpp" -#include "denseLinearAlgebra/common/layouts.hpp" - -#include - -namespace geos -{ - -namespace denseLinearAlgebra -{ - -namespace internal -{ -/** - * @brief Solves a 2x2 linear system A * x = b. - * - * This function solves a linear system of the form A * x = b, where A is a 2x2 matrix, - * b is a 2x1 vector, and x is the solution vector. The function checks the sizes - * of the inputs to ensure they conform to the expected dimensions. It also checks that - * the determinant of matrix A is not near zero to avoid solving a singular system. - * - * @tparam MATRIX_TYPE The type of the matrix A. Must support indexing with `A[i][j]`. - * @tparam RHS_TYPE The type of the right-hand side vector b. Must support indexing with `b[i]`. - * @tparam SOL_TYPE The type of the solution vector x. Must support indexing with `x[i]`. - * - * @param[in] A The 2x2 matrix representing the system of equations. Must have size 2x2. - * @param[in] b The 2-element vector representing the right-hand side of the equation. - * @param[out] x The 2-element vector that will store the solution to the system. - */ -template< typename MATRIX_TYPE, - typename RHS_TYPE, - typename SOL_TYPE > -GEOS_HOST_DEVICE -inline -void solveTwoByTwoSystem( MATRIX_TYPE const & A, RHS_TYPE const & b, SOL_TYPE && x) -{ - LvArray::tensorOps::internal::checkSizes< 2, 2 >( A ); - LvArray::tensorOps::internal::checkSizes< 2 >( b ); - LvArray::tensorOps::internal::checkSizes< 2 >( x ); - - real64 const detA = A[0][0] * A[1][1] - A[0][1] * A[1][0]; - - GEOS_ERROR_IF_LT_MSG( LvArray::math::abs(detA), LvArray::NumericLimits< real64 >::epsilon;, "Singular system." ); - - x[0] = (A[1][1] * b[0] - A[0][1] * b[1] ) / detA; - x[1] = (A[0][0] * b[1] - A[1][0] * b[0] ) / detA; -} - -/** - * @brief Solves a 3x3 linear system A * x = b. - * - * This function solves a linear system of the form A * x = b, where A is a 3x3 matrix, - * b is a 3x1 vector, and x is the solution vector. The function checks the sizes - * of the inputs to ensure they conform to the expected dimensions. It also checks that - * the determinant of matrix A is not near zero to avoid solving a singular system. - * - * @tparam MATRIX_TYPE The type of the matrix A. Must support indexing with `A[i][j]`. - * @tparam RHS_TYPE The type of the right-hand side vector b. Must support indexing with `b[i]`. - * @tparam SOL_TYPE The type of the solution vector x. Must support indexing with `x[i]`. - * - * @param[in] A The 3x3 matrix representing the system of equations. Must have size 3x3. - * @param[in] b The 3-element vector representing the right-hand side of the equation. - * @param[out] x The 3-element vector that will store the solution to the system. - */ -template< typename MATRIX_TYPE, - typename RHS_TYPE, - typename SOL_TYPE > -GEOS_HOST_DEVICE -inline -void solveThreeByThreeSystem( MATRIX_TYPE const & A, RHS_TYPE const & b, SOL_TYPE && x) -{ - LvArray::tensorOps::internal::checkSizes< 3, 3 >( A ); - LvArray::tensorOps::internal::checkSizes< 3 >( b ); - LvArray::tensorOps::internal::checkSizes< 3 >( x ); - - real64 const detA = A[0][0] * (A[1][1] * A[2][2] - A[1][2] * A[2][1]) - - A[0][1] * (A[1][0] * A[2][2] - A[1][2] * A[2][0]) + - A[0][2] * (A[1][0] * A[2][1] - A[1][1] * A[2][0]); - - GEOS_ERROR_IF_LT_MSG( LvArray::math::abs(detA), LvArray::NumericLimits< real64 >::epsilon;, "Singular system." ); - - real64 const detX0 = b[0] * (A[1][1] * A[2][2] - A[1][2] * A[2][1]) - - b[1] * (A[0][1] * A[2][2] - A[0][2] * A[2][1]) + - b[2] * (A[0][1] * A[1][2] - A[0][2] * A[1][1]); - - real64 const detX1 = A[0][0] * (b[1] * A[2][2] - b[2] * A[2][1]) - - A[0][1] * (b[0] * A[2][2] - b[2] * A[2][0]) + - A[0][2] * (b[0] * A[1][2] - b[1] * A[1][0]); - - real64 const detX2 = A[0][0] * (A[1][1] * b[2] - A[1][2] * b[1]) - - A[0][1] * (A[1][0] * b[2] - A[1][2] * b[0]) + - A[0][2] * (A[1][0] * b[1] - A[1][1] * b[0]); - - x[0] = detX0 / detA; - x[1] = detX1 / detA; - x[2] = detX2 / detA; -} - - -template< std::ptrdiff_t N, - typename MATRIX_TYPE, - typename RHS_TYPE, - typename SOL_TYPE > -void solveUpperTriangularSystem( MATRIX_TYPE const & A, RHS_TYPE & b, SOL_TYPE && x ) -{ - for (std::ptrdiff_t i = N - 1; i >= 0; --i) - { - real64 sum = b[i]; - for (std::ptrdiff_t j = i + 1; j < N; ++j) - { - sum -= A[i][j] * x[j]; - } - x[i] = sum / A[i][i]; - } -} - -template< std::ptrdiff_t N, - typename MATRIX_TYPE, - typename RHS_TYPE, - typename SOL_TYPE > -GEOS_HOST_DEVICE -inline -void solveGaussianElimination( MATRIX_TYPE & A, RHS_TYPE & b, SOL_TYPE && x ) -{ - static_assert( N > 0, "N must be greater than 0." ); - internal::checkSizes< N, N >( matrix ); - internal::checkSizes< N >( b ); - internal::checkSizes< N >( x ); - - - // Step 1: Transform into an upper triangular matrix - - // 1.a. Find the pivot - for (std::ptrdiff_t i = 0; i < N; ++i) - { - std::ptrdiff_t max_row = i; - for (std::ptrdiff_t k = i + 1; k < N; ++k) - { - if (std::abs(A[k][i]) > std::abs(A[max_row][i])) - { - max_row = k; - } - } - - // 1.b. Swap rows - for (std::ptrdiff_t k = i; k < N; ++k) - { - std::swap(A[i][k], A[max_row][k]); - } - std::swap(b[i], b[max_row]); - - GEOS_ERROR_IF_LT_MSG( LvArray::math::abs(A[i][i]), LvArray::NumericLimits< real64 >::epsilon, "Singular matrix." ); - - // 1.c Eliminate entries below the pivot - for (std::ptrdiff_t k = i + 1; k < N; ++k) - { - real64 const scaling = A[k][i] / A[i][i]; - for (std::ptrdiff_t j = i; j < N; ++j) - { - A[k][j] -= scaling * A[i][j]; - } - b[k] -= scaling * b[i]; - } - } - - // Step 2: Backward substitution - solveUpperTriangularSystem( A, b, std::forward(x) ) -} - -/** - * Const version of the function - */ -template< std::ptrdiff_t N, - typename MATRIX_TYPE, - typename RHS_TYPE, - typename SOL_TYPE > -GEOS_HOST_DEVICE -inline -void solveGaussianElimination( MATRIX_TYPE const & A, RHS_TYPE const & b, SOL_TYPE && x ) -{ - real64[N][N] A_copy{}; - real64[N] b_copy{}; - - for(std::ptrdiff_t i=0; i < N; ++j) - { - b_copy[i] = b[i]; - for( std::ptrdiff_t j=0; j < N; ++j ) - { - A_copy[i][j] = A[i][j]; - }; - }; - - solveGaussianElimination( A_copy, b_copy, std::forward(x) ); -} - -}; // internal namespace - - -/** - * - */ -template< std::ptrdiff_t N, - typename MATRIX_TYPE, - typename RHS_TYPE, - typename SOL_TYPE > -GEOS_HOST_DEVICE -inline -void solve( MATRIX_TYPE const & A, RHS_TYPE const & b, SOL_TYPE && x ) -{ - static_assert( N > 0, "N must be greater than 0." ); - internal::checkSizes< N, N >( A ); - internal::checkSizes< N >( b ); - internal::checkSizes< N >( x ); - - if constexpr ( N == 2 ) - { - internal::solveTwoByTwoSystem( A, b, std::forward(x) ); - } - else if constexpr( N == 3 ) - { - internal::solveThreeByThreeSystem( A, b, std::forward(x) ); - } - else - { - internal::solveGaussianElimination< N >( A, b, std::forward(x) ); - } -} - -}; - -}; - - -#endif /*GEOS_DENSELINEARALGEBRA_DENSELASOLVERS_HPP_*/ From bd377d4e2700b59007f01a2600fcd3e4ea2a030c Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Fri, 13 Sep 2024 14:29:08 -0700 Subject: [PATCH 08/53] add physicsPackage. --- .../inducedSeismicity/SeismicityRate.cpp | 2 ++ .../inducedSeismicity/SeismicityRate.hpp | 8 +------- .../kernels/RateAndStateKernels.hpp | 2 +- .../inducedSeismicity/rateAndStateFields.hpp | 18 +++++++++++++++++- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.cpp index a690a29dea3..57ff15befce 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.cpp @@ -25,6 +25,8 @@ #include "mesh/mpiCommunications/CommunicationTools.hpp" #include "physicsSolvers/solidMechanics/SolidMechanicsLagrangianFEM.hpp" #include "kernels/SeismicityRateKernels.hpp" +#include "physicsSolvers/inducedSeismicity/inducedSeismicityFields.hpp" +#include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" namespace geos { diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.hpp index 30124cb34fa..2b94f4ac296 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.hpp @@ -16,13 +16,7 @@ #ifndef GEOS_PHYSICSSOLVERS_INDUCED_SEISMICITY_SEISMICITYRATE_HPP #define GEOS_PHYSICSSOLVERS_INDUCED_SEISMICITY_SEISMICITYRATE_HPP -#include "codingUtilities/EnumStrings.hpp" // facilities for enum-string conversion (for reading enum values from XML input) -#include "physicsSolvers/SolverBase.hpp" // an abstraction class shared by all physics solvers -#include "fieldSpecification/FieldSpecificationManager.hpp" // a manager that can access and set values on the discretized domain - -#include "physicsSolvers/inducedSeismicity/inducedSeismicityFields.hpp" - -#include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" +#include "physicsSolvers/SolverBase.hpp" namespace geos { diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index 3129b63954f..f40d6d0bf8b 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -107,7 +107,7 @@ class RateAndStateKernel /// Solve 2x2 system real64 const solution[2] = {0.0, 0.0}; - denseLinearAlgebra::solveTwoByTwoSystem( stack.jacobian, stack.rhs, solution ); + denseLinearAlgebra::solve( stack.jacobian, stack.rhs, solution ); /// Update variables m_stateVariable[k] += solution[0]; diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp index 3a054f6b95c..97f2708541a 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp @@ -46,7 +46,23 @@ DECLARE_FIELD( stateVariable, 0.6, LEVEL_0, WRITE_AND_READ, - "Rate- and state-dependent friction state variable" ); + "Rate- and state-dependent friction state variable" ); + +DECLARE_FIELD( slipRate_n, + "slipRate_n", + array1d< real64 >, + 1.0e-6, + NO_PLOT, + WRITE_AND_READ, + "Slip rate at previous time step" ); + +DECLARE_FIELD( stateVariable_n, + "stateVariable_n", + array1d< real64 >, + 0.6, + NO_PLOT, + WRITE_AND_READ, + "Rate- and state-dependent friction state variable at previous time step" ); } From b0024410070e4aa973c264492fea06e369991ae4 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Fri, 13 Sep 2024 14:55:17 -0700 Subject: [PATCH 09/53] add o cmake list plus add some needed keys. --- .../physicsSolvers/inducedSeismicity/CMakeLists.txt | 4 ++-- .../inducedSeismicity/kernels/RateAndStateKernels.hpp | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/CMakeLists.txt b/src/coreComponents/physicsSolvers/inducedSeismicity/CMakeLists.txt index aaa15658069..7edf040454d 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/CMakeLists.txt +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/CMakeLists.txt @@ -3,7 +3,7 @@ set( physicsSolvers_headers ${physicsSolvers_headers} inducedSeismicity/inducedSeismicityFields.hpp inducedSeismicity/rateAndStateFields.hpp - inducedSeismicity/RateAndState.hpp + inducedSeismicity/QuasiDynamicEQ.hpp inducedSeismicity/SeismicityRate.hpp inducedSeismicity/kernels/RateAndStateKernels.hpp inducedSeismicity/kernels/SeismicityRateKernels.hpp @@ -12,6 +12,6 @@ set( physicsSolvers_headers # Specify solver sources set( physicsSolvers_sources ${physicsSolvers_sources} - inducedSeismicity/RateAndState.cpp + inducedSeismicity/QuasiDynamicEQ.cpp inducedSeismicity/SeismicityRate.cpp PARENT_SCOPE ) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index f40d6d0bf8b..07b137b3c5a 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -139,13 +139,14 @@ class RateAndStateKernel template< typename POLICY > static void createAndLaunch( SurfaceElementSubRegion & subRegion, - string const & frictionLawName, + string const & frictionLawNameKey, integer const maxNewtonIter, real64 const time_n, real64 const dt ) { GEOS_MARK_FUNCTION; - + + string const & frictionaLawName = subRegion.getReference< string >( vfrictionLawNameKey ); RateAndStateFrction const & frictionLaw = subRegion.getConstitutiveModel( frictionaLawName ); RateAndStateKernel kernel( subRegion, frictionLaw ); From 0c23356c2351b40ecdf8b82029514e81e6c1ef42 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Fri, 13 Sep 2024 15:09:52 -0700 Subject: [PATCH 10/53] add missing files. --- .../contact/RateAndStateFriction.cpp | 316 ++++++++++++++++++ .../inducedSeismicity/QuasiDynamicEQ.cpp | 155 +++++++++ .../inducedSeismicity/QuasiDynamicEQ.hpp | 81 +++++ 3 files changed, 552 insertions(+) create mode 100644 src/coreComponents/constitutive/contact/RateAndStateFriction.cpp create mode 100644 src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp create mode 100644 src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp new file mode 100644 index 00000000000..8905cd75247 --- /dev/null +++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp @@ -0,0 +1,316 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file RateAndStateFriction.hpp + */ + +#ifndef GEOS_CONSTITUTIVE_CONTACT_RATEANDSTATEFRICTION_HPP_ +#define GEOS_CONSTITUTIVE_CONTACT_RATEANDSTATEFRICTION_HPP_ + +#include "FrictionBase.hpp" + +namespace geos +{ + +namespace constitutive +{ + +/** + * @class RateAndStateFrictionUpdates + * + * This class is used for in-kernel contact relation updates + */ + + +/** + * @class RateAndStateFriction + * + * Class to provide a RateAndStateFriction friction model. + */ +class RateAndStateFriction : public FrictionBase +{ +public: + + /** + * constructor + * @param[in] name name of the instance in the catalog + * @param[in] parent the group which contains this instance + */ + RateAndStateFriction( string const & name, Group * const parent ); + + /** + * Default Destructor + */ + virtual ~RateAndStateFriction() override; + + static string catalogName() { return "RateAndStateFriction"; } + + virtual string getCatalogName() const override { return catalogName(); } + + ///@} + + virtual void allocateConstitutiveData( dataRepository::Group & parent, + localIndex const numConstitutivePointsPerParentIndex ) override final; + + +class KernelWrapper : public FrictionBaseUpdates +{ +public: + KernelWrapper( real64 const displacementJumpThreshold, + arrayView1d< real64 > frictionCoefficient, + arrayView1d< real64 const > a, + arrayView1d< real64 const > b, + arrayView1d< real64 const > Dc, + arrayView1d< real64 const > V0, + arrayView1d< real64 const > mu0 ) + : FrictionBaseUpdates( displacementJumpThreshold ), + m_frictionCoefficient( frictionCoefficient ), + m_a( a ), + m_b( b ), + m_Dc( Dc ), + m_V0( V0 ), + m_mu0( mu0 ) + {} + + /// Default copy constructor + KernelWrapper( KernelWrapper const & ) = default; + + /// Default move constructor + KernelWrapper( KernelWrapper && ) = default; + + /// Deleted default constructor + KernelWrapper() = delete; + + /// Deleted copy assignment operator + KernelWrapper & operator=( KernelWrapper const & ) = delete; + + /// Deleted move assignment operator + KernelWrapper & operator=( KernelWrapper && ) = delete; + + GEOS_HOST_DEVICE + inline + virtual void updateFractureState( localIndex const k, + arraySlice1d< real64 const > const & dispJump, + arraySlice1d< real64 const > const & tractionVector, + integer & fractureState ) const override final; + +GEOS_HOST_DEVICE +inline std::tuple< real64, real64, real64 > +computeShearTraction( real64 const normalTraction, + real64 const slipRate, + real64 const stateVariable ) const; + +GEOS_HOST_DEVICE +inline real64 frictionCoefficient( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const; + +GEOS_HOST_DEVICE +inline real64 dfrictionCoefficient_dSlipRate( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const; + +GEOS_HOST_DEVICE +inline real64 dfrictionCoefficient_dStateVariable( localIndex const k, + real64 const slipRate, + real64 const stateVariable) const; + +GEOS_HOST_DEVICE +inline real64 dStateVariabledT( localIndex const k, + real64 const slipRate, + real64 const stateVariable) const; + +GEOS_HOST_DEVICE +inline real64 dStateVariabledT_dStateVariable( localIndex const k, + real64 const slipRate, + real64 const stateVariable) const; + +GEOS_HOST_DEVICE +inline real64 dStateVariabledT_dSlipRate( localIndex const k, + real64 const slipRate, + real64 const stateVariable) const; +private: + /// The friction coefficient + arrayView1d< real64 > m_frictionCoefficient; + + /// Rate and State coefficient a + arrayView1d< real64 const > m_a; + + /// Rate and State coefficient b + arrayView1d< real64 const > m_b; + + /// Rate and State characteristic length + arrayView1d< real64 const > m_Dc; + + /// Rate and State reference velocity + arrayView1d< real64 const > m_V0; + + /// Rate and State reference friction coefficient + arrayView1d< real64 const > m_mu0; +}; + + + /** + * @brief Create an update kernel wrapper. + * @return the wrapper + */ + KernelWrapper createKernelWrapper() const; + +private: + + virtual void postInputInitialization() override; + + /// The friction coefficient for each upper level dimension (i.e. cell) of *this + array1d< real64 > m_frictionCoefficient; + + /// Rate and State coefficient a + array1d< real64 > m_a; + + /// Rate and State coefficient b + array1d< real64 > m_b; + + /// Rate and State characteristic length + array1d< real64 > m_Dc; + + /// Rate and State reference velocity + array1d< real64 > m_V0; + + /// Rate and State reference friction coefficient + array1d< real64 > m_mu0; + +/** + * @struct Set of "char const *" and keys for data specified in this class. + */ + struct viewKeyStruct : public FrictionBase::viewKeyStruct + { + /// string/key for friction coefficient + static constexpr char const * frictionCoefficientString() { return "frictionCoefficient"; } + /// string/key for friction coefficient + static constexpr char const * aCoefficientString() { return "a"; } + /// string/key for friction coefficient + static constexpr char const * bCoefficientString() { return "b"; } + /// string/key for friction coefficient + static constexpr char const * DcCoefficientString() { return "Dc"; } + /// string/key for friction coefficient + static constexpr char const * referenceVelocityString() { return "referenceVelocity"; } + /// string/key for friction coefficient + static constexpr char const * referenceFrictionCoefficientString() { return "referenceFrictionCoefficient"; } + }; + +}; + +GEOS_HOST_DEVICE +inline void RateAndStateFriction::KernelWrapper::updateFractureState( localIndex const k, + arraySlice1d< real64 const > const & dispJump, + arraySlice1d< real64 const > const & tractionVector, + integer & fractureState ) const +{ + + GEOS_UNUSED_VAR(tractionVector, k); + using namespace fields::contact; + + if( dispJump[0] > -m_displacementJumpThreshold ) + { + fractureState = FractureState::Open; + } else + { + fractureState = FractureState::Slip; + } +} + +GEOS_HOST_DEVICE +inline std::tuple< real64, real64, real64 > +RateAndStateFriction::KernelWrapper::computeShearTraction( real64 const normalTraction, + real64 const slipRate, + real64 const stateVariable ) const +{ + GEOS_UNUSED_VAR(normalTraction, slipRate, stateVariable); + real64 shearTraction = 0.0; + real64 dTauFriction[2] = {0.0, 0.0}; + + return std::make_tuple( shearTraction, dTauFriction[0], dTauFriction[1] ); +} + +GEOS_HOST_DEVICE +inline real64 RateAndStateFriction::KernelWrapper::frictionCoefficient( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const +{ + real64 const arg = ( slipRate / (2 * m_V0[k]) ) * LvArray::math::exp( stateVariable / m_a[k] ); + real64 const frictionCoefficient = m_a[k] * LvArray::math::asin( arg ); //TODO: change!! asinh + + m_frictionCoefficient[k] = frictionCoefficient; + + return frictionCoefficient; +} + +GEOS_HOST_DEVICE +inline real64 RateAndStateFriction::KernelWrapper::dfrictionCoefficient_dSlipRate( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const +{ + + real64 const inner_expression = ( slipRate / (2 * m_V0[k]) ) * LvArray::math::exp( stateVariable / m_a[k] ); + + return (m_a[k] / LvArray::math::sqrt(1 + inner_expression*inner_expression )) * (1 / (2 * m_V0[k])) * LvArray::math::exp( stateVariable / m_a[k] ); +} + +GEOS_HOST_DEVICE +inline real64 RateAndStateFriction::KernelWrapper::dfrictionCoefficient_dStateVariable( localIndex const k, + real64 const slipRate, + real64 const stateVariable) const +{ + + real64 const arg = (slipRate / (2 * m_V0[k])) * LvArray::math::exp(stateVariable / m_a[k]); + + return ( slipRate / (2 * m_V0[k])) * LvArray::math::exp(stateVariable / m_a[k]) / LvArray::math::sqrt(arg * arg + 1); +} + +GEOS_HOST_DEVICE +inline real64 RateAndStateFriction::KernelWrapper::dStateVariabledT( localIndex const k, + real64 const slipRate, + real64 const stateVariable) const +{ + real64 const mu = frictionCoefficient(k, slipRate, stateVariable); + + return -slipRate / m_Dc[k] * (mu - m_mu0[k] + (m_b[k] - m_a[k]) * LvArray::math::log(slipRate / m_V0[k])) ; +} + +GEOS_HOST_DEVICE +inline real64 RateAndStateFriction::KernelWrapper::dStateVariabledT_dStateVariable( localIndex const k, + real64 const slipRate, + real64 const stateVariable) const +{ + return -slipRate / m_Dc[k] * dfrictionCoefficient_dStateVariable( k, slipRate, stateVariable ); +} + +GEOS_HOST_DEVICE +inline real64 RateAndStateFriction::KernelWrapper::dStateVariabledT_dSlipRate( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const +{ + real64 const part1 = - 1.0 / m_Dc[k] * (frictionCoefficient(k, slipRate, stateVariable) - m_mu0[k] + (m_b[k] - m_a[k]) * LvArray::math::log(slipRate / m_V0[k])); + + real64 const part2 = - slipRate / m_Dc[k] * (dfrictionCoefficient_dSlipRate(k, slipRate, stateVariable) + (m_b[k] - m_a[k]) / slipRate); + + return part1 + part2; +} + +} /* namespace constitutive */ + +} /* namespace geos */ + +#endif /* GEOS_CONSTITUTIVE_CONTACT_RATEANDSTATEFRICTION_HPP_ */ diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp new file mode 100644 index 00000000000..16298279a82 --- /dev/null +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp @@ -0,0 +1,155 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file QuasiDynamicEQ.cpp + */ + +#include "QuasiDynamicEQ.hpp" + +#include "dataRepository/InputFlags.hpp" +#include "mesh/DomainPartition.hpp" +#include "kernels/RateAndStateKernels.hpp" +#include "rateAndStateFields.hpp" + +namespace geos +{ + +using namespace dataRepository; +using namespace fields; +using namespace constitutive; + +QuasiDynamicEQ::QuasiDynamicEQ( const string & name, + Group * const parent ): + SolverBase( name, parent ), + m_stressSolver( nullptr ) +{ + this->registerWrapper( viewKeyStruct::maxNumberOfNewtonIterationsString(), &m_maxNewtonIterations ). + setInputFlag( InputFlags::REQUIRED ). + setApplyDefaultValue( 5 ). + setDescription( "Maximum number of Newton iterations string." ); + + this->registerWrapper( viewKeyStruct::stressSolverNameString(), &m_stressSolverName ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Name of solver for computing stress" ); + + this->getWrapper< string >( viewKeyStruct::discretizationString() ). + setInputFlag( InputFlags::FALSE ); +} + +void QuasiDynamicEQ::postInputInitialization() +{ + + // Initialize member stress solver as specified in XML input + if( !m_stressSolverName.empty() ) + { + m_stressSolver = &this->getParent().getGroup< SolverBase >( m_stressSolverName ); + } + + SolverBase::postInputInitialization(); +} + +QuasiDynamicEQ::~QuasiDynamicEQ() +{ + // TODO Auto-generated destructor stub +} + +void QuasiDynamicEQ::registerDataOnMesh( Group & meshBodies ) +{ + SolverBase::registerDataOnMesh( meshBodies ); + + forDiscretizationOnMeshTargets( meshBodies, [&] ( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + ElementRegionManager & elemManager = mesh.getElemManager(); + + elemManager.forElementSubRegions< ElementSubRegionBase >( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + subRegion.registerField< rateAndState::stateVariable >( getName() ); + subRegion.registerField< rateAndState::slipRate >( getName() ); + subRegion.registerField< rateAndState::stateVariable_n >( getName() ); + subRegion.registerField< rateAndState::slipRate_n >( getName() ); + } ); + } ); +} + +real64 QuasiDynamicEQ::solverStep( real64 const & time_n, + real64 const & dt, + const int cycleNumber, + DomainPartition & domain ) +{ + real64 const dtStress = updateStresses( time_n, dt, cycleNumber, domain ); + + // Loop over subRegions to solve for seismicity rate + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) + { + // solve rate and state equations. + rateAndStateKernels::createAndLaunch( subRegion, viewKeyStruct::frictionLawNameString(), m_maxNewtonIterations, time_n, dt ); + // save old state + saveOldState( subRegion ); + } ); + } ); + + // return time step size achieved by stress solver + return dtStress; +} + +real64 QuasiDynamicEQ::updateStresses( real64 const & time_n, + real64 const & dt, + const int cycleNumber, + DomainPartition & domain ) const +{ + // Call member variable stress solver to update the stress state + if( m_stressSolver ) + { + + // 1. Solve the momentum balance + real64 const dtStress = m_stressSolver->solverStep( time_n, dt, cycleNumber, domain ); + + return dtStress; + } + else + { + // Spring-slider version + } + return dt; +} + +void QuasiDynamicEQ::saveOldState( ElementSubRegionBase & subRegion ) const +{ + arrayView1d< real64 > const stateVariable = subRegion.getField< rateAndState::stateVariable >(); + arrayView1d< real64 > const stateVariable_n = subRegion.getField< rateAndState::stateVariable_n >(); + arrayView1d< real64 > const slipRate = subRegion.getField< rateAndState::slipRate >(); + arrayView1d< real64 > const slipRate_n = subRegion.getField< rateAndState::slipRate_n >(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + slipRate_n[k] = slipRate[k]; + stateVariable_n[k] = stateVariable[k]; + } ); +} + +REGISTER_CATALOG_ENTRY( SolverBase, QuasiDynamicEQ, string const &, dataRepository::Group * const ) +} // namespace geos diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp new file mode 100644 index 00000000000..86708a9e867 --- /dev/null +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp @@ -0,0 +1,81 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +#ifndef GEOS_PHYSICSSOLVERS_INDUCED_QUASIDYNAMICEQ_HPP +#define GEOS_PHYSICSSOLVERS_INDUCED_QUASIDYNAMICEQ_HPP + +#include "physicsSolvers/SolverBase.hpp" + +namespace geos +{ + +class QuasiDynamicEQ : public SolverBase +{ +public: + /// The default nullary constructor is disabled to avoid compiler auto-generation: + QuasiDynamicEQ() = delete; + + /// The constructor needs a user-defined "name" and a parent Group (to place this instance in the tree structure of classes) + QuasiDynamicEQ( const string & name, + Group * const parent ); + + /// Destructor + virtual ~QuasiDynamicEQ() override; + + static string catalogName() { return "QuasiDynamicEQ"; } + + /** + * @return Get the final class Catalog name + */ + virtual string getCatalogName() const override { return catalogName(); } + + /// This method ties properties with their supporting mesh + virtual void registerDataOnMesh( Group & meshBodies ) override; + + struct viewKeyStruct : public SolverBase::viewKeyStruct + { + /// stress solver name + static constexpr char const * stressSolverNameString() { return "stressSolverName"; } + /// Friction law name string + constexpr static char const * frictionLawNameString() { return "frictionLawName"; } + /// max number of Newton iterations string + constexpr static char const * maxNumberOfNewtonIterationsString() { return "maxNumberOfNewtonIterations"; } + }; + + virtual real64 solverStep( real64 const & time_n, + real64 const & dt, + integer const cycleNumber, + DomainPartition & domain ) override final; + + /** + * @brief save the old state + * @param subRegion + */ + void saveOldState( ElementSubRegionBase & subRegion ) const; + +protected: + + virtual void postInputInitialization() override; + + /// pointer to stress solver + SolverBase * m_stressSolver; + + /// max number of newton iterations for rate and state solver + integer m_maxNewtonIterations; +}; + +} /* namespace geos */ + +#endif /* GEOS_PHYSICSSOLVERS_INDUCED_QUASIDYNAMICEQ_HPP */ From b892630bef8546ae4ebfd9a43be52da59e2fc399 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Mon, 16 Sep 2024 16:03:47 -0700 Subject: [PATCH 11/53] added shearIMpedance. --- .../contact/RateAndStateFriction.cpp | 300 ++---------------- .../inducedSeismicity/QuasiDynamicEQ.cpp | 10 +- .../inducedSeismicity/QuasiDynamicEQ.hpp | 5 + .../kernels/RateAndStateKernels.hpp | 12 +- 4 files changed, 45 insertions(+), 282 deletions(-) diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp index 8905cd75247..0121ba06dec 100644 --- a/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp +++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp @@ -5,7 +5,7 @@ * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC * Copyright (c) 2018-2024 Total, S.A * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University - * Copyright (c) 2018-2024 Chevron + * Copyright (c) 2023-2024 Chevron * Copyright (c) 2019- GEOS/GEOSX Contributors * All rights reserved * @@ -14,303 +14,51 @@ */ /** - * @file RateAndStateFriction.hpp + * @file RateAndStateFriction.cpp */ -#ifndef GEOS_CONSTITUTIVE_CONTACT_RATEANDSTATEFRICTION_HPP_ -#define GEOS_CONSTITUTIVE_CONTACT_RATEANDSTATEFRICTION_HPP_ - -#include "FrictionBase.hpp" +#include "RateAndStateFriction.hpp" namespace geos { -namespace constitutive -{ - -/** - * @class RateAndStateFrictionUpdates - * - * This class is used for in-kernel contact relation updates - */ - - -/** - * @class RateAndStateFriction - * - * Class to provide a RateAndStateFriction friction model. - */ -class RateAndStateFriction : public FrictionBase -{ -public: - - /** - * constructor - * @param[in] name name of the instance in the catalog - * @param[in] parent the group which contains this instance - */ - RateAndStateFriction( string const & name, Group * const parent ); - - /** - * Default Destructor - */ - virtual ~RateAndStateFriction() override; - - static string catalogName() { return "RateAndStateFriction"; } - - virtual string getCatalogName() const override { return catalogName(); } - - ///@} - - virtual void allocateConstitutiveData( dataRepository::Group & parent, - localIndex const numConstitutivePointsPerParentIndex ) override final; - - -class KernelWrapper : public FrictionBaseUpdates -{ -public: - KernelWrapper( real64 const displacementJumpThreshold, - arrayView1d< real64 > frictionCoefficient, - arrayView1d< real64 const > a, - arrayView1d< real64 const > b, - arrayView1d< real64 const > Dc, - arrayView1d< real64 const > V0, - arrayView1d< real64 const > mu0 ) - : FrictionBaseUpdates( displacementJumpThreshold ), - m_frictionCoefficient( frictionCoefficient ), - m_a( a ), - m_b( b ), - m_Dc( Dc ), - m_V0( V0 ), - m_mu0( mu0 ) - {} - - /// Default copy constructor - KernelWrapper( KernelWrapper const & ) = default; - - /// Default move constructor - KernelWrapper( KernelWrapper && ) = default; - - /// Deleted default constructor - KernelWrapper() = delete; - - /// Deleted copy assignment operator - KernelWrapper & operator=( KernelWrapper const & ) = delete; - - /// Deleted move assignment operator - KernelWrapper & operator=( KernelWrapper && ) = delete; - - GEOS_HOST_DEVICE - inline - virtual void updateFractureState( localIndex const k, - arraySlice1d< real64 const > const & dispJump, - arraySlice1d< real64 const > const & tractionVector, - integer & fractureState ) const override final; - -GEOS_HOST_DEVICE -inline std::tuple< real64, real64, real64 > -computeShearTraction( real64 const normalTraction, - real64 const slipRate, - real64 const stateVariable ) const; - -GEOS_HOST_DEVICE -inline real64 frictionCoefficient( localIndex const k, - real64 const slipRate, - real64 const stateVariable ) const; - -GEOS_HOST_DEVICE -inline real64 dfrictionCoefficient_dSlipRate( localIndex const k, - real64 const slipRate, - real64 const stateVariable ) const; - -GEOS_HOST_DEVICE -inline real64 dfrictionCoefficient_dStateVariable( localIndex const k, - real64 const slipRate, - real64 const stateVariable) const; - -GEOS_HOST_DEVICE -inline real64 dStateVariabledT( localIndex const k, - real64 const slipRate, - real64 const stateVariable) const; +using namespace dataRepository; -GEOS_HOST_DEVICE -inline real64 dStateVariabledT_dStateVariable( localIndex const k, - real64 const slipRate, - real64 const stateVariable) const; - -GEOS_HOST_DEVICE -inline real64 dStateVariabledT_dSlipRate( localIndex const k, - real64 const slipRate, - real64 const stateVariable) const; -private: - /// The friction coefficient - arrayView1d< real64 > m_frictionCoefficient; - - /// Rate and State coefficient a - arrayView1d< real64 const > m_a; - - /// Rate and State coefficient b - arrayView1d< real64 const > m_b; - - /// Rate and State characteristic length - arrayView1d< real64 const > m_Dc; - - /// Rate and State reference velocity - arrayView1d< real64 const > m_V0; - - /// Rate and State reference friction coefficient - arrayView1d< real64 const > m_mu0; -}; - - - /** - * @brief Create an update kernel wrapper. - * @return the wrapper - */ - KernelWrapper createKernelWrapper() const; - -private: - - virtual void postInputInitialization() override; - - /// The friction coefficient for each upper level dimension (i.e. cell) of *this - array1d< real64 > m_frictionCoefficient; - - /// Rate and State coefficient a - array1d< real64 > m_a; - - /// Rate and State coefficient b - array1d< real64 > m_b; - - /// Rate and State characteristic length - array1d< real64 > m_Dc; - - /// Rate and State reference velocity - array1d< real64 > m_V0; - - /// Rate and State reference friction coefficient - array1d< real64 > m_mu0; - -/** - * @struct Set of "char const *" and keys for data specified in this class. - */ - struct viewKeyStruct : public FrictionBase::viewKeyStruct - { - /// string/key for friction coefficient - static constexpr char const * frictionCoefficientString() { return "frictionCoefficient"; } - /// string/key for friction coefficient - static constexpr char const * aCoefficientString() { return "a"; } - /// string/key for friction coefficient - static constexpr char const * bCoefficientString() { return "b"; } - /// string/key for friction coefficient - static constexpr char const * DcCoefficientString() { return "Dc"; } - /// string/key for friction coefficient - static constexpr char const * referenceVelocityString() { return "referenceVelocity"; } - /// string/key for friction coefficient - static constexpr char const * referenceFrictionCoefficientString() { return "referenceFrictionCoefficient"; } - }; - -}; - -GEOS_HOST_DEVICE -inline void RateAndStateFriction::KernelWrapper::updateFractureState( localIndex const k, - arraySlice1d< real64 const > const & dispJump, - arraySlice1d< real64 const > const & tractionVector, - integer & fractureState ) const +namespace constitutive { - GEOS_UNUSED_VAR(tractionVector, k); - using namespace fields::contact; - - if( dispJump[0] > -m_displacementJumpThreshold ) - { - fractureState = FractureState::Open; - } else - { - fractureState = FractureState::Slip; - } -} - -GEOS_HOST_DEVICE -inline std::tuple< real64, real64, real64 > -RateAndStateFriction::KernelWrapper::computeShearTraction( real64 const normalTraction, - real64 const slipRate, - real64 const stateVariable ) const +RateAndStateFriction::RateAndStateFriction( string const & name, Group * const parent ): + FrictionBase( name, parent ), + m_cohesion(), + m_frictionCoefficient(), + m_elasticSlip() { - GEOS_UNUSED_VAR(normalTraction, slipRate, stateVariable); - real64 shearTraction = 0.0; - real64 dTauFriction[2] = {0.0, 0.0}; - - return std::make_tuple( shearTraction, dTauFriction[0], dTauFriction[1] ); } -GEOS_HOST_DEVICE -inline real64 RateAndStateFriction::KernelWrapper::frictionCoefficient( localIndex const k, - real64 const slipRate, - real64 const stateVariable ) const -{ - real64 const arg = ( slipRate / (2 * m_V0[k]) ) * LvArray::math::exp( stateVariable / m_a[k] ); - real64 const frictionCoefficient = m_a[k] * LvArray::math::asin( arg ); //TODO: change!! asinh - - m_frictionCoefficient[k] = frictionCoefficient; +RateAndStateFriction::~RateAndStateFriction() +{} - return frictionCoefficient; -} +void RateAndStateFriction::postInputInitialization() +{} -GEOS_HOST_DEVICE -inline real64 RateAndStateFriction::KernelWrapper::dfrictionCoefficient_dSlipRate( localIndex const k, - real64 const slipRate, - real64 const stateVariable ) const +void RateAndStateFriction::allocateConstitutiveData( Group & parent, + localIndex const numConstitutivePointsPerParentIndex ) { - - real64 const inner_expression = ( slipRate / (2 * m_V0[k]) ) * LvArray::math::exp( stateVariable / m_a[k] ); - - return (m_a[k] / LvArray::math::sqrt(1 + inner_expression*inner_expression )) * (1 / (2 * m_V0[k])) * LvArray::math::exp( stateVariable / m_a[k] ); -} - -GEOS_HOST_DEVICE -inline real64 RateAndStateFriction::KernelWrapper::dfrictionCoefficient_dStateVariable( localIndex const k, - real64 const slipRate, - real64 const stateVariable) const -{ - - real64 const arg = (slipRate / (2 * m_V0[k])) * LvArray::math::exp(stateVariable / m_a[k]); - - return ( slipRate / (2 * m_V0[k])) * LvArray::math::exp(stateVariable / m_a[k]) / LvArray::math::sqrt(arg * arg + 1); + FrictionBase::allocateConstitutiveData( parent, numConstitutivePointsPerParentIndex ); } -GEOS_HOST_DEVICE -inline real64 RateAndStateFriction::KernelWrapper::dStateVariabledT( localIndex const k, - real64 const slipRate, - real64 const stateVariable) const -{ - real64 const mu = frictionCoefficient(k, slipRate, stateVariable); - - return -slipRate / m_Dc[k] * (mu - m_mu0[k] + (m_b[k] - m_a[k]) * LvArray::math::log(slipRate / m_V0[k])) ; -} -GEOS_HOST_DEVICE -inline real64 RateAndStateFriction::KernelWrapper::dStateVariabledT_dStateVariable( localIndex const k, - real64 const slipRate, - real64 const stateVariable) const +RateAndStateFrictionUpdates RateAndStateFriction::createKernelWrapper() const { - return -slipRate / m_Dc[k] * dfrictionCoefficient_dStateVariable( k, slipRate, stateVariable ); + return RateAndStateFrictionUpdates( m_displacementJumpThreshold, + m_shearStiffness, + m_cohesion, + m_frictionCoefficient, + m_elasticSlip ); } -GEOS_HOST_DEVICE -inline real64 RateAndStateFriction::KernelWrapper::dStateVariabledT_dSlipRate( localIndex const k, - real64 const slipRate, - real64 const stateVariable ) const -{ - real64 const part1 = - 1.0 / m_Dc[k] * (frictionCoefficient(k, slipRate, stateVariable) - m_mu0[k] + (m_b[k] - m_a[k]) * LvArray::math::log(slipRate / m_V0[k])); - - real64 const part2 = - slipRate / m_Dc[k] * (dfrictionCoefficient_dSlipRate(k, slipRate, stateVariable) + (m_b[k] - m_a[k]) / slipRate); - - return part1 + part2; -} +REGISTER_CATALOG_ENTRY( ConstitutiveBase, RateAndStateFriction, string const &, Group * const ) } /* namespace constitutive */ } /* namespace geos */ - -#endif /* GEOS_CONSTITUTIVE_CONTACT_RATEANDSTATEFRICTION_HPP_ */ diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp index 16298279a82..0fe333b7a0c 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp @@ -34,13 +34,19 @@ using namespace constitutive; QuasiDynamicEQ::QuasiDynamicEQ( const string & name, Group * const parent ): SolverBase( name, parent ), - m_stressSolver( nullptr ) + m_stressSolver( nullptr ), + m_maxNewtonIterations( 10 ), + m_shearImpedance( 0.0 ) { this->registerWrapper( viewKeyStruct::maxNumberOfNewtonIterationsString(), &m_maxNewtonIterations ). - setInputFlag( InputFlags::REQUIRED ). + setInputFlag( InputFlags::OPTIONAL ). setApplyDefaultValue( 5 ). setDescription( "Maximum number of Newton iterations string." ); + this->registerWrapper( viewKeyStruct::shearImpedanceString(), &m_shearImpedance ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Shear impedance." ); + this->registerWrapper( viewKeyStruct::stressSolverNameString(), &m_stressSolverName ). setInputFlag( InputFlags::OPTIONAL ). setDescription( "Name of solver for computing stress" ); diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp index 86708a9e867..87bc4aec25a 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp @@ -50,6 +50,8 @@ class QuasiDynamicEQ : public SolverBase static constexpr char const * stressSolverNameString() { return "stressSolverName"; } /// Friction law name string constexpr static char const * frictionLawNameString() { return "frictionLawName"; } + /// Friction law name string + constexpr static char const * shearImpedanceString() { return "shearImpedance"; } /// max number of Newton iterations string constexpr static char const * maxNumberOfNewtonIterationsString() { return "maxNumberOfNewtonIterations"; } }; @@ -74,6 +76,9 @@ class QuasiDynamicEQ : public SolverBase /// max number of newton iterations for rate and state solver integer m_maxNewtonIterations; + + /// Shear impedance + real64 m_shearImpedance; }; } /* namespace geos */ diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index 07b137b3c5a..1e9182a0947 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -28,7 +28,7 @@ namespace geos namespace rateAndStateKernels { /** - * @class DieterichSeismicityRate + * @class RateAndStateKernel * * @brief * @@ -39,13 +39,15 @@ class RateAndStateKernel public: RateAndStateKernel( SurfaceElementSubRegion & subRegion, - RateAndStateFriction const & frictionLaw ): + RateAndStateFriction const & frictionLaw, + real64 const shearImpedance ): m_slipRate( subRegion.getField< fields::rateAndState::slipRate >() ), m_stateVariable( subRegion.getField< fields::rateAndState::stateVariable >() ), m_stateVariable_n( subRegion.getField< fields::rateAndState::stateVariable >() ), m_normalTraction( subRegion.getField< fields::rateAndState::slipRate >() ), m_shearTraction( subRegion.getField< fields::rateAndState::slipRate >() ), - m_frictionLaw( frictionLaw.createKernelWrapper() ) + m_frictionLaw( frictionLaw.createKernelWrapper() ), + m_shearImpedance( shearImpedance ) {} /** @@ -82,7 +84,7 @@ class RateAndStateKernel tauFriction, dTauFriction ); - stack.rhs[0] = m_shearTraction[k] - tauFriction; + stack.rhs[0] = m_shearTraction[k] - tauFriction - m_shearImpedance * m_slipRate[k]; // Eq 2: slip law stack.rhs[1] = (m_stateVariable[k] - m_stateVariable_n[k]) / dt - m_frictionLaw.dStateVariabledT( m_slipRate[k], m_stateVariable[k] ) @@ -126,6 +128,8 @@ class RateAndStateKernel arrayView1d< real64 const > const m_shearTraction; + real64 const m_shearImpedance; + RateAndStateFriction::KernelWrapper m_frictionLaw; }; From fdde350fdda328a4b5cec2f61f9beff979d2ef55 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Wed, 18 Sep 2024 16:32:37 -0700 Subject: [PATCH 12/53] fixed compilation errors. --- .../contact/RateAndStateFriction.cpp | 17 +- .../contact/RateAndStateFriction.hpp | 264 ++++++++---------- .../inducedSeismicity/QuasiDynamicEQ.cpp | 16 +- .../inducedSeismicity/QuasiDynamicEQ.hpp | 18 +- .../inducedSeismicity/SeismicityRate.cpp | 3 + .../inducedSeismicity/SeismicityRate.hpp | 2 +- .../kernels/RateAndStateKernels.hpp | 116 ++++---- .../inducedSeismicity/rateAndStateFields.hpp | 6 +- 8 files changed, 214 insertions(+), 228 deletions(-) diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp index 0121ba06dec..b8b555bdbff 100644 --- a/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp +++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp @@ -29,11 +29,8 @@ namespace constitutive RateAndStateFriction::RateAndStateFriction( string const & name, Group * const parent ): FrictionBase( name, parent ), - m_cohesion(), - m_frictionCoefficient(), - m_elasticSlip() -{ -} + m_frictionCoefficient() +{} RateAndStateFriction::~RateAndStateFriction() {} @@ -42,19 +39,17 @@ void RateAndStateFriction::postInputInitialization() {} void RateAndStateFriction::allocateConstitutiveData( Group & parent, - localIndex const numConstitutivePointsPerParentIndex ) + localIndex const numConstitutivePointsPerParentIndex ) { FrictionBase::allocateConstitutiveData( parent, numConstitutivePointsPerParentIndex ); } - +using RateAndStateFrictionUpdates = RateAndStateFriction::KernelWrapper; RateAndStateFrictionUpdates RateAndStateFriction::createKernelWrapper() const { return RateAndStateFrictionUpdates( m_displacementJumpThreshold, - m_shearStiffness, - m_cohesion, - m_frictionCoefficient, - m_elasticSlip ); + m_frictionCoefficient, m_a, m_b, + m_Dc, m_V0, m_mu0 ); } REGISTER_CATALOG_ENTRY( ConstitutiveBase, RateAndStateFriction, string const &, Group * const ) diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp index 8905cd75247..89cb50b86e1 100644 --- a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp +++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp @@ -65,102 +65,96 @@ class RateAndStateFriction : public FrictionBase virtual void allocateConstitutiveData( dataRepository::Group & parent, localIndex const numConstitutivePointsPerParentIndex ) override final; - -class KernelWrapper : public FrictionBaseUpdates -{ -public: - KernelWrapper( real64 const displacementJumpThreshold, - arrayView1d< real64 > frictionCoefficient, - arrayView1d< real64 const > a, - arrayView1d< real64 const > b, - arrayView1d< real64 const > Dc, - arrayView1d< real64 const > V0, - arrayView1d< real64 const > mu0 ) - : FrictionBaseUpdates( displacementJumpThreshold ), - m_frictionCoefficient( frictionCoefficient ), - m_a( a ), - m_b( b ), - m_Dc( Dc ), - m_V0( V0 ), - m_mu0( mu0 ) - {} - - /// Default copy constructor - KernelWrapper( KernelWrapper const & ) = default; - - /// Default move constructor - KernelWrapper( KernelWrapper && ) = default; - - /// Deleted default constructor - KernelWrapper() = delete; - - /// Deleted copy assignment operator - KernelWrapper & operator=( KernelWrapper const & ) = delete; - - /// Deleted move assignment operator - KernelWrapper & operator=( KernelWrapper && ) = delete; - - GEOS_HOST_DEVICE - inline - virtual void updateFractureState( localIndex const k, - arraySlice1d< real64 const > const & dispJump, - arraySlice1d< real64 const > const & tractionVector, - integer & fractureState ) const override final; -GEOS_HOST_DEVICE -inline std::tuple< real64, real64, real64 > -computeShearTraction( real64 const normalTraction, - real64 const slipRate, - real64 const stateVariable ) const; - -GEOS_HOST_DEVICE -inline real64 frictionCoefficient( localIndex const k, - real64 const slipRate, - real64 const stateVariable ) const; - -GEOS_HOST_DEVICE -inline real64 dfrictionCoefficient_dSlipRate( localIndex const k, - real64 const slipRate, + class KernelWrapper : public FrictionBaseUpdates + { +public: + KernelWrapper( real64 const displacementJumpThreshold, + arrayView1d< real64 > frictionCoefficient, + arrayView1d< real64 const > a, + arrayView1d< real64 const > b, + arrayView1d< real64 const > Dc, + arrayView1d< real64 const > V0, + arrayView1d< real64 const > mu0 ) + : FrictionBaseUpdates( displacementJumpThreshold ), + m_frictionCoefficient( frictionCoefficient ), + m_a( a ), + m_b( b ), + m_Dc( Dc ), + m_V0( V0 ), + m_mu0( mu0 ) + {} + + /// Default copy constructor + KernelWrapper( KernelWrapper const & ) = default; + + /// Default move constructor + KernelWrapper( KernelWrapper && ) = default; + + /// Deleted default constructor + KernelWrapper() = delete; + + /// Deleted copy assignment operator + KernelWrapper & operator=( KernelWrapper const & ) = delete; + + /// Deleted move assignment operator + KernelWrapper & operator=( KernelWrapper && ) = delete; + + GEOS_HOST_DEVICE + inline + virtual void updateFractureState( localIndex const k, + arraySlice1d< real64 const > const & dispJump, + arraySlice1d< real64 const > const & tractionVector, + integer & fractureState ) const override final; + + GEOS_HOST_DEVICE + inline real64 frictionCoefficient( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const; + + GEOS_HOST_DEVICE + inline real64 dfrictionCoefficient_dSlipRate( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const; + + GEOS_HOST_DEVICE + inline real64 dfrictionCoefficient_dStateVariable( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const; + + GEOS_HOST_DEVICE + inline real64 dStateVariabledT( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const; + + GEOS_HOST_DEVICE + inline real64 dStateVariabledT_dStateVariable( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const; + + GEOS_HOST_DEVICE + inline real64 dStateVariabledT_dSlipRate( localIndex const k, + real64 const slipRate, real64 const stateVariable ) const; +private: + /// The friction coefficient + arrayView1d< real64 > m_frictionCoefficient; -GEOS_HOST_DEVICE -inline real64 dfrictionCoefficient_dStateVariable( localIndex const k, - real64 const slipRate, - real64 const stateVariable) const; + /// Rate and State coefficient a + arrayView1d< real64 const > m_a; -GEOS_HOST_DEVICE -inline real64 dStateVariabledT( localIndex const k, - real64 const slipRate, - real64 const stateVariable) const; + /// Rate and State coefficient b + arrayView1d< real64 const > m_b; -GEOS_HOST_DEVICE -inline real64 dStateVariabledT_dStateVariable( localIndex const k, - real64 const slipRate, - real64 const stateVariable) const; + /// Rate and State characteristic length + arrayView1d< real64 const > m_Dc; -GEOS_HOST_DEVICE -inline real64 dStateVariabledT_dSlipRate( localIndex const k, - real64 const slipRate, - real64 const stateVariable) const; -private: - /// The friction coefficient - arrayView1d< real64 > m_frictionCoefficient; - - /// Rate and State coefficient a - arrayView1d< real64 const > m_a; - - /// Rate and State coefficient b - arrayView1d< real64 const > m_b; - - /// Rate and State characteristic length - arrayView1d< real64 const > m_Dc; - - /// Rate and State reference velocity - arrayView1d< real64 const > m_V0; + /// Rate and State reference velocity + arrayView1d< real64 const > m_V0; - /// Rate and State reference friction coefficient - arrayView1d< real64 const > m_mu0; -}; + /// Rate and State reference friction coefficient + arrayView1d< real64 const > m_mu0; + }; /** @@ -176,15 +170,15 @@ inline real64 dStateVariabledT_dSlipRate( localIndex const k, /// The friction coefficient for each upper level dimension (i.e. cell) of *this array1d< real64 > m_frictionCoefficient; - /// Rate and State coefficient a + /// Rate and State coefficient a array1d< real64 > m_a; - - /// Rate and State coefficient b + + /// Rate and State coefficient b array1d< real64 > m_b; /// Rate and State characteristic length array1d< real64 > m_Dc; - + /// Rate and State reference velocity array1d< real64 > m_V0; @@ -219,93 +213,79 @@ inline void RateAndStateFriction::KernelWrapper::updateFractureState( localIndex integer & fractureState ) const { - GEOS_UNUSED_VAR(tractionVector, k); + GEOS_UNUSED_VAR( tractionVector, k ); using namespace fields::contact; if( dispJump[0] > -m_displacementJumpThreshold ) { fractureState = FractureState::Open; - } else + } + else { fractureState = FractureState::Slip; } } GEOS_HOST_DEVICE -inline std::tuple< real64, real64, real64 > -RateAndStateFriction::KernelWrapper::computeShearTraction( real64 const normalTraction, - real64 const slipRate, - real64 const stateVariable ) const -{ - GEOS_UNUSED_VAR(normalTraction, slipRate, stateVariable); - real64 shearTraction = 0.0; - real64 dTauFriction[2] = {0.0, 0.0}; - - return std::make_tuple( shearTraction, dTauFriction[0], dTauFriction[1] ); -} - -GEOS_HOST_DEVICE -inline real64 RateAndStateFriction::KernelWrapper::frictionCoefficient( localIndex const k, - real64 const slipRate, +inline real64 RateAndStateFriction::KernelWrapper::frictionCoefficient( localIndex const k, + real64 const slipRate, real64 const stateVariable ) const { real64 const arg = ( slipRate / (2 * m_V0[k]) ) * LvArray::math::exp( stateVariable / m_a[k] ); - real64 const frictionCoefficient = m_a[k] * LvArray::math::asin( arg ); //TODO: change!! asinh - - m_frictionCoefficient[k] = frictionCoefficient; + m_frictionCoefficient[k] = m_a[k] * LvArray::math::asin( arg ); //TODO: change!! asinh - return frictionCoefficient; -} + return m_frictionCoefficient[k]; +} GEOS_HOST_DEVICE -inline real64 RateAndStateFriction::KernelWrapper::dfrictionCoefficient_dSlipRate( localIndex const k, - real64 const slipRate, - real64 const stateVariable ) const +inline real64 RateAndStateFriction::KernelWrapper::dfrictionCoefficient_dSlipRate( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const { - real64 const inner_expression = ( slipRate / (2 * m_V0[k]) ) * LvArray::math::exp( stateVariable / m_a[k] ); + real64 const inner_expression = ( slipRate / (2 * m_V0[k]) ) * LvArray::math::exp( stateVariable / m_a[k] ); - return (m_a[k] / LvArray::math::sqrt(1 + inner_expression*inner_expression )) * (1 / (2 * m_V0[k])) * LvArray::math::exp( stateVariable / m_a[k] ); + return (m_a[k] / LvArray::math::sqrt( 1 + inner_expression*inner_expression )) * (1 / (2 * m_V0[k])) * LvArray::math::exp( stateVariable / m_a[k] ); } - + GEOS_HOST_DEVICE -inline real64 RateAndStateFriction::KernelWrapper::dfrictionCoefficient_dStateVariable( localIndex const k, - real64 const slipRate, - real64 const stateVariable) const +inline real64 RateAndStateFriction::KernelWrapper::dfrictionCoefficient_dStateVariable( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const { - - real64 const arg = (slipRate / (2 * m_V0[k])) * LvArray::math::exp(stateVariable / m_a[k]); - - return ( slipRate / (2 * m_V0[k])) * LvArray::math::exp(stateVariable / m_a[k]) / LvArray::math::sqrt(arg * arg + 1); + + real64 const arg = (slipRate / (2 * m_V0[k])) * LvArray::math::exp( stateVariable / m_a[k] ); + + return ( slipRate / (2 * m_V0[k])) * LvArray::math::exp( stateVariable / m_a[k] ) / LvArray::math::sqrt( arg * arg + 1 ); } GEOS_HOST_DEVICE -inline real64 RateAndStateFriction::KernelWrapper::dStateVariabledT( localIndex const k, - real64 const slipRate, - real64 const stateVariable) const +inline real64 RateAndStateFriction::KernelWrapper::dStateVariabledT( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const { - real64 const mu = frictionCoefficient(k, slipRate, stateVariable); - - return -slipRate / m_Dc[k] * (mu - m_mu0[k] + (m_b[k] - m_a[k]) * LvArray::math::log(slipRate / m_V0[k])) ; + real64 const mu = frictionCoefficient( k, slipRate, stateVariable ); + + return -slipRate / m_Dc[k] * (mu - m_mu0[k] + (m_b[k] - m_a[k]) * LvArray::math::log( slipRate / m_V0[k] )); } GEOS_HOST_DEVICE inline real64 RateAndStateFriction::KernelWrapper::dStateVariabledT_dStateVariable( localIndex const k, - real64 const slipRate, - real64 const stateVariable) const + real64 const slipRate, + real64 const stateVariable ) const { return -slipRate / m_Dc[k] * dfrictionCoefficient_dStateVariable( k, slipRate, stateVariable ); } GEOS_HOST_DEVICE inline real64 RateAndStateFriction::KernelWrapper::dStateVariabledT_dSlipRate( localIndex const k, - real64 const slipRate, + real64 const slipRate, real64 const stateVariable ) const -{ - real64 const part1 = - 1.0 / m_Dc[k] * (frictionCoefficient(k, slipRate, stateVariable) - m_mu0[k] + (m_b[k] - m_a[k]) * LvArray::math::log(slipRate / m_V0[k])); - - real64 const part2 = - slipRate / m_Dc[k] * (dfrictionCoefficient_dSlipRate(k, slipRate, stateVariable) + (m_b[k] - m_a[k]) / slipRate); - +{ + real64 const part1 = -1.0 / m_Dc[k] * (frictionCoefficient( k, slipRate, stateVariable ) - m_mu0[k] + (m_b[k] - m_a[k]) * LvArray::math::log( slipRate / m_V0[k] )); + + real64 const part2 = -slipRate / m_Dc[k] * (dfrictionCoefficient_dSlipRate( k, slipRate, stateVariable ) + (m_b[k] - m_a[k]) / slipRate); + return part1 + part2; } diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp index 0fe333b7a0c..addfa033851 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp @@ -35,6 +35,7 @@ QuasiDynamicEQ::QuasiDynamicEQ( const string & name, Group * const parent ): SolverBase( name, parent ), m_stressSolver( nullptr ), + m_stressSolverName( "SpringSlider" ), m_maxNewtonIterations( 10 ), m_shearImpedance( 0.0 ) { @@ -49,15 +50,15 @@ QuasiDynamicEQ::QuasiDynamicEQ( const string & name, this->registerWrapper( viewKeyStruct::stressSolverNameString(), &m_stressSolverName ). setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Name of solver for computing stress" ); + setDescription( "Name of solver for computing stress. If empty, the spring-slider model is run." ); this->getWrapper< string >( viewKeyStruct::discretizationString() ). - setInputFlag( InputFlags::FALSE ); + setInputFlag( InputFlags::FALSE ); } void QuasiDynamicEQ::postInputInitialization() { - + // Initialize member stress solver as specified in XML input if( !m_stressSolverName.empty() ) { @@ -107,12 +108,12 @@ real64 QuasiDynamicEQ::solverStep( real64 const & time_n, arrayView1d< string const > const & regionNames ) { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - SurfaceElementSubRegion & subRegion ) + mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) { // solve rate and state equations. - rateAndStateKernels::createAndLaunch( subRegion, viewKeyStruct::frictionLawNameString(), m_maxNewtonIterations, time_n, dt ); + rateAndStateKernels::createAndLaunch< parallelDevicePolicy<> >( subRegion, viewKeyStruct::frictionLawNameString(), m_shearImpedance, m_maxNewtonIterations, time_n, dt ); // save old state saveOldState( subRegion ); } ); @@ -158,4 +159,5 @@ void QuasiDynamicEQ::saveOldState( ElementSubRegionBase & subRegion ) const } REGISTER_CATALOG_ENTRY( SolverBase, QuasiDynamicEQ, string const &, dataRepository::Group * const ) + } // namespace geos diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp index 87bc4aec25a..1f4349d9b9f 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp @@ -16,7 +16,7 @@ #ifndef GEOS_PHYSICSSOLVERS_INDUCED_QUASIDYNAMICEQ_HPP #define GEOS_PHYSICSSOLVERS_INDUCED_QUASIDYNAMICEQ_HPP -#include "physicsSolvers/SolverBase.hpp" +#include "physicsSolvers/SolverBase.hpp" namespace geos { @@ -61,19 +61,27 @@ class QuasiDynamicEQ : public SolverBase integer const cycleNumber, DomainPartition & domain ) override final; +private: + + virtual void postInputInitialization() override; + + real64 updateStresses( real64 const & time_n, + real64 const & dt, + const int cycleNumber, + DomainPartition & domain ) const; + /** * @brief save the old state * @param subRegion */ void saveOldState( ElementSubRegionBase & subRegion ) const; -protected: - - virtual void postInputInitialization() override; - /// pointer to stress solver SolverBase * m_stressSolver; + /// stress solver name + string m_stressSolverName; + /// max number of newton iterations for rate and state solver integer m_maxNewtonIterations; diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.cpp index 428965cb2dc..f0d87febd02 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.cpp @@ -28,6 +28,9 @@ #include "physicsSolvers/inducedSeismicity/inducedSeismicityFields.hpp" #include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" +#include "fieldSpecification/FieldSpecificationManager.hpp" + + namespace geos { diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.hpp index 6f41ea564b1..5e89ab1214c 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/SeismicityRate.hpp @@ -16,7 +16,7 @@ #ifndef GEOS_PHYSICSSOLVERS_INDUCED_SEISMICITY_SEISMICITYRATE_HPP #define GEOS_PHYSICSSOLVERS_INDUCED_SEISMICITY_SEISMICITYRATE_HPP -#include "physicsSolvers/SolverBase.hpp" +#include "physicsSolvers/SolverBase.hpp" namespace geos { diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index 1e9182a0947..529ac9e3455 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -30,24 +30,24 @@ namespace rateAndStateKernels /** * @class RateAndStateKernel * - * @brief + * @brief * - * @details + * @details */ class RateAndStateKernel { public: RateAndStateKernel( SurfaceElementSubRegion & subRegion, - RateAndStateFriction const & frictionLaw, + constitutive::RateAndStateFriction const & frictionLaw, real64 const shearImpedance ): - m_slipRate( subRegion.getField< fields::rateAndState::slipRate >() ), - m_stateVariable( subRegion.getField< fields::rateAndState::stateVariable >() ), - m_stateVariable_n( subRegion.getField< fields::rateAndState::stateVariable >() ), - m_normalTraction( subRegion.getField< fields::rateAndState::slipRate >() ), - m_shearTraction( subRegion.getField< fields::rateAndState::slipRate >() ), - m_frictionLaw( frictionLaw.createKernelWrapper() ), - m_shearImpedance( shearImpedance ) + m_slipRate( subRegion.getField< fields::rateAndState::slipRate >() ), + m_stateVariable( subRegion.getField< fields::rateAndState::stateVariable >() ), + m_stateVariable_n( subRegion.getField< fields::rateAndState::stateVariable >() ), + m_normalTraction( subRegion.getField< fields::rateAndState::slipRate >() ), + m_shearTraction( subRegion.getField< fields::rateAndState::slipRate >() ), + m_shearImpedance( shearImpedance ), + m_frictionLaw( frictionLaw.createKernelWrapper() ) {} /** @@ -62,9 +62,9 @@ class RateAndStateKernel StackVariables( ) {} - real64 jacobian[2][2]{}; + real64 jacobian[2][2]{}; - real64 rhs[2]{}; + real64 rhs[2]{}; }; @@ -73,33 +73,28 @@ class RateAndStateKernel real64 const dt, StackVariables & stack ) const { - + // Eq 1: shear stress balance - real64 tauFriction = 0.0; - real64 dTauFriction[2] = {0.0, 0.0}; - - frictionLaw.computeShearTraction( m_normalTraction[k], - m_slipRate[k], - m_stateVariable[k], - tauFriction, - dTauFriction ); - + real64 const tauFriction = m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] ) * m_normalTraction[k]; + real64 const dTauFriction[2] = { m_frictionLaw.dfrictionCoefficient_dStateVariable( k, m_slipRate[k], m_stateVariable[k] ) * m_normalTraction[k], + m_frictionLaw.dfrictionCoefficient_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) * m_normalTraction[k] }; + stack.rhs[0] = m_shearTraction[k] - tauFriction - m_shearImpedance * m_slipRate[k]; // Eq 2: slip law - stack.rhs[1] = (m_stateVariable[k] - m_stateVariable_n[k]) / dt - m_frictionLaw.dStateVariabledT( m_slipRate[k], m_stateVariable[k] ) - real64 const dStateEvolutionLaw[0] = 1 / dt - m_frictionLaw.dStateVariabledT_dtheta( m_slipRate[k], m_stateVariable[k] ) - real64 const dStateEvolutionLaw[1] = - m_frictionLaw.dStateVariabledT_dSlipRate( m_slipRate[k], m_stateVariable[k] ) - + stack.rhs[1] = (m_stateVariable[k] - m_stateVariable_n[k]) / dt - m_frictionLaw.dStateVariabledT( k, m_slipRate[k], m_stateVariable[k] ); + real64 const dStateEvolutionLaw[2] = { 1 / dt - m_frictionLaw.dStateVariabledT_dStateVariable( k, m_slipRate[k], m_stateVariable[k] ), + -m_frictionLaw.dStateVariabledT_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) }; + // Assemble Jacobian matrix // derivative shear stress balance w.r.t. theta - stack.jacobian[0][0] = - dTauFriction[0] + stack.jacobian[0][0] = -dTauFriction[0]; // derivative shear stress balance w.r.t. slip_velocity - stack.jacobian[0][1] = - dTauFriction[1] + stack.jacobian[0][1] = -dTauFriction[1]; // derivative slip law w.r.t. theta - stack.jacobian[1][0] = dStateEvolutionLaw[0] + stack.jacobian[1][0] = dStateEvolutionLaw[0]; // derivative slip law w.r.t. slip_velocity - stack.jacobian[1][1] = dStateEvolutionLaw[1] + stack.jacobian[1][1] = dStateEvolutionLaw[1]; } GEOS_HOST_DEVICE @@ -107,9 +102,9 @@ class RateAndStateKernel StackVariables & stack ) const { /// Solve 2x2 system - real64 const solution[2] = {0.0, 0.0}; + real64 solution[2] = {0.0, 0.0}; - denseLinearAlgebra::solve( stack.jacobian, stack.rhs, solution ); + denseLinearAlgebra::solve< 2 >( stack.jacobian, stack.rhs, solution ); /// Update variables m_stateVariable[k] += solution[0]; @@ -118,20 +113,20 @@ class RateAndStateKernel private: - arrayView1d< real64 > const m_slipRate; + arrayView1d< real64 > const m_slipRate; + + arrayView1d< real64 > const m_stateVariable; - arrayView1d< real64 > const m_stateVariable; + arrayView1d< real64 const > const m_stateVariable_n; - arrayView1d< real64 const > const m_stateVariable_n; + arrayView1d< real64 const > const m_normalTraction; - arrayView1d< real64 const > const m_normalTraction; + arrayView1d< real64 const > const m_shearTraction; - arrayView1d< real64 const > const m_shearTraction; + real64 const m_shearImpedance; - real64 const m_shearImpedance; + constitutive::RateAndStateFriction::KernelWrapper m_frictionLaw; - RateAndStateFriction::KernelWrapper m_frictionLaw; - }; @@ -144,32 +139,35 @@ template< typename POLICY > static void createAndLaunch( SurfaceElementSubRegion & subRegion, string const & frictionLawNameKey, - integer const maxNewtonIter, + real64 const shearImpedance, + integer const maxNewtonIter, real64 const time_n, real64 const dt ) { GEOS_MARK_FUNCTION; - - string const & frictionaLawName = subRegion.getReference< string >( vfrictionLawNameKey ); - RateAndStateFrction const & frictionLaw = subRegion.getConstitutiveModel( frictionaLawName ); - RateAndStateKernel kernel( subRegion, frictionLaw ); - + + GEOS_UNUSED_VAR( time_n ); + + string const & frictionaLawName = subRegion.getReference< string >( frictionLawNameKey ); + constitutive::RateAndStateFriction const & frictionLaw = subRegion.getConstitutiveModel< constitutive::RateAndStateFriction >( frictionaLawName ); + RateAndStateKernel kernel( subRegion, frictionLaw, shearImpedance ); + // Newton loops outside of the kernel launch for( integer iter = 0; iter < maxNewtonIter; iter++ ) { - /// Kernel 1: Do a solver for all non converged elements - forAll< POLICY >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) - { - RateAndStateKernel::StackVariables stack(); - kernel.setup( k, dt, stack ); - kernel.solve( k, stack ); - } ); - - /// Kernel 2: Update set of non-converged elements - // forAll< POLICY >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) - // { - - // } ); + /// Kernel 1: Do a solver for all non converged elements + forAll< POLICY >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + RateAndStateKernel::StackVariables stack; + kernel.setup( k, dt, stack ); + kernel.solve( k, stack ); + } ); + + /// Kernel 2: Update set of non-converged elements + // forAll< POLICY >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + // { + + // } ); } } diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp index 97f2708541a..5e9efea45de 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp @@ -52,7 +52,7 @@ DECLARE_FIELD( slipRate_n, "slipRate_n", array1d< real64 >, 1.0e-6, - NO_PLOT, + NOPLOT, WRITE_AND_READ, "Slip rate at previous time step" ); @@ -60,9 +60,9 @@ DECLARE_FIELD( stateVariable_n, "stateVariable_n", array1d< real64 >, 0.6, - NO_PLOT, + NOPLOT, WRITE_AND_READ, - "Rate- and state-dependent friction state variable at previous time step" ); + "Rate- and state-dependent friction state variable at previous time step" ); } From 26263d3c7d35f6c385bc0dfaf102f2a342421a9e Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Thu, 3 Oct 2024 05:54:25 -0700 Subject: [PATCH 13/53] submodule update --- src/coreComponents/LvArray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/LvArray b/src/coreComponents/LvArray index 355e8d987fb..63404cc3f20 160000 --- a/src/coreComponents/LvArray +++ b/src/coreComponents/LvArray @@ -1 +1 @@ -Subproject commit 355e8d987fbf15c9ac07442bda28bc52a8e80480 +Subproject commit 63404cc3f207884cdd3f5d655c03a3a2f9f918f1 From e146040f00506364e7d8888b173de994a9ecae4f Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Thu, 3 Oct 2024 06:19:20 -0700 Subject: [PATCH 14/53] submodule update --- src/coreComponents/LvArray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/LvArray b/src/coreComponents/LvArray index 63404cc3f20..30902328d6e 160000 --- a/src/coreComponents/LvArray +++ b/src/coreComponents/LvArray @@ -1 +1 @@ -Subproject commit 63404cc3f207884cdd3f5d655c03a3a2f9f918f1 +Subproject commit 30902328d6e83b534525c682a677a7789563a5a8 From 593ef7cffc54d7e9b080cc923518c0c0481fbc53 Mon Sep 17 00:00:00 2001 From: Matteo Cusini <49037133+CusiniM@users.noreply.github.com> Date: Thu, 3 Oct 2024 06:19:55 -0700 Subject: [PATCH 15/53] Use asinh. --- .../constitutive/contact/RateAndStateFriction.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp index 89cb50b86e1..74927ee0148 100644 --- a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp +++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp @@ -232,7 +232,7 @@ inline real64 RateAndStateFriction::KernelWrapper::frictionCoefficient( localInd real64 const stateVariable ) const { real64 const arg = ( slipRate / (2 * m_V0[k]) ) * LvArray::math::exp( stateVariable / m_a[k] ); - m_frictionCoefficient[k] = m_a[k] * LvArray::math::asin( arg ); //TODO: change!! asinh + m_frictionCoefficient[k] = m_a[k] * LvArray::math::asinh( arg ); return m_frictionCoefficient[k]; } From 23e926d75c3745d311ef460ba12c0f36fd6fff76 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Thu, 3 Oct 2024 07:18:57 -0700 Subject: [PATCH 16/53] compiles fine. --- src/coreComponents/LvArray | 2 +- src/coreComponents/schema/schema.xsd | 40 ++++++++++++++++++++++ src/coreComponents/schema/schema.xsd.other | 16 +++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/coreComponents/LvArray b/src/coreComponents/LvArray index 30902328d6e..854f4664b8a 160000 --- a/src/coreComponents/LvArray +++ b/src/coreComponents/LvArray @@ -1 +1 @@ -Subproject commit 30902328d6e83b534525c682a677a7789563a5a8 +Subproject commit 854f4664b8a1d466465bff0fbf3de3ba5deb532a diff --git a/src/coreComponents/schema/schema.xsd b/src/coreComponents/schema/schema.xsd index a8430b98131..aff73cc9d90 100644 --- a/src/coreComponents/schema/schema.xsd +++ b/src/coreComponents/schema/schema.xsd @@ -389,6 +389,10 @@ + + + + @@ -817,6 +821,10 @@ + + + + @@ -2185,6 +2193,7 @@ the relative residual norm satisfies: + @@ -3166,6 +3175,30 @@ Local- Add jump stabilization on interior of macro elements--> + + + + + + + + + + + + + + + + + + + + + + + + @@ -4229,6 +4262,7 @@ Local- Add jump stabilization on interior of macro elements--> + @@ -5442,6 +5476,12 @@ If you want to do a three-phase simulation, please use instead wettingIntermedia + + + + + + diff --git a/src/coreComponents/schema/schema.xsd.other b/src/coreComponents/schema/schema.xsd.other index d59f6b947e5..7ecf8441420 100644 --- a/src/coreComponents/schema/schema.xsd.other +++ b/src/coreComponents/schema/schema.xsd.other @@ -522,6 +522,7 @@ + @@ -1000,6 +1001,19 @@ + + + + + + + + + + + + + @@ -1478,6 +1492,7 @@ + @@ -2554,6 +2569,7 @@ + From b7ca2aaeb5dda7f62a241f89d59f5ebd3a8fc506 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Mon, 7 Oct 2024 03:19:44 -0700 Subject: [PATCH 17/53] wip: adding spring-slider example. --- .../inducedSeismicity/SpringSlider_base.xml | 80 +++++++++++++++++++ .../inducedSeismicity/SpringSlider_smoke.xml | 7 ++ .../inducedSeismicity/QuasiDynamicEQ.cpp | 18 ++++- .../kernels/RateAndStateKernels.hpp | 19 ++--- 4 files changed, 112 insertions(+), 12 deletions(-) create mode 100644 inputFiles/inducedSeismicity/SpringSlider_base.xml create mode 100644 inputFiles/inducedSeismicity/SpringSlider_smoke.xml diff --git a/inputFiles/inducedSeismicity/SpringSlider_base.xml b/inputFiles/inducedSeismicity/SpringSlider_base.xml new file mode 100644 index 00000000000..276bf69ded8 --- /dev/null +++ b/inputFiles/inducedSeismicity/SpringSlider_base.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/inputFiles/inducedSeismicity/SpringSlider_smoke.xml b/inputFiles/inducedSeismicity/SpringSlider_smoke.xml new file mode 100644 index 00000000000..ccbd0be5d69 --- /dev/null +++ b/inputFiles/inducedSeismicity/SpringSlider_smoke.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp index addfa033851..7c9e6d9dd90 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp @@ -100,9 +100,11 @@ real64 QuasiDynamicEQ::solverStep( real64 const & time_n, const int cycleNumber, DomainPartition & domain ) { + + /// 1. Compute shear and normal tractions real64 const dtStress = updateStresses( time_n, dt, cycleNumber, domain ); - // Loop over subRegions to solve for seismicity rate + /// 2. Solve for slip rate and state variable and, compute slip forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, arrayView1d< string const > const & regionNames ) @@ -139,8 +141,18 @@ real64 QuasiDynamicEQ::updateStresses( real64 const & time_n, } else { - // Spring-slider version - } + // Spring-slider shear traction computation + mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) + { + arrayView1d< real64 const > const slip = subRegion.getField< fields::contact::slip >().toViewConst(); + arrayView2d< real64 > const traction = subRegion.getField< fields::contact::traction >(); + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + traction[k][1] = traction[k][1] + tauRate * dt - springStiffness * slip; + } ); + } ); return dt; } diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index 529ac9e3455..543f4ffe8ec 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -44,8 +44,7 @@ class RateAndStateKernel m_slipRate( subRegion.getField< fields::rateAndState::slipRate >() ), m_stateVariable( subRegion.getField< fields::rateAndState::stateVariable >() ), m_stateVariable_n( subRegion.getField< fields::rateAndState::stateVariable >() ), - m_normalTraction( subRegion.getField< fields::rateAndState::slipRate >() ), - m_shearTraction( subRegion.getField< fields::rateAndState::slipRate >() ), + m_traction( subRegion.getField< fields::contact::traction >() ), m_shearImpedance( shearImpedance ), m_frictionLaw( frictionLaw.createKernelWrapper() ) {} @@ -73,13 +72,17 @@ class RateAndStateKernel real64 const dt, StackVariables & stack ) const { + + // + real64 const normalTraction = m_traction[k][0]; + real64 const shearTraction = LvArray::math::sqrt( m_traction[k][1]*m_traction[k][1] + m_traction[k][2]*m_traction[k][2] ); // Eq 1: shear stress balance - real64 const tauFriction = m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] ) * m_normalTraction[k]; - real64 const dTauFriction[2] = { m_frictionLaw.dfrictionCoefficient_dStateVariable( k, m_slipRate[k], m_stateVariable[k] ) * m_normalTraction[k], - m_frictionLaw.dfrictionCoefficient_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) * m_normalTraction[k] }; + real64 const tauFriction = m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] ) * normalTraction; + real64 const dTauFriction[2] = { m_frictionLaw.dfrictionCoefficient_dStateVariable( k, m_slipRate[k], m_stateVariable[k] ) * normalTraction, + m_frictionLaw.dfrictionCoefficient_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) * normalTraction }; - stack.rhs[0] = m_shearTraction[k] - tauFriction - m_shearImpedance * m_slipRate[k]; + stack.rhs[0] = shearTraction - tauFriction - m_shearImpedance * m_slipRate[k]; // Eq 2: slip law stack.rhs[1] = (m_stateVariable[k] - m_stateVariable_n[k]) / dt - m_frictionLaw.dStateVariabledT( k, m_slipRate[k], m_stateVariable[k] ); @@ -119,9 +122,7 @@ class RateAndStateKernel arrayView1d< real64 const > const m_stateVariable_n; - arrayView1d< real64 const > const m_normalTraction; - - arrayView1d< real64 const > const m_shearTraction; + arrayView2d< real64 const > const m_traction; real64 const m_shearImpedance; From 91425f42c7b019faaf349c469eaa82aea26dfd49 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Mon, 7 Oct 2024 04:05:02 -0700 Subject: [PATCH 18/53] wip: spring-slider. --- .../inducedSeismicity/SpringSlider_base.xml | 124 ++++++++++-------- .../inducedSeismicity/SpringSlider_smoke.xml | 35 ++++- .../contact/RateAndStateFriction.cpp | 22 +++- .../contact/RateAndStateFriction.hpp | 10 +- .../inducedSeismicity/QuasiDynamicEQ.cpp | 2 + 5 files changed, 129 insertions(+), 64 deletions(-) diff --git a/inputFiles/inducedSeismicity/SpringSlider_base.xml b/inputFiles/inducedSeismicity/SpringSlider_base.xml index 276bf69ded8..cd3cbb72ecc 100644 --- a/inputFiles/inducedSeismicity/SpringSlider_base.xml +++ b/inputFiles/inducedSeismicity/SpringSlider_base.xml @@ -1,56 +1,77 @@ - - - - - - - - - - + + + + + + + - + + + - - - - + + + + + + + + - - - - + + + + + + + + + - + @@ -58,15 +79,15 @@ name="timeHistoryOutput" sources="{/Tasks/seismicRateCollection}" filename="seismicityRate" /> - + - + - @@ -76,5 +97,4 @@ objectPath="ElementRegions/Domain/cb1" fieldName="stateVariable"/> - - \ No newline at end of file + \ No newline at end of file diff --git a/inputFiles/inducedSeismicity/SpringSlider_smoke.xml b/inputFiles/inducedSeismicity/SpringSlider_smoke.xml index ccbd0be5d69..4ef103047ac 100644 --- a/inputFiles/inducedSeismicity/SpringSlider_smoke.xml +++ b/inputFiles/inducedSeismicity/SpringSlider_smoke.xml @@ -1,7 +1,30 @@ - - - - - \ No newline at end of file + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp index b8b555bdbff..b4f7dda5f6e 100644 --- a/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp +++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp @@ -30,7 +30,27 @@ namespace constitutive RateAndStateFriction::RateAndStateFriction( string const & name, Group * const parent ): FrictionBase( name, parent ), m_frictionCoefficient() -{} +{ + registerWrapper( viewKeyStruct::aCoefficientString(), &m_a ). + setApplyDefaultValue( 0.01 ). + setDescription( "Rate- and State-dependent friction coefficient a." ); + + registerWrapper( viewKeyStruct::aCoefficientString(), &m_b ). + setApplyDefaultValue( 0.015 ). + setDescription( "Rate- and State-dependent friction coefficient b." ); + + registerWrapper( viewKeyStruct::aCoefficientString(), &m_Dc ). + setApplyDefaultValue( 10e-6 ). + setDescription( "Rate- and State-dependent friction characteristic length." ); + + registerWrapper( viewKeyStruct::aCoefficientString(), &m_referenceVelocity ). + setApplyDefaultValue( 1.0e-6 ). + setDescription( "Rate- and State-dependent friction reference slip rate." ); + + registerWrapper( viewKeyStruct::aCoefficientString(), &m_referenceFrictionCoefficient ). + setApplyDefaultValue( 0.6 ). + setDescription( "Rate- and State-dependent friction reference friction coefficient." ); +} RateAndStateFriction::~RateAndStateFriction() {} diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp index 74927ee0148..b0fa31cdb07 100644 --- a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp +++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp @@ -192,15 +192,15 @@ class RateAndStateFriction : public FrictionBase { /// string/key for friction coefficient static constexpr char const * frictionCoefficientString() { return "frictionCoefficient"; } - /// string/key for friction coefficient + /// string/key for Rate and State coefficient a static constexpr char const * aCoefficientString() { return "a"; } - /// string/key for friction coefficient + /// string/key for Rate and State coefficient b static constexpr char const * bCoefficientString() { return "b"; } - /// string/key for friction coefficient + /// string/key for Rate and State characteristic length static constexpr char const * DcCoefficientString() { return "Dc"; } - /// string/key for friction coefficient + /// string/key for reference slip rate static constexpr char const * referenceVelocityString() { return "referenceVelocity"; } - /// string/key for friction coefficient + /// string/key for reference friction coefficient static constexpr char const * referenceFrictionCoefficientString() { return "referenceFrictionCoefficient"; } }; diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp index 7c9e6d9dd90..7f25c2e19bb 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp @@ -148,6 +148,8 @@ real64 QuasiDynamicEQ::updateStresses( real64 const & time_n, { arrayView1d< real64 const > const slip = subRegion.getField< fields::contact::slip >().toViewConst(); arrayView2d< real64 > const traction = subRegion.getField< fields::contact::traction >(); + + real64 const tauRate = 1e-4; forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { traction[k][1] = traction[k][1] + tauRate * dt - springStiffness * slip; From 272eb34553b44e769914e09a8fe23f545fc62e8c Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Mon, 7 Oct 2024 20:14:54 -0700 Subject: [PATCH 19/53] move changes. --- .../physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp index 7f25c2e19bb..8b9ce2a077d 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp @@ -149,9 +149,11 @@ real64 QuasiDynamicEQ::updateStresses( real64 const & time_n, arrayView1d< real64 const > const slip = subRegion.getField< fields::contact::slip >().toViewConst(); arrayView2d< real64 > const traction = subRegion.getField< fields::contact::traction >(); - real64 const tauRate = 1e-4; + real64 const tauRate = 1e-4; // (MPa/s) forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { + real64 const criticalStiffness = normalTraction * (frictionLaw.b - frictionLaw.a) / frictionLaw.D_c; + real64 const springStiffness = 0.9 * criticalStiffness; traction[k][1] = traction[k][1] + tauRate * dt - springStiffness * slip; } ); } ); From 81772bf5802f8ec56d2381b269499bab9f5ddffa Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Tue, 8 Oct 2024 15:05:38 -0700 Subject: [PATCH 20/53] wip spring-slider --- .../inducedSeismicity/SpringSlider_base.xml | 9 ++- .../contact/RateAndStateFriction.cpp | 55 +++++++++++++++---- .../contact/RateAndStateFriction.hpp | 36 +++++++++++- .../inducedSeismicity/QuasiDynamicEQ.cpp | 49 ++++++++++++----- .../inducedSeismicity/QuasiDynamicEQ.hpp | 35 +++++++++++- .../kernels/RateAndStateKernels.hpp | 6 +- 6 files changed, 155 insertions(+), 35 deletions(-) diff --git a/inputFiles/inducedSeismicity/SpringSlider_base.xml b/inputFiles/inducedSeismicity/SpringSlider_base.xml index cd3cbb72ecc..a7b8ef53d1c 100644 --- a/inputFiles/inducedSeismicity/SpringSlider_base.xml +++ b/inputFiles/inducedSeismicity/SpringSlider_base.xml @@ -12,7 +12,7 @@ targetRegions="{ Domain }" rockToughness="1.0" nodeBasedSIF="1" - mpiCommOrder="1"/> + mpiCommOrder="1"/> @@ -50,7 +50,12 @@ + name="frictionLaw" + defaultA="0.01" + defaultB="0.015" + defaultDc="1.0e-5" + defaultReferenceVelocity="1.0e-6" + defaultReferenceFrictionCoefficient="0.6"/> diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp index b4f7dda5f6e..4def6a5ea38 100644 --- a/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp +++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp @@ -32,31 +32,62 @@ RateAndStateFriction::RateAndStateFriction( string const & name, Group * const p m_frictionCoefficient() { registerWrapper( viewKeyStruct::aCoefficientString(), &m_a ). - setApplyDefaultValue( 0.01 ). setDescription( "Rate- and State-dependent friction coefficient a." ); - registerWrapper( viewKeyStruct::aCoefficientString(), &m_b ). - setApplyDefaultValue( 0.015 ). + registerWrapper( viewKeyStruct::bCoefficientString(), &m_b ). setDescription( "Rate- and State-dependent friction coefficient b." ); - registerWrapper( viewKeyStruct::aCoefficientString(), &m_Dc ). - setApplyDefaultValue( 10e-6 ). + registerWrapper( viewKeyStruct::DcCoefficientString(), &m_Dc ). setDescription( "Rate- and State-dependent friction characteristic length." ); - registerWrapper( viewKeyStruct::aCoefficientString(), &m_referenceVelocity ). - setApplyDefaultValue( 1.0e-6 ). + registerWrapper( viewKeyStruct::referenceVelocityString(), &m_V0 ). setDescription( "Rate- and State-dependent friction reference slip rate." ); - registerWrapper( viewKeyStruct::aCoefficientString(), &m_referenceFrictionCoefficient ). - setApplyDefaultValue( 0.6 ). - setDescription( "Rate- and State-dependent friction reference friction coefficient." ); + registerWrapper( viewKeyStruct::referenceFrictionCoefficientString(), &m_mu0 ). + setDescription( "Rate- and State-dependent friction reference friction coefficient." ); + + /// Default values + registerWrapper( viewKeyStruct::defaultACoefficientString(), &m_defaultA ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Default value of the Rate- and State-dependent friction coefficient a." ); + + registerWrapper( viewKeyStruct::defaultBCoefficientString(), &m_defaultB ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Default value of the Rate- and State-dependent friction coefficient b." ); + + registerWrapper( viewKeyStruct::defaultDcCoefficientString(), &m_defaultDc ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Default value of the Rate- and State-dependent friction characteristic length." ); + + registerWrapper( viewKeyStruct::defaultReferenceVelocityString(), &m_defaultV0 ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Default value of the Rate- and State-dependent friction reference slip rate." ); + + registerWrapper( viewKeyStruct::defaultReferenceFrictionCoefficientString(), &m_defaultMu0 ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Default value of the Rate- and State-dependent friction reference friction coefficient." ); } RateAndStateFriction::~RateAndStateFriction() {} void RateAndStateFriction::postInputInitialization() -{} +{ + this->getWrapper< array1d< real64 > >( viewKeyStruct::aCoefficientString() ). + setApplyDefaultValue( m_defaultA ); + + this->getWrapper< array1d< real64 > >( viewKeyStruct::bCoefficientString() ). + setApplyDefaultValue( m_defaultB ); + + this->getWrapper< array1d< real64 > >( viewKeyStruct::DcCoefficientString() ). + setApplyDefaultValue( m_defaultDc ); + + this->getWrapper< array1d< real64 > >( viewKeyStruct::referenceVelocityString() ). + setApplyDefaultValue( m_defaultV0 ); + + this->getWrapper< array1d< real64 > >( viewKeyStruct::referenceFrictionCoefficientString() ). + setApplyDefaultValue( m_defaultMu0 ); +} void RateAndStateFriction::allocateConstitutiveData( Group & parent, localIndex const numConstitutivePointsPerParentIndex ) @@ -65,7 +96,7 @@ void RateAndStateFriction::allocateConstitutiveData( Group & parent, } using RateAndStateFrictionUpdates = RateAndStateFriction::KernelWrapper; -RateAndStateFrictionUpdates RateAndStateFriction::createKernelWrapper() const +RateAndStateFrictionUpdates RateAndStateFriction::createKernelUpdates() const { return RateAndStateFrictionUpdates( m_displacementJumpThreshold, m_frictionCoefficient, m_a, m_b, diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp index b0fa31cdb07..20688080551 100644 --- a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp +++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp @@ -65,7 +65,6 @@ class RateAndStateFriction : public FrictionBase virtual void allocateConstitutiveData( dataRepository::Group & parent, localIndex const numConstitutivePointsPerParentIndex ) override final; - class KernelWrapper : public FrictionBaseUpdates { public: @@ -99,6 +98,15 @@ class RateAndStateFriction : public FrictionBase /// Deleted move assignment operator KernelWrapper & operator=( KernelWrapper && ) = delete; + + GEOS_HOST_DEVICE + real64 getACoefficient( localIndex const k ) const { return m_a[k]; } + + GEOS_HOST_DEVICE + real64 getBCoefficient( localIndex const k ) const { return m_b[k]; } + + GEOS_HOST_DEVICE + real64 getDcCoefficient( localIndex const k ) const { return m_Dc[k]; } GEOS_HOST_DEVICE inline @@ -161,7 +169,7 @@ class RateAndStateFriction : public FrictionBase * @brief Create an update kernel wrapper. * @return the wrapper */ - KernelWrapper createKernelWrapper() const; + KernelWrapper createKernelUpdates() const; private: @@ -185,6 +193,20 @@ class RateAndStateFriction : public FrictionBase /// Rate and State reference friction coefficient array1d< real64 > m_mu0; + /// Default value of Rate and State coefficient a + real64 m_defaultA; + /// Default value of Rate and State coefficient b + real64 m_defaultB; + + /// Default value of Rate and State characteristic length + real64 m_defaultDc; + + /// Default value of Rate and State reference velocity + real64 m_defaultV0; + + /// Default value of Rate and State reference friction coefficient + real64 m_defaultMu0; + /** * @struct Set of "char const *" and keys for data specified in this class. */ @@ -202,6 +224,16 @@ class RateAndStateFriction : public FrictionBase static constexpr char const * referenceVelocityString() { return "referenceVelocity"; } /// string/key for reference friction coefficient static constexpr char const * referenceFrictionCoefficientString() { return "referenceFrictionCoefficient"; } + /// string/key for the default value of Rate and State coefficient a + static constexpr char const * defaultACoefficientString() { return "defaultA"; } + /// string/key for the default value of Rate and State coefficient b + static constexpr char const * defaultBCoefficientString() { return "defaultB"; } + /// string/key for the default value of Rate and State characteristic length + static constexpr char const * defaultDcCoefficientString() { return "defaultDc"; } + /// string/key for the default value ofreference slip rate + static constexpr char const * defaultReferenceVelocityString() { return "defaultReferenceVelocity"; } + /// string/key for the default value of reference friction coefficient + static constexpr char const * defaultReferenceFrictionCoefficientString() { return "defaultReferenceFrictionCoefficient"; } }; }; diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp index 8b9ce2a077d..e93eb278577 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp @@ -23,6 +23,7 @@ #include "mesh/DomainPartition.hpp" #include "kernels/RateAndStateKernels.hpp" #include "rateAndStateFields.hpp" +#include "physicsSolvers/contact/ContactFields.hpp" namespace geos { @@ -117,7 +118,7 @@ real64 QuasiDynamicEQ::solverStep( real64 const & time_n, // solve rate and state equations. rateAndStateKernels::createAndLaunch< parallelDevicePolicy<> >( subRegion, viewKeyStruct::frictionLawNameString(), m_shearImpedance, m_maxNewtonIterations, time_n, dt ); // save old state - saveOldState( subRegion ); + saveOldStateAndUpdateSlip( subRegion, dt ); } ); } ); @@ -142,35 +143,53 @@ real64 QuasiDynamicEQ::updateStresses( real64 const & time_n, else { // Spring-slider shear traction computation - mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, - [&]( localIndex const, - SurfaceElementSubRegion & subRegion ) - { - arrayView1d< real64 const > const slip = subRegion.getField< fields::contact::slip >().toViewConst(); - arrayView2d< real64 > const traction = subRegion.getField< fields::contact::traction >(); + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) - real64 const tauRate = 1e-4; // (MPa/s) - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) { - real64 const criticalStiffness = normalTraction * (frictionLaw.b - frictionLaw.a) / frictionLaw.D_c; - real64 const springStiffness = 0.9 * criticalStiffness; - traction[k][1] = traction[k][1] + tauRate * dt - springStiffness * slip; - } ); + arrayView1d< real64 const > const slip = subRegion.getField< fields::contact::slip >().toViewConst(); + arrayView2d< real64 > const traction = subRegion.getField< fields::contact::traction >(); + + string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); + RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); + + RateAndStateFriction::KernelWrapper frictionKernelWrapper= frictionLaw.createKernelUpdates(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + SpringSliderParameters springSliderParameters = SpringSliderParameters( traction[k][0], + frictionKernelWrapper.getACoefficient(k), + frictionKernelWrapper.getBCoefficient(k), + frictionKernelWrapper.getDcCoefficient(k) ); + + traction[k][1] = traction[k][1] + springSliderParameters.tauRate * dt - springSliderParameters.springStiffness * slip[k]; + traction[k][2] = 0.0; + } ); + } ); } ); - return dt; + return dt; + } } -void QuasiDynamicEQ::saveOldState( ElementSubRegionBase & subRegion ) const +void QuasiDynamicEQ::saveOldStateAndUpdateSlip( ElementSubRegionBase & subRegion, real64 const dt ) const { arrayView1d< real64 > const stateVariable = subRegion.getField< rateAndState::stateVariable >(); arrayView1d< real64 > const stateVariable_n = subRegion.getField< rateAndState::stateVariable_n >(); arrayView1d< real64 > const slipRate = subRegion.getField< rateAndState::slipRate >(); arrayView1d< real64 > const slipRate_n = subRegion.getField< rateAndState::slipRate_n >(); + arrayView1d< real64 > const slip = subRegion.getField< contact::slip >(); + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { slipRate_n[k] = slipRate[k]; stateVariable_n[k] = stateVariable[k]; + slip[k] = slip[k] + slipRate[k] * dt; } ); } diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp index 1f4349d9b9f..39c4e23713d 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp @@ -74,7 +74,7 @@ class QuasiDynamicEQ : public SolverBase * @brief save the old state * @param subRegion */ - void saveOldState( ElementSubRegionBase & subRegion ) const; + void saveOldStateAndUpdateSlip( ElementSubRegionBase & subRegion, real64 const dt ) const; /// pointer to stress solver SolverBase * m_stressSolver; @@ -87,6 +87,39 @@ class QuasiDynamicEQ : public SolverBase /// Shear impedance real64 m_shearImpedance; + + class SpringSliderParameters + { + public: + + GEOS_HOST_DEVICE + SpringSliderParameters( real64 const normalTraction, real64 const a, real64 const b, real64 const Dc ) : + tauRate( 1e-4 ), + springStiffness( 0.0 ) + { + real64 const criticalStiffness = normalTraction * (b - a) / Dc; + springStiffness = 0.9 * criticalStiffness; + } + + /// Default copy constructor + SpringSliderParameters( SpringSliderParameters const & ) = default; + + /// Default move constructor + SpringSliderParameters( SpringSliderParameters && ) = default; + + /// Deleted default constructor + SpringSliderParameters() = delete; + + /// Deleted copy assignment operator + SpringSliderParameters & operator=( SpringSliderParameters const & ) = delete; + + /// Deleted move assignment operator + SpringSliderParameters & operator=( SpringSliderParameters && ) = delete; + + real64 tauRate; + + real64 springStiffness; + }; }; } /* namespace geos */ diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index 543f4ffe8ec..8163d52ff13 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -46,7 +46,7 @@ class RateAndStateKernel m_stateVariable_n( subRegion.getField< fields::rateAndState::stateVariable >() ), m_traction( subRegion.getField< fields::contact::traction >() ), m_shearImpedance( shearImpedance ), - m_frictionLaw( frictionLaw.createKernelWrapper() ) + m_frictionLaw( frictionLaw.createKernelUpdates() ) {} /** @@ -72,8 +72,8 @@ class RateAndStateKernel real64 const dt, StackVariables & stack ) const { - - // + + // real64 const normalTraction = m_traction[k][0]; real64 const shearTraction = LvArray::math::sqrt( m_traction[k][1]*m_traction[k][1] + m_traction[k][2]*m_traction[k][2] ); From 6a95883e8dd44eed4bbd42a91c6345c560e63f3a Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Wed, 9 Oct 2024 12:12:51 -0700 Subject: [PATCH 21/53] added timestep control --- .../contact/RateAndStateFriction.hpp | 8 +-- .../inducedSeismicity/QuasiDynamicEQ.cpp | 58 ++++++++++++++++--- .../inducedSeismicity/QuasiDynamicEQ.hpp | 20 +++++-- 3 files changed, 67 insertions(+), 19 deletions(-) diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp index 20688080551..b2bb3dbf86c 100644 --- a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp +++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp @@ -98,13 +98,13 @@ class RateAndStateFriction : public FrictionBase /// Deleted move assignment operator KernelWrapper & operator=( KernelWrapper && ) = delete; - + GEOS_HOST_DEVICE real64 getACoefficient( localIndex const k ) const { return m_a[k]; } - + GEOS_HOST_DEVICE - real64 getBCoefficient( localIndex const k ) const { return m_b[k]; } - + real64 getBCoefficient( localIndex const k ) const { return m_b[k]; } + GEOS_HOST_DEVICE real64 getDcCoefficient( localIndex const k ) const { return m_Dc[k]; } diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp index e93eb278577..224d79854d3 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp @@ -38,7 +38,8 @@ QuasiDynamicEQ::QuasiDynamicEQ( const string & name, m_stressSolver( nullptr ), m_stressSolverName( "SpringSlider" ), m_maxNewtonIterations( 10 ), - m_shearImpedance( 0.0 ) + m_shearImpedance( 0.0 ), + m_targetSlipIncrement( 1.0e-7 ) { this->registerWrapper( viewKeyStruct::maxNumberOfNewtonIterationsString(), &m_maxNewtonIterations ). setInputFlag( InputFlags::OPTIONAL ). @@ -53,6 +54,11 @@ QuasiDynamicEQ::QuasiDynamicEQ( const string & name, setInputFlag( InputFlags::OPTIONAL ). setDescription( "Name of solver for computing stress. If empty, the spring-slider model is run." ); + this->registerWrapper( viewKeyStruct::targetSlipIncrementString(), &m_targetSlipIncrement ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( 1.0e-7 ). + setDescription( "Target slip incrmeent for timestep size selction" ); + this->getWrapper< string >( viewKeyStruct::discretizationString() ). setInputFlag( InputFlags::FALSE ); } @@ -116,12 +122,14 @@ real64 QuasiDynamicEQ::solverStep( real64 const & time_n, SurfaceElementSubRegion & subRegion ) { // solve rate and state equations. - rateAndStateKernels::createAndLaunch< parallelDevicePolicy<> >( subRegion, viewKeyStruct::frictionLawNameString(), m_shearImpedance, m_maxNewtonIterations, time_n, dt ); + rateAndStateKernels::createAndLaunch< parallelDevicePolicy<> >( subRegion, viewKeyStruct::frictionLawNameString(), m_shearImpedance, m_maxNewtonIterations, time_n, dtStress ); // save old state saveOldStateAndUpdateSlip( subRegion, dt ); } ); } ); + m_nextDt = setNextDt( dtStress, domain ); + // return time step size achieved by stress solver return dtStress; } @@ -154,7 +162,7 @@ real64 QuasiDynamicEQ::updateStresses( real64 const & time_n, { arrayView1d< real64 const > const slip = subRegion.getField< fields::contact::slip >().toViewConst(); arrayView2d< real64 > const traction = subRegion.getField< fields::contact::traction >(); - + string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); @@ -162,10 +170,10 @@ real64 QuasiDynamicEQ::updateStresses( real64 const & time_n, forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { - SpringSliderParameters springSliderParameters = SpringSliderParameters( traction[k][0], - frictionKernelWrapper.getACoefficient(k), - frictionKernelWrapper.getBCoefficient(k), - frictionKernelWrapper.getDcCoefficient(k) ); + SpringSliderParameters springSliderParameters = SpringSliderParameters( traction[k][0], + frictionKernelWrapper.getACoefficient( k ), + frictionKernelWrapper.getBCoefficient( k ), + frictionKernelWrapper.getDcCoefficient( k ) ); traction[k][1] = traction[k][1] + springSliderParameters.tauRate * dt - springSliderParameters.springStiffness * slip[k]; traction[k][2] = 0.0; @@ -176,7 +184,7 @@ real64 QuasiDynamicEQ::updateStresses( real64 const & time_n, } } -void QuasiDynamicEQ::saveOldStateAndUpdateSlip( ElementSubRegionBase & subRegion, real64 const dt ) const +void QuasiDynamicEQ::saveOldStateAndUpdateSlip( ElementSubRegionBase & subRegion, real64 const dt ) const { arrayView1d< real64 > const stateVariable = subRegion.getField< rateAndState::stateVariable >(); arrayView1d< real64 > const stateVariable_n = subRegion.getField< rateAndState::stateVariable_n >(); @@ -189,10 +197,42 @@ void QuasiDynamicEQ::saveOldStateAndUpdateSlip( ElementSubRegionBase & subRegion { slipRate_n[k] = slipRate[k]; stateVariable_n[k] = stateVariable[k]; - slip[k] = slip[k] + slipRate[k] * dt; + slip[k] = slip[k] + slipRate[k] * dt; } ); } +real64 QuasiDynamicEQ::setNextDt( real64 const & currentDt, DomainPartition & domain ) +{ + GEOS_UNUSED_VAR( currentDt ); + + real64 maxSlipRate = 0.0; + // Spring-slider shear traction computation + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel const & mesh, + arrayView1d< string const > const & regionNames ) + + { + real64 maxSlipRateOnThisRank = 0.0; + mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion const & subRegion ) + { + arrayView1d< real64 const > const slipRate = subRegion.getField< rateAndState::slipRate >(); + + RAJA::ReduceMax< parallelDeviceReduce, real64 > maximumSlipRateOnThisRegion( 0.0 ); + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + maximumSlipRateOnThisRegion.max( LvArray::math::abs( slipRate[k] ) ); + } ); + if( maximumSlipRateOnThisRegion.get() > maxSlipRateOnThisRank ) + maxSlipRateOnThisRank = maximumSlipRateOnThisRegion.get(); + } ); + maxSlipRate = MpiWrapper::max( maxSlipRateOnThisRank ); + } ); + + return m_targetSlipIncrement / maxSlipRate; +} + REGISTER_CATALOG_ENTRY( SolverBase, QuasiDynamicEQ, string const &, dataRepository::Group * const ) } // namespace geos diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp index 39c4e23713d..227ad36088f 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp @@ -54,6 +54,8 @@ class QuasiDynamicEQ : public SolverBase constexpr static char const * shearImpedanceString() { return "shearImpedance"; } /// max number of Newton iterations string constexpr static char const * maxNumberOfNewtonIterationsString() { return "maxNumberOfNewtonIterations"; } + /// target slip increment + constexpr static char const * targetSlipIncrementString() { return "targetSlipIncrement"; } }; virtual real64 solverStep( real64 const & time_n, @@ -63,6 +65,9 @@ class QuasiDynamicEQ : public SolverBase private: + virtual real64 setNextDt( real64 const & currentDt, + DomainPartition & domain ) override final; + virtual void postInputInitialization() override; real64 updateStresses( real64 const & time_n, @@ -85,17 +90,20 @@ class QuasiDynamicEQ : public SolverBase /// max number of newton iterations for rate and state solver integer m_maxNewtonIterations; - /// Shear impedance + /// shear impedance real64 m_shearImpedance; + /// target slip rate + real64 m_targetSlipIncrement; + class SpringSliderParameters { - public: +public: GEOS_HOST_DEVICE - SpringSliderParameters( real64 const normalTraction, real64 const a, real64 const b, real64 const Dc ) : - tauRate( 1e-4 ), - springStiffness( 0.0 ) + SpringSliderParameters( real64 const normalTraction, real64 const a, real64 const b, real64 const Dc ): + tauRate( 1e-4 ), + springStiffness( 0.0 ) { real64 const criticalStiffness = normalTraction * (b - a) / Dc; springStiffness = 0.9 * criticalStiffness; @@ -116,7 +124,7 @@ class QuasiDynamicEQ : public SolverBase /// Deleted move assignment operator SpringSliderParameters & operator=( SpringSliderParameters && ) = delete; - real64 tauRate; + real64 tauRate; real64 springStiffness; }; From 2032024d327b9e41e7c89548ceb5229dfabe729f Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Wed, 9 Oct 2024 19:18:09 -0700 Subject: [PATCH 22/53] wip: running. --- .../inducedSeismicity/SpringSlider_base.xml | 48 ++++++++++--------- .../inducedSeismicity/SpringSlider_smoke.xml | 23 +++++++-- .../inducedSeismicity/QuasiDynamicEQ.cpp | 39 ++++++++++++--- .../surfaceGeneration/SurfaceGenerator.cpp | 2 +- 4 files changed, 79 insertions(+), 33 deletions(-) diff --git a/inputFiles/inducedSeismicity/SpringSlider_base.xml b/inputFiles/inducedSeismicity/SpringSlider_base.xml index a7b8ef53d1c..34e24d4b802 100644 --- a/inputFiles/inducedSeismicity/SpringSlider_base.xml +++ b/inputFiles/inducedSeismicity/SpringSlider_base.xml @@ -4,17 +4,28 @@ + shearImpedance="4.41" + initialDt="1" + logLevel="1" + discretization="FE1"> + mpiCommOrder="1" + fractureRegion="Fault"/> + + + + + + @@ -66,40 +77,33 @@ objectPath="faceManager" scale="1" setNames="{ faultPlane }"/> - - - + + name="vtkOutput" + plotFileRoot="springSlider"/> + sources="{/Tasks/slipCollection,/Tasks/slipRateCollection,/Tasks/stateVariableCollection}" + filename="springSlider"/> \ No newline at end of file diff --git a/inputFiles/inducedSeismicity/SpringSlider_smoke.xml b/inputFiles/inducedSeismicity/SpringSlider_smoke.xml index 4ef103047ac..28a6cd38d17 100644 --- a/inputFiles/inducedSeismicity/SpringSlider_smoke.xml +++ b/inputFiles/inducedSeismicity/SpringSlider_smoke.xml @@ -6,20 +6,37 @@ + maxTime="2.0"> + + + + target="/Tasks/slipCollection"/> + + + + getWrapper< string >( viewKeyStruct::discretizationString() ). - setInputFlag( InputFlags::FALSE ); } void QuasiDynamicEQ::postInputInitialization() @@ -90,14 +87,30 @@ void QuasiDynamicEQ::registerDataOnMesh( Group & meshBodies ) { ElementRegionManager & elemManager = mesh.getElemManager(); - elemManager.forElementSubRegions< ElementSubRegionBase >( regionNames, + elemManager.forElementSubRegions< SurfaceElementSubRegion >( regionNames, [&]( localIndex const, - ElementSubRegionBase & subRegion ) + SurfaceElementSubRegion & subRegion ) { subRegion.registerField< rateAndState::stateVariable >( getName() ); subRegion.registerField< rateAndState::slipRate >( getName() ); subRegion.registerField< rateAndState::stateVariable_n >( getName() ); subRegion.registerField< rateAndState::slipRate_n >( getName() ); + + if ( !subRegion.hasWrapper( contact::slip::key() )) + { + subRegion.registerField< contact::slip >( getName() ); + subRegion.registerField< contact::traction >( getName() ); + + subRegion.registerWrapper< string >( viewKeyStruct::frictionLawNameString() ). + setPlotLevel( PlotLevel::NOPLOT ). + setRestartFlags( RestartFlags::NO_WRITE ). + setSizedFromParent( 0 ); + + string & frictionLawName = subRegion.getReference< string >( viewKeyStruct::frictionLawNameString() ); + frictionLawName = SolverBase::getConstitutiveName< FrictionBase >( subRegion ); + GEOS_ERROR_IF( frictionLawName.empty(), GEOS_FMT( "{}: FrictionBase model not found on subregion {}", + getDataContext(), subRegion.getDataContext() ) ); + } } ); } ); } @@ -107,11 +120,16 @@ real64 QuasiDynamicEQ::solverStep( real64 const & time_n, const int cycleNumber, DomainPartition & domain ) { + if(cycleNumber == 0) + {} /// 1. Compute shear and normal tractions + GEOS_LOG_LEVEL_RANK_0( 1, "Stress solver" ); + real64 const dtStress = updateStresses( time_n, dt, cycleNumber, domain ); /// 2. Solve for slip rate and state variable and, compute slip + GEOS_LOG_LEVEL_RANK_0( 1, "Rate and State solver" ); forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, arrayView1d< string const > const & regionNames ) @@ -142,7 +160,6 @@ real64 QuasiDynamicEQ::updateStresses( real64 const & time_n, // Call member variable stress solver to update the stress state if( m_stressSolver ) { - // 1. Solve the momentum balance real64 const dtStress = m_stressSolver->solverStep( time_n, dt, cycleNumber, domain ); @@ -166,7 +183,9 @@ real64 QuasiDynamicEQ::updateStresses( real64 const & time_n, string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); - RateAndStateFriction::KernelWrapper frictionKernelWrapper= frictionLaw.createKernelUpdates(); + RateAndStateFriction::KernelWrapper frictionKernelWrapper = frictionLaw.createKernelUpdates(); + + std::cout << "Launching kernel " << std::endl; forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { @@ -175,6 +194,9 @@ real64 QuasiDynamicEQ::updateStresses( real64 const & time_n, frictionKernelWrapper.getBCoefficient( k ), frictionKernelWrapper.getDcCoefficient( k ) ); + std::cout << "tau rate " << springSliderParameters.tauRate << std::endl; + std::cout << "Spring stiffness" << springSliderParameters.springStiffness << std::endl; + traction[k][1] = traction[k][1] + springSliderParameters.tauRate * dt - springSliderParameters.springStiffness * slip[k]; traction[k][2] = 0.0; } ); @@ -198,6 +220,9 @@ void QuasiDynamicEQ::saveOldStateAndUpdateSlip( ElementSubRegionBase & subRegion slipRate_n[k] = slipRate[k]; stateVariable_n[k] = stateVariable[k]; slip[k] = slip[k] + slipRate[k] * dt; + std::cout << "slip" << slip[k] << std::endl; + std::cout << "slipRate" << slipRate[k] << std::endl; + std::cout << "stateVariable" << stateVariable[k] << std::endl; } ); } diff --git a/src/coreComponents/physicsSolvers/surfaceGeneration/SurfaceGenerator.cpp b/src/coreComponents/physicsSolvers/surfaceGeneration/SurfaceGenerator.cpp index 9bcce6125f0..72c692557b7 100644 --- a/src/coreComponents/physicsSolvers/surfaceGeneration/SurfaceGenerator.cpp +++ b/src/coreComponents/physicsSolvers/surfaceGeneration/SurfaceGenerator.cpp @@ -2842,7 +2842,7 @@ void SurfaceGenerator::calculateNodeAndFaceSif( DomainPartition const & domain, SIFNode.zero(); SIFonFace.zero(); - + arrayView2d< real64 const > const & fext = nodeManager.getField< fields::solidMechanics::externalForce >(); arrayView2d< real64 const, nodes::TOTAL_DISPLACEMENT_USD > const & displacement = nodeManager.getField< fields::solidMechanics::totalDisplacement >(); From 863a6bef8d88922b3223a76a066f61949b46d02f Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Thu, 10 Oct 2024 18:15:12 -0700 Subject: [PATCH 23/53] spring slider first timestep working. Wip on continuing. --- .../inducedSeismicity/SpringSlider_base.xml | 32 +++++++++++ .../inducedSeismicity/SpringSlider_smoke.xml | 4 +- .../constitutive/contact/CoulombFriction.cpp | 1 - .../contact/RateAndStateFriction.cpp | 10 +++- .../contact/RateAndStateFriction.hpp | 1 + .../inducedSeismicity/QuasiDynamicEQ.cpp | 50 ++++++++++++----- .../kernels/RateAndStateKernels.hpp | 56 ++++++++++++++++--- 7 files changed, 125 insertions(+), 29 deletions(-) diff --git a/inputFiles/inducedSeismicity/SpringSlider_base.xml b/inputFiles/inducedSeismicity/SpringSlider_base.xml index 34e24d4b802..65cf76ea0f5 100644 --- a/inputFiles/inducedSeismicity/SpringSlider_base.xml +++ b/inputFiles/inducedSeismicity/SpringSlider_base.xml @@ -77,6 +77,38 @@ objectPath="faceManager" scale="1" setNames="{ faultPlane }"/> + + + + + + diff --git a/inputFiles/inducedSeismicity/SpringSlider_smoke.xml b/inputFiles/inducedSeismicity/SpringSlider_smoke.xml index 28a6cd38d17..7c2598a6bb4 100644 --- a/inputFiles/inducedSeismicity/SpringSlider_smoke.xml +++ b/inputFiles/inducedSeismicity/SpringSlider_smoke.xml @@ -6,7 +6,8 @@ + maxTime="200" + maxCycle="2"> \ No newline at end of file diff --git a/src/coreComponents/constitutive/contact/CoulombFriction.cpp b/src/coreComponents/constitutive/contact/CoulombFriction.cpp index 1199f652d7e..a7bc27300dc 100644 --- a/src/coreComponents/constitutive/contact/CoulombFriction.cpp +++ b/src/coreComponents/constitutive/contact/CoulombFriction.cpp @@ -50,7 +50,6 @@ CoulombFriction::CoulombFriction( string const & name, Group * const parent ): registerWrapper( viewKeyStruct::elasticSlipString(), &m_elasticSlip ). setApplyDefaultValue( 0.0 ). setDescription( "Elastic Slip" ); - } CoulombFriction::~CoulombFriction() diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp index 4def6a5ea38..1635f8d2c27 100644 --- a/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp +++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp @@ -28,8 +28,7 @@ namespace constitutive { RateAndStateFriction::RateAndStateFriction( string const & name, Group * const parent ): - FrictionBase( name, parent ), - m_frictionCoefficient() + FrictionBase( name, parent ) { registerWrapper( viewKeyStruct::aCoefficientString(), &m_a ). setDescription( "Rate- and State-dependent friction coefficient a." ); @@ -46,6 +45,10 @@ RateAndStateFriction::RateAndStateFriction( string const & name, Group * const p registerWrapper( viewKeyStruct::referenceFrictionCoefficientString(), &m_mu0 ). setDescription( "Rate- and State-dependent friction reference friction coefficient." ); + registerWrapper( viewKeyStruct::frictionCoefficientString(), &m_frictionCoefficient ). + setApplyDefaultValue( 0.0 ). + setDescription( "Friction coefficient" ); + /// Default values registerWrapper( viewKeyStruct::defaultACoefficientString(), &m_defaultA ). setInputFlag( InputFlags::REQUIRED ). @@ -87,6 +90,9 @@ void RateAndStateFriction::postInputInitialization() this->getWrapper< array1d< real64 > >( viewKeyStruct::referenceFrictionCoefficientString() ). setApplyDefaultValue( m_defaultMu0 ); + + this->getWrapper< array1d< real64 > >( viewKeyStruct::frictionCoefficientString() ). + setApplyDefaultValue( m_defaultMu0 ); } void RateAndStateFriction::allocateConstitutiveData( Group & parent, diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp index b2bb3dbf86c..38da5a4c774 100644 --- a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp +++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp @@ -264,6 +264,7 @@ inline real64 RateAndStateFriction::KernelWrapper::frictionCoefficient( localInd real64 const stateVariable ) const { real64 const arg = ( slipRate / (2 * m_V0[k]) ) * LvArray::math::exp( stateVariable / m_a[k] ); + m_frictionCoefficient[k] = m_a[k] * LvArray::math::asinh( arg ); return m_frictionCoefficient[k]; diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp index eaae2a66f27..c0db8f925ee 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp @@ -24,6 +24,7 @@ #include "kernels/RateAndStateKernels.hpp" #include "rateAndStateFields.hpp" #include "physicsSolvers/contact/ContactFields.hpp" +#include "fieldSpecification/FieldSpecificationManager.hpp" namespace geos { @@ -37,7 +38,7 @@ QuasiDynamicEQ::QuasiDynamicEQ( const string & name, SolverBase( name, parent ), m_stressSolver( nullptr ), m_stressSolverName( "SpringSlider" ), - m_maxNewtonIterations( 10 ), + m_maxNewtonIterations( 2 ), m_shearImpedance( 0.0 ), m_targetSlipIncrement( 1.0e-7 ) { @@ -98,8 +99,12 @@ void QuasiDynamicEQ::registerDataOnMesh( Group & meshBodies ) if ( !subRegion.hasWrapper( contact::slip::key() )) { + string const labels[3] = { "normal", "tangent1", "tangent2" }; + subRegion.registerField< contact::slip >( getName() ); - subRegion.registerField< contact::traction >( getName() ); + subRegion.registerField< contact::traction >( getName() ). + setDimLabels( 1, labels ). + reference().resizeDimension< 1 >( 3 ); subRegion.registerWrapper< string >( viewKeyStruct::frictionLawNameString() ). setPlotLevel( PlotLevel::NOPLOT ). @@ -117,11 +122,22 @@ void QuasiDynamicEQ::registerDataOnMesh( Group & meshBodies ) real64 QuasiDynamicEQ::solverStep( real64 const & time_n, real64 const & dt, - const int cycleNumber, + int const cycleNumber, DomainPartition & domain ) { if(cycleNumber == 0) - {} + { + /// Apply initial conditions to the Fault + FieldSpecificationManager & fieldSpecificationManager = FieldSpecificationManager::getInstance(); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & ) + + { + fieldSpecificationManager.applyInitialConditions( mesh ); + } ); + } /// 1. Compute shear and normal tractions GEOS_LOG_LEVEL_RANK_0( 1, "Stress solver" ); @@ -146,7 +162,7 @@ real64 QuasiDynamicEQ::solverStep( real64 const & time_n, } ); } ); - m_nextDt = setNextDt( dtStress, domain ); + // m_nextDt = setNextDt( dtStress, domain ); // return time step size achieved by stress solver return dtStress; @@ -185,20 +201,20 @@ real64 QuasiDynamicEQ::updateStresses( real64 const & time_n, RateAndStateFriction::KernelWrapper frictionKernelWrapper = frictionLaw.createKernelUpdates(); - std::cout << "Launching kernel " << std::endl; - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { + // std::cout << "traction" << traction[k][0] << std::endl; + SpringSliderParameters springSliderParameters = SpringSliderParameters( traction[k][0], frictionKernelWrapper.getACoefficient( k ), frictionKernelWrapper.getBCoefficient( k ), - frictionKernelWrapper.getDcCoefficient( k ) ); - - std::cout << "tau rate " << springSliderParameters.tauRate << std::endl; - std::cout << "Spring stiffness" << springSliderParameters.springStiffness << std::endl; + frictionKernelWrapper.getDcCoefficient( k ) ); traction[k][1] = traction[k][1] + springSliderParameters.tauRate * dt - springSliderParameters.springStiffness * slip[k]; traction[k][2] = 0.0; + + // std::cout << "tau rate " << springSliderParameters.tauRate << std::endl; + // std::cout << "Spring stiffness" << springSliderParameters.springStiffness << std::endl; } ); } ); } ); @@ -220,9 +236,9 @@ void QuasiDynamicEQ::saveOldStateAndUpdateSlip( ElementSubRegionBase & subRegion slipRate_n[k] = slipRate[k]; stateVariable_n[k] = stateVariable[k]; slip[k] = slip[k] + slipRate[k] * dt; - std::cout << "slip" << slip[k] << std::endl; - std::cout << "slipRate" << slipRate[k] << std::endl; - std::cout << "stateVariable" << stateVariable[k] << std::endl; + // std::cout << "slip" << slip[k] << std::endl; + // std::cout << "slipRate" << slipRate[k] << std::endl; + // std::cout << "stateVariable" << stateVariable[k] << std::endl; } ); } @@ -255,7 +271,11 @@ real64 QuasiDynamicEQ::setNextDt( real64 const & currentDt, DomainPartition & do maxSlipRate = MpiWrapper::max( maxSlipRateOnThisRank ); } ); - return m_targetSlipIncrement / maxSlipRate; + real64 const nextDt = m_targetSlipIncrement / maxSlipRate; + + GEOS_LOG_LEVEL_RANK_0( 1, GEOS_FMT( "The next dt will be {} s", nextDt)); + + return nextDt; } REGISTER_CATALOG_ENTRY( SolverBase, QuasiDynamicEQ, string const &, dataRepository::Group * const ) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index 8163d52ff13..e0980b44380 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -72,22 +72,27 @@ class RateAndStateKernel real64 const dt, StackVariables & stack ) const { - - // real64 const normalTraction = m_traction[k][0]; real64 const shearTraction = LvArray::math::sqrt( m_traction[k][1]*m_traction[k][1] + m_traction[k][2]*m_traction[k][2] ); + // std::cout << "normalTraction: " << normalTraction << std::endl; + // std::cout << "shearTraction: " << shearTraction << std::endl; // Eq 1: shear stress balance real64 const tauFriction = m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] ) * normalTraction; + // std::cout << "tauFriction: " << tauFriction << std::endl; real64 const dTauFriction[2] = { m_frictionLaw.dfrictionCoefficient_dStateVariable( k, m_slipRate[k], m_stateVariable[k] ) * normalTraction, m_frictionLaw.dfrictionCoefficient_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) * normalTraction }; + // std::cout << "dTauFriction " << dTauFriction[0] << " - " << dTauFriction[1] << std::endl; + + // std::cout << "force balance" << std::endl; stack.rhs[0] = shearTraction - tauFriction - m_shearImpedance * m_slipRate[k]; // Eq 2: slip law stack.rhs[1] = (m_stateVariable[k] - m_stateVariable_n[k]) / dt - m_frictionLaw.dStateVariabledT( k, m_slipRate[k], m_stateVariable[k] ); real64 const dStateEvolutionLaw[2] = { 1 / dt - m_frictionLaw.dStateVariabledT_dStateVariable( k, m_slipRate[k], m_stateVariable[k] ), -m_frictionLaw.dStateVariabledT_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) }; + // Assemble Jacobian matrix // derivative shear stress balance w.r.t. theta @@ -98,6 +103,14 @@ class RateAndStateKernel stack.jacobian[1][0] = dStateEvolutionLaw[0]; // derivative slip law w.r.t. slip_velocity stack.jacobian[1][1] = dStateEvolutionLaw[1]; + // for (int i = 0; i < 2; i++) + // { + // std::cout << "rhs[" << i << "] = " << stack.rhs[i] << std::endl; + // for (int j = 0; j < 2; j++) + // { + // std::cout << "j(" << i << "," << j << ") = " << stack.jacobian[i][j] << std::endl; + // } + // } } GEOS_HOST_DEVICE @@ -110,8 +123,24 @@ class RateAndStateKernel denseLinearAlgebra::solve< 2 >( stack.jacobian, stack.rhs, solution ); /// Update variables - m_stateVariable[k] += solution[0]; - m_slipRate[k] += solution[1]; + m_stateVariable[k] -= solution[0]; + m_slipRate[k] -= solution[1]; + + // std::cout << "solution[0]" << solution[0] << std::endl; + // std::cout << "solution[1]" << solution[1] << std::endl; + + // std::cout << "m_stateVariable[k]" << m_stateVariable[k] << std::endl; + // std::cout << "m_slipRate[k]" << m_slipRate[k] << std::endl; + + } + + GEOS_HOST_DEVICE + int checkConvergence( StackVariables const & stack, + real64 const tol ) const + { + int const converged = LvArray::tensorOps::l2Norm< 2 >( stack.rhs ) < tol ? 1 : 0; + std::cout << "norm: " << LvArray::tensorOps::l2Norm< 2 >( stack.rhs ) << std::endl; + return converged; } private: @@ -154,21 +183,30 @@ createAndLaunch( SurfaceElementSubRegion & subRegion, RateAndStateKernel kernel( subRegion, frictionLaw, shearImpedance ); // Newton loops outside of the kernel launch + bool allConverged = false; for( integer iter = 0; iter < maxNewtonIter; iter++ ) { /// Kernel 1: Do a solver for all non converged elements + RAJA::ReduceMin< parallelDeviceReduce, int > converged( 1 ); forAll< POLICY >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { RateAndStateKernel::StackVariables stack; kernel.setup( k, dt, stack ); kernel.solve( k, stack ); + converged.min( kernel.checkConvergence( stack, 1.0e-6 ) ); } ); - /// Kernel 2: Update set of non-converged elements - // forAll< POLICY >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) - // { - - // } ); + std::cout << converged.get() << std::endl; + if ( converged.get() ) + { + allConverged = true; + break; + } + } + + if ( !allConverged ) + { + GEOS_ERROR(" Failed to converge"); } } From f57ea0b5c680bb61847a4516be3f891740ff8d88 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Fri, 11 Oct 2024 15:29:33 -0700 Subject: [PATCH 24/53] Spring slider works --- .../inducedSeismicity/SpringSlider_smoke.xml | 11 ++- src/coreComponents/LvArray | 2 +- .../contact/RateAndStateFriction.cpp | 2 +- .../inducedSeismicity/QuasiDynamicEQ.cpp | 45 ++++++------ .../kernels/RateAndStateKernels.hpp | 73 ++++++++++--------- .../inducedSeismicity/rateAndStateFields.hpp | 8 ++ .../surfaceGeneration/SurfaceGenerator.cpp | 2 +- 7 files changed, 78 insertions(+), 65 deletions(-) diff --git a/inputFiles/inducedSeismicity/SpringSlider_smoke.xml b/inputFiles/inducedSeismicity/SpringSlider_smoke.xml index 7c2598a6bb4..9db6a48ea0d 100644 --- a/inputFiles/inducedSeismicity/SpringSlider_smoke.xml +++ b/inputFiles/inducedSeismicity/SpringSlider_smoke.xml @@ -6,8 +6,7 @@ + maxTime="2e5"> \ No newline at end of file diff --git a/src/coreComponents/LvArray b/src/coreComponents/LvArray index 854f4664b8a..59766afb585 160000 --- a/src/coreComponents/LvArray +++ b/src/coreComponents/LvArray @@ -1 +1 @@ -Subproject commit 854f4664b8a1d466465bff0fbf3de3ba5deb532a +Subproject commit 59766afb585f2d2e2a00595aecdfb9f8d8fba513 diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp index 1635f8d2c27..f26954a3316 100644 --- a/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp +++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp @@ -47,7 +47,7 @@ RateAndStateFriction::RateAndStateFriction( string const & name, Group * const p registerWrapper( viewKeyStruct::frictionCoefficientString(), &m_frictionCoefficient ). setApplyDefaultValue( 0.0 ). - setDescription( "Friction coefficient" ); + setDescription( "Friction coefficient" ); /// Default values registerWrapper( viewKeyStruct::defaultACoefficientString(), &m_defaultA ). diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp index c0db8f925ee..8b51b47efba 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp @@ -89,32 +89,33 @@ void QuasiDynamicEQ::registerDataOnMesh( Group & meshBodies ) ElementRegionManager & elemManager = mesh.getElemManager(); elemManager.forElementSubRegions< SurfaceElementSubRegion >( regionNames, - [&]( localIndex const, - SurfaceElementSubRegion & subRegion ) + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) { subRegion.registerField< rateAndState::stateVariable >( getName() ); subRegion.registerField< rateAndState::slipRate >( getName() ); subRegion.registerField< rateAndState::stateVariable_n >( getName() ); subRegion.registerField< rateAndState::slipRate_n >( getName() ); + subRegion.registerField< rateAndState::deltaSlip >( getName() ); - if ( !subRegion.hasWrapper( contact::slip::key() )) - { + if( !subRegion.hasWrapper( contact::slip::key() )) + { string const labels[3] = { "normal", "tangent1", "tangent2" }; subRegion.registerField< contact::slip >( getName() ); subRegion.registerField< contact::traction >( getName() ). - setDimLabels( 1, labels ). - reference().resizeDimension< 1 >( 3 ); - + setDimLabels( 1, labels ). + reference().resizeDimension< 1 >( 3 ); + subRegion.registerWrapper< string >( viewKeyStruct::frictionLawNameString() ). - setPlotLevel( PlotLevel::NOPLOT ). - setRestartFlags( RestartFlags::NO_WRITE ). - setSizedFromParent( 0 ); + setPlotLevel( PlotLevel::NOPLOT ). + setRestartFlags( RestartFlags::NO_WRITE ). + setSizedFromParent( 0 ); string & frictionLawName = subRegion.getReference< string >( viewKeyStruct::frictionLawNameString() ); frictionLawName = SolverBase::getConstitutiveName< FrictionBase >( subRegion ); GEOS_ERROR_IF( frictionLawName.empty(), GEOS_FMT( "{}: FrictionBase model not found on subregion {}", - getDataContext(), subRegion.getDataContext() ) ); + getDataContext(), subRegion.getDataContext() ) ); } } ); } ); @@ -125,11 +126,11 @@ real64 QuasiDynamicEQ::solverStep( real64 const & time_n, int const cycleNumber, DomainPartition & domain ) { - if(cycleNumber == 0) + if( cycleNumber == 0 ) { /// Apply initial conditions to the Fault FieldSpecificationManager & fieldSpecificationManager = FieldSpecificationManager::getInstance(); - + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, arrayView1d< string const > const & ) @@ -193,28 +194,23 @@ real64 QuasiDynamicEQ::updateStresses( real64 const & time_n, [&]( localIndex const, SurfaceElementSubRegion & subRegion ) { - arrayView1d< real64 const > const slip = subRegion.getField< fields::contact::slip >().toViewConst(); + arrayView1d< real64 const > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); arrayView2d< real64 > const traction = subRegion.getField< fields::contact::traction >(); string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); RateAndStateFriction::KernelWrapper frictionKernelWrapper = frictionLaw.createKernelUpdates(); - + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { - // std::cout << "traction" << traction[k][0] << std::endl; - SpringSliderParameters springSliderParameters = SpringSliderParameters( traction[k][0], frictionKernelWrapper.getACoefficient( k ), frictionKernelWrapper.getBCoefficient( k ), - frictionKernelWrapper.getDcCoefficient( k ) ); + frictionKernelWrapper.getDcCoefficient( k ) ); - traction[k][1] = traction[k][1] + springSliderParameters.tauRate * dt - springSliderParameters.springStiffness * slip[k]; + traction[k][1] = traction[k][1] + springSliderParameters.tauRate * dt - springSliderParameters.springStiffness * deltaSlip[k]; traction[k][2] = 0.0; - - // std::cout << "tau rate " << springSliderParameters.tauRate << std::endl; - // std::cout << "Spring stiffness" << springSliderParameters.springStiffness << std::endl; } ); } ); } ); @@ -228,6 +224,8 @@ void QuasiDynamicEQ::saveOldStateAndUpdateSlip( ElementSubRegionBase & subRegion arrayView1d< real64 > const stateVariable_n = subRegion.getField< rateAndState::stateVariable_n >(); arrayView1d< real64 > const slipRate = subRegion.getField< rateAndState::slipRate >(); arrayView1d< real64 > const slipRate_n = subRegion.getField< rateAndState::slipRate_n >(); + arrayView1d< real64 > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); + arrayView1d< real64 > const slip = subRegion.getField< contact::slip >(); @@ -235,6 +233,7 @@ void QuasiDynamicEQ::saveOldStateAndUpdateSlip( ElementSubRegionBase & subRegion { slipRate_n[k] = slipRate[k]; stateVariable_n[k] = stateVariable[k]; + deltaSlip[k] = slipRate[k] * dt; slip[k] = slip[k] + slipRate[k] * dt; // std::cout << "slip" << slip[k] << std::endl; // std::cout << "slipRate" << slipRate[k] << std::endl; @@ -273,7 +272,7 @@ real64 QuasiDynamicEQ::setNextDt( real64 const & currentDt, DomainPartition & do real64 const nextDt = m_targetSlipIncrement / maxSlipRate; - GEOS_LOG_LEVEL_RANK_0( 1, GEOS_FMT( "The next dt will be {} s", nextDt)); + GEOS_LOG_LEVEL_RANK_0( 1, GEOS_FMT( "The next dt will be {:.2e} s", nextDt )); return nextDt; } diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index e0980b44380..aef9c7f1891 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -43,7 +43,7 @@ class RateAndStateKernel real64 const shearImpedance ): m_slipRate( subRegion.getField< fields::rateAndState::slipRate >() ), m_stateVariable( subRegion.getField< fields::rateAndState::stateVariable >() ), - m_stateVariable_n( subRegion.getField< fields::rateAndState::stateVariable >() ), + m_stateVariable_n( subRegion.getField< fields::rateAndState::stateVariable_n >() ), m_traction( subRegion.getField< fields::contact::traction >() ), m_shearImpedance( shearImpedance ), m_frictionLaw( frictionLaw.createKernelUpdates() ) @@ -74,8 +74,6 @@ class RateAndStateKernel { real64 const normalTraction = m_traction[k][0]; real64 const shearTraction = LvArray::math::sqrt( m_traction[k][1]*m_traction[k][1] + m_traction[k][2]*m_traction[k][2] ); - // std::cout << "normalTraction: " << normalTraction << std::endl; - // std::cout << "shearTraction: " << shearTraction << std::endl; // Eq 1: shear stress balance real64 const tauFriction = m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] ) * normalTraction; @@ -83,32 +81,38 @@ class RateAndStateKernel real64 const dTauFriction[2] = { m_frictionLaw.dfrictionCoefficient_dStateVariable( k, m_slipRate[k], m_stateVariable[k] ) * normalTraction, m_frictionLaw.dfrictionCoefficient_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) * normalTraction }; - // std::cout << "dTauFriction " << dTauFriction[0] << " - " << dTauFriction[1] << std::endl; - // std::cout << "force balance" << std::endl; stack.rhs[0] = shearTraction - tauFriction - m_shearImpedance * m_slipRate[k]; // Eq 2: slip law - stack.rhs[1] = (m_stateVariable[k] - m_stateVariable_n[k]) / dt - m_frictionLaw.dStateVariabledT( k, m_slipRate[k], m_stateVariable[k] ); + real64 const dStateVariabledT = m_frictionLaw.dStateVariabledT( k, m_slipRate[k], m_stateVariable[k] ); + stack.rhs[1] = (m_stateVariable[k] - m_stateVariable_n[k]) / dt - dStateVariabledT; real64 const dStateEvolutionLaw[2] = { 1 / dt - m_frictionLaw.dStateVariabledT_dStateVariable( k, m_slipRate[k], m_stateVariable[k] ), -m_frictionLaw.dStateVariabledT_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) }; - // Assemble Jacobian matrix // derivative shear stress balance w.r.t. theta stack.jacobian[0][0] = -dTauFriction[0]; // derivative shear stress balance w.r.t. slip_velocity - stack.jacobian[0][1] = -dTauFriction[1]; + stack.jacobian[0][1] = -dTauFriction[1] - m_shearImpedance; // derivative slip law w.r.t. theta stack.jacobian[1][0] = dStateEvolutionLaw[0]; // derivative slip law w.r.t. slip_velocity stack.jacobian[1][1] = dStateEvolutionLaw[1]; - // for (int i = 0; i < 2; i++) - // { - // std::cout << "rhs[" << i << "] = " << stack.rhs[i] << std::endl; - // for (int j = 0; j < 2; j++) - // { - // std::cout << "j(" << i << "," << j << ") = " << stack.jacobian[i][j] << std::endl; + + + /// Matteo: debugging tools. + // printf("dStateVariabledT = %.10e\n", dStateVariabledT); + // printf("m_stateVariable = %.10e\n", m_stateVariable[k]); + // printf("m_stateVariable_n = %.10e\n", m_stateVariable_n[k]); + // printf("dt = %.10e\n", dt); + + // for( int i = 0; i < 2; i++ ) + // { + // printf( "rhs[%d] = %.10e\n", i, stack.rhs[i] ); + // for( int j = 0; j < 2; j++ ) + // { + // printf( "j(%d,%d) = %.10e\n", i, j, stack.jacobian[i][j] ); // } // } } @@ -126,21 +130,21 @@ class RateAndStateKernel m_stateVariable[k] -= solution[0]; m_slipRate[k] -= solution[1]; - // std::cout << "solution[0]" << solution[0] << std::endl; - // std::cout << "solution[1]" << solution[1] << std::endl; - - // std::cout << "m_stateVariable[k]" << m_stateVariable[k] << std::endl; - // std::cout << "m_slipRate[k]" << m_slipRate[k] << std::endl; + /// Matteo: debugging tools. + // printf("solution[0] = %.10e\n", solution[0]); + // printf("solution[1] = %.10e\n", solution[1]); + // printf("m_stateVariable[%d] = %.10e\n", k, m_stateVariable[k]); + // printf("m_slipRate[%d] = %.10e\n", k, m_slipRate[k]); } - + GEOS_HOST_DEVICE - int checkConvergence( StackVariables const & stack, - real64 const tol ) const + std::pair< int, real64 > checkConvergence( StackVariables const & stack, + real64 const tol ) const { - int const converged = LvArray::tensorOps::l2Norm< 2 >( stack.rhs ) < tol ? 1 : 0; - std::cout << "norm: " << LvArray::tensorOps::l2Norm< 2 >( stack.rhs ) << std::endl; - return converged; + real64 const residualNorm = LvArray::tensorOps::l2Norm< 2 >( stack.rhs ); + int const converged = residualNorm < tol ? 1 : 0; + return std::make_pair( converged, residualNorm ); } private: @@ -182,31 +186,34 @@ createAndLaunch( SurfaceElementSubRegion & subRegion, constitutive::RateAndStateFriction const & frictionLaw = subRegion.getConstitutiveModel< constitutive::RateAndStateFriction >( frictionaLawName ); RateAndStateKernel kernel( subRegion, frictionLaw, shearImpedance ); - // Newton loops outside of the kernel launch + // Newton loop (outside of the kernel launch) bool allConverged = false; for( integer iter = 0; iter < maxNewtonIter; iter++ ) { - /// Kernel 1: Do a solver for all non converged elements RAJA::ReduceMin< parallelDeviceReduce, int > converged( 1 ); + RAJA::ReduceMax< parallelDeviceReduce, real64 > residualNorm( 0.0 ); forAll< POLICY >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { RateAndStateKernel::StackVariables stack; kernel.setup( k, dt, stack ); kernel.solve( k, stack ); - converged.min( kernel.checkConvergence( stack, 1.0e-6 ) ); + auto result = kernel.checkConvergence( stack, 1.0e-6 ); + converged.min( std::get< 0 >( result ) ); + residualNorm.max( std::get< 1 >( result ) ); } ); - std::cout << converged.get() << std::endl; - if ( converged.get() ) + real64 const maxResidualNorm = MpiWrapper::max( residualNorm.get() ); + GEOS_LOG_RANK_0( GEOS_FMT( "-----iter {} : residual = {:.10e} ", iter, maxResidualNorm ) ); + + if( converged.get() ) { allConverged = true; break; } } - - if ( !allConverged ) + if( !allConverged ) { - GEOS_ERROR(" Failed to converge"); + GEOS_ERROR( " Failed to converge" ); } } diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp index 5e9efea45de..343f3eacc29 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp @@ -64,6 +64,14 @@ DECLARE_FIELD( stateVariable_n, WRITE_AND_READ, "Rate- and state-dependent friction state variable at previous time step" ); +DECLARE_FIELD( deltaSlip, + "deltaSlip", + array1d< real64 >, + 0.0, + LEVEL_0, + WRITE_AND_READ, + "Slip increment" ); + } diff --git a/src/coreComponents/physicsSolvers/surfaceGeneration/SurfaceGenerator.cpp b/src/coreComponents/physicsSolvers/surfaceGeneration/SurfaceGenerator.cpp index 72c692557b7..9bcce6125f0 100644 --- a/src/coreComponents/physicsSolvers/surfaceGeneration/SurfaceGenerator.cpp +++ b/src/coreComponents/physicsSolvers/surfaceGeneration/SurfaceGenerator.cpp @@ -2842,7 +2842,7 @@ void SurfaceGenerator::calculateNodeAndFaceSif( DomainPartition const & domain, SIFNode.zero(); SIFonFace.zero(); - + arrayView2d< real64 const > const & fext = nodeManager.getField< fields::solidMechanics::externalForce >(); arrayView2d< real64 const, nodes::TOTAL_DISPLACEMENT_USD > const & displacement = nodeManager.getField< fields::solidMechanics::totalDisplacement >(); From f3e6573f9407b1207544cc43a253d5add83ce3c0 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Fri, 11 Oct 2024 16:41:12 -0700 Subject: [PATCH 25/53] add integratedTest. --- inputFiles/inducedSeismicity/SpringSlider_smoke.xml | 4 ++-- inputFiles/inducedSeismicity/inducedSeismicity.ats | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/inputFiles/inducedSeismicity/SpringSlider_smoke.xml b/inputFiles/inducedSeismicity/SpringSlider_smoke.xml index 9db6a48ea0d..9fb68852703 100644 --- a/inputFiles/inducedSeismicity/SpringSlider_smoke.xml +++ b/inputFiles/inducedSeismicity/SpringSlider_smoke.xml @@ -6,7 +6,7 @@ + maxTime="4.5e4"> diff --git a/inputFiles/inducedSeismicity/inducedSeismicity.ats b/inputFiles/inducedSeismicity/inducedSeismicity.ats index 58a28bf9c40..21890d67bdf 100644 --- a/inputFiles/inducedSeismicity/inducedSeismicity.ats +++ b/inputFiles/inducedSeismicity/inducedSeismicity.ats @@ -15,12 +15,19 @@ decks = [ restart_step=20, check_step=30, restartcheck_params=RestartcheckParameters(atol=1e-4, rtol=1e-3)), - TestDeck( + TestDeck( name="SeismicityRate_analytical_verification_smoke", description="Prescribed logarithmic stressing history", partitions=((1, 1, 1), ), restart_step=0, check_step=100, curvecheck_params=CurveCheckParameters(**curvecheck_params)) + TestDeck( + name="SpringSlider_smoke", + description="Spring slider 0D system", + partitions=((1, 1, 1), ), + restart_step=0, + check_step=3265, + restartcheck_params=RestartcheckParameters(atol=1e-4, rtol=1e-3) ) ] generate_geos_tests(decks) From 7515bc37ce1082b9f1b53cef84710890e6338388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Mon, 14 Oct 2024 16:09:05 -0700 Subject: [PATCH 26/53] wip: Use 2-component slip/slipRate in rate-and-state kernel --- .../inducedSeismicity/SpringSlider_base.xml | 3 +- .../contact/RateAndStateFriction.hpp | 56 ++++---- .../inducedSeismicity/QuasiDynamicEQ.cpp | 55 ++++---- .../kernels/RateAndStateKernels.hpp | 123 ++++++++++++------ .../inducedSeismicity/rateAndStateFields.hpp | 6 +- 5 files changed, 146 insertions(+), 97 deletions(-) diff --git a/inputFiles/inducedSeismicity/SpringSlider_base.xml b/inputFiles/inducedSeismicity/SpringSlider_base.xml index 65cf76ea0f5..49fa56d2470 100644 --- a/inputFiles/inducedSeismicity/SpringSlider_base.xml +++ b/inputFiles/inducedSeismicity/SpringSlider_base.xml @@ -107,6 +107,7 @@ fieldName="slipRate" initialCondition="1" objectPath="ElementRegions/Fault/FractureSubRegion" + component="0" scale="1.0e-6" setNames="{all}"/> @@ -126,7 +127,7 @@ + fieldName="displacementJump"/> ( getName() ); - subRegion.registerField< rateAndState::slipRate >( getName() ); subRegion.registerField< rateAndState::stateVariable_n >( getName() ); - subRegion.registerField< rateAndState::slipRate_n >( getName() ); - subRegion.registerField< rateAndState::deltaSlip >( getName() ); - - if( !subRegion.hasWrapper( contact::slip::key() )) + + // Tangent (2-component) functions on fault + string const labels2Comp[2] = {"tangent1", "tangent2" }; + subRegion.registerField< rateAndState::slipRate >( getName() ).setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); + subRegion.registerField< rateAndState::slipRate_n >( getName() ).setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); + subRegion.registerField< rateAndState::deltaSlip >( getName() ).setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); + + if( !subRegion.hasWrapper( contact::dispJump::key() )) { - string const labels[3] = { "normal", "tangent1", "tangent2" }; - - subRegion.registerField< contact::slip >( getName() ); + // 3-component functions on fault + string const labels3Comp[3] = { "normal", "tangent1", "tangent2" }; + subRegion.registerField< contact::dispJump >( getName() ). + setDimLabels( 1, labels3Comp ). + reference().resizeDimension< 1 >( 3 ); subRegion.registerField< contact::traction >( getName() ). - setDimLabels( 1, labels ). + setDimLabels( 1, labels3Comp ). reference().resizeDimension< 1 >( 3 ); subRegion.registerWrapper< string >( viewKeyStruct::frictionLawNameString() ). @@ -194,7 +200,8 @@ real64 QuasiDynamicEQ::updateStresses( real64 const & time_n, [&]( localIndex const, SurfaceElementSubRegion & subRegion ) { - arrayView1d< real64 const > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); + + arrayView2d< real64 const > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); arrayView2d< real64 > const traction = subRegion.getField< fields::contact::traction >(); string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); @@ -209,7 +216,8 @@ real64 QuasiDynamicEQ::updateStresses( real64 const & time_n, frictionKernelWrapper.getBCoefficient( k ), frictionKernelWrapper.getDcCoefficient( k ) ); - traction[k][1] = traction[k][1] + springSliderParameters.tauRate * dt - springSliderParameters.springStiffness * deltaSlip[k]; + + traction[k][1] = traction[k][1] + springSliderParameters.tauRate * dt - springSliderParameters.springStiffness * deltaSlip[k][0]; traction[k][2] = 0.0; } ); } ); @@ -222,19 +230,22 @@ void QuasiDynamicEQ::saveOldStateAndUpdateSlip( ElementSubRegionBase & subRegion { arrayView1d< real64 > const stateVariable = subRegion.getField< rateAndState::stateVariable >(); arrayView1d< real64 > const stateVariable_n = subRegion.getField< rateAndState::stateVariable_n >(); - arrayView1d< real64 > const slipRate = subRegion.getField< rateAndState::slipRate >(); - arrayView1d< real64 > const slipRate_n = subRegion.getField< rateAndState::slipRate_n >(); - arrayView1d< real64 > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); - + arrayView2d< real64 > const slipRate = subRegion.getField< rateAndState::slipRate >(); + arrayView2d< real64 > const slipRate_n = subRegion.getField< rateAndState::slipRate_n >(); + arrayView2d< real64 > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); - arrayView1d< real64 > const slip = subRegion.getField< contact::slip >(); + arrayView2d< real64 > const dispJump = subRegion.getField< contact::dispJump >(); forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { - slipRate_n[k] = slipRate[k]; - stateVariable_n[k] = stateVariable[k]; - deltaSlip[k] = slipRate[k] * dt; - slip[k] = slip[k] + slipRate[k] * dt; + slipRate_n[k][0] = slipRate[k][0]; + slipRate_n[k][0] = slipRate[k][0]; + stateVariable_n[k] = stateVariable[k]; + deltaSlip[k][0] = slipRate[k][0] * dt; + deltaSlip[k][1] = slipRate[k][1] * dt; + // Update tangential components of the displacement jump + dispJump[k][1] = dispJump[k][1] + slipRate[k][0] * dt; + dispJump[k][2] = dispJump[k][2] + slipRate[k][1] * dt; // std::cout << "slip" << slip[k] << std::endl; // std::cout << "slipRate" << slipRate[k] << std::endl; // std::cout << "stateVariable" << stateVariable[k] << std::endl; @@ -257,12 +268,12 @@ real64 QuasiDynamicEQ::setNextDt( real64 const & currentDt, DomainPartition & do [&]( localIndex const, SurfaceElementSubRegion const & subRegion ) { - arrayView1d< real64 const > const slipRate = subRegion.getField< rateAndState::slipRate >(); + arrayView2d< real64 const > const slipRate = subRegion.getField< rateAndState::slipRate >(); RAJA::ReduceMax< parallelDeviceReduce, real64 > maximumSlipRateOnThisRegion( 0.0 ); forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { - maximumSlipRateOnThisRegion.max( LvArray::math::abs( slipRate[k] ) ); + maximumSlipRateOnThisRegion.max( LvArray::math::sqrt( slipRate[k][0]*slipRate[k][0] + slipRate[k][1]*slipRate[k][1]) ); } ); if( maximumSlipRateOnThisRegion.get() > maxSlipRateOnThisRank ) maxSlipRateOnThisRank = maximumSlipRateOnThisRegion.get(); diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index aef9c7f1891..4ebfd40d844 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -61,9 +61,9 @@ class RateAndStateKernel StackVariables( ) {} - real64 jacobian[2][2]{}; + real64 jacobian[3][3]{}; - real64 rhs[2]{}; + real64 rhs[3]{}; }; @@ -72,84 +72,121 @@ class RateAndStateKernel real64 const dt, StackVariables & stack ) const { + m_slipRate[k][1] = 0.; //TODO. Remove once solution is correctly initialized. real64 const normalTraction = m_traction[k][0]; - real64 const shearTraction = LvArray::math::sqrt( m_traction[k][1]*m_traction[k][1] + m_traction[k][2]*m_traction[k][2] ); + real64 const shearTraction[2] = { m_traction[k][1], + m_traction[k][2]}; + real64 const slipRateMagnitude = LvArray::math::sqrt(m_slipRate[k][0] * m_slipRate[k][0] + m_slipRate[k][1] * m_slipRate[k][1] ); + real64 const normalizedSlipRate[2] = { m_slipRate[k][0] / slipRateMagnitude, + m_slipRate[k][1] / slipRateMagnitude }; + // std::cout << "normalTraction: " << normalTraction << std::endl; + // std::cout << "shearTraction[0]: " << shearTraction[0] << std::endl; + // std::cout << "shearTraction[1]: " << shearTraction[1] << std::endl; + + // std::cout << "normalizedSlipRate[0]: " << normalizedSlipRate[0] << std::endl; + // std::cout << "normalizedSlipRate[1]: " << normalizedSlipRate[1] << std::endl; // Eq 1: shear stress balance - real64 const tauFriction = m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] ) * normalTraction; - // std::cout << "tauFriction: " << tauFriction << std::endl; - real64 const dTauFriction[2] = { m_frictionLaw.dfrictionCoefficient_dStateVariable( k, m_slipRate[k], m_stateVariable[k] ) * normalTraction, - m_frictionLaw.dfrictionCoefficient_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) * normalTraction }; + // Frictional shear strength + real64 const frictionForce = normalTraction * m_frictionLaw.frictionCoefficient( k, slipRateMagnitude, m_stateVariable[k] ); + real64 const tauFriction[2] = { frictionForce * normalizedSlipRate[0], + frictionForce * normalizedSlipRate[1] }; + + // Jacobian entries + real64 const dFrictionForce_dStateVariable = normalTraction * m_frictionLaw.dFrictionCoefficient_dStateVariable( k, slipRateMagnitude, m_stateVariable[k] ); + real64 const dFrictionForce_dSlipRateMagnitude = normalTraction * m_frictionLaw.dFrictionCoefficient_dSlipRate( k, slipRateMagnitude, m_stateVariable[k] ); + + // Tangential component 1 + real64 const dTauFriction1_dStateVariable = dFrictionForce_dStateVariable * normalizedSlipRate[0]; + + real64 const dTauFriction1_dSlipRate1 = dFrictionForce_dSlipRateMagnitude * normalizedSlipRate[0] * normalizedSlipRate[0] + + frictionForce / slipRateMagnitude * normalizedSlipRate[1] * normalizedSlipRate[1]; + + real64 const dTauFriction1_dSlipRate2 = ( dFrictionForce_dSlipRateMagnitude + frictionForce / slipRateMagnitude ) + * ( normalizedSlipRate[0] * normalizedSlipRate[1]); + + real64 const dTauFriction1[3] = { dTauFriction1_dStateVariable, dTauFriction1_dSlipRate1, dTauFriction1_dSlipRate2 }; + + // Tangential component 2 + real64 const dTauFriction2_dStateVariable = dFrictionForce_dStateVariable * normalizedSlipRate[1]; + + real64 const dTauFriction2_dSlipRate1 = dTauFriction1_dSlipRate2; + + real64 const dTauFriction2_dSlipRate2 = dFrictionForce_dSlipRateMagnitude * normalizedSlipRate[1] * normalizedSlipRate[1] + + frictionForce / slipRateMagnitude * normalizedSlipRate[0] * normalizedSlipRate[0]; + + real64 const dTauFriction2[3] = { dTauFriction2_dStateVariable, dTauFriction2_dSlipRate1, dTauFriction2_dSlipRate2 }; + // std::cout << "force balance" << std::endl; - stack.rhs[0] = shearTraction - tauFriction - m_shearImpedance * m_slipRate[k]; + stack.rhs[0] = shearTraction[0] - tauFriction[0] - m_shearImpedance * m_slipRate[k][0]; + + stack.rhs[1] = shearTraction[1] - tauFriction[1] - m_shearImpedance * m_slipRate[k][1]; // Eq 2: slip law - real64 const dStateVariabledT = m_frictionLaw.dStateVariabledT( k, m_slipRate[k], m_stateVariable[k] ); - stack.rhs[1] = (m_stateVariable[k] - m_stateVariable_n[k]) / dt - dStateVariabledT; - real64 const dStateEvolutionLaw[2] = { 1 / dt - m_frictionLaw.dStateVariabledT_dStateVariable( k, m_slipRate[k], m_stateVariable[k] ), - -m_frictionLaw.dStateVariabledT_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) }; + stack.rhs[2] = (m_stateVariable[k] - m_stateVariable_n[k]) / dt - m_frictionLaw.stateEvolution( k, slipRateMagnitude, m_stateVariable[k] ); + real64 const dStateEvolutionLaw[3] = { 1 / dt - m_frictionLaw.dStateEvolution_dStateVariable( k, slipRateMagnitude, m_stateVariable[k] ), + -m_frictionLaw.dStateEvolution_dSlipRate( k, slipRateMagnitude, m_stateVariable[k] ) * normalizedSlipRate[0], + -m_frictionLaw.dStateEvolution_dSlipRate( k, slipRateMagnitude, m_stateVariable[k] ) * normalizedSlipRate[1]} ; + // Assemble Jacobian matrix - // derivative shear stress balance w.r.t. theta - stack.jacobian[0][0] = -dTauFriction[0]; - // derivative shear stress balance w.r.t. slip_velocity - stack.jacobian[0][1] = -dTauFriction[1] - m_shearImpedance; + // derivative shear stress balance component 1 w.r.t. theta + stack.jacobian[0][0] = -dTauFriction1[0]; + // derivative shear stress balance component 1 w.r.t. slip_velocity component 1 + stack.jacobian[0][1] = -dTauFriction1[1]- m_shearImpedance; + // derivative shear stress balance component 1 w.r.t. slip_velocity component 2 + stack.jacobian[0][2] = -dTauFriction1[2]; + // derivative shear stress balance component 2 w.r.t. theta + stack.jacobian[1][0] = -dTauFriction2[0]; + // derivative shear stress balance component 2 w.r.t. slip_velocity component 1 + stack.jacobian[1][1] = -dTauFriction2[1]; + // derivative shear stress balance component 2 w.r.t. slip_velocity component 2 + stack.jacobian[1][2] = -dTauFriction2[2] - m_shearImpedance; // derivative slip law w.r.t. theta - stack.jacobian[1][0] = dStateEvolutionLaw[0]; - // derivative slip law w.r.t. slip_velocity - stack.jacobian[1][1] = dStateEvolutionLaw[1]; - - - /// Matteo: debugging tools. - // printf("dStateVariabledT = %.10e\n", dStateVariabledT); - // printf("m_stateVariable = %.10e\n", m_stateVariable[k]); - // printf("m_stateVariable_n = %.10e\n", m_stateVariable_n[k]); - // printf("dt = %.10e\n", dt); - - // for( int i = 0; i < 2; i++ ) - // { - // printf( "rhs[%d] = %.10e\n", i, stack.rhs[i] ); - // for( int j = 0; j < 2; j++ ) - // { - // printf( "j(%d,%d) = %.10e\n", i, j, stack.jacobian[i][j] ); - // } - // } + stack.jacobian[2][0] = dStateEvolutionLaw[0]; + // derivative slip law w.r.t. slip_velocity component 1 + stack.jacobian[2][1] = dStateEvolutionLaw[1]; + // derivative slip law w.r.t. slip_velocity component 2 + stack.jacobian[2][2] = dStateEvolutionLaw[2]; } GEOS_HOST_DEVICE void solve( localIndex const k, StackVariables & stack ) const { - /// Solve 2x2 system - real64 solution[2] = {0.0, 0.0}; + /// Solve 3x3 system + real64 solution[3] = {0.0, 0.0, 0.0}; - denseLinearAlgebra::solve< 2 >( stack.jacobian, stack.rhs, solution ); + denseLinearAlgebra::solve< 3 >( stack.jacobian, stack.rhs, solution ); /// Update variables m_stateVariable[k] -= solution[0]; - m_slipRate[k] -= solution[1]; + m_slipRate[k][0] -= solution[1]; + m_slipRate[k][1] -= solution[2]; - /// Matteo: debugging tools. + // // Matteo: debugging tools. // printf("solution[0] = %.10e\n", solution[0]); // printf("solution[1] = %.10e\n", solution[1]); + // printf("solution[2] = %.10e\n", solution[2]); // printf("m_stateVariable[%d] = %.10e\n", k, m_stateVariable[k]); - // printf("m_slipRate[%d] = %.10e\n", k, m_slipRate[k]); + // printf("m_slipRate[0][%d] = %.10e\n", k, m_slipRate[k][0]); + // printf("m_slipRate[1][%d] = %.10e\n", k, m_slipRate[k][1]); } GEOS_HOST_DEVICE std::pair< int, real64 > checkConvergence( StackVariables const & stack, real64 const tol ) const { - real64 const residualNorm = LvArray::tensorOps::l2Norm< 2 >( stack.rhs ); + real64 const residualNorm = LvArray::tensorOps::l2Norm< 3 >( stack.rhs ); int const converged = residualNorm < tol ? 1 : 0; return std::make_pair( converged, residualNorm ); } private: - arrayView1d< real64 > const m_slipRate; + arrayView2d< real64 > const m_slipRate; arrayView1d< real64 > const m_stateVariable; diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp index 343f3eacc29..66d2293a7d4 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp @@ -34,7 +34,7 @@ namespace rateAndState DECLARE_FIELD( slipRate, "slipRate", - array1d< real64 >, + array2d< real64 >, 1.0e-6, LEVEL_0, WRITE_AND_READ, @@ -50,7 +50,7 @@ DECLARE_FIELD( stateVariable, DECLARE_FIELD( slipRate_n, "slipRate_n", - array1d< real64 >, + array2d< real64 >, 1.0e-6, NOPLOT, WRITE_AND_READ, @@ -66,7 +66,7 @@ DECLARE_FIELD( stateVariable_n, DECLARE_FIELD( deltaSlip, "deltaSlip", - array1d< real64 >, + array2d< real64 >, 0.0, LEVEL_0, WRITE_AND_READ, From 53497118f3f6dded6da1ff6622c04262bb1feec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Mon, 14 Oct 2024 16:39:59 -0700 Subject: [PATCH 27/53] 1D spring slider with 2-component slip/sliprate working --- inputFiles/inducedSeismicity/SpringSlider_base.xml | 10 +++++++++- .../inducedSeismicity/kernels/RateAndStateKernels.hpp | 1 - 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/inputFiles/inducedSeismicity/SpringSlider_base.xml b/inputFiles/inducedSeismicity/SpringSlider_base.xml index 49fa56d2470..633e3dc8c9c 100644 --- a/inputFiles/inducedSeismicity/SpringSlider_base.xml +++ b/inputFiles/inducedSeismicity/SpringSlider_base.xml @@ -103,13 +103,21 @@ scale="0.6" setNames="{all}"/> + diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index 4ebfd40d844..41637cfa6f4 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -72,7 +72,6 @@ class RateAndStateKernel real64 const dt, StackVariables & stack ) const { - m_slipRate[k][1] = 0.; //TODO. Remove once solution is correctly initialized. real64 const normalTraction = m_traction[k][0]; real64 const shearTraction[2] = { m_traction[k][1], m_traction[k][2]}; From 0ef3b42b57a15fb562e84b4671190a237fa5c7ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Thu, 17 Oct 2024 11:47:44 -0700 Subject: [PATCH 28/53] Fix copy of slip rate vector --- .../physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp index f5620eb0b8b..09aa4da28b8 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp @@ -238,17 +238,13 @@ void QuasiDynamicEQ::saveOldStateAndUpdateSlip( ElementSubRegionBase & subRegion forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { - slipRate_n[k][0] = slipRate[k][0]; - slipRate_n[k][0] = slipRate[k][0]; + LvArray::tensorOps::copy< 2 >(slipRate_n[k], slipRate[k]); stateVariable_n[k] = stateVariable[k]; deltaSlip[k][0] = slipRate[k][0] * dt; deltaSlip[k][1] = slipRate[k][1] * dt; // Update tangential components of the displacement jump dispJump[k][1] = dispJump[k][1] + slipRate[k][0] * dt; dispJump[k][2] = dispJump[k][2] + slipRate[k][1] * dt; - // std::cout << "slip" << slip[k] << std::endl; - // std::cout << "slipRate" << slipRate[k] << std::endl; - // std::cout << "stateVariable" << stateVariable[k] << std::endl; } ); } From 7996ae628bbfa0d52498b9e4f0c525a22d5c84c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Thu, 17 Oct 2024 11:48:25 -0700 Subject: [PATCH 29/53] wip: Add missing components to xml required for setting up 2D spring slider --- inputFiles/inducedSeismicity/SpringSlider_base.xml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/inputFiles/inducedSeismicity/SpringSlider_base.xml b/inputFiles/inducedSeismicity/SpringSlider_base.xml index 633e3dc8c9c..551c2fb42b3 100644 --- a/inputFiles/inducedSeismicity/SpringSlider_base.xml +++ b/inputFiles/inducedSeismicity/SpringSlider_base.xml @@ -88,13 +88,21 @@ setNames="{all}"/> + Date: Fri, 18 Oct 2024 10:58:56 -0700 Subject: [PATCH 30/53] Use non-linear solve for slip rate + projection to compute slip velocity --- .../inducedSeismicity/SpringSlider_base.xml | 19 ++- .../inducedSeismicity/QuasiDynamicEQ.cpp | 36 ++--- .../kernels/RateAndStateKernels.hpp | 130 ++++++------------ .../inducedSeismicity/rateAndStateFields.hpp | 10 +- 4 files changed, 76 insertions(+), 119 deletions(-) diff --git a/inputFiles/inducedSeismicity/SpringSlider_base.xml b/inputFiles/inducedSeismicity/SpringSlider_base.xml index 551c2fb42b3..ff605bcf8a8 100644 --- a/inputFiles/inducedSeismicity/SpringSlider_base.xml +++ b/inputFiles/inducedSeismicity/SpringSlider_base.xml @@ -93,7 +93,7 @@ initialCondition="1" objectPath="ElementRegions/Fault/FractureSubRegion" component="1" - scale="30" + scale="21.2132034356" setNames="{all}"/> + registerWrapper( viewKeyStruct::maxNumberOfNewtonIterationsString(), &m_maxNewtonIterations ). setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( 5 ). + setApplyDefaultValue( 10 ). setDescription( "Maximum number of Newton iterations string." ); this->registerWrapper( viewKeyStruct::shearImpedanceString(), &m_shearImpedance ). @@ -95,12 +95,14 @@ void QuasiDynamicEQ::registerDataOnMesh( Group & meshBodies ) // Scalar functions on fault subRegion.registerField< rateAndState::stateVariable >( getName() ); subRegion.registerField< rateAndState::stateVariable_n >( getName() ); + subRegion.registerField< rateAndState::slipRate >( getName() ); // Tangent (2-component) functions on fault string const labels2Comp[2] = {"tangent1", "tangent2" }; - subRegion.registerField< rateAndState::slipRate >( getName() ).setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); - subRegion.registerField< rateAndState::slipRate_n >( getName() ).setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); - subRegion.registerField< rateAndState::deltaSlip >( getName() ).setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); + subRegion.registerField< rateAndState::slipVelocity >( getName() ). + setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); + subRegion.registerField< rateAndState::deltaSlip >( getName() ). + setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); if( !subRegion.hasWrapper( contact::dispJump::key() )) { @@ -201,8 +203,8 @@ real64 QuasiDynamicEQ::updateStresses( real64 const & time_n, SurfaceElementSubRegion & subRegion ) { - arrayView2d< real64 const > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); - arrayView2d< real64 > const traction = subRegion.getField< fields::contact::traction >(); + arrayView2d< real64 const > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); + arrayView2d< real64 > const traction = subRegion.getField< fields::contact::traction >(); string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); @@ -217,8 +219,10 @@ real64 QuasiDynamicEQ::updateStresses( real64 const & time_n, frictionKernelWrapper.getDcCoefficient( k ) ); - traction[k][1] = traction[k][1] + springSliderParameters.tauRate * dt - springSliderParameters.springStiffness * deltaSlip[k][0]; - traction[k][2] = 0.0; + traction[k][1] = traction[k][1] + springSliderParameters.tauRate * dt + - springSliderParameters.springStiffness * deltaSlip[k][0]; + traction[k][2] = traction[k][2] + springSliderParameters.tauRate * dt + - springSliderParameters.springStiffness * deltaSlip[k][1]; } ); } ); } ); @@ -230,21 +234,19 @@ void QuasiDynamicEQ::saveOldStateAndUpdateSlip( ElementSubRegionBase & subRegion { arrayView1d< real64 > const stateVariable = subRegion.getField< rateAndState::stateVariable >(); arrayView1d< real64 > const stateVariable_n = subRegion.getField< rateAndState::stateVariable_n >(); - arrayView2d< real64 > const slipRate = subRegion.getField< rateAndState::slipRate >(); - arrayView2d< real64 > const slipRate_n = subRegion.getField< rateAndState::slipRate_n >(); + arrayView2d< real64 > const slipVelocity = subRegion.getField< rateAndState::slipVelocity >(); arrayView2d< real64 > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); arrayView2d< real64 > const dispJump = subRegion.getField< contact::dispJump >(); forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { - LvArray::tensorOps::copy< 2 >(slipRate_n[k], slipRate[k]); stateVariable_n[k] = stateVariable[k]; - deltaSlip[k][0] = slipRate[k][0] * dt; - deltaSlip[k][1] = slipRate[k][1] * dt; + deltaSlip[k][0] = slipVelocity[k][0] * dt; + deltaSlip[k][1] = slipVelocity[k][1] * dt; // Update tangential components of the displacement jump - dispJump[k][1] = dispJump[k][1] + slipRate[k][0] * dt; - dispJump[k][2] = dispJump[k][2] + slipRate[k][1] * dt; + dispJump[k][1] = dispJump[k][1] + slipVelocity[k][0] * dt; + dispJump[k][2] = dispJump[k][2] + slipVelocity[k][1] * dt; } ); } @@ -264,12 +266,12 @@ real64 QuasiDynamicEQ::setNextDt( real64 const & currentDt, DomainPartition & do [&]( localIndex const, SurfaceElementSubRegion const & subRegion ) { - arrayView2d< real64 const > const slipRate = subRegion.getField< rateAndState::slipRate >(); + arrayView1d< real64 const > const slipRate = subRegion.getField< rateAndState::slipRate >(); RAJA::ReduceMax< parallelDeviceReduce, real64 > maximumSlipRateOnThisRegion( 0.0 ); forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { - maximumSlipRateOnThisRegion.max( LvArray::math::sqrt( slipRate[k][0]*slipRate[k][0] + slipRate[k][1]*slipRate[k][1]) ); + maximumSlipRateOnThisRegion.max( slipRate[k] ); } ); if( maximumSlipRateOnThisRegion.get() > maxSlipRateOnThisRank ) maxSlipRateOnThisRank = maximumSlipRateOnThisRegion.get(); diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index 41637cfa6f4..6d54fa79591 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -45,6 +45,7 @@ class RateAndStateKernel m_stateVariable( subRegion.getField< fields::rateAndState::stateVariable >() ), m_stateVariable_n( subRegion.getField< fields::rateAndState::stateVariable_n >() ), m_traction( subRegion.getField< fields::contact::traction >() ), + m_slipVelocity( subRegion.getField< fields::rateAndState::slipVelocity >() ), m_shearImpedance( shearImpedance ), m_frictionLaw( frictionLaw.createKernelUpdates() ) {} @@ -61,9 +62,9 @@ class RateAndStateKernel StackVariables( ) {} - real64 jacobian[3][3]{}; + real64 jacobian[2][2]{}; - real64 rhs[3]{}; + real64 rhs[2]{}; }; @@ -73,119 +74,60 @@ class RateAndStateKernel StackVariables & stack ) const { real64 const normalTraction = m_traction[k][0]; - real64 const shearTraction[2] = { m_traction[k][1], - m_traction[k][2]}; - real64 const slipRateMagnitude = LvArray::math::sqrt(m_slipRate[k][0] * m_slipRate[k][0] + m_slipRate[k][1] * m_slipRate[k][1] ); - real64 const normalizedSlipRate[2] = { m_slipRate[k][0] / slipRateMagnitude, - m_slipRate[k][1] / slipRateMagnitude }; - // std::cout << "normalTraction: " << normalTraction << std::endl; - // std::cout << "shearTraction[0]: " << shearTraction[0] << std::endl; - // std::cout << "shearTraction[1]: " << shearTraction[1] << std::endl; - - // std::cout << "normalizedSlipRate[0]: " << normalizedSlipRate[0] << std::endl; - // std::cout << "normalizedSlipRate[1]: " << normalizedSlipRate[1] << std::endl; - - // Eq 1: shear stress balance - // Frictional shear strength - real64 const frictionForce = normalTraction * m_frictionLaw.frictionCoefficient( k, slipRateMagnitude, m_stateVariable[k] ); - real64 const tauFriction[2] = { frictionForce * normalizedSlipRate[0], - frictionForce * normalizedSlipRate[1] }; - - // Jacobian entries - real64 const dFrictionForce_dStateVariable = normalTraction * m_frictionLaw.dFrictionCoefficient_dStateVariable( k, slipRateMagnitude, m_stateVariable[k] ); - real64 const dFrictionForce_dSlipRateMagnitude = normalTraction * m_frictionLaw.dFrictionCoefficient_dSlipRate( k, slipRateMagnitude, m_stateVariable[k] ); - - // Tangential component 1 - real64 const dTauFriction1_dStateVariable = dFrictionForce_dStateVariable * normalizedSlipRate[0]; - - real64 const dTauFriction1_dSlipRate1 = dFrictionForce_dSlipRateMagnitude * normalizedSlipRate[0] * normalizedSlipRate[0] - + frictionForce / slipRateMagnitude * normalizedSlipRate[1] * normalizedSlipRate[1]; - - real64 const dTauFriction1_dSlipRate2 = ( dFrictionForce_dSlipRateMagnitude + frictionForce / slipRateMagnitude ) - * ( normalizedSlipRate[0] * normalizedSlipRate[1]); - - real64 const dTauFriction1[3] = { dTauFriction1_dStateVariable, dTauFriction1_dSlipRate1, dTauFriction1_dSlipRate2 }; - - // Tangential component 2 - real64 const dTauFriction2_dStateVariable = dFrictionForce_dStateVariable * normalizedSlipRate[1]; - - real64 const dTauFriction2_dSlipRate1 = dTauFriction1_dSlipRate2; - - real64 const dTauFriction2_dSlipRate2 = dFrictionForce_dSlipRateMagnitude * normalizedSlipRate[1] * normalizedSlipRate[1] - + frictionForce / slipRateMagnitude * normalizedSlipRate[0] * normalizedSlipRate[0]; - - real64 const dTauFriction2[3] = { dTauFriction2_dStateVariable, dTauFriction2_dSlipRate1, dTauFriction2_dSlipRate2 }; - - - // std::cout << "force balance" << std::endl; - stack.rhs[0] = shearTraction[0] - tauFriction[0] - m_shearImpedance * m_slipRate[k][0]; - - stack.rhs[1] = shearTraction[1] - tauFriction[1] - m_shearImpedance * m_slipRate[k][1]; + real64 const shearTractionMagnitude = LvArray::math::sqrt( m_traction[k][1] * m_traction[k][1] + m_traction[k][2] * m_traction[k][2] ); + // Eq 1: Scalar force balance for slipRate and shear traction magnitude + stack.rhs[0] = shearTractionMagnitude - m_shearImpedance * m_slipRate[k] + - normalTraction * m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] ); + real64 const dFriction[2] = { -normalTraction * m_frictionLaw.dFrictionCoefficient_dStateVariable( k, m_slipRate[k], m_stateVariable[k] ), + -m_shearImpedance - normalTraction * m_frictionLaw.dFrictionCoefficient_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) }; // Eq 2: slip law - stack.rhs[2] = (m_stateVariable[k] - m_stateVariable_n[k]) / dt - m_frictionLaw.stateEvolution( k, slipRateMagnitude, m_stateVariable[k] ); - real64 const dStateEvolutionLaw[3] = { 1 / dt - m_frictionLaw.dStateEvolution_dStateVariable( k, slipRateMagnitude, m_stateVariable[k] ), - -m_frictionLaw.dStateEvolution_dSlipRate( k, slipRateMagnitude, m_stateVariable[k] ) * normalizedSlipRate[0], - -m_frictionLaw.dStateEvolution_dSlipRate( k, slipRateMagnitude, m_stateVariable[k] ) * normalizedSlipRate[1]} ; - + stack.rhs[1] = (m_stateVariable[k] - m_stateVariable_n[k]) / dt - m_frictionLaw.stateEvolution( k, m_slipRate[k], m_stateVariable[k] ); + real64 const dStateEvolutionLaw[2] = { 1 / dt - m_frictionLaw.dStateEvolution_dStateVariable( k, m_slipRate[k], m_stateVariable[k] ), + -m_frictionLaw.dStateEvolution_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) } ; // Assemble Jacobian matrix - // derivative shear stress balance component 1 w.r.t. theta - stack.jacobian[0][0] = -dTauFriction1[0]; - // derivative shear stress balance component 1 w.r.t. slip_velocity component 1 - stack.jacobian[0][1] = -dTauFriction1[1]- m_shearImpedance; - // derivative shear stress balance component 1 w.r.t. slip_velocity component 2 - stack.jacobian[0][2] = -dTauFriction1[2]; - // derivative shear stress balance component 2 w.r.t. theta - stack.jacobian[1][0] = -dTauFriction2[0]; - // derivative shear stress balance component 2 w.r.t. slip_velocity component 1 - stack.jacobian[1][1] = -dTauFriction2[1]; - // derivative shear stress balance component 2 w.r.t. slip_velocity component 2 - stack.jacobian[1][2] = -dTauFriction2[2] - m_shearImpedance; - // derivative slip law w.r.t. theta - stack.jacobian[2][0] = dStateEvolutionLaw[0]; - // derivative slip law w.r.t. slip_velocity component 1 - stack.jacobian[2][1] = dStateEvolutionLaw[1]; - // derivative slip law w.r.t. slip_velocity component 2 - stack.jacobian[2][2] = dStateEvolutionLaw[2]; + stack.jacobian[0][0] = dFriction[0]; // derivative of Eq 1 w.r.t. stateVariable + stack.jacobian[0][1] = dFriction[1]; // derivative of Eq 1 w.r.t. slipRate + stack.jacobian[1][0] = dStateEvolutionLaw[0]; // derivative of Eq 2 w.r.t. stateVariable + stack.jacobian[1][1] = dStateEvolutionLaw[1]; // derivative of Eq 2 w.r.t. m_slipRate } GEOS_HOST_DEVICE void solve( localIndex const k, StackVariables & stack ) const { - /// Solve 3x3 system - real64 solution[3] = {0.0, 0.0, 0.0}; + /// Solve 2x2 system + real64 solution[2] = {0.0, 0.0}; + denseLinearAlgebra::solve< 2 >( stack.jacobian, stack.rhs, solution ); - denseLinearAlgebra::solve< 3 >( stack.jacobian, stack.rhs, solution ); - - /// Update variables - m_stateVariable[k] -= solution[0]; - m_slipRate[k][0] -= solution[1]; - m_slipRate[k][1] -= solution[2]; - - // // Matteo: debugging tools. - // printf("solution[0] = %.10e\n", solution[0]); - // printf("solution[1] = %.10e\n", solution[1]); - // printf("solution[2] = %.10e\n", solution[2]); + // Update variables + m_stateVariable[k] -= solution[0]; + m_slipRate[k] -= solution[1]; + } - // printf("m_stateVariable[%d] = %.10e\n", k, m_stateVariable[k]); - // printf("m_slipRate[0][%d] = %.10e\n", k, m_slipRate[k][0]); - // printf("m_slipRate[1][%d] = %.10e\n", k, m_slipRate[k][1]); + GEOS_HOST_DEVICE + void projectSlipRate( localIndex const k) const + { + // Project slip rate onto shear traction to get slip velocity components + real64 const frictionForce = m_traction[k][0] * m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] ); + real64 const projectionScaling = 1.0 / ( m_shearImpedance + frictionForce / m_slipRate[k] ); + m_slipVelocity[k][0] = projectionScaling * m_traction[k][1]; + m_slipVelocity[k][1] = projectionScaling * m_traction[k][2]; } GEOS_HOST_DEVICE std::pair< int, real64 > checkConvergence( StackVariables const & stack, real64 const tol ) const { - real64 const residualNorm = LvArray::tensorOps::l2Norm< 3 >( stack.rhs ); + real64 const residualNorm = LvArray::tensorOps::l2Norm< 2 >( stack.rhs ); int const converged = residualNorm < tol ? 1 : 0; return std::make_pair( converged, residualNorm ); } private: - arrayView2d< real64 > const m_slipRate; + arrayView1d< real64 > const m_slipRate; arrayView1d< real64 > const m_stateVariable; @@ -193,6 +135,8 @@ class RateAndStateKernel arrayView2d< real64 const > const m_traction; + arrayView2d< real64 > const m_slipVelocity; + real64 const m_shearImpedance; constitutive::RateAndStateFriction::KernelWrapper m_frictionLaw; @@ -251,6 +195,10 @@ createAndLaunch( SurfaceElementSubRegion & subRegion, { GEOS_ERROR( " Failed to converge" ); } + forAll< POLICY >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + kernel.projectSlipRate( k ); + } ); } } /* namespace rateAndStateKernels */ diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp index 66d2293a7d4..8031ab1c344 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp @@ -34,7 +34,7 @@ namespace rateAndState DECLARE_FIELD( slipRate, "slipRate", - array2d< real64 >, + array1d< real64 >, 1.0e-6, LEVEL_0, WRITE_AND_READ, @@ -48,13 +48,13 @@ DECLARE_FIELD( stateVariable, WRITE_AND_READ, "Rate- and state-dependent friction state variable" ); -DECLARE_FIELD( slipRate_n, - "slipRate_n", +DECLARE_FIELD( slipVelocity, + "slipVelocity", array2d< real64 >, 1.0e-6, - NOPLOT, + LEVEL_0, WRITE_AND_READ, - "Slip rate at previous time step" ); + "Slip velocity" ); DECLARE_FIELD( stateVariable_n, "stateVariable_n", From 53e1fca0c24e8ecdd5b3524455748d2fab87a697 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Mon, 21 Oct 2024 13:19:33 -0700 Subject: [PATCH 31/53] change size of spring slider. --- inputFiles/inducedSeismicity/SpringSlider_base.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inputFiles/inducedSeismicity/SpringSlider_base.xml b/inputFiles/inducedSeismicity/SpringSlider_base.xml index ff605bcf8a8..c6bcd6bff77 100644 --- a/inputFiles/inducedSeismicity/SpringSlider_base.xml +++ b/inputFiles/inducedSeismicity/SpringSlider_base.xml @@ -33,7 +33,7 @@ xCoords="{ 0, 1 }" yCoords="{ 0, 2 }" zCoords="{ 0, 1 }" - nx="{ 1 }" + nx="{ 100 }" ny="{ 2 }" nz="{ 1 }" cellBlockNames="{ cb1 }"/> From 16fdabd903e7625c10ebead633a62b3321bca1d8 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Fri, 25 Oct 2024 10:27:58 -0700 Subject: [PATCH 32/53] use nonlinearSolverParameters. --- .../contact/RateAndStateFriction.hpp | 36 +++++++++---------- .../inducedSeismicity/QuasiDynamicEQ.cpp | 16 ++++----- .../inducedSeismicity/QuasiDynamicEQ.hpp | 5 --- .../kernels/RateAndStateKernels.hpp | 10 +++--- 4 files changed, 29 insertions(+), 38 deletions(-) diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp index 267f1591173..9b9341ce1aa 100644 --- a/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp +++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.hpp @@ -98,13 +98,13 @@ class RateAndStateFriction : public FrictionBase /// Deleted move assignment operator KernelWrapper & operator=( KernelWrapper && ) = delete; - + GEOS_HOST_DEVICE real64 getACoefficient( localIndex const k ) const { return m_a[k]; } - + GEOS_HOST_DEVICE - real64 getBCoefficient( localIndex const k ) const { return m_b[k]; } - + real64 getBCoefficient( localIndex const k ) const { return m_b[k]; } + GEOS_HOST_DEVICE real64 getDcCoefficient( localIndex const k ) const { return m_Dc[k]; } @@ -132,18 +132,18 @@ class RateAndStateFriction : public FrictionBase GEOS_HOST_DEVICE inline real64 stateEvolution( localIndex const k, - real64 const slipRate, - real64 const stateVariable ) const; + real64 const slipRate, + real64 const stateVariable ) const; GEOS_HOST_DEVICE inline real64 dStateEvolution_dStateVariable( localIndex const k, - real64 const slipRate, - real64 const stateVariable ) const; + real64 const slipRate, + real64 const stateVariable ) const; GEOS_HOST_DEVICE inline real64 dStateEvolution_dSlipRate( localIndex const k, - real64 const slipRate, - real64 const stateVariable ) const; + real64 const slipRate, + real64 const stateVariable ) const; private: /// The friction coefficient arrayView1d< real64 > m_frictionCoefficient; @@ -263,7 +263,7 @@ inline real64 RateAndStateFriction::KernelWrapper::frictionCoefficient( localInd real64 const slipRate, real64 const stateVariable ) const { - + real64 const arg = ( slipRate / (2 * m_V0[k]) ) * LvArray::math::exp( stateVariable / m_a[k] ); m_frictionCoefficient[k] = m_a[k] * LvArray::math::asinh( arg ); @@ -275,7 +275,7 @@ inline real64 RateAndStateFriction::KernelWrapper::dFrictionCoefficient_dSlipRat real64 const slipRate, real64 const stateVariable ) const { - + real64 const arg = ( slipRate / (2 * m_V0[k]) ) * LvArray::math::exp( stateVariable / m_a[k] ); return ( m_a[k] * LvArray::math::exp( stateVariable / m_a[k] ) ) / (2 * m_V0[k] * LvArray::math::sqrt( 1 + arg * arg )); @@ -293,9 +293,9 @@ inline real64 RateAndStateFriction::KernelWrapper::dFrictionCoefficient_dStateVa } GEOS_HOST_DEVICE -inline real64 RateAndStateFriction::KernelWrapper::stateEvolution( localIndex const k, - real64 const slipRate, - real64 const stateVariable ) const +inline real64 RateAndStateFriction::KernelWrapper::stateEvolution( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const { real64 const mu = frictionCoefficient( k, slipRate, stateVariable ); @@ -303,9 +303,9 @@ inline real64 RateAndStateFriction::KernelWrapper::stateEvolution( localIndex c } GEOS_HOST_DEVICE -inline real64 RateAndStateFriction::KernelWrapper::dStateEvolution_dStateVariable( localIndex const k, - real64 const slipRate, - real64 const stateVariable ) const +inline real64 RateAndStateFriction::KernelWrapper::dStateEvolution_dStateVariable( localIndex const k, + real64 const slipRate, + real64 const stateVariable ) const { return -slipRate / m_Dc[k] * dFrictionCoefficient_dStateVariable( k, slipRate, stateVariable ); } diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp index b12da8908cc..3982435b14a 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp @@ -38,15 +38,9 @@ QuasiDynamicEQ::QuasiDynamicEQ( const string & name, SolverBase( name, parent ), m_stressSolver( nullptr ), m_stressSolverName( "SpringSlider" ), - m_maxNewtonIterations( 2 ), m_shearImpedance( 0.0 ), m_targetSlipIncrement( 1.0e-7 ) { - this->registerWrapper( viewKeyStruct::maxNumberOfNewtonIterationsString(), &m_maxNewtonIterations ). - setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( 10 ). - setDescription( "Maximum number of Newton iterations string." ); - this->registerWrapper( viewKeyStruct::shearImpedanceString(), &m_shearImpedance ). setInputFlag( InputFlags::REQUIRED ). setDescription( "Shear impedance." ); @@ -96,7 +90,7 @@ void QuasiDynamicEQ::registerDataOnMesh( Group & meshBodies ) subRegion.registerField< rateAndState::stateVariable >( getName() ); subRegion.registerField< rateAndState::stateVariable_n >( getName() ); subRegion.registerField< rateAndState::slipRate >( getName() ); - + // Tangent (2-component) functions on fault string const labels2Comp[2] = {"tangent1", "tangent2" }; subRegion.registerField< rateAndState::slipVelocity >( getName() ). @@ -155,6 +149,8 @@ real64 QuasiDynamicEQ::solverStep( real64 const & time_n, /// 2. Solve for slip rate and state variable and, compute slip GEOS_LOG_LEVEL_RANK_0( 1, "Rate and State solver" ); + + integer const maxNewtonIter = m_nonlinearSolverParameters.m_maxIterNewton; forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, arrayView1d< string const > const & regionNames ) @@ -165,7 +161,7 @@ real64 QuasiDynamicEQ::solverStep( real64 const & time_n, SurfaceElementSubRegion & subRegion ) { // solve rate and state equations. - rateAndStateKernels::createAndLaunch< parallelDevicePolicy<> >( subRegion, viewKeyStruct::frictionLawNameString(), m_shearImpedance, m_maxNewtonIterations, time_n, dtStress ); + rateAndStateKernels::createAndLaunch< parallelDevicePolicy<> >( subRegion, viewKeyStruct::frictionLawNameString(), m_shearImpedance, maxNewtonIter, time_n, dtStress ); // save old state saveOldStateAndUpdateSlip( subRegion, dt ); } ); @@ -220,9 +216,9 @@ real64 QuasiDynamicEQ::updateStresses( real64 const & time_n, traction[k][1] = traction[k][1] + springSliderParameters.tauRate * dt - - springSliderParameters.springStiffness * deltaSlip[k][0]; + - springSliderParameters.springStiffness * deltaSlip[k][0]; traction[k][2] = traction[k][2] + springSliderParameters.tauRate * dt - - springSliderParameters.springStiffness * deltaSlip[k][1]; + - springSliderParameters.springStiffness * deltaSlip[k][1]; } ); } ); } ); diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp index 227ad36088f..cc687c341a5 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp @@ -52,8 +52,6 @@ class QuasiDynamicEQ : public SolverBase constexpr static char const * frictionLawNameString() { return "frictionLawName"; } /// Friction law name string constexpr static char const * shearImpedanceString() { return "shearImpedance"; } - /// max number of Newton iterations string - constexpr static char const * maxNumberOfNewtonIterationsString() { return "maxNumberOfNewtonIterations"; } /// target slip increment constexpr static char const * targetSlipIncrementString() { return "targetSlipIncrement"; } }; @@ -87,9 +85,6 @@ class QuasiDynamicEQ : public SolverBase /// stress solver name string m_stressSolverName; - /// max number of newton iterations for rate and state solver - integer m_maxNewtonIterations; - /// shear impedance real64 m_shearImpedance; diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index 6d54fa79591..4d2db044491 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -77,14 +77,14 @@ class RateAndStateKernel real64 const shearTractionMagnitude = LvArray::math::sqrt( m_traction[k][1] * m_traction[k][1] + m_traction[k][2] * m_traction[k][2] ); // Eq 1: Scalar force balance for slipRate and shear traction magnitude stack.rhs[0] = shearTractionMagnitude - m_shearImpedance * m_slipRate[k] - - normalTraction * m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] ); + - normalTraction * m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] ); real64 const dFriction[2] = { -normalTraction * m_frictionLaw.dFrictionCoefficient_dStateVariable( k, m_slipRate[k], m_stateVariable[k] ), -m_shearImpedance - normalTraction * m_frictionLaw.dFrictionCoefficient_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) }; // Eq 2: slip law stack.rhs[1] = (m_stateVariable[k] - m_stateVariable_n[k]) / dt - m_frictionLaw.stateEvolution( k, m_slipRate[k], m_stateVariable[k] ); real64 const dStateEvolutionLaw[2] = { 1 / dt - m_frictionLaw.dStateEvolution_dStateVariable( k, m_slipRate[k], m_stateVariable[k] ), - -m_frictionLaw.dStateEvolution_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) } ; + -m_frictionLaw.dStateEvolution_dSlipRate( k, m_slipRate[k], m_stateVariable[k] ) }; // Assemble Jacobian matrix stack.jacobian[0][0] = dFriction[0]; // derivative of Eq 1 w.r.t. stateVariable @@ -107,7 +107,7 @@ class RateAndStateKernel } GEOS_HOST_DEVICE - void projectSlipRate( localIndex const k) const + void projectSlipRate( localIndex const k ) const { // Project slip rate onto shear traction to get slip velocity components real64 const frictionForce = m_traction[k][0] * m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] ); @@ -196,8 +196,8 @@ createAndLaunch( SurfaceElementSubRegion & subRegion, GEOS_ERROR( " Failed to converge" ); } forAll< POLICY >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) - { - kernel.projectSlipRate( k ); + { + kernel.projectSlipRate( k ); } ); } From e98519d18c86ccce4dce9b2583c114378ce2e40c Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Fri, 25 Oct 2024 14:11:07 -0700 Subject: [PATCH 33/53] fix timestepping. --- .../physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp index 3982435b14a..ee8e8f3f94b 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp @@ -163,12 +163,10 @@ real64 QuasiDynamicEQ::solverStep( real64 const & time_n, // solve rate and state equations. rateAndStateKernels::createAndLaunch< parallelDevicePolicy<> >( subRegion, viewKeyStruct::frictionLawNameString(), m_shearImpedance, maxNewtonIter, time_n, dtStress ); // save old state - saveOldStateAndUpdateSlip( subRegion, dt ); + saveOldStateAndUpdateSlip( subRegion, dtStress ); } ); } ); - // m_nextDt = setNextDt( dtStress, domain ); - // return time step size achieved by stress solver return dtStress; } From ae028752eabd2330193207ed344ce1f3cd85ff39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Sun, 17 Nov 2024 15:09:12 -0800 Subject: [PATCH 34/53] Add rate-and-state kernel for explicit time stepping and quasi-dynamic solver using Runge-Kutta 3(2) --- .../inducedSeismicity/SpringSlider_base.xml | 16 +- .../physicsSolvers/contact/ContactFields.hpp | 16 + .../inducedSeismicity/CMakeLists.txt | 4 +- .../inducedSeismicity/QuasiDynamicEQ.cpp | 7 +- .../inducedSeismicity/QuasiDynamicEQRK32.cpp | 534 ++++++++++++++++++ .../inducedSeismicity/QuasiDynamicEQRK32.hpp | 142 +++++ .../kernels/RateAndStateKernels.hpp | 143 ++++- .../inducedSeismicity/rateAndStateFields.hpp | 75 ++- 8 files changed, 902 insertions(+), 35 deletions(-) create mode 100644 src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp create mode 100644 src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp diff --git a/inputFiles/inducedSeismicity/SpringSlider_base.xml b/inputFiles/inducedSeismicity/SpringSlider_base.xml index c6bcd6bff77..268b588b23b 100644 --- a/inputFiles/inducedSeismicity/SpringSlider_base.xml +++ b/inputFiles/inducedSeismicity/SpringSlider_base.xml @@ -1,15 +1,17 @@ - - - + + @@ -123,7 +125,7 @@ initialCondition="1" objectPath="ElementRegions/Fault/FractureSubRegion" component="0" - scale="0." + scale="0.70710678118e-6" setNames="{all}"/> diff --git a/src/coreComponents/physicsSolvers/contact/ContactFields.hpp b/src/coreComponents/physicsSolvers/contact/ContactFields.hpp index 4792ca2d019..c155e9cddad 100644 --- a/src/coreComponents/physicsSolvers/contact/ContactFields.hpp +++ b/src/coreComponents/physicsSolvers/contact/ContactFields.hpp @@ -74,6 +74,14 @@ DECLARE_FIELD( dispJump, WRITE_AND_READ, "Displacement jump vector in the local reference system" ); +DECLARE_FIELD( dispJump_n, + "displacementJump", + array2d< real64 >, + 0, + NOPLOT, + WRITE_AND_READ, + "Displacement jump vector in the local reference system at the current time-step" ); + DECLARE_FIELD( slip, "slip", array1d< real64 >, @@ -106,6 +114,14 @@ DECLARE_FIELD( traction, WRITE_AND_READ, "Fracture traction vector in the local reference system." ); +DECLARE_FIELD( traction_n, + "traction_n", + array2d< real64 >, + 0, + NOPLOT, + WRITE_AND_READ, + "Fracture traction vector in the local reference system at the current time-step." ); + DECLARE_FIELD( deltaTraction, "deltaTraction", array2d< real64 >, diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/CMakeLists.txt b/src/coreComponents/physicsSolvers/inducedSeismicity/CMakeLists.txt index 7edf040454d..c8f23c55323 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/CMakeLists.txt +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/CMakeLists.txt @@ -4,6 +4,7 @@ set( physicsSolvers_headers inducedSeismicity/inducedSeismicityFields.hpp inducedSeismicity/rateAndStateFields.hpp inducedSeismicity/QuasiDynamicEQ.hpp + inducedSeismicity/QuasiDynamicEQRK32.hpp inducedSeismicity/SeismicityRate.hpp inducedSeismicity/kernels/RateAndStateKernels.hpp inducedSeismicity/kernels/SeismicityRateKernels.hpp @@ -12,6 +13,7 @@ set( physicsSolvers_headers # Specify solver sources set( physicsSolvers_sources ${physicsSolvers_sources} - inducedSeismicity/QuasiDynamicEQ.cpp + inducedSeismicity/QuasiDynamicEQ.cpp + inducedSeismicity/QuasiDynamicEQRK32.cpp inducedSeismicity/SeismicityRate.cpp PARENT_SCOPE ) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp index ee8e8f3f94b..088504ab795 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp @@ -32,6 +32,7 @@ namespace geos using namespace dataRepository; using namespace fields; using namespace constitutive; +using namespace rateAndStateKernels; QuasiDynamicEQ::QuasiDynamicEQ( const string & name, Group * const parent ): @@ -149,8 +150,8 @@ real64 QuasiDynamicEQ::solverStep( real64 const & time_n, /// 2. Solve for slip rate and state variable and, compute slip GEOS_LOG_LEVEL_RANK_0( 1, "Rate and State solver" ); - - integer const maxNewtonIter = m_nonlinearSolverParameters.m_maxIterNewton; + integer const maxIterNewton = m_nonlinearSolverParameters.m_maxIterNewton; + real64 const newtonTol = m_nonlinearSolverParameters.m_newtonTol; forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, arrayView1d< string const > const & regionNames ) @@ -161,7 +162,7 @@ real64 QuasiDynamicEQ::solverStep( real64 const & time_n, SurfaceElementSubRegion & subRegion ) { // solve rate and state equations. - rateAndStateKernels::createAndLaunch< parallelDevicePolicy<> >( subRegion, viewKeyStruct::frictionLawNameString(), m_shearImpedance, maxNewtonIter, time_n, dtStress ); + createAndLaunch >( subRegion, viewKeyStruct::frictionLawNameString(), m_shearImpedance, maxIterNewton, newtonTol, time_n, dtStress ); // save old state saveOldStateAndUpdateSlip( subRegion, dtStress ); } ); diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp new file mode 100644 index 00000000000..2a0b715212a --- /dev/null +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp @@ -0,0 +1,534 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file QuasiDynamicEQRK32.cpp + */ + +#include "QuasiDynamicEQRK32.hpp" + +#include "dataRepository/InputFlags.hpp" +#include "mesh/DomainPartition.hpp" +#include "kernels/RateAndStateKernels.hpp" +#include "rateAndStateFields.hpp" +#include "physicsSolvers/contact/ContactFields.hpp" +#include "fieldSpecification/FieldSpecificationManager.hpp" + +namespace geos +{ + +using namespace dataRepository; +using namespace fields; +using namespace constitutive; +using namespace rateAndStateKernels; + +QuasiDynamicEQRK32::QuasiDynamicEQRK32( const string & name, + Group * const parent ): + SolverBase( name, parent ), + m_stressSolver( nullptr ), + m_stressSolverName( "SpringSlider" ), + m_shearImpedance( 0.0 ), + m_timeStepTol( 5.0e-4 ), + m_timeStepError( 0.0 ) +{ + this->registerWrapper( viewKeyStruct::shearImpedanceString(), &m_shearImpedance ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Shear impedance." ); + + this->registerWrapper( viewKeyStruct::stressSolverNameString(), &m_stressSolverName ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Name of solver for computing stress. If empty, the spring-slider model is run." ); + + this->registerWrapper( viewKeyStruct::timeStepTol(), &m_timeStepTol ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( 5e-4 ). + setDescription( "Target slip incrmeent for timestep size selction" ); +} + +void QuasiDynamicEQRK32::postInputInitialization() +{ + + // Initialize member stress solver as specified in XML input + if( !m_stressSolverName.empty() ) + { + m_stressSolver = &this->getParent().getGroup< SolverBase >( m_stressSolverName ); + } + + SolverBase::postInputInitialization(); +} + +QuasiDynamicEQRK32::~QuasiDynamicEQRK32() +{ + // TODO Auto-generated destructor stub +} + + +// TODO The vectors listed below are only temporary memory buffers used within an adaptive +// time step in the solverStep function. They don't need to persist between time steps, +// and could be allocated in the beginning of each call to solverStep, instead of +// being managed by the region manager. This would of course result in more heap allocations. +// Not sure what is preferable. +// +// slipVelocity_n +// traction_n +// deltaSlip_n +// dDeltaSlipStage1 +// dDeltaSlipStage2 +// dDeltaSlipStage2 +// stateVariable_n +// dStateVariableStage1 +// dStateVariableStage2 +void QuasiDynamicEQRK32::registerDataOnMesh( Group & meshBodies ) +{ + SolverBase::registerDataOnMesh( meshBodies ); + + forDiscretizationOnMeshTargets( meshBodies, [&] ( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + ElementRegionManager & elemManager = mesh.getElemManager(); + + elemManager.forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) + { + // Scalar functions on fault + subRegion.registerField< rateAndState::stateVariable >( getName() ); + subRegion.registerField< rateAndState::stateVariable_n >( getName() ); + subRegion.registerField< rateAndState::dStateVariableStage1 >( getName() ); + subRegion.registerField< rateAndState::dStateVariableStage2 >( getName() ); + subRegion.registerField< rateAndState::slipRate >( getName() ); + subRegion.registerField< rateAndState::error >( getName() ); + + // Tangent (2-component) functions on fault + string const labels2Comp[2] = {"tangent1", "tangent2" }; + subRegion.registerField< rateAndState::slipVelocity >( getName() ). + setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); + subRegion.registerField< rateAndState::slipVelocity_n >( getName() ). + setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); + subRegion.registerField< rateAndState::deltaSlip >( getName() ). + setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); + subRegion.registerField< rateAndState::deltaSlip_n >( getName() ). + setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); + subRegion.registerField< rateAndState::dDeltaSlipStage1 >( getName() ). + setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); + subRegion.registerField< rateAndState::dDeltaSlipStage2 >( getName() ). + setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); + + if( !subRegion.hasWrapper( contact::dispJump::key() )) + { + // 3-component functions on fault + string const labels3Comp[3] = { "normal", "tangent1", "tangent2" }; + subRegion.registerField< contact::dispJump >( getName() ). + setDimLabels( 1, labels3Comp ). + reference().resizeDimension< 1 >( 3 ); + subRegion.registerField< contact::dispJump_n >( getName() ). + setDimLabels( 1, labels3Comp ). + reference().resizeDimension< 1 >( 3 ); + subRegion.registerField< contact::traction >( getName() ). + setDimLabels( 1, labels3Comp ). + reference().resizeDimension< 1 >( 3 ); + subRegion.registerField< contact::traction_n >( getName() ). + setDimLabels( 1, labels3Comp ). + reference().resizeDimension< 1 >( 3 ); + + subRegion.registerWrapper< string >( viewKeyStruct::frictionLawNameString() ). + setPlotLevel( PlotLevel::NOPLOT ). + setRestartFlags( RestartFlags::NO_WRITE ). + setSizedFromParent( 0 ); + + string & frictionLawName = subRegion.getReference< string >( viewKeyStruct::frictionLawNameString() ); + frictionLawName = SolverBase::getConstitutiveName< FrictionBase >( subRegion ); + GEOS_ERROR_IF( frictionLawName.empty(), GEOS_FMT( "{}: FrictionBase model not found on subregion {}", + getDataContext(), subRegion.getDataContext() ) ); + } + } ); + } ); +} + +real64 QuasiDynamicEQRK32::solverStep( real64 const & time_n, + real64 const & dt, + int const cycleNumber, + DomainPartition & domain ) +{ + if( cycleNumber == 0 ) + { + /// Apply initial conditions to the Fault + FieldSpecificationManager & fieldSpecificationManager = FieldSpecificationManager::getInstance(); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & ) + + { + fieldSpecificationManager.applyInitialConditions( mesh ); + + } ); + saveState(domain); + } + + real64 dtAdaptive = dt; + + GEOS_LOG_LEVEL_RANK_0( 1, "Begin adaptive time step" ); + while (true) // Adaptive time step loop. Performs a Runge-Kutta time stepping with error control on state and slip + { + + // First Runge-Kutta stage + + // Evolve deltaSlip, dispJump and stateVariable to t + 0.5*dtAdaptive + // Store the first stage rates for deltaSlip and stateVariable + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + + { + mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) + { + + string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); + RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); + RateAndStateFriction::KernelWrapper frictionKernelWrapper = frictionLaw.createKernelUpdates(); + + // Fields read for this stage + arrayView2d< real64 const > const slipVelocity_n = subRegion.getField< rateAndState::slipVelocity >(); + arrayView1d< real64 const > const stateVariable_n = subRegion.getField< rateAndState::stateVariable_n >(); + arrayView2d< real64 const > const deltaSlip_n = subRegion.getField< rateAndState::deltaSlip_n >(); + arrayView2d< real64 const > const dispJump_n = subRegion.getField< contact::dispJump_n >(); + // Fields written for this stage + arrayView1d< real64 > const stateVariable = subRegion.getField< rateAndState::stateVariable >(); + arrayView1d< real64 > const slipRate = subRegion.getField< rateAndState::slipRate >(); + arrayView2d< real64 > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); + arrayView1d< real64 > const dStateVariableStage1 = subRegion.getField< rateAndState::dStateVariableStage1 >(); + arrayView2d< real64 > const dDeltaSlipStage1 = subRegion.getField< rateAndState::dDeltaSlipStage1 >(); + arrayView2d< real64 > const dispJump = subRegion.getField< contact::dispJump >(); + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + slipRate[k] = LvArray::math::sqrt(slipVelocity_n[k][0] * slipVelocity_n[k][0] + slipVelocity_n[k][1]*slipVelocity_n[k][1]); + // Runge-Kutta stage rates for stage 1 + dStateVariableStage1[k] = frictionKernelWrapper.stateEvolution(k, slipRate[k], stateVariable_n[k]); + LvArray::tensorOps::copy< 2 >( dDeltaSlipStage1[k], slipVelocity_n[k] ); + // Runge-Kutta stage values for stage 1 + stateVariable[k] = stateVariable_n[k] + 0.5*dtAdaptive*dStateVariableStage1[k]; + deltaSlip[k][0] = deltaSlip_n[k][0] + 0.5*dtAdaptive*dDeltaSlipStage1[k][0]; + deltaSlip[k][1] = deltaSlip_n[k][1] + 0.5*dtAdaptive*dDeltaSlipStage1[k][1]; + // Set tangential components of the displacement jump for stress solver and state variable for non-linear solve + dispJump[k][1] = dispJump_n[k][1] + deltaSlip[k][0]; + dispJump[k][2] = dispJump_n[k][2] + deltaSlip[k][1]; + } ); + } ); + } ); + + // Update stresses using the updated value of deltaSlip/dispJump at t + 0.5*dtAdapt + real64 dtStress = updateStresses( time_n, 0.5*dtAdaptive, cycleNumber, domain ); + GEOS_UNUSED_VAR( dtStress ); + + // Update slipRate/slipVelocity using tractions, and stateVariable at t + 0.5*dtAdapt + updateSlipVelocity( time_n, 0.5*dt, domain ); + + + // Second Runge-Kutta stage + + // Evolve deltaSlip, dispJump and stateVariable to t + dtAdaptive + // Store the second stage rates for deltaSlip and stateVariable + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + + { + mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) + { + + string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); + RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); + RateAndStateFriction::KernelWrapper frictionKernelWrapper = frictionLaw.createKernelUpdates(); + + // Fields read for this stage + arrayView1d< real64 const > const stateVariable_n = subRegion.getField< rateAndState::stateVariable_n >(); + arrayView2d< real64 const > const deltaSlip_n = subRegion.getField< rateAndState::deltaSlip_n >(); + arrayView2d< real64 const > const dispJump_n = subRegion.getField< contact::dispJump_n >(); + arrayView1d< real64 const > const slipRate = subRegion.getField< rateAndState::slipRate >(); + arrayView2d< real64 const > const slipVelocity = subRegion.getField< rateAndState::slipVelocity >(); + arrayView1d< real64 const > const dStateVariableStage1 = subRegion.getField< rateAndState::dStateVariableStage1 >(); + arrayView2d< real64 const > const dDeltaSlipStage1 = subRegion.getField< rateAndState::dDeltaSlipStage1 >(); + + // Fields written for this stage + arrayView1d< real64 > const stateVariable = subRegion.getField< rateAndState::stateVariable >(); + arrayView2d< real64 > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); + arrayView1d< real64 > const dStateVariableStage2 = subRegion.getField< rateAndState::dStateVariableStage2 >(); + arrayView2d< real64 > const dDeltaSlipStage2 = subRegion.getField< rateAndState::dDeltaSlipStage2 >(); + arrayView2d< real64 > const dispJump = subRegion.getField< contact::dispJump >(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + // Runge-Kutta stage rates for stage 2 + dStateVariableStage2[k] = frictionKernelWrapper.stateEvolution(k, slipRate[k], stateVariable[k]); + LvArray::tensorOps::copy< 2 >( dDeltaSlipStage2[k], slipVelocity[k] ); + + // Runge-Kutta stage values for stage 2 + stateVariable[k] = stateVariable_n[k] + dtAdaptive*( -dStateVariableStage1[k] + 2*dStateVariableStage2[k] ); + deltaSlip[k][0] = deltaSlip_n[k][0] + dtAdaptive*( -dDeltaSlipStage1[k][0] + 2*dDeltaSlipStage2[k][0] ); + deltaSlip[k][1] = deltaSlip_n[k][1] + dtAdaptive*( -dDeltaSlipStage1[k][1] + 2*dDeltaSlipStage2[k][1] ); + // Set tangential components of the displacement jump for stress solver and state variable for non-linear solve + dispJump[k][1] = dispJump_n[k][1] + deltaSlip[k][0]; + dispJump[k][2] = dispJump_n[k][2] + deltaSlip[k][1]; + } ); + } ); + } ); + + // Update stresses using the updated value of deltaSlip/dispJump at dtAdapt + dtStress = updateStresses( time_n, dtAdaptive, cycleNumber, domain ); + + // Update slipRate/slipVelocity using tractions, and stateVariable at t + 0.5*dtAdapt + updateSlipVelocity( time_n, dtAdaptive, domain ); + + // Third Runge-Kutta stage + + // Perform third and second order update of deltaSlip and stateVariable, and compute + // error + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + + { + mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) + { + + string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); + RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); + RateAndStateFriction::KernelWrapper frictionKernelWrapper = frictionLaw.createKernelUpdates(); + + // Fields read for this stage + arrayView1d< real64 const > const stateVariable_n = subRegion.getField< rateAndState::stateVariable_n >(); + arrayView2d< real64 const > const deltaSlip_n = subRegion.getField< rateAndState::deltaSlip_n >(); + arrayView1d< real64 const > const slipRate = subRegion.getField< rateAndState::slipRate >(); + arrayView2d< real64 const > const slipVelocity = subRegion.getField< rateAndState::slipVelocity >(); + arrayView2d< real64 const > const dispJump_n = subRegion.getField< contact::dispJump_n >(); + arrayView1d< real64 const > const dStateVariableStage1 = subRegion.getField< rateAndState::dStateVariableStage1 >(); + arrayView1d< real64 const > const dStateVariableStage2 = subRegion.getField< rateAndState::dStateVariableStage2 >(); + arrayView2d< real64 const > const dDeltaSlipStage1 = subRegion.getField< rateAndState::dDeltaSlipStage1 >(); + arrayView2d< real64 const > const dDeltaSlipStage2 = subRegion.getField< rateAndState::dDeltaSlipStage2 >(); + + // Fields written for this stage + arrayView1d< real64 > const stateVariable = subRegion.getField< rateAndState::stateVariable >(); + arrayView2d< real64 > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); + arrayView2d< real64 > const dispJump = subRegion.getField< contact::dispJump >(); + arrayView1d< real64 > const rateStateError = subRegion.getField< rateAndState::error >(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + // Runge-Kutta stage rates for stage 3 + real64 const dStateVariableStage3 = frictionKernelWrapper.stateEvolution(k, slipRate[k], stateVariable[k]); + real64 const dDeltaSlipStage3[2] = {slipVelocity[k][0], slipVelocity[k][1]}; + + // Third order update + stateVariable[k] = stateVariable_n[k] + dtAdaptive/6*( dStateVariableStage1[k] + 4*dStateVariableStage2[k] + dStateVariableStage3 ); + deltaSlip[k][0] = deltaSlip_n[k][0] + dtAdaptive/6*( dDeltaSlipStage1[k][0] + 4*dDeltaSlipStage2[k][0] + dDeltaSlipStage3[0] ); + deltaSlip[k][1] = deltaSlip_n[k][1] + dtAdaptive/6*( dDeltaSlipStage1[k][1] + 4*dDeltaSlipStage2[k][1] + dDeltaSlipStage3[1] ); + + dispJump[k][1] = dispJump_n[k][1] + deltaSlip[k][0]; + dispJump[k][2] = dispJump_n[k][2] + deltaSlip[k][1]; + + // Second order updates used for adaptive error comparison + real64 const stateVariableRK2 = stateVariable_n[k] + dtAdaptive/2*(dStateVariableStage1[k] + dStateVariableStage3); + real64 const deltaSlipRK2[2] = { deltaSlip_n[k][0] + dtAdaptive/2*( dDeltaSlipStage1[k][1] + dDeltaSlipStage3[0] ), + deltaSlip_n[k][1] + dtAdaptive/2*( dDeltaSlipStage1[k][1] + dDeltaSlipStage3[1] ) }; + + // Compute relative errors based on the maximum error in state or slip + // TODO: Avoid division by zero in error comparison + // by adding small number to denominator. Better way to to this? + real64 const errorStateVariable = LvArray::math::abs(stateVariable[k] - stateVariableRK2)/(stateVariable[k] + 1e-13); + real64 const errorSlip[2] = { (deltaSlip[k][0] - deltaSlipRK2[0])/(deltaSlip[k][0] + 1e-13), + (deltaSlip[k][1] - deltaSlipRK2[1])/(deltaSlip[k][0] + 1e-13) }; + real64 const errorDeltaSlip = LvArray::math::sqrt(errorSlip[0]*errorSlip[0] + errorSlip[1]*errorSlip[1]); + // Take maximum of slip and state error + rateStateError[k] = (errorStateVariable > errorDeltaSlip) ? errorStateVariable : errorDeltaSlip; + } ); + } ); + } ); + // Update timestep based on the time step error + dtAdaptive = setNextDt(dtAdaptive, domain); + if (m_timeStepError <= m_timeStepTol) // m_timeStepError updated in setNextDt + { + // Successful step. Compute stresses, and slip velocity and save results, then exit the adaptive time step loop + dtStress = updateStresses( time_n, dt, cycleNumber, domain ); + updateSlipVelocity( time_n, dt, domain ); + saveState(domain); + GEOS_LOG_LEVEL_RANK_0( 1, "Adaptive time step successful" ); + break; + } + else // Unsuccessful step. Retry with the updated time step + { + GEOS_LOG_LEVEL_RANK_0( 1, "Adaptive time step failed" ); + } + } + + // return time step size achieved by stress solver + return dtAdaptive; +} + +real64 QuasiDynamicEQRK32::updateStresses( real64 const & time_n, + real64 const & dt, + const int cycleNumber, + DomainPartition & domain ) const +{ + GEOS_LOG_LEVEL_RANK_0( 1, "Stress solver" ); + // Call member variable stress solver to update the stress state + if( m_stressSolver ) + { + // 1. Solve the momentum balance + real64 const dtStress = m_stressSolver->solverStep( time_n, dt, cycleNumber, domain ); + + return dtStress; + } + else + { + // Spring-slider shear traction computation + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + + { + mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) + { + + arrayView2d< real64 const > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); + arrayView2d< real64 > const traction = subRegion.getField< fields::contact::traction >(); + arrayView2d< real64 const > const traction_n = subRegion.getField< fields::contact::traction_n >(); + + string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); + RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); + + RateAndStateFriction::KernelWrapper frictionKernelWrapper = frictionLaw.createKernelUpdates(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + SpringSliderParameters springSliderParameters = SpringSliderParameters( traction[k][0], + frictionKernelWrapper.getACoefficient( k ), + frictionKernelWrapper.getBCoefficient( k ), + frictionKernelWrapper.getDcCoefficient( k ) ); + + + traction[k][1] = traction_n[k][1] + springSliderParameters.tauRate * dt + - springSliderParameters.springStiffness * deltaSlip[k][0]; + traction[k][2] = traction_n[k][2] + springSliderParameters.tauRate * dt + - springSliderParameters.springStiffness * deltaSlip[k][1]; + } ); + } ); + } ); + return dt; + } +} + +void QuasiDynamicEQRK32::updateSlipVelocity( real64 const & time_n, + real64 const & dt, + DomainPartition & domain ) const +{ + GEOS_LOG_LEVEL_RANK_0( 1, "Rate and State solver" ); + integer const maxIterNewton = m_nonlinearSolverParameters.m_maxIterNewton; + real64 const newtonTol = m_nonlinearSolverParameters.m_newtonTol; + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + + { + mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) + { + // solve rate and state equations. + rateAndStateKernels::createAndLaunch >( subRegion, viewKeyStruct::frictionLawNameString(), m_shearImpedance, maxIterNewton, newtonTol, time_n, dt ); + } ); + } ); +} + +void QuasiDynamicEQRK32::saveState( DomainPartition & domain) const +{ + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + + { + mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) + { + arrayView1d< real64 const > const stateVariable = subRegion.getField< rateAndState::stateVariable >(); + arrayView2d< real64 const > const slipVelocity = subRegion.getField< rateAndState::slipVelocity >(); + arrayView2d< real64 const > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); + arrayView2d< real64 const > const dispJump = subRegion.getField< contact::dispJump >(); + arrayView2d< real64 const > const traction = subRegion.getField< contact::traction >(); + + arrayView1d< real64 > const stateVariable_n = subRegion.getField< rateAndState::stateVariable_n >(); + arrayView2d< real64 > const slipVelocity_n = subRegion.getField< rateAndState::slipVelocity_n >(); + arrayView2d< real64 > const deltaSlip_n = subRegion.getField< rateAndState::deltaSlip >(); + arrayView2d< real64 > const dispJump_n = subRegion.getField< contact::dispJump_n >(); + arrayView2d< real64 > const traction_n = subRegion.getField< contact::traction_n >(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + stateVariable_n[k] = stateVariable[k]; + LvArray::tensorOps::copy< 2 >( deltaSlip_n[k], deltaSlip[k] ); + LvArray::tensorOps::copy< 2 >( slipVelocity_n[k], slipVelocity[k] ); + LvArray::tensorOps::copy< 3 >( dispJump_n[k], dispJump[k] ); + LvArray::tensorOps::copy< 3 >( traction_n[k], traction[k] ); + } ); + } ); + } ); +} + +real64 QuasiDynamicEQRK32::setNextDt( real64 const & currentDt, DomainPartition & domain ) +{ + + // Spring-slider shear traction computation + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel const & mesh, + arrayView1d< string const > const & regionNames ) + + { + real64 maxErrorOnThisRank = 0.0; + mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion const & subRegion ) + { + arrayView1d< real64 const > const error = subRegion.getField< rateAndState::error >(); + + RAJA::ReduceMax< parallelDeviceReduce, real64 > maxErrorOnThisRegion( 0.0 ); + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + maxErrorOnThisRegion.max( error[k] ); + } ); + if( maxErrorOnThisRegion.get() > maxErrorOnThisRank ) + maxErrorOnThisRank = maxErrorOnThisRegion.get(); + } ); + m_timeStepError = MpiWrapper::max( maxErrorOnThisRank ); + } ); + real64 const nextDt = 0.9 * currentDt * pow( m_timeStepTol/m_timeStepError, 1.0 / 3.0 ); + + GEOS_LOG_LEVEL_RANK_0( 1, GEOS_FMT( "The next dt will be {:.2e} s", nextDt )); + + return nextDt; +} + +REGISTER_CATALOG_ENTRY( SolverBase, QuasiDynamicEQRK32, string const &, dataRepository::Group * const ) + +} // namespace geos diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp new file mode 100644 index 00000000000..fa078415f2a --- /dev/null +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp @@ -0,0 +1,142 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +#ifndef GEOS_PHYSICSSOLVERS_INDUCED_QUASIDYNAMICEQRK32_HPP +#define GEOS_PHYSICSSOLVERS_INDUCED_QUASIDYNAMICEQRK32_HPP + +#include "physicsSolvers/SolverBase.hpp" + +namespace geos +{ + +class QuasiDynamicEQRK32 : public SolverBase +{ +public: + /// The default nullary constructor is disabled to avoid compiler auto-generation: + QuasiDynamicEQRK32() = delete; + + /// The constructor needs a user-defined "name" and a parent Group (to place this instance in the tree structure of classes) + QuasiDynamicEQRK32( const string & name, + Group * const parent ); + + /// Destructor + virtual ~QuasiDynamicEQRK32() override; + + static string catalogName() { return "QuasiDynamicEQRK32"; } + + /** + * @return Get the final class Catalog name + */ + virtual string getCatalogName() const override { return catalogName(); } + + /// This method ties properties with their supporting mesh + virtual void registerDataOnMesh( Group & meshBodies ) override; + + struct viewKeyStruct : public SolverBase::viewKeyStruct + { + /// stress solver name + static constexpr char const * stressSolverNameString() { return "stressSolverName"; } + /// Friction law name string + constexpr static char const * frictionLawNameString() { return "frictionLawName"; } + /// Friction law name string + constexpr static char const * shearImpedanceString() { return "shearImpedance"; } + /// target slip increment + constexpr static char const * timeStepTol() { return "timeStepTol"; } + }; + + virtual real64 solverStep( real64 const & time_n, + real64 const & dt, + integer const cycleNumber, + DomainPartition & domain ) override final; + +private: + + virtual real64 setNextDt( real64 const & currentDt, + DomainPartition & domain ) override final; + + virtual void postInputInitialization() override; + + real64 updateStresses( real64 const & time_n, + real64 const & dt, + const int cycleNumber, + DomainPartition & domain ) const; + + /** + * @brief updates rate-and-state slip velocity and slip rate + * @param domain + */ + void updateSlipVelocity( real64 const & time_n, + real64 const & dt, + DomainPartition & domain ) const; + + /** + * @brief save the current state + * @param domain + */ + void saveState( DomainPartition & domain) const; + + + /// pointer to stress solver + SolverBase * m_stressSolver; + + /// stress solver name + string m_stressSolverName; + + /// shear impedance + real64 m_shearImpedance; + + /// time step tolerance + real64 m_timeStepTol; + + /// time step error + real64 m_timeStepError; + + class SpringSliderParameters + { +public: + + GEOS_HOST_DEVICE + SpringSliderParameters( real64 const normalTraction, real64 const a, real64 const b, real64 const Dc ): + tauRate( 1e-4 ), + springStiffness( 0.0 ) + { + real64 const criticalStiffness = normalTraction * (b - a) / Dc; + springStiffness = 0.9 * criticalStiffness; + } + + /// Default copy constructor + SpringSliderParameters( SpringSliderParameters const & ) = default; + + /// Default move constructor + SpringSliderParameters( SpringSliderParameters && ) = default; + + /// Deleted default constructor + SpringSliderParameters() = delete; + + /// Deleted copy assignment operator + SpringSliderParameters & operator=( SpringSliderParameters const & ) = delete; + + /// Deleted move assignment operator + SpringSliderParameters & operator=( SpringSliderParameters && ) = delete; + + real64 tauRate; + + real64 springStiffness; + }; +}; + +} /* namespace geos */ + +#endif /* GEOS_PHYSICSSOLVERS_INDUCED_QUASIDYNAMICEQRK32_HPP */ diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index 4d2db044491..4a6ba609d9e 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -27,18 +27,36 @@ namespace geos namespace rateAndStateKernels { + +// TBD: Pass the kernel and add getters for relevant fields to make this function general purpose and avoid +// wrappers? +GEOS_HOST_DEVICE +static void projectSlipRateBase( localIndex const k, + real64 const frictionCoefficient, + real64 const shearImpedance, + arrayView2d< real64 const > const traction, + arrayView1d< real64 const > const slipRate, + arrayView2d< real64 > const slipVelocity) +{ + // Project slip rate onto shear traction to get slip velocity components + real64 const frictionForce = traction[k][0] * frictionCoefficient; + real64 const projectionScaling = 1.0 / ( shearImpedance + frictionForce / slipRate[k] ); + slipVelocity[k][0] = projectionScaling * traction[k][1]; + slipVelocity[k][1] = projectionScaling * traction[k][2]; +} + /** - * @class RateAndStateKernel + * @class ImplicitFixedStressRateAndStateKernel * * @brief * * @details */ -class RateAndStateKernel +class ImplicitFixedStressRateAndStateKernel { public: - RateAndStateKernel( SurfaceElementSubRegion & subRegion, + ImplicitFixedStressRateAndStateKernel( SurfaceElementSubRegion & subRegion, constitutive::RateAndStateFriction const & frictionLaw, real64 const shearImpedance ): m_slipRate( subRegion.getField< fields::rateAndState::slipRate >() ), @@ -90,7 +108,7 @@ class RateAndStateKernel stack.jacobian[0][0] = dFriction[0]; // derivative of Eq 1 w.r.t. stateVariable stack.jacobian[0][1] = dFriction[1]; // derivative of Eq 1 w.r.t. slipRate stack.jacobian[1][0] = dStateEvolutionLaw[0]; // derivative of Eq 2 w.r.t. stateVariable - stack.jacobian[1][1] = dStateEvolutionLaw[1]; // derivative of Eq 2 w.r.t. m_slipRate + stack.jacobian[1][1] = dStateEvolutionLaw[1]; // derivative of Eq 2 w.r.t. slipRate } GEOS_HOST_DEVICE @@ -109,11 +127,8 @@ class RateAndStateKernel GEOS_HOST_DEVICE void projectSlipRate( localIndex const k ) const { - // Project slip rate onto shear traction to get slip velocity components - real64 const frictionForce = m_traction[k][0] * m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] ); - real64 const projectionScaling = 1.0 / ( m_shearImpedance + frictionForce / m_slipRate[k] ); - m_slipVelocity[k][0] = projectionScaling * m_traction[k][1]; - m_slipVelocity[k][1] = projectionScaling * m_traction[k][2]; + real64 const frictionCoefficient = m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] ); + projectSlipRateBase(k, frictionCoefficient, m_shearImpedance, m_traction, m_slipRate, m_slipVelocity); } GEOS_HOST_DEVICE @@ -143,18 +158,116 @@ class RateAndStateKernel }; +/** + * @class ExplicitRateAndStateKernel + * + * @brief + * + * @details + */ +class ExplicitRateAndStateKernel +{ +public: + + ExplicitRateAndStateKernel( SurfaceElementSubRegion & subRegion, + constitutive::RateAndStateFriction const & frictionLaw, + real64 const shearImpedance ): + m_slipRate( subRegion.getField< fields::rateAndState::slipRate >() ), + m_stateVariable( subRegion.getField< fields::rateAndState::stateVariable >() ), + m_traction( subRegion.getField< fields::contact::traction >() ), + m_slipVelocity( subRegion.getField< fields::rateAndState::slipVelocity >() ), + m_shearImpedance( shearImpedance ), + m_frictionLaw( frictionLaw.createKernelUpdates() ) + {} + + /** + * @struct StackVariables + * @brief Kernel variables located on the stack + */ + struct StackVariables + { +public: + + GEOS_HOST_DEVICE + StackVariables( ) + {} + + real64 jacobian; + real64 rhs; + + }; + + GEOS_HOST_DEVICE + void setup( localIndex const k, + real64 const dt, + StackVariables & stack ) const + { + GEOS_UNUSED_VAR( dt ); + real64 const normalTraction = m_traction[k][0]; + real64 const shearTractionMagnitude = LvArray::math::sqrt( m_traction[k][1] * m_traction[k][1] + m_traction[k][2] * m_traction[k][2] ); + + // Slip rate is bracketed between [0, shear traction magnitude / shear impedance] + // If slip rate is outside the bracket, re-initialize to the middle value + real64 const upperBound = shearTractionMagnitude/m_shearImpedance; + real64 const bracketedSlipRate = m_slipRate[k] > upperBound ? upperBound/2 : m_slipRate[k]; + //real64 const bracketedSlipRate = m_slipRate[k]; + + stack.rhs = shearTractionMagnitude - m_shearImpedance *bracketedSlipRate - normalTraction * m_frictionLaw.frictionCoefficient( k,bracketedSlipRate, m_stateVariable[k] ); + stack.jacobian = -m_shearImpedance - normalTraction * m_frictionLaw.dFrictionCoefficient_dSlipRate( k, bracketedSlipRate, m_stateVariable[k] ); + } + + GEOS_HOST_DEVICE + void solve( localIndex const k, + StackVariables & stack) const + { + m_slipRate[k] -= stack.rhs/stack.jacobian; + } + + + GEOS_HOST_DEVICE + std::pair< int, real64 > checkConvergence( StackVariables const & stack, + real64 const tol ) const + { + real64 const residualNorm = LvArray::math::abs(stack.rhs); + int const converged = residualNorm < tol ? 1 : 0; + return std::make_pair( converged, residualNorm ); + } + + GEOS_HOST_DEVICE + void projectSlipRate( localIndex const k ) const + { + real64 const frictionCoefficient = m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] ); + projectSlipRateBase(k, frictionCoefficient, m_shearImpedance, m_traction, m_slipRate, m_slipVelocity); + } + +private: + + arrayView1d< real64 > const m_slipRate; + + arrayView1d< real64 > const m_stateVariable; + + arrayView2d< real64 const > const m_traction; + + arrayView2d< real64 > const m_slipVelocity; + + real64 const m_shearImpedance; + + constitutive::RateAndStateFriction::KernelWrapper m_frictionLaw; + +}; /** * @brief Performs the kernel launch * @tparam POLICY the policy used in the RAJA kernels */ -template< typename POLICY > +template< typename KernelType, typename POLICY > static void createAndLaunch( SurfaceElementSubRegion & subRegion, string const & frictionLawNameKey, real64 const shearImpedance, - integer const maxNewtonIter, + integer const maxIterNewton, + real64 const newtonTol, real64 const time_n, real64 const dt ) { @@ -164,20 +277,20 @@ createAndLaunch( SurfaceElementSubRegion & subRegion, string const & frictionaLawName = subRegion.getReference< string >( frictionLawNameKey ); constitutive::RateAndStateFriction const & frictionLaw = subRegion.getConstitutiveModel< constitutive::RateAndStateFriction >( frictionaLawName ); - RateAndStateKernel kernel( subRegion, frictionLaw, shearImpedance ); + KernelType kernel( subRegion, frictionLaw, shearImpedance ); // Newton loop (outside of the kernel launch) bool allConverged = false; - for( integer iter = 0; iter < maxNewtonIter; iter++ ) + for( integer iter = 0; iter < maxIterNewton; iter++ ) { RAJA::ReduceMin< parallelDeviceReduce, int > converged( 1 ); RAJA::ReduceMax< parallelDeviceReduce, real64 > residualNorm( 0.0 ); forAll< POLICY >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { - RateAndStateKernel::StackVariables stack; + typename KernelType::StackVariables stack; kernel.setup( k, dt, stack ); kernel.solve( k, stack ); - auto result = kernel.checkConvergence( stack, 1.0e-6 ); + auto result = kernel.checkConvergence( stack, newtonTol ); converged.min( std::get< 0 >( result ) ); residualNorm.max( std::get< 1 >( result ) ); } ); diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp index 8031ab1c344..6ebc0af6feb 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp @@ -36,10 +36,26 @@ DECLARE_FIELD( slipRate, "slipRate", array1d< real64 >, 1.0e-6, - LEVEL_0, + NOPLOT, WRITE_AND_READ, "Slip rate" ); +DECLARE_FIELD( slipVelocity, + "slipVelocity", + array2d< real64 >, + 0.70710678118e-6, + LEVEL_0, + WRITE_AND_READ, + "Slip velocity" ); + +DECLARE_FIELD( slipVelocity_n, + "slipVelocity_n", + array2d< real64 >, + 0.70710678118e-6, + NOPLOT, + WRITE_AND_READ, + "Slip velocity" ); + DECLARE_FIELD( stateVariable, "stateVariable", array1d< real64 >, @@ -48,14 +64,6 @@ DECLARE_FIELD( stateVariable, WRITE_AND_READ, "Rate- and state-dependent friction state variable" ); -DECLARE_FIELD( slipVelocity, - "slipVelocity", - array2d< real64 >, - 1.0e-6, - LEVEL_0, - WRITE_AND_READ, - "Slip velocity" ); - DECLARE_FIELD( stateVariable_n, "stateVariable_n", array1d< real64 >, @@ -64,6 +72,22 @@ DECLARE_FIELD( stateVariable_n, WRITE_AND_READ, "Rate- and state-dependent friction state variable at previous time step" ); +DECLARE_FIELD( dStateVariableStage1, + "dStateVariableStage1", + array1d< real64 >, + 0.0, + NOPLOT, + WRITE_AND_READ, + "Rate- and state-dependent friction state variable at previous time step" ); + +DECLARE_FIELD( dStateVariableStage2, + "dStateVariableStage2", + array1d< real64 >, + 0.0, + NOPLOT, + WRITE_AND_READ, + "Rate- and state-dependent friction state variable at previous time step" ); + DECLARE_FIELD( deltaSlip, "deltaSlip", array2d< real64 >, @@ -72,6 +96,39 @@ DECLARE_FIELD( deltaSlip, WRITE_AND_READ, "Slip increment" ); +DECLARE_FIELD( deltaSlip_n, + "deltaSlip_n", + array2d< real64 >, + 0.0, + NOPLOT, + WRITE_AND_READ, + "Slip increment" ); + + +DECLARE_FIELD( dDeltaSlipStage1, + "dDeltaSlipStage1", + array2d< real64 >, + 0.0, + NOPLOT, + WRITE_AND_READ, + "Slip increment" ); + +DECLARE_FIELD( dDeltaSlipStage2, + "dDeltaSlipStage2", + array2d< real64 >, + 0.0, + NOPLOT, + WRITE_AND_READ, + "Slip increment" ); + + +DECLARE_FIELD( error, + "error", + array1d< real64 >, + 0.0, + LEVEL_0, + WRITE_AND_READ, + "Error" ); } From a57165c7b1763007716d68aeae580e20b3716105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Mon, 18 Nov 2024 10:44:50 -0800 Subject: [PATCH 35/53] Remove commented-out line --- .../inducedSeismicity/kernels/RateAndStateKernels.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index 4a6ba609d9e..e1fb64a4a92 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -210,7 +210,6 @@ class ExplicitRateAndStateKernel // If slip rate is outside the bracket, re-initialize to the middle value real64 const upperBound = shearTractionMagnitude/m_shearImpedance; real64 const bracketedSlipRate = m_slipRate[k] > upperBound ? upperBound/2 : m_slipRate[k]; - //real64 const bracketedSlipRate = m_slipRate[k]; stack.rhs = shearTractionMagnitude - m_shearImpedance *bracketedSlipRate - normalTraction * m_frictionLaw.frictionCoefficient( k,bracketedSlipRate, m_stateVariable[k] ); stack.jacobian = -m_shearImpedance - normalTraction * m_frictionLaw.dFrictionCoefficient_dSlipRate( k, bracketedSlipRate, m_stateVariable[k] ); From 03d13bcb548563d04ab1f2ec9e57d4b5e2118c39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Tue, 19 Nov 2024 10:47:51 -0800 Subject: [PATCH 36/53] Update strings for added rate-and-state fields --- .../inducedSeismicity/rateAndStateFields.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp index 6ebc0af6feb..122bae0b410 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp @@ -54,7 +54,7 @@ DECLARE_FIELD( slipVelocity_n, 0.70710678118e-6, NOPLOT, WRITE_AND_READ, - "Slip velocity" ); + "Slip velocity at previous time step" ); DECLARE_FIELD( stateVariable, "stateVariable", @@ -78,7 +78,7 @@ DECLARE_FIELD( dStateVariableStage1, 0.0, NOPLOT, WRITE_AND_READ, - "Rate- and state-dependent friction state variable at previous time step" ); + "First Runge-Kutta stage rate for friction state variable" ); DECLARE_FIELD( dStateVariableStage2, "dStateVariableStage2", @@ -86,7 +86,7 @@ DECLARE_FIELD( dStateVariableStage2, 0.0, NOPLOT, WRITE_AND_READ, - "Rate- and state-dependent friction state variable at previous time step" ); + "Second Runge-Kutta stage rate for friction state variable" ); DECLARE_FIELD( deltaSlip, "deltaSlip", @@ -102,7 +102,7 @@ DECLARE_FIELD( deltaSlip_n, 0.0, NOPLOT, WRITE_AND_READ, - "Slip increment" ); + "Slip increment at previous time step" ); DECLARE_FIELD( dDeltaSlipStage1, @@ -111,7 +111,7 @@ DECLARE_FIELD( dDeltaSlipStage1, 0.0, NOPLOT, WRITE_AND_READ, - "Slip increment" ); + "First Runge-Kutta stage rate for slip increment" ); DECLARE_FIELD( dDeltaSlipStage2, "dDeltaSlipStage2", @@ -119,7 +119,7 @@ DECLARE_FIELD( dDeltaSlipStage2, 0.0, NOPLOT, WRITE_AND_READ, - "Slip increment" ); + "Second Runge-Kutta stage rate for slip increment" ); DECLARE_FIELD( error, @@ -128,7 +128,7 @@ DECLARE_FIELD( error, 0.0, LEVEL_0, WRITE_AND_READ, - "Error" ); + "Error for rate-and-state fields" ); } From be6c4db079a9d47c7243661e42b961635807ba8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Wed, 20 Nov 2024 21:05:01 -0800 Subject: [PATCH 37/53] Change to using a single multi-d array for the Runge-Kutta stage rates --- .../inducedSeismicity/QuasiDynamicEQRK32.cpp | 73 +++++++++---------- .../inducedSeismicity/rateAndStateFields.hpp | 35 +++------ 2 files changed, 43 insertions(+), 65 deletions(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp index 2a0b715212a..8223df9df89 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp @@ -84,12 +84,7 @@ QuasiDynamicEQRK32::~QuasiDynamicEQRK32() // slipVelocity_n // traction_n // deltaSlip_n -// dDeltaSlipStage1 -// dDeltaSlipStage2 -// dDeltaSlipStage2 // stateVariable_n -// dStateVariableStage1 -// dStateVariableStage2 void QuasiDynamicEQRK32::registerDataOnMesh( Group & meshBodies ) { SolverBase::registerDataOnMesh( meshBodies ); @@ -107,8 +102,6 @@ void QuasiDynamicEQRK32::registerDataOnMesh( Group & meshBodies ) // Scalar functions on fault subRegion.registerField< rateAndState::stateVariable >( getName() ); subRegion.registerField< rateAndState::stateVariable_n >( getName() ); - subRegion.registerField< rateAndState::dStateVariableStage1 >( getName() ); - subRegion.registerField< rateAndState::dStateVariableStage2 >( getName() ); subRegion.registerField< rateAndState::slipRate >( getName() ); subRegion.registerField< rateAndState::error >( getName() ); @@ -122,10 +115,11 @@ void QuasiDynamicEQRK32::registerDataOnMesh( Group & meshBodies ) setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); subRegion.registerField< rateAndState::deltaSlip_n >( getName() ). setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); - subRegion.registerField< rateAndState::dDeltaSlipStage1 >( getName() ). - setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); - subRegion.registerField< rateAndState::dDeltaSlipStage2 >( getName() ). - setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); + + // Runge-Kutta stage rates + subRegion.registerField< rateAndState::stateVariableRKStageRate >( getName() ).reference().resizeDimension< 1 >( 2 ); + subRegion.registerField< rateAndState::deltaSlipRKStageRate >( getName() ).reference().resizeDimension< 1, 2>( 2, 2 ); + if( !subRegion.hasWrapper( contact::dispJump::key() )) { @@ -212,19 +206,20 @@ real64 QuasiDynamicEQRK32::solverStep( real64 const & time_n, arrayView1d< real64 > const stateVariable = subRegion.getField< rateAndState::stateVariable >(); arrayView1d< real64 > const slipRate = subRegion.getField< rateAndState::slipRate >(); arrayView2d< real64 > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); - arrayView1d< real64 > const dStateVariableStage1 = subRegion.getField< rateAndState::dStateVariableStage1 >(); - arrayView2d< real64 > const dDeltaSlipStage1 = subRegion.getField< rateAndState::dDeltaSlipStage1 >(); arrayView2d< real64 > const dispJump = subRegion.getField< contact::dispJump >(); + // Stage rates + arrayView2d< real64 > const stateVariableRKStageRate = subRegion.getField< rateAndState::stateVariableRKStageRate >(); + arrayView3d< real64 > const deltaSlipRKStageRate = subRegion.getField< rateAndState::deltaSlipRKStageRate >(); forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { slipRate[k] = LvArray::math::sqrt(slipVelocity_n[k][0] * slipVelocity_n[k][0] + slipVelocity_n[k][1]*slipVelocity_n[k][1]); // Runge-Kutta stage rates for stage 1 - dStateVariableStage1[k] = frictionKernelWrapper.stateEvolution(k, slipRate[k], stateVariable_n[k]); - LvArray::tensorOps::copy< 2 >( dDeltaSlipStage1[k], slipVelocity_n[k] ); + stateVariableRKStageRate[k][0] = frictionKernelWrapper.stateEvolution(k, slipRate[k], stateVariable_n[k]); + LvArray::tensorOps::copy< 2 >( deltaSlipRKStageRate[k][0], slipVelocity_n[k] ); // Runge-Kutta stage values for stage 1 - stateVariable[k] = stateVariable_n[k] + 0.5*dtAdaptive*dStateVariableStage1[k]; - deltaSlip[k][0] = deltaSlip_n[k][0] + 0.5*dtAdaptive*dDeltaSlipStage1[k][0]; - deltaSlip[k][1] = deltaSlip_n[k][1] + 0.5*dtAdaptive*dDeltaSlipStage1[k][1]; + stateVariable[k] = stateVariable_n[k] + 0.5*dtAdaptive*stateVariableRKStageRate[0][k]; + deltaSlip[k][0] = deltaSlip_n[k][0] + 0.5*dtAdaptive*deltaSlipRKStageRate[k][0][0]; + deltaSlip[k][1] = deltaSlip_n[k][1] + 0.5*dtAdaptive*deltaSlipRKStageRate[k][0][1]; // Set tangential components of the displacement jump for stress solver and state variable for non-linear solve dispJump[k][1] = dispJump_n[k][1] + deltaSlip[k][0]; dispJump[k][2] = dispJump_n[k][2] + deltaSlip[k][1]; @@ -264,26 +259,26 @@ real64 QuasiDynamicEQRK32::solverStep( real64 const & time_n, arrayView2d< real64 const > const dispJump_n = subRegion.getField< contact::dispJump_n >(); arrayView1d< real64 const > const slipRate = subRegion.getField< rateAndState::slipRate >(); arrayView2d< real64 const > const slipVelocity = subRegion.getField< rateAndState::slipVelocity >(); - arrayView1d< real64 const > const dStateVariableStage1 = subRegion.getField< rateAndState::dStateVariableStage1 >(); - arrayView2d< real64 const > const dDeltaSlipStage1 = subRegion.getField< rateAndState::dDeltaSlipStage1 >(); // Fields written for this stage arrayView1d< real64 > const stateVariable = subRegion.getField< rateAndState::stateVariable >(); arrayView2d< real64 > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); - arrayView1d< real64 > const dStateVariableStage2 = subRegion.getField< rateAndState::dStateVariableStage2 >(); - arrayView2d< real64 > const dDeltaSlipStage2 = subRegion.getField< rateAndState::dDeltaSlipStage2 >(); arrayView2d< real64 > const dispJump = subRegion.getField< contact::dispJump >(); + // Stage rates + arrayView2d< real64 > const stateVariableRKStageRate = subRegion.getField< rateAndState::stateVariableRKStageRate >(); + arrayView3d< real64 > const deltaSlipRKStageRate = subRegion.getField< rateAndState::deltaSlipRKStageRate >(); + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { // Runge-Kutta stage rates for stage 2 - dStateVariableStage2[k] = frictionKernelWrapper.stateEvolution(k, slipRate[k], stateVariable[k]); - LvArray::tensorOps::copy< 2 >( dDeltaSlipStage2[k], slipVelocity[k] ); + stateVariableRKStageRate[k][1] = frictionKernelWrapper.stateEvolution(k, slipRate[k], stateVariable[k]); + LvArray::tensorOps::copy< 2 >( deltaSlipRKStageRate[k][1], slipVelocity[k] ); // Runge-Kutta stage values for stage 2 - stateVariable[k] = stateVariable_n[k] + dtAdaptive*( -dStateVariableStage1[k] + 2*dStateVariableStage2[k] ); - deltaSlip[k][0] = deltaSlip_n[k][0] + dtAdaptive*( -dDeltaSlipStage1[k][0] + 2*dDeltaSlipStage2[k][0] ); - deltaSlip[k][1] = deltaSlip_n[k][1] + dtAdaptive*( -dDeltaSlipStage1[k][1] + 2*dDeltaSlipStage2[k][1] ); + stateVariable[k] = stateVariable_n[k] + dtAdaptive*( -stateVariableRKStageRate[k][0] + 2*stateVariableRKStageRate[k][1] ); + deltaSlip[k][0] = deltaSlip_n[k][0] + dtAdaptive*( -deltaSlipRKStageRate[k][0][0] + 2*deltaSlipRKStageRate[k][1][0] ); + deltaSlip[k][1] = deltaSlip_n[k][1] + dtAdaptive*( -deltaSlipRKStageRate[k][0][1] + 2*deltaSlipRKStageRate[k][1][1] ); // Set tangential components of the displacement jump for stress solver and state variable for non-linear solve dispJump[k][1] = dispJump_n[k][1] + deltaSlip[k][0]; dispJump[k][2] = dispJump_n[k][2] + deltaSlip[k][1]; @@ -321,10 +316,6 @@ real64 QuasiDynamicEQRK32::solverStep( real64 const & time_n, arrayView1d< real64 const > const slipRate = subRegion.getField< rateAndState::slipRate >(); arrayView2d< real64 const > const slipVelocity = subRegion.getField< rateAndState::slipVelocity >(); arrayView2d< real64 const > const dispJump_n = subRegion.getField< contact::dispJump_n >(); - arrayView1d< real64 const > const dStateVariableStage1 = subRegion.getField< rateAndState::dStateVariableStage1 >(); - arrayView1d< real64 const > const dStateVariableStage2 = subRegion.getField< rateAndState::dStateVariableStage2 >(); - arrayView2d< real64 const > const dDeltaSlipStage1 = subRegion.getField< rateAndState::dDeltaSlipStage1 >(); - arrayView2d< real64 const > const dDeltaSlipStage2 = subRegion.getField< rateAndState::dDeltaSlipStage2 >(); // Fields written for this stage arrayView1d< real64 > const stateVariable = subRegion.getField< rateAndState::stateVariable >(); @@ -332,24 +323,28 @@ real64 QuasiDynamicEQRK32::solverStep( real64 const & time_n, arrayView2d< real64 > const dispJump = subRegion.getField< contact::dispJump >(); arrayView1d< real64 > const rateStateError = subRegion.getField< rateAndState::error >(); + // Stage rates + arrayView2d< real64 const > const stateVariableRKStageRate = subRegion.getField< rateAndState::stateVariableRKStageRate >(); + arrayView3d< real64 const > const deltaSlipRKStageRate = subRegion.getField< rateAndState::deltaSlipRKStageRate >(); + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { // Runge-Kutta stage rates for stage 3 - real64 const dStateVariableStage3 = frictionKernelWrapper.stateEvolution(k, slipRate[k], stateVariable[k]); - real64 const dDeltaSlipStage3[2] = {slipVelocity[k][0], slipVelocity[k][1]}; + real64 const stateVariableRKStageRate3 = frictionKernelWrapper.stateEvolution(k, slipRate[k], stateVariable[k]); + real64 const deltaSlipRKStageRate3[2] = {slipVelocity[k][0], slipVelocity[k][1]}; // Third order update - stateVariable[k] = stateVariable_n[k] + dtAdaptive/6*( dStateVariableStage1[k] + 4*dStateVariableStage2[k] + dStateVariableStage3 ); - deltaSlip[k][0] = deltaSlip_n[k][0] + dtAdaptive/6*( dDeltaSlipStage1[k][0] + 4*dDeltaSlipStage2[k][0] + dDeltaSlipStage3[0] ); - deltaSlip[k][1] = deltaSlip_n[k][1] + dtAdaptive/6*( dDeltaSlipStage1[k][1] + 4*dDeltaSlipStage2[k][1] + dDeltaSlipStage3[1] ); + stateVariable[k] = stateVariable_n[k] + dtAdaptive/6*( stateVariableRKStageRate[k][0] + 4*stateVariableRKStageRate[k][1] + stateVariableRKStageRate3 ); + deltaSlip[k][0] = deltaSlip_n[k][0] + dtAdaptive/6*( deltaSlipRKStageRate[k][0][0] + 4*deltaSlipRKStageRate[k][1][0] + deltaSlipRKStageRate3[0] ); + deltaSlip[k][1] = deltaSlip_n[k][1] + dtAdaptive/6*( deltaSlipRKStageRate[k][0][1] + 4*deltaSlipRKStageRate[k][1][1] + deltaSlipRKStageRate3[1] ); dispJump[k][1] = dispJump_n[k][1] + deltaSlip[k][0]; dispJump[k][2] = dispJump_n[k][2] + deltaSlip[k][1]; // Second order updates used for adaptive error comparison - real64 const stateVariableRK2 = stateVariable_n[k] + dtAdaptive/2*(dStateVariableStage1[k] + dStateVariableStage3); - real64 const deltaSlipRK2[2] = { deltaSlip_n[k][0] + dtAdaptive/2*( dDeltaSlipStage1[k][1] + dDeltaSlipStage3[0] ), - deltaSlip_n[k][1] + dtAdaptive/2*( dDeltaSlipStage1[k][1] + dDeltaSlipStage3[1] ) }; + real64 const stateVariableRK2 = stateVariable_n[k] + dtAdaptive/2*(stateVariableRKStageRate[k][0] + stateVariableRKStageRate3); + real64 const deltaSlipRK2[2] = { deltaSlip_n[k][0] + dtAdaptive/2*( deltaSlipRKStageRate[k][0][1] + deltaSlipRKStageRate3[0] ), + deltaSlip_n[k][1] + dtAdaptive/2*( deltaSlipRKStageRate[k][0][1] + deltaSlipRKStageRate3[1] ) }; // Compute relative errors based on the maximum error in state or slip // TODO: Avoid division by zero in error comparison diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp index 122bae0b410..7c5b6d84635 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp @@ -70,23 +70,15 @@ DECLARE_FIELD( stateVariable_n, 0.6, NOPLOT, WRITE_AND_READ, - "Rate- and state-dependent friction state variable at previous time step" ); + "Initial rate- and state-dependent friction state variable at this time step" ); -DECLARE_FIELD( dStateVariableStage1, - "dStateVariableStage1", - array1d< real64 >, - 0.0, - NOPLOT, - WRITE_AND_READ, - "First Runge-Kutta stage rate for friction state variable" ); - -DECLARE_FIELD( dStateVariableStage2, - "dStateVariableStage2", - array1d< real64 >, +DECLARE_FIELD( stateVariableRKStageRate, + "stateVariableStageRates", + array2d< real64 >, 0.0, NOPLOT, WRITE_AND_READ, - "Second Runge-Kutta stage rate for friction state variable" ); + "Runge-Kutta stage rates for friction state variable" ); DECLARE_FIELD( deltaSlip, "deltaSlip", @@ -102,25 +94,16 @@ DECLARE_FIELD( deltaSlip_n, 0.0, NOPLOT, WRITE_AND_READ, - "Slip increment at previous time step" ); + "Initial slip increment at this time step" ); -DECLARE_FIELD( dDeltaSlipStage1, +DECLARE_FIELD( deltaSlipRKStageRate, "dDeltaSlipStage1", - array2d< real64 >, + array3d< real64 >, 0.0, NOPLOT, WRITE_AND_READ, - "First Runge-Kutta stage rate for slip increment" ); - -DECLARE_FIELD( dDeltaSlipStage2, - "dDeltaSlipStage2", - array2d< real64 >, - 0.0, - NOPLOT, - WRITE_AND_READ, - "Second Runge-Kutta stage rate for slip increment" ); - + "Runge-Kutta stage rates for slip increment" ); DECLARE_FIELD( error, "error", From 1b3a893a85c200649147673f997c5f0f07ea029f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Wed, 20 Nov 2024 21:06:14 -0800 Subject: [PATCH 38/53] Update string --- src/coreComponents/physicsSolvers/contact/ContactFields.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/contact/ContactFields.hpp b/src/coreComponents/physicsSolvers/contact/ContactFields.hpp index c155e9cddad..1d94c10fb35 100644 --- a/src/coreComponents/physicsSolvers/contact/ContactFields.hpp +++ b/src/coreComponents/physicsSolvers/contact/ContactFields.hpp @@ -120,7 +120,7 @@ DECLARE_FIELD( traction_n, 0, NOPLOT, WRITE_AND_READ, - "Fracture traction vector in the local reference system at the current time-step." ); + "Initial fracture traction vector in the local reference system at this time-step." ); DECLARE_FIELD( deltaTraction, "deltaTraction", From baa5aef787c5186682b5f2446f139980b7c5d106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Mon, 25 Nov 2024 16:48:42 -0800 Subject: [PATCH 39/53] Add PID controller to adaptive time step update --- .../inducedSeismicity/QuasiDynamicEQRK32.cpp | 86 ++++++++++++------- .../inducedSeismicity/QuasiDynamicEQRK32.hpp | 14 ++- .../inducedSeismicity/rateAndStateFields.hpp | 2 +- 3 files changed, 66 insertions(+), 36 deletions(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp index 8223df9df89..e23ba99d57c 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp @@ -40,8 +40,14 @@ QuasiDynamicEQRK32::QuasiDynamicEQRK32( const string & name, m_stressSolver( nullptr ), m_stressSolverName( "SpringSlider" ), m_shearImpedance( 0.0 ), - m_timeStepTol( 5.0e-4 ), - m_timeStepError( 0.0 ) + m_timestepAbsTol( 1.0e-5 ), + m_timestepRelTol( 1.0e-5 ), + + m_timestepAcceptSafety( 0.81 ), + m_prevTimestepErrors{ 0.0, 0.0 } , + m_beta{ 1.0/18.0, 1.0/9.0, 1.0/18.0 } , + m_rkOrders{ 3, 2 }, + m_successfulStep( false ) { this->registerWrapper( viewKeyStruct::shearImpedanceString(), &m_shearImpedance ). setInputFlag( InputFlags::REQUIRED ). @@ -50,11 +56,6 @@ QuasiDynamicEQRK32::QuasiDynamicEQRK32( const string & name, this->registerWrapper( viewKeyStruct::stressSolverNameString(), &m_stressSolverName ). setInputFlag( InputFlags::OPTIONAL ). setDescription( "Name of solver for computing stress. If empty, the spring-slider model is run." ); - - this->registerWrapper( viewKeyStruct::timeStepTol(), &m_timeStepTol ). - setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( 5e-4 ). - setDescription( "Target slip incrmeent for timestep size selction" ); } void QuasiDynamicEQRK32::postInputInitialization() @@ -103,7 +104,6 @@ void QuasiDynamicEQRK32::registerDataOnMesh( Group & meshBodies ) subRegion.registerField< rateAndState::stateVariable >( getName() ); subRegion.registerField< rateAndState::stateVariable_n >( getName() ); subRegion.registerField< rateAndState::slipRate >( getName() ); - subRegion.registerField< rateAndState::error >( getName() ); // Tangent (2-component) functions on fault string const labels2Comp[2] = {"tangent1", "tangent2" }; @@ -119,6 +119,10 @@ void QuasiDynamicEQRK32::registerDataOnMesh( Group & meshBodies ) // Runge-Kutta stage rates subRegion.registerField< rateAndState::stateVariableRKStageRate >( getName() ).reference().resizeDimension< 1 >( 2 ); subRegion.registerField< rateAndState::deltaSlipRKStageRate >( getName() ).reference().resizeDimension< 1, 2>( 2, 2 ); + // Error + string const labelsError[3] = { "deltaSlip1", "deltaSlip2", "stateVariable"}; + subRegion.registerField< rateAndState::error >( getName() ). + setDimLabels( 1, labelsError ).reference().resizeDimension< 1 >( 3 ); if( !subRegion.hasWrapper( contact::dispJump::key() )) @@ -321,7 +325,7 @@ real64 QuasiDynamicEQRK32::solverStep( real64 const & time_n, arrayView1d< real64 > const stateVariable = subRegion.getField< rateAndState::stateVariable >(); arrayView2d< real64 > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); arrayView2d< real64 > const dispJump = subRegion.getField< contact::dispJump >(); - arrayView1d< real64 > const rateStateError = subRegion.getField< rateAndState::error >(); + arrayView2d< real64 > const rateStateError = subRegion.getField< rateAndState::error >(); // Stage rates arrayView2d< real64 const > const stateVariableRKStageRate = subRegion.getField< rateAndState::stateVariableRKStageRate >(); @@ -346,33 +350,32 @@ real64 QuasiDynamicEQRK32::solverStep( real64 const & time_n, real64 const deltaSlipRK2[2] = { deltaSlip_n[k][0] + dtAdaptive/2*( deltaSlipRKStageRate[k][0][1] + deltaSlipRKStageRate3[0] ), deltaSlip_n[k][1] + dtAdaptive/2*( deltaSlipRKStageRate[k][0][1] + deltaSlipRKStageRate3[1] ) }; + // TODO: Change error computation // Compute relative errors based on the maximum error in state or slip - // TODO: Avoid division by zero in error comparison - // by adding small number to denominator. Better way to to this? - real64 const errorStateVariable = LvArray::math::abs(stateVariable[k] - stateVariableRK2)/(stateVariable[k] + 1e-13); - real64 const errorSlip[2] = { (deltaSlip[k][0] - deltaSlipRK2[0])/(deltaSlip[k][0] + 1e-13), - (deltaSlip[k][1] - deltaSlipRK2[1])/(deltaSlip[k][0] + 1e-13) }; - real64 const errorDeltaSlip = LvArray::math::sqrt(errorSlip[0]*errorSlip[0] + errorSlip[1]*errorSlip[1]); - // Take maximum of slip and state error - rateStateError[k] = (errorStateVariable > errorDeltaSlip) ? errorStateVariable : errorDeltaSlip; + + rateStateError[k][0] = (deltaSlip[k][0] - deltaSlipRK2[0]) / + ( m_timestepAbsTol + m_timestepRelTol * LvArray::math::max( LvArray::math::abs(deltaSlip[k][0]), LvArray::math::abs(deltaSlipRK2[0]) )); + rateStateError[k][1] = (deltaSlip[k][1] - deltaSlipRK2[1]) / + ( m_timestepAbsTol + m_timestepRelTol * LvArray::math::max( LvArray::math::abs(deltaSlip[k][1]), LvArray::math::abs(deltaSlipRK2[1]) )); + rateStateError[k][2] = (stateVariable[k] - stateVariableRK2) / + ( m_timestepAbsTol + m_timestepRelTol * LvArray::math::max( LvArray::math::abs(stateVariable[k]), LvArray::math::abs(stateVariableRK2) )); + // real64 const errorStateVariable = LvArray::math::abs( (stateVariable[k] - stateVariableRK2) /( stateVariable[k] + std::numeric_limits< real64 >::epsilon() ) ); + // real64 const errorSlip[2] = { ( deltaSlip[k][0] - deltaSlipRK2[0] )/( deltaSlip[k][0] + std::numeric_limits< real64 >::epsilon() ), + // ( deltaSlip[k][1] - deltaSlipRK2[1] )/( deltaSlip[k][0] + std::numeric_limits< real64 >::epsilon() ) }; } ); } ); } ); // Update timestep based on the time step error dtAdaptive = setNextDt(dtAdaptive, domain); - if (m_timeStepError <= m_timeStepTol) // m_timeStepError updated in setNextDt + if (m_successfulStep) // set in setNextDt { // Successful step. Compute stresses, and slip velocity and save results, then exit the adaptive time step loop dtStress = updateStresses( time_n, dt, cycleNumber, domain ); updateSlipVelocity( time_n, dt, domain ); saveState(domain); - GEOS_LOG_LEVEL_RANK_0( 1, "Adaptive time step successful" ); break; } - else // Unsuccessful step. Retry with the updated time step - { - GEOS_LOG_LEVEL_RANK_0( 1, "Adaptive time step failed" ); - } + } // return time step size achieved by stress solver @@ -495,31 +498,48 @@ real64 QuasiDynamicEQRK32::setNextDt( real64 const & currentDt, DomainPartition { // Spring-slider shear traction computation + real64 scaledL2Error = 0.0; forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel const & mesh, arrayView1d< string const > const & regionNames ) { - real64 maxErrorOnThisRank = 0.0; mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, [&]( localIndex const, SurfaceElementSubRegion const & subRegion ) { - arrayView1d< real64 const > const error = subRegion.getField< rateAndState::error >(); + arrayView2d< real64 const > const error = subRegion.getField< rateAndState::error >(); - RAJA::ReduceMax< parallelDeviceReduce, real64 > maxErrorOnThisRegion( 0.0 ); + RAJA::ReduceSum< parallelDeviceReduce, real64 > scaledl2ErrorSquared( 0.0 ); + integer const N = subRegion.size(); forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { - maxErrorOnThisRegion.max( error[k] ); + scaledl2ErrorSquared += LvArray::tensorOps::l2NormSquared<3>(error[k]); } ); - if( maxErrorOnThisRegion.get() > maxErrorOnThisRank ) - maxErrorOnThisRank = maxErrorOnThisRegion.get(); - } ); - m_timeStepError = MpiWrapper::max( maxErrorOnThisRank ); + scaledL2Error = LvArray::math::sqrt(MpiWrapper::sum( scaledl2ErrorSquared.get() / (3.0*N) )); + } ); } ); - real64 const nextDt = 0.9 * currentDt * pow( m_timeStepTol/m_timeStepError, 1.0 / 3.0 ); - GEOS_LOG_LEVEL_RANK_0( 1, GEOS_FMT( "The next dt will be {:.2e} s", nextDt )); + // PID error controller + limiter + real64 const k = LvArray::math::min(m_rkOrders[0], m_rkOrders[1]) + 1.0; + real64 const eps0 = 1.0/(scaledL2Error + std::numeric_limits< real64 >::epsilon()); // n + 1 + real64 const eps1 = 1.0/(m_prevTimestepErrors[0] + std::numeric_limits< real64 >::epsilon()); // n + real64 const eps2 = 1.0/(m_prevTimestepErrors[1] + std::numeric_limits< real64 >::epsilon()); // n-1 + // Limiter is 1.0 + atan(x - 1.0). Here use atan(x) = atan2(x, 1.0) + real64 const dtFactor = 1.0 + LvArray::math::atan2( pow(eps0, m_beta[0] / k ) * pow(eps1, m_beta[1] / k ) * pow(eps2, m_beta[2] / k ) - 1.0, 1.0); + + real64 const nextDt = dtFactor*currentDt; + m_successfulStep = (dtFactor >= m_timestepAcceptSafety) ? true : false; + if ( m_successfulStep ) + { + m_prevTimestepErrors[1] = m_prevTimestepErrors[0]; + m_prevTimestepErrors[0] = scaledL2Error; + GEOS_LOG_LEVEL_RANK_0( 1, GEOS_FMT( "Adaptive time step successful. The next dt will be {:.2e} s", nextDt )); + } + else + { + GEOS_LOG_LEVEL_RANK_0( 1, GEOS_FMT( "Adaptive time step failed. The next dt will be {:.2e} s", nextDt )); + } return nextDt; } diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp index fa078415f2a..67d0665bd9c 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp @@ -98,10 +98,20 @@ class QuasiDynamicEQRK32 : public SolverBase real64 m_shearImpedance; /// time step tolerance - real64 m_timeStepTol; + real64 m_timestepAbsTol; + + real64 m_timestepRelTol; + + real64 m_timestepAcceptSafety; + real64 m_prevTimestepErrors[2]; + /// time step error - real64 m_timeStepError; + real64 m_beta[3]; + + integer m_rkOrders[2]; + + bool m_successfulStep; class SpringSliderParameters { diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp index 7c5b6d84635..6c44477836f 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp @@ -107,7 +107,7 @@ DECLARE_FIELD( deltaSlipRKStageRate, DECLARE_FIELD( error, "error", - array1d< real64 >, + array2d< real64 >, 0.0, LEVEL_0, WRITE_AND_READ, From 4ae1d9fd4605955eeabd93292ae187412f6d2eb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Mon, 25 Nov 2024 16:50:55 -0800 Subject: [PATCH 40/53] Bracket slip rate after Newton update --- .../inducedSeismicity/kernels/RateAndStateKernels.hpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index e1fb64a4a92..d4d3b3a826f 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -209,7 +209,7 @@ class ExplicitRateAndStateKernel // Slip rate is bracketed between [0, shear traction magnitude / shear impedance] // If slip rate is outside the bracket, re-initialize to the middle value real64 const upperBound = shearTractionMagnitude/m_shearImpedance; - real64 const bracketedSlipRate = m_slipRate[k] > upperBound ? upperBound/2 : m_slipRate[k]; + real64 const bracketedSlipRate = m_slipRate[k] > upperBound ? 0.5*upperBound : m_slipRate[k]; stack.rhs = shearTractionMagnitude - m_shearImpedance *bracketedSlipRate - normalTraction * m_frictionLaw.frictionCoefficient( k,bracketedSlipRate, m_stateVariable[k] ); stack.jacobian = -m_shearImpedance - normalTraction * m_frictionLaw.dFrictionCoefficient_dSlipRate( k, bracketedSlipRate, m_stateVariable[k] ); @@ -220,6 +220,13 @@ class ExplicitRateAndStateKernel StackVariables & stack) const { m_slipRate[k] -= stack.rhs/stack.jacobian; + + // Slip rate is bracketed between [0, shear traction magnitude / shear impedance] + // Check that the update did not end outside of the bracket. + real64 const shearTractionMagnitude = LvArray::math::sqrt( m_traction[k][1] * m_traction[k][1] + m_traction[k][2] * m_traction[k][2] ); + real64 const upperBound = shearTractionMagnitude/m_shearImpedance; + if ( m_slipRate[k] > upperBound ) m_slipRate[k] = 0.5*upperBound; + } From 7290dd1e801fdf21cbbae14960b5549bbafcc564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Wed, 27 Nov 2024 16:47:36 -0800 Subject: [PATCH 41/53] Add kernel for EmbeddedRungeKutta time stepping of slip and state and refactor QuasiDynamicEQRK32 solver --- .../inducedSeismicity/QuasiDynamicEQRK32.cpp | 230 +++++------------- .../inducedSeismicity/QuasiDynamicEQRK32.hpp | 12 +- .../kernels/RateAndStateKernels.hpp | 147 ++++++++++- .../inducedSeismicity/rateAndStateFields.hpp | 14 +- 4 files changed, 221 insertions(+), 182 deletions(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp index e23ba99d57c..43fc9eda475 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp @@ -42,12 +42,11 @@ QuasiDynamicEQRK32::QuasiDynamicEQRK32( const string & name, m_shearImpedance( 0.0 ), m_timestepAbsTol( 1.0e-5 ), m_timestepRelTol( 1.0e-5 ), - m_timestepAcceptSafety( 0.81 ), m_prevTimestepErrors{ 0.0, 0.0 } , - m_beta{ 1.0/18.0, 1.0/9.0, 1.0/18.0 } , - m_rkOrders{ 3, 2 }, - m_successfulStep( false ) + m_beta{ 1.0/18.0, 1.0/9.0, 1.0/18.0 }, + m_successfulStep( false ), + m_butcherTable(RK32Table()) { this->registerWrapper( viewKeyStruct::shearImpedanceString(), &m_shearImpedance ). setInputFlag( InputFlags::REQUIRED ). @@ -117,8 +116,7 @@ void QuasiDynamicEQRK32::registerDataOnMesh( Group & meshBodies ) setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); // Runge-Kutta stage rates - subRegion.registerField< rateAndState::stateVariableRKStageRate >( getName() ).reference().resizeDimension< 1 >( 2 ); - subRegion.registerField< rateAndState::deltaSlipRKStageRate >( getName() ).reference().resizeDimension< 1, 2>( 2, 2 ); + subRegion.registerField< rateAndState::rungeKuttaStageRates >( getName() ).reference().resizeDimension< 1, 2>( 3, 3 ); // Error string const labelsError[3] = { "deltaSlip1", "deltaSlip2", "stateVariable"}; subRegion.registerField< rateAndState::error >( getName() ). @@ -182,68 +180,45 @@ real64 QuasiDynamicEQRK32::solverStep( real64 const & time_n, GEOS_LOG_LEVEL_RANK_0( 1, "Begin adaptive time step" ); while (true) // Adaptive time step loop. Performs a Runge-Kutta time stepping with error control on state and slip { - - // First Runge-Kutta stage - - // Evolve deltaSlip, dispJump and stateVariable to t + 0.5*dtAdaptive - // Store the first stage rates for deltaSlip and stateVariable - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) - - { - mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, - [&]( localIndex const, - SurfaceElementSubRegion & subRegion ) - { - - string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); - RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); - RateAndStateFriction::KernelWrapper frictionKernelWrapper = frictionLaw.createKernelUpdates(); - - // Fields read for this stage - arrayView2d< real64 const > const slipVelocity_n = subRegion.getField< rateAndState::slipVelocity >(); - arrayView1d< real64 const > const stateVariable_n = subRegion.getField< rateAndState::stateVariable_n >(); - arrayView2d< real64 const > const deltaSlip_n = subRegion.getField< rateAndState::deltaSlip_n >(); - arrayView2d< real64 const > const dispJump_n = subRegion.getField< contact::dispJump_n >(); - // Fields written for this stage - arrayView1d< real64 > const stateVariable = subRegion.getField< rateAndState::stateVariable >(); - arrayView1d< real64 > const slipRate = subRegion.getField< rateAndState::slipRate >(); - arrayView2d< real64 > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); - arrayView2d< real64 > const dispJump = subRegion.getField< contact::dispJump >(); - // Stage rates - arrayView2d< real64 > const stateVariableRKStageRate = subRegion.getField< rateAndState::stateVariableRKStageRate >(); - arrayView3d< real64 > const deltaSlipRKStageRate = subRegion.getField< rateAndState::deltaSlipRKStageRate >(); - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) - { - slipRate[k] = LvArray::math::sqrt(slipVelocity_n[k][0] * slipVelocity_n[k][0] + slipVelocity_n[k][1]*slipVelocity_n[k][1]); - // Runge-Kutta stage rates for stage 1 - stateVariableRKStageRate[k][0] = frictionKernelWrapper.stateEvolution(k, slipRate[k], stateVariable_n[k]); - LvArray::tensorOps::copy< 2 >( deltaSlipRKStageRate[k][0], slipVelocity_n[k] ); - // Runge-Kutta stage values for stage 1 - stateVariable[k] = stateVariable_n[k] + 0.5*dtAdaptive*stateVariableRKStageRate[0][k]; - deltaSlip[k][0] = deltaSlip_n[k][0] + 0.5*dtAdaptive*deltaSlipRKStageRate[k][0][0]; - deltaSlip[k][1] = deltaSlip_n[k][1] + 0.5*dtAdaptive*deltaSlipRKStageRate[k][0][1]; - // Set tangential components of the displacement jump for stress solver and state variable for non-linear solve - dispJump[k][1] = dispJump_n[k][1] + deltaSlip[k][0]; - dispJump[k][2] = dispJump_n[k][2] + deltaSlip[k][1]; - } ); - } ); - } ); - - // Update stresses using the updated value of deltaSlip/dispJump at t + 0.5*dtAdapt - real64 dtStress = updateStresses( time_n, 0.5*dtAdaptive, cycleNumber, domain ); + real64 dtStress; GEOS_UNUSED_VAR( dtStress ); - - // Update slipRate/slipVelocity using tractions, and stateVariable at t + 0.5*dtAdapt - updateSlipVelocity( time_n, 0.5*dt, domain ); + for (integer stageIndex = 0; stageIndex < m_butcherTable.numStages-1; stageIndex++) + { + stepRateStateODESubstage( stageIndex, dtAdaptive, domain ); + real64 dtStage = m_butcherTable.c[stageIndex+1]*dtAdaptive; + dtStress = updateStresses( time_n, dtStage, cycleNumber, domain ); + updateSlipVelocity( time_n, dtStage, domain ); + } + stepRateStateODEAndComputeError(dtAdaptive, domain); + // Update timestep based on the time step error + real64 const dtNext = setNextDt(dtAdaptive, domain); + if (m_successfulStep) // set in setNextDt + { + // Compute stresses, and slip velocity and save results at updated time, + dtStress = updateStresses( time_n, dtAdaptive, cycleNumber, domain ); + updateSlipVelocity( time_n, dtAdaptive, domain ); + saveState(domain); + // pdate the time step and exit the adaptive time step loop + dtAdaptive = dtNext; + break; + } + else + { + // Retry with updated time step + dtAdaptive = dtNext; + } + } + // return time step size achieved by stress solver + return dtAdaptive; +} - // Second Runge-Kutta stage - - // Evolve deltaSlip, dispJump and stateVariable to t + dtAdaptive - // Store the second stage rates for deltaSlip and stateVariable - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, +void QuasiDynamicEQRK32::stepRateStateODESubstage( integer const stageIndex, + real64 const dt, + DomainPartition & domain ) const +{ + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, arrayView1d< string const > const & regionNames ) @@ -255,52 +230,25 @@ real64 QuasiDynamicEQRK32::solverStep( real64 const & time_n, string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); - RateAndStateFriction::KernelWrapper frictionKernelWrapper = frictionLaw.createKernelUpdates(); - - // Fields read for this stage - arrayView1d< real64 const > const stateVariable_n = subRegion.getField< rateAndState::stateVariable_n >(); - arrayView2d< real64 const > const deltaSlip_n = subRegion.getField< rateAndState::deltaSlip_n >(); - arrayView2d< real64 const > const dispJump_n = subRegion.getField< contact::dispJump_n >(); - arrayView1d< real64 const > const slipRate = subRegion.getField< rateAndState::slipRate >(); - arrayView2d< real64 const > const slipVelocity = subRegion.getField< rateAndState::slipVelocity >(); + rateAndStateKernels::EmbeddedRungeKuttaKernel rkKernel( subRegion, frictionLaw, m_butcherTable); + arrayView3d< real64 > const rkStageRates = subRegion.getField< rateAndState::rungeKuttaStageRates >(); - // Fields written for this stage - arrayView1d< real64 > const stateVariable = subRegion.getField< rateAndState::stateVariable >(); - arrayView2d< real64 > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); - arrayView2d< real64 > const dispJump = subRegion.getField< contact::dispJump >(); - - // Stage rates - arrayView2d< real64 > const stateVariableRKStageRate = subRegion.getField< rateAndState::stateVariableRKStageRate >(); - arrayView3d< real64 > const deltaSlipRKStageRate = subRegion.getField< rateAndState::deltaSlipRKStageRate >(); - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { - // Runge-Kutta stage rates for stage 2 - stateVariableRKStageRate[k][1] = frictionKernelWrapper.stateEvolution(k, slipRate[k], stateVariable[k]); - LvArray::tensorOps::copy< 2 >( deltaSlipRKStageRate[k][1], slipVelocity[k] ); - - // Runge-Kutta stage values for stage 2 - stateVariable[k] = stateVariable_n[k] + dtAdaptive*( -stateVariableRKStageRate[k][0] + 2*stateVariableRKStageRate[k][1] ); - deltaSlip[k][0] = deltaSlip_n[k][0] + dtAdaptive*( -deltaSlipRKStageRate[k][0][0] + 2*deltaSlipRKStageRate[k][1][0] ); - deltaSlip[k][1] = deltaSlip_n[k][1] + dtAdaptive*( -deltaSlipRKStageRate[k][0][1] + 2*deltaSlipRKStageRate[k][1][1] ); - // Set tangential components of the displacement jump for stress solver and state variable for non-linear solve - dispJump[k][1] = dispJump_n[k][1] + deltaSlip[k][0]; - dispJump[k][2] = dispJump_n[k][2] + deltaSlip[k][1]; + if (stageIndex == 0) + { + rkKernel.initialize(k); + } + rkKernel.updateStageRates(k, stageIndex); + rkKernel.updateStageValues(k, stageIndex+1, dt); } ); } ); } ); +} - // Update stresses using the updated value of deltaSlip/dispJump at dtAdapt - dtStress = updateStresses( time_n, dtAdaptive, cycleNumber, domain ); - - // Update slipRate/slipVelocity using tractions, and stateVariable at t + 0.5*dtAdapt - updateSlipVelocity( time_n, dtAdaptive, domain ); - - // Third Runge-Kutta stage - - // Perform third and second order update of deltaSlip and stateVariable, and compute - // error - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, +void QuasiDynamicEQRK32::stepRateStateODEAndComputeError(real64 const dt, DomainPartition & domain ) const +{ + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, arrayView1d< string const > const & regionNames ) @@ -312,74 +260,18 @@ real64 QuasiDynamicEQRK32::solverStep( real64 const & time_n, string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); - RateAndStateFriction::KernelWrapper frictionKernelWrapper = frictionLaw.createKernelUpdates(); - - // Fields read for this stage - arrayView1d< real64 const > const stateVariable_n = subRegion.getField< rateAndState::stateVariable_n >(); - arrayView2d< real64 const > const deltaSlip_n = subRegion.getField< rateAndState::deltaSlip_n >(); - arrayView1d< real64 const > const slipRate = subRegion.getField< rateAndState::slipRate >(); - arrayView2d< real64 const > const slipVelocity = subRegion.getField< rateAndState::slipVelocity >(); - arrayView2d< real64 const > const dispJump_n = subRegion.getField< contact::dispJump_n >(); - - // Fields written for this stage - arrayView1d< real64 > const stateVariable = subRegion.getField< rateAndState::stateVariable >(); - arrayView2d< real64 > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); - arrayView2d< real64 > const dispJump = subRegion.getField< contact::dispJump >(); - arrayView2d< real64 > const rateStateError = subRegion.getField< rateAndState::error >(); - - // Stage rates - arrayView2d< real64 const > const stateVariableRKStageRate = subRegion.getField< rateAndState::stateVariableRKStageRate >(); - arrayView3d< real64 const > const deltaSlipRKStageRate = subRegion.getField< rateAndState::deltaSlipRKStageRate >(); + rateAndStateKernels::EmbeddedRungeKuttaKernel rkKernel( subRegion, frictionLaw, m_butcherTable); + arrayView3d< real64 > const rkStageRates = subRegion.getField< rateAndState::rungeKuttaStageRates >(); forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) - { - // Runge-Kutta stage rates for stage 3 - real64 const stateVariableRKStageRate3 = frictionKernelWrapper.stateEvolution(k, slipRate[k], stateVariable[k]); - real64 const deltaSlipRKStageRate3[2] = {slipVelocity[k][0], slipVelocity[k][1]}; - - // Third order update - stateVariable[k] = stateVariable_n[k] + dtAdaptive/6*( stateVariableRKStageRate[k][0] + 4*stateVariableRKStageRate[k][1] + stateVariableRKStageRate3 ); - deltaSlip[k][0] = deltaSlip_n[k][0] + dtAdaptive/6*( deltaSlipRKStageRate[k][0][0] + 4*deltaSlipRKStageRate[k][1][0] + deltaSlipRKStageRate3[0] ); - deltaSlip[k][1] = deltaSlip_n[k][1] + dtAdaptive/6*( deltaSlipRKStageRate[k][0][1] + 4*deltaSlipRKStageRate[k][1][1] + deltaSlipRKStageRate3[1] ); - - dispJump[k][1] = dispJump_n[k][1] + deltaSlip[k][0]; - dispJump[k][2] = dispJump_n[k][2] + deltaSlip[k][1]; - - // Second order updates used for adaptive error comparison - real64 const stateVariableRK2 = stateVariable_n[k] + dtAdaptive/2*(stateVariableRKStageRate[k][0] + stateVariableRKStageRate3); - real64 const deltaSlipRK2[2] = { deltaSlip_n[k][0] + dtAdaptive/2*( deltaSlipRKStageRate[k][0][1] + deltaSlipRKStageRate3[0] ), - deltaSlip_n[k][1] + dtAdaptive/2*( deltaSlipRKStageRate[k][0][1] + deltaSlipRKStageRate3[1] ) }; - - // TODO: Change error computation - // Compute relative errors based on the maximum error in state or slip - - rateStateError[k][0] = (deltaSlip[k][0] - deltaSlipRK2[0]) / - ( m_timestepAbsTol + m_timestepRelTol * LvArray::math::max( LvArray::math::abs(deltaSlip[k][0]), LvArray::math::abs(deltaSlipRK2[0]) )); - rateStateError[k][1] = (deltaSlip[k][1] - deltaSlipRK2[1]) / - ( m_timestepAbsTol + m_timestepRelTol * LvArray::math::max( LvArray::math::abs(deltaSlip[k][1]), LvArray::math::abs(deltaSlipRK2[1]) )); - rateStateError[k][2] = (stateVariable[k] - stateVariableRK2) / - ( m_timestepAbsTol + m_timestepRelTol * LvArray::math::max( LvArray::math::abs(stateVariable[k]), LvArray::math::abs(stateVariableRK2) )); - // real64 const errorStateVariable = LvArray::math::abs( (stateVariable[k] - stateVariableRK2) /( stateVariable[k] + std::numeric_limits< real64 >::epsilon() ) ); - // real64 const errorSlip[2] = { ( deltaSlip[k][0] - deltaSlipRK2[0] )/( deltaSlip[k][0] + std::numeric_limits< real64 >::epsilon() ), - // ( deltaSlip[k][1] - deltaSlipRK2[1] )/( deltaSlip[k][0] + std::numeric_limits< real64 >::epsilon() ) }; + { + // Perform last stage rate update + rkKernel.updateStageRates(k, m_butcherTable.numStages-1); + // Update solution to final time and compute errors + rkKernel.updateSolutionAndLocalError(k, dt, m_timestepAbsTol, m_timestepRelTol); } ); } ); - } ); - // Update timestep based on the time step error - dtAdaptive = setNextDt(dtAdaptive, domain); - if (m_successfulStep) // set in setNextDt - { - // Successful step. Compute stresses, and slip velocity and save results, then exit the adaptive time step loop - dtStress = updateStresses( time_n, dt, cycleNumber, domain ); - updateSlipVelocity( time_n, dt, domain ); - saveState(domain); - break; - } - - } - - // return time step size achieved by stress solver - return dtAdaptive; + } ); } real64 QuasiDynamicEQRK32::updateStresses( real64 const & time_n, @@ -521,7 +413,7 @@ real64 QuasiDynamicEQRK32::setNextDt( real64 const & currentDt, DomainPartition } ); // PID error controller + limiter - real64 const k = LvArray::math::min(m_rkOrders[0], m_rkOrders[1]) + 1.0; + real64 const k = LvArray::math::min(m_butcherTable.algHighOrder, m_butcherTable.algLowOrder) + 1.0; real64 const eps0 = 1.0/(scaledL2Error + std::numeric_limits< real64 >::epsilon()); // n + 1 real64 const eps1 = 1.0/(m_prevTimestepErrors[0] + std::numeric_limits< real64 >::epsilon()); // n real64 const eps2 = 1.0/(m_prevTimestepErrors[1] + std::numeric_limits< real64 >::epsilon()); // n-1 diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp index 67d0665bd9c..5a27a30b861 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp @@ -17,6 +17,7 @@ #define GEOS_PHYSICSSOLVERS_INDUCED_QUASIDYNAMICEQRK32_HPP #include "physicsSolvers/SolverBase.hpp" +#include "kernels/RateAndStateKernels.hpp" namespace geos { @@ -68,6 +69,13 @@ class QuasiDynamicEQRK32 : public SolverBase virtual void postInputInitialization() override; + void stepRateStateODESubstage( integer const stageIndex, + real64 const dt, + DomainPartition & domain ) const; + + void stepRateStateODEAndComputeError(real64 const dt, + DomainPartition & domain ) const; + real64 updateStresses( real64 const & time_n, real64 const & dt, const int cycleNumber, @@ -109,10 +117,10 @@ class QuasiDynamicEQRK32 : public SolverBase /// time step error real64 m_beta[3]; - integer m_rkOrders[2]; - bool m_successfulStep; + rateAndStateKernels::RK32Table m_butcherTable; + class SpringSliderParameters { public: diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index d4d3b3a826f..6342a4b96a4 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -320,8 +320,153 @@ createAndLaunch( SurfaceElementSubRegion & subRegion, } ); } + +struct RK32Table +{ + integer const algHighOrder = 3; + integer const algLowOrder = 2; + integer const numStages = 3; + real64 const a[2][2] = { { 1.0/2.0, 0.0}, // Coefficients for stage value updates + { -1.0, 2.0} }; // (lower-triangular part of table). + real64 const c[3] = { 0.0, 1.0/2.0, 1.0}; // Coefficients for time increments of substages + real64 const b[3] = { 1.0/6.0, 4.0/6.0, 1.0/6.0 }; // Quadrature weights used to evolve the solution to next time + real64 const bStar[3] = { 1.0/2.0, 0.0, 1.0/2.0 }; // Quadrature weights used for low-order comparision solution +}; + +template class EmbeddedRungeKuttaKernel +{ + +public: + EmbeddedRungeKuttaKernel(SurfaceElementSubRegion & subRegion, + constitutive::RateAndStateFriction const & frictionLaw, + Table butcherTable): + m_stateVariable( subRegion.getField< fields::rateAndState::stateVariable >() ), + m_stateVariable_n( subRegion.getField< fields::rateAndState::stateVariable_n >() ), + m_slipRate( subRegion.getField< fields::rateAndState::slipRate >() ), + m_slipVelocity( subRegion.getField< fields::rateAndState::slipVelocity >() ), + m_slipVelocity_n( subRegion.getField< fields::rateAndState::slipVelocity_n >() ), + m_deltaSlip( subRegion.getField< fields::rateAndState::deltaSlip >() ), + m_deltaSlip_n( subRegion.getField< fields::rateAndState::deltaSlip_n >() ), + m_dispJump( subRegion.getField< fields::contact::dispJump >() ), + m_dispJump_n( subRegion.getField< fields::contact::dispJump_n >() ), + m_error( subRegion.getField< fields::rateAndState::error >() ), + m_stageRates( subRegion.getField< fields::rateAndState::rungeKuttaStageRates >() ), + m_frictionLaw( frictionLaw.createKernelUpdates() ), + m_butcherTable( butcherTable ) +{} + + GEOS_HOST_DEVICE + void initialize(localIndex const k) const + { + LvArray::tensorOps::copy<2>(m_slipVelocity[k], m_slipVelocity_n[k]); + m_slipRate[k] = LvArray::tensorOps::l2Norm<2>(m_slipVelocity_n[k]); + m_stateVariable[k] = m_stateVariable_n[k]; + } + + GEOS_HOST_DEVICE + void updateStageRates(localIndex const k, localIndex const stageIndex) const + { + m_stageRates[k][stageIndex][0] = m_slipVelocity[k][0]; + m_stageRates[k][stageIndex][1] = m_slipVelocity[k][1]; + m_stageRates[k][stageIndex][2] = m_frictionLaw.stateEvolution(k, m_slipRate[k], m_stateVariable[k]); + } + + GEOS_HOST_DEVICE + void updateStageValues(localIndex const k, localIndex const stageIndex, real64 const dt) const + { + + real64 stateVariableIncrement = 0.0; + real64 deltaSlipIncrement[2] = {0.0, 0.0}; + + for (localIndex i = 0; i < stageIndex; i++) + { + deltaSlipIncrement[0] += m_butcherTable.a[stageIndex-1][i] * m_stageRates[k][i][0]; + deltaSlipIncrement[1] += m_butcherTable.a[stageIndex-1][i] * m_stageRates[k][i][1]; + stateVariableIncrement += m_butcherTable.a[stageIndex-1][i] * m_stageRates[k][i][2]; + } + m_deltaSlip[k][0] = m_deltaSlip_n[k][0] + dt*deltaSlipIncrement[0]; + m_deltaSlip[k][1] = m_deltaSlip_n[k][1] + dt*deltaSlipIncrement[1]; + m_stateVariable[k] = m_stateVariable_n[k] + dt*stateVariableIncrement; + + m_dispJump[k][1] = m_dispJump_n[k][1] + m_deltaSlip[k][0]; + m_dispJump[k][2] = m_dispJump_n[k][2] + m_deltaSlip[k][1]; + } + + GEOS_HOST_DEVICE + void updateSolutionAndLocalError(localIndex const k, real64 const dt, real64 const absTol, real64 const relTol) const + { + + real64 deltaSlipIncrement[2] = {0.0, 0.0}; + real64 deltaSlipIncrementLowOrder[2] = {0.0, 0.0}; + + real64 stateVariableIncrement = 0.0; + real64 stateVariableIncrementLowOrder = 0.0; + + for (localIndex i = 0; i < m_butcherTable.numStages; i++) + { + + // High order update of solution + deltaSlipIncrement[0] += m_butcherTable.b[i] * m_stageRates[k][i][0]; + deltaSlipIncrement[1] += m_butcherTable.b[i] * m_stageRates[k][i][1]; + stateVariableIncrement += m_butcherTable.b[i] * m_stageRates[k][i][2]; + + // Low order update for error + deltaSlipIncrementLowOrder[0] += m_butcherTable.bStar[i] * m_stageRates[k][i][0]; + deltaSlipIncrementLowOrder[1] += m_butcherTable.bStar[i] * m_stageRates[k][i][1]; + stateVariableIncrementLowOrder += m_butcherTable.bStar[i] * m_stageRates[k][i][2]; + } + + m_deltaSlip[k][0] = m_deltaSlip_n[k][0] + dt * deltaSlipIncrement[0]; + m_deltaSlip[k][1] = m_deltaSlip_n[k][1] + dt * deltaSlipIncrement[1]; + m_stateVariable[k] = m_stateVariable_n[k] + dt * stateVariableIncrement; + + real64 const deltaSlipLowOrder[2] = {m_deltaSlip_n[k][0] + dt * deltaSlipIncrementLowOrder[0], + m_deltaSlip_n[k][1] + dt * deltaSlipIncrementLowOrder[1]}; + real64 const stateVariableLowOrder = m_stateVariable_n[k] + dt * stateVariableIncrementLowOrder; + + m_dispJump[k][1] = m_dispJump_n[k][1] + m_deltaSlip[k][0]; + m_dispJump[k][2] = m_dispJump_n[k][2] + m_deltaSlip[k][1]; + + // Compute error + m_error[k][0] = (m_deltaSlip[k][0] - deltaSlipLowOrder[0]) / + ( absTol + relTol * LvArray::math::max( LvArray::math::abs(m_deltaSlip[k][0]), LvArray::math::abs(deltaSlipLowOrder[0]) )); + m_error[k][1] = (m_deltaSlip[k][1] - deltaSlipLowOrder[1]) / + ( absTol + relTol * LvArray::math::max( LvArray::math::abs(m_deltaSlip[k][1]), LvArray::math::abs(deltaSlipLowOrder[1]) )); + m_error[k][2] = (m_stateVariable[k] - stateVariableLowOrder) / + ( absTol + relTol * LvArray::math::max( LvArray::math::abs(m_stateVariable[k]), LvArray::math::abs(stateVariableLowOrder) )); + } + + private: + + arrayView1d< real64 > const m_stateVariable; + + arrayView1d< real64 > const m_stateVariable_n; + + arrayView1d< real64 > const m_slipRate; + + arrayView2d< real64 > const m_slipVelocity; + + arrayView2d< real64 > const m_slipVelocity_n; + + arrayView2d< real64 > const m_deltaSlip; + + arrayView2d< real64 > const m_deltaSlip_n; + + arrayView2d< real64 > const m_dispJump; + + arrayView2d< real64 > const m_dispJump_n; + + arrayView2d< real64 > const m_error; + + arrayView3d< real64 > const m_stageRates; + + constitutive::RateAndStateFriction::KernelWrapper m_frictionLaw; + + Table m_butcherTable; +}; + } /* namespace rateAndStateKernels */ -}/* namespace geos */ +} /* namespace geos */ #endif /* GEOS_PHYSICSSOLVERS_RATEANDSTATEKERNELS_HPP_ */ diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp index 6c44477836f..53864de3214 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp @@ -72,13 +72,6 @@ DECLARE_FIELD( stateVariable_n, WRITE_AND_READ, "Initial rate- and state-dependent friction state variable at this time step" ); -DECLARE_FIELD( stateVariableRKStageRate, - "stateVariableStageRates", - array2d< real64 >, - 0.0, - NOPLOT, - WRITE_AND_READ, - "Runge-Kutta stage rates for friction state variable" ); DECLARE_FIELD( deltaSlip, "deltaSlip", @@ -97,13 +90,14 @@ DECLARE_FIELD( deltaSlip_n, "Initial slip increment at this time step" ); -DECLARE_FIELD( deltaSlipRKStageRate, - "dDeltaSlipStage1", +DECLARE_FIELD( rungeKuttaStageRates, + "rungeKuttaStageRates", array3d< real64 >, 0.0, NOPLOT, WRITE_AND_READ, - "Runge-Kutta stage rates for slip increment" ); + "Runge-Kutta stage rates for rate-and-state variables" ); + DECLARE_FIELD( error, "error", From 35abee20a4d4f4960086d4e97b5a972546621835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Wed, 27 Nov 2024 17:00:16 -0800 Subject: [PATCH 42/53] Add some comments to QuasiDynamicEQRK32 solver --- .../inducedSeismicity/QuasiDynamicEQRK32.cpp | 4 ++-- .../inducedSeismicity/QuasiDynamicEQRK32.hpp | 21 +++++++++++-------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp index 43fc9eda475..aa7d82de640 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp @@ -40,13 +40,13 @@ QuasiDynamicEQRK32::QuasiDynamicEQRK32( const string & name, m_stressSolver( nullptr ), m_stressSolverName( "SpringSlider" ), m_shearImpedance( 0.0 ), + m_butcherTable(RK32Table()), m_timestepAbsTol( 1.0e-5 ), m_timestepRelTol( 1.0e-5 ), m_timestepAcceptSafety( 0.81 ), m_prevTimestepErrors{ 0.0, 0.0 } , m_beta{ 1.0/18.0, 1.0/9.0, 1.0/18.0 }, - m_successfulStep( false ), - m_butcherTable(RK32Table()) + m_successfulStep( false ) { this->registerWrapper( viewKeyStruct::shearImpedanceString(), &m_shearImpedance ). setInputFlag( InputFlags::REQUIRED ). diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp index 5a27a30b861..1e316286dab 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp @@ -105,21 +105,24 @@ class QuasiDynamicEQRK32 : public SolverBase /// shear impedance real64 m_shearImpedance; - /// time step tolerance - real64 m_timestepAbsTol; + /// Runge-Kutta Butcher table (specifies the embedded RK method) + // TODO: The specific type should not be hardcoded! + // Should be possible to change RK-method based on the table. + rateAndStateKernels::RK32Table m_butcherTable; + + /// Parameters for the PID error controller + real64 m_timestepAbsTol; // absolut tolerence - real64 m_timestepRelTol; + real64 m_timestepRelTol; // relative tolerence - real64 m_timestepAcceptSafety; + real64 m_timestepAcceptSafety; // Acceptance safety - real64 m_prevTimestepErrors[2]; + real64 m_prevTimestepErrors[2]; // Errors from last two time steps - /// time step error - real64 m_beta[3]; + real64 m_beta[3]; // Controller parameters - bool m_successfulStep; + bool m_successfulStep; // Flag indicating if the adative time step was accepted - rateAndStateKernels::RK32Table m_butcherTable; class SpringSliderParameters { From 806ac22caaef304a896cca4c1dd0d8c420b71842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Thu, 28 Nov 2024 18:10:20 -0800 Subject: [PATCH 43/53] Add Bogacki-Shampine 3(2) Runge-Kutta method --- .../inducedSeismicity/QuasiDynamicEQRK32.cpp | 123 ++++++++++++------ .../inducedSeismicity/QuasiDynamicEQRK32.hpp | 11 +- .../kernels/RateAndStateKernels.hpp | 77 +++++++++-- 3 files changed, 155 insertions(+), 56 deletions(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp index aa7d82de640..b175d1f09e3 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp @@ -40,9 +40,9 @@ QuasiDynamicEQRK32::QuasiDynamicEQRK32( const string & name, m_stressSolver( nullptr ), m_stressSolverName( "SpringSlider" ), m_shearImpedance( 0.0 ), - m_butcherTable(RK32Table()), - m_timestepAbsTol( 1.0e-5 ), - m_timestepRelTol( 1.0e-5 ), + m_butcherTable(BogackiShampine32Table()), + m_timestepAbsTol( 1.0e-6 ), + m_timestepRelTol( 1.0e-6 ), m_timestepAcceptSafety( 0.81 ), m_prevTimestepErrors{ 0.0, 0.0 } , m_beta{ 1.0/18.0, 1.0/9.0, 1.0/18.0 }, @@ -75,16 +75,6 @@ QuasiDynamicEQRK32::~QuasiDynamicEQRK32() } -// TODO The vectors listed below are only temporary memory buffers used within an adaptive -// time step in the solverStep function. They don't need to persist between time steps, -// and could be allocated in the beginning of each call to solverStep, instead of -// being managed by the region manager. This would of course result in more heap allocations. -// Not sure what is preferable. -// -// slipVelocity_n -// traction_n -// deltaSlip_n -// stateVariable_n void QuasiDynamicEQRK32::registerDataOnMesh( Group & meshBodies ) { SolverBase::registerDataOnMesh( meshBodies ); @@ -115,12 +105,10 @@ void QuasiDynamicEQRK32::registerDataOnMesh( Group & meshBodies ) subRegion.registerField< rateAndState::deltaSlip_n >( getName() ). setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); - // Runge-Kutta stage rates - subRegion.registerField< rateAndState::rungeKuttaStageRates >( getName() ).reference().resizeDimension< 1, 2>( 3, 3 ); - // Error - string const labelsError[3] = { "deltaSlip1", "deltaSlip2", "stateVariable"}; - subRegion.registerField< rateAndState::error >( getName() ). - setDimLabels( 1, labelsError ).reference().resizeDimension< 1 >( 3 ); + // Runge-Kutta stage rates and error + integer const numRKComponents = 3; + subRegion.registerField< rateAndState::rungeKuttaStageRates >( getName() ).reference().resizeDimension< 1, 2>( m_butcherTable.numStages, numRKComponents); + subRegion.registerField< rateAndState::error >( getName() ).reference().resizeDimension< 1 >( numRKComponents ); if( !subRegion.hasWrapper( contact::dispJump::key() )) @@ -180,25 +168,36 @@ real64 QuasiDynamicEQRK32::solverStep( real64 const & time_n, GEOS_LOG_LEVEL_RANK_0( 1, "Begin adaptive time step" ); while (true) // Adaptive time step loop. Performs a Runge-Kutta time stepping with error control on state and slip { - real64 dtStress; - GEOS_UNUSED_VAR( dtStress ); - for (integer stageIndex = 0; stageIndex < m_butcherTable.numStages-1; stageIndex++) - { + real64 dtStress;GEOS_UNUSED_VAR( dtStress ); + + // Initial Runge-Kutta stage + stepRateStateODEInitialSubstage(dtAdaptive, domain ); + real64 dtStage = m_butcherTable.c[1]*dtAdaptive; + dtStress = updateStresses( time_n, dtStage, cycleNumber, domain ); + updateSlipVelocity( time_n, dtStage, domain ); + + // Remaining stages + for (integer stageIndex = 1; stageIndex < m_butcherTable.numStages-1; stageIndex++) + { stepRateStateODESubstage( stageIndex, dtAdaptive, domain ); - real64 dtStage = m_butcherTable.c[stageIndex+1]*dtAdaptive; + dtStage = m_butcherTable.c[stageIndex+1]*dtAdaptive; dtStress = updateStresses( time_n, dtStage, cycleNumber, domain ); updateSlipVelocity( time_n, dtStage, domain ); } + stepRateStateODEAndComputeError(dtAdaptive, domain); // Update timestep based on the time step error real64 const dtNext = setNextDt(dtAdaptive, domain); if (m_successfulStep) // set in setNextDt { // Compute stresses, and slip velocity and save results at updated time, - dtStress = updateStresses( time_n, dtAdaptive, cycleNumber, domain ); - updateSlipVelocity( time_n, dtAdaptive, domain ); + if (!m_butcherTable.FSAL) + { + dtStress = updateStresses( time_n, dtAdaptive, cycleNumber, domain ); + updateSlipVelocity( time_n, dtAdaptive, domain ); + } saveState(domain); - // pdate the time step and exit the adaptive time step loop + // update the time step and exit the adaptive time step loop dtAdaptive = dtNext; break; } @@ -212,6 +211,44 @@ real64 QuasiDynamicEQRK32::solverStep( real64 const & time_n, return dtAdaptive; } +void QuasiDynamicEQRK32::stepRateStateODEInitialSubstage(real64 const dt, DomainPartition & domain ) const +{ + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + + { + mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) + { + + string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); + RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); + rateAndStateKernels::EmbeddedRungeKuttaKernel rkKernel( subRegion, frictionLaw, m_butcherTable); + arrayView3d< real64 > const rkStageRates = subRegion.getField< rateAndState::rungeKuttaStageRates >(); + + if (m_butcherTable.FSAL && m_successfulStep) + { + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + rkKernel.updateStageRatesFSAL(k); + rkKernel.updateStageValues(k, 1, dt); + } ); + } + else + { + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + rkKernel.initialize(k); + rkKernel.updateStageRates(k, 0); + rkKernel.updateStageValues(k, 1, dt); + } ); + } + } ); + } ); +} void QuasiDynamicEQRK32::stepRateStateODESubstage( integer const stageIndex, real64 const dt, @@ -235,10 +272,6 @@ void QuasiDynamicEQRK32::stepRateStateODESubstage( integer const stageIndex, forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { - if (stageIndex == 0) - { - rkKernel.initialize(k); - } rkKernel.updateStageRates(k, stageIndex); rkKernel.updateStageValues(k, stageIndex+1, dt); } ); @@ -262,14 +295,26 @@ void QuasiDynamicEQRK32::stepRateStateODEAndComputeError(real64 const dt, Domain RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); rateAndStateKernels::EmbeddedRungeKuttaKernel rkKernel( subRegion, frictionLaw, m_butcherTable); arrayView3d< real64 > const rkStageRates = subRegion.getField< rateAndState::rungeKuttaStageRates >(); - - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) - { - // Perform last stage rate update - rkKernel.updateStageRates(k, m_butcherTable.numStages-1); - // Update solution to final time and compute errors - rkKernel.updateSolutionAndLocalError(k, dt, m_timestepAbsTol, m_timestepRelTol); - } ); + if (m_butcherTable.FSAL) + { + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + // Perform last stage rate update + rkKernel.updateStageRates(k, m_butcherTable.numStages-1); + // Update solution to final time and compute errors + rkKernel.updateSolutionAndLocalErrorFSAL(k, dt, m_timestepAbsTol, m_timestepRelTol); + } ); + } + else + { + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + // Perform last stage rate update + rkKernel.updateStageRates(k, m_butcherTable.numStages-1); + // Update solution to final time and compute errors + rkKernel.updateSolutionAndLocalError(k, dt, m_timestepAbsTol, m_timestepRelTol); + } ); + } } ); } ); } diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp index 1e316286dab..520ac68cafa 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp @@ -69,12 +69,13 @@ class QuasiDynamicEQRK32 : public SolverBase virtual void postInputInitialization() override; + void stepRateStateODEInitialSubstage( real64 const dt, DomainPartition & domain ) const; + void stepRateStateODESubstage( integer const stageIndex, - real64 const dt, - DomainPartition & domain ) const; + real64 const dt, + DomainPartition & domain ) const; - void stepRateStateODEAndComputeError(real64 const dt, - DomainPartition & domain ) const; + void stepRateStateODEAndComputeError(real64 const dt, DomainPartition & domain ) const; real64 updateStresses( real64 const & time_n, real64 const & dt, @@ -108,7 +109,7 @@ class QuasiDynamicEQRK32 : public SolverBase /// Runge-Kutta Butcher table (specifies the embedded RK method) // TODO: The specific type should not be hardcoded! // Should be possible to change RK-method based on the table. - rateAndStateKernels::RK32Table m_butcherTable; + rateAndStateKernels::BogackiShampine32Table m_butcherTable; /// Parameters for the PID error controller real64 m_timestepAbsTol; // absolut tolerence diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index 6342a4b96a4..ab97cbe9252 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -326,11 +326,26 @@ struct RK32Table integer const algHighOrder = 3; integer const algLowOrder = 2; integer const numStages = 3; - real64 const a[2][2] = { { 1.0/2.0, 0.0}, // Coefficients for stage value updates - { -1.0, 2.0} }; // (lower-triangular part of table). - real64 const c[3] = { 0.0, 1.0/2.0, 1.0}; // Coefficients for time increments of substages + real64 const a[2][2] = { { 1.0/2.0, 0.0 }, // Coefficients for stage value updates + { -1.0, 2.0 } }; // (lower-triangular part of table). + real64 const c[3] = { 0.0, 1.0/2.0, 1.0 }; // Coefficients for time increments of substages real64 const b[3] = { 1.0/6.0, 4.0/6.0, 1.0/6.0 }; // Quadrature weights used to evolve the solution to next time real64 const bStar[3] = { 1.0/2.0, 0.0, 1.0/2.0 }; // Quadrature weights used for low-order comparision solution + real64 const FSAL = false; +}; + +struct BogackiShampine32Table +{ + integer const algHighOrder = 3; + integer const algLowOrder = 2; + integer const numStages = 4; + real64 const a[3][3] = { { 1.0/2.0, 0.0, 0.0 }, // Coefficients for stage value updates + { 0.0, 3.0/4.0, 0.0 }, + { 2.0/9.0, 1.0/3.0, 4.0/9.0 } }; // (lower-triangular part of table). + real64 const c[4] = { 0.0, 1.0/2.0, 3.0/4.0, 1.0 }; // Coefficients for time increments of substages + real64 const b[4] = { 2.0/9.0, 1.0/3.0, 4.0/9.0, 0.0 }; // Quadrature weights used to evolve the solution to next time + real64 const bStar[4] = { 7.0/24.0, 1.0/4.0, 1.0/3.0, 1.0/8.0}; // Quadrature weights used for low-order comparision solution + bool FSAL = true; // first same as last (can reuse the last stage rate) }; template class EmbeddedRungeKuttaKernel @@ -362,8 +377,13 @@ template class EmbeddedRungeKuttaKernel m_slipRate[k] = LvArray::tensorOps::l2Norm<2>(m_slipVelocity_n[k]); m_stateVariable[k] = m_stateVariable_n[k]; } - - GEOS_HOST_DEVICE + + GEOS_HOST_DEVICE + void updateStageRatesFSAL(localIndex const k) const + { + LvArray::tensorOps::copy<3>(m_stageRates[k][0],m_stageRates[k][m_butcherTable.numStages-1]); + } + void updateStageRates(localIndex const k, localIndex const stageIndex) const { m_stageRates[k][stageIndex][0] = m_slipVelocity[k][0]; @@ -401,7 +421,7 @@ template class EmbeddedRungeKuttaKernel real64 stateVariableIncrement = 0.0; real64 stateVariableIncrementLowOrder = 0.0; - + for (localIndex i = 0; i < m_butcherTable.numStages; i++) { @@ -428,12 +448,45 @@ template class EmbeddedRungeKuttaKernel m_dispJump[k][2] = m_dispJump_n[k][2] + m_deltaSlip[k][1]; // Compute error - m_error[k][0] = (m_deltaSlip[k][0] - deltaSlipLowOrder[0]) / - ( absTol + relTol * LvArray::math::max( LvArray::math::abs(m_deltaSlip[k][0]), LvArray::math::abs(deltaSlipLowOrder[0]) )); - m_error[k][1] = (m_deltaSlip[k][1] - deltaSlipLowOrder[1]) / - ( absTol + relTol * LvArray::math::max( LvArray::math::abs(m_deltaSlip[k][1]), LvArray::math::abs(deltaSlipLowOrder[1]) )); - m_error[k][2] = (m_stateVariable[k] - stateVariableLowOrder) / - ( absTol + relTol * LvArray::math::max( LvArray::math::abs(m_stateVariable[k]), LvArray::math::abs(stateVariableLowOrder) )); + m_error[k][0] = computeError(m_deltaSlip[k][0], deltaSlipLowOrder[0], absTol, relTol); + m_error[k][1] = computeError(m_deltaSlip[k][1], deltaSlipLowOrder[1], absTol, relTol); + m_error[k][2] = computeError(m_stateVariable[k], stateVariableLowOrder, absTol, relTol); + } + + GEOS_HOST_DEVICE + void updateSolutionAndLocalErrorFSAL(localIndex const k, real64 const dt, real64 const absTol, real64 const relTol) const + { + + real64 deltaSlipIncrementLowOrder[2] = {0.0, 0.0}; + real64 stateVariableIncrementLowOrder = 0.0; + + for (localIndex i = 0; i < m_butcherTable.numStages; i++) + { + // In FSAL algorithms the last RK substage update coincides with the + // high-order update. Only need to compute increments for the the + // low-order updates for error computation. + deltaSlipIncrementLowOrder[0] += m_butcherTable.bStar[i] * m_stageRates[k][i][0]; + deltaSlipIncrementLowOrder[1] += m_butcherTable.bStar[i] * m_stageRates[k][i][1]; + stateVariableIncrementLowOrder += m_butcherTable.bStar[i] * m_stageRates[k][i][2]; + } + + real64 const deltaSlipLowOrder[2] = {m_deltaSlip_n[k][0] + dt * deltaSlipIncrementLowOrder[0], + m_deltaSlip_n[k][1] + dt * deltaSlipIncrementLowOrder[1]}; + real64 const stateVariableLowOrder = m_stateVariable_n[k] + dt * stateVariableIncrementLowOrder; + + m_dispJump[k][1] = m_dispJump_n[k][1] + m_deltaSlip[k][0]; + m_dispJump[k][2] = m_dispJump_n[k][2] + m_deltaSlip[k][1]; + + // Compute error + m_error[k][0] = computeError(m_deltaSlip[k][0], deltaSlipLowOrder[0], absTol, relTol); + m_error[k][1] = computeError(m_deltaSlip[k][1], deltaSlipLowOrder[1], absTol, relTol); + m_error[k][2] = computeError(m_stateVariable[k], stateVariableLowOrder, absTol, relTol); + } + + real64 computeError(real64 const highOrderApprox, real64 const lowOrderApprox, real64 const absTol, real64 const relTol) const + { + return (highOrderApprox - lowOrderApprox) / + ( absTol + relTol * LvArray::math::max( LvArray::math::abs(highOrderApprox), LvArray::math::abs(lowOrderApprox) )); } private: From 9d21e4e8c9b47e06912c714153bcbf600b7e8d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Fri, 29 Nov 2024 13:56:30 -0800 Subject: [PATCH 44/53] Add PIDController class for time step control --- .../inducedSeismicity/QuasiDynamicEQRK32.cpp | 35 ++++------- .../inducedSeismicity/QuasiDynamicEQRK32.hpp | 63 ++++++++++++++++--- 2 files changed, 68 insertions(+), 30 deletions(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp index b175d1f09e3..14b21e15c1b 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp @@ -40,13 +40,10 @@ QuasiDynamicEQRK32::QuasiDynamicEQRK32( const string & name, m_stressSolver( nullptr ), m_stressSolverName( "SpringSlider" ), m_shearImpedance( 0.0 ), - m_butcherTable(BogackiShampine32Table()), - m_timestepAbsTol( 1.0e-6 ), - m_timestepRelTol( 1.0e-6 ), - m_timestepAcceptSafety( 0.81 ), - m_prevTimestepErrors{ 0.0, 0.0 } , - m_beta{ 1.0/18.0, 1.0/9.0, 1.0/18.0 }, - m_successfulStep( false ) + m_butcherTable(BogackiShampine32Table()), // TODO: The butcher table should be specified in the XML input. + m_successfulStep( false ), + m_controller(PIDController({ 1.0/18.0, 1.0/9.0, 1.0/18.0 }, + 1.0e-6, 1.0e-6, 0.81)) // TODO: The control parameters should be specified in the XML input { this->registerWrapper( viewKeyStruct::shearImpedanceString(), &m_shearImpedance ). setInputFlag( InputFlags::REQUIRED ). @@ -302,7 +299,7 @@ void QuasiDynamicEQRK32::stepRateStateODEAndComputeError(real64 const dt, Domain // Perform last stage rate update rkKernel.updateStageRates(k, m_butcherTable.numStages-1); // Update solution to final time and compute errors - rkKernel.updateSolutionAndLocalErrorFSAL(k, dt, m_timestepAbsTol, m_timestepRelTol); + rkKernel.updateSolutionAndLocalErrorFSAL(k, dt, m_controller.absTol, m_controller.relTol); } ); } else @@ -312,7 +309,7 @@ void QuasiDynamicEQRK32::stepRateStateODEAndComputeError(real64 const dt, Domain // Perform last stage rate update rkKernel.updateStageRates(k, m_butcherTable.numStages-1); // Update solution to final time and compute errors - rkKernel.updateSolutionAndLocalError(k, dt, m_timestepAbsTol, m_timestepRelTol); + rkKernel.updateSolutionAndLocalError(k, dt, m_controller.absTol, m_controller.relTol); } ); } } ); @@ -435,7 +432,6 @@ real64 QuasiDynamicEQRK32::setNextDt( real64 const & currentDt, DomainPartition { // Spring-slider shear traction computation - real64 scaledL2Error = 0.0; forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel const & mesh, arrayView1d< string const > const & regionNames ) @@ -453,24 +449,19 @@ real64 QuasiDynamicEQRK32::setNextDt( real64 const & currentDt, DomainPartition { scaledl2ErrorSquared += LvArray::tensorOps::l2NormSquared<3>(error[k]); } ); - scaledL2Error = LvArray::math::sqrt(MpiWrapper::sum( scaledl2ErrorSquared.get() / (3.0*N) )); + m_controller.errors[0] = LvArray::math::sqrt(MpiWrapper::sum( scaledl2ErrorSquared.get() / (3.0*N) )); } ); } ); - // PID error controller + limiter - real64 const k = LvArray::math::min(m_butcherTable.algHighOrder, m_butcherTable.algLowOrder) + 1.0; - real64 const eps0 = 1.0/(scaledL2Error + std::numeric_limits< real64 >::epsilon()); // n + 1 - real64 const eps1 = 1.0/(m_prevTimestepErrors[0] + std::numeric_limits< real64 >::epsilon()); // n - real64 const eps2 = 1.0/(m_prevTimestepErrors[1] + std::numeric_limits< real64 >::epsilon()); // n-1 - // Limiter is 1.0 + atan(x - 1.0). Here use atan(x) = atan2(x, 1.0) - real64 const dtFactor = 1.0 + LvArray::math::atan2( pow(eps0, m_beta[0] / k ) * pow(eps1, m_beta[1] / k ) * pow(eps2, m_beta[2] / k ) - 1.0, 1.0); - + // Compute update factor to currentDt using PID error controller + limiter + real64 const dtFactor = m_controller.computeUpdateFactor(m_butcherTable.algHighOrder, m_butcherTable.algLowOrder); real64 const nextDt = dtFactor*currentDt; - m_successfulStep = (dtFactor >= m_timestepAcceptSafety) ? true : false; + // Check if step was acceptable + m_successfulStep = (dtFactor >= m_controller.acceptSafety) ? true : false; if ( m_successfulStep ) { - m_prevTimestepErrors[1] = m_prevTimestepErrors[0]; - m_prevTimestepErrors[0] = scaledL2Error; + m_controller.errors[2] = m_controller.errors[1]; + m_controller.errors[1] = m_controller.errors[0]; GEOS_LOG_LEVEL_RANK_0( 1, GEOS_FMT( "Adaptive time step successful. The next dt will be {:.2e} s", nextDt )); } else diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp index 520ac68cafa..5010d65863f 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp @@ -111,18 +111,65 @@ class QuasiDynamicEQRK32 : public SolverBase // Should be possible to change RK-method based on the table. rateAndStateKernels::BogackiShampine32Table m_butcherTable; - /// Parameters for the PID error controller - real64 m_timestepAbsTol; // absolut tolerence + bool m_successfulStep; // Flag indicating if the adative time step was accepted - real64 m_timestepRelTol; // relative tolerence + class PIDController + { +public: - real64 m_timestepAcceptSafety; // Acceptance safety - - real64 m_prevTimestepErrors[2]; // Errors from last two time steps + GEOS_HOST_DEVICE + PIDController(std::array const & controlParameters, real64 absTol, real64 relTol, real64 acceptSafety): + controlParameters{controlParameters}, + absTol(absTol), + relTol(relTol), + acceptSafety(acceptSafety), + errors{{0.0, 0.0, 0.0}} + {} - real64 m_beta[3]; // Controller parameters + /// Default copy constructor + PIDController( PIDController const & ) = default; - bool m_successfulStep; // Flag indicating if the adative time step was accepted + /// Default move constructor + PIDController( PIDController && ) = default; + + /// Deleted default constructor + PIDController() = delete; + + /// Deleted copy assignment operator + PIDController & operator=( PIDController const & ) = delete; + + /// Deleted move assignment operator + PIDController & operator=( PIDController && ) = delete; + + /// Parameters for the PID error controller + const std::array controlParameters; // Controller parameters + + real64 const absTol; // absolut tolerence + + real64 const relTol; // relative tolerence + + real64 const acceptSafety; // Acceptance safety + + std::array errors; // Errors for current and two previous updates + // stored as [n+1, n, n-1] + + real64 computeUpdateFactor(integer const algHighOrder, integer const algLowOrder) + { + // PID error controller + limiter + real64 const k = LvArray::math::min(algHighOrder, algLowOrder) + 1.0; + real64 const eps0 = 1.0/(errors[0] + std::numeric_limits< real64 >::epsilon()); // n + 1 + real64 const eps1 = 1.0/(errors[1] + std::numeric_limits< real64 >::epsilon()); // n + real64 const eps2 = 1.0/(errors[2] + std::numeric_limits< real64 >::epsilon()); // n-1 + // Compute update factor eps0^(beta0/k)*eps1^(beta1/k)*eps2^(beta2/k) where + // beta0 - beta2 are the control parameters. Also apply limiter to smoothen changes. + // Limiter is 1.0 + atan(x - 1.0). Here use atan(x) = atan2(x, 1.0). + return 1.0 + LvArray::math::atan2( pow(eps0, controlParameters[0] / k ) * + pow(eps1, controlParameters[1] / k ) * + pow(eps2, controlParameters[2] / k ) - 1.0, 1.0); + } + }; + + PIDController m_controller; class SpringSliderParameters From da0f674b73de7a3675c5331ea218c77f7c8323d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Fri, 29 Nov 2024 14:48:26 -0800 Subject: [PATCH 45/53] Add comments --- .../kernels/RateAndStateKernels.hpp | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index ab97cbe9252..cf322707168 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -320,32 +320,39 @@ createAndLaunch( SurfaceElementSubRegion & subRegion, } ); } - -struct RK32Table +/** + * @brief Butcher table for embedded RK3(2) method using Kuttas third order + * method for the high-order update, and an explicit trapezoidal rule + * based on the first and third stage rates for the low-order update. + */ +struct Kutta32Table { - integer const algHighOrder = 3; - integer const algLowOrder = 2; - integer const numStages = 3; - real64 const a[2][2] = { { 1.0/2.0, 0.0 }, // Coefficients for stage value updates - { -1.0, 2.0 } }; // (lower-triangular part of table). - real64 const c[3] = { 0.0, 1.0/2.0, 1.0 }; // Coefficients for time increments of substages - real64 const b[3] = { 1.0/6.0, 4.0/6.0, 1.0/6.0 }; // Quadrature weights used to evolve the solution to next time + integer const algHighOrder = 3; // High-order update order + integer const algLowOrder = 2; // Low-order update order + integer const numStages = 3; // Number of stages + real64 const a[2][2] = { { 1.0/2.0, 0.0 }, // Coefficients for stage value updates + { -1.0, 2.0 } }; // (lower-triangular part of table). + real64 const c[3] = { 0.0, 1.0/2.0, 1.0 }; // Coefficients for time increments of substages + real64 const b[3] = { 1.0/6.0, 4.0/6.0, 1.0/6.0 }; // Quadrature weights used to step the solution to next time real64 const bStar[3] = { 1.0/2.0, 0.0, 1.0/2.0 }; // Quadrature weights used for low-order comparision solution - real64 const FSAL = false; + real64 const FSAL = false; // Not first same as last }; +/** + * @brief Butcher table for the BogackiShampine 3(2) method. + */ struct BogackiShampine32Table { - integer const algHighOrder = 3; - integer const algLowOrder = 2; - integer const numStages = 4; - real64 const a[3][3] = { { 1.0/2.0, 0.0, 0.0 }, // Coefficients for stage value updates - { 0.0, 3.0/4.0, 0.0 }, - { 2.0/9.0, 1.0/3.0, 4.0/9.0 } }; // (lower-triangular part of table). - real64 const c[4] = { 0.0, 1.0/2.0, 3.0/4.0, 1.0 }; // Coefficients for time increments of substages - real64 const b[4] = { 2.0/9.0, 1.0/3.0, 4.0/9.0, 0.0 }; // Quadrature weights used to evolve the solution to next time + integer const algHighOrder = 3; // High-order update order + integer const algLowOrder = 2; // Low-order update order + integer const numStages = 4; // Number of stages + real64 const a[3][3] = { { 1.0/2.0, 0.0, 0.0 }, // Coefficients for stage value updates + { 0.0, 3.0/4.0, 0.0 }, // (lower-triangular part of table). + { 2.0/9.0, 1.0/3.0, 4.0/9.0 } }; + real64 const c[4] = { 0.0, 1.0/2.0, 3.0/4.0, 1.0 }; // Coefficients for time increments of substages + real64 const b[4] = { 2.0/9.0, 1.0/3.0, 4.0/9.0, 0.0 }; // Quadrature weights used to step the solution to next time real64 const bStar[4] = { 7.0/24.0, 1.0/4.0, 1.0/3.0, 1.0/8.0}; // Quadrature weights used for low-order comparision solution - bool FSAL = true; // first same as last (can reuse the last stage rate) + bool FSAL = true; // First same as last (can reuse the last stage rate in next update) }; template class EmbeddedRungeKuttaKernel From 66ab9bcd74cc5c125101d29a5ad010ee305dc4d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Thu, 5 Dec 2024 17:23:30 -0800 Subject: [PATCH 46/53] Add xml input for explicit solver, update subrepo, add docs --- .../SpringSliderExplicit_base.xml | 167 ++++++++++++++++++ .../SpringSliderExplicit_smoke.xml | 32 ++++ .../inducedSeismicity/inducedSeismicity.ats | 19 +- src/coreComponents/constitutive/PVTPackage | 2 +- .../inducedSeismicity/QuasiDynamicEQRK32.hpp | 22 ++- .../kernels/RateAndStateKernels.hpp | 60 ++++++- 6 files changed, 282 insertions(+), 20 deletions(-) create mode 100644 inputFiles/inducedSeismicity/SpringSliderExplicit_base.xml create mode 100644 inputFiles/inducedSeismicity/SpringSliderExplicit_smoke.xml diff --git a/inputFiles/inducedSeismicity/SpringSliderExplicit_base.xml b/inputFiles/inducedSeismicity/SpringSliderExplicit_base.xml new file mode 100644 index 00000000000..a0c0381fb23 --- /dev/null +++ b/inputFiles/inducedSeismicity/SpringSliderExplicit_base.xml @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/inputFiles/inducedSeismicity/SpringSliderExplicit_smoke.xml b/inputFiles/inducedSeismicity/SpringSliderExplicit_smoke.xml new file mode 100644 index 00000000000..2de09b79a03 --- /dev/null +++ b/inputFiles/inducedSeismicity/SpringSliderExplicit_smoke.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/inputFiles/inducedSeismicity/inducedSeismicity.ats b/inputFiles/inducedSeismicity/inducedSeismicity.ats index f1c8f1f0285..735b625bebf 100644 --- a/inputFiles/inducedSeismicity/inducedSeismicity.ats +++ b/inputFiles/inducedSeismicity/inducedSeismicity.ats @@ -21,23 +21,20 @@ decks = [ partitions=((1, 1, 1), ), restart_step=0, check_step=100, -<<<<<<< HEAD - curvecheck_params=CurveCheckParameters(**curvecheck_params)) -======= curvecheck_params=CurveCheckParameters(**curvecheck_params)), ->>>>>>> develop TestDeck( name="SpringSlider_smoke", description="Spring slider 0D system", partitions=((1, 1, 1), ), restart_step=0, -<<<<<<< HEAD - check_step=3265, - restartcheck_params=RestartcheckParameters(atol=1e-4, rtol=1e-3) ) - ] -======= check_step=3262, - restartcheck_params=RestartcheckParameters(atol=1e-4, rtol=1e-3)) + restartcheck_params=RestartcheckParameters(atol=1e-4, rtol=1e-3)) + TestDeck( + name="SpringSliderExplicit_smoke", + description="Spring slider 0D system", + partitions=((1, 1, 1), ), + restart_step=0, + check_step=532, + restartcheck_params=RestartcheckParameters(atol=1e-4, rtol=1e-3)) ] ->>>>>>> develop generate_geos_tests(decks) diff --git a/src/coreComponents/constitutive/PVTPackage b/src/coreComponents/constitutive/PVTPackage index 59d81b149e3..3bf1c021569 160000 --- a/src/coreComponents/constitutive/PVTPackage +++ b/src/coreComponents/constitutive/PVTPackage @@ -1 +1 @@ -Subproject commit 59d81b149e35ea5db0d715e608217d8bd56e9291 +Subproject commit 3bf1c02156911768f022fc2954939ee1c1c2f66d diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp index 5adb132e3df..be653c8416c 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp @@ -69,12 +69,28 @@ class QuasiDynamicEQRK32 : public PhysicsSolverBase virtual void postInputInitialization() override; + /** + * @brief Computes stage rates for the initial Runge-Kutta substage and updates slip and state + * @param dt + * @param domain + */ void stepRateStateODEInitialSubstage( real64 const dt, DomainPartition & domain ) const; + /** + * @brief Computes stage rates at the Runge-Kutta substage specified by stageIndex and updates slip and state + * @param stageIndex + * @param dt + * @param domain + */ void stepRateStateODESubstage( integer const stageIndex, real64 const dt, DomainPartition & domain ) const; + /** + * @brief Updates slip and state to t + dt and approximates the error + * @param dt + * @param domain + */ void stepRateStateODEAndComputeError(real64 const dt, DomainPartition & domain ) const; real64 updateStresses( real64 const & time_n, @@ -83,7 +99,7 @@ class QuasiDynamicEQRK32 : public PhysicsSolverBase DomainPartition & domain ) const; /** - * @brief updates rate-and-state slip velocity and slip rate + * @brief Updates rate-and-state slip velocity * @param domain */ void updateSlipVelocity( real64 const & time_n, @@ -113,6 +129,10 @@ class QuasiDynamicEQRK32 : public PhysicsSolverBase bool m_successfulStep; // Flag indicating if the adative time step was accepted + /** + * @brief Proportional-integral-derivative controller used for updating time step + * based error estimate in the current and previous time steps. + */ class PIDController { public: diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index 54e9805a926..e1a7f4982f5 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -265,6 +265,7 @@ class ExplicitRateAndStateKernel /** * @brief Performs the kernel launch + * @tparam KernelType The Rate-and-state kernel to launch * @tparam POLICY the policy used in the RAJA kernels */ template< typename KernelType, typename POLICY > @@ -355,6 +356,13 @@ struct BogackiShampine32Table bool FSAL = true; // First same as last (can reuse the last stage rate in next update) }; +/** + * @brief Runge-Kutta method used to time integrate slip and state. Uses of a high order + * update used to integrate the solutions, and a lower order update to estimate the error + * in the time step. + * + * @tparam Butcher table defining the Runge-Kutta method. + */ template class EmbeddedRungeKuttaKernel { @@ -377,6 +385,9 @@ template class EmbeddedRungeKuttaKernel m_butcherTable( butcherTable ) {} + /** + * @brief Initialize slip and state buffers + */ GEOS_HOST_DEVICE void initialize(localIndex const k) const { @@ -385,27 +396,38 @@ template class EmbeddedRungeKuttaKernel m_stateVariable[k] = m_stateVariable_n[k]; } - GEOS_HOST_DEVICE + /** + * @brief Re-uses the last stage rate from the previous time step as the first + * in the next update. Only valid for FSAL (first-same-as-last) Runge-Kutta methods. + */ + GEOS_HOST_DEVICE void updateStageRatesFSAL(localIndex const k) const { LvArray::tensorOps::copy<3>(m_stageRates[k][0],m_stageRates[k][m_butcherTable.numStages-1]); } - - void updateStageRates(localIndex const k, localIndex const stageIndex) const + + /** + * @brief Updates the stage rates rates (the right-hand-side of the ODEs for slip and state) + */ + GEOS_HOST_DEVICE + void updateStageRates(localIndex const k, integer const stageIndex) const { m_stageRates[k][stageIndex][0] = m_slipVelocity[k][0]; m_stageRates[k][stageIndex][1] = m_slipVelocity[k][1]; m_stageRates[k][stageIndex][2] = m_frictionLaw.stateEvolution(k, m_slipRate[k], m_stateVariable[k]); } + /** + * @brief Update stage values (slip, state and displacement jump) to a Runge-Kutta substage. + */ GEOS_HOST_DEVICE - void updateStageValues(localIndex const k, localIndex const stageIndex, real64 const dt) const + void updateStageValues(localIndex const k, integer const stageIndex, real64 const dt) const { real64 stateVariableIncrement = 0.0; real64 deltaSlipIncrement[2] = {0.0, 0.0}; - for (localIndex i = 0; i < stageIndex; i++) + for (integer i = 0; i < stageIndex; i++) { deltaSlipIncrement[0] += m_butcherTable.a[stageIndex-1][i] * m_stageRates[k][i][0]; deltaSlipIncrement[1] += m_butcherTable.a[stageIndex-1][i] * m_stageRates[k][i][1]; @@ -419,6 +441,10 @@ template class EmbeddedRungeKuttaKernel m_dispJump[k][2] = m_dispJump_n[k][2] + m_deltaSlip[k][1]; } + /** + * @brief Updates slip, state and displacement jump to the next time computes error the local error + * in the time step + */ GEOS_HOST_DEVICE void updateSolutionAndLocalError(localIndex const k, real64 const dt, real64 const absTol, real64 const relTol) const { @@ -460,6 +486,10 @@ template class EmbeddedRungeKuttaKernel m_error[k][2] = computeError(m_stateVariable[k], stateVariableLowOrder, absTol, relTol); } + /** + * @brief Updates slip, state and displacement jump to the next time computes error the local error + * in the time step. Uses the FSAL (first-same-as-last) property. + */ GEOS_HOST_DEVICE void updateSolutionAndLocalErrorFSAL(localIndex const k, real64 const dt, real64 const absTol, real64 const relTol) const { @@ -490,6 +520,9 @@ template class EmbeddedRungeKuttaKernel m_error[k][2] = computeError(m_stateVariable[k], stateVariableLowOrder, absTol, relTol); } + /** + * @brief Computes the relative error scaled by error tolerances + */ real64 computeError(real64 const highOrderApprox, real64 const lowOrderApprox, real64 const absTol, real64 const relTol) const { return (highOrderApprox - lowOrderApprox) / @@ -498,30 +531,43 @@ template class EmbeddedRungeKuttaKernel private: + /// Current state variable arrayView1d< real64 > const m_stateVariable; + /// State variable at t = t_n arrayView1d< real64 > const m_stateVariable_n; + /// Current slip rate (magnitude of slip velocity) arrayView1d< real64 > const m_slipRate; + /// Current slip velocity arrayView2d< real64 > const m_slipVelocity; + /// Slip velocity at time t_n arrayView2d< real64 > const m_slipVelocity_n; + /// Current slip change arrayView2d< real64 > const m_deltaSlip; + /// Slip change at time t_n arrayView2d< real64 > const m_deltaSlip_n; + /// Current displacment jump arrayView2d< real64 > const m_dispJump; - + + /// Displacment jump at time t_n arrayView2d< real64 > const m_dispJump_n; + /// Local error for each solution component stored as slip1, slip2, state arrayView2d< real64 > const m_error; - arrayView3d< real64 > const m_stageRates; + /// Stage rates for each solution component stored as slip1, slip2, state + arrayView3d< real64 > const m_stageRates; + /// Friction law used for rate-and-state updates constitutive::RateAndStateFriction::KernelWrapper m_frictionLaw; + /// Butcher table used for explicit time stepping of rate and state Table m_butcherTable; }; From e9ac3673c7099914364f9249ee5accb502d50c03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Fri, 6 Dec 2024 13:15:22 -0800 Subject: [PATCH 47/53] Address review comments --- .../inducedSeismicity/QuasiDynamicEQ.cpp | 3 +- .../inducedSeismicity/QuasiDynamicEQ.hpp | 2 +- .../inducedSeismicity/QuasiDynamicEQRK32.cpp | 285 +++++------ .../inducedSeismicity/QuasiDynamicEQRK32.hpp | 54 +- .../kernels/RateAndStateKernels.hpp | 477 +++++++++--------- .../inducedSeismicity/rateAndStateFields.hpp | 6 +- 6 files changed, 416 insertions(+), 411 deletions(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp index bd55baddcb7..d00e64357e0 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.cpp @@ -162,7 +162,8 @@ real64 QuasiDynamicEQ::solverStep( real64 const & time_n, SurfaceElementSubRegion & subRegion ) { // solve rate and state equations. - createAndLaunch >( subRegion, viewKeyStruct::frictionLawNameString(), m_shearImpedance, maxIterNewton, newtonTol, time_n, dtStress ); + createAndLaunch< ImplicitFixedStressRateAndStateKernel, parallelDevicePolicy<> >( subRegion, viewKeyStruct::frictionLawNameString(), m_shearImpedance, maxIterNewton, newtonTol, time_n, + dtStress ); // save old state saveOldStateAndUpdateSlip( subRegion, dtStress ); } ); diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp index edff334c003..97b202ee7e6 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQ.hpp @@ -47,7 +47,7 @@ class QuasiDynamicEQ : public PhysicsSolverBase struct viewKeyStruct : public PhysicsSolverBase::viewKeyStruct { /// stress solver name - static constexpr char const * stressSolverNameString() { return "stressSolverName"; } + constexpr static char const * stressSolverNameString() { return "stressSolverName"; } /// Friction law name string constexpr static char const * frictionLawNameString() { return "frictionLawName"; } /// Friction law name string diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp index a96f2f22f28..7b569118934 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.cpp @@ -40,10 +40,10 @@ QuasiDynamicEQRK32::QuasiDynamicEQRK32( const string & name, m_stressSolver( nullptr ), m_stressSolverName( "SpringSlider" ), m_shearImpedance( 0.0 ), - m_butcherTable(BogackiShampine32Table()), // TODO: The butcher table should be specified in the XML input. + m_butcherTable( BogackiShampine32Table()), // TODO: The butcher table should be specified in the XML input. m_successfulStep( false ), - m_controller(PIDController({ 1.0/18.0, 1.0/9.0, 1.0/18.0 }, - 1.0e-6, 1.0e-6, 0.81)) // TODO: The control parameters should be specified in the XML input + m_controller( PIDController( { 1.0/18.0, 1.0/9.0, 1.0/18.0 }, + 1.0e-6, 1.0e-6, 0.81 )) // TODO: The control parameters should be specified in the XML input { this->registerWrapper( viewKeyStruct::shearImpedanceString(), &m_shearImpedance ). setInputFlag( InputFlags::REQUIRED ). @@ -90,23 +90,23 @@ void QuasiDynamicEQRK32::registerDataOnMesh( Group & meshBodies ) subRegion.registerField< rateAndState::stateVariable >( getName() ); subRegion.registerField< rateAndState::stateVariable_n >( getName() ); subRegion.registerField< rateAndState::slipRate >( getName() ); - + // Tangent (2-component) functions on fault string const labels2Comp[2] = {"tangent1", "tangent2" }; subRegion.registerField< rateAndState::slipVelocity >( getName() ). setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); subRegion.registerField< rateAndState::slipVelocity_n >( getName() ). - setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); + setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); subRegion.registerField< rateAndState::deltaSlip >( getName() ). setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); subRegion.registerField< rateAndState::deltaSlip_n >( getName() ). - setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); + setDimLabels( 1, labels2Comp ).reference().resizeDimension< 1 >( 2 ); // Runge-Kutta stage rates and error integer const numRKComponents = 3; - subRegion.registerField< rateAndState::rungeKuttaStageRates >( getName() ).reference().resizeDimension< 1, 2>( m_butcherTable.numStages, numRKComponents); - subRegion.registerField< rateAndState::error >( getName() ).reference().resizeDimension< 1 >( numRKComponents ); - + subRegion.registerField< rateAndState::rungeKuttaStageRates >( getName() ).reference().resizeDimension< 1, 2 >( m_butcherTable.numStages, numRKComponents ); + subRegion.registerField< rateAndState::error >( getName() ).reference().resizeDimension< 1 >( numRKComponents ); + if( !subRegion.hasWrapper( contact::dispJump::key() )) { @@ -117,13 +117,13 @@ void QuasiDynamicEQRK32::registerDataOnMesh( Group & meshBodies ) reference().resizeDimension< 1 >( 3 ); subRegion.registerField< contact::dispJump_n >( getName() ). setDimLabels( 1, labels3Comp ). - reference().resizeDimension< 1 >( 3 ); + reference().resizeDimension< 1 >( 3 ); subRegion.registerField< contact::traction >( getName() ). setDimLabels( 1, labels3Comp ). reference().resizeDimension< 1 >( 3 ); subRegion.registerField< contact::traction_n >( getName() ). setDimLabels( 1, labels3Comp ). - reference().resizeDimension< 1 >( 3 ); + reference().resizeDimension< 1 >( 3 ); subRegion.registerWrapper< string >( viewKeyStruct::frictionLawNameString() ). setPlotLevel( PlotLevel::NOPLOT ). @@ -157,43 +157,43 @@ real64 QuasiDynamicEQRK32::solverStep( real64 const & time_n, fieldSpecificationManager.applyInitialConditions( mesh ); } ); - saveState(domain); + saveState( domain ); } real64 dtAdaptive = dt; GEOS_LOG_LEVEL_RANK_0( 1, "Begin adaptive time step" ); - while (true) // Adaptive time step loop. Performs a Runge-Kutta time stepping with error control on state and slip + while( true ) // Adaptive time step loop. Performs a Runge-Kutta time stepping with error control on state and slip { - real64 dtStress;GEOS_UNUSED_VAR( dtStress ); + real64 dtStress; GEOS_UNUSED_VAR( dtStress ); // Initial Runge-Kutta stage - stepRateStateODEInitialSubstage(dtAdaptive, domain ); + stepRateStateODEInitialSubstage( dtAdaptive, domain ); real64 dtStage = m_butcherTable.c[1]*dtAdaptive; dtStress = updateStresses( time_n, dtStage, cycleNumber, domain ); updateSlipVelocity( time_n, dtStage, domain ); - + // Remaining stages - for (integer stageIndex = 1; stageIndex < m_butcherTable.numStages-1; stageIndex++) - { + for( integer stageIndex = 1; stageIndex < m_butcherTable.numStages-1; stageIndex++ ) + { stepRateStateODESubstage( stageIndex, dtAdaptive, domain ); - dtStage = m_butcherTable.c[stageIndex+1]*dtAdaptive; + dtStage = m_butcherTable.c[stageIndex+1]*dtAdaptive; dtStress = updateStresses( time_n, dtStage, cycleNumber, domain ); updateSlipVelocity( time_n, dtStage, domain ); } - - stepRateStateODEAndComputeError(dtAdaptive, domain); - // Update timestep based on the time step error - real64 const dtNext = setNextDt(dtAdaptive, domain); - if (m_successfulStep) // set in setNextDt + + stepRateStateODEAndComputeError( dtAdaptive, domain ); + // Update timestep based on the time step error + real64 const dtNext = setNextDt( dtAdaptive, domain ); + if( m_successfulStep ) // set in setNextDt { // Compute stresses, and slip velocity and save results at updated time, - if (!m_butcherTable.FSAL) + if( !m_butcherTable.FSAL ) { dtStress = updateStresses( time_n, dtAdaptive, cycleNumber, domain ); updateSlipVelocity( time_n, dtAdaptive, domain ); - } - saveState(domain); + } + saveState( domain ); // update the time step and exit the adaptive time step loop dtAdaptive = dtNext; break; @@ -208,118 +208,118 @@ real64 QuasiDynamicEQRK32::solverStep( real64 const & time_n, return dtAdaptive; } -void QuasiDynamicEQRK32::stepRateStateODEInitialSubstage(real64 const dt, DomainPartition & domain ) const +void QuasiDynamicEQRK32::stepRateStateODEInitialSubstage( real64 const dt, DomainPartition & domain ) const { - + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) { - mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, - [&]( localIndex const, - SurfaceElementSubRegion & subRegion ) + + string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); + RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); + rateAndStateKernels::EmbeddedRungeKuttaKernel rkKernel( subRegion, frictionLaw, m_butcherTable ); + arrayView3d< real64 > const rkStageRates = subRegion.getField< rateAndState::rungeKuttaStageRates >(); + + if( m_butcherTable.FSAL && m_successfulStep ) { - - string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); - RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); - rateAndStateKernels::EmbeddedRungeKuttaKernel rkKernel( subRegion, frictionLaw, m_butcherTable); - arrayView3d< real64 > const rkStageRates = subRegion.getField< rateAndState::rungeKuttaStageRates >(); - - if (m_butcherTable.FSAL && m_successfulStep) - { - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) - { - rkKernel.updateStageRatesFSAL(k); - rkKernel.updateStageValues(k, 1, dt); - } ); - } - else + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { + rkKernel.updateStageRatesFSAL( k ); + rkKernel.updateStageValues( k, 1, dt ); + } ); + } + else + { forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) - { - rkKernel.initialize(k); - rkKernel.updateStageRates(k, 0); - rkKernel.updateStageValues(k, 1, dt); + { + rkKernel.initialize( k ); + rkKernel.updateStageRates( k, 0 ); + rkKernel.updateStageValues( k, 1, dt ); } ); - } - } ); + } } ); + } ); } void QuasiDynamicEQRK32::stepRateStateODESubstage( integer const stageIndex, real64 const dt, DomainPartition & domain ) const { - + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) { - mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, - [&]( localIndex const, - SurfaceElementSubRegion & subRegion ) + + string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); + RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); + rateAndStateKernels::EmbeddedRungeKuttaKernel rkKernel( subRegion, frictionLaw, m_butcherTable ); + arrayView3d< real64 > const rkStageRates = subRegion.getField< rateAndState::rungeKuttaStageRates >(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { - - string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); - RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); - rateAndStateKernels::EmbeddedRungeKuttaKernel rkKernel( subRegion, frictionLaw, m_butcherTable); - arrayView3d< real64 > const rkStageRates = subRegion.getField< rateAndState::rungeKuttaStageRates >(); - - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) - { - rkKernel.updateStageRates(k, stageIndex); - rkKernel.updateStageValues(k, stageIndex+1, dt); - } ); + rkKernel.updateStageRates( k, stageIndex ); + rkKernel.updateStageValues( k, stageIndex+1, dt ); } ); } ); + } ); } -void QuasiDynamicEQRK32::stepRateStateODEAndComputeError(real64 const dt, DomainPartition & domain ) const +void QuasiDynamicEQRK32::stepRateStateODEAndComputeError( real64 const dt, DomainPartition & domain ) const { forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) { - mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, - [&]( localIndex const, - SurfaceElementSubRegion & subRegion ) + + string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); + RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); + rateAndStateKernels::EmbeddedRungeKuttaKernel rkKernel( subRegion, frictionLaw, m_butcherTable ); + arrayView3d< real64 > const rkStageRates = subRegion.getField< rateAndState::rungeKuttaStageRates >(); + if( m_butcherTable.FSAL ) { - - string const & fricitonLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); - RateAndStateFriction const & frictionLaw = getConstitutiveModel< RateAndStateFriction >( subRegion, fricitonLawName ); - rateAndStateKernels::EmbeddedRungeKuttaKernel rkKernel( subRegion, frictionLaw, m_butcherTable); - arrayView3d< real64 > const rkStageRates = subRegion.getField< rateAndState::rungeKuttaStageRates >(); - if (m_butcherTable.FSAL) + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) - { - // Perform last stage rate update - rkKernel.updateStageRates(k, m_butcherTable.numStages-1); - // Update solution to final time and compute errors - rkKernel.updateSolutionAndLocalErrorFSAL(k, dt, m_controller.absTol, m_controller.relTol); - } ); - } - else + // Perform last stage rate update + rkKernel.updateStageRates( k, m_butcherTable.numStages-1 ); + // Update solution to final time and compute errors + rkKernel.updateSolutionAndLocalErrorFSAL( k, dt, m_controller.absTol, m_controller.relTol ); + } ); + } + else + { + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) - { - // Perform last stage rate update - rkKernel.updateStageRates(k, m_butcherTable.numStages-1); - // Update solution to final time and compute errors - rkKernel.updateSolutionAndLocalError(k, dt, m_controller.absTol, m_controller.relTol); - } ); - } - } ); - } ); + // Perform last stage rate update + rkKernel.updateStageRates( k, m_butcherTable.numStages-1 ); + // Update solution to final time and compute errors + rkKernel.updateSolutionAndLocalError( k, dt, m_controller.absTol, m_controller.relTol ); + } ); + } + } ); + } ); } real64 QuasiDynamicEQRK32::updateStresses( real64 const & time_n, - real64 const & dt, - const int cycleNumber, - DomainPartition & domain ) const + real64 const & dt, + const int cycleNumber, + DomainPartition & domain ) const { GEOS_LOG_LEVEL_RANK_0( 1, "Stress solver" ); // Call member variable stress solver to update the stress state @@ -372,8 +372,8 @@ real64 QuasiDynamicEQRK32::updateStresses( real64 const & time_n, } void QuasiDynamicEQRK32::updateSlipVelocity( real64 const & time_n, - real64 const & dt, - DomainPartition & domain ) const + real64 const & dt, + DomainPartition & domain ) const { GEOS_LOG_LEVEL_RANK_0( 1, "Rate and State solver" ); integer const maxIterNewton = m_nonlinearSolverParameters.m_maxIterNewton; @@ -388,44 +388,45 @@ void QuasiDynamicEQRK32::updateSlipVelocity( real64 const & time_n, SurfaceElementSubRegion & subRegion ) { // solve rate and state equations. - rateAndStateKernels::createAndLaunch >( subRegion, viewKeyStruct::frictionLawNameString(), m_shearImpedance, maxIterNewton, newtonTol, time_n, dt ); + rateAndStateKernels::createAndLaunch< rateAndStateKernels::ExplicitRateAndStateKernel, parallelDevicePolicy<> >( subRegion, viewKeyStruct::frictionLawNameString(), m_shearImpedance, + maxIterNewton, newtonTol, time_n, dt ); } ); } ); } -void QuasiDynamicEQRK32::saveState( DomainPartition & domain) const +void QuasiDynamicEQRK32::saveState( DomainPartition & domain ) const { forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + SurfaceElementSubRegion & subRegion ) { - mesh.getElemManager().forElementSubRegions< SurfaceElementSubRegion >( regionNames, - [&]( localIndex const, - SurfaceElementSubRegion & subRegion ) - { - arrayView1d< real64 const > const stateVariable = subRegion.getField< rateAndState::stateVariable >(); - arrayView2d< real64 const > const slipVelocity = subRegion.getField< rateAndState::slipVelocity >(); - arrayView2d< real64 const > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); - arrayView2d< real64 const > const dispJump = subRegion.getField< contact::dispJump >(); - arrayView2d< real64 const > const traction = subRegion.getField< contact::traction >(); - - arrayView1d< real64 > const stateVariable_n = subRegion.getField< rateAndState::stateVariable_n >(); - arrayView2d< real64 > const slipVelocity_n = subRegion.getField< rateAndState::slipVelocity_n >(); - arrayView2d< real64 > const deltaSlip_n = subRegion.getField< rateAndState::deltaSlip >(); - arrayView2d< real64 > const dispJump_n = subRegion.getField< contact::dispJump_n >(); - arrayView2d< real64 > const traction_n = subRegion.getField< contact::traction_n >(); + arrayView1d< real64 const > const stateVariable = subRegion.getField< rateAndState::stateVariable >(); + arrayView2d< real64 const > const slipVelocity = subRegion.getField< rateAndState::slipVelocity >(); + arrayView2d< real64 const > const deltaSlip = subRegion.getField< rateAndState::deltaSlip >(); + arrayView2d< real64 const > const dispJump = subRegion.getField< contact::dispJump >(); + arrayView2d< real64 const > const traction = subRegion.getField< contact::traction >(); + + arrayView1d< real64 > const stateVariable_n = subRegion.getField< rateAndState::stateVariable_n >(); + arrayView2d< real64 > const slipVelocity_n = subRegion.getField< rateAndState::slipVelocity_n >(); + arrayView2d< real64 > const deltaSlip_n = subRegion.getField< rateAndState::deltaSlip >(); + arrayView2d< real64 > const dispJump_n = subRegion.getField< contact::dispJump_n >(); + arrayView2d< real64 > const traction_n = subRegion.getField< contact::traction_n >(); - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) - { - stateVariable_n[k] = stateVariable[k]; - LvArray::tensorOps::copy< 2 >( deltaSlip_n[k], deltaSlip[k] ); - LvArray::tensorOps::copy< 2 >( slipVelocity_n[k], slipVelocity[k] ); - LvArray::tensorOps::copy< 3 >( dispJump_n[k], dispJump[k] ); - LvArray::tensorOps::copy< 3 >( traction_n[k], traction[k] ); - } ); + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + stateVariable_n[k] = stateVariable[k]; + LvArray::tensorOps::copy< 2 >( deltaSlip_n[k], deltaSlip[k] ); + LvArray::tensorOps::copy< 2 >( slipVelocity_n[k], slipVelocity[k] ); + LvArray::tensorOps::copy< 3 >( dispJump_n[k], dispJump[k] ); + LvArray::tensorOps::copy< 3 >( traction_n[k], traction[k] ); } ); } ); + } ); } real64 QuasiDynamicEQRK32::setNextDt( real64 const & currentDt, DomainPartition & domain ) @@ -447,26 +448,26 @@ real64 QuasiDynamicEQRK32::setNextDt( real64 const & currentDt, DomainPartition integer const N = subRegion.size(); forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const k ) { - scaledl2ErrorSquared += LvArray::tensorOps::l2NormSquared<3>(error[k]); + scaledl2ErrorSquared += LvArray::tensorOps::l2NormSquared< 3 >( error[k] ); } ); - m_controller.errors[0] = LvArray::math::sqrt(MpiWrapper::sum( scaledl2ErrorSquared.get() / (3.0*N) )); - } ); + m_controller.errors[0] = LvArray::math::sqrt( MpiWrapper::sum( scaledl2ErrorSquared.get() / (3.0*N) )); + } ); } ); // Compute update factor to currentDt using PID error controller + limiter - real64 const dtFactor = m_controller.computeUpdateFactor(m_butcherTable.algHighOrder, m_butcherTable.algLowOrder); + real64 const dtFactor = m_controller.computeUpdateFactor( m_butcherTable.algHighOrder, m_butcherTable.algLowOrder ); real64 const nextDt = dtFactor*currentDt; // Check if step was acceptable m_successfulStep = (dtFactor >= m_controller.acceptSafety) ? true : false; - if ( m_successfulStep ) + if( m_successfulStep ) { m_controller.errors[2] = m_controller.errors[1]; m_controller.errors[1] = m_controller.errors[0]; - GEOS_LOG_LEVEL_RANK_0( 1, GEOS_FMT( "Adaptive time step successful. The next dt will be {:.2e} s", nextDt )); + GEOS_LOG_LEVEL_RANK_0( 1, GEOS_FMT( "Adaptive time step successful. The next dt will be {:.2e} s", nextDt )); } else { - GEOS_LOG_LEVEL_RANK_0( 1, GEOS_FMT( "Adaptive time step failed. The next dt will be {:.2e} s", nextDt )); + GEOS_LOG_LEVEL_RANK_0( 1, GEOS_FMT( "Adaptive time step failed. The next dt will be {:.2e} s", nextDt )); } return nextDt; diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp index be653c8416c..e2e94bd21c5 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp @@ -30,7 +30,7 @@ class QuasiDynamicEQRK32 : public PhysicsSolverBase /// The constructor needs a user-defined "name" and a parent Group (to place this instance in the tree structure of classes) QuasiDynamicEQRK32( const string & name, - Group * const parent ); + Group * const parent ); /// Destructor virtual ~QuasiDynamicEQRK32() override; @@ -48,7 +48,7 @@ class QuasiDynamicEQRK32 : public PhysicsSolverBase struct viewKeyStruct : public PhysicsSolverBase::viewKeyStruct { /// stress solver name - static constexpr char const * stressSolverNameString() { return "stressSolverName"; } + constexpr static char const * stressSolverNameString() { return "stressSolverName"; } /// Friction law name string constexpr static char const * frictionLawNameString() { return "frictionLawName"; } /// Friction law name string @@ -72,10 +72,10 @@ class QuasiDynamicEQRK32 : public PhysicsSolverBase /** * @brief Computes stage rates for the initial Runge-Kutta substage and updates slip and state * @param dt - * @param domain + * @param domain */ void stepRateStateODEInitialSubstage( real64 const dt, DomainPartition & domain ) const; - + /** * @brief Computes stage rates at the Runge-Kutta substage specified by stageIndex and updates slip and state * @param stageIndex @@ -91,26 +91,26 @@ class QuasiDynamicEQRK32 : public PhysicsSolverBase * @param dt * @param domain */ - void stepRateStateODEAndComputeError(real64 const dt, DomainPartition & domain ) const; + void stepRateStateODEAndComputeError( real64 const dt, DomainPartition & domain ) const; real64 updateStresses( real64 const & time_n, real64 const & dt, const int cycleNumber, DomainPartition & domain ) const; - /** + /** * @brief Updates rate-and-state slip velocity * @param domain */ void updateSlipVelocity( real64 const & time_n, real64 const & dt, - DomainPartition & domain ) const; + DomainPartition & domain ) const; /** * @brief save the current state * @param domain */ - void saveState( DomainPartition & domain) const; + void saveState( DomainPartition & domain ) const; /// pointer to stress solver @@ -138,15 +138,15 @@ class QuasiDynamicEQRK32 : public PhysicsSolverBase public: GEOS_HOST_DEVICE - PIDController(std::array const & controlParameters, - const real64 absTol, - const real64 relTol, - const real64 acceptSafety): - controlParameters{controlParameters}, - absTol(absTol), - relTol(relTol), - acceptSafety(acceptSafety), - errors{{0.0, 0.0, 0.0}} + PIDController( std::array< const real64, 3 > const & controlParameters, + const real64 absTol, + const real64 relTol, + const real64 acceptSafety ): + controlParameters{ controlParameters }, + absTol( absTol ), + relTol( relTol ), + acceptSafety( acceptSafety ), + errors{ {0.0, 0.0, 0.0} } {} /// Default copy constructor @@ -165,31 +165,31 @@ class QuasiDynamicEQRK32 : public PhysicsSolverBase PIDController & operator=( PIDController && ) = delete; /// Parameters for the PID error controller - const std::array controlParameters; // Controller parameters + const std::array< const real64, 3 > controlParameters; // Controller parameters real64 const absTol; // absolut tolerence real64 const relTol; // relative tolerence real64 const acceptSafety; // Acceptance safety - - std::array errors; // Errors for current and two previous updates - // stored as [n+1, n, n-1] - real64 computeUpdateFactor(integer const algHighOrder, integer const algLowOrder) + std::array< real64, 3 > errors; // Errors for current and two previous updates + // stored as [n+1, n, n-1] + + real64 computeUpdateFactor( integer const algHighOrder, integer const algLowOrder ) { // PID error controller + limiter - real64 const k = LvArray::math::min(algHighOrder, algLowOrder) + 1.0; + real64 const k = LvArray::math::min( algHighOrder, algLowOrder ) + 1.0; real64 const eps0 = 1.0/(errors[0] + std::numeric_limits< real64 >::epsilon()); // n + 1 real64 const eps1 = 1.0/(errors[1] + std::numeric_limits< real64 >::epsilon()); // n real64 const eps2 = 1.0/(errors[2] + std::numeric_limits< real64 >::epsilon()); // n-1 // Compute update factor eps0^(beta0/k)*eps1^(beta1/k)*eps2^(beta2/k) where // beta0 - beta2 are the control parameters. Also apply limiter to smoothen changes. // Limiter is 1.0 + atan(x - 1.0). Here use atan(x) = atan2(x, 1.0). - return 1.0 + LvArray::math::atan2( pow(eps0, controlParameters[0] / k ) * - pow(eps1, controlParameters[1] / k ) * - pow(eps2, controlParameters[2] / k ) - 1.0, 1.0); - } + return 1.0 + LvArray::math::atan2( pow( eps0, controlParameters[0] / k ) * + pow( eps1, controlParameters[1] / k ) * + pow( eps2, controlParameters[2] / k ) - 1.0, 1.0 ); + } }; PIDController m_controller; diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index e1a7f4982f5..43f0ea15b05 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -32,11 +32,11 @@ namespace rateAndStateKernels // wrappers? GEOS_HOST_DEVICE static void projectSlipRateBase( localIndex const k, - real64 const frictionCoefficient, - real64 const shearImpedance, - arrayView2d< real64 const > const traction, - arrayView1d< real64 const > const slipRate, - arrayView2d< real64 > const slipVelocity) + real64 const frictionCoefficient, + real64 const shearImpedance, + arrayView2d< real64 const > const traction, + arrayView1d< real64 const > const slipRate, + arrayView2d< real64 > const slipVelocity ) { // Project slip rate onto shear traction to get slip velocity components real64 const frictionForce = traction[k][0] * frictionCoefficient; @@ -57,8 +57,8 @@ class ImplicitFixedStressRateAndStateKernel public: ImplicitFixedStressRateAndStateKernel( SurfaceElementSubRegion & subRegion, - constitutive::RateAndStateFriction const & frictionLaw, - real64 const shearImpedance ): + constitutive::RateAndStateFriction const & frictionLaw, + real64 const shearImpedance ): m_slipRate( subRegion.getField< fields::rateAndState::slipRate >() ), m_stateVariable( subRegion.getField< fields::rateAndState::stateVariable >() ), m_stateVariable_n( subRegion.getField< fields::rateAndState::stateVariable_n >() ), @@ -128,16 +128,17 @@ class ImplicitFixedStressRateAndStateKernel void projectSlipRate( localIndex const k ) const { real64 const frictionCoefficient = m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] ); - projectSlipRateBase(k, frictionCoefficient, m_shearImpedance, m_traction, m_slipRate, m_slipVelocity); + projectSlipRateBase( k, frictionCoefficient, m_shearImpedance, m_traction, m_slipRate, m_slipVelocity ); } GEOS_HOST_DEVICE - std::pair< int, real64 > checkConvergence( StackVariables const & stack, - real64 const tol ) const + camp::tuple< int, real64 > checkConvergence( StackVariables const & stack, + real64 const tol ) const { real64 const residualNorm = LvArray::tensorOps::l2Norm< 2 >( stack.rhs ); int const converged = residualNorm < tol ? 1 : 0; - return std::make_pair( converged, residualNorm ); + camp::tuple< int, real64 > result { converged, residualNorm }; + return result; } private: @@ -206,44 +207,45 @@ class ExplicitRateAndStateKernel real64 const normalTraction = m_traction[k][0]; real64 const shearTractionMagnitude = LvArray::math::sqrt( m_traction[k][1] * m_traction[k][1] + m_traction[k][2] * m_traction[k][2] ); - // Slip rate is bracketed between [0, shear traction magnitude / shear impedance] + // Slip rate is bracketed between [0, shear traction magnitude / shear impedance] // If slip rate is outside the bracket, re-initialize to the middle value real64 const upperBound = shearTractionMagnitude/m_shearImpedance; real64 const bracketedSlipRate = m_slipRate[k] > upperBound ? 0.5*upperBound : m_slipRate[k]; - - stack.rhs = shearTractionMagnitude - m_shearImpedance *bracketedSlipRate - normalTraction * m_frictionLaw.frictionCoefficient( k,bracketedSlipRate, m_stateVariable[k] ); + + stack.rhs = shearTractionMagnitude - m_shearImpedance *bracketedSlipRate - normalTraction * m_frictionLaw.frictionCoefficient( k, bracketedSlipRate, m_stateVariable[k] ); stack.jacobian = -m_shearImpedance - normalTraction * m_frictionLaw.dFrictionCoefficient_dSlipRate( k, bracketedSlipRate, m_stateVariable[k] ); } GEOS_HOST_DEVICE void solve( localIndex const k, - StackVariables & stack) const - { + StackVariables & stack ) const + { m_slipRate[k] -= stack.rhs/stack.jacobian; - // Slip rate is bracketed between [0, shear traction magnitude / shear impedance] + // Slip rate is bracketed between [0, shear traction magnitude / shear impedance] // Check that the update did not end outside of the bracket. real64 const shearTractionMagnitude = LvArray::math::sqrt( m_traction[k][1] * m_traction[k][1] + m_traction[k][2] * m_traction[k][2] ); real64 const upperBound = shearTractionMagnitude/m_shearImpedance; - if ( m_slipRate[k] > upperBound ) m_slipRate[k] = 0.5*upperBound; + if( m_slipRate[k] > upperBound ) m_slipRate[k] = 0.5*upperBound; } - + GEOS_HOST_DEVICE - std::pair< int, real64 > checkConvergence( StackVariables const & stack, - real64 const tol ) const + camp::tuple< int, real64 > checkConvergence( StackVariables const & stack, + real64 const tol ) const { - real64 const residualNorm = LvArray::math::abs(stack.rhs); + real64 const residualNorm = LvArray::math::abs( stack.rhs ); int const converged = residualNorm < tol ? 1 : 0; - return std::make_pair( converged, residualNorm ); + camp::tuple< int, real64 > result { converged, residualNorm }; + return result; } GEOS_HOST_DEVICE void projectSlipRate( localIndex const k ) const { real64 const frictionCoefficient = m_frictionLaw.frictionCoefficient( k, m_slipRate[k], m_stateVariable[k] ); - projectSlipRateBase(k, frictionCoefficient, m_shearImpedance, m_traction, m_slipRate, m_slipVelocity); + projectSlipRateBase( k, frictionCoefficient, m_shearImpedance, m_traction, m_slipRate, m_slipVelocity ); } private: @@ -327,248 +329,249 @@ createAndLaunch( SurfaceElementSubRegion & subRegion, * based on the first and third stage rates for the low-order update. */ struct Kutta32Table -{ - integer const algHighOrder = 3; // High-order update order - integer const algLowOrder = 2; // Low-order update order - integer const numStages = 3; // Number of stages - real64 const a[2][2] = { { 1.0/2.0, 0.0 }, // Coefficients for stage value updates - { -1.0, 2.0 } }; // (lower-triangular part of table). - real64 const c[3] = { 0.0, 1.0/2.0, 1.0 }; // Coefficients for time increments of substages - real64 const b[3] = { 1.0/6.0, 4.0/6.0, 1.0/6.0 }; // Quadrature weights used to step the solution to next time - real64 const bStar[3] = { 1.0/2.0, 0.0, 1.0/2.0 }; // Quadrature weights used for low-order comparision solution - real64 const FSAL = false; // Not first same as last +{ + integer constexpr static algHighOrder = 3; // High-order update order + integer constexpr static algLowOrder = 2; // Low-order update order + integer constexpr static numStages = 3; // Number of stages + real64 constexpr static a[2][2] = { { 1.0/2.0, 0.0 }, // Coefficients for stage value updates + { -1.0, 2.0 } }; // (lower-triangular part of table). + real64 constexpr static c[3] = { 0.0, 1.0/2.0, 1.0 }; // Coefficients for time increments of substages + real64 constexpr static b[3] = { 1.0/6.0, 4.0/6.0, 1.0/6.0 }; // Quadrature weights used to step the solution to next time + real64 constexpr static bStar[3] = { 1.0/2.0, 0.0, 1.0/2.0 }; // Quadrature weights used for low-order comparision solution + real64 constexpr static FSAL = false; // Not first same as last }; /** * @brief Butcher table for the BogackiShampine 3(2) method. */ struct BogackiShampine32Table -{ - integer const algHighOrder = 3; // High-order update order - integer const algLowOrder = 2; // Low-order update order - integer const numStages = 4; // Number of stages - real64 const a[3][3] = { { 1.0/2.0, 0.0, 0.0 }, // Coefficients for stage value updates - { 0.0, 3.0/4.0, 0.0 }, // (lower-triangular part of table). - { 2.0/9.0, 1.0/3.0, 4.0/9.0 } }; - real64 const c[4] = { 0.0, 1.0/2.0, 3.0/4.0, 1.0 }; // Coefficients for time increments of substages - real64 const b[4] = { 2.0/9.0, 1.0/3.0, 4.0/9.0, 0.0 }; // Quadrature weights used to step the solution to next time - real64 const bStar[4] = { 7.0/24.0, 1.0/4.0, 1.0/3.0, 1.0/8.0}; // Quadrature weights used for low-order comparision solution - bool FSAL = true; // First same as last (can reuse the last stage rate in next update) +{ + integer constexpr static algHighOrder = 3; // High-order update order + integer constexpr static algLowOrder = 2; // Low-order update order + integer constexpr static numStages = 4; // Number of stages + real64 constexpr static a[3][3] = { { 1.0/2.0, 0.0, 0.0 }, // Coefficients for stage value updates + { 0.0, 3.0/4.0, 0.0 }, // (lower-triangular part of table). + { 2.0/9.0, 1.0/3.0, 4.0/9.0 } }; + real64 constexpr static c[4] = { 0.0, 1.0/2.0, 3.0/4.0, 1.0 }; // Coefficients for time increments of substages + real64 constexpr static b[4] = { 2.0/9.0, 1.0/3.0, 4.0/9.0, 0.0 }; // Quadrature weights used to step the solution to next time + real64 constexpr static bStar[4] = { 7.0/24.0, 1.0/4.0, 1.0/3.0, 1.0/8.0}; // Quadrature weights used for low-order comparision solution + bool constexpr static FSAL = true; // First same as last (can reuse the last stage rate in next + // update) }; /** * @brief Runge-Kutta method used to time integrate slip and state. Uses of a high order * update used to integrate the solutions, and a lower order update to estimate the error * in the time step. - * - * @tparam Butcher table defining the Runge-Kutta method. + * + * @tparam Butcher table defining the Runge-Kutta method. */ -template class EmbeddedRungeKuttaKernel +template< typename TABLE_TYPE > class EmbeddedRungeKuttaKernel { public: - EmbeddedRungeKuttaKernel(SurfaceElementSubRegion & subRegion, - constitutive::RateAndStateFriction const & frictionLaw, - Table butcherTable): - m_stateVariable( subRegion.getField< fields::rateAndState::stateVariable >() ), - m_stateVariable_n( subRegion.getField< fields::rateAndState::stateVariable_n >() ), - m_slipRate( subRegion.getField< fields::rateAndState::slipRate >() ), - m_slipVelocity( subRegion.getField< fields::rateAndState::slipVelocity >() ), - m_slipVelocity_n( subRegion.getField< fields::rateAndState::slipVelocity_n >() ), - m_deltaSlip( subRegion.getField< fields::rateAndState::deltaSlip >() ), - m_deltaSlip_n( subRegion.getField< fields::rateAndState::deltaSlip_n >() ), - m_dispJump( subRegion.getField< fields::contact::dispJump >() ), - m_dispJump_n( subRegion.getField< fields::contact::dispJump_n >() ), - m_error( subRegion.getField< fields::rateAndState::error >() ), - m_stageRates( subRegion.getField< fields::rateAndState::rungeKuttaStageRates >() ), - m_frictionLaw( frictionLaw.createKernelUpdates() ), - m_butcherTable( butcherTable ) -{} - - /** - * @brief Initialize slip and state buffers - */ - GEOS_HOST_DEVICE - void initialize(localIndex const k) const - { - LvArray::tensorOps::copy<2>(m_slipVelocity[k], m_slipVelocity_n[k]); - m_slipRate[k] = LvArray::tensorOps::l2Norm<2>(m_slipVelocity_n[k]); - m_stateVariable[k] = m_stateVariable_n[k]; - } + EmbeddedRungeKuttaKernel( SurfaceElementSubRegion & subRegion, + constitutive::RateAndStateFriction const & frictionLaw, + TABLE_TYPE butcherTable ): + m_stateVariable( subRegion.getField< fields::rateAndState::stateVariable >() ), + m_stateVariable_n( subRegion.getField< fields::rateAndState::stateVariable_n >() ), + m_slipRate( subRegion.getField< fields::rateAndState::slipRate >() ), + m_slipVelocity( subRegion.getField< fields::rateAndState::slipVelocity >() ), + m_slipVelocity_n( subRegion.getField< fields::rateAndState::slipVelocity_n >() ), + m_deltaSlip( subRegion.getField< fields::rateAndState::deltaSlip >() ), + m_deltaSlip_n( subRegion.getField< fields::rateAndState::deltaSlip_n >() ), + m_dispJump( subRegion.getField< fields::contact::dispJump >() ), + m_dispJump_n( subRegion.getField< fields::contact::dispJump_n >() ), + m_error( subRegion.getField< fields::rateAndState::error >() ), + m_stageRates( subRegion.getField< fields::rateAndState::rungeKuttaStageRates >() ), + m_frictionLaw( frictionLaw.createKernelUpdates() ), + m_butcherTable( butcherTable ) + {} - /** - * @brief Re-uses the last stage rate from the previous time step as the first - * in the next update. Only valid for FSAL (first-same-as-last) Runge-Kutta methods. - */ - GEOS_HOST_DEVICE - void updateStageRatesFSAL(localIndex const k) const - { - LvArray::tensorOps::copy<3>(m_stageRates[k][0],m_stageRates[k][m_butcherTable.numStages-1]); - } + /** + * @brief Initialize slip and state buffers + */ + GEOS_HOST_DEVICE + void initialize( localIndex const k ) const + { + LvArray::tensorOps::copy< 2 >( m_slipVelocity[k], m_slipVelocity_n[k] ); + m_slipRate[k] = LvArray::tensorOps::l2Norm< 2 >( m_slipVelocity_n[k] ); + m_stateVariable[k] = m_stateVariable_n[k]; + } - /** - * @brief Updates the stage rates rates (the right-hand-side of the ODEs for slip and state) - */ - GEOS_HOST_DEVICE - void updateStageRates(localIndex const k, integer const stageIndex) const - { - m_stageRates[k][stageIndex][0] = m_slipVelocity[k][0]; - m_stageRates[k][stageIndex][1] = m_slipVelocity[k][1]; - m_stageRates[k][stageIndex][2] = m_frictionLaw.stateEvolution(k, m_slipRate[k], m_stateVariable[k]); - } + /** + * @brief Re-uses the last stage rate from the previous time step as the first + * in the next update. Only valid for FSAL (first-same-as-last) Runge-Kutta methods. + */ + GEOS_HOST_DEVICE + void updateStageRatesFSAL( localIndex const k ) const + { + LvArray::tensorOps::copy< 3 >( m_stageRates[k][0], m_stageRates[k][m_butcherTable.numStages-1] ); + } - /** - * @brief Update stage values (slip, state and displacement jump) to a Runge-Kutta substage. - */ - GEOS_HOST_DEVICE - void updateStageValues(localIndex const k, integer const stageIndex, real64 const dt) const - { - - real64 stateVariableIncrement = 0.0; - real64 deltaSlipIncrement[2] = {0.0, 0.0}; - - for (integer i = 0; i < stageIndex; i++) - { - deltaSlipIncrement[0] += m_butcherTable.a[stageIndex-1][i] * m_stageRates[k][i][0]; - deltaSlipIncrement[1] += m_butcherTable.a[stageIndex-1][i] * m_stageRates[k][i][1]; - stateVariableIncrement += m_butcherTable.a[stageIndex-1][i] * m_stageRates[k][i][2]; - } - m_deltaSlip[k][0] = m_deltaSlip_n[k][0] + dt*deltaSlipIncrement[0]; - m_deltaSlip[k][1] = m_deltaSlip_n[k][1] + dt*deltaSlipIncrement[1]; - m_stateVariable[k] = m_stateVariable_n[k] + dt*stateVariableIncrement; - - m_dispJump[k][1] = m_dispJump_n[k][1] + m_deltaSlip[k][0]; - m_dispJump[k][2] = m_dispJump_n[k][2] + m_deltaSlip[k][1]; - } + /** + * @brief Updates the stage rates rates (the right-hand-side of the ODEs for slip and state) + */ + GEOS_HOST_DEVICE + void updateStageRates( localIndex const k, integer const stageIndex ) const + { + m_stageRates[k][stageIndex][0] = m_slipVelocity[k][0]; + m_stageRates[k][stageIndex][1] = m_slipVelocity[k][1]; + m_stageRates[k][stageIndex][2] = m_frictionLaw.stateEvolution( k, m_slipRate[k], m_stateVariable[k] ); + } - /** - * @brief Updates slip, state and displacement jump to the next time computes error the local error - * in the time step - */ - GEOS_HOST_DEVICE - void updateSolutionAndLocalError(localIndex const k, real64 const dt, real64 const absTol, real64 const relTol) const + /** + * @brief Update stage values (slip, state and displacement jump) to a Runge-Kutta substage. + */ + GEOS_HOST_DEVICE + void updateStageValues( localIndex const k, integer const stageIndex, real64 const dt ) const + { + + real64 stateVariableIncrement = 0.0; + real64 deltaSlipIncrement[2] = {0.0, 0.0}; + + for( integer i = 0; i < stageIndex; i++ ) { - - real64 deltaSlipIncrement[2] = {0.0, 0.0}; - real64 deltaSlipIncrementLowOrder[2] = {0.0, 0.0}; - - real64 stateVariableIncrement = 0.0; - real64 stateVariableIncrementLowOrder = 0.0; - - for (localIndex i = 0; i < m_butcherTable.numStages; i++) - { - - // High order update of solution - deltaSlipIncrement[0] += m_butcherTable.b[i] * m_stageRates[k][i][0]; - deltaSlipIncrement[1] += m_butcherTable.b[i] * m_stageRates[k][i][1]; - stateVariableIncrement += m_butcherTable.b[i] * m_stageRates[k][i][2]; - - // Low order update for error - deltaSlipIncrementLowOrder[0] += m_butcherTable.bStar[i] * m_stageRates[k][i][0]; - deltaSlipIncrementLowOrder[1] += m_butcherTable.bStar[i] * m_stageRates[k][i][1]; - stateVariableIncrementLowOrder += m_butcherTable.bStar[i] * m_stageRates[k][i][2]; - } - - m_deltaSlip[k][0] = m_deltaSlip_n[k][0] + dt * deltaSlipIncrement[0]; - m_deltaSlip[k][1] = m_deltaSlip_n[k][1] + dt * deltaSlipIncrement[1]; - m_stateVariable[k] = m_stateVariable_n[k] + dt * stateVariableIncrement; - - real64 const deltaSlipLowOrder[2] = {m_deltaSlip_n[k][0] + dt * deltaSlipIncrementLowOrder[0], - m_deltaSlip_n[k][1] + dt * deltaSlipIncrementLowOrder[1]}; - real64 const stateVariableLowOrder = m_stateVariable_n[k] + dt * stateVariableIncrementLowOrder; - - m_dispJump[k][1] = m_dispJump_n[k][1] + m_deltaSlip[k][0]; - m_dispJump[k][2] = m_dispJump_n[k][2] + m_deltaSlip[k][1]; - - // Compute error - m_error[k][0] = computeError(m_deltaSlip[k][0], deltaSlipLowOrder[0], absTol, relTol); - m_error[k][1] = computeError(m_deltaSlip[k][1], deltaSlipLowOrder[1], absTol, relTol); - m_error[k][2] = computeError(m_stateVariable[k], stateVariableLowOrder, absTol, relTol); + deltaSlipIncrement[0] += m_butcherTable.a[stageIndex-1][i] * m_stageRates[k][i][0]; + deltaSlipIncrement[1] += m_butcherTable.a[stageIndex-1][i] * m_stageRates[k][i][1]; + stateVariableIncrement += m_butcherTable.a[stageIndex-1][i] * m_stageRates[k][i][2]; } + m_deltaSlip[k][0] = m_deltaSlip_n[k][0] + dt*deltaSlipIncrement[0]; + m_deltaSlip[k][1] = m_deltaSlip_n[k][1] + dt*deltaSlipIncrement[1]; + m_stateVariable[k] = m_stateVariable_n[k] + dt*stateVariableIncrement; - /** - * @brief Updates slip, state and displacement jump to the next time computes error the local error - * in the time step. Uses the FSAL (first-same-as-last) property. - */ - GEOS_HOST_DEVICE - void updateSolutionAndLocalErrorFSAL(localIndex const k, real64 const dt, real64 const absTol, real64 const relTol) const + m_dispJump[k][1] = m_dispJump_n[k][1] + m_deltaSlip[k][0]; + m_dispJump[k][2] = m_dispJump_n[k][2] + m_deltaSlip[k][1]; + } + + /** + * @brief Updates slip, state and displacement jump to the next time computes error the local error + * in the time step + */ + GEOS_HOST_DEVICE + void updateSolutionAndLocalError( localIndex const k, real64 const dt, real64 const absTol, real64 const relTol ) const + { + + real64 deltaSlipIncrement[2] = {0.0, 0.0}; + real64 deltaSlipIncrementLowOrder[2] = {0.0, 0.0}; + + real64 stateVariableIncrement = 0.0; + real64 stateVariableIncrementLowOrder = 0.0; + + for( localIndex i = 0; i < m_butcherTable.numStages; i++ ) { - - real64 deltaSlipIncrementLowOrder[2] = {0.0, 0.0}; - real64 stateVariableIncrementLowOrder = 0.0; - - for (localIndex i = 0; i < m_butcherTable.numStages; i++) - { - // In FSAL algorithms the last RK substage update coincides with the - // high-order update. Only need to compute increments for the the - // low-order updates for error computation. - deltaSlipIncrementLowOrder[0] += m_butcherTable.bStar[i] * m_stageRates[k][i][0]; - deltaSlipIncrementLowOrder[1] += m_butcherTable.bStar[i] * m_stageRates[k][i][1]; - stateVariableIncrementLowOrder += m_butcherTable.bStar[i] * m_stageRates[k][i][2]; - } - - real64 const deltaSlipLowOrder[2] = {m_deltaSlip_n[k][0] + dt * deltaSlipIncrementLowOrder[0], - m_deltaSlip_n[k][1] + dt * deltaSlipIncrementLowOrder[1]}; - real64 const stateVariableLowOrder = m_stateVariable_n[k] + dt * stateVariableIncrementLowOrder; - - m_dispJump[k][1] = m_dispJump_n[k][1] + m_deltaSlip[k][0]; - m_dispJump[k][2] = m_dispJump_n[k][2] + m_deltaSlip[k][1]; - - // Compute error - m_error[k][0] = computeError(m_deltaSlip[k][0], deltaSlipLowOrder[0], absTol, relTol); - m_error[k][1] = computeError(m_deltaSlip[k][1], deltaSlipLowOrder[1], absTol, relTol); - m_error[k][2] = computeError(m_stateVariable[k], stateVariableLowOrder, absTol, relTol); + + // High order update of solution + deltaSlipIncrement[0] += m_butcherTable.b[i] * m_stageRates[k][i][0]; + deltaSlipIncrement[1] += m_butcherTable.b[i] * m_stageRates[k][i][1]; + stateVariableIncrement += m_butcherTable.b[i] * m_stageRates[k][i][2]; + + // Low order update for error + deltaSlipIncrementLowOrder[0] += m_butcherTable.bStar[i] * m_stageRates[k][i][0]; + deltaSlipIncrementLowOrder[1] += m_butcherTable.bStar[i] * m_stageRates[k][i][1]; + stateVariableIncrementLowOrder += m_butcherTable.bStar[i] * m_stageRates[k][i][2]; } - /** - * @brief Computes the relative error scaled by error tolerances - */ - real64 computeError(real64 const highOrderApprox, real64 const lowOrderApprox, real64 const absTol, real64 const relTol) const + m_deltaSlip[k][0] = m_deltaSlip_n[k][0] + dt * deltaSlipIncrement[0]; + m_deltaSlip[k][1] = m_deltaSlip_n[k][1] + dt * deltaSlipIncrement[1]; + m_stateVariable[k] = m_stateVariable_n[k] + dt * stateVariableIncrement; + + real64 const deltaSlipLowOrder[2] = {m_deltaSlip_n[k][0] + dt * deltaSlipIncrementLowOrder[0], + m_deltaSlip_n[k][1] + dt * deltaSlipIncrementLowOrder[1]}; + real64 const stateVariableLowOrder = m_stateVariable_n[k] + dt * stateVariableIncrementLowOrder; + + m_dispJump[k][1] = m_dispJump_n[k][1] + m_deltaSlip[k][0]; + m_dispJump[k][2] = m_dispJump_n[k][2] + m_deltaSlip[k][1]; + + // Compute error + m_error[k][0] = computeError( m_deltaSlip[k][0], deltaSlipLowOrder[0], absTol, relTol ); + m_error[k][1] = computeError( m_deltaSlip[k][1], deltaSlipLowOrder[1], absTol, relTol ); + m_error[k][2] = computeError( m_stateVariable[k], stateVariableLowOrder, absTol, relTol ); + } + + /** + * @brief Updates slip, state and displacement jump to the next time computes error the local error + * in the time step. Uses the FSAL (first-same-as-last) property. + */ + GEOS_HOST_DEVICE + void updateSolutionAndLocalErrorFSAL( localIndex const k, real64 const dt, real64 const absTol, real64 const relTol ) const + { + + real64 deltaSlipIncrementLowOrder[2] = {0.0, 0.0}; + real64 stateVariableIncrementLowOrder = 0.0; + + for( localIndex i = 0; i < m_butcherTable.numStages; i++ ) { - return (highOrderApprox - lowOrderApprox) / - ( absTol + relTol * LvArray::math::max( LvArray::math::abs(highOrderApprox), LvArray::math::abs(lowOrderApprox) )); + // In FSAL algorithms the last RK substage update coincides with the + // high-order update. Only need to compute increments for the the + // low-order updates for error computation. + deltaSlipIncrementLowOrder[0] += m_butcherTable.bStar[i] * m_stageRates[k][i][0]; + deltaSlipIncrementLowOrder[1] += m_butcherTable.bStar[i] * m_stageRates[k][i][1]; + stateVariableIncrementLowOrder += m_butcherTable.bStar[i] * m_stageRates[k][i][2]; } - private: - - /// Current state variable - arrayView1d< real64 > const m_stateVariable; - - /// State variable at t = t_n - arrayView1d< real64 > const m_stateVariable_n; - - /// Current slip rate (magnitude of slip velocity) - arrayView1d< real64 > const m_slipRate; - - /// Current slip velocity - arrayView2d< real64 > const m_slipVelocity; - - /// Slip velocity at time t_n - arrayView2d< real64 > const m_slipVelocity_n; - - /// Current slip change - arrayView2d< real64 > const m_deltaSlip; - - /// Slip change at time t_n - arrayView2d< real64 > const m_deltaSlip_n; - - /// Current displacment jump - arrayView2d< real64 > const m_dispJump; - - /// Displacment jump at time t_n - arrayView2d< real64 > const m_dispJump_n; - - /// Local error for each solution component stored as slip1, slip2, state - arrayView2d< real64 > const m_error; - - /// Stage rates for each solution component stored as slip1, slip2, state - arrayView3d< real64 > const m_stageRates; - - /// Friction law used for rate-and-state updates - constitutive::RateAndStateFriction::KernelWrapper m_frictionLaw; - - /// Butcher table used for explicit time stepping of rate and state - Table m_butcherTable; + real64 const deltaSlipLowOrder[2] = {m_deltaSlip_n[k][0] + dt * deltaSlipIncrementLowOrder[0], + m_deltaSlip_n[k][1] + dt * deltaSlipIncrementLowOrder[1]}; + real64 const stateVariableLowOrder = m_stateVariable_n[k] + dt * stateVariableIncrementLowOrder; + + m_dispJump[k][1] = m_dispJump_n[k][1] + m_deltaSlip[k][0]; + m_dispJump[k][2] = m_dispJump_n[k][2] + m_deltaSlip[k][1]; + + // Compute error + m_error[k][0] = computeError( m_deltaSlip[k][0], deltaSlipLowOrder[0], absTol, relTol ); + m_error[k][1] = computeError( m_deltaSlip[k][1], deltaSlipLowOrder[1], absTol, relTol ); + m_error[k][2] = computeError( m_stateVariable[k], stateVariableLowOrder, absTol, relTol ); + } + + /** + * @brief Computes the relative error scaled by error tolerances + */ + real64 computeError( real64 const highOrderApprox, real64 const lowOrderApprox, real64 const absTol, real64 const relTol ) const + { + return (highOrderApprox - lowOrderApprox) / + ( absTol + relTol * LvArray::math::max( LvArray::math::abs( highOrderApprox ), LvArray::math::abs( lowOrderApprox ) )); + } + +private: + + /// Current state variable + arrayView1d< real64 > const m_stateVariable; + + /// State variable at t = t_n + arrayView1d< real64 > const m_stateVariable_n; + + /// Current slip rate (magnitude of slip velocity) + arrayView1d< real64 > const m_slipRate; + + /// Current slip velocity + arrayView2d< real64 > const m_slipVelocity; + + /// Slip velocity at time t_n + arrayView2d< real64 > const m_slipVelocity_n; + + /// Current slip change + arrayView2d< real64 > const m_deltaSlip; + + /// Slip change at time t_n + arrayView2d< real64 > const m_deltaSlip_n; + + /// Current displacment jump + arrayView2d< real64 > const m_dispJump; + + /// Displacment jump at time t_n + arrayView2d< real64 > const m_dispJump_n; + + /// Local error for each solution component stored as slip1, slip2, state + arrayView2d< real64 > const m_error; + + /// Stage rates for each solution component stored as slip1, slip2, state + arrayView3d< real64 > const m_stageRates; + + /// Friction law used for rate-and-state updates + constitutive::RateAndStateFriction::KernelWrapper m_frictionLaw; + + /// Butcher table used for explicit time stepping of slip and state + TABLE_TYPE m_butcherTable; }; } /* namespace rateAndStateKernels */ diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp index 53864de3214..df5e63a2d19 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/rateAndStateFields.hpp @@ -54,7 +54,7 @@ DECLARE_FIELD( slipVelocity_n, 0.70710678118e-6, NOPLOT, WRITE_AND_READ, - "Slip velocity at previous time step" ); + "Slip velocity at previous time step" ); DECLARE_FIELD( stateVariable, "stateVariable", @@ -96,7 +96,7 @@ DECLARE_FIELD( rungeKuttaStageRates, 0.0, NOPLOT, WRITE_AND_READ, - "Runge-Kutta stage rates for rate-and-state variables" ); + "Runge-Kutta stage rates for rate-and-state variables" ); DECLARE_FIELD( error, @@ -105,7 +105,7 @@ DECLARE_FIELD( error, 0.0, LEVEL_0, WRITE_AND_READ, - "Error for rate-and-state fields" ); + "Error for rate-and-state fields" ); } From c79e65af8ffeef5b71238f3de73dcdb01f471fc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Fri, 6 Dec 2024 14:58:37 -0800 Subject: [PATCH 48/53] Rename constructor arguments to prevent shadowing --- .../inducedSeismicity/QuasiDynamicEQRK32.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp index e2e94bd21c5..e3a61696572 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp @@ -138,14 +138,14 @@ class QuasiDynamicEQRK32 : public PhysicsSolverBase public: GEOS_HOST_DEVICE - PIDController( std::array< const real64, 3 > const & controlParameters, - const real64 absTol, - const real64 relTol, - const real64 acceptSafety ): - controlParameters{ controlParameters }, - absTol( absTol ), - relTol( relTol ), - acceptSafety( acceptSafety ), + PIDController( std::array< const real64, 3 > const & cparams, + const real64 atol, + const real64 rtol, + const real64 safety ): + controlParameters{ cparams }, + absTol( atol ), + relTol( rtol ), + acceptSafety( safety ), errors{ {0.0, 0.0, 0.0} } {} From 36fd40d3d557e59bd5c6d1a91f44a09ec73f2a1e Mon Sep 17 00:00:00 2001 From: Matteo Cusini <49037133+CusiniM@users.noreply.github.com> Date: Fri, 6 Dec 2024 17:05:09 -0800 Subject: [PATCH 49/53] Update inputFiles/inducedSeismicity/inducedSeismicity.ats --- inputFiles/inducedSeismicity/inducedSeismicity.ats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inputFiles/inducedSeismicity/inducedSeismicity.ats b/inputFiles/inducedSeismicity/inducedSeismicity.ats index 735b625bebf..813bdf08b8b 100644 --- a/inputFiles/inducedSeismicity/inducedSeismicity.ats +++ b/inputFiles/inducedSeismicity/inducedSeismicity.ats @@ -28,7 +28,7 @@ decks = [ partitions=((1, 1, 1), ), restart_step=0, check_step=3262, - restartcheck_params=RestartcheckParameters(atol=1e-4, rtol=1e-3)) + restartcheck_params=RestartcheckParameters(atol=1e-4, rtol=1e-3)), TestDeck( name="SpringSliderExplicit_smoke", description="Spring slider 0D system", From 9dcdbbdd1c0e0a5f60bd92bf9c80f61f9ea277ec Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Sun, 8 Dec 2024 15:40:51 -0800 Subject: [PATCH 50/53] rebaseline --- .integrated_tests.yaml | 2 +- BASELINE_NOTES.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.integrated_tests.yaml b/.integrated_tests.yaml index 3aa31a7e4cb..31ce96119a9 100644 --- a/.integrated_tests.yaml +++ b/.integrated_tests.yaml @@ -1,6 +1,6 @@ baselines: bucket: geosx - baseline: integratedTests/baseline_integratedTests-pr3480-9217-caaecb8 + baseline: integratedTests/baseline_integratedTests-pr3450-9221-37d940c allow_fail: all: '' streak: '' diff --git a/BASELINE_NOTES.md b/BASELINE_NOTES.md index acbeb39e382..3b097223255 100644 --- a/BASELINE_NOTES.md +++ b/BASELINE_NOTES.md @@ -6,6 +6,10 @@ This file is designed to track changes to the integrated test baselines. Any developer who updates the baseline ID in the .integrated_tests.yaml file is expected to create an entry in this file with the pull request number, date, and their justification for rebaselining. These notes should be in reverse-chronological order, and use the following time format: (YYYY-MM-DD). +PR #3450 (2024-12-08) +===================== +Added test for explicit runge kutta sprinslider. + PR #3480 (2024-12-06) ===================== Add "logLevel" parameter under /Problem/Outputs in baseline files From 62de8e95cd9e53657d0da02439eb4de32b025b7f Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Sun, 8 Dec 2024 20:50:45 -0800 Subject: [PATCH 51/53] make functions public for nvcc. --- .../inducedSeismicity/QuasiDynamicEQRK32.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp index e3a61696572..362217a0d32 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp @@ -62,13 +62,10 @@ class QuasiDynamicEQRK32 : public PhysicsSolverBase integer const cycleNumber, DomainPartition & domain ) override final; -private: virtual real64 setNextDt( real64 const & currentDt, DomainPartition & domain ) override final; - virtual void postInputInitialization() override; - /** * @brief Computes stage rates for the initial Runge-Kutta substage and updates slip and state * @param dt @@ -93,6 +90,10 @@ class QuasiDynamicEQRK32 : public PhysicsSolverBase */ void stepRateStateODEAndComputeError( real64 const dt, DomainPartition & domain ) const; +private: + + virtual void postInputInitialization() override; + real64 updateStresses( real64 const & time_n, real64 const & dt, const int cycleNumber, From 1caf325978f8af57edbcdbd9a6b8af6494817ed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vidar=20Stiernstr=C3=B6m?= Date: Mon, 9 Dec 2024 09:43:56 -0800 Subject: [PATCH 52/53] Change methods from private to public --- .../inducedSeismicity/QuasiDynamicEQRK32.hpp | 8 ++--- src/coreComponents/schema/schema.xsd | 31 ++++++++++++++++++- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp index 362217a0d32..0979fd22dd7 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/QuasiDynamicEQRK32.hpp @@ -90,10 +90,6 @@ class QuasiDynamicEQRK32 : public PhysicsSolverBase */ void stepRateStateODEAndComputeError( real64 const dt, DomainPartition & domain ) const; -private: - - virtual void postInputInitialization() override; - real64 updateStresses( real64 const & time_n, real64 const & dt, const int cycleNumber, @@ -113,6 +109,10 @@ class QuasiDynamicEQRK32 : public PhysicsSolverBase */ void saveState( DomainPartition & domain ) const; +private: + + virtual void postInputInitialization() override; + /// pointer to stress solver PhysicsSolverBase * m_stressSolver; diff --git a/src/coreComponents/schema/schema.xsd b/src/coreComponents/schema/schema.xsd index 6cea491860c..e130b1e56d4 100644 --- a/src/coreComponents/schema/schema.xsd +++ b/src/coreComponents/schema/schema.xsd @@ -2113,6 +2113,11 @@ the relative residual norm satisfies: + + @@ -2129,6 +2134,11 @@ the relative residual norm satisfies: + + @@ -2143,6 +2153,11 @@ the relative residual norm satisfies: + + @@ -2151,6 +2166,11 @@ the relative residual norm satisfies: + + @@ -2161,6 +2181,11 @@ the relative residual norm satisfies: + + @@ -2199,7 +2224,7 @@ the relative residual norm satisfies: - + @@ -2652,6 +2677,8 @@ Level 0 outputs no specific information for this solver. Higher levels require m + + @@ -2739,6 +2766,8 @@ Level 0 outputs no specific information for this solver. Higher levels require m + + From f861184e77cb8893d9c2484cb0a3b57bf549599b Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Mon, 9 Dec 2024 13:36:09 -0800 Subject: [PATCH 53/53] fix nvcc compilation erros. --- .../kernels/RateAndStateKernels.hpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp index 43f0ea15b05..87d05f3b443 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/kernels/RateAndStateKernels.hpp @@ -333,11 +333,11 @@ struct Kutta32Table integer constexpr static algHighOrder = 3; // High-order update order integer constexpr static algLowOrder = 2; // Low-order update order integer constexpr static numStages = 3; // Number of stages - real64 constexpr static a[2][2] = { { 1.0/2.0, 0.0 }, // Coefficients for stage value updates + real64 const a[2][2] = { { 1.0/2.0, 0.0 }, // Coefficients for stage value updates { -1.0, 2.0 } }; // (lower-triangular part of table). - real64 constexpr static c[3] = { 0.0, 1.0/2.0, 1.0 }; // Coefficients for time increments of substages - real64 constexpr static b[3] = { 1.0/6.0, 4.0/6.0, 1.0/6.0 }; // Quadrature weights used to step the solution to next time - real64 constexpr static bStar[3] = { 1.0/2.0, 0.0, 1.0/2.0 }; // Quadrature weights used for low-order comparision solution + real64 const c[3] = { 0.0, 1.0/2.0, 1.0 }; // Coefficients for time increments of substages + real64 const b[3] = { 1.0/6.0, 4.0/6.0, 1.0/6.0 }; // Quadrature weights used to step the solution to next time + real64 const bStar[3] = { 1.0/2.0, 0.0, 1.0/2.0 }; // Quadrature weights used for low-order comparision solution real64 constexpr static FSAL = false; // Not first same as last }; @@ -349,12 +349,12 @@ struct BogackiShampine32Table integer constexpr static algHighOrder = 3; // High-order update order integer constexpr static algLowOrder = 2; // Low-order update order integer constexpr static numStages = 4; // Number of stages - real64 constexpr static a[3][3] = { { 1.0/2.0, 0.0, 0.0 }, // Coefficients for stage value updates + real64 const a[3][3] = { { 1.0/2.0, 0.0, 0.0 }, // Coefficients for stage value updates { 0.0, 3.0/4.0, 0.0 }, // (lower-triangular part of table). { 2.0/9.0, 1.0/3.0, 4.0/9.0 } }; - real64 constexpr static c[4] = { 0.0, 1.0/2.0, 3.0/4.0, 1.0 }; // Coefficients for time increments of substages - real64 constexpr static b[4] = { 2.0/9.0, 1.0/3.0, 4.0/9.0, 0.0 }; // Quadrature weights used to step the solution to next time - real64 constexpr static bStar[4] = { 7.0/24.0, 1.0/4.0, 1.0/3.0, 1.0/8.0}; // Quadrature weights used for low-order comparision solution + real64 const c[4] = { 0.0, 1.0/2.0, 3.0/4.0, 1.0 }; // Coefficients for time increments of substages + real64 const b[4] = { 2.0/9.0, 1.0/3.0, 4.0/9.0, 0.0 }; // Quadrature weights used to step the solution to next time + real64 const bStar[4] = { 7.0/24.0, 1.0/4.0, 1.0/3.0, 1.0/8.0}; // Quadrature weights used for low-order comparision solution bool constexpr static FSAL = true; // First same as last (can reuse the last stage rate in next // update) }; @@ -526,6 +526,7 @@ template< typename TABLE_TYPE > class EmbeddedRungeKuttaKernel /** * @brief Computes the relative error scaled by error tolerances */ + GEOS_HOST_DEVICE real64 computeError( real64 const highOrderApprox, real64 const lowOrderApprox, real64 const absTol, real64 const relTol ) const { return (highOrderApprox - lowOrderApprox) /