Flow123d  last_with_con_2.0.0-4-g42e6930
time_governor.hh
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file time_governor.hh
15  * @brief Basic time management class.
16  * @author Jan Brezina
17  */
18 
19 #ifndef TIME_HH_
20 #define TIME_HH_
21 
22 #include <limits>
23 #include <cmath>
24 #include <algorithm>
25 #include <boost/circular_buffer.hpp>
26 
27 
28 #include "system/global_defs.h"
29 #include "system/system.hh"
31 #include "input/input_exception.hh"
32 #include "tools/time_marks.hh"
33 
34 namespace Input {
35  class Record;
36  namespace Type {
37  class Record;
38  }
39 }
40 
41 
42 
43 
44 /**
45  * @brief Representation of one time step.\
46  *
47  * Time step consists of the time step @p length() and from time step @end() time.
48  * More over we store the index of the time step within it time governor.
49  *
50  * The reason to store both the end time and the length of the time step is to allow
51  * safe comparisons of the time with safety margin small relative to the
52  * time step length.
53  */
54 class TimeStep {
55 public:
56  /**
57  * Constructor of the zero time step.
58  */
59  TimeStep(double init_time);
60 
61  /**
62  * Default constructor.
63  * Creates undefined time step.
64  */
65  TimeStep();
66 
67  /**
68  * Copy constructor.
69  */
70  TimeStep(const TimeStep &other);
71 
72  /**
73  * Create subsequent time step.
74  */
75  TimeStep make_next(double new_length) const;
76 
77  /**
78  * Create subsequent time step, with the @end_time
79  * explicitly specified. This allow slight discrepancy to
80  * overcome rounding errors in the case of fixed time step.
81  * Otherwise using small fixed time step, we may miss long term fixed
82  * goal time.
83  *
84  */
85  TimeStep make_next(double new_lenght, double end_time) const;
86 
87  /**
88  * Getters.
89  */
90  unsigned int index() const {return index_;}
91  double length() const { return length_;}
92  double end() const { return end_;}
93  /**
94  * Performs rounding safe comparison time > other_time, i.e. time is strictly greater than given parameter
95  * other_time with precision relative to the magnitude of the numbers time step.
96  * TODO: introduce type TimeDouble with overloaded comparison operators, use it consistently in TimeMarks.
97  */
98  inline bool gt(double other_time) const
99  { return ! safe_compare(other_time, end());}
100 
101  /**
102  * Performs rounding safe comparison time >= other_time See @fn gt
103  */
104  inline bool ge(double other_time) const
105  { return safe_compare(end(), other_time); }
106 
107  /**
108  * Performs rounding safe comparison time < other_time. See @fn gt
109  */
110  inline bool lt(double other_time) const
111  { return ! safe_compare(end(), other_time); }
112 
113  /**
114  * Performs rounding safe comparison time <= other_time. See @fn gt
115  */
116  inline bool le(double other_time) const
117  { return safe_compare(other_time, end()); }
118 
119  /**
120  * Performs rounding safe comparison time (step) == other_time. See @fn gt
121  */
122  inline bool eq(double other_time) const
123  { return this->le(other_time) && this->ge(other_time); }
124 
125  inline bool contains(double other_time) const
126  { return this->ge(other_time) && this->lt(other_time + length_); }
127 
128  /**
129  * Returns true if two time steps are exactly the same.
130  */
131  bool operator==(const TimeStep & other)
132  { return (index_ == other.index_)
133  && (length_ == other.length_)
134  && (end_ == other.end_);
135  }
136 private:
137 
138  /* Returns true if t1-t0 > delta. Where delta is choosen
139  * related to the current time step and magnitude of t1, t0.
140  */
141  bool safe_compare(double t1, double t0) const;
142 
143  /// Index of the step is index if the end time. Zero time step is artificial.
144  unsigned int index_;
145  /// Length of the time step. Theoretically @p end minus end of the previous time step.
146  /// However may be slightly different due to rounding errors.
147  double length_;
148  /// End time point of the time step.
149  double end_;
150 };
151 
152 std::ostream& operator<<(std::ostream& out, const TimeStep& t_step);
153 
154 
155 
156 /**
157  * @brief
158  * Basic time management functionality for unsteady (and steady) solvers (class Equation).
159  *
160  * <h2> Common features and unsteady time governor (TG) </h2>
161  *
162  * This class provides algorithm for selecting next time step, and information about current time step frame.
163  * Step estimating is constrained by several bounds (permanent maximal and minimal time step, upper
164  * and lower constraint of time step). The permanent constraints are set in the constructor from the input
165  * record so that user can set the time step constraints for the whole simulation.
166  * Function set_permanent_constraint() should be used only in very specific cases and possibly right after
167  * the constructor before using other functions of TG.
168  *
169  * Choice of the very next time step can be constrained using functions set_upper_constraint()
170  * and set_lower_constraint().
171  * Lower and upper constraints are set equal to permanent ones in the constructor and can only
172  * become stricter. If one tries to set these constraints outside the interval of the previous constraints,
173  * nothing is changed and a specified value is returned. Upper and lower constraints are reset in function
174  * next_time() to the permanent constraints.
175  *
176  * The later one can be called multiple times with various constraint values and we use the minimum of them.
177  * Function next_time() choose the next time step in such a way that it meets actual constraints and
178  * a uniform discrete time grid with this step hits the nearest fixed time in lowest possible number of steps.
179  *
180  * The fixed times are time marks of TimeMarks object passed at construction time with particular mask.
181  *
182  * There is just one set of time marks for the whole problem. Therefore TimeMarks object is static and is shared umong
183  * all the equations and time governors. Each equation creates its own specific time mark type.
184  *
185  * Information provided by TG includes:
186  * - actual time, last time, end time
187  * - actual time step
188  * - number of the time level
189  * - end of interval with fixed time step
190  * - time comparison
191  * - static pointer to time marks
192  *
193  * <h2> Steady time governor</h2>
194  *
195  * Steady TG can be constructed by default constructor (initial time is zero) or by
196  * constructor with initial time as parameter. End time and time step are set to infinity.
197  * One can check if the time governor is steady by calling is_steady().
198  * Calling estimate_dt() will return infinity.
199  *
200  * Setting constraints have no consequences. Calling fix_dt_until_mark() will only return zero
201  * and will not do anything.
202  *
203  * The steady TG works in two states. At first the time is set to initial and time level
204  * is equal zero. To use steady TG properly one should call next_time() after the computation
205  * of steady problem is done. Current time is then set to infinity, time level is set to 1 and
206  * calling estimate_dt() will return zero.
207  *
208  * Note: For example class TransportNothing (which computes really nothing) uses also steady TG but
209  * it calls next_time() immediately after TG's construction. This means that the 'computation'of transport
210  * is done.
211  *
212  *
213  */
214 
216 {
217 public:
218 
219  DECLARE_INPUT_EXCEPTION(ExcTimeGovernorMessage, << EI_Message::val);
220  TYPEDEF_ERR_INFO( EI_Index, int);
221  TYPEDEF_ERR_INFO( EI_BackIndex, unsigned int);
222  TYPEDEF_ERR_INFO( EI_HistorySize, unsigned int);
223  DECLARE_EXCEPTION(ExcMissingTimeStep,
224  << "Time step index: " << EI_Index::val
225  << ", history index: " << EI_BackIndex::val
226  << " out of history of size: " << EI_HistorySize::val);
227 
228  static const Input::Type::Record & get_input_type();
229 
230  /**
231  * Getter for time marks.
232  */
233  static inline TimeMarks &marks()
234  {return time_marks_;}
235 
236  /**
237  * @brief Constructor for unsteady solvers.
238  *
239  * @param input accessor to input data
240  * @param fixed_time_mask TimeMark mask used to select fixed time marks from all the time marks.
241  * This value is bitwise added to the default one defined in TimeMarks::type_fixed_time().
242  *
243  */
244  TimeGovernor(const Input::Record &input,
245  TimeMark::Type fixed_time_mask = TimeMark::none_type);
246 
247  /**
248  * @brief Default constructor - steady time governor.
249  *
250  * We can have "zero step" steady problem (no computation, e.g. EquationNothing) and one step steady problem
251  * (e.g. steady water flow).
252  *
253  * Time is set to zero, time step and end time to infinity.
254  *
255  * First call of next_time() pushes the actual time to infinity.
256  *
257  * However, you have to use full constructor for the "steady problem" that has time-variable input data.
258  *
259  * Has a private pointer to static TimeMarks and can access them by marks().
260  */
261  explicit TimeGovernor(double init_time=0.0,
262  TimeMark::Type fixed_time_mask = TimeMark::none_type);
263 
264  /**
265  * The aim of this constuctor is simple way to make a time governor without Input interface.
266  *
267  * TODO: Partially tested as part of field test. Needs its own unit test.
268  */
269  TimeGovernor(double init_time, double dt);
270 
271  /**
272  * @brief Sets permanent constraints for time step.
273  *
274  * This function should not be normally used. These values are to be set in constructor
275  * from the input record or by default.
276  * @param min_dt is the minimal value allowed for time step
277  * @param max_dt is the maximal value allowed for time step
278  */
279  void set_permanent_constraint( double min_dt, double max_dt);
280 
281  /**
282  * @brief Sets upper constraint for the next time step estimating.
283  *
284  * This function can only make the constraint stricter. Upper constraint is reset to @p max_dt after the next_time() call.
285  * The return value mimics result of the comparison: current constraint compared to @param upper.
286  * @param message describes the origin of the constraint
287  * In particular the return values is:
288  * - -1: Current upper constraint is less then the @param upper. No change happen.
289  * - 0: Current constraint interval contains the @param upper. The upper constraint is set.
290  * - +1: Current lower constraint is greater then the @param upper. No change happen.
291  */
292  int set_upper_constraint(double upper, std::string message);
293 
294  /**
295  * @brief Sets lower constraint for the next time step estimating.
296  *
297  * This function can only make the constraint stricter. Lower constraint is reset to @p min_dt after the next_time() call.
298  * The return value mimics result of the comparison: current constraint compared to @param upper.
299  * In particular the return values is:
300  * - -1: Current upper constraint is less then the @param lower. No change happen.
301  * - 0: Current constraint interval contains the @param lower. The lower constraint is set.
302  * - +1: Current upper constraint is greater then the @param lower. No change happen.
303  */
304  /**
305  * @brief Sets lower constraint for the next time step estimating.
306  * @param lower is the lower constraint for time step
307  * @param message describes the origin of the constraint
308  * @return -1, 0 or 1 according to the success.
309  * @see set_upper_constrain().
310  */
311  int set_lower_constraint(double lower, std::string message);
312 
313  /**
314  * @brief Fixing time step until fixed time mark.
315  *
316  * Fix time step until first fixed time mark. When called inside an already fixed interval,
317  * it overwrites previous setting.
318  * @return actual end of fixed time step.
319  */
320  double fix_dt_until_mark();
321 
322  /**
323  * @brief Proceed to the next time according to current estimated time step.
324  *
325  * The timestep constraints are relaxed to the permanent constraints.
326  */
327  void next_time();
328 
329  /**
330  * @brief Force timestep reduction in particular in the case of failure of the non-linear solver.
331  *
332  * Calling this method also force immediate end of the fixed timestep interval.
333  * Returns true reduce factor used. It is larger then given factor if we hit the lower timestep constraint.
334  *
335  * TODO: How to keep constraints active for the last next_time call.
336  */
337  double reduce_timestep(double factor);
338 
339  /**
340  * Returns reference to required time step in the recent history.
341  * Without parameter the actual time step is returned.
342  * Use negative indices to get recent time steps: step(-1) the actual step, step(-2) the last one.
343  * Use positive index to get time step by its index: step(0) the first time step.
344  * However only limited number of last time steps is stored.
345  * If the time step is not accessible any more, we throw an exception ExcMissingTimeStep.
346  */
347  const TimeStep &step(int index=-1) const;
348 
349  /**
350  * Specific time mark of the equation owning the time governor.
351  */
353  { return eq_mark_type_;}
354 
355  /**
356  * Specific time mark of the fixed times of the equation owning the time governor.
357  */
359  { return eq_mark_type_ | marks().type_fixed_time(); }
360 
361  /**
362  * Add sequence of time marks starting from the initial time up to the end time with given @p step.
363  * Time marks type combines given mark_type (none by default) and native mark type of the time governor.
364  */
365  void add_time_marks_grid(double step, TimeMark::Type mark_type= TimeMark::none_type) const;
366 
367  /**
368  * Simpler interface to TimeMarks::is_current().
369  */
370  bool is_current(const TimeMark::Type &mask) const;
371 
372 
373  /**
374  * Simpler interface to TimeMarks::next().
375  */
376  inline TimeMarks::iterator next(const TimeMark::Type &mask) const
377  {return time_marks_.next(*this, mask);}
378 
379  /**
380  * Simpler interface to TimeMarks::last().
381  */
382  inline TimeMarks::iterator last(const TimeMark::Type &mask) const
383  {return time_marks_.last(*this, mask);}
384 
385  /**
386  * Getter for upper constrain.
387  */
388  inline double upper_constraint() const
389  {return upper_constraint_;}
390 
391  /**
392  * Returns lower constraint.
393  */
394  inline double lower_constraint() const
395  {return lower_constraint_;}
396 
397  /**
398  * End of interval with currently fixed time step. Can be changed by next call of method fix_dt_until_mark.
399  */
400  inline double end_of_fixed_dt() const
401  {return end_of_fixed_dt_interval_;}
402 
403  /**
404  * Getter for dt_changed. Returns whether the time step has been changed.
405  */
406  inline bool is_changed_dt() const
407  {return time_step_changed_;}
408 
409 
410  /**
411  * Initial time getter.
412  */
413  inline double init_time() const
414  {return this->init_time_;}
415 
416  /**
417  * End of actual time interval; i.e. where the solution is computed.
418  */
419  inline double t() const
420  {return step().end();}
421 
422  /**
423  * Previous time step.
424  */
425  inline double last_dt() const
426  {if (step().index() >0) return step(-2).length();
427  else return inf_time;
428  }
429 
430  /**
431  * Previous time.
432  */
433  inline double last_t() const
434  {if (step().index() >0) return step(-2).end();
435  else return step().end() - step().length();
436  }
437 
438 
439  /**
440  * Length of actual time interval; i.e. the actual time step.
441  */
442  inline double dt() const
443  {return step().length();}
444 
445  /**
446  * @brief Estimate choice of next time step according to actual setting of constraints.
447  *
448  * Precedence of constraints:
449  *
450  * -# meet next fixed time (always satisfied)
451  * -# permanent upper constraint (always satisfied)
452  * -# upper constraint (always satisfied)
453  * -# lower constraint (satisfied if not in conflict with 1.)
454  * -# permanent lower constraint (satisfied if 4.)
455  * -# else writes the difference between lower constraint and estimated time step
456  * -# If there are more then one step to the next fixed time, try to
457  * use the last time step if it is nearly the same.
458  */
459  double estimate_dt() const;
460 
461  /**
462  * Estimate next time.
463  */
464  inline double estimate_time() const
465  {return t()+estimate_dt();}
466 
467  /// End time.
468  inline double end_time() const
469  { return end_time_; }
470 
471  /// Returns true if the actual time is greater than or equal to the end time.
472  inline bool is_end() const
473  { return (this->step().ge(end_time_) || t() == inf_time); }
474 
475  /// Returns true if the time governor is used for steady problem.
476  inline bool is_steady() const
477  { return steady_; }
478 
479 
480 
481  /**
482  * Returns the time level.
483  */
484  inline int tlevel() const
485  {return step().index();}
486 
487  /**
488  * Prints output of TimeGovernor.
489  * @param name is the name of time governor that you want to show up in output (just for your convenience)
490  *
491  */
492  void view(const char *name="") const;
493 
494  /// Infinity time used for steady case.
495  static const double inf_time;
496 
497  /**
498  * Rounding precision for computing time_step.
499  * Used as technical lower bound for the time step.
500  */
501  static const double time_step_precision;
502 
503 private:
504 
505 
506  /**
507  * \brief Common part of the constructors. Set most important parameters, check they are valid and set default values to other.
508  *
509  * Set main parameters to given values.
510  * Check they are correct.
511  * Set soft and permanent constrains to the same, the least restricting values.
512  * Set time marks for the start time and end time (if finite).
513  */
514  void init_common(double init_time, double end_time, TimeMark::Type type);
515 
516  /**
517  * Size of the time step buffer, i.e. recent_time_steps_.
518  */
519  static const unsigned int size_of_recent_steps_ = 3;
520 
521  /// Circular buffer of recent time steps. Implicit size is 3.
522  boost::circular_buffer<TimeStep> recent_steps_;
523  /// Initial time.
524  double init_time_;
525  /// End of interval if fixed time step.
527  /// End time of the simulation.
528  double end_time_;
529 
530  /// Next fixed time step.
532  /// Flag that is set when the fixed step is set (lasts only one time step).
534  /// Flag is set if the time step has been changed (lasts only one time step).
536 
537  /// Description of the upper constraint.
539  /// Description of the upper constraint.
541  /// Upper constraint for the choice of the next time step.
543  /// Lower constraint for the choice of the next time step.
545  /// Permanent upper limit for the time step.
547  /// Permanent lower limit for the time step.
549 
550  /// Upper constraint used for choice of current time.
552  /// Lower constraint used for choice of current time.
554 
555  /**
556  * When the next time is chosen we need only the lowest fix time. Therefore we use
557  * minimum priority queue of doubles based on the vector container.
558  * This is one global set of time marks for the whole problem and is shared among all equations.
559  * Therefore this object is static constant pointer.
560  */
562 
563  /// TimeMark type of the equation.
565 
566  /// True if the time governor is used for steady problem.
567  bool steady_;
568 
569  friend TimeMarks;
570 };
571 
572 /**
573  * \brief Stream output operator for TimeGovernor.
574  *
575  * Currently for debugging purposes.
576  * In the future it should be customized for use in combination with
577  * streams for various log targets.
578  *
579  */
580 std::ostream& operator<<(std::ostream& out, const TimeGovernor& tg);
581 
582 
583 
584 #endif /* TIME_HH_ */
bool operator==(const TimeStep &other)
unsigned long int Type
Definition: time_marks.hh:51
double init_time_
Initial time.
double lower_constraint_
Lower constraint for the choice of the next time step.
Iterator over TimeMark objects in TimeMarks object (database of TimeMark objects).
Definition: time_marks.hh:302
double end_time() const
End time.
double estimate_time() const
bool is_time_step_fixed_
Flag that is set when the fixed step is set (lasts only one time step).
boost::circular_buffer< TimeStep > recent_steps_
Circular buffer of recent time steps. Implicit size is 3.
int tlevel() const
static TimeMarks time_marks_
bool lt(double other_time) const
TYPEDEF_ERR_INFO(EI_KeyName, const string)
double upper_constraint() const
double end_time_
End time of the simulation.
bool contains(double other_time) const
bool is_end() const
Returns true if the actual time is greater than or equal to the end time.
TimeMarks::iterator last(const TimeMark::Type &mask) const
TimeMarks::iterator next(const TimeMark::Type &mask) const
double end_of_fixed_dt() const
double t() const
Basic time management functionality for unsteady (and steady) solvers (class Equation).
static const Type none_type
Mark Type with all bits unset.
Definition: time_marks.hh:56
static TimeMarks & marks()
bool time_step_changed_
Flag is set if the time step has been changed (lasts only one time step).
double last_t() const
bool le(double other_time) const
double upper_constraint_
Upper constraint for the choice of the next time step.
double init_time() const
TimeMark::Type eq_mark_type_
TimeMark type of the equation.
Global macros to enhance readability and debugging, general constants.
bool ge(double other_time) const
static const double time_step_precision
TimeMark::Type equation_fixed_mark_type() const
Accessor to the data with type Type::Record.
Definition: accessors.hh:277
TimeMark::Type equation_mark_type() const
bool is_changed_dt() const
double length() const
double last_lower_constraint_
Lower constraint used for choice of current time.
double lower_constraint() const
unsigned int index_
Index of the step is index if the end time. Zero time step is artificial.
double end() const
This class is a collection of time marks to manage various events occurring during simulation time...
Definition: time_marks.hh:163
double end_of_fixed_dt_interval_
End of interval if fixed time step.
bool steady_
True if the time governor is used for steady problem.
bool is_steady() const
Returns true if the time governor is used for steady problem.
double max_time_step_
Permanent upper limit for the time step.
double dt() const
std::string upper_constraint_message_
Description of the upper constraint.
bool gt(double other_time) const
DECLARE_EXCEPTION(ExcWrongDefaultJSON,<< "Consistency Error: Not valid JSON of Default value "<< EI_DefaultStr::qval<< " of type "<< EI_TypeName::qval<< ";\n"<< "During declaration of the key: "<< EI_KeyName::qval)
std::ostream & operator<<(std::ostream &stream, const TypeBase &type)
For convenience we provide also redirection operator for output documentation of Input:Type classes...
Definition: type_base.cc:169
unsigned int index() const
Record type proxy class.
Definition: type_record.hh:171
double length_
double fixed_time_step_
Next fixed time step.
DECLARE_INPUT_EXCEPTION(ExcInputMessage,<< EI_Message::val)
Simple input exception that accepts just string message.
double last_upper_constraint_
Upper constraint used for choice of current time.
double last_dt() const
static const double inf_time
Infinity time used for steady case.
Representation of one time step..
double end_
End time point of the time step.
std::string lower_constraint_message_
Description of the upper constraint.
bool eq(double other_time) const
double min_time_step_
Permanent lower limit for the time step.