Reference documentation for deal.II version Git 7026f387cc 2019-10-15 14:19:01 -0400
\(\newcommand{\dealcoloneq}{\mathrel{\vcenter{:}}=}\)
solver_control.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1998 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/base/logstream.h>
17 #include <deal.II/base/parameter_handler.h>
18 #include <deal.II/base/signaling_nan.h>
19 
20 #include <deal.II/lac/solver_control.h>
21 
22 #include <cmath>
23 #include <sstream>
24 
25 DEAL_II_NAMESPACE_OPEN
26 
27 /*----------------------- SolverControl ---------------------------------*/
28 
29 
30 SolverControl::SolverControl(const unsigned int maxiter,
31  const double tolerance,
32  const bool m_log_history,
33  const bool m_log_result)
34  : maxsteps(maxiter)
35  , tol(tolerance)
36  , lcheck(failure)
37  , initial_val(numbers::signaling_nan<double>())
38  , lvalue(numbers::signaling_nan<double>())
39  , lstep(numbers::invalid_unsigned_int)
40  , check_failure(false)
41  , relative_failure_residual(0)
42  , failure_residual(0)
43  , m_log_history(m_log_history)
44  , m_log_frequency(1)
45  , m_log_result(m_log_result)
46  , history_data_enabled(false)
47 {}
48 
49 
50 
52 SolverControl::check(const unsigned int step, const double check_value)
53 {
54  // if this is the first time we
55  // come here, then store the
56  // residual for later comparisons
57  if (step == 0)
58  {
59  initial_val = check_value;
60  }
61 
62  if (m_log_history && ((step % m_log_frequency) == 0))
63  deallog << "Check " << step << "\t" << check_value << std::endl;
64 
65  lstep = step;
66  lvalue = check_value;
67 
68  if (step == 0)
69  {
70  if (check_failure)
72 
73  if (m_log_result)
74  deallog << "Starting value " << check_value << std::endl;
75  }
76 
78  history_data.push_back(check_value);
79 
80  if (check_value <= tol)
81  {
82  if (m_log_result)
83  deallog << "Convergence step " << step << " value " << check_value
84  << std::endl;
85  lcheck = success;
86  return success;
87  }
88 
89  if ((step >= maxsteps) || std::isnan(check_value) ||
90  (check_failure && (check_value > failure_residual)))
91  {
92  if (m_log_result)
93  deallog << "Failure step " << step << " value " << check_value
94  << std::endl;
95  lcheck = failure;
96  return failure;
97  }
98 
99  lcheck = iterate;
100  return iterate;
101 }
102 
103 
104 
107 {
108  return lcheck;
109 }
110 
111 
112 double
114 {
115  return initial_val;
116 }
117 
118 
119 double
121 {
122  return lvalue;
123 }
124 
125 
126 unsigned int
128 {
129  return lstep;
130 }
131 
132 
133 unsigned int
135 {
136  if (f == 0)
137  f = 1;
138  unsigned int old = m_log_frequency;
139  m_log_frequency = f;
140  return old;
141 }
142 
143 
144 void
146 {
147  history_data_enabled = true;
148 }
149 
150 
151 
152 const std::vector<double> &
154 {
156  Assert(
157  history_data.size() > 0,
158  ExcMessage(
159  "The SolverControl object was asked for the solver history "
160  "data, but there is no data. Possibly you requested the data before the "
161  "solver was run."));
162 
163  return history_data;
164 }
165 
166 
167 
168 double
170 {
171  if (lstep == 0)
172  return 0.;
173 
178 
179  return std::pow(history_data[lstep] / history_data[0], 1. / lstep);
180 }
181 
182 
183 
184 double
185 SolverControl::step_reduction(unsigned int step) const
186 {
189  Assert(step <= lstep, ExcIndexRange(step, 1, lstep + 1));
190  Assert(step > 0, ExcIndexRange(step, 1, lstep + 1));
191 
192  return history_data[step] / history_data[step - 1];
193 }
194 
195 
196 double
198 {
199  return step_reduction(lstep);
200 }
201 
202 
203 void
205 {
206  param.declare_entry("Max steps", "100", Patterns::Integer());
207  param.declare_entry("Tolerance", "1.e-10", Patterns::Double());
208  param.declare_entry("Log history", "false", Patterns::Bool());
209  param.declare_entry("Log frequency", "1", Patterns::Integer());
210  param.declare_entry("Log result", "true", Patterns::Bool());
211 }
212 
213 
214 void
216 {
217  set_max_steps(param.get_integer("Max steps"));
218  set_tolerance(param.get_double("Tolerance"));
219  log_history(param.get_bool("Log history"));
220  log_result(param.get_bool("Log result"));
221  log_frequency(param.get_integer("Log frequency"));
222 }
223 
224 /*----------------------- ReductionControl ---------------------------------*/
225 
226 
228  const double tol,
229  const double red,
230  const bool m_log_history,
231  const bool m_log_result)
232  : SolverControl(n, tol, m_log_history, m_log_result)
233  , reduce(red)
234  , reduced_tol(numbers::signaling_nan<double>())
235 {}
236 
237 
239  : SolverControl(c)
240  , reduce(numbers::signaling_nan<double>())
241  , reduced_tol(numbers::signaling_nan<double>())
242 {
243  set_reduction(0.);
244 }
245 
246 
249 {
251  set_reduction(0.);
252  return *this;
253 }
254 
255 
256 
258 ReductionControl::check(const unsigned int step, const double check_value)
259 {
260  // if this is the first time we
261  // come here, then store the
262  // residual for later comparisons
263  if (step == 0)
264  {
265  initial_val = check_value;
266  reduced_tol = check_value * reduce;
267  }
268 
269  // check whether desired reduction
270  // has been achieved. also check
271  // for equality in case initial
272  // residual already was zero
273  if (check_value <= reduced_tol)
274  {
275  if (m_log_result)
276  deallog << "Convergence step " << step << " value " << check_value
277  << std::endl;
278  lstep = step;
279  lvalue = check_value;
280  lcheck = success;
281 
283  history_data.push_back(check_value);
284 
285  return success;
286  }
287  else
288  return SolverControl::check(step, check_value);
289 }
290 
291 
292 
293 void
295 {
297  param.declare_entry("Reduction", "1.e-2", Patterns::Double());
298 }
299 
300 
301 void
303 {
305  set_reduction(param.get_double("Reduction"));
306 }
307 
308 
309 /*---------------------- IterationNumberControl -----------------------------*/
310 
311 
313  const double tolerance,
314  const bool m_log_history,
315  const bool m_log_result)
316  : SolverControl(n, tolerance, m_log_history, m_log_result)
317 {}
318 
319 
320 
322 IterationNumberControl::check(const unsigned int step, const double check_value)
323 {
324  // check whether the given number of iterations was reached, and return
325  // success in that case. Otherwise, go on to the check of the base class.
326  if (step >= this->maxsteps)
327  {
328  if (m_log_result)
329  deallog << "Convergence step " << step << " value " << check_value
330  << std::endl;
331  lstep = step;
332  lvalue = check_value;
333 
334  lcheck = success;
335  return success;
336  }
337  else
338  return SolverControl::check(step, check_value);
339 }
340 
341 /*------------------------ ConsecutiveControl -------------------------------*/
342 
343 
345  const unsigned int n,
346  const double tolerance,
347  const unsigned int n_consecutive_iterations,
348  const bool m_log_history,
349  const bool m_log_result)
350  : SolverControl(n, tolerance, m_log_history, m_log_result)
351  , n_consecutive_iterations(n_consecutive_iterations)
352  , n_converged_iterations(0)
353 {
354  AssertThrow(n_consecutive_iterations > 0,
355  ExcMessage("n_consecutive_iterations should be positive"));
356 }
357 
358 
359 
361  : SolverControl(c)
364 {}
365 
366 
367 
370 {
374  return *this;
375 }
376 
377 
378 
380 ConsecutiveControl::check(const unsigned int step, const double check_value)
381 {
382  // reset the counter if ConsecutiveControl is being reused
383  if (step == 0)
385  else
386  {
387  // check two things:
388  // (i) steps are ascending without repetitions
389  // (ii) user started from zero even when solver is being reused.
390  Assert(step - 1 == lstep,
391  ExcMessage("steps should be ascending integers."));
392  }
393 
394  SolverControl::State state = SolverControl::check(step, check_value);
395  // check if we need to override the success:
396  if (state == success)
397  {
400  {
401  return success;
402  }
403  else
404  {
405  lcheck = iterate;
406  return iterate;
407  }
408  }
409  else
410  {
412  return state;
413  }
414 }
415 
416 DEAL_II_NAMESPACE_CLOSE
virtual State check(const unsigned int step, const double check_value) override
double initial_value() const
Stop iteration, goal not reached.
long int get_integer(const std::string &entry_string) const
bool log_history() const
virtual State check(const unsigned int step, const double check_value)
void declare_entry(const std::string &entry, const std::string &default_value, const Patterns::PatternBase &pattern=Patterns::Anything(), const std::string &documentation="")
bool history_data_enabled
Continue iteration.
Subscriptor & operator=(const Subscriptor &)
Definition: subscriptor.h:283
const std::vector< double > & get_history_data() const
static void declare_parameters(ParameterHandler &param)
unsigned int n_consecutive_iterations
double step_reduction(unsigned int step) const
double final_reduction() const
void parse_parameters(ParameterHandler &param)
ConsecutiveControl(const unsigned int maxiter=100, const double tolerance=1.e-10, const unsigned int n_consecutive_iterations=2, const bool log_history=false, const bool log_result=false)
#define AssertThrow(cond, exc)
Definition: exceptions.h:1519
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
ConsecutiveControl & operator=(const SolverControl &c)
double failure_residual
static ::ExceptionBase & ExcMessage(std::string arg1)
virtual State check(const unsigned int step, const double check_value) override
double get_double(const std::string &entry_name) const
static void declare_parameters(ParameterHandler &param)
unsigned int log_frequency(unsigned int)
Stop iteration, goal reached.
#define Assert(cond, exc)
Definition: exceptions.h:1407
unsigned int m_log_frequency
double set_reduction(const double)
static ::ExceptionBase & ExcHistoryDataRequired()
virtual State check(const unsigned int step, const double check_value) override
bool get_bool(const std::string &entry_name) const
double relative_failure_residual
double last_value() const
double average_reduction() const
unsigned int lstep
double tolerance() const
unsigned int last_step() const
IterationNumberControl(const unsigned int maxiter=100, const double tolerance=1e-12, const bool log_history=false, const bool log_result=true)
unsigned int n_converged_iterations
State last_check() const
void enable_history_data()
double set_tolerance(const double)
ReductionControl(const unsigned int maxiter=100, const double tolerance=1.e-10, const double reduce=1.e-2, const bool log_history=false, const bool log_result=true)
unsigned int maxsteps
void parse_parameters(ParameterHandler &param)
std::vector< double > history_data
SolverControl(const unsigned int n=100, const double tol=1.e-10, const bool log_history=false, const bool log_result=true)
bool log_result() const
unsigned int set_max_steps(const unsigned int)
ReductionControl & operator=(const SolverControl &c)
static ::ExceptionBase & ExcInternalError()