/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
Discretization Framework for functional Renormalization Group flows
newton.hh
Go to the documentation of this file.
1#pragma once
2
4
5// standard library
6#include <functional>
7
8// external libraries
9#include <deal.II/base/config.h>
10#include <deal.II/base/timer.h>
11
12namespace DiFfRG
13{
14 using namespace dealii;
15
21 template <typename VectorType_> class Newton
22 {
23 public:
24 using VectorType = VectorType_;
25
26 Newton(double abstol_ = 1e-10, double reltol_ = 1e-6, double assemble_threshold_ = 0., uint max_steps_ = 21,
27 uint n_stepsize_iterations_ = 21)
28 : abstol(abstol_), reltol(reltol_), assemble_threshold(assemble_threshold_), max_steps(max_steps_),
29 n_stepsize_iterations(n_stepsize_iterations_), ignore_nonconv(false)
30 {
31 }
32
33 void set_report_port(ReportPort port) { report_port = std::move(port); }
34
38 void reinit(const VectorType &u) { update_jacobian(u); }
39
45 void operator()(VectorType &iterate)
46 {
47 Timer timer;
48
49 converged = false;
50 step = 0;
51 resnorm = 1.;
52 jacobians = 0;
53
54 initial_vector = iterate;
55 iterate_vector = iterate;
57
58 Du.reinit(u);
59 residual_vector.reinit(u);
60
61 // fill res with (f(u), v)
63 if (!std::isfinite(residual_vector.l2_norm())) throw std::runtime_error("Initial residual non-finite!");
64 resnorm = get_EEst();
65 double old_residual = 0.;
66 double res_l2 = residual_vector.l2_norm();
67 double assembly_time = 0.;
68
69 while (check()) {
70 step++;
71
72 // assemble (Df(u), v)
73 if ((step > 1) && (resnorm / old_residual >= assemble_threshold)) {
74 Timer timer_assembly;
76 assembly_time += timer_assembly.wall_time();
77 jacobians++;
78 }
79
80 Du.reinit(u);
81 try {
83 } catch (std::exception &) {
84 throw std::runtime_error("Linear solve failed!");
85 }
86
87 u.add(-1., Du);
88 old_residual = resnorm;
89 double old_res_l2 = res_l2;
90
92 res_l2 = residual_vector.l2_norm();
93 if (!std::isfinite(res_l2)) throw std::runtime_error("Residual non-finite!");
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;
191
197 double get_EEst()
198 {
199 const VectorType &err = residual_vector;
200 const VectorType &u_prev = initial_vector;
201 const VectorType &u = iterate_vector;
202
203 eest_tmp.reinit(u);
204
205 using std::abs, std::max, std::sqrt;
206 tbb::parallel_for(tbb::blocked_range<uint>(0, eest_tmp.size()), [&](tbb::blocked_range<uint> r) {
207 for (uint n = r.begin(); n < r.end(); ++n) {
208 eest_tmp[n] = abs(err[n]) / (abstol + max(abs(u_prev[n]), abs(u[n])) * reltol);
209 }
210 });
211 return eest_tmp.l2_norm() / sqrt(eest_tmp.size());
212 }
213
220 bool check()
221 {
222 if (step > max_steps) return false;
223 if (step == 0) return true;
224 double err = get_EEst();
225 converged = err <= 1.;
226 return !converged;
227 }
228 };
229} // namespace DiFfRG
A newton solver, using local error estimates for each vector component.
Definition newton.hh:22
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:26
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:197
uint n_stepsize_iterations
Definition newton.hh:182
bool check()
Check if the iteration should go on.
Definition newton.hh:220
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
void set_report_port(ReportPort port)
Definition newton.hh:33
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:38
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
ReportPort report_port
Definition newton.hh:190
bool converged
Definition newton.hh:184
std::function< void(VectorType &, const VectorType &)> lin_solve
Definition newton.hh:157
VectorType_ VectorType
Definition newton.hh:24
void operator()(VectorType &iterate)
Perform a newton iteration on the input vector.
Definition newton.hh:45
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 run_reporter.hh:96
Definition complex_math.hh:10
unsigned int uint
Definition utils.hh:24