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,
77  string const & solverWrapperKey,
78  string const & solverType )
79  {
80  string_array availableSolvers;
81 
82  this->getParent().template forSubGroups< T >( [&]( T & group )
83  {
84 
85  availableSolvers.emplace_back( group.getName());
86 
87  } );
88 
89  if( availableSolvers.empty() )
90  {
91  errorMessage << GEOS_FMT( "No {} solver has been found.", solverType );
92  }
93  else
94  {
95  errorMessage << GEOS_FMT( "Available {} solvers are: {}. ", solverType,
96  stringutilities::join( availableSolvers, ", " ) );
97  }
98 
99  GEOS_THROW( errorMessage.str(),
100  InputError, getWrapperDataContext( solverWrapperKey ) );
101  }
105  void
107  {
108  forEachArgInTuple( m_solvers, [&]( auto & solver, auto idx )
109  {
110  using SolverPtr = TYPEOFREF( solver );
111  using SolverType = TYPEOFPTR( SolverPtr {} );
112  auto const & solverName = m_names[idx()];
113  solver = this->getParent().template getGroupPointer< SolverType >( solverName );
114  if( solver== nullptr )
115  {
116  string const solverWrapperKey = SolverType::coupledSolverAttributePrefix() + "SolverName";
117  std::ostringstream errorMessage;
118  errorMessage << GEOS_FMT( "Could not find solver named '{}'.\n", solverName );
119  throwSolversNotFound< SolverType >( errorMessage, solverWrapperKey, SolverType::coupledSolverAttributePrefix() );
120  }
121 
122 
123  GEOS_LOG_LEVEL_RANK_0( logInfo::Coupling,
124  GEOS_FMT( "{}: found {} solver named {}",
125  getName(), solver->getCatalogName(), solverName ) );
126  } );
127  }
128 
129 
135  virtual void
137  DofManager & dofManager ) const
138  { GEOS_UNUSED_VAR( domain, dofManager ); }
139 
149  virtual void
151  real64 const dt,
152  DomainPartition const & domain,
153  DofManager const & dofManager,
154  CRSMatrixView< real64, globalIndex const > const & localMatrix,
155  arrayView1d< real64 > const & localRhs )
156  { GEOS_UNUSED_VAR( time_n, dt, domain, dofManager, localMatrix, localRhs ); }
157 
165  void
166  setupDofs( DomainPartition const & domain,
167  DofManager & dofManager ) const override
168  {
169  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
170  {
171  solver->setupDofs( domain, dofManager );
172  } );
173 
174  setupCoupling( domain, dofManager );
175  }
176 
177  virtual void
178  implicitStepSetup( real64 const & time_n,
179  real64 const & dt,
180  DomainPartition & domain ) override
181  {
182  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
183  {
184  solver->implicitStepSetup( time_n, dt, domain );
185  } );
186  }
187 
188  virtual void
189  implicitStepComplete( real64 const & time_n,
190  real64 const & dt,
191  DomainPartition & domain ) override
192  {
193  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
194  {
195  solver->implicitStepComplete( time_n, dt, domain );
196  } );
197  }
198 
199  // general version of assembleSystem function, keep in mind many solvers will override it
200  virtual void
201  assembleSystem( real64 const time_n,
202  real64 const dt,
203  DomainPartition & domain,
204  DofManager const & dofManager,
205  CRSMatrixView< real64, globalIndex const > const & localMatrix,
206  arrayView1d< real64 > const & localRhs ) override
207  {
209 
210  // 1. Assemble matrix blocks of each individual solver
211  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
212  {
213  solver->assembleSystem( time_n, dt, domain, dofManager, localMatrix, localRhs );
214  } );
215 
216  // 2. Assemble coupling blocks
217  assembleCouplingTerms( time_n, dt, domain, dofManager, localMatrix, localRhs );
218  }
219 
220  virtual void
221  applySystemSolution( DofManager const & dofManager,
222  arrayView1d< real64 const > const & localSolution,
223  real64 const scalingFactor,
224  real64 const dt,
225  DomainPartition & domain ) override
226  {
227  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
228  {
229  solver->applySystemSolution( dofManager, localSolution, scalingFactor, dt, domain );
230  } );
231  }
232 
233  virtual void
234  updateState( DomainPartition & domain ) override
235  {
236  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
237  {
238  solver->updateState( domain );
239  } );
240  }
241 
242  virtual void
244  {
245  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
246  {
247  solver->resetStateToBeginningOfStep( domain );
248  } );
249  }
250 
253  real64
254  solverStep( real64 const & time_n,
255  real64 const & dt,
256  int const cycleNumber,
257  DomainPartition & domain ) override final
258  {
260 
262  {
263  return fullyCoupledSolverStep( time_n, dt, cycleNumber, domain );
264  }
266  {
267  return sequentiallyCoupledSolverStep( time_n, dt, cycleNumber, domain );
268  }
269  else
270  {
271  GEOS_ERROR( "Invalid coupling type option.", getDataContext() );
272  return 0;
273  }
274 
275  }
276 
277 
278  virtual void
279  updateAndWriteConvergenceStep( real64 const & time_n, real64 const & dt,
280  integer const cycleNumber, integer const iteration ) override
281  {
282  PhysicsSolverBase::updateAndWriteConvergenceStep( time_n, dt, cycleNumber, iteration );
283  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
284  {
285  solver->updateAndWriteConvergenceStep( time_n, dt, cycleNumber, iteration );
286  } );
287  }
288 
289  virtual real64
290  calculateResidualNorm( real64 const & time_n,
291  real64 const & dt,
292  DomainPartition const & domain,
293  DofManager const & dofManager,
294  arrayView1d< real64 const > const & localRhs ) override
295  {
296  real64 norm = 0.0;
297  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
298  {
299  real64 const singlePhysicsNorm = solver->calculateResidualNorm( time_n, dt, domain, dofManager, localRhs );
300  norm += singlePhysicsNorm * singlePhysicsNorm;
301  } );
302 
303  return sqrt( norm );
304  }
305 
306  virtual void
308  real64 const dt,
309  DomainPartition & domain,
310  DofManager const & dofManager,
311  CRSMatrixView< real64, globalIndex const > const & localMatrix,
312  arrayView1d< real64 > const & localRhs ) override
313  {
314  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
315  {
316  solver->applyBoundaryConditions( time_n, dt, domain, dofManager, localMatrix, localRhs );
317  } );
318  }
319 
320  virtual bool
322  DofManager const & dofManager,
323  arrayView1d< real64 const > const & localSolution,
324  real64 const scalingFactor ) override
325  {
326  bool validSolution = true;
327  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
328  {
329  bool const validSinglePhysicsSolution = solver->checkSystemSolution( domain, dofManager, localSolution, scalingFactor );
330  if( !validSinglePhysicsSolution )
331  {
332  GEOS_LOG_RANK_0( GEOS_FMT( " {}/{}: Solution check failed. Newton loop terminated.", getName(), solver->getName()) );
333  }
334  validSolution = validSolution && validSinglePhysicsSolution;
335  } );
336  return validSolution;
337  }
338 
339  virtual real64
341  DofManager const & dofManager,
342  arrayView1d< real64 const > const & localSolution ) override
343  {
344  real64 scalingFactor = PhysicsSolverBase::scalingForSystemSolution( domain, dofManager, localSolution );
345  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
346  {
347  real64 const singlePhysicsScalingFactor = solver->scalingForSystemSolution( domain, dofManager, localSolution );
348  scalingFactor = LvArray::math::min( scalingFactor, singlePhysicsScalingFactor );
349  } );
350  return scalingFactor;
351  }
352 
353  virtual real64
354  setNextDt( real64 const & currentTime,
355  real64 const & currentDt,
356  DomainPartition & domain ) override
357  {
358  real64 nextDt = PhysicsSolverBase::setNextDt( currentTime, currentDt, domain );
359  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
360  {
361  real64 const singlePhysicsNextDt =
362  solver->setNextDt( currentTime, currentDt, domain );
363  nextDt = LvArray::math::min( singlePhysicsNextDt, nextDt );
364  } );
365  return nextDt;
366  }
367 
368  virtual void cleanup( real64 const time_n,
369  integer const cycleNumber,
370  integer const eventCounter,
371  real64 const eventProgress,
372  DomainPartition & domain ) override
373  {
374  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
375  {
376  solver->cleanup( time_n, cycleNumber, eventCounter, eventProgress, domain );
377  } );
378  PhysicsSolverBase::cleanup( time_n, cycleNumber, eventCounter, eventProgress, domain );
379  }
380 
383  virtual bool checkSequentialSolutionIncrements( DomainPartition & domain ) const override
384  {
385  bool isConverged = true;
386  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
387  {
388  isConverged &= solver->checkSequentialSolutionIncrements( domain );
389  } );
390  return isConverged;
391  }
392 
393  virtual bool updateConfiguration( DomainPartition & domain,
394  integer const configurationLoopIter ) override
395  {
396  bool result = true;
397  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
398  {
399  result &= solver->updateConfiguration( domain, configurationLoopIter );
400  } );
401  return result;
402  }
403 
404  virtual void outputConfigurationStatistics( DomainPartition const & domain ) const override
405  {
406  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
407  {
408  solver->outputConfigurationStatistics( domain );
409  } );
410  }
411 
412  virtual void resetConfigurationToBeginningOfStep( DomainPartition & domain ) override
413  {
414  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
415  {
416  solver->resetConfigurationToBeginningOfStep( domain );
417  } );
418  }
419 
420  virtual bool resetConfigurationToDefault( DomainPartition & domain ) const override
421  {
422  bool result = true;
423  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
424  {
425  result &= solver->resetConfigurationToDefault( domain );
426  } );
427  return result;
428  }
429 
430  virtual void
432  {
433  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
434  {
435  solver->getNonlinearSolverParameters() = getNonlinearSolverParameters();
436  solver->synchronizeNonlinearSolverParameters();
437  } );
438  }
439 
440 protected:
441 
451  virtual real64 fullyCoupledSolverStep( real64 const & time_n,
452  real64 const & dt,
453  int const cycleNumber,
454  DomainPartition & domain )
455  {
456  return PhysicsSolverBase::solverStep( time_n, dt, cycleNumber, domain );
457  }
458 
469  virtual real64 sequentiallyCoupledSolverStep( real64 const & time_n,
470  real64 const & dt,
471  integer const cycleNumber,
472  DomainPartition & domain )
473  {
475 
476  // Only build the sparsity pattern if the mesh has changed
477  Timestamp const meshModificationTimestamp = getMeshModificationTimestamp( domain );
478  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
479  {
480  if( meshModificationTimestamp > solver->getSystemSetupTimestamp() )
481  {
482  solver->setupSystem( domain,
483  solver->getDofManager(),
484  solver->getLocalMatrix(),
485  solver->getSystemRhs(),
486  solver->getSystemSolution() );
487  solver->setSystemSetupTimestamp( meshModificationTimestamp );
488  }
489  } );
490 
491  implicitStepSetup( time_n, dt, domain );
492 
494  integer const maxNumberDtCuts = solverParams.m_maxTimeStepCuts;
495  real64 const dtCutFactor = solverParams.m_timeStepCutFactor;
496  integer & dtAttempt = solverParams.m_numTimeStepAttempts;
497 
498  bool isConverged = false;
499  // dt may be cut during the course of this step, so we are keeping a local
500  // value to track the achieved dt for this step.
501  real64 stepDt = dt;
502 
503  // outer loop attempts to apply full timestep, and managed the cutting of the timestep if
504  // required.
505  for( dtAttempt = 0; dtAttempt < maxNumberDtCuts; ++dtAttempt )
506  {
507  // TODO configuration loop
508 
509  // Reset the states of all solvers if any of them had to restart
510  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
511  {
512  solver->resetStateToBeginningOfStep( domain );
513  solver->getIterationStats().resetCurrentTimeStepStatistics(); // initialize counters for subsolvers
514  } );
515  resetStateToBeginningOfStep( domain );
516 
517  integer & iter = solverParams.m_numNewtonIterations;
518 
520  for( iter = 0; iter < solverParams.m_maxIterNewton; iter++ )
521  {
522  // Increment the solver statistics for reporting purposes
524 
525  startSequentialIteration( iter, domain );
526 
527  // Solve the subproblems nonlinearly
528  forEachArgInTuple( m_solvers, [&]( auto & solver, auto idx )
529  {
530  GEOS_LOG_LEVEL_RANK_0( logInfo::NonlinearSolver,
531  GEOS_FMT( " Iteration {:2}: {}", iter + 1, solver->getName() ) );
532  real64 solverDt = solver->nonlinearImplicitStep( time_n,
533  stepDt,
534  cycleNumber,
535  domain );
536 
537  // save fields (e.g. pressure and temperature) after inner solve
538  if( solver->getNonlinearSolverParameters().couplingType() == NonlinearSolverParameters::CouplingType::Sequential )
539  {
540  solver->saveSequentialIterationState( domain );
541  }
542 
543  mapSolutionBetweenSolvers( domain, idx() );
544 
545  if( solverDt < stepDt ) // subsolver had to cut the time step
546  {
547  iter = 0; // restart outer loop
548  stepDt = solverDt; // sync time step
550  }
551  } );
552  // Check convergence of the outer loop
553  isConverged = checkSequentialConvergence( cycleNumber,
554  iter,
555  time_n,
556  stepDt,
557  domain );
558 
559  if( isConverged )
560  {
561  // we still want to count current iteration
562  ++iter;
563  // exit outer loop
564  break;
565  }
566  else
567  {
568  finishSequentialIteration( iter, domain );
569  }
570  }
571 
572  if( isConverged )
573  {
574  // Save time step statistics for the subsolvers
575  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
576  {
577  solver->getIterationStats().iterateTimeStepStatistics();
578  } );
579  // get out of the time loop
580  break;
581  }
582  else
583  {
584  // cut timestep, go back to beginning of step and restart the Newton loop
585  stepDt *= dtCutFactor;
587  GEOS_LOG_LEVEL_RANK_0( logInfo::TimeStep, GEOS_FMT( "New dt = {}", stepDt ) );
588 
589  // notify the solver statistics counter that this is a time step cut
591  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
592  {
593  solver->getIterationStats().updateTimeStepCut();
594  } );
595  }
596  }
597 
598  if( !isConverged )
599  {
600  GEOS_LOG_RANK_0( "Convergence not achieved." );
601 
603  {
604  GEOS_LOG_RANK_0( "The accepted solution may be inaccurate." );
605  }
606  else
607  {
608  GEOS_ERROR( "Nonconverged solutions not allowed. Terminating...", getDataContext() );
609  }
610  }
611 
612  implicitStepComplete( time_n, stepDt, domain );
613 
614  return stepDt;
615  }
616 
624  integer const solverType )
625  {
626  GEOS_UNUSED_VAR( domain, solverType );
627  }
628 
629  virtual bool checkSequentialConvergence( integer const cycleNumber,
630  integer const iter,
631  real64 const & time_n,
632  real64 const & dt,
633  DomainPartition & domain )
634  {
636  bool isConverged = true;
637 
638  if( params.m_subcyclingOption == 0 )
639  {
640  GEOS_LOG_LEVEL_RANK_0( logInfo::Convergence, "***** Single Pass solver, no subcycling *****" );
641  }
642  else
643  {
644  GEOS_LOG_LEVEL_RANK_0( logInfo::Convergence, GEOS_FMT( " Iteration {:2}: outer-loop convergence check", iter + 1 ) );
645 
647  {
648  real64 residualNorm = 0;
649 
650  // loop over all the single-physics solvers
651  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
652  {
653 
654  solver->getLocalMatrix().toViewConstSizes().zero();
655  solver->getSystemRhs().zero();
656  arrayView1d< real64 > const localRhs = solver->getSystemRhs().open();
657 
658  // for each solver, we have to recompute the residual (and Jacobian, although not necessary)
659  solver->assembleSystem( time_n,
660  dt,
661  domain,
662  solver->getDofManager(),
663  solver->getLocalMatrix().toViewConstSizes(),
664  localRhs );
665  solver->applyBoundaryConditions( time_n,
666  dt,
667  domain,
668  solver->getDofManager(),
669  solver->getLocalMatrix().toViewConstSizes(),
670  localRhs );
671  solver->getSystemRhs().close();
672 
673  // once this is done, we recompute the single-physics residual
674  real64 const singlePhysicsNorm =
675  solver->calculateResidualNorm( time_n,
676  dt,
677  domain,
678  solver->getDofManager(),
679  solver->getSystemRhs().values() );
680  residualNorm += singlePhysicsNorm * singlePhysicsNorm;
681  } );
682 
683  // finally, we perform the convergence check on the multiphysics residual
684  residualNorm = sqrt( residualNorm );
685  GEOS_LOG_LEVEL_RANK_0( logInfo::ResidualNorm,
686  GEOS_FMT( " ( R ) = ( {:4.2e} )", residualNorm ) );
687  getConvergenceStats().setResidualValue( "R", residualNorm );
688  updateAndWriteConvergenceStep( time_n, dt, cycleNumber, iter );
689 
690  isConverged = ( residualNorm < params.m_newtonTol );
691 
692  }
694  {
695  // TODO also make recursive?
696  forEachArgInTuple( m_solvers, [&]( auto & solver, auto )
697  {
698  NonlinearSolverParameters const & singlePhysicsParams = solver->getNonlinearSolverParameters();
699  if( singlePhysicsParams.m_numNewtonIterations > singlePhysicsParams.m_minIterNewton )
700  {
701  isConverged = false;
702  }
703  } );
704  }
706  {
707  isConverged = checkSequentialSolutionIncrements( domain );
708  }
709  else
710  {
711  GEOS_ERROR( "Invalid sequential convergence criterion.", getDataContext() );
712  }
713 
714  if( isConverged )
715  {
716  GEOS_LOG_LEVEL_RANK_0( logInfo::Convergence,
717  GEOS_FMT( "***** The iterative coupling has converged in {} iteration(s) *****", iter + 1 ) );
718  }
719  }
720  return isConverged;
721  }
722 
723  virtual void
725  {
726  setSubSolvers();
727 
729 
732  GEOS_THROW_IF( isSequential && usesLineSearch,
733  GEOS_FMT( "{}: line search is not supported by the coupled solver when {} is set to `{}`. Please set {} to `{}` to remove this error",
734  getNonlinearSolverParameters().getWrapperDataContext( NonlinearSolverParameters::viewKeysStruct::couplingTypeString() ),
735  NonlinearSolverParameters::viewKeysStruct::couplingTypeString(),
737  NonlinearSolverParameters::viewKeysStruct::lineSearchActionString(),
739  InputError, getNonlinearSolverParameters().getWrapperDataContext( NonlinearSolverParameters::viewKeysStruct::couplingTypeString() ) );
740 
742  {
743  validateNonlinearAcceleration();
744  }
745  }
746 
747  virtual void validateNonlinearAcceleration()
748  {
749  GEOS_THROW ( GEOS_FMT( "{}: Nonlinear acceleration {} is not supported by {} solver '{}'",
750  getWrapperDataContext( NonlinearSolverParameters::viewKeysStruct::nonlinearAccelerationTypeString() ),
752  getCatalogName(), getName()),
753  InputError );
754  }
755 
756  virtual void initializePreSubGroups() override
757  {
759 
761  if( !isSequential )
762  {
764  }
765  }
766 
767  virtual void startSequentialIteration( integer const & iter,
768  DomainPartition & domain )
769  {
770  GEOS_UNUSED_VAR( iter, domain );
771  }
772 
773  virtual void finishSequentialIteration( integer const & iter,
774  DomainPartition & domain )
775  {
776  GEOS_UNUSED_VAR( iter, domain );
777  }
778 
779 protected:
780 
782  std::tuple< SOLVERS *... > m_solvers;
783 
785  std::array< string, sizeof...( SOLVERS ) > m_names;
786 };
787 
788 } /* namespace geos */
789 
790 #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,...)
Conditionally raise a hard error and terminate the program.
Definition: Logger.hpp:273
#define GEOS_ERROR(...)
Raise a hard error and terminate the program.
Definition: Logger.hpp:204
#define GEOS_LOG_RANK_0(msg)
Log a message on screen on rank 0.
Definition: Logger.hpp:99
#define GEOS_THROW_IF(COND, MSG,...)
Conditionally raise a hard error and terminate the program.
Definition: Logger.hpp:263
#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:1544
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:1343
string const & getName() const
Get group name.
Definition: Group.hpp:1329
Group & getParent()
Access the group's parent.
Definition: Group.hpp:1362
DataContext const & getWrapperDataContext(KEY key) const
Definition: Group.hpp:1354
#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.
static constexpr char const * discretizationString()