deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
solver_control.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 1998 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#include <deal.II/base/config.h>
14
22#include <deal.II/base/types.h>
23
25
26#include <Kokkos_Macros.hpp>
27
28#include <cmath>
29#include <sstream>
30#include <string>
31#include <vector>
32
34
35/*----------------------- SolverControl ---------------------------------*/
36
37
38SolverControl::SolverControl(const unsigned int maxiter,
39 const double tolerance,
40 const bool m_log_history,
41 const bool m_log_result)
42 : maxsteps(maxiter)
43 , tol(tolerance)
44 , lcheck(failure)
45 , initial_val(numbers::signaling_nan<double>())
46 , lvalue(numbers::signaling_nan<double>())
47 , lstep(numbers::invalid_unsigned_int)
48 , check_failure(false)
49 , relative_failure_residual(0)
50 , failure_residual(0)
51 , m_log_history(m_log_history)
52 , m_log_frequency(1)
53 , m_log_result(m_log_result)
54 , history_data_enabled(false)
55{}
56
57
58
60SolverControl::check(const unsigned int step, const double check_value)
61{
62 // if this is the first time we
63 // come here, then store the
64 // residual for later comparisons
65 if (step == 0)
66 {
67 initial_val = check_value;
68
70 history_data.clear();
71 }
72
73 if (m_log_history && ((step % m_log_frequency) == 0))
74 deallog << "Check " << step << "\t" << check_value << std::endl;
75
76 lstep = step;
77 lvalue = check_value;
78
79 if (step == 0)
80 {
81 if (check_failure)
83
84 if (m_log_result)
85 deallog << "Starting value " << check_value << std::endl;
86 }
87
89 history_data.push_back(check_value);
90
91 if (check_value <= tol)
92 {
93 if (m_log_result)
94 deallog << "Convergence step " << step << " value " << check_value
95 << std::endl;
97 return success;
98 }
99
100 if ((step >= maxsteps) || numbers::is_nan(check_value) ||
101 (check_failure && (check_value > failure_residual)))
102 {
103 if (m_log_result)
104 deallog << "Failure step " << step << " value " << check_value
105 << std::endl;
106 lcheck = failure;
107 return failure;
108 }
109
110 lcheck = iterate;
111 return iterate;
112}
113
114
115
118{
119 return lcheck;
120}
121
122
123double
125{
126 return initial_val;
127}
128
129
130double
132{
133 return lvalue;
134}
135
136
137unsigned int
139{
140 return lstep;
141}
142
143
144unsigned int
146{
147 if (f == 0)
148 f = 1;
149 unsigned int old = m_log_frequency;
150 m_log_frequency = f;
151 return old;
152}
153
154
155void
160
161
162
163const std::vector<double> &
165{
167 Assert(
168 history_data.size() > 0,
170 "The SolverControl object was asked for the solver history "
171 "data, but there is no data. Possibly you requested the data before the "
172 "solver was run."));
173
174 return history_data;
175}
176
177
178
179double
192
193
194
195double
196SolverControl::step_reduction(unsigned int step) const
197{
200 Assert(step <= lstep, ExcIndexRange(step, 1, lstep + 1));
201 Assert(step > 0, ExcIndexRange(step, 1, lstep + 1));
202
203 return history_data[step] / history_data[step - 1];
204}
205
206
207double
212
213
214void
216{
217 param.declare_entry("Max steps", "100", Patterns::Integer());
218 param.declare_entry("Tolerance", "1.e-10", Patterns::Double());
219 param.declare_entry("Log history", "false", Patterns::Bool());
220 param.declare_entry("Log frequency", "1", Patterns::Integer());
221 param.declare_entry("Log result", "true", Patterns::Bool());
222}
223
224
225void
227{
228 set_max_steps(param.get_integer("Max steps"));
229 set_tolerance(param.get_double("Tolerance"));
230 log_history(param.get_bool("Log history"));
231 log_result(param.get_bool("Log result"));
232 log_frequency(param.get_integer("Log frequency"));
233}
234
235/*----------------------- ReductionControl ---------------------------------*/
236
237
239 const double tol,
240 const double red,
241 const bool m_log_history,
242 const bool m_log_result)
243 : SolverControl(n, tol, m_log_history, m_log_result)
244 , reduce(red)
245 , reduced_tol(numbers::signaling_nan<double>())
246{}
247
248
250 : SolverControl(c)
251 , reduce(numbers::signaling_nan<double>())
252 , reduced_tol(numbers::signaling_nan<double>())
253{
254 set_reduction(0.);
255}
256
257
260{
262 set_reduction(0.);
263 return *this;
264}
265
266
267
269ReductionControl::check(const unsigned int step, const double check_value)
270{
271 // if this is the first time we
272 // come here, then store the
273 // residual for later comparisons
274 if (step == 0)
275 {
276 initial_val = check_value;
277 reduced_tol = check_value * reduce;
278
280 history_data.clear();
281 }
282
283 // check whether desired reduction
284 // has been achieved. also check
285 // for equality in case initial
286 // residual already was zero
287 if (check_value <= reduced_tol)
288 {
289 if (m_log_result)
290 deallog << "Convergence step " << step << " value " << check_value
291 << std::endl;
292 lstep = step;
293 lvalue = check_value;
294 lcheck = success;
295
297 history_data.push_back(check_value);
298
299 return success;
300 }
301 else
302 return SolverControl::check(step, check_value);
303}
304
305
306
307void
313
314
315void
321
322
323/*---------------------- IterationNumberControl -----------------------------*/
324
325
327 const double tolerance,
328 const bool m_log_history,
329 const bool m_log_result)
330 : SolverControl(n, tolerance, m_log_history, m_log_result)
331{}
332
333
334
336IterationNumberControl::check(const unsigned int step, const double check_value)
337{
338 // check whether the given number of iterations was reached, and return
339 // success in that case. Otherwise, go on to the check of the base class.
340 if (step >= this->maxsteps)
341 {
342 if (m_log_result)
343 deallog << "Convergence step " << step << " value " << check_value
344 << std::endl;
345 lstep = step;
346 lvalue = check_value;
347
348 lcheck = success;
349 return success;
350 }
351 else
352 return SolverControl::check(step, check_value);
353}
354
355/*------------------------ ConsecutiveControl -------------------------------*/
356
357
359 const unsigned int n,
360 const double tolerance,
361 const unsigned int n_consecutive_iterations,
362 const bool m_log_history,
363 const bool m_log_result)
364 : SolverControl(n, tolerance, m_log_history, m_log_result)
365 , n_consecutive_iterations(n_consecutive_iterations)
366 , n_converged_iterations(0)
367{
369 ExcMessage("n_consecutive_iterations should be positive"));
370}
371
372
373
375 : SolverControl(c)
376 , n_consecutive_iterations(1)
377 , n_converged_iterations(0)
378{}
379
380
381
390
391
392
394ConsecutiveControl::check(const unsigned int step, const double check_value)
395{
396 // reset the counter if ConsecutiveControl is being reused
397 if (step == 0)
399 else
400 {
401 // check two things:
402 // (i) steps are ascending without repetitions
403 // (ii) user started from zero even when solver is being reused.
404 Assert(step - 1 == lstep,
405 ExcMessage("steps should be ascending integers."));
406 }
407
408 SolverControl::State state = SolverControl::check(step, check_value);
409 // check if we need to override the success:
410 if (state == success)
411 {
414 {
415 return success;
416 }
417 else
418 {
419 lcheck = iterate;
420 return iterate;
421 }
422 }
423 else
424 {
426 return state;
427 }
428}
429
ConsecutiveControl & operator=(const SolverControl &c)
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)
unsigned int n_consecutive_iterations
unsigned int n_converged_iterations
virtual State check(const unsigned int step, const double check_value) override
EnableObserverPointer & operator=(const EnableObserverPointer &)
IterationNumberControl(const unsigned int maxiter=100, const double tolerance=1e-12, const bool log_history=false, const bool log_result=false)
virtual State check(const unsigned int step, const double check_value) override
long int get_integer(const std::string &entry_string) const
bool get_bool(const std::string &entry_name) const
void declare_entry(const std::string &entry, const std::string &default_value, const Patterns::PatternBase &pattern=Patterns::Anything(), const std::string &documentation="", const bool has_to_be_set=false)
double get_double(const std::string &entry_name) const
double set_reduction(const double)
void parse_parameters(ParameterHandler &param)
virtual State check(const unsigned int step, const double check_value) override
static void declare_parameters(ParameterHandler &param)
ReductionControl & operator=(const SolverControl &c)
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=false)
static void declare_parameters(ParameterHandler &param)
SolverControl(const unsigned int n=100, const double tol=1.e-10, const bool log_history=false, const bool log_result=false)
State last_check() const
double average_reduction() const
const std::vector< double > & get_history_data() const
unsigned int lstep
unsigned int last_step() const
double last_value() const
unsigned int m_log_frequency
unsigned int log_frequency(unsigned int)
virtual State check(const unsigned int step, const double check_value)
unsigned int maxsteps
bool log_history() const
void enable_history_data()
double step_reduction(unsigned int step) const
std::vector< double > history_data
double failure_residual
double relative_failure_residual
unsigned int set_max_steps(const unsigned int)
double set_tolerance(const double)
double initial_value() const
bool log_result() const
void parse_parameters(ParameterHandler &param)
double final_reduction() const
@ iterate
Continue iteration.
@ success
Stop iteration, goal reached.
@ failure
Stop iteration, goal not reached.
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define Assert(cond, exc)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcHistoryDataRequired()
static ::ExceptionBase & ExcIndexRange(std::size_t arg1, std::size_t arg2, std::size_t arg3)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
LogStream deallog
Definition logstream.cc:36
bool is_nan(const double x)
Definition numbers.h:501
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)