<h1>Results</h1>


The output of the program looks as follows:
@code
Cycle 0:
   Number of active cells:       20
   Number of degrees of freedom: 89
Cycle 1:
   Number of active cells:       44
   Number of degrees of freedom: 209
Cycle 2:
   Number of active cells:       92
   Number of degrees of freedom: 449
Cycle 3:
   Number of active cells:       200
   Number of degrees of freedom: 961
Cycle 4:
   Number of active cells:       440
   Number of degrees of freedom: 2033
Cycle 5:
   Number of active cells:       932
   Number of degrees of freedom: 4465
Cycle 6:
   Number of active cells:       1916
   Number of degrees of freedom: 9113
Cycle 7:
   Number of active cells:       3884
   Number of degrees of freedom: 18401
@endcode



As intended, the number of cells roughly doubles in each cycle.  The
number of degrees is slightly more than four times the number of
cells; one would expect a factor of exactly four in two spatial
dimensions on an infinite grid (since the spacing between the degrees
of freedom is half the cell width: one additional degree of freedom on
each edge and one in the middle of each cell), but it is larger than
that factor due to the finite size of the mesh and due to additional
degrees of freedom which are introduced by hanging nodes and local
refinement.



The final solution, as written by the program at the end of the
<code>%run()</code> function, looks as follows:



<img src="http://www.dealii.org/images/steps/developer/step-6.solution.png" alt="">



In each cycle, the program furthermore writes the grid in EPS
format. These are shown in the following:



<TABLE WIDTH="100%">
<tr>
<td>
  <img src="http://www.dealii.org/images/steps/developer/step-6.grid-0.png" alt="">
</td>
<td>
  <img src="http://www.dealii.org/images/steps/developer/step-6.grid-1.png" alt="">
</td>
</tr>

<tr>
<td>
  <img src="http://www.dealii.org/images/steps/developer/step-6.grid-2.png" alt="">
</td>
<td>
  <img src="http://www.dealii.org/images/steps/developer/step-6.grid-3.png" alt="">
</td>
</tr>

<tr>
<td>
  <img src="http://www.dealii.org/images/steps/developer/step-6.grid-4.png" alt="">
</td>
<td>
  <img src="http://www.dealii.org/images/steps/developer/step-6.grid-5.png" alt="">
</td>
</tr>

<tr>
<td>
  <img src="http://www.dealii.org/images/steps/developer/step-6.grid-6.png" alt="">
</td>
<td>
  <img src="http://www.dealii.org/images/steps/developer/step-6.grid-7.png" alt="">
</td>
</tr>
</table>



It is clearly visible that the region where the solution has a kink,
i.e. the circle at radial distance 0.5 from the center, is
refined most. Furthermore, the central region where the solution is
very smooth and almost flat, is almost not refined at all, but this
results from the fact that we did not take into account that the
coefficient is large there. The region outside is refined rather
randomly, since the second derivative is constant there and refinement
is therefore mostly based on the size of the cells and their deviation
from the optimal square.




For completeness, we show what happens if the code we commented about
in the destructor of the <code>Step6</code> class is omitted
from this example.

@code
--------------------------------------------------------
An error occurred in line <79> of file <source/subscriptor.cc> in function
    virtual Subscriptor::~Subscriptor()
The violated condition was:
    counter == 0
The name and call sequence of the exception was:
    ExcInUse(counter, object_info->name(), infostring)
Additional Information:
Object of class 4FE_QILi2EE is still used by 1 other objects.
  from Subscriber 10DoFHandlerILi2EE

Stacktrace:
-----------
#0  /u/bangerth/p/deal.II/1/deal.II/lib/libbase.g.so: Subscriptor::~Subscriptor()
#1  /u/bangerth/p/deal.II/1/deal.II/lib/libdeal_II_2d.g.so: FiniteElement<2>::~FiniteElement()
#2  ./\step-6: FE_Poly<TensorProductPolynomials<2>, 2>::~FE_Poly()
#3  ./\step-6: FE_Q<2>::~FE_Q()
#4  ./\step-6: Step6<2>::~Step6()
#5  ./\step-6: main
--------------------------------------------------------
make: *** [run] Aborted
@endcode



From the above error message, we conclude that an object of type
<code>10DoFHandlerILi2EE</code> is still using the object of type
<code>4FE_QILi2EE</code>. These are of course <a
href="http://en.wikipedia.org/wiki/Name_mangling">"mangled" names</a> for
<code>DoFHandler</code> and <code>FE_Q</code>. The mangling works as
follows: the first number indicates the number of characters of the
template class, i.e. 10 for <code>DoFHandler</code> and 4
for<code>FE_Q</code>; the rest of the text is then template
arguments. From this we can already glean a little bit who's the
culprit here, and who the victim:
The one object that still uses the finite element is the
<code>dof_handler</code> object.



