21 #ifndef GEOS_PHYSICSSOLVERS_MULTIPHYSICS_POROMECHANICSSOLVER_HPP_
22 #define GEOS_PHYSICSSOLVERS_MULTIPHYSICS_POROMECHANICSSOLVER_HPP_
29 #include "constitutive/solid/CoupledSolidBase.hpp"
30 #include "constitutive/contact/HydraulicApertureBase.hpp"
33 #include "codingUtilities/Utilities.hpp"
38 namespace stabilization
40 enum class StabilizationType :
integer
54 template<
typename FLOW_SOLVER,
typename MECHANICS_SOLVER = Sol
idMechanicsLagrangianFEM >
82 :
Base( name, parent ),
87 setApplyDefaultValue( 0 ).
89 setDescription(
"Flag indicating whether the problem is thermal or not. Set isThermal=\"1\" to enable the thermal coupling" );
93 setDescription(
"StabilizationType. Options are:\n" +
94 toString( stabilization::StabilizationType::None ) +
"- Add no stabilization to mass equation \n" +
95 toString( stabilization::StabilizationType::Global ) +
"- Add jump stabilization to all faces \n" +
96 toString( stabilization::StabilizationType::Local ) +
"- Add jump stabilization on interior of macro elements" );
99 setRTTypeName( rtTypes::CustomTypes::groupNameRefArray ).
101 setDescription(
"Regions where stabilization is applied." );
104 setApplyDefaultValue( 1.0 ).
106 setDescription(
"Constant multiplier of stabilization strength" );
118 GEOS_FMT(
"{} {}: The attribute `{}` of the flow solver must be thermal since the poromechanics solver is thermal",
123 GEOS_FMT(
"{} {}: The attribute `{}` of solid mechanics solver `{}` must be `{}`",
125 SolidMechanicsLagrangianFEM::viewKeyStruct::timeIntegrationOptionString(),
137 this->
template setConstitutiveName< constitutive::CoupledSolidBase >( subRegion,
141 this->
template setConstitutiveName< constitutive::PorosityBase >( subRegion,
142 constitutive::CoupledSolidBase::viewKeyStruct::porosityModelNameString(),
"porosity" );
146 this->
template setConstitutiveName< constitutive::HydraulicApertureBase >( subRegion,
157 ": Local stabilization has been temporarily disabled",
160 DomainPartition & domain = this->
template getGroupByPath< DomainPartition >(
"/Problem/domain" );
162 this->
template forDiscretizationOnMeshTargets<>( domain.
getMeshBodies(), [&] (
string const &,
166 ElementRegionManager & elementRegionManager = mesh.getElemManager();
167 elementRegionManager.forElementSubRegions< CellElementSubRegion >( regionNames,
168 [&]( localIndex const,
169 ElementSubRegionBase & subRegion )
171 if( subRegion.hasField< fields::poromechanics::bulkDensity >() )
174 constitutive::CoupledSolidBase const & solid =
175 this->template getConstitutiveModel< constitutive::CoupledSolidBase >( subRegion,
176 subRegion.getReference< string >( viewKeyStruct::porousMaterialNamesString() ) );
177 subRegion.getField< fields::poromechanics::bulkDensity >().resizeDimension< 1 >( solid.getDensity().size( 1 ) );
185 Base::registerDataOnMesh( meshBodies );
190 solidMechanicsSolver()->enableFixedStressPoromechanicsUpdate();
192 flowSolver()->enableFixedStressPoromechanicsUpdate();
195 if( m_stabilizationType == stabilization::StabilizationType::Global || m_stabilizationType == stabilization::StabilizationType::Local )
197 flowSolver()->enableJumpStabilization();
200 this->forDiscretizationOnMeshTargets( meshBodies, [&] (
string const &,
210 subRegion.registerWrapper<
string >( viewKeyStruct::porousMaterialNamesString() ).
213 setSizedFromParent( 0 );
216 subRegion.registerWrapper<
string >( constitutive::CoupledSolidBase::viewKeyStruct::porosityModelNameString() ).
219 setSizedFromParent( 0 );
223 subRegion.registerField< fields::poromechanics::bulkDensity >( this->getName() );
225 if( m_stabilizationType == stabilization::StabilizationType::Global || m_stabilizationType == stabilization::StabilizationType::Local )
227 subRegion.registerField< fields::flow::macroElementIndex >( this->getName());
228 subRegion.registerField< fields::flow::elementStabConstant >( this->getName());
238 flowSolver()->setKeepVariablesConstantDuringInitStep( m_performStressInitialization );
240 if( this->m_stabilizationType == stabilization::StabilizationType::Global || this->m_stabilizationType == stabilization::StabilizationType::Local )
242 this->updateStabilizationParameters( domain );
245 Base::implicitStepSetup( time_n, dt, domain );
254 solidMechanicsSolver()->setupDofs( domain, dofManager );
255 flowSolver()->setupDofs( domain, dofManager );
256 this->setupCoupling( domain, dofManager );
262 dofManager.
addCoupling( fields::solidMechanics::totalDisplacement::key(),
277 assembleElementBasedTerms( time,
286 if( m_stabilizationType == stabilization::StabilizationType::Global ||
287 m_stabilizationType == stabilization::StabilizationType::Local )
289 this->flowSolver()->assembleStabilizedFluxTerms( dt,
297 this->flowSolver()->assembleFluxTerms( dt,
305 virtual void assembleElementBasedTerms(
real64 const time_n,
312 virtual bool checkSequentialConvergence(
integer const cycleNumber,
319 auto & subcycling = this->getNonlinearSolverParameters().m_subcyclingOption;
320 auto const subcycling_orig = subcycling;
321 if( m_performStressInitialization )
323 bool isConverged = Base::checkSequentialConvergence( cycleNumber, iter, time_n, dt, domain );
326 subcycling = subcycling_orig;
337 return std::get< toUnderlying( SolverType::SolidMechanics ) >( m_solvers );
346 return std::get< toUnderlying( SolverType::Flow ) >( m_solvers );
353 void setStressInitialization(
bool const performStressInitialization )
355 m_performStressInitialization = performStressInitialization;
356 solidMechanicsSolver()->setStressInitialization( performStressInitialization );
385 for(
string const & regionName : m_stabilizationRegionNames )
387 regionFilter.insert( regionName );
391 this->
template forDiscretizationOnMeshTargets<>( domain.
getMeshBodies(), [&] (
string const &,
396 string_array filteredTargetRegionNames;
397 filteredTargetRegionNames.reserve( targetRegionNames.size() );
399 for( string const & targetRegionName : targetRegionNames )
401 if( regionFilter.count( targetRegionName ) )
403 filteredTargetRegionNames.emplace_back( targetRegionName );
408 mesh.getElemManager().forElementSubRegions( filteredTargetRegionNames, [&](
localIndex const,
409 ElementSubRegionBase & subRegion )
411 arrayView1d< integer > const macroElementIndex = subRegion.getField< fields::flow::macroElementIndex >();
412 arrayView1d< real64 > const elementStabConstant = subRegion.getField< fields::flow::elementStabConstant >();
414 constitutive::CoupledSolidBase const & porousSolid =
415 this->template getConstitutiveModel< constitutive::CoupledSolidBase >( subRegion,
416 subRegion.getReference< string >( viewKeyStruct::porousMaterialNamesString() ) );
418 arrayView1d< real64 const > const bulkModulus = porousSolid.getBulkModulus();
419 arrayView1d< real64 const > const shearModulus = porousSolid.getShearModulus();
420 arrayView1d< real64 const > const biotCoefficient = porousSolid.getBiotCoefficient();
422 real64 const stabilizationMultiplier = m_stabilizationMultiplier;
424 forAll< parallelDevicePolicy<> >( subRegion.size(), [bulkModulus,
427 stabilizationMultiplier,
429 elementStabConstant] GEOS_HOST_DEVICE ( localIndex const ei )
432 real64 const bM = bulkModulus[ei];
433 real64 const sM = shearModulus[ei];
434 real64 const bC = biotCoefficient[ei];
436 macroElementIndex[ei] = 1;
437 elementStabConstant[ei] = stabilizationMultiplier * 9.0 * (bC * bC) / (32.0 * (10.0 * sM / 3.0 + bM));
444 void updateBulkDensity( DomainPartition & domain )
446 this->
template forDiscretizationOnMeshTargets<>( domain.getMeshBodies(), [&](
string const &,
450 mesh.getElemManager().forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const,
456 updateBulkDensity( subRegion );
465 Base::initializePostInitialConditionsPreSubGroups();
468 this->
template getReference< string_array >( PhysicsSolverBase::viewKeyStruct::targetRegionsString() );
470 this->solidMechanicsSolver()->template getReference< string_array >( PhysicsSolverBase::viewKeyStruct::targetRegionsString() );
472 this->flowSolver()->template getReference< string_array >( PhysicsSolverBase::viewKeyStruct::targetRegionsString() );
473 for(
size_t i = 0; i < poromechanicsTargetRegionNames.size(); ++i )
475 GEOS_THROW_IF( std::find( solidMechanicsTargetRegionNames.begin(), solidMechanicsTargetRegionNames.end(),
476 poromechanicsTargetRegionNames[i] )
477 == solidMechanicsTargetRegionNames.end(),
478 GEOS_FMT(
"{} {}: region {} must be a target region of {}",
479 this->getCatalogName(), this->getDataContext(), poromechanicsTargetRegionNames[i],
480 this->solidMechanicsSolver()->getDataContext() ),
482 GEOS_THROW_IF( std::find( flowTargetRegionNames.begin(), flowTargetRegionNames.end(), poromechanicsTargetRegionNames[i] )
483 == flowTargetRegionNames.end(),
484 GEOS_FMT(
"{} {}: region `{}` must be a target region of `{}`",
485 this->getCatalogName(), this->getDataContext(), poromechanicsTargetRegionNames[i], this->flowSolver()->getDataContext() ),
490 template<
typename TYPE_LIST,
491 typename KERNEL_WRAPPER,
492 typename ... PARAMS >
496 string const & materialNamesString,
500 PARAMS && ... params )
506 string const dofKey = dofManager.
getKey( fields::solidMechanics::totalDisplacement::key() );
509 real64 const gravityVectorData[3] = LVARRAY_TENSOROPS_INIT_LOCAL_3( this->gravityVector() );
511 KERNEL_WRAPPER kernelWrapper( dofNumber,
517 std::forward< PARAMS >( params )... );
519 return finiteElement::
520 regionBasedKernelApplication< parallelDevicePolicy< >,
523 this->solidMechanicsSolver()->getDiscretizationName(),
530 void recordAverageMeanTotalStressIncrement( DomainPartition & domain,
531 array1d< real64 > & averageMeanTotalStressIncrement )
533 averageMeanTotalStressIncrement.resize( 0 );
534 this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&](
string const &,
538 mesh.getElemManager().forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const,
542 string const & solidName =
543 subRegion.template getReference< string >( viewKeyStruct::porousMaterialNamesString() );
544 constitutive::CoupledSolidBase & solid =
545 this->template getConstitutiveModel< constitutive::CoupledSolidBase >( subRegion, solidName );
547 arrayView1d< const real64 > const & averageMeanTotalStressIncrement_k = solid.getAverageMeanTotalStressIncrement_k();
548 for( localIndex k = 0; k < localIndex( averageMeanTotalStressIncrement_k.size()); k++ )
550 averageMeanTotalStressIncrement.emplace_back( averageMeanTotalStressIncrement_k[k] );
556 void applyAcceleratedAverageMeanTotalStressIncrement( DomainPartition & domain,
557 array1d< real64 > & averageMeanTotalStressIncrement )
560 this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&](
string const &,
564 mesh.getElemManager().forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const,
568 string const & solidName = subRegion.template getReference< string >( viewKeyStruct::porousMaterialNamesString() );
569 constitutive::CoupledSolidBase & solid =
570 this->template getConstitutiveModel< constitutive::CoupledSolidBase >( subRegion, solidName );
571 auto & porosityModel = dynamic_cast< constitutive::BiotPorosity const & >( solid.getBasePorosityModel());
572 arrayView1d< real64 > const & averageMeanTotalStressIncrement_k = solid.getAverageMeanTotalStressIncrement_k();
573 for( localIndex k = 0; k < localIndex( averageMeanTotalStressIncrement_k.size()); k++ )
575 porosityModel.updateAverageMeanTotalStressIncrement( k, averageMeanTotalStressIncrement[i] );
582 real64 computeAitkenRelaxationFactor( array1d< real64 >
const & s0,
583 array1d< real64 >
const & s1,
584 array1d< real64 >
const & s1_tilde,
585 array1d< real64 >
const & s2_tilde,
588 array1d< real64 > r1 = axpy( s1_tilde, s0, -1.0 );
589 array1d< real64 > r2 = axpy( s2_tilde, s1, -1.0 );
592 array1d< real64 > diff = axpy( r2, r1, -1.0 );
594 real64 const denom = dot( diff, diff );
595 real64 const numer = dot( r1, diff );
598 if( !isZero( denom ))
600 omega1 = -1.0 * omega0 * numer / denom;
605 array1d< real64 > computeUpdate( array1d< real64 >
const & s1,
606 array1d< real64 >
const & s2_tilde,
609 return axpy( scale( s1, 1.0 - omega1 ),
610 scale( s2_tilde, omega1 ),
614 void startSequentialIteration(
integer const & iter,
615 DomainPartition & domain )
override
617 if( this->getNonlinearSolverParameters().m_nonlinearAccelerationType == NonlinearSolverParameters::NonlinearAccelerationType::Aitken )
621 recordAverageMeanTotalStressIncrement( domain, m_s1 );
627 m_s1_tilde = m_s2_tilde;
633 void finishSequentialIteration(
integer const & iter,
634 DomainPartition & domain )
override
636 if( this->getNonlinearSolverParameters().m_nonlinearAccelerationType == NonlinearSolverParameters::NonlinearAccelerationType::Aitken )
645 m_omega1 = computeAitkenRelaxationFactor( m_s0, m_s1, m_s1_tilde, m_s2_tilde, m_omega0 );
646 m_s2 = computeUpdate( m_s1, m_s2_tilde, m_omega1 );
647 applyAcceleratedAverageMeanTotalStressIncrement( domain, m_s2 );
657 if( solverType ==
static_cast< integer >( SolverType::Flow ) )
659 updateBulkDensity( domain );
663 if( solverType ==
static_cast< integer >( SolverType::SolidMechanics )
664 && !m_performStressInitialization )
667 averageMeanTotalStressIncrement( domain );
669 this->
template forDiscretizationOnMeshTargets<>( domain.
getMeshBodies(), [&](
string const &,
674 mesh.getElemManager().forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const,
679 flowSolver()->updatePorosityAndPermeability( subRegion );
681 updateBulkDensity( subRegion );
687 if( solverType ==
static_cast< integer >( SolverType::SolidMechanics ) &&
688 this->getNonlinearSolverParameters().m_nonlinearAccelerationType== NonlinearSolverParameters::NonlinearAccelerationType::Aitken )
690 recordAverageMeanTotalStressIncrement( domain, m_s2_tilde );
700 this->
template forDiscretizationOnMeshTargets<>( domain.
getMeshBodies(), [&](
string const &,
704 mesh.getElemManager().forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const,
708 string const & solidName = subRegion.template getReference< string >( viewKeyStruct::porousMaterialNamesString() );
709 constitutive::CoupledSolidBase & solid =
710 this->template getConstitutiveModel< constitutive::CoupledSolidBase >( subRegion, solidName );
712 arrayView2d< real64 const > const meanTotalStressIncrement_k = solid.getMeanTotalStressIncrement_k();
713 arrayView1d< real64 > const averageMeanTotalStressIncrement_k = solid.getAverageMeanTotalStressIncrement_k();
715 finiteElement::FiniteElementBase & subRegionFE =
716 subRegion.template getReference< finiteElement::FiniteElementBase >( solidMechanicsSolver()->getDiscretizationName() );
719 finiteElement::FiniteElementDispatchHandler< BASE_FE_TYPES >::
720 dispatch3D( subRegionFE, [&] ( auto const finiteElement )
722 using FE_TYPE = decltype( finiteElement );
725 AverageOverQuadraturePoints1DKernelFactory::
726 createAndLaunch< CellElementSubRegion,
728 parallelDevicePolicy<> >( mesh.getNodeManager(),
729 mesh.getEdgeManager(),
730 mesh.getFaceManager(),
733 meanTotalStressIncrement_k,
734 averageMeanTotalStressIncrement_k );
740 virtual void setMGRStrategy() = 0;
742 virtual void updateBulkDensity( ElementSubRegionBase & subRegion ) = 0;
744 virtual string getFlowDofKey()
const = 0;
746 virtual void validateNonlinearAcceleration()
override
750 GEOS_ERROR(
"Nonlinear acceleration is not implemented for MPI runs" );
#define GEOS_UNUSED_PARAM(X)
Mark an unused argument and silence compiler warnings.
#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 initializePreSubGroups() override
Called by Initialize() prior to initializing sub-Groups.
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,...
globalIndex rankOffset(string const &fieldName) const
void addCoupling(string const &rowFieldName, string const &colFieldName, Connector connectivity, stdVector< FieldSupport > const ®ions={}, bool symmetric=true)
Add coupling between two fields.
@ Elem
connectivity is element (like in finite elements)
string const & getKey(string const &fieldName) const
Return the key used to record the field in the DofManager.
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.
NodeManager const & getNodeManager() const
Get the node manager.
ElementRegionManager const & getElemManager() const
Get the element region manager.
The NodeManager class provides an interface to ObjectManagerBase in order to manage node data.
@ 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 initializePostInitialConditionsPreSubGroups() override
Called by InitializePostInitialConditions() prior to initializing sub-Groups.
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.
virtual void assembleSystem(real64 const time, real64 const dt, DomainPartition &domain, DofManager const &dofManager, CRSMatrixView< real64, globalIndex const > const &localMatrix, arrayView1d< real64 > const &localRhs) override
function to assemble the linear system matrix and rhs
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.
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.
GEOS_DECLTYPE_AUTO_RETURN getReference(LOOKUP_TYPE const &lookup) const
Look up a wrapper and get reference to wrapped object.
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.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
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).
LvArray::CRSMatrixView< T, COL_INDEX, INDEX_TYPE const, LvArray::ChaiBuffer > CRSMatrixView
Alias for CRS Matrix View.
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.