Flow123d  release_3.0.0-506-g34af125
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  "Setting of the simulation time (can be specific to one equation).\n"
70  "TimeGovernor allows to:\n"
71  " - define start time and end time of simulation\n"
72  " - define lower and upper limits of time steps\n"
73  " - direct fixed time marks of whole simulation\n"
74  " - set global time unit of equation (see 'common_time_unit' key)\n"
75  "Limits of time steps are defined by keys 'min_dt', 'max_dt', 'init_dt' and 'dt_limits'. Key "
76  "'init_dt' has the highest priority and allows set fix size of time steps. Pair of keys 'min_dt' "
77  "and 'max_dt' define interval of time steps. Both previous cases ('init_dt' or pair 'min_dt' "
78  "and 'max_dt') set global limits of whole simulation. In contrasts, 'dt_limits' allow set "
79  "time-dependent function of min_dt/max_dt. Used time steps of simulation can be printed to YAML "
80  "output file (see 'write_used_timesteps'.\n"
81  "Fixed time marks define exact values of time steps. They are defined in:\n"
82  " - start time and end time of simulation\n"
83  " - output times printed to output mesh file\n"
84  " - times defined in 'dt_limits' table (optional, see 'add_dt_limits_time_marks' key)")
85  .allow_auto_conversion("max_dt")
86  .declare_key("start_time", TimeGovernor::get_input_time_type(), Default("0.0"),
87  "Start time of the simulation.")
89  "End time of the simulation. Default value is more then age of universe in seconds.")
90  .declare_key("init_dt", TimeGovernor::get_input_time_type(0.0), Default("0.0"),
91  "Initial guess for the time step.\n"
92  "Only useful for equations that use adaptive time stepping."
93  "If set to 0.0, the time step is determined in fully autonomous"
94  " way if the equation supports it.")
96  Default::read_time("Machine precision."),
97  "Soft lower limit for the time step. Equation using adaptive time stepping can not"
98  "suggest smaller time step, but actual time step could be smaller in order to match "
99  "prescribed input or output times.")
101  Default::read_time("Whole time of the simulation if specified, infinity else."),
102  "Hard upper limit for the time step. Actual length of the time step is also limited"
103  "by input and output times.")
104  .declare_key("dt_limits", Array(dt_step), Default::optional(),
105  "Allow to set a time dependent changes in min_dt and max_dt limits. This list is processed "
106  "at individual times overwriting previous setting of min_dt/max_dt. Limits equal to 0 are "
107  "ignored and replaced with min_dt/max_dt values.")
108  .declare_key("add_dt_limits_time_marks", Bool(), Default("false"), "Add all times defined in 'dt_limits' "
109  "table to list of fixed TimeMarks.")
110  .declare_key("write_used_timesteps", FileName::output(), Default::optional(),
111  "Write used time steps to given file in YAML format corresponding with format of 'dt_limits'.")
112  .declare_key("common_time_unit", String(), Default("\"s\""),
113  "Common time unit of equation. This unit will be used for all time inputs and outputs "
114  "within the equation. On inputs can be overwrite for every time definition.\n"
115  "Time units are used in following cases:\n"
116  "1) Time units of time value keys in: TimeGovernor, FieldDescriptors.\n"
117  " Global definition of unit can be overwrite for every declared time.\n"
118  "2) Time units in: \n"
119  " a) input fields: FieldInterpolatedP0, FieldFE and FieldTimeFunction\n"
120  " b) time steps definition of OutputTimeSet\n"
121  " Global definition can be overwrite by one unit value for every whole mesh data file or time function.\n"
122  "3) Time units in output files: Observe times, balance times, frame times of VTK and GMSH\n"
123  " Global definition can't be overwritten.\n"
124  )
125  .close();
126 }
127 
128 
129 
130 /*******************************************************************
131  * implementation of TimeUnitConversion
132  */
133 
134 TimeUnitConversion::TimeUnitConversion(std::string user_defined_unit)
135 : unit_string_(user_defined_unit)
136 {
137  coef_ = UnitSI().s().convert_unit_from(user_defined_unit);
138 }
139 
140 
141 
143 : coef_(1.0), unit_string_("s") {}
144 
145 
146 
147 double TimeUnitConversion::read_time(Input::Iterator<Input::Tuple> time_it, double default_time) const {
148  if (time_it) {
149  double time = time_it->val<double>("time");
150  string time_unit;
151  if (time_it->opt_val<string>("unit", time_unit)) {
152  return ( time * UnitSI().s().convert_unit_from(time_unit) );
153  } else {
154  return ( time * coef_ );
155  }
156  } else {
157  ASSERT(default_time!=std::numeric_limits<double>::quiet_NaN()).error("Undefined default time!");
158  return default_time;
159  }
160 }
161 
162 
163 
165  if (unit_it) {
166  return UnitSI().s().convert_unit_from(*unit_it);
167  } else {
168  return coef_;
169  }
170 }
171 
172 
173 
174 /*******************************************************************
175  * implementation of TimeStep
176  */
177 
178 TimeStep::TimeStep(double init_time, std::shared_ptr<TimeUnitConversion> time_unit_conversion) :
179 index_(0),
180 length_(1.0),
181 end_(init_time),
182 time_unit_conversion_(time_unit_conversion)
183 {}
184 
185 
186 
188 index_(0),
189 length_(TimeGovernor::inf_time),
190 end_(-TimeGovernor::inf_time)
191 {
192  time_unit_conversion_ = std::make_shared<TimeUnitConversion>();
193 }
194 
195 
196 
197 
199 index_(other.index_),
200 length_(other.length_),
201 end_(other.end_),
203 {}
204 
205 
206 
207 TimeStep TimeStep::make_next(double new_length) const
208 {
209  return make_next(new_length, this->end_+new_length);
210 }
211 
212 
213 
214 TimeStep TimeStep::make_next(double new_lenght, double end_time) const
215 {
216  TimeStep ts;
217  ts.index_=this->index_ +1;
218  ts.length_=new_lenght;
219  ts.end_=end_time;
221  return ts;
222 }
223 
224 
225 
226 bool TimeStep::safe_compare(double t1, double t0) const
227 {
228  return t1 >= t0
229  - 16*numeric_limits<double>::epsilon()*(1.0+max(abs(t1),abs(t0)));
230 }
231 
232 
233 
234 double TimeStep::read_time(Input::Iterator<Input::Tuple> time_it, double default_time) const {
235  return time_unit_conversion_->read_time(time_it, default_time);
236 }
237 
238 
239 
241  return time_unit_conversion_->read_coef(unit_it);
242 }
243 
244 
245 
246 double TimeStep::get_coef() const {
247  return time_unit_conversion_->get_coef();
248 }
249 
250 
251 
252 ostream& operator<<(ostream& out, const TimeStep& t_step) {
253  out << "time: " << t_step.end() << "step: " << t_step.length() << endl;
254  return out;
255 }
256 
257 
258 
259 /*******************************************************************
260  * implementation of TimeGovernor
261  */
262 
263 TimeGovernor::TimeGovernor(const Input::Record &input, TimeMark::Type eq_mark_type, bool timestep_output)
264 : timestep_output_(timestep_output)
265 {
266  // use new mark type as default
267  if (eq_mark_type == TimeMark::none_type) eq_mark_type = marks().new_mark_type();
268 
269  try {
270 
271  string common_unit_string=input.val<string>("common_time_unit");
272  time_unit_conversion_ = std::make_shared<TimeUnitConversion>(common_unit_string);
273  limits_time_marks_ = input.val<bool>("add_dt_limits_time_marks");
274 
275  // Get rid of rounding errors.
276  double end_time = read_time( input.find<Input::Tuple>("end_time") );
277  if (end_time> 0.99*max_end_time) end_time = max_end_time;
278 
279  // set permanent limits
280  init_common(read_time( input.find<Input::Tuple>("start_time") ),
281  end_time,
282  eq_mark_type);
283  Input::Array limits_array = Input::Array();
284  input.opt_val("dt_limits", limits_array);
286  read_time( input.find<Input::Tuple>("min_dt"), min_time_step_),
287  read_time( input.find<Input::Tuple>("max_dt"), max_time_step_),
288  limits_array
289  );
290 
291  // check key write_used_timesteps, open YAML file, print first time step
292  if (timestep_output_)
293  if (input.opt_val("write_used_timesteps", timesteps_output_file_) ) {
294  try {
296  } INPUT_CATCH(FilePath::ExcFileOpen, FilePath::EI_Address_String, input)
297  timesteps_output_ << "- [ " << t() << ", " << dt_limits_table_[0].min_dt << ", " << dt_limits_table_[0].max_dt << " ]\n";
299  }
300 
301  double init_dt=read_time( input.find<Input::Tuple>("init_dt") );
302  if (init_dt > 0.0) {
303  // set first time step suggested by user
304  //time_step_=min(init_dt, time_step_);
305  lower_constraint_=init_dt;
306  lower_constraint_message_ = "Initial time step set by user.";
307  upper_constraint_=init_dt;
308  upper_constraint_message_ = "Initial time step set by user.";
309  }
310 
311 
312  } catch(ExcTimeGovernorMessage &exc) {
313  exc << input.ei_address();
314  throw;
315  }
316 
317 }
318 
320 : dt_limits_pos_(0), timestep_output_(false)
321 {
322  time_unit_conversion_ = std::make_shared<TimeUnitConversion>();
324  // fixed time step
325  if (dt < time_step_precision)
326  THROW(ExcTimeGovernorMessage() << EI_Message("Fixed time step smaller then machine precision. \n") );
327 
329  is_time_step_fixed_=true;
330  time_step_changed_=true;
332 
333  // fill table limits with two records (start time, end time)
334  dt_limits_table_.push_back( DtLimitRow(init_time, dt, dt) );
335  dt_limits_table_.push_back( DtLimitRow(inf_time, dt, dt) );
336 
338  lower_constraint_message_ = "Initial time step set by user.";
340  upper_constraint_message_ = "Initial time step set by user.";
341 
342  //time_step_=dt;
343 }
344 
345 
346 // steady time governor constructor
348 : dt_limits_pos_(0), timestep_output_(false)
349 {
350  // use new mark type as default
351  if (eq_mark_type == TimeMark::none_type) eq_mark_type = marks().new_mark_type();
352 
353  time_unit_conversion_ = std::make_shared<TimeUnitConversion>();
354  init_common(init_time, inf_time, eq_mark_type);
355 
356  // fill table limits with two records (start time, end time)
357  dt_limits_table_.push_back( DtLimitRow(init_time, min_time_step_, max_time_step_) );
359 
360  steady_ = true;
361 }
362 
363 
365 {
367  timesteps_output_.close();
368  }
369 }
370 
371 
372 // common part of constructors
374 {
375 
376  if (init_time < 0.0) {
377  THROW(ExcTimeGovernorMessage()
378  << EI_Message("Start time has to be greater or equal to 0.0\n")
379 
380  );
381  }
382 
383  recent_steps_.set_capacity(size_of_recent_steps_);
384  recent_steps_.push_front(TimeStep(init_time, time_unit_conversion_));
386 
387  if (end_time < init_time) {
388  THROW(ExcTimeGovernorMessage() << EI_Message("End time must be greater than start time.\n") );
389  } else {
391  }
392 
393  //if (dt == 0.0) {
394  // variable time step
395  fixed_time_step_=0.0;
396  is_time_step_fixed_=false;
397  time_step_changed_=true;
399 
401  lower_constraint_message_ = "Permanent minimal constraing, default, time_step_precision.";
403  upper_constraint_message_ = "Permanent maximal constraint, default, total simulation time.";
404  // choose maximum possible time step
405  //time_step_=max_time_step_;
406  /*} else {
407  // fixed time step
408  if (dt < time_step_lower_bound)
409  THROW(ExcTimeGovernorMessage() << EI_Message("Fixed time step smaller then machine precision. \n") );
410 
411  fixed_time_step_=dt;
412  is_time_step_fixed_=true;
413  time_step_changed_=true;
414  end_of_fixed_dt_interval_ = inf_time;
415 
416  upper_constraint_=max_time_step_=dt;
417  lower_constraint_=min_time_step_=dt;
418  time_step_=dt;
419 
420  }*/
421 
422  eq_mark_type_=type;
423  steady_=false;
425  //if (end_time_ != inf_time)
427 }
428 
429 
430 
431 void TimeGovernor::set_dt_limits( double min_dt, double max_dt, Input::Array dt_limits_list)
432 {
433  dt_limits_table_.clear();
434 
435  // check min_dt and max_dt set by user
436  if (min_dt < time_step_precision) {
437  THROW(ExcTimeGovernorMessage() << EI_Message("'min_dt' smaller than machine precision.\n") );
438  }
439  if (max_dt < min_dt) {
440  THROW(ExcTimeGovernorMessage() << EI_Message("'max_dt' smaller than 'min_dt'.\n") );
441  }
442 
443  bool first_step = true;
444  if (dt_limits_list.size())
445  for(auto it = dt_limits_list.begin<Input::Tuple>(); it != dt_limits_list.end(); ++it) {
446  double time = read_time( it->find<Input::Tuple>("time"));
447 
448  if (first_step) { // we need special check before setting first time step to the table
449  if (time > init_time_) { // table starts later than simulation, we need to add start time to the table
450  dt_limits_table_.push_back( DtLimitRow(init_time_, min_dt, max_dt) );
451  }
452  first_step = false;
453  }
454 
455  // next cases will be skipped
456  if (time < init_time_) {
457  WarningOut().fmt("Time {} define in 'dt_limits' table at address {} is lesser than start time of simulation "
458  "and can be skipped.\n", time, dt_limits_list.address_string());
459  }
460  if (dt_limits_table_.size() && (time <= dt_limits_table_[dt_limits_table_.size()-1].time) ) {
461  WarningOut().fmt("Time {} define in 'dt_limits' table at address {} is in incorrect order "
462  "and will be skipped.\n", time, dt_limits_list.address_string());
463  continue;
464  }
465  if ((time > end_time_) ) {
466  WarningOut().fmt("Time {} define in 'dt_limits' table at address {} is greater than end time of simulation "
467  "and will be skipped.\n", time, dt_limits_list.address_string());
468  continue;
469  }
470 
471  double min = read_time( it->find<Input::Tuple>("min_dt"), 0.0);
472  if (min == 0.0) min = min_dt;
473  double max = read_time( it->find<Input::Tuple>("max_dt"), 0.0);
474  if (max == 0.0) max = max_dt;
475 
476  if (min < time_step_precision) {
477  THROW(ExcTimeGovernorMessage() << EI_Message("'min_dt' in 'dt_limits' smaller than machine precision.\n") );
478  }
479  if (max < min) {
480  THROW(ExcTimeGovernorMessage() << EI_Message("'max_dt' in 'dt_limits' smaller than 'min_dt'.\n") );
481  }
482 
483  dt_limits_table_.push_back( DtLimitRow(time, min, max) );
484  if (limits_time_marks_) this->marks().add(TimeMark(time, this->equation_fixed_mark_type()));
485  }
486 
487  if (dt_limits_table_.size() == 0) {
488  // add start time to limit table if it is empty
489  dt_limits_table_.push_back( DtLimitRow(init_time_, min_dt, max_dt) );
490  }
491  if (dt_limits_table_[dt_limits_table_.size()-1].time < end_time_) {
492  // add time == end_time_ to limits table, we need only for check time, not for limits
493  dt_limits_table_.push_back( DtLimitRow(end_time_, min_dt, max_dt) );
494  }
495 
496  dt_limits_pos_ = 0;
497  while (dt_limits_table_[dt_limits_pos_+1].time <= init_time_) {
498  ++dt_limits_pos_;
499  }
500 
502 }
503 
504 
506 {
508  lower_constraint_message_ = "Permanent minimal constraint, custom.";
510  upper_constraint_message_ = "Permanent maximal constraint, custom.";
511  ++dt_limits_pos_;
512 }
513 
514 
515 // int set_constrain - dle nastaveni constraint
516 // interval - constraint - jako v cmp u Qsortu
517 // -1 vetsi nez interval (min_dt,max_dt)
518 // +1 mensi
519 // 0 OK
520 
521 int TimeGovernor::set_upper_constraint (double upper, std::string message)
522 {
523  if (upper_constraint_ < upper) {
524  //do not change upper_constraint_
525  return -1;
526  } else
527  if (lower_constraint_ > upper) {
528  // set upper constraint to the lower constraint
530  upper_constraint_message_ = "Forced lower constraint. " + message;
531  return 1;
532  } else {
533  //change upper_constraint_ to upper
534  upper_constraint_ = upper;
535  upper_constraint_message_ = message;
536  return 0;
537  }
538 }
539 
540 
541 
542 int TimeGovernor::set_lower_constraint (double lower, std::string message)
543 {
544  if (upper_constraint_ < lower) {
545  // set lower constraint to the upper constraint
547  return -1;
548  } else
549  if (lower_constraint_ > lower) {
550  //do not change lower_constraint_
551  return 1;
552  } else {
553  //change lower_constraint_ to lower
554  lower_constraint_ = lower;
555  lower_constraint_message_ = message;
556  return 0;
557  }
558 }
559 
560 
561 
562 
564  if (steady_) return 0.0;
565  end_of_fixed_dt_interval_=-inf_time; // release previous fixed interval
567  is_time_step_fixed_ = true; //flag means fixed step has been set since now
569 }
570 
571 
572 
573 
575 {
576  if (end_time() == inf_time) {
577  THROW(ExcTimeGovernorMessage()
578  << EI_Message("Missing end time for making output grid required by key 'time_step' of the output stream.\n")
579  );
580  }
581 
582  marks().add_time_marks(init_time_, step, end_time(), mark_type | eq_mark_type_);
583  // always add start time and end time
584  marks().add(TimeMark(init_time_, mark_type | eq_mark_type_));
585  marks().add(TimeMark(end_time(), mark_type | eq_mark_type_));
586 }
587 
588 
590 {
591  TimeMark::Type type = equation_mark_type() | mask;
592  return time_marks_.current(step(), type) != time_marks_.end(type);
593 }
594 
595 
596 
598  if (is_end()) return 0.0;
599 
600  if (this->step().lt(end_of_fixed_dt_interval_)) return fixed_time_step_;
601 
602  // jump to the first future fix time
604  // compute step to next fix time and apply constraints
605  double full_step = fix_time_it->time() - t();
606 
607  double step_estimate = min(full_step, upper_constraint_);
608  step_estimate = max(step_estimate, lower_constraint_); //these two must be in this order
609 
610  if (step_estimate == inf_time) return step_estimate;
611 
612  // round the time step to have integer number of steps till next fix time
613  // this always selects shorter time step,
614  // but allows time step larger then constraint by a number close to machine epsilon
615  //
616  double n_steps = ceil( full_step / step_estimate - time_step_precision);
617  step_estimate = full_step / n_steps;
618 
619  // try to avoid time_step changes
620  if (n_steps > 1 && abs(step_estimate - step().length()) < time_step_precision) {
621  step_estimate=step().length();
622  }
623 
624  // if the step estimate gets by rounding lower than lower constraint program will not crash
625  // will just output a user warning.
626  if (step_estimate < lower_constraint_) {
627  DebugOut().fmt("Time step estimate is below the lower constraint of time step. The difference is: {:.16f}.\n",
628  lower_constraint_ - step_estimate);
629  }
630 
631  return step_estimate;
632 }
633 
634 
635 
637 {
638  OLD_ASSERT_LE(0.0, t());
639  if (is_end()) return;
640 
641 
642  if (this->step().lt(end_of_fixed_dt_interval_)) {
643  // this is done for fixed step
644  // make tiny correction of time step in order to avoid big rounding errors
645  // tiny correction means that dt_changed 'is NOT changed'
648  }
649 
650  recent_steps_.push_front(recent_steps_.front().make_next(fixed_time_step_));
651 
652 
653  //checking whether fixed time step has been changed (by fix_dt_until_mark() method) since last time
655  {
656  is_time_step_fixed_ = false;
657 
658  //is true unless new fixed_dt is not equal previous time_step
659  time_step_changed_ = (step(-2).length() != step().length());
660  }
661  else
662  time_step_changed_ = false;
663  }
664  else
665  {
666  // this is done if end_of_fixed_dt_interval is not set (means it is equal to -infinity)
667  double dt=estimate_dt();
668  TimeStep step_ = recent_steps_.front().make_next(dt);
669  //DebugOut().fmt("step: {}, end: {}\n", step_.length(), step_.end());
670  recent_steps_.push_front(step_);
671  //DebugOut().fmt("last: {}, new: {}\n",step(-1).length(),step().length());
672  time_step_changed_= (step(-2).length() != step().length());
673  }
674 
677  // refreshing the upper_constraint_
680  lower_constraint_message_ = "Permanent minimal constraint, in next time.";
681  upper_constraint_message_ = "Permanent maximal constraint, in next time.";
682 
684 
685  // write time step to YAML file
687  double time = t();
688  if (time > last_printed_timestep_) {
689  if (is_end()) timesteps_output_ << "- [ " << time << ", 0, 0 ]\n";
690  else timesteps_output_ << "- [ " << time << ", " << lower_constraint_ << ", " << upper_constraint_ << " ]\n";
691  last_printed_timestep_ = time;
692  }
693  }
694 }
695 
696 
697 double TimeGovernor::reduce_timestep(double factor) {
698  double prior_dt = dt();
699  double new_upper_constraint = factor * dt();
700 
701  // Revert time.
702 // DebugOut().fmt("tg idx: {}\n", recent_steps_.front().index());
703  recent_steps_.pop_front();
704 // DebugOut().fmt("tg idx: {}\n", recent_steps_.back().index());
707 
708  // Set constraint.
709  int current_minus_new = set_upper_constraint(new_upper_constraint, "Reduce time step.");
710  if (current_minus_new < 0)
711  // current constraint < reduced dt, should not happen
712  THROW(ExcMessage() << EI_Message("Internal error."));
713 
714  next_time();
715 
716  // Return false if we hit lower time step constraint.
717  return dt() / prior_dt;
718 }
719 
720 
721 
722 const TimeStep &TimeGovernor::step(int index) const {
723  unsigned int back_idx;
724  if (index < 0) {
725  back_idx = static_cast<unsigned int>(-index-1);
726  } else {
727  back_idx = static_cast<unsigned int>(recent_steps_[0].index() - index);
728  }
729  if ( back_idx >= recent_steps_.size())
730  THROW(ExcMissingTimeStep() << EI_Index(index) << EI_BackIndex(back_idx) << EI_HistorySize(recent_steps_.size()));
731 
732  return recent_steps_[back_idx];
733 }
734 
735 
736 
737 
738 void TimeGovernor::view(const char *name) const
739 {
740  static char buffer[1024];
741 #ifdef FLOW123D_DEBUG_MESSAGES
742  MessageOut().fmt(
743  "TG[{}]:{:06d} t:{:10.4f} dt:{:10.6f} dt_int<{:10.6f},{:10.6f}> "
744  "end_time: {} end_fixed_time: {} type: {:#x}\n",
747 
748  MessageOut().fmt("Lower time step constraint [{}]: {} \nUpper time step constraint [{}]: {} \n",
751 #else
752  MessageOut().fmt(
753  "TG[{}]:{:06d} t:{:10.4f} dt:{:10.6f} dt_int<{:10.6f},{:10.6f}>\n",
754  name, tlevel(), t(), dt(), lower_constraint_, upper_constraint_);
755 
756  //sprintf(buffer, "TG[%s]:%06d t:%10.4f dt:%10.6f dt_int<%10.6f,%10.6f>\n",
757  // name, tlevel(), t(), dt(), lower_constraint_, upper_constraint_ );
758 #endif
759 }
760 
761 
762 
763 double TimeGovernor::read_time(Input::Iterator<Input::Tuple> time_it, double default_time) const {
764  return time_unit_conversion_->read_time(time_it, default_time);
765 }
766 
767 
768 
770  return time_unit_conversion_->read_coef(unit_it);
771 }
772 
773 
774 
775 double TimeGovernor::get_coef() const {
776  return time_unit_conversion_->get_coef();
777 }
778 
779 
780 
782  return time_unit_conversion_->get_unit_string();
783 }
784 
785 
786 
787 
788 ostream& operator<<(ostream& out, const TimeGovernor& tg)
789 {
790  static char buffer[1024];
791  sprintf(buffer, "\n%06d t:%10.4f dt:%10.6f dt_int<%10.6f,%10.6f>\n",
792  tg.tlevel(), tg.t(), tg.dt(), tg.lower_constraint(), tg.upper_constraint());
793  return (out << buffer);
794 }
795 
796 
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.