--- /dev/null
+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.
+<br>
+(Denis Davydov, 2017/05/17)
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;
+
+};
+
/*@}*/
//---------------------------------------------------------------------------
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
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// 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 <deal.II/base/utilities.h>
+#include <cmath>
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+#include <deal.II/lac/solver_control.h>
+
+
+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
+
+ }
+}
--- /dev/null
+
+DEAL::0
+DEAL::0
+DEAL::0
+DEAL::0
+DEAL::0
+DEAL::0
+DEAL::1
+DEAL::0
+DEAL::0
+DEAL::1