FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
newton_raphson_linesearch.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
8#include <kernel/solver/linesearch.hpp>
9
10namespace FEAT
11{
12 namespace Solver
13 {
30 template<typename Functional_, typename Filter_>
31 class NewtonRaphsonLinesearch : public Linesearch<Functional_, Filter_>
32 {
33 public:
35 typedef Filter_ FilterType;
37 typedef typename Functional_::VectorTypeR VectorType;
39 typedef typename Functional_::DataType DataType;
42
43 public:
57 explicit NewtonRaphsonLinesearch(Functional_& functional, Filter_& filter, bool keep_iterates = false) :
58 BaseClass("NR-LS", functional, filter, keep_iterates)
59 {
60 }
61
80 explicit NewtonRaphsonLinesearch(const String& section_name, const PropertyMap* section,
81 Functional_& functional, Filter_& filter) :
82 BaseClass("NR-LS", section_name, section, functional, filter)
83 {
84 }
85
88 {
89 }
90
92 virtual String name() const override
93 {
94 return "Newton-Raphson-Linesearch";
95 }
96
108 virtual Status apply(VectorType& vec_cor, const VectorType& vec_dir) override
109 {
110 // clear solution vector
111 vec_cor.format();
112 this->_functional.prepare(vec_cor, this->_filter);
113
114 // apply
115 this->_status = _apply_intern(vec_cor, vec_dir);
116 this->plot_summary();
117 return this->_status;
118 }
119
131 virtual Status correct(VectorType& vec_sol, const VectorType& vec_dir) override
132 {
133 this->_functional.prepare(vec_sol, this->_filter);
134 // apply
135 this->_status = _apply_intern(vec_sol, vec_dir);
136 this->plot_summary();
137 return this->_status;
138 }
139
140 protected:
155 virtual Status _apply_intern(VectorType& vec_sol, const VectorType& vec_dir)
156 {
157 Statistics::add_solver_expression(std::make_shared<ExpressionStartSolve>(this->name()));
158
159 // The step length wrt. to the NORMALISED search direction
160 DataType alpha(0);
161 // The functional value
162 DataType fval(0);
164 DataType df(0);
165
166 // Perform initializations and checks
167 Status st = this->_startup(alpha, fval, df, vec_sol, vec_dir);
168 // Because of the Newton-Raphson update x[k+1] = x[k] + alpha[k+1] d and alpha[k+1] = alpha[k] - < g[k], d > / < d, H[k] d >,
169 // || d ||_2 does not matter and the relative update is invariant
170
171 // Compute new _alpha <- _alpha - grad.dot(vec_dir) / vec_dir.dot(Hess*vec_dir)
172 this->_functional.apply_hess(this->_vec_tmp, this->_vec_pn);
173 this->_filter.filter_def(this->_vec_tmp);
174
175 alpha = -this->_vec_grad.dot(this->_vec_pn)/this->_vec_pn.dot(this->_vec_tmp);
176
177 // start iterating
178 while(st == Status::progress)
179 {
180 IterationStats stat(*this);
181
182 // Increase iteration count
183 ++this->_num_iter;
184
185 this->_functional.prepare(vec_sol, this->_filter);
186 this->_functional.eval_fval_grad(fval, this->_vec_grad);
187 // DO NOT call trim() here, as this simple linesearch accepts bad steps too, which would then be trimmed
188 // and used.
189 //this->trim_func_grad(fval);
190 this->_filter.filter_def(this->_vec_grad);
191
192 df = this->_vec_pn.dot(this->_vec_grad);
193
194 if(fval <= this->_fval_min)
195 {
196 this->_fval_min = fval;
197 this->_alpha_min = alpha;
198 }
199
200 st = this->_check_convergence(fval, df, alpha);
201
202 if(st != Status::progress)
203 {
204 break;
205 }
206
207 // Compute new _alpha <- _alpha - grad.dot(this->_vec_pn) / this->_vec_pn.dot(Hess*this->_vec_pn)
208 this->_functional.apply_hess(this->_vec_tmp, this->_vec_pn);
209 this->_filter.filter_def(this->_vec_tmp);
210
211 alpha -= this->_vec_grad.dot(this->_vec_pn)/this->_vec_pn.dot(this->_vec_tmp);
212
213 // Update solution
214 vec_sol.copy(this->_vec_initial_sol);
215 vec_sol.axpy(this->_vec_pn, alpha);
216
217 }
218
219 // If we are not successful, we update the best step length and need to re-evaluate everything for that
220 // step
221 if(st != Status::success)
222 {
223 vec_sol.copy(this->_vec_initial_sol);
224 vec_sol.axpy(this->_vec_pn, this->_alpha_min);
225
226 // Prepare and evaluate
227 this->_functional.prepare(vec_sol, this->_filter);
228 this->_functional.eval_fval_grad(fval, this->_vec_grad);
229 // DO NOT call trim() here, as this simple linesearch accepts bad steps too, which would then be trimmed
230 // and used.
231 this->trim_func_grad(fval);
232 this->_filter.filter_def(this->_vec_grad);
233 }
234
235 Statistics::add_solver_expression(std::make_shared<ExpressionEndSolve>(this->name(), Status::undefined, this->get_num_iter()));
236 return st;
237 }
238
239 }; // class NewtonRaphsonLinesearch
240
256 template<typename Functional_, typename Filter_>
257 inline std::shared_ptr<NewtonRaphsonLinesearch<Functional_, Filter_>> new_newton_raphson_linesearch(
258 Functional_& functional, Filter_& filter, bool keep_iterates = false)
259 {
260 return std::make_shared<NewtonRaphsonLinesearch<Functional_, Filter_>>(functional, filter, keep_iterates);
261 }
262
281 template<typename Functional_, typename Filter_>
282 inline std::shared_ptr<NewtonRaphsonLinesearch<Functional_, Filter_>> new_newton_raphson_linesearch(
283 const String& section_name, const PropertyMap* section,
284 Functional_& functional, Filter_& filter)
285 {
286 return std::make_shared<NewtonRaphsonLinesearch<Functional_, Filter_>>(section_name, section, functional, filter);
287 }
288 } // namespace Solver
289} // namespace FEAT
FEAT Kernel base header.
A class organizing a tree of key-value pairs.
Helper class for iteration statistics collection.
Definition: base.hpp:392
Index get_num_iter() const
Returns number of performed iterations.
Definition: iterative.hpp:462
Index _num_iter
number of performed iterations
Definition: iterative.hpp:231
virtual void plot_summary() const
Plot a summary of the last solver run.
Definition: iterative.hpp:627
Linesearch base class.
Definition: linesearch.hpp:34
VectorType _vec_grad
Gradient vector.
Definition: linesearch.hpp:53
Functional_ & _functional
The (nonlinear) functional.
Definition: linesearch.hpp:48
VectorType _vec_initial_sol
Initial solution.
Definition: linesearch.hpp:55
virtual void trim_func_grad(DataType &func)
Trims the function value and gradient according to some threshold.
Definition: linesearch.hpp:430
virtual Status _startup(DataType &alpha, DataType &fval, DataType &delta, const VectorType &vec_sol, const VectorType &vec_dir)
Performs the startup of the iteration.
Definition: linesearch.hpp:464
VectorType _vec_pn
descend direction vector, normalized for better numerical stability
Definition: linesearch.hpp:59
DataType _fval_min
Functional functional value.
Definition: linesearch.hpp:62
Filter_ & _filter
The filter to be applied to the functional's gradient.
Definition: linesearch.hpp:50
DataType _alpha_min
Line search parameter.
Definition: linesearch.hpp:71
VectorType _vec_tmp
temporary vector
Definition: linesearch.hpp:57
virtual Status _check_convergence(const DataType fval, const DataType df, const DataType alpha)
Performs the line search convergence checks using the strong Wolfe conditions.
Definition: linesearch.hpp:543
NewtonRaphsonLinesearch(const String &section_name, const PropertyMap *section, Functional_ &functional, Filter_ &filter)
Constructor using a PropertyMap.
Functional_::VectorTypeR VectorType
Input vector type for the functional's gradient.
NewtonRaphsonLinesearch(Functional_ &functional, Filter_ &filter, bool keep_iterates=false)
Standard constructor.
virtual Status correct(VectorType &vec_sol, const VectorType &vec_dir) override
Applies the solver, making use of an initial guess.
Filter_ FilterType
Filter type to be applied to the gradient of the functional.
virtual Status apply(VectorType &vec_cor, const VectorType &vec_dir) override
Applies the solver, setting the initial guess to zero.
Functional_::DataType DataType
Underlying floating point type.
virtual String name() const override
Returns a descriptive string.
virtual Status _apply_intern(VectorType &vec_sol, const VectorType &vec_dir)
Internal function: Applies the solver.
Linesearch< Functional_, Filter_ > BaseClass
Our base class.
String class implementation.
Definition: string.hpp:46
std::shared_ptr< NewtonRaphsonLinesearch< Functional_, Filter_ > > new_newton_raphson_linesearch(Functional_ &functional, Filter_ &filter, bool keep_iterates=false)
Creates a new NewtonRaphsonLinesearch object.
Status
Solver status return codes enumeration.
Definition: base.hpp:47
@ success
solving successful (convergence criterion fulfilled)
@ progress
continue iteration (internal use only)
@ undefined
undefined status
FEAT namespace.
Definition: adjactor.hpp:12