version 0.4.1
newtonraphson.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2021-2024 The Ikarus Developers mueller@ibb.uni-stuttgart.de
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
9#pragma once
10
18
19namespace Ikarus {
20
21template <typename NLO, typename LS = utils::SolverDefault, typename UF = utils::UpdateDefault>
22class NewtonRaphson;
23
25{
26 double tol{1e-8};
27 int maxIter{20};
28 int minIter{0};
29};
30
35template <typename LS = utils::SolverDefault, typename UF = utils::UpdateDefault>
37{
38 using LinearSolver = LS;
39 using UpdateFunction = UF;
43
44 template <typename UF2>
47 .parameters = parameters, .linearSolver = linearSolver, .updateFunction = std::forward<UF2>(updateFunction)};
48 return settings;
49 }
50
51 template <typename NLO>
53};
54
63template <typename NLO, typename NRConfig>
64requires traits::isSpecialization<NewtonRaphsonConfig, std::remove_cvref_t<NRConfig>>::value
65auto createNonlinearSolver(NRConfig&& config, NLO&& nonLinearOperator) {
67 using UF = std::remove_cvref_t<NRConfig>::UpdateFunction;
68 auto solverFactory = []<class NLO2, class LS2, class UF2>(NLO2&& nlo2, LS2&& ls, UF2&& uf) {
69 return std::make_shared<
70 NewtonRaphson<std::remove_cvref_t<NLO2>, std::remove_cvref_t<LS2>, std::remove_cvref_t<UF2>>>(
71 nlo2, std::forward<LS2>(ls), std::forward<UF2>(uf));
72 };
73
74 if constexpr (std::remove_cvref_t<NLO>::numberOfFunctions == 3) {
75 auto solver =
76 solverFactory(nonLinearOperator.template subOperator<1, 2>(), std::forward<NRConfig>(config).linearSolver,
77 std::forward<NRConfig>(config).updateFunction);
78 solver->setup(config.parameters);
79 return solver;
80 } else {
81 static_assert(std::remove_cvref_t<NLO>::numberOfFunctions > 1,
82 "The number of derivatives in the nonlinear operator have to be more than 1");
83 auto solver = solverFactory(nonLinearOperator, std::forward<NRConfig>(config).linearSolver,
84 std::forward<NRConfig>(config).updateFunction);
85 ;
86
87 solver->setup(std::forward<NRConfig>(config).parameters);
88 return solver;
89 }
90}
91
101template <typename NLO, typename LS, typename UF>
102class NewtonRaphson : public IObservable<NonLinearSolverMessages>
103{
104public:
107 static constexpr bool isLinearSolver =
109
111 using ValueType = typename NLO::template ParameterValue<0>;
112
113 using UpdateFunction = UF;
114 using NonLinearOperator = NLO;
115
122 template <typename LS2 = LS, typename UF2 = UF>
123 explicit NewtonRaphson(const NonLinearOperator& nonLinearOperator, LS2&& linearSolver = {}, UF2&& updateFunction = {})
124 : nonLinearOperator_{nonLinearOperator},
125 linearSolver_{std::forward<LS2>(linearSolver)},
126 updateFunction_{std::forward<UF2>(updateFunction)} {
127 if constexpr (std::is_same_v<typename NonLinearOperator::ValueType, Eigen::VectorXd>)
128 correction_.setZero(this->nonLinearOperator().value().size());
129 }
130
135 void setup(const Settings& settings) {
136 if (settings.minIter > settings.maxIter)
137 DUNE_THROW(Dune::InvalidStateException,
138 "Minimum number of iterations cannot be greater than maximum number of iterations");
139 settings_ = settings;
140 }
141
142#ifndef DOXYGEN
143 struct NoPredictor
144 {
145 };
146#endif
152 template <typename SolutionType = NoPredictor>
153 requires std::is_same_v<SolutionType, NoPredictor> ||
154 std::is_convertible_v<SolutionType, std::remove_cvref_t<typename NonLinearOperator::ValueType>>
155 [[nodiscard(
156 "The solve method returns information of the solution process. You should store this information and check if "
157 "it was successful")]] Ikarus::NonLinearSolverInformation
158 solve(const SolutionType& dxPredictor = NoPredictor{}) {
160 Ikarus::NonLinearSolverInformation solverInformation;
161 solverInformation.success = true;
162 auto& x = nonLinearOperator().firstParameter();
163 if constexpr (not std::is_same_v<SolutionType, NoPredictor>)
164 updateFunction_(x, dxPredictor);
165 nonLinearOperator().updateAll();
166 const auto& rx = nonLinearOperator().value();
167 const auto& Ax = nonLinearOperator().derivative();
168 auto rNorm = norm(rx);
169 decltype(rNorm) dNorm;
170 int iter{0};
171 if constexpr (isLinearSolver)
172 linearSolver_.analyzePattern(Ax);
173 while ((rNorm > settings_.tol && iter < settings_.maxIter) or iter < settings_.minIter) {
175 if constexpr (isLinearSolver) {
176 linearSolver_.factorize(Ax);
177 linearSolver_.solve(correction_, -rx);
178 dNorm = correction_.norm();
179 updateFunction_(x, correction_);
180 } else {
181 correction_ = -linearSolver_(rx, Ax);
182 dNorm = norm(correction_);
183 updateFunction_(x, correction_);
184 }
185 this->notify(NonLinearSolverMessages::CORRECTIONNORM_UPDATED, static_cast<double>(dNorm));
187 nonLinearOperator().updateAll();
188 rNorm = norm(rx);
189 this->notify(NonLinearSolverMessages::RESIDUALNORM_UPDATED, static_cast<double>(rNorm));
191 ++iter;
192 }
193 if (iter == settings_.maxIter)
194 solverInformation.success = false;
195 solverInformation.iterations = iter;
196 solverInformation.residualNorm = static_cast<double>(rNorm);
197 solverInformation.correctionNorm = static_cast<double>(dNorm);
198 if (solverInformation.success)
200 return solverInformation;
201 }
202
207 auto& nonLinearOperator() { return nonLinearOperator_; }
208
209private:
210 NonLinearOperator nonLinearOperator_;
211 typename NonLinearOperator::ValueType correction_;
212 LS linearSolver_;
213 UpdateFunction updateFunction_;
214 Settings settings_;
215};
216
227template <typename NLO, typename LS = utils::SolverDefault, typename UF = utils::UpdateDefault>
228auto makeNewtonRaphson(const NLO& nonLinearOperator, LS&& linearSolver = {}, UF&& updateFunction = {}) {
229 return std::make_shared<NewtonRaphson<NLO, LS, UF>>(nonLinearOperator, std::forward<LS>(linearSolver),
230 std::move(updateFunction));
231}
232
233template <typename NLO, typename LS = utils::SolverDefault, typename UF = utils::UpdateDefault>
234NewtonRaphson(const NLO& nonLinearOperator, LS&& linearSolver = {},
235 UF&& updateFunction = {}) -> NewtonRaphson<NLO, std::remove_cvref_t<LS>, std::remove_cvref_t<UF>>;
236
237} // namespace Ikarus
Helper for the autodiff library.
Several concepts.
Collection of fallback default functions.
Enums for observer messages.
Implementation of the observer design pattern.
Implementation of the Newton-Raphson method for solving nonlinear equations.
Type-erased linear solver with templated scalar type.
auto norm(const Eigen::MatrixBase< Derived > &v)
Adding free norm function to Eigen types.
Definition: linearalgebrahelper.hh:259
Definition: assemblermanipulatorbuildingblocks.hh:22
LinearSolverTemplate< double > LinearSolver
Definition: linearsolver.hh:235
::value auto createNonlinearSolver(NRConfig &&config, NLO &&nonLinearOperator)
Function to create a NewtonRaphson solver instance.
Definition: newtonraphson.hh:65
NewtonRaphson(const NLO &nonLinearOperator, LS &&linearSolver={}, UF &&updateFunction={}) -> NewtonRaphson< NLO, std::remove_cvref_t< LS >, std::remove_cvref_t< UF > >
auto makeNewtonRaphson(const NLO &nonLinearOperator, LS &&linearSolver={}, UF &&updateFunction={})
Function to create a NewtonRaphson solver instance.
Definition: newtonraphson.hh:228
Implementation of the Newton-Raphson method for solving nonlinear equations.
Definition: newtonraphson.hh:103
Ikarus::NonLinearSolverInformation solve(const SolutionType &dxPredictor=NoPredictor{})
Solve the nonlinear system.
Definition: newtonraphson.hh:158
NRSettings Settings
Compile-time boolean indicating if the linear solver satisfies the non-linear solver concept.
Definition: newtonraphson.hh:106
UF UpdateFunction
Type representing the update function.
Definition: newtonraphson.hh:113
NLO NonLinearOperator
Type of the non-linear operator.
Definition: newtonraphson.hh:114
NewtonRaphson(const NonLinearOperator &nonLinearOperator, LS2 &&linearSolver={}, UF2 &&updateFunction={})
Constructor for NewtonRaphson.
Definition: newtonraphson.hh:123
void setup(const Settings &settings)
Set up the solver with the given settings.
Definition: newtonraphson.hh:135
auto & nonLinearOperator()
Access the nonlinear operator.
Definition: newtonraphson.hh:207
static constexpr bool isLinearSolver
Type representing the parameter vector of the nonlinear operator.
Definition: newtonraphson.hh:107
typename NLO::template ParameterValue< 0 > ValueType
Definition: newtonraphson.hh:111
Definition: newtonraphson.hh:25
int maxIter
Definition: newtonraphson.hh:27
int minIter
Definition: newtonraphson.hh:28
double tol
Definition: newtonraphson.hh:26
Config for the Newton-Raphson solver.
Definition: newtonraphson.hh:37
NRSettings parameters
Definition: newtonraphson.hh:40
UF updateFunction
Definition: newtonraphson.hh:42
LS LinearSolver
Definition: newtonraphson.hh:38
LS linearSolver
Definition: newtonraphson.hh:41
UF UpdateFunction
Definition: newtonraphson.hh:39
auto rebindUpdateFunction(UF2 &&updateFunction) const
Definition: newtonraphson.hh:45
Information about the result of a non-linear solver.
Definition: solverinfos.hh:19
double correctionNorm
Definition: solverinfos.hh:28
int iterations
Definition: solverinfos.hh:29
double residualNorm
Definition: solverinfos.hh:27
bool success
Definition: solverinfos.hh:26
Represents a NonLinearOperator class for handling nonlinear operators.
Definition: nonlinearoperator.hh:156
Generic observable interface for the Observer design pattern. See for a description of the design pa...
Definition: observer.hh:129
void notify(NonLinearSolverMessages message)
Notify observers about a specific message type.
Concept to check if a linear solver implements all the needed functions for given vector and matrix t...
Definition: concepts.hh:215