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