Processing math: 0%
OGS
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, std::optional< double > const damping_reduction=std::nullopt)
 
 ~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
 
std::optional< double > const _damping_reduction
 
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,
std::optional< double > const damping_reduction = std::nullopt )
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
Parameters
damping_reductionA parameter that reduces damping
See also
_damping_reduction

Definition at line 94 of file NonlinearSolver.h.

100 : _linear_solver(linear_solver),
101 _maxiter(maxiter),
102 _recompute_jacobian(recompute_jacobian),
103 _damping(damping),
104 _damping_reduction(damping_reduction)
105 {
106 }
int const _maxiter
maximum number of iterations

◆ ~NonlinearSolver()

Definition at line 613 of file NonlinearSolver.cpp.

614{
615 if (_r_neq != nullptr)
616 {
618 }
619}
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 304 of file NonlinearSolver.cpp.

308{
310 {
311 return;
312 }
313
314 INFO("Calculate non-equilibrium initial residuum.");
315
316 _equation_system->assemble(x, x_prev, process_id);
318 _equation_system->getResidual(*x[process_id], *x_prev[process_id], *_r_neq);
319
320 // Set the values of the selected entries of _r_neq, which are associated
321 // with the equations that do not need initial residual compensation, to
322 // zero.
323 const auto selected_global_indices =
325 std::vector<double> zero_entries(selected_global_indices.size(), 0.0);
326
327 _r_neq->set(selected_global_indices, zero_entries);
328
330}
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:35
void set(IndexType rowId, double v)
set entry
Definition EigenVector.h:74
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 130 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 112 of file NonlinearSolver.h.

113 {
114 _equation_system = &eq;
115 _convergence_criterion = &conv_crit;
116 }

◆ 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 332 of file NonlinearSolver.cpp.

