OGS
NewtonRaphson.h
Go to the documentation of this file.
1
11#pragma once
12
13#include <Eigen/Core>
14#include <optional>
15
16#include "BaseLib/Logging.h"
17
18namespace NumLib
19{
26
31template <typename LinearSolver, typename JacobianMatrixUpdate,
32 typename ResidualUpdate, typename SolutionUpdate>
33class NewtonRaphson final
34{
35private:
36 template <typename T>
38 {
39 static_assert(
40 !std::is_same_v<T, T>,
41 "For the type T in the expression !std::is_same_v<T, T>: Could not "
42 "find overload for FirstArgument<T>. Expected T to be a callable "
43 "with one argument. Could be a missing overload of FirstArgument "
44 "for the type T.");
45 };
46
47 // Specialization for lambdas and functors with const operator()
48 template <typename C, typename R, typename Arg, typename... Args>
49 struct FirstArgument<R (C::*)(Arg, Args...) const>
50 {
51 using type = std::remove_reference_t<Arg>;
52 };
53
54 template <typename F>
56 decltype(&std::remove_reference_t<F>::operator())>::type;
57
60
61public:
62 NewtonRaphson(LinearSolver& linear_solver,
63 JacobianMatrixUpdate jacobian_update,
64 ResidualUpdate residual_update,
65 SolutionUpdate solution_update,
66 NewtonRaphsonSolverParameters const& solver_parameters)
67 : _linear_solver(linear_solver),
68 _jacobian_update(jacobian_update),
69 _residual_update(residual_update),
70 _solution_update(solution_update),
71 _maximum_iterations(solver_parameters.maximum_iterations),
72 _residuum_tolerance_squared(solver_parameters.residuum_tolerance *
73 solver_parameters.residuum_tolerance),
74 _increment_tolerance_squared(solver_parameters.increment_tolerance *
75 solver_parameters.increment_tolerance)
76 {
77 }
78
81 std::optional<int> solve(JacobianMatrix& jacobian) const
82 {
83 int iteration = 0;
84 ResidualVector increment;
85 ResidualVector residual;
86 do
87 {
88 // The jacobian and the residual are updated simultaneously to keep
89 // consistency. The jacobian is used after the non-linear solver
90 // onward.
91 _jacobian_update(jacobian);
92 _residual_update(residual);
93
94 if (residual.squaredNorm() < _residuum_tolerance_squared)
95 {
96 break; // convergence criteria fulfilled.
97 }
98
99 increment.noalias() =
100 _linear_solver.compute(jacobian).solve(-residual);
101 // DBUG("Local linear solver accuracy |J dx - r| = {:g}",
102 // (jacobian * increment + residual).norm());
103
104 _solution_update(increment);
105
106 if (increment.squaredNorm() < _increment_tolerance_squared)
107 {
108 break; // increment to small.
109 }
110
111 // DBUG("Local Newton: Iteration #{:d} |dx| = {:g}, |r| = {:g}",
112 // iteration, increment.norm(), residual.norm());
113 // fmt::print("Local Newton: Increment {}\n",
114 // fmt::join(increment.data(),
115 // increment.data() + increment.size(), ", "));
116 // fmt::print("Local Newton: Residuum {}\n",
117 // fmt::join(residual.data(),
118 // residual.data() + residual.size(), ", "));
119 } while (iteration++ < _maximum_iterations);
120
121 if (iteration > _maximum_iterations)
122 {
123 ERR("The local Newton method did not converge within the given "
124 "number of iterations. Iteration: {:d}, increment {:g}, "
125 "residual: "
126 "{:g}",
127 iteration - 1, increment.norm(), residual.norm());
128 return std::nullopt;
129 }
130
131 return iteration;
132 };
133
134private:
135 LinearSolver& _linear_solver;
136 JacobianMatrixUpdate _jacobian_update;
137 ResidualUpdate _residual_update;
138 SolutionUpdate _solution_update;
140 const double
142 const double
144};
145} // namespace NumLib
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:45
ResidualUpdate _residual_update
JacobianMatrixUpdate _jacobian_update
const int _maximum_iterations
Maximum number of iterations.
FirstArgumentType< JacobianMatrixUpdate > JacobianMatrix
NewtonRaphson(LinearSolver &linear_solver, JacobianMatrixUpdate jacobian_update, ResidualUpdate residual_update, SolutionUpdate solution_update, NewtonRaphsonSolverParameters const &solver_parameters)
LinearSolver & _linear_solver
const double _residuum_tolerance_squared
Error tolerance for the residuum.
SolutionUpdate _solution_update
FirstArgumentType< ResidualUpdate > ResidualVector
typename FirstArgument< decltype(&std::remove_reference_t< F >::operator())>::type FirstArgumentType
std::optional< int > solve(JacobianMatrix &jacobian) const
const double _increment_tolerance_squared
Error tolerance for the increment.