OGS
Loading...
Searching...
No Matches
NumLib::NonlinearSolver< NonlinearSolverTag::Newton > Class Referencefinal

Detailed Description

Find a solution to a nonlinear equation using the Newton-Raphson method.

Definition at line 76 of file NonlinearSolver.h.

#include <NonlinearSolver.h>

Inheritance diagram for NumLib::NonlinearSolver< NonlinearSolverTag::Newton >:
[legend]
Collaboration diagram for NumLib::NonlinearSolver< NonlinearSolverTag::Newton >:
[legend]

Public Types

using System = NonlinearSystem<NonlinearSolverTag::Newton>
 Type of the nonlinear equation system to be solved.
 

Public Member Functions

 NonlinearSolver (GlobalLinearSolver &linear_solver, int const maxiter, int const recompute_jacobian=1, double const damping=1.0)
 
 ~NonlinearSolver ()
 
void setEquationSystem (System &eq, ConvergenceCriterion &conv_crit)
 
void calculateNonEquilibriumInitialResiduum (std::vector< GlobalVector * > const &x, std::vector< GlobalVector * > const &x_prev, int const process_id) override
 
NonlinearSolverStatus solve (std::vector< GlobalVector * > &x, std::vector< GlobalVector * > const &x_prev, std::function< void(int, bool, std::vector< GlobalVector * > const &)> const &postIterationCallback, int const process_id) override
 
void compensateNonEquilibriumInitialResiduum (bool const value)
 
- Public Member Functions inherited from NumLib::NonlinearSolverBase
virtual ~NonlinearSolverBase ()=default
 

Private Attributes

GlobalLinearSolver_linear_solver
 
System_equation_system = nullptr
 
ConvergenceCriterion_convergence_criterion = nullptr
 
int const _maxiter
 maximum number of iterations
 
int const _recompute_jacobian = 1
 
double const _damping
 
GlobalVector_r_neq = nullptr
 non-equilibrium initial residuum.
 
std::size_t _res_id = 0u
 ID of the residual vector.
 
std::size_t _J_id = 0u
 ID of the Jacobian matrix.
 
std::size_t _minus_delta_x_id = 0u
 ID of the \( -\Delta x\) vector.
 
std::size_t _x_new_id
 ID of the vector storing \( x - (-\Delta x) \).
 
std::size_t _r_neq_id = 0u
 
bool _compensate_non_equilibrium_initial_residuum = false
 

Member Typedef Documentation

◆ System

Type of the nonlinear equation system to be solved.

Definition at line 81 of file NonlinearSolver.h.

Constructor & Destructor Documentation

◆ NonlinearSolver()

NumLib::NonlinearSolver< NonlinearSolverTag::Newton >::NonlinearSolver ( GlobalLinearSolver & linear_solver,
int const maxiter,
int const recompute_jacobian = 1,
double const damping = 1.0 )
inlineexplicit

Constructs a new instance.

Parameters
linear_solverthe linear solver used by this nonlinear solver.
maxiterthe maximum number of iterations used to solve the equation.
recompute_jacobianrecompute jacobian for the follow-up steps
dampingA positive damping factor.
See also
_damping

Definition at line 92 of file NonlinearSolver.h.

◆ ~NonlinearSolver()

Definition at line 600 of file NonlinearSolver.cpp.

601{
602 if (_r_neq != nullptr)
603 {
605 }
606}
GlobalVector * _r_neq
non-equilibrium initial residuum.
virtual void releaseVector(GlobalVector const &x)=0
static NUMLIB_EXPORT VectorProvider & provider

References NumLib::GlobalVectorProvider::provider, and NumLib::VectorProvider::releaseVector().

Member Function Documentation

◆ calculateNonEquilibriumInitialResiduum()

void NumLib::NonlinearSolver< NonlinearSolverTag::Newton >::calculateNonEquilibriumInitialResiduum ( std::vector< GlobalVector * > const & x,
std::vector< GlobalVector * > const & x_prev,
int const process_id )
overridevirtual

Implements NumLib::NonlinearSolverBase.

Definition at line 302 of file NonlinearSolver.cpp.

