30 #define MAX_END_TIME 5.0e+17 31 #define MAX_END_TIME_STR "5.0e+17" 42 return Record(
"TimeGovernor",
43 "Setting of the simulation time. (can be specific to one equation)")
46 "Start time of the simulation.")
48 "End time of the simulation. Default value is more then age of universe in seconds.")
50 "Initial guess for the time step.\n" 51 "Only useful for equations that use adaptive time stepping." 52 "If set to 0.0, the time step is determined in fully autonomous" 53 " way if the equation supports it.")
56 "Soft lower limit for the time step. Equation using adaptive time stepping can not" 57 "suggest smaller time step, but actual time step could be smaller in order to match " 58 "prescribed input or output times.")
61 "Hard upper limit for the time step. Actual length of the time step is also limited" 62 "by input and output times.")
120 out <<
"time: " << t_step.
end() <<
"step: " << t_step.
length() << endl;
133 double end_time = input.
val<
double>(
"end_time");
134 if (end_time> 0.99*max_end_time) end_time = max_end_time;
137 init_common(input.
val<
double>(
"start_time"),
140 set_permanent_constraint(
141 input.
val<
double>(
"min_dt", min_time_step_),
142 input.
val<
double>(
"max_dt", max_time_step_)
145 double init_dt=input.
val<
double>(
"init_dt");
149 lower_constraint_=init_dt;
150 lower_constraint_message_ =
"Initial time step set by user.";
151 upper_constraint_=init_dt;
152 upper_constraint_message_ =
"Initial time step set by user.";
156 }
catch(ExcTimeGovernorMessage &exc) {
167 if (dt < time_step_precision)
168 THROW(ExcTimeGovernorMessage() << EI_Message(
"Fixed time step smaller then machine precision. \n") );
171 is_time_step_fixed_=
true;
172 time_step_changed_=
true;
173 end_of_fixed_dt_interval_ = inf_time;
175 lower_constraint_=min_time_step_=dt;
176 lower_constraint_message_ =
"Initial time step set by user.";
177 upper_constraint_=max_time_step_=dt;
178 upper_constraint_message_ =
"Initial time step set by user.";
190 init_common(init_time, inf_time, eq_mark_type);
199 if (init_time < 0.0) {
200 THROW(ExcTimeGovernorMessage()
201 << EI_Message(
"Start time has to be greater or equal to 0.0\n")
206 recent_steps_.set_capacity(size_of_recent_steps_);
207 recent_steps_.push_front(
TimeStep(init_time));
208 init_time_=init_time;
210 if (end_time < init_time) {
211 THROW(ExcTimeGovernorMessage() << EI_Message(
"End time must be greater than start time.\n") );
213 end_time_ = end_time;
218 fixed_time_step_=0.0;
219 is_time_step_fixed_=
false;
220 time_step_changed_=
true;
221 end_of_fixed_dt_interval_ = init_time_;
223 min_time_step_=lower_constraint_=time_step_precision;
224 lower_constraint_message_ =
"Permanent minimal constraing, default, time_step_precision.";
225 max_time_step_=upper_constraint_= end_time - init_time_;
226 upper_constraint_message_ =
"Permanent maximal constraint, default, total simulation time.";
247 time_marks_.add(
TimeMark(init_time_, equation_fixed_mark_type()) );
249 time_marks_.add(
TimeMark(end_time_, equation_fixed_mark_type()) );
259 if (min_dt < time_step_precision) {
260 THROW(ExcTimeGovernorMessage() << EI_Message(
"'min_dt' smaller then machine precision.\n") );
262 if (max_dt < min_dt) {
263 THROW(ExcTimeGovernorMessage() << EI_Message(
"'max_dt' smaller then 'min_dt'.\n") );
266 lower_constraint_ = min_time_step_ = max(min_dt, time_step_precision);
267 lower_constraint_message_ =
"Permanent minimal constraint, custom.";
268 upper_constraint_ = max_time_step_ = min(max_dt, end_time_-t());
269 upper_constraint_message_ =
"Permanent maximal constraint, custom.";
282 if (upper_constraint_ < upper) {
286 if (lower_constraint_ > upper) {
288 upper_constraint_ = lower_constraint_;
289 upper_constraint_message_ =
"Forced lower constraint. " + message;
293 upper_constraint_ = upper;
294 upper_constraint_message_ = message;
303 if (upper_constraint_ < lower) {
305 lower_constraint_ = upper_constraint_;
308 if (lower_constraint_ > lower) {
313 lower_constraint_ = lower;
314 lower_constraint_message_ = message;
323 if (steady_)
return 0.0;
324 end_of_fixed_dt_interval_=-inf_time;
325 fixed_time_step_ = estimate_dt();
326 is_time_step_fixed_ =
true;
327 return end_of_fixed_dt_interval_ = time_marks_.next(*
this, equation_fixed_mark_type())->time();
335 if (end_time() == inf_time) {
336 THROW(ExcTimeGovernorMessage()
337 << EI_Message(
"Missing end time for making output grid required by key 'time_step' of the output stream.\n")
341 marks().add_time_marks(init_time_, step, end_time(), mark_type | eq_mark_type_);
343 marks().add(
TimeMark(init_time_, mark_type | eq_mark_type_));
344 marks().add(
TimeMark(end_time(), mark_type | eq_mark_type_));
351 return time_marks_.current(step(), type) != time_marks_.end(type);
357 if (is_end())
return 0.0;
359 if (this->step().
lt(end_of_fixed_dt_interval_))
return fixed_time_step_;
364 double full_step = fix_time_it->
time() - t();
366 double step_estimate = min(full_step, upper_constraint_);
367 step_estimate = max(step_estimate, lower_constraint_);
369 if (step_estimate == inf_time)
return step_estimate;
375 double n_steps = ceil( full_step / step_estimate - time_step_precision);
376 step_estimate = full_step / n_steps;
379 if (n_steps > 1 && abs(step_estimate - step().
length()) < time_step_precision) {
380 step_estimate=step().length();
385 if (step_estimate < lower_constraint_) {
386 DebugOut().fmt(
"Time step estimate is below the lower constraint of time step. The difference is: {:.16f}.\n",
387 lower_constraint_ - step_estimate);
390 return step_estimate;
398 if (is_end())
return;
401 if (this->step().
lt(end_of_fixed_dt_interval_)) {
405 if (end_of_fixed_dt_interval_ < inf_time) {
406 fixed_time_step_ = (end_of_fixed_dt_interval_-t()) / round( (end_of_fixed_dt_interval_-t()) / fixed_time_step_ );
409 recent_steps_.push_front(recent_steps_.front().make_next(fixed_time_step_));
413 if (is_time_step_fixed_)
415 is_time_step_fixed_ =
false;
418 time_step_changed_ = (step(-2).length() != step().length());
421 time_step_changed_ =
false;
426 double dt=estimate_dt();
429 recent_steps_.push_front(step_);
431 time_step_changed_= (step(-2).length() != step().length());
434 last_lower_constraint_ = lower_constraint_;
435 last_upper_constraint_ = upper_constraint_;
437 upper_constraint_ = min(end_time_ - t(), max_time_step_);
438 lower_constraint_ = min_time_step_;
439 lower_constraint_message_ =
"Permanent minimal constraint, in next time.";
440 upper_constraint_message_ =
"Permanent maximal constraint, in next time.";
445 double prior_dt = dt();
446 double new_upper_constraint = factor * dt();
450 recent_steps_.pop_front();
452 upper_constraint_ = last_upper_constraint_;
453 lower_constraint_ = last_lower_constraint_;
456 int current_minus_new = set_upper_constraint(new_upper_constraint,
"Reduce time step.");
457 if (current_minus_new < 0)
459 THROW(ExcMessage() << EI_Message(
"Internal error."));
464 return dt() / prior_dt;
470 unsigned int back_idx;
472 back_idx =
static_cast<unsigned int>(-index-1);
474 back_idx =
static_cast<unsigned int>(recent_steps_[0].index() -
index);
476 if ( back_idx >= recent_steps_.size())
477 THROW(ExcMissingTimeStep() << EI_Index(index) << EI_BackIndex(back_idx) << EI_HistorySize(recent_steps_.size()));
479 return recent_steps_[back_idx];
487 static char buffer[1024];
488 #ifdef FLOW123D_DEBUG_MESSAGES 490 "TG[{}]:{:06d} t:{:10.4f} dt:{:10.6f} dt_int<{:10.6f},{:10.6f}> " 491 "end_time: {} end_fixed_time: {} type: {:#x}\n",
492 name, tlevel(), t(), dt(), lower_constraint_, upper_constraint_,
493 end_time_, end_of_fixed_dt_interval_, eq_mark_type_.bitmap_);
495 MessageOut().fmt(
"Lower time step constraint [{}]: {} \nUpper time step constraint [{}]: {} \n",
496 lower_constraint_, lower_constraint_message_.c_str(),
497 upper_constraint_, upper_constraint_message_.c_str() );
500 "TG[{}]:{:06d} t:{:10.4f} dt:{:10.6f} dt_int<{:10.6f},{:10.6f}>\n",
501 name, tlevel(), t(), dt(), lower_constraint_, upper_constraint_);
513 static char buffer[1024];
514 sprintf(buffer,
"\n%06d t:%10.4f dt:%10.6f dt_int<%10.6f,%10.6f>\n",
516 return (out << buffer);
Iterator over TimeMark objects in TimeMarks object (database of TimeMark objects).
double reduce_timestep(double factor)
Force timestep reduction in particular in the case of failure of the non-linear solver.
static TimeMarks time_marks_
bool lt(double other_time) const
double upper_constraint() const
TimeGovernor(const Input::Record &input, TimeMark::Type fixed_time_mask=TimeMark::none_type)
Constructor for unsteady solvers.
#define MessageOut()
Macro defining 'message' record of log.
double fix_dt_until_mark()
Fixing time step until fixed time mark.
int set_lower_constraint(double lower, std::string message)
Sets lower constraint for the next time step estimating.
void set_permanent_constraint(double min_dt, double max_dt)
Sets permanent constraints for time step.
void next_time()
Proceed to the next time according to current estimated time step.
bool is_current(const TimeMark::Type &mask) const
const TimeStep & step(int index=-1) const
static const double max_end_time
Basic time management functionality for unsteady (and steady) solvers (class Equation).
static const Type none_type
Mark Type with all bits unset.
Basic time management class.
static const Type every_type
Mark Type with all bits set.
double estimate_dt() const
Estimate choice of next time step according to actual setting of constraints.
void view(const char *name="") const
void add_time_marks_grid(double step, TimeMark::Type mark_type=TimeMark::none_type) const
std::string sprintf(CStringRef format, ArgList args)
static const double time_step_precision
double lower_constraint() 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...
TimeStep make_next(double new_length) const
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 ...
bool safe_compare(double t1, double t0) const
double time() const
Getter for the time of the TimeMark.
static const Input::Type::Record & get_input_type()
unsigned int index() const
Class used for marking specified times at which some events occur.
#define OLD_ASSERT_LE(a, b)
ostream & operator<<(ostream &out, const TimeStep &t_step)
#define DebugOut()
Macro defining 'debug' record of log.
static const double inf_time
Infinity time used for steady case.
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Representation of one time step..
double end_
End time point of the time step.