GEOS
PoromechanicsSolver.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_POROMECHANICSSOLVER_HPP_
22 #define GEOS_PHYSICSSOLVERS_MULTIPHYSICS_POROMECHANICSSOLVER_HPP_
23 
29 #include "constitutive/solid/CoupledSolidBase.hpp"
30 #include "constitutive/contact/HydraulicApertureBase.hpp"
31 #include "mesh/DomainPartition.hpp"
33 #include "codingUtilities/Utilities.hpp"
34 
35 namespace geos
36 {
37 
38 namespace stabilization
39 {
40 enum class StabilizationType : integer
41 {
42  None,
43  Global,
44  Local,
45 };
46 
47 ENUM_STRINGS( StabilizationType,
48  "None",
49  "Global",
50  "Local" );
51 }
52 
53 
54 template< typename FLOW_SOLVER, typename MECHANICS_SOLVER = SolidMechanicsLagrangianFEM >
55 class PoromechanicsSolver : public CoupledSolver< FLOW_SOLVER, MECHANICS_SOLVER >
56 {
57 public:
58 
60  using Base::m_solvers;
61  using Base::m_dofManager;
62  using Base::m_localMatrix;
63  using Base::m_rhs;
64  using Base::m_solution;
65 
66  enum class SolverType : integer
67  {
68  Flow = 0,
69  SolidMechanics = 1
70  };
71 
73  static string coupledSolverAttributePrefix() { return "poromechanics"; }
74 
80  PoromechanicsSolver( const string & name,
81  dataRepository::Group * const parent )
82  : Base( name, parent ),
83  m_isThermal( 0 ),
85  {
87  setApplyDefaultValue( 0 ).
89  setDescription( "Flag indicating whether the problem is thermal or not. Set isThermal=\"1\" to enable the thermal coupling" );
90 
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" );
97 
99  setRTTypeName( rtTypes::CustomTypes::groupNameRefArray ).
100  setInputFlag( dataRepository::InputFlags::OPTIONAL ).
101  setDescription( "Regions where stabilization is applied." );
102 
104  setApplyDefaultValue( 1.0 ).
105  setInputFlag( dataRepository::InputFlags::OPTIONAL ).
106  setDescription( "Constant multiplier of stabilization strength" );
107 
108  LinearSolverParameters & linearSolverParameters = this->m_linearSolverParameters.get();
109  linearSolverParameters.dofsPerNode = 3;
110  linearSolverParameters.multiscale.label = "poro";
111  }
112 
113  virtual void postInputInitialization() override
114  {
116 
117  GEOS_THROW_IF( this->m_isThermal && !this->flowSolver()->isThermal(),
118  GEOS_FMT( "{} {}: The attribute `{}` of the flow solver must be thermal since the poromechanics solver is thermal",
119  this->getCatalogName(), this->getName(), this->flowSolver()->getName() ),
120  InputError );
121 
123  GEOS_FMT( "{} {}: The attribute `{}` of solid mechanics solver `{}` must be `{}`",
124  this->getCatalogName(), this->getName(),
125  SolidMechanicsLagrangianFEM::viewKeyStruct::timeIntegrationOptionString(),
126  this->solidMechanicsSolver()->getName(),
128  InputError );
129 
130  setMGRStrategy();
131  }
132 
133  virtual void setConstitutiveNamesCallSuper( ElementSubRegionBase & subRegion ) const override final
134  {
136 
137  this->template setConstitutiveName< constitutive::CoupledSolidBase >( subRegion,
138  viewKeyStruct::porousMaterialNamesString(), "coupled solid" );
139 
140  // This is needed by the way the surface generator currently does things.
141  this->template setConstitutiveName< constitutive::PorosityBase >( subRegion,
142  constitutive::CoupledSolidBase::viewKeyStruct::porosityModelNameString(), "porosity" );
143 
144  if( dynamic_cast< SurfaceElementSubRegion * >( &subRegion ) )
145  {
146  this->template setConstitutiveName< constitutive::HydraulicApertureBase >( subRegion,
147  viewKeyStruct::hydraulicApertureRelationNameString(), "hydraulic aperture" );
148  }
149  }
150 
151  virtual void initializePreSubGroups() override
152  {
154 
155  GEOS_THROW_IF( m_stabilizationType == stabilization::StabilizationType::Local,
157  ": Local stabilization has been temporarily disabled",
158  InputError );
159 
160  DomainPartition & domain = this->template getGroupByPath< DomainPartition >( "/Problem/domain" );
161 
162  this->template forDiscretizationOnMeshTargets<>( domain.getMeshBodies(), [&] ( string const &,
163  MeshLevel & mesh,
164  string_array const & regionNames )
165  {
166  ElementRegionManager & elementRegionManager = mesh.getElemManager();
167  elementRegionManager.forElementSubRegions< CellElementSubRegion >( regionNames,
168  [&]( localIndex const,
169  ElementSubRegionBase & subRegion )
170  {
171  if( subRegion.hasField< fields::poromechanics::bulkDensity >() )
172  {
173  // get the solid model to know the number of quadrature points and resize the bulk density
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 ) );
178  }
179  } );
180  } );
181  }
182 
183  virtual void registerDataOnMesh( dataRepository::Group & meshBodies ) override
184  {
185  Base::registerDataOnMesh( meshBodies );
186 
187  if( this->getNonlinearSolverParameters().m_couplingType == NonlinearSolverParameters::CouplingType::Sequential )
188  {
189  // to let the solid mechanics solver that there is a pressure and temperature RHS in the mechanics solve
190  solidMechanicsSolver()->enableFixedStressPoromechanicsUpdate();
191  // to let the flow solver that saving pressure_k and temperature_k is necessary (for the fixed-stress porosity terms)
192  flowSolver()->enableFixedStressPoromechanicsUpdate();
193  }
194 
195  if( m_stabilizationType == stabilization::StabilizationType::Global || m_stabilizationType == stabilization::StabilizationType::Local )
196  {
197  flowSolver()->enableJumpStabilization();
198  }
199 
200  this->forDiscretizationOnMeshTargets( meshBodies, [&] ( string const &,
201  MeshLevel & mesh,
202  string_array const & regionNames )
203  {
204  ElementRegionManager & elemManager = mesh.getElemManager();
205 
206  elemManager.forElementSubRegions< CellElementSubRegion >( regionNames,
207  [&]( localIndex const,
208  ElementSubRegionBase & subRegion )
209  {
210  subRegion.registerWrapper< string >( viewKeyStruct::porousMaterialNamesString() ).
211  setPlotLevel( dataRepository::PlotLevel::NOPLOT ).
212  setRestartFlags( dataRepository::RestartFlags::NO_WRITE ).
213  setSizedFromParent( 0 );
214 
215  // This is needed by the way the surface generator currently does things.
216  subRegion.registerWrapper< string >( constitutive::CoupledSolidBase::viewKeyStruct::porosityModelNameString() ).
217  setPlotLevel( dataRepository::PlotLevel::NOPLOT ).
218  setRestartFlags( dataRepository::RestartFlags::NO_WRITE ).
219  setSizedFromParent( 0 );
220 
221  // register the bulk density for use in the solid mechanics solver
222  // ideally we would resize it here as well, but the solid model name is not available yet (see below)
223  subRegion.registerField< fields::poromechanics::bulkDensity >( this->getName() );
224 
225  if( m_stabilizationType == stabilization::StabilizationType::Global || m_stabilizationType == stabilization::StabilizationType::Local )
226  {
227  subRegion.registerField< fields::flow::macroElementIndex >( this->getName());
228  subRegion.registerField< fields::flow::elementStabConstant >( this->getName());
229  }
230  } );
231  } );
232  }
233 
234  virtual void implicitStepSetup( real64 const & time_n,
235  real64 const & dt,
236  DomainPartition & domain ) override
237  {
238  flowSolver()->setKeepVariablesConstantDuringInitStep( m_performStressInitialization );
239 
240  if( this->m_stabilizationType == stabilization::StabilizationType::Global || this->m_stabilizationType == stabilization::StabilizationType::Local )
241  {
242  this->updateStabilizationParameters( domain );
243  }
244 
245  Base::implicitStepSetup( time_n, dt, domain );
246  }
247 
248  virtual void setupDofs( DomainPartition const & domain,
249  DofManager & dofManager ) const override
250  {
251  // note that the order of operations matters a lot here (for instance for the MGR labels)
252  // we must set up dofs for solid mechanics first, and then for flow
253  // that's the reason why this function is here and not in CoupledSolvers.hpp
254  solidMechanicsSolver()->setupDofs( domain, dofManager );
255  flowSolver()->setupDofs( domain, dofManager );
256  this->setupCoupling( domain, dofManager );
257  }
258 
259  virtual void setupCoupling( DomainPartition const & GEOS_UNUSED_PARAM( domain ),
260  DofManager & dofManager ) const override
261  {
262  dofManager.addCoupling( fields::solidMechanics::totalDisplacement::key(),
263  getFlowDofKey(),
265  }
266 
267  virtual void assembleSystem( real64 const time,
268  real64 const dt,
269  DomainPartition & domain,
270  DofManager const & dofManager,
271  CRSMatrixView< real64, globalIndex const > const & localMatrix,
272  arrayView1d< real64 > const & localRhs ) override
273  {
275 
276  // Steps 1 and 2: compute element-based terms (mechanics and local flow terms)
277  assembleElementBasedTerms( time,
278  dt,
279  domain,
280  dofManager,
281  localMatrix,
282  localRhs );
283 
284  // Step 3: compute the fluxes (face-based contributions)
285 
286  if( m_stabilizationType == stabilization::StabilizationType::Global ||
287  m_stabilizationType == stabilization::StabilizationType::Local )
288  {
289  this->flowSolver()->assembleStabilizedFluxTerms( dt,
290  domain,
291  dofManager,
292  localMatrix,
293  localRhs );
294  }
295  else
296  {
297  this->flowSolver()->assembleFluxTerms( dt,
298  domain,
299  dofManager,
300  localMatrix,
301  localRhs );
302  }
303  }
304 
305  virtual void assembleElementBasedTerms( real64 const time_n,
306  real64 const dt,
307  DomainPartition & domain,
308  DofManager const & dofManager,
309  CRSMatrixView< real64, globalIndex const > const & localMatrix,
310  arrayView1d< real64 > const & localRhs ) = 0;
311 
312  virtual bool checkSequentialConvergence( integer const cycleNumber,
313  integer const iter,
314  real64 const & time_n,
315  real64 const & dt,
316  DomainPartition & domain ) override
317  {
318  // always force outer loop for initialization
319  auto & subcycling = this->getNonlinearSolverParameters().m_subcyclingOption;
320  auto const subcycling_orig = subcycling;
321  if( m_performStressInitialization )
322  subcycling = 1;
323  bool isConverged = Base::checkSequentialConvergence( cycleNumber, iter, time_n, dt, domain );
324 
325  // restore original
326  subcycling = subcycling_orig;
327 
328  return isConverged;
329  }
330 
335  MECHANICS_SOLVER * solidMechanicsSolver() const
336  {
337  return std::get< toUnderlying( SolverType::SolidMechanics ) >( m_solvers );
338  }
339 
344  FLOW_SOLVER * flowSolver() const
345  {
346  return std::get< toUnderlying( SolverType::Flow ) >( m_solvers );
347  }
348 
349  /*
350  * @brief Utility function to set the stress initialization flag
351  * @param[in] performStressInitialization true if the solver has to initialize stress, false otherwise
352  */
353  void setStressInitialization( bool const performStressInitialization )
354  {
355  m_performStressInitialization = performStressInitialization;
356  solidMechanicsSolver()->setStressInitialization( performStressInitialization );
357  }
358 
360  {
362  constexpr static char const * porousMaterialNamesString() { return "porousMaterialNames"; }
363 
365  constexpr static char const * isThermalString() { return "isThermal"; }
366 
368  constexpr static char const * stabilizationTypeString() {return "stabilizationType"; }
369 
371  constexpr static const char * stabilizationRegionNamesString() {return "stabilizationRegionNames"; }
372 
374  constexpr static const char * stabilizationMultiplierString() {return "stabilizationMultiplier"; }
375 
377  static constexpr char const * hydraulicApertureRelationNameString() {return "hydraulicApertureRelationName"; }
378 
379  };
380 
381  void updateStabilizationParameters( DomainPartition & domain ) const
382  {
383  // Step 1: we loop over the regions where stabilization is active and collect their name
384  set< string > regionFilter;
385  for( string const & regionName : m_stabilizationRegionNames )
386  {
387  regionFilter.insert( regionName );
388  }
389 
390  // Step 2: loop over target regions of solver, and tag the elements belonging to the stabilization regions
391  this->template forDiscretizationOnMeshTargets<>( domain.getMeshBodies(), [&] ( string const &,
392  MeshLevel & mesh,
393  string_array const & targetRegionNames )
394  {
395  //keep only target regions in filter
396  string_array filteredTargetRegionNames;
397  filteredTargetRegionNames.reserve( targetRegionNames.size() );
398 
399  for( string const & targetRegionName : targetRegionNames )
400  {
401  if( regionFilter.count( targetRegionName ) )
402  {
403  filteredTargetRegionNames.emplace_back( targetRegionName );
404  }
405  }
406 
407  // Loop over elements and update stabilization constant
408  mesh.getElemManager().forElementSubRegions( filteredTargetRegionNames, [&]( localIndex const,
409  ElementSubRegionBase & subRegion )
410  {
411  arrayView1d< integer > const macroElementIndex = subRegion.getField< fields::flow::macroElementIndex >();
412  arrayView1d< real64 > const elementStabConstant = subRegion.getField< fields::flow::elementStabConstant >();
413 
414  constitutive::CoupledSolidBase const & porousSolid =
415  this->template getConstitutiveModel< constitutive::CoupledSolidBase >( subRegion,
416  subRegion.getReference< string >( viewKeyStruct::porousMaterialNamesString() ) );
417 
418  arrayView1d< real64 const > const bulkModulus = porousSolid.getBulkModulus();
419  arrayView1d< real64 const > const shearModulus = porousSolid.getShearModulus();
420  arrayView1d< real64 const > const biotCoefficient = porousSolid.getBiotCoefficient();
421 
422  real64 const stabilizationMultiplier = m_stabilizationMultiplier;
423 
424  forAll< parallelDevicePolicy<> >( subRegion.size(), [bulkModulus,
425  shearModulus,
426  biotCoefficient,
427  stabilizationMultiplier,
428  macroElementIndex,
429  elementStabConstant] GEOS_HOST_DEVICE ( localIndex const ei )
430 
431  {
432  real64 const bM = bulkModulus[ei];
433  real64 const sM = shearModulus[ei];
434  real64 const bC = biotCoefficient[ei];
435 
436  macroElementIndex[ei] = 1;
437  elementStabConstant[ei] = stabilizationMultiplier * 9.0 * (bC * bC) / (32.0 * (10.0 * sM / 3.0 + bM));
438  } );
439  } );
440  } );
441 
442  }
443 
444  void updateBulkDensity( DomainPartition & domain )
445  {
446  this->template forDiscretizationOnMeshTargets<>( domain.getMeshBodies(), [&]( string const &,
447  MeshLevel & mesh,
448  string_array const & regionNames )
449  {
450  mesh.getElemManager().forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const,
451  auto & subRegion )
452  {
453  // update the bulk density
454  // TODO: ideally, we would not recompute the bulk density, but a more general "rhs" containing the body force and the
455  // pressure/temperature terms
456  updateBulkDensity( subRegion );
457  } );
458  } );
459  }
460 
461 protected:
462 
464  {
465  Base::initializePostInitialConditionsPreSubGroups();
466 
467  string_array const & poromechanicsTargetRegionNames =
468  this->template getReference< string_array >( PhysicsSolverBase::viewKeyStruct::targetRegionsString() );
469  string_array const & solidMechanicsTargetRegionNames =
470  this->solidMechanicsSolver()->template getReference< string_array >( PhysicsSolverBase::viewKeyStruct::targetRegionsString() );
471  string_array const & flowTargetRegionNames =
472  this->flowSolver()->template getReference< string_array >( PhysicsSolverBase::viewKeyStruct::targetRegionsString() );
473  for( size_t i = 0; i < poromechanicsTargetRegionNames.size(); ++i )
474  {
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() ),
481  InputError );
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() ),
486  InputError );
487  }
488  }
489 
490  template< typename TYPE_LIST,
491  typename KERNEL_WRAPPER,
492  typename ... PARAMS >
493  real64 assemblyLaunch( MeshLevel & mesh,
494  DofManager const & dofManager,
495  string_array const & regionNames,
496  string const & materialNamesString,
497  CRSMatrixView< real64, globalIndex const > const & localMatrix,
498  arrayView1d< real64 > const & localRhs,
499  real64 const dt,
500  PARAMS && ... params )
501  {
503 
504  NodeManager const & nodeManager = mesh.getNodeManager();
505 
506  string const dofKey = dofManager.getKey( fields::solidMechanics::totalDisplacement::key() );
507  arrayView1d< globalIndex const > const & dofNumber = nodeManager.getReference< globalIndex_array >( dofKey );
508 
509  real64 const gravityVectorData[3] = LVARRAY_TENSOROPS_INIT_LOCAL_3( this->gravityVector() );
510 
511  KERNEL_WRAPPER kernelWrapper( dofNumber,
512  dofManager.rankOffset(),
513  localMatrix,
514  localRhs,
515  dt,
516  gravityVectorData,
517  std::forward< PARAMS >( params )... );
518 
519  return finiteElement::
520  regionBasedKernelApplication< parallelDevicePolicy< >,
521  TYPE_LIST >( mesh,
522  regionNames,
523  this->solidMechanicsSolver()->getDiscretizationName(),
524  materialNamesString,
525  kernelWrapper );
526  }
527 
528  /* Implementation of Nonlinear Acceleration (Aitken) of averageMeanTotalStressIncrement */
529 
530  void recordAverageMeanTotalStressIncrement( DomainPartition & domain,
531  array1d< real64 > & averageMeanTotalStressIncrement )
532  {
533  averageMeanTotalStressIncrement.resize( 0 );
534  this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &,
535  MeshLevel & mesh,
536  string_array const & regionNames )
537  {
538  mesh.getElemManager().forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const,
539  auto & subRegion )
540  {
541  // get the solid model (to access stress increment)
542  string const & solidName =
543  subRegion.template getReference< string >( viewKeyStruct::porousMaterialNamesString() );
544  constitutive::CoupledSolidBase & solid =
545  this->template getConstitutiveModel< constitutive::CoupledSolidBase >( subRegion, solidName );
546 
547  arrayView1d< const real64 > const & averageMeanTotalStressIncrement_k = solid.getAverageMeanTotalStressIncrement_k();
548  for( localIndex k = 0; k < localIndex( averageMeanTotalStressIncrement_k.size()); k++ )
549  {
550  averageMeanTotalStressIncrement.emplace_back( averageMeanTotalStressIncrement_k[k] );
551  }
552  } );
553  } );
554  }
555 
556  void applyAcceleratedAverageMeanTotalStressIncrement( DomainPartition & domain,
557  array1d< real64 > & averageMeanTotalStressIncrement )
558  {
559  integer i = 0;
560  this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &,
561  MeshLevel & mesh,
562  string_array const & regionNames )
563  {
564  mesh.getElemManager().forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const,
565  auto & subRegion )
566  {
567  // get the solid model (to access stress increment)
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++ )
574  {
575  porosityModel.updateAverageMeanTotalStressIncrement( k, averageMeanTotalStressIncrement[i] );
576  i++;
577  }
578  } );
579  } );
580  }
581 
582  real64 computeAitkenRelaxationFactor( array1d< real64 > const & s0,
583  array1d< real64 > const & s1,
584  array1d< real64 > const & s1_tilde,
585  array1d< real64 > const & s2_tilde,
586  real64 const omega0 )
587  {
588  array1d< real64 > r1 = axpy( s1_tilde, s0, -1.0 );
589  array1d< real64 > r2 = axpy( s2_tilde, s1, -1.0 );
590 
591  // diff = r2 - r1
592  array1d< real64 > diff = axpy( r2, r1, -1.0 );
593 
594  real64 const denom = dot( diff, diff );
595  real64 const numer = dot( r1, diff );
596 
597  real64 omega1 = 1.0;
598  if( !isZero( denom ))
599  {
600  omega1 = -1.0 * omega0 * numer / denom;
601  }
602  return omega1;
603  }
604 
605  array1d< real64 > computeUpdate( array1d< real64 > const & s1,
606  array1d< real64 > const & s2_tilde,
607  real64 const omega1 )
608  {
609  return axpy( scale( s1, 1.0 - omega1 ),
610  scale( s2_tilde, omega1 ),
611  1.0 );
612  }
613 
614  void startSequentialIteration( integer const & iter,
615  DomainPartition & domain ) override
616  {
617  if( this->getNonlinearSolverParameters().m_nonlinearAccelerationType == NonlinearSolverParameters::NonlinearAccelerationType::Aitken )
618  {
619  if( iter == 0 )
620  {
621  recordAverageMeanTotalStressIncrement( domain, m_s1 );
622  }
623  else
624  {
625  m_s0 = m_s1;
626  m_s1 = m_s2;
627  m_s1_tilde = m_s2_tilde;
628  m_omega0 = m_omega1;
629  }
630  }
631  }
632 
633  void finishSequentialIteration( integer const & iter,
634  DomainPartition & domain ) override
635  {
636  if( this->getNonlinearSolverParameters().m_nonlinearAccelerationType == NonlinearSolverParameters::NonlinearAccelerationType::Aitken )
637  {
638  if( iter == 0 )
639  {
640  m_s2 = m_s2_tilde;
641  m_omega1 = 1.0;
642  }
643  else
644  {
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 );
648  }
649  }
650  }
651 
652  virtual void mapSolutionBetweenSolvers( DomainPartition & domain, integer const solverType ) override
653  {
655 
657  if( solverType == static_cast< integer >( SolverType::Flow ) )
658  {
659  updateBulkDensity( domain );
660  }
661 
663  if( solverType == static_cast< integer >( SolverType::SolidMechanics )
664  && !m_performStressInitialization ) // do not update during poromechanics initialization
665  {
666  // compute the average of the mean total stress increment over quadrature points
667  averageMeanTotalStressIncrement( domain );
668 
669  this->template forDiscretizationOnMeshTargets<>( domain.getMeshBodies(), [&]( string const &,
670  MeshLevel & mesh,
671  string_array const & regionNames )
672  {
673 
674  mesh.getElemManager().forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const,
675  auto & subRegion )
676  {
677  // update the porosity after a change in displacement (after mechanics solve)
678  // or a change in pressure/temperature (after a flow solve)
679  flowSolver()->updatePorosityAndPermeability( subRegion );
680  // update bulk density to reflect porosity change into mechanics
681  updateBulkDensity( subRegion );
682  } );
683  } );
684  }
685 
686  // needed to perform nonlinear acceleration
687  if( solverType == static_cast< integer >( SolverType::SolidMechanics ) &&
688  this->getNonlinearSolverParameters().m_nonlinearAccelerationType== NonlinearSolverParameters::NonlinearAccelerationType::Aitken )
689  {
690  recordAverageMeanTotalStressIncrement( domain, m_s2_tilde );
691  }
692  }
693 
699  {
700  this->template forDiscretizationOnMeshTargets<>( domain.getMeshBodies(), [&]( string const &,
701  MeshLevel & mesh,
702  string_array const & regionNames )
703  {
704  mesh.getElemManager().forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const,
705  auto & subRegion )
706  {
707  // get the solid model (to access stress increment)
708  string const & solidName = subRegion.template getReference< string >( viewKeyStruct::porousMaterialNamesString() );
709  constitutive::CoupledSolidBase & solid =
710  this->template getConstitutiveModel< constitutive::CoupledSolidBase >( subRegion, solidName );
711 
712  arrayView2d< real64 const > const meanTotalStressIncrement_k = solid.getMeanTotalStressIncrement_k();
713  arrayView1d< real64 > const averageMeanTotalStressIncrement_k = solid.getAverageMeanTotalStressIncrement_k();
714 
715  finiteElement::FiniteElementBase & subRegionFE =
716  subRegion.template getReference< finiteElement::FiniteElementBase >( solidMechanicsSolver()->getDiscretizationName() );
717 
718  // determine the finite element type
719  finiteElement::FiniteElementDispatchHandler< BASE_FE_TYPES >::
720  dispatch3D( subRegionFE, [&] ( auto const finiteElement )
721  {
722  using FE_TYPE = decltype( finiteElement );
723 
724  // call the factory and launch the kernel
725  AverageOverQuadraturePoints1DKernelFactory::
726  createAndLaunch< CellElementSubRegion,
727  FE_TYPE,
728  parallelDevicePolicy<> >( mesh.getNodeManager(),
729  mesh.getEdgeManager(),
730  mesh.getFaceManager(),
731  subRegion,
732  finiteElement,
733  meanTotalStressIncrement_k,
734  averageMeanTotalStressIncrement_k );
735  } );
736  } );
737  } );
738  }
739 
740  virtual void setMGRStrategy() = 0;
741 
742  virtual void updateBulkDensity( ElementSubRegionBase & subRegion ) = 0;
743 
744  virtual string getFlowDofKey() const = 0;
745 
746  virtual void validateNonlinearAcceleration() override
747  {
748  if( MpiWrapper::commSize( MPI_COMM_GEOS ) > 1 )
749  {
750  GEOS_ERROR( "Nonlinear acceleration is not implemented for MPI runs" );
751  }
752  }
753 
756 
759 
761  stabilization::StabilizationType m_stabilizationType;
762 
765 
768 
770  array1d< real64 > m_s0; // Accelerated averageMeanTotalStresIncrement @ outer iteration v ( two iterations ago )
771  array1d< real64 > m_s1; // Accelerated averageMeanTotalStresIncrement @ outer iteration v + 1 ( previous iteration )
772  array1d< real64 > m_s1_tilde; // Unaccelerated averageMeanTotalStresIncrement @ outer iteration v + 1 ( previous iteration )
773  array1d< real64 > m_s2; // Accelerated averageMeanTotalStresIncrement @ outer iteration v + 2 ( current iteration )
774  array1d< real64 > m_s2_tilde; // Unaccelerated averageMeanTotalStresIncrement @ outer iteration v + 1 ( current iteration )
775  real64 m_omega0; // Old Aitken relaxation factor
776  real64 m_omega1; // New Aitken relaxation factor
777 
778 };
779 
780 } /* namespace geos */
781 
782 #endif //GEOS_PHYSICSSOLVERS_MULTIPHYSICS_POROMECHANICSSOLVER_HPP_
#define GEOS_UNUSED_PARAM(X)
Mark an unused argument and silence compiler warnings.
Definition: GeosxMacros.hpp:72
#define GEOS_ERROR(msg)
Raise a hard error and terminate the program.
Definition: Logger.hpp:157
#define GEOS_THROW_IF(EXP, msg, TYPE)
Conditionally throw an exception.
Definition: Logger.hpp:151
#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,...
Definition: DofManager.hpp:45
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.
@ 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.
Definition: MeshLevel.hpp:42
NodeManager const & getNodeManager() const
Get the node manager.
Definition: MeshLevel.hpp:155
ElementRegionManager const & getElemManager() const
Get the element region manager.
Definition: MeshLevel.hpp:207
The NodeManager class provides an interface to ObjectManagerBase in order to manage node data.
Definition: NodeManager.hpp:46
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.
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.
Definition: Group.hpp:1331
GEOS_DECLTYPE_AUTO_RETURN getReference(LOOKUP_TYPE const &lookup) const
Look up a wrapper and get reference to wrapped object.
Definition: Group.hpp:1275
DataContext const & getWrapperDataContext(KEY key) const
Definition: Group.hpp:1356
@ 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.
Definition: DataTypes.hpp:179
stdVector< string > string_array
A 1-dimensional array of geos::string types.
Definition: DataTypes.hpp:361
int MPI_COMM_GEOS
Global MPI communicator used by GEOSX.
array1d< globalIndex > globalIndex_array
A 1-dimensional array of geos::globalIndex types.
Definition: DataTypes.hpp:370
std::set< T > set
A set of local indices.
Definition: DataTypes.hpp:262
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
LvArray::CRSMatrixView< T, COL_INDEX, INDEX_TYPE const, LvArray::ChaiBuffer > CRSMatrixView
Alias for CRS Matrix View.
Definition: DataTypes.hpp:309
int integer
Signed integer type.
Definition: DataTypes.hpp:81
Array< T, 1 > array1d
Alias for 1D array.
Definition: DataTypes.hpp:175
ENUM_STRINGS(LinearSolverParameters::SolverType, "direct", "cg", "gmres", "fgmres", "bicgstab", "richardson", "preconditioner")
Declare strings associated with enumeration values.
Provides enum <-> string conversion facilities.
Exception class used to report errors in user input.
Definition: Logger.hpp:464
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.
Definition: Group.hpp:1444