Flow123d  JS_before_hm-2196-g9bdbf60c0
time_governor.cc
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.cc
15  * @ingroup application
16  * @brief Basic time management class.
17  */
18 
19 #include <limits>
20 #include "system/system.hh"
21 #include "input/accessors.hh"
22 #include "time_governor.hh"
23 #include "time_marks.hh"
24 #include "unit_si.hh"
25 #include "unit_converter.hh"
26 
27 /*******************************************************************
28  * implementation of TimeGovernor static values and methods
29  */
30 
31 //initialize constant pointer to TimeMarks object
33 
34 //const double TimeGovernor::time_step_lower_bound = numeric_limits<double>::epsilon();
35 
36 #define MAX_END_TIME 5.0e+17
37 #define MAX_END_TIME_STR "5.0e+17"
38 
39 const double TimeGovernor::inf_time = numeric_limits<double>::infinity();
40 const double TimeGovernor::max_end_time = MAX_END_TIME; // more then age of universe in seconds.
41 const double TimeGovernor::time_step_precision = 16*numeric_limits<double>::epsilon();
42 
43 
44 using namespace Input::Type;
45 
46 
47 const Tuple & TimeGovernor::get_input_time_type(double lower_bound, double upper_bound)
48 {
49  return Tuple("TimeValue", "A time with optional unit specification.")
50  .declare_key("time", Double(lower_bound, upper_bound), Default::obligatory(),
51  "The time value." )
53  "Predefined units include: `s` seconds, `min` minutes, `h` hours, `d` days, `y` years.\n"
54  "The default time unit is set from the equation's time governor, see the key `common_time_unit`"
55  "in the equation's time record.\n\n"
56  "User can benefit from the Unit Convertor funcionality and create different time units.\n"
57  "Year length example considering leap years (Gregorian calendar): `year; year = 365.2425*d`.\n"
58  "Miliseconds example : `milisec; milisec = 0.001*s`.")
59  .close();
60 }
61 
62 
64  static const Tuple &dt_step =
65  Tuple("DtLimits", "Time dependent changes in min_dt and max_dt limits.")
67  "The start time of dt step set.")
68  .declare_key("min_dt", TimeGovernor::get_input_time_type(), Default::read_time("'min_dt' value of TimeGovernor."),
69  "Soft lower limit for the time step.")
70  .declare_key("max_dt", TimeGovernor::get_input_time_type(), Default::read_time("'max_dt' value of TimeGovernor."),
71  "Whole time of the simulation if specified, infinity else.")
72  .close();
73 
74  return Record("TimeGovernor",
75  "Time axis settings of the simulation.\n"
76  "The settings is specific to a particular equation.\n"
77  "TimeGovernor allows to:\n"
78  " - define start time and end time of simulation\n"
79  " - define lower and upper limits of time steps\n"
80  " - direct fixed time marks of whole simulation\n"
81  " - set global time unit of equation (see 'common_time_unit' key)\n"
82  "Limits of time steps are defined by keys 'min_dt', 'max_dt', 'init_dt' and 'dt_limits'. Key "
83  "'init_dt' has the highest priority and allows set fix size of time steps. Pair of keys 'min_dt' "
84  "and 'max_dt' define interval of time steps. Both previous cases ('init_dt' or pair 'min_dt' "
85  "and 'max_dt') set global limits of whole simulation. In contrasts, 'dt_limits' allow set "
86  "time-dependent function of min_dt/max_dt. Used time steps of simulation can be printed to YAML "
87  "output file (see 'write_used_timesteps'.\n"
88  "Fixed time marks define exact values of time steps. They are defined in:\n"
89  " - start time and end time of simulation\n"
90  " - output times printed to output mesh file\n"
91  " - times defined in 'dt_limits' table (optional, see 'add_dt_limits_time_marks' key)")
92  .allow_auto_conversion("max_dt")
93  .declare_key("start_time", TimeGovernor::get_input_time_type(), Default("0.0"),
94  "Start time of the simulation.")
96  "End time of the simulation.\n"
97  "The default value is higher than the age of the Universe (given in seconds).")
98  .declare_key("init_dt", TimeGovernor::get_input_time_type(0.0), Default("0.0"),
99  "Initial guess for the time step.\n"
100  "It applies to equations that use an adaptive time stepping. "
101  "If set to 0.0, the time step is determined in fully autonomous "
102  "way, assuming the equation supports it.")
104  Default::read_time("Machine precision."),
105  "Soft lower limit for the time step.\n"
106  "Equation using an adaptive time stepping cannot suggest smaller time step. "
107  "The actual time step can only decrease below the limit in order to match "
108  "the prescribed input or output times.")
110  Default::read_time("Whole time of the simulation if specified, infinity else."),
111  "Hard upper limit for the time step.\n"
112  "The actual time step can only increase above the limit in order to match "
113  "the prescribed input or output times.")
114  .declare_key("dt_limits", Array(dt_step), Default::optional(),
115  "Allow to set a time dependent changes in ``min_dt`` and ``max_dt`` limits. This list is processed "
116  "at individual times overwriting previous values of ``min_dt``/``max_dt``. Limits equal to 0 are "
117  "ignored and replaced with ``min_dt``/``max_dt`` values.")
118  .declare_key("add_dt_limits_time_marks", Bool(), Default("false"), "Add all times defined in ``dt_limits`` "
119  "table to the list of fixed TimeMarks.")
120  .declare_key("write_used_timesteps", FileName::output(), Default::optional(),
121  "Write used time steps to the given file in YAML format corresponding with the format of ``dt_limits``.")
122  .declare_key("common_time_unit", UnitConverter::get_input_type(), Default("\"s\""),
123  "Common time unit of the equation.\nThis unit will be used for all time inputs and outputs "
124  "within the equation. Individually, the common time unit can be overwritten for every declared time.\n"
125  "Time units are used in the following cases:\n"
126  "1) Time units of time value keys in: TimeGovernor, FieldDescriptors.\n"
127  " The common time unit can be overwritten for every declared time.\n"
128  "2) Time units in: \n"
129  " a) input fields: FieldFE and FieldTimeFunction\n"
130  " b) time steps definition of OutputTimeSet\n"
131  " Common time unit can be overwritten by one unit value for every whole mesh data file or time function.\n"
132  "3) Time units in output files: observation times, balance times, frame times of VTK and GMSH\n"
133  " Common time unit cannot be overwritten in these cases."
134  )
135  .close();
136 }
137 
138 
139 
140 /*******************************************************************
141  * implementation of TimeUnitConversion
142  */
143 
145 : coef_(1.0), unit_string_("s") {}
146 
148 {
149  unit_string_ = input.val<std::string>("unit_formula");
151 }
152 
154 {
155  std::string unit_str = input.val<std::string>("unit_formula");
156  try {
157  return UnitSI().s().convert_unit_from(unit_str);
158  } catch (ExcInvalidUnit &e) {
159  e << input.ei_address();
160  throw;
161  } catch (ExcNoncorrespondingUnit &e) {
162  e << input.ei_address();
163  throw;
164  }
165 }
166 
167 
168 
169 double TimeUnitConversion::read_time(Input::Iterator<Input::Tuple> time_it, double default_time) const {
170  if (time_it) {
171  double time = time_it->val<double>("time");
172 
173  Input::Record unit_record;
174  if ( time_it->opt_val("unit", unit_record) ) {
175  double unit_coef = read_unit_coef_from_input(unit_record);
176  return ( time * unit_coef );
177  }
178  else {
179  return ( time * coef_ );
180  }
181  } else {
182  ASSERT(default_time!=std::numeric_limits<double>::quiet_NaN()).error("Undefined default time!");
183  return default_time;
184  }
185 }
186 
187 
188 
190  if (unit_it) {
191  return read_unit_coef_from_input(*unit_it);
192  } else {
193  return coef_;
194  }
195 }
196 
197 
198 
199 /*******************************************************************
200  * implementation of TimeStep
201  */
202 
203 TimeStep::TimeStep(double init_time, std::shared_ptr<TimeUnitConversion> time_unit_conversion) :
204 use_fparser_(false),
205 index_(0),
206 length_(1.0),
207 end_(init_time),
208 time_unit_conversion_(time_unit_conversion)
209 {}
210 
211 
212 
214 use_fparser_(false),
215 index_(0),
216 length_(TimeGovernor::inf_time),
217 end_(-TimeGovernor::inf_time)
218 {
219  time_unit_conversion_ = std::make_shared<TimeUnitConversion>();
220 }
221 
222 
223 
224 
226 use_fparser_(false),
227 index_(other.index_),
228 length_(other.length_),
229 end_(other.end_),
230 time_unit_conversion_(other.time_unit_conversion_)
231 {}
232 
233 
234 
235 TimeStep TimeStep::make_next(double new_length) const
236 {
237  return make_next(new_length, this->end_+new_length);
238 }
239 
240 
241 
242 TimeStep TimeStep::make_next(double new_lenght, double end_time) const
243 {
244  TimeStep ts;
245  ts.index_=this->index_ +1;
246  ts.length_=new_lenght;
247  ts.end_=end_time;
249  return ts;
250 }
251 
252 
253 
254 bool TimeStep::safe_compare(double t1, double t0) const
255 {
256  return t1 >= t0
257  - 16*numeric_limits<double>::epsilon()*(1.0+max(abs(t1),abs(t0)));
258 }
259 
260 
261 
262 double TimeStep::read_time(Input::Iterator<Input::Tuple> time_it, double default_time) const {
263  return time_unit_conversion_->read_time(time_it, default_time);
264 }
265 
266 
267 
269  return time_unit_conversion_->read_coef(unit_it);
270 }
271 
272 
273 
274 double TimeStep::get_coef() const {
275  return time_unit_conversion_->get_coef();
276 }
277 
278 
279 
280 std::shared_ptr<TimeUnitConversion> TimeStep::get_unit_conversion() const
281 {
282  return time_unit_conversion_;
283 }
284 
285 ostream& operator<<(ostream& out, const TimeStep& t_step) {
286  out << "time: " << t_step.end() << " dt: " << t_step.length() << endl;
287  return out;
288 }
289 
290 
291 
292 /*******************************************************************
293  * implementation of TimeGovernor
294  */
295 
296 TimeGovernor::TimeGovernor(const Input::Record &input, TimeMark::Type eq_mark_type, bool timestep_output)
297 : timestep_output_(timestep_output)
298 {
299  // use new mark type as default
300  if (eq_mark_type == TimeMark::none_type) eq_mark_type = marks().new_mark_type();
301 
302  try {
303 
304  Input::Record common_unit_record = input.val<Input::Record>("common_time_unit");
305  time_unit_conversion_ = std::make_shared<TimeUnitConversion>(common_unit_record);
306 
307  limits_time_marks_ = input.val<bool>("add_dt_limits_time_marks");
308 
309  // Get rid of rounding errors.
310  double end_time = read_time( input.find<Input::Tuple>("end_time") );
312 
313  // set permanent limits
314  init_common(read_time( input.find<Input::Tuple>("start_time") ),
315  end_time,
316  eq_mark_type);
317  Input::Array limits_array = Input::Array();
318  input.opt_val("dt_limits", limits_array);
320  read_time( input.find<Input::Tuple>("min_dt"), min_time_step_),
321  read_time( input.find<Input::Tuple>("max_dt"), max_time_step_),
322  limits_array
323  );
324 
325  // check key write_used_timesteps, open YAML file, print first time step
326  if (timestep_output_)
327  if (input.opt_val("write_used_timesteps", timesteps_output_file_) ) {
328  try {
330  } INPUT_CATCH(FilePath::ExcFileOpen, FilePath::EI_Address_String, input)
331  timesteps_output_ << "- [ " << t() << ", " << dt_limits_table_[0].min_dt << ", " << dt_limits_table_[0].max_dt << " ]\n";
333  }
334 
335  double init_dt=read_time( input.find<Input::Tuple>("init_dt") );
336  if (init_dt > 0.0) {
337  // set first time step suggested by user
338  //time_step_=min(init_dt, time_step_);
339  lower_constraint_=init_dt;
340  lower_constraint_message_ = "Initial time step set by user.";
341  upper_constraint_=init_dt;
342  upper_constraint_message_ = "Initial time step set by user.";
343  }
344 
345 
346  } catch(ExcTimeGovernorMessage &exc) {
347  exc << input.ei_address();
348  throw;
349  }
350 
351 }
352 
353 TimeGovernor::TimeGovernor(double init_time, double dt)
354 : dt_limits_pos_(0), timestep_output_(false)
355 {
356  time_unit_conversion_ = std::make_shared<TimeUnitConversion>();
358  // fixed time step
359  if (dt < time_step_precision)
360  THROW(ExcTimeGovernorMessage() << EI_Message("Fixed time step smaller then machine precision. \n") );
361 
363  is_time_step_fixed_=true;
364  time_step_changed_=true;
366 
367  // fill table limits with two records (start time, end time)
368  dt_limits_table_.push_back( DtLimitRow(init_time, dt, dt) );
369  dt_limits_table_.push_back( DtLimitRow(inf_time, dt, dt) );
370 
372  lower_constraint_message_ = "Initial time step set by user.";
374  upper_constraint_message_ = "Initial time step set by user.";
375 
376  //time_step_=dt;
377 }
378 
379 
380 // steady time governor constructor
381 TimeGovernor::TimeGovernor(double init_time, TimeMark::Type eq_mark_type)
382 : dt_limits_pos_(0), timestep_output_(false)
383 {
384  // use new mark type as default
385  if (eq_mark_type == TimeMark::none_type) eq_mark_type = marks().new_mark_type();
386 
387  time_unit_conversion_ = std::make_shared<TimeUnitConversion>();
388  init_common(init_time, inf_time, eq_mark_type);
389 
390  // fill table limits with two records (start time, end time)
393 
394  steady_ = true;
395 }
396 
397 
399 {
401  timesteps_output_.close();
402  }
403 }
404 
405 
406 // common part of constructors
407 void TimeGovernor::init_common(double init_time, double end_time, TimeMark::Type type)
408 {
409 
410  if (init_time < 0.0) {
411  THROW(ExcTimeGovernorMessage()
412  << EI_Message("Start time has to be greater or equal to 0.0\n")
413 
414  );
415  }
416 
417  recent_steps_.set_capacity(size_of_recent_steps_);
420 
421  if (end_time < init_time) {
422  THROW(ExcTimeGovernorMessage() << EI_Message("End time must be greater than start time.\n") );
423  } else {
425  }
426 
427  //if (dt == 0.0) {
428  // variable time step
429  fixed_time_step_=0.0;
430  is_time_step_fixed_=false;
431  time_step_changed_=true;
433 
435  lower_constraint_message_ = "Permanent minimal constraing, default, time_step_precision.";
437  upper_constraint_message_ = "Permanent maximal constraint, default, total simulation time.";
438  // choose maximum possible time step
439  //time_step_=max_time_step_;
440  /*} else {
441  // fixed time step
442  if (dt < time_step_lower_bound)
443  THROW(ExcTimeGovernorMessage() << EI_Message("Fixed time step smaller then machine precision. \n") );
444 
445  fixed_time_step_=dt;
446  is_time_step_fixed_=true;
447  time_step_changed_=true;
448  end_of_fixed_dt_interval_ = inf_time;
449 
450  upper_constraint_=max_time_step_=dt;
451  lower_constraint_=min_time_step_=dt;
452  time_step_=dt;
453 
454  }*/
455 
456  eq_mark_type_=type;
457  steady_=false;
459  //if (end_time_ != inf_time)
461 }
462 
463 
464 
465 void TimeGovernor::set_dt_limits( double min_dt, double max_dt, Input::Array dt_limits_list)
466 {
467  dt_limits_table_.clear();
468 
469  // check min_dt and max_dt set by user
470  if (min_dt < time_step_precision) {
471  THROW(ExcTimeGovernorMessage() << EI_Message("'min_dt' smaller than machine precision.\n") );
472  }
473  if (max_dt < min_dt) {
474  THROW(ExcTimeGovernorMessage() << EI_Message("'max_dt' smaller than 'min_dt'.\n") );
475  }
476 
477  bool first_step = true;
478  if (dt_limits_list.size())
479  for(auto it = dt_limits_list.begin<Input::Tuple>(); it != dt_limits_list.end(); ++it) {
480  double time = read_time( it->find<Input::Tuple>("time"));
481 
482  if (first_step) { // we need special check before setting first time step to the table
483  if (time > init_time_) { // table starts later than simulation, we need to add start time to the table
484  dt_limits_table_.push_back( DtLimitRow(init_time_, min_dt, max_dt) );
485  }
486  first_step = false;
487  }
488 
489  // next cases will be skipped
490  if (time < init_time_) {
491  WarningOut().fmt("Time {} define in 'dt_limits' table at address {} is lesser than start time of simulation "
492  "and can be skipped.\n", time, dt_limits_list.address_string());
493  }
494  if (dt_limits_table_.size() && (time <= dt_limits_table_[dt_limits_table_.size()-1].time) ) {
495  WarningOut().fmt("Time {} define in 'dt_limits' table at address {} is in incorrect order "
496  "and will be skipped.\n", time, dt_limits_list.address_string());
497  continue;
498  }
499  if ((time > end_time_) ) {
500  WarningOut().fmt("Time {} define in 'dt_limits' table at address {} is greater than end time of simulation "
501  "and will be skipped.\n", time, dt_limits_list.address_string());
502  continue;
503  }
504 
505  double min = read_time( it->find<Input::Tuple>("min_dt"), 0.0);
506  if (min == 0.0) min = min_dt;
507  double max = read_time( it->find<Input::Tuple>("max_dt"), 0.0);
508  if (max == 0.0) max = max_dt;
509 
510  if (min < time_step_precision) {
511  THROW(ExcTimeGovernorMessage() << EI_Message("'min_dt' in 'dt_limits' smaller than machine precision.\n") );
512  }
513  if (max < min) {
514  THROW(ExcTimeGovernorMessage() << EI_Message("'max_dt' in 'dt_limits' smaller than 'min_dt'.\n") );
515  }
516 
517  dt_limits_table_.push_back( DtLimitRow(time, min, max) );
518  if (limits_time_marks_) this->marks().add(TimeMark(time, this->equation_fixed_mark_type()));
519  }
520 
521  if (dt_limits_table_.size() == 0) {
522  // add start time to limit table if it is empty
523  dt_limits_table_.push_back( DtLimitRow(init_time_, min_dt, max_dt) );
524  }
525  if (dt_limits_table_[dt_limits_table_.size()-1].time < end_time_) {
526  // add time == end_time_ to limits table, we need only for check time, not for limits
527  dt_limits_table_.push_back( DtLimitRow(end_time_, min_dt, max_dt) );
528  }
529 
530  dt_limits_pos_ = 0;
531  while (dt_limits_table_[dt_limits_pos_+1].time <= init_time_) {
532  ++dt_limits_pos_;
533  }
534 
536 }
537 
538 
540 {
542  lower_constraint_message_ = "Permanent minimal constraint, custom.";
544  upper_constraint_message_ = "Permanent maximal constraint, custom.";
545  ++dt_limits_pos_;
546 }
547 
548 
549 // int set_constrain - dle nastaveni constraint
550 // interval - constraint - jako v cmp u Qsortu
551 // -1 vetsi nez interval (min_dt,max_dt)
552 // +1 mensi
553 // 0 OK
554 
555 int TimeGovernor::set_upper_constraint (double upper, std::string message)
556 {
557  if (upper_constraint_ < upper) {
558  //do not change upper_constraint_
559  return -1;
560  } else
561  if (lower_constraint_ > upper) {
562  // set upper constraint to the lower constraint
564  upper_constraint_message_ = "Forced lower constraint. " + message;
565  return 1;
566  } else {
567  //change upper_constraint_ to upper
568  upper_constraint_ = upper;
569  upper_constraint_message_ = message;
570  return 0;
571  }
572 }
573 
574 
575 
576 int TimeGovernor::set_lower_constraint (double lower, std::string message)
577 {
578  if (upper_constraint_ < lower) {
579  // set lower constraint to the upper constraint
581  return -1;
582  } else
583  if (lower_constraint_ > lower) {
584  //do not change lower_constraint_
585  return 1;
586  } else {
587  //change lower_constraint_ to lower
588  lower_constraint_ = lower;
589  lower_constraint_message_ = message;
590  return 0;
591  }
592 }
593 
594 
595 
596 
598  if (steady_) return 0.0;
599  end_of_fixed_dt_interval_=-inf_time; // release previous fixed interval
601  is_time_step_fixed_ = true; //flag means fixed step has been set since now
603 }
604 
605 
606 
607 
608 void TimeGovernor::add_time_marks_grid(double step, TimeMark::Type mark_type) const
609 {
610  if (end_time() == inf_time) {
611  THROW(ExcTimeGovernorMessage()
612  << EI_Message("Missing end time for making output grid required by key 'time_step' of the output stream.\n")
613  );
614  }
615 
617  // always add start time and end time
618  marks().add(TimeMark(init_time_, mark_type | eq_mark_type_));
619  marks().add(TimeMark(end_time(), mark_type | eq_mark_type_));
620 }
621 
622 
624 {
625  TimeMark::Type type = equation_mark_type() | mask;
626  return time_marks_.current(step(), type) != time_marks_.end(type);
627 }
628 
629 
630 
632  if (is_end()) return 0.0;
633 
634  if (this->step().lt(end_of_fixed_dt_interval_)) return fixed_time_step_;
635 
636  // jump to the first future fix time
638  // compute step to next fix time and apply constraints
639  double full_step = fix_time_it->time() - t();
640 
641  double step_estimate = min(full_step, upper_constraint_);
642  step_estimate = max(step_estimate, lower_constraint_); //these two must be in this order
643 
644  if (step_estimate == inf_time) return step_estimate;
645 
646  // round the time step to have integer number of steps till next fix time
647  // this always selects shorter time step,
648  // but allows time step larger then constraint by a number close to machine epsilon
649  //
650  double n_steps = ceil( full_step / step_estimate - time_step_precision);
651  step_estimate = full_step / n_steps;
652 
653  // try to avoid time_step changes
654  if (n_steps > 1 && abs(step_estimate - step().length()) < time_step_precision) {
655  step_estimate=step().length();
656  }
657 
658  // if the step estimate gets by rounding lower than lower constraint program will not crash
659  // will just output a user warning.
660  if (step_estimate < lower_constraint_) {
661  DebugOut().fmt("Time step estimate is below the lower constraint of time step. The difference is: {:.16f}.\n",
662  lower_constraint_ - step_estimate);
663  }
664 
665  return step_estimate;
666 }
667 
668 
669 
671 {
672  OLD_ASSERT_LE(0.0, t());
673  if (is_end()) return;
674 
675 
676  if (this->step().lt(end_of_fixed_dt_interval_)) {
677  // this is done for fixed step
678  // make tiny correction of time step in order to avoid big rounding errors
679  // tiny correction means that dt_changed 'is NOT changed'
682  }
683 
684  recent_steps_.push_front(recent_steps_.front().make_next(fixed_time_step_));
685 
686 
687  //checking whether fixed time step has been changed (by fix_dt_until_mark() method) since last time
689  {
690  is_time_step_fixed_ = false;
691 
692  //is true unless new fixed_dt is not equal previous time_step
693  time_step_changed_ = (step(-2).length() != step().length());
694  }
695  else
696  time_step_changed_ = false;
697  }
698  else
699  {
700  // this is done if end_of_fixed_dt_interval is not set (means it is equal to -infinity)
701  double dt=estimate_dt();
702  TimeStep step_ = recent_steps_.front().make_next(dt);
703  //DebugOut().fmt("step: {}, end: {}\n", step_.length(), step_.end());
704  recent_steps_.push_front(step_);
705  //DebugOut().fmt("last: {}, new: {}\n",step(-1).length(),step().length());
706  time_step_changed_= (step(-2).length() != step().length());
707  }
708 
711  // refreshing the upper_constraint_
714  lower_constraint_message_ = "Permanent minimal constraint, in next time.";
715  upper_constraint_message_ = "Permanent maximal constraint, in next time.";
716 
718 
719  // write time step to YAML file
721  double time = t();
722  if (time > last_printed_timestep_) {
723  if (is_end()) timesteps_output_ << "- [ " << time << ", 0, 0 ]\n";
724  else timesteps_output_ << "- [ " << time << ", " << lower_constraint_ << ", " << upper_constraint_ << " ]\n";
725  last_printed_timestep_ = time;
726  }
727  }
728 }
729 
730 
731 double TimeGovernor::reduce_timestep(double factor) {
732  double prior_dt = dt();
733  double new_upper_constraint = factor * dt();
734 
735  // Revert time.
736 // DebugOut().fmt("tg idx: {}\n", recent_steps_.front().index());
737  recent_steps_.pop_front();
738 // DebugOut().fmt("tg idx: {}\n", recent_steps_.back().index());
741 
742  // Set constraint.
743  int current_minus_new = set_upper_constraint(new_upper_constraint, "Reduce time step.");
744  if (current_minus_new < 0)
745  // current constraint < reduced dt, should not happen
746  THROW(ExcMessage() << EI_Message("Internal error."));
747 
748  next_time();
749 
750  // Return false if we hit lower time step constraint.
751  return dt() / prior_dt;
752 }
753 
754 
755 
756 const TimeStep &TimeGovernor::step(int index) const {
757  unsigned int back_idx;
758  if (index < 0) {
759  back_idx = static_cast<unsigned int>(-index-1);
760  } else {
761  back_idx = static_cast<unsigned int>(recent_steps_[0].index() - index);
762  }
763  if ( back_idx >= recent_steps_.size())
764  THROW(ExcMissingTimeStep() << EI_Index(index) << EI_BackIndex(back_idx) << EI_HistorySize(recent_steps_.size()));
765 
766  return recent_steps_[back_idx];
767 }
768 
769 
770 
771 
772 void TimeGovernor::view(const char *name) const
773 {
774 #ifdef FLOW123D_DEBUG_MESSAGES
775  MessageOut().fmt(
776  "TG[{}]:{:06d} t:{:10.4f} dt:{:10.6f} dt_int<{:10.6f},{:10.6f}> "
777  "end_time: {} end_fixed_time: {} type: {:#x}\n",
780 
781  MessageOut().fmt("Lower time step constraint [{}]: {} \nUpper time step constraint [{}]: {} \n",
784 #else
785  MessageOut().fmt(
786  "TG[{}]:{:06d} t:{:10.4f} dt:{:10.6f} dt_int<{:10.6f},{:10.6f}>\n",
787  name, tlevel(), t(), dt(), lower_constraint_, upper_constraint_);
788 #endif
789 }
790 
791 
792 
793 double TimeGovernor::read_time(Input::Iterator<Input::Tuple> time_it, double default_time) const {
794  return time_unit_conversion_->read_time(time_it, default_time);
795 }
796 
797 
798 
800  return time_unit_conversion_->read_coef(unit_it);
801 }
802 
803 
804 
805 double TimeGovernor::get_coef() const {
806  return time_unit_conversion_->get_coef();
807 }
808 
809 
810 std::shared_ptr<TimeUnitConversion> TimeGovernor::get_unit_conversion() const
811 {
812  return time_unit_conversion_;
813 }
814 
815 
816 ostream& operator<<(ostream& out, const TimeGovernor& tg)
817 {
818  static char buffer[1024];
819  sprintf(buffer, "\n%06d t:%10.4f dt:%10.6f dt_int<%10.6f,%10.6f>\n",
820  tg.tlevel(), tg.t(), tg.dt(), tg.lower_constraint(), tg.upper_constraint());
821  return (out << buffer);
822 }
823 
824 
TimeStep::read_coef
double read_coef(Input::Iterator< Input::Record > unit_it) const
Definition: time_governor.cc:268
TimeStep::get_coef
double get_coef() const
Definition: time_governor.cc:274
TimeMark::Type::bitmap_
unsigned long int bitmap_
Definition: time_marks.hh:88
TimeGovernor::add_time_marks_grid
void add_time_marks_grid(double step, TimeMark::Type mark_type=TimeMark::none_type) const
Definition: time_governor.cc:608
TimeStep::safe_compare
bool safe_compare(double t1, double t0) const
Definition: time_governor.cc:254
TimeUnitConversion::read_unit_coef_from_input
double read_unit_coef_from_input(const Input::Record &input) const
Reads the Unit record and computes the coef.
Definition: time_governor.cc:153
Input::Type::Bool
Class for declaration of the input of type Bool.
Definition: type_base.hh:452
TimeMarks::next
TimeMarks::iterator next(const TimeGovernor &tg, const TimeMark::Type &mask) const
Definition: time_marks.cc:149
TimeGovernor::~TimeGovernor
~TimeGovernor()
Definition: time_governor.cc:398
TimeMarks::current
TimeMarks::iterator current(const TimeStep &time_step, const TimeMark::Type &mask) const
Definition: time_marks.cc:141
TimeGovernor::dt
double dt() const
Definition: time_governor.hh:565
TimeMarks::new_mark_type
TimeMark::Type new_mark_type()
Definition: time_marks.cc:68
TimeGovernor::last_printed_timestep_
double last_printed_timestep_
Store last printed time to YAML output, try multiplicity output of one time.
Definition: time_governor.hh:753
TimeUnitConversion::get_input_default
static Input::Type::Default get_input_default()
Definition: time_governor.hh:66
TimeGovernor::set_permanent_constraint
void set_permanent_constraint()
Sets permanent constraints for actual time step.
Definition: time_governor.cc:539
time_governor.hh
Basic time management class.
TimeGovernor::end_time
double end_time() const
End time.
Definition: time_governor.hh:591
TimeGovernor::dt_limits_pos_
unsigned int dt_limits_pos_
Index to actual position of DT limits.
Definition: time_governor.hh:744
TimeGovernor::upper_constraint_message_
std::string upper_constraint_message_
Description of the upper constraint.
Definition: time_governor.hh:706
TimeGovernor::get_unit_conversion
std::shared_ptr< TimeUnitConversion > get_unit_conversion() const
Getter for time unit conversion object.
Definition: time_governor.cc:810
TimeUnitConversion::read_time
double read_time(Input::Iterator< Input::Tuple > time_it, double default_time) const
Definition: time_governor.cc:169
TimeGovernor::init_time_
double init_time_
Initial time.
Definition: time_governor.hh:692
ASSERT
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:347
TimeGovernor::fixed_time_step_
double fixed_time_step_
Next fixed time step.
Definition: time_governor.hh:699
TimeGovernor::TimeGovernor
TimeGovernor(const Input::Record &input, TimeMark::Type fixed_time_mask=TimeMark::none_type, bool timestep_output=true)
Constructor for unsteady solvers.
Definition: time_governor.cc:296
TimeGovernor::equation_fixed_mark_type
TimeMark::Type equation_fixed_mark_type() const
Definition: time_governor.hh:481
Input::Record::val
const Ret val(const string &key) const
Definition: accessors_impl.hh:31
TimeGovernor::set_upper_constraint
int set_upper_constraint(double upper, std::string message)
Sets upper constraint for the next time step estimating.
Definition: time_governor.cc:555
TimeGovernor::end_of_fixed_dt_interval_
double end_of_fixed_dt_interval_
End of interval if fixed time step.
Definition: time_governor.hh:694
TimeGovernor::size_of_recent_steps_
static const unsigned int size_of_recent_steps_
Definition: time_governor.hh:687
TimeStep::get_unit_conversion
std::shared_ptr< TimeUnitConversion > get_unit_conversion() const
Getter for time unit conversion object.
Definition: time_governor.cc:280
FilePath
Dedicated class for storing path to input and output files.
Definition: file_path.hh:54
Input::Type::Double
Class for declaration of the input data that are floating point numbers.
Definition: type_base.hh:534
TimeGovernor::recent_steps_
boost::circular_buffer< TimeStep > recent_steps_
Circular buffer of recent time steps. Implicit size is 3.
Definition: time_governor.hh:690
TimeGovernor::upper_constraint_
double upper_constraint_
Upper constraint for the choice of the next time step.
Definition: time_governor.hh:710
TimeGovernor::time_marks_
static TimeMarks time_marks_
Definition: time_governor.hh:729
THROW
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
Input::Type::Default::read_time
static Default read_time(const std::string &description)
The factory function to make an default value that will be specified at the time when a key will be r...
Definition: type_record.hh:97
Input::Type::FileName::output
static FileName output()
The factory function for declaring type FileName for input files.
Definition: type_base.cc:531
TimeMarks::end
TimeMarks::iterator end(TimeMark::Type mask) const
Iterator for the end mimics container-like of TimeMarks.
Definition: time_marks.cc:206
fmt::sprintf
std::string sprintf(CStringRef format, ArgList args)
Definition: printf.h:457
system.hh
TimeGovernor::read_coef
double read_coef(Input::Iterator< Input::Record > unit_it) const
Definition: time_governor.cc:799
Input::Type::Tuple
Tuple type proxy class.
Definition: type_tuple.hh:45
UnitSI::convert_unit_from
double convert_unit_from(std::string actual_unit) const
Convert and check user-defined unit.
Definition: unit_si.cc:217
TimeGovernor::min_time_step_
double min_time_step_
Permanent lower limit for the time step.
Definition: time_governor.hh:716
TimeStep::read_time
double read_time(Input::Iterator< Input::Tuple > time_it, double default_time=std::numeric_limits< double >::quiet_NaN()) const
Definition: time_governor.cc:262
TimeGovernor::steady_
bool steady_
True if the time governor is used for steady problem.
Definition: time_governor.hh:735
FilePath::open_stream
void open_stream(Stream &stream) const
Definition: file_path.cc:211
Input::Array::begin
Iterator< ValueType > begin() const
Definition: accessors_impl.hh:145
TimeGovernor::set_lower_constraint
int set_lower_constraint(double lower, std::string message)
Sets lower constraint for the next time step estimating.
Definition: time_governor.cc:576
TimeUnitConversion::unit_string_
std::string unit_string_
String representation of global unit of all time values within the equation.
Definition: time_governor.hh:107
TimeGovernor::set_dt_limits
void set_dt_limits(double min_dt, double max_dt, Input::Array dt_limits_list)
Sets dt limits for time dependent DT limits in simulation.
Definition: time_governor.cc:465
TimeGovernor::last_lower_constraint_
double last_lower_constraint_
Lower constraint used for choice of current time.
Definition: time_governor.hh:721
TimeGovernor::init_common
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 ...
Definition: time_governor.cc:407
Input::Iterator
Definition: accessors.hh:143
TimeUnitConversion::TimeUnitConversion
TimeUnitConversion()
Definition: time_governor.cc:144
TimeGovernor::is_end
bool is_end() const
Returns true if the actual time is greater than or equal to the end time.
Definition: time_governor.hh:595
TimeGovernor::lower_constraint_message_
std::string lower_constraint_message_
Description of the upper constraint.
Definition: time_governor.hh:708
TimeGovernor::last_upper_constraint_
double last_upper_constraint_
Upper constraint used for choice of current time.
Definition: time_governor.hh:719
Input::Type::Default
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
TimeStep::length_
double length_
Definition: time_governor.hh:247
TimeGovernor::timestep_output_
bool timestep_output_
Special flag allows forbid output time steps during multiple initialization of TimeGovernor.
Definition: time_governor.hh:756
TimeMark
Class used for marking specified times at which some events occur.
Definition: time_marks.hh:45
TimeStep::end
double end() const
Definition: time_governor.hh:161
TimeGovernor::limits_time_marks_
bool limits_time_marks_
Allows add all times defined in dt_limits_table_ to list of TimeMarks.
Definition: time_governor.hh:759
Input::Record
Accessor to the data with type Type::Record.
Definition: accessors.hh:291
TimeGovernor::time_step_precision
static const double time_step_precision
Definition: time_governor.hh:651
TimeStep::time_unit_conversion_
std::shared_ptr< TimeUnitConversion > time_unit_conversion_
Conversion unit of all time values within the equation.
Definition: time_governor.hh:251
TimeGovernor::tlevel
int tlevel() const
Definition: time_governor.hh:607
TimeGovernor::upper_constraint
double upper_constraint() const
Definition: time_governor.hh:511
TimeGovernor::end_time_
double end_time_
End time of the simulation.
Definition: time_governor.hh:696
TimeGovernor::reduce_timestep
double reduce_timestep(double factor)
Force timestep reduction in particular in the case of failure of the non-linear solver.
Definition: time_governor.cc:731
Input::Type::Tuple::close
const Tuple & close() const
Close the Tuple for further declarations of keys.
Definition: type_tuple.cc:70
Input::Type::Record::allow_auto_conversion
virtual Record & allow_auto_conversion(const string &from_key)
Allows shorter input of the Record providing only value of the from_key given as the parameter.
Definition: type_record.cc:133
accessors.hh
INPUT_CATCH
#define INPUT_CATCH(ExceptionType, AddressEITag, input_accessor)
Definition: accessors.hh:63
TimeStep
Representation of one time step..
Definition: time_governor.hh:123
TimeGovernor
Basic time management functionality for unsteady (and steady) solvers (class Equation).
Definition: time_governor.hh:317
TimeGovernor::step
const TimeStep & step(int index=-1) const
Definition: time_governor.cc:756
MAX_END_TIME
#define MAX_END_TIME
Definition: time_governor.cc:36
Input::Type::Default::obligatory
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:110
TimeMark::Type
Definition: time_marks.hh:60
TimeGovernor::DtLimitRow
Structure that stores one record of DT limit.
Definition: time_governor.hh:656
Input::Record::ei_address
EI_Address ei_address() const
Definition: accessors.cc:178
UnitSI
Class for representation SI units of Fields.
Definition: unit_si.hh:40
TimeUnitConversion::read_coef
double read_coef(Input::Iterator< Input::Record > unit_it) const
Definition: time_governor.cc:189
Input::Type::Tuple::declare_key
Tuple & declare_key(const string &key, std::shared_ptr< TypeBase > type, const Default &default_value, const string &description, TypeBase::attribute_map key_attributes=TypeBase::attribute_map())
Overrides Record::declare_key(const string &, std::shared_ptr<TypeBase>, const Default &,...
Definition: type_tuple.cc:173
Input::Record::opt_val
bool opt_val(const string &key, Ret &value) const
Definition: accessors_impl.hh:107
TimeMark::every_type
static const Type every_type
Mark Type with all bits set.
Definition: time_marks.hh:93
Input::Type::Record::declare_key
Record & declare_key(const string &key, std::shared_ptr< TypeBase > type, const Default &default_value, const string &description, TypeBase::attribute_map key_attributes=TypeBase::attribute_map())
Declares a new key of the Record.
Definition: type_record.cc:503
Input::Array::size
unsigned int size() const
Definition: accessors_impl.hh:163
TimeStep::end_
double end_
End time point of the time step.
Definition: time_governor.hh:249
Input::Record::find
Iterator< Ret > find(const string &key) const
Definition: accessors_impl.hh:91
TimeUnitConversion::coef_
double coef_
Conversion coefficient of all time values within the equation.
Definition: time_governor.hh:104
TimeGovernor::estimate_dt
double estimate_dt() const
Estimate choice of next time step according to actual setting of constraints.
Definition: time_governor.cc:631
TimeMarks::add
TimeMark add(const TimeMark &mark)
Definition: time_marks.cc:81
TimeGovernor::get_input_type
static const Input::Type::Record & get_input_type()
Definition: time_governor.cc:63
TimeGovernor::view
void view(const char *name="") const
Definition: time_governor.cc:772
UnitConverter::get_input_type
static const Input::Type::Record & get_input_type()
Definition: unit_converter.cc:100
Input::Type::Record::close
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
Input::Type
Definition: balance.hh:41
TimeGovernor::lower_constraint_
double lower_constraint_
Lower constraint for the choice of the next time step.
Definition: time_governor.hh:712
Input::Type::Record
Record type proxy class.
Definition: type_record.hh:182
TimeMark::none_type
static const Type none_type
Mark Type with all bits unset.
Definition: time_marks.hh:95
TimeStep::make_next
TimeStep make_next(double new_length) const
Definition: time_governor.cc:235
TimeStep::index_
unsigned int index_
Index of the step is index if the end time. Zero time step is artificial.
Definition: time_governor.hh:244
TimeMarks
This class is a collection of time marks to manage various events occurring during simulation time.
Definition: time_marks.hh:206
TimeGovernor::dt_limits_table_
std::vector< DtLimitRow > dt_limits_table_
Table of DT limits.
Definition: time_governor.hh:741
OLD_ASSERT_LE
#define OLD_ASSERT_LE(a, b)
Definition: global_defs.h:112
TimeGovernor::read_time
double read_time(Input::Iterator< Input::Tuple > time_it, double default_time=std::numeric_limits< double >::quiet_NaN()) const
Definition: time_governor.cc:793
Input::Type::Array
Class for declaration of inputs sequences.
Definition: type_base.hh:339
TimeGovernor::marks
static TimeMarks & marks()
Definition: time_governor.hh:338
TimeGovernor::timesteps_output_
std::ofstream timesteps_output_
Handle for file for output time steps to YAML format.
Definition: time_governor.hh:750
Input::Array
Accessor to input data conforming to declared Array.
Definition: accessors.hh:566
unit_si.hh
TimeGovernor::get_coef
double get_coef() const
Definition: time_governor.cc:805
WarningOut
#define WarningOut()
Macro defining 'warning' record of log.
Definition: logger.hh:278
unit_converter.hh
Input::Tuple
Accessor to the data with type Type::Tuple.
Definition: accessors.hh:411
UnitSI::s
UnitSI & s(int exp=1)
Definition: unit_si.cc:76
TimeGovernor::time_unit_conversion_
std::shared_ptr< TimeUnitConversion > time_unit_conversion_
Conversion unit of all time values within the equation.
Definition: time_governor.hh:738
Input::Array::address_string
string address_string() const
Definition: accessors.cc:321
TimeGovernor::inf_time
static const double inf_time
Infinity time used for steady case.
Definition: time_governor.hh:645
TimeStep::TimeStep
TimeStep()
Definition: time_governor.cc:213
TimeGovernor::equation_mark_type
TimeMark::Type equation_mark_type() const
Definition: time_governor.hh:475
TimeGovernor::max_time_step_
double max_time_step_
Permanent upper limit for the time step.
Definition: time_governor.hh:714
TimeGovernor::max_end_time
static const double max_end_time
Definition: time_governor.hh:642
TimeGovernor::timesteps_output_file_
FilePath timesteps_output_file_
File path for timesteps_output_ stream.
Definition: time_governor.hh:747
TimeGovernor::is_current
bool is_current(const TimeMark::Type &mask) const
Definition: time_governor.cc:623
TimeGovernor::get_input_time_type
static const Input::Type::Tuple & get_input_time_type(double lower_bound=-std::numeric_limits< double >::max(), double upper_bound=std::numeric_limits< double >::max())
Definition: time_governor.cc:47
time_marks.hh
TimeMark::time
double time() const
Getter for the time of the TimeMark.
Definition: time_marks.hh:115
TimeMarks::add_time_marks
void add_time_marks(double time, double dt, double end_time, TimeMark::Type type)
Definition: time_marks.cc:106
TimeGovernor::lower_constraint
double lower_constraint() const
Definition: time_governor.hh:517
DebugOut
#define DebugOut()
Macro defining 'debug' record of log.
Definition: logger.hh:284
TimeGovernor::next_time
void next_time()
Proceed to the next time according to current estimated time step.
Definition: time_governor.cc:670
TimeStep::length
double length() const
Definition: time_governor.hh:160
TimeGovernor::time_step_changed_
bool time_step_changed_
Flag is set if the time step has been changed (lasts only one time step).
Definition: time_governor.hh:703
Input::Type::Default::optional
static Default optional()
The factory function to make an empty default value which is optional.
Definition: type_record.hh:124
TimeGovernor::fix_dt_until_mark
double fix_dt_until_mark()
Fixing time step until fixed time mark.
Definition: time_governor.cc:597
TimeGovernor::init_time
double init_time() const
Definition: time_governor.hh:536
Input::Array::end
IteratorBase end() const
Definition: accessors_impl.hh:157
MAX_END_TIME_STR
#define MAX_END_TIME_STR
Definition: time_governor.cc:37
TimeMarksIterator
Iterator over TimeMark objects in TimeMarks object (database of TimeMark objects).
Definition: time_marks.hh:351
TimeGovernor::eq_mark_type_
TimeMark::Type eq_mark_type_
TimeMark type of the equation.
Definition: time_governor.hh:732
operator<<
ostream & operator<<(ostream &out, const TimeStep &t_step)
Definition: time_governor.cc:285
TimeGovernor::is_time_step_fixed_
bool is_time_step_fixed_
Flag that is set when the fixed step is set (lasts only one time step).
Definition: time_governor.hh:701
MessageOut
#define MessageOut()
Macro defining 'message' record of log.
Definition: logger.hh:275
TimeGovernor::t
double t() const
Definition: time_governor.hh:542