From: Denis Davydov Date: Wed, 17 May 2017 14:25:01 +0000 (+0200) Subject: add ConsecutiveControl X-Git-Tag: v9.0.0-rc1~1584^2 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7371f21cfe0fed3dc7f847b79cde41a6c9db3816;p=dealii.git add ConsecutiveControl --- diff --git a/doc/news/changes/minor/20170517DenisDavydov b/doc/news/changes/minor/20170517DenisDavydov new file mode 100644 index 0000000000..24bac6e507 --- /dev/null +++ b/doc/news/changes/minor/20170517DenisDavydov @@ -0,0 +1,5 @@ +New: add a new class ConsecutiveControl which returns SolverControl::State::success +if and only if a certain positive number of consecutive iterations satisfy the +specified tolerance. +
+(Denis Davydov, 2017/05/17) diff --git a/include/deal.II/lac/solver_control.h b/include/deal.II/lac/solver_control.h index ec6d0435b2..71434fed6d 100644 --- a/include/deal.II/lac/solver_control.h +++ b/include/deal.II/lac/solver_control.h @@ -528,6 +528,74 @@ public: const double check_value); }; + +/** + * Specialization of @p SolverControl which returns SolverControl::State::success if + * and only if a certain positive number of consecutive iterations satisfy the + * specified tolerance. This is useful in cases when solving nonlinear problems + * using inexact Hessian. + * + * For example: The requested number of consecutively converged iterations is 2, + * the tolerance is 0.2. The ConsecutiveControl will return SolverControl::State::success + * only at the last step in the sequence 0.5, 0.0005, 1.0, 0.05, 0.01. + * + * @author Denis Davydov, 2017 + */ +class ConsecutiveControl : public SolverControl +{ +public: + /** + * Constructor. @p n_consecutive_iterations is the number of + * consecutive iterations which should satisfy the prescribed tolerance for + * convergence. Other arguments have the same meaning as those of the + * constructor of the SolverControl. + */ + 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); + + /** + * Initialize with a SolverControl object. The result will emulate + * SolverControl by setting @p n_consecutive_iterations to one. + */ + ConsecutiveControl (const SolverControl &c); + + /** + * Assign a SolverControl object to ConsecutiveControl. The result of the + * assignment will emulate SolverControl by setting @p n_consecutive_iterations + * to one. + */ + ConsecutiveControl &operator= (const SolverControl &c); + + /** + * Virtual destructor is needed as there are virtual functions in this + * class. + */ + virtual ~ConsecutiveControl(); + + /** + * Decide about success or failure of an iteration, see the class description + * above. + */ + virtual State check (const unsigned int step, + const double check_value); + +protected: + /** + * The number of consecutive iterations which should satisfy the prescribed + * tolerance for convergence. + */ + unsigned int n_consecutive_iterations; + + /** + * Counter for the number of consecutively converged iterations. + */ + unsigned int n_converged_iterations; + +}; + /*@}*/ //--------------------------------------------------------------------------- diff --git a/source/lac/solver_control.cc b/source/lac/solver_control.cc index 82d3a8452a..ceb720cf70 100644 --- a/source/lac/solver_control.cc +++ b/source/lac/solver_control.cc @@ -349,4 +349,77 @@ IterationNumberControl::check (const unsigned int step, return SolverControl::check(step, check_value); } +/*------------------------ ConsecutiveControl -------------------------------*/ + + +ConsecutiveControl::ConsecutiveControl(const unsigned int n, + const double tolerance, + const unsigned int n_consecutive_iterations, + const bool m_log_history, + const bool m_log_result) + : + SolverControl (n, tolerance, m_log_history, m_log_result), + n_consecutive_iterations(n_consecutive_iterations), + n_converged_iterations(0) +{ + AssertThrow(n_consecutive_iterations>0, + ExcMessage("n_consecutive_iterations should be positive")); +} + + + +ConsecutiveControl::ConsecutiveControl (const SolverControl &c) + : + SolverControl(c), + n_consecutive_iterations(1), + n_converged_iterations(0) +{} + + + +ConsecutiveControl & +ConsecutiveControl::operator= (const SolverControl &c) +{ + SolverControl::operator=(c); + n_consecutive_iterations = 1; + n_converged_iterations = 0; + return *this; +} + + + +ConsecutiveControl::~ConsecutiveControl() +{} + + +SolverControl::State +ConsecutiveControl::check (const unsigned int step, + const double check_value) +{ + // reset the counter if ConsecutiveControl is being reused + if (step==0) + n_converged_iterations = 0; + + SolverControl::State state = SolverControl::check(step, check_value); + // check if we need to override the success: + if (state == success) + { + n_converged_iterations++; + if (n_converged_iterations == n_consecutive_iterations) + { + return success; + } + else + { + lcheck = iterate; + return iterate; + } + } + else + { + n_converged_iterations = 0; + return state; + } +} + DEAL_II_NAMESPACE_CLOSE diff --git a/tests/lac/solver_control_05.cc b/tests/lac/solver_control_05.cc new file mode 100644 index 0000000000..c9ca4fcc77 --- /dev/null +++ b/tests/lac/solver_control_05.cc @@ -0,0 +1,53 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2017 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE at +// the top level of the deal.II distribution. +// +// --------------------------------------------------------------------- + + +// test ConsecutiveControl + + +#include "../tests.h" +#include +#include +#include +#include +#include +#include + + +int main(int argc, char **argv) +{ + std::ofstream logfile("output"); + logfile.precision(4); + deallog.attach(logfile); + deallog.threshold_double(1.e-10); + + { + ConsecutiveControl solver_control(12345, 1.e-3, 3, false, false); + // // n_converged_iterations: + deallog << solver_control.check(0,1.e-1) << std::endl; // 0 + deallog << solver_control.check(1,1.e-4) << std::endl; // 1 + deallog << solver_control.check(2,1.e-5) << std::endl; // 2 + deallog << solver_control.check(3,2.e-3) << std::endl; // 0 + deallog << solver_control.check(4,5.e-4) << std::endl; // 1 + deallog << solver_control.check(5,4.e-4) << std::endl; // 2 + deallog << solver_control.check(6,3.e-4) << std::endl; // 3 ==> success + + // reuse + deallog << solver_control.check(0,3.e-4) << std::endl; // 1 + deallog << solver_control.check(1,2.e-4) << std::endl; // 2 + deallog << solver_control.check(2,1.e-4) << std::endl; // 3 ==> success + + } +} diff --git a/tests/lac/solver_control_05.output b/tests/lac/solver_control_05.output new file mode 100644 index 0000000000..e9d49e3fb7 --- /dev/null +++ b/tests/lac/solver_control_05.output @@ -0,0 +1,11 @@ + +DEAL::0 +DEAL::0 +DEAL::0 +DEAL::0 +DEAL::0 +DEAL::0 +DEAL::1 +DEAL::0 +DEAL::0 +DEAL::1