21 #ifndef GEOS_PHYSICSSOLVERS_MULTIPHYSICS_POROMECHANICSCONFORMINGFRACTURES_HPP_
22 #define GEOS_PHYSICSSOLVERS_MULTIPHYSICS_POROMECHANICSCONFORMINGFRACTURES_HPP_
30 #include "constitutive/solid/CoupledSolidBase.hpp"
31 #include "constitutive/contact/HydraulicApertureBase.hpp"
32 #include "constitutive/contact/HydraulicApertureRelationSelector.hpp"
40 template<
template<
typename,
typename >
class POROMECHANICS_BASE,
typename FLOW_SOLVER >
44 using Base = POROMECHANICS_BASE< FLOW_SOLVER, SolidMechanicsLagrangeContact >;
48 : Base( name, parent )
56 Base::setupCoupling( domain, dofManager );
60 fields::contact::traction::key(),
69 bool const setSparsity =
true )
override
77 this->setupDofs( domain, dofManager );
88 for(
localIndex localRow = 0; localRow < patternOriginal.numRows(); ++localRow )
90 rowLengths[localRow] = patternOriginal.numNonZeros( localRow );
98 pattern.resizeFromRowCapacities< parallelHostPolicy >( patternOriginal.numRows(),
99 patternOriginal.numColumns(),
103 for(
localIndex localRow = 0; localRow < patternOriginal.numRows(); ++localRow )
105 globalIndex const * cols = patternOriginal.getColumns( localRow ).dataIfContiguous();
106 pattern.insertNonZeros( localRow, cols, cols + patternOriginal.numNonZeros( localRow ) );
112 localMatrix.setName( this->getName() +
"/matrix" );
113 localMatrix.assimilate< parallelDevicePolicy<> >( std::move( pattern ) );
115 rhs.setName( this->getName() +
"/rhs" );
118 solution.setName( this->getName() +
"/solution" );
129 virtual void assembleSystem(
real64 const time_n,
139 this->solidMechanicsSolver()->synchronizeFractureState( domain );
149 this->flowSolver()->assembleHydrofracFluxTerms( time_n,
155 getDerivativeFluxResidual_dNormalJump() );
166 virtual void updateState( DomainPartition & domain )
override
171 Base::updateState( domain );
173 this->solidMechanicsSolver()->updateState( domain );
176 this->flowSolver()->prepareStencilWeights( domain );
178 updateHydraulicApertureAndFracturePermeability( domain );
181 this->flowSolver()->updateStencilWeights( domain );
198 this->forDiscretizationOnMeshTargets( domain.
getMeshBodies(), [&] (
string const &,
202 ElementRegionManager const & elemManager = mesh.getElemManager();
204 string const flowDofKey = dofManager.getKey( getFlowDofKey() );
206 globalIndex const rankOffset = dofManager.rankOffset();
208 NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager();
209 FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager();
210 FluxApproximationBase const & stabilizationMethod = fvManager.getFluxApproximation( this->solidMechanicsSolver()->getStabilizationName() );
212 stabilizationMethod.forStencils< SurfaceElementStencil >( mesh, [&]( SurfaceElementStencil const & stencil )
214 for( localIndex iconn=0; iconn<stencil.size(); ++iconn )
216 localIndex const numFluxElems = stencil.stencilSize( iconn );
217 typename SurfaceElementStencil::IndexContainerViewConstType const & seri = stencil.getElementRegionIndices();
218 typename SurfaceElementStencil::IndexContainerViewConstType const & sesri = stencil.getElementSubRegionIndices();
219 typename SurfaceElementStencil::IndexContainerViewConstType const & sei = stencil.getElementIndices();
221 FaceElementSubRegion const & elementSubRegion =
222 elemManager.getRegion( seri[iconn][0] ).getSubRegion< FaceElementSubRegion >( sesri[iconn][0] );
224 ArrayOfArraysView< localIndex const > const elemsToNodes = elementSubRegion.nodeList().toViewConst();
226 arrayView1d< globalIndex const > const faceElementDofNumber =
227 elementSubRegion.getReference< array1d< globalIndex > >( flowDofKey );
229 for( localIndex k0=0; k0<numFluxElems; ++k0 )
231 globalIndex const activeFlowDOF = faceElementDofNumber[sei[iconn][k0]];
232 globalIndex const rowNumber = activeFlowDOF - rankOffset;
234 if( rowNumber >= 0 && rowNumber < rowLengths.size() )
236 for( localIndex k1=0; k1<numFluxElems; ++k1 )
242 localIndex const numNodesPerElement = elemsToNodes[sei[iconn][k1]].size();
243 rowLengths[rowNumber] += 3*numNodesPerElement;
266 this->forDiscretizationOnMeshTargets( domain.
getMeshBodies(), [&] (
string const &,
270 FaceManager const & faceManager = mesh.getFaceManager();
271 NodeManager const & nodeManager = mesh.getNodeManager();
272 ElementRegionManager const & elemManager = mesh.getElemManager();
274 string const dispDofKey = dofManager.getKey( fields::solidMechanics::totalDisplacement::key() );
275 string const flowDofKey = dofManager.getKey( getFlowDofKey() );
277 arrayView1d< globalIndex const > const &
278 dispDofNumber = nodeManager.getReference< globalIndex_array >( dispDofKey );
279 ArrayOfArraysView< localIndex const > const & faceToNodeMap = faceManager.nodeList().toViewConst();
282 NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager();
283 FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager();
284 FluxApproximationBase const & fvDiscretization = fvManager.getFluxApproximation( this->flowSolver()->getDiscretizationName() );
286 SurfaceElementRegion const & fractureRegion =
287 elemManager.getRegion< SurfaceElementRegion >( this->solidMechanicsSolver()->getUniqueFractureRegionName() );
288 FaceElementSubRegion const & fractureSubRegion =
289 fractureRegion.getUniqueSubRegion< FaceElementSubRegion >();
291 GEOS_ERROR_IF( !fractureSubRegion.hasWrapper( fields::flow::pressure::key() ),
292 this->getDataContext() <<
": The fracture subregion must contain pressure field." );
294 arrayView2d< localIndex const > const elem2dToFaces = fractureSubRegion.faceList().toViewConst();
296 arrayView1d< globalIndex const > const &
297 flowDofNumber = fractureSubRegion.getReference< globalIndex_array >( flowDofKey );
299 globalIndex const rankOffset = dofManager.rankOffset();
301 fvDiscretization.forStencils< SurfaceElementStencil >( mesh, [&]( SurfaceElementStencil const & stencil )
303 forAll< serialPolicy >( stencil.size(), [=] ( localIndex const iconn )
305 localIndex const numFluxElems = stencil.stencilSize( iconn );
308 if( numFluxElems == 2 )
310 typename SurfaceElementStencil::IndexContainerViewConstType const & sei = stencil.getElementIndices();
313 for( localIndex kf = 0; kf < 2; ++kf )
318 localIndex const rowIndex = flowDofNumber[sei[iconn][1-kf]] - rankOffset;
320 if( rowIndex >= 0 && rowIndex < pattern.numRows() )
324 localIndex const fractureIndex = sei[iconn][kf];
327 localIndex const numNodesPerFace = faceToNodeMap.sizeOfArray( elem2dToFaces[fractureIndex][0] );
330 for( localIndex kf1 = 0; kf1 < 2; ++kf1 )
332 localIndex const faceIndex = elem2dToFaces[fractureIndex][kf1];
335 for( localIndex a=0; a<numNodesPerFace; ++a )
337 for( localIndex i = 0; i < 3; ++i )
339 globalIndex const colIndex = dispDofNumber[faceToNodeMap( faceIndex, a )] + LvArray::integerConversion< globalIndex >( i );
340 pattern.insertNonZero( rowIndex, colIndex );
363 integer const numComp = numFluidComponents();
365 this->forDiscretizationOnMeshTargets( domain.
getMeshBodies(), [&] (
string const &,
369 std::unique_ptr< CRSMatrix< real64, localIndex > > & derivativeFluxResidual_dAperture = getRefDerivativeFluxResidual_dAperture();
373 localIndex numRows = 0;
374 mesh.getElemManager().forElementSubRegions< FaceElementSubRegion >( regionNames,
375 [&]( localIndex const, FaceElementSubRegion const & subRegion )
377 numRows += subRegion.size();
380 localIndex numCol = numRows;
384 derivativeFluxResidual_dAperture = std::make_unique< CRSMatrix< real64, localIndex > >( numRows, numCol );
385 derivativeFluxResidual_dAperture->setName( this->getName() +
"/derivativeFluxResidual_dAperture" );
387 derivativeFluxResidual_dAperture->reserveNonZeros( localMatrix.numNonZeros() );
388 localIndex maxRowSize = -1;
389 for( localIndex row = 0; row < localMatrix.numRows(); ++row )
391 localIndex const rowSize = localMatrix.numNonZeros( row );
392 maxRowSize = maxRowSize > rowSize ? maxRowSize : rowSize;
395 for( localIndex row = 0; row < numRows; ++row )
397 derivativeFluxResidual_dAperture->reserveNonZeros( row, maxRowSize );
403 FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( this->flowSolver()->getDiscretizationName() );
407 for( localIndex iconn = 0; iconn < stencil.size(); ++iconn )
409 localIndex const numFluxElems = stencil.stencilSize( iconn );
410 typename SurfaceElementStencil::IndexContainerViewConstType const & sei = stencil.getElementIndices();
412 for( localIndex k0 = 0; k0 < numFluxElems; ++k0 )
414 for( localIndex k1 = 0; k1 < numFluxElems; ++k1 )
416 for( integer ic = 0; ic < numComp; ic++ )
418 derivativeFluxResidual_dAperture->insertNonZero( sei[iconn][k0] * numComp + ic, sei[iconn][k1], 0.0 );
438 Base::assembleElementBasedTerms( time_n, dt, domain, dofManager, localMatrix, localRhs );
441 this->forDiscretizationOnMeshTargets( domain.
getMeshBodies(), [&] (
string const &,
445 mesh.getElemManager().forElementSubRegions< FaceElementSubRegion >( regionNames, [&]( localIndex const,
446 FaceElementSubRegion const & subRegion )
448 this->flowSolver()->accumulationAssemblyLaunch( dofManager, subRegion, localMatrix, localRhs );
452 this->solidMechanicsSolver()->assembleContact( domain, dofManager, localMatrix, localRhs );
464 this->forDiscretizationOnMeshTargets( domain.
getMeshBodies(), [&] (
string const &,
469 assembleForceResidualDerivativeWrtPressure( mesh, regionNames, dofManager, localMatrix, localRhs );
470 assembleFluidMassResidualDerivativeWrtDisplacement( mesh, regionNames, dofManager, localMatrix, localRhs );
474 void assembleForceResidualDerivativeWrtPressure(
MeshLevel const & mesh,
494 string const & dispDofKey = dofManager.
getKey( fields::solidMechanics::totalDisplacement::key() );
495 string const & flowDofKey = dofManager.
getKey( getFlowDofKey() );
513 forAll< serialPolicy >( subRegion.size(), [=](
localIndex const kfe )
515 localIndex const kf0 = elemsToFaces[kfe][0];
516 localIndex const numNodesPerFace = faceToNodeMap.sizeOfArray( kf0 );
519 Nbar[ 0 ] = faceNormal[elemsToFaces[kfe][0]][0] - faceNormal[elemsToFaces[kfe][1]][0];
520 Nbar[ 1 ] = faceNormal[elemsToFaces[kfe][0]][1] - faceNormal[elemsToFaces[kfe][1]][1];
521 Nbar[ 2 ] = faceNormal[elemsToFaces[kfe][0]][2] - faceNormal[elemsToFaces[kfe][1]][2];
522 LvArray::tensorOps::normalize< 3 >( Nbar );
523 globalIndex rowDOF[3 * m_maxFaceNodes];
524 real64 nodeRHS[3 * m_maxFaceNodes];
525 stackArray1d< real64, 3 * m_maxFaceNodes > dRdP( 3*m_maxFaceNodes );
526 globalIndex colDOF[1];
527 colDOF[0] = flowDofNumber[kfe];
529 for( localIndex kf=0; kf<2; ++kf )
531 localIndex const faceIndex = elemsToFaces[kfe][kf];
534 stackArray1d< real64, FaceManager::maxFaceNodes() > nodalArea;
535 this->solidMechanicsSolver()->computeFaceNodalArea( elemsToFaces[kfe][kf],
544 for( localIndex a=0; a<numNodesPerFace; ++a )
546 real64 const nodalForceMag = -( pressure[kfe] ) * nodalArea[a];
547 real64 globalNodalForce[ 3 ];
548 LvArray::tensorOps::scaledCopy< 3 >( globalNodalForce, Nbar, nodalForceMag );
550 for( localIndex i=0; i<3; ++i )
552 rowDOF[3*a+i] = dispDofNumber[faceToNodeMap( faceIndex, a )] + LvArray::integerConversion< globalIndex >( i );
554 nodeRHS[3*a+i] = +globalNodalForce[i] * pow( -1, kf );
557 dRdP( 3*a+i ) = -nodalArea[a] * Nbar[i] * pow( -1, kf );
561 for( localIndex idof = 0; idof < numNodesPerFace * 3; ++idof )
563 localIndex const localRow = LvArray::integerConversion< localIndex >( rowDOF[idof] - rankOffset );
565 if( localRow >= 0 && localRow < localMatrix.numRows() )
567 localMatrix.addToRow< parallelHostAtomic >( localRow,
571 RAJA::atomicAdd( parallelHostAtomic{}, &localRhs[localRow], nodeRHS[idof] );
579 virtual void assembleFluidMassResidualDerivativeWrtDisplacement( MeshLevel
const & mesh,
581 DofManager
const & dofManager,
582 CRSMatrixView< real64, globalIndex const >
const & localMatrix,
583 arrayView1d< real64 >
const & localRhs ) = 0;
585 void updateHydraulicApertureAndFracturePermeability( DomainPartition & domain )
587 using namespace constitutive;
589 this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] (
string const &,
593 ElementRegionManager & elemManager = mesh.getElemManager();
595 elemManager.forElementSubRegions< FaceElementSubRegion >( regionNames,
596 [&]( localIndex const,
597 FaceElementSubRegion & subRegion )
599 arrayView2d< real64 const > const dispJump = subRegion.getField< fields::contact::dispJump >();
600 arrayView1d< real64 const > const area = subRegion.getElementArea();
601 arrayView1d< real64 const > const volume = subRegion.getElementVolume();
602 arrayView2d< real64 const > const fractureTraction = subRegion.getField< fields::contact::traction >();
603 arrayView1d< real64 const > const pressure = subRegion.getField< fields::flow::pressure >();
604 arrayView1d< real64 const > const oldHydraulicAperture = subRegion.getField< fields::flow::aperture0 >();
606 arrayView1d< real64 > const aperture = subRegion.getElementAperture();
607 arrayView1d< real64 > const hydraulicAperture = subRegion.getField< fields::flow::hydraulicAperture >();
608 arrayView1d< real64 > const deltaVolume = subRegion.getField< fields::flow::deltaVolume >();
610 string const porousSolidName = subRegion.getReference< string >( FlowSolverBase::viewKeyStruct::solidNamesString() );
611 CoupledSolidBase & porousSolid = subRegion.getConstitutiveModel< CoupledSolidBase >( porousSolidName );
613 string const & hydraulicApertureRelationName = subRegion.template getReference< string >( viewKeyStruct::hydraulicApertureRelationNameString() );
614 HydraulicApertureBase const & hydraulicApertureModel = this->template getConstitutiveModel< HydraulicApertureBase >( subRegion, hydraulicApertureRelationName );
616 constitutiveUpdatePassThru( hydraulicApertureModel, [&] ( auto & castedHydraulicAperture )
618 using HydraulicApertureType = TYPEOFREF( castedHydraulicAperture );
619 typename HydraulicApertureType::KernelWrapper hydraulicApertureWrapper = castedHydraulicAperture.createKernelWrapper();
621 ConstitutivePassThru< CompressibleSolidBase >::execute( porousSolid, [=, &subRegion] ( auto & castedPorousSolid )
623 typename TYPEOFREF( castedPorousSolid ) ::KernelWrapper porousMaterialWrapper = castedPorousSolid.createKernelUpdates();
625 poromechanicsFracturesKernels::StateUpdateKernel::
626 launch< parallelDevicePolicy<> >( subRegion.size(),
627 porousMaterialWrapper,
628 hydraulicApertureWrapper,
635 oldHydraulicAperture,
645 std::unique_ptr< CRSMatrix< real64, localIndex > > & getRefDerivativeFluxResidual_dAperture()
647 return m_derivativeFluxResidual_dAperture;
650 CRSMatrixView< real64, localIndex const > getDerivativeFluxResidual_dNormalJump()
652 return m_derivativeFluxResidual_dAperture->toViewConstSizes();
655 CRSMatrixView< real64 const, localIndex const > getDerivativeFluxResidual_dNormalJump()
const
657 return m_derivativeFluxResidual_dAperture->toViewConst();
660 virtual string getFlowDofKey()
const = 0;
662 virtual integer numFluidComponents()
const = 0;
669 std::unique_ptr< CRSMatrix< real64, localIndex > > m_derivativeFluxResidual_dAperture;
#define GEOS_UNUSED_VAR(...)
Mark an unused variable and silence compiler warnings.
#define GEOS_UNUSED_PARAM(X)
Mark an unused argument and silence compiler warnings.
#define GEOS_MARK_FUNCTION
Mark function with both Caliper and NVTX if enabled.
The DoFManager is responsible for allocating global dofs, constructing sparsity patterns,...
void setSparsityPattern(SparsityPattern< globalIndex > &pattern) const
Populate sparsity pattern of the entire system matrix.
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.
void reorderByRank()
Finish populating fields and apply appropriate dof renumbering.
localIndex numLocalDofs(string const &fieldName) const
@ Elem
connectivity is element (like in finite elements)
void setDomain(DomainPartition &domain)
Assign a domain.
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.
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.
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.
int MPI_COMM_GEOS
Global MPI communicator used by GEOSX.
LvArray::CRSMatrixView< T, COL_INDEX, localIndex const, LvArray::ChaiBuffer > CRSMatrixView
Alias for CRS Matrix View.
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::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).
std::int32_t integer
Signed integer type.
LvArray::CRSMatrix< T, COL_INDEX, localIndex, LvArray::ChaiBuffer > CRSMatrix
Alias for CRS Matrix class.
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
Array< T, 1 > array1d
Alias for 1D array.
LAInterface::ParallelVector ParallelVector
Alias for ParallelVector.