The stacktrace gives an indication of where the problem happened. We
see that the exception was triggered in the
destructor of the <code>FiniteElement</code> class that was called
through a few more functions from the destructor of the
<code>Step6</code> class, exactly where we have commented out
the call to <code>DoFHandler::clear()</code>.



<a name="extensions"></a>
<h3>Possibilities for extensions</h3>

One thing that is always worth playing around with if one solves
problems of appreciable size (much bigger than the one we have here)
is to try different solvers or preconditioners. In the current case,
the linear system is symmetric and positive definite, which makes the
CG algorithm pretty much the canonical choice for solving. However,
the SSOR preconditioner we use in the <code>solve()</code> function is
up for grabs.

In deal.II, it is relatively simple to change the preconditioner. For
example, by changing the existing lines of code
@code
  PreconditionSSOR<> preconditioner;
  preconditioner.initialize(system_matrix, 1.2);
@endcode
into
@code
  PreconditionSSOR<> preconditioner;
  preconditioner.initialize(system_matrix, 1.0);
@endcode
we can try out different relaxation parameters for SSOR. By using
(you have to also add the header file <code>lac/sparse_ilu.h</code> to
the include list at the top of the file)
@code
  PreconditionJacobi<> preconditioner;
  preconditioner.initialize(system_matrix);
@endcode
we can use Jacobi as a preconditioner. And by using
@code
  SparseILU<double> preconditioner;
  preconditioner.initialize(system_matrix);
@endcode
we can use a very simply incomplete LU decomposition without any
thresholding or strengthening of the diagonal.

Using these various different preconditioners, we can compare the
number of CG iterations needed (available through the
<code>solver_control.last_step()</code> call, see @ref step_4
"step-4") as well as CPU time needed (using the Timer class,
discussed, for example, in step-12) and get the
following results (left: iterations; right: CPU time):

<TABLE WIDTH="60%" ALIGN="center">
  <tr>
    <td ALIGN="center">
      <img src="http://www.dealii.org/images/steps/developer/step-6.q2.dofs_vs_iterations.png" alt="">
    </td>

    <td ALIGN="center">
      <img src="http://www.dealii.org/images/steps/developer/step-6.q2.dofs_vs_time.png" alt="">
    </td>
  </tr>
</table>

As we can see, all preconditioners behave pretty much the same on this
simple problem, with the number of iterations growing like ${\cal
O}(N^{1/2})$ and because each iteration requires around ${\cal
O}(N)$ operations the total CPU time grows like ${\cal
O}(N^{3/2})$ (for the few smallest meshes, the CPU time is so small
that it doesn't record). Note that even though it is the simplest
method, Jacobi is the fastest for this problem.

The situation changes slightly when the finite element is not a
bi-quadratic one as set in the constructor of this program, but a
bi-linear one. If one makes this change, the results are as follows:

<TABLE WIDTH="60%" ALIGN="center">
  <tr>
    <td ALIGN="center">
      <img src="http://www.dealii.org/images/steps/developer/step-6.q1.dofs_vs_iterations.png" alt="">
    </td>

    <td ALIGN="center">
      <img src="http://www.dealii.org/images/steps/developer/step-6.q1.dofs_vs_time.png" alt="">
    </td>
  </tr>
</table>

In other words, while the increase in iterations and CPU time is as
before, Jacobi is now the method that requires the most iterations; it
is still the fastest one, however, owing to the simplicity of the
operations it has to perform.

The message to take away from this is not that simplicity in
preconditioners is always best. While this may be true for the current
problem, it definitely is not once we move to more complicated
problems (elasticity or Stokes, for examples step-8 or
step-22). Secondly, all of these preconditioners still
lead to an increase in the number of iterations as the number $N$ of
degrees of freedom grows, for example ${\cal O}(N^\alpha)$; this, in
turn, leads to a total growth in effort as ${\cal O}(N^{1+\alpha})$
since each iteration takes ${\cal O}(N)$ work. This behavior is
undesirable, we would really like to solve linear systems with $N$
unknowns in a total of ${\cal O}(N)$ work; there is a class
of preconditioners that can achieve this, namely geometric (@ref
step_16 "step-16") or algebraic (step-31) multigrid
preconditioners. They are, however, significantly more complex than
the preconditioners outlined above. Finally, the last message to take
home is that today (in 2008), linear systems with 100,000 unknowns are
easily solved on a desktop machine in well under 10 seconds, making
the solution of relatively simple 2d problems even to very high
accuracy not that big a task as it used to be even in the recent
past. Of course, the situation for 3d problems is entirely different.

