From f3400f75cd15eae68edfae043f0e4c411836a80f Mon Sep 17 00:00:00 2001
From: Wenqing Wang <wenqing.wang@ufz.de>
Date: Thu, 20 Apr 2017 18:09:29 +0200
Subject: [PATCH] [dt] Added a member of NormType

---
 NumLib/ODESolver/TimeDiscretization.cpp       | 20 ++++++---
 .../Algorithms/EvolutionaryPIDcontroller.cpp  | 24 +++++++++--
 .../Algorithms/EvolutionaryPIDcontroller.h    | 13 +-----
 .../Algorithms/FixedTimeStepping.cpp          |  7 +++-
 .../Algorithms/FixedTimeStepping.h            |  1 -
 .../Algorithms/ITimeStepAlgorithm.h           | 41 +++++++++++++++----
 ...erationNumberBasedAdaptiveTimeStepping.cpp |  6 +--
 7 files changed, 76 insertions(+), 36 deletions(-)

diff --git a/NumLib/ODESolver/TimeDiscretization.cpp b/NumLib/ODESolver/TimeDiscretization.cpp
index 4e84ac8ccf9..a3236ca1c5c 100644
--- a/NumLib/ODESolver/TimeDiscretization.cpp
+++ b/NumLib/ODESolver/TimeDiscretization.cpp
@@ -25,6 +25,9 @@ namespace NumLib
 static double computeRelativeError(GlobalVector const& x, GlobalVector& x_old,
                                    MathLib::VecNormType norm_type)
 {
+    if (norm_type == MathLib::VecNormType::INVALID)
+        return 0.;
+
     const double norm2_x = MathLib::LinAlg::norm(x, norm_type);
     assert(norm2_x > std::numeric_limits<double>::epsilon());
 
@@ -33,25 +36,30 @@ static double computeRelativeError(GlobalVector const& x, GlobalVector& x_old,
     return MathLib::LinAlg::norm(x_old, norm_type) / norm2_x;
 }
 
-double BackwardEuler::getRelativeError(GlobalVector const& x, MathLib::VecNormType norm_type)
+double BackwardEuler::getRelativeError(GlobalVector const& x,
+                                       MathLib::VecNormType norm_type)
 {
     return computeRelativeError(x, _x_old, norm_type);
 }
 
-double ForwardEuler::getRelativeError(GlobalVector const& x, MathLib::VecNormType norm_type)
+double ForwardEuler::getRelativeError(GlobalVector const& x,
+                                      MathLib::VecNormType norm_type)
 {
     return computeRelativeError(x, _x_old, norm_type);
 }
 
-double CrankNicolson::getRelativeError(GlobalVector const& x, MathLib::VecNormType norm_type)
+double CrankNicolson::getRelativeError(GlobalVector const& x,
+                                       MathLib::VecNormType norm_type)
 {
     return computeRelativeError(x, _x_old, norm_type);
 }
 
-double BackwardDifferentiationFormula::getRelativeError(GlobalVector const& x, MathLib::VecNormType norm_type)
+double BackwardDifferentiationFormula::getRelativeError(
+    GlobalVector const& x, MathLib::VecNormType norm_type)
 {
-    return (_xs_old.size() < _num_steps) ? 0. : computeRelativeError(
-                                                    x, *_xs_old[_offset], norm_type);
+    return (_xs_old.size() < _num_steps)
+               ? 0.
+               : computeRelativeError(x, *_xs_old[_offset], norm_type);
 }
 
 void BackwardDifferentiationFormula::pushState(const double,
diff --git a/NumLib/TimeStepping/Algorithms/EvolutionaryPIDcontroller.cpp b/NumLib/TimeStepping/Algorithms/EvolutionaryPIDcontroller.cpp
index fda6f69bb33..df1af35e162 100644
--- a/NumLib/TimeStepping/Algorithms/EvolutionaryPIDcontroller.cpp
+++ b/NumLib/TimeStepping/Algorithms/EvolutionaryPIDcontroller.cpp
@@ -42,8 +42,6 @@ bool EvolutionaryPIDcontroller::next(const double solution_error)
 
     // step accepted.
     _is_accepted = true;
-    if (_specific_times.size() > 0)
-        _specific_times.pop_back();
 
     if (_ts_current.steps() == 0)
     {
@@ -81,10 +79,11 @@ bool EvolutionaryPIDcontroller::next(const double solution_error)
             h_new = limitStepSize(h_new, h_n);
         }
 
-        _dt_vector.push_back(h_new);
+        const double checked_h_new = checkSpecificTimeReached(h_new);
+        _dt_vector.push_back(checked_h_new);
 
         _ts_prev = _ts_current;
-        _ts_current += h_new;
+        _ts_current += checked_h_new;
 
         _e_n_minus2 = _e_n_minus1;
         _e_n_minus1 = e_n;
@@ -93,6 +92,23 @@ bool EvolutionaryPIDcontroller::next(const double solution_error)
     return true;
 }
 
+double EvolutionaryPIDcontroller::checkSpecificTimeReached(const double h_new)
+{
+    if (_specific_times.empty())
+        return h_new;
+
+    const double specific_time = _specific_times.back();
+    const double zero_threshlod = std::numeric_limits<double>::epsilon();
+    if ((specific_time > _ts_current.current()) &&
+        (_ts_current.current() + h_new - specific_time > zero_threshlod))
+    {
+        _specific_times.pop_back();
+        return specific_time - _ts_current.current();
+    }
+
+    return h_new;
+}
+
 /// Create an EvolutionaryPIDcontroller time stepper from the given
 /// configuration
 std::unique_ptr<ITimeStepAlgorithm> createEvolutionaryPIDcontroller(
diff --git a/NumLib/TimeStepping/Algorithms/EvolutionaryPIDcontroller.h b/NumLib/TimeStepping/Algorithms/EvolutionaryPIDcontroller.h
index 0f167dbce79..9cdc115542b 100644
--- a/NumLib/TimeStepping/Algorithms/EvolutionaryPIDcontroller.h
+++ b/NumLib/TimeStepping/Algorithms/EvolutionaryPIDcontroller.h
@@ -16,8 +16,6 @@
 
 #include "ITimeStepAlgorithm.h"
 
-#include "MathLib/LinAlg/LinAlg.h"
-
 namespace BaseLib
 {
 class ConfigTree;
@@ -60,7 +58,7 @@ public:
                               const std::vector<double>&& specific_times,
                               const double tol,
                               const MathLib::VecNormType norm_type)
-        : ITimeStepAlgorithm(t0, t_end),
+        : ITimeStepAlgorithm(t0, t_end, norm_type),
           _h0(h0),
           _h_min(h_min),
           _h_max(h_max),
@@ -68,7 +66,6 @@ public:
           _rel_h_max(rel_h_max),
           _specific_times(std::move(specific_times)),
           _tol(tol),
-          _norm_type(norm_type),
           _e_n_minus1(0.),
           _e_n_minus2(0.),
           _is_accepted(true)
@@ -103,7 +100,6 @@ private:
     std::vector<double> _specific_times;
 
     const double _tol;
-    const MathLib::VecNormType _norm_type;
 
     double _e_n_minus1;  ///< \f$e_{n-1}\f$.
     double _e_n_minus2;  ///< \f$e_{n-2}\f$.
@@ -117,12 +113,7 @@ private:
                         std::min(h_in_range, _rel_h_max * h_n));
     }
 
-    double checkSpecificTimeReached(const double h_new) const
-    {
-        if (_ts_current.current() + h_new;
-        return std::max(_rel_h_min * h_n,
-                        std::min(h_in_range, _rel_h_max * h_n));
-    }
+    double checkSpecificTimeReached(const double h_new);
 };
 
 /// Create an EvolutionaryPIDcontroller time stepper from the given
diff --git a/NumLib/TimeStepping/Algorithms/FixedTimeStepping.cpp b/NumLib/TimeStepping/Algorithms/FixedTimeStepping.cpp
index fa74b69f7ad..cc6024d1ecb 100644
--- a/NumLib/TimeStepping/Algorithms/FixedTimeStepping.cpp
+++ b/NumLib/TimeStepping/Algorithms/FixedTimeStepping.cpp
@@ -26,12 +26,15 @@ namespace NumLib
 FixedTimeStepping::FixedTimeStepping(double t0,
                                      double tn,
                                      const std::vector<double>& vec_all_dt)
-    : ITimeStepAlgorithm(t0, computeEnd(t0, tn, vec_all_dt), vec_all_dt)
+    : ITimeStepAlgorithm(t0,
+                         computeEnd(t0, tn, vec_all_dt),
+                         vec_all_dt,
+                         MathLib::VecNormType::INVALID)
 {
 }
 
 FixedTimeStepping::FixedTimeStepping(double t0, double tn, double dt)
-    : ITimeStepAlgorithm(t0, tn, dt)
+    : ITimeStepAlgorithm(t0, tn, dt, MathLib::VecNormType::INVALID)
 {
 }
 
diff --git a/NumLib/TimeStepping/Algorithms/FixedTimeStepping.h b/NumLib/TimeStepping/Algorithms/FixedTimeStepping.h
index 40e0e3cf179..db8d8608a59 100644
--- a/NumLib/TimeStepping/Algorithms/FixedTimeStepping.h
+++ b/NumLib/TimeStepping/Algorithms/FixedTimeStepping.h
@@ -71,7 +71,6 @@ public:
 
     /// return if current time step is accepted
     bool accepted() const override { return true; }
-
 private:
     /// determine true end time
     static double computeEnd(double t_initial, double t_end,
diff --git a/NumLib/TimeStepping/Algorithms/ITimeStepAlgorithm.h b/NumLib/TimeStepping/Algorithms/ITimeStepAlgorithm.h
index e43b2cee496..c5c3e56acf2 100644
--- a/NumLib/TimeStepping/Algorithms/ITimeStepAlgorithm.h
+++ b/NumLib/TimeStepping/Algorithms/ITimeStepAlgorithm.h
@@ -16,6 +16,8 @@
 
 #include "NumLib/TimeStepping/TimeStep.h"
 
+#include "MathLib/LinAlg/LinAlg.h"  // For MathLib::VecNormType
+
 namespace NumLib
 {
 /**
@@ -25,24 +27,42 @@ namespace NumLib
 class ITimeStepAlgorithm
 {
 public:
-    ITimeStepAlgorithm(const double t0, const double t_end)
-        : _t_initial(t0), _t_end(t_end), _ts_prev(t0), _ts_current(t0)
+    ITimeStepAlgorithm(const double t0, const double t_end,
+                       const MathLib::VecNormType norm_type)
+        : _t_initial(t0),
+          _t_end(t_end),
+          _ts_prev(t0),
+          _ts_current(t0),
+          _norm_type(norm_type)
     {
     }
 
-    ITimeStepAlgorithm(const double t0, const double t_end, const double dt)
-        : _t_initial(t0), _t_end(t_end), _ts_prev(t0), _ts_current(t0),
-          _dt_vector(static_cast<std::size_t>(std::ceil((t_end - t0) / dt)), dt)
+    ITimeStepAlgorithm(const double t0, const double t_end, const double dt,
+                       const MathLib::VecNormType norm_type)
+        : _t_initial(t0),
+          _t_end(t_end),
+          _ts_prev(t0),
+          _ts_current(t0),
+          _dt_vector(static_cast<std::size_t>(std::ceil((t_end - t0) / dt)),
+                     dt),
+          _norm_type(norm_type)
     {
     }
 
     ITimeStepAlgorithm(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)
+                       const std::vector<double>& all_step_sizes,
+                       const MathLib::VecNormType norm_type)
+        : _t_initial(t0),
+          _t_end(t_end),
+          _ts_prev(t0),
+          _ts_current(t0),
+          _dt_vector(all_step_sizes),
+          _norm_type(norm_type)
     {
     }
 
+    virtual ~ITimeStepAlgorithm() = default;
+
     /// return the beginning of time steps
     double begin() const { return _t_initial; }
     /// return the end of time steps
@@ -70,7 +90,7 @@ public:
         return _dt_vector;
     }
 
-    virtual ~ITimeStepAlgorithm() = default;
+    MathLib::VecNormType getSolutionNormType() const { return _norm_type; }
 protected:
     /// initial time
     const double _t_initial;
@@ -84,6 +104,9 @@ protected:
 
     /// a vector of time step sizes
     std::vector<double> _dt_vector;
+
+    /// Type of the norm of the solution vector.
+    const MathLib::VecNormType _norm_type;
 };
 
 }  // NumLib
diff --git a/NumLib/TimeStepping/Algorithms/IterationNumberBasedAdaptiveTimeStepping.cpp b/NumLib/TimeStepping/Algorithms/IterationNumberBasedAdaptiveTimeStepping.cpp
index 001f569af1f..a136671ca6c 100644
--- a/NumLib/TimeStepping/Algorithms/IterationNumberBasedAdaptiveTimeStepping.cpp
+++ b/NumLib/TimeStepping/Algorithms/IterationNumberBasedAdaptiveTimeStepping.cpp
@@ -24,9 +24,9 @@ IterationNumberBasedAdaptiveTimeStepping::
         double t0, double tn, double min_ts, double max_ts, double initial_ts,
         std::vector<std::size_t>& iter_times_vector,
         std::vector<double>& multiplier_vector)
-    : ITimeStepAlgorithm(t0, tn),
-      _iter_times_vector(std::move(iter_times_vector)),
-      _multiplier_vector(std::move(multiplier_vector)),
+    : ITimeStepAlgorithm(t0, tn, MathLib::VecNormType::INVALID),
+      _iter_times_vector(iter_times_vector),
+      _multiplier_vector(multiplier_vector),
       _min_ts(min_ts),
       _max_ts(max_ts),
       _initial_ts(initial_ts),
-- 
GitLab