30 #define MAX_END_TIME 5.0e+17 31 #define MAX_END_TIME_STR "5.0e+17" 42 return Record(
"TimeGovernor",
43 "Time axis settings of the simulation.\n" 44 "The settings is specific to a particular equation.")
47 "Start time of the simulation.")
49 "End time of the simulation.\n" 50 "The default value is higher than the age of the Universe (given in seconds).")
52 "Initial guess for the time step.\n" 53 "It applies to equations that use an adaptive time stepping." 54 "If set to 0.0, the time step is determined in fully autonomous" 55 " way, assuming the equation supports it.")
58 "Soft lower limit for the time step.\n" 59 "Equation using an adaptive time stepping cannot suggest smaller time step." 60 "The actual time step can only decrease below the limit in order to match " 61 "the prescribed input or output times.")
64 "Hard upper limit for the time step.\n" 65 "The actual time step can only increase above the limit in order to match " 66 "the prescribed input or output times.")
124 out <<
"time: " << t_step.
end() <<
"step: " << t_step.
length() << endl;
137 double end_time = input.
val<
double>(
"end_time");
138 if (end_time> 0.99*max_end_time) end_time = max_end_time;
141 init_common(input.
val<
double>(
"start_time"),
144 set_permanent_constraint(
145 input.
val<
double>(
"min_dt", min_time_step_),
146 input.
val<
double>(
"max_dt", max_time_step_)
149 double init_dt=input.
val<
double>(
"init_dt");
153 lower_constraint_=init_dt;
154 lower_constraint_message_ =
"Initial time step set by user.";
155 upper_constraint_=init_dt;
156 upper_constraint_message_ =
"Initial time step set by user.";
160 }
catch(ExcTimeGovernorMessage &exc) {
171 if (dt < time_step_precision)
172 THROW(ExcTimeGovernorMessage() << EI_Message(
"Fixed time step smaller then machine precision. \n") );
175 is_time_step_fixed_=
true;
176 time_step_changed_=
true;
177 end_of_fixed_dt_interval_ = inf_time;
179 lower_constraint_=min_time_step_=dt;
180 lower_constraint_message_ =
"Initial time step set by user.";
181 upper_constraint_=max_time_step_=dt;
182 upper_constraint_message_ =
"Initial time step set by user.";
194 init_common(init_time, inf_time, eq_mark_type);
203 if (init_time < 0.0) {
204 THROW(ExcTimeGovernorMessage()
205 << EI_Message(
"Start time has to be greater or equal to 0.0\n")
210 recent_steps_.set_capacity(size_of_recent_steps_);
211 recent_steps_.push_front(
TimeStep(init_time));
212 init_time_=init_time;
214 if (end_time < init_time) {
215 THROW(ExcTimeGovernorMessage() << EI_Message(
"End time must be greater than start time.\n") );
217 end_time_ = end_time;
222 fixed_time_step_=0.0;
223 is_time_step_fixed_=
false;
224 time_step_changed_=
true;
225 end_of_fixed_dt_interval_ = init_time_;
227 min_time_step_=lower_constraint_=time_step_precision;
228 lower_constraint_message_ =
"Permanent minimal constraing, default, time_step_precision.";
229 max_time_step_=upper_constraint_= end_time - init_time_;
230 upper_constraint_message_ =
"Permanent maximal constraint, default, total simulation time.";
251 time_marks_.add(
TimeMark(init_time_, equation_fixed_mark_type()) );
253 time_marks_.add(
TimeMark(end_time_, equation_fixed_mark_type()) );
263 if (min_dt < time_step_precision) {
264 THROW(ExcTimeGovernorMessage() << EI_Message(
"'min_dt' smaller then machine precision.\n") );
266 if (max_dt < min_dt) {
267 THROW(ExcTimeGovernorMessage() << EI_Message(
"'max_dt' smaller then 'min_dt'.\n") );
270 lower_constraint_ = min_time_step_ = max(min_dt, time_step_precision);
271 lower_constraint_message_ =
"Permanent minimal constraint, custom.";
272 upper_constraint_ = max_time_step_ = min(max_dt, end_time_-t());
273 upper_constraint_message_ =
"Permanent maximal constraint, custom.";
286 if (upper_constraint_ < upper) {
290 if (lower_constraint_ > upper) {
292 upper_constraint_ = lower_constraint_;
293 upper_constraint_message_ =
"Forced lower constraint. " + message;
297 upper_constraint_ = upper;
298 upper_constraint_message_ = message;
307 if (upper_constraint_ < lower) {
309 lower_constraint_ = upper_constraint_;
312 if (lower_constraint_ > lower) {
317 lower_constraint_ = lower;
318 lower_constraint_message_ = message;
327 if (steady_)
return 0.0;
328 end_of_fixed_dt_interval_=-inf_time;
329 fixed_time_step_ = estimate_dt();
330 is_time_step_fixed_ =
true;
331 return end_of_fixed_dt_interval_ = time_marks_.next(*
this, equation_fixed_mark_type())->time();
339 if (end_time() == inf_time) {
340 THROW(ExcTimeGovernorMessage()
341 << EI_Message(
"Missing end time for making output grid required by key 'time_step' of the output stream.\n")
345 marks().add_time_marks(init_time_, step, end_time(), mark_type | eq_mark_type_);
347 marks().add(
TimeMark(init_time_, mark_type | eq_mark_type_));
348 marks().add(
TimeMark(end_time(), mark_type | eq_mark_type_));
355 return time_marks_.current(step(), type) != time_marks_.end(type);
361 if (is_end())
return 0.0;
363 if (this->step().
lt(end_of_fixed_dt_interval_))
return fixed_time_step_;
368 double full_step = fix_time_it->
time() - t();
370 double step_estimate = min(full_step, upper_constraint_);
371 step_estimate = max(step_estimate, lower_constraint_);
373 if (step_estimate == inf_time)
return step_estimate;
379 double n_steps = ceil( full_step / step_estimate - time_step_precision);
380 step_estimate = full_step / n_steps;
383 if (n_steps > 1 && abs(step_estimate - step().
length()) < time_step_precision) {
384 step_estimate=step().length();
389 if (step_estimate < lower_constraint_) {
390 DebugOut().fmt(
"Time step estimate is below the lower constraint of time step. The difference is: {:.16f}.\n",
391 lower_constraint_ - step_estimate);
394 return step_estimate;
402 if (is_end())
return;
405 if (this->step().
lt(end_of_fixed_dt_interval_)) {
409 if (end_of_fixed_dt_interval_ < inf_time) {
410 fixed_time_step_ = (end_of_fixed_dt_interval_-t()) / round( (end_of_fixed_dt_interval_-t()) / fixed_time_step_ );
413 recent_steps_.push_front(recent_steps_.front().make_next(fixed_time_step_));
417 if (is_time_step_fixed_)
419 is_time_step_fixed_ =
false;
422 time_step_changed_ = (step(-2).length() != step().length());
425 time_step_changed_ =
false;
430 double dt=estimate_dt();
433 recent_steps_.push_front(step_);
435 time_step_changed_= (step(-2).length() != step().length());
438 last_lower_constraint_ = lower_constraint_;
439 last_upper_constraint_ = upper_constraint_;
441 upper_constraint_ = min(end_time_ - t(), max_time_step_);
442 lower_constraint_ = min_time_step_;
443 lower_constraint_message_ =
"Permanent minimal constraint, in next time.";
444 upper_constraint_message_ =
"Permanent maximal constraint, in next time.";
449 double prior_dt = dt();
450 double new_upper_constraint = factor * dt();
454 recent_steps_.pop_front();
456 upper_constraint_ = last_upper_constraint_;
457 lower_constraint_ = last_lower_constraint_;
460 int current_minus_new = set_upper_constraint(new_upper_constraint,
"Reduce time step.");
461 if (current_minus_new < 0)
463 THROW(ExcMessage() << EI_Message(
"Internal error."));
468 return dt() / prior_dt;
474 unsigned int back_idx;
476 back_idx =
static_cast<unsigned int>(-index-1);
478 back_idx =
static_cast<unsigned int>(recent_steps_[0].index() -
index);
480 if ( back_idx >= recent_steps_.size())
481 THROW(ExcMissingTimeStep() << EI_Index(index) << EI_BackIndex(back_idx) << EI_HistorySize(recent_steps_.size()));
483 return recent_steps_[back_idx];
491 static char buffer[1024];
492 #ifdef FLOW123D_DEBUG_MESSAGES 494 "TG[{}]:{:06d} t:{:10.4f} dt:{:10.6f} dt_int<{:10.6f},{:10.6f}> " 495 "end_time: {} end_fixed_time: {} type: {:#x}\n",
496 name, tlevel(), t(), dt(), lower_constraint_, upper_constraint_,
497 end_time_, end_of_fixed_dt_interval_, eq_mark_type_.bitmap_);
499 MessageOut().fmt(
"Lower time step constraint [{}]: {} \nUpper time step constraint [{}]: {} \n",
500 lower_constraint_, lower_constraint_message_.c_str(),
501 upper_constraint_, upper_constraint_message_.c_str() );
504 "TG[{}]:{:06d} t:{:10.4f} dt:{:10.6f} dt_int<{:10.6f},{:10.6f}>\n",
505 name, tlevel(), t(), dt(), lower_constraint_, upper_constraint_);
517 static char buffer[1024];
518 sprintf(buffer,
"\n%06d t:%10.4f dt:%10.6f dt_int<%10.6f,%10.6f>\n",
520 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.