306{
308 {
309 return;
310 }
311
312 INFO("Calculate non-equilibrium initial residuum.");
313
314 _equation_system->assemble(x, x_prev, process_id);
316 _equation_system->getResidual(*x[process_id], *x_prev[process_id], *_r_neq);
317
318 // Set the values of the selected entries of _r_neq, which are associated
319 // with the equations that do not need initial residual compensation, to
320 // zero.
321 const auto selected_global_indices =
323 std::vector<double> zero_entries(selected_global_indices.size(), 0.0);
324
325 _r_neq->set(selected_global_indices, zero_entries);
326
328}
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:35
void set(IndexType rowId, double v)
set entry
Definition EigenVector.h:73
virtual std::vector< GlobalIndexType > getIndicesOfResiduumWithoutInitialCompensation() const =0
virtual void assemble(std::vector< GlobalVector * > const &x, std::vector< GlobalVector * > const &x_prev, int const process_id)=0
virtual void getResidual(GlobalVector const &x, GlobalVector const &x_prev, GlobalVector &res) const =0
virtual GlobalVector & getVector(std::size_t &id)=0
Get an uninitialized vector with the given id.
void finalizeAssembly(PETScMatrix &A)
Definition LinAlg.cpp:198

References MathLib::LinAlg::finalizeAssembly(), NumLib::VectorProvider::getVector(), INFO(), and NumLib::GlobalVectorProvider::provider.

◆ compensateNonEquilibriumInitialResiduum()

void NumLib::NonlinearSolver< NonlinearSolverTag::Newton >::compensateNonEquilibriumInitialResiduum ( bool const value)
inline

Definition at line 125 of file NonlinearSolver.h.

◆ setEquationSystem()

void NumLib::NonlinearSolver< NonlinearSolverTag::Newton >::setEquationSystem ( System & eq,
ConvergenceCriterion & conv_crit )
inline

Set the nonlinear equation system that will be solved. TODO doc

Definition at line 107 of file NonlinearSolver.h.

108 {
109 _equation_system = &eq;
110 _convergence_criterion = &conv_crit;
111 }

◆ solve()

NonlinearSolverStatus NumLib::NonlinearSolver< NonlinearSolverTag::Newton >::solve ( std::vector< GlobalVector * > & x,
std::vector< GlobalVector * > const & x_prev,
std::function< void(int, bool, std::vector< GlobalVector * > const &)> const & postIterationCallback,
int const process_id )
overridevirtual

Assemble and solve the equation system.

Parameters
xin: the initial guess, out: the solution.
x_prevprevious time step solution.
postIterationCallbackcalled after each iteration if set.
process_idusually used in staggered schemes.
Return values
trueif the equation system could be solved
falseotherwise

Implements NumLib::NonlinearSolverBase.

Definition at line 330 of file NonlinearSolver.cpp.

