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