Raw File
TimeStepAlgorithm.h
/**
 * \file
 * \author Norihiro Watanabe
 * \date   2012-08-03
 *
 * \copyright
 * Copyright (c) 2012-2021, 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 <cmath>
#include <tuple>
#include <vector>

#include "BaseLib/Error.h"
#include "NumLib/TimeStepping/TimeStep.h"

namespace NumLib
{
/**
 * \brief Interface of time stepping algorithms
 */
class TimeStepAlgorithm
{
public:
    TimeStepAlgorithm(const double t0, const double t_end)
        : _t_initial(t0), _t_end(t_end), _ts_prev(t0), _ts_current(t0)
    {
    }

    TimeStepAlgorithm(const double t0, const double t_end, const double dt)
        : _t_initial(t0), _t_end(t_end), _ts_prev(t0), _ts_current(t0)
    {
        auto const new_size =
            static_cast<std::size_t>(std::ceil((t_end - t0) / dt));
        try
        {
            _dt_vector = std::vector<double>(new_size, dt);
        }
        catch (std::length_error const& e)
        {
            OGS_FATAL(
                "Resize of the time steps vector failed for the requested new "
                "size {:d}. Probably there is not enough memory ({:g} GiB "
                "requested).\n"
                "Thrown exception: {:s}",
                new_size, new_size * sizeof(double) / 1024. / 1024. / 1024.,
                e.what());
        }
        catch (std::bad_alloc const& e)
        {
            OGS_FATAL(
                "Allocation of the time steps vector failed for the requested "
                "size {:d}. Probably there is not enough memory ({:d} GiB "
                "requested).\n"
                "Thrown exception: {:s}",
                new_size,
                new_size * sizeof(double) / 1024. / 1024. / 1024.,
                e.what());
        }
    }

    TimeStepAlgorithm(const double t0, const double t_end,
                      const std::vector<double>& all_step_sizes)
        : _t_initial(t0),
          _t_end(t_end),
          _ts_prev(t0),
          _ts_current(t0),
          _dt_vector(all_step_sizes)
    {
    }

    virtual ~TimeStepAlgorithm() = default;

    /// return the beginning of time steps
    double begin() const { return _t_initial; }
    /// return the end of time steps
    double end() const { return _t_end; }
    /// return current time step
    const TimeStep getTimeStep() const { return _ts_current; }
    /// reset the current step size from the previous time
    void resetCurrentTimeStep(const double dt)
    {
        _ts_prev = _ts_current;
        _ts_current += dt;
        _dt_vector.push_back(dt);
    }

    /// Move to the next time step
    /// \param solution_error Solution error \f$e_n\f$ between two successive
    ///        time steps.
    /// \param number_iterations Number of non-linear iterations used.
    /// \return A step acceptance flag and the computed step size.
    virtual std::tuple<bool, double> next(const double solution_error,
                                          int number_iterations) = 0;

    /// return if current time step is accepted or not
    virtual bool accepted() const = 0;

    /// Set the status of the step.
    /// \param accepted A boolean parameter is needed to indicated whether the
    /// step is accepted or not.
    virtual void setAcceptedOrNot(const bool accepted) { (void)accepted; };

    /// return a history of time step sizes
    const std::vector<double>& getTimeStepSizeHistory() const
    {
        return _dt_vector;
    }

    /// Get a flag to indicate whether this algorithm needs to compute
    /// solution error. The default return value is false.
    virtual bool isSolutionErrorComputationNeeded() const { return false; }

    /// Query the timestepper if further time step size reduction is possible.
    virtual bool canReduceTimestepSize() const { return false; }

protected:
    /// initial time
    const double _t_initial;
    /// end time
    const double _t_end;

    /// previous time step information
    TimeStep _ts_prev;
    /// current time step information
    TimeStep _ts_current;

    /// a vector of time step sizes
    std::vector<double> _dt_vector;
};

/// If any of the fixed times will be reached with given time increment, it will
/// be reduced, otherwise the input will be returned.
/// \pre The input vector of fixed times must be sorted.
/// \param t Current time.
/// \param dt Suggested time increment.
/// \param fixed_output_times Sorted list of times which are to be reached.
double possiblyClampDtToNextFixedTime(
    double const t, double const dt,
    std::vector<double> const& fixed_output_times);

}  // namespace NumLib
back to top