system_rhs,
false);
@endcode
+
+ <li>deal.II being a library that supports adaptive meshes it would of course be
+ nice if this program supported change the mesh every few time steps. Given the
+ structure of the solution — a wave that travels through the domain —
+ it would seem appropriate if we only refined the mesh where the wave currently is,
+ and not simply everywhere. It is intuitively clear that we should be able to
+ save a significant amount of cells this way. (Though upon further thought one
+ realizes that this is really only the case in the initial stages of the simulation.
+ After some time, for wave phenomena, the domain is filled with reflections of
+ the initial wave going in every direction and filling every corner of the domain.
+ At this point, there is in general little one can gain using local mesh
+ refinement.)
+
+ To make adaptively changing meshes possible, there are basically two routes.
+ The "correct" way would be to go back to the weak form we get using Rothe's
+ method. For example, the first of the two equations to be solved in each time
+ step looked like this:
+ \f{eqnarray*}
+ (u^n,\varphi) + k^2\theta^2(\nabla u^n,\nabla \varphi) &=&
+ (u^{n-1},\varphi) - k^2\theta(1-\theta)(\nabla u^{n-1},\nabla \varphi)
+ +
+ k(v^{n-1},\varphi)
+ + k^2\theta
+ \left[
+ \theta (f^n,\varphi) + (1-\theta) (f^{n-1},\varphi)
+ \right].
+ \f}
+ Now, note that we solve for $u^n$ on mesh ${\mathbb T}^n$, and
+ consequently the test functions $\varphi$ have to be from the space
+ $V_h^n$ as well. As discussed in the introduction, terms like
+ $(u^{n-1},\varphi)$ then require us to integrate the solution of the
+ previous step (which may have been computed on a different mesh
+ ${\mathbb T}^{n-1}$) against the test functions of the current mesh,
+ leading to a matrix $M^{n,n-1}$. This process of integrating shape
+ functions from different meshes is, at best, awkward. It can be done
+ but because it is difficult to ensure that ${\mathbb T}^{n-1}$ and
+ ${\mathbb T}^{n}$ differ by at most one level of refinement, one
+ has to recursively match cells from both meshes. It is feasible to
+ do this, but it leads to lengthy and not entirely obvious code.
+
+ The second approach is the following: whenever we change the mesh,
+ we simply interpolate the solution from the last time step on the old
+ mesh to the new mesh, using the SolutionTransfer class. In other words,
+ instead of the equation above, we would solve
+ \f{eqnarray*}
+ (u^n,\varphi) + k^2\theta^2(\nabla u^n,\nabla \varphi) &=&
+ (I^n u^{n-1},\varphi) - k^2\theta(1-\theta)(\nabla I^n u^{n-1},\nabla \varphi)
+ +
+ k(I^n v^{n-1},\varphi)
+ + k^2\theta
+ \left[
+ \theta (f^n,\varphi) + (1-\theta) (f^{n-1},\varphi)
+ \right],
+ \f}
+ where $I^n$ interpolates a given function onto mesh ${\mathbb T}^n$.
+ This is a much simpler approach because, in each time step, we no
+ longer have to worry whether $u^{n-1},v^{n-1}$ were computed on the
+ same mesh as we are using now or on a different mesh. Consequently,
+ the only changes to the code necessary are the addition of a function
+ that computes the error, marks cells for refinement, sets up a
+ SolutionTransfer object, transfers the solution to the new mesh, and
+ rebuilds matrices and right hand side vectors on the new mesh. Neither
+ the functions building the matrices and right hand sides, nor the
+ solvers need to be changed.
+
+ While this second approach is, strictly speaking,
+ not quite correct in the Rothe framework (it introduces an addition source
+ of error, namely the interpolation), it is nevertheless what
+ almost everyone solving time dependent equations does. We will use this
+ method in step-31, for example.
</ul>