336{
337 namespace LinAlg = MathLib::LinAlg;
338 auto& sys = *_equation_system;
339
341 auto& minus_delta_x =
344
345 bool error_norms_met = false;
346
347 // TODO be more efficient
348 // init minus_delta_x to the right size
349 LinAlg::copy(*x[process_id], minus_delta_x);
350
352
353 int iteration = 1;
354#if !defined(USE_PETSC) && !defined(USE_LIS)
355 int next_iteration_inv_jacobian_recompute = 1;
356#endif
357 for (; iteration <= _maxiter; ++iteration, _convergence_criterion->reset())
358 {
359 BaseLib::RunTime timer_dirichlet;
360 double time_dirichlet = 0.0;
361
362 BaseLib::RunTime time_iteration;
363 time_iteration.start();
364
365 timer_dirichlet.start();
366 sys.computeKnownSolutions(*x[process_id], process_id);
367 time_dirichlet += timer_dirichlet.elapsed();
368
369 sys.preIteration(iteration, *x[process_id]);
370
371 BaseLib::RunTime time_assembly;
372 time_assembly.start();
373 bool mpi_rank_assembly_ok = true;
374 try
375 {
376 sys.assemble(x, x_prev, process_id);
377 }
378 catch (AssemblyException const& e)
379 {
380 ERR("Abort nonlinear iteration. Repeating timestep. Reason: {:s}",
381 e.what());
382 error_norms_met = false;
383 iteration = _maxiter;
384 mpi_rank_assembly_ok = false;
385 }
386 if (BaseLib::MPI::anyOf(!mpi_rank_assembly_ok))
387 {
388 break;
389 }
390 sys.getResidual(*x[process_id], *x_prev[process_id], res);
391 sys.getJacobian(J);
392 INFO("[time] Assembly took {:g} s.", time_assembly.elapsed());
393
394 // Subtract non-equilibrium initial residuum if set
395 if (_r_neq != nullptr)
396 LinAlg::axpy(res, -1, *_r_neq);
397
398 minus_delta_x.setZero();
399
400 timer_dirichlet.start();
401 sys.applyKnownSolutionsNewton(J, res, *x[process_id], minus_delta_x);
402 time_dirichlet += timer_dirichlet.elapsed();
403 INFO("[time] Applying Dirichlet BCs took {:g} s.", time_dirichlet);
404
405 if (!sys.isLinear() && _convergence_criterion->hasResidualCheck())
406 {
408 }
409
410 BaseLib::RunTime time_linear_solver;
411 time_linear_solver.start();
412#if !defined(USE_PETSC) && !defined(USE_LIS)
413 auto linear_solver_behaviour = MathLib::LinearSolverBehaviour::REUSE;
414 if (iteration == next_iteration_inv_jacobian_recompute)
415 {
416 linear_solver_behaviour =
418 next_iteration_inv_jacobian_recompute =
419 next_iteration_inv_jacobian_recompute + _recompute_jacobian;
420 }
421 if (!_linear_solver.compute(J, linear_solver_behaviour))
422 {
423 ERR("Newton: The linear solver failed in the compute() step.");
424 }
425 bool iteration_succeeded = _linear_solver.solve(res, minus_delta_x);
426#else
427 bool iteration_succeeded = _linear_solver.solve(J, res, minus_delta_x);
428#endif
429 INFO("[time] Linear solver took {:g} s.", time_linear_solver.elapsed());
430
431 if (!iteration_succeeded)
432 {
433 ERR("Newton: The linear solver failed.");
434 }
435 else
436 {
437 // TODO could be solved in a better way
438 // cf.
439 // https://petsc.org/release/manualpages/Vec/VecWAXPY
440
441 // Copy pointers, replace the one for the given process id.
442 std::vector<GlobalVector*> x_new{x};
443 x_new[process_id] =
445 *x[process_id], _x_new_id);
446 double damping = _damping;
448 {
450 minus_delta_x, *x[process_id], _damping);
451 }
452 LinAlg::axpy(*x_new[process_id], -damping, minus_delta_x);
453
454 if (postIterationCallback)
455 {
456 postIterationCallback(iteration, error_norms_met, x_new);
457 }
458
459 switch (sys.postIteration(*x_new[process_id]))
460 {
462 break;
464 ERR("Newton: The postIteration() hook reported a "
465 "non-recoverable error.");
466 iteration_succeeded = false;
467 break;
469 INFO(
470 "Newton: The postIteration() hook decided that this "
471 "iteration has to be repeated.");
472 // TODO introduce some onDestroy hook.
474 *x_new[process_id]);
475 continue; // That throws the iteration result away.
476 }
477
478 LinAlg::copy(*x_new[process_id],
479 *x[process_id]); // copy new solution to x
481 *x_new[process_id]);
482 }
483
484 if (!iteration_succeeded)
485 {
486 // Don't compute further error norms, but break here.
487 error_norms_met = false;
488 break;
489 }
490
491 if (sys.isLinear())
492 {
493 error_norms_met = true;
494 }
495 else
496 {
498 {
499 // Note: x contains the new solution!
500 _convergence_criterion->checkDeltaX(minus_delta_x,
501 *x[process_id]);
502 }
503
504 error_norms_met = _convergence_criterion->isSatisfied();
505 }
506
507 INFO("[time] Iteration #{:d} took {:g} s.", iteration,
508 time_iteration.elapsed());
509
510 if (error_norms_met)
511 {
512 break;
513 }
514
515 // Avoid increment of the 'iteration' if the error norms are not met,
516 // but maximum number of iterations is reached.
517 if (iteration >= _maxiter)
518 {
519 break;
520 }
521 }
522
523 if (iteration > _maxiter)
524 {
525 ERR("Newton: Could not solve the given nonlinear system within {:d} "
526 "iterations",
527 _maxiter);
528 }
529
533
534 return {error_norms_met, iteration};
535}
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:45
Count the running time.
Definition RunTime.h:29
double elapsed() const
Get the elapsed time in seconds.
Definition RunTime.h:42
void start()
Start the timer.
Definition RunTime.h:32
bool solve(EigenMatrix &A, EigenVector &b, EigenVector &x)
virtual double getDampingFactor(GlobalVector const &minus_delta_x, GlobalVector const &x, double damping_orig)=0
virtual void checkResidual(GlobalVector const &residual)=0
Check if the residual satisfies the convergence criterion.
virtual bool hasResidualCheck() const =0
virtual bool isSatisfied() const
Tell if the convergence criterion is satisfied.
virtual void checkDeltaX(GlobalVector const &minus_delta_x, GlobalVector const &x)=0
virtual bool hasDeltaXCheck() const =0
virtual bool hasNonNegativeDamping() const =0
virtual void releaseMatrix(GlobalMatrix const &A)=0
virtual GlobalMatrix & getMatrix(std::size_t &id)=0
Get an uninitialized matrix with the given id.
std::size_t _J_id
ID of the Jacobian matrix.
std::size_t _x_new_id
ID of the vector storing .
std::size_t _res_id
ID of the residual vector.
static bool anyOf(bool const val, Mpi const &mpi=Mpi{MPI_COMM_WORLD})
Definition MPI.h:187
void copy(PETScVector const &x, PETScVector &y)
Definition LinAlg.cpp:37
void axpy(PETScVector &y, PetscScalar const a, PETScVector const &x)
Definition LinAlg.cpp:57
static NUMLIB_EXPORT MatrixProvider & provider

