21 #ifndef GEOS_PHYSICSSOLVERS_MULTIPHYSICS_POROMECHANICSSOLVER_HPP_
22 #define GEOS_PHYSICSSOLVERS_MULTIPHYSICS_POROMECHANICSSOLVER_HPP_
28 #include "constitutive/solid/CoupledSolidBase.hpp"
29 #include "constitutive/contact/HydraulicApertureBase.hpp"
32 #include "codingUtilities/Utilities.hpp"
37 namespace stabilization
39 enum class StabilizationType :
integer
53 template<
typename FLOW_SOLVER,
typename MECHANICS_SOLVER = Sol
idMechanicsLagrangianFEM >
81 :
Base( name, parent ),
86 setApplyDefaultValue( 0 ).
88 setDescription(
"Flag indicating whether the problem is thermal or not. Set isThermal=\"1\" to enable the thermal coupling" );
92 setDescription(
"StabilizationType. Options are:\n" +
93 toString( stabilization::StabilizationType::None ) +
"- Add no stabilization to mass equation \n" +
94 toString( stabilization::StabilizationType::Global ) +
"- Add jump stabilization to all faces \n" +
95 toString( stabilization::StabilizationType::Local ) +
"- Add jump stabilization on interior of macro elements" );
98 setRTTypeName( rtTypes::CustomTypes::groupNameRefArray ).
100 setDescription(
"Regions where stabilization is applied." );
103 setApplyDefaultValue( 1.0 ).
105 setDescription(
"Constant multiplier of stabilization strength" );
117 GEOS_FMT(
"{} {}: The attribute `{}` of the flow solver must be thermal since the poromechanics solver is thermal",
122 GEOS_FMT(
"{} {}: The attribute `{}` of solid mechanics solver `{}` must be `{}`",
124 SolidMechanicsLagrangianFEM::viewKeyStruct::timeIntegrationOptionString(),
134 this->
template setConstitutiveName< constitutive::CoupledSolidBase >( subRegion,
138 this->
template setConstitutiveName< constitutive::PorosityBase >( subRegion,
139 constitutive::CoupledSolidBase::viewKeyStruct::porosityModelNameString(),
"porosity" );
143 this->
template setConstitutiveName< constitutive::HydraulicApertureBase >( subRegion,
154 ": Local stabilization has been temporarily disabled",
157 DomainPartition & domain = this->
template getGroupByPath< DomainPartition >(
"/Problem/domain" );
159 this->
template forDiscretizationOnMeshTargets<>( domain.
getMeshBodies(), [&] (
string const &,
163 ElementRegionManager & elementRegionManager = mesh.getElemManager();
164 elementRegionManager.forElementSubRegions< CellElementSubRegion >( regionNames,
165 [&]( localIndex const,
166 ElementSubRegionBase & subRegion )
168 if( subRegion.hasField< fields::poromechanics::bulkDensity >() )
171 constitutive::CoupledSolidBase const & solid =
172 this->template getConstitutiveModel< constitutive::CoupledSolidBase >( subRegion,
173 subRegion.getReference< string >( viewKeyStruct::porousMaterialNamesString() ) );
174 subRegion.getField< fields::poromechanics::bulkDensity >().resizeDimension< 1 >( solid.getDensity().size( 1 ) );
182 Base::registerDataOnMesh( meshBodies );
187 solidMechanicsSolver()->enableFixedStressPoromechanicsUpdate();
189 flowSolver()->enableFixedStressPoromechanicsUpdate();
192 if( m_stabilizationType == stabilization::StabilizationType::Global || m_stabilizationType == stabilization::StabilizationType::Local )
194 flowSolver()->enableJumpStabilization();
197 this->forDiscretizationOnMeshTargets( meshBodies, [&] (
string const &,
207 subRegion.registerWrapper<
string >( viewKeyStruct::porousMaterialNamesString() ).
210 setSizedFromParent( 0 );
213 subRegion.registerWrapper<
string >( constitutive::CoupledSolidBase::viewKeyStruct::porosityModelNameString() ).
216 setSizedFromParent( 0 );
220 subRegion.registerField< fields::poromechanics::bulkDensity >( this->getName() );
222 if( m_stabilizationType == stabilization::StabilizationType::Global || m_stabilizationType == stabilization::StabilizationType::Local )
224 subRegion.registerField< fields::flow::macroElementIndex >( this->getName());
225 subRegion.registerField< fields::flow::elementStabConstant >( this->getName());
235 flowSolver()->setKeepVariablesConstantDuringInitStep( m_performStressInitialization );
237 if( this->m_stabilizationType == stabilization::StabilizationType::Global || this->m_stabilizationType == stabilization::StabilizationType::Local )
239 this->updateStabilizationParameters( domain );
242 Base::implicitStepSetup( time_n, dt, domain );
251 solidMechanicsSolver()->setupDofs( domain, dofManager );
252 flowSolver()->setupDofs( domain, dofManager );
253 this->setupCoupling( domain, dofManager );
256 virtual bool checkSequentialConvergence(
integer const cycleNumber,
263 auto & subcycling = this->getNonlinearSolverParameters().m_subcyclingOption;
264 auto const subcycling_orig = subcycling;
265 if( m_performStressInitialization )
267 bool isConverged = Base::checkSequentialConvergence( cycleNumber, iter, time_n, dt, domain );
270 subcycling = subcycling_orig;
281 return std::get< toUnderlying( SolverType::SolidMechanics ) >( m_solvers );
290 return std::get< toUnderlying( SolverType::Flow ) >( m_solvers );
297 void setStressInitialization(
bool const performStressInitialization )
299 m_performStressInitialization = performStressInitialization;
300 solidMechanicsSolver()->setStressInitialization( performStressInitialization );
329 for(
string const & regionName : m_stabilizationRegionNames )
331 regionFilter.insert( regionName );
335 this->
template forDiscretizationOnMeshTargets<>( domain.
getMeshBodies(), [&] (
string const &,
340 string_array filteredTargetRegionNames;
341 filteredTargetRegionNames.reserve( targetRegionNames.size() );
343 for( string const & targetRegionName : targetRegionNames )
345 if( regionFilter.count( targetRegionName ) )
347 filteredTargetRegionNames.emplace_back( targetRegionName );
352 mesh.getElemManager().forElementSubRegions( filteredTargetRegionNames, [&](
localIndex const,
353 ElementSubRegionBase & subRegion )
355 arrayView1d< integer > const macroElementIndex = subRegion.getField< fields::flow::macroElementIndex >();
356 arrayView1d< real64 > const elementStabConstant = subRegion.getField< fields::flow::elementStabConstant >();
358 constitutive::CoupledSolidBase const & porousSolid =
359 this->template getConstitutiveModel< constitutive::CoupledSolidBase >( subRegion,
360 subRegion.getReference< string >( viewKeyStruct::porousMaterialNamesString() ) );
362 arrayView1d< real64 const > const bulkModulus = porousSolid.getBulkModulus();
363 arrayView1d< real64 const > const shearModulus = porousSolid.getShearModulus();
364 arrayView1d< real64 const > const biotCoefficient = porousSolid.getBiotCoefficient();
366 real64 const stabilizationMultiplier = m_stabilizationMultiplier;
368 forAll< parallelDevicePolicy<> >( subRegion.size(), [bulkModulus,
371 stabilizationMultiplier,
373 elementStabConstant] GEOS_HOST_DEVICE ( localIndex const ei )
376 real64 const bM = bulkModulus[ei];
377 real64 const sM = shearModulus[ei];
378 real64 const bC = biotCoefficient[ei];
380 macroElementIndex[ei] = 1;
381 elementStabConstant[ei] = stabilizationMultiplier * 9.0 * (bC * bC) / (32.0 * (10.0 * sM / 3.0 + bM));
388 void updateBulkDensity( DomainPartition & domain )
390 this->
template forDiscretizationOnMeshTargets<>( domain.getMeshBodies(), [&](
string const &,
394 mesh.getElemManager().forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const,
400 updateBulkDensity( subRegion );
407 template<
typename TYPE_LIST,
408 typename KERNEL_WRAPPER,
409 typename ... PARAMS >
410 real64 assemblyLaunch( MeshLevel & mesh,
411 DofManager
const & dofManager,
413 string const & materialNamesString,
414 CRSMatrixView< real64, globalIndex const >
const & localMatrix,
415 arrayView1d< real64 >
const & localRhs,
417 PARAMS && ... params )
421 NodeManager
const & nodeManager = mesh.getNodeManager();
423 string const dofKey = dofManager.getKey( fields::solidMechanics::totalDisplacement::key() );
424 arrayView1d< globalIndex const >
const & dofNumber = nodeManager.getReference<
globalIndex_array >( dofKey );
426 real64 const gravityVectorData[3] = LVARRAY_TENSOROPS_INIT_LOCAL_3( this->gravityVector() );
428 KERNEL_WRAPPER kernelWrapper( dofNumber,
429 dofManager.rankOffset(),
434 std::forward< PARAMS >( params )... );
436 return finiteElement::
437 regionBasedKernelApplication< parallelDevicePolicy< >,
440 this->solidMechanicsSolver()->getDiscretizationName(),
447 void recordAverageMeanTotalStressIncrement( DomainPartition & domain,
448 array1d< real64 > & averageMeanTotalStressIncrement )
450 averageMeanTotalStressIncrement.resize( 0 );
451 this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&](
string const &,
455 mesh.getElemManager().forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const,
459 string const & solidName =
460 subRegion.template getReference< string >( viewKeyStruct::porousMaterialNamesString() );
461 constitutive::CoupledSolidBase & solid =
462 this->template getConstitutiveModel< constitutive::CoupledSolidBase >( subRegion, solidName );
464 arrayView1d< const real64 > const & averageMeanTotalStressIncrement_k = solid.getAverageMeanTotalStressIncrement_k();
465 for( localIndex k = 0; k < localIndex( averageMeanTotalStressIncrement_k.size()); k++ )
467 averageMeanTotalStressIncrement.emplace_back( averageMeanTotalStressIncrement_k[k] );
473 void applyAcceleratedAverageMeanTotalStressIncrement( DomainPartition & domain,
474 array1d< real64 > & averageMeanTotalStressIncrement )
477 this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&](
string const &,
481 mesh.getElemManager().forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const,
485 string const & solidName = subRegion.template getReference< string >( viewKeyStruct::porousMaterialNamesString() );
486 constitutive::CoupledSolidBase & solid =
487 this->template getConstitutiveModel< constitutive::CoupledSolidBase >( subRegion, solidName );
488 auto & porosityModel = dynamic_cast< constitutive::BiotPorosity const & >( solid.getBasePorosityModel());
489 arrayView1d< real64 > const & averageMeanTotalStressIncrement_k = solid.getAverageMeanTotalStressIncrement_k();
490 for( localIndex k = 0; k < localIndex( averageMeanTotalStressIncrement_k.size()); k++ )
492 porosityModel.updateAverageMeanTotalStressIncrement( k, averageMeanTotalStressIncrement[i] );
499 real64 computeAitkenRelaxationFactor( array1d< real64 >
const & s0,
500 array1d< real64 >
const & s1,
501 array1d< real64 >
const & s1_tilde,
502 array1d< real64 >
const & s2_tilde,
505 array1d< real64 > r1 = axpy( s1_tilde, s0, -1.0 );
506 array1d< real64 > r2 = axpy( s2_tilde, s1, -1.0 );
509 array1d< real64 > diff = axpy( r2, r1, -1.0 );
511 real64 const denom = dot( diff, diff );
512 real64 const numer = dot( r1, diff );
515 if( !isZero( denom ))
517 omega1 = -1.0 * omega0 * numer / denom;
522 array1d< real64 > computeUpdate( array1d< real64 >
const & s1,
523 array1d< real64 >
const & s2_tilde,
526 return axpy( scale( s1, 1.0 - omega1 ),
527 scale( s2_tilde, omega1 ),
531 void startSequentialIteration(
integer const & iter,
532 DomainPartition & domain )
override
534 if( this->getNonlinearSolverParameters().m_nonlinearAccelerationType == NonlinearSolverParameters::NonlinearAccelerationType::Aitken )
538 recordAverageMeanTotalStressIncrement( domain, m_s1 );
544 m_s1_tilde = m_s2_tilde;
550 void finishSequentialIteration(
integer const & iter,
551 DomainPartition & domain )
override
553 if( this->getNonlinearSolverParameters().m_nonlinearAccelerationType == NonlinearSolverParameters::NonlinearAccelerationType::Aitken )
562 m_omega1 = computeAitkenRelaxationFactor( m_s0, m_s1, m_s1_tilde, m_s2_tilde, m_omega0 );
563 m_s2 = computeUpdate( m_s1, m_s2_tilde, m_omega1 );
564 applyAcceleratedAverageMeanTotalStressIncrement( domain, m_s2 );
574 if( solverType ==
static_cast< integer >( SolverType::Flow ) )
576 updateBulkDensity( domain );
580 if( solverType ==
static_cast< integer >( SolverType::SolidMechanics )
581 && !m_performStressInitialization )
584 averageMeanTotalStressIncrement( domain );
586 this->
template forDiscretizationOnMeshTargets<>( domain.
getMeshBodies(), [&](
string const &,
591 mesh.getElemManager().forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const,
596 flowSolver()->updatePorosityAndPermeability( subRegion );
598 updateBulkDensity( subRegion );
604 if( solverType ==
static_cast< integer >( SolverType::SolidMechanics ) &&
605 this->getNonlinearSolverParameters().m_nonlinearAccelerationType== NonlinearSolverParameters::NonlinearAccelerationType::Aitken )
607 recordAverageMeanTotalStressIncrement( domain, m_s2_tilde );
617 this->
template forDiscretizationOnMeshTargets<>( domain.
getMeshBodies(), [&](
string const &,
621 mesh.getElemManager().forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const,
625 string const & solidName = subRegion.template getReference< string >( viewKeyStruct::porousMaterialNamesString() );
626 constitutive::CoupledSolidBase & solid =
627 this->template getConstitutiveModel< constitutive::CoupledSolidBase >( subRegion, solidName );
629 arrayView2d< real64 const > const meanTotalStressIncrement_k = solid.getMeanTotalStressIncrement_k();
630 arrayView1d< real64 > const averageMeanTotalStressIncrement_k = solid.getAverageMeanTotalStressIncrement_k();
632 finiteElement::FiniteElementBase & subRegionFE =
633 subRegion.template getReference< finiteElement::FiniteElementBase >( solidMechanicsSolver()->getDiscretizationName() );
636 finiteElement::FiniteElementDispatchHandler< BASE_FE_TYPES >::
637 dispatch3D( subRegionFE, [&] ( auto const finiteElement )
639 using FE_TYPE = decltype( finiteElement );
642 AverageOverQuadraturePoints1DKernelFactory::
643 createAndLaunch< CellElementSubRegion,
645 parallelDevicePolicy<> >( mesh.getNodeManager(),
646 mesh.getEdgeManager(),
647 mesh.getFaceManager(),
650 meanTotalStressIncrement_k,
651 averageMeanTotalStressIncrement_k );
657 virtual void updateBulkDensity( ElementSubRegionBase & subRegion ) = 0;
659 virtual void validateNonlinearAcceleration()
override
663 GEOS_ERROR(
"Nonlinear acceleration is not implemented for MPI runs" );
#define GEOS_ERROR(msg)
Raise a hard error and terminate the program.
#define GEOS_THROW_IF(EXP, msg, TYPE)
Conditionally throw an exception.
#define GEOS_MARK_FUNCTION
Mark function with both Caliper and NVTX if enabled.
virtual void postInputInitialization() override
std::tuple< SOLVERS *... > m_solvers
Pointers of the single-physics solvers.
The DoFManager is responsible for allocating global dofs, constructing sparsity patterns,...
Partition of the decomposed physical domain. It also manages the connexion information to its neighbo...
Group const & getMeshBodies() const
Get the mesh bodies, const version.
The ElementRegionManager class provides an interface to ObjectManagerBase in order to manage ElementR...
void forElementSubRegions(LAMBDA &&lambda)
This function is used to launch kernel function over the element subregions of all the subregion type...
Class facilitating the representation of a multi-level discretization of a MeshBody.
ElementRegionManager const & getElemManager() const
Get the element region manager.
@ Sequential
Sequential coupling.
virtual string getCatalogName() const =0
virtual void setConstitutiveNamesCallSuper(ElementSubRegionBase &subRegion) const
This function sets constitutive name fields on an ElementSubRegionBase, and calls the base function i...
CRSMatrix< real64, globalIndex > m_localMatrix
Local system matrix and rhs.
DofManager m_dofManager
Data structure to handle degrees of freedom.
ParallelVector m_solution
System solution vector.
ParallelVector m_rhs
System right-hand side vector.
LinearSolverParametersInput m_linearSolverParameters
Linear solver parameters.
array1d< real64 > m_s0
Member variables needed for Nonlinear Acceleration ( Aitken ). Naming convention follows ( Jiang & Tc...
virtual void implicitStepSetup(real64 const &time_n, real64 const &dt, DomainPartition &domain) override
function to perform setup for implicit timestep
real64 m_stabilizationMultiplier
Stabilization Multiplier.
virtual void initializePreSubGroups() override
Called by Initialize() prior to initializing sub-Groups.
stabilization::StabilizationType m_stabilizationType
Type of stabilization used.
virtual void postInputInitialization() override
FLOW_SOLVER * flowSolver() const
accessor for the pointer to the flow solver
PoromechanicsSolver(const string &name, dataRepository::Group *const parent)
main constructor for CoupledSolver Objects
virtual void setConstitutiveNamesCallSuper(ElementSubRegionBase &subRegion) const override final
This function sets constitutive name fields on an ElementSubRegionBase, and calls the base function i...
MECHANICS_SOLVER * solidMechanicsSolver() const
accessor for the pointer to the solid mechanics solver
virtual void mapSolutionBetweenSolvers(DomainPartition &domain, integer const solverType) override
Maps the solution obtained from one solver to the fields used by the other solver(s)
integer m_isThermal
Flag to determine whether or not this is a thermal simulation.
bool m_performStressInitialization
Flag to indicate that the solver is going to perform stress initialization.
string_array m_stabilizationRegionNames
Names of regions where stabilization applied.
virtual void setupDofs(DomainPartition const &domain, DofManager &dofManager) const override
Populate degree-of-freedom manager with fields relevant to this solver.
virtual void registerDataOnMesh(dataRepository::Group &meshBodies) override
Register wrappers that contain data on the mesh objects.
void averageMeanTotalStressIncrement(DomainPartition &domain)
Helper function to average the mean total stress increment over quadrature points.
static string coupledSolverAttributePrefix()
String used to form the solverName used to register solvers in CoupledSolver.
@ QuasiStatic
QuasiStatic.
virtual void initializePreSubGroups()
Called by Initialize() prior to initializing sub-Groups.
Wrapper< TBASE > & registerWrapper(string const &name, wrapperMap::KeyIndex::index_type *const rkey=nullptr)
Create and register a Wrapper around a new object.
string const & getName() const
Get group name.
DataContext const & getWrapperDataContext(KEY key) const
@ NOPLOT
Do not ever write to plot file.
@ OPTIONAL
Optional in input.
@ NO_WRITE
Do not write into restart.
stdVector< string > string_array
A 1-dimensional array of geos::string types.
int MPI_COMM_GEOS
Global MPI communicator used by GEOSX.
array1d< globalIndex > globalIndex_array
A 1-dimensional array of geos::globalIndex types.
std::set< T > set
A set of local indices.
double real64
64-bit floating point type.
GEOS_LOCALINDEX_TYPE localIndex
Local index type (for indexing objects within an MPI partition).
int integer
Signed integer type.
Array< T, 1 > array1d
Alias for 1D array.
ENUM_STRINGS(LinearSolverParameters::SolverType, "direct", "cg", "gmres", "fgmres", "bicgstab", "richardson", "preconditioner")
Declare strings associated with enumeration values.
Provides enum <-> string conversion facilities.
string label
User-displayed label of the scheme.
Set of parameters for a linear solver or preconditioner.
integer dofsPerNode
Dofs per node (or support location) for non-scalar problems.
struct geos::LinearSolverParameters::Multiscale multiscale
Multiscale preconditioner parameters.
constexpr static char const * porousMaterialNamesString()
Names of the porous materials.
constexpr static const char * stabilizationRegionNamesString()
Name of regions on which stabilization applied.
static constexpr char const * hydraulicApertureRelationNameString()
Name of the hydraulicApertureRelationName.
constexpr static char const * isThermalString()
Flag to indicate that the simulation is thermal.
constexpr static char const * stabilizationTypeString()
Type of pressure stabilization.
constexpr static const char * stabilizationMultiplierString()
Multiplier on stabilization strength.
Structure to hold scoped key names.