21 #ifndef GEOS_PHYSICSSOLVERS_MULTIPHYSICS_POROMECHANICSCONFORMINGFRACTURES_HPP_
22 #define GEOS_PHYSICSSOLVERS_MULTIPHYSICS_POROMECHANICSCONFORMINGFRACTURES_HPP_
31 #include "constitutive/solid/CoupledSolidBase.hpp"
32 #include "constitutive/contact/HydraulicApertureBase.hpp"
33 #include "constitutive/contact/HydraulicApertureRelationSelector.hpp"
42 template<
template<
typename,
typename >
class POROMECHANICS_BASE,
typename FLOW_SOLVER >
46 using Base = POROMECHANICS_BASE< FLOW_SOLVER, SolidMechanicsLagrangeContact >;
50 : Base( name, parent )
58 Base::setupCoupling( domain, dofManager );
62 fields::contact::traction::key(),
73 this->flowSolver()->setSparsityPattern( domain, dofManager, localMatrix, patternOriginal );
77 for(
localIndex localRow = 0; localRow < patternOriginal.numRows(); ++localRow )
79 rowLengths[localRow] = patternOriginal.numNonZeros( localRow );
86 pattern.resizeFromRowCapacities< parallelHostPolicy >( patternOriginal.numRows(),
87 patternOriginal.numColumns(),
99 virtual void assembleSystem(
real64 const time_n,
101 DomainPartition & domain,
102 DofManager
const & dofManager,
103 CRSMatrixView< real64, globalIndex const >
const & localMatrix,
104 arrayView1d< real64 >
const & localRhs )
override
109 this->solidMechanicsSolver()->synchronizeFractureState( domain );
114 if( !m_derivativeFluxResidual_dAperture )
118 m_derivativeFluxResidual_dAperture->move( parallelDeviceMemorySpace,
false );
119 m_derivativeFluxResidual_dAperture->zero();
129 this->flowSolver()->assembleHydrofracFluxTerms( time_n,
135 getDerivativeFluxResidual_dNormalJump(),
138 m_derivativeFluxResidual_dAperture->move( hostMemorySpace,
false );
149 virtual void updateState( DomainPartition & domain )
override
154 Base::updateState( domain );
156 this->solidMechanicsSolver()->updateState( domain );
159 this->flowSolver()->prepareStencilWeights( domain );
161 updateHydraulicApertureAndFracturePermeability( domain );
164 this->flowSolver()->updateStencilWeights( domain );
181 integer const numComp = numFluidComponents();
183 this->forDiscretizationOnMeshTargets( domain.
getMeshBodies(), [&] (
string const &,
187 ElementRegionManager const & elemManager = mesh.getElemManager();
189 string const flowDofKey = dofManager.getKey( this->getFlowDofKey() );
191 globalIndex const rankOffset = dofManager.rankOffset();
193 NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager();
194 FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager();
195 FluxApproximationBase const & stabilizationMethod = fvManager.getFluxApproximation( this->solidMechanicsSolver()->getStabilizationName() );
197 stabilizationMethod.forStencils< SurfaceElementStencil >( mesh, [&]( SurfaceElementStencil const & stencil )
199 for( localIndex iconn=0; iconn<stencil.size(); ++iconn )
201 localIndex const numFluxElems = stencil.stencilSize( iconn );
202 typename SurfaceElementStencil::IndexContainerViewConstType const & seri = stencil.getElementRegionIndices();
203 typename SurfaceElementStencil::IndexContainerViewConstType const & sesri = stencil.getElementSubRegionIndices();
204 typename SurfaceElementStencil::IndexContainerViewConstType const & sei = stencil.getElementIndices();
206 FaceElementSubRegion const & elementSubRegion =
207 elemManager.getRegion( seri[iconn][0] ).getSubRegion< FaceElementSubRegion >( sesri[iconn][0] );
209 ArrayOfArraysView< localIndex const > const elemsToNodes = elementSubRegion.nodeList().toViewConst();
211 arrayView1d< globalIndex const > const faceElementDofNumber =
212 elementSubRegion.getReference< array1d< globalIndex > >( flowDofKey );
214 for( localIndex k0=0; k0<numFluxElems; ++k0 )
216 globalIndex const activeFlowDOF = faceElementDofNumber[sei[iconn][k0]];
217 globalIndex const rowNumber = activeFlowDOF - rankOffset;
219 if( rowNumber >= 0 && rowNumber < rowLengths.size() )
221 for( localIndex k1=0; k1<numFluxElems; ++k1 )
227 localIndex const numNodesPerElement = elemsToNodes[sei[iconn][k1]].size();
228 for( integer ic = 0; ic < numComp; ic++ )
230 rowLengths[rowNumber + ic] += 3*numNodesPerElement;
254 integer const numComp = numFluidComponents();
256 this->forDiscretizationOnMeshTargets( domain.
getMeshBodies(), [&] (
string const &,
260 FaceManager const & faceManager = mesh.getFaceManager();
261 NodeManager const & nodeManager = mesh.getNodeManager();
262 ElementRegionManager const & elemManager = mesh.getElemManager();
264 string const dispDofKey = dofManager.getKey( fields::solidMechanics::totalDisplacement::key() );
265 string const flowDofKey = dofManager.getKey( this->getFlowDofKey() );
267 arrayView1d< globalIndex const > const &
268 dispDofNumber = nodeManager.getReference< globalIndex_array >( dispDofKey );
269 ArrayOfArraysView< localIndex const > const & faceToNodeMap = faceManager.nodeList().toViewConst();
272 NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager();
273 FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager();
274 FluxApproximationBase const & fvDiscretization = fvManager.getFluxApproximation( this->flowSolver()->getDiscretizationName() );
276 SurfaceElementRegion const & fractureRegion =
277 elemManager.getRegion< SurfaceElementRegion >( this->solidMechanicsSolver()->getUniqueFractureRegionName() );
278 FaceElementSubRegion const & fractureSubRegion =
279 fractureRegion.getUniqueSubRegion< FaceElementSubRegion >();
281 GEOS_ERROR_IF( !fractureSubRegion.hasWrapper( fields::flow::pressure::key() ),
282 "The fracture subregion must contain pressure field.", this->getDataContext() );
284 arrayView2d< localIndex const > const elem2dToFaces = fractureSubRegion.faceList().toViewConst();
286 arrayView1d< globalIndex const > const &
287 flowDofNumber = fractureSubRegion.getReference< globalIndex_array >( flowDofKey );
289 globalIndex const rankOffset = dofManager.rankOffset();
291 fvDiscretization.forStencils< SurfaceElementStencil >( mesh, [&]( SurfaceElementStencil const & stencil )
293 forAll< serialPolicy >( stencil.size(), [=] ( localIndex const iconn )
295 localIndex const numFluxElems = stencil.stencilSize( iconn );
298 if( numFluxElems == 2 )
300 typename SurfaceElementStencil::IndexContainerViewConstType const & sei = stencil.getElementIndices();
303 for( localIndex kf = 0; kf < 2; ++kf )
308 localIndex const rowIndex = flowDofNumber[sei[iconn][1-kf]] - rankOffset;
310 if( rowIndex >= 0 && rowIndex < pattern.numRows() )
314 localIndex const fractureIndex = sei[iconn][kf];
317 localIndex const numNodesPerFace = faceToNodeMap.sizeOfArray( elem2dToFaces[fractureIndex][0] );
320 for( localIndex kf1 = 0; kf1 < 2; ++kf1 )
322 localIndex const faceIndex = elem2dToFaces[fractureIndex][kf1];
325 for( localIndex a=0; a<numNodesPerFace; ++a )
327 for( localIndex i = 0; i < 3; ++i )
329 globalIndex const colIndex = dispDofNumber[faceToNodeMap( faceIndex, a )] + LvArray::integerConversion< globalIndex >( i );
330 for( integer ic = 0; ic < numComp; ic++ )
332 pattern.insertNonZero( rowIndex + ic, colIndex );
352 integer const numComp = numFluidComponents();
358 this->forDiscretizationOnMeshTargets( domain.
getMeshBodies(), [&] (
string const & meshName,
362 std::unique_ptr< CRSMatrix< real64, localIndex > > & derivativeFluxResidual_dAperture = getRefDerivativeFluxResidual_dAperture();
368 GEOS_ERROR_IF_GT_MSG( numMeshTargets, 1,
369 GEOS_FMT(
"{}: this solver supports a single mesh target; '{}' is the second.",
370 this->getName(), meshName ) );
372 localIndex numRows = 0;
373 localIndex numCol = 0;
376 mesh.getElemManager().forElementSubRegions< FaceElementSubRegion >( regionNames,
377 [&]( localIndex const, FaceElementSubRegion const & subRegion )
379 numRows += subRegion.size();
386 derivativeFluxResidual_dAperture = std::make_unique< CRSMatrix< real64, localIndex > >( numRows, numCol );
387 derivativeFluxResidual_dAperture->setName( this->getName() +
"/derivativeFluxResidual_dAperture" );
394 for(
localIndex iconn = 0; iconn < stencil.size(); ++iconn )
396 localIndex const numFluxElems = stencil.stencilSize( iconn );
399 for(
localIndex k0 = 0; k0 < numFluxElems; ++k0 )
404 "Surface stencil index exceeds the fracture derivative matrix size." );
405 for(
integer ic = 0; ic < numComp; ic++ )
407 rowCapacities[sei[iconn][k0] * numComp + ic] += numFluxElems;
415 derivativeFluxResidual_dAperture->resizeFromRowCapacities< parallelHostPolicy >( numRows,
417 rowCapacities.data() );
422 for(
localIndex iconn = 0; iconn < stencil.size(); ++iconn )
424 localIndex const numFluxElems = stencil.stencilSize( iconn );
427 for(
localIndex k0 = 0; k0 < numFluxElems; ++k0 )
430 "Surface stencil index exceeds the fracture derivative matrix size." );
431 for(
localIndex k1 = 0; k1 < numFluxElems; ++k1 )
433 for(
integer ic = 0; ic < numComp; ++ic )
435 derivativeFluxResidual_dAperture->insertNonZero( sei[iconn][k0] * numComp + ic,
457 Base::assembleElementBasedTerms( time_n, dt, domain, dofManager, localMatrix, localRhs );
460 this->forDiscretizationOnMeshTargets( domain.
getMeshBodies(), [&] (
string const &,
464 mesh.getElemManager().forElementSubRegions< FaceElementSubRegion >( regionNames, [&]( localIndex const,
465 FaceElementSubRegion const & subRegion )
467 this->flowSolver()->accumulationAssemblyLaunch( dofManager, subRegion, localMatrix, localRhs );
471 this->solidMechanicsSolver()->assembleContact( domain, dofManager, localMatrix, localRhs );
483 this->forDiscretizationOnMeshTargets( domain.
getMeshBodies(), [&] (
string const &,
488 assembleForceResidualDerivativeWrtPressure( mesh, regionNames, dofManager, localMatrix, localRhs );
489 assembleFluidMassResidualDerivativeWrtDisplacement( mesh, regionNames, dofManager, localMatrix, localRhs );
493 void assembleForceResidualDerivativeWrtPressure(
MeshLevel const & mesh,
513 string const & dispDofKey = dofManager.
getKey( fields::solidMechanics::totalDisplacement::key() );
514 string const & flowDofKey = dofManager.
getKey( this->getFlowDofKey() );
532 forAll< serialPolicy >( subRegion.size(), [=,
this](
localIndex const kfe )
534 localIndex const kf0 = elemsToFaces[kfe][0];
535 localIndex const numNodesPerFace = faceToNodeMap.sizeOfArray( kf0 );
538 Nbar[ 0 ] = faceNormal[elemsToFaces[kfe][0]][0] - faceNormal[elemsToFaces[kfe][1]][0];
539 Nbar[ 1 ] = faceNormal[elemsToFaces[kfe][0]][1] - faceNormal[elemsToFaces[kfe][1]][1];
540 Nbar[ 2 ] = faceNormal[elemsToFaces[kfe][0]][2] - faceNormal[elemsToFaces[kfe][1]][2];
541 LvArray::tensorOps::normalize< 3 >( Nbar );
542 globalIndex rowDOF[3 * m_maxFaceNodes];
543 real64 nodeRHS[3 * m_maxFaceNodes];
544 stackArray1d< real64, 3 * m_maxFaceNodes > dRdP( 3*m_maxFaceNodes );
545 globalIndex colDOF[1];
546 colDOF[0] = flowDofNumber[kfe];
548 for( localIndex kf=0; kf<2; ++kf )
550 localIndex const faceIndex = elemsToFaces[kfe][kf];
553 stackArray1d< real64, FaceManager::maxFaceNodes() > nodalArea;
554 this->solidMechanicsSolver()->computeFaceNodalArea( elemsToFaces[kfe][kf],
563 for( localIndex a=0; a<numNodesPerFace; ++a )
565 real64 const nodalForceMag = -( pressure[kfe] ) * nodalArea[a];
566 real64 globalNodalForce[ 3 ];
567 LvArray::tensorOps::scaledCopy< 3 >( globalNodalForce, Nbar, nodalForceMag );
569 for( localIndex i=0; i<3; ++i )
571 rowDOF[3*a+i] = dispDofNumber[faceToNodeMap( faceIndex, a )] + LvArray::integerConversion< globalIndex >( i );
573 nodeRHS[3*a+i] = +globalNodalForce[i] * pow( -1, kf );
576 dRdP( 3*a+i ) = -nodalArea[a] * Nbar[i] * pow( -1, kf );
580 for( localIndex idof = 0; idof < numNodesPerFace * 3; ++idof )
582 localIndex const localRow = LvArray::integerConversion< localIndex >( rowDOF[idof] - rankOffset );
584 if( localRow >= 0 && localRow < localMatrix.numRows() )
586 localMatrix.addToRow< parallelHostAtomic >( localRow,
590 RAJA::atomicAdd( parallelHostAtomic{}, &localRhs[localRow], nodeRHS[idof] );
598 virtual void assembleFluidMassResidualDerivativeWrtDisplacement( MeshLevel
const & mesh,
600 DofManager
const & dofManager,
601 CRSMatrixView< real64, globalIndex const >
const & localMatrix,
602 arrayView1d< real64 >
const & localRhs ) = 0;
609 if( solverType ==
static_cast< integer >( Base::SolverType::SolidMechanics )
610 && !this->m_performStressInitialization )
613 this->flowSolver()->prepareStencilWeights( domain );
615 updateHydraulicApertureAndFracturePermeability( domain );
618 this->flowSolver()->updateStencilWeights( domain );
621 Base::mapSolutionBetweenSolvers( domain, solverType );
624 void updateHydraulicApertureAndFracturePermeability(
DomainPartition & domain )
626 using namespace constitutive;
628 this->forDiscretizationOnMeshTargets( domain.
getMeshBodies(), [&] (
string const &,
632 ElementRegionManager & elemManager = mesh.getElemManager();
634 elemManager.forElementSubRegions< FaceElementSubRegion >( regionNames,
635 [&]( localIndex const,
636 FaceElementSubRegion & subRegion )
638 arrayView2d< real64 const > const dispJump = subRegion.getField< fields::contact::dispJump >();
639 arrayView1d< real64 const > const area = subRegion.getElementArea();
640 arrayView1d< real64 const > const volume = subRegion.getElementVolume();
641 arrayView2d< real64 const > const fractureTraction = subRegion.getField< fields::contact::traction >();
642 arrayView1d< real64 const > const pressure = subRegion.getField< fields::flow::pressure >();
643 arrayView1d< real64 const > const oldHydraulicAperture = subRegion.getField< fields::flow::aperture0 >();
645 arrayView1d< real64 > const aperture = subRegion.getElementAperture();
646 arrayView1d< real64 > const hydraulicAperture = subRegion.getField< fields::flow::hydraulicAperture >();
647 arrayView1d< real64 > const deltaVolume = subRegion.getField< fields::flow::deltaVolume >();
648 arrayView1d< integer > const & fractureState = subRegion.getField< fields::contact::fractureState >();
650 string const porousSolidName = subRegion.getReference< string >( FlowSolverBase::viewKeyStruct::solidNamesString() );
651 CoupledSolidBase & porousSolid = subRegion.getConstitutiveModel< CoupledSolidBase >( porousSolidName );
653 string const & hydraulicApertureRelationName = subRegion.template getReference< string >( viewKeyStruct::hydraulicApertureRelationNameString() );
654 HydraulicApertureBase const & hydraulicApertureModel = this->template getConstitutiveModel< HydraulicApertureBase >( subRegion, hydraulicApertureRelationName );
656 constitutiveUpdatePassThru( hydraulicApertureModel, [&] ( auto & castedHydraulicAperture )
658 using HydraulicApertureType = TYPEOFREF( castedHydraulicAperture );
659 typename HydraulicApertureType::KernelWrapper hydraulicApertureWrapper = castedHydraulicAperture.createKernelWrapper();
661 ConstitutivePassThru< CompressibleSolidBase >::execute( porousSolid, [=, &subRegion] ( auto & castedPorousSolid )
663 typename TYPEOFREF( castedPorousSolid ) ::KernelWrapper porousMaterialWrapper = castedPorousSolid.createKernelUpdates();
665 poromechanicsFracturesKernels::StateUpdateKernel::
666 launch< parallelDevicePolicy<> >( subRegion.size(),
667 porousMaterialWrapper,
668 hydraulicApertureWrapper,
675 oldHydraulicAperture,
686 std::unique_ptr< CRSMatrix< real64, localIndex > > & getRefDerivativeFluxResidual_dAperture()
688 return m_derivativeFluxResidual_dAperture;
691 CRSMatrixView< real64, localIndex const > getDerivativeFluxResidual_dNormalJump()
693 return m_derivativeFluxResidual_dAperture->toViewConstSizes();
696 CRSMatrixView< real64 const, localIndex const > getDerivativeFluxResidual_dNormalJump()
const
698 return m_derivativeFluxResidual_dAperture->toViewConst();
701 virtual integer numFluidComponents()
const = 0;
708 std::unique_ptr< CRSMatrix< real64, localIndex > > m_derivativeFluxResidual_dAperture;
#define GEOS_UNUSED_VAR(...)
Mark an unused variable and silence compiler warnings.
#define GEOS_ERROR_IF_GE_MSG(lhs, rhs,...)
Raise a hard error if one value compares greater than or equal to the other.
#define GEOS_MARK_FUNCTION
Mark function with both Caliper and NVTX if enabled.
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.
NumericalMethodsManager const & getNumericalMethodManager() const
This class provides an interface to ObjectManagerBase in order to manage edge data.
NodeMapType & nodeList()
Get a node list.
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...
The FaceManager class provides an interface to ObjectManagerBase in order to manage face data.
array2d< real64 > & faceNormal()
Get a mutable accessor to an array containing all the face normals.
array1d< real64 > & faceArea()
Get a mutable accessor to an array containing all the face area.
array2d< real64 > & faceCenter()
Get a mutable accessor to an array containing all the face center.
NodeMapType & nodeList()
Get a mutable accessor to a map containing the list of each nodes for each faces.
EdgeMapType & edgeList()
Get a mutable accessor to a map containing the list of each edges for each faces.
FluxApproximationBase const & getFluxApproximation(string const &name) const
Return the FluxApproximation associated with the provided name.
void forStencils(MeshLevel const &mesh, LAMBDA &&lambda) const
Call a user-provided function for the each stencil according to the provided TYPE.
Class facilitating the representation of a multi-level discretization of a MeshBody.
NodeManager const & getNodeManager() const
Get the node manager.
FaceManager const & getFaceManager() const
Get the face manager.
ElementRegionManager const & getElemManager() const
Get the element region manager.
EdgeManager const & getEdgeManager() const
Get the edge manager.
The NodeManager class provides an interface to ObjectManagerBase in order to manage node data.
FiniteVolumeManager & getFiniteVolumeManager()
Provides management of the interior stencil points for a face elements when using Two-Point flux appr...
GEOS_DECLTYPE_AUTO_RETURN getReference(LOOKUP_TYPE const &lookup) const
Look up a wrapper and get reference to wrapped object.
array2d< real64, nodes::REFERENCE_POSITION_PERM > & referencePosition()
Get the mutable reference position array. This table will contain all the node coordinates.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
stdVector< string > string_array
A 1-dimensional array of geos::string types.
GEOS_GLOBALINDEX_TYPE globalIndex
Global index type (for indexing objects across MPI partitions).
array1d< globalIndex > globalIndex_array
A 1-dimensional array of geos::globalIndex types.
LvArray::CRSMatrix< T, COL_INDEX, INDEX_TYPE, LvArray::ChaiBuffer > CRSMatrix
Alias for CRS Matrix class.
LvArray::SparsityPatternView< COL_INDEX, INDEX_TYPE const, LvArray::ChaiBuffer > SparsityPatternView
Alias for Sparsity pattern View.
LvArray::SparsityPattern< COL_INDEX, INDEX_TYPE, LvArray::ChaiBuffer > SparsityPattern
Alias for Sparsity pattern class.
LvArray::ArrayOfArraysView< T, INDEX_TYPE const, CONST_SIZES, LvArray::ChaiBuffer > ArrayOfArraysView
View of array of variable-sized arrays. See LvArray::ArrayOfArraysView for details.
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.
void appendSparsityPattern(SparsityPattern< globalIndex > &target, SparsityPattern< globalIndex > const &source)
Append all entries from one sparsity pattern to another.
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
int integer
Signed integer type.
Array< T, 1 > array1d
Alias for 1D array.
LvArray::typeManipulation::NestedViewTypeConst< IndexContainerType > IndexContainerViewConstType
The array view to const type for the stencil indices.