version 0.4.4
newtonraphson.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2021-2025 The Ikarus Developers ikarus@ibb.uni-stuttgart.de
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
9#pragma once
10
20
21namespace Ikarus {
22
23template <typename F, typename LS = utils::SolverDefault, typename UF = utils::UpdateDefault>
24class NewtonRaphson;
25
27{
28 double tol{1e-8};
29 int maxIter{20};
30 int minIter{0};
31};
32
37template <typename LS = utils::SolverDefault, typename UF = utils::UpdateDefault>
39{
40 using LinearSolver = LS;
41 using UpdateFunction = UF;
45
46 template <typename UF2>
49 .parameters = parameters, .linearSolver = linearSolver, .updateFunction = std::forward<UF2>(updateFunction)};
50 return settings;
51 }
52
53 template <typename F>
55};
56
57// THE CTAD is broken for designated initializers in clang 16, when we drop support this can be simplified
58#ifndef DOXYGEN
61
62template <typename LS>
64
65template <typename LS, typename UF>
67
68template <typename UF>
70#endif
71
80template <typename F, typename NRConfig>
81requires traits::isSpecialization<NewtonRaphsonConfig, std::remove_cvref_t<NRConfig>>::value
82auto createNonlinearSolver(NRConfig&& config, F&& f) {
84 using UF = std::remove_cvref_t<NRConfig>::UpdateFunction;
85 auto solverFactory = []<class F2, class LS2, class UF2>(F2&& f2, LS2&& ls, UF2&& uf) {
86 return std::make_shared<NewtonRaphson<std::remove_cvref_t<F2>, std::remove_cvref_t<LS2>, std::remove_cvref_t<UF2>>>(
87 f2, std::forward<LS2>(ls), std::forward<UF2>(uf));
88 };
89
90 if constexpr (std::remove_cvref_t<F>::nDerivatives == 2) {
91 auto solver = solverFactory(derivative(f), std::forward<NRConfig>(config).linearSolver,
92 std::forward<NRConfig>(config).updateFunction);
93 solver->setup(config.parameters);
94 return solver;
95 } else {
96 static_assert(std::remove_cvref_t<F>::nDerivatives >= 1,
97 "The number of derivatives in the differentiable function have to be more than 0");
98 auto solver =
99 solverFactory(f, std::forward<NRConfig>(config).linearSolver, std::forward<NRConfig>(config).updateFunction);
100 ;
101
102 solver->setup(std::forward<NRConfig>(config).parameters);
103 return solver;
104 }
105}
106
116template <typename F, typename LS, typename UF>
118{
119public:
121 using SignatureTraits = typename F::Traits;
122 using CorrectionType = typename SignatureTraits::template Range<0>;
123 using JacobianType = typename SignatureTraits::template Range<1>;
126
127 using Domain = typename SignatureTraits::Domain;
128
129 using UpdateFunction = UF;
131
138 template <typename LS2 = LS, typename UF2 = UF>
139 explicit NewtonRaphson(const DifferentiableFunction& residual, LS2&& linearSolver = {}, UF2&& updateFunction = {})
140 : residualFunction_{residual},
141 jacobianFunction_{derivative(residualFunction_)},
142 linearSolver_{std::forward<LS2>(linearSolver)},
143 updateFunction_{std::forward<UF2>(updateFunction)} {}
144
149 void setup(const Settings& settings) {
150 if (settings.minIter > settings.maxIter)
151 DUNE_THROW(Dune::InvalidStateException,
152 "Minimum number of iterations cannot be greater than maximum number of iterations");
153 settings_ = settings;
154 }
155
161 [[nodiscard(
162 "The solve method returns information of the solution process. You should store this information and check if "
163 "it was successful")]] NonLinearSolverInformation
165 using enum NonLinearSolverMessages;
166
167 NonLinearSolverInformation solverInformation{};
168 auto state = typename NewtonRaphson::State(x, correction_, solverInformation);
169 this->notify(INIT, state);
170 solverInformation.success = true;
171
172 decltype(auto) rx = residualFunction_(x);
173 decltype(auto) Ax = jacobianFunction_(x);
174 auto rNorm = norm(rx);
175 solverInformation.residualNorm = static_cast<double>(rNorm);
176
177 decltype(rNorm) dNorm;
178 int iter{0};
179 if constexpr (isLinearSolver)
180 linearSolver_.analyzePattern(Ax);
181
182 while ((rNorm > settings_.tol && iter < settings_.maxIter) or iter < settings_.minIter) {
183 this->notify(ITERATION_STARTED, state);
184 if constexpr (isLinearSolver) {
185 linearSolver_.factorize(Ax);
186 linearSolver_.solve(correction_, -rx);
187 dNorm = correction_.norm();
188 } else {
189 correction_ = -linearSolver_(rx, Ax);
190 dNorm = norm(correction_);
191 }
192 solverInformation.correctionNorm = static_cast<double>(dNorm);
193
194 this->notify(CORRECTION_UPDATED, state);
195 updateFunction_(x, correction_);
196 this->notify(CORRECTIONNORM_UPDATED, state);
197 this->notify(SOLUTION_CHANGED, state);
198
199 rx = residualFunction_(x);
200 Ax = jacobianFunction_(x);
201 rNorm = norm(rx);
202 solverInformation.residualNorm = static_cast<double>(rNorm);
203 this->notify(RESIDUALNORM_UPDATED, state);
204
205 ++iter;
206 solverInformation.iterations = iter;
207 this->notify(ITERATION_ENDED, state);
208 }
209 if (iter == settings_.maxIter)
210 solverInformation.success = false;
211 solverInformation.iterations = iter;
212 if (solverInformation.success)
213 this->notify(FINISHED_SUCESSFULLY, state);
214 return solverInformation;
215 }
216
221 auto& residual() { return residualFunction_; }
222
223private:
224 DifferentiableFunction residualFunction_;
225 typename DifferentiableFunction::Derivative jacobianFunction_;
226 std::remove_cvref_t<CorrectionType> correction_;
227 LS linearSolver_;
228 UpdateFunction updateFunction_;
229 Settings settings_;
230};
231
242template <typename F, typename LS = utils::SolverDefault, typename UF = utils::UpdateDefault>
243auto makeNewtonRaphson(const F& f, LS&& linearSolver = {}, UF&& updateFunction = {}) {
244 return std::make_shared<NewtonRaphson<F, LS, UF>>(f, std::forward<LS>(linearSolver), std::move(updateFunction));
245}
246
247template <typename F, typename LS = utils::SolverDefault, typename UF = utils::UpdateDefault>
248NewtonRaphson(const F& f, LS&& linearSolver = {},
249 UF&& updateFunction = {}) -> NewtonRaphson<F, std::remove_cvref_t<LS>, std::remove_cvref_t<UF>>;
250
251} // namespace Ikarus
Collection of fallback default functions.
Helper for the autodiff library.
State for all nonlinear solvers.
Implementation of the solver information returned by the nonlinear solvers.
Base for all nonlinear solvers.
Type-erased linear solver with templated scalar type.
Implementation of the observer design pattern with broadcasters.
Enums for observer messages.
auto norm(const Eigen::MatrixBase< Derived > &v)
Adding free norm function to Eigen types.
Definition: linearalgebrahelper.hh:259
Definition: assemblermanipulatorbuildingblocks.hh:22
auto makeNewtonRaphson(const F &f, LS &&linearSolver={}, UF &&updateFunction={})
Function to create a NewtonRaphson solver instance.
Definition: newtonraphson.hh:243
LinearSolverTemplate< double > LinearSolver
Definition: linearsolver.hh:235
::value auto createNonlinearSolver(NRConfig &&config, F &&f)
Function to create a NewtonRaphson solver instance.
Definition: newtonraphson.hh:82
NonLinearSolverMessages
Enum class defining non-linear solver-related messages.
Definition: broadcastermessages.hh:22
NewtonRaphson(const F &f, LS &&linearSolver={}, UF &&updateFunction={}) -> NewtonRaphson< F, std::remove_cvref_t< LS >, std::remove_cvref_t< UF > >
Implementation of the Newton-Raphson method for solving nonlinear equations.
Definition: newtonraphson.hh:118
static constexpr bool isLinearSolver
Definition: newtonraphson.hh:125
NRSettings Settings
Definition: newtonraphson.hh:120
typename SignatureTraits::Domain Domain
Type representing the parameter vector of the function.
Definition: newtonraphson.hh:127
F DifferentiableFunction
Type of the non-linear operator.
Definition: newtonraphson.hh:130
typename SignatureTraits::template Range< 0 > CorrectionType
Type of the correction of x += deltaX.
Definition: newtonraphson.hh:122
typename F::Traits SignatureTraits
Definition: newtonraphson.hh:121
void setup(const Settings &settings)
Set up the solver with the given settings.
Definition: newtonraphson.hh:149
NonLinearSolverInformation solve(Domain &x)
Solve the nonlinear system.
Definition: newtonraphson.hh:164
typename SignatureTraits::template Range< 1 > JacobianType
Compile-time boolean indicating if the linear solver satisfies the non-linear solver concept.
Definition: newtonraphson.hh:124
NewtonRaphson(const DifferentiableFunction &residual, LS2 &&linearSolver={}, UF2 &&updateFunction={})
Constructor for NewtonRaphson.
Definition: newtonraphson.hh:139
auto & residual()
Access the function.
Definition: newtonraphson.hh:221
UF UpdateFunction
Type representing the update function.
Definition: newtonraphson.hh:129
Definition: newtonraphson.hh:27
int maxIter
Definition: newtonraphson.hh:29
int minIter
Definition: newtonraphson.hh:30
double tol
Definition: newtonraphson.hh:28
Config for the Newton-Raphson solver.
Definition: newtonraphson.hh:39
NRSettings parameters
Definition: newtonraphson.hh:42
UF updateFunction
Definition: newtonraphson.hh:44
LS LinearSolver
Definition: newtonraphson.hh:40
LS linearSolver
Definition: newtonraphson.hh:43
UF UpdateFunction
Definition: newtonraphson.hh:41
auto rebindUpdateFunction(UF2 &&updateFunction) const
Definition: newtonraphson.hh:47
Base for all nonlinear solvers. Defines the message interface that can be broadcasted to listeners.
Definition: nonlinearsolverbase.hh:24
NonlinearSolverStateType< F > State
Definition: nonlinearsolverbase.hh:25
Information about the result of a non-linear solver.
Definition: solverinfos.hh:21
void notify(NonLinearSolverMessages message, const State &data)
This calls all the registered functions.
Definition: broadcaster.hh:61
Default functor for solving operations.
Definition: defaultfunctions.hh:26
Concept to check if a linear solver implements all the needed functions for given vector and matrix t...
Definition: utils/concepts.hh:226
Several concepts.