Flow123d  release_1.8.2-1603-g0109a2b
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  * Returns true if two time steps are exactly the same.
121  */
122  bool operator==(const TimeStep & other)
123  { return (index_ == other.index_)
124  && (length_ == other.length_)
125  && (end_ == other.end_);
126  }
127 private:
128 
129  /* Returns true if t1-t0 > delta. Where delta is choosen
130  * related to the current time step and magnitude of t1, t0.
131  */
132  bool safe_compare(double t1, double t0) const;
133 
134  /// Index of the step is index if the end time. Zero time step is artificial.
135  unsigned int index_;
136  /// Length of the time step. Theoretically @p end minus end of the previous time step.
137  /// However may be slightly different due to rounding errors.
138  double length_;
139  /// End time point of the time step.
140  double end_;
141 };
142 
143 
144 
145 /**
146  * @brief
147  * Basic time management functionality for unsteady (and steady) solvers (class Equation).
148  *
149  * <h2> Common features and unsteady time governor (TG) </h2>
150  *
151  * This class provides algorithm for selecting next time step, and information about current time step frame.
152  * Step estimating is constrained by several bounds (permanent maximal and minimal time step, upper
153  * and lower constraint of time step). The permanent constraints are set in the constructor from the input
154  * record so that user can set the time step constraints for the whole simulation.
155  * Function set_permanent_constraint() should be used only in very specific cases and possibly right after
156  * the constructor before using other functions of TG.
157  *
158  * Choice of the very next time step can be constrained using functions set_upper_constraint()
159  * and set_lower_constraint().
160  * Lower and upper constraints are set equal to permanent ones in the constructor and can only
161  * become stricter. If one tries to set these constraints outside the interval of the previous constraints,
162  * nothing is changed and a specified value is returned. Upper and lower constraints are reset in function
163  * next_time() to the permanent constraints.
164  *
165  * The later one can be called multiple times with various constraint values and we use the minimum of them.
166  * Function next_time() choose the next time step in such a way that it meets actual constraints and
167  * a uniform discrete time grid with this step hits the nearest fixed time in lowest possible number of steps.
168  *
169  * The fixed times are time marks of TimeMarks object passed at construction time with particular mask.
170  *
171  * There is just one set of time marks for the whole problem. Therefore TimeMarks object is static and is shared umong
172  * all the equations and time governors. Each equation creates its own specific time mark type.
173  *
174  * Information provided by TG includes:
175  * - actual time, last time, end time
176  * - actual time step
177  * - number of the time level
178  * - end of interval with fixed time step
179  * - time comparison
180  * - static pointer to time marks
181  *
182  * <h2> Steady time governor</h2>
183  *
184  * Steady TG can be constructed by default constructor (initial time is zero) or by
185  * constructor with initial time as parameter. End time and time step are set to infinity.
186  * One can check if the time governor is steady by calling is_steady().
187  * Calling estimate_dt() will return infinity.
188  *
189  * Setting constraints have no consequences. Calling fix_dt_until_mark() will only return zero
190  * and will not do anything.
191  *
192  * The steady TG works in two states. At first the time is set to initial and time level
193  * is equal zero. To use steady TG properly one should call next_time() after the computation
194  * of steady problem is done. Current time is then set to infinity, time level is set to 1 and
195  * calling estimate_dt() will return zero.
196  *
197  * Note: For example class TransportNothing (which computes really nothing) uses also steady TG but
198  * it calls next_time() immediately after TG's construction. This means that the 'computation'of transport
199  * is done.
200  *
201  *
202  */
203 
205 {
206 public:
207 
208  DECLARE_INPUT_EXCEPTION(ExcTimeGovernorMessage, << EI_Message::val);
209  TYPEDEF_ERR_INFO( EI_Index, int);
210  TYPEDEF_ERR_INFO( EI_BackIndex, unsigned int);
211  TYPEDEF_ERR_INFO( EI_HistorySize, unsigned int);
212  DECLARE_EXCEPTION(ExcMissingTimeStep,
213  << "Time step index: " << EI_Index::val
214  << ", history index: " << EI_BackIndex::val
215  << " out of history of size: " << EI_HistorySize::val);
216 
217  static const Input::Type::Record & get_input_type();
218 
219  /**
220  * Getter for time marks.
221  */
222  static inline TimeMarks &marks()
223  {return time_marks_;}
224 
225  /**
226  * @brief Constructor for unsteady solvers.
227  *
228  * @param input accessor to input data
229  * @param fixed_time_mask TimeMark mask used to select fixed time marks from all the time marks.
230  * This value is bitwise added to the default one defined in TimeMarks::type_fixed_time().
231  *
232  */
233  TimeGovernor(const Input::Record &input,
234  TimeMark::Type fixed_time_mask = TimeMark::none_type);
235 
236  /**
237  * @brief Default constructor - steady time governor.
238  *
239  * We can have "zero step" steady problem (no computation, e.g. EquationNothing) and one step steady problem
240  * (e.g. steady water flow).
241  *
242  * Time is set to zero, time step and end time to infinity.
243  *
244  * First call of next_time() pushes the actual time to infinity.
245  *
246  * However, you have to use full constructor for the "steady problem" that has time-variable input data.
247  *
248  * Has a private pointer to static TimeMarks and can access them by marks().
249  */
250  explicit TimeGovernor(double init_time=0.0,
251  TimeMark::Type fixed_time_mask = TimeMark::none_type);
252 
253  /**
254  * The aim of this constuctor is simple way to make a time governor without Input interface.
255  *
256  * TODO: Partially tested as part of field test. Needs its own unit test.
257  */
258  TimeGovernor(double init_time, double dt);
259 
260  /**
261  * @brief Sets permanent constraints for time step.
262  *
263  * This function should not be normally used. These values are to be set in constructor
264  * from the input record or by default.
265  * @param min_dt is the minimal value allowed for time step
266  * @param max_dt is the maximal value allowed for time step
267  */
268  void set_permanent_constraint( double min_dt, double max_dt);
269 
270  /**
271  * @brief Sets upper constraint for the next time step estimating.
272  *
273  * This function can only make the constraint stricter. Upper constraint is reset to @p max_dt after the next_time() call.
274  * The return value mimics result of the comparison: current constraint compared to @param upper.
275  * @param message describes the origin of the constraint
276  * In particular the return values is:
277  * - -1: Current upper constraint is less then the @param upper. No change happen.
278  * - 0: Current constraint interval contains the @param upper. The upper constraint is set.
279  * - +1: Current lower constraint is greater then the @param upper. No change happen.
280  */
281  int set_upper_constraint(double upper, std::string message);
282 
283  /**
284  * @brief Sets lower constraint for the next time step estimating.
285  *
286  * This function can only make the constraint stricter. Lower constraint is reset to @p min_dt after the next_time() call.
287  * The return value mimics result of the comparison: current constraint compared to @param upper.
288  * In particular the return values is:
289  * - -1: Current upper constraint is less then the @param lower. No change happen.
290  * - 0: Current constraint interval contains the @param lower. The lower constraint is set.
291  * - +1: Current upper constraint is greater then the @param lower. No change happen.
292  */
293  /**
294  * @brief Sets lower constraint for the next time step estimating.
295  * @param lower is the lower constraint for time step
296  * @param message describes the origin of the constraint
297  * @return -1, 0 or 1 according to the success.
298  * @see set_upper_constrain().
299  */
300  int set_lower_constraint(double lower, std::string message);
301 
302  /**
303  * @brief Fixing time step until fixed time mark.
304  *
305  * Fix time step until first fixed time mark. When called inside an already fixed interval,
306  * it overwrites previous setting.
307  * @return actual end of fixed time step.
308  */
309  double fix_dt_until_mark();
310 
311  /**
312  * @brief Proceed to the next time according to current estimated time step.
313  *
314  * The timestep constraints are relaxed to the permanent constraints.
315  */
316  void next_time();
317 
318  /**
319  * @brief Force timestep reduction in particular in the case of failure of the non-linear solver.
320  *
321  * Calling this method also force immediate end of the fixed timestep interval.
322  * Returns true reduce factor used. It is larger then given factor if we hit the lower timestep constraint.
323  *
324  * TODO: How to keep constraints active for the last next_time call.
325  */
326  double reduce_timestep(double factor);
327 
328  /**
329  * Returns reference to required time step in the recent history.
330  * Without parameter the actual time step is returned.
331  * Use negative indices to get recent time steps: step(-1) the actual step, step(-2) the last one.
332  * Use positive index to get time step by its index: step(0) the first time step.
333  * However only limited number of last time steps is stored.
334  * If the time step is not accessible any more, we throw an exception ExcMissingTimeStep.
335  */
336  const TimeStep &step(int index=-1) const;
337 
338  /**
339  * Specific time mark of the equation owning the time governor.
340  */
342  { return eq_mark_type_;}
343 
344  /**
345  * Specific time mark of the fixed times of the equation owning the time governor.
346  */
348  { return eq_mark_type_ | marks().type_fixed_time(); }
349 
350  /**
351  * Add sequence of time marks starting from the initial time up to the end time with given @p step.
352  * Time marks type combines given mark_type (none by default) and native mark type of the time governor.
353  */
354  void add_time_marks_grid(double step, TimeMark::Type mark_type= TimeMark::none_type) const;
355 
356  /**
357  * Simpler interface to TimeMarks::is_current().
358  */
359  inline bool is_current(const TimeMark::Type &mask) const
360  {return time_marks_.is_current(*this, equation_mark_type() | mask); }
361 
362  /**
363  * Simpler interface to TimeMarks::next().
364  */
365  inline TimeMarks::iterator next(const TimeMark::Type &mask) const
366  {return time_marks_.next(*this, mask);}
367 
368  /**
369  * Simpler interface to TimeMarks::last().
370  */
371  inline TimeMarks::iterator last(const TimeMark::Type &mask) const
372  {return time_marks_.last(*this, mask);}
373 
374  /**
375  * Getter for upper constrain.
376  */
377  inline double upper_constraint() const
378  {return upper_constraint_;}
379 
380  /**
381  * Returns lower constraint.
382  */
383  inline double lower_constraint() const
384  {return lower_constraint_;}
385 
386  /**
387  * End of interval with currently fixed time step. Can be changed by next call of method fix_dt_until_mark.
388  */
389  inline double end_of_fixed_dt() const
390  {return end_of_fixed_dt_interval_;}
391 
392  /**
393  * Getter for dt_changed. Returns whether the time step has been changed.
394  */
395  inline bool is_changed_dt() const
396  {return time_step_changed_;}
397 
398 
399  /**
400  * Initial time getter.
401  */
402  inline double init_time() const
403  {return this->init_time_;}
404 
405  /**
406  * End of actual time interval; i.e. where the solution is computed.
407  */
408  inline double t() const
409  {return step().end();}
410 
411  /**
412  * Previous time step.
413  */
414  inline double last_dt() const
415  {if (step().index() >0) return step(-2).length();
416  else return inf_time;
417  }
418 
419  /**
420  * Previous time.
421  */
422  inline double last_t() const
423  {if (step().index() >0) return step(-2).end();
424  else return step().end() - step().length();
425  }
426 
427 
428  /**
429  * Length of actual time interval; i.e. the actual time step.
430  */
431  inline double dt() const
432  {return step().length();}
433 
434  /**
435  * @brief Estimate choice of next time step according to actual setting of constraints.
436  *
437  * Precedence of constraints:
438  *
439  * -# meet next fixed time (always satisfied)
440  * -# permanent upper constraint (always satisfied)
441  * -# upper constraint (always satisfied)
442  * -# lower constraint (satisfied if not in conflict with 1.)
443  * -# permanent lower constraint (satisfied if 4.)
444  * -# else writes the difference between lower constraint and estimated time step
445  * -# If there are more then one step to the next fixed time, try to
446  * use the last time step if it is nearly the same.
447  */
448  double estimate_dt() const;
449 
450  /**
451  * Estimate next time.
452  */
453  inline double estimate_time() const
454  {return t()+estimate_dt();}
455 
456  /// End time.
457  inline double end_time() const
458  { return end_time_; }
459 
460  /// Returns true if the actual time is greater than or equal to the end time.
461  inline bool is_end() const
462  { return (this->step().ge(end_time_) || t() == inf_time); }
463 
464  /// Returns true if the time governor is used for steady problem.
465  inline bool is_steady() const
466  { return steady_; }
467 
468 
469 
470  /**
471  * Returns the time level.
472  */
473  inline int tlevel() const
474  {return step().index();}
475 
476  /**
477  * Prints output of TimeGovernor.
478  * @param name is the name of time governor that you want to show up in output (just for your convenience)
479  *
480  */
481  void view(const char *name="") const;
482 
483  /// Infinity time used for steady case.
484  static const double inf_time;
485 
486 private:
487 
488 
489  /**
490  * \brief Common part of the constructors. Set most important parameters, check they are valid and set default values to other.
491  *
492  * Set main parameters to given values.
493  * Check they are correct.
494  * Set soft and permanent constrains to the same, the least restricting values.
495  * Set time marks for the start time and end time (if finite).
496  */
497  void init_common(double init_time, double end_time, TimeMark::Type type);
498 
499  /**
500  * Rounding precision for computing time_step.
501  * Used as technical lower bound for the time step.
502  */
503  static const double time_step_precision;
504 
505  /**
506  * Size of the time step buffer, i.e. recent_time_steps_.
507  */
508  static const unsigned int size_of_recent_steps_ = 3;
509 
510  /// Circular buffer of recent time steps. Implicit size is 3.
511  boost::circular_buffer<TimeStep> recent_steps_;
512  /// Initial time.
513  double init_time_;
514  /// End of interval if fixed time step.
516  /// End time of the simulation.
517  double end_time_;
518 
519  /// Next fixed time step.
521  /// Flag that is set when the fixed step is set (lasts only one time step).
523  /// Flag is set if the time step has been changed (lasts only one time step).
525 
526  /// Description of the upper constraint.
528  /// Description of the upper constraint.
530  /// Upper constraint for the choice of the next time step.
532  /// Lower constraint for the choice of the next time step.
534  /// Permanent upper limit for the time step.
536  /// Permanent lower limit for the time step.
538 
539  /// Upper constraint used for choice of current time.
541  /// Lower constraint used for choice of current time.
543 
544  /**
545  * When the next time is chosen we need only the lowest fix time. Therefore we use
546  * minimum priority queue of doubles based on the vector container.
547  * This is one global set of time marks for the whole problem and is shared among all equations.
548  * Therefore this object is static constant pointer.
549  */
551 
552  /// TimeMark type of the equation.
554 
555  /// True if the time governor is used for steady problem.
556  bool steady_;
557 
558  friend TimeMarks;
559 };
560 
561 /**
562  * \brief Stream output operator for TimeGovernor.
563  *
564  * Currently for debugging purposes.
565  * In the future it should be customized for use in combination with
566  * streams for various log targets.
567  *
568  */
569 ostream& operator<<(ostream& out, const TimeGovernor& tg);
570 
571 
572 #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:281
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 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
bool is_current(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:157
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(ExcWrongDefault,<< "Default value "<< EI_DefaultStr::qval<< " do not match 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.
double min_time_step_
Permanent lower limit for the time step.