class TimestepControl : public Subscriptor
{
public:
- /**
- * The time stepping strategies. These are controlled by the value of
- * tolerance() and start_step().
- */
- enum Strategy
- {
- /**
- * Choose a uniform time step size. The step size is determined by
- * start_step(), tolerance() is ignored.
- */
- uniform,
- /**
- * Start with the time step size given by start_step() and double it in
- * every step. tolerance() is ignored.
- *
- * This strategy is intended for pseudo-timestepping schemes computing a
- * stationary limit.
- */
- doubling
- };
-
/**
* Constructor setting default values
*/
*/
void
tolerance(double);
- /**
- * Set strategy.
- */
- void strategy(Strategy);
/**
* Set size of the first step. This may be overwritten by the time
*/
double tolerance_val;
- /**
- * Time-stepping strategy.
- */
- Strategy strategy_val;
-
/**
* The size of the first step.
*/
}
- inline void
- TimestepControl::strategy(Strategy t)
- {
- strategy_val = t;
- }
-
-
inline void
TimestepControl::start_step(const double t)
{
: start_val(start)
, final_val(final)
, tolerance_val(tolerance)
- , strategy_val(uniform)
, start_step_val(start_step)
, max_step_val(max_step)
, min_step_val(0)
param.declare_entry("Max step", "1.", Patterns::Double(0.));
param.declare_entry("Tolerance", "1.e-2", Patterns::Double(0.));
param.declare_entry("Print step", "-1.", Patterns::Double());
- param.declare_entry("Strategy",
- "uniform",
- Patterns::Selection("uniform|doubling"));
}
max_step(param.get_double("Max step"));
final(param.get_double("Final"));
tolerance(param.get_double("Tolerance"));
- print_step = param.get_double("Print step");
- const std::string strategy = param.get("Strategy");
- if (strategy == std::string("uniform"))
- strategy_val = uniform;
- else if (strategy == std::string("doubling"))
- strategy_val = doubling;
- restart();
+ print_step = param.get_double("Print step");
}
bool
TimestepControl::advance()
{
- bool changed = false;
- double s = step_val;
-
- // Do time step control, but not in
- // first step.
- if (now_val != start())
- {
- if (strategy_val == doubling && 2 * s <= tolerance_val)
- s *= 2;
- if (s > max_step_val)
- s = max_step_val;
- }
+ bool changed = false;
// Try incrementing time by s
- double h = now_val + s;
- changed = s != step_val;
-
- step_val = s;
- current_step_val = s;
- // If we just missed the final
- // time, increase the step size a
- // bit. This way, we avoid a very
- // small final step. If the step
- // shot over the final time, adjust
- // it so we hit the final time
- // exactly.
- double s1 = .01 * s;
- if (h > final_val - s1)
+ double now_trial = now_val + step_val;
+ current_step_val = step_val;
+
+ // If we just missed the final time, increase the step size a bit. This way,
+ // we avoid a very small final step. If the step shot over the final time,
+ // adjust it so we hit the final time exactly.
+ double s1 = .01 * step_val;
+ if (now_trial > final_val - s1)
{
current_step_val = final_val - now_val;
- h = final_val;
+ now_trial = final_val;
changed = true;
}
- now_val = h;
+ now_val = now_trial;
return changed;
}