<h1>Results</h1>
-The meshes created by this program are discussed in the introduction.
+The mesh created by this program and the benefits of the
+TransfiniteInterpolationManifold are discussed in the introduction.
<h3>Program output</h3>
+If we run the three-dimensional version of this program with polynomials of
+degree three, we get the following program output:
+
@code
$ make run
Scanning dependencies of target step-65
Number of active cells: 6656
Number of degrees of freedom: 181609
Number of solver iterations: 285
- L2 error vs exact solution: 8.99328e-08
+ L2 error vs exact solution: 8.99339e-08
H1 error vs exact solution: 6.45341e-06
+ Max cell-wise error estimate: 0.00743406
+---------------------------------------------+------------+------------+
-| Total wallclock time elapsed since start | 56.3s | |
+| Total wallclock time elapsed since start | 49.4s | |
| | | |
| Section | no. calls | wall time | % of total |
+---------------------------------+-----------+------------+------------+
-| Assemble linear system | 1 | 5.39s | 9.6% |
-| Compute constraints | 1 | 0.109s | 0.19% |
-| Compute error estimator | 1 | 17.3s | 31% |
-| Compute error norms | 1 | 9.53s | 17% |
-| Solve linear system | 1 | 10.6s | 19% |
-| Write output | 2 | 10.3s | 18% |
+| Assemble linear system | 1 | 5.8s | 12% |
+| Compute constraints | 1 | 0.109s | 0.22% |
+| Compute error estimator | 1 | 16.5s | 33% |
+| Compute error norms | 1 | 9.11s | 18% |
+| Solve linear system | 1 | 9.92s | 20% |
+| Write output | 1 | 4.85s | 9.8% |
+---------------------------------+-----------+------------+------------+
====== Running with the optimized MappingQCache class ======
Number of active cells: 6656
Number of degrees of freedom: 181609
Number of solver iterations: 285
- L2 error vs exact solution: 8.99328e-08
+ L2 error vs exact solution: 8.99339e-08
H1 error vs exact solution: 6.45341e-06
+ Max cell-wise error estimate: 0.00743406
+---------------------------------------------+------------+------------+
-| Total wallclock time elapsed since start | 19.7s | |
+| Total wallclock time elapsed since start | 18.4s | |
| | | |
| Section | no. calls | wall time | % of total |
+---------------------------------+-----------+------------+------------+
-| Assemble linear system | 1 | 0.876s | 4.4% |
-| Compute constraints | 1 | 0.00368s | 0% |
-| Compute error estimator | 1 | 0.488s | 2.5% |
-| Compute error norms | 1 | 0.513s | 2.6% |
-| Initialize mapping cache | 1 | 5.2s | 26% |
-| Solve linear system | 1 | 10.6s | 54% |
-| Write output | 2 | 1.86s | 9.5% |
+| Assemble linear system | 1 | 1.44s | 7.8% |
+| Compute constraints | 1 | 0.00336s | 0% |
+| Compute error estimator | 1 | 0.476s | 2.6% |
+| Compute error norms | 1 | 0.505s | 2.7% |
+| Initialize mapping cache | 1 | 4.96s | 27% |
+| Solve linear system | 1 | 9.95s | 54% |
+| Write output | 1 | 0.875s | 4.8% |
+---------------------------------+-----------+------------+------------+
[100%] Built target run
@endcode
+
+Before discussing the timings, we look at the memory consumption for the
+MappingQCache object: Our program prints that it utilizes 23.0 MB of
+memory. If we relate this number to the memory consumption of a single vector,
+which is 1.5 MB (181,609 * 8 [Byte/double]), or to the memory consumed by the
+system matrix and the sparsity pattern, which is 274 MB, we realize that it is
+not an overly heavy data structure, given its benefits.
+
+With respect to the timers, we see a clear improvement in the overall run time
+of the program by a factor of 2.7. If we disregard the iterative solver, which
+is the same in both cases (and not optimal, given the simple preconditioner we
+use, and the fact that sparse matrix-vector products waste operations for
+cubic polynomials), the advantage is a factor of almost 5. This is pretty
+impressive for a linear stationary problem, and cost savings would indeed be
+much more prominent for time-dependent and nonlinear problems where assembly
+is called several times. If we look into the individual components, we get a
+clearer picture of what is going on and why the cache is so efficient: In the
+MappingQGeneric case, essentially every operation that involves a mapping take
+at least 5 seconds to run. The norm computation runs two
+VectorTools::integrate_difference() functions, which each take almost 5
+seconds. (The computation of constraints is cheaper because it only evaluates
+the mapping in cells at the boundary for the interpolation of boundary
+conditions.) If we compare these 5 seconds to the time it takes to fill the
+MappingQCache, which is 5.2 seconds (for all cells, not just the active ones),
+it becomes obvious that the computation of the mapping support points
+dominates over everything else in the MappingQGeneric case. Perhaps the most
+striking result is the time for the error estimator, labeled "Compute error
+estimator", where the MappingQGeneric implementation takes 17.3 seconds and
+the MappingQCache variant less than 0.5 seconds. The reason why the former is
+so expensive (three times more expensive than the assembly, for instance) is
+that the error estimation involves evaluation of quantities over faces, where
+each face in the mesh requests additional points of the mapping that in turn
+go through the very expensive TransfiniteInterpolationManifold class. As there
+are six faces per cell, this happens much more often than in assembly. Again,
+MappingQCache nicely eliminates the repeated evaluation, aggregating all the
+expensive steps involving the manifold in a single initialization call that
+gets repeatedly used.