References BaseLib::MPI::anyOf(), MathLib::LinAlg::axpy(), MathLib::LinAlg::copy(), BaseLib::RunTime::elapsed(), ERR(), NumLib::FAILURE, NumLib::MatrixProvider::getMatrix(), NumLib::VectorProvider::getVector(), INFO(), NumLib::GlobalMatrixProvider::provider, NumLib::GlobalVectorProvider::provider, MathLib::RECOMPUTE_AND_STORE, NumLib::MatrixProvider::releaseMatrix(), NumLib::VectorProvider::releaseVector(), NumLib::REPEAT_ITERATION, MathLib::REUSE, BaseLib::RunTime::start(), and NumLib::SUCCESS.

Member Data Documentation

◆ _compensate_non_equilibrium_initial_residuum

bool NumLib::NonlinearSolver< NonlinearSolverTag::Newton >::_compensate_non_equilibrium_initial_residuum = false
private

Enables computation of the non-equilibrium initial residuum \( r_{\rm neq} \) before the first time step. The forces are zero if the external forces are in equilibrium with the initial state/initial conditions. During the simulation the new residuum reads \( \tilde r = r - r_{\rm neq} \).

Definition at line 160 of file NonlinearSolver.h.

◆ _convergence_criterion

ConvergenceCriterion* NumLib::NonlinearSolver< NonlinearSolverTag::Newton >::_convergence_criterion = nullptr
private

Definition at line 135 of file NonlinearSolver.h.

◆ _damping

double const NumLib::NonlinearSolver< NonlinearSolverTag::Newton >::_damping
private

A positive damping factor. The default value 1.0 gives a non-damped Newton method. Common values are in the range 0.5 to 0.7 for somewhat conservative method and seldom become smaller than 0.2 for very conservative approach.

Definition at line 144 of file NonlinearSolver.h.

◆ _equation_system

System* NumLib::NonlinearSolver< NonlinearSolverTag::Newton >::_equation_system = nullptr
private

Definition at line 132 of file NonlinearSolver.h.

◆ _J_id

std::size_t NumLib::NonlinearSolver< NonlinearSolverTag::Newton >::_J_id = 0u
private

ID of the Jacobian matrix.

Definition at line 148 of file NonlinearSolver.h.

◆ _linear_solver

Definition at line 131 of file NonlinearSolver.h.

◆ _maxiter

int const NumLib::NonlinearSolver< NonlinearSolverTag::Newton >::_maxiter
private

maximum number of iterations

Definition at line 136 of file NonlinearSolver.h.

◆ _minus_delta_x_id

std::size_t NumLib::NonlinearSolver< NonlinearSolverTag::Newton >::_minus_delta_x_id = 0u
private

ID of the \( -\Delta x\) vector.

Definition at line 149 of file NonlinearSolver.h.

◆ _r_neq

non-equilibrium initial residuum.

Definition at line 146 of file NonlinearSolver.h.

◆ _r_neq_id

std::size_t NumLib::NonlinearSolver< NonlinearSolverTag::Newton >::_r_neq_id = 0u
private

ID of the non-equilibrium initial residuum vector.

Definition at line 152 of file NonlinearSolver.h.

◆ _recompute_jacobian

int const NumLib::NonlinearSolver< NonlinearSolverTag::Newton >::_recompute_jacobian = 1
private

Definition at line 138 of file NonlinearSolver.h.

◆ _res_id

std::size_t NumLib::NonlinearSolver< NonlinearSolverTag::Newton >::_res_id = 0u
private

ID of the residual vector.

Definition at line 147 of file NonlinearSolver.h.

◆ _x_new_id

std::size_t NumLib::NonlinearSolver< NonlinearSolverTag::Newton >::_x_new_id
private
Initial value:
=
0u

ID of the vector storing \( x - (-\Delta x) \).

Definition at line 150 of file NonlinearSolver.h.


The documentation for this class was generated from the following files: