OGS
IterationNumberBasedTimeStepping.cpp
Go to the documentation of this file.
1
14
15#include <algorithm>
16#include <cassert>
17#include <cmath>
18#include <limits>
19#include <utility>
20
21#include "BaseLib/Algorithm.h"
22
23namespace NumLib
24{
26 double const t_initial, double const t_end, double const min_dt,
27 double const max_dt, double const initial_dt,
28 std::vector<int>&& iter_times_vector,
29 std::vector<double>&& multiplier_vector,
30 std::vector<double> const& fixed_times_for_output)
31 : TimeStepAlgorithm(t_initial, t_end),
32 _iter_times_vector(std::move(iter_times_vector)),
33 _multiplier_vector(std::move(multiplier_vector)),
34 _min_dt(min_dt),
35 _max_dt(max_dt),
36 _initial_dt(initial_dt),
37 _max_iter(_iter_times_vector.empty() ? 0 : _iter_times_vector.back()),
38 _fixed_times_for_output(fixed_times_for_output)
39{
40 if (_iter_times_vector.empty())
41 {
42 OGS_FATAL("Vector of iteration numbers must not be empty.");
43 }
44 if (_iter_times_vector.size() != _multiplier_vector.size())
45 {
47 "Vector of iteration numbers must be of the same size as the "
48 "vector of multipliers.");
49 }
50 if (!std::is_sorted(std::begin(_iter_times_vector),
51 std::end(_iter_times_vector)))
52 {
53 OGS_FATAL("Vector of iteration numbers must be sorted.");
54 }
55}
56
58 double const /*solution_error*/, int const number_iterations,
59 NumLib::TimeStep& ts_previous, NumLib::TimeStep& ts_current)
60{
61 _iter_times = number_iterations;
62
64 {
65 ts_previous = ts_current;
66 }
67
68 // confirm current time and move to the next if accepted
69 if (ts_current.isAccepted())
70 {
72 return std::make_tuple(_previous_time_step_accepted,
73 getNextTimeStepSize(ts_previous, ts_current));
74 }
75 else
76 {
77 double dt = getNextTimeStepSize(ts_previous, ts_current);
78 // In case it is the first time be rejected, re-computed dt again with
79 // current dt
80 if (std::abs(dt - ts_current.dt()) <
81 std::numeric_limits<double>::epsilon())
82 {
83 // time step was rejected, keep dt for the next dt computation.
84 ts_previous = // essentially equal to _ts_prev.dt = _ts_current.dt.
85 TimeStep{ts_previous.previous(), ts_previous.previous() + dt,
86 ts_previous.timeStepNumber()};
87 dt = getNextTimeStepSize(ts_previous, ts_current);
88 }
89
90 // time step was rejected, keep dt for the next dt computation.
91 ts_previous = // essentially equal to ts_previous.dt = _ts_current.dt.
92 TimeStep{ts_previous.previous(), ts_previous.previous() + dt,
93 ts_previous.timeStepNumber()};
94
96 return std::make_tuple(_previous_time_step_accepted, dt);
97 }
98}
99
101 int const number_iterations, NumLib::TimeStep const& ts_current) const
102{
103 double multiplier = _multiplier_vector.front();
104 for (std::size_t i = 0; i < _iter_times_vector.size(); i++)
105 {
106 if (number_iterations >= _iter_times_vector[i])
107 {
108 multiplier = _multiplier_vector[i];
109 }
110 }
111
112 if (!ts_current.isAccepted() && (multiplier >= 1.0))
113 {
114 return *std::min_element(_multiplier_vector.begin(),
115 _multiplier_vector.end());
116 }
117
118 return multiplier;
119}
120
122 NumLib::TimeStep const& ts_previous,
123 NumLib::TimeStep const& ts_current) const
124{
125 double dt = 0.0;
126
127 // In first time step and first non-linear iteration take the initial dt.
128 if (ts_previous.timeStepNumber() == 0 && _iter_times == 0)
129 {
130 dt = _initial_dt;
131 }
132 else
133 {
134 // Attention: for the first time step and second iteration the
135 // ts_prev.dt is 0 and 0*multiplier is the next dt, which will be
136 // clamped to the minimum dt.
137 dt = ts_previous.dt() * findMultiplier(_iter_times, ts_current);
138 }
139
140 if (_fixed_times_for_output.empty())
141 {
142 return std::clamp(dt, _min_dt, _max_dt);
143 }
144
145 // find first fixed timestep for output larger than the current time, i.e.,
146 // current time < fixed output time
147 auto fixed_output_time_it = std::find_if(
149 [&ts_current](auto const fixed_output_time)
150 { return ts_current.current() < fixed_output_time; });
151
152 if (fixed_output_time_it != _fixed_times_for_output.end())
153 {
154 // check if the fixed output time is in the interval
155 // (current time, current time + dt)
156 if (*fixed_output_time_it < ts_current.current() + dt)
157 {
158 // check if the potential adjusted time step is larger than zero
159 if (std::abs(*fixed_output_time_it - ts_current.current()) >
160 std::numeric_limits<double>::epsilon() * ts_current.current())
161 {
162 return *fixed_output_time_it - ts_current.current();
163 }
164 }
165 }
166 return std::clamp(dt, _min_dt, _max_dt);
167}
168
170 NumLib::TimeStep const& timestep_previous,
171 NumLib::TimeStep const& timestep_current) const
172{
173 return NumLib::canReduceTimestepSize(timestep_previous, timestep_current,
174 _min_dt);
175}
176
177} // namespace NumLib
#define OGS_FATAL(...)
Definition Error.h:26
std::tuple< bool, double > next(double solution_error, int number_iterations, NumLib::TimeStep &ts_previous, NumLib::TimeStep &ts_current) override
double getNextTimeStepSize(NumLib::TimeStep const &ts_previous, NumLib::TimeStep const &ts_current) const
Calculate the next time step size.
const double _max_dt
The maximum allowed time step size.
const std::vector< double > _multiplier_vector
This vector stores the multiplier coefficients.
double findMultiplier(int const number_iterations, NumLib::TimeStep const &ts_current) const
Find a multiplier for the given number of iterations.
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, std::vector< double > const &fixed_times_for_output)
bool canReduceTimestepSize(NumLib::TimeStep const &timestep_previous, NumLib::TimeStep const &timestep_current) const override
Query the timestepper if further time step size reduction is possible.
int _iter_times
The number of nonlinear iterations.
const double _min_dt
The minimum allowed time step size.
Interface of time stepping algorithms.
Time step object.
Definition TimeStep.h:28
double current() const
return current time step
Definition TimeStep.h:90
bool isAccepted() const
Definition TimeStep.h:97
double dt() const
time step size from _previous
Definition TimeStep.h:92
std::size_t timeStepNumber() const
the time step number
Definition TimeStep.h:94
double previous() const
return previous time step
Definition TimeStep.h:88
bool canReduceTimestepSize(TimeStep const &timestep_previous, TimeStep const &timestep_current, double const min_dt)