/** * \file * \author Haibing Shao and Norihiro Watanabe * \date 2013-08-07 * * \copyright * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org) * Distributed under a Modified BSD License. * See accompanying file LICENSE.txt or * http://www.opengeosys.org/project/license */ #pragma once #include <vector> #include "TimeStepAlgorithm.h" namespace NumLib { /** * \brief Iteration number based adaptive time stepping. * * This algorithm estimates a time step size depending on the number of * iterations (e.g. of iterative linear solvers, nonlinear methods, partitioned * coupling) needed in the last time step (see Hoffmann (2010) for * Newton-Raphson case). * The new time step \f$\Delta t_{n+1}\f$ size is calculated as * \f[ * \Delta t_{n+1} = \alpha \Delta t_n * \f] * with the previous time step size \f$\Delta t_{n}\f$ and a multiplier * coefficient * \f$\alpha\f$ depending on the iteration number. * Note that a time step size is always bounded by the minimum and maximum * allowed * value. * \f[ * \Delta t_{\min} \le \Delta t \le \Delta t_{\max} * \f] * * For example, users can setup the following time stepping strategy based on * the iteration number of the Newton-Raphson method in the last time step. * <table border="1"> * <tr><th>Num. of Newton * steps</th><th>0-2</th><th>3-6</th><th>7-8</th><th>9<</th></tr> * <tr><th>Time step size * multiplier</th><th>1.6</th><th>1.</th><th>0.5</th><th>0.25 (repeat time * step)</th></tr> * <tr><th>Upper and lower bound</th><th colspan="4"> \f$ 1. \le \Delta t \le * 10.\f$ </th></tr> * </table> * A time step size is increased for the small iteration number, and decreased * for the * large iteration number. If the iteration number exceeds a user-defined * threshold (e.g. 9), * a time step is repeated with a smaller time step size. * * Reference * - Hoffmann J (2010) Reactive Transport and Mineral Dissolution/Precipitation * in Porous Media:Efficient Solution Algorithms, Benchmark Computations and * Existence of Global Solutions. PhD thesis. pp82. * Friedrich-Alexander-Universität Erlangen-Nürnberg. * */ class IterationNumberBasedTimeStepping final : public TimeStepAlgorithm { public: /** * @param t_initial start time * @param t_end end time * @param min_dt the minimum allowed time step size * @param max_dt the maximum allowed time step size * @param initial_dt initial time step size * @param iter_times_vector a vector of iteration numbers * (\f$i_1\f$, \f$i_2\f$, ..., \f$i_n\f$) which defines intervals as * \f$[i_1,i_2)\f$, \f$[i_2,i_3)\f$, ..., \f$[i_n,\infty)\f$. * If an iteration number is larger than \f$i_n\f$, current time step is * repeated with the new time step size. * @param multiplier_vector a vector of multiplier coefficients * (\f$a_1\f$, \f$a_2\f$, ..., \f$a_n\f$) corresponding to the intervals * given by iter_times_vector. * A time step size is calculated by \f$\Delta t_{n+1} = a * \Delta t_{n}\f$ */ IterationNumberBasedTimeStepping(double const t_initial, double const t_end, double const min_dt, double const max_dt, double const initial_dt, std::vector<int>&& iter_times_vector, std::vector<double>&& multiplier_vector); ~IterationNumberBasedTimeStepping() override = default; bool next(double solution_error, int number_iterations) override; bool accepted() const override; void setAcceptedOrNot(bool accepted) override { _accepted = accepted; }; bool isSolutionErrorComputationNeeded() const override { return true; } bool canReduceTimestepSize() const override; /// Return the number of repeated steps. int getNumberOfRepeatedSteps() const { return _n_rejected_steps; } private: /// Calculate the next time step size. double getNextTimeStepSize() const; /// Find a multiplier for the given number of iterations. double findMultiplier(int number_iterations) const; /// This vector stores the number of iterations to which the respective /// multiplier coefficient will be applied. const std::vector<int> _iter_times_vector; /// This vector stores the multiplier coefficients. const std::vector<double> _multiplier_vector; /// The minimum allowed time step size. const double _min_dt; /// The maximum allowed time step size. const double _max_dt; /// Initial time step size. const double _initial_dt; /// The maximum allowed iteration number to accept current time step. const int _max_iter; /// The number of nonlinear iterations. int _iter_times = 0; /// The number of rejected steps. int _n_rejected_steps = 0; /// True, if the timestep is accepted. bool _accepted = true; }; } // namespace NumLib