338{
339 namespace LinAlg = MathLib::LinAlg;
340 auto& sys = *_equation_system;
341
343 auto& minus_delta_x =
346
347 bool error_norms_met = false;
348
349 // TODO be more efficient
350 // init minus_delta_x to the right size
351 LinAlg::copy(*x[process_id], minus_delta_x);
352
354
355 int iteration = 1;
356#if !defined(USE_PETSC) && !defined(USE_LIS)
357 int next_iteration_inv_jacobian_recompute = 1;
358#endif
359 for (; iteration <= _maxiter; ++iteration, _convergence_criterion->reset())
360 {
361 BaseLib::RunTime timer_dirichlet;
362 double time_dirichlet = 0.0;
363
364 BaseLib::RunTime time_iteration;
365 INFO("Iteration #{:d} started.", iteration);
366 time_iteration.start();
367
368 timer_dirichlet.start();
369 sys.computeKnownSolutions(*x[process_id], process_id);
370 time_dirichlet += timer_dirichlet.elapsed();
371
372 sys.preIteration(iteration, *x[process_id]);
373
374 BaseLib::RunTime time_assembly;
375 time_assembly.start();
376 bool mpi_rank_assembly_ok = true;
377 try
378 {
379 sys.assemble(x, x_prev, process_id);
380 }
381 catch (AssemblyException const& e)
382 {
383 ERR("Abort nonlinear iteration. Repeating timestep. Reason: {:s}",
384 e.what());
385 error_norms_met = false;
386 iteration = _maxiter;
387 mpi_rank_assembly_ok = false;
388 }
389 if (BaseLib::MPI::anyOf(!mpi_rank_assembly_ok))
390 {
391 break;
392 }
393 sys.getResidual(*x[process_id], *x_prev[process_id], res);
394 sys.getJacobian(J);
395 INFO("[time] Assembly took {:g} s.", time_assembly.elapsed());
396
397 // Subtract non-equilibrium initial residuum if set
398 if (_r_neq != nullptr)
399 LinAlg::axpy(res, -1, *_r_neq);
400
401 minus_delta_x.setZero();
402
403 timer_dirichlet.start();
404 sys.applyKnownSolutionsNewton(J, res, *x[process_id], minus_delta_x);
405 time_dirichlet += timer_dirichlet.elapsed();
406 INFO("[time] Applying Dirichlet BCs took {:g} s.", time_dirichlet);
407
408 if (!sys.isLinear() && _convergence_criterion->hasResidualCheck())
409 {
411 }
412
413 BaseLib::RunTime time_linear_solver;
414 time_linear_solver.start();
415#if !defined(USE_PETSC) && !defined(USE_LIS)
416 auto linear_solver_behaviour = MathLib::LinearSolverBehaviour::REUSE;
417 if (iteration == next_iteration_inv_jacobian_recompute)
418 {
419 linear_solver_behaviour =
421 next_iteration_inv_jacobian_recompute =
422 next_iteration_inv_jacobian_recompute + _recompute_jacobian;
423 }
424 if (!_linear_solver.compute(J, linear_solver_behaviour))
425 {
426 ERR("Newton: The linear solver failed in the compute() step.");
427 }
428 bool iteration_succeeded = _linear_solver.solve(res, minus_delta_x);
429#else
430 bool iteration_succeeded = _linear_solver.solve(J, res, minus_delta_x);
431#endif
432 INFO("[time] Linear solver took {:g} s.", time_linear_solver.elapsed());
433
434 if (!iteration_succeeded)
435 {
436 ERR("Newton: The linear solver failed.");
437 }
438 else
439 {
440 // TODO could be solved in a better way
441 // cf.
442 // https://petsc.org/release/manualpages/Vec/VecWAXPY
443
444 // Copy pointers, replace the one for the given process id.
445 std::vector<GlobalVector*> x_new{x};
446 x_new[process_id] =
448 *x[process_id], _x_new_id);
449 double damping = _damping;
451 {
453 minus_delta_x, *x[process_id], _damping);
454 }
456 {
457 damping =
458 damping +
459 (1 - damping) *
460 std::clamp(iteration / *_damping_reduction, 0.0, 1.0);
461 }
462 LinAlg::axpy(*x_new[process_id], -damping, minus_delta_x);
463
464 if (postIterationCallback)
465 {
466 postIterationCallback(iteration, error_norms_met, x_new);
467 }
468
469 switch (sys.postIteration(*x_new[process_id]))
470 {
472 break;
474 ERR("Newton: The postIteration() hook reported a "
475 "non-recoverable error.");
476 iteration_succeeded = false;
477 break;
479 INFO(
480 "Newton: The postIteration() hook decided that this "
481 "iteration has to be repeated.");
482 // TODO introduce some onDestroy hook.
484 *x_new[process_id]);
485 continue; // That throws the iteration result away.
486 }
487
488 LinAlg::copy(*x_new[process_id],
489 *x[process_id]); // copy new solution to x
491 *x_new[process_id]);
492 }
493
494 if (!iteration_succeeded)
495 {
496 // Don't compute further error norms, but break here.
497 error_norms_met = false;
498 break;
499 }
500
501 if (sys.isLinear())
502 {
503 error_norms_met = true;
504 }
505 else
506 {
508 {
509 // Note: x contains the new solution!
510 _convergence_criterion->checkDeltaX(minus_delta_x,
511 *x[process_id]);
512 }
513
514 error_norms_met = _convergence_criterion->isSatisfied();
515 }
516
517 INFO("[time] Iteration #{:d} took {:g} s.", iteration,
518 time_iteration.elapsed());
519
520 if (error_norms_met)
521 {
522 break;
523 }
524
525 // Avoid increment of the 'iteration' if the error norms are not met,
526 // but maximum number of iterations is reached.
527 if (iteration >= _maxiter)
528 {
529 break;
530 }
531 }
532
533 if (iteration > _maxiter)
534 {
535 ERR("Newton: Could not solve the given nonlinear system within {:d} "
536 "iterations",
537 _maxiter);
538 }
539
543
544 return {error_norms_met, iteration};
545}
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{OGS_COMM_WORLD})
Definition MPI.h:191
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 170 of file NonlinearSolver.h.

◆ _convergence_criterion

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

Definition at line 140 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 149 of file NonlinearSolver.h.

◆ _damping_reduction

std::optional<double> const NumLib::NonlinearSolver< NonlinearSolverTag::Newton >::_damping_reduction
private

A parameter that reduces the damping by iteration / _damping_reduction If the expression is smaller than zero, then damping is the same for all iterations. If the expression is bigger than one it is clamped by one.

Definition at line 154 of file NonlinearSolver.h.

◆ _equation_system

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

Definition at line 137 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 158 of file NonlinearSolver.h.

◆ _linear_solver

Definition at line 136 of file NonlinearSolver.h.

◆ _maxiter

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

maximum number of iterations

Definition at line 141 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 159 of file NonlinearSolver.h.

◆ _r_neq

non-equilibrium initial residuum.

Definition at line 156 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 162 of file NonlinearSolver.h.

◆ _recompute_jacobian

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

Definition at line 143 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 157 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 160 of file NonlinearSolver.h.


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