GEOS
CoupledSolver.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_COUPLEDSOLVER_HPP_
22 #define GEOS_PHYSICSSOLVERS_MULTIPHYSICS_COUPLEDSOLVER_HPP_
23 
26 
27 #include <tuple>
28 
29 namespace geos
30 {
31 
32 template< typename ... SOLVERS >
34 {
35 
36 public:
37 
43  CoupledSolver( const string & name,
44  Group * const parent )
45  : PhysicsSolverBase( name, parent )
46  {
47  forEachArgInTuple( m_solvers, [&]( auto solver, auto idx )
48  {
49  using SolverType = TYPEOFPTR( solver );
50  string const key = SolverType::coupledSolverAttributePrefix() + "SolverName";
51  registerWrapper( key, &m_names[idx()] ).
52  setRTTypeName( rtTypes::CustomTypes::groupNameRef ).
54  setDescription( "Name of the " + SolverType::coupledSolverAttributePrefix() + " solver used by the coupled solver" );
55  } );
56 
57  this->getWrapper< string >( PhysicsSolverBase::viewKeyStruct::discretizationString() ).
58  setInputFlag( dataRepository::InputFlags::FALSE );
59 
60  addLogLevel< logInfo::Coupling >();
61  }
62 
64  CoupledSolver( CoupledSolver const & ) = delete;
65 
67  CoupledSolver( CoupledSolver && ) = default;
68 
70  CoupledSolver & operator=( CoupledSolver const & ) = delete;
71 
74 
75  template< typename T >
76  void throwSolversNotFound( std::ostringstream & errorMessage, string const & solverType )
77  {
78  string_array availableSolvers;
79 
80  this->getParent().template forSubGroups< T >( [&]( T & group )
81  {
82 
83  availableSolvers.emplace_back( group.getName());
84 
85  } );
86 
87  if( availableSolvers.empty() )
88  {
89  errorMessage << GEOS_FMT( "No {} solver has been found.", solverType );
90  }
91  else
92  {
93  errorMessage << GEOS_FMT( "Available {} solvers are: {}. ", solverType,
94  stringutilities::join( availableSolvers, ", " ) );
95  }
96 
97  GEOS_THROW( errorMessage.str(), InputError );
98  }
102  void
104  {
105  forEachArgInTuple( m_solvers, [&]( auto & solver, auto idx )
106  {
107  using SolverPtr = TYPEOFREF( solver );
108  using SolverType = TYPEOFPTR( SolverPtr {} );
109  auto const & solverName = m_names[idx()];
110  solver = this->getParent().template getGroupPointer< SolverType >( solverName );
111  if( solver== nullptr )
112  {
113  string const solverWrapperKey = SolverType::coupledSolverAttributePrefix() + "SolverName";
114  std::ostringstream errorMessage;
115  errorMessage << GEOS_FMT( "{}: Could not find solver named '{}'.\n",
116  getWrapperDataContext( solverWrapperKey ), solverName );
117  throwSolversNotFound< SolverType >( errorMessage, SolverType::coupledSolverAttributePrefix() );
118  }
119 
120 
121  GEOS_LOG_LEVEL_RANK_0( logInfo::Coupling,
122  GEOS_FMT( "{}: found {} solver named {}",
123  getName(), solver->getCatalogName(), solverName ) );
124  } );
125  }
126 
127 
133  virtual void
135  DofManager & dofManager ) const
136  { GEOS_UNUSED_VAR( domain, dofManager ); }
137 
147  virtual void
149  real64 const dt,
150  DomainPartition const & domain,
151  DofManager const & dofManager,
152  CRSMatrixView< real64, globalIndex const > const & localMatrix,
153  arrayView1d< real64 > const & localRhs )
154  { GEOS_UNUSED_VAR( time_n, dt, domain, dofManager, localMatrix, localRhs ); }
155 
163  void
164  setupDofs( DomainPartition const & domain,
165  DofManager & dofManager ) const override
166  {
167  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
168  {
169  solver->setupDofs( domain, dofManager );
170  } );
171 
172  setupCoupling( domain, dofManager );
173  }
174 
175  virtual void
176  implicitStepSetup( real64 const & time_n,
177  real64 const & dt,
178  DomainPartition & domain ) override
179  {
180  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
181  {
182  solver->implicitStepSetup( time_n, dt, domain );
183  } );
184  }
185 
186  virtual void
187  implicitStepComplete( real64 const & time_n,
188  real64 const & dt,
189  DomainPartition & domain ) override
190  {
191  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
192  {
193  solver->implicitStepComplete( time_n, dt, domain );
194  } );
195  }
196 
197  // general version of assembleSystem function, keep in mind many solvers will override it
198  virtual void
199  assembleSystem( real64 const time_n,
200  real64 const dt,
201  DomainPartition & domain,
202  DofManager const & dofManager,
203  CRSMatrixView< real64, globalIndex const > const & localMatrix,
204  arrayView1d< real64 > const & localRhs ) override
205  {
207 
208  // 1. Assemble matrix blocks of each individual solver
209  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
210  {
211  solver->assembleSystem( time_n, dt, domain, dofManager, localMatrix, localRhs );
212  } );
213 
214  // 2. Assemble coupling blocks
215  assembleCouplingTerms( time_n, dt, domain, dofManager, localMatrix, localRhs );
216  }
217 
218  virtual void
219  applySystemSolution( DofManager const & dofManager,
220  arrayView1d< real64 const > const & localSolution,
221  real64 const scalingFactor,
222  real64 const dt,
223  DomainPartition & domain ) override
224  {
225  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
226  {
227  solver->applySystemSolution( dofManager, localSolution, scalingFactor, dt, domain );
228  } );
229  }
230 
231  virtual void
232  updateState( DomainPartition & domain ) override
233  {
234  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
235  {
236  solver->updateState( domain );
237  } );
238  }
239 
240  virtual void
242  {
243  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
244  {
245  solver->resetStateToBeginningOfStep( domain );
246  } );
247  }
248 
251  real64
252  solverStep( real64 const & time_n,
253  real64 const & dt,
254  int const cycleNumber,
255  DomainPartition & domain ) override final
256  {
258 
260  {
261  return fullyCoupledSolverStep( time_n, dt, cycleNumber, domain );
262  }
264  {
265  return sequentiallyCoupledSolverStep( time_n, dt, cycleNumber, domain );
266  }
267  else
268  {
269  GEOS_ERROR( getDataContext() << ": Invalid coupling type option." );
270  return 0;
271  }
272 
273  }
274 
275 
276  virtual void
277  updateAndWriteConvergenceStep( real64 const & time_n, real64 const & dt,
278  integer const cycleNumber, integer const iteration ) override
279  {
280  PhysicsSolverBase::updateAndWriteConvergenceStep( time_n, dt, cycleNumber, iteration );
281  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
282  {
283  solver->updateAndWriteConvergenceStep( time_n, dt, cycleNumber, iteration );
284  } );
285  }
286 
287  virtual real64
288  calculateResidualNorm( real64 const & time_n,
289  real64 const & dt,
290  DomainPartition const & domain,
291  DofManager const & dofManager,
292  arrayView1d< real64 const > const & localRhs ) override
293  {
294  real64 norm = 0.0;
295  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
296  {
297  real64 const singlePhysicsNorm = solver->calculateResidualNorm( time_n, dt, domain, dofManager, localRhs );
298  norm += singlePhysicsNorm * singlePhysicsNorm;
299  } );
300 
301  return sqrt( norm );
302  }
303 
304  virtual void
306  real64 const dt,
307  DomainPartition & domain,
308  DofManager const & dofManager,
309  CRSMatrixView< real64, globalIndex const > const & localMatrix,
310  arrayView1d< real64 > const & localRhs ) override
311  {
312  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
313  {
314  solver->applyBoundaryConditions( time_n, dt, domain, dofManager, localMatrix, localRhs );
315  } );
316  }
317 
318  virtual bool
320  DofManager const & dofManager,
321  arrayView1d< real64 const > const & localSolution,
322  real64 const scalingFactor ) override
323  {
324  bool validSolution = true;
325  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
326  {
327  bool const validSinglePhysicsSolution = solver->checkSystemSolution( domain, dofManager, localSolution, scalingFactor );
328  if( !validSinglePhysicsSolution )
329  {
330  GEOS_LOG_RANK_0( GEOS_FMT( " {}/{}: Solution check failed. Newton loop terminated.", getName(), solver->getName()) );
331  }
332  validSolution = validSolution && validSinglePhysicsSolution;
333  } );
334  return validSolution;
335  }
336 
337  virtual real64
339  DofManager const & dofManager,
340  arrayView1d< real64 const > const & localSolution ) override
341  {
342  real64 scalingFactor = PhysicsSolverBase::scalingForSystemSolution( domain, dofManager, localSolution );
343  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
344  {
345  real64 const singlePhysicsScalingFactor = solver->scalingForSystemSolution( domain, dofManager, localSolution );
346  scalingFactor = LvArray::math::min( scalingFactor, singlePhysicsScalingFactor );
347  } );
348  return scalingFactor;
349  }
350 
351  virtual real64
352  setNextDt( real64 const & currentTime,
353  real64 const & currentDt,
354  DomainPartition & domain ) override
355  {
356  real64 nextDt = PhysicsSolverBase::setNextDt( currentTime, currentDt, domain );
357  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
358  {
359  real64 const singlePhysicsNextDt =
360  solver->setNextDt( currentTime, currentDt, domain );
361  nextDt = LvArray::math::min( singlePhysicsNextDt, nextDt );
362  } );
363  return nextDt;
364  }
365 
366  virtual void cleanup( real64 const time_n,
367  integer const cycleNumber,
368  integer const eventCounter,
369  real64 const eventProgress,
370  DomainPartition & domain ) override
371  {
372  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
373  {
374  solver->cleanup( time_n, cycleNumber, eventCounter, eventProgress, domain );
375  } );
376  PhysicsSolverBase::cleanup( time_n, cycleNumber, eventCounter, eventProgress, domain );
377  }
378 
381  virtual bool checkSequentialSolutionIncrements( DomainPartition & domain ) const override
382  {
383  bool isConverged = true;
384  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
385  {
386  isConverged &= solver->checkSequentialSolutionIncrements( domain );
387  } );
388  return isConverged;
389  }
390 
391  virtual bool updateConfiguration( DomainPartition & domain,
392  integer const configurationLoopIter ) override
393  {
394  bool result = true;
395  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
396  {
397  result &= solver->updateConfiguration( domain, configurationLoopIter );
398  } );
399  return result;
400  }
401 
402  virtual void outputConfigurationStatistics( DomainPartition const & domain ) const override
403  {
404  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
405  {
406  solver->outputConfigurationStatistics( domain );
407  } );
408  }
409 
410  virtual void resetConfigurationToBeginningOfStep( DomainPartition & domain ) override
411  {
412  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
413  {
414  solver->resetConfigurationToBeginningOfStep( domain );
415  } );
416  }
417 
418  virtual bool resetConfigurationToDefault( DomainPartition & domain ) const override
419  {
420  bool result = true;
421  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
422  {
423  result &= solver->resetConfigurationToDefault( domain );
424  } );
425  return result;
426  }
427 
428  virtual void
430  {
431  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
432  {
433  solver->getNonlinearSolverParameters() = getNonlinearSolverParameters();
434  solver->synchronizeNonlinearSolverParameters();
435  } );
436  }
437 
438 protected:
439 
449  virtual real64 fullyCoupledSolverStep( real64 const & time_n,
450  real64 const & dt,
451  int const cycleNumber,
452  DomainPartition & domain )
453  {
454  return PhysicsSolverBase::solverStep( time_n, dt, cycleNumber, domain );
455  }
456 
467  virtual real64 sequentiallyCoupledSolverStep( real64 const & time_n,
468  real64 const & dt,
469  integer const cycleNumber,
470  DomainPartition & domain )
471  {
473 
474  // Only build the sparsity pattern if the mesh has changed
475  Timestamp const meshModificationTimestamp = getMeshModificationTimestamp( domain );
476  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
477  {
478  if( meshModificationTimestamp > solver->getSystemSetupTimestamp() )
479  {
480  solver->setupSystem( domain,
481  solver->getDofManager(),
482  solver->getLocalMatrix(),
483  solver->getSystemRhs(),
484  solver->getSystemSolution() );
485  solver->setSystemSetupTimestamp( meshModificationTimestamp );
486  }
487  } );
488 
489  implicitStepSetup( time_n, dt, domain );
490 
492  integer const maxNumberDtCuts = solverParams.m_maxTimeStepCuts;
493  real64 const dtCutFactor = solverParams.m_timeStepCutFactor;
494  integer & dtAttempt = solverParams.m_numTimeStepAttempts;
495 
496  bool isConverged = false;
497  // dt may be cut during the course of this step, so we are keeping a local
498  // value to track the achieved dt for this step.
499  real64 stepDt = dt;
500 
501  // outer loop attempts to apply full timestep, and managed the cutting of the timestep if
502  // required.
503  for( dtAttempt = 0; dtAttempt < maxNumberDtCuts; ++dtAttempt )
504  {
505  // TODO configuration loop
506 
507  // Reset the states of all solvers if any of them had to restart
508  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
509  {
510  solver->resetStateToBeginningOfStep( domain );
511  solver->getIterationStats().resetCurrentTimeStepStatistics(); // initialize counters for subsolvers
512  } );
513  resetStateToBeginningOfStep( domain );
514 
515  integer & iter = solverParams.m_numNewtonIterations;
516 
518  for( iter = 0; iter < solverParams.m_maxIterNewton; iter++ )
519  {
520  // Increment the solver statistics for reporting purposes
522 
523  startSequentialIteration( iter, domain );
524 
525  // Solve the subproblems nonlinearly
526  forEachArgInTuple( m_solvers, [&]( auto & solver, auto idx )
527  {
528  GEOS_LOG_LEVEL_RANK_0( logInfo::NonlinearSolver,
529  GEOS_FMT( " Iteration {:2}: {}", iter + 1, solver->getName() ) );
530  real64 solverDt = solver->nonlinearImplicitStep( time_n,
531  stepDt,
532  cycleNumber,
533  domain );
534 
535  // save fields (e.g. pressure and temperature) after inner solve
536  if( solver->getNonlinearSolverParameters().couplingType() == NonlinearSolverParameters::CouplingType::Sequential )
537  {
538  solver->saveSequentialIterationState( domain );
539  }
540 
541  mapSolutionBetweenSolvers( domain, idx() );
542 
543  if( solverDt < stepDt ) // subsolver had to cut the time step
544  {
545  iter = 0; // restart outer loop
546  stepDt = solverDt; // sync time step
548  }
549  } );
550  // Check convergence of the outer loop
551  isConverged = checkSequentialConvergence( cycleNumber,
552  iter,
553  time_n,
554  stepDt,
555  domain );
556 
557  if( isConverged )
558  {
559  // we still want to count current iteration
560  ++iter;
561  // exit outer loop
562  break;
563  }
564  else
565  {
566  finishSequentialIteration( iter, domain );
567  }
568  }
569 
570  if( isConverged )
571  {
572  // Save time step statistics for the subsolvers
573  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
574  {
575  solver->getIterationStats().iterateTimeStepStatistics();
576  } );
577  // get out of the time loop
578  break;
579  }
580  else
581  {
582  // cut timestep, go back to beginning of step and restart the Newton loop
583  stepDt *= dtCutFactor;
585  GEOS_LOG_LEVEL_RANK_0( logInfo::TimeStep, GEOS_FMT( "New dt = {}", stepDt ) );
586 
587  // notify the solver statistics counter that this is a time step cut
589  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
590  {
591  solver->getIterationStats().updateTimeStepCut();
592  } );
593  }
594  }
595 
596  if( !isConverged )
597  {
598  GEOS_LOG_RANK_0( "Convergence not achieved." );
599 
601  {
602  GEOS_LOG_RANK_0( "The accepted solution may be inaccurate." );
603  }
604  else
605  {
606  GEOS_ERROR( "Nonconverged solutions not allowed. Terminating..." );
607  }
608  }
609 
610  implicitStepComplete( time_n, stepDt, domain );
611 
612  return stepDt;
613  }
614 
622  integer const solverType )
623  {
624  GEOS_UNUSED_VAR( domain, solverType );
625  }
626 
627  virtual bool checkSequentialConvergence( integer const cycleNumber,
628  integer const iter,
629  real64 const & time_n,
630  real64 const & dt,
631  DomainPartition & domain )
632  {
634  bool isConverged = true;
635 
636  if( params.m_subcyclingOption == 0 )
637  {
638  GEOS_LOG_LEVEL_RANK_0( logInfo::Convergence, "***** Single Pass solver, no subcycling *****" );
639  }
640  else
641  {
642  GEOS_LOG_LEVEL_RANK_0( logInfo::Convergence, GEOS_FMT( " Iteration {:2}: outer-loop convergence check", iter + 1 ) );
643 
645  {
646  real64 residualNorm = 0;
647 
648  // loop over all the single-physics solvers
649  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
650  {
651 
652  solver->getLocalMatrix().toViewConstSizes().zero();
653  solver->getSystemRhs().zero();
654  arrayView1d< real64 > const localRhs = solver->getSystemRhs().open();
655 
656  // for each solver, we have to recompute the residual (and Jacobian, although not necessary)
657  solver->assembleSystem( time_n,
658  dt,
659  domain,
660  solver->getDofManager(),
661  solver->getLocalMatrix().toViewConstSizes(),
662  localRhs );
663  solver->applyBoundaryConditions( time_n,
664  dt,
665  domain,
666  solver->getDofManager(),
667  solver->getLocalMatrix().toViewConstSizes(),
668  localRhs );
669  solver->getSystemRhs().close();
670 
671  // once this is done, we recompute the single-physics residual
672  real64 const singlePhysicsNorm =
673  solver->calculateResidualNorm( time_n,
674  dt,
675  domain,
676  solver->getDofManager(),
677  solver->getSystemRhs().values() );
678  residualNorm += singlePhysicsNorm * singlePhysicsNorm;
679  } );
680 
681  // finally, we perform the convergence check on the multiphysics residual
682  residualNorm = sqrt( residualNorm );
683  GEOS_LOG_LEVEL_RANK_0( logInfo::ResidualNorm,
684  GEOS_FMT( " ( R ) = ( {:4.2e} )", residualNorm ) );
685  getConvergenceStats().setResidualValue( "R", residualNorm );
686  updateAndWriteConvergenceStep( time_n, dt, cycleNumber, iter );
687 
688  isConverged = ( residualNorm < params.m_newtonTol );
689 
690  }
692  {
693  // TODO also make recursive?
694  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
695  {
696  NonlinearSolverParameters const & singlePhysicsParams = solver->getNonlinearSolverParameters();
697  if( singlePhysicsParams.m_numNewtonIterations > singlePhysicsParams.m_minIterNewton )
698  {
699  isConverged = false;
700  }
701  } );
702  }
704  {
705  isConverged = checkSequentialSolutionIncrements( domain );
706  }
707  else
708  {
709  GEOS_ERROR( getDataContext() << ": Invalid sequential convergence criterion." );
710  }
711 
712  if( isConverged )
713  {
714  GEOS_LOG_LEVEL_RANK_0( logInfo::Convergence,
715  GEOS_FMT( "***** The iterative coupling has converged in {} iteration(s) *****", iter + 1 ) );
716  }
717  }
718  return isConverged;
719  }
720 
721  virtual void
723  {
724  setSubSolvers();
725 
727 
730  GEOS_THROW_IF( isSequential && usesLineSearch,
731  GEOS_FMT( "{}: line search is not supported by the coupled solver when {} is set to `{}`. Please set {} to `{}` to remove this error",
732  getNonlinearSolverParameters().getWrapperDataContext( NonlinearSolverParameters::viewKeysStruct::couplingTypeString() ),
733  NonlinearSolverParameters::viewKeysStruct::couplingTypeString(),
735  NonlinearSolverParameters::viewKeysStruct::lineSearchActionString(),
737  InputError );
738 
740  {
741  validateNonlinearAcceleration();
742  }
743  }
744 
745  virtual void validateNonlinearAcceleration()
746  {
747  GEOS_THROW ( GEOS_FMT( "{}: Nonlinear acceleration {} is not supported by {} solver '{}'",
748  getWrapperDataContext( NonlinearSolverParameters::viewKeysStruct::nonlinearAccelerationTypeString() ),
750  getCatalogName(), getName()),
751  InputError );
752  }
753 
754  virtual void initializePreSubGroups() override
755  {
757 
759  if( !isSequential )
760  {
762  }
763  }
764 
765  virtual void startSequentialIteration( integer const & iter,
766  DomainPartition & domain )
767  {
768  GEOS_UNUSED_VAR( iter, domain );
769  }
770 
771  virtual void finishSequentialIteration( integer const & iter,
772  DomainPartition & domain )
773  {
774  GEOS_UNUSED_VAR( iter, domain );
775  }
776 
777 protected:
778 
780  std::tuple< SOLVERS *... > m_solvers;
781 
783  std::array< string, sizeof...( SOLVERS ) > m_names;
784 };
785 
786 } /* namespace geos */
787 
788 #endif /* GEOS_PHYSICSSOLVERS_MULTIPHYSICS_COUPLEDSOLVER_HPP_ */
#define GEOS_UNUSED_VAR(...)
Mark an unused variable and silence compiler warnings.
Definition: GeosxMacros.hpp:84
#define GEOS_THROW(msg, TYPE)
Throw an exception.
Definition: Logger.hpp:164
#define GEOS_ERROR(msg)
Raise a hard error and terminate the program.
Definition: Logger.hpp:157
#define GEOS_LOG_RANK_0(msg)
Log a message on screen on rank 0.
Definition: Logger.hpp:101
#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.
void setResidualValue(string const &key, real64 const value)
Set a residual value given a key ( column in the CSV )
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)
Utility function to compute coupling terms.
CoupledSolver & operator=(CoupledSolver const &)=delete
deleted assignment operator
virtual real64 fullyCoupledSolverStep(real64 const &time_n, real64 const &dt, int const cycleNumber, DomainPartition &domain)
Fully coupled solution approach solution step.
virtual bool resetConfigurationToDefault(DomainPartition &domain) const override
resets the configuration to the default value.
CoupledSolver(const string &name, Group *const parent)
main constructor for CoupledSolver Objects
virtual void outputConfigurationStatistics(DomainPartition const &domain) const override
CoupledSolver(CoupledSolver &&)=default
default move constructor
virtual void resetConfigurationToBeginningOfStep(DomainPartition &domain) override
resets the configuration to the beginning of the time-step.
virtual void initializePreSubGroups() override
Called by Initialize() prior to initializing sub-Groups.
virtual real64 sequentiallyCoupledSolverStep(real64 const &time_n, real64 const &dt, integer const cycleNumber, DomainPartition &domain)
Sequentially coupled solver step. It solves a nonlinear system of equations using a sequential approa...
CoupledSolver(CoupledSolver const &)=delete
deleted copy constructor
virtual void synchronizeNonlinearSolverParameters() override
synchronize the nonlinear solver parameters.
virtual void setupCoupling(DomainPartition const &domain, DofManager &dofManager) const
Utility function to set the coupling between degrees of freedom.
virtual bool checkSequentialSolutionIncrements(DomainPartition &domain) const override
Check if the solution increments are ok to use.
virtual bool updateConfiguration(DomainPartition &domain, integer const configurationLoopIter) override
updates the configuration (if needed) based on the state after a converged Newton loop.
virtual void postInputInitialization() override
std::array< string, sizeof...(SOLVERS) > m_names
Names of the single-physics solvers.
std::tuple< SOLVERS *... > m_solvers
Pointers of the single-physics solvers.
CoupledSolver & operator=(CoupledSolver &&)=delete
deleted move operator
void setSubSolvers()
Utility function to set the subsolvers pointers using the names provided by the user.
virtual void mapSolutionBetweenSolvers(DomainPartition &domain, integer const solverType)
Maps the solution obtained from one solver to the fields used by the other solver(s)
The DoFManager is responsible for allocating global dofs, constructing sparsity patterns,...
Definition: DofManager.hpp:45
Partition of the decomposed physical domain. It also manages the connexion information to its neighbo...
void updateNonlinearIteration(integer const numLinearIterations)
Tell the solverStatistics that we have done a newton iteration.
void updateTimeStepCut()
Tell the solverStatistics that we cut the time step and we increment the cumulative counters for disc...
SequentialConvergenceCriterion sequentialConvergenceCriterion() const
Getter for the sequential convergence criterion.
integer m_allowNonConverged
Flag to allow for a non-converged nonlinear solution and continue with the problem.
real64 m_newtonTol
The tolerance for the nonlinear convergence check.
NonlinearAccelerationType m_nonlinearAccelerationType
Type of nonlinear acceleration for sequential solver.
integer m_maxIterNewton
The maximum number of nonlinear iterations that are allowed.
real64 m_timeStepCutFactor
Factor by which the time step will be cut if a timestep cut is required.
integer m_numNewtonIterations
The number of nonlinear iterations that have been exectued.
integer m_numTimeStepAttempts
Number of times that the time-step had to be cut.
integer m_maxTimeStepCuts
Max number of time step cuts.
CouplingType couplingType() const
Getter for the coupling type.
LineSearchAction m_lineSearchAction
Flag to apply a line search.
@ ResidualNorm
convergence achieved when the residual drops below a given norm
@ NumberOfNonlinearIterations
convergence achieved when the subproblems convergence is achieved in less than minNewtonIteration
@ SolutionIncrements
convergence achieved when the solution increments are small enough
integer m_subcyclingOption
Flag to specify whether subcycling is allowed or not in sequential schemes.
Base class for all physics solvers.
virtual string getCatalogName() const =0
IterationsStatistics & getIterationStats()
integer m_numTimestepsSinceLastDtCut
Number of cycles since last timestep cut.
virtual void cleanup(real64 const time_n, integer const cycleNumber, integer const eventCounter, real64 const eventProgress, DomainPartition &domain) override
Called as the code exits the main run loop.
Timestamp getMeshModificationTimestamp(DomainPartition &domain) const
getter for the timestamp of the mesh modification on the mesh levels
virtual void postInputInitialization() override
ConvergenceStatistics & getConvergenceStats()
NonlinearSolverParameters & getNonlinearSolverParameters()
accessor for the nonlinear solver parameters.
NonlinearSolverParameters m_nonlinearSolverParameters
Nonlinear solver parameters.
virtual void initializePreSubGroups()
Called by Initialize() prior to initializing sub-Groups.
Definition: Group.hpp:1542
Wrapper< TBASE > & registerWrapper(string const &name, wrapperMap::KeyIndex::index_type *const rkey=nullptr)
Create and register a Wrapper around a new object.
DataContext const & getDataContext() const
Definition: Group.hpp:1345
string const & getName() const
Get group name.
Definition: Group.hpp:1331
Group & getParent()
Access the group's parent.
Definition: Group.hpp:1364
DataContext const & getWrapperDataContext(KEY key) const
Definition: Group.hpp:1356
#define GEOS_LOG_LEVEL_RANK_0(logInfoStruct, msg)
Output messages (only on rank 0) based on current Group's log level.
virtual void implicitStepSetup(real64 const &time_n, real64 const &dt, DomainPartition &domain) override
function to perform setup for implicit timestep
virtual void cleanup(real64 const time_n, integer const cycleNumber, integer const eventCounter, real64 const eventProgress, DomainPartition &domain) override
Called as the code exits the main run loop.
virtual real64 scalingForSystemSolution(DomainPartition &domain, DofManager const &dofManager, arrayView1d< real64 const > const &localSolution) override
Function to determine if the solution vector should be scaled back in order to maintain a known const...
virtual void updateAndWriteConvergenceStep(real64 const &time_n, real64 const &dt, integer const cycleNumber, integer const iteration) override
Update the convergence information and write then into a CSV file.
virtual void updateState(DomainPartition &domain) override
Recompute all dependent quantities from primary variables (including constitutive models)
virtual void implicitStepComplete(real64 const &time_n, real64 const &dt, DomainPartition &domain) override
perform cleanup for implicit timestep
virtual void applyBoundaryConditions(real64 const time_n, real64 const dt, DomainPartition &domain, DofManager const &dofManager, CRSMatrixView< real64, globalIndex const > const &localMatrix, arrayView1d< real64 > const &localRhs) override
apply boundary condition to system
virtual real64 scalingForSystemSolution(DomainPartition &domain, DofManager const &dofManager, arrayView1d< real64 const > const &localSolution)
Function to determine if the solution vector should be scaled back in order to maintain a known const...
virtual real64 calculateResidualNorm(real64 const &time_n, real64 const &dt, DomainPartition const &domain, DofManager const &dofManager, arrayView1d< real64 const > const &localRhs) override
calculate the norm of the global system residual
real64 solverStep(real64 const &time_n, real64 const &dt, int const cycleNumber, DomainPartition &domain) override final
virtual real64 setNextDt(real64 const &currentTime, real64 const &currentDt, DomainPartition &domain) override
function to set the next time step size
virtual real64 solverStep(real64 const &time_n, real64 const &dt, integer const cycleNumber, DomainPartition &domain)
entry function to perform a solver step
void setupDofs(DomainPartition const &domain, DofManager &dofManager) const override
Populate degree-of-freedom manager with fields relevant to this solver.
virtual void applySystemSolution(DofManager const &dofManager, arrayView1d< real64 const > const &localSolution, real64 const scalingFactor, real64 const dt, DomainPartition &domain) override
Function to apply the solution vector to the state.
virtual real64 setNextDt(real64 const &currentTime, real64 const &currentDt, DomainPartition &domain)
function to set the next time step size
virtual void updateAndWriteConvergenceStep(real64 const &time_n, real64 const &dt, integer const cycleNumber, integer const iteration)
Update the convergence information and write then into a CSV file.
virtual void assembleSystem(real64 const time_n, 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
virtual bool checkSystemSolution(DomainPartition &domain, DofManager const &dofManager, arrayView1d< real64 const > const &localSolution, real64 const scalingFactor) override
Function to check system solution for physical consistency and constraint violation.
virtual void resetStateToBeginningOfStep(DomainPartition &domain) override
reset state of physics back to the beginning of the step.
@ FALSE
Not read from input.
@ REQUIRED
Required in input.
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
unsigned long long int Timestamp
Timestamp type (used to perform actions such a sparsity pattern computation after mesh modifications)
Definition: DataTypes.hpp:126
std::string string
String type.
Definition: DataTypes.hpp:90
double real64
64-bit floating point type.
Definition: DataTypes.hpp:98
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
Provides enum <-> string conversion facilities.
Exception class used to report errors in user input.
Definition: Logger.hpp:464
static constexpr char const * discretizationString()