21 #ifndef GEOS_PHYSICSSOLVERS_MULTIPHYSICS_COUPLEDSOLVER_HPP_
22 #define GEOS_PHYSICSSOLVERS_MULTIPHYSICS_COUPLEDSOLVER_HPP_
32 template<
typename ... SOLVERS >
44 Group *
const parent )
47 forEachArgInTuple(
m_solvers, [&](
auto solver,
auto idx )
49 using SolverType = TYPEOFPTR( solver );
50 string const key = SolverType::coupledSolverAttributePrefix() +
"SolverName";
52 setRTTypeName( rtTypes::CustomTypes::groupNameRef ).
54 setDescription(
"Name of the " + SolverType::coupledSolverAttributePrefix() +
" solver used by the coupled solver" );
60 addLogLevel< logInfo::Coupling >();
82 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto idx )
84 using SolverPtr = TYPEOFREF( solver );
85 using SolverType = TYPEOFPTR( SolverPtr {} );
86 auto const & solverName =
m_names[idx()];
87 auto const & solverType = LvArray::system::demangleType< SolverType >();
88 solver = this->
getParent().template getGroupPointer< SolverType >( solverName );
90 GEOS_FMT(
"{}: Could not find solver '{}' of type {}",
92 solverName, solverType ),
125 {
GEOS_UNUSED_VAR( time_n, dt, domain, dofManager, localMatrix, localRhs ); }
138 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
140 solver->setupDofs( domain, dofManager );
151 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
153 solver->implicitStepSetup( time_n, dt, domain );
162 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
164 solver->implicitStepComplete( time_n, dt, domain );
180 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
182 solver->assembleSystem( time_n, dt, domain, dofManager, localMatrix, localRhs );
192 real64 const scalingFactor,
196 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
198 solver->applySystemSolution( dofManager, localSolution, scalingFactor, dt, domain );
205 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
207 solver->updateState( domain );
214 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
216 solver->resetStateToBeginningOfStep( domain );
225 int const cycleNumber,
255 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
257 real64 const singlePhysicsNorm = solver->calculateResidualNorm( time_n, dt, domain, dofManager, localRhs );
258 norm += singlePhysicsNorm * singlePhysicsNorm;
272 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
274 solver->applyBoundaryConditions( time_n, dt, domain, dofManager, localMatrix, localRhs );
282 real64 const scalingFactor )
override
284 bool validSolution =
true;
285 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
287 bool const validSinglePhysicsSolution = solver->checkSystemSolution( domain, dofManager, localSolution, scalingFactor );
288 if( !validSinglePhysicsSolution )
290 GEOS_LOG_RANK_0( GEOS_FMT(
" {}/{}: Solution check failed. Newton loop terminated.",
getName(), solver->getName()) );
292 validSolution = validSolution && validSinglePhysicsSolution;
294 return validSolution;
302 real64 scalingFactor = 1e9;
303 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
305 real64 const singlePhysicsScalingFactor = solver->scalingForSystemSolution( domain, dofManager, localSolution );
306 scalingFactor = LvArray::math::min( scalingFactor, singlePhysicsScalingFactor );
308 return scalingFactor;
315 real64 nextDt = LvArray::NumericLimits< real64 >::max;
316 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
318 real64 const singlePhysicsNextDt =
319 solver->setNextDtBasedOnStateChange( currentDt, domain );
320 nextDt = LvArray::math::min( singlePhysicsNextDt, nextDt );
328 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
330 real64 const singlePhysicsNextDt =
331 solver->setNextDtBasedOnNewtonIter( currentDt );
332 nextDt = LvArray::math::min( singlePhysicsNextDt, nextDt );
340 real64 const eventProgress,
343 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
345 solver->cleanup( time_n, cycleNumber, eventCounter, eventProgress, domain );
354 bool isConverged =
true;
355 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
357 isConverged &= solver->checkSequentialSolutionIncrements( domain );
365 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
367 result &= solver->updateConfiguration( domain );
374 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
376 solver->outputConfigurationStatistics( domain );
382 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
384 solver->resetConfigurationToBeginningOfStep( domain );
391 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
393 result &= solver->resetConfigurationToDefault( domain );
411 int const cycleNumber,
429 int const cycleNumber,
436 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
438 if( meshModificationTimestamp > solver->getSystemSetupTimestamp() )
440 solver->setupSystem( domain,
441 solver->getDofManager(),
442 solver->getLocalMatrix(),
443 solver->getSystemRhs(),
444 solver->getSystemSolution() );
445 solver->setSystemSetupTimestamp( meshModificationTimestamp );
456 bool isConverged =
false;
463 for( dtAttempt = 0; dtAttempt < maxNumberDtCuts; ++dtAttempt )
468 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
470 solver->resetStateToBeginningOfStep( domain );
471 solver->getSolverStatistics().initializeTimeStepStatistics();
484 startSequentialIteration( iter, domain );
487 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto idx )
490 real64 solverDt = solver->nonlinearImplicitStep( time_n,
496 solver->saveSequentialIterationState( domain );
500 if( solverDt < stepDt )
508 isConverged = checkSequentialConvergence( iter,
522 finishSequentialIteration( iter, domain );
529 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
531 solver->getSolverStatistics().saveTimeStepStatistics();
539 stepDt *= dtCutFactor;
544 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
546 solver->getSolverStatistics().logTimeStepCut();
561 GEOS_ERROR(
"Nonconverged solutions not allowed. Terminating..." );
582 virtual bool checkSequentialConvergence(
int const & iter,
588 bool isConverged =
true;
603 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
606 solver->getLocalMatrix().toViewConstSizes().zero();
607 solver->getSystemRhs().zero();
608 arrayView1d< real64 >
const localRhs = solver->getSystemRhs().open();
611 solver->assembleSystem( time_n,
614 solver->getDofManager(),
615 solver->getLocalMatrix().toViewConstSizes(),
617 solver->applyBoundaryConditions( time_n,
620 solver->getDofManager(),
621 solver->getLocalMatrix().toViewConstSizes(),
623 solver->getSystemRhs().close();
626 real64 const singlePhysicsNorm =
627 solver->calculateResidualNorm( time_n,
630 solver->getDofManager(),
631 solver->getSystemRhs().values() );
632 residualNorm += singlePhysicsNorm * singlePhysicsNorm;
636 residualNorm = sqrt( residualNorm );
638 isConverged = ( residualNorm < params.
m_newtonTol );
644 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
646 NonlinearSolverParameters
const & singlePhysicsParams = solver->getNonlinearSolverParameters();
647 if( singlePhysicsParams.m_numNewtonIterations > singlePhysicsParams.m_minIterNewton )
664 GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::Convergence, GEOS_FMT(
"***** The iterative coupling has converged in {} iteration(s) *****", iter + 1 ) );
678 GEOS_FMT(
"{}: line search is not supported by the coupled solver when {} is set to `{}`. Please set {} to `{}` to remove this error",
680 NonlinearSolverParameters::viewKeysStruct::couplingTypeString(),
682 NonlinearSolverParameters::viewKeysStruct::lineSearchActionString(),
692 validateNonlinearAcceleration();
695 virtual void validateNonlinearAcceleration()
697 GEOS_THROW ( GEOS_FMT(
"{}: Nonlinear acceleration {} is not supported by {} solver '{}'",
698 getWrapperDataContext( NonlinearSolverParameters::viewKeysStruct::nonlinearAccelerationTypeString() ),
707 forEachArgInTuple(
m_solvers, [&](
auto & solver,
auto )
713 virtual void startSequentialIteration(
integer const & iter,
719 virtual void finishSequentialIteration(
integer const & iter,
720 DomainPartition & domain )
#define GEOS_UNUSED_VAR(...)
Mark an unused variable and silence compiler warnings.
#define GEOS_THROW(msg, TYPE)
Throw an exception.
#define GEOS_ERROR(msg)
Raise a hard error and terminate the program.
#define GEOS_LOG_RANK_0(msg)
Log a message on screen on rank 0.
#define GEOS_THROW_IF(EXP, msg, TYPE)
Conditionally throw an exception.
#define GEOS_MARK_FUNCTION
Mark function with both Caliper and NVTX if enabled.
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.
CoupledSolver(CoupledSolver const &)=delete
deleted copy constructor
virtual void synchronizeNonlinearSolverParameters() override
syncronize the nonlinear solver parameters.
virtual void setupCoupling(DomainPartition const &domain, DofManager &dofManager) const
Utility function to set the coupling between degrees of freedom.
virtual real64 sequentiallyCoupledSolverStep(real64 const &time_n, real64 const &dt, int const cycleNumber, DomainPartition &domain)
Sequentially coupled solver step. It solves a nonlinear system of equations using a sequential approa...
virtual bool checkSequentialSolutionIncrements(DomainPartition &domain) const override
Check if the solution increments are ok to use.
virtual void postInputInitialization() override
virtual bool updateConfiguration(DomainPartition &domain) override
updates the configuration (if needed) based on the state after a converged Newton loop.
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,...
Partition of the decomposed physical domain. It also manages the connexion information to its neighbo...
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.
@ FullyImplicit
Fully-implicit coupling.
@ Sequential
Sequential coupling.
real64 m_newtonTol
The tolerance for the nonlinear convergence check.
NonlinearAccelerationType m_nonlinearAccelerationType
Type of nonlinear acceleration for sequential solver.
@ None
Do not use line search.
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
SolverStatistics m_solverStatistics
Solver statistics.
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
NonlinearSolverParameters & getNonlinearSolverParameters()
accessor for the nonlinear solver parameters.
NonlinearSolverParameters m_nonlinearSolverParameters
Nonlinear solver parameters.
void logTimeStepCut()
Tell the solverStatistics that there is a time step cut.
void logNonlinearIteration(integer const numLinearIterations)
Tell the solverStatistics that we are doing a nonlinear iteration.
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
string const & getName() const
Get group name.
Group & getParent()
Access the group's parent.
DataContext const & getWrapperDataContext(KEY key) const
#define GEOS_LOG_LEVEL_INFO_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 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 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 setNextDtBasedOnStateChange(real64 const ¤tDt, DomainPartition &domain) override
function to set the next dt based on state change
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 setNextDtBasedOnNewtonIter(real64 const ¤tDt) override
function to set the next time step size based on Newton convergence
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 real64 setNextDtBasedOnNewtonIter(real64 const ¤tDt)
function to set the next time step size based on Newton convergence
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.
unsigned long long int Timestamp
Timestamp type (used to perform actions such a sparsity pattern computation after mesh modifications)
LvArray::CRSMatrixView< T, COL_INDEX, localIndex const, LvArray::ChaiBuffer > CRSMatrixView
Alias for CRS Matrix View.
std::string string
String type.
double real64
64-bit floating point type.
std::int32_t integer
Signed integer type.
Provides enum <-> string conversion facilities.
static constexpr char const * discretizationString()