Reference documentation for deal.II version 9.0.0
solver_control.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1998 - 2017 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 at
12 // the top level of the deal.II distribution.
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 #include <deal.II/lac/solver_control.h>
20 
21 #include <cmath>
22 #include <sstream>
23 
24 DEAL_II_NAMESPACE_OPEN
25 
26 /*----------------------- SolverControl ---------------------------------*/
27 
28 
29 SolverControl::SolverControl (const unsigned int maxiter,
30  const double tolerance,
31  const bool m_log_history,
32  const bool m_log_result)
33  :
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,
53  const double check_value)
54 {
55  // if this is the first time we
56  // come here, then store the
57  // residual for later comparisons
58  if (step==0)
59  {
60  initial_val = check_value;
61  }
62 
63  if (m_log_history && ((step % m_log_frequency) == 0))
64  deallog << "Check " << step << "\t" << check_value << std::endl;
65 
66  lstep = step;
67  lvalue = check_value;
68 
69  if (step==0)
70  {
71  if (check_failure)
73 
74  if (m_log_result)
75  deallog << "Starting value " << check_value << std::endl;
76  }
77 
79  history_data.push_back(check_value);
80 
81  if (check_value <= tol)
82  {
83  if (m_log_result)
84  deallog << "Convergence step " << step
85  << " value " << check_value << std::endl;
86  lcheck = success;
87  return success;
88  }
89 
90  if ((step >= maxsteps) ||
91  std::isnan(check_value) ||
92  (check_failure && (check_value > failure_residual))
93  )
94  {
95  if (m_log_result)
96  deallog << "Failure step " << step
97  << " value " << check_value << std::endl;
98  lcheck = failure;
99  return failure;
100  }
101 
102  lcheck = iterate;
103  return iterate;
104 }
105 
106 
107 
110 {
111  return lcheck;
112 }
113 
114 
115 double
117 {
118  return initial_val;
119 }
120 
121 
122 double
124 {
125  return lvalue;
126 }
127 
128 
129 unsigned int
131 {
132  return lstep;
133 }
134 
135 
136 unsigned int
138 {
139  if (f==0)
140  f = 1;
141  unsigned int old = m_log_frequency;
142  m_log_frequency = f;
143  return old;
144 }
145 
146 
147 void
149 {
150  history_data_enabled = true;
151 }
152 
153 
154 
155 const std::vector<double> &SolverControl::get_history_data() const
156 {
158  Assert (history_data.size() > 0,
159  ExcMessage("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 
176  Assert (history_data[0] > 0., ExcInternalError());
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[@ref step_1 "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 
215 {
216  set_max_steps (param.get_integer("Max steps"));
217  set_tolerance (param.get_double("Tolerance"));
218  log_history (param.get_bool("Log history"));
219  log_result (param.get_bool("Log result"));
220  log_frequency (param.get_integer("Log frequency"));
221 }
222 
223 /*----------------------- ReductionControl ---------------------------------*/
224 
225 
227  const double tol,
228  const double red,
229  const bool m_log_history,
230  const bool m_log_result)
231  :
232  SolverControl (n, tol, m_log_history, m_log_result),
233  reduce(red),
234  reduced_tol(numbers::signaling_nan<double>())
235 {}
236 
237 
239  :
240  SolverControl(c),
241  reduce(numbers::signaling_nan<double>()),
242  reduced_tol(numbers::signaling_nan<double>())
243 {
244  set_reduction(0.);
245 }
246 
247 
250 {
252  set_reduction(0.);
253  return *this;
254 }
255 
256 
257 
259 ReductionControl::check (const unsigned int step,
260  const double check_value)
261 {
262  // if this is the first time we
263  // come here, then store the
264  // residual for later comparisons
265  if (step==0)
266  {
267  initial_val = check_value;
268  reduced_tol = check_value * reduce;
269  }
270 
271  // check whether desired reduction
272  // has been achieved. also check
273  // for equality in case initial
274  // residual already was zero
275  if (check_value <= reduced_tol)
276  {
277  if (m_log_result)
278  deallog << "Convergence step " << step
279  << " value " << check_value << std::endl;
280  lstep = step;
281  lvalue = check_value;
282  lcheck = success;
283 
285  history_data.push_back(check_value);
286 
287  return success;
288  }
289  else
290  return SolverControl::check(step, check_value);
291 }
292 
293 
294 
295 void
297 {
299  param.declare_entry("Reduction", "1.e-2", Patterns::Double());
300 }
301 
302 
303 void
305 {
307  set_reduction (param.get_double("Reduction"));
308 }
309 
310 
311 /*---------------------- IterationNumberControl -----------------------------*/
312 
313 
315  const double tolerance,
316  const bool m_log_history,
317  const bool m_log_result)
318  :
319  SolverControl (n, tolerance, m_log_history, m_log_result) {}
320 
321 
322 
323 
325 IterationNumberControl::check (const unsigned int step,
326  const double check_value)
327 {
328  // check whether the given number of iterations was reached, and return
329  // success in that case. Otherwise, go on to the check of the base class.
330  if (step >= this->maxsteps)
331  {
332  if (m_log_result)
333  deallog << "Convergence step " << step
334  << " value " << check_value << std::endl;
335  lstep = step;
336  lvalue = check_value;
337 
338  lcheck = success;
339  return success;
340  }
341  else
342  return SolverControl::check(step, check_value);
343 }
344 
345 /*------------------------ ConsecutiveControl -------------------------------*/
346 
347 
349  const double tolerance,
350  const unsigned int n_consecutive_iterations,
351  const bool m_log_history,
352  const bool m_log_result)
353  :
354  SolverControl (n, tolerance, m_log_history, m_log_result),
355  n_consecutive_iterations(n_consecutive_iterations),
356  n_converged_iterations(0)
357 {
359  ExcMessage("n_consecutive_iterations should be positive"));
360 }
361 
362 
363 
365  :
366  SolverControl(c),
367  n_consecutive_iterations(1),
368  n_converged_iterations(0)
369 {}
370 
371 
372 
375 {
379  return *this;
380 }
381 
382 
383 
385 ConsecutiveControl::check (const unsigned int step,
386  const double check_value)
387 {
388  // reset the counter if ConsecutiveControl is being reused
389  if (step==0)
391  else
392  {
393  // check two things:
394  // (i) steps are ascending without repetitions
395  // (ii) user started from zero even when solver is being reused.
396  Assert (@ref step_1 "step-1" == lstep,
397  ExcMessage("steps should be ascending integers."));
398  }
399 
400  SolverControl::State state = SolverControl::check(step, check_value);
401  // check if we need to override the success:
402  if (state == success)
403  {
406  {
407  return success;
408  }
409  else
410  {
411  lcheck = iterate;
412  return iterate;
413  }
414  }
415  else
416  {
418  return state;
419  }
420 }
421 
422 DEAL_II_NAMESPACE_CLOSE
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)
bool history_data_enabled
Continue iteration.
Subscriptor & operator=(const Subscriptor &)
Definition: subscriptor.cc:129
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:1221
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
ConsecutiveControl & operator=(const SolverControl &c)
double failure_residual
static ::ExceptionBase & ExcMessage(std::string arg1)
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:1142
unsigned int m_log_frequency
double set_reduction(const double)
static ::ExceptionBase & ExcHistoryDataRequired()
virtual State check(const unsigned int step, const double check_value)
bool get_bool(const std::string &entry_name) const
double relative_failure_residual
double last_value() const
double average_reduction() const
unsigned int lstep
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 declare_entry(const std::string &entry, const std::string &default_value, const Patterns::PatternBase &pattern=Patterns::Anything(), const std::string &documentation=std::string())
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
virtual State check(const unsigned int step, const double check_value)
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)
virtual State check(const unsigned int step, const double check_value)
ReductionControl & operator=(const SolverControl &c)
static ::ExceptionBase & ExcInternalError()