40 return Record(
"TimeGovernor",
41 "Setting of the simulation time. (can be specific to one equation)")
44 "Start time of the simulation.")
46 "End time of the simulation.")
48 "Initial guess for the time step.\n" 49 "Only useful for equations that use adaptive time stepping." 50 "If set to 0.0, the time step is determined in fully autonomous" 51 " way if the equation supports it.")
54 "Soft lower limit for the time step. Equation using adaptive time stepping can not" 55 "suggest smaller time step, but actual time step could be smaller in order to match " 56 "prescribed input or output times.")
59 "Hard upper limit for the time step. Actual length of the time step is also limited" 60 "by input and output times.")
124 init_common(input.
val<
double>(
"start_time"),
125 input.
val<
double>(
"end_time", inf_time),
127 set_permanent_constraint(
128 input.
val<
double>(
"min_dt", min_time_step_),
129 input.
val<
double>(
"max_dt", max_time_step_)
132 double init_dt=input.
val<
double>(
"init_dt");
136 lower_constraint_=init_dt;
137 lower_constraint_message_ =
"Initial time step set by user.";
138 upper_constraint_=init_dt;
139 upper_constraint_message_ =
"Initial time step set by user.";
143 }
catch(ExcTimeGovernorMessage &exc) {
154 if (dt < time_step_precision)
155 THROW(ExcTimeGovernorMessage() << EI_Message(
"Fixed time step smaller then machine precision. \n") );
158 is_time_step_fixed_=
true;
159 time_step_changed_=
true;
160 end_of_fixed_dt_interval_ = inf_time;
162 lower_constraint_=min_time_step_=dt;
163 lower_constraint_message_ =
"Initial time step set by user.";
164 upper_constraint_=max_time_step_=dt;
165 upper_constraint_message_ =
"Initial time step set by user.";
177 init_common(init_time, inf_time, eq_mark_type);
188 if (init_time < 0.0) {
189 THROW(ExcTimeGovernorMessage()
190 << EI_Message(
"Start time has to be greater or equal to 0.0\n")
195 recent_steps_.set_capacity(size_of_recent_steps_);
196 recent_steps_.push_front(
TimeStep(init_time));
197 init_time_=init_time;
199 if (end_time < init_time) {
200 THROW(ExcTimeGovernorMessage() << EI_Message(
"End time must be greater than start time.\n") );
202 end_time_ = end_time;
207 fixed_time_step_=0.0;
208 is_time_step_fixed_=
false;
209 time_step_changed_=
true;
210 end_of_fixed_dt_interval_ = init_time_;
212 min_time_step_=lower_constraint_=time_step_precision;
213 lower_constraint_message_ =
"Permanent minimal constraing, default, time_step_precision.";
214 if (end_time_ == inf_time) {
215 max_time_step_=upper_constraint_=inf_time;
217 max_time_step_=upper_constraint_= end_time - init_time_;
219 upper_constraint_message_ =
"Permanent maximal constraint, default, total simulation time.";
240 time_marks_.add(
TimeMark(init_time_, equation_fixed_mark_type()) );
241 if (end_time_ != inf_time)
242 time_marks_.add(
TimeMark(end_time_, equation_fixed_mark_type()) );
252 if (min_dt < time_step_precision) {
253 THROW(ExcTimeGovernorMessage() << EI_Message(
"'min_dt' smaller then machine precision.\n") );
255 if (max_dt < min_dt) {
256 THROW(ExcTimeGovernorMessage() << EI_Message(
"'max_dt' smaller then 'min_dt'.\n") );
259 lower_constraint_ = min_time_step_ = max(min_dt, time_step_precision);
260 lower_constraint_message_ =
"Permanent minimal constraint, custom.";
261 upper_constraint_ = max_time_step_ = min(max_dt, end_time_-t());
262 upper_constraint_message_ =
"Permanent maximal constraint, custom.";
275 if (upper_constraint_ < upper) {
279 if (lower_constraint_ > upper) {
281 upper_constraint_ = lower_constraint_;
282 upper_constraint_message_ =
"Forced lower constraint. " + message;
286 upper_constraint_ = upper;
287 upper_constraint_message_ = message;
296 if (upper_constraint_ < lower) {
298 lower_constraint_ = upper_constraint_;
301 if (lower_constraint_ > lower) {
306 lower_constraint_ = lower;
307 lower_constraint_message_ = message;
316 if (steady_)
return 0.0;
317 end_of_fixed_dt_interval_=-inf_time;
318 fixed_time_step_ = estimate_dt();
319 is_time_step_fixed_ =
true;
320 return end_of_fixed_dt_interval_ = time_marks_.next(*
this, equation_fixed_mark_type())->time();
328 if (end_time() == inf_time) {
329 THROW(ExcTimeGovernorMessage()
330 << EI_Message(
"Missing end time for making output grid required by key 'time_step' of the output stream.\n")
334 marks().add_time_marks(init_time_, step, end_time(), mark_type | eq_mark_type_);
336 marks().add(
TimeMark(init_time_, mark_type | eq_mark_type_));
337 marks().add(
TimeMark(end_time(), mark_type | eq_mark_type_));
343 if (is_end())
return 0.0;
345 if (this->step().
lt(end_of_fixed_dt_interval_))
return fixed_time_step_;
350 double full_step = fix_time_it->
time() - t();
352 double step_estimate = min(full_step, upper_constraint_);
353 step_estimate = max(step_estimate, lower_constraint_);
355 if (step_estimate == inf_time)
return step_estimate;
362 double n_steps = ceil( full_step / step_estimate - time_step_precision);
363 step_estimate = full_step / n_steps;
366 if (n_steps > 1 && abs(step_estimate - step().
length()) < time_step_precision) {
367 step_estimate=step().length();
372 if (step_estimate < lower_constraint_)
373 xprintf(
Warn,
"Time step estimate is below the lower constraint of time step. The difference is: %.16f.\n",
374 lower_constraint_ - step_estimate);
376 return step_estimate;
384 if (is_end())
return;
387 if (this->step().
lt(end_of_fixed_dt_interval_)) {
391 if (end_of_fixed_dt_interval_ < inf_time) {
392 fixed_time_step_ = (end_of_fixed_dt_interval_-t()) / round( (end_of_fixed_dt_interval_-t()) / fixed_time_step_ );
395 recent_steps_.push_front(recent_steps_.front().make_next(fixed_time_step_));
399 if (is_time_step_fixed_)
401 is_time_step_fixed_ =
false;
404 time_step_changed_ = (step(-2).length() != step().length());
407 time_step_changed_ =
false;
412 double dt=estimate_dt();
415 recent_steps_.push_front(step_);
417 time_step_changed_= (step(-2).length() != step().length());
420 last_lower_constraint_ = lower_constraint_;
421 last_upper_constraint_ = upper_constraint_;
423 upper_constraint_ = min(end_time_ - t(), max_time_step_);
424 lower_constraint_ = min_time_step_;
425 lower_constraint_message_ =
"Permanent minimal constraint, in next time.";
426 upper_constraint_message_ =
"Permanent maximal constraint, in next time.";
431 double prior_dt = dt();
432 double new_upper_constraint = factor * dt();
436 recent_steps_.pop_front();
438 upper_constraint_ = last_upper_constraint_;
439 lower_constraint_ = last_lower_constraint_;
442 int current_minus_new = set_upper_constraint(new_upper_constraint,
"Reduce time step.");
443 if (current_minus_new < 0)
445 THROW(ExcMessage() << EI_Message(
"Internal error."));
450 return dt() / prior_dt;
456 unsigned int back_idx;
458 back_idx =
static_cast<unsigned int>(-index-1);
460 back_idx =
static_cast<unsigned int>(recent_steps_[0].index() -
index);
462 if ( back_idx >= recent_steps_.size())
463 THROW(ExcMissingTimeStep() << EI_Index(index) << EI_BackIndex(back_idx) << EI_HistorySize(recent_steps_.size()));
465 return recent_steps_[back_idx];
473 xprintf(
Msg,
"\nTG[%s]:%06d t:%10.4f dt:%10.6f dt_int<%10.6f,%10.6f>",
474 name, tlevel(), t(), dt(), lower_constraint_, upper_constraint_ );
475 #ifdef FLOW123D_DEBUG_MESSAGES 476 xprintf(
Msg,
" end_time: %f end_fixed_time: %f type: 0x%x\n" , end_time_, end_of_fixed_dt_interval_, eq_mark_type_);
480 xprintf(
Msg,
"Lower time step constraint [%f]: %s \nUpper time step constraint [%f]: %s \n",
481 lower_constraint_, lower_constraint_message_.c_str(),
482 upper_constraint_, upper_constraint_message_.c_str() );
490 static char buffer[1024];
491 sprintf(buffer,
"\n%06d t:%10.4f dt:%10.6f dt_int<%10.6f,%10.6f>\n",
493 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.
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.
const TimeStep & step(int index=-1) const
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.
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
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.
ostream & operator<<(ostream &out, const TimeGovernor &tg)
Stream output operator for TimeGovernor.
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)
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.