/home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/timestepping/solver/newton.hh Source File#

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/timestepping/solver/newton.hh Source File
DiFfRG
newton.hh
Go to the documentation of this file.
1#pragma once
2
3// standard library
4#include <functional>
5#include <iostream>
6
7// external libraries
8#include <deal.II/base/config.h>
9#include <deal.II/base/timer.h>
10
11namespace DiFfRG
12{
13 using namespace dealii;
14
20 template <typename VectorType_> class Newton
21 {
22 public:
23 using VectorType = VectorType_;
24
25 Newton(double abstol_ = 1e-10, double reltol_ = 1e-6, double assemble_threshold_ = 0., uint max_steps_ = 21,
26 uint n_stepsize_iterations_ = 21)
27 : abstol(abstol_), reltol(reltol_), assemble_threshold(assemble_threshold_), max_steps(max_steps_),
28 n_stepsize_iterations(n_stepsize_iterations_), ignore_nonconv(false)
29 {
30 }
31
35 void reinit(const VectorType &u) { update_jacobian(u); }
36
42 void operator()(VectorType &iterate)
43 {
44 Timer timer;
45
46 converged = false;
47 step = 0;
48 resnorm = 1.;
49 jacobians = 0;
50
51 initial_vector = iterate;
52 iterate_vector = iterate;
54
55 Du.reinit(u);
56 residual_vector.reinit(u);
57
58 // fill res with (f(u), v)
60 if (!std::isfinite(residual_vector.l2_norm())) throw std::runtime_error("Initial residual non-finite!");
61 resnorm = get_EEst();
62 double old_residual = 0.;
63 double res_l2 = residual_vector.l2_norm();
64 double assembly_time = 0.;
65
66 while (check()) {
67 step++;
68
69 // assemble (Df(u), v)
70 if ((step > 1) && (resnorm / old_residual >= assemble_threshold)) {
71 Timer timer_assembly;
73 assembly_time += timer_assembly.wall_time();
74 jacobians++;
75 }
76
77 Du.reinit(u);
78 try {
80 } catch (std::exception &) {
81 throw std::runtime_error("Linear solve failed!");
82 }
83
84 u.add(-1., Du);
85 old_residual = resnorm;
86 double old_res_l2 = res_l2;
87
89 res_l2 = residual_vector.l2_norm();
90 if (!std::isfinite(res_l2)) {
91 std::cerr << "Residual non-finite!" << std::endl;
92 throw std::runtime_error("Residual non-finite!");
93 }
94
95 // Simple line search: use cheap l2_norm comparisons instead of full get_EEst()
96 uint step_size = 0;
97 while (res_l2 >= old_res_l2) {
98 ++step_size;
99 if (step_size > n_stepsize_iterations) {
100 break;
101 }
102 u.add(1. / double(1 << step_size), Du);
104 res_l2 = residual_vector.l2_norm();
105 }
106
107 // compute full error estimate once after line search
108 resnorm = get_EEst();
109 }
110
111 timings_newton.push_back(timer.wall_time() - assembly_time);
112
113 // in case of failure: throw exception
114 if (!(converged || ignore_nonconv) || !std::isfinite(resnorm)) {
115 throw std::runtime_error("Newton did not converge!");
116 }
117 // otherwise exit as normal
118 else
119 iterate = iterate_vector;
120 }
121
127 double threshold(const double thr)
128 {
129 const double t = assemble_threshold;
130 assemble_threshold = thr;
131 return t;
132 }
133
134 const VectorType &get_residual() const { return residual_vector; }
135 const VectorType &get_initial() const { return initial_vector; }
136 const VectorType &get_iterate() const { return iterate_vector; }
137
138 double average_time_newton() const
139 {
140 double t = 0.;
141 double n = timings_newton.size();
142 for (const auto &t_ : timings_newton)
143 t += t_ / n;
144 return t;
145 }
146 uint num_newton_calls() const { return timings_newton.size(); }
147
154 void set_ignore_nonconv(bool x) { ignore_nonconv = x; }
155
156 std::function<void(VectorType &, const VectorType &)> residual;
157 std::function<void(VectorType &, const VectorType &)> lin_solve;
158 std::function<void(const VectorType &)> update_jacobian;
159
163 double get_error() { return resnorm; }
164
168 uint get_step() { return step; }
169
174
175 private:
183
186 double resnorm;
188
189 std::vector<double> timings_newton;
190
196 double get_EEst()
197 {
198 const VectorType &err = residual_vector;
199 const VectorType &u_prev = initial_vector;
200 const VectorType &u = iterate_vector;
201
202 eest_tmp.reinit(u);
203
204 using std::abs, std::max, std::sqrt;
205 tbb::parallel_for(tbb::blocked_range<uint>(0, eest_tmp.size()), [&](tbb::blocked_range<uint> r) {
206 for (uint n = r.begin(); n < r.end(); ++n) {
207 eest_tmp[n] = abs(err[n]) / (abstol + max(abs(u_prev[n]), abs(u[n])) * reltol);
208 }
209 });
210 return eest_tmp.l2_norm() / sqrt(eest_tmp.size());
211 }
212
219 bool check()
220 {
221 if (step > max_steps) return false;
222 if (step == 0) return true;
223 double err = get_EEst();
224 converged = err <= 1.;
225 return !converged;
226 }
227 };
228} // namespace DiFfRG
A newton solver, using local error estimates for each vector component.
Definition newton.hh:21
Newton(double abstol_=1e-10, double reltol_=1e-6, double assemble_threshold_=0., uint max_steps_=21, uint n_stepsize_iterations_=21)
Definition newton.hh:25
VectorType eest_tmp
Definition newton.hh:180
uint num_newton_calls() const
Definition newton.hh:146
bool ignore_nonconv
Definition newton.hh:185
double average_time_newton() const
Definition newton.hh:138
double get_EEst()
Calculate the current error estimate.
Definition newton.hh:196
uint n_stepsize_iterations
Definition newton.hh:182
bool check()
Check if the iteration should go on.
Definition newton.hh:219
std::function< void(const VectorType &)> update_jacobian
Definition newton.hh:158
const VectorType & get_iterate() const
Definition newton.hh:136
void set_ignore_nonconv(bool x)
Make the newton algorithm return a success even if the evolution did not fulfill the convergence crit...
Definition newton.hh:154
std::function< void(VectorType &, const VectorType &)> residual
Definition newton.hh:156
double get_error()
Get the latest error.
Definition newton.hh:163
const VectorType & get_initial() const
Definition newton.hh:135
uint max_steps
Definition newton.hh:182
double assemble_threshold
Definition newton.hh:181
double resnorm
Definition newton.hh:186
VectorType iterate_vector
Definition newton.hh:178
uint get_step()
Get the number of steps taken in the latest iteration.
Definition newton.hh:168
const VectorType & get_residual() const
Definition newton.hh:134
uint get_jacobians()
Get the number of jacobians created in the latest iteration.
Definition newton.hh:173
void reinit(const VectorType &u)
Should it be necessary, one can force a recalculation of the jacobian hereby.
Definition newton.hh:35
VectorType initial_vector
Definition newton.hh:177
double threshold(const double thr)
Set the jacobian recalculation threshold, i.e. below which reduction we force a jacobian update.
Definition newton.hh:127
VectorType residual_vector
Definition newton.hh:176
bool converged
Definition newton.hh:184
std::function< void(VectorType &, const VectorType &)> lin_solve
Definition newton.hh:157
VectorType_ VectorType
Definition newton.hh:23
void operator()(VectorType &iterate)
Perform a newton iteration on the input vector.
Definition newton.hh:42
double abstol
Definition newton.hh:181
std::vector< double > timings_newton
Definition newton.hh:189
uint step
Definition newton.hh:187
VectorType Du
Definition newton.hh:179
uint jacobians
Definition newton.hh:187
double reltol
Definition newton.hh:181
Definition complex_math.hh:10
unsigned int uint
Definition utils.hh:24