version 0.4
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
21
22namespace Ikarus {
28 double tol{1e-8};
29 int maxIter{20};
30 };
31
42 template <typename NonLinearOperatorImpl, typename LinearSolver = utils::SolverDefault,
43 typename UpdateFunctionTypeImpl = utils::UpdateDefault>
44 class NewtonRaphsonWithSubsidiaryFunction : public IObservable<NonLinearSolverMessages> {
45 public:
47 static constexpr bool isLinearSolver
48 = Ikarus::Concepts::LinearSolverCheck<LinearSolver, typename NonLinearOperatorImpl::DerivativeType,
49 typename NonLinearOperatorImpl::ValueType>;
50
52 using ValueType = typename NonLinearOperatorImpl::template ParameterValue<0>;
54 using UpdateFunctionType = UpdateFunctionTypeImpl;
55 using NonLinearOperator = NonLinearOperatorImpl;
56
64 explicit NewtonRaphsonWithSubsidiaryFunction(const NonLinearOperatorImpl& p_nonLinearOperator,
65 LinearSolver&& p_linearSolver = {},
66 UpdateFunctionType p_updateFunction = {})
67 : nonLinearOperator_{p_nonLinearOperator},
68 linearSolver{std::move(p_linearSolver)},
69 updateFunction{p_updateFunction} {}
70
76 void setup(const NewtonRaphsonWithSubsidiaryFunctionSettings& p_settings) { settings = p_settings; }
77
78#ifndef DOXYGEN
79 struct NoPredictor {};
80#endif
81
92 template <typename SolutionType = NoPredictor, typename SubsidiaryType>
93 requires std::is_same_v<SolutionType, NoPredictor> || std::is_convertible_v<
94 SolutionType, std::remove_cvref_t<typename NonLinearOperatorImpl::ValueType>>
95 [[nodiscard(
96 "The solve method returns information of the solution process. You should store this information and check if "
97 "it was successful")]] NonLinearSolverInformation
98 solve(SubsidiaryType& subsidiaryFunction, SubsidiaryArgs& subsidiaryArgs,
99 const SolutionType& dx_predictor = NoPredictor{}) {
101
103 Ikarus::NonLinearSolverInformation solverInformation;
104 solverInformation.success = true;
105 auto& x = nonLinearOperator().firstParameter(); // x = D (Displacements)
106 if constexpr (not std::is_same_v<SolutionType, NoPredictor>) updateFunction(x, dx_predictor);
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) linearSolver.analyzePattern(Ax);
138
140 while (rNorm > settings.tol && iter < settings.maxIter) {
142
144 residual2d.resize(rx.rows(), 2);
145 residual2d << -rx, Fext0;
146 sol2d.resize(rx.rows(), 2);
147
148 if constexpr (isLinearSolver) {
149 linearSolver.factorize(Ax);
150 linearSolver.solve(sol2d, residual2d);
151 } else {
152 sol2d = linearSolver(residual2d, Ax);
153 }
154
155 subsidiaryFunction(subsidiaryArgs);
156
157 const double deltalambda = (-subsidiaryArgs.f - subsidiaryArgs.dfdDD.dot(sol2d.col(0)))
158 / (subsidiaryArgs.dfdDD.dot(sol2d.col(1)) + subsidiaryArgs.dfdDlambda);
159 deltaD = sol2d.col(0) + deltalambda * sol2d.col(1);
160
161 updateFunction(x, deltaD);
162 updateFunction(subsidiaryArgs.DD, deltaD);
163
164 lambda += deltalambda;
165 subsidiaryArgs.Dlambda += deltalambda;
166
167 dNorm = sqrt(deltaD.dot(deltaD) + deltalambda * deltalambda);
168 nonLinearOperator().updateAll();
169 rNorm = sqrt(rx.dot(rx) + subsidiaryArgs.f * subsidiaryArgs.f);
170
171 this->notify(NonLinearSolverMessages::SOLUTION_CHANGED, static_cast<double>(lambda));
172 this->notify(NonLinearSolverMessages::CORRECTIONNORM_UPDATED, static_cast<double>(dNorm));
173 this->notify(NonLinearSolverMessages::RESIDUALNORM_UPDATED, static_cast<double>(rNorm));
175
176 ++iter;
177 }
178
179 if (iter == settings.maxIter) solverInformation.success = false;
180 solverInformation.iterations = iter;
181 solverInformation.residualNorm = rNorm;
182 solverInformation.correctionNorm = dNorm;
183 if (solverInformation.success) this->notify(NonLinearSolverMessages::FINISHED_SUCESSFULLY, iter);
184
185 return solverInformation;
186 }
187
192 auto& nonLinearOperator() { return nonLinearOperator_; }
193
194 private:
195 NonLinearOperatorImpl nonLinearOperator_;
196 LinearSolver linearSolver;
197 UpdateFunctionType updateFunction;
199 };
200
211 template <typename NonLinearOperatorImpl, typename LinearSolver = utils::SolverDefault,
212 typename UpdateFunctionType = utils::UpdateDefault>
213 auto makeNewtonRaphsonWithSubsidiaryFunction(const NonLinearOperatorImpl& p_nonLinearOperator,
214 LinearSolver&& p_linearSolver = {},
215 UpdateFunctionType&& p_updateFunction = {}) {
216 return std::make_shared<
217 NewtonRaphsonWithSubsidiaryFunction<NonLinearOperatorImpl, LinearSolver, UpdateFunctionType>>(
218 p_nonLinearOperator, std::forward<LinearSolver>(p_linearSolver), std::move(p_updateFunction));
219 }
220} // namespace Ikarus
Provides a NonLinearOperator class for handling nonlinear operators.
Several concepts.
Helper for the autodiff library.
Enums for observer messages.
Implementation of the observer design pattern.
Implementation of the Newton-Raphson method for solving nonlinear equations.
Defines structures and methods related to subsidiary functions for control routines.
Definition: simpleassemblers.hh:21
auto makeNewtonRaphsonWithSubsidiaryFunction(const NonLinearOperatorImpl &p_nonLinearOperator, LinearSolver &&p_linearSolver={}, UpdateFunctionType &&p_updateFunction={})
Function to create a NewtonRaphson with subsidiary function solver instance.
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:213
LinearSolverTemplate< double > LinearSolver
Definition: linearsolver.hh:234
Structure containing arguments for subsidiary functions.
Definition: pathfollowingfunctions.hh:38
double Dlambda
The increment in the load factor.
Definition: pathfollowingfunctions.hh:41
double dfdDlambda
The derivative of the subsidiary function with respect to Dlambda.
Definition: pathfollowingfunctions.hh:44
double f
The value of the subsidiary function.
Definition: pathfollowingfunctions.hh:42
Eigen::VectorX< double > dfdDD
The derivative of the subsidiary function with respect to DD.
Definition: pathfollowingfunctions.hh:43
Eigen::VectorX< double > DD
The vector representing the solution increment.
Definition: pathfollowingfunctions.hh:40
void analyzePattern(const MatrixType &A)
Analyze the pattern of the matrix.
Definition: linearsolver.hh:195
void solve(Eigen::VectorX< ScalarType > &x, const Eigen::VectorX< ScalarType > &b)
Solve the linear system for a vector.
Definition: linearsolver.hh:211
void factorize(const MatrixType &A)
Factorize the matrix.
Definition: linearsolver.hh:204
Settings for the Newton-Raphson solver with subsidiary function.
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:27
double tol
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:28
int maxIter
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:29
Newton-Raphson solver with subsidiary function.
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:44
auto & nonLinearOperator()
Access the nonlinear operator.
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:192
typename NonLinearOperatorImpl::template ParameterValue< 0 > ValueType
Type representing the update function.
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:53
NewtonRaphsonWithSubsidiaryFunction(const NonLinearOperatorImpl &p_nonLinearOperator, LinearSolver &&p_linearSolver={}, UpdateFunctionType p_updateFunction={})
Constructor for NewtonRaphsonWithSubsidiaryFunction.
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:64
NonLinearSolverInformation solve(SubsidiaryType &subsidiaryFunction, SubsidiaryArgs &subsidiaryArgs, const SolutionType &dx_predictor=NoPredictor{})
Solve the nonlinear system using the Newton-Raphson method with subsidiary function.
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:98
UpdateFunctionTypeImpl UpdateFunctionType
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:54
NonLinearOperatorImpl NonLinearOperator
Type of the non-linear operator.
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:55
void setup(const NewtonRaphsonWithSubsidiaryFunctionSettings &p_settings)
Setup the Newton-Raphson solver with subsidiary function.
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:76
static constexpr bool isLinearSolver
< Compile-time boolean indicating if the linear solver satisfies the non-linear solver concept
Definition: newtonraphsonwithscalarsubsidiaryfunction.hh:48
Information about the result of a non-linear solver.
Definition: solverinfos.hh:18
double correctionNorm
Definition: solverinfos.hh:27
int iterations
Definition: solverinfos.hh:28
double residualNorm
Definition: solverinfos.hh:26
bool success
Definition: solverinfos.hh:25
Generic observable interface for the Observer design pattern. See for a description of the design pa...
Definition: observer.hh:125
void notify(NonLinearSolverMessages message)
Notify observers about a specific message type.
Definition: observer.hh:254
Concept to check if a linear solver implements all the needed functions for given vector and matrix t...
Definition: concepts.hh:218