// @sect4{TwoPhaseFlowProblem::TwoPhaseFlowProblem}
// First for the constructor. We use $RT_k \times DQ_k \times DQ_k$
- // spaces. The time step is set to zero initially, but will be computed
- // before it is needed first, as described in a subsection of the
- // introduction. The time object internally prevents itself from being
- // incremented with $dt = 0$, forcing us to set a non-zero desired size for
+ // spaces. For initializing the DiscreteTime object, we don't set the time
+ // step size in the constructor because we don't have its value yet.
+ // The time step size is initially set to zero, but it will be computed
+ // before it is needed to increment time, as described in a subsection of
+ // the introduction. The time object internally prevents itself from being
+ // incremented when $dt = 0$, forcing us to set a non-zero desired size for
// $dt$ before advancing time.
template <int dim>
TwoPhaseFlowProblem<dim>::TwoPhaseFlowProblem(const unsigned int degree)
1)
, dof_handler(triangulation)
, n_refinement_steps(5)
- , time(/*start time*/ 0., /*end time*/ 1., /*time step*/ 0.)
+ , time(/*start time*/ 0., /*end time*/ 1.)
, viscosity(0.2)
{}
//
// The maximal velocity we compute using a helper function to compute the
// maximal velocity defined below, and with all this we can evaluate our
- // new time step length. The method DiscreteTime::set_next_time_step() is
- // used to assign the new value of the time step to the DiscreteTime
- // object.
- time.set_next_step_size(std::pow(0.5, double(n_refinement_steps)) /
- get_maximal_velocity());
+ // new time step length. We use the method
+ // DiscreteTime::set_desired_next_time_step() to suggest the new
+ // calculated value of the time step to the DiscreteTime object. In most
+ // cases, the time object uses the exact provided value to increment time.
+ // It some case, the step size may be modified further by the time object.
+ // For example, if the calculated time increment overshoots the end time,
+ // it is truncated accordingly.
+ time.set_desired_next_step_size(std::pow(0.5, double(n_refinement_steps)) /
+ get_maximal_velocity());
// The next step is to assemble the right hand side, and then to pass
// everything on for solution. At the end, we project back saturations
/**
* Constructor.
*
- * @pre @p start_step_size must be non-negative.
+ * @param[in] start_time The time at the start of the simulation.
*
- * @note If @p start_step_size is specified as zero, it indicates that the
+ * @param[in] end_time The time at the end of the simulation.
+ *
+ * @param[in] desired_start_step_size A desired step size for incrementing
+ * time for the first step. It is not guaranteed that this value will be
+ * actually used as the size of the first step, as discussed in the
+ * introduction.
+ *
+ * @pre @p desired_start_step_size must be non-negative.
+ *
+ * @note @p desired_start_step_size is an optional parameter. If it is not
+ * provided or it is specified as zero, it indicates that the
* desired size for the time step will be calculated at a different location
* in the code. In this case, the created object cannot increment time until
* the step size is changed by calling set_desired_next_step_size().
*/
DiscreteTime(const double start_time,
const double end_time,
- const double start_step_size);
+ const double desired_start_step_size = 0.);
/**
* Return the current time.
get_step_number() const;
/**
- * Set the value of the next time step size. The next time advance_time()
- * is called, the newly set @p time_step_size will be used to advance
- * the simulation time. However, if the step is too large such that the next
+ * Set the *desired* value of the next time step size. By calling this
+ * method, we are indicating the the next time advance_time() is called, we
+ * would like @p time_step_size to be used to advance the simulation time.
+ * However, if the step is too large such that the next
* simulation time exceeds the end time, the step size is truncated.
* Additionally, if the step size is such that the next simulation time
* approximates the end time (but falls just slightly short of it), the step
* end time.
*/
void
- set_next_step_size(const double time_step_size);
+ set_desired_next_step_size(const double time_step_size);
/**
* Advance the current time based on the value of the current step.
* If you want to adjust the next time step size, call the method
- * set_next_step_size() before calling this method.
+ * set_desired_next_step_size() before calling this method.
* If you call this function repeatedly, the time
* is increased with the same step size until it reaches the end
- * time. See the documentation of set_next_step_size() for explanation
- * of the rules for automatic adjustment of the step size.
+ * time. See the documentation of set_desired_next_step_size() for
+ * explanation of the rules for automatic adjustment of the step size.
*
* @pre Current time must be smaller than the end time. The object cannot
* advance time if it is already at the end time. This rule is created to
*/
const double end_time;
- /**
- * The size of the first step.
- */
- const double start_step_size;
-
/**
* The current time.
*/
* The time at the next step.
*
* @note Internally, the next simulation time is stored instead of the
- * current step size. For example, when the method set_next_step_size()
- * is called, it computes the appropriate next simulation time and stores
- * it. When advance_time() is called, the current_time is replaced by
- * next_time. This choice for the internal state allows for simpler code
- * and ensures than when we call advance_time() at the last step, the
- * floating-point value of the time exactly matches the end time.
+ * current step size. For example, when the method
+ * set_desired_next_step_size() is called, it computes the appropriate next
+ * simulation time and stores it. When advance_time() is called, the
+ * current_time is replaced by next_time. This choice for the internal state
+ * allows for simpler code and ensures than when we call advance_time() at
+ * the last step, the floating-point value of the time exactly matches the
+ * end time.
*/
double next_time;
*/
double previous_time;
+ /**
+ * The size of the first step.
+ */
+ const double start_step_size;
+
/**
* The step number i.e. the number of times the simulation time ha been
* incremented.
DiscreteTime::DiscreteTime(const double start_time,
const double end_time,
- const double start_step_size)
+ const double desired_start_step_size)
: start_time{start_time}
, end_time{end_time}
- , start_step_size{start_step_size}
, current_time{start_time}
- , next_time{calculate_next_time(start_time, start_step_size, end_time)}
+ , next_time{calculate_next_time(start_time,
+ desired_start_step_size,
+ end_time)}
, previous_time{start_time}
+ , start_step_size{next_time - start_time}
, step_number{0}
{}
void
-DiscreteTime::set_next_step_size(const double next_step_size)
+DiscreteTime::set_desired_next_step_size(const double next_step_size)
{
next_time = calculate_next_time(current_time, next_step_size, end_time);
}
DiscreteTime time(/*start_time*/ 0.,
/*end_time*/ 1.5,
- /*start_step_size*/ 0.123);
+ /*desired_start_step_size*/ 0.123);
deallog << "Start time = " << time.get_start_time() << std::endl;
deallog << "End time = " << time.get_end_time() << std::endl;
DiscreteTime time(/*start_time*/ 0.4,
/*end_time*/ 2.1,
- /*start_step_size*/ 0.15);
+ /*desired_start_step_size*/ 0.15);
print_time(time);
time.advance_time();
print_time(time);
- time.set_next_step_size(0.36);
+ time.set_desired_next_step_size(0.36);
time.advance_time();
print_time(time);
time.advance_time();
print_time(time);
- time.set_next_step_size(0.61);
+ time.set_desired_next_step_size(0.61);
time.advance_time();
print_time(time);
time.advance_time(); // Here we reach the end time.