Flow123d  jenkins-Flow123d-windows32-release-multijob-51
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 
37 #include "system/global_defs.h"
38 #include "system/system.hh"
39 #include "time_marks.hh"
40 #include "input/accessors.hh"
41 
42 namespace Input {
43  class Record;
44  namespace Type {
45  class Record;
46  }
47 }
48 
49 /**
50  * @brief
51  * Basic time management functionality for unsteady (and steady) solvers (class Equation).
52  *
53  * <h2> Common features and unsteady time governor (TG) </h2>
54  *
55  * This class provides algorithm for selecting next time step, and information about current time step frame.
56  * Step estimating is constrained by several bounds (permanent maximal and minimal time step, upper
57  * and lower constraint of time step). The permanent constraints are set in the constructor from the input
58  * record so that user can set the time step constraints for the whole model.
59  * Function set_permanent_constraint() should be used only in very specific cases and possibly right after
60  * the constructor before using other functions of TG.
61  *
62  * Choice of the very next time step can be constrained using functions set_upper_constraint() and set_lower_constraint().
63  * Lower and upper constraints are set equal to permanent ones in the constructor and can only
64  * become stricter. If one tries to set these constraints outside the interval of the previous constraints,
65  * nothing is changed and a specified value is returned. Upper and lower constraints are reset in function
66  * next_time() to the permanent constraints.
67  *
68  *
69  * The later one can be called multiple times with various
70  * constraint values and we use the minimum of them. Function next_time() choose the next time step in such a way that it meets actual constraints and
71  * a uniform discrete time grid with this step hits the nearest fixed time in lowest possible number of steps.
72  *
73  * The fixed times are time marks of TimeMarks object passed at construction time with particular mask.
74  *
75  * There is just one set of time marks for the whole problem. Therefore TimeMarks object is static and is shared umong
76  * all the equations and time governors. Each equation creates its own specific time mark type.
77  *
78  * Solution of the next time step proceeds in following steps:
79  * -# Estimate next time step and set constraints (this can be usefull in hc_seq_explicit for estimating next transport time)
80  * -# Fix next time step up to the next time mark (this is necessary for ConvectionTransport)
81  * -# Proceed to the next time when solution is available. (this can replace solved flag in equation classes)
82  *
83  * Information provided by TG includes:
84  * - actual time, last time, end time
85  * - actual time step
86  * - number of the time level
87  * - end of interval with fixed time step
88  * - time comparison
89  * - static pointer to time marks
90  *
91  * <h2> Steady time governor</h2>
92  *
93  * Steady TG can be constructed by default constructor (initial time is zero) or by
94  * constructor with initial time as parameter. End time and time step are set to infinity.
95  * One can check if the time governor is steady by calling is_steady().
96  * Calling estimate_dt() will return infinity.
97  *
98  * Setting constraints have no consequences. Calling fix_dt_until_mark() will only return zero
99  * and will not do anything.
100  *
101  * The steady TG works in two states. At first the time is set to initial and time level
102  * is equal zero. To use steady TG properly one should call next_time() after the computation
103  * of steady problem is done. Current time is then set to infinity, time level is set to 1 and
104  * calling estimate_dt() will return zero.
105  *
106  * Note: For example class TransportNothing (which computes really nothing) uses also steady TG but
107  * it calls next_time() immediately after TG's construction. This means that the 'computation'of transport
108  * is done.
109  *
110  *
111  * TODO:
112  * - still we have problems with time comparisons
113  * 1) TimeMarks can merge marks only with fixed precision, since they are shared by several equations with possibly different timesteps.
114  * 2) On the other hand comparing of times by time governor can be done relatively to the current time step.
115  *
116  *
117  */
118 
120 {
121 public:
122 
123  DECLARE_INPUT_EXCEPTION(ExcTimeGovernorMessage, << EI_Message::val);
124 
126 
127  /**
128  * Getter for time marks.
129  */
130  static inline TimeMarks &marks()
131  {return time_marks_;}
132 
133 
134  /**
135  * @brief Constructor for unsteady solvers.
136  *
137  * @param input accessor to input data
138  * @param fixed_time_mask TimeMark mask used to select fixed time marks from all the time marks.
139  * This value is bitwise added to the default one defined in TimeMarks::type_fixed_time().
140  *
141  */
142  TimeGovernor(const Input::Record &input,
143  TimeMark::Type fixed_time_mask = TimeMark::none_type);
144 
145 
146  /**
147  * @brief Default constructor - steady time governor.
148  *
149  * We can have "zero step" steady problem (no computation, e.g. EquationNothing) and one step steady problem
150  * (e.g. steady water flow).
151  *
152  * Time is set to zero, time step and end time to infinity.
153  *
154  * First call of next_time() pushes the actual time to infinity.
155  *
156  * However, you have to use full constructor for the "steady problem" that has time-variable input data.
157  *
158  * Has a private pointer to static TimeMarks and can access them by marks().
159  */
160  explicit TimeGovernor(double init_time=0.0,
161  TimeMark::Type fixed_time_mask = TimeMark::none_type);
162 
163  /**
164  * The aim of this constuctor is simple way to make a time governor without Input interface.
165  *
166  * TODO: Partially tested as part of field test. Needs its own unit test.
167  */
168  TimeGovernor(double init_time, double dt);
169 
170 
171 
172 
173  /**
174  * @brief Sets permanent constraints for time step.
175  *
176  * This function should not be normally used. These values are to be set in constructor
177  * from the input record or by default.
178  * @param min_dt is the minimal value allowed for time step
179  * @param max_dt is the maximal value allowed for time step
180  */
181  void set_permanent_constraint( double min_dt, double max_dt);
182 
183 
184  /**
185  * @brief Sets upper constraint for the next time step estimating.
186  *
187  * This function can only make the constraint stricter. Upper constraint is reset to @p max_dt in next_time().
188  * @param upper is the upper constraint for time step
189  * @return -1, 0 or 1 according to the success
190  *
191  * - -1: constraint is higher than the permanent upper constraint @p max_dt. Setting failed, no change happened.
192  * - 0: constraint is in the interval of permanent constraints @p min_dt and @p max_dt. The upper constraint has been set.
193  * - 1: constraint is lower than permanent lower constraint @p min_dt. Setting failed, no change happened.
194  */
195  int set_upper_constraint(double upper);
196 
197  /**
198  * @brief Sets lower constraint for the next time step estimating.
199  * @return -1, 0 or 1 according to the success.
200  * @see set_upper_constrain().
201  */
202  int set_lower_constraint(double lower);
203 
204  /**
205  * @brief Fixing time step until fixed time mark.
206  *
207  * Fix time step until first fixed time mark. When called inside an already fixed interval,
208  * it overwrites previous setting.
209  * @return actual end of fixed time step.
210  */
211  inline double fix_dt_until_mark() {
212  if (steady_) return 0.0;
213  end_of_fixed_dt_interval_=-inf_time; // release previous fixed interval
215  is_time_step_fixed_ = true; //flag means fixed step has been set since now
217  }
218 
219  /**
220  * @brief Proceed to the next time according to current estimated time step.
221  */
222  void next_time();
223 
224 
225  /**
226  * Specific time mark of the equation owning the time governor.
227  */
229  { return eq_mark_type_;}
230 
231  /**
232  * Specific time mark of the fixed times of the equation owning the time governor.
233  */
235  { return eq_mark_type_ | marks().type_fixed_time(); }
236 
237  /**
238  * Add sequence of time marks starting from the initial time up to the end time with given @p step.
239  * Time marks type combines given mark_type (none by default) and native mark type of the time governor.
240  */
241  void add_time_marks_grid(double step, TimeMark::Type mark_type= TimeMark::none_type) const;
242 
243  /**
244  * Simpler interface to TimeMarks::is_current().
245  */
246  inline bool is_current(const TimeMark::Type &mask) const
247  {return time_marks_.is_current(*this, equation_mark_type() | mask); }
248 
249  /**
250  * Simpler interface to TimeMarks::next().
251  */
252  inline TimeMarks::iterator next(const TimeMark::Type &mask) const
253  {return time_marks_.next(*this, mask);}
254 
255  /**
256  * Simpler interface to TimeMarks::last().
257  */
258  inline TimeMarks::iterator last(const TimeMark::Type &mask) const
259  {return time_marks_.last(*this, mask);}
260 
261  /**
262  * Getter for upper constrain.
263  */
264  inline double upper_constraint() const
265  {return upper_constraint_;}
266 
267  /**
268  * Returns lower constraint.
269  */
270  inline double lower_constraint() const
271  {return lower_constraint_;}
272 
273  /**
274  * End of interval with currently fixed time step. Can be changed by next call of method fix_dt_until_mark.
275  */
276  inline double end_of_fixed_dt() const
277  {return end_of_fixed_dt_interval_;}
278 
279  /**
280  * Getter for dt_changed. Returns whether the time step has been changed.
281  */
282  inline bool is_changed_dt() const
283  {return time_step_changed_;}
284 
285 
286  /**
287  * End of actual time interval; i.e. where the solution is computed.
288  */
289  inline double t() const
290  {return time_;}
291 
292  /**
293  * Previous time step.
294  */
295  inline double last_dt() const
296  {return last_time_step_;}
297 
298  /**
299  * Previous time.
300  */
301  inline double last_t() const
302  { return last_time_; }
303 
304 
305  /**
306  * Length of actual time interval; i.e. the actual time step.
307  */
308  inline double dt() const
309  {return time_step_;}
310 
311  /**
312  * @brief Estimate choice of next time step according to actual setting of constraints.
313  *
314  * Precedence of constraints:
315  *
316  * -# meet next fixed time (always satisfied)
317  * -# permanent upper constraint (always satisfied)
318  * -# upper constraint (always satisfied)
319  * -# lower constraint (satisfied if not in conflict with 1.)
320  * -# permanent lower constraint (satisfied if 4.)
321  * -# else writes the difference between lower constraint and estimated time step
322  */
323  double estimate_dt() const;
324 
325  /**
326  * Estimate next time.
327  */
328  inline double estimate_time() const
329  {return time_+estimate_dt();}
330 
331  /// End time.
332  inline double end_time() const
333  { return end_time_; }
334 
335  /// Returns true if the actual time is greater than or equal to the end time.
336  inline bool is_end() const
337  { return (this->ge(end_time_) || time_ == inf_time); }
338 
339  /// Returns true if the time governor is used for steady problem.
340  inline bool is_steady() const
341  { return steady_; }
342 
343  /**
344  * Performs rounding safe comparison time > other_time, i.e. time is strictly greater than given parameter
345  * other_time with precision relative to the magnitude of the numbers time step.
346  * TODO: introduce type TimeDouble with overloaded comparison operators, use it consistently in TimeMarks.
347  */
348  inline bool gt(double other_time) const
349  {
350  return ! (time_ <= other_time
351  + 16*numeric_limits<double>::epsilon()*max(abs(time_),abs(other_time)) );
352  }
353 
354  /**
355  * Performs rounding safe comparison time >= other_time See @fn gt
356  */
357  inline bool ge(double other_time) const
358  {
359  return time_ >= other_time
360  - 16*numeric_limits<double>::epsilon()*max(abs(time_),abs(other_time));
361  }
362 
363  /**
364  * Performs rounding safe comparison time < other_time. See @fn gt
365  */
366  inline bool lt(double other_time) const
367  {
368  double b=other_time
369  - 16*numeric_limits<double>::epsilon()*max(abs(time_),abs(other_time));
370  return ! (time_ >= b);
371  }
372 
373  /**
374  * Performs rounding safe comparison time <= other_time. See @fn gt
375  */
376  inline bool le(double other_time) const
377  {
378  return time_ <= other_time
379  + 16*numeric_limits<double>::epsilon()*max(abs(time_),abs(other_time));
380  }
381 
382  /**
383  * Returns the time level.
384  */
385  inline int tlevel() const
386  {return time_level_;}
387 
388  /**
389  * Prints output of TimeGovernor.
390  * @param name is the name of time governor that you want to show up in output (just for your convenience)
391  *
392  */
393  void view(const char *name="") const;
394 
395  /// Infinity time used for steady case.
396  static const double inf_time;
397 
398 private:
399 
400  /**
401  * \brief Common part of the constructors. Set most important parameters, check they are valid and set default values to other.
402  *
403  * Set main parameters to given values.
404  * Check they are correct.
405  * Distinguish fixed time step and variable time step case.
406  * Set soft and permanent constrains to the same, the least restricting values.
407  * Set time marks for the start time and end time (if finite).
408  */
409  void init_common(double dt, double init_time, double end_time, TimeMark::Type type);
410 
411 
412  /// Technical bound for the time step given by finite precision.
413  static const double time_step_lower_bound;
414  /// Rounding precision for computing number of steps. Used in estimate_dt().
415  static const double round_n_steps_precision;
416 
417  /// Number of time_next calls, i.e. total number of performed time steps.
419 
420  /// Initial time.
421  double init_time_;
422  /// End of actual time interval; i.e. where the solution is computed.
423  double time_;
424  /// Beginning of the actual time interval; i.e. the time of last computed solution.
425  double last_time_;
426  /// End of interval if fixed time step.
428  /// End time of the simulation.
429  double end_time_;
430 
431  /// Length of actual time interval; i.e. the actual time step.
432  double time_step_;
433  /// Time step just before last_time.
435  /// Next fixed time step.
437  /// Flag that is set when the fixed step is set (lasts only one time step).
439  /// Flag is set if the time step has been changed (lasts only one time step).
441 
442 
443  /// Upper constraint for the choice of the next time step.
445  /// Lower constraint for the choice of the next time step.
447  /// Permanent upper limit for the time step.
449  /// Permanent lower limit for the time step.
451 
452  /**
453  * When the next time is chosen we need only the lowest fix time. Therefore we use
454  * minimum priority queue of doubles based on the vector container.
455  * This is one global set of time marks for the whole problem and is shared among all equations.
456  * Therefore this object is static constant pointer.
457  */
459 
460  /// TimeMark type of the equation.
462 
463  /// True if the time governor is used for steady problem.
464  bool steady_;
465 
466 };
467 
468 /**
469  * \brief Redirection operator for TimeGovernor.
470  *
471  * Currently for debugging purposes.
472  * In the future it should be customized for use in combination with
473  * streams for various log targets.
474  *
475  */
476 ostream& operator<<(ostream& out, const TimeGovernor& tg);
477 
478 
479 #endif /* TIME_HH_ */
TimeMark::Type type_fixed_time()
Definition: time_marks.hh:187
unsigned long int Type
Definition: time_marks.hh:59
void init_common(double dt, 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 ...
static const double round_n_steps_precision
Rounding precision for computing number of steps. Used in estimate_dt().
double init_time_
Initial time.
TimeMarks::iterator next(const TimeGovernor &tg, const TimeMark::Type &mask) const
Definition: time_marks.cc:116
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:283
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).
int time_level_
Number of time_next calls, i.e. total number of performed time steps.
double last_time_
Beginning of the actual time interval; i.e. the time of last computed solution.
int tlevel() const
double time_step_
Length of actual time interval; i.e. the actual time step.
static TimeMarks time_marks_
ostream & operator<<(ostream &out, const TimeGovernor &tg)
Redirection operator for TimeGovernor.
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.
bool ge(double other_time) const
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
double last_time_step_
Time step just before last_time.
double t() const
Basic time management functionality for unsteady (and steady) solvers (class Equation).
static const Type none_type
Mask that matches no type of TimeMark.
Definition: time_marks.hh:64
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
double upper_constraint_
Upper constraint for the choice of the next time step.
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:109
bool lt(double other_time) const
void add_time_marks_grid(double step, TimeMark::Type mark_type=TimeMark::none_type) const
bool le(double other_time) const
TimeMark::Type equation_fixed_mark_type() const
Accessor to the data with type Type::Record.
Definition: accessors.hh:308
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.
double lower_constraint() const
static Input::Type::Record input_type
This class is a collection of time marks to manage various events occurring during simulation time...
Definition: time_marks.hh:165
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.
const double epsilon
Definition: mathfce.h:6
int set_upper_constraint(double upper)
Sets upper constraint for the next time step estimating.
double dt() const
static const double time_step_lower_bound
Technical bound for the time step given by finite precision.
double time() const
Getter for the time of the TimeMark.
Definition: time_marks.hh:84
Record type proxy class.
Definition: type_record.hh:161
double fixed_time_step_
Next fixed time step.
bool gt(double other_time) const
double last_dt() const
double time_
End of actual time interval; i.e. where the solution is computed.
static const double inf_time
Infinity time used for steady case.
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:125