From 7c745adaec2ce9679b2893d622415c9aabf3929b Mon Sep 17 00:00:00 2001 From: jacques franc Date: Tue, 4 Nov 2025 18:08:17 +0100 Subject: [PATCH 01/25] starting implementation --- .../contact/FrictionDriver.cpp | 256 ++++++++++++++++++ .../contact/FrictionDriver.hpp | 122 +++++++++ .../contact/FrictionDriverRunTest.hpp | 106 ++++++++ .../contact/LogLevelsInfo.hpp | 52 ++++ 4 files changed, 536 insertions(+) create mode 100644 src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp create mode 100644 src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp create mode 100644 src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp create mode 100644 src/coreComponents/constitutiveDrivers/contact/LogLevelsInfo.hpp diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp new file mode 100644 index 00000000000..f51425517a9 --- /dev/null +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -0,0 +1,256 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * 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. + * ------------------------------------------------------------------------------------------------------------ + */ + +#include "common/MpiWrapper.hpp" +#include "constitutive/ConstitutiveManager.hpp" +#include "constitutiveDrivers/contact/LogLevelsInfo.hpp" +#include "constitutive/contact/FrictionBase.hpp" +#include "constitutive/contact/FrictionSelector.hpp" + +#include "FrictionDriver.hpp" + +namespace geos { + +using namespace dataRepository; +using namespace constitutive; + +FrictionDriver::FrictionDriver(const string& name, Group * const parent) +: +TaskBase(name, parent) +{ + registerWrapper( viewKeyStruct::frictionNameString(), &m_frictionName ). + setRTTypeName( rtTypes::CustomTypes::groupNameRef ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Relperm model to test" ); + + registerWrapper( viewKeyStruct::numStepsString(), &m_numSteps ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Number of saturation steps to take" ); + + registerWrapper( viewKeyStruct::outputString(), &m_outputFile ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( "none" ). + setDescription( "Output file" ); + + registerWrapper( viewKeyStruct::baselineString(), &m_baselineFile ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( "none" ). + setDescription( "Baseline file" ); + + addLogLevel< logInfo::LogOutput >(); +} + +void FrictionDriver::outputResults() +{ + // TODO: improve file path output to grab command line -o directory + // for the moment, we just use the specified m_outputFile directly + + FILE * fp = fopen( m_outputFile.c_str(), "w" ); + + fprintf( fp, "# column 1 = time\n" ); + fprintf( fp, "# columns %d-%d = phase vol fractions\n", 2, 1 + m_numPhases ); + fprintf( fp, "# columns %d-%d = phase relperm\n", 2 + m_numPhases, 1 + 2 * m_numPhases ); + + if( ( m_numPhases == 2 && m_table.size( 1 ) > 5 ) || m_table.size( 1 ) > 7 ) + { + fprintf( fp, "# columns %d-%d = phase relperm (hyst)\n", 1 + 2 * m_numPhases, 1 + 3 * m_numPhases ); + } + + + for( integer n = 0; n < m_table.size( 0 ); ++n ) + { + for( integer col = 0; col < m_table.size( 1 ); ++col ) + { + fprintf( fp, "%.4e ", m_table( n, col ) ); + } + fprintf( fp, "\n" ); + } + fclose( fp ); + + +} + + +void FrictionDriver::postInputInitialization() +{ + ConstitutiveManager + & constitutiveManager = this->getGroupByPath< ConstitutiveManager >( "/Problem/domain/Constitutive" ); + FrictionBase& baseFriction = constitutiveManager.getGroup< FrictionBase >( m_frictionName ); + +// m_numPhases = baseFriction.numSubGroups(); + +} + + +bool FrictionDriver::execute( const geos::real64 GEOS_UNUSED_PARAM( time_n ), + const geos::real64 GEOS_UNUSED_PARAM( dt ), + const geos::integer GEOS_UNUSED_PARAM( cycleNumber ), + const geos::integer GEOS_UNUSED_PARAM( eventCounter ), + const geos::real64 GEOS_UNUSED_PARAM( eventProgress ), + geos::DomainPartition & + GEOS_UNUSED_PARAM( domain ) ) +{ + // this code only makes sense in serial + + GEOS_THROW_IF( MpiWrapper::commRank() > 0, "RelpermDriver should only be run in serial", std::runtime_error ); + + + ConstitutiveManager + & constitutiveManager = this->getGroupByPath< ConstitutiveManager >( "/Problem/domain/Constitutive" ); + FrictionBase + & baseFriction = constitutiveManager.getGroup< FrictionBase >( m_frictionName ); + + GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, "Launching Relperm Driver" ); + GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Relperm .................. " << m_frictionName ); + GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Type ................... " << baseFriction.getCatalogName() ); +// GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " No. of Phases .......... " << m_numPhases ); + GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Steps .................. " << m_numSteps ); + GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Output ................. " << m_outputFile ); + GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Baseline ............... " << m_baselineFile ); + + // create a dummy discretization with one quadrature point for + // storing constitutive data + + conduit::Node node; + dataRepository::Group rootGroup( "root", node ); + dataRepository::Group discretization( "discretization", &rootGroup ); + + discretization.resize( 1 ); // one element + baseRelperm.allocateConstitutiveData( discretization, 1 ); // one quadrature point + + constitutiveUpdatePassThru( baseFriction, [&]( auto & selectedFrictionModel ) + { + using RELPERM_TYPE = TYPEOFREF( selectedFrictionModel ); + resizeTables< RELPERM_TYPE >(); + runTest< RELPERM_TYPE >( selectedFrictionModel, m_table ); + } ); + + // move table back to host for output + m_table.move( LvArray::MemorySpace::host ); + + if( m_outputFile != "none" ) + { + outputResults(); + } + + if( m_baselineFile != "none" ) + { + compareWithBaseline(); + } + + return false; +} + + +template< typename RELPERM_TYPE > +void FrictionDriver::resizeTables() +{ + ConstitutiveManager + & constitutiveManager = this->getGroupByPath< ConstitutiveManager >( "/Problem/domain/Constitutive" ); + FrictionBase + & baseRelperm = constitutiveManager.getGroup< FrictionBaseBase >( m_frictionName ); + + using PT = RelativePermeabilityBase::PhaseType; + integer const ipWater = baseRelperm.getPhaseOrder()[PT::WATER]; + integer const ipOil = baseRelperm.getPhaseOrder()[PT::OIL]; + integer const ipGas = baseRelperm.getPhaseOrder()[PT::GAS]; + + real64 minSw = 0., minSnw = 0.; + if( baseRelperm.numFluidPhases() > 2 ) + { + minSw = baseRelperm.getWettingPhaseMinVolumeFraction(); + minSnw = baseRelperm.getNonWettingMinVolumeFraction(); + } + else + { + if( ipWater < 0 )// a.k.a o/g + { + minSw = 0; + minSnw = baseRelperm.getNonWettingMinVolumeFraction(); + } + else if( ipGas < 0 || ipOil < 0 )// a.k.a w/o or w/g + { + minSnw = 0; + minSw = baseRelperm.getWettingPhaseMinVolumeFraction(); + } + } + + real64 const dSw = ( 1 - minSw - minSnw ) / m_numSteps; + // set input columns + + resizeTable< RELPERM_TYPE >(); + // 3-phase branch + if( m_numPhases > 2 ) + { + for( integer ni = 0; ni < m_numSteps + 1; ++ni ) + { + for( integer nj = 0; nj < m_numSteps + 1; ++nj ) + { + + integer index = ni * ( m_numSteps + 1 ) + nj; + m_table( index, TIME ) = minSw + index * dSw; + m_table( index, ipWater + 1 ) = minSw + nj * dSw; + m_table( index, ipGas + 1 ) = minSnw + ni * dSw; + m_table( index, ipOil + 1 ) = + 1. - m_table( index, ipWater + 1 ) - m_table( index, ipOil + 1 ); + } + } + } + else // 2-phase branch + { + for( integer ni = 0; ni < m_numSteps + 1; ++ni ) + { + integer index = ni; + m_table( index, TIME ) = minSw + index * dSw; + if( ipWater < 0 ) + { + m_table( index, ipGas + 1 ) = minSnw + ni * dSw; + m_table( index, ipOil + 1 ) = 1. - m_table( index, ipGas + 1 ); + } + else if( ipGas < 0 ) + { + m_table( index, ipWater + 1 ) = minSw + ni * dSw; + m_table( index, ipOil + 1 ) = 1. - m_table( index, ipWater + 1 ); + } + else if( ipOil < 0 ) + { + m_table( index, ipWater + 1 ) = minSw + ni * dSw; + m_table( index, ipGas + 1 ) = 1. - m_table( index, ipWater + 1 ); + } + } + + } + + +} + + +// template< typename RELPERM_TYPE > +// std::enable_if_t< std::is_same< TableRelativePermeabilityHysteresis, RELPERM_TYPE >::value, void > +// RelpermDriver::resizeTable() +// { +// if( m_numPhases > 2 ) +// { +// m_table.resize( ( m_numSteps + 1 ) * ( m_numSteps + 1 ), 1 + 3 * m_numPhases ); +// } +// else +// { +// m_table.resize( m_numSteps + 1, 1 + 3 * m_numPhases ); +// } + +// } + + +} \ No newline at end of file diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp new file mode 100644 index 00000000000..ae02bb12a5c --- /dev/null +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -0,0 +1,122 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * 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_frictionDRIVER_HPP_ +#define GEOS_frictionDRIVER_HPP_ + +#include "events/tasks/TaskBase.hpp" + +namespace geos +{ + +class FrictionDriver : public TaskBase +{ + +public: + FrictionDriver( const string & name, + Group * const parent ); + + static string catalogName() + { return "frictionDriver"; } + + void postInputInitialization() override; + + virtual bool execute( real64 const GEOS_UNUSED_PARAM( time_n ), + real64 const GEOS_UNUSED_PARAM( dt ), + integer const GEOS_UNUSED_PARAM( cycleNumber ), + integer const GEOS_UNUSED_PARAM( eventCounter ), + real64 const GEOS_UNUSED_PARAM( eventProgress ), + DomainPartition & + GEOS_UNUSED_PARAM( domain ) ) override; + + // /** + // * @brief Run test using loading protocol in table + // * @param i friction constitutive model + // * @param table Table with input/output time history + // */ + // template< typename friction_TYPE > + // std::enable_if_t< std::is_same< constitutive::TableRelativePermeabilityHysteresis, friction_TYPE >::value, void > + // runTest( friction_TYPE & friction, + // const arrayView2d< real64, 1 > & table ); + + // template< typename friction_TYPE > + // std::enable_if_t< !std::is_same< constitutive::TableRelativePermeabilityHysteresis, friction_TYPE >::value, void > + // runTest( friction_TYPE & friction, + // const arrayView2d< real64, 1 > & table ); + + /** + * @brief Ouput table to file for easy plotting + */ + void outputResults(); + + /** + * @brief Read in a baseline table from file and compare with computed one (for unit testing purposes) + */ + void compareWithBaseline(); + +private: + + template< typename FRICTION_TYPE > + void resizeTables(); + + // template< typename friction_TYPE > + // std::enable_if_t< std::is_same< constitutive::TableRelativePermeabilityHysteresis, friction_TYPE >::value, void > + // resizeTable(); + + // template< typename friction_TYPE > + // std::enable_if_t< !std::is_same< constitutive::TableRelativePermeabilityHysteresis, friction_TYPE >::value, void > + // resizeTable(); + + /** + * @struct viewKeyStruct holds char strings and viewKeys for fast lookup + */ + struct viewKeyStruct + { + constexpr static char const * frictionNameString() + { return "friction"; } + + constexpr static char const * numStepsString() + { return "steps"; } + + constexpr static char const * outputString() + { return "output"; } + + constexpr static char const * baselineString() + { return "baseline"; } + }; + + integer m_numSteps; ///< Number of load steps + integer m_numColumns; ///< Number of columns in data table (depends on number of fluid phases) + integer m_numPhases; ///< Number of fluid phases + + string m_frictionName; ///< frictionType identifier + string m_outputFile; ///< Output file (optional, no output if not specified) + + array2d< real64 > m_table; ///< Table storing time-history of input/output + + Path m_baselineFile; ///< Baseline file (optional, for unit testing of solid models) + + enum columnKeys + { + TIME + }; ///< Enumeration of "input" column keys for readability + + static constexpr real64 m_baselineTol = 1e-3; ///< Comparison tolerance for baseline results +}; + + +} + +#endif //GEOS_FRICTIONDRIVER_HPP_ diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp new file mode 100644 index 00000000000..eaaa5bae76a --- /dev/null +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp @@ -0,0 +1,106 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * 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_FRICTIONDRIVERRUNTEST_HPP_ +#define GEOS_FRICTIONDRIVERRUNTEST_HPP_ + +#include "constitutive/contact/FrictionDriver.hpp" +#include "physicsSolvers/solidMechanics/contact/FractureState.hpp" +#include "constitutive/solid/SolidFields.hpp" + + +namespace geos +{ + + +template< typename FRICTION_TYPE > +void +FrictionDriver::runTest( FRICTION_TYPE & relperm, + const arrayView2d< real64 > & table ) +{ + // get number of phases and components + + integer const numPhases = relperm.numFluidPhases(); + + // create kernel wrapper + + typename RELPERM_TYPE::KernelWrapper const kernelWrapper = relperm.createKernelWrapper(); + + // set saturation to user specified feed + // it is more convenient to provide input in molar, so perform molar to mass conversion here + + array2d< real64, compflow::LAYOUT_PHASE > saturationValues; + if( numPhases > 2 ) + { + saturationValues.resize(( m_numSteps + 1 ) * ( m_numSteps + 1 ), numPhases ); + } + else + { + saturationValues.resize( m_numSteps + 1, numPhases ); + } + integer const ipWater = relperm.getPhaseOrder()[PT::WATER]; + integer const ipOil = relperm.getPhaseOrder()[PT::OIL]; + integer const ipGas = relperm.getPhaseOrder()[PT::GAS]; + const localIndex offset = std::max( std::max( ipOil, ipWater ), std::max( ipOil, ipGas ) ) + 1; + + for( integer n = 0; n < table.size( 0 ); ++n ) + { + + + if( m_numPhases > 2 ) + { + saturationValues[n][ipWater] = table( n, ipWater + 1 ); + saturationValues[n][ipOil] = table( n, ipOil + 1 ); + saturationValues[n][ipGas] = table( n, ipGas + 1 ); + } + else//two-phase + { + if( ipWater < 0 ) + { + saturationValues[n][ipOil] = table( n, ipOil + 1 ); + saturationValues[n][ipGas] = table( n, ipGas + 1 ); + } + else if( ipGas < 0 ) + { + saturationValues[n][ipWater] = table( n, ipWater + 1 ); + saturationValues[n][ipOil] = table( n, ipOil + 1 ); + } + } + + } + + arrayView2d< real64 const, compflow::USD_PHASE > const saturation = saturationValues.toViewConst(); + + // perform relperm update using table (Swet,Snonwet) and save resulting total density, etc. + // note: column indexing should be kept consistent with output file header below. + + forAll< parallelDevicePolicy<> >( saturation.size( 0 ), + [numPhases, kernelWrapper, saturation, table, + offset] GEOS_HOST_DEVICE ( integer const n ) + { + kernelWrapper.update( 0, 0, saturation[n] ); + for( integer p = 0; p < numPhases; ++p ) + { + table( n, offset + 1 + p ) = kernelWrapper.relperm()( 0, 0, p ); + } + } ); + +} + + +} + + +#endif //GEOS_FRICTIONDRIVERRUNTEST_HPP_ diff --git a/src/coreComponents/constitutiveDrivers/contact/LogLevelsInfo.hpp b/src/coreComponents/constitutiveDrivers/contact/LogLevelsInfo.hpp new file mode 100644 index 00000000000..1a0319a7db4 --- /dev/null +++ b/src/coreComponents/constitutiveDrivers/contact/LogLevelsInfo.hpp @@ -0,0 +1,52 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * 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 LogLevelsInfo.hpp + * This file contains common log level informations for PVT driver + */ + +#ifndef GEOS_CONSTITUTIVEDRIVERS_CONTACT_LOGLEVELSINFO_HPP_ +#define GEOS_CONSTITUTIVEDRIVERS_CONTACT_LOGLEVELSINFO_HPP_ + +#include "common/DataTypes.hpp" + +namespace geos +{ + +namespace logInfo +{ + +/** + * @name Common LogLevels info structures. They must comply with the `is_log_level_info` trait. + */ +///@{ + +/// @cond DO_NOT_DOCUMENT + +struct LogOutput +{ + static constexpr int getMinLogLevel() { return 1; } + static constexpr std::string_view getDescription() { return "Enable log output"; } +}; + +/// @endcond +///@} + +} + +} + +#endif // GEOS_CONSTITUTIVEDRIVERS_CONTACT_LOGLEVELSINFO_HPP_ From 67b1df99800130c68793fa6268473a488802cd80 Mon Sep 17 00:00:00 2001 From: jacques franc Date: Wed, 5 Nov 2025 17:45:17 +0100 Subject: [PATCH 02/25] first working v --- .../frictionDriver/frictionDriver_Coulomb.xml | 20 ++ .../frictionDriver/frictionDriver_base.xml | 62 +++++ inputFiles/frictionDriver/tables/jumps.geos | 6 + inputFiles/frictionDriver/tables/time.geos | 6 + .../frictionDriver/tables/tractions.geos | 6 + .../constitutiveDrivers/CMakeLists.txt | 4 + .../contact/FrictionDriver.cpp | 233 ++++++++++-------- .../contact/FrictionDriver.hpp | 43 ++-- .../contact/FrictionDriverRunTest.cpp | 26 ++ .../contact/FrictionDriverRunTest.hpp | 80 ++---- 10 files changed, 317 insertions(+), 169 deletions(-) create mode 100644 inputFiles/frictionDriver/frictionDriver_Coulomb.xml create mode 100644 inputFiles/frictionDriver/frictionDriver_base.xml create mode 100644 inputFiles/frictionDriver/tables/jumps.geos create mode 100644 inputFiles/frictionDriver/tables/time.geos create mode 100644 inputFiles/frictionDriver/tables/tractions.geos create mode 100644 src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.cpp diff --git a/inputFiles/frictionDriver/frictionDriver_Coulomb.xml b/inputFiles/frictionDriver/frictionDriver_Coulomb.xml new file mode 100644 index 00000000000..3a1c0a5b630 --- /dev/null +++ b/inputFiles/frictionDriver/frictionDriver_Coulomb.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + diff --git a/inputFiles/frictionDriver/frictionDriver_base.xml b/inputFiles/frictionDriver/frictionDriver_base.xml new file mode 100644 index 00000000000..df5ef688301 --- /dev/null +++ b/inputFiles/frictionDriver/frictionDriver_base.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inputFiles/frictionDriver/tables/jumps.geos b/inputFiles/frictionDriver/tables/jumps.geos new file mode 100644 index 00000000000..3c922732f7a --- /dev/null +++ b/inputFiles/frictionDriver/tables/jumps.geos @@ -0,0 +1,6 @@ +0 +1e-3 +2e-3 +3e-3 +4e-3 +5e-3 diff --git a/inputFiles/frictionDriver/tables/time.geos b/inputFiles/frictionDriver/tables/time.geos new file mode 100644 index 00000000000..e8371f00609 --- /dev/null +++ b/inputFiles/frictionDriver/tables/time.geos @@ -0,0 +1,6 @@ +0 +1 +2 +3 +4 +5 diff --git a/inputFiles/frictionDriver/tables/tractions.geos b/inputFiles/frictionDriver/tables/tractions.geos new file mode 100644 index 00000000000..c80b1f6d1bd --- /dev/null +++ b/inputFiles/frictionDriver/tables/tractions.geos @@ -0,0 +1,6 @@ +0 +1e6 +2e6 +3e6 +4e6 +5e6 diff --git a/src/coreComponents/constitutiveDrivers/CMakeLists.txt b/src/coreComponents/constitutiveDrivers/CMakeLists.txt index de519ea2fdb..b64c154dd1d 100644 --- a/src/coreComponents/constitutiveDrivers/CMakeLists.txt +++ b/src/coreComponents/constitutiveDrivers/CMakeLists.txt @@ -29,6 +29,8 @@ set( constitutiveDrivers_headers relativePermeability/RelpermDriver.hpp relativePermeability/RelpermDriverRunTest.hpp solid/TriaxialDriver.hpp + contact/FrictionDriver.hpp + contact/FrictionDriverRunTest.hpp ) # # Specify all sources @@ -57,6 +59,8 @@ set( constitutiveDrivers_sources relativePermeability/RelpermDriverTableRelativeRunTest.cpp relativePermeability/RelpermDriverTableRelativeHysteresisRunTest.cpp solid/TriaxialDriver.cpp + contact/FrictionDriver.cpp + contact/FrictionDriverRunTest.cpp ) set( dependencyList ${parallelDeps} constitutive events ) diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp index f51425517a9..0239141cddc 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -19,6 +19,10 @@ #include "constitutive/contact/FrictionBase.hpp" #include "constitutive/contact/FrictionSelector.hpp" +#include "functions/FunctionManager.hpp" +#include "functions/TableFunction.hpp" +#include + #include "FrictionDriver.hpp" namespace geos { @@ -33,11 +37,27 @@ TaskBase(name, parent) registerWrapper( viewKeyStruct::frictionNameString(), &m_frictionName ). setRTTypeName( rtTypes::CustomTypes::groupNameRef ). setInputFlag( InputFlags::REQUIRED ). - setDescription( "Relperm model to test" ); + setDescription( "Friction model to test" ); registerWrapper( viewKeyStruct::numStepsString(), &m_numSteps ). setInputFlag( InputFlags::REQUIRED ). - setDescription( "Number of saturation steps to take" ); + setDescription( "Number of sample step to take in both jumps and traction increments" ); + + registerWrapper( viewKeyStruct::jumpFunctionString(), &m_jumpFunctionName ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Name of the input function representing jump function along world x-axis" ); + + registerWrapper( viewKeyStruct::tractionFunctionString(), &m_tractionFunctionName ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Name of the input function representing traction function along world x-axis"); + + registerWrapper( viewKeyStruct::thetaString(), &m_theta ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Number of increment step to take in both jumps and traction increments" ); + + registerWrapper( viewKeyStruct::phiString(), &m_phi ). + setInputFlag( InputFlags::INVALID). + setDescription( "Number of increment step to take in both jumps and traction increments" ); registerWrapper( viewKeyStruct::outputString(), &m_outputFile ). setInputFlag( InputFlags::OPTIONAL ). @@ -52,22 +72,67 @@ TaskBase(name, parent) addLogLevel< logInfo::LogOutput >(); } -void FrictionDriver::outputResults() +void FrictionDriver::compareWithBaseline() { - // TODO: improve file path output to grab command line -o directory - // for the moment, we just use the specified m_outputFile directly + // open baseline file - FILE * fp = fopen( m_outputFile.c_str(), "w" ); + std::ifstream file( m_baselineFile.c_str() ); + GEOS_THROW_IF( !file.is_open(), "Can't seem to open the baseline file " << m_baselineFile, InputError ); - fprintf( fp, "# column 1 = time\n" ); - fprintf( fp, "# columns %d-%d = phase vol fractions\n", 2, 1 + m_numPhases ); - fprintf( fp, "# columns %d-%d = phase relperm\n", 2 + m_numPhases, 1 + 2 * m_numPhases ); + // discard file header - if( ( m_numPhases == 2 && m_table.size( 1 ) > 5 ) || m_table.size( 1 ) > 7 ) + string line; + for( integer row=0; row < m_numColumns; ++row ) { - fprintf( fp, "# columns %d-%d = phase relperm (hyst)\n", 1 + 2 * m_numPhases, 1 + 3 * m_numPhases ); + getline( file, line ); } + // read data block. we assume the file size is consistent with m_table, + // but check for a premature end-of-file. we then compare results value by value. + // we ignore the newton iteration and residual columns, as those may be platform + // specific. + + real64 value; + real64 error; + + for( integer row=0; row < m_table.size( 0 ); ++row ) + { + for( integer col=0; col < m_table.size( 1 ); ++col ) + { + GEOS_THROW_IF( file.eof(), "Baseline file appears shorter than internal results", std::runtime_error ); + file >> value; + + error = fabs( m_table[row][col]-value ) / ( fabs( value )+1 ); + GEOS_THROW_IF( error > m_baselineTol, "Results do not match baseline at data row " << row+1 + << " (row " << row+10 << " with header)" + << " and column " << col+1, std::runtime_error ); + + } + } + + // check we actually reached the end of the baseline file + + file >> value; + GEOS_THROW_IF( !file.eof(), "Baseline file appears longer than internal results", std::runtime_error ); + + // success + + GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Comparison ........ Internal results consistent with baseline." ); + + file.close(); +} + +void FrictionDriver::outputResults() +{ + // TODO: improve file path output to grab command line -o directory + // for the moment, we just use the specified m_outputFile directly + + FILE * fp = fopen( m_outputFile.c_str(), "w" ); + + fprintf( fp, "# column 1-3 = normal and in-plane displacement jump\n" ); + fprintf( fp, "# columns 4-6 = normal and in-place tractions\n"); + fprintf( fp, "# columns 7 = fracture state (0:Stick,1-2:[new]Slip,3:Open)\n"); + fprintf( fp, "# columns 8 = tau lim\n"); for( integer n = 0; n < m_table.size( 0 ); ++n ) { @@ -79,7 +144,6 @@ void FrictionDriver::outputResults() } fclose( fp ); - } @@ -104,7 +168,7 @@ bool FrictionDriver::execute( const geos::real64 GEOS_UNUSED_PARAM( time_n ), { // this code only makes sense in serial - GEOS_THROW_IF( MpiWrapper::commRank() > 0, "RelpermDriver should only be run in serial", std::runtime_error ); + GEOS_THROW_IF( MpiWrapper::commRank() > 0, "FrictionDriver should only be run in serial", std::runtime_error ); ConstitutiveManager @@ -112,8 +176,8 @@ bool FrictionDriver::execute( const geos::real64 GEOS_UNUSED_PARAM( time_n ), FrictionBase & baseFriction = constitutiveManager.getGroup< FrictionBase >( m_frictionName ); - GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, "Launching Relperm Driver" ); - GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Relperm .................. " << m_frictionName ); + GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, "Launching Friction Driver" ); + GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Friction .................. " << m_frictionName ); GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Type ................... " << baseFriction.getCatalogName() ); // GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " No. of Phases .......... " << m_numPhases ); GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Steps .................. " << m_numSteps ); @@ -128,13 +192,13 @@ bool FrictionDriver::execute( const geos::real64 GEOS_UNUSED_PARAM( time_n ), dataRepository::Group discretization( "discretization", &rootGroup ); discretization.resize( 1 ); // one element - baseRelperm.allocateConstitutiveData( discretization, 1 ); // one quadrature point + baseFriction.allocateConstitutiveData( discretization, 1 ); // one quadrature point constitutiveUpdatePassThru( baseFriction, [&]( auto & selectedFrictionModel ) { - using RELPERM_TYPE = TYPEOFREF( selectedFrictionModel ); - resizeTables< RELPERM_TYPE >(); - runTest< RELPERM_TYPE >( selectedFrictionModel, m_table ); + using FRICTION_TYPE = TYPEOFREF( selectedFrictionModel ); + resizeTables< FRICTION_TYPE >(); + runTest< FRICTION_TYPE >( selectedFrictionModel, m_table ); } ); // move table back to host for output @@ -154,103 +218,76 @@ bool FrictionDriver::execute( const geos::real64 GEOS_UNUSED_PARAM( time_n ), } -template< typename RELPERM_TYPE > +template< typename FRICTION_TYPE > void FrictionDriver::resizeTables() { ConstitutiveManager & constitutiveManager = this->getGroupByPath< ConstitutiveManager >( "/Problem/domain/Constitutive" ); FrictionBase - & baseRelperm = constitutiveManager.getGroup< FrictionBaseBase >( m_frictionName ); + & baseFriction = constitutiveManager.getGroup< FrictionBase >( m_frictionName ); - using PT = RelativePermeabilityBase::PhaseType; - integer const ipWater = baseRelperm.getPhaseOrder()[PT::WATER]; - integer const ipOil = baseRelperm.getPhaseOrder()[PT::OIL]; - integer const ipGas = baseRelperm.getPhaseOrder()[PT::GAS]; + // initialize table functions + FunctionManager & functionManager = FunctionManager::getInstance(); - real64 minSw = 0., minSnw = 0.; - if( baseRelperm.numFluidPhases() > 2 ) - { - minSw = baseRelperm.getWettingPhaseMinVolumeFraction(); - minSnw = baseRelperm.getNonWettingMinVolumeFraction(); - } - else - { - if( ipWater < 0 )// a.k.a o/g - { - minSw = 0; - minSnw = baseRelperm.getNonWettingMinVolumeFraction(); - } - else if( ipGas < 0 || ipOil < 0 )// a.k.a w/o or w/g - { - minSnw = 0; - minSw = baseRelperm.getWettingPhaseMinVolumeFraction(); - } - } + TableFunction & jumpFunction = functionManager.getGroup< TableFunction >( m_jumpFunctionName ); + TableFunction & tractionFunction = functionManager.getGroup< TableFunction >( m_tractionFunctionName ); - real64 const dSw = ( 1 - minSw - minSnw ) / m_numSteps; + jumpFunction.initializeFunction(); + tractionFunction.initializeFunction(); + + ArrayOfArraysView< real64 > Jcoordinates = jumpFunction.getCoordinates(); + real64 const minJump = Jcoordinates[0][0]; + real64 const maxJump = Jcoordinates[0][Jcoordinates.sizeOfArray( 0 )-1]; + real64 const dJ = (maxJump-minJump) / m_numSteps; + ArrayOfArraysView< real64 > Tcoordinates = jumpFunction.getCoordinates(); + real64 const minTrac = Tcoordinates[0][0]; + real64 const maxTrac = Tcoordinates[0][Tcoordinates.sizeOfArray( 0 )-1]; + real64 const dT = (maxTrac-minTrac) / m_numSteps; // set input columns + resizeTable< FRICTION_TYPE >(); - resizeTable< RELPERM_TYPE >(); - // 3-phase branch - if( m_numPhases > 2 ) - { - for( integer ni = 0; ni < m_numSteps + 1; ++ni ) - { - for( integer nj = 0; nj < m_numSteps + 1; ++nj ) - { - - integer index = ni * ( m_numSteps + 1 ) + nj; - m_table( index, TIME ) = minSw + index * dSw; - m_table( index, ipWater + 1 ) = minSw + nj * dSw; - m_table( index, ipGas + 1 ) = minSnw + ni * dSw; - m_table( index, ipOil + 1 ) = - 1. - m_table( index, ipWater + 1 ) - m_table( index, ipOil + 1 ); - } - } - } - else // 2-phase branch + // real64 const cohesion = baseFriction.getWrapper("cohesion"); + // real64 const frictionCoeff = baseFriction.getGroup("frictionCoefficient"); + + //All variation + for( integer nt = 0; nt < m_numSteps+1; ++nt ) { - for( integer ni = 0; ni < m_numSteps + 1; ++ni ) + + + for( integer nj = 0; nj < m_numSteps+1; ++nj ) { - integer index = ni; - m_table( index, TIME ) = minSw + index * dSw; - if( ipWater < 0 ) - { - m_table( index, ipGas + 1 ) = minSnw + ni * dSw; - m_table( index, ipOil + 1 ) = 1. - m_table( index, ipGas + 1 ); - } - else if( ipGas < 0 ) - { - m_table( index, ipWater + 1 ) = minSw + ni * dSw; - m_table( index, ipOil + 1 ) = 1. - m_table( index, ipWater + 1 ); - } - else if( ipOil < 0 ) - { - m_table( index, ipWater + 1 ) = minSw + ni * dSw; - m_table( index, ipGas + 1 ) = 1. - m_table( index, ipWater + 1 ); - } - } - } + integer index = nt * (m_numSteps+1) + nj; + m_table( index, NTRAC ) = (minTrac + nt*dT)*cos(m_theta * 180/M_PI); + m_table( index, STRAC0 ) = (minTrac + nt*dT)*sin(m_theta * 180/M_PI); + m_table( index, STRAC1 ) = (minTrac + nt*dT)*sin(m_theta * 180/M_PI); + + m_table( index, NJUMP ) = (minJump + nj*dJ)*cos(m_theta * 180/M_PI); + m_table( index, SLIP0 ) = (minJump + nj*dJ)*sin(m_theta * 180/M_PI); + m_table( index, SLIP1 ) = (minJump + nj*dJ)*sin(m_theta * 180/M_PI); + m_table( index, FS ) = fields::contact::FractureState::Stick; -} + m_table( index, TLIM ) = -1; + //Only for Coulomb + // m_table( index, TLIM ) = cohesion - m_table(index, NTRAC) * frictionCoeff; -// template< typename RELPERM_TYPE > -// std::enable_if_t< std::is_same< TableRelativePermeabilityHysteresis, RELPERM_TYPE >::value, void > -// RelpermDriver::resizeTable() -// { -// if( m_numPhases > 2 ) -// { -// m_table.resize( ( m_numSteps + 1 ) * ( m_numSteps + 1 ), 1 + 3 * m_numPhases ); -// } -// else -// { -// m_table.resize( m_numSteps + 1, 1 + 3 * m_numPhases ); -// } + } + } + +} -// } +template< typename FRICTION_TYPE > +void +FrictionDriver::resizeTable() +{ + m_table.resize((m_numSteps + 1)*(m_numSteps + 1), m_numColumns ); +} + +REGISTER_CATALOG_ENTRY( TaskBase, + FrictionDriver, + string const &, dataRepository::Group * const ) } \ No newline at end of file diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp index ae02bb12a5c..c7e5f4ce6c2 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -29,7 +29,7 @@ class FrictionDriver : public TaskBase Group * const parent ); static string catalogName() - { return "frictionDriver"; } + { return "FrictionDriver"; } void postInputInitialization() override; @@ -51,10 +51,10 @@ class FrictionDriver : public TaskBase // runTest( friction_TYPE & friction, // const arrayView2d< real64, 1 > & table ); - // template< typename friction_TYPE > - // std::enable_if_t< !std::is_same< constitutive::TableRelativePermeabilityHysteresis, friction_TYPE >::value, void > - // runTest( friction_TYPE & friction, - // const arrayView2d< real64, 1 > & table ); + template< typename FRICTION_TYPE > + void + runTest( FRICTION_TYPE & friction, + const arrayView2d< real64, 1 > & table ); /** * @brief Ouput table to file for easy plotting @@ -69,11 +69,10 @@ class FrictionDriver : public TaskBase private: template< typename FRICTION_TYPE > - void resizeTables(); + void resizeTable(); - // template< typename friction_TYPE > - // std::enable_if_t< std::is_same< constitutive::TableRelativePermeabilityHysteresis, friction_TYPE >::value, void > - // resizeTable(); + template< typename FRICTION_TYPE > + void resizeTables(); // template< typename friction_TYPE > // std::enable_if_t< !std::is_same< constitutive::TableRelativePermeabilityHysteresis, friction_TYPE >::value, void > @@ -90,16 +89,34 @@ class FrictionDriver : public TaskBase constexpr static char const * numStepsString() { return "steps"; } + constexpr static char const * jumpFunctionString() + { return "jumpControl"; } + + constexpr static char const * tractionFunctionString() + { return "tractionControl"; } + + constexpr static char const * thetaString() + { return "xTiltAngle";} + + constexpr static char const * phiString() + { return "yTiltAngle";} + constexpr static char const * outputString() { return "output"; } constexpr static char const * baselineString() { return "baseline"; } + }; integer m_numSteps; ///< Number of load steps - integer m_numColumns; ///< Number of columns in data table (depends on number of fluid phases) - integer m_numPhases; ///< Number of fluid phases + static integer const m_numColumns = 8; ///< Number of columns in dat + enum columnKeys { NJUMP, SLIP0, SLIP1, NTRAC, STRAC0, STRAC1, FS, TLIM }; + + string m_jumpFunctionName; ///< + string m_tractionFunctionName; ///< + + float m_theta, m_phi;///< x- and y-tilt of fault string m_frictionName; ///< frictionType identifier string m_outputFile; ///< Output file (optional, no output if not specified) @@ -108,10 +125,6 @@ class FrictionDriver : public TaskBase Path m_baselineFile; ///< Baseline file (optional, for unit testing of solid models) - enum columnKeys - { - TIME - }; ///< Enumeration of "input" column keys for readability static constexpr real64 m_baselineTol = 1e-3; ///< Comparison tolerance for baseline results }; diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.cpp new file mode 100644 index 00000000000..2d40f34235f --- /dev/null +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.cpp @@ -0,0 +1,26 @@ +#include "FrictionDriverRunTest.hpp" +#include "constitutive/contact/CoulombFriction.hpp" +#include "constitutive/contact/FrictionlessContact.hpp" +#include "constitutive/contact/RateAndStateFriction.hpp" +#include + + +namespace geos { + +template +void +FrictionDriver::runTest(constitutive::CoulombFriction&, const arrayView2d &); + +template +void +FrictionDriver::runTest(constitutive::FrictionlessContact&, const arrayView2d &); + +template +void +FrictionDriver::runTest(constitutive::RateAndStateFriction>&, const arrayView2d &); + +template +void +FrictionDriver::runTest(constitutive::RateAndStateFriction>&, const arrayView2d &); + +} diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp index eaaa5bae76a..cde385ff032 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp @@ -16,7 +16,7 @@ #ifndef GEOS_FRICTIONDRIVERRUNTEST_HPP_ #define GEOS_FRICTIONDRIVERRUNTEST_HPP_ -#include "constitutive/contact/FrictionDriver.hpp" +#include "constitutiveDrivers/contact/FrictionDriver.hpp" #include "physicsSolvers/solidMechanics/contact/FractureState.hpp" #include "constitutive/solid/SolidFields.hpp" @@ -27,79 +27,47 @@ namespace geos template< typename FRICTION_TYPE > void -FrictionDriver::runTest( FRICTION_TYPE & relperm, +FrictionDriver::runTest( FRICTION_TYPE & friction, const arrayView2d< real64 > & table ) { - // get number of phases and components - integer const numPhases = relperm.numFluidPhases(); + array2d< real64 > jumps, tractions; + jumps.resize(table.size(0),3); + tractions.resize(table.size(0),3); - // create kernel wrapper - - typename RELPERM_TYPE::KernelWrapper const kernelWrapper = relperm.createKernelWrapper(); - - // set saturation to user specified feed - // it is more convenient to provide input in molar, so perform molar to mass conversion here - - array2d< real64, compflow::LAYOUT_PHASE > saturationValues; - if( numPhases > 2 ) - { - saturationValues.resize(( m_numSteps + 1 ) * ( m_numSteps + 1 ), numPhases ); - } - else - { - saturationValues.resize( m_numSteps + 1, numPhases ); - } - integer const ipWater = relperm.getPhaseOrder()[PT::WATER]; - integer const ipOil = relperm.getPhaseOrder()[PT::OIL]; - integer const ipGas = relperm.getPhaseOrder()[PT::GAS]; - const localIndex offset = std::max( std::max( ipOil, ipWater ), std::max( ipOil, ipGas ) ) + 1; - - for( integer n = 0; n < table.size( 0 ); ++n ) + for( integer n = 0; n < table.size(0); ++n) { + jumps[n][0] = table(n,NJUMP); + jumps[n][1] = table(n,SLIP0); + jumps[n][2] = table(n,SLIP1); - - if( m_numPhases > 2 ) - { - saturationValues[n][ipWater] = table( n, ipWater + 1 ); - saturationValues[n][ipOil] = table( n, ipOil + 1 ); - saturationValues[n][ipGas] = table( n, ipGas + 1 ); - } - else//two-phase - { - if( ipWater < 0 ) - { - saturationValues[n][ipOil] = table( n, ipOil + 1 ); - saturationValues[n][ipGas] = table( n, ipGas + 1 ); - } - else if( ipGas < 0 ) - { - saturationValues[n][ipWater] = table( n, ipWater + 1 ); - saturationValues[n][ipOil] = table( n, ipOil + 1 ); - } - } + tractions[n][0] = table(n,NTRAC); + tractions[n][1] = table(n,STRAC0); + tractions[n][2] = table(n,STRAC1); } - arrayView2d< real64 const, compflow::USD_PHASE > const saturation = saturationValues.toViewConst(); - // perform relperm update using table (Swet,Snonwet) and save resulting total density, etc. - // note: column indexing should be kept consistent with output file header below. + // create kernel wrapper + typename FRICTION_TYPE::KernelWrapper const kernelWrapper = friction.createKernelUpdates(); - forAll< parallelDevicePolicy<> >( saturation.size( 0 ), - [numPhases, kernelWrapper, saturation, table, - offset] GEOS_HOST_DEVICE ( integer const n ) + forAll< parallelDevicePolicy<> >( 1, + [ kernelWrapper, table, jumps, tractions ] + GEOS_HOST_DEVICE ( integer const ei ) { - kernelWrapper.update( 0, 0, saturation[n] ); - for( integer p = 0; p < numPhases; ++p ) + for( integer i = 1; i < table.size(0) ; ++i ) { - table( n, offset + 1 + p ) = kernelWrapper.relperm()( 0, 0, p ); + integer fs = fields::contact::FractureState::Stick; + kernelWrapper.updateFractureState( jumps[i], + tractions[i], + fs ); + + table(i,FS) = fs; } } ); } - } From 833f25aea0e91a7e95aad8f5c00aedc10e4d7201 Mon Sep 17 00:00:00 2001 From: jacques franc Date: Wed, 5 Nov 2025 18:17:45 +0100 Subject: [PATCH 03/25] Add tau lim --- .../constitutive/contact/CoulombFriction.hpp | 8 ++++++++ .../contact/FrictionDriver.cpp | 16 +++++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/coreComponents/constitutive/contact/CoulombFriction.hpp b/src/coreComponents/constitutive/contact/CoulombFriction.hpp index e5a3387743d..5bf8057fef6 100644 --- a/src/coreComponents/constitutive/contact/CoulombFriction.hpp +++ b/src/coreComponents/constitutive/contact/CoulombFriction.hpp @@ -182,6 +182,14 @@ class CoulombFriction : public FrictionBase */ KernelWrapper createKernelUpdates() const; + /// getting cohesion value + real64 getCohesion() const + { return m_cohesion; } + + /// getting friction coeff + real64 getFrictionCoeff() const + { return m_frictionCoefficient; } + /** * @struct Set of "char const *" and keys for data specified in this class. */ diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp index 0239141cddc..1388b8ecc6c 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -22,6 +22,7 @@ #include "functions/FunctionManager.hpp" #include "functions/TableFunction.hpp" #include +#include #include "FrictionDriver.hpp" @@ -246,14 +247,17 @@ void FrictionDriver::resizeTables() // set input columns resizeTable< FRICTION_TYPE >(); - // real64 const cohesion = baseFriction.getWrapper("cohesion"); - // real64 const frictionCoeff = baseFriction.getGroup("frictionCoefficient"); + real64 cohesion = 0.; + real64 frictionCoeff = 0.; + if constexpr ( std::is_same_v< CoulombFriction, FRICTION_TYPE> ) { + + cohesion = dynamic_cast(&baseFriction)->getCohesion(); + frictionCoeff = dynamic_cast(&baseFriction)->getFrictionCoeff(); + } //All variation for( integer nt = 0; nt < m_numSteps+1; ++nt ) { - - for( integer nj = 0; nj < m_numSteps+1; ++nj ) { @@ -268,10 +272,8 @@ void FrictionDriver::resizeTables() m_table( index, FS ) = fields::contact::FractureState::Stick; - - m_table( index, TLIM ) = -1; //Only for Coulomb - // m_table( index, TLIM ) = cohesion - m_table(index, NTRAC) * frictionCoeff; + m_table( index, TLIM ) = cohesion - m_table(index, NTRAC) * frictionCoeff; } } From 49116212d639040b0c68953d4e90665f08d11b10 Mon Sep 17 00:00:00 2001 From: jacques franc Date: Thu, 6 Nov 2025 14:54:34 +0100 Subject: [PATCH 04/25] fixes --- .../contact/FrictionDriver.cpp | 42 +++++++++++-------- .../contact/FrictionDriver.hpp | 4 +- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp index 1388b8ecc6c..1f475f27a45 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -130,10 +130,11 @@ void FrictionDriver::outputResults() FILE * fp = fopen( m_outputFile.c_str(), "w" ); - fprintf( fp, "# column 1-3 = normal and in-plane displacement jump\n" ); - fprintf( fp, "# columns 4-6 = normal and in-place tractions\n"); - fprintf( fp, "# columns 7 = fracture state (0:Stick,1-2:[new]Slip,3:Open)\n"); - fprintf( fp, "# columns 8 = tau lim\n"); + fprintf( fp, "# column 1 = index \n" ); + fprintf( fp, "# column 2-3 = normal and in-plane displacement jump\n" ); + fprintf( fp, "# columns 5-7 = normal and in-place tractions\n"); + fprintf( fp, "# columns 8 = fracture state (0:Stick,1-2:[new]Slip,3:Open)\n"); + fprintf( fp, "# columns 9 = tau lim\n"); for( integer n = 0; n < m_table.size( 0 ); ++n ) { @@ -236,16 +237,21 @@ void FrictionDriver::resizeTables() jumpFunction.initializeFunction(); tractionFunction.initializeFunction(); - ArrayOfArraysView< real64 > Jcoordinates = jumpFunction.getCoordinates(); - real64 const minJump = Jcoordinates[0][0]; - real64 const maxJump = Jcoordinates[0][Jcoordinates.sizeOfArray( 0 )-1]; - real64 const dJ = (maxJump-minJump) / m_numSteps; - ArrayOfArraysView< real64 > Tcoordinates = jumpFunction.getCoordinates(); - real64 const minTrac = Tcoordinates[0][0]; - real64 const maxTrac = Tcoordinates[0][Tcoordinates.sizeOfArray( 0 )-1]; - real64 const dT = (maxTrac-minTrac) / m_numSteps; + ArrayOfArraysView< real64 > coordinates = jumpFunction.getCoordinates(); + real64 const minTime = coordinates[0][0]; + real64 const maxTime = coordinates[0][coordinates.sizeOfArray( 0 )-1]; + real64 const dt = (maxTime-minTime) / m_numSteps; + // set input columns resizeTable< FRICTION_TYPE >(); + + // set time column + for( integer k=0; k Date: Thu, 6 Nov 2025 14:54:34 +0100 Subject: [PATCH 05/25] fixes --- .../contact/FrictionDriver.cpp | 50 ++++++++++++------- .../contact/FrictionDriver.hpp | 4 +- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp index 1388b8ecc6c..4ee41eaeac9 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -130,10 +130,11 @@ void FrictionDriver::outputResults() FILE * fp = fopen( m_outputFile.c_str(), "w" ); - fprintf( fp, "# column 1-3 = normal and in-plane displacement jump\n" ); - fprintf( fp, "# columns 4-6 = normal and in-place tractions\n"); - fprintf( fp, "# columns 7 = fracture state (0:Stick,1-2:[new]Slip,3:Open)\n"); - fprintf( fp, "# columns 8 = tau lim\n"); + fprintf( fp, "# column 1 = index \n" ); + fprintf( fp, "# column 2-3 = normal and in-plane displacement jump\n" ); + fprintf( fp, "# columns 5-7 = normal and in-place tractions\n"); + fprintf( fp, "# columns 8 = fracture state (0:Stick,1-2:[new]Slip,3:Open)\n"); + fprintf( fp, "# columns 9 = tau lim\n"); for( integer n = 0; n < m_table.size( 0 ); ++n ) { @@ -236,16 +237,23 @@ void FrictionDriver::resizeTables() jumpFunction.initializeFunction(); tractionFunction.initializeFunction(); - ArrayOfArraysView< real64 > Jcoordinates = jumpFunction.getCoordinates(); - real64 const minJump = Jcoordinates[0][0]; - real64 const maxJump = Jcoordinates[0][Jcoordinates.sizeOfArray( 0 )-1]; - real64 const dJ = (maxJump-minJump) / m_numSteps; - ArrayOfArraysView< real64 > Tcoordinates = jumpFunction.getCoordinates(); - real64 const minTrac = Tcoordinates[0][0]; - real64 const maxTrac = Tcoordinates[0][Tcoordinates.sizeOfArray( 0 )-1]; - real64 const dT = (maxTrac-minTrac) / m_numSteps; + ArrayOfArraysView< real64 > coordinates = jumpFunction.getCoordinates(); + real64 const minTime = coordinates[0][0]; + real64 const maxTime = coordinates[0][coordinates.sizeOfArray( 0 )-1]; + real64 const dt = (maxTime-minTime) / m_numSteps; + // set input columns resizeTable< FRICTION_TYPE >(); + + // set time column + for( integer k=0; k void diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp index c7e5f4ce6c2..dddaffafc80 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -110,8 +110,8 @@ class FrictionDriver : public TaskBase }; integer m_numSteps; ///< Number of load steps - static integer const m_numColumns = 8; ///< Number of columns in dat - enum columnKeys { NJUMP, SLIP0, SLIP1, NTRAC, STRAC0, STRAC1, FS, TLIM }; + static integer const m_numColumns = 9; ///< Number of columns in dat + enum columnKeys { TIME, NJUMP, SLIP0, SLIP1, NTRAC, STRAC0, STRAC1, FS, TLIM }; string m_jumpFunctionName; ///< string m_tractionFunctionName; ///< From cd3d4fe523123f8a4eadc65decabc4b28a7a9090 Mon Sep 17 00:00:00 2001 From: Dickson Kachuma <81433670+dkachuma@users.noreply.github.com> Date: Fri, 24 Apr 2026 11:26:57 -0500 Subject: [PATCH 06/25] Friction driver suggestions (#4037) --- .../friction}/frictionDriver_Coulomb.xml | 4 +- .../friction}/frictionDriver_base.xml | 34 +-- .../friction}/tables/jumps.geos | 0 .../friction}/tables/time.geos | 0 .../friction}/tables/tractions.geos | 0 .../constitutiveDrivers/CMakeLists.txt | 4 +- .../contact/FrictionDriver.cpp | 271 ++++++------------ .../contact/FrictionDriver.hpp | 87 ++---- .../contact/FrictionDriverRunTest.hpp | 52 ++-- .../contact/LogLevelsInfo.hpp | 52 ---- src/coreComponents/schema/schema.xsd | 28 ++ src/coreComponents/schema/schema.xsd.other | 7 + 12 files changed, 174 insertions(+), 365 deletions(-) rename inputFiles/{frictionDriver => constitutiveDriver/friction}/frictionDriver_Coulomb.xml (85%) rename inputFiles/{frictionDriver => constitutiveDriver/friction}/frictionDriver_base.xml (66%) rename inputFiles/{frictionDriver => constitutiveDriver/friction}/tables/jumps.geos (100%) rename inputFiles/{frictionDriver => constitutiveDriver/friction}/tables/time.geos (100%) rename inputFiles/{frictionDriver => constitutiveDriver/friction}/tables/tractions.geos (100%) delete mode 100644 src/coreComponents/constitutiveDrivers/contact/LogLevelsInfo.hpp diff --git a/inputFiles/frictionDriver/frictionDriver_Coulomb.xml b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml similarity index 85% rename from inputFiles/frictionDriver/frictionDriver_Coulomb.xml rename to inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml index 3a1c0a5b630..6fd8f7907a2 100644 --- a/inputFiles/frictionDriver/frictionDriver_Coulomb.xml +++ b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml @@ -9,8 +9,8 @@ jumpControl="jFunction" xTiltAngle="80" tractionControl="tFunction" - steps="10" - output="FrictionDriver.txt" /> + steps="10" + output="frictionDriver_Coulomb.txt" /> diff --git a/inputFiles/frictionDriver/frictionDriver_base.xml b/inputFiles/constitutiveDriver/friction/frictionDriver_base.xml similarity index 66% rename from inputFiles/frictionDriver/frictionDriver_base.xml rename to inputFiles/constitutiveDriver/friction/frictionDriver_base.xml index df5ef688301..bf4b23983db 100644 --- a/inputFiles/frictionDriver/frictionDriver_base.xml +++ b/inputFiles/constitutiveDriver/friction/frictionDriver_base.xml @@ -1,12 +1,24 @@ + + + + + + @@ -37,26 +49,4 @@ voxelFile="tables/tractions.geos"/> - - - - - - - - - - diff --git a/inputFiles/frictionDriver/tables/jumps.geos b/inputFiles/constitutiveDriver/friction/tables/jumps.geos similarity index 100% rename from inputFiles/frictionDriver/tables/jumps.geos rename to inputFiles/constitutiveDriver/friction/tables/jumps.geos diff --git a/inputFiles/frictionDriver/tables/time.geos b/inputFiles/constitutiveDriver/friction/tables/time.geos similarity index 100% rename from inputFiles/frictionDriver/tables/time.geos rename to inputFiles/constitutiveDriver/friction/tables/time.geos diff --git a/inputFiles/frictionDriver/tables/tractions.geos b/inputFiles/constitutiveDriver/friction/tables/tractions.geos similarity index 100% rename from inputFiles/frictionDriver/tables/tractions.geos rename to inputFiles/constitutiveDriver/friction/tables/tractions.geos diff --git a/src/coreComponents/constitutiveDrivers/CMakeLists.txt b/src/coreComponents/constitutiveDrivers/CMakeLists.txt index 6c38181d3fc..b3554ad559c 100644 --- a/src/coreComponents/constitutiveDrivers/CMakeLists.txt +++ b/src/coreComponents/constitutiveDrivers/CMakeLists.txt @@ -37,6 +37,8 @@ set( constitutiveDrivers_headers # set( constitutiveDrivers_sources ConstitutiveDriver.cpp + contact/FrictionDriver.cpp + contact/FrictionDriverRunTest.cpp fluid/multiFluid/PVTDriver.cpp fluid/multiFluid/constant/PVTDriverRunTestInvariantImmiscibleFluid.cpp fluid/multiFluid/blackOil/PVTDriverRunTestDeadOilFluid.cpp @@ -59,8 +61,6 @@ set( constitutiveDrivers_sources relativePermeability/RelpermDriverTableRelativeRunTest.cpp relativePermeability/RelpermDriverTableRelativeHysteresisRunTest.cpp solid/TriaxialDriver.cpp - contact/FrictionDriver.cpp - contact/FrictionDriverRunTest.cpp ) set( dependencyList ${parallelDeps} constitutive events ) diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp index 985077a7bba..c2538822f04 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -13,18 +13,15 @@ * ------------------------------------------------------------------------------------------------------------ */ -#include "common/MpiWrapper.hpp" +#include "FrictionDriver.hpp" + #include "constitutive/ConstitutiveManager.hpp" -#include "constitutiveDrivers/contact/LogLevelsInfo.hpp" +#include "constitutiveDrivers/LogLevelsInfo.hpp" #include "constitutive/contact/FrictionBase.hpp" #include "constitutive/contact/FrictionSelector.hpp" #include "functions/FunctionManager.hpp" #include "functions/TableFunction.hpp" -#include -#include - -#include "FrictionDriver.hpp" namespace geos { @@ -33,8 +30,7 @@ using namespace dataRepository; using namespace constitutive; FrictionDriver::FrictionDriver( const string & name, Group * const parent ) - : - TaskBase( name, parent ) + : ConstitutiveDriver( name, parent ) { registerWrapper( viewKeyStruct::frictionNameString(), &m_frictionName ). setRTTypeName( rtTypes::CustomTypes::groupNameRef ). @@ -61,133 +57,55 @@ FrictionDriver::FrictionDriver( const string & name, Group * const parent ) setInputFlag( InputFlags::INVALID ). setDescription( "Number of increment step to take in both jumps and traction increments" ); - registerWrapper( viewKeyStruct::outputString(), &m_outputFile ). - setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( "none" ). - setDescription( "Output file" ); - - registerWrapper( viewKeyStruct::baselineString(), &m_baselineFile ). - setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( "none" ). - setDescription( "Baseline file" ); - addLogLevel< logInfo::LogOutput >(); } -void FrictionDriver::compareWithBaseline() -{ - // open baseline file - - std::ifstream file( m_baselineFile.c_str() ); - GEOS_THROW_IF( !file.is_open(), GEOS_FMT( "Can't seem to open the baseline file ", m_baselineFile ), InputError ); - - // discard file header - - string line; - for( integer row=0; row < m_numColumns; ++row ) - { - getline( file, line ); - } - - // read data block. we assume the file size is consistent with m_table, - // but check for a premature end-of-file. we then compare results value by value. - // we ignore the newton iteration and residual columns, as those may be platform - // specific. - - real64 value; - real64 error; - - for( integer row=0; row < m_table.size( 0 ); ++row ) - { - for( integer col=0; col < m_table.size( 1 ); ++col ) - { - GEOS_THROW_IF( file.eof(), "Baseline file appears shorter than internal results", InputError ); - file >> value; - - error = fabs( m_table[row][col]-value ) / ( fabs( value )+1 ); - GEOS_THROW_IF( error > m_baselineTol, GEOS_FMT( "Results do not match baseline at data row {} (row {} with header) and column {}", - row+1, - row+10, - col+1 ), - InputError ); - - } - } - - // check we actually reached the end of the baseline file - - file >> value; - GEOS_THROW_IF( !file.eof(), "Baseline file appears longer than internal results", InputError ); - - // success - - GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Comparison ........ Internal results consistent with baseline." ); - - file.close(); -} - -void FrictionDriver::outputResults() +void FrictionDriver::postInputInitialization() { - // TODO: improve file path output to grab command line -o directory - // for the moment, we just use the specified m_outputFile directly + ConstitutiveDriver::postInputInitialization(); - FILE * fp = fopen( m_outputFile.c_str(), "w" ); + // Check that the functions exist + FunctionManager & functionManager = FunctionManager::getInstance(); + GEOS_ERROR_IF( !functionManager.hasGroup< TableFunction >( m_jumpFunctionName ), + GEOS_FMT( "Jump function with name '{}' not found", m_jumpFunctionName ), + getWrapperDataContext( viewKeyStruct::jumpFunctionString() ) ); - fprintf( fp, "# column 1 = index \n" ); - fprintf( fp, "# column 2-3 = normal and in-plane displacement jump\n" ); - fprintf( fp, "# columns 5-7 = normal and in-place tractions\n" ); - fprintf( fp, "# columns 8 = fracture state (0:Stick,1-2:[new]Slip,3:Open)\n" ); - fprintf( fp, "# columns 9 = tau lim\n" ); + GEOS_ERROR_IF( !functionManager.hasGroup< TableFunction >( m_tractionFunctionName ), + GEOS_FMT( "Traction function with name '{}' not found", m_tractionFunctionName ), + getWrapperDataContext( viewKeyStruct::tractionFunctionString() ) ); - for( integer n = 0; n < m_table.size( 0 ); ++n ) - { - for( integer col = 0; col < m_table.size( 1 ); ++col ) - { - fprintf( fp, "%.4e ", m_table( n, col ) ); - } - fprintf( fp, "\n" ); - } - fclose( fp ); + string_array columnNames; + getColumnNames( columnNames ); + integer const numCols = static_cast< integer >(columnNames.size()); -} + // initialize functions + TableFunction & jumpFunction = functionManager.getGroup< TableFunction >( m_jumpFunctionName ); + TableFunction & tractionFunction = functionManager.getGroup< TableFunction >( m_tractionFunctionName ); + jumpFunction.initializeFunction(); + tractionFunction.initializeFunction(); -void FrictionDriver::postInputInitialization() -{ -// ConstitutiveManager -// & constitutiveManager = this->getGroupByPath< ConstitutiveManager >( "/Problem/domain/Constitutive" ); -// FrictionBase& baseFriction = constitutiveManager.getGroup< FrictionBase >( m_frictionName ); + // TODO: Maybe we should take the maximum extent of jumpFunction and tractionFunction + ArrayOfArraysView< real64 > coordinates = jumpFunction.getCoordinates(); + real64 const minTime = coordinates[0][0]; + real64 const maxTime = coordinates[0][coordinates.sizeOfArray( 0 )-1]; -// // m_numPhases = baseFriction.numSubGroups(); + // Allocate the data + allocateTable( numCols, minTime, maxTime ); + // set input columns + initializeTable(); } - -bool FrictionDriver::execute( const geos::real64 GEOS_UNUSED_PARAM( time_n ), - const geos::real64 GEOS_UNUSED_PARAM( dt ), - const geos::integer GEOS_UNUSED_PARAM( cycleNumber ), - const geos::integer GEOS_UNUSED_PARAM( eventCounter ), - const geos::real64 GEOS_UNUSED_PARAM( eventProgress ), - geos::DomainPartition & - GEOS_UNUSED_PARAM( domain ) ) +bool FrictionDriver::execute() { - // this code only makes sense in serial - - GEOS_THROW_IF( MpiWrapper::commRank() > 0, "FrictionDriver should only be run in serial", geos::RuntimeError ); - - - ConstitutiveManager - & constitutiveManager = this->getGroupByPath< ConstitutiveManager >( "/Problem/domain/Constitutive" ); - FrictionBase - & baseFriction = constitutiveManager.getGroup< FrictionBase >( m_frictionName ); + FrictionBase & baseFriction = getFriction(); GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, "Launching Friction Driver" ); - GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Friction .................. " << m_frictionName ); + GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Friction ............... " << m_frictionName ); GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Type ................... " << baseFriction.getCatalogName() ); -// GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " No. of Phases .......... " << m_numPhases ); GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Steps .................. " << m_numSteps ); GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Output ................. " << m_outputFile ); - GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Baseline ............... " << m_baselineFile ); // create a dummy discretization with one quadrature point for // storing constitutive data @@ -196,113 +114,88 @@ bool FrictionDriver::execute( const geos::real64 GEOS_UNUSED_PARAM( time_n ), dataRepository::Group rootGroup( "root", node ); dataRepository::Group discretization( "discretization", &rootGroup ); - discretization.resize( 1 ); // one element + integer const numRows = m_table.size( 0 ); + discretization.resize( numRows ); // numRows elements baseFriction.allocateConstitutiveData( discretization, 1 ); // one quadrature point constitutiveUpdatePassThru( baseFriction, [&]( auto & selectedFrictionModel ) { using FRICTION_TYPE = TYPEOFREF( selectedFrictionModel ); - resizeTables< FRICTION_TYPE >(); runTest< FRICTION_TYPE >( selectedFrictionModel, m_table ); } ); - // move table back to host for output - m_table.move( LvArray::MemorySpace::host ); - - if( m_outputFile != "none" ) - { - outputResults(); - } + return false; +} - if( m_baselineFile != "none" ) +void FrictionDriver::getColumnNames( string_array & columnNames ) const +{ + columnNames.emplace_back( "time" ); + columnNames.emplace_back( "traction,normal" ); + columnNames.emplace_back( "traction,tangent1" ); + columnNames.emplace_back( "traction,tangent2" ); + columnNames.emplace_back( "displacement jump,normal" ); + columnNames.emplace_back( "displacement jump,tangent1" ); + columnNames.emplace_back( "displacement jump,tangent2" ); + columnNames.emplace_back( "fracture state" ); + + if( dynamic_cast< CoulombFriction const * >(&getFriction()) != nullptr ) { - compareWithBaseline(); + columnNames.emplace_back( "tau limit" ); } - - return false; } - -template< typename FRICTION_TYPE > -void FrictionDriver::resizeTables() +void FrictionDriver::initializeTable() { - ConstitutiveManager - & constitutiveManager = this->getGroupByPath< ConstitutiveManager >( "/Problem/domain/Constitutive" ); - FrictionBase - & baseFriction = constitutiveManager.getGroup< FrictionBase >( m_frictionName ); + integer const numRows = m_table.size( 0 ); - // initialize table functions FunctionManager & functionManager = FunctionManager::getInstance(); + TableFunction const & jumpFunction = functionManager.getGroup< TableFunction >( m_jumpFunctionName ); + TableFunction const & tractionFunction = functionManager.getGroup< TableFunction >( m_tractionFunctionName ); - TableFunction & jumpFunction = functionManager.getGroup< TableFunction >( m_jumpFunctionName ); - TableFunction & tractionFunction = functionManager.getGroup< TableFunction >( m_tractionFunctionName ); - - jumpFunction.initializeFunction(); - tractionFunction.initializeFunction(); - - ArrayOfArraysView< real64 > coordinates = jumpFunction.getCoordinates(); - real64 const minTime = coordinates[0][0]; - real64 const maxTime = coordinates[0][coordinates.sizeOfArray( 0 )-1]; - real64 const dt = (maxTime-minTime) / m_numSteps; + real64 const cos_theta = cos( m_theta * M_PI/180.0 ); + real64 const sin_theta = sin( m_theta * M_PI/180.0 ); - // set input columns - resizeTable< FRICTION_TYPE >(); + real64 const cos_phi = cos( m_phi * M_PI/180.0 ); + real64 const sin_phi = sin( m_phi * M_PI/180.0 ); - // set time column - for( integer k=0; k ) { + m_table( index, NJUMP ) = jump*sin_theta; + m_table( index, SLIP0 ) = jump*cos_theta*cos_phi; + m_table( index, SLIP1 ) = jump*cos_theta*sin_phi; - cohesion = dynamic_cast< CoulombFriction * >(&baseFriction)->getCohesion(); - frictionCoeff = dynamic_cast< CoulombFriction * >(&baseFriction)->getFrictionCoeff(); + m_table( index, FS ) = fields::contact::FractureState::Stick; } - //All variation - for( integer nt = 0; nt < m_numSteps+1; ++nt ) + if( CoulombFriction const * coulombFriction = dynamic_cast< CoulombFriction const * >(&getFriction()) ) { - for( integer nj = 0; nj < m_numSteps+1; ++nj ) + real64 const cohesion = coulombFriction->getCohesion(); + real64 const frictionCoeff = coulombFriction->getFrictionCoeff(); + for( integer index = 0; index < numRows; ++index ) { - - integer index = nt * (m_numSteps+1) + nj; - m_table( index, NTRAC ) = tractionFunction.evaluate( &m_table( nt, TIME ))*sin( m_theta * M_PI/180 ); - m_table( index, STRAC0 ) = tractionFunction.evaluate( &m_table( nt, TIME ))*cos( m_theta * M_PI/180 ); - m_table( index, STRAC1 ) = tractionFunction.evaluate( &m_table( nt, TIME ))*cos( m_theta * M_PI/180 ); - - m_table( index, NJUMP ) = jumpFunction.evaluate( &m_table( nj, TIME ))*sin( m_theta * M_PI/180 ); - m_table( index, SLIP0 ) = jumpFunction.evaluate( &m_table( nj, TIME ))*cos( m_theta * M_PI/180 ); - m_table( index, SLIP1 ) = jumpFunction.evaluate( &m_table( nj, TIME ))*cos( m_theta * M_PI/180 ); - - m_table( index, FS ) = fields::contact::FractureState::Stick; - - //Only for Coulomb - m_table( index, TLIM ) = cohesion - m_table( index, NTRAC ) * frictionCoeff; - + real64 const normal_traction = m_table( index, NTRAC ); + m_table( index, TLIM ) = cohesion - normal_traction * frictionCoeff; } } - } -//TODO updateConfig proxy -// simultaneaous branch -// unsim -// checkconstaint -// *keep track of iter - +FrictionBase & FrictionDriver::getFriction() +{ + return getConstitutiveManager().getGroup< FrictionBase >( m_frictionName ); +} -template< typename FRICTION_TYPE > -void -FrictionDriver::resizeTable() +FrictionBase const & FrictionDriver::getFriction() const { - m_table.resize((m_numSteps + 1)*(m_numSteps + 1), m_numColumns ); + return getConstitutiveManager().getGroup< FrictionBase >( m_frictionName ); } REGISTER_CATALOG_ENTRY( TaskBase, diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp index 6374d6c49d1..d912eed02d6 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -13,17 +13,20 @@ * ------------------------------------------------------------------------------------------------------------ */ -#ifndef GEOS_frictionDRIVER_HPP_ -#define GEOS_frictionDRIVER_HPP_ +#ifndef GEOS_CONSTITUTIVEDRIVERS_CONTACT_FRICTIONDRIVER_HPP +#define GEOS_CONSTITUTIVEDRIVERS_CONTACT_FRICTIONDRIVER_HPP -#include "events/tasks/TaskBase.hpp" +#include "constitutiveDrivers/ConstitutiveDriver.hpp" namespace geos { - -class FrictionDriver : public TaskBase +namespace constitutive { +class FrictionBase; +} +class FrictionDriver : public ConstitutiveDriver +{ public: FrictionDriver( const string & name, Group * const parent ); @@ -33,62 +36,32 @@ class FrictionDriver : public TaskBase void postInputInitialization() override; - virtual bool execute( real64 const GEOS_UNUSED_PARAM( time_n ), - real64 const GEOS_UNUSED_PARAM( dt ), - integer const GEOS_UNUSED_PARAM( cycleNumber ), - integer const GEOS_UNUSED_PARAM( eventCounter ), - real64 const GEOS_UNUSED_PARAM( eventProgress ), - DomainPartition & - GEOS_UNUSED_PARAM( domain ) ) override; - - // /** - // * @brief Run test using loading protocol in table - // * @param i friction constitutive model - // * @param table Table with input/output time history - // */ - // template< typename friction_TYPE > - // std::enable_if_t< std::is_same< constitutive::TableRelativePermeabilityHysteresis, friction_TYPE >::value, void > - // runTest( friction_TYPE & friction, - // const arrayView2d< real64, 1 > & table ); + bool execute() override; + + void getColumnNames( string_array & columnNames ) const override; template< typename FRICTION_TYPE > void runTest( FRICTION_TYPE & friction, const arrayView2d< real64, 1 > & table ); +private: /** - * @brief Ouput table to file for easy plotting - */ - void outputResults(); - - /** - * @brief Read in a baseline table from file and compare with computed one (for unit testing purposes) + * @brief Get the friction model from the catalog */ - void compareWithBaseline(); - -private: + constitutive::FrictionBase & getFriction(); + constitutive::FrictionBase const & getFriction() const; - template< typename FRICTION_TYPE > - void resizeTable(); - - template< typename FRICTION_TYPE > - void resizeTables(); - - // template< typename friction_TYPE > - // std::enable_if_t< !std::is_same< constitutive::TableRelativePermeabilityHysteresis, friction_TYPE >::value, void > - // resizeTable(); + void initializeTable(); /** * @struct viewKeyStruct holds char strings and viewKeys for fast lookup */ - struct viewKeyStruct + struct viewKeyStruct : ConstitutiveDriver::viewKeyStruct { constexpr static char const * frictionNameString() { return "friction"; } - constexpr static char const * numStepsString() - { return "steps"; } - constexpr static char const * jumpFunctionString() { return "jumpControl"; } @@ -100,36 +73,20 @@ class FrictionDriver : public TaskBase constexpr static char const * phiString() { return "yTiltAngle";} - - constexpr static char const * outputString() - { return "output"; } - - constexpr static char const * baselineString() - { return "baseline"; } - }; - integer m_numSteps; ///< Number of load steps - static integer const m_numColumns = 9; ///< Number of columns in dat - enum columnKeys { TIME, NJUMP, SLIP0, SLIP1, NTRAC, STRAC0, STRAC1, FS, TLIM }; + // Time is defined in base class + enum columnKeys { NJUMP = 1, SLIP0, SLIP1, NTRAC, STRAC0, STRAC1, FS, TLIM }; string m_jumpFunctionName; ///< string m_tractionFunctionName; ///< - float m_theta, m_phi;///< x- and y-tilt of fault + real64 m_theta{0.0}; ///< x-tilt of fault + real64 m_phi{0.0}; ///< y-tilt of fault string m_frictionName; ///< frictionType identifier - string m_outputFile; ///< Output file (optional, no output if not specified) - - array2d< real64 > m_table; ///< Table storing time-history of input/output - - Path m_baselineFile; ///< Baseline file (optional, for unit testing of solid models) - - - static constexpr real64 m_baselineTol = 1e-3; ///< Comparison tolerance for baseline results }; - } -#endif //GEOS_FRICTIONDRIVER_HPP_ +#endif //GEOS_CONSTITUTIVEDRIVERS_CONTACT_FRICTIONDRIVER_HPP diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp index b05e42a8fc4..5c0e5875dfa 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp @@ -20,56 +20,42 @@ #include "physicsSolvers/solidMechanics/contact/FractureState.hpp" #include "constitutive/solid/SolidFields.hpp" - namespace geos { - template< typename FRICTION_TYPE > void FrictionDriver::runTest( FRICTION_TYPE & friction, const arrayView2d< real64 > & table ) { + // Create kernel wrapper + typename FRICTION_TYPE::KernelWrapper const kernelWrapper = friction.createKernelUpdates(); - array2d< real64 > jumps, tractions; - jumps.resize( table.size( 0 ), 3 ); - tractions.resize( table.size( 0 ), 3 ); - - for( integer n = 0; n < table.size( 0 ); ++n ) + integer const numRows = m_table.size( 0 ); + forAll< parallelDevicePolicy<> >( numRows, + [ kernelWrapper, table ] + GEOS_HOST_DEVICE ( integer const ei ) { - jumps[n][0] = table( n, NJUMP ); - jumps[n][1] = table( n, SLIP0 ); - jumps[n][2] = table( n, SLIP1 ); - - tractions[n][0] = table( n, NTRAC ); - tractions[n][1] = table( n, STRAC0 ); - tractions[n][2] = table( n, STRAC1 ); + stackArray1d< real64, 3 > jump( 3 ); + stackArray1d< real64, 3 > traction( 3 ); - } + jump[0] = table( ei, NJUMP ); + jump[1] = table( ei, SLIP0 ); + jump[2] = table( ei, SLIP1 ); + traction[0] = table( ei, NTRAC ); + traction[1] = table( ei, STRAC0 ); + traction[2] = table( ei, STRAC1 ); - // create kernel wrapper - typename FRICTION_TYPE::KernelWrapper const kernelWrapper = friction.createKernelUpdates(); + integer fracture_state = fields::contact::FractureState::Stick; + kernelWrapper.updateFractureState( jump.toSliceConst(), + traction.toSliceConst(), + fracture_state ); - forAll< parallelDevicePolicy<> >( 1, - [ kernelWrapper, table, jumps, tractions ] - GEOS_HOST_DEVICE ( integer const GEOS_UNUSED_PARAM( ei ) ) - { - - for( integer i = 1; i < table.size( 0 ); ++i ) - { - integer fs = fields::contact::FractureState::Stick; - kernelWrapper.updateFractureState( jumps[i], - tractions[i], - fs ); - - table( i, FS ) = fs; - } + table( ei, FS ) = fracture_state; } ); - } } - #endif //GEOS_FRICTIONDRIVERRUNTEST_HPP_ diff --git a/src/coreComponents/constitutiveDrivers/contact/LogLevelsInfo.hpp b/src/coreComponents/constitutiveDrivers/contact/LogLevelsInfo.hpp deleted file mode 100644 index 1a0319a7db4..00000000000 --- a/src/coreComponents/constitutiveDrivers/contact/LogLevelsInfo.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * SPDX-License-Identifier: LGPL-2.1-only - * - * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 TotalEnergies - * 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 LogLevelsInfo.hpp - * This file contains common log level informations for PVT driver - */ - -#ifndef GEOS_CONSTITUTIVEDRIVERS_CONTACT_LOGLEVELSINFO_HPP_ -#define GEOS_CONSTITUTIVEDRIVERS_CONTACT_LOGLEVELSINFO_HPP_ - -#include "common/DataTypes.hpp" - -namespace geos -{ - -namespace logInfo -{ - -/** - * @name Common LogLevels info structures. They must comply with the `is_log_level_info` trait. - */ -///@{ - -/// @cond DO_NOT_DOCUMENT - -struct LogOutput -{ - static constexpr int getMinLogLevel() { return 1; } - static constexpr std::string_view getDescription() { return "Enable log output"; } -}; - -/// @endcond -///@} - -} - -} - -#endif // GEOS_CONSTITUTIVEDRIVERS_CONTACT_LOGLEVELSINFO_HPP_ diff --git a/src/coreComponents/schema/schema.xsd b/src/coreComponents/schema/schema.xsd index 9a9bb51d843..30a9887b6a5 100644 --- a/src/coreComponents/schema/schema.xsd +++ b/src/coreComponents/schema/schema.xsd @@ -569,6 +569,10 @@ + + + + @@ -6266,6 +6270,7 @@ When set to `all` output both convergence & iteration information to a csv.--> + @@ -6380,6 +6385,29 @@ Information output from lower logLevels is added with the desired log level + + + + + + + + + + + + + + + + + + + + + + + + From 937b3a7bb1a783415fbbeadeb8699aea9ea03b92 Mon Sep 17 00:00:00 2001 From: jacques franc Date: Mon, 1 Jun 2026 15:16:22 +0200 Subject: [PATCH 07/25] wip --- .../contact/FrictionDriver.cpp | 24 ++++++++++++++++++- .../contact/FrictionDriver.hpp | 12 +++++++++- .../contact/FrictionDriverRunTest.cpp | 8 +++---- .../contact/FrictionDriverRunTest.hpp | 16 ++++++++++--- 4 files changed, 51 insertions(+), 9 deletions(-) diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp index c2538822f04..4c201261c52 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -36,6 +36,11 @@ FrictionDriver::FrictionDriver( const string & name, Group * const parent ) setRTTypeName( rtTypes::CustomTypes::groupNameRef ). setInputFlag( InputFlags::REQUIRED ). setDescription( "Friction model to test" ); + + registerWrapper( viewKeyStruct::frictionNameString(), &m_contactName ). + setRTTypeName( rtTypes::CustomTypes::groupNameRef ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Contact model to test" ); registerWrapper( viewKeyStruct::numStepsString(), &m_numSteps ). setInputFlag( InputFlags::REQUIRED ). @@ -100,9 +105,15 @@ void FrictionDriver::postInputInitialization() bool FrictionDriver::execute() { FrictionBase & baseFriction = getFriction(); + ContactSolverBase & baseContact = getContact(); + + //temp + auto& castedContactModel = dynamic_cast< SolidMechanicsAugmentedLagrangianContact& >( baseContact ); + assert( castedContactModel ); GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, "Launching Friction Driver" ); GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Friction ............... " << m_frictionName ); + GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Contact ............... " << m_contactName ); GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Type ................... " << baseFriction.getCatalogName() ); GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Steps .................. " << m_numSteps ); GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Output ................. " << m_outputFile ); @@ -121,7 +132,8 @@ bool FrictionDriver::execute() constitutiveUpdatePassThru( baseFriction, [&]( auto & selectedFrictionModel ) { using FRICTION_TYPE = TYPEOFREF( selectedFrictionModel ); - runTest< FRICTION_TYPE >( selectedFrictionModel, m_table ); + using CONTACT_TYPE = TYPEOFREF( castedContactModel ); + runTest< FRICTION_TYPE, CONTACT_TYPE >( selectedFrictionModel, castedContactModel, m_table ); } ); return false; @@ -198,6 +210,16 @@ FrictionBase const & FrictionDriver::getFriction() const return getConstitutiveManager().getGroup< FrictionBase >( m_frictionName ); } +ContactSolverBase & FrictionDriver::getContact() +{ + return getConstitutiveManager().getGroup< ContactSolverBase >( m_contactName ); +} + +ContactSolverBase const & FrictionDriver::getContact() const +{ + return getConstitutiveManager().getGroup< ContactSolverBase >( m_contactName ); +} + REGISTER_CATALOG_ENTRY( TaskBase, FrictionDriver, string const &, dataRepository::Group * const ) diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp index d912eed02d6..ab54add3a65 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -17,6 +17,8 @@ #define GEOS_CONSTITUTIVEDRIVERS_CONTACT_FRICTIONDRIVER_HPP #include "constitutiveDrivers/ConstitutiveDriver.hpp" +#include "physicsSolvers/solidMechanics/contact/ContactSolverBase.hpp" +#include "physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp" namespace geos { @@ -40,9 +42,10 @@ class FrictionDriver : public ConstitutiveDriver void getColumnNames( string_array & columnNames ) const override; - template< typename FRICTION_TYPE > + template< typename FRICTION_TYPE, typename CONTACT_SOLVER > void runTest( FRICTION_TYPE & friction, + CONTACT_SOLVER& contact, const arrayView2d< real64, 1 > & table ); private: @@ -52,6 +55,9 @@ class FrictionDriver : public ConstitutiveDriver constitutive::FrictionBase & getFriction(); constitutive::FrictionBase const & getFriction() const; + ContactSolverBase & getContact(); + ContactSolverBase const & getContact() const; + void initializeTable(); /** @@ -62,6 +68,9 @@ class FrictionDriver : public ConstitutiveDriver constexpr static char const * frictionNameString() { return "friction"; } + constexpr static char const * contactNameString() + { return "contact"; } + constexpr static char const * jumpFunctionString() { return "jumpControl"; } @@ -85,6 +94,7 @@ class FrictionDriver : public ConstitutiveDriver real64 m_phi{0.0}; ///< y-tilt of fault string m_frictionName; ///< frictionType identifier + string m_contactName; ///< ContactSolver identifier }; } diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.cpp index f06fe66436d..88cb5d3af5d 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.cpp @@ -10,18 +10,18 @@ namespace geos template void -FrictionDriver::runTest( constitutive::CoulombFriction &, const arrayView2d< real64 > & ); +FrictionDriver::runTest( constitutive::CoulombFriction &, SolidMechanicsAugmentedLagrangianContact&, const arrayView2d< real64 > & ); template void -FrictionDriver::runTest( constitutive::FrictionlessContact &, const arrayView2d< real64 > & ); +FrictionDriver::runTest( constitutive::FrictionlessContact &, SolidMechanicsAugmentedLagrangianContact&,const arrayView2d< real64 > & ); template void -FrictionDriver::runTest( constitutive::RateAndStateFriction< std::integral_constant< bool, true > > &, const arrayView2d< real64 > & ); +FrictionDriver::runTest( constitutive::RateAndStateFriction< std::integral_constant< bool, true > > &, SolidMechanicsAugmentedLagrangianContact&,const arrayView2d< real64 > & ); template void -FrictionDriver::runTest( constitutive::RateAndStateFriction< std::integral_constant< bool, false > > &, const arrayView2d< real64 > & ); +FrictionDriver::runTest( constitutive::RateAndStateFriction< std::integral_constant< bool, false > > &, SolidMechanicsAugmentedLagrangianContact&,const arrayView2d< real64 > & ); } diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp index 5c0e5875dfa..c821f60191c 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp @@ -2,7 +2,7 @@ * ------------------------------------------------------------------------------------------------------------ * SPDX-License-Identifier: LGPL-2.1-only * - * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC* * Copyright (c) 2018-2024 TotalEnergies * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University * Copyright (c) 2023-2024 Chevron @@ -20,15 +20,25 @@ #include "physicsSolvers/solidMechanics/contact/FractureState.hpp" #include "constitutive/solid/SolidFields.hpp" +#include "mesh/DomainPartition.hpp" +#include + namespace geos { -template< typename FRICTION_TYPE > +template< typename FRICTION_TYPE, typename CONTACT_SOLVER > void FrictionDriver::runTest( FRICTION_TYPE & friction, + CONTACT_SOLVER & contact, const arrayView2d< real64 > & table ) { - // Create kernel wrapper + // Create kernel wrapper and trigger solver configuration update. + conduit::Node dummyRoot; + DomainPartition dummyDomain( "FrictionDriverRunTestDomain", dummyRoot ); + // CONTACT_SOLVER const solver( "FrictionDriverRunTestSolver", &dummyDomain ); + // solver.updateConfiguration( dummyDomain, 0 ); + contact.updateConfiguration( dummyDomain, 0 ); + typename FRICTION_TYPE::KernelWrapper const kernelWrapper = friction.createKernelUpdates(); integer const numRows = m_table.size( 0 ); From 0f7ed3677e98b61b4953dd94d7e7765e55dcd201 Mon Sep 17 00:00:00 2001 From: jacques franc Date: Wed, 3 Jun 2026 15:33:31 +0200 Subject: [PATCH 08/25] wip --- .../friction/frictionDriver_Coulomb.xml | 1 + .../friction/frictionDriver_base.xml | 8 +- .../friction/tables/djumps.geos | 6 + .../contact/FrictionDriver.cpp | 7 + .../contact/FrictionDriver.hpp | 6 +- .../contact/FrictionDriverRunTest.hpp | 76 +++++++--- ...lidMechanicsAugmentedLagrangianContact.cpp | 141 +++++++++++------- ...lidMechanicsAugmentedLagrangianContact.hpp | 18 ++- 8 files changed, 192 insertions(+), 71 deletions(-) create mode 100644 inputFiles/constitutiveDriver/friction/tables/djumps.geos diff --git a/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml index 6fd8f7907a2..bc136e77660 100644 --- a/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml +++ b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml @@ -7,6 +7,7 @@ name="frictionDriver" friction="fractureContact0" jumpControl="jFunction" + dJumpControl="djFunction" xTiltAngle="80" tractionControl="tFunction" steps="10" diff --git a/inputFiles/constitutiveDriver/friction/frictionDriver_base.xml b/inputFiles/constitutiveDriver/friction/frictionDriver_base.xml index bf4b23983db..eddcd8efbe8 100644 --- a/inputFiles/constitutiveDriver/friction/frictionDriver_base.xml +++ b/inputFiles/constitutiveDriver/friction/frictionDriver_base.xml @@ -29,7 +29,7 @@ frictionCoefficient="0.01"/> @@ -42,6 +42,12 @@ coordinateFiles="{ tables/time.geos }" voxelFile="tables/jumps.geos"/> + + (&getFriction()) != nullptr ) { diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp index ab54add3a65..9e80f5064a7 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -74,6 +74,9 @@ class FrictionDriver : public ConstitutiveDriver constexpr static char const * jumpFunctionString() { return "jumpControl"; } + constexpr static char const * dJumpFunctionString() + { return "dJumpControl"; } + constexpr static char const * tractionFunctionString() { return "tractionControl"; } @@ -85,9 +88,10 @@ class FrictionDriver : public ConstitutiveDriver }; // Time is defined in base class - enum columnKeys { NJUMP = 1, SLIP0, SLIP1, NTRAC, STRAC0, STRAC1, FS, TLIM }; + enum columnKeys { NJUMP = 1, SLIP0, SLIP1, NDJUMP, DSLIP0, DSLIP1, NTRAC, STRAC0, STRAC1, FS, NEWTRAC, SNEWTRAC0, SNEWTRAC1, TLIM }; string m_jumpFunctionName; ///< + string m_dJumpFunctionName; ///< string m_tractionFunctionName; ///< real64 m_theta{0.0}; ///< x-tilt of fault diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp index c821f60191c..ac1284bc82e 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp @@ -33,36 +33,76 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, const arrayView2d< real64 > & table ) { // Create kernel wrapper and trigger solver configuration update. - conduit::Node dummyRoot; - DomainPartition dummyDomain( "FrictionDriverRunTestDomain", dummyRoot ); + // conduit::Node dummyRoot; + // DomainPartition dummyDomain( "FrictionDriverRunTestDomain", dummyRoot ); // CONTACT_SOLVER const solver( "FrictionDriverRunTestSolver", &dummyDomain ); // solver.updateConfiguration( dummyDomain, 0 ); - contact.updateConfiguration( dummyDomain, 0 ); - typename FRICTION_TYPE::KernelWrapper const kernelWrapper = friction.createKernelUpdates(); + array1d< integer > const ghostRank(1); ghostRank[0] = -1; + array1d< real64 > const normalDisplacementTol(1);normalDisplacementTol[0]=10; + array1d< real64 > const normalTractionTol(1); normalTractionTol[0]=1.; + array1d< real64 > const slidingTol(1); slidingTol[0]=.1;//normalDispTol should scale as 1/E + + real64 kt = 1.; + array2d< real64 > const iterPen(1,5); + iterPen[0][0] = 100*kt; + iterPen[0][1] = kt; + iterPen[0][2] = kt; iterPen[0][3] = kt; iterPen[0][4] = 0.; + array1d< integer > fractureState(1); + + fractureState[0] = fields::contact::FractureState::Stick; + array2d< real64 > traction(1,3); + array2d< real64 > jump(1,3); + array2d< real64 > djump(1,3); + + //TODO computeTolerance eleme to Elem + // typename FRICTION_TYPE::KernelWrapper const kernelWrapper = friction.createKernelUpdates(); integer const numRows = m_table.size( 0 ); forAll< parallelDevicePolicy<> >( numRows, - [ kernelWrapper, table ] + [&friction, &table, &contact, + &ghostRank,&normalDisplacementTol, &normalTractionTol, & slidingTol, &iterPen, + &jump, &djump, + &fractureState, &traction ] GEOS_HOST_DEVICE ( integer const ei ) { - stackArray1d< real64, 3 > jump( 3 ); - stackArray1d< real64, 3 > traction( 3 ); + // stackArray1d< real64, 3 > jump( 3 ); + // stackArray1d< real64, 3 > djump( 3 ); + + jump[0][0] = table( ei, NJUMP ); + jump[0][1] = table( ei, SLIP0 ); + jump[0][2] = table( ei, SLIP1 ); + + djump[0][0] = table( ei, NDJUMP ); + djump[0][1] = table( ei, DSLIP0 ); + djump[0][2] = table( ei, DSLIP1 ); - jump[0] = table( ei, NJUMP ); - jump[1] = table( ei, SLIP0 ); - jump[2] = table( ei, SLIP1 ); + traction[0][0] = table( ei, NTRAC ); + traction[0][1] = table( ei, STRAC0 ); + traction[0][2] = table( ei, STRAC1 ); - traction[0] = table( ei, NTRAC ); - traction[1] = table( ei, STRAC0 ); - traction[2] = table( ei, STRAC1 ); + + contact.updateTractionAndConstraintCheck(1, + friction, + normalDisplacementTol, + normalTractionTol, + slidingTol, + iterPen, + jump, + djump, + ghostRank, + fractureState.toView(), + traction.toView() + ); + // kernelWrapper.updateFractureState( jump.toSliceConst(), + // traction.toSliceConst(), + // fracture_state ); - integer fracture_state = fields::contact::FractureState::Stick; - kernelWrapper.updateFractureState( jump.toSliceConst(), - traction.toSliceConst(), - fracture_state ); + table( ei, FS ) = fractureState[0]; + table( ei, NEWTRAC ) = traction[0][0]; + table( ei, SNEWTRAC0 ) = traction[0][1]; + table( ei, SNEWTRAC1 ) = traction[0][2]; - table( ei, FS ) = fracture_state; } ); } diff --git a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp index 8dd1d59330e..e5c33b3d9b7 100644 --- a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp +++ b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp @@ -40,7 +40,9 @@ #include "finiteElement/FiniteElementDiscretization.hpp" #include "mesh/DomainPartition.hpp" +#include #include +#include #if defined( GEOS_USE_CUDA ) #include @@ -1067,52 +1069,26 @@ void SolidMechanicsAugmentedLagrangianContact::updateState( DomainPartition & do GEOS_UNUSED_VAR( domain ); } -bool SolidMechanicsAugmentedLagrangianContact::updateConfiguration( DomainPartition & domain, - integer const GEOS_UNUSED_PARAM( configurationLoopIter ) ) -{ - GEOS_MARK_FUNCTION; - - array1d< int > condConv; - localIndex globalCondConv[5] = {0, 0, 0, 0, 0}; - - array2d< real64 > traction_new; - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - ElementRegionManager & elemManager = mesh.getElemManager(); - - elemManager.forElementSubRegions< FaceElementSubRegion >( regionNames, [&]( localIndex const, - FaceElementSubRegion & subRegion ) - { - - string const & frictionLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); - FrictionBase const & frictionLaw = getConstitutiveModel< FrictionBase >( subRegion, frictionLawName ); - - arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); - arrayView2d< real64 > const traction = subRegion.getField< contact::traction >(); - arrayView2d< real64 const > const dispJump = subRegion.getField< contact::dispJump >(); - - arrayView2d< real64 const > const deltaDispJump = subRegion.getField< contact::deltaDispJump >(); - arrayView2d< real64 const > const iterativePenalty = subRegion.getField< contact::iterativePenalty >(); - arrayView1d< integer const > const fractureState = subRegion.getField< contact::fractureState >(); - arrayView1d< real64 const > const normalDisplacementTolerance = - subRegion.getReference< array1d< real64 > >( viewKeyStruct::normalDisplacementToleranceString() ); - arrayView1d< real64 > const & slidingTolerance = - subRegion.getReference< array1d< real64 > >( viewKeyStruct::slidingToleranceString() ); - arrayView1d< real64 const > const & normalTractionTolerance = - subRegion.getReference< array1d< real64 > >( viewKeyStruct::normalTractionToleranceString() ); - - std::ptrdiff_t const sizes[ 2 ] = {subRegion.size(), 3}; - traction_new.resize( 2, sizes ); - arrayView2d< real64 > const traction_new_v = traction_new.toView(); - - condConv.resize( subRegion.size()); - arrayView1d< int > const condConv_v = condConv.toView(); +std::tuple< array2d, array1d> SolidMechanicsAugmentedLagrangianContact::updateTractionAndConstraintCheck( +std::ptrdiff_t const rsize, +FrictionBase const& frictionLaw, +arrayView1d< real64 const > const& normalDisplacementTolerance, +arrayView1d< real64 const > const& normalTractionTolerance, +arrayView1d< real64 const > const& slidingTolerance, +arrayView2d const & iterativePenalty, +arrayView2d const & dispJump, +arrayView2d const & deltaDispJump, +arrayView1d< integer const> const& ghostRank, +arrayView1d< integer const> const& fractureState, +arrayView2d const & traction ) +{ + array2d< real64 > traction_new; + std::ptrdiff_t const sizes[2] = {rsize, 3}; + traction_new.resize(2, sizes); + array1d< int > condConv; - // Update the traction field based on the displacement results from the nonlinear solve + // Update the traction field based on the displacement results from the nonlinear solve constitutiveUpdatePassThru( frictionLaw, [&] ( auto & castedFrictionLaw ) { using FrictionType = TYPEOFREF( castedFrictionLaw ); @@ -1121,23 +1097,23 @@ bool SolidMechanicsAugmentedLagrangianContact::updateConfiguration( DomainPartit if( m_simultaneous ) { solidMechanicsALMKernels::ComputeTractionSimultaneousKernel:: - launch< parallelDevicePolicy<> >( subRegion.size(), + launch< parallelDevicePolicy<> >( rsize, iterativePenalty, traction, dispJump, deltaDispJump, - traction_new_v ); + traction_new.toView() ); } else { solidMechanicsALMKernels::ComputeTractionKernel:: - launch< parallelDevicePolicy<> >( subRegion.size(), + launch< parallelDevicePolicy<> >( rsize, frictionWrapper, iterativePenalty, traction, dispJump, deltaDispJump, - traction_new_v ); + traction_new.toView() ); } } ); @@ -1149,7 +1125,7 @@ bool SolidMechanicsAugmentedLagrangianContact::updateConfiguration( DomainPartit typename FrictionType::KernelWrapper frictionWrapper = castedFrictionLaw.createKernelUpdates(); solidMechanicsALMKernels::ConstraintCheckKernel:: - launch< parallelDevicePolicy<> >( subRegion.size(), + launch< parallelDevicePolicy<> >( rsize, frictionWrapper, ghostRank, traction, @@ -1160,9 +1136,74 @@ bool SolidMechanicsAugmentedLagrangianContact::updateConfiguration( DomainPartit slidingTolerance, slidingCheckTolerance, fractureState, - condConv_v ); + condConv.toView() ); } ); + + return std::make_tuple(traction_new,condConv); +} + + +bool SolidMechanicsAugmentedLagrangianContact::updateConfiguration( DomainPartition & domain, + integer const GEOS_UNUSED_PARAM( configurationLoopIter ) ) +{ + GEOS_MARK_FUNCTION; + + array1d< int > condConv; + localIndex globalCondConv[5] = {0, 0, 0, 0, 0}; + + array2d< real64 > traction_new; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + ElementRegionManager & elemManager = mesh.getElemManager(); + + elemManager.forElementSubRegions< FaceElementSubRegion >( regionNames, [&]( localIndex const, + FaceElementSubRegion & subRegion ) + { + + string const & frictionLawName = subRegion.template getReference< string >( viewKeyStruct::frictionLawNameString() ); + FrictionBase const & frictionLaw = getConstitutiveModel< FrictionBase >( subRegion, frictionLawName ); + + arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); + arrayView2d< real64 > const traction = subRegion.getField< contact::traction >(); + arrayView2d< real64 const > const dispJump = subRegion.getField< contact::dispJump >(); + + arrayView2d< real64 const > const deltaDispJump = subRegion.getField< contact::deltaDispJump >(); + arrayView2d< real64 const > const iterativePenalty = subRegion.getField< contact::iterativePenalty >(); + arrayView1d< integer const > const fractureState = subRegion.getField< contact::fractureState >(); + + arrayView1d< real64 const > const normalDisplacementTolerance = + subRegion.getReference< array1d< real64 > >( viewKeyStruct::normalDisplacementToleranceString() ); + arrayView1d< real64 > const & slidingTolerance = + subRegion.getReference< array1d< real64 > >( viewKeyStruct::slidingToleranceString() ); + arrayView1d< real64 const > const & normalTractionTolerance = + subRegion.getReference< array1d< real64 > >( viewKeyStruct::normalTractionToleranceString() ); + + std::ptrdiff_t const sizes[ 2 ] = {subRegion.size(), 3}; + traction_new.resize( 2, sizes ); + // arrayView2d< real64 > const traction_new_v = traction_new.toView(); + + // condConv.resize( subRegion.size()); + + std::tie(traction_new, condConv) = updateTractionAndConstraintCheck( + subRegion.size(), + frictionLaw, + normalDisplacementTolerance, + normalTractionTolerance, + slidingTolerance, + iterativePenalty, + dispJump, + deltaDispJump, + ghostRank, + fractureState, + traction + ); + arrayView1d< int > const condConv_v = condConv.toView(); + + RAJA::ReduceSum< parallelDeviceReduce, localIndex > localSum[5] = { RAJA::ReduceSum< parallelDeviceReduce, localIndex >( 0 ), RAJA::ReduceSum< parallelDeviceReduce, localIndex >( 0 ), diff --git a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp index 02af0550280..7488f8b186f 100644 --- a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp +++ b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp @@ -22,6 +22,7 @@ #define GEOS_PHYSICSSOLVERS_CONTACT_SOLIDMECHANICSAUGMENTEDLAGRANGIANCONTACT_HPP_ #include "physicsSolvers/solidMechanics/contact/ContactSolverBase.hpp" +#include "constitutive/contact/FrictionSelector.hpp" namespace geos { @@ -113,7 +114,7 @@ class SolidMechanicsAugmentedLagrangianContact : public ContactSolverBase virtual bool updateConfiguration( DomainPartition & domain, integer configurationLoopIter ) override final; - + /** * @brief Loop over the finite element type on the fracture subregions of meshName and apply callback. * @tparam LAMBDA The callback function type @@ -215,8 +216,23 @@ class SolidMechanicsAugmentedLagrangianContact : public ContactSolverBase */ void createBubbleCellList( DomainPartition & domain ) const; + + std::tuple< array2d, array1d> updateTractionAndConstraintCheck(std::ptrdiff_t const rsize, + constitutive::FrictionBase const& frictionLaw, + arrayView1d< real64 const > const& normalDisplacementTolerance, + arrayView1d< real64 const > const& normalTractionTolerance, + arrayView1d< real64 const > const& slidingTolerance, + arrayView2d const & iterativePenalty, + arrayView2d const & dispJump, + arrayView2d const & deltaDispJump, + arrayView1d< integer const> const& ghostRank, + arrayView1d< integer const> const& fractureState, + arrayView2d const & traction ); + private: + + /** * @brief Validate that tetrahedral meshes use high-order quadrature rules * @param meshBodies the group containing the mesh bodies From 2521e23877fe268fbc6c8b27338079758a76dc80 Mon Sep 17 00:00:00 2001 From: jacques franc Date: Wed, 3 Jun 2026 18:07:24 +0200 Subject: [PATCH 09/25] to static function --- .../friction/frictionDriver_Coulomb.xml | 28 ++++++++++ .../friction/frictionDriver_base.xml | 2 +- .../contact/FrictionDriver.cpp | 54 ++++++++++++------- .../contact/FrictionDriver.hpp | 12 ++--- .../contact/FrictionDriverRunTest.cpp | 8 +-- .../contact/FrictionDriverRunTest.hpp | 22 ++++---- ...lidMechanicsAugmentedLagrangianContact.cpp | 9 +++- ...lidMechanicsAugmentedLagrangianContact.hpp | 3 ++ 8 files changed, 93 insertions(+), 45 deletions(-) diff --git a/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml index bc136e77660..6f10c793dcc 100644 --- a/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml +++ b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml @@ -1,6 +1,34 @@ + + + + + diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp index b1ff1d93280..024ca216d05 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -23,6 +23,8 @@ #include "functions/FunctionManager.hpp" #include "functions/TableFunction.hpp" +//TODO take friction from contact solver + namespace geos { @@ -37,10 +39,10 @@ FrictionDriver::FrictionDriver( const string & name, Group * const parent ) setInputFlag( InputFlags::REQUIRED ). setDescription( "Friction model to test" ); - registerWrapper( viewKeyStruct::frictionNameString(), &m_contactName ). - setRTTypeName( rtTypes::CustomTypes::groupNameRef ). - setInputFlag( InputFlags::REQUIRED ). - setDescription( "Contact model to test" ); + // registerWrapper( viewKeyStruct::frictionNameString(), &m_contactName ). + // setRTTypeName( rtTypes::CustomTypes::groupNameRef ). + // setInputFlag( InputFlags::REQUIRED ). + // setDescription( "Contact model to test" ); registerWrapper( viewKeyStruct::numStepsString(), &m_numSteps ). setInputFlag( InputFlags::REQUIRED ). @@ -79,6 +81,10 @@ void FrictionDriver::postInputInitialization() GEOS_FMT( "Jump function with name '{}' not found", m_jumpFunctionName ), getWrapperDataContext( viewKeyStruct::jumpFunctionString() ) ); + GEOS_ERROR_IF( !functionManager.hasGroup< TableFunction >( m_dJumpFunctionName ), + GEOS_FMT( "dJump function with name '{}' not found", m_dJumpFunctionName ), + getWrapperDataContext( viewKeyStruct::dJumpFunctionString() ) ); + GEOS_ERROR_IF( !functionManager.hasGroup< TableFunction >( m_tractionFunctionName ), GEOS_FMT( "Traction function with name '{}' not found", m_tractionFunctionName ), getWrapperDataContext( viewKeyStruct::tractionFunctionString() ) ); @@ -89,9 +95,11 @@ void FrictionDriver::postInputInitialization() // initialize functions TableFunction & jumpFunction = functionManager.getGroup< TableFunction >( m_jumpFunctionName ); + TableFunction & dJumpFunction = functionManager.getGroup< TableFunction >( m_dJumpFunctionName ); TableFunction & tractionFunction = functionManager.getGroup< TableFunction >( m_tractionFunctionName ); jumpFunction.initializeFunction(); + dJumpFunction.initializeFunction(); tractionFunction.initializeFunction(); // TODO: Maybe we should take the maximum extent of jumpFunction and tractionFunction @@ -109,15 +117,13 @@ void FrictionDriver::postInputInitialization() bool FrictionDriver::execute() { FrictionBase & baseFriction = getFriction(); - ContactSolverBase & baseContact = getContact(); + // ContactSolverBase & baseContact = getContact(); //temp - auto& castedContactModel = dynamic_cast< SolidMechanicsAugmentedLagrangianContact& >( baseContact ); - assert( castedContactModel ); + // auto& castedContactModel = dynamic_cast< SolidMechanicsAugmentedLagrangianContact& >( baseContact ); GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, "Launching Friction Driver" ); GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Friction ............... " << m_frictionName ); - GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Contact ............... " << m_contactName ); GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Type ................... " << baseFriction.getCatalogName() ); GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Steps .................. " << m_numSteps ); GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Output ................. " << m_outputFile ); @@ -136,8 +142,8 @@ bool FrictionDriver::execute() constitutiveUpdatePassThru( baseFriction, [&]( auto & selectedFrictionModel ) { using FRICTION_TYPE = TYPEOFREF( selectedFrictionModel ); - using CONTACT_TYPE = TYPEOFREF( castedContactModel ); - runTest< FRICTION_TYPE, CONTACT_TYPE >( selectedFrictionModel, castedContactModel, m_table ); + // using CONTACT_TYPE = TYPEOFREF( castedContactModel ); + runTest< FRICTION_TYPE >( selectedFrictionModel, m_table ); } ); return false; @@ -152,6 +158,9 @@ void FrictionDriver::getColumnNames( string_array & columnNames ) const columnNames.emplace_back( "displacement jump,normal" ); columnNames.emplace_back( "displacement jump,tangent1" ); columnNames.emplace_back( "displacement jump,tangent2" ); + columnNames.emplace_back( "delta displacement jump,normal" ); + columnNames.emplace_back( "delta displacement jump,tangent1" ); + columnNames.emplace_back( "delta displacement jump,tangent2" ); columnNames.emplace_back( "fracture state" ); columnNames.emplace_back( "newtraction,normal" ); columnNames.emplace_back( "newtraction,tangent1" ); @@ -169,6 +178,7 @@ void FrictionDriver::initializeTable() FunctionManager & functionManager = FunctionManager::getInstance(); TableFunction const & jumpFunction = functionManager.getGroup< TableFunction >( m_jumpFunctionName ); + TableFunction const & dJumpFunction = functionManager.getGroup< TableFunction >( m_dJumpFunctionName ); TableFunction const & tractionFunction = functionManager.getGroup< TableFunction >( m_tractionFunctionName ); real64 const cos_theta = cos( m_theta * M_PI/180.0 ); @@ -182,15 +192,19 @@ void FrictionDriver::initializeTable() real64 const time = m_table( index, TIME ); real64 const traction = tractionFunction.evaluate( &time ); - real64 const jump = jumpFunction.evaluate( &time ); - m_table( index, NTRAC ) = traction*sin_theta; m_table( index, STRAC0 ) = traction*cos_theta*cos_phi; m_table( index, STRAC1 ) = traction*cos_theta*sin_phi; + real64 const jump = jumpFunction.evaluate( &time ); m_table( index, NJUMP ) = jump*sin_theta; m_table( index, SLIP0 ) = jump*cos_theta*cos_phi; m_table( index, SLIP1 ) = jump*cos_theta*sin_phi; + + real64 const dJump = dJumpFunction.evaluate( &time ); + m_table( index, NDJUMP ) = dJump*sin_theta; + m_table( index, DSLIP0 ) = dJump*cos_theta*cos_phi; + m_table( index, DSLIP1 ) = dJump*cos_theta*sin_phi; m_table( index, FS ) = fields::contact::FractureState::Stick; } @@ -217,15 +231,15 @@ FrictionBase const & FrictionDriver::getFriction() const return getConstitutiveManager().getGroup< FrictionBase >( m_frictionName ); } -ContactSolverBase & FrictionDriver::getContact() -{ - return getConstitutiveManager().getGroup< ContactSolverBase >( m_contactName ); -} +// ContactSolverBase & FrictionDriver::getContact() +// { +// return getConstitutiveManager().getGroup< ContactSolverBase >( m_contactName ); +// } -ContactSolverBase const & FrictionDriver::getContact() const -{ - return getConstitutiveManager().getGroup< ContactSolverBase >( m_contactName ); -} +// ContactSolverBase const & FrictionDriver::getContact() const +// { +// return getConstitutiveManager().getGroup< ContactSolverBase >( m_contactName ); +// } REGISTER_CATALOG_ENTRY( TaskBase, FrictionDriver, diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp index 9e80f5064a7..daa3f32e4d3 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -18,7 +18,7 @@ #include "constitutiveDrivers/ConstitutiveDriver.hpp" #include "physicsSolvers/solidMechanics/contact/ContactSolverBase.hpp" -#include "physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp" +// #include "physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp" namespace geos { @@ -42,10 +42,10 @@ class FrictionDriver : public ConstitutiveDriver void getColumnNames( string_array & columnNames ) const override; - template< typename FRICTION_TYPE, typename CONTACT_SOLVER > + template< typename FRICTION_TYPE > void runTest( FRICTION_TYPE & friction, - CONTACT_SOLVER& contact, + // CONTACT_SOLVER& contact, const arrayView2d< real64, 1 > & table ); private: @@ -55,8 +55,8 @@ class FrictionDriver : public ConstitutiveDriver constitutive::FrictionBase & getFriction(); constitutive::FrictionBase const & getFriction() const; - ContactSolverBase & getContact(); - ContactSolverBase const & getContact() const; + // ContactSolverBase & getContact(); + // ContactSolverBase const & getContact() const; void initializeTable(); @@ -98,7 +98,7 @@ class FrictionDriver : public ConstitutiveDriver real64 m_phi{0.0}; ///< y-tilt of fault string m_frictionName; ///< frictionType identifier - string m_contactName; ///< ContactSolver identifier + // string m_contactName; ///< ContactSolver identifier }; } diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.cpp index 88cb5d3af5d..200a8e39464 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.cpp @@ -10,18 +10,18 @@ namespace geos template void -FrictionDriver::runTest( constitutive::CoulombFriction &, SolidMechanicsAugmentedLagrangianContact&, const arrayView2d< real64 > & ); +FrictionDriver::runTest( constitutive::CoulombFriction &, const arrayView2d< real64 > & ); template void -FrictionDriver::runTest( constitutive::FrictionlessContact &, SolidMechanicsAugmentedLagrangianContact&,const arrayView2d< real64 > & ); +FrictionDriver::runTest( constitutive::FrictionlessContact &,const arrayView2d< real64 > & ); template void -FrictionDriver::runTest( constitutive::RateAndStateFriction< std::integral_constant< bool, true > > &, SolidMechanicsAugmentedLagrangianContact&,const arrayView2d< real64 > & ); +FrictionDriver::runTest( constitutive::RateAndStateFriction< std::integral_constant< bool, true > > &,const arrayView2d< real64 > & ); template void -FrictionDriver::runTest( constitutive::RateAndStateFriction< std::integral_constant< bool, false > > &, SolidMechanicsAugmentedLagrangianContact&,const arrayView2d< real64 > & ); +FrictionDriver::runTest( constitutive::RateAndStateFriction< std::integral_constant< bool, false > > &,const arrayView2d< real64 > & ); } diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp index ac1284bc82e..198addf6940 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp @@ -18,25 +18,20 @@ #include "constitutiveDrivers/contact/FrictionDriver.hpp" #include "physicsSolvers/solidMechanics/contact/FractureState.hpp" +#include "physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp" #include "constitutive/solid/SolidFields.hpp" -#include "mesh/DomainPartition.hpp" #include namespace geos { -template< typename FRICTION_TYPE, typename CONTACT_SOLVER > +template< typename FRICTION_TYPE> void FrictionDriver::runTest( FRICTION_TYPE & friction, - CONTACT_SOLVER & contact, + // CONTACT_SOLVER & contact, const arrayView2d< real64 > & table ) { - // Create kernel wrapper and trigger solver configuration update. - // conduit::Node dummyRoot; - // DomainPartition dummyDomain( "FrictionDriverRunTestDomain", dummyRoot ); - // CONTACT_SOLVER const solver( "FrictionDriverRunTestSolver", &dummyDomain ); - // solver.updateConfiguration( dummyDomain, 0 ); array1d< integer > const ghostRank(1); ghostRank[0] = -1; array1d< real64 > const normalDisplacementTol(1);normalDisplacementTol[0]=10; @@ -60,14 +55,15 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, integer const numRows = m_table.size( 0 ); forAll< parallelDevicePolicy<> >( numRows, - [&friction, &table, &contact, + [&friction, &table, &ghostRank,&normalDisplacementTol, &normalTractionTol, & slidingTol, &iterPen, &jump, &djump, &fractureState, &traction ] GEOS_HOST_DEVICE ( integer const ei ) { - // stackArray1d< real64, 3 > jump( 3 ); - // stackArray1d< real64, 3 > djump( 3 ); + + GEOS_LOG_RANK("[debug] Table Evaluation"); + GEOS_LOG_RANK(GEOS_FMT(" jump [{}x{}]", jump.size(0),jump.size(1))); jump[0][0] = table( ei, NJUMP ); jump[0][1] = table( ei, SLIP0 ); @@ -82,8 +78,10 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, traction[0][2] = table( ei, STRAC1 ); - contact.updateTractionAndConstraintCheck(1, + SolidMechanicsAugmentedLagrangianContact::updateTractionAndConstraintCheck(1, friction, + true,//simultaneous + 0.05,//slidingCheckTolerance normalDisplacementTol, normalTractionTol, slidingTol, diff --git a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp index e5c33b3d9b7..c28739a1068 100644 --- a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp +++ b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp @@ -1073,6 +1073,8 @@ void SolidMechanicsAugmentedLagrangianContact::updateState( DomainPartition & do std::tuple< array2d, array1d> SolidMechanicsAugmentedLagrangianContact::updateTractionAndConstraintCheck( std::ptrdiff_t const rsize, FrictionBase const& frictionLaw, +bool isSimultaneous, +real64 const slidingCheckTolerance, arrayView1d< real64 const > const& normalDisplacementTolerance, arrayView1d< real64 const > const& normalTractionTolerance, arrayView1d< real64 const > const& slidingTolerance, @@ -1087,6 +1089,7 @@ arrayView2d const & traction ) std::ptrdiff_t const sizes[2] = {rsize, 3}; traction_new.resize(2, sizes); array1d< int > condConv; + condConv.resize(rsize); // Update the traction field based on the displacement results from the nonlinear solve constitutiveUpdatePassThru( frictionLaw, [&] ( auto & castedFrictionLaw ) @@ -1094,7 +1097,7 @@ arrayView2d const & traction ) using FrictionType = TYPEOFREF( castedFrictionLaw ); typename FrictionType::KernelWrapper frictionWrapper = castedFrictionLaw.createKernelUpdates(); - if( m_simultaneous ) + if( isSimultaneous ) { solidMechanicsALMKernels::ComputeTractionSimultaneousKernel:: launch< parallelDevicePolicy<> >( rsize, @@ -1117,7 +1120,7 @@ arrayView2d const & traction ) } } ); - real64 const slidingCheckTolerance = m_slidingCheckTolerance; + // real64 const slidingCheckTolerance = m_slidingCheckTolerance; constitutiveUpdatePassThru( frictionLaw, [&] ( auto & castedFrictionLaw ) { @@ -1191,6 +1194,8 @@ bool SolidMechanicsAugmentedLagrangianContact::updateConfiguration( DomainPartit std::tie(traction_new, condConv) = updateTractionAndConstraintCheck( subRegion.size(), frictionLaw, + m_simultaneous, + m_slidingCheckTolerance, normalDisplacementTolerance, normalTractionTolerance, slidingTolerance, diff --git a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp index 7488f8b186f..12ec43ca333 100644 --- a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp +++ b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp @@ -217,8 +217,11 @@ class SolidMechanicsAugmentedLagrangianContact : public ContactSolverBase void createBubbleCellList( DomainPartition & domain ) const; + static std::tuple< array2d, array1d> updateTractionAndConstraintCheck(std::ptrdiff_t const rsize, constitutive::FrictionBase const& frictionLaw, + bool isSimultaneous, + real64 const slidingCheckTolerance, arrayView1d< real64 const > const& normalDisplacementTolerance, arrayView1d< real64 const > const& normalTractionTolerance, arrayView1d< real64 const > const& slidingTolerance, From d56ab6f4a054bc7293a40d6c888a28f1ae870b85 Mon Sep 17 00:00:00 2001 From: jacques franc Date: Thu, 4 Jun 2026 10:09:15 +0200 Subject: [PATCH 10/25] clean up --- .../friction/frictionDriver_Coulomb.xml | 28 ---- .../contact/FrictionDriver.cpp | 26 +--- .../contact/FrictionDriver.hpp | 7 +- .../contact/FrictionDriverRunTest.cpp | 6 +- .../contact/FrictionDriverRunTest.hpp | 64 ++++---- ...lidMechanicsAugmentedLagrangianContact.cpp | 140 +++++++++--------- ...lidMechanicsAugmentedLagrangianContact.hpp | 30 ++-- 7 files changed, 120 insertions(+), 181 deletions(-) diff --git a/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml index 6f10c793dcc..bc136e77660 100644 --- a/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml +++ b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml @@ -1,34 +1,6 @@ - - - - - ( baseContact ); GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, "Launching Friction Driver" ); GEOS_LOG_LEVEL_RANK_0( logInfo::LogOutput, " Friction ............... " << m_frictionName ); @@ -130,7 +119,6 @@ bool FrictionDriver::execute() // create a dummy discretization with one quadrature point for // storing constitutive data - conduit::Node node; dataRepository::Group rootGroup( "root", node ); dataRepository::Group discretization( "discretization", &rootGroup ); @@ -142,7 +130,6 @@ bool FrictionDriver::execute() constitutiveUpdatePassThru( baseFriction, [&]( auto & selectedFrictionModel ) { using FRICTION_TYPE = TYPEOFREF( selectedFrictionModel ); - // using CONTACT_TYPE = TYPEOFREF( castedContactModel ); runTest< FRICTION_TYPE >( selectedFrictionModel, m_table ); } ); @@ -200,7 +187,7 @@ void FrictionDriver::initializeTable() m_table( index, NJUMP ) = jump*sin_theta; m_table( index, SLIP0 ) = jump*cos_theta*cos_phi; m_table( index, SLIP1 ) = jump*cos_theta*sin_phi; - + real64 const dJump = dJumpFunction.evaluate( &time ); m_table( index, NDJUMP ) = dJump*sin_theta; m_table( index, DSLIP0 ) = dJump*cos_theta*cos_phi; @@ -231,15 +218,6 @@ FrictionBase const & FrictionDriver::getFriction() const return getConstitutiveManager().getGroup< FrictionBase >( m_frictionName ); } -// ContactSolverBase & FrictionDriver::getContact() -// { -// return getConstitutiveManager().getGroup< ContactSolverBase >( m_contactName ); -// } - -// ContactSolverBase const & FrictionDriver::getContact() const -// { -// return getConstitutiveManager().getGroup< ContactSolverBase >( m_contactName ); -// } REGISTER_CATALOG_ENTRY( TaskBase, FrictionDriver, diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp index daa3f32e4d3..1a2dc7ed438 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -45,7 +45,6 @@ class FrictionDriver : public ConstitutiveDriver template< typename FRICTION_TYPE > void runTest( FRICTION_TYPE & friction, - // CONTACT_SOLVER& contact, const arrayView2d< real64, 1 > & table ); private: @@ -55,9 +54,6 @@ class FrictionDriver : public ConstitutiveDriver constitutive::FrictionBase & getFriction(); constitutive::FrictionBase const & getFriction() const; - // ContactSolverBase & getContact(); - // ContactSolverBase const & getContact() const; - void initializeTable(); /** @@ -70,7 +66,7 @@ class FrictionDriver : public ConstitutiveDriver constexpr static char const * contactNameString() { return "contact"; } - + constexpr static char const * jumpFunctionString() { return "jumpControl"; } @@ -98,7 +94,6 @@ class FrictionDriver : public ConstitutiveDriver real64 m_phi{0.0}; ///< y-tilt of fault string m_frictionName; ///< frictionType identifier - // string m_contactName; ///< ContactSolver identifier }; } diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.cpp index 200a8e39464..f06fe66436d 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.cpp @@ -14,14 +14,14 @@ FrictionDriver::runTest( constitutive::CoulombFriction &, const arrayView2d< rea template void -FrictionDriver::runTest( constitutive::FrictionlessContact &,const arrayView2d< real64 > & ); +FrictionDriver::runTest( constitutive::FrictionlessContact &, const arrayView2d< real64 > & ); template void -FrictionDriver::runTest( constitutive::RateAndStateFriction< std::integral_constant< bool, true > > &,const arrayView2d< real64 > & ); +FrictionDriver::runTest( constitutive::RateAndStateFriction< std::integral_constant< bool, true > > &, const arrayView2d< real64 > & ); template void -FrictionDriver::runTest( constitutive::RateAndStateFriction< std::integral_constant< bool, false > > &,const arrayView2d< real64 > & ); +FrictionDriver::runTest( constitutive::RateAndStateFriction< std::integral_constant< bool, false > > &, const arrayView2d< real64 > & ); } diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp index 198addf6940..73a5dce2c70 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp @@ -26,44 +26,42 @@ namespace geos { -template< typename FRICTION_TYPE> +template< typename FRICTION_TYPE > void FrictionDriver::runTest( FRICTION_TYPE & friction, - // CONTACT_SOLVER & contact, const arrayView2d< real64 > & table ) { - array1d< integer > const ghostRank(1); ghostRank[0] = -1; - array1d< real64 > const normalDisplacementTol(1);normalDisplacementTol[0]=10; - array1d< real64 > const normalTractionTol(1); normalTractionTol[0]=1.; - array1d< real64 > const slidingTol(1); slidingTol[0]=.1;//normalDispTol should scale as 1/E + array1d< integer > const ghostRank( 1 ); ghostRank[0] = -1; + array1d< real64 > const normalDisplacementTol( 1 ); normalDisplacementTol[0]=10; + array1d< real64 > const normalTractionTol( 1 ); normalTractionTol[0]=1.; + array1d< real64 > const slidingTol( 1 ); slidingTol[0]=.1;//normalDispTol should scale as 1/E real64 kt = 1.; - array2d< real64 > const iterPen(1,5); + array2d< real64 > const iterPen( 1, 5 ); iterPen[0][0] = 100*kt; iterPen[0][1] = kt; iterPen[0][2] = kt; iterPen[0][3] = kt; iterPen[0][4] = 0.; - array1d< integer > fractureState(1); + array1d< integer > fractureState( 1 ); fractureState[0] = fields::contact::FractureState::Stick; - array2d< real64 > traction(1,3); - array2d< real64 > jump(1,3); - array2d< real64 > djump(1,3); + array2d< real64 > traction( 1, 3 ); + array2d< real64 > jump( 1, 3 ); + array2d< real64 > djump( 1, 3 ); //TODO computeTolerance eleme to Elem - // typename FRICTION_TYPE::KernelWrapper const kernelWrapper = friction.createKernelUpdates(); integer const numRows = m_table.size( 0 ); forAll< parallelDevicePolicy<> >( numRows, [&friction, &table, - &ghostRank,&normalDisplacementTol, &normalTractionTol, & slidingTol, &iterPen, - &jump, &djump, - &fractureState, &traction ] + &ghostRank, &normalDisplacementTol, &normalTractionTol, &slidingTol, &iterPen, + &jump, &djump, + &fractureState, &traction ] GEOS_HOST_DEVICE ( integer const ei ) { - GEOS_LOG_RANK("[debug] Table Evaluation"); - GEOS_LOG_RANK(GEOS_FMT(" jump [{}x{}]", jump.size(0),jump.size(1))); + GEOS_LOG_RANK( "[debug] Table Evaluation" ); + GEOS_LOG_RANK( GEOS_FMT( " jump [{}x{}]", jump.size( 0 ), jump.size( 1 ))); jump[0][0] = table( ei, NJUMP ); jump[0][1] = table( ei, SLIP0 ); @@ -77,25 +75,21 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, traction[0][1] = table( ei, STRAC0 ); traction[0][2] = table( ei, STRAC1 ); - - SolidMechanicsAugmentedLagrangianContact::updateTractionAndConstraintCheck(1, - friction, - true,//simultaneous - 0.05,//slidingCheckTolerance - normalDisplacementTol, - normalTractionTol, - slidingTol, - iterPen, - jump, - djump, - ghostRank, - fractureState.toView(), - traction.toView() - ); - // kernelWrapper.updateFractureState( jump.toSliceConst(), - // traction.toSliceConst(), - // fracture_state ); + SolidMechanicsAugmentedLagrangianContact::updateTractionAndConstraintCheck( 1, + friction, + true,//simultaneous + 0.05,//slidingCheckTolerance + normalDisplacementTol, + normalTractionTol, + slidingTol, + iterPen, + jump, + djump, + ghostRank, + fractureState.toView(), + traction.toView() + ); table( ei, FS ) = fractureState[0]; table( ei, NEWTRAC ) = traction[0][0]; table( ei, SNEWTRAC0 ) = traction[0][1]; diff --git a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp index c28739a1068..d3717daadc1 100644 --- a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp +++ b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp @@ -1070,80 +1070,80 @@ void SolidMechanicsAugmentedLagrangianContact::updateState( DomainPartition & do } -std::tuple< array2d, array1d> SolidMechanicsAugmentedLagrangianContact::updateTractionAndConstraintCheck( -std::ptrdiff_t const rsize, -FrictionBase const& frictionLaw, -bool isSimultaneous, -real64 const slidingCheckTolerance, -arrayView1d< real64 const > const& normalDisplacementTolerance, -arrayView1d< real64 const > const& normalTractionTolerance, -arrayView1d< real64 const > const& slidingTolerance, -arrayView2d const & iterativePenalty, -arrayView2d const & dispJump, -arrayView2d const & deltaDispJump, -arrayView1d< integer const> const& ghostRank, -arrayView1d< integer const> const& fractureState, -arrayView2d const & traction ) +std::tuple< array2d< real64 >, array1d< int > > SolidMechanicsAugmentedLagrangianContact::updateTractionAndConstraintCheck( + std::ptrdiff_t const rsize, + FrictionBase const & frictionLaw, + bool isSimultaneous, + real64 const slidingCheckTolerance, + arrayView1d< real64 const > const & normalDisplacementTolerance, + arrayView1d< real64 const > const & normalTractionTolerance, + arrayView1d< real64 const > const & slidingTolerance, + arrayView2d< real64 const > const & iterativePenalty, + arrayView2d< real64 const > const & dispJump, + arrayView2d< real64 const > const & deltaDispJump, + arrayView1d< integer const > const & ghostRank, + arrayView1d< integer const > const & fractureState, + arrayView2d< real64 > const & traction ) { - array2d< real64 > traction_new; - std::ptrdiff_t const sizes[2] = {rsize, 3}; - traction_new.resize(2, sizes); - array1d< int > condConv; - condConv.resize(rsize); - - // Update the traction field based on the displacement results from the nonlinear solve - constitutiveUpdatePassThru( frictionLaw, [&] ( auto & castedFrictionLaw ) - { - using FrictionType = TYPEOFREF( castedFrictionLaw ); - typename FrictionType::KernelWrapper frictionWrapper = castedFrictionLaw.createKernelUpdates(); + array2d< real64 > traction_new; + std::ptrdiff_t const sizes[2] = {rsize, 3}; + traction_new.resize( 2, sizes ); + array1d< int > condConv; + condConv.resize( rsize ); - if( isSimultaneous ) - { - solidMechanicsALMKernels::ComputeTractionSimultaneousKernel:: - launch< parallelDevicePolicy<> >( rsize, - iterativePenalty, - traction, - dispJump, - deltaDispJump, - traction_new.toView() ); - } - else - { - solidMechanicsALMKernels::ComputeTractionKernel:: - launch< parallelDevicePolicy<> >( rsize, - frictionWrapper, - iterativePenalty, - traction, - dispJump, - deltaDispJump, - traction_new.toView() ); - } - } ); + // Update the traction field based on the displacement results from the nonlinear solve + constitutiveUpdatePassThru( frictionLaw, [&] ( auto & castedFrictionLaw ) + { + using FrictionType = TYPEOFREF( castedFrictionLaw ); + typename FrictionType::KernelWrapper frictionWrapper = castedFrictionLaw.createKernelUpdates(); - // real64 const slidingCheckTolerance = m_slidingCheckTolerance; + if( isSimultaneous ) + { + solidMechanicsALMKernels::ComputeTractionSimultaneousKernel:: + launch< parallelDevicePolicy<> >( rsize, + iterativePenalty, + traction, + dispJump, + deltaDispJump, + traction_new.toView() ); + } + else + { + solidMechanicsALMKernels::ComputeTractionKernel:: + launch< parallelDevicePolicy<> >( rsize, + frictionWrapper, + iterativePenalty, + traction, + dispJump, + deltaDispJump, + traction_new.toView() ); + } + } ); - constitutiveUpdatePassThru( frictionLaw, [&] ( auto & castedFrictionLaw ) - { - using FrictionType = TYPEOFREF( castedFrictionLaw ); - typename FrictionType::KernelWrapper frictionWrapper = castedFrictionLaw.createKernelUpdates(); - - solidMechanicsALMKernels::ConstraintCheckKernel:: - launch< parallelDevicePolicy<> >( rsize, - frictionWrapper, - ghostRank, - traction, - dispJump, - deltaDispJump, - normalTractionTolerance, - normalDisplacementTolerance, - slidingTolerance, - slidingCheckTolerance, - fractureState, - condConv.toView() ); - } ); + // real64 const slidingCheckTolerance = m_slidingCheckTolerance; + + constitutiveUpdatePassThru( frictionLaw, [&] ( auto & castedFrictionLaw ) + { + using FrictionType = TYPEOFREF( castedFrictionLaw ); + typename FrictionType::KernelWrapper frictionWrapper = castedFrictionLaw.createKernelUpdates(); + + solidMechanicsALMKernels::ConstraintCheckKernel:: + launch< parallelDevicePolicy<> >( rsize, + frictionWrapper, + ghostRank, + traction, + dispJump, + deltaDispJump, + normalTractionTolerance, + normalDisplacementTolerance, + slidingTolerance, + slidingCheckTolerance, + fractureState, + condConv.toView() ); + } ); - return std::make_tuple(traction_new,condConv); + return std::make_tuple( traction_new, condConv ); } @@ -1191,7 +1191,7 @@ bool SolidMechanicsAugmentedLagrangianContact::updateConfiguration( DomainPartit // condConv.resize( subRegion.size()); - std::tie(traction_new, condConv) = updateTractionAndConstraintCheck( + std::tie( traction_new, condConv ) = updateTractionAndConstraintCheck( subRegion.size(), frictionLaw, m_simultaneous, @@ -1205,7 +1205,7 @@ bool SolidMechanicsAugmentedLagrangianContact::updateConfiguration( DomainPartit ghostRank, fractureState, traction - ); + ); arrayView1d< int > const condConv_v = condConv.toView(); diff --git a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp index 12ec43ca333..d4e411fdc39 100644 --- a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp +++ b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp @@ -114,7 +114,7 @@ class SolidMechanicsAugmentedLagrangianContact : public ContactSolverBase virtual bool updateConfiguration( DomainPartition & domain, integer configurationLoopIter ) override final; - + /** * @brief Loop over the finite element type on the fracture subregions of meshName and apply callback. * @tparam LAMBDA The callback function type @@ -218,20 +218,20 @@ class SolidMechanicsAugmentedLagrangianContact : public ContactSolverBase static - std::tuple< array2d, array1d> updateTractionAndConstraintCheck(std::ptrdiff_t const rsize, - constitutive::FrictionBase const& frictionLaw, - bool isSimultaneous, - real64 const slidingCheckTolerance, - arrayView1d< real64 const > const& normalDisplacementTolerance, - arrayView1d< real64 const > const& normalTractionTolerance, - arrayView1d< real64 const > const& slidingTolerance, - arrayView2d const & iterativePenalty, - arrayView2d const & dispJump, - arrayView2d const & deltaDispJump, - arrayView1d< integer const> const& ghostRank, - arrayView1d< integer const> const& fractureState, - arrayView2d const & traction ); - + std::tuple< array2d< real64 >, array1d< int > > updateTractionAndConstraintCheck( std::ptrdiff_t const rsize, + constitutive::FrictionBase const & frictionLaw, + bool isSimultaneous, + real64 const slidingCheckTolerance, + arrayView1d< real64 const > const & normalDisplacementTolerance, + arrayView1d< real64 const > const & normalTractionTolerance, + arrayView1d< real64 const > const & slidingTolerance, + arrayView2d< real64 const > const & iterativePenalty, + arrayView2d< real64 const > const & dispJump, + arrayView2d< real64 const > const & deltaDispJump, + arrayView1d< integer const > const & ghostRank, + arrayView1d< integer const > const & fractureState, + arrayView2d< real64 > const & traction ); + private: From 0dcf7a40456100aa2344e0d0b23ad3553d5f6a53 Mon Sep 17 00:00:00 2001 From: jacques franc Date: Thu, 4 Jun 2026 11:51:53 +0200 Subject: [PATCH 11/25] correct column ordering --- .../friction/tables/djumps.geos | 2 +- .../friction/tables/tractions.geos | 10 ++-- .../contact/FrictionDriver.hpp | 2 +- .../contact/FrictionDriverRunTest.hpp | 46 +++++++++++-------- 4 files changed, 35 insertions(+), 25 deletions(-) diff --git a/inputFiles/constitutiveDriver/friction/tables/djumps.geos b/inputFiles/constitutiveDriver/friction/tables/djumps.geos index 799f546332d..e1174543015 100644 --- a/inputFiles/constitutiveDriver/friction/tables/djumps.geos +++ b/inputFiles/constitutiveDriver/friction/tables/djumps.geos @@ -3,4 +3,4 @@ 2e-5 3e-5 4e-5 -5e-5 +5e-5 \ No newline at end of file diff --git a/inputFiles/constitutiveDriver/friction/tables/tractions.geos b/inputFiles/constitutiveDriver/friction/tables/tractions.geos index c80b1f6d1bd..1655949d91f 100644 --- a/inputFiles/constitutiveDriver/friction/tables/tractions.geos +++ b/inputFiles/constitutiveDriver/friction/tables/tractions.geos @@ -1,6 +1,6 @@ 0 -1e6 -2e6 -3e6 -4e6 -5e6 +-1e6 +-2e6 +-3e6 +-4e6 +-5e6 diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp index 1a2dc7ed438..b5e6a4a6983 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -84,7 +84,7 @@ class FrictionDriver : public ConstitutiveDriver }; // Time is defined in base class - enum columnKeys { NJUMP = 1, SLIP0, SLIP1, NDJUMP, DSLIP0, DSLIP1, NTRAC, STRAC0, STRAC1, FS, NEWTRAC, SNEWTRAC0, SNEWTRAC1, TLIM }; + enum columnKeys { NTRAC=1, STRAC0, STRAC1, NJUMP, SLIP0, SLIP1, NDJUMP, DSLIP0, DSLIP1, FS, NEWTRAC, SNEWTRAC0, SNEWTRAC1, TLIM }; string m_jumpFunctionName; ///< string m_dJumpFunctionName; ///< diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp index 73a5dce2c70..20913c9ea8e 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp @@ -49,12 +49,16 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, array2d< real64 > jump( 1, 3 ); array2d< real64 > djump( 1, 3 ); + bool isSimultaneous = true; + real64 const slidingCheckTol = .05; //default + //TODO computeTolerance eleme to Elem integer const numRows = m_table.size( 0 ); forAll< parallelDevicePolicy<> >( numRows, [&friction, &table, &ghostRank, &normalDisplacementTol, &normalTractionTol, &slidingTol, &iterPen, + &slidingCheckTol, &isSimultaneous, &jump, &djump, &fractureState, &traction ] GEOS_HOST_DEVICE ( integer const ei ) @@ -70,30 +74,36 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, djump[0][0] = table( ei, NDJUMP ); djump[0][1] = table( ei, DSLIP0 ); djump[0][2] = table( ei, DSLIP1 ); + GEOS_LOG_RANK( GEOS_FMT( "[debug : before] djump [0:3]\n \t {} \n\t {} \n\t {}", + djump[0][0], djump[0][1], djump[0][2] )); traction[0][0] = table( ei, NTRAC ); traction[0][1] = table( ei, STRAC0 ); traction[0][2] = table( ei, STRAC1 ); - SolidMechanicsAugmentedLagrangianContact::updateTractionAndConstraintCheck( 1, - friction, - true,//simultaneous - 0.05,//slidingCheckTolerance - normalDisplacementTol, - normalTractionTol, - slidingTol, - iterPen, - jump, - djump, - ghostRank, - fractureState.toView(), - traction.toView() - ); - table( ei, FS ) = fractureState[0]; - table( ei, NEWTRAC ) = traction[0][0]; - table( ei, SNEWTRAC0 ) = traction[0][1]; - table( ei, SNEWTRAC1 ) = traction[0][2]; + auto [newTraction, condCov] = SolidMechanicsAugmentedLagrangianContact::updateTractionAndConstraintCheck( 1, + friction, + isSimultaneous, + slidingCheckTol, + normalDisplacementTol, + normalTractionTol, + slidingTol, + iterPen, + jump, + djump, + ghostRank, + fractureState.toView(), + traction.toView() + ); + GEOS_LOG_RANK( GEOS_FMT( "[debug : after] djump [0:3]\n \t {} \n\t {} \n\t {}", + djump[0][0], djump[0][1], djump[0][2] )); + + // table( ei, FS ) = fractureState[0]; + table( ei, FS ) = condCov[0]; + table( ei, NEWTRAC ) = newTraction[0][0]; + table( ei, SNEWTRAC0 ) = newTraction[0][1]; + table( ei, SNEWTRAC1 ) = newTraction[0][2]; } ); } From e24a7a1d472560ebf815cab2f352d6785df411db Mon Sep 17 00:00:00 2001 From: jacques franc Date: Thu, 4 Jun 2026 14:42:40 +0200 Subject: [PATCH 12/25] parametrize --- .../friction/frictionDriver_Coulomb.xml | 4 ++++ .../contact/FrictionDriver.cpp | 23 +++++++++++++++++-- .../contact/FrictionDriver.hpp | 20 ++++++++++++++++ .../contact/FrictionDriverRunTest.hpp | 10 ++++---- 4 files changed, 50 insertions(+), 7 deletions(-) diff --git a/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml index bc136e77660..70de7cc8d4c 100644 --- a/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml +++ b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml @@ -11,6 +11,10 @@ xTiltAngle="80" tractionControl="tFunction" steps="10" + simultaneous="1" + tolJumpN="1e-10" + tolJumpT="1e-5" + tolNormalTrac="1e2" output="frictionDriver_Coulomb.txt" /> diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp index e0686e0a25f..607a0bc4dd7 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -55,11 +55,30 @@ FrictionDriver::FrictionDriver( const string & name, Group * const parent ) registerWrapper( viewKeyStruct::thetaString(), &m_theta ). setInputFlag( InputFlags::REQUIRED ). - setDescription( "Number of increment step to take in both jumps and traction increments" ); + setDescription( "x-Tilt angle in degree" ); registerWrapper( viewKeyStruct::phiString(), &m_phi ). setInputFlag( InputFlags::INVALID ). - setDescription( "Number of increment step to take in both jumps and traction increments" ); + setDescription( "y-Tilt angle in degree" ); + + //first batch of parameters + registerWrapper( viewKeyStruct::normalDispTol(), &m_normalDispTol ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "normal Displacement Tolerance (scale as inverse of average Young modulus)." ); + + registerWrapper( viewKeyStruct::normalTractionTol(), &m_normalTracTol ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "normal Traction Tolerance" ); + + registerWrapper( viewKeyStruct::slidingTol(), &m_slidingTol ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "tangential Displacement Tolerance" ); + + registerWrapper( viewKeyStruct::simultaneous(), &m_isSimultaneous ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "isSimultaneous" ); + + addLogLevel< logInfo::LogOutput >(); } diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp index b5e6a4a6983..856df8e6a08 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -81,6 +81,20 @@ class FrictionDriver : public ConstitutiveDriver constexpr static char const * phiString() { return "yTiltAngle";} + + constexpr static char const * normalDispTol() + { return "tolJumpN"; } + + constexpr static char const * normalTractionTol() + { return "tolNormalTrac"; } + + constexpr static char const * slidingTol() + { return "tolJumpT"; } + + constexpr static char const * simultaneous() + { return "simultaneous"; } + + }; // Time is defined in base class @@ -93,6 +107,12 @@ class FrictionDriver : public ConstitutiveDriver real64 m_theta{0.0}; ///< x-tilt of fault real64 m_phi{0.0}; ///< y-tilt of fault + real64 m_normalDispTol{1.e-8}; + real64 m_normalTracTol{100.}; + real64 m_slidingTol{1e-5}; + + integer m_isSimultaneous{1}; + string m_frictionName; ///< frictionType identifier }; diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp index 20913c9ea8e..5fee99d8e73 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp @@ -33,11 +33,11 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, { array1d< integer > const ghostRank( 1 ); ghostRank[0] = -1; - array1d< real64 > const normalDisplacementTol( 1 ); normalDisplacementTol[0]=10; - array1d< real64 > const normalTractionTol( 1 ); normalTractionTol[0]=1.; - array1d< real64 > const slidingTol( 1 ); slidingTol[0]=.1;//normalDispTol should scale as 1/E + array1d< real64 > const normalDisplacementTol( 1 ); normalDisplacementTol[0]=m_normalDispTol;//normalDispTol should scale as 1/E + array1d< real64 > const normalTractionTol( 1 ); normalTractionTol[0]=m_normalTracTol; + array1d< real64 > const slidingTol( 1 ); slidingTol[0]=m_slidingTol; - real64 kt = 1.; + real64 kt = 1e7; array2d< real64 > const iterPen( 1, 5 ); iterPen[0][0] = 100*kt; iterPen[0][1] = kt; @@ -49,7 +49,7 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, array2d< real64 > jump( 1, 3 ); array2d< real64 > djump( 1, 3 ); - bool isSimultaneous = true; + bool isSimultaneous = m_isSimultaneous; real64 const slidingCheckTol = .05; //default //TODO computeTolerance eleme to Elem From 22f75d6d974e01da953fff7fba9c4ad0fa54441b Mon Sep 17 00:00:00 2001 From: jacques franc Date: Thu, 4 Jun 2026 15:27:46 +0200 Subject: [PATCH 13/25] update FS prior/posterior --- .../contact/FrictionDriver.cpp | 4 +++- .../contact/FrictionDriver.hpp | 2 +- .../contact/FrictionDriverRunTest.hpp | 20 +++++++++++-------- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp index 607a0bc4dd7..a57b775f1d9 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -167,7 +167,8 @@ void FrictionDriver::getColumnNames( string_array & columnNames ) const columnNames.emplace_back( "delta displacement jump,normal" ); columnNames.emplace_back( "delta displacement jump,tangent1" ); columnNames.emplace_back( "delta displacement jump,tangent2" ); - columnNames.emplace_back( "fracture state" ); + columnNames.emplace_back( "encoded constaint (0:converged, 1:stick & gn>0 (opening), 2: interpenetration, 3: stick & gt>lim (disp-sliding), 4: tau>taulim (trac-sliding) )" ); + columnNames.emplace_back( "fracture state (0:stick, 1:slip , 2: new slip, 3: open)" ); columnNames.emplace_back( "newtraction,normal" ); columnNames.emplace_back( "newtraction,tangent1" ); columnNames.emplace_back( "newtraction,tangent2" ); @@ -212,6 +213,7 @@ void FrictionDriver::initializeTable() m_table( index, DSLIP0 ) = dJump*cos_theta*cos_phi; m_table( index, DSLIP1 ) = dJump*cos_theta*sin_phi; + m_table( index, CC ) = 0; m_table( index, FS ) = fields::contact::FractureState::Stick; } diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp index 856df8e6a08..771cb411d36 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -98,7 +98,7 @@ class FrictionDriver : public ConstitutiveDriver }; // Time is defined in base class - enum columnKeys { NTRAC=1, STRAC0, STRAC1, NJUMP, SLIP0, SLIP1, NDJUMP, DSLIP0, DSLIP1, FS, NEWTRAC, SNEWTRAC0, SNEWTRAC1, TLIM }; + enum columnKeys { NTRAC=1, STRAC0, STRAC1, NJUMP, SLIP0, SLIP1, NDJUMP, DSLIP0, DSLIP1, CC, FS, NEWTRAC, SNEWTRAC0, SNEWTRAC1, TLIM }; string m_jumpFunctionName; ///< string m_dJumpFunctionName; ///< diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp index 5fee99d8e73..9ba716392ef 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp @@ -53,10 +53,11 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, real64 const slidingCheckTol = .05; //default //TODO computeTolerance eleme to Elem + typename FRICTION_TYPE::KernelWrapper const kernelWrapper = friction.createKernelUpdates(); integer const numRows = m_table.size( 0 ); forAll< parallelDevicePolicy<> >( numRows, - [&friction, &table, + [&friction, &table, &kernelWrapper, &ghostRank, &normalDisplacementTol, &normalTractionTol, &slidingTol, &iterPen, &slidingCheckTol, &isSimultaneous, &jump, &djump, @@ -65,7 +66,6 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, { GEOS_LOG_RANK( "[debug] Table Evaluation" ); - GEOS_LOG_RANK( GEOS_FMT( " jump [{}x{}]", jump.size( 0 ), jump.size( 1 ))); jump[0][0] = table( ei, NJUMP ); jump[0][1] = table( ei, SLIP0 ); @@ -74,13 +74,15 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, djump[0][0] = table( ei, NDJUMP ); djump[0][1] = table( ei, DSLIP0 ); djump[0][2] = table( ei, DSLIP1 ); - GEOS_LOG_RANK( GEOS_FMT( "[debug : before] djump [0:3]\n \t {} \n\t {} \n\t {}", - djump[0][0], djump[0][1], djump[0][2] )); + traction[0][0] = table( ei, NTRAC ); traction[0][1] = table( ei, STRAC0 ); traction[0][2] = table( ei, STRAC1 ); + kernelWrapper.updateFractureState( jump[0], + traction[0], + fractureState[0] ); auto [newTraction, condCov] = SolidMechanicsAugmentedLagrangianContact::updateTractionAndConstraintCheck( 1, friction, @@ -96,11 +98,13 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, fractureState.toView(), traction.toView() ); - GEOS_LOG_RANK( GEOS_FMT( "[debug : after] djump [0:3]\n \t {} \n\t {} \n\t {}", - djump[0][0], djump[0][1], djump[0][2] )); - // table( ei, FS ) = fractureState[0]; - table( ei, FS ) = condCov[0]; + kernelWrapper.updateFractureState( jump[0], + newTraction[0], + fractureState[0] ); + + table( ei, CC ) = condCov[0]; + table( ei, FS ) = fractureState[0]; table( ei, NEWTRAC ) = newTraction[0][0]; table( ei, SNEWTRAC0 ) = newTraction[0][1]; table( ei, SNEWTRAC1 ) = newTraction[0][2]; From a9014b8d6d0f66e7401efdb5ee16bb99cb4d22d5 Mon Sep 17 00:00:00 2001 From: jacques franc Date: Mon, 8 Jun 2026 16:26:05 +0200 Subject: [PATCH 14/25] minus sign handling --- src/coreComponents/constitutiveDrivers/ConstitutiveDriver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/constitutiveDrivers/ConstitutiveDriver.cpp b/src/coreComponents/constitutiveDrivers/ConstitutiveDriver.cpp index e7d29b7582c..cb98979ee5d 100644 --- a/src/coreComponents/constitutiveDrivers/ConstitutiveDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/ConstitutiveDriver.cpp @@ -137,7 +137,7 @@ void ConstitutiveDriver::outputToFile() const integer const precision = LvArray::math::max( LvArray::math::min( m_precision, maxPrecision ), minPrecision ); file << std::scientific << std::setprecision( precision ); - integer const width = precision+7; + integer const width = precision+7+1;//spacing for minus sign for( integer step = 0; step <= m_numSteps; ++step ) { From db6f9f10e1250ed64827aa9fd303ae51a372f885 Mon Sep 17 00:00:00 2001 From: jacques franc Date: Mon, 8 Jun 2026 17:44:22 +0200 Subject: [PATCH 15/25] extracting computeTolerances for Driver --- ...lidMechanicsAugmentedLagrangianContact.cpp | 155 ++++++++++++------ ...lidMechanicsAugmentedLagrangianContact.hpp | 36 ++++ 2 files changed, 138 insertions(+), 53 deletions(-) diff --git a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp index d3717daadc1..8ff239c353c 100644 --- a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp +++ b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp @@ -1969,6 +1969,77 @@ void SolidMechanicsAugmentedLagrangianContact::addCouplingSparsityPattern( Domai } +void SolidMechanicsAugmentedLagrangianContact::_computeTolerances( real64 const area, + real64 const (&volume)[2], + real64 const (&bulkModulus)[2], + real64 const (&shearModulus)[2], + arraySlice2d< real64 const> const &faceRotationMatrix, + real64 const tolJumpDispNFac, + real64 const tolJumpDispTFac, + real64 const tolNormalTracFac, + real64 const iterPenaltyNFac, + real64 const iterPenaltyTFac, + real64 & normalDisplacementTolerance, + real64 & slidingTolerance, + real64 & normalTractionTolerance, + real64 (&iterativePenalty)[2] ) +{ + // approximation of the stiffness along coordinate directions + // ( first, second ) index -> ( element index, direction ) + // 1. T -> top (index 0), B -> bottom (index 1) + // 2. the coordinate direction (x, y, z) + real64 stiffDiagApprox[ 2 ][ 3 ]; + real64 averageYoungModulus = 0.0; + real64 averageConstrainedModulus = 0.0; + real64 averageCharLength = 0.0; + + for( localIndex i = 0; i < 2; ++i ) + { + // Get linear elastic isotropic constitutive parameters for the element + real64 const K = bulkModulus[i]; + real64 const G = shearModulus[i]; + real64 const E = 9.0 * K * G / ( 3.0 * K + G ); + real64 const nu = ( 3.0 * K - 2.0 * G ) / ( 2.0 * ( 3.0 * K + G ) ); + real64 const M = K + 4.0 / 3.0 * G; + + real64 const charLength = pow( volume[i], 1.0 / 3.0 ); + + // Combine E and nu to obtain a stiffness approximation (like it was an hexahedron) + for( localIndex j = 0; j < 3; ++j ) + { + stiffDiagApprox[ i ][ j ] = E / ( ( 1.0 + nu )*( 1.0 - 2.0*nu ) ) * 4.0 / 9.0 * ( 2.0 - 3.0 * nu ) * charLength; + } + + averageYoungModulus += 0.5*E; + averageConstrainedModulus += 0.5*M; + averageCharLength += 0.5*charLength; + } + + // Average the stiffness and compute the inverse + real64 invStiffApprox[ 3 ][ 3 ] = { { 0 } }; + for( localIndex j = 0; j < 3; ++j ) + { + invStiffApprox[ j ][ j ] = ( stiffDiagApprox[ 0 ][ j ] + stiffDiagApprox[ 1 ][ j ] ) / ( stiffDiagApprox[ 0 ][ j ] * stiffDiagApprox[ 1 ][ j ] ); + } + + // Rotate in the local reference system, computing R^T * (invK) * R + real64 temp[ 3 ][ 3 ]; + LvArray::tensorOps::Rij_eq_AkiBkj< 3, 3, 3 >( temp, faceRotationMatrix, invStiffApprox ); + real64 rotatedInvStiffApprox[ 3 ][ 3 ]; + LvArray::tensorOps::Rij_eq_AikBkj< 3, 3, 3 >( rotatedInvStiffApprox, temp, faceRotationMatrix ); + LvArray::tensorOps::scale< 3, 3 >( rotatedInvStiffApprox, area ); + + // Finally, compute tolerances and iterative penalties for the given fracture element + normalDisplacementTolerance = rotatedInvStiffApprox[ 0 ][ 0 ] * averageYoungModulus * tolJumpDispNFac; + slidingTolerance = sqrt( pow( rotatedInvStiffApprox[ 1 ][ 1 ], 2 ) + + pow( rotatedInvStiffApprox[ 2 ][ 2 ], 2 ) ) * averageYoungModulus * tolJumpDispTFac; + normalTractionTolerance = tolNormalTracFac * ( averageConstrainedModulus / averageCharLength ) * + normalDisplacementTolerance; + + iterativePenalty[0] = iterPenaltyNFac * averageConstrainedModulus / averageCharLength; + iterativePenalty[1] = iterPenaltyTFac * averageConstrainedModulus / averageCharLength; +} + void SolidMechanicsAugmentedLagrangianContact::computeTolerances( DomainPartition & domain ) const { GEOS_MARK_FUNCTION; @@ -2021,20 +2092,19 @@ void SolidMechanicsAugmentedLagrangianContact::computeTolerances( DomainPartitio arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); + real64 const tolJumpDispNFac = m_tolJumpDispNFac; + real64 const tolJumpDispTFac = m_tolJumpDispTFac; + real64 const tolNormalTracFac = m_tolNormalTracFac; + real64 const iterPenaltyNFac = m_iterPenaltyNFac; + real64 const iterPenaltyTFac = m_iterPenaltyTFac; + forAll< parallelHostPolicy >( subRegion.size(), [=] ( localIndex const kfe ) { - if( ghostRank[kfe] < 0 ) { - real64 const area = faceArea[kfe]; - // approximation of the stiffness along coordinate directions - // ( first, second ) index -> ( element index, direction ) - // 1. T -> top (index 0), B -> bottom (index 1) - // 2. the coordinate direction (x, y, z) - real64 stiffDiagApprox[ 2 ][ 3 ]; - real64 averageYoungModulus = 0.0; - real64 averageConstrainedModulus = 0.0; - real64 averageCharLength = 0.0; + real64 volume[2]{}; + real64 bulk[2]{}; + real64 shear[2]{}; for( localIndex i = 0; i < 2; ++i ) { @@ -2043,51 +2113,30 @@ void SolidMechanicsAugmentedLagrangianContact::computeTolerances( DomainPartitio localIndex const esr = faceToElemSubRegion[faceIndex][0]; localIndex const ei = faceToElemIndex[faceIndex][0]; - real64 const volume = elemVolume[er][esr][ei]; - - // Get linear elastic isotropic constitutive parameters for the element - real64 const K = bulkModulus[er][esr][ei]; - real64 const G = shearModulus[er][esr][ei]; - real64 const E = 9.0 * K * G / ( 3.0 * K + G ); - real64 const nu = ( 3.0 * K - 2.0 * G ) / ( 2.0 * ( 3.0 * K + G ) ); - real64 const M = K + 4.0 / 3.0 * G; - - real64 const charLength = pow( volume, 1.0 / 3.0 ); - - // Combine E and nu to obtain a stiffness approximation (like it was an hexahedron) - for( localIndex j = 0; j < 3; ++j ) - { - stiffDiagApprox[ i ][ j ] = E / ( ( 1.0 + nu )*( 1.0 - 2.0*nu ) ) * 4.0 / 9.0 * ( 2.0 - 3.0 * nu ) * charLength; - } - - averageYoungModulus += 0.5*E; - averageConstrainedModulus += 0.5*M; - averageCharLength += 0.5*charLength; - } - - // Average the stiffness and compute the inverse - real64 invStiffApprox[ 3 ][ 3 ] = { { 0 } }; - for( localIndex j = 0; j < 3; ++j ) - { - invStiffApprox[ j ][ j ] = ( stiffDiagApprox[ 0 ][ j ] + stiffDiagApprox[ 1 ][ j ] ) / ( stiffDiagApprox[ 0 ][ j ] * stiffDiagApprox[ 1 ][ j ] ); + volume[i] = elemVolume[er][esr][ei]; + bulk[i] = bulkModulus[er][esr][ei]; + shear[i] = shearModulus[er][esr][ei]; } - // Rotate in the local reference system, computing R^T * (invK) * R - real64 temp[ 3 ][ 3 ]; - LvArray::tensorOps::Rij_eq_AkiBkj< 3, 3, 3 >( temp, faceRotationMatrix[ kfe ], invStiffApprox ); - real64 rotatedInvStiffApprox[ 3 ][ 3 ]; - LvArray::tensorOps::Rij_eq_AikBkj< 3, 3, 3 >( rotatedInvStiffApprox, temp, faceRotationMatrix[ kfe ] ); - LvArray::tensorOps::scale< 3, 3 >( rotatedInvStiffApprox, area ); - - // Finally, compute tolerances for the given fracture element - normalDisplacementTolerance[kfe] = rotatedInvStiffApprox[ 0 ][ 0 ] * averageYoungModulus * m_tolJumpDispNFac; - slidingTolerance[kfe] = sqrt( pow( rotatedInvStiffApprox[ 1 ][ 1 ], 2 ) + - pow( rotatedInvStiffApprox[ 2 ][ 2 ], 2 )) * averageYoungModulus * m_tolJumpDispTFac; - normalTractionTolerance[kfe] = m_tolNormalTracFac * (averageConstrainedModulus / averageCharLength) * - (normalDisplacementTolerance[kfe]); - - iterativePenalty[kfe][0] = m_iterPenaltyNFac*averageConstrainedModulus/(averageCharLength); - iterativePenalty[kfe][1] = m_iterPenaltyTFac*averageConstrainedModulus/(averageCharLength); + real64 iterativePenaltyKfe[2]{}; + + _computeTolerances( faceArea[kfe], + volume, + bulk, + shear, + faceRotationMatrix[kfe], + tolJumpDispNFac, + tolJumpDispTFac, + tolNormalTracFac, + iterPenaltyNFac, + iterPenaltyTFac, + normalDisplacementTolerance[kfe], + slidingTolerance[kfe], + normalTractionTolerance[kfe], + iterativePenaltyKfe ); + + iterativePenalty[kfe][0] = iterativePenaltyKfe[0]; + iterativePenalty[kfe][1] = iterativePenaltyKfe[1]; } } ); } diff --git a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp index d4e411fdc39..5673412f276 100644 --- a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp +++ b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp @@ -217,7 +217,9 @@ class SolidMechanicsAugmentedLagrangianContact : public ContactSolverBase void createBubbleCellList( DomainPartition & domain ) const; + //TODO (change return idiom to passed through interface) static + GEOS_HOST_DEVICE std::tuple< array2d< real64 >, array1d< int > > updateTractionAndConstraintCheck( std::ptrdiff_t const rsize, constitutive::FrictionBase const & frictionLaw, bool isSimultaneous, @@ -232,6 +234,40 @@ class SolidMechanicsAugmentedLagrangianContact : public ContactSolverBase arrayView1d< integer const > const & fractureState, arrayView2d< real64 > const & traction ); + + /** + * @brief Compute the augmented-Lagrangian tolerances and iterative penalties for a single + * fracture (contact interface) element. + * @param area area of the fracture element + * @param volume volume of the two adjacent cells (index 0/1 -> top/bottom) + * @param bulkModulus bulk modulus of the two adjacent cells + * @param shearModulus shear modulus of the two adjacent cells + * @param faceRotationMatrix rotation matrix bringing global -> local (fault) reference frame + * @param tolJumpDispNFac factor for the normal displacement jump tolerance + * @param tolJumpDispTFac factor for the tangential displacement jump (sliding) tolerance + * @param tolNormalTracFac factor for the normal traction tolerance + * @param iterPenaltyNFac factor for the normal iterative penalty + * @param iterPenaltyTFac factor for the tangential iterative penalty + * @param[out] normalDisplacementTolerance normal displacement jump tolerance for this element + * @param[out] slidingTolerance sliding (tangential displacement jump) tolerance for this element + * @param[out] normalTractionTolerance normal traction tolerance for this element + * @param[out] iterativePenalty iterative penalties (normal, tangential) for this element + */ + static GEOS_HOST_DEVICE void _computeTolerances( real64 const area, + real64 const (&volume)[2], + real64 const (&bulkModulus)[2], + real64 const (&shearModulus)[2], + arraySlice2d< real64 const> const &faceRotationMatrix, + real64 const tolJumpDispNFac, + real64 const tolJumpDispTFac, + real64 const tolNormalTracFac, + real64 const iterPenaltyNFac, + real64 const iterPenaltyTFac, + real64 & normalDisplacementTolerance, + real64 & slidingTolerance, + real64 & normalTractionTolerance, + real64 (&iterativePenalty)[2] ); + private: From 709305fecf0c11784e7a98ec2842344dabc01d2b Mon Sep 17 00:00:00 2001 From: jacques franc Date: Mon, 8 Jun 2026 18:32:51 +0200 Subject: [PATCH 16/25] integrating computeTolerances --- .../friction/frictionDriver_Coulomb.xml | 10 ++- .../friction/tables/djumps.geos | 10 +-- .../friction/tables/jumps.geos | 10 +-- .../friction/tables/tractions.geos | 10 +-- .../contact/FrictionDriver.cpp | 27 ++++++- .../contact/FrictionDriver.hpp | 33 ++++++-- .../contact/FrictionDriverRunTest.hpp | 76 +++++++++++++++---- ...lidMechanicsAugmentedLagrangianContact.cpp | 56 +++++++------- ...lidMechanicsAugmentedLagrangianContact.hpp | 28 +++---- 9 files changed, 179 insertions(+), 81 deletions(-) diff --git a/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml index 70de7cc8d4c..65e5225b1f0 100644 --- a/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml +++ b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml @@ -12,12 +12,20 @@ tractionControl="tFunction" steps="10" simultaneous="1" - tolJumpN="1e-10" + tolJumpN="1e-15" tolJumpT="1e-5" tolNormalTrac="1e2" + faceArea="1" + neighborsVolume="{1,1}" + neighborsShear="{1e9,1e9}" + neighborsBulk="{1e7,1e7}" output="frictionDriver_Coulomb.txt" /> + + + + diff --git a/inputFiles/constitutiveDriver/friction/tables/djumps.geos b/inputFiles/constitutiveDriver/friction/tables/djumps.geos index e1174543015..cedef2718a7 100644 --- a/inputFiles/constitutiveDriver/friction/tables/djumps.geos +++ b/inputFiles/constitutiveDriver/friction/tables/djumps.geos @@ -1,6 +1,6 @@ 0 -1e-5 -2e-5 -3e-5 -4e-5 -5e-5 \ No newline at end of file +-1e-2 +-1e-3 +0 +1e-3 +1e-2 \ No newline at end of file diff --git a/inputFiles/constitutiveDriver/friction/tables/jumps.geos b/inputFiles/constitutiveDriver/friction/tables/jumps.geos index 3c922732f7a..c31e4986824 100644 --- a/inputFiles/constitutiveDriver/friction/tables/jumps.geos +++ b/inputFiles/constitutiveDriver/friction/tables/jumps.geos @@ -1,6 +1,6 @@ 0 -1e-3 -2e-3 -3e-3 -4e-3 -5e-3 +-1e-3 +-2e-3 +-3e-3 +-4e-3 +-5e-3 diff --git a/inputFiles/constitutiveDriver/friction/tables/tractions.geos b/inputFiles/constitutiveDriver/friction/tables/tractions.geos index 1655949d91f..b45f7ff7fc8 100644 --- a/inputFiles/constitutiveDriver/friction/tables/tractions.geos +++ b/inputFiles/constitutiveDriver/friction/tables/tractions.geos @@ -1,6 +1,6 @@ 0 --1e6 --2e6 --3e6 --4e6 --5e6 +-1e2 +-2e2 +-3e2 +-4e2 +-5e2 diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp index a57b775f1d9..1cfbf55afa2 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -62,18 +62,37 @@ FrictionDriver::FrictionDriver( const string & name, Group * const parent ) setDescription( "y-Tilt angle in degree" ); //first batch of parameters - registerWrapper( viewKeyStruct::normalDispTol(), &m_normalDispTol ). + registerWrapper( viewKeyStruct::normalDispTolFac(), &m_normalDispTolFac ). setInputFlag( InputFlags::REQUIRED ). setDescription( "normal Displacement Tolerance (scale as inverse of average Young modulus)." ); - registerWrapper( viewKeyStruct::normalTractionTol(), &m_normalTracTol ). + registerWrapper( viewKeyStruct::normalTractionTolFac(), &m_normalTracTolFac ). setInputFlag( InputFlags::REQUIRED ). setDescription( "normal Traction Tolerance" ); - registerWrapper( viewKeyStruct::slidingTol(), &m_slidingTol ). + registerWrapper( viewKeyStruct::slidingTolFac(), &m_slidingTolFac ). setInputFlag( InputFlags::REQUIRED ). setDescription( "tangential Displacement Tolerance" ); + + //geometry + registerWrapper( viewKeyStruct::area(), &m_area ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Face area" ); + + registerWrapper( viewKeyStruct::volume(), &m_volume ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Neighboring cells' volume" ); + + registerWrapper( viewKeyStruct::bulk(), &m_bulkModulus ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Neighboring cells' bulk Modulus" ); + + registerWrapper( viewKeyStruct::shear(), &m_shearModulus ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Neighboring cells' shear Modulus" ); + + //algo tune registerWrapper( viewKeyStruct::simultaneous(), &m_isSimultaneous ). setInputFlag( InputFlags::REQUIRED ). setDescription( "isSimultaneous" ); @@ -172,6 +191,8 @@ void FrictionDriver::getColumnNames( string_array & columnNames ) const columnNames.emplace_back( "newtraction,normal" ); columnNames.emplace_back( "newtraction,tangent1" ); columnNames.emplace_back( "newtraction,tangent2" ); + columnNames.emplace_back( "iterative penalty, normal" ); + columnNames.emplace_back( "iterative penalty, tangent" ); if( dynamic_cast< CoulombFriction const * >(&getFriction()) != nullptr ) { diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp index 771cb411d36..6a4ec6b3797 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -82,15 +82,28 @@ class FrictionDriver : public ConstitutiveDriver constexpr static char const * phiString() { return "yTiltAngle";} - constexpr static char const * normalDispTol() + constexpr static char const * normalDispTolFac() { return "tolJumpN"; } - constexpr static char const * normalTractionTol() + constexpr static char const * normalTractionTolFac() { return "tolNormalTrac"; } - constexpr static char const * slidingTol() + constexpr static char const * slidingTolFac() { return "tolJumpT"; } + //geometry + constexpr static char const * area() + { return "faceArea"; } + + constexpr static char const * volume() + { return "neighborsVolume"; } + + constexpr static char const * shear() + { return "neighborsShear"; } + + constexpr static char const * bulk() + { return "neighborsBulk"; } + constexpr static char const * simultaneous() { return "simultaneous"; } @@ -98,7 +111,7 @@ class FrictionDriver : public ConstitutiveDriver }; // Time is defined in base class - enum columnKeys { NTRAC=1, STRAC0, STRAC1, NJUMP, SLIP0, SLIP1, NDJUMP, DSLIP0, DSLIP1, CC, FS, NEWTRAC, SNEWTRAC0, SNEWTRAC1, TLIM }; + enum columnKeys { NTRAC=1, STRAC0, STRAC1, NJUMP, SLIP0, SLIP1, NDJUMP, DSLIP0, DSLIP1, CC, FS, NEWTRAC, SNEWTRAC0, SNEWTRAC1, ITERPEN0, ITERPEN1, TLIM }; string m_jumpFunctionName; ///< string m_dJumpFunctionName; ///< @@ -107,9 +120,15 @@ class FrictionDriver : public ConstitutiveDriver real64 m_theta{0.0}; ///< x-tilt of fault real64 m_phi{0.0}; ///< y-tilt of fault - real64 m_normalDispTol{1.e-8}; - real64 m_normalTracTol{100.}; - real64 m_slidingTol{1e-5}; + real64 m_normalDispTolFac{1.e-8}; + real64 m_normalTracTolFac{100.}; + real64 m_slidingTolFac{1e-5}; + + //geometry for iterPen + real64 m_area{0.0}; + array1d< real64 > m_volume{}; + array1d< real64 > m_shearModulus{}; + array1d< real64 > m_bulkModulus{}; integer m_isSimultaneous{1}; diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp index 9ba716392ef..c9148898e05 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp @@ -21,6 +21,7 @@ #include "physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp" #include "constitutive/solid/SolidFields.hpp" +#include #include namespace geos @@ -33,15 +34,7 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, { array1d< integer > const ghostRank( 1 ); ghostRank[0] = -1; - array1d< real64 > const normalDisplacementTol( 1 ); normalDisplacementTol[0]=m_normalDispTol;//normalDispTol should scale as 1/E - array1d< real64 > const normalTractionTol( 1 ); normalTractionTol[0]=m_normalTracTol; - array1d< real64 > const slidingTol( 1 ); slidingTol[0]=m_slidingTol; - - real64 kt = 1e7; - array2d< real64 > const iterPen( 1, 5 ); - iterPen[0][0] = 100*kt; - iterPen[0][1] = kt; - iterPen[0][2] = kt; iterPen[0][3] = kt; iterPen[0][4] = 0.; + array1d< integer > fractureState( 1 ); fractureState[0] = fields::contact::FractureState::Stick; @@ -51,6 +44,21 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, bool isSimultaneous = m_isSimultaneous; real64 const slidingCheckTol = .05; //default + real64 cos_phi = cos( m_phi * M_PI/180 ); + real64 cos_theta = cos( m_theta * M_PI/180 ); + real64 sin_phi = sin( m_phi * M_PI/180 ); + real64 sin_theta = sin( m_theta * M_PI/180 ); + + real64 normalDispTolFac = m_normalDispTolFac; + real64 normalTracTolFac = m_normalTracTolFac; + real64 slidingTolFac = m_slidingTolFac; + real64 iterPenNFac = 100; + real64 iterPenTFac = 100; + + real64 area = m_area; + real64 volumes[2]{m_volume[0], m_volume[1]}; + real64 shearModuli[2]{m_shearModulus[0], m_shearModulus[1]}; + real64 bulkModuli[2]{m_bulkModulus[0], m_bulkModulus[1]}; //TODO computeTolerance eleme to Elem typename FRICTION_TYPE::KernelWrapper const kernelWrapper = friction.createKernelUpdates(); @@ -58,7 +66,12 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, integer const numRows = m_table.size( 0 ); forAll< parallelDevicePolicy<> >( numRows, [&friction, &table, &kernelWrapper, - &ghostRank, &normalDisplacementTol, &normalTractionTol, &slidingTol, &iterPen, + &ghostRank, + // &normalDisplacementTol, &normalTractionTol, &slidingTol, + &normalDispTolFac, &normalTracTolFac, &slidingTolFac, + &iterPenNFac, &iterPenTFac, + &area, &volumes, &bulkModuli, &shearModuli, + &cos_phi, &sin_phi, &cos_theta, &sin_theta, &slidingCheckTol, &isSimultaneous, &jump, &djump, &fractureState, &traction ] @@ -84,13 +97,47 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, traction[0], fractureState[0] ); + real64 normalDispTol{}, slidingTol{}, normalTractionTol{}; + real64 iterativePen[2]{}; + + + array2d< real64 > rotationMatrix( 3, 3 ); + rotationMatrix[0][0] = cos_phi; rotationMatrix[0][1] = 0.; rotationMatrix[0][1] = sin_phi; + rotationMatrix[1][0] = sin_theta*sin_phi; rotationMatrix[1][1] = cos_theta; rotationMatrix[1][1] = -sin_theta*cos_phi; + rotationMatrix[2][0] = -cos_theta*sin_phi; rotationMatrix[2][1] = sin_theta; rotationMatrix[2][1] = cos_theta*cos_phi; + + SolidMechanicsAugmentedLagrangianContact::computeTolerancePerFace( area, + volumes, + bulkModuli, + shearModuli, + rotationMatrix, + normalDispTolFac, + normalTracTolFac, + slidingTol, + iterPenNFac, + iterPenTFac, + normalDispTol, + slidingTol, + normalTractionTol, + iterativePen ); + + //small adapter + array2d< real64 > const iterPen( 1, 5 ); + iterPen[0][0] = iterativePen[0]; + iterPen[0][1] = iterativePen[1]; + iterPen[0][2] = iterativePen[1]; iterPen[0][3] = iterativePen[1]; iterPen[0][4] = 0.; + + array1d< real64 > const a_normalDisplacementTol( 1 ); a_normalDisplacementTol[0]=normalDispTol;//normalDispTol should scale as 1/E + array1d< real64 > const a_normalTractionTol( 1 ); a_normalTractionTol[0]=normalTractionTol; + array1d< real64 > const a_slidingTol( 1 ); a_slidingTol[0]=slidingTol; + auto [newTraction, condCov] = SolidMechanicsAugmentedLagrangianContact::updateTractionAndConstraintCheck( 1, friction, isSimultaneous, slidingCheckTol, - normalDisplacementTol, - normalTractionTol, - slidingTol, + a_normalDisplacementTol, + a_normalTractionTol, + a_slidingTol, iterPen, jump, djump, @@ -109,6 +156,9 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, table( ei, SNEWTRAC0 ) = newTraction[0][1]; table( ei, SNEWTRAC1 ) = newTraction[0][2]; + table( ei, ITERPEN0 ) = iterPen[0][0]; + table( ei, ITERPEN1 ) = iterPen[0][1]; + } ); } diff --git a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp index 8ff239c353c..180086fbd0f 100644 --- a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp +++ b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp @@ -1969,20 +1969,20 @@ void SolidMechanicsAugmentedLagrangianContact::addCouplingSparsityPattern( Domai } -void SolidMechanicsAugmentedLagrangianContact::_computeTolerances( real64 const area, - real64 const (&volume)[2], - real64 const (&bulkModulus)[2], - real64 const (&shearModulus)[2], - arraySlice2d< real64 const> const &faceRotationMatrix, - real64 const tolJumpDispNFac, - real64 const tolJumpDispTFac, - real64 const tolNormalTracFac, - real64 const iterPenaltyNFac, - real64 const iterPenaltyTFac, - real64 & normalDisplacementTolerance, - real64 & slidingTolerance, - real64 & normalTractionTolerance, - real64 (&iterativePenalty)[2] ) +void SolidMechanicsAugmentedLagrangianContact::computeTolerancePerFace( real64 const area, + real64 const (&volume)[2], + real64 const (&bulkModulus)[2], + real64 const (&shearModulus)[2], + arraySlice2d< real64 const > const & faceRotationMatrix, + real64 const tolJumpDispNFac, + real64 const tolJumpDispTFac, + real64 const tolNormalTracFac, + real64 const iterPenaltyNFac, + real64 const iterPenaltyTFac, + real64 & normalDisplacementTolerance, + real64 & slidingTolerance, + real64 & normalTractionTolerance, + real64 (& iterativePenalty)[2] ) { // approximation of the stiffness along coordinate directions // ( first, second ) index -> ( element index, direction ) @@ -2120,20 +2120,20 @@ void SolidMechanicsAugmentedLagrangianContact::computeTolerances( DomainPartitio real64 iterativePenaltyKfe[2]{}; - _computeTolerances( faceArea[kfe], - volume, - bulk, - shear, - faceRotationMatrix[kfe], - tolJumpDispNFac, - tolJumpDispTFac, - tolNormalTracFac, - iterPenaltyNFac, - iterPenaltyTFac, - normalDisplacementTolerance[kfe], - slidingTolerance[kfe], - normalTractionTolerance[kfe], - iterativePenaltyKfe ); + computeTolerancePerFace( faceArea[kfe], + volume, + bulk, + shear, + faceRotationMatrix[kfe], + tolJumpDispNFac, + tolJumpDispTFac, + tolNormalTracFac, + iterPenaltyNFac, + iterPenaltyTFac, + normalDisplacementTolerance[kfe], + slidingTolerance[kfe], + normalTractionTolerance[kfe], + iterativePenaltyKfe ); iterativePenalty[kfe][0] = iterativePenaltyKfe[0]; iterativePenalty[kfe][1] = iterativePenaltyKfe[1]; diff --git a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp index 5673412f276..281c16d8734 100644 --- a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp +++ b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp @@ -253,20 +253,20 @@ class SolidMechanicsAugmentedLagrangianContact : public ContactSolverBase * @param[out] normalTractionTolerance normal traction tolerance for this element * @param[out] iterativePenalty iterative penalties (normal, tangential) for this element */ - static GEOS_HOST_DEVICE void _computeTolerances( real64 const area, - real64 const (&volume)[2], - real64 const (&bulkModulus)[2], - real64 const (&shearModulus)[2], - arraySlice2d< real64 const> const &faceRotationMatrix, - real64 const tolJumpDispNFac, - real64 const tolJumpDispTFac, - real64 const tolNormalTracFac, - real64 const iterPenaltyNFac, - real64 const iterPenaltyTFac, - real64 & normalDisplacementTolerance, - real64 & slidingTolerance, - real64 & normalTractionTolerance, - real64 (&iterativePenalty)[2] ); + static GEOS_HOST_DEVICE void computeTolerancePerFace( real64 const area, + real64 const (&volume)[2], + real64 const (&bulkModulus)[2], + real64 const (&shearModulus)[2], + arraySlice2d< real64 const > const &faceRotationMatrix, + real64 const tolJumpDispNFac, + real64 const tolJumpDispTFac, + real64 const tolNormalTracFac, + real64 const iterPenaltyNFac, + real64 const iterPenaltyTFac, + real64 & normalDisplacementTolerance, + real64 & slidingTolerance, + real64 & normalTractionTolerance, + real64 ( &iterativePenalty )[2] ); private: From e2764a85ee8e4ea4d973338511d26e7f8fcc6369 Mon Sep 17 00:00:00 2001 From: jacques franc Date: Tue, 9 Jun 2026 13:53:29 +0200 Subject: [PATCH 17/25] adding iterative Penalty --- .../friction/frictionDriver_Coulomb.xml | 2 ++ .../constitutiveDrivers/contact/FrictionDriver.cpp | 8 ++++++++ .../constitutiveDrivers/contact/FrictionDriver.hpp | 9 +++++++++ .../contact/FrictionDriverRunTest.hpp | 4 ++-- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml index 65e5225b1f0..66c3332bfd1 100644 --- a/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml +++ b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml @@ -15,6 +15,8 @@ tolJumpN="1e-15" tolJumpT="1e-5" tolNormalTrac="1e2" + iterPenNFac="1" + iterPenTFac="100" faceArea="1" neighborsVolume="{1,1}" neighborsShear="{1e9,1e9}" diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp index 1cfbf55afa2..370aab92016 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -74,6 +74,14 @@ FrictionDriver::FrictionDriver( const string & name, Group * const parent ) setInputFlag( InputFlags::REQUIRED ). setDescription( "tangential Displacement Tolerance" ); + registerWrapper( viewKeyStruct::iterPenNFac(), &m_iterPenNFac ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "normal Penalty Factor" ); + + registerWrapper( viewKeyStruct::iterPenTFac(), &m_iterPenTFac ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "tangential Penatly Factor" ); + //geometry registerWrapper( viewKeyStruct::area(), &m_area ). diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp index 6a4ec6b3797..91d4e792522 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -91,6 +91,12 @@ class FrictionDriver : public ConstitutiveDriver constexpr static char const * slidingTolFac() { return "tolJumpT"; } + constexpr static char const * iterPenNFac() + { return "iterPenNFac"; } + + constexpr static char const * iterPenTFac() + { return "iterPenTFac"; } + //geometry constexpr static char const * area() { return "faceArea"; } @@ -124,6 +130,9 @@ class FrictionDriver : public ConstitutiveDriver real64 m_normalTracTolFac{100.}; real64 m_slidingTolFac{1e-5}; + real64 m_iterPenNFac{100}; + real64 m_iterPenTFac{1}; + //geometry for iterPen real64 m_area{0.0}; array1d< real64 > m_volume{}; diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp index c9148898e05..176ebbdf59d 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp @@ -52,8 +52,8 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, real64 normalDispTolFac = m_normalDispTolFac; real64 normalTracTolFac = m_normalTracTolFac; real64 slidingTolFac = m_slidingTolFac; - real64 iterPenNFac = 100; - real64 iterPenTFac = 100; + real64 iterPenNFac = m_iterPenNFac; + real64 iterPenTFac = m_iterPenTFac; real64 area = m_area; real64 volumes[2]{m_volume[0], m_volume[1]}; From 38bd5f14e3c0358a262db85a7531980e6af0cb17 Mon Sep 17 00:00:00 2001 From: jacques franc Date: Tue, 9 Jun 2026 14:48:01 +0200 Subject: [PATCH 18/25] index fix --- .../constitutiveDrivers/contact/FrictionDriverRunTest.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp index 176ebbdf59d..f6102490f7b 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp @@ -102,9 +102,9 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, array2d< real64 > rotationMatrix( 3, 3 ); - rotationMatrix[0][0] = cos_phi; rotationMatrix[0][1] = 0.; rotationMatrix[0][1] = sin_phi; - rotationMatrix[1][0] = sin_theta*sin_phi; rotationMatrix[1][1] = cos_theta; rotationMatrix[1][1] = -sin_theta*cos_phi; - rotationMatrix[2][0] = -cos_theta*sin_phi; rotationMatrix[2][1] = sin_theta; rotationMatrix[2][1] = cos_theta*cos_phi; + rotationMatrix[0][0] = cos_phi; rotationMatrix[0][1] = 0.; rotationMatrix[0][2] = sin_phi; + rotationMatrix[1][0] = sin_theta*sin_phi; rotationMatrix[1][1] = cos_theta; rotationMatrix[1][2] = -sin_theta*cos_phi; + rotationMatrix[2][0] = -cos_theta*sin_phi; rotationMatrix[2][1] = sin_theta; rotationMatrix[2][2] = cos_theta*cos_phi; SolidMechanicsAugmentedLagrangianContact::computeTolerancePerFace( area, volumes, From a2c3e98b83104731ffd315d54458573b5353245f Mon Sep 17 00:00:00 2001 From: jacques franc Date: Tue, 9 Jun 2026 15:11:17 +0200 Subject: [PATCH 19/25] correct rotation --- .../constitutiveDrivers/contact/FrictionDriver.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp index 370aab92016..e8d024973b8 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -228,18 +228,18 @@ void FrictionDriver::initializeTable() real64 const time = m_table( index, TIME ); real64 const traction = tractionFunction.evaluate( &time ); - m_table( index, NTRAC ) = traction*sin_theta; - m_table( index, STRAC0 ) = traction*cos_theta*cos_phi; - m_table( index, STRAC1 ) = traction*cos_theta*sin_phi; + m_table( index, NTRAC ) = traction*cos_phi; + m_table( index, STRAC0 ) = traction*sin_theta*sin_phi; + m_table( index, STRAC1 ) = -traction*cos_theta*sin_phi; real64 const jump = jumpFunction.evaluate( &time ); - m_table( index, NJUMP ) = jump*sin_theta; - m_table( index, SLIP0 ) = jump*cos_theta*cos_phi; + m_table( index, NJUMP ) = jump*cos_phi; + m_table( index, SLIP0 ) = jump*sin_theta*sin_phi; m_table( index, SLIP1 ) = jump*cos_theta*sin_phi; real64 const dJump = dJumpFunction.evaluate( &time ); - m_table( index, NDJUMP ) = dJump*sin_theta; - m_table( index, DSLIP0 ) = dJump*cos_theta*cos_phi; + m_table( index, NDJUMP ) = dJump*cos_phi; + m_table( index, DSLIP0 ) = dJump*sin_theta*sin_phi; m_table( index, DSLIP1 ) = dJump*cos_theta*sin_phi; m_table( index, CC ) = 0; From 2d8dfd7eea6147de98688fe2e1eaf83942c5bfe0 Mon Sep 17 00:00:00 2001 From: jacques franc Date: Tue, 9 Jun 2026 15:51:42 +0200 Subject: [PATCH 20/25] changing the tilt angles --- .../contact/FrictionDriver.cpp | 25 ++++++++++--------- .../contact/FrictionDriver.hpp | 4 +-- .../contact/FrictionDriverRunTest.hpp | 6 ++--- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp index e8d024973b8..f5f336671f4 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -55,11 +55,12 @@ FrictionDriver::FrictionDriver( const string & name, Group * const parent ) registerWrapper( viewKeyStruct::thetaString(), &m_theta ). setInputFlag( InputFlags::REQUIRED ). - setDescription( "x-Tilt angle in degree" ); + setDescription( "y-Tilt angle in degree" ); registerWrapper( viewKeyStruct::phiString(), &m_phi ). - setInputFlag( InputFlags::INVALID ). - setDescription( "y-Tilt angle in degree" ); + setInputFlag( InputFlags::OPTIONAL ). + setDefaultValue(0.). + setDescription( "z-Tilt angle in degree" ); //first batch of parameters registerWrapper( viewKeyStruct::normalDispTolFac(), &m_normalDispTolFac ). @@ -228,19 +229,19 @@ void FrictionDriver::initializeTable() real64 const time = m_table( index, TIME ); real64 const traction = tractionFunction.evaluate( &time ); - m_table( index, NTRAC ) = traction*cos_phi; - m_table( index, STRAC0 ) = traction*sin_theta*sin_phi; - m_table( index, STRAC1 ) = -traction*cos_theta*sin_phi; + m_table( index, NTRAC ) = traction*cos_phi*cos_theta; + m_table( index, STRAC0 ) = traction*cos_theta*sin_phi; + m_table( index, STRAC1 ) = -traction*sin_theta; real64 const jump = jumpFunction.evaluate( &time ); - m_table( index, NJUMP ) = jump*cos_phi; - m_table( index, SLIP0 ) = jump*sin_theta*sin_phi; - m_table( index, SLIP1 ) = jump*cos_theta*sin_phi; + m_table( index, NJUMP ) = jump*cos_phi*cos_theta; + m_table( index, SLIP0 ) = jump*cos_theta*sin_phi; + m_table( index, SLIP1 ) = jump*sin_theta; real64 const dJump = dJumpFunction.evaluate( &time ); - m_table( index, NDJUMP ) = dJump*cos_phi; - m_table( index, DSLIP0 ) = dJump*sin_theta*sin_phi; - m_table( index, DSLIP1 ) = dJump*cos_theta*sin_phi; + m_table( index, NDJUMP ) = dJump*cos_phi*cos_theta; + m_table( index, DSLIP0 ) = dJump*cos_theta*sin_phi; + m_table( index, DSLIP1 ) = dJump*sin_theta; m_table( index, CC ) = 0; m_table( index, FS ) = fields::contact::FractureState::Stick; diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp index 91d4e792522..c1c3c897f47 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -77,10 +77,10 @@ class FrictionDriver : public ConstitutiveDriver { return "tractionControl"; } constexpr static char const * thetaString() - { return "xTiltAngle";} + { return "yTiltAngle";} constexpr static char const * phiString() - { return "yTiltAngle";} + { return "zTiltAngle";} constexpr static char const * normalDispTolFac() { return "tolJumpN"; } diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp index f6102490f7b..5bf85d53464 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp @@ -102,9 +102,9 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, array2d< real64 > rotationMatrix( 3, 3 ); - rotationMatrix[0][0] = cos_phi; rotationMatrix[0][1] = 0.; rotationMatrix[0][2] = sin_phi; - rotationMatrix[1][0] = sin_theta*sin_phi; rotationMatrix[1][1] = cos_theta; rotationMatrix[1][2] = -sin_theta*cos_phi; - rotationMatrix[2][0] = -cos_theta*sin_phi; rotationMatrix[2][1] = sin_theta; rotationMatrix[2][2] = cos_theta*cos_phi; + rotationMatrix[0][0] = cos_phi*cos_theta; rotationMatrix[0][1] = -sin_phi; rotationMatrix[0][2] = cos_phi*sin_theta; + rotationMatrix[1][0] = sin_phi*sin_theta; rotationMatrix[1][1] = cos_phi; rotationMatrix[1][2] = sin_theta*sin_phi; + rotationMatrix[2][0] = -sin_theta; rotationMatrix[2][1] = 0.; rotationMatrix[2][2] = cos_theta; SolidMechanicsAugmentedLagrangianContact::computeTolerancePerFace( area, volumes, From db21cb75a0a96d4aed2234c782411fb74cdce50b Mon Sep 17 00:00:00 2001 From: jacques franc Date: Tue, 9 Jun 2026 17:45:11 +0200 Subject: [PATCH 21/25] adding tolerances in report --- .../constitutiveDrivers/contact/FrictionDriver.cpp | 3 +++ .../constitutiveDrivers/contact/FrictionDriver.hpp | 5 ++++- .../constitutiveDrivers/contact/FrictionDriverRunTest.hpp | 5 +++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp index f5f336671f4..cd302f7cc30 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -200,6 +200,9 @@ void FrictionDriver::getColumnNames( string_array & columnNames ) const columnNames.emplace_back( "newtraction,normal" ); columnNames.emplace_back( "newtraction,tangent1" ); columnNames.emplace_back( "newtraction,tangent2" ); + columnNames.emplace_back( "derived disp tol, normal" ); + columnNames.emplace_back( "derived disp tol, tangent" ); + columnNames.emplace_back( "derived traction tol, normal" ); columnNames.emplace_back( "iterative penalty, normal" ); columnNames.emplace_back( "iterative penalty, tangent" ); diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp index c1c3c897f47..46bd7325970 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -117,7 +117,10 @@ class FrictionDriver : public ConstitutiveDriver }; // Time is defined in base class - enum columnKeys { NTRAC=1, STRAC0, STRAC1, NJUMP, SLIP0, SLIP1, NDJUMP, DSLIP0, DSLIP1, CC, FS, NEWTRAC, SNEWTRAC0, SNEWTRAC1, ITERPEN0, ITERPEN1, TLIM }; + enum columnKeys { NTRAC=1, STRAC0, STRAC1, NJUMP, SLIP0, SLIP1, NDJUMP, DSLIP0, DSLIP1, CC, FS, + NEWTRAC, SNEWTRAC0, SNEWTRAC1, + NTOL, TTOL, NTRACTOL, + ITERPEN0, ITERPEN1, TLIM }; string m_jumpFunctionName; ///< string m_dJumpFunctionName; ///< diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp index 5bf85d53464..0cd17976183 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp @@ -156,6 +156,11 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, table( ei, SNEWTRAC0 ) = newTraction[0][1]; table( ei, SNEWTRAC1 ) = newTraction[0][2]; + + table( ei, NTOL ) = normalDispTol; + table( ei, TTOL ) = slidingTol; + table( ei, NTRACTOL ) = normalTractionTol; + table( ei, ITERPEN0 ) = iterPen[0][0]; table( ei, ITERPEN1 ) = iterPen[0][1]; From 1718f69dffff977c874e7437d94925d657fecf92 Mon Sep 17 00:00:00 2001 From: jacques franc Date: Tue, 18 Aug 2026 11:08:29 +0200 Subject: [PATCH 22/25] wip --- .../friction/frictionDriver_Coulomb.xml | 16 +- .../constitutive/contact/CoulombFriction.hpp | 5 +- .../contact/FrictionDriver.cpp | 626 +++++++++++++++++- .../contact/FrictionDriver.hpp | 131 +++- .../contact/FrictionDriverRunTest.hpp | 8 +- 5 files changed, 730 insertions(+), 56 deletions(-) diff --git a/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml index 66c3332bfd1..b60bc4f4086 100644 --- a/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml +++ b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml @@ -8,26 +8,22 @@ friction="fractureContact0" jumpControl="jFunction" dJumpControl="djFunction" - xTiltAngle="80" tractionControl="tFunction" + yTiltAngle="0" + zTiltAngle="1" steps="10" simultaneous="1" - tolJumpN="1e-15" + tolJumpN="1e-1" tolJumpT="1e-5" - tolNormalTrac="1e2" - iterPenNFac="1" - iterPenTFac="100" + tolNormalTrac="1e-1" + iterPenNFac="10" + iterPenTFac="1" faceArea="1" neighborsVolume="{1,1}" neighborsShear="{1e9,1e9}" neighborsBulk="{1e7,1e7}" output="frictionDriver_Coulomb.txt" /> - - - - - diff --git a/src/coreComponents/constitutive/contact/CoulombFriction.hpp b/src/coreComponents/constitutive/contact/CoulombFriction.hpp index 1ceccd2e7e0..071cbdeb679 100644 --- a/src/coreComponents/constitutive/contact/CoulombFriction.hpp +++ b/src/coreComponents/constitutive/contact/CoulombFriction.hpp @@ -189,13 +189,14 @@ class CoulombFriction : public FrictionBase */ KernelWrapper createKernelUpdates() const; + // TODO (jafranc) make sure it is only helpers for FrictionDriver /// getting cohesion value real64 getCohesion() const - { return m_cohesion; } + { return m_cohesion[0]; } /// getting friction coeff real64 getFrictionCoeff() const - { return m_frictionCoefficient; } + { return m_frictionCoefficient[0]; } /** * @struct Set of "char const *" and keys for data specified in this class. diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp index cd302f7cc30..2d94b7d8e88 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -23,9 +23,516 @@ #include "functions/FunctionManager.hpp" #include "functions/TableFunction.hpp" +#define TEST_PBQ 1 + namespace geos { + namespace LUsolver{ + +bool luDecompose(std::vector& A, int n, std::vector& piv) +{ + piv.resize(n); + for (int i = 0; i < n; ++i) piv[i] = i; + + for (int k = 0; k < n; ++k) + { + // partial pivot: largest |entry| in column k, rows k..n-1 + int p = k; + double maxVal = std::abs(A[k*n + k]); + for (int i = k+1; i < n; ++i) + { + double v = std::abs(A[i*n + k]); + if (v > maxVal) { maxVal = v; p = i; } + } + if (maxVal < 1e-13) return false; // singular / near-singular + + if (p != k) + { + for (int j = 0; j < n; ++j) std::swap(A[k*n+j], A[p*n+j]); + std::swap(piv[k], piv[p]); + } + + for (int i = k+1; i < n; ++i) + { + double factor = A[i*n + k] / A[k*n + k]; + A[i*n + k] = factor; // store multiplier (L entry) + for (int j = k+1; j < n; ++j) + A[i*n + j] -= factor * A[k*n + j]; + } + } + return true; +} + + +// Solve A x = b given the LU-factored A (from luDecompose) and its pivot. +std::vector luSolve(const std::vector& LU, int n, + const std::vector& piv, + const std::vector& b) +{ + std::vector x(n); + for (int i = 0; i < n; ++i) x[i] = b[piv[i]]; // apply permutation + + // forward substitution, L has implicit unit diagonal + for (int i = 0; i < n; ++i) + for (int j = 0; j < i; ++j) + x[i] -= LU[i*n + j] * x[j]; + + // backward substitution + for (int i = n-1; i >= 0; --i) + { + for (int j = i+1; j < n; ++j) + x[i] -= LU[i*n + j] * x[j]; + x[i] /= LU[i*n + i]; + } + return x; +} + +// Convenience: solve a SMALL fixed-size system (used for the 3x3 bubble +// condensation) via the same LU machinery, working on a flat copy. +template +std::array,N> invertSmall(const std::array,N>& M) +{ + std::vector A(N*N); + for (int i=0;i piv; + bool ok = luDecompose(A, N, piv); + if (!ok) std::cerr << "WARNING: singular bubble block!\n"; + + std::array,N> Inv{}; + for (int col=0; col e(N, 0.0); e[col] = 1.0; + std::vector x = luSolve(A, N, piv, e); + for (int row=0; row buildD(double K, double G) + { + array2d D{6,6}; + + D[0][0] = D[1][1] = D[2][2] = K + 4/3*G; + D[0][1] = D[1][0] = D[0][2] = D[2][0] = D[1][2] = D[2][1] = K - 2./3 * G; + D[3][3] = D[4][4] = D[5][5] = G; + + + return D; + } + +void shapeAndGrad(double xi, double eta, double zeta, + std::array& N, + std::array,8>& dNdXi) +{ + for (int a = 0; a < 8; ++a) + { + double xa = refCorners[a][0], ya = refCorners[a][1], za = refCorners[a][2]; + N[a] = 0.125 * (1+xa*xi) * (1+ya*eta) * (1+za*zeta); + dNdXi[a][0] = 0.125 * xa * (1+ya*eta) * (1+za*zeta); + dNdXi[a][1] = 0.125 * (1+xa*xi) * ya * (1+za*zeta); + dNdXi[a][2] = 0.125 * (1+xa*xi) * (1+ya*eta) * za; + } +} + +// Face bubble (Frigo Eq. 20a) for the face at xi_j = sign, on an axis-aligned +// hex. faceAxis in {0,1,2} = which parent coordinate is pinned to the face; +// faceSign = +1 or -1. +void bubbleAndGrad(double xi, double eta, double zeta, + int faceAxis, double faceSign, + double& b, array1d& dbdXi) +{ + std::array c{xi, eta, zeta}; + double linear = 0.5 * (1.0 + faceSign * c[faceAxis]); + double dlinear = 0.5 * faceSign; // wrt c[faceAxis] + + // product of (1 - c_i^2) over the two axes orthogonal to faceAxis + std::array other; + { int k=0; for (int i=0;i<3;++i) if (i!=faceAxis) other[k++]=i; } + + double q0 = 1.0 - c[other[0]]*c[other[0]]; + double q1 = 1.0 - c[other[1]]*c[other[1]]; + + b = linear * q0 * q1; + + array1d grad{}; + grad[faceAxis] = dlinear * q0 * q1; + grad[other[0]] = linear * (-2.0 * c[other[0]]) * q1; + grad[other[1]] = linear * q0 * (-2.0 * c[other[1]]); + dbdXi = grad;//[1x3] +} + +// Voigt B-column for a generic scalar shape function's physical gradient +array2d bColumn(double dNdx, double dNdy, double dNdz) +{ + array2d Bc{6,3}; Bc.zero(); + // Bc.resize(6,3); + + Bc(0,0)=dNdx; Bc(1,1)=dNdy; Bc(2,2)=dNdz; + Bc(3,1)=dNdz; Bc(3,2)=dNdy; + Bc(4,0)=dNdz; Bc(4,2)=dNdx; + Bc(5,0)=dNdy; Bc(5,1)=dNdx; + return Bc; +} + +LocalBlocks integrateElement(const array2d& D, const HexElem& e) +{ + LocalBlocks L; + L.Kuu.zero(); L.Kub.zero(); L.Kbb.zero(); + + const double scale = 2.0; // dPhysical/dParent for unit-length edges + const double detJ = 1.0/8.0; + const double w = 1.0; + + for (const auto& gpt : gaussPts) + { + double xi=gpt[0], eta=gpt[1], zeta=gpt[2]; + std::array N; + std::array,8> dNdXi; + shapeAndGrad(xi, eta, zeta, N, dNdXi);//TODO use GEOS's function as in H1_TriangleFace_Lagrange1_Gauss.hpp + array2d mat(3,3); mat.zero(); + array2d mat36(6,3); mat36.zero(); + + array2d Ba[8]; + // L.Kuu.resize(L.nnodes,L.nnodes); + // L.Kbb.resize(L.ncenters,L.ncenters); + // L.Kub.resize(L.nnodes,L.ncenters); + + for (int a=0;a<8;++a){ + Ba[a].resize(6,3); + Ba[a] = bColumn(dNdXi[a][0]*scale, dNdXi[a][1]*scale, dNdXi[a][2]*scale);} + + for (int a=0;a<8;++a) + for (int b=0;b<8;++b){ + // L.Kuu.block<3,3>(3*a,3*b) += gaussW*detJ * (Ba[a].transpose()*D*Ba[b]); + mat.zero(); + #if TEST_PBQ + LvArray::tensorOps::Rij_eq_PkiBklQlj<6,3>(mat,Ba[a],D,Ba[b]); + #else + mat36.zero(); + LvArray::tensorOps::Rij_eq_AkiBkj<3,6,6>(mat36, Ba[a],D); + LvArray::tensorOps::Rij_eq_AikBkj<3,3,6>(mat,mat36,Ba[b]); + #endif + LvArray::tensorOps::scale<3,3>(mat, w*gaussW*detJ); + for (int i=0; i<3; ++i) + for (int j=0; j<3; ++j) + L.Kuu[3*a + i][3*b + j ]+=mat[i][j]; + } + + if (e.hasBubble) + { + double bub; array1d dbdXi; + bubbleAndGrad(xi,eta,zeta, e.bubbleFaceAxis, e.bubbleFaceSign, bub, dbdXi); + auto Bb = bColumn(dbdXi[0]*scale, dbdXi[1]*scale, dbdXi[2]*scale); + + for (int a=0;a<8;++a){ + // L.Kub.block<3,3>(3*a,0) += gaussW*detJ * (Ba[a].transpose()*D*Bb); + mat.zero(); + #if TEST_PBQ + LvArray::tensorOps::Rij_eq_PkiBklQlj<6,3>(mat,Ba[a],D,Bb); + #else + mat36.zero(); + LvArray::tensorOps::Rij_eq_AkiBkj<3,6,6>(mat36, Ba[a],D); + LvArray::tensorOps::Rij_eq_AikBkj<3,3,6>(mat,mat36,Bb); + #endif + LvArray::tensorOps::scale<3,3>(mat, w*gaussW*detJ); + for (int i=0; i<3; ++i) + for (int j=0; j<3; ++j) + L.Kuu[3*a + i][ j ]+=mat[i][j]; + } + + + + // L.Kbb += gaussW*detJ * (Bb.transpose()*D*Bb); + mat.zero(); + #if TEST_PBQ + LvArray::tensorOps::Rij_eq_PkiBklPlj<6,3>(mat,Bb,D); + #else + mat36.zero(); + LvArray::tensorOps::Rij_eq_AkiBkj<3,6,6>(mat36, Bb,D); + LvArray::tensorOps::Rij_eq_AikBkj<3,3,6>(mat,mat36,Bb); + #endif + LvArray::tensorOps::scale<3,3>(mat, w*gaussW*detJ); + LvArray::tensorOps::add<3,3>(L.Kbb, mat); + } + } + return L; +} + +// Kcond = Kuu - Kub * Kbb^-1 * Kub^T (3x3 inverse via our own LU, small enough +// that we go through the same generic solver rather than a closed form) +array2d condense(const LocalBlocks& L) +{ + // std::vector Kbb3(9); + // for (int i=0;i<3;++i) for (int j=0;j<3;++j) Kbb3[i*3+j] = L.Kbb(i,j); + // std::vector piv; + // luDecompose(Kbb3, 3, piv); + + array2d KbbInv(3,3); + LvArray::tensorOps::invert(KbbInv, L.Kbb); + // for (int col=0; col<3; ++col) + // { + // std::vector e(3,0.0); e[col]=1.0; + // auto x = luSolve(Kbb3, 3, piv, e); + // for (int row=0; row<3; ++row) KbbInv(row,col) = x[row]; + // } + + array2d Kcond(24,24), mat(24,24), mat243(24,3); + LvArray::tensorOps::copy(Kcond,L.Kuu); + // Eigen::Matrix Kcond = L.Kuu - L.Kub * KbbInv * L.Kub.transpose(); + //TODO (test - test - test) + #if TEST_PBQ + LvArray::tensorOps::Rij_eq_PkiBklPlj(mat,L.Kub,KbbInv); + LvArray::tensorOps::scaledAdd(Kcond,mat,-1); + #else// main road + LvArray::tensorOps::Rij_eq_AikBkj(mat243, L.Kub, KbbInv); + LvArray::tensorOps::Rij_eq_AikBkj(mat,mat243,L.Kub); + LvArray::tensorOps::scaledAdd(Kcond,mat,-1); + #endif + + // for (int r=0;r<24;++r) + // for (int c=0;c<24;++c) + // { + // double s=0.0; + // for (int k1=0;k1<3;++k1) + // for (int k2=0;k2<3;++k2) + // s += L.Kub(r,k1)*KbbInv(k1,k2)*L.Kub(c,k2); + // Kcond(r,c) = L.Kuu(r,c) - s; + // } + return Kcond; +} + +CRSMat assemble(const array2d& D) +{ + HexElem elemA, elemB; + elemA.x0=0; elemA.y0=0; elemA.z0=0; + elemA.node = {0,1,2,3,4,5,6,7}; + elemA.hasBubble = true; elemA.bubbleId = 0; + elemA.bubbleFaceAxis = 0; elemA.bubbleFaceSign = +1.0; // xi=+1 face -> x=1 + + elemB.x0=1; elemB.y0=0; elemB.z0=0; + elemB.node = {8,9,10,11,12,13,14,15}; + elemB.hasBubble = true; elemB.bubbleId = 1; + elemB.bubbleFaceAxis = 0; elemB.bubbleFaceSign = -1.0; // xi=-1 face -> x=1 + + const int nNodes = 16, nDof = nNodes*3; + + // ---------------- assemble & condense each element --------------- + // Eigen::Matrix KcondA = assembleCondensed(elemA); + // Eigen::Matrix KcondB = assembleCondensed(elemB); + array2d KcondA = mimicAssembly::condense(integrateElement(D,elemA)); + array2d KcondB = mimicAssembly::condense(integrateElement(D,elemB)); + + // ---------------- GEOS-style two-phase CRSMatrix assembly ---------------- + // Phase 1 (symbolic): reserve every (row,col) pair that will ever be + // written -- elastic pairs from both elements, PLUS the 4x4 cross-face + // contact coupling pairs (needed even though epsN only activates them + // conditionally, since CRSMatrix pre-allocates its sparsity). + CRSMat Kelastic; + Kelastic.resize(nDof, nDof, 24); // generous initial row capacity + + auto elemDofs = [&](const HexElem& e) + { + std::array dofs; + for (int a=0;a<8;++a) for (int c=0;c<3;++c) dofs[3*a+c] = 3*e.node[a]+c; + return dofs; + }; + auto dofsA = elemDofs(elemA); + auto dofsB = elemDofs(elemB); + + for (auto row : dofsA) for (auto col : dofsA) Kelastic.insertNonZero(row, col, 0.0); + for (auto row : dofsB) for (auto col : dofsB) Kelastic.insertNonZero(row, col, 0.0); + + + // NOTE: the contact tangent (state-dependent, rebuilt every Newton + // iteration) is deliberately NOT part of Kelastic's sparsity -- it's a + // tiny 8x8 dense coupling added directly to the dense Jacobian buffer + // each iteration (see solveStep). Kelastic only ever holds the constant + // elastic operator. + + // Phase 2 helper (numeric): accumulate the CONSTANT elastic contribution + // via addToRow -- exactly the GEOS kernel pattern (columns must be sorted + // per row, which our simple 8-node connectivity already is after a sort). + auto scatterElastic = [&](const std::array& dofs, const array2d& Kc) + { + for (int a=0;a<24;++a) + { + std::vector cols(dofs.begin(), dofs.end()); + std::vector vals(24); + for (int b=0;b<24;++b) vals[b] = Kc(a,b); + // sort cols and vals together (addToRow requires sorted columns) + std::vector order(24); for (int i=0;i<24;++i) order[i]=i; + std::sort(order.begin(), order.end(), [&](int i,int j){return cols[i] colsSorted(24); std::vector valsSorted(24); + for (int i=0;i<24;++i){ colsSorted[i]=cols[order[i]]; valsSorted[i]=vals[order[i]]; } + Kelastic.addToRow< RAJA::seq_atomic >(dofs[a], colsSorted.data(), valsSorted.data(), 24); + } + }; + scatterElastic(dofsA, KcondA); + scatterElastic(dofsB, KcondB); + + // Kelastic now holds the constant, condensed elastic operator. Each + // Newton iteration below extracts it to a dense buffer and adds the + // state-dependent contact tangent on top -- Kelastic itself is never + // touched again. + + return Kelastic; +}; + +std::vector solveStep(double imposedUx, ContactState& contact, CRSMat const & Kelastic, double epsN, std::function& updateNormalTraction ) + { + //prep -- duplicate (pass element A and B ?) + HexElem elemA, elemB; + elemA.x0=0; elemA.y0=0; elemA.z0=0; + elemA.node = {0,1,2,3,4,5,6,7}; + elemA.hasBubble = true; elemA.bubbleId = 0; + elemA.bubbleFaceAxis = 0; elemA.bubbleFaceSign = +1.0; // xi=+1 face -> x=1 + + elemB.x0=1; elemB.y0=0; elemB.z0=0; + elemB.node = {8,9,10,11,12,13,14,15}; + elemB.hasBubble = true; elemB.bubbleId = 1; + elemB.bubbleFaceAxis = 0; elemB.bubbleFaceSign = -1.0; // xi=-1 face -> x=1 + + // const int nNodes = 16, nDof = nNodes*3; + const auto nDof = Kelastic.numRows(); + // elemA reference corners with xi=+1 are local nodes {1,2,5,6} -> fault face "-" + // elemB reference corners with xi=-1 are local nodes {0,3,4,7} -> fault face "+" + std::array faceLocalMinus = {1,2,5,6}; + std::array faceLocalPlus = {0,3,4,7}; + std::array faceGlobalMinus, faceGlobalPlus; + for (int i=0;i<4;++i) + { + faceGlobalMinus[i] = elemA.node[faceLocalMinus[i]]; + faceGlobalPlus[i] = elemB.node[faceLocalPlus[i]]; + } + std::array,4> faceDofMinus, faceDofPlus; + for (int i=0;i<4;++i) + for (int c=0;i<3;++c) + { + faceDofMinus[i][c] = 3*faceGlobalMinus[i]+c; + faceDofPlus[i][c] = 3*faceGlobalPlus[i]+c; + } + + std::vector u(nDof, 0.0); + double tNold = contact.tN; + const double faceWeight = 1.0/4.0; + + auto denseFromCRS = [&](const CRSMat& M) + { + std::vector A(nDof*nDof, 0.0); + auto view = M.toViewConst(); + for (IndexType row=0; row Kdense = denseFromCRS(Kelastic); + std::vector r(nDof, 0.0); + for (int i=0;i J = Kdense; + if (!trial.open) + { + double kc = faceWeight*epsN/4.0; + for (int i=0;i<4;++i) + for (int j=0;j<4;++j) + for (int a=0;a<3;++a) + for (int b=0;b<3;++b) + { + int pi=faceDofPlus[i][a], pj=faceDofPlus[j][b]; + int mi=faceDofMinus[i][a], mj=faceDofMinus[j][b]; + J[pi*nDof+pj] += kc * fault.nf[a] * fault.nf[b]; + J[pi*nDof+mj] -= kc* fault.nf[a] * fault.nf[b]; + J[mi*nDof+pj] -= kc* fault.nf[a] * fault.nf[b]; + J[mi*nDof+mj] += kc* fault.nf[a] * fault.nf[b]; + } + } + + // BCs + std::array fixedLocal = {0,3,4,7}; + std::array drivenLocal = {1,2,5,6}; + std::vector fixedDofs, drivenDofsX, drivenDofsYZ; + for (int ln : fixedLocal) for (int c=0;c<3;++c) fixedDofs.push_back(3*elemA.node[ln]+c); + for (int ln : drivenLocal) + { + drivenDofsX.push_back(3*elemB.node[ln]+0); + drivenDofsYZ.push_back(3*elemB.node[ln]+1); + drivenDofsYZ.push_back(3*elemB.node[ln]+2); + } + std::vector isFixed(nDof,false); + for (auto d: fixedDofs) isFixed[d]=true; + for (auto d: drivenDofsYZ) isFixed[d]=true; + for (auto d: drivenDofsX) isFixed[d]=true; + + // apply BCs by row/col elimination + std::vector rhs(nDof); + for (int i=0;i piv; + bool ok = LUsolver::luDecompose(J, (int)nDof, piv); + if (!ok) { std::cerr << "singular Jacobian!\n"; break; } + std::vector du = LUsolver::luSolve(J, (int)nDof, piv, rhs); + + double duNorm = 0.0; + for (int i=0;i(); } @@ -117,33 +626,37 @@ void FrictionDriver::postInputInitialization() // Check that the functions exist FunctionManager & functionManager = FunctionManager::getInstance(); - GEOS_ERROR_IF( !functionManager.hasGroup< TableFunction >( m_jumpFunctionName ), - GEOS_FMT( "Jump function with name '{}' not found", m_jumpFunctionName ), - getWrapperDataContext( viewKeyStruct::jumpFunctionString() ) ); + // GEOS_ERROR_IF( !functionManager.hasGroup< TableFunction >( m_jumpFunctionName ), + // GEOS_FMT( "Jump function with name '{}' not found", m_jumpFunctionName ), + // getWrapperDataContext( viewKeyStruct::jumpFunctionString() ) ); GEOS_ERROR_IF( !functionManager.hasGroup< TableFunction >( m_dJumpFunctionName ), GEOS_FMT( "dJump function with name '{}' not found", m_dJumpFunctionName ), getWrapperDataContext( viewKeyStruct::dJumpFunctionString() ) ); - GEOS_ERROR_IF( !functionManager.hasGroup< TableFunction >( m_tractionFunctionName ), - GEOS_FMT( "Traction function with name '{}' not found", m_tractionFunctionName ), - getWrapperDataContext( viewKeyStruct::tractionFunctionString() ) ); + GEOS_ERROR_IF( !functionManager.hasGroup< TableFunction >( m_stressFunctionsNamesR ), + GEOS_FMT( "Stress functions with name '{}' not found", m_stressFunctionsNamesR ), + getWrapperDataContext( viewKeyStruct::stressFunctionRString() ) ); + + GEOS_ERROR_IF( !functionManager.hasGroup< TableFunction >( m_stressFunctionsNamesL ), + GEOS_FMT( "Stress functions with name '{}' not found", m_stressFunctionsNamesL ), + getWrapperDataContext( viewKeyStruct::stressFunctionLString() ) ); string_array columnNames; getColumnNames( columnNames ); integer const numCols = static_cast< integer >(columnNames.size()); // initialize functions - TableFunction & jumpFunction = functionManager.getGroup< TableFunction >( m_jumpFunctionName ); + // TableFunction & jumpFunction = functionManager.getGroup< TableFunction >( m_jumpFunctionName ); TableFunction & dJumpFunction = functionManager.getGroup< TableFunction >( m_dJumpFunctionName ); - TableFunction & tractionFunction = functionManager.getGroup< TableFunction >( m_tractionFunctionName ); + // TableFunction & tractionFunction = functionManager.getGroup< TableFunction >( m_tractionFunctionName ); - jumpFunction.initializeFunction(); + // jumpFunction.initializeFunction(); dJumpFunction.initializeFunction(); - tractionFunction.initializeFunction(); + // tractionFunction.initializeFunction(); - // TODO: Maybe we should take the maximum extent of jumpFunction and tractionFunction - ArrayOfArraysView< real64 > coordinates = jumpFunction.getCoordinates(); + // // TODO: Maybe we should take the maximum extent of jumpFunction and tractionFunction + ArrayOfArraysView< real64 > coordinates = dJumpFunction.getCoordinates(); real64 const minTime = coordinates[0][0]; real64 const maxTime = coordinates[0][coordinates.sizeOfArray( 0 )-1]; @@ -189,9 +702,6 @@ void FrictionDriver::getColumnNames( string_array & columnNames ) const columnNames.emplace_back( "traction,normal" ); columnNames.emplace_back( "traction,tangent1" ); columnNames.emplace_back( "traction,tangent2" ); - columnNames.emplace_back( "displacement jump,normal" ); - columnNames.emplace_back( "displacement jump,tangent1" ); - columnNames.emplace_back( "displacement jump,tangent2" ); columnNames.emplace_back( "delta displacement jump,normal" ); columnNames.emplace_back( "delta displacement jump,tangent1" ); columnNames.emplace_back( "delta displacement jump,tangent2" ); @@ -200,11 +710,16 @@ void FrictionDriver::getColumnNames( string_array & columnNames ) const columnNames.emplace_back( "newtraction,normal" ); columnNames.emplace_back( "newtraction,tangent1" ); columnNames.emplace_back( "newtraction,tangent2" ); + columnNames.emplace_back( "displacement jump,normal" ); + columnNames.emplace_back( "displacement jump,tangent1" ); + columnNames.emplace_back( "displacement jump,tangent2" ); columnNames.emplace_back( "derived disp tol, normal" ); columnNames.emplace_back( "derived disp tol, tangent" ); columnNames.emplace_back( "derived traction tol, normal" ); columnNames.emplace_back( "iterative penalty, normal" ); columnNames.emplace_back( "iterative penalty, tangent" ); + columnNames.emplace_back( "iteration" ); + if( dynamic_cast< CoulombFriction const * >(&getFriction()) != nullptr ) { @@ -217,9 +732,22 @@ void FrictionDriver::initializeTable() integer const numRows = m_table.size( 0 ); FunctionManager & functionManager = FunctionManager::getInstance(); - TableFunction const & jumpFunction = functionManager.getGroup< TableFunction >( m_jumpFunctionName ); + // TableFunction const & jumpFunction = functionManager.getGroup< TableFunction >( m_jumpFunctionName ); TableFunction const & dJumpFunction = functionManager.getGroup< TableFunction >( m_dJumpFunctionName ); - TableFunction const & tractionFunction = functionManager.getGroup< TableFunction >( m_tractionFunctionName ); + + TableFunction const & tractionFunctionR00 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//should be Voigt full from stress + TableFunction const & tractionFunctionR11 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//1 + TableFunction const & tractionFunctionR22 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//2 + TableFunction const & tractionFunctionR21 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//3 + TableFunction const & tractionFunctionR02 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//4 + TableFunction const & tractionFunctionR01 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//5 + // + TableFunction const & tractionFunctionL00 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); + TableFunction const & tractionFunctionL11 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); + TableFunction const & tractionFunctionL22 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); + TableFunction const & tractionFunctionL21 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); + TableFunction const & tractionFunctionL02 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); + TableFunction const & tractionFunctionL01 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); real64 const cos_theta = cos( m_theta * M_PI/180.0 ); real64 const sin_theta = sin( m_theta * M_PI/180.0 ); @@ -231,15 +759,47 @@ void FrictionDriver::initializeTable() { real64 const time = m_table( index, TIME ); - real64 const traction = tractionFunction.evaluate( &time ); - m_table( index, NTRAC ) = traction*cos_phi*cos_theta; - m_table( index, STRAC0 ) = traction*cos_theta*sin_phi; - m_table( index, STRAC1 ) = -traction*sin_theta; + real64 const leftStress[6]{ tractionFunctionR00.evaluate(&time), + tractionFunctionR11.evaluate(&time), + tractionFunctionR22.evaluate(&time), + tractionFunctionR21.evaluate(&time), + tractionFunctionR02.evaluate(&time), + tractionFunctionR01.evaluate(&time), + };//should be full 6-Voigt + + real64 const rightStress[6]{ tractionFunctionL00.evaluate(&time), + tractionFunctionL11.evaluate(&time), + tractionFunctionL22.evaluate(&time), + tractionFunctionL21.evaluate(&time), + tractionFunctionL02.evaluate(&time), + tractionFunctionL01.evaluate(&time), + };//should be full 6-Voigt + + real64 const n[3]{cos_theta,sin_theta*sin_phi,-cos_theta*sin_phi}; + + //rotate and project stress + for(const auto& sigma : {leftStress, rightStress }){ + + constexpr real64 NCELLS = 2.0; + + const real64 sigman[3]{ + sigma[0]*n[0]+sigma[5]*n[1]+sigma[4]*n[2], + sigma[5]*n[0]+sigma[1]*n[1]+sigma[3]*n[2], + sigma[4]*n[0]+sigma[3]*n[1]+sigma[2]*n[2], + }; + + m_table( index, NTRAC ) += 1./NCELLS*(sigman[0]*cos_phi + sigman[1]*sin_phi*sin_theta + sigman[2]*cos_theta*sin_phi); + m_table( index, STRAC0 ) += 1./NCELLS*(sigman[1]*cos_theta - sigman[2]*sin_theta); + m_table( index, STRAC1 ) += 1./NCELLS*(-sigman[0]*sin_phi + sigman[1]*sin_theta*cos_phi + sigman[2]*cos_theta*cos_phi); + + } - real64 const jump = jumpFunction.evaluate( &time ); - m_table( index, NJUMP ) = jump*cos_phi*cos_theta; - m_table( index, SLIP0 ) = jump*cos_theta*sin_phi; - m_table( index, SLIP1 ) = jump*sin_theta; + //Project and average Left and Right stress + //jump = tLocal/(kn kt) + // real64 const jump = jumpFunction.evaluate( &time ); + // m_table( index, NJUMP ) = m_table( index, NTRAC )/m_iterPenNFac;//might need compute tol --> move to evaluation part + // m_table( index, SLIP0 ) = m_table( index, STRAC0 )/m_iterPenTFac; + // m_table( index, SLIP1 ) = m_table( index, STRAC1 )/m_iterPenTFac; real64 const dJump = dJumpFunction.evaluate( &time ); m_table( index, NDJUMP ) = dJump*cos_phi*cos_theta; diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp index 46bd7325970..414e8ad5ec1 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -16,6 +16,7 @@ #ifndef GEOS_CONSTITUTIVEDRIVERS_CONTACT_FRICTIONDRIVER_HPP #define GEOS_CONSTITUTIVEDRIVERS_CONTACT_FRICTIONDRIVER_HPP + #include "constitutiveDrivers/ConstitutiveDriver.hpp" #include "physicsSolvers/solidMechanics/contact/ContactSolverBase.hpp" // #include "physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.hpp" @@ -27,6 +28,113 @@ namespace constitutive class FrictionBase; } +namespace LUsolver{ + +// ============================================================================ +// Minimal dense linear algebra: LU with partial pivoting +// ============================================================================ + +// In-place LU decomposition of an n x n matrix stored row-major in A +// (A is overwritten: U in upper incl. diag, L multipliers below diag, +// unit diagonal for L implied). piv[i] = original row that ended up at row i. +// Returns false if the matrix is (numerically) singular. +bool luDecompose(std::vector& A, int n, std::vector& piv); + + +// Solve A x = b given the LU-factored A (from luDecompose) and its pivot. +std::vector luSolve(const std::vector& LU, int n, + const std::vector& piv, + const std::vector& b); + +// Convenience: solve a SMALL fixed-size system (used for the 3x3 bubble +// condensation) via the same LU machinery, working on a flat copy. +template +std::array,N> invertSmall(const std::array,N>& M); + +} + +namespace mimicAssembly{ + +using IndexType = std::ptrdiff_t; +using CRSMat = CRSMatrix< real64, IndexType, IndexType >; + +array2d buildD(double K, double G); + +// ---------------------------------------------------------------------------- +// Reference hex: trilinear shape functions and their parent-coordinate +// derivatives at (xi, eta, zeta) in [-1,1]^3. Standard node ordering. +// ---------------------------------------------------------------------------- +constexpr std::array,8> refCorners = {{ + {-1,-1,-1},{ 1,-1,-1},{ 1, 1,-1},{-1, 1,-1}, + {-1,-1, 1},{ 1,-1, 1},{ 1, 1, 1},{-1, 1, 1} +}}; + +void shapeAndGrad(double xi, double eta, double zeta, + std::array& N, + std::array,8>& dNdXi); + +// Face bubble (Frigo Eq. 20a) for the face at xi_j = sign, on an axis-aligned +// hex. faceAxis in {0,1,2} = which parent coordinate is pinned to the face; +// faceSign = +1 or -1. +void bubbleAndGrad(double xi, double eta, double zeta, + int faceAxis, double faceSign, + double& b, array1d& dbdXi); + +// 2x2x2 Gauss rule +const double gp = 1.0 / std::sqrt(3.0); +const std::array,8> gaussPts = {{ + {-gp,-gp,-gp},{ gp,-gp,-gp},{ gp, gp,-gp},{-gp, gp,-gp}, + {-gp,-gp, gp},{ gp,-gp, gp},{ gp, gp, gp},{-gp, gp, gp} +}}; +const double gaussW = 1.0; // weight 1 each for 2-pt rule per axis + +// Voigt B-column for a generic scalar shape function's physical gradient +array2d bColumn(double dNdx, double dNdy, double dNdz); + +// ---------------------------------------------------------------------------- +// Element geometry: axis-aligned unit cube, origin = (x0,y0,z0). +// Physical gradient = parent gradient * 2/L (L=1 here) -> factor 2. +// detJ = (L/2)^3 = 1/8. +// ---------------------------------------------------------------------------- +struct HexElem +{ + double x0, y0, z0; // corner with min x,y,z + std::array node; // global node ids + bool hasBubble = false; + int bubbleId = -1; // global bubble block index + int bubbleFaceAxis = 0; // which parent axis the fault face sits on + double bubbleFaceSign = 1.0; +}; + +// Local nodal-nodal (24x24), nodal-bubble (24x3), bubble-bubble (3x3) +struct LocalBlocks +{ + static constexpr int nnodes = 24; + static constexpr int ncenters = 3; + + array2d Kuu{nnodes,nnodes}; + array2d Kub{nnodes,ncenters}; + array2d Kbb{ncenters,ncenters}; +}; + +LocalBlocks integrateElement(const array2d& D, const HexElem& e); + +// Kcond = Kuu - Kub * Kbb^-1 * Kub^T (3x3 inverse via our own LU, small enough +// that we go through the same generic solver rather than a closed form) +array2d condense(const LocalBlocks& L); + +CRSMat assemble(const array2d& D); + +struct ContactState { double tN = 0.0; bool open = true; }; + +std::vector solveStep(double imposedUx, ContactState& contact, CRSMat const & Kelastic, + double epsN, std::function& updateNormalTraction ); + +} + + + + class FrictionDriver : public ConstitutiveDriver { public: @@ -67,14 +175,17 @@ class FrictionDriver : public ConstitutiveDriver constexpr static char const * contactNameString() { return "contact"; } - constexpr static char const * jumpFunctionString() - { return "jumpControl"; } + // constexpr static char const * jumpFunctionString() + // { return "jumpControl"; } constexpr static char const * dJumpFunctionString() { return "dJumpControl"; } - constexpr static char const * tractionFunctionString() - { return "tractionControl"; } + constexpr static char const * stressFunctionRString() + { return "stressControlsR"; } + + constexpr static char const * stressFunctionLString() + { return "stressControlsL"; } constexpr static char const * thetaString() { return "yTiltAngle";} @@ -113,18 +224,20 @@ class FrictionDriver : public ConstitutiveDriver constexpr static char const * simultaneous() { return "simultaneous"; } - }; // Time is defined in base class - enum columnKeys { NTRAC=1, STRAC0, STRAC1, NJUMP, SLIP0, SLIP1, NDJUMP, DSLIP0, DSLIP1, CC, FS, + enum columnKeys { NTRAC=1, STRAC0, STRAC1, NDJUMP, DSLIP0, DSLIP1, CC, FS, NEWTRAC, SNEWTRAC0, SNEWTRAC1, + NJUMP, SLIP0, SLIP1, NTOL, TTOL, NTRACTOL, - ITERPEN0, ITERPEN1, TLIM }; + ITERPEN0, ITERPEN1, TLIM, + ITER }; - string m_jumpFunctionName; ///< + // string m_jumpFunctionName; ///< string m_dJumpFunctionName; ///< - string m_tractionFunctionName; ///< + string m_stressFunctionsNamesR; ///< + string m_stressFunctionsNamesL; ///< real64 m_theta{0.0}; ///< x-tilt of fault real64 m_phi{0.0}; ///< y-tilt of fault diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp index 0cd17976183..38a3f0d038c 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp @@ -89,11 +89,14 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, djump[0][2] = table( ei, DSLIP1 ); + + traction[0][0] = table( ei, NTRAC ); traction[0][1] = table( ei, STRAC0 ); traction[0][2] = table( ei, STRAC1 ); - kernelWrapper.updateFractureState( jump[0], + kernelWrapper.updateFractureState( 0, + jump[0], traction[0], fractureState[0] ); @@ -146,7 +149,8 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, traction.toView() ); - kernelWrapper.updateFractureState( jump[0], + kernelWrapper.updateFractureState( 0, + jump[0], newTraction[0], fractureState[0] ); From 2cf8550d38c672460db53dc9d815c3cf29306ef3 Mon Sep 17 00:00:00 2001 From: jacques franc Date: Wed, 19 Aug 2026 18:17:54 +0200 Subject: [PATCH 23/25] with rotation --- .../contact/FrictionDriver.cpp | 158 +++++++++++++----- .../contact/FrictionDriver.hpp | 12 +- 2 files changed, 128 insertions(+), 42 deletions(-) diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp index 2d94b7d8e88..550e710cd5e 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -159,7 +159,7 @@ void bubbleAndGrad(double xi, double eta, double zeta, b = linear * q0 * q1; - array1d grad{}; + array1d grad{3}; grad[faceAxis] = dlinear * q0 * q1; grad[other[0]] = linear * (-2.0 * c[other[0]]) * q1; grad[other[1]] = linear * q0 * (-2.0 * c[other[1]]); @@ -179,13 +179,25 @@ array2d bColumn(double dNdx, double dNdy, double dNdz) return Bc; } +array2d computeJacobian(const std::array,8>& coords, + const std::array,8>& dNdXi) +{ + array2d J{3,3}; J.zero(); + for (int a=0;a<8;++a) + { + array1d dN{3}; dN[0] = dNdXi[a][0]; dN[1] = dNdXi[a][1]; dN[2] = dNdXi[a][2]; + LvArray::tensorOps::Rij_add_AiBj< 3, 3 >( J, coords[a], dN ); // J += coords[a] (x) dNdXi[a] + } + return J; +} + + LocalBlocks integrateElement(const array2d& D, const HexElem& e) { LocalBlocks L; L.Kuu.zero(); L.Kub.zero(); L.Kbb.zero(); - const double scale = 2.0; // dPhysical/dParent for unit-length edges - const double detJ = 1.0/8.0; + double detJ = 0.; const double w = 1.0; for (const auto& gpt : gaussPts) @@ -194,17 +206,25 @@ LocalBlocks integrateElement(const array2d& D, const HexElem& e) std::array N; std::array,8> dNdXi; shapeAndGrad(xi, eta, zeta, N, dNdXi);//TODO use GEOS's function as in H1_TriangleFace_Lagrange1_Gauss.hpp + array2d mat(3,3); mat.zero(); array2d mat36(6,3); mat36.zero(); - array2d Ba[8]; // L.Kuu.resize(L.nnodes,L.nnodes); // L.Kbb.resize(L.ncenters,L.ncenters); // L.Kub.resize(L.nnodes,L.ncenters); + array2d J = computeJacobian(e.coords, dNdXi), invJ{3,3}; + detJ = LvArray::tensorOps::invert<3>(invJ,J); + for (int a=0;a<8;++a){ Ba[a].resize(6,3); - Ba[a] = bColumn(dNdXi[a][0]*scale, dNdXi[a][1]*scale, dNdXi[a][2]*scale);} + array1d g{3}; + array1d dN{3}; + dN[0] = dNdXi[a][0]; dN[1] = dNdXi[a][1]; dN[2] = dNdXi[a][2]; + LvArray::tensorOps::Ri_eq_AijBj<3,3>(g, invJ, dN); + Ba[a] = bColumn(g[0],g[1],g[2]); + } for (int a=0;a<8;++a) for (int b=0;b<8;++b){ @@ -220,14 +240,18 @@ LocalBlocks integrateElement(const array2d& D, const HexElem& e) LvArray::tensorOps::scale<3,3>(mat, w*gaussW*detJ); for (int i=0; i<3; ++i) for (int j=0; j<3; ++j) - L.Kuu[3*a + i][3*b + j ]+=mat[i][j]; + L.Kuu[3*a + i][3*b + j ] += mat[i][j]; } if (e.hasBubble) { double bub; array1d dbdXi; bubbleAndGrad(xi,eta,zeta, e.bubbleFaceAxis, e.bubbleFaceSign, bub, dbdXi); - auto Bb = bColumn(dbdXi[0]*scale, dbdXi[1]*scale, dbdXi[2]*scale); + array1d gb{3}; + array1d db{3}; + db[0] = dbdXi[0]; db[1] = dbdXi[1]; db[2] = dbdXi[2]; + LvArray::tensorOps::Ri_eq_AjiBj<3,3>(gb, invJ, db); + auto Bb = bColumn(gb[0],gb[1],gb[2]); for (int a=0;a<8;++a){ // L.Kub.block<3,3>(3*a,0) += gaussW*detJ * (Ba[a].transpose()*D*Bb); @@ -242,7 +266,7 @@ LocalBlocks integrateElement(const array2d& D, const HexElem& e) LvArray::tensorOps::scale<3,3>(mat, w*gaussW*detJ); for (int i=0; i<3; ++i) for (int j=0; j<3; ++j) - L.Kuu[3*a + i][ j ]+=mat[i][j]; + L.Kuu[3*a + i][ j ] += mat[i][j]; } @@ -284,14 +308,14 @@ array2d condense(const LocalBlocks& L) array2d Kcond(24,24), mat(24,24), mat243(24,3); LvArray::tensorOps::copy(Kcond,L.Kuu); // Eigen::Matrix Kcond = L.Kuu - L.Kub * KbbInv * L.Kub.transpose(); - //TODO (test - test - test) + //TODO (recheck formula) #if TEST_PBQ - LvArray::tensorOps::Rij_eq_PkiBklPlj(mat,L.Kub,KbbInv); - LvArray::tensorOps::scaledAdd(Kcond,mat,-1); + LvArray::tensorOps::Rij_eq_PikBklQjl(mat, L.Kub, KbbInv, L.Kub); + LvArray::tensorOps::scaledAdd(Kcond, mat, -1); #else// main road LvArray::tensorOps::Rij_eq_AikBkj(mat243, L.Kub, KbbInv); - LvArray::tensorOps::Rij_eq_AikBkj(mat,mat243,L.Kub); - LvArray::tensorOps::scaledAdd(Kcond,mat,-1); + LvArray::tensorOps::Rij_eq_AikBjk(mat, mat243, L.Kub); + LvArray::tensorOps::scaledAdd(Kcond, mat, -1); #endif // for (int r=0;r<24;++r) @@ -306,19 +330,12 @@ array2d condense(const LocalBlocks& L) return Kcond; } -CRSMat assemble(const array2d& D) +CRSMat assemble(const array2d& D, const ContactState& contact) { + array2d R{3,3}; HexElem elemA, elemB; - elemA.x0=0; elemA.y0=0; elemA.z0=0; - elemA.node = {0,1,2,3,4,5,6,7}; - elemA.hasBubble = true; elemA.bubbleId = 0; - elemA.bubbleFaceAxis = 0; elemA.bubbleFaceSign = +1.0; // xi=+1 face -> x=1 - - elemB.x0=1; elemB.y0=0; elemB.z0=0; - elemB.node = {8,9,10,11,12,13,14,15}; - elemB.hasBubble = true; elemB.bubbleId = 1; - elemB.bubbleFaceAxis = 0; elemB.bubbleFaceSign = -1.0; // xi=-1 face -> x=1 - + setElement(contact, elemA,elemB,R); + const int nNodes = 16, nDof = nNodes*3; // ---------------- assemble & condense each element --------------- @@ -383,19 +400,79 @@ CRSMat assemble(const array2d& D) return Kelastic; }; -std::vector solveStep(double imposedUx, ContactState& contact, CRSMat const & Kelastic, double epsN, std::function& updateNormalTraction ) - { - //prep -- duplicate (pass element A and B ?) - HexElem elemA, elemB; - elemA.x0=0; elemA.y0=0; elemA.z0=0; +void setElement(const ContactState& contact, HexElem& elemA, HexElem& elemB, array2d& RR ) +{ + // elemA.x0=0; elemA.y0=0; elemA.z0=0; elemA.node = {0,1,2,3,4,5,6,7}; elemA.hasBubble = true; elemA.bubbleId = 0; elemA.bubbleFaceAxis = 0; elemA.bubbleFaceSign = +1.0; // xi=+1 face -> x=1 - elemB.x0=1; elemB.y0=0; elemB.z0=0; + // elemB.x0=1; elemB.y0=0; elemB.z0=0; elemB.node = {8,9,10,11,12,13,14,15}; elemB.hasBubble = true; elemB.bubbleId = 1; elemB.bubbleFaceAxis = 0; elemB.bubbleFaceSign = -1.0; // xi=-1 face -> x=1 + + + //rotations and geometry + auto rotZ = [](double a){ array2d R; R.zero(); R[0][0]=cos(a);R[0][1]=-sin(a);R[0][2]=0; + R[1][0]=sin(a);R[1][1]=cos(a); R[1][2]=0; + R[2][0]=0; R[2][1]=0; R[2][2]=1; return R; }; + auto rotY = [](double a){ array2d R; R.zero(); R[0][0]=cos(a); R[0][1]=0;R[0][2]=sin(a); + R[1][0]=0; R[1][1]=1;R[1][2]=0; + R[2][0]=-sin(a);R[2][1]=0;R[2][2]=cos(a); return R; }; + + + //setters + LvArray::tensorOps::Rij_eq_AikBkj<3,3,3>(RR,rotY(contact.theta),rotZ(contact.phi)); + auto unitCubeCorner = [&](array1d origin, int localIndex) + { + array1d c; c.zero(); + c[0] = origin[0] + 0.5*(1+refCorners[localIndex][0]); + c[1] = origin[1] + 0.5*(1+refCorners[localIndex][1]); + c[2] = origin[2] + 0.5*(1+refCorners[localIndex][2]); + array1d res{3}; + LvArray::tensorOps::Ri_eq_AijBj<3,3>(res, RR, c); + return res; + }; + + array1d e0, e1; + e0.zero(); e1.zero(); e1[0] = 1.; + for (int a=0;a<8;++a) elemA.coords[a] = unitCubeCorner(e0, a); + for (int a=0;a<8;++a) elemB.coords[a] = unitCubeCorner(e1, a); + +} + +std::vector solveStep(double imposedUx, ContactState& contact, CRSMat const & Kelastic, double epsN, std::function& updateNormalTraction ) + { + //prep -- duplicate (pass element A and B ?) + HexElem elemA, elemB; + array2d R{3,3}; + setElement(contact, elemA,elemB, R); + + // ---------------- fault normal DERIVED from geometry -------------------- + // Two edge vectors of the (planar, quad) fault face, physical corners + // taken directly from elemA's rotated coordinates -- no assumption + // about which global axis the fault points along. + array1d nf{3}; nf[0] = R[0][0]; nf[1] = R[1][0]; nf[2] = R[2][0]; + + // Orient outward from "-" element into "+" element: check against the + // vector between element centroids and flip if pointing the wrong way. + array1d centroidA, centroidB; + centroidA.zero(); centroidB.zero(); + for (int a=0;a<8;++a) + for (int c=0;c<3;++c) + { centroidA[c]+=elemA.coords[a][c]/8.0; centroidB[c]+=elemB.coords[a][c]/8.0; } + + array1d aToB{3}; aToB.zero(); + aToB[0] = centroidB[0]-centroidA[0]; aToB[1] = centroidB[1]-centroidA[1]; aToB[2] = centroidB[2]-centroidA[2]; + + if (LvArray::tensorOps::AiBi<3>(nf, aToB) < 0.0) { LvArray::tensorOps::scale<3>(nf,-1); } + + std::cout << std::fixed << std::setprecision(6); + std::cout << "Derived fault normal: (" << nf[0] << ", " << nf[1] << ", " << nf[2] << ")\n" + << "Expected (rotated x-axis): (" << R[0][0] << ", " << R[1][0] << ", " << R[2][0] << ")\n\n"; + + // const int nNodes = 16, nDof = nNodes*3; const auto nDof = Kelastic.numRows(); @@ -438,7 +515,7 @@ std::vector solveStep(double imposedUx, ContactState& contact, CRSMat co { double jumpAvg[3] = {0.,0.,0.}; for (int i=0;i<4;++i) for(int c=0; c<3; ++c) jumpAvg[c] += (u[faceDofPlus[i][c]] - u[faceDofMinus[i][c]])/4; - double gN = LvArray::tensorOps::AiBi(jumpAvg,fault.nf); + double gN = LvArray::tensorOps::AiBi<3>(jumpAvg,nf); ContactState trial = updateNormalTraction(tNold, gN, epsN); @@ -455,10 +532,12 @@ std::vector solveStep(double imposedUx, ContactState& contact, CRSMat co for (int j=0;j solveStep(double imposedUx, ContactState& contact, CRSMat co { int pi=faceDofPlus[i][a], pj=faceDofPlus[j][b]; int mi=faceDofMinus[i][a], mj=faceDofMinus[j][b]; - J[pi*nDof+pj] += kc * fault.nf[a] * fault.nf[b]; - J[pi*nDof+mj] -= kc* fault.nf[a] * fault.nf[b]; - J[mi*nDof+pj] -= kc* fault.nf[a] * fault.nf[b]; - J[mi*nDof+mj] += kc* fault.nf[a] * fault.nf[b]; + J[pi*nDof+pj] += kc * nf[a] * nf[b]; + J[pi*nDof+mj] -= kc* nf[a] * nf[b]; + J[mi*nDof+pj] -= kc* nf[a] * nf[b]; + J[mi*nDof+mj] += kc* nf[a] * nf[b]; } } @@ -484,7 +563,10 @@ std::vector solveStep(double imposedUx, ContactState& contact, CRSMat co std::array fixedLocal = {0,3,4,7}; std::array drivenLocal = {1,2,5,6}; std::vector fixedDofs, drivenDofsX, drivenDofsYZ; - for (int ln : fixedLocal) for (int c=0;c<3;++c) fixedDofs.push_back(3*elemA.node[ln]+c); + for (int ln : fixedLocal) + for(int c=0;c<3;++c) + fixedDofs.push_back(3*elemA.node[ln]+c); + for (int ln : drivenLocal) { drivenDofsX.push_back(3*elemB.node[ln]+0); diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp index 414e8ad5ec1..33581777320 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -90,7 +90,8 @@ const double gaussW = 1.0; // weight 1 each for 2-pt rule per axis // Voigt B-column for a generic scalar shape function's physical gradient array2d bColumn(double dNdx, double dNdy, double dNdz); - +array2d computeJacobian(const std::array,8>& coords, + const std::array,8>& dNdXi); // ---------------------------------------------------------------------------- // Element geometry: axis-aligned unit cube, origin = (x0,y0,z0). // Physical gradient = parent gradient * 2/L (L=1 here) -> factor 2. @@ -98,7 +99,10 @@ array2d bColumn(double dNdx, double dNdy, double dNdz); // ---------------------------------------------------------------------------- struct HexElem { - double x0, y0, z0; // corner with min x,y,z + // double x0, y0, z0; // corner with min x,y,z + std::array,8> coords; // PHYSICAL corner coordinates (arbitrary, + // not assumed axis-aligned or unit-length) + std::array node; // global node ids bool hasBubble = false; int bubbleId = -1; // global bubble block index @@ -118,14 +122,14 @@ struct LocalBlocks }; LocalBlocks integrateElement(const array2d& D, const HexElem& e); - +struct ContactState { double tN = 0.0; bool open = true; double theta = 0.; double phi = 0.; }; +void setElement(const ContactState& contact, HexElem& elemA, HexElem& elemB, array2d& RR ); // Kcond = Kuu - Kub * Kbb^-1 * Kub^T (3x3 inverse via our own LU, small enough // that we go through the same generic solver rather than a closed form) array2d condense(const LocalBlocks& L); CRSMat assemble(const array2d& D); -struct ContactState { double tN = 0.0; bool open = true; }; std::vector solveStep(double imposedUx, ContactState& contact, CRSMat const & Kelastic, double epsN, std::function& updateNormalTraction ); From b48d6619ca850c24d837b91ea64debb1926c0e21 Mon Sep 17 00:00:00 2001 From: jacques franc Date: Fri, 21 Aug 2026 15:48:56 +0200 Subject: [PATCH 24/25] testing --- .../friction/frictionDriver_Coulomb.xml | 9 +- .../friction/frictionDriver_base.xml | 15 ++- .../friction/tables/constant.geos | 6 + .../contact/FrictionDriver.cpp | 93 +++++++++----- .../contact/FrictionDriver.hpp | 42 ++++-- .../contact/FrictionDriverRunTest.hpp | 120 ++++++++++++++---- 6 files changed, 201 insertions(+), 84 deletions(-) create mode 100644 inputFiles/constitutiveDriver/friction/tables/constant.geos diff --git a/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml index b60bc4f4086..a24ffec9f26 100644 --- a/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml +++ b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml @@ -6,12 +6,13 @@ + defaultCohesion="0.0e6" + defaultFrictionCoefficient="0.01"/> + defaultCohesion="1.0e6" + defaultFrictionCoefficient="0.01"/> @@ -49,10 +49,15 @@ voxelFile="tables/djumps.geos"/> + diff --git a/inputFiles/constitutiveDriver/friction/tables/constant.geos b/inputFiles/constitutiveDriver/friction/tables/constant.geos new file mode 100644 index 00000000000..2e69888bf68 --- /dev/null +++ b/inputFiles/constitutiveDriver/friction/tables/constant.geos @@ -0,0 +1,6 @@ +1e2 +1e2 +1e2 +1e2 +1e2 +1e2 diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp index 550e710cd5e..96473aebeee 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -23,7 +23,7 @@ #include "functions/FunctionManager.hpp" #include "functions/TableFunction.hpp" -#define TEST_PBQ 1 +#define TEST_PBQ 0 namespace geos { @@ -442,8 +442,9 @@ void setElement(const ContactState& contact, HexElem& elemA, HexElem& elemB, arr } -std::vector solveStep(double imposedUx, ContactState& contact, CRSMat const & Kelastic, double epsN, std::function& updateNormalTraction ) +std::vector solveStep(double imposedUx, ContactState& contact, CRSMat const & Kelastic, double epsN, std::function& updateNormalTraction ) { + std::vector results; //prep -- duplicate (pass element A and B ?) HexElem elemA, elemB; array2d R{3,3}; @@ -488,7 +489,7 @@ std::vector solveStep(double imposedUx, ContactState& contact, CRSMat co } std::array,4> faceDofMinus, faceDofPlus; for (int i=0;i<4;++i) - for (int c=0;i<3;++c) + for (int c=0;c<3;++c) { faceDofMinus[i][c] = 3*faceGlobalMinus[i]+c; faceDofPlus[i][c] = 3*faceGlobalPlus[i]+c; @@ -513,11 +514,15 @@ std::vector solveStep(double imposedUx, ContactState& contact, CRSMat co for (int newtonIt = 0; newtonIt < 20; ++newtonIt) { + ContactState trial; + double gN = 0.; + { double jumpAvg[3] = {0.,0.,0.}; for (int i=0;i<4;++i) for(int c=0; c<3; ++c) jumpAvg[c] += (u[faceDofPlus[i][c]] - u[faceDofMinus[i][c]])/4; - double gN = LvArray::tensorOps::AiBi<3>(jumpAvg,nf); + gN = LvArray::tensorOps::AiBi<3>(jumpAvg,nf); + trial = updateNormalTraction(tNold, gN, epsN); + } - ContactState trial = updateNormalTraction(tNold, gN, epsN); // residual r = K_elastic*u + contact virtual work (tangent is // NOT part of this -- residual uses ONLY the elastic operator, @@ -606,9 +611,19 @@ std::vector solveStep(double imposedUx, ContactState& contact, CRSMat co for (int i=0;i(jumpAvg,nf); + results.emplace_back(u, gN, newtonIt, (std::sqrt(duNorm) < 1e-12)); + break; + } + else{ + results.emplace_back(u, gN, newtonIt, (std::sqrt(duNorm) < 1e-12)); + } } - return u; + + return results; }; };//end mimicAssembly @@ -630,9 +645,9 @@ FrictionDriver::FrictionDriver( const string & name, Group * const parent ) setInputFlag( InputFlags::REQUIRED ). setDescription( "Number of sample step to take in both jumps and traction increments" ); - // registerWrapper( viewKeyStruct::jumpFunctionString(), &m_jumpFunctionName ). - // setInputFlag( InputFlags::REQUIRED ). - // setDescription( "Name of the input function representing jump function along world x-axis" ); + registerWrapper( viewKeyStruct::displacementFunctionString(), &m_dispFunctionName ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Name of the input function representing displacement function along world x-axis" ); registerWrapper( viewKeyStruct::dJumpFunctionString(), &m_dJumpFunctionName ).//should be derive from convergence history setInputFlag( InputFlags::REQUIRED ). @@ -708,9 +723,9 @@ void FrictionDriver::postInputInitialization() // Check that the functions exist FunctionManager & functionManager = FunctionManager::getInstance(); - // GEOS_ERROR_IF( !functionManager.hasGroup< TableFunction >( m_jumpFunctionName ), - // GEOS_FMT( "Jump function with name '{}' not found", m_jumpFunctionName ), - // getWrapperDataContext( viewKeyStruct::jumpFunctionString() ) ); + GEOS_ERROR_IF( !functionManager.hasGroup< TableFunction >( m_dispFunctionName ), + GEOS_FMT( "Jump function with name '{}' not found", m_dispFunctionName ), + getWrapperDataContext( viewKeyStruct::displacementFunctionString() ) ); GEOS_ERROR_IF( !functionManager.hasGroup< TableFunction >( m_dJumpFunctionName ), GEOS_FMT( "dJump function with name '{}' not found", m_dJumpFunctionName ), @@ -729,18 +744,18 @@ void FrictionDriver::postInputInitialization() integer const numCols = static_cast< integer >(columnNames.size()); // initialize functions - // TableFunction & jumpFunction = functionManager.getGroup< TableFunction >( m_jumpFunctionName ); + TableFunction & dispFunction = functionManager.getGroup< TableFunction >( m_dispFunctionName ); TableFunction & dJumpFunction = functionManager.getGroup< TableFunction >( m_dJumpFunctionName ); // TableFunction & tractionFunction = functionManager.getGroup< TableFunction >( m_tractionFunctionName ); - // jumpFunction.initializeFunction(); + dispFunction.initializeFunction(); dJumpFunction.initializeFunction(); // tractionFunction.initializeFunction(); // // TODO: Maybe we should take the maximum extent of jumpFunction and tractionFunction ArrayOfArraysView< real64 > coordinates = dJumpFunction.getCoordinates(); real64 const minTime = coordinates[0][0]; - real64 const maxTime = coordinates[0][coordinates.sizeOfArray( 0 )-1]; + real64 const maxTime = coordinates[0][coordinates.sizeOfArray( 0 )-1] * 20; // Allocate the data allocateTable( numCols, minTime, maxTime ); @@ -800,7 +815,11 @@ void FrictionDriver::getColumnNames( string_array & columnNames ) const columnNames.emplace_back( "derived traction tol, normal" ); columnNames.emplace_back( "iterative penalty, normal" ); columnNames.emplace_back( "iterative penalty, tangent" ); - columnNames.emplace_back( "iteration" ); +columnNames.emplace_back( "mimicAssembly FEM solve, converged normal traction" ); +columnNames.emplace_back( "mimicAssembly FEM solve, converged normal displacement jump" ); +columnNames.emplace_back( "mimicAssembly FEM solve, Newton iteration count" ); +columnNames.emplace_back( "mimicAssembly FEM solve, converged flag (1=converged, 0=not converged)" ); +columnNames.emplace_back( "iteration" ); if( dynamic_cast< CoulombFriction const * >(&getFriction()) != nullptr ) @@ -814,22 +833,22 @@ void FrictionDriver::initializeTable() integer const numRows = m_table.size( 0 ); FunctionManager & functionManager = FunctionManager::getInstance(); - // TableFunction const & jumpFunction = functionManager.getGroup< TableFunction >( m_jumpFunctionName ); + TableFunction const & dispFunction = functionManager.getGroup< TableFunction >( m_dispFunctionName ); TableFunction const & dJumpFunction = functionManager.getGroup< TableFunction >( m_dJumpFunctionName ); TableFunction const & tractionFunctionR00 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//should be Voigt full from stress TableFunction const & tractionFunctionR11 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//1 TableFunction const & tractionFunctionR22 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//2 - TableFunction const & tractionFunctionR21 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//3 - TableFunction const & tractionFunctionR02 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//4 - TableFunction const & tractionFunctionR01 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//5 + // TableFunction const & tractionFunctionR21 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//3 + // TableFunction const & tractionFunctionR02 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//4 + // TableFunction const & tractionFunctionR01 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//5 // TableFunction const & tractionFunctionL00 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); TableFunction const & tractionFunctionL11 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); TableFunction const & tractionFunctionL22 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); - TableFunction const & tractionFunctionL21 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); - TableFunction const & tractionFunctionL02 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); - TableFunction const & tractionFunctionL01 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); + // TableFunction const & tractionFunctionL21 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); + // TableFunction const & tractionFunctionL02 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); + // TableFunction const & tractionFunctionL01 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); real64 const cos_theta = cos( m_theta * M_PI/180.0 ); real64 const sin_theta = sin( m_theta * M_PI/180.0 ); @@ -837,28 +856,32 @@ void FrictionDriver::initializeTable() real64 const cos_phi = cos( m_phi * M_PI/180.0 ); real64 const sin_phi = sin( m_phi * M_PI/180.0 ); - for( integer index = 0; index < numRows; ++index ) + for( integer index = 0; index < numRows; index+=20 ) { - real64 const time = m_table( index, TIME ); + std::cerr << " index: " << index << "/" << numRows << std::endl; + real64 const time = m_table( index, TIME )/20; + std::cerr << " time: " << time << std::endl; + real64 const leftStress[6]{ tractionFunctionR00.evaluate(&time), tractionFunctionR11.evaluate(&time), - tractionFunctionR22.evaluate(&time), - tractionFunctionR21.evaluate(&time), - tractionFunctionR02.evaluate(&time), - tractionFunctionR01.evaluate(&time), + tractionFunctionR22.evaluate(&time), + 0.,// tractionFunctionR21.evaluate(&time), + 0.,// tractionFunctionR02.evaluate(&time), + 0.// tractionFunctionR01.evaluate(&time) };//should be full 6-Voigt - + real64 const rightStress[6]{ tractionFunctionL00.evaluate(&time), tractionFunctionL11.evaluate(&time), tractionFunctionL22.evaluate(&time), - tractionFunctionL21.evaluate(&time), - tractionFunctionL02.evaluate(&time), - tractionFunctionL01.evaluate(&time), + 0.,// tractionFunctionL21.evaluate(&time), + 0.,// tractionFunctionL02.evaluate(&time), + 0.// tractionFunctionL01.evaluate(&time) };//should be full 6-Voigt real64 const n[3]{cos_theta,sin_theta*sin_phi,-cos_theta*sin_phi}; + m_table( index, DISP ) = dispFunction.evaluate(&time); //rotate and project stress for(const auto& sigma : {leftStress, rightStress }){ @@ -896,7 +919,7 @@ void FrictionDriver::initializeTable() { real64 const cohesion = coulombFriction->getCohesion(); real64 const frictionCoeff = coulombFriction->getFrictionCoeff(); - for( integer index = 0; index < numRows; ++index ) + for( integer index = 0; index < numRows; index+=20 ) { real64 const normal_traction = m_table( index, NTRAC ); m_table( index, TLIM ) = cohesion - normal_traction * frictionCoeff; diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp index 33581777320..587922beffa 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -128,12 +128,22 @@ void setElement(const ContactState& contact, HexElem& elemA, HexElem& elemB, ar // that we go through the same generic solver rather than a closed form) array2d condense(const LocalBlocks& L); -CRSMat assemble(const array2d& D); +CRSMat assemble(const array2d& D, const ContactState& contact); +struct SolverStepResult +{ + SolverStepResult(std::vector& u_,double gN_, int newtonIterations_, bool converged_): + u(u_),gN(gN_),newtonIterations(newtonIterations_),converged(converged_){}; + std::vector u; + double gN = 0.; + int newtonIterations = 0; + bool converged = false; +}; -std::vector solveStep(double imposedUx, ContactState& contact, CRSMat const & Kelastic, +std::vector solveStep(double imposedUx, ContactState& contact, CRSMat const & Kelastic, double epsN, std::function& updateNormalTraction ); + } @@ -179,8 +189,8 @@ class FrictionDriver : public ConstitutiveDriver constexpr static char const * contactNameString() { return "contact"; } - // constexpr static char const * jumpFunctionString() - // { return "jumpControl"; } + constexpr static char const * displacementFunctionString() + { return "dispControl"; } constexpr static char const * dJumpFunctionString() { return "dJumpControl"; } @@ -231,14 +241,22 @@ class FrictionDriver : public ConstitutiveDriver }; // Time is defined in base class - enum columnKeys { NTRAC=1, STRAC0, STRAC1, NDJUMP, DSLIP0, DSLIP1, CC, FS, - NEWTRAC, SNEWTRAC0, SNEWTRAC1, - NJUMP, SLIP0, SLIP1, - NTOL, TTOL, NTRACTOL, - ITERPEN0, ITERPEN1, TLIM, - ITER }; - - // string m_jumpFunctionName; ///< +// enum columnKeys { NTRAC=1, STRAC0, STRAC1, NDJUMP, DSLIP0, DSLIP1, CC, FS, +// NEWTRAC, SNEWTRAC0, SNEWTRAC1, +// NJUMP, SLIP0, SLIP1, +// NTOL, TTOL, NTRACTOL, +// ITERPEN0, ITERPEN1, TLIM, +// ITER }; +enum columnKeys { NTRAC=1, STRAC0, STRAC1, DISP, NDJUMP, DSLIP0, DSLIP1, CC, FS, + NEWTRAC, SNEWTRAC0, SNEWTRAC1, + NJUMP, SLIP0, SLIP1, + NTOL, TTOL, NTRACTOL, + ITERPEN0, ITERPEN1, + FEMNTRAC, FEMGN, FEMNEWTONITER, FEMCONVERGED, // NEW + TLIM, + ITER }; + + string m_dispFunctionName; ///< string m_dJumpFunctionName; ///< string m_stressFunctionsNamesR; ///< string m_stressFunctionsNamesL; ///< diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp index 38a3f0d038c..87492b1c3db 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp @@ -60,22 +60,42 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, real64 shearModuli[2]{m_shearModulus[0], m_shearModulus[1]}; real64 bulkModuli[2]{m_bulkModulus[0], m_bulkModulus[1]}; + // mimicAssembly only models a single homogeneous material for its two-hex + // mock geometry -- average the two neighboring cells' moduli. + array2d const D = mimicAssembly::buildD( + 0.5*(bulkModuli[0]+bulkModuli[1]), + 0.5*(shearModuli[0]+shearModuli[1]) ); + + // Persistent contact state carried across rows. theta/phi are fixed + // geometry inputs, so Kelastic only needs to be built once. + mimicAssembly::ContactState contact{ + table( 0, NTRAC ), // initial normal traction guess + true, // start unconstrained + m_theta * M_PI/180.0, + m_phi * M_PI/180.0 }; + + mimicAssembly::CRSMat const Kelastic = mimicAssembly::assemble( D, contact ); + + real64 cumulativeImposedUx = 0.0; // running sum of table(ei,NDJUMP) + //TODO computeTolerance eleme to Elem typename FRICTION_TYPE::KernelWrapper const kernelWrapper = friction.createKernelUpdates(); integer const numRows = m_table.size( 0 ); - forAll< parallelDevicePolicy<> >( numRows, - [&friction, &table, &kernelWrapper, - &ghostRank, - // &normalDisplacementTol, &normalTractionTol, &slidingTol, - &normalDispTolFac, &normalTracTolFac, &slidingTolFac, - &iterPenNFac, &iterPenTFac, - &area, &volumes, &bulkModuli, &shearModuli, - &cos_phi, &sin_phi, &cos_theta, &sin_theta, - &slidingCheckTol, &isSimultaneous, - &jump, &djump, - &fractureState, &traction ] - GEOS_HOST_DEVICE ( integer const ei ) + // forAll< parallelDevicePolicy<> >( numRows, + // [&friction, &table, &kernelWrapper, + // &ghostRank, + // // &normalDisplacementTol, &normalTractionTol, &slidingTol, + // &normalDispTolFac, &normalTracTolFac, &slidingTolFac, + // &iterPenNFac, &iterPenTFac, + // &area, &volumes, &bulkModuli, &shearModuli, + // &cos_phi, &sin_phi, &cos_theta, &sin_theta, + // &slidingCheckTol, &isSimultaneous, + // &jump, &djump, + // &fractureState, &traction ] + // GEOS_HOST_DEVICE ( integer const ei ) + + for(integer ei=0; ei const a_normalTractionTol( 1 ); a_normalTractionTol[0]=normalTractionTol; array1d< real64 > const a_slidingTol( 1 ); a_slidingTol[0]=slidingTol; + + + auto [newTraction, condCov] = SolidMechanicsAugmentedLagrangianContact::updateTractionAndConstraintCheck( 1, friction, isSimultaneous, @@ -154,23 +174,67 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, newTraction[0], fractureState[0] ); - table( ei, CC ) = condCov[0]; - table( ei, FS ) = fractureState[0]; - table( ei, NEWTRAC ) = newTraction[0][0]; - table( ei, SNEWTRAC0 ) = newTraction[0][1]; - table( ei, SNEWTRAC1 ) = newTraction[0][2]; - table( ei, NTOL ) = normalDispTol; - table( ei, TTOL ) = slidingTol; - table( ei, NTRACTOL ) = normalTractionTol; - table( ei, ITERPEN0 ) = iterPen[0][0]; - table( ei, ITERPEN1 ) = iterPen[0][1]; + cumulativeImposedUx += table( ei, DISP ); - } ); + // Bridges solveStep's Newton iterate (tNold, gN) to the actual configured + // friction model, reusing the same call as the primary update above. Built + // fresh each row: captures this row's tolerance/iterPen locals by reference. + std::function< mimicAssembly::ContactState(double,double,double) > updateNormalTraction = + [&]( double tNold, double gN, double /*epsNArg*/ ) -> mimicAssembly::ContactState + { + jump[0][0] = gN; jump[0][1] = 0.0; jump[0][2] = 0.0; + traction[0][0] = tNold; traction[0][1] = table( ei, STRAC0 ); traction[0][2] = table( ei, STRAC1 ); + + kernelWrapper.updateFractureState( 0, jump[0], traction[0], fractureState[0] ); + + std::tie(newTraction, condCov) = SolidMechanicsAugmentedLagrangianContact::updateTractionAndConstraintCheck( + 1, friction, isSimultaneous, slidingCheckTol, + a_normalDisplacementTol, a_normalTractionTol, a_slidingTol, + iterPen, jump, djump, ghostRank, fractureState.toView(), traction.toView() ); + + kernelWrapper.updateFractureState( 0, jump[0], newTraction[0], fractureState[0] ); + + return mimicAssembly::ContactState{ + newTraction[0][0], + fractureState[0] == fields::contact::FractureState::Open, + contact.theta, contact.phi }; + }; + + // epsN: reuse this row's normal iterative penalty (already folds in + // area/volume/moduli scaling via computeTolerancePerFace) so the FEM + // Newton loop's contact tangent stays consistent with the table-driven path. + const auto stepResult = + mimicAssembly::solveStep( cumulativeImposedUx, contact, Kelastic, iterativePen[0], updateNormalTraction ); + + for(const auto& step : stepResult ){ + table( ei, FEMNTRAC ) = contact.tN; + table( ei, FEMGN ) = step.gN; + table( ei, FEMNEWTONITER ) = step.newtonIterations; + table( ei, FEMCONVERGED ) = step.converged ? 1.0 : 0.0; + + //old cols + table( ei, CC ) = condCov[0]; + table( ei, FS ) = fractureState[0]; + table( ei, NEWTRAC ) = newTraction[0][0]; + table( ei, SNEWTRAC0 ) = newTraction[0][1]; + table( ei, SNEWTRAC1 ) = newTraction[0][2]; + + + table( ei, NTOL ) = normalDispTol; + table( ei, TTOL ) = slidingTol; + table( ei, NTRACTOL ) = normalTractionTol; + + table( ei, ITERPEN0 ) = iterPen[0][0]; + table( ei, ITERPEN1 ) = iterPen[0][1]; + + } + // } ); //TODO restore once forAll<> } +}//function +}//namespace -} #endif //GEOS_FRICTIONDRIVERRUNTEST_HPP_ From da36d79e1695b54ecf08728ae186f5b30ea49fb0 Mon Sep 17 00:00:00 2001 From: jacques franc Date: Fri, 21 Aug 2026 15:48:56 +0200 Subject: [PATCH 25/25] testing - wip --- .../friction/frictionDriver_Coulomb.xml | 9 +- .../friction/frictionDriver_base.xml | 15 +- .../friction/tables/constant.geos | 2 + .../friction/tables/djumps.geos | 6 +- .../friction/tables/jumps.geos | 4 - .../friction/tables/time.geos | 4 - .../friction/tables/tractions.geos | 4 - .../ConstitutiveDriver.cpp | 4 +- .../contact/FrictionDriver.cpp | 185 +++++++++++------- .../contact/FrictionDriver.hpp | 56 ++++-- .../contact/FrictionDriverRunTest.hpp | 135 +++++++++---- 11 files changed, 276 insertions(+), 148 deletions(-) create mode 100644 inputFiles/constitutiveDriver/friction/tables/constant.geos diff --git a/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml index b60bc4f4086..a24ffec9f26 100644 --- a/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml +++ b/inputFiles/constitutiveDriver/friction/frictionDriver_Coulomb.xml @@ -6,12 +6,13 @@ + defaultCohesion="0.0e6" + defaultFrictionCoefficient="0.01"/> + defaultCohesion="1.0e6" + defaultFrictionCoefficient="0.01"/> @@ -49,10 +49,15 @@ voxelFile="tables/djumps.geos"/> + diff --git a/inputFiles/constitutiveDriver/friction/tables/constant.geos b/inputFiles/constitutiveDriver/friction/tables/constant.geos new file mode 100644 index 00000000000..f53496892fa --- /dev/null +++ b/inputFiles/constitutiveDriver/friction/tables/constant.geos @@ -0,0 +1,2 @@ +1e2 +1e2 diff --git a/inputFiles/constitutiveDriver/friction/tables/djumps.geos b/inputFiles/constitutiveDriver/friction/tables/djumps.geos index cedef2718a7..9aea9e0ce5f 100644 --- a/inputFiles/constitutiveDriver/friction/tables/djumps.geos +++ b/inputFiles/constitutiveDriver/friction/tables/djumps.geos @@ -1,6 +1,2 @@ 0 --1e-2 --1e-3 -0 -1e-3 -1e-2 \ No newline at end of file +0 \ No newline at end of file diff --git a/inputFiles/constitutiveDriver/friction/tables/jumps.geos b/inputFiles/constitutiveDriver/friction/tables/jumps.geos index c31e4986824..d9a5218f002 100644 --- a/inputFiles/constitutiveDriver/friction/tables/jumps.geos +++ b/inputFiles/constitutiveDriver/friction/tables/jumps.geos @@ -1,6 +1,2 @@ 0 --1e-3 --2e-3 --3e-3 --4e-3 -5e-3 diff --git a/inputFiles/constitutiveDriver/friction/tables/time.geos b/inputFiles/constitutiveDriver/friction/tables/time.geos index e8371f00609..fd3306644d5 100644 --- a/inputFiles/constitutiveDriver/friction/tables/time.geos +++ b/inputFiles/constitutiveDriver/friction/tables/time.geos @@ -1,6 +1,2 @@ 0 -1 -2 -3 -4 5 diff --git a/inputFiles/constitutiveDriver/friction/tables/tractions.geos b/inputFiles/constitutiveDriver/friction/tables/tractions.geos index b45f7ff7fc8..8fd577fe1f0 100644 --- a/inputFiles/constitutiveDriver/friction/tables/tractions.geos +++ b/inputFiles/constitutiveDriver/friction/tables/tractions.geos @@ -1,6 +1,2 @@ 0 --1e2 --2e2 --3e2 --4e2 -5e2 diff --git a/src/coreComponents/constitutiveDrivers/ConstitutiveDriver.cpp b/src/coreComponents/constitutiveDrivers/ConstitutiveDriver.cpp index 75b5c71607a..8080e7c197a 100644 --- a/src/coreComponents/constitutiveDrivers/ConstitutiveDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/ConstitutiveDriver.cpp @@ -147,7 +147,7 @@ void ConstitutiveDriver::outputToFile() const file << std::scientific << std::setprecision( precision ); integer const width = precision+7+1;//spacing for minus sign - for( integer step = 0; step <= m_numSteps; ++step ) + for( integer step = 0; step < m_table.size(0); ++step ) { file << std::setw( width ) << m_table( step, 0 ); for( integer col = 1; col < numColumns; ++col ) @@ -213,7 +213,7 @@ void ConstitutiveDriver::outputToConsole() const TableData tableData; stdVector< TableData::CellData > tableRow( numColumns ); - for( integer step = 0; step <= m_numSteps; ++step ) + for( integer step = 0; step < m_table.size(0); ++step ) { for( integer col = 0; col < numColumns; ++col ) { diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp index 550e710cd5e..5c31b51192d 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.cpp @@ -23,7 +23,7 @@ #include "functions/FunctionManager.hpp" #include "functions/TableFunction.hpp" -#define TEST_PBQ 1 +#define TEST_PBQ 0 namespace geos { @@ -414,10 +414,10 @@ void setElement(const ContactState& contact, HexElem& elemA, HexElem& elemB, arr //rotations and geometry - auto rotZ = [](double a){ array2d R; R.zero(); R[0][0]=cos(a);R[0][1]=-sin(a);R[0][2]=0; + auto rotZ = [](double a){ array2d R{3,3}; R.zero(); R[0][0]=cos(a);R[0][1]=-sin(a);R[0][2]=0; R[1][0]=sin(a);R[1][1]=cos(a); R[1][2]=0; R[2][0]=0; R[2][1]=0; R[2][2]=1; return R; }; - auto rotY = [](double a){ array2d R; R.zero(); R[0][0]=cos(a); R[0][1]=0;R[0][2]=sin(a); + auto rotY = [](double a){ array2d R{3,3}; R.zero(); R[0][0]=cos(a); R[0][1]=0;R[0][2]=sin(a); R[1][0]=0; R[1][1]=1;R[1][2]=0; R[2][0]=-sin(a);R[2][1]=0;R[2][2]=cos(a); return R; }; @@ -426,7 +426,7 @@ void setElement(const ContactState& contact, HexElem& elemA, HexElem& elemB, arr LvArray::tensorOps::Rij_eq_AikBkj<3,3,3>(RR,rotY(contact.theta),rotZ(contact.phi)); auto unitCubeCorner = [&](array1d origin, int localIndex) { - array1d c; c.zero(); + array1d c{3}; c.zero(); c[0] = origin[0] + 0.5*(1+refCorners[localIndex][0]); c[1] = origin[1] + 0.5*(1+refCorners[localIndex][1]); c[2] = origin[2] + 0.5*(1+refCorners[localIndex][2]); @@ -434,16 +434,18 @@ void setElement(const ContactState& contact, HexElem& elemA, HexElem& elemB, arr LvArray::tensorOps::Ri_eq_AijBj<3,3>(res, RR, c); return res; }; + - array1d e0, e1; + array1d e0{3}, e1{3}; e0.zero(); e1.zero(); e1[0] = 1.; for (int a=0;a<8;++a) elemA.coords[a] = unitCubeCorner(e0, a); for (int a=0;a<8;++a) elemB.coords[a] = unitCubeCorner(e1, a); } -std::vector solveStep(double imposedUx, ContactState& contact, CRSMat const & Kelastic, double epsN, std::function& updateNormalTraction ) +std::vector solveStep(double imposedUx, ContactState& contact, CRSMat const & Kelastic, double epsN, int kMaxNewton, std::function& updateNormalTraction ) { + std::vector results; //prep -- duplicate (pass element A and B ?) HexElem elemA, elemB; array2d R{3,3}; @@ -457,7 +459,7 @@ std::vector solveStep(double imposedUx, ContactState& contact, CRSMat co // Orient outward from "-" element into "+" element: check against the // vector between element centroids and flip if pointing the wrong way. - array1d centroidA, centroidB; + array1d centroidA{3}, centroidB{3}; centroidA.zero(); centroidB.zero(); for (int a=0;a<8;++a) for (int c=0;c<3;++c) @@ -483,13 +485,15 @@ std::vector solveStep(double imposedUx, ContactState& contact, CRSMat co std::array faceGlobalMinus, faceGlobalPlus; for (int i=0;i<4;++i) { + // std::cout << " elemA.node : " << elemA.node[faceLocalMinus[i]] << "\n elemB.node : " << elemB.node[faceLocalPlus[i]] << std::endl; faceGlobalMinus[i] = elemA.node[faceLocalMinus[i]]; faceGlobalPlus[i] = elemB.node[faceLocalPlus[i]]; } std::array,4> faceDofMinus, faceDofPlus; for (int i=0;i<4;++i) - for (int c=0;i<3;++c) + for (int c=0;c<3;++c) { + // std::cout << " dofMinus: " << 3*faceGlobalMinus[i] + c << "\n dofPlus : " << 3*faceGlobalPlus[i] + c << std::endl; faceDofMinus[i][c] = 3*faceGlobalMinus[i]+c; faceDofPlus[i][c] = 3*faceGlobalPlus[i]+c; } @@ -511,13 +515,18 @@ std::vector solveStep(double imposedUx, ContactState& contact, CRSMat co return A; }; - for (int newtonIt = 0; newtonIt < 20; ++newtonIt) + for (int newtonIt = 0; newtonIt < kMaxNewton; ++newtonIt) { + ContactState trial; + double gN = 0.; + { double jumpAvg[3] = {0.,0.,0.}; for (int i=0;i<4;++i) for(int c=0; c<3; ++c) jumpAvg[c] += (u[faceDofPlus[i][c]] - u[faceDofMinus[i][c]])/4; - double gN = LvArray::tensorOps::AiBi<3>(jumpAvg,nf); + gN = LvArray::tensorOps::AiBi<3>(jumpAvg,nf); + trial = updateNormalTraction(tNold, gN, epsN); + std::cout << "\n[ " << newtonIt << " ] trial : " << contact.tN << std::endl; + } - ContactState trial = updateNormalTraction(tNold, gN, epsN); // residual r = K_elastic*u + contact virtual work (tangent is // NOT part of this -- residual uses ONLY the elastic operator, @@ -532,6 +541,7 @@ std::vector solveStep(double imposedUx, ContactState& contact, CRSMat co for (int j=0;j(std::cout,",")); for (int i=0;i<4;++i) for (int c=0;c<3;++c) @@ -606,9 +616,19 @@ std::vector solveStep(double imposedUx, ContactState& contact, CRSMat co for (int i=0;i(jumpAvg,nf); + results.emplace_back(u, gN, newtonIt, (std::sqrt(duNorm) < 1e-12)); + break; + } + else{ + results.emplace_back(u, gN, newtonIt, (std::sqrt(duNorm) < 1e-12)); + } } - return u; + + return results; }; };//end mimicAssembly @@ -630,13 +650,13 @@ FrictionDriver::FrictionDriver( const string & name, Group * const parent ) setInputFlag( InputFlags::REQUIRED ). setDescription( "Number of sample step to take in both jumps and traction increments" ); - // registerWrapper( viewKeyStruct::jumpFunctionString(), &m_jumpFunctionName ). - // setInputFlag( InputFlags::REQUIRED ). - // setDescription( "Name of the input function representing jump function along world x-axis" ); - - registerWrapper( viewKeyStruct::dJumpFunctionString(), &m_dJumpFunctionName ).//should be derive from convergence history + registerWrapper( viewKeyStruct::displacementFunctionString(), &m_dispFunctionName ). setInputFlag( InputFlags::REQUIRED ). - setDescription( "Name of the input function representing deltaDisplacementJump function along world x-axis" ); + setDescription( "Name of the input function representing displacement function along world x-axis" ); + + // registerWrapper( viewKeyStruct::dJumpFunctionString(), &m_dJumpFunctionName ).//should be derive from convergence history + // setInputFlag( InputFlags::REQUIRED ). + // setDescription( "Name of the input function representing deltaDisplacementJump function along world x-axis" ); registerWrapper( viewKeyStruct::stressFunctionLString(), &m_stressFunctionsNamesL ). setInputFlag( InputFlags::REQUIRED ). @@ -695,11 +715,16 @@ FrictionDriver::FrictionDriver( const string & name, Group * const parent ) setDescription( "Neighboring cells' shear Modulus" ); //algo tune - registerWrapper( viewKeyStruct::simultaneous(), &m_isSimultaneous ). - setInputFlag( InputFlags::REQUIRED ). - setDescription( "isSimultaneous" ); + registerWrapper( viewKeyStruct::simultaneous(), &m_isSimultaneous ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "isSimultaneous" ); + + registerWrapper( viewKeyStruct::maxNewtonIterString(), &m_maxNewtonIter ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( 20 ). + setDescription( "Maximum Newton iterations" ); - addLogLevel< logInfo::LogOutput >(); + addLogLevel< logInfo::LogOutput >(); } void FrictionDriver::postInputInitialization() @@ -708,13 +733,13 @@ void FrictionDriver::postInputInitialization() // Check that the functions exist FunctionManager & functionManager = FunctionManager::getInstance(); - // GEOS_ERROR_IF( !functionManager.hasGroup< TableFunction >( m_jumpFunctionName ), - // GEOS_FMT( "Jump function with name '{}' not found", m_jumpFunctionName ), - // getWrapperDataContext( viewKeyStruct::jumpFunctionString() ) ); + GEOS_ERROR_IF( !functionManager.hasGroup< TableFunction >( m_dispFunctionName ), + GEOS_FMT( "Jump function with name '{}' not found", m_dispFunctionName ), + getWrapperDataContext( viewKeyStruct::displacementFunctionString() ) ); - GEOS_ERROR_IF( !functionManager.hasGroup< TableFunction >( m_dJumpFunctionName ), - GEOS_FMT( "dJump function with name '{}' not found", m_dJumpFunctionName ), - getWrapperDataContext( viewKeyStruct::dJumpFunctionString() ) ); + // GEOS_ERROR_IF( !functionManager.hasGroup< TableFunction >( m_dJumpFunctionName ), + // GEOS_FMT( "dJump function with name '{}' not found", m_dJumpFunctionName ), + // getWrapperDataContext( viewKeyStruct::dJumpFunctionString() ) ); GEOS_ERROR_IF( !functionManager.hasGroup< TableFunction >( m_stressFunctionsNamesR ), GEOS_FMT( "Stress functions with name '{}' not found", m_stressFunctionsNamesR ), @@ -729,22 +754,33 @@ void FrictionDriver::postInputInitialization() integer const numCols = static_cast< integer >(columnNames.size()); // initialize functions - // TableFunction & jumpFunction = functionManager.getGroup< TableFunction >( m_jumpFunctionName ); - TableFunction & dJumpFunction = functionManager.getGroup< TableFunction >( m_dJumpFunctionName ); + TableFunction & dispFunction = functionManager.getGroup< TableFunction >( m_dispFunctionName ); + // TableFunction & dJumpFunction = functionManager.getGroup< TableFunction >( m_dJumpFunctionName ); + TableFunction & tractionFunctionR00 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR ); + TableFunction & tractionFunctionL00 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); // TableFunction & tractionFunction = functionManager.getGroup< TableFunction >( m_tractionFunctionName ); - // jumpFunction.initializeFunction(); - dJumpFunction.initializeFunction(); + dispFunction.initializeFunction(); + // dJumpFunction.initializeFunction(); + tractionFunctionR00.initializeFunction(); + tractionFunctionL00.initializeFunction(); // tractionFunction.initializeFunction(); // // TODO: Maybe we should take the maximum extent of jumpFunction and tractionFunction - ArrayOfArraysView< real64 > coordinates = dJumpFunction.getCoordinates(); + ArrayOfArraysView< real64 > coordinates = dispFunction.getCoordinates(); real64 const minTime = coordinates[0][0]; real64 const maxTime = coordinates[0][coordinates.sizeOfArray( 0 )-1]; // Allocate the data allocateTable( numCols, minTime, maxTime ); + m_table.resize( (m_numSteps+1)*m_maxNewtonIter, numCols ); + real64 const dt = (maxTime-minTime) / m_numSteps; + // set time columns + for( integer step = 0; step < m_table.size(0) ; ++step ) + { + m_table( step, TIME ) = minTime + (step/m_maxNewtonIter)*dt; + } // set input columns initializeTable(); } @@ -800,6 +836,10 @@ void FrictionDriver::getColumnNames( string_array & columnNames ) const columnNames.emplace_back( "derived traction tol, normal" ); columnNames.emplace_back( "iterative penalty, normal" ); columnNames.emplace_back( "iterative penalty, tangent" ); + columnNames.emplace_back( "mimicAssembly FEM solve, converged normal traction" ); + columnNames.emplace_back( "mimicAssembly FEM solve, converged normal displacement jump" ); + columnNames.emplace_back( "mimicAssembly FEM solve, Newton iteration count" ); + columnNames.emplace_back( "mimicAssembly FEM solve, converged flag (1=converged, 0=not converged)" ); columnNames.emplace_back( "iteration" ); @@ -814,22 +854,22 @@ void FrictionDriver::initializeTable() integer const numRows = m_table.size( 0 ); FunctionManager & functionManager = FunctionManager::getInstance(); - // TableFunction const & jumpFunction = functionManager.getGroup< TableFunction >( m_jumpFunctionName ); - TableFunction const & dJumpFunction = functionManager.getGroup< TableFunction >( m_dJumpFunctionName ); + TableFunction const & dispFunction = functionManager.getGroup< TableFunction >( m_dispFunctionName ); + // TableFunction const & dJumpFunction = functionManager.getGroup< TableFunction >( m_dJumpFunctionName ); TableFunction const & tractionFunctionR00 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//should be Voigt full from stress - TableFunction const & tractionFunctionR11 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//1 - TableFunction const & tractionFunctionR22 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//2 - TableFunction const & tractionFunctionR21 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//3 - TableFunction const & tractionFunctionR02 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//4 - TableFunction const & tractionFunctionR01 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//5 + // TableFunction const & tractionFunctionR11 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//1 + // TableFunction const & tractionFunctionR22 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//2 + // TableFunction const & tractionFunctionR21 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//3 + // TableFunction const & tractionFunctionR02 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//4 + // TableFunction const & tractionFunctionR01 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesR );//5 // TableFunction const & tractionFunctionL00 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); - TableFunction const & tractionFunctionL11 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); - TableFunction const & tractionFunctionL22 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); - TableFunction const & tractionFunctionL21 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); - TableFunction const & tractionFunctionL02 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); - TableFunction const & tractionFunctionL01 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); + // TableFunction const & tractionFunctionL11 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); + // TableFunction const & tractionFunctionL22 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); + // TableFunction const & tractionFunctionL21 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); + // TableFunction const & tractionFunctionL02 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); + // TableFunction const & tractionFunctionL01 = functionManager.getGroup< TableFunction >( m_stressFunctionsNamesL ); real64 const cos_theta = cos( m_theta * M_PI/180.0 ); real64 const sin_theta = sin( m_theta * M_PI/180.0 ); @@ -837,34 +877,36 @@ void FrictionDriver::initializeTable() real64 const cos_phi = cos( m_phi * M_PI/180.0 ); real64 const sin_phi = sin( m_phi * M_PI/180.0 ); - for( integer index = 0; index < numRows; ++index ) + for( integer index = 0; index < numRows; index+=m_maxNewtonIter ) { real64 const time = m_table( index, TIME ); - real64 const leftStress[6]{ tractionFunctionR00.evaluate(&time), - tractionFunctionR11.evaluate(&time), - tractionFunctionR22.evaluate(&time), - tractionFunctionR21.evaluate(&time), - tractionFunctionR02.evaluate(&time), - tractionFunctionR01.evaluate(&time), + real64 const leftStress[6] = { tractionFunctionR00.evaluate(&time), + tractionFunctionR00.evaluate(&time), + tractionFunctionR00.evaluate(&time), + 0.,// tractionFunctionR21.evaluate(&time), + 0.,// tractionFunctionR02.evaluate(&time), + 0.// tractionFunctionR01.evaluate(&time) };//should be full 6-Voigt - real64 const rightStress[6]{ tractionFunctionL00.evaluate(&time), - tractionFunctionL11.evaluate(&time), - tractionFunctionL22.evaluate(&time), - tractionFunctionL21.evaluate(&time), - tractionFunctionL02.evaluate(&time), - tractionFunctionL01.evaluate(&time), + + real64 const rightStress[6] = { tractionFunctionL00.evaluate(&time), + tractionFunctionL00.evaluate(&time), + tractionFunctionL00.evaluate(&time), + 0.,// tractionFunctionL21.evaluate(&time), + 0.,// tractionFunctionL02.evaluate(&time), + 0.// tractionFunctionL01.evaluate(&time) };//should be full 6-Voigt - real64 const n[3]{cos_theta,sin_theta*sin_phi,-cos_theta*sin_phi}; + real64 const n[3] = {cos_theta,sin_theta*sin_phi,-cos_theta*sin_phi}; + m_table( index, DISP ) = dispFunction.evaluate(&time); //rotate and project stress for(const auto& sigma : {leftStress, rightStress }){ constexpr real64 NCELLS = 2.0; - const real64 sigman[3]{ + const real64 sigman[3] = { sigma[0]*n[0]+sigma[5]*n[1]+sigma[4]*n[2], sigma[5]*n[0]+sigma[1]*n[1]+sigma[3]*n[2], sigma[4]*n[0]+sigma[3]*n[1]+sigma[2]*n[2], @@ -883,21 +925,26 @@ void FrictionDriver::initializeTable() // m_table( index, SLIP0 ) = m_table( index, STRAC0 )/m_iterPenTFac; // m_table( index, SLIP1 ) = m_table( index, STRAC1 )/m_iterPenTFac; - real64 const dJump = dJumpFunction.evaluate( &time ); - m_table( index, NDJUMP ) = dJump*cos_phi*cos_theta; - m_table( index, DSLIP0 ) = dJump*cos_theta*sin_phi; - m_table( index, DSLIP1 ) = dJump*sin_theta; + // real64 const dJump = dJumpFunction.evaluate( &time ); + // m_table( index, NDJUMP ) = dJump*cos_phi*cos_theta; + // m_table( index, DSLIP0 ) = dJump*cos_theta*sin_phi; + // m_table( index, DSLIP1 ) = dJump*sin_theta; + m_table( index, NDJUMP ) = 0.; + m_table( index, DSLIP0 ) = 0.; + m_table( index, DSLIP1 ) = 0.; m_table( index, CC ) = 0; m_table( index, FS ) = fields::contact::FractureState::Stick; } - if( CoulombFriction const * coulombFriction = dynamic_cast< CoulombFriction const * >(&getFriction()) ) + // if( CoulombFriction const * coulombFriction = dynamic_cast< CoulombFriction const * >(&getFriction()) ) + if( dynamic_cast< CoulombFriction const * >(&getFriction()) ) { - real64 const cohesion = coulombFriction->getCohesion(); - real64 const frictionCoeff = coulombFriction->getFrictionCoeff(); - for( integer index = 0; index < numRows; ++index ) + real64 const cohesion = 0e6;//coulombFriction->getCohesion(); //sized-0 mesh crash --> getDefault + real64 const frictionCoeff = 0.01;//coulombFriction->getFrictionCoeff(); + for( integer index = 0; index < numRows; index+=m_maxNewtonIter ) { + real64 const normal_traction = m_table( index, NTRAC ); m_table( index, TLIM ) = cohesion - normal_traction * frictionCoeff; } diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp index 33581777320..1af200bc459 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriver.hpp @@ -128,11 +128,21 @@ void setElement(const ContactState& contact, HexElem& elemA, HexElem& elemB, ar // that we go through the same generic solver rather than a closed form) array2d condense(const LocalBlocks& L); -CRSMat assemble(const array2d& D); +CRSMat assemble(const array2d& D, const ContactState& contact); +struct SolverStepResult +{ + SolverStepResult(std::vector& u_,double gN_, int newtonIterations_, bool converged_): + u(u_),gN(gN_),newtonIterations(newtonIterations_),converged(converged_){}; + std::vector u; + double gN = 0.; + int newtonIterations = 0; + bool converged = false; +}; + +std::vector solveStep(double imposedUx, ContactState& contact, CRSMat const & Kelastic, + double epsN, int kMaxNewton, std::function& updateNormalTraction); -std::vector solveStep(double imposedUx, ContactState& contact, CRSMat const & Kelastic, - double epsN, std::function& updateNormalTraction ); } @@ -179,11 +189,11 @@ class FrictionDriver : public ConstitutiveDriver constexpr static char const * contactNameString() { return "contact"; } - // constexpr static char const * jumpFunctionString() - // { return "jumpControl"; } + constexpr static char const * displacementFunctionString() + { return "dispControl"; } - constexpr static char const * dJumpFunctionString() - { return "dJumpControl"; } + // constexpr static char const * dJumpFunctionString() + // { return "dJumpControl"; } constexpr static char const * stressFunctionRString() { return "stressControlsR"; } @@ -228,18 +238,29 @@ class FrictionDriver : public ConstitutiveDriver constexpr static char const * simultaneous() { return "simultaneous"; } + constexpr static char const * maxNewtonIterString() + { return "maxNewtonIter"; } + }; // Time is defined in base class - enum columnKeys { NTRAC=1, STRAC0, STRAC1, NDJUMP, DSLIP0, DSLIP1, CC, FS, - NEWTRAC, SNEWTRAC0, SNEWTRAC1, - NJUMP, SLIP0, SLIP1, - NTOL, TTOL, NTRACTOL, - ITERPEN0, ITERPEN1, TLIM, - ITER }; - - // string m_jumpFunctionName; ///< - string m_dJumpFunctionName; ///< +// enum columnKeys { NTRAC=1, STRAC0, STRAC1, NDJUMP, DSLIP0, DSLIP1, CC, FS, +// NEWTRAC, SNEWTRAC0, SNEWTRAC1, +// NJUMP, SLIP0, SLIP1, +// NTOL, TTOL, NTRACTOL, +// ITERPEN0, ITERPEN1, TLIM, +// ITER }; +enum columnKeys { NTRAC=1, STRAC0, STRAC1, DISP, NDJUMP, DSLIP0, DSLIP1, CC, FS, + NEWTRAC, SNEWTRAC0, SNEWTRAC1, + NJUMP, SLIP0, SLIP1, + NTOL, TTOL, NTRACTOL, + ITERPEN0, ITERPEN1, + FEMNTRAC, FEMGN, FEMNEWTONITER, FEMCONVERGED, // NEW + TLIM, + ITER }; + + string m_dispFunctionName; ///< + // string m_dJumpFunctionName; ///< string m_stressFunctionsNamesR; ///< string m_stressFunctionsNamesL; ///< @@ -259,7 +280,8 @@ class FrictionDriver : public ConstitutiveDriver array1d< real64 > m_shearModulus{}; array1d< real64 > m_bulkModulus{}; - integer m_isSimultaneous{1}; + integer m_isSimultaneous{1}; + integer m_maxNewtonIter{20}; ///< Maximum Newton iterations string m_frictionName; ///< frictionType identifier }; diff --git a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp index 38a3f0d038c..be8237c4b62 100644 --- a/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp +++ b/src/coreComponents/constitutiveDrivers/contact/FrictionDriverRunTest.hpp @@ -60,36 +60,55 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, real64 shearModuli[2]{m_shearModulus[0], m_shearModulus[1]}; real64 bulkModuli[2]{m_bulkModulus[0], m_bulkModulus[1]}; + // mimicAssembly only models a single homogeneous material for its two-hex + // mock geometry -- average the two neighboring cells' moduli. + array2d const D = mimicAssembly::buildD( + 0.5*(bulkModuli[0]+bulkModuli[1]), + 0.5*(shearModuli[0]+shearModuli[1]) ); + + // Persistent contact state carried across rows. theta/phi are fixed + // geometry inputs, so Kelastic only needs to be built once. + mimicAssembly::ContactState contact{ + table( 0, NTRAC ), // initial normal traction guess + true, // start unconstrained + m_theta * M_PI/180.0, + m_phi * M_PI/180.0 }; + + mimicAssembly::CRSMat const Kelastic = mimicAssembly::assemble( D, contact ); + + real64 cumulativeImposedUx = 0.0; // running sum of table(ei,NDJUMP) + //TODO computeTolerance eleme to Elem typename FRICTION_TYPE::KernelWrapper const kernelWrapper = friction.createKernelUpdates(); integer const numRows = m_table.size( 0 ); - forAll< parallelDevicePolicy<> >( numRows, - [&friction, &table, &kernelWrapper, - &ghostRank, - // &normalDisplacementTol, &normalTractionTol, &slidingTol, - &normalDispTolFac, &normalTracTolFac, &slidingTolFac, - &iterPenNFac, &iterPenTFac, - &area, &volumes, &bulkModuli, &shearModuli, - &cos_phi, &sin_phi, &cos_theta, &sin_theta, - &slidingCheckTol, &isSimultaneous, - &jump, &djump, - &fractureState, &traction ] - GEOS_HOST_DEVICE ( integer const ei ) + // forAll< parallelDevicePolicy<> >( numRows, + // [&friction, &table, &kernelWrapper, + // &ghostRank, + // // &normalDisplacementTol, &normalTractionTol, &slidingTol, + // &normalDispTolFac, &normalTracTolFac, &slidingTolFac, + // &iterPenNFac, &iterPenTFac, + // &area, &volumes, &bulkModuli, &shearModuli, + // &cos_phi, &sin_phi, &cos_theta, &sin_theta, + // &slidingCheckTol, &isSimultaneous, + // &jump, &djump, + // &fractureState, &traction ] + // GEOS_HOST_DEVICE ( integer const ei ) + + for(integer ei=0; ei const a_normalTractionTol( 1 ); a_normalTractionTol[0]=normalTractionTol; array1d< real64 > const a_slidingTol( 1 ); a_slidingTol[0]=slidingTol; + + + auto [newTraction, condCov] = SolidMechanicsAugmentedLagrangianContact::updateTractionAndConstraintCheck( 1, friction, isSimultaneous, @@ -154,23 +176,68 @@ FrictionDriver::runTest( FRICTION_TYPE & friction, newTraction[0], fractureState[0] ); - table( ei, CC ) = condCov[0]; - table( ei, FS ) = fractureState[0]; - table( ei, NEWTRAC ) = newTraction[0][0]; - table( ei, SNEWTRAC0 ) = newTraction[0][1]; - table( ei, SNEWTRAC1 ) = newTraction[0][2]; - table( ei, NTOL ) = normalDispTol; - table( ei, TTOL ) = slidingTol; - table( ei, NTRACTOL ) = normalTractionTol; - table( ei, ITERPEN0 ) = iterPen[0][0]; - table( ei, ITERPEN1 ) = iterPen[0][1]; + cumulativeImposedUx += table( ei, DISP ); - } ); + // Bridges solveStep's Newton iterate (tNold, gN) to the actual configured + // friction model, reusing the same call as the primary update above. Built + // fresh each row: captures this row's tolerance/iterPen locals by reference. + std::function< mimicAssembly::ContactState(double,double,double) > updateNormalTraction = + [&]( double tNold, double gN, double /*epsNArg*/ ) -> mimicAssembly::ContactState + { + jump[0][0] = gN; jump[0][1] = 0.0; jump[0][2] = 0.0; + traction[0][0] = tNold; traction[0][1] = table( ei, STRAC0 ); traction[0][2] = table( ei, STRAC1 ); + + kernelWrapper.updateFractureState( 0, jump[0], traction[0], fractureState[0] ); + + std::tie(newTraction, condCov) = SolidMechanicsAugmentedLagrangianContact::updateTractionAndConstraintCheck( + 1, friction, isSimultaneous, slidingCheckTol, + a_normalDisplacementTol, a_normalTractionTol, a_slidingTol, + iterPen, jump, djump, ghostRank, fractureState.toView(), traction.toView() ); + + kernelWrapper.updateFractureState( 0, jump[0], newTraction[0], fractureState[0] ); + + return mimicAssembly::ContactState{ + newTraction[0][0], + fractureState[0] == fields::contact::FractureState::Open, + contact.theta, contact.phi }; + }; + + // epsN: reuse this row's normal iterative penalty (already folds in + // area/volume/moduli scaling via computeTolerancePerFace) so the FEM + // Newton loop's contact tangent stays consistent with the table-driven path. + const auto stepResult = + mimicAssembly::solveStep( cumulativeImposedUx, contact, Kelastic, iterativePen[0], m_maxNewtonIter, updateNormalTraction ); + + int iter = 0; + for(const auto& step : stepResult ){ + table( ei*m_maxNewtonIter + iter, FEMNTRAC ) = contact.tN; + table( ei*m_maxNewtonIter + iter, FEMGN ) = step.gN; + table( ei*m_maxNewtonIter + iter, FEMNEWTONITER ) = step.newtonIterations; + table( ei*m_maxNewtonIter + iter, FEMCONVERGED ) = step.converged ? 1.0 : 0.0; + + //old cols + table( ei*m_maxNewtonIter + iter, CC ) = condCov[0]; + table( ei*m_maxNewtonIter + iter, FS ) = fractureState[0]; + table( ei*m_maxNewtonIter + iter, NEWTRAC ) = newTraction[0][0]; + table( ei*m_maxNewtonIter + iter, SNEWTRAC0 ) = newTraction[0][1]; + table( ei*m_maxNewtonIter + iter, SNEWTRAC1 ) = newTraction[0][2]; + + + table( ei*m_maxNewtonIter + iter, NTOL ) = normalDispTol; + table( ei*m_maxNewtonIter + iter, TTOL ) = slidingTol; + table( ei*m_maxNewtonIter + iter, NTRACTOL ) = normalTractionTol; + + table( ei*m_maxNewtonIter + iter, ITERPEN0 ) = iterPen[0][0]; + table( ei*m_maxNewtonIter + iter, ITERPEN1 ) = iterPen[0][1]; + ++iter; + } + // } ); //TODO restore once forAll<> } +}//function +}//namespace -} #endif //GEOS_FRICTIONDRIVERRUNTEST_HPP_