Heidelberg Educational Numerics Library Version 0.27 (from 15 March 2021)
newton.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil -*-
2#ifndef HDNUM_NEWTON_HH
3#define HDNUM_NEWTON_HH
4
5#include "lr.hh"
6#include <type_traits>
7
12namespace hdnum {
13
20 template<class N>
22 {
23 public:
25 typedef std::size_t size_type;
26
28 typedef N number_type;
29
34
36 std::size_t size () const
37 {
38 return 1;
39 }
40
42 void F (const Vector<N>& x, Vector<N>& result) const
43 {
44 result[0] = x[0]*x[0] - a;
45 }
46
48 void F_x (const Vector<N>& x, DenseMatrix<N>& result) const
49 {
50 result[0][0] = number_type(2.0)*x[0];
51 }
52
53 private:
55 };
56
57
63 template<typename Lambda, typename Vec>
65 {
66 Lambda lambda; // lambda defining the problem "lambda(x)=0"
67 size_t s;
68 typename Vec::value_type eps;
69
70 public:
72 typedef std::size_t size_type;
73
75 typedef typename Vec::value_type number_type;
76
79 : lambda(l_), s(x_.size()), eps(eps_)
80 {}
81
83 std::size_t size () const
84 {
85 return s;
86 }
87
89 void F (const Vec& x, Vec& result) const
90 {
91 result = lambda(x);
92 }
93
95 void F_x (const Vec& x, DenseMatrix<number_type>& result) const
96 {
97 Vec Fx(x.size());
98 F(x,Fx);
99 Vec z(x);
100 Vec Fz(x.size());
101
102 // numerische Jacobimatrix
103 for (int j=0; j<result.colsize(); ++j)
104 {
105 auto zj = z[j];
106 auto dz = (1.0+abs(zj))*eps;
107 z[j] += dz;
108 F(z,Fz);
109 for (int i=0; i<result.rowsize(); i++)
110 result[i][j] = (Fz[i]-Fx[i])/dz;
111 z[j] = zj;
112 }
113 }
114 };
115
123 template<typename F, typename X>
124 GenericNonlinearProblem<F,X> getNonlinearProblem (const F& f, const X& x, typename X::value_type eps = 1e-7)
125 {
126 return GenericNonlinearProblem<F,X>(f,x,eps);
127 }
128
135 class Newton
136 {
137 typedef std::size_t size_type;
138
139 public:
142 : maxit(25), linesearchsteps(10), verbosity(0),
143 reduction(1e-14), abslimit(1e-30), converged(false)
144 {}
145
147 void set_maxit (size_type n)
148 {
149 maxit = n;
150 }
151
152 void set_sigma (double sigma_)
153 {
154
155 }
156
158 void set_linesearchsteps (size_type n)
159 {
160 linesearchsteps = n;
161 }
162
164 void set_verbosity (size_type n)
165 {
166 verbosity = n;
167 }
168
170 void set_abslimit (double l)
171 {
172 abslimit = l;
173 }
174
176 void set_reduction (double l)
177 {
178 reduction = l;
179 }
180
182 template<class M>
183 void solve (const M& model, Vector<typename M::number_type> & x) const
184 {
185 typedef typename M::number_type N;
186 // In complex case, we still need to use real valued numbers for residual norms etc.
187 using Real = typename std::conditional<std::is_same<std::complex<double>, N>::value, double, N>::type;
188 Vector<N> r(model.size()); // residual
189 DenseMatrix<N> A(model.size(),model.size()); // Jacobian matrix
190 Vector<N> y(model.size()); // temporary solution in line search
191 Vector<N> z(model.size()); // solution of linear system
192 Vector<N> s(model.size()); // scaling factors
193 Vector<size_type> p(model.size()); // row permutations
194 Vector<size_type> q(model.size()); // column permutations
195
196 model.F(x,r); // compute nonlinear residual
197 Real R0(std::abs(norm(r))); // norm of initial residual
198 Real R(R0); // current residual norm
199 if (verbosity>=1)
200 {
201 std::cout << "Newton "
202 << " norm=" << std::scientific << std::showpoint
203 << std::setprecision(4) << R0
204 << std::endl;
205 }
206
207 converged = false;
208 for (size_type i=1; i<=maxit; i++) // do Newton iterations
209 {
210 // check absolute size of residual
211 if (R<=abslimit)
212 {
213 converged = true;
214 return;
215 }
216
217 // solve Jacobian system for update
218 model.F_x(x,A); // compute Jacobian matrix
219 row_equilibrate(A,s); // equilibrate rows
220 lr_fullpivot(A,p,q); // LR decomposition of A
221 z = N(0.0); // clear solution
222 apply_equilibrate(s,r); // equilibration of right hand side
223 permute_forward(p,r); // permutation of right hand side
224 solveL(A,r,r); // forward substitution
225 solveR(A,z,r); // backward substitution
226 permute_backward(q,z); // backward permutation
227
228 // line search
229 Real lambda(1.0); // start with lambda=1
230 for (size_type k=0; k<linesearchsteps; k++)
231 {
232 y = x;
233 y.update(-lambda,z); // y = x+lambda*z
234 model.F(y,r); // r = F(y)
235 Real newR(std::abs(norm(r))); // compute norm
236 if (verbosity>=3)
237 {
238 std::cout << " line search " << std::setw(2) << k
239 << " lambda=" << std::scientific << std::showpoint
240 << std::setprecision(4) << lambda
241 << " norm=" << std::scientific << std::showpoint
242 << std::setprecision(4) << newR
243 << " red=" << std::scientific << std::showpoint
244 << std::setprecision(4) << newR/R
245 << std::endl;
246 }
247 if (newR<(1.0-0.25*lambda)*R) // check convergence
248 {
249 if (verbosity>=2)
250 {
251 std::cout << " step" << std::setw(3) << i
252 << " norm=" << std::scientific << std::showpoint
253 << std::setprecision(4) << newR
254 << " red=" << std::scientific << std::showpoint
255 << std::setprecision(4) << newR/R
256 << std::endl;
257 }
258 x = y;
259 R = newR;
260 break; // continue with Newton loop
261 }
262 else lambda *= 0.5; // reduce damping factor
263 if (k==linesearchsteps-1)
264 {
265 if (verbosity>=3)
266 std::cout << " line search not converged within " << linesearchsteps << " steps" << std::endl;
267 return;
268 }
269 }
270
271 // check convergence
272 if (R<=reduction*R0)
273 {
274 if (verbosity>=1)
275 {
276 std::cout << "Newton converged in " << i << " steps"
277 << " reduction=" << std::scientific << std::showpoint
278 << std::setprecision(4) << R/R0
279 << std::endl;
280 }
281 iterations_taken = i;
282 converged = true;
283 return;
284 }
285 if (i==maxit)
286 {
287 iterations_taken = i;
288 if (verbosity>=1)
289 std::cout << "Newton not converged within " << maxit << " iterations" << std::endl;
290 }
291 }
292 }
293
294 bool has_converged () const
295 {
296 return converged;
297 }
298 size_type iterations() const {
299 return iterations_taken;
300 }
301
302
303 private:
304 size_type maxit;
305 mutable size_type iterations_taken = -1;
306 size_type linesearchsteps;
307 size_type verbosity;
308 double reduction;
309 double abslimit;
310 mutable bool converged;
311 };
312
313
314
315
323 class Banach
324 {
325 typedef std::size_t size_type;
326
327 public:
330 : maxit(25), linesearchsteps(10), verbosity(0),
331 reduction(1e-14), abslimit(1e-30), sigma(1.0), converged(false)
332 {}
333
335 void set_maxit (size_type n)
336 {
337 maxit = n;
338 }
339
341 void set_sigma (double sigma_)
342 {
343 sigma = sigma_;
344 }
345
347 void set_linesearchsteps (size_type n)
348 {
349 linesearchsteps = n;
350 }
351
353 void set_verbosity (size_type n)
354 {
355 verbosity = n;
356 }
357
359 void set_abslimit (double l)
360 {
361 abslimit = l;
362 }
363
365 void set_reduction (double l)
366 {
367 reduction = l;
368 }
369
371 template<class M>
372 void solve (const M& model, Vector<typename M::number_type>& x) const
373 {
374 typedef typename M::number_type N;
375 Vector<N> r(model.size()); // residual
376 Vector<N> y(model.size()); // temporary solution in line search
377
378 model.F(x,r); // compute nonlinear residual
379 N R0(norm(r)); // norm of initial residual
380 N R(R0); // current residual norm
381 if (verbosity>=1)
382 {
383 std::cout << "Banach "
384 << " norm=" << std::scientific << std::showpoint
385 << std::setprecision(4) << R0
386 << std::endl;
387 }
388
389 converged = false;
390 for (size_type i=1; i<=maxit; i++) // do iterations
391 {
392 // check absolute size of residual
393 if (R<=abslimit)
394 {
395 converged = true;
396 return;
397 }
398
399 // next iterate
400 y = x;
401 y.update(-sigma,r); // y = x+lambda*z
402 model.F(y,r); // r = F(y)
403 N newR(norm(r)); // compute norm
404 if (verbosity>=2)
405 {
406 std::cout << " " << std::setw(3) << i
407 << " norm=" << std::scientific << std::showpoint
408 << std::setprecision(4) << newR
409 << " red=" << std::scientific << std::showpoint
410 << std::setprecision(4) << newR/R
411 << std::endl;
412 }
413 x = y; // accept new iterate
414 R = newR; // remember new norm
415
416 // check convergence
417 if (R<=reduction*R0 || R<=abslimit)
418 {
419 if (verbosity>=1)
420 {
421 std::cout << "Banach converged in " << i << " steps"
422 << " reduction=" << std::scientific << std::showpoint
423 << std::setprecision(4) << R/R0
424 << std::endl;
425 }
426 converged = true;
427 return;
428 }
429 }
430 }
431
432 bool has_converged () const
433 {
434 return converged;
435 }
436
437 private:
438 size_type maxit;
439 size_type linesearchsteps;
440 size_type verbosity;
441 double reduction;
442 double abslimit;
443 double sigma;
444 mutable bool converged;
445 };
446
447} // namespace hdnum
448
449#endif
Solve nonlinear problem using a fixed point iteration.
Definition newton.hh:324
void set_linesearchsteps(size_type n)
maximum number of steps in linesearch before giving up
Definition newton.hh:347
void set_abslimit(double l)
basolute limit for defect
Definition newton.hh:359
void set_verbosity(size_type n)
control output given 0=nothing, 1=summary, 2=every step, 3=include line search
Definition newton.hh:353
void set_sigma(double sigma_)
damping parameter
Definition newton.hh:341
void set_maxit(size_type n)
maximum number of iterations before giving up
Definition newton.hh:335
void solve(const M &model, Vector< typename M::number_type > &x) const
do one step
Definition newton.hh:372
void set_reduction(double l)
reduction factor
Definition newton.hh:365
Banach()
constructor stores reference to the model
Definition newton.hh:329
Class with mathematical matrix operations.
Definition densematrix.hh:33
void update(const REAL s, const DenseMatrix &B)
Scaled update of a Matrix.
Definition densematrix.hh:489
size_t rowsize() const
get number of rows of the matrix
Definition densematrix.hh:136
size_t colsize() const
get number of columns of the matrix
Definition densematrix.hh:153
A generic problem class that can be set up with a lambda defining F(x)=0.
Definition newton.hh:65
Vec::value_type number_type
export number_type
Definition newton.hh:75
GenericNonlinearProblem(const Lambda &l_, const Vec &x_, number_type eps_=1e-7)
constructor stores parameter lambda
Definition newton.hh:78
void F(const Vec &x, Vec &result) const
model evaluation
Definition newton.hh:89
void F_x(const Vec &x, DenseMatrix< number_type > &result) const
jacobian evaluation needed for implicit solvers
Definition newton.hh:95
std::size_t size() const
return number of componentes for the model
Definition newton.hh:83
std::size_t size_type
export size_type
Definition newton.hh:72
Solve nonlinear problem using a damped Newton method.
Definition newton.hh:136
void set_abslimit(double l)
basolute limit for defect
Definition newton.hh:170
void set_verbosity(size_type n)
control output given 0=nothing, 1=summary, 2=every step, 3=include line search
Definition newton.hh:164
void set_linesearchsteps(size_type n)
maximum number of steps in linesearch before giving up
Definition newton.hh:158
void set_maxit(size_type n)
maximum number of iterations before giving up
Definition newton.hh:147
void set_reduction(double l)
reduction factor
Definition newton.hh:176
Newton()
constructor stores reference to the model
Definition newton.hh:141
void solve(const M &model, Vector< typename M::number_type > &x) const
do one step
Definition newton.hh:183
Example class for a nonlinear model F(x) = 0;.
Definition newton.hh:22
N number_type
export number_type
Definition newton.hh:28
void F_x(const Vector< N > &x, DenseMatrix< N > &result) const
jacobian evaluation needed for implicit solvers
Definition newton.hh:48
SquareRootProblem(number_type a_)
constructor stores parameter lambda
Definition newton.hh:31
void F(const Vector< N > &x, Vector< N > &result) const
model evaluation
Definition newton.hh:42
std::size_t size() const
return number of componentes for the model
Definition newton.hh:36
std::size_t size_type
export size_type
Definition newton.hh:25
This file implements LU decomposition.
void permute_forward(const Vector< std::size_t > &p, Vector< T > &b)
apply permutations to a right hand side vector
Definition lr.hh:160
T abs(const T &t)
our own abs class that works also for multiprecision types
Definition lr.hh:55
void lr_fullpivot(DenseMatrix< T > &A, Vector< std::size_t > &p, Vector< std::size_t > &q)
lr decomposition of A with full pivoting
Definition lr.hh:107
void permute_backward(const Vector< std::size_t > &q, Vector< T > &z)
apply permutations to a solution vector
Definition lr.hh:171
void apply_equilibrate(Vector< T > &s, Vector< T > &b)
apply row equilibration to right hand side vector
Definition lr.hh:203
void solveR(const DenseMatrix< T > &A, Vector< T > &x, const Vector< T > &b)
Assume R = upper triangle of A and solve R x = b.
Definition lr.hh:233
void solveL(const DenseMatrix< T > &A, Vector< T > &x, const Vector< T > &b)
Assume L = lower triangle of A with l_ii=1, solve L x = b.
Definition lr.hh:215
void row_equilibrate(DenseMatrix< T > &A, Vector< T > &s)
perform a row equilibration of a matrix; return scaling for later use
Definition lr.hh:182
GenericNonlinearProblem< F, X > getNonlinearProblem(const F &f, const X &x, typename X::value_type eps=1e-7)
A function returning a problem class.
Definition newton.hh:124