version 0.4.1
newtonraphsonwithscalarsubsidiaryfunction.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
11#include <iosfwd>
12#include <utility>
13
19
20namespace Ikarus {
26{
27 double tol{1e-8};
28 int maxIter{20};
29};
30
41template <typename NLO, typename LS = utils::SolverDefault, typename UF = utils::UpdateDefault>
42class NewtonRaphsonWithSubsidiaryFunction : public IObservable<NonLinearSolverMessages>
43{
44public:
46 static constexpr bool isLinearSolver =
48
50 using ValueType = typename NLO::template ParameterValue<0>;
53 using NonLinearOperator = NLO;
54
62 explicit NewtonRaphsonWithSubsidiaryFunction(const NLO& nonLinearOperator, LS&& linearSolver = {},
63 UpdateFunctionType updateFunction = {})
64 : nonLinearOperator_{nonLinearOperator},
65 linearSolver_{std::move(linearSolver)},
66 updateFunction_{updateFunction} {}
67
73 void setup(const NewtonRaphsonWithSubsidiaryFunctionSettings& settings) { settings_ = settings; }
74
75#ifndef DOXYGEN
76 struct NoPredictor
77 {
78 };
79#endif
80
91 template <typename SolutionType = NoPredictor, typename SubsidiaryType>
92 requires std::is_same_v<SolutionType, NoPredictor> ||
93 std::is_convertible_v<SolutionType, std::remove_cvref_t<typename NLO::ValueType>>
94 [[nodiscard(
95 "The solve method returns information of the solution process. You should store this information and check if "
96 "it was successful")]] NonLinearSolverInformation
97 solve(SubsidiaryType&& subsidiaryFunction, SubsidiaryArgs& subsidiaryArgs,
98 const SolutionType& dxPredictor = NoPredictor{}) {
100
102 Ikarus::NonLinearSolverInformation solverInformation;
103 solverInformation.success = true;
104 auto& x = nonLinearOperator().firstParameter(); // x = D (Displacements)
105 if constexpr (not std::is_same_v<SolutionType, NoPredictor>)
106 updateFunction_(x, dxPredictor);
107 auto& lambda = nonLinearOperator().lastParameter();
108
112
113 auto lambdaDummy = lambda;
114 auto DDummy = x;
115 x.setZero();
116 lambda = 1.0;
117 nonLinearOperator().template update<0>();
118 const auto Fext0 = (-nonLinearOperator().value()).eval(); // dRdlambda(lambda)
119 lambda = lambdaDummy;
120 x = DDummy;
121
122 Eigen::MatrixX2<double> residual2d, sol2d;
123 nonLinearOperator().updateAll();
124 const auto& rx = nonLinearOperator().value();
125 const auto& Ax = nonLinearOperator().derivative();
126
127 Eigen::VectorXd deltaD;
128 deltaD.resizeLike(rx);
129 deltaD.setZero();
130
131 subsidiaryArgs.dfdDD.resizeLike(Fext0);
132
133 subsidiaryFunction(subsidiaryArgs);
134 auto rNorm = sqrt(rx.dot(rx));
135 decltype(rNorm) dNorm;
136 int iter{0};
137 if constexpr (isLinearSolver)
138 linearSolver_.analyzePattern(Ax);
139
141 while (rNorm > settings_.tol && iter < settings_.maxIter) {
143
145 residual2d.resize(rx.rows(), 2);
146 residual2d << -rx, Fext0;
147 sol2d.resize(rx.rows(), 2);
148
149 if constexpr (isLinearSolver) {
150 linearSolver_.factorize(Ax);
151 linearSolver_.solve(sol2d, residual2d);
152 } else {
153 sol2d = linearSolver(residual2d, Ax);
154 }
155
156 subsidiaryFunction(subsidiaryArgs);
157
158 const double deltalambda = (-subsidiaryArgs.f - subsidiaryArgs.dfdDD.dot(sol2d.col(0))) /
159 (subsidiaryArgs.dfdDD.dot(sol2d.col(1)) + subsidiaryArgs.dfdDlambda);
160 deltaD = sol2d.col(0) + deltalambda * sol2d.col(1);
161
162 updateFunction_(x, deltaD);
163 updateFunction_(subsidiaryArgs.DD, deltaD);
164
165 lambda += deltalambda;
166 subsidiaryArgs.Dlambda += deltalambda;
167
168 dNorm = sqrt(deltaD.dot(deltaD) + deltalambda * deltalambda);
169 nonLinearOperator().updateAll();
170 rNorm = sqrt(rx.dot(rx) + subsidiaryArgs.f * subsidiaryArgs.f);
171
172 this->notify(NonLinearSolverMessages::SOLUTION_CHANGED, static_cast<double>(lambda));
173 this->notify(NonLinearSolverMessages::CORRECTIONNORM_UPDATED, static_cast<double>(dNorm));
174 this->notify(NonLinearSolverMessages::RESIDUALNORM_UPDATED, static_cast<double>(rNorm));
176
177 ++iter;
178 }
179
180 if (iter == settings_.maxIter)
181 solverInformation.success = false;
182 solverInformation.iterations = iter;
183 solverInformation.residualNorm = rNorm;
184 solverInformation.correctionNorm = dNorm;
185 if (solverInformation.success)
187
188 return solverInformation;
189 }
190
195 auto& nonLinearOperator() { return nonLinearOperator_; }
196
197private:
198 NLO nonLinearOperator_;
199 LinearSolver linearSolver_;
200 UpdateFunctionType updateFunction_;
202};
203
214template <typename NLO, typename LS = utils::SolverDefault, typename UF = utils::UpdateDefault>
215auto makeNewtonRaphsonWithSubsidiaryFunction(const NLO& nonLinearOperator, LS&& linearSolver = {},
216 UF&& updateFunction = {}) {
217 return std::make_shared<NewtonRaphsonWithSubsidiaryFunction<NLO, LS, UF>>(
218 nonLinearOperator, std::forward<LS>(linearSolver), std::move(updateFunction));
219}
220} // namespace Ikarus
Several concepts.
Implementation of the Newton-Raphson method for solving nonlinear equations.
Defines structures and methods related to subsidiary functions for control routines.
Enums for observer messages.
Implementation of the observer design pattern.
Definition: simpleassemblers.hh:22
auto makeNewtonRaphsonWithSubsidiaryFunction(const NLO &nonLinearOperator, LS &&linearSolver={}, UF &&updateFunction={})
Function to create a NewtonRaphson with subsidiary function solver instance.
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:215
Structure containing arguments for subsidiary functions.
Definition: pathfollowingfunctions.hh:39
double Dlambda
The increment in the load factor.
Definition: pathfollowingfunctions.hh:42
double dfdDlambda
The derivative of the subsidiary function with respect to Dlambda.
Definition: pathfollowingfunctions.hh:45
double f
The value of the subsidiary function.
Definition: pathfollowingfunctions.hh:43
Eigen::VectorX< double > dfdDD
The derivative of the subsidiary function with respect to DD.
Definition: pathfollowingfunctions.hh:44
Eigen::VectorX< double > DD
The vector representing the solution increment.
Definition: pathfollowingfunctions.hh:41
void analyzePattern(const MatrixType &A)
Analyze the pattern of the matrix.
Definition: linearsolver.hh:202
void factorize(const MatrixType &A)
Factorize the matrix.
Definition: linearsolver.hh:213
void solve(Eigen::VectorX< ScalarType > &x, const Eigen::VectorX< ScalarType > &b)
Solve the linear system for a vector.
Definition: linearsolver.hh:222
Settings for the Newton-Raphson solver with subsidiary function.
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:26
double tol
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:27
int maxIter
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:28
Newton-Raphson solver with subsidiary function.
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:43
UF UpdateFunctionType
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:52
typename NLO::template ParameterValue< 0 > ValueType
Type representing the update function.
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:51
static constexpr bool isLinearSolver
< Compile-time boolean indicating if the linear solver satisfies the non-linear solver concept
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:46
void setup(const NewtonRaphsonWithSubsidiaryFunctionSettings &settings)
Setup the Newton-Raphson solver with subsidiary function.
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:73
NewtonRaphsonWithSubsidiaryFunction(const NLO &nonLinearOperator, LS &&linearSolver={}, UpdateFunctionType updateFunction={})
Constructor for NewtonRaphsonWithSubsidiaryFunction.
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:62
auto & nonLinearOperator()
Access the nonlinear operator.
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:195
NonLinearSolverInformation solve(SubsidiaryType &&subsidiaryFunction, SubsidiaryArgs &subsidiaryArgs, const SolutionType &dxPredictor=NoPredictor{})
Solve the nonlinear system using the Newton-Raphson method with subsidiary function.
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:97
NLO NonLinearOperator
Type of the non-linear operator.
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:53
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
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:210