GEOS
PoromechanicsConformingFractures.hpp
Go to the documentation of this file.
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2024 TotalEnergies
7  * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
8  * Copyright (c) 2023-2024 Chevron
9  * Copyright (c) 2019- GEOS/GEOSX Contributors
10  * All rights reserved
11  *
12  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
13  * ------------------------------------------------------------------------------------------------------------
14  */
15 
21 #ifndef GEOS_PHYSICSSOLVERS_MULTIPHYSICS_POROMECHANICSCONFORMINGFRACTURES_HPP_
22 #define GEOS_PHYSICSSOLVERS_MULTIPHYSICS_POROMECHANICSCONFORMINGFRACTURES_HPP_
23 
30 #include "constitutive/solid/CoupledSolidBase.hpp"
31 #include "constitutive/contact/HydraulicApertureBase.hpp"
32 #include "constitutive/contact/HydraulicApertureRelationSelector.hpp"
34 #include "common/DataTypes.hpp"
35 #include "mesh/DomainPartition.hpp"
36 
37 namespace geos
38 {
39 
40 template< template< typename, typename > class POROMECHANICS_BASE, typename FLOW_SOLVER >
41 class PoromechanicsConformingFractures : public POROMECHANICS_BASE< FLOW_SOLVER, SolidMechanicsLagrangeContact >
42 {
43 public:
44  using Base = POROMECHANICS_BASE< FLOW_SOLVER, SolidMechanicsLagrangeContact >;
45 
46  PoromechanicsConformingFractures( const string & name,
47  dataRepository::Group * const parent )
48  : Base( name, parent )
49  {}
50 
51  virtual void setupCoupling( DomainPartition const & domain,
52  DofManager & dofManager ) const override
53  {
55  // 1. Poromechanical coupling in the bulk
56  Base::setupCoupling( domain, dofManager );
57 
58  // 2. Traction - pressure coupling in the fracture
59  dofManager.addCoupling( getFlowDofKey(),
60  fields::contact::traction::key(),
62  }
63 
64  virtual void setupSystem( DomainPartition & domain,
65  DofManager & dofManager,
67  ParallelVector & rhs,
68  ParallelVector & solution,
69  bool const setSparsity = true ) override
70  {
72 
73  GEOS_UNUSED_VAR( setSparsity );
74 
76  dofManager.setDomain( domain );
77  this->setupDofs( domain, dofManager );
78  dofManager.reorderByRank();
79 
81  localIndex const numLocalRows = dofManager.numLocalDofs();
82 
83  SparsityPattern< globalIndex > patternOriginal;
84  dofManager.setSparsityPattern( patternOriginal );
85 
86  // Get the original row lengths (diagonal blocks only)
87  array1d< localIndex > rowLengths( patternOriginal.numRows() );
88  for( localIndex localRow = 0; localRow < patternOriginal.numRows(); ++localRow )
89  {
90  rowLengths[localRow] = patternOriginal.numNonZeros( localRow );
91  }
92 
93  // Add the number of nonzeros induced by coupling
94  addTransmissibilityCouplingNNZ( domain, dofManager, rowLengths.toView() );
95 
96  // Create a new pattern with enough capacity for coupled matrix
98  pattern.resizeFromRowCapacities< parallelHostPolicy >( patternOriginal.numRows(),
99  patternOriginal.numColumns(),
100  rowLengths.data() );
101 
102  // Copy the original nonzeros
103  for( localIndex localRow = 0; localRow < patternOriginal.numRows(); ++localRow )
104  {
105  globalIndex const * cols = patternOriginal.getColumns( localRow ).dataIfContiguous();
106  pattern.insertNonZeros( localRow, cols, cols + patternOriginal.numNonZeros( localRow ) );
107  }
108 
109  // Add the nonzeros from coupling
110  addTransmissibilityCouplingPattern( domain, dofManager, pattern.toView() );
111 
112  localMatrix.setName( this->getName() + "/matrix" );
113  localMatrix.assimilate< parallelDevicePolicy<> >( std::move( pattern ) );
114 
115  rhs.setName( this->getName() + "/rhs" );
116  rhs.create( numLocalRows, MPI_COMM_GEOS );
117 
118  solution.setName( this->getName() + "/solution" );
119  solution.create( numLocalRows, MPI_COMM_GEOS );
120 
121  setUpDflux_dApertureMatrix( domain, dofManager, localMatrix );
122 
123  // if( !m_precond && m_linearSolverParameters.get().solverType != LinearSolverParameters::SolverType::direct )
124  // {
125  // createPreconditioner( domain );
126  // }
127  }
128 
129  virtual void assembleSystem( real64 const time_n,
130  real64 const dt,
131  DomainPartition & domain,
132  DofManager const & dofManager,
133  CRSMatrixView< real64, globalIndex const > const & localMatrix,
134  arrayView1d< real64 > const & localRhs ) override
135  {
136 
138 
139  this->solidMechanicsSolver()->synchronizeFractureState( domain );
140 
142  dt,
143  domain,
144  dofManager,
145  localMatrix,
146  localRhs );
147 
148  // Assemble fluxes 3D/2D and get dFluidResidualDAperture
149  this->flowSolver()->assembleHydrofracFluxTerms( time_n,
150  dt,
151  domain,
152  dofManager,
153  localMatrix,
154  localRhs,
155  getDerivativeFluxResidual_dNormalJump() );
156 
157  // This step must occur after the fluxes are assembled because that's when DerivativeFluxResidual_dAperture is filled.
158  assembleCouplingTerms( time_n,
159  dt,
160  domain,
161  dofManager,
162  localMatrix,
163  localRhs );
164  }
165 
166  virtual void updateState( DomainPartition & domain ) override
167  {
169 
170  // call base poromechanics update
171  Base::updateState( domain );
172  // need to call solid mechanics update separately to compute face displacement jump
173  this->solidMechanicsSolver()->updateState( domain );
174 
175  // remove the contribution of the hydraulic aperture from the stencil weights
176  this->flowSolver()->prepareStencilWeights( domain );
177 
178  updateHydraulicApertureAndFracturePermeability( domain );
179 
180  // update the stencil weights using the updated hydraulic aperture
181  this->flowSolver()->updateStencilWeights( domain );
182  }
183 
184 protected:
185 
193  DofManager const & dofManager,
194  arrayView1d< localIndex > const & rowLengths ) const
195  {
197 
198  this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, // meshBodyName,
199  MeshLevel const & mesh,
200  string_array const & ) // regionNames
201  {
202  ElementRegionManager const & elemManager = mesh.getElemManager();
203 
204  string const flowDofKey = dofManager.getKey( getFlowDofKey() );
205 
206  globalIndex const rankOffset = dofManager.rankOffset();
207 
208  NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager();
209  FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager();
210  FluxApproximationBase const & stabilizationMethod = fvManager.getFluxApproximation( this->solidMechanicsSolver()->getStabilizationName() );
211 
212  stabilizationMethod.forStencils< SurfaceElementStencil >( mesh, [&]( SurfaceElementStencil const & stencil )
213  {
214  for( localIndex iconn=0; iconn<stencil.size(); ++iconn )
215  {
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();
220 
221  FaceElementSubRegion const & elementSubRegion =
222  elemManager.getRegion( seri[iconn][0] ).getSubRegion< FaceElementSubRegion >( sesri[iconn][0] );
223 
224  ArrayOfArraysView< localIndex const > const elemsToNodes = elementSubRegion.nodeList().toViewConst();
225 
226  arrayView1d< globalIndex const > const faceElementDofNumber =
227  elementSubRegion.getReference< array1d< globalIndex > >( flowDofKey );
228 
229  for( localIndex k0=0; k0<numFluxElems; ++k0 )
230  {
231  globalIndex const activeFlowDOF = faceElementDofNumber[sei[iconn][k0]];
232  globalIndex const rowNumber = activeFlowDOF - rankOffset;
233 
234  if( rowNumber >= 0 && rowNumber < rowLengths.size() )
235  {
236  for( localIndex k1=0; k1<numFluxElems; ++k1 )
237  {
238  // The coupling with the nodal displacements of the cell itself has already been added by the dofManager
239  // so we only add the coupling with the nodal displacements of the neighbors.
240  if( k1 != k0 )
241  {
242  localIndex const numNodesPerElement = elemsToNodes[sei[iconn][k1]].size();
243  rowLengths[rowNumber] += 3*numNodesPerElement;
244  }
245  }
246  }
247  }
248  }
249  } );
250  } );
251  }
252 
261  DofManager const & dofManager,
262  SparsityPatternView< globalIndex > const & pattern ) const
263  {
265 
266  this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &,
267  MeshLevel const & mesh,
268  string_array const & )
269  {
270  FaceManager const & faceManager = mesh.getFaceManager();
271  NodeManager const & nodeManager = mesh.getNodeManager();
272  ElementRegionManager const & elemManager = mesh.getElemManager();
273 
274  string const dispDofKey = dofManager.getKey( fields::solidMechanics::totalDisplacement::key() );
275  string const flowDofKey = dofManager.getKey( getFlowDofKey() );
276 
277  arrayView1d< globalIndex const > const &
278  dispDofNumber = nodeManager.getReference< globalIndex_array >( dispDofKey );
279  ArrayOfArraysView< localIndex const > const & faceToNodeMap = faceManager.nodeList().toViewConst();
280 
281  // Get the finite volume method used to compute the stabilization
282  NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager();
283  FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager();
284  FluxApproximationBase const & fvDiscretization = fvManager.getFluxApproximation( this->flowSolver()->getDiscretizationName() );
285 
286  SurfaceElementRegion const & fractureRegion =
287  elemManager.getRegion< SurfaceElementRegion >( this->solidMechanicsSolver()->getUniqueFractureRegionName() );
288  FaceElementSubRegion const & fractureSubRegion =
289  fractureRegion.getUniqueSubRegion< FaceElementSubRegion >();
290 
291  GEOS_ERROR_IF( !fractureSubRegion.hasWrapper( fields::flow::pressure::key() ),
292  this->getDataContext() << ": The fracture subregion must contain pressure field." );
293 
294  arrayView2d< localIndex const > const elem2dToFaces = fractureSubRegion.faceList().toViewConst();
295 
296  arrayView1d< globalIndex const > const &
297  flowDofNumber = fractureSubRegion.getReference< globalIndex_array >( flowDofKey );
298 
299  globalIndex const rankOffset = dofManager.rankOffset();
300 
301  fvDiscretization.forStencils< SurfaceElementStencil >( mesh, [&]( SurfaceElementStencil const & stencil )
302  {
303  forAll< serialPolicy >( stencil.size(), [=] ( localIndex const iconn )
304  {
305  localIndex const numFluxElems = stencil.stencilSize( iconn );
306 
307  // A fracture connector has to be an edge shared by two faces
308  if( numFluxElems == 2 )
309  {
310  typename SurfaceElementStencil::IndexContainerViewConstType const & sei = stencil.getElementIndices();
311 
312  // First index: face element. Second index: node
313  for( localIndex kf = 0; kf < 2; ++kf )
314  {
315  // Set row DOF index
316  // Note that the 1-kf index is intentional, as this is coupling the pressure of one face cell
317  // to the nodes of the adjacent cell
318  localIndex const rowIndex = flowDofNumber[sei[iconn][1-kf]] - rankOffset;
319 
320  if( rowIndex >= 0 && rowIndex < pattern.numRows() )
321  {
322 
323  // Get fracture, face and region/subregion/element indices (for elements on both sides)
324  localIndex const fractureIndex = sei[iconn][kf];
325 
326  // Get the number of nodes
327  localIndex const numNodesPerFace = faceToNodeMap.sizeOfArray( elem2dToFaces[fractureIndex][0] );
328 
329  // Loop over the two sides of each fracture element
330  for( localIndex kf1 = 0; kf1 < 2; ++kf1 )
331  {
332  localIndex const faceIndex = elem2dToFaces[fractureIndex][kf1];
333 
334  // Save the list of DOF associated with nodes
335  for( localIndex a=0; a<numNodesPerFace; ++a )
336  {
337  for( localIndex i = 0; i < 3; ++i )
338  {
339  globalIndex const colIndex = dispDofNumber[faceToNodeMap( faceIndex, a )] + LvArray::integerConversion< globalIndex >( i );
340  pattern.insertNonZero( rowIndex, colIndex );
341  }
342  }
343  }
344  }
345  }
346  }
347  } );
348  } );
349  } );
350  }
351 
360  DofManager const & GEOS_UNUSED_PARAM( dofManager ),
361  CRSMatrix< real64, globalIndex > & localMatrix )
362  {
363  integer const numComp = numFluidComponents();
364 
365  this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &,
366  MeshLevel const & mesh,
367  string_array const & regionNames )
368  {
369  std::unique_ptr< CRSMatrix< real64, localIndex > > & derivativeFluxResidual_dAperture = getRefDerivativeFluxResidual_dAperture();
370 
371  {
372  // calculate number of fracture elements
373  localIndex numRows = 0;
374  mesh.getElemManager().forElementSubRegions< FaceElementSubRegion >( regionNames,
375  [&]( localIndex const, FaceElementSubRegion const & subRegion )
376  {
377  numRows += subRegion.size();
378  } );
379  // number of columns (derivatives) = number of fracture elements
380  localIndex numCol = numRows;
381  // number of rows (equations) = number of fracture elements * number of components
382  numRows *= numComp;
383 
384  derivativeFluxResidual_dAperture = std::make_unique< CRSMatrix< real64, localIndex > >( numRows, numCol );
385  derivativeFluxResidual_dAperture->setName( this->getName() + "/derivativeFluxResidual_dAperture" );
386 
387  derivativeFluxResidual_dAperture->reserveNonZeros( localMatrix.numNonZeros() );
388  localIndex maxRowSize = -1;
389  for( localIndex row = 0; row < localMatrix.numRows(); ++row )
390  {
391  localIndex const rowSize = localMatrix.numNonZeros( row );
392  maxRowSize = maxRowSize > rowSize ? maxRowSize : rowSize;
393  }
394  // TODO This is way too much. The With the full system rowSize is not a good estimate for this.
395  for( localIndex row = 0; row < numRows; ++row )
396  {
397  derivativeFluxResidual_dAperture->reserveNonZeros( row, maxRowSize );
398  }
399  }
400 
401  NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager();
402  FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager();
403  FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( this->flowSolver()->getDiscretizationName() );
404 
405  fluxApprox.forStencils< SurfaceElementStencil >( mesh, [&]( SurfaceElementStencil const & stencil )
406  {
407  for( localIndex iconn = 0; iconn < stencil.size(); ++iconn )
408  {
409  localIndex const numFluxElems = stencil.stencilSize( iconn );
410  typename SurfaceElementStencil::IndexContainerViewConstType const & sei = stencil.getElementIndices();
411 
412  for( localIndex k0 = 0; k0 < numFluxElems; ++k0 )
413  {
414  for( localIndex k1 = 0; k1 < numFluxElems; ++k1 )
415  {
416  for( integer ic = 0; ic < numComp; ic++ )
417  {
418  derivativeFluxResidual_dAperture->insertNonZero( sei[iconn][k0] * numComp + ic, sei[iconn][k1], 0.0 );
419  }
420  }
421  }
422  }
423  } );
424  } );
425  }
426 
428  real64 const dt,
429  DomainPartition & domain,
430  DofManager const & dofManager,
431  CRSMatrixView< real64, globalIndex const > const & localMatrix,
432  arrayView1d< real64 > const & localRhs )
433  {
434  GEOS_UNUSED_VAR( time_n, dt );
435 
437 
438  Base::assembleElementBasedTerms( time_n, dt, domain, dofManager, localMatrix, localRhs );
439 
440  // Flow accumulation for fractures
441  this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &,
442  MeshLevel & mesh,
443  string_array const & regionNames )
444  {
445  mesh.getElemManager().forElementSubRegions< FaceElementSubRegion >( regionNames, [&]( localIndex const,
446  FaceElementSubRegion const & subRegion )
447  {
448  this->flowSolver()->accumulationAssemblyLaunch( dofManager, subRegion, localMatrix, localRhs );
449  } );
450  } );
451 
452  this->solidMechanicsSolver()->assembleContact( domain, dofManager, localMatrix, localRhs );
453  }
454 
455  virtual void assembleCouplingTerms( real64 const time_n,
456  real64 const dt,
457  DomainPartition const & domain,
458  DofManager const & dofManager,
459  CRSMatrixView< real64, globalIndex const > const & localMatrix,
460  arrayView1d< real64 > const & localRhs ) override
461  {
462  GEOS_UNUSED_VAR( time_n, dt );
463  // These 2 steps need to occur after the fluxes are assembled because that's when DerivativeFluxResidual_dAperture is filled.
464  this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &,
465  MeshLevel const & mesh,
466  string_array const & regionNames )
467  {
469  assembleForceResidualDerivativeWrtPressure( mesh, regionNames, dofManager, localMatrix, localRhs );
470  assembleFluidMassResidualDerivativeWrtDisplacement( mesh, regionNames, dofManager, localMatrix, localRhs );
471  } );
472  }
473 
474  void assembleForceResidualDerivativeWrtPressure( MeshLevel const & mesh,
475  string_array const & regionNames,
476  DofManager const & dofManager,
477  CRSMatrixView< real64, globalIndex const > const & localMatrix,
478  arrayView1d< real64 > const & localRhs )
479  {
481 
482  FaceManager const & faceManager = mesh.getFaceManager();
483  NodeManager const & nodeManager = mesh.getNodeManager();
484  EdgeManager const & edgeManager = mesh.getEdgeManager();
485  ElementRegionManager const & elemManager = mesh.getElemManager();
486 
487  ArrayOfArraysView< localIndex const > const & faceToNodeMap = faceManager.nodeList().toViewConst();
488  ArrayOfArraysView< localIndex const > const faceToEdgeMap = faceManager.edgeList().toViewConst();
489  arrayView2d< localIndex const > const & edgeToNodeMap = edgeManager.nodeList().toViewConst();
490  arrayView2d< real64 const > faceCenters = faceManager.faceCenter();
491  arrayView2d< real64 const > const & faceNormal = faceManager.faceNormal();
492  arrayView1d< real64 const > faceAreas = faceManager.faceArea();
493 
494  string const & dispDofKey = dofManager.getKey( fields::solidMechanics::totalDisplacement::key() );
495  string const & flowDofKey = dofManager.getKey( getFlowDofKey() );
496 
498  dispDofNumber = nodeManager.getReference< globalIndex_array >( dispDofKey );
499  globalIndex const rankOffset = dofManager.rankOffset();
500 
501  // Get the coordinates for all nodes
503 
504  elemManager.forElementSubRegions< FaceElementSubRegion >( regionNames,
505  [&]( localIndex const,
506  FaceElementSubRegion const & subRegion )
507  {
509  flowDofNumber = subRegion.getReference< globalIndex_array >( flowDofKey );
510  arrayView1d< real64 const > const & pressure = subRegion.getReference< array1d< real64 > >( fields::flow::pressure::key() );
511  arrayView2d< localIndex const > const & elemsToFaces = subRegion.faceList().toViewConst();
512 
513  forAll< serialPolicy >( subRegion.size(), [=]( localIndex const kfe )
514  {
515  localIndex const kf0 = elemsToFaces[kfe][0];
516  localIndex const numNodesPerFace = faceToNodeMap.sizeOfArray( kf0 );
517 
518  real64 Nbar[3];
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]; // this needs to be changed when dealing with arbitrary element types
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]; // pressure is always first
528 
529  for( localIndex kf=0; kf<2; ++kf )
530  {
531  localIndex const faceIndex = elemsToFaces[kfe][kf];
532 
533  // Compute local area contribution for each node
534  stackArray1d< real64, FaceManager::maxFaceNodes() > nodalArea;
535  this->solidMechanicsSolver()->computeFaceNodalArea( elemsToFaces[kfe][kf],
536  nodePosition,
537  faceToNodeMap,
538  faceToEdgeMap,
539  edgeToNodeMap,
540  faceCenters,
541  faceNormal,
542  faceAreas,
543  nodalArea );
544  for( localIndex a=0; a<numNodesPerFace; ++a )
545  {
546  real64 const nodalForceMag = -( pressure[kfe] ) * nodalArea[a];
547  real64 globalNodalForce[ 3 ];
548  LvArray::tensorOps::scaledCopy< 3 >( globalNodalForce, Nbar, nodalForceMag );
549 
550  for( localIndex i=0; i<3; ++i )
551  {
552  rowDOF[3*a+i] = dispDofNumber[faceToNodeMap( faceIndex, a )] + LvArray::integerConversion< globalIndex >( i );
553  // Opposite sign w.r.t. theory because of minus sign in stiffness matrix definition (K < 0)
554  nodeRHS[3*a+i] = +globalNodalForce[i] * pow( -1, kf );
555 
556  // Opposite sign w.r.t. theory because of minus sign in stiffness matrix definition (K < 0)
557  dRdP( 3*a+i ) = -nodalArea[a] * Nbar[i] * pow( -1, kf );
558  }
559  }
560 
561  for( localIndex idof = 0; idof < numNodesPerFace * 3; ++idof )
562  {
563  localIndex const localRow = LvArray::integerConversion< localIndex >( rowDOF[idof] - rankOffset );
564 
565  if( localRow >= 0 && localRow < localMatrix.numRows() )
566  {
567  localMatrix.addToRow< parallelHostAtomic >( localRow,
568  colDOF,
569  &dRdP[idof],
570  1 );
571  RAJA::atomicAdd( parallelHostAtomic{}, &localRhs[localRow], nodeRHS[idof] );
572  }
573  }
574  }
575  } );
576  } );
577  }
578 
579  virtual void assembleFluidMassResidualDerivativeWrtDisplacement( MeshLevel const & mesh,
580  string_array const & regionNames,
581  DofManager const & dofManager,
582  CRSMatrixView< real64, globalIndex const > const & localMatrix,
583  arrayView1d< real64 > const & localRhs ) = 0;
584 
585  void updateHydraulicApertureAndFracturePermeability( DomainPartition & domain )
586  {
587  using namespace constitutive;
588 
589  this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &,
590  MeshLevel & mesh,
591  string_array const & regionNames )
592  {
593  ElementRegionManager & elemManager = mesh.getElemManager();
594 
595  elemManager.forElementSubRegions< FaceElementSubRegion >( regionNames,
596  [&]( localIndex const,
597  FaceElementSubRegion & subRegion )
598  {
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 >();
605 
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 >();
609 
610  string const porousSolidName = subRegion.getReference< string >( FlowSolverBase::viewKeyStruct::solidNamesString() );
611  CoupledSolidBase & porousSolid = subRegion.getConstitutiveModel< CoupledSolidBase >( porousSolidName );
612 
613  string const & hydraulicApertureRelationName = subRegion.template getReference< string >( viewKeyStruct::hydraulicApertureRelationNameString() );
614  HydraulicApertureBase const & hydraulicApertureModel = this->template getConstitutiveModel< HydraulicApertureBase >( subRegion, hydraulicApertureRelationName );
615 
616  constitutiveUpdatePassThru( hydraulicApertureModel, [&] ( auto & castedHydraulicAperture )
617  {
618  using HydraulicApertureType = TYPEOFREF( castedHydraulicAperture );
619  typename HydraulicApertureType::KernelWrapper hydraulicApertureWrapper = castedHydraulicAperture.createKernelWrapper();
620 
621  ConstitutivePassThru< CompressibleSolidBase >::execute( porousSolid, [=, &subRegion] ( auto & castedPorousSolid )
622  {
623  typename TYPEOFREF( castedPorousSolid ) ::KernelWrapper porousMaterialWrapper = castedPorousSolid.createKernelUpdates();
624 
625  poromechanicsFracturesKernels::StateUpdateKernel::
626  launch< parallelDevicePolicy<> >( subRegion.size(),
627  porousMaterialWrapper,
628  hydraulicApertureWrapper,
629  dispJump,
630  pressure,
631  area,
632  volume,
633  deltaVolume,
634  aperture,
635  oldHydraulicAperture,
636  hydraulicAperture,
637  fractureTraction );
638 
639  } );
640  } );
641  } );
642  } );
643  }
644 
645  std::unique_ptr< CRSMatrix< real64, localIndex > > & getRefDerivativeFluxResidual_dAperture()
646  {
647  return m_derivativeFluxResidual_dAperture;
648  }
649 
650  CRSMatrixView< real64, localIndex const > getDerivativeFluxResidual_dNormalJump()
651  {
652  return m_derivativeFluxResidual_dAperture->toViewConstSizes();
653  }
654 
655  CRSMatrixView< real64 const, localIndex const > getDerivativeFluxResidual_dNormalJump() const
656  {
657  return m_derivativeFluxResidual_dAperture->toViewConst();
658  }
659 
660  virtual string getFlowDofKey() const = 0;
661 
662  virtual integer numFluidComponents() const = 0;
663 
664  struct viewKeyStruct : public Base::viewKeyStruct
665  {};
666 
667  static const localIndex m_maxFaceNodes = 11; // Maximum number of nodes on a contact face
668 
669  std::unique_ptr< CRSMatrix< real64, localIndex > > m_derivativeFluxResidual_dAperture;
670 
671 };
672 
673 }
674 
675 #endif //GEOS_PHYSICSSOLVERS_MULTIPHYSICS_POROMECHANICSCONFORMINGFRACTURES_HPP_
#define GEOS_UNUSED_VAR(...)
Mark an unused variable and silence compiler warnings.
Definition: GeosxMacros.hpp:84
#define GEOS_UNUSED_PARAM(X)
Mark an unused argument and silence compiler warnings.
Definition: GeosxMacros.hpp:72
#define GEOS_MARK_FUNCTION
Mark function with both Caliper and NVTX if enabled.
The DoFManager is responsible for allocating global dofs, constructing sparsity patterns,...
Definition: DofManager.hpp:44
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 &regions={}, 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.
Definition: EdgeManager.hpp:43
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.
Definition: FaceManager.hpp:44
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.
Definition: MeshLevel.hpp:42
NodeManager const & getNodeManager() const
Get the node manager.
Definition: MeshLevel.hpp:155
FaceManager const & getFaceManager() const
Get the face manager.
Definition: MeshLevel.hpp:194
ElementRegionManager const & getElemManager() const
Get the element region manager.
Definition: MeshLevel.hpp:207
EdgeManager const & getEdgeManager() const
Get the edge manager.
Definition: MeshLevel.hpp:181
The NodeManager class provides an interface to ObjectManagerBase in order to manage node data.
Definition: NodeManager.hpp:46
void setUpDflux_dApertureMatrix(DomainPartition &domain, DofManager const &GEOS_UNUSED_PARAM(dofManager), CRSMatrix< real64, globalIndex > &localMatrix)
Set up the Dflux_dApertureMatrix object.
void addTransmissibilityCouplingPattern(DomainPartition const &domain, DofManager const &dofManager, SparsityPatternView< globalIndex > const &pattern) const
Set up the Dflux_dApertureMatrix object.
void assembleElementBasedContributions(real64 const time_n, real64 const dt, DomainPartition &domain, DofManager const &dofManager, CRSMatrixView< real64, globalIndex const > const &localMatrix, arrayView1d< real64 > const &localRhs)
void addTransmissibilityCouplingNNZ(DomainPartition const &domain, DofManager const &dofManager, arrayView1d< localIndex > const &rowLengths) const
virtual void assembleCouplingTerms(real64 const time_n, real64 const dt, DomainPartition const &domain, DofManager const &dofManager, CRSMatrixView< real64, globalIndex const > const &localMatrix, arrayView1d< real64 > const &localRhs) override
virtual void setupCoupling(DomainPartition const &domain, DofManager &dofManager) const override
virtual void setupSystem(DomainPartition &domain, DofManager &dofManager, CRSMatrix< real64, globalIndex > &localMatrix, ParallelVector &rhs, ParallelVector &solution, bool const setSparsity=true) override
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.
Definition: Group.hpp:1275
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.
Definition: DataTypes.hpp:188
stdVector< string > string_array
A 1-dimensional array of geos::string types.
Definition: DataTypes.hpp:401
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.
Definition: DataTypes.hpp:318
GEOS_GLOBALINDEX_TYPE globalIndex
Global index type (for indexing objects across MPI partitions).
Definition: DataTypes.hpp:87
array1d< globalIndex > globalIndex_array
A 1-dimensional array of geos::globalIndex types.
Definition: DataTypes.hpp:410
LvArray::SparsityPatternView< COL_INDEX, INDEX_TYPE const, LvArray::ChaiBuffer > SparsityPatternView
Alias for Sparsity pattern View.
Definition: DataTypes.hpp:310
LvArray::SparsityPattern< COL_INDEX, INDEX_TYPE, LvArray::ChaiBuffer > SparsityPattern
Alias for Sparsity pattern class.
Definition: DataTypes.hpp:306
LvArray::ArrayOfArraysView< T, INDEX_TYPE const, CONST_SIZES, LvArray::ChaiBuffer > ArrayOfArraysView
View of array of variable-sized arrays. See LvArray::ArrayOfArraysView for details.
Definition: DataTypes.hpp:294
double real64
64-bit floating point type.
Definition: DataTypes.hpp:98
GEOS_LOCALINDEX_TYPE localIndex
Local index type (for indexing objects within an MPI partition).
Definition: DataTypes.hpp:84
std::int32_t integer
Signed integer type.
Definition: DataTypes.hpp:81
LvArray::CRSMatrix< T, COL_INDEX, localIndex, LvArray::ChaiBuffer > CRSMatrix
Alias for CRS Matrix class.
Definition: DataTypes.hpp:314
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
Definition: DataTypes.hpp:204
Array< T, 1 > array1d
Alias for 1D array.
Definition: DataTypes.hpp:184
LAInterface::ParallelVector ParallelVector
Alias for ParallelVector.