diff --git a/agglomeration_poisson/README.md b/agglomeration_poisson/README.md
index 39c0fbd9..4878ebab 100644
--- a/agglomeration_poisson/README.md
+++ b/agglomeration_poisson/README.md
@@ -82,7 +82,7 @@ The mesh skeleton is defined by
@f}
The mesh skeleton $\Gamma$ is decomposed into $(d-1)$–dimensional simplices $F$ representing the mesh faces, shared by at most two elements. These are distinct from elemental interfaces, which are defined as the simply connected components of the intersection between the boundary of an element and either a neighboring element or $\partial \Omega$. As such, an interface between two elements may consist of more than one face, separated by hanging nodes/edges shared by those two elements only. We denote by $\Gamma_{\mathrm{int}}$ the union of all interior faces, and by $\Gamma_{\mathrm D} := \Gamma \cap \partial\Omega$ the union of Dirichlet boundary faces.
-In practice, the polytopic mesh is obtained by agglomeration, so that each element $K \in T_h$ is the union of a collection of leaf cells. For each agglomerated element $K$, we associate an axis-aligned bounding box $B_K$. On $B_K$ we define the standard polynomial space $Q_p(B_K)$ spanned by tensor-product Lagrange polynomials of degree $p$ in each coordinate direction. Since $K \subset B_K$, the basis on $K$ is defined by restricting each basis function to $K$. In the implementation, this corresponds to using the deal.II finite element `FE_DGQ` on the bounding box and taking its restriction to the agglomerated element. The global discrete space $V_h$ is then obtained by assembling these local spaces in a discontinuous manner over all $K \in T_h$. For $u_h, v_h \in V_h$ we use the broken gradient $\nabla_h$ and the standard jump and average operators $[\![\cdot]\!]$ and $\{\!\!\{\cdot\}\!\!\}$ on faces.
+In practice, the polytopic mesh is obtained by agglomeration, so that each element $K \in T_h$ is the union of a collection of leaf cells. For each agglomerated element $K$, we associate an axis-aligned bounding box $B_K$. On $B_K$ we define the standard polynomial space $Q_p(B_K)$ spanned by tensor-product Lagrange polynomials of degree $p$ in each coordinate direction. Since $K \subset B_K$, the basis on $K$ is defined by restricting each basis function to $K$. In the implementation, this corresponds to using the deal.II finite element `FE_DGQ` on the bounding box and taking its restriction to the agglomerated element. The global discrete space $V_h$ is then obtained by assembling these local spaces in a discontinuous manner over all $K \in T_h$. For $u_h, v_h \in V_h$ we use the broken gradient $\nabla_h$ and the standard jump and average operators $[\![\cdot]\!]$ and $\{\!\!\{\cdot\}\!\!\}$ on faces.
The DG formulation reads: find $u_h \in V_h$ such that
@f{align*}{
@@ -190,14 +190,7 @@ with their enclosing MBRs, while the right image shows the associated tree
structure (leaf and internal nodes). This visual example helps explain how the
hierarchical grouping is later used to extract agglomerates.
-
-

-

-
-
(1) Examples of MBRs holding geometric data and their MBRs
-
(2) Corresponding R-tree data structure elements
-
-
+
#### Agglomeration extraction
@@ -215,7 +208,7 @@ Given a collection of fine-level cells, or of cut-cell bounding boxes, the agglo
Construct an R-tree from the set of bounding boxes associated with the fine-level cells.
- **Step 2: Select a target level**
- Choose a tree level $l \in {1,\dots,L}$ to control the agglomeration granularity.
+ Choose a tree level $l$ with $1\le l \le L$ to control the agglomeration granularity.
- **Step 3: Collect leaf descendants**
For each node on level $l$, recursively traverse its children until leaf nodes are reached.
@@ -235,18 +228,7 @@ In the present setting, this makes the R-tree approach particularly convenient f
For illustration, the following images show R-tree-based agglomeration on a structured fine mesh:
-
-

-

-
-
(3) Original 8x8 mesh
-
(4) Bounding boxes and mesh elements
-
-

-
-
(5) Tree hierarchy: root node, internal nodes, and leaf nodes from top to bottom (only two child subtrees of the root are shown for clarity)
-
-
+
Figures (3)-(5) show, respectively, the original fine mesh, the blocks induced by the R-tree on the cell bounding boxes, and the corresponding tree structure.
### METIS-based partitioning
@@ -273,13 +255,9 @@ assess the quality of the numerical approximation.
In this example, we start from an unstructured initial mesh and then perform five global refinement steps. The resulting meshes are shown below.
-
-

-

-
-
(6) Input mesh
-
(7) Fine level mesh obtained by five global refinements of the input mesh
-
+
+
+
Agglomerates are then constructed from the fine level mesh by METIS and by the
R-tree strategy, leading to different polytopal meshes. The following images
compare the resulting agglomerates corresponding to two
@@ -287,27 +265,7 @@ different agglomeration levels (91 and 364 agglomerates).
Comparison of agglomeration strategies
-
-

-

-
-
(8) METIS, 91 agglomerates
-
(9) METIS, 364 agglomerates
-
-
-
-
-

-

-
-
(10) R-tree, 91 agglomerates
-
(11) R-tree, 364 agglomerates
-
-
+
These plots illustrate how the two strategies distribute and shape the
agglomerates starting from the same fine level mesh. In particular, the R-tree approach produces
@@ -319,11 +277,9 @@ mesh refinement or increasing the polynomial degree. The plots below are obtaine
collecting the program outputs over multiple runs and post-processing the
reported error data.
-
-

-
-
(12) h-convergence for Q_p elements (p=1,2,3) with METIS and R-tree agglomeration
-
+
+*(12) h-convergence for Q_p elements (p=1,2,3) with METIS and R-tree agglomeration*
+
The figure reports the $L^2$-norm error with respect to the
manufactured solution. Optimal convergence rates are observed for all
@@ -334,11 +290,8 @@ comparable to those obtained with METIS-based partitioning.
We next compare p-convergence for the two agglomeration strategies in both
the $L^2$-norm and the $H^1$-seminorm.
-
-

-
-
(13) Convergence under p-refinement for METIS and R-tree agglomeration (p = 1,2,3,4,5)
-
+
+*(13) Convergence under p-refinement for METIS and R-tree agglomeration (p = 1,2,3,4,5)*
In addition to accuracy, the cost of constructing the agglomerated polytopal
@@ -346,26 +299,20 @@ meshes is also relevant in practice. The following timing plot compares the
wall-clock time required by the R-tree and METIS strategies. The timing values
are collected from the program outputs and summarized in post-processing.
-
-

-
-
(14) Wall-clock time (seconds) for building polytopal grids with R-tree and METIS
-
+
+*(14) Wall-clock time (seconds) for building polytopal grids with R-tree and METIS*
-Finally, the program also outputs VTU files for visualization in ParaView. Figures (15) and (16) show the solution computed on 91 agglomerates and then interpolated back onto the fine mesh, for the R-tree and METIS strategies, respectively, visualized in ParaView using Warp By Scalar together with the Surface representation.
-
-

-

-
-
(15) Numerical solution using the R-tree strategy
-
(16) Numerical solution using the METIS strategy
-
+Finally, the program also outputs VTU files for visualization in ParaView. Figures (15) and (16) show the solution computed on 91 agglomerates and then interpolated back onto the fine mesh, for the R-tree and METIS strategies, respectively, visualized in ParaView using Warp By Scalar together with the Surface representation.
+
## References
* [1] Marco Feder, Andrea Cangiani and Luca Heltai (2025), R3MG: R-tree based agglomeration of polytopal grids with applications to multilevel methods. DOI: [10.1016/j.jcp.2025.113773](https://doi.org/10.1016/j.jcp.2025.113773)
+
* [2] Daniele Antonio Di Pietro and Alexandre Ern (2012), Mathematical Aspects of Discontinuous Galerkin Methods. DOI: [10.1007/978-3-642-22980-0](https://doi.org/10.1007/978-3-642-22980-0)
+
* [3] Norbert Beckmann, Hans-Peter Kriegel, Ralf Schneider and Bernhard Seeger (1990), The R*-tree: an efficient and robust access method for points and rectangles. DOI: [10.1145/93597.98741](https://doi.org/10.1145/93597.98741)
+
* [4] George Karypis and Vipin Kumar (1998), A fast and high quality multilevel scheme for partitioning irregular graphs. DOI: [10.1137/S1064827595287997](https://doi.org/10.1137/S1064827595287997)
diff --git a/agglomeration_poisson/agglomeration_poisson.cc b/agglomeration_poisson/agglomeration_poisson.cc
index 244b8383..375d04f3 100644
--- a/agglomeration_poisson/agglomeration_poisson.cc
+++ b/agglomeration_poisson/agglomeration_poisson.cc
@@ -44,13 +44,10 @@
#include
#include
-// Auxiliary data structures and manufactured solution data.
-/**
- * We use this struct to store the number of degrees of freedom together
- * with the corresponding L2 and H1 errors, and print a simple
- * convergence table to the console.
- */
+// We use the struct ConvergenceInfo to store the number of degrees of freedom together
+// with the corresponding L2 and H1 errors, and print a simple
+// convergence table to the console.
struct ConvergenceInfo
{
ConvergenceInfo() = default;
@@ -77,10 +74,9 @@ struct ConvergenceInfo
vec_data;
};
-/** We will compare the performance of three different partitioning strategies:
-* using METIS, using an R-tree based agglomeration, or not performing any
-* partitioning at all.
-*/
+// We will compare the performance of three different partitioning strategies:
+// using METIS, using an R-tree based agglomeration, or not performing any
+// partitioning at all.
enum class PartitionerType
{
metis,
@@ -88,11 +84,10 @@ enum class PartitionerType
no_partition
};
-/** We then implement the manufactured right-hand side
-* f(x, y) = 2 π² sin(π x) sin(π y),
-* which corresponds to the exact solution
-* u(x, y) = sin(π x) sin(π y).
- */
+//We then implement the manufactured right-hand side
+// f(x, y) = 2 π² sin(π x) sin(π y),
+// which corresponds to the exact solution
+// u(x, y) = sin(π x) sin(π y).
template
class RightHandSide : public Function
{
@@ -113,14 +108,11 @@ class RightHandSide : public Function
}
};
-/**
- * Exact solution
- * u(x,y) = sin(pi x) sin(pi y).
- *
- * It is used to impose Dirichlet boundary conditions and to evaluate
- * the L2 and H1-seminorm errors. Its gradient is also provided for
- * the computation of the H1 error.
- */
+
+// Exact solution is set as u(x,y) = sin(pi x) sin(pi y).
+// It is used to impose Dirichlet boundary conditions and to evaluate
+// the L2 and H1-seminorm errors. Its gradient is also provided for
+// the computation of the H1 error.
template
class ExactSolution : public Function
{
@@ -160,19 +152,15 @@ class ExactSolution : public Function
}
};
-// Main class implementing the agglomerated SIPG discretization.
-
-/** The Poisson class encapsulates the solution of the model Poisson
-* problem
-* @f[ -\Delta u = f \quad \text{in } \Omega, \qquad u = u_D \quad \text{on } \partial\Omega. @f]
- *
-* It sets up a fine triangulation, constructs agglomerated polytopal
-* cells according to the chosen partitioning strategy, assembles the
-* symmetric interior penalty DG discretization on the agglomerated mesh,
-* solves the resulting linear system, and finally postprocesses the
-* numerical solution by writing visualization output and computing
-* global error norms.
-*/
+// The Poisson class encapsulates the solution of the model Poisson
+// problem
+// @f[ -\Delta u = f \quad \text{in } \Omega, \qquad u = u_D \quad \text{on } \partial\Omega. @f]
+// It sets up a fine triangulation, constructs agglomerated polytopal
+// cells according to the chosen partitioning strategy, assembles the
+// symmetric interior penalty DG discretization on the agglomerated mesh,
+// solves the resulting linear system, and finally postprocesses the
+// numerical solution by writing visualization output and computing
+// global error norms.
template
class Poisson
{
@@ -224,11 +212,10 @@ class Poisson
double semih1_err;
};
-/**
- * The constructor initializes the Poisson solver with the selected partitioning
- * strategy, agglomeration parameters, polynomial degree, and the
- * manufactured exact solution and right-hand side.
- */
+
+// The constructor initializes the Poisson solver with the selected partitioning
+// strategy, agglomeration parameters, polynomial degree, and the
+// manufactured exact solution and right-hand side.
template
Poisson::Poisson(const PartitionerType &partitioner_type,
const unsigned int extraction_level,
@@ -248,11 +235,11 @@ Poisson::Poisson(const PartitionerType &partitioner_type,
}
-/**
- * Build the fine triangulation from a Gmsh mesh, apply a global
- * refinement, initialize the cache and agglomeration handler, and
- * define agglomerates according to the selected partitioning strategy.
- */
+
+// Build the fine triangulation from a Gmsh mesh, apply a global
+// refinement, initialize the cache and agglomeration handler, and
+// define agglomerates according to the selected partitioning strategy.
+
template
void
Poisson::make_grid()
@@ -263,21 +250,18 @@ Poisson::make_grid()
"/unit_square_quad_unstructured.msh");
grid_in.read_msh(gmsh_file);
- // Write the input mesh (before any refinement), for documentation/figures.
{
GridOut grid_out;
std::ofstream out("grid_input_mesh.vtu");
- grid_out.write_vtu(tria, out);
+ grid_out.write_vtu(tria, out); // Write the input mesh (before any refinement), for documentation/figures.
}
- // Refine the mesh to obtain the fine grid used for agglomeration.
- tria.refine_global(5);
+ tria.refine_global(5); // Refine the mesh to obtain the fine grid used for agglomeration.
- // Write the refined (fine) mesh used as starting point for agglomeration.
{
GridOut grid_out;
std::ofstream out("grid_fine_mesh_refined.vtu");
- grid_out.write_vtu(tria, out);
+ grid_out.write_vtu(tria, out); // Write the refined (fine) mesh used as starting point for agglomeration.
}
@@ -286,8 +270,7 @@ Poisson::make_grid()
ah = std::make_unique>(*cached_tria);
if (partitioner_type == PartitionerType::metis)
- {
- // Partition the triangulation with a graph partitioner.
+ { // Partition the triangulation with a graph partitioner.
auto start = std::chrono::system_clock::now();
GridTools::partition_triangulation(n_subdomains,
tria,
@@ -299,8 +282,7 @@ Poisson::make_grid()
for (const auto &cell : tria.active_cell_iterators())
cells_per_subdomain[cell->subdomain_id()].push_back(cell);
- // Define one agglomerate for each subdomain
- for (std::size_t i = 0; i < n_subdomains; ++i)
+ for (std::size_t i = 0; i < n_subdomains; ++i) // Define one agglomerate for each subdomain
ah->define_agglomerate(cells_per_subdomain[i]);
std::chrono::duration wctduration =
@@ -309,8 +291,7 @@ Poisson::make_grid()
<< " seconds [wall clock]" << std::endl;
}
else if (partitioner_type == PartitionerType::rtree)
- {
- // Build agglomerates from the R-tree hierarchy
+ { // Build agglomerates from the R-tree hierarchy
namespace bgi = boost::geometry::index;
static constexpr unsigned int max_elem_per_node =
@@ -329,8 +310,7 @@ Poisson::make_grid()
extraction_level};
const auto vec_agglomerates = agglomerator.extract_agglomerates();
- // Flag elements for agglomeration
- for (const auto &agglo : vec_agglomerates)
+ for (const auto &agglo : vec_agglomerates) // Flag elements for agglomeration
ah->define_agglomerate(agglo);
std::chrono::duration wctduration =
@@ -349,22 +329,18 @@ Poisson::make_grid()
std::cout << "N subdomains = " << n_subdomains << std::endl;
}
-/**
- * Finalize the agglomeration.
- *
- * In the no-partition case, each fine cell is declared as its own
- * agglomerate. The function then distributes the degrees of freedom
- * on the agglomerated mesh, builds the corresponding sparsity pattern,
- * and writes a VTU file visualizing the agglomeration and the
- * partitioning of the fine grid.
- */
+
+// To finalize the agglomeration. In the no-partition case, each fine cell is declared as its own
+// agglomerate. The function then distributes the degrees of freedom
+// on the agglomerated mesh, builds the corresponding sparsity pattern,
+// and writes a VTU file visualizing the agglomeration and the
+// partitioning of the fine grid.
template
void
Poisson::setup_agglomeration()
{
if (partitioner_type == PartitionerType::no_partition)
- {
- // No partitioning means that each cell is a master cell
+ { // No partitioning means that each cell is a master cell
for (const auto &cell : tria.active_cell_iterators())
ah->define_agglomerate({cell});
}
@@ -393,16 +369,14 @@ Poisson::setup_agglomeration()
const auto &rel = ah->get_relationships();
- // Store the agglomeration relationships on the fine grid by distinguishing master/slave cells
- Vector agglo_relationships(tria.n_active_cells());
+ Vector agglo_relationships(tria.n_active_cells()); // Store the agglomeration relationships on the fine grid by distinguishing master/slave cells
for (const auto &cell : tria.active_cell_iterators())
{
const unsigned int i = cell->active_cell_index();
agglo_relationships[i] = rel[i];
}
- // Generate agglo_idx for visualization
- Vector agglo_idx(tria.n_active_cells());
+ Vector agglo_idx(tria.n_active_cells()); // Generate agglo_idx for visualization
for (const auto &polytope : ah->polytope_iterators())
{
@@ -426,15 +400,13 @@ Poisson::setup_agglomeration()
}
-/**
- * Assemble the global SIPG matrix and right-hand side on the
- * agglomerated mesh.
- *
- * It initializes the system matrix and right-hand side, sets up FEValues
- * objects on polytopal cells and interfaces, and then adds the volume,
- * boundary, and interior face contributions of the symmetric interior
- * penalty formulation.
- */
+// Assemble the global SIPG matrix and right-hand side on the
+// agglomerated mesh.
+//
+// It initializes the system matrix and right-hand side, sets up FEValues
+// objects on polytopal cells and interfaces, and then adds the volume,
+// boundary, and interior face contributions of the symmetric interior
+// penalty formulation.
template
void
Poisson::assemble_system()
@@ -494,7 +466,7 @@ Poisson::assemble_system()
}
}
- // Assemble boundary and interior face contributions.
+
const unsigned int n_faces = polytope->n_faces();
AssertThrow(n_faces > 0,
ExcMessage(
@@ -504,8 +476,7 @@ Poisson::assemble_system()
for (unsigned int f = 0; f < n_faces; ++f)
{
if (polytope->at_boundary(f))
- {
- // std::cout << "at boundary!" << std::endl;
+ { // std::cout << "at boundary!" << std::endl;
const auto &fe_face = ah->reinit(polytope, f);
const unsigned int dofs_per_cell = fe_face.dofs_per_cell;
@@ -516,9 +487,8 @@ Poisson::assemble_system()
analytical_solution->value_list(face_q_points,
analytical_solution_values,
1);
-
- // Get normal vectors seen from each agglomeration.
- const auto &normals = fe_face.get_normal_vectors();
+
+ const auto &normals = fe_face.get_normal_vectors(); // Get normal vectors seen from each agglomeration.
const double penalty =
penalty_constant / std::fabs(polytope->diameter());
@@ -552,8 +522,7 @@ Poisson::assemble_system()
{
const auto &neigh_polytope = polytope->neighbor(f);
- // This is necessary to loop over internal faces only once.
- if (polytope->index() < neigh_polytope->index())
+ if (polytope->index() < neigh_polytope->index()) // This is necessary to loop over internal faces only once.
{
unsigned int nofn =
polytope->neighbor_of_agglomerated_neighbor(f);
@@ -575,11 +544,9 @@ Poisson::assemble_system()
const double penalty =
penalty_constant / std::min(polytope->diameter(), neigh_polytope->diameter());
- //const double penalty =
- // penalty_constant / std::fabs(polytope->diameter());
- // M11
- for (unsigned int q_index :
+
+ for (unsigned int q_index : // M11
fe_faces0.quadrature_point_indices())
{
for (unsigned int i = 0; i < dofs_per_cell; ++i)
@@ -608,8 +575,8 @@ Poisson::assemble_system()
fe_faces1.shape_value(j, q_index)) *
fe_faces1.JxW(q_index);
- // A10
- M21(i, j) +=
+
+ M21(i, j) += // A10
(-0.5 * fe_faces1.shape_grad(i, q_index) *
normals[q_index] *
fe_faces0.shape_value(j, q_index) +
@@ -620,8 +587,8 @@ Poisson::assemble_system()
fe_faces0.shape_value(j, q_index)) *
fe_faces1.JxW(q_index);
- // A11
- M22(i, j) +=
+
+ M22(i, j) += // A11
(0.5 * fe_faces1.shape_grad(i, q_index) *
normals[q_index] *
fe_faces1.shape_value(j, q_index) +
@@ -662,9 +629,7 @@ Poisson::assemble_system()
} // Loop over cells
}
-/**
- * Solve the linear system by means of a sparse direct solver.
- */
+// Solve the linear system by means of a sparse direct solver.
template
void
Poisson::solve()
@@ -674,10 +639,9 @@ Poisson::solve()
A_direct.vmult(solution, system_rhs);
}
-/**
- * Write VTU output and compute the global $L^2$ and $H^1$-seminorm
- * errors of the agglomerated DG approximation.
- */
+
+// Write VTU output and compute the global $L^2$ and $H^1$-seminorm
+// errors of the agglomerated DG approximation.
template
void
Poisson::output_results()
@@ -713,8 +677,7 @@ Poisson::output_results()
{
const types::global_cell_index polytope_index = polytope->index();
const auto &patch_of_cells = polytope->get_agglomerate(); // Fine cells
- // Mark all fine cells belonging to the current agglomerate.
- for (const auto &cell : patch_of_cells)
+ for (const auto &cell : patch_of_cells) // Mark all fine cells belonging to the current agglomerate.
agglo_idx[cell->active_cell_index()] = polytope_index;
}
@@ -725,22 +688,20 @@ Poisson::output_results()
data_out.build_patches(mapping);
data_out.write_vtu(output);
- // Compute the global L2 and H1-seminorm errors.
std::vector errors;
PolyUtils::compute_global_error(*ah,
solution,
*analytical_solution,
{VectorTools::L2_norm,
VectorTools::H1_seminorm},
- errors);
+ errors); // Compute the global L2 and H1-seminorm errors.
l2_err = errors[0];
semih1_err = errors[1];
}
}
-/**
- * Return the number of degrees of freedom on the agglomerated mesh.
- */
+
+// Return the number of degrees of freedom on the agglomerated mesh.
template
inline types::global_dof_index
Poisson::get_n_dofs() const
@@ -748,10 +709,8 @@ Poisson::get_n_dofs() const
return ah->n_dofs();
}
-/**
- * Return the pair consisting of the $L^2$ error and the $H^1$-seminorm
- * error of the numerical solution.
- */
+
+// Return the pair consisting of the $L^2$ error and the $H^1$-seminorm error of the numerical solution.
template
inline std::pair
Poisson::get_error() const
@@ -759,10 +718,9 @@ Poisson::get_error() const
return std::make_pair(l2_err, semih1_err);
}
-/**
- * Run the full workflow: mesh generation, agglomeration setup,
- * assembly, solution, and postprocessing.
- */
+
+// Run the full workflow: mesh generation, agglomeration setup,
+// assembly, solution, and postprocessing.
template
void
Poisson::run()
diff --git a/agglomeration_poisson/doc/images/MBR_R_tree.png b/agglomeration_poisson/doc/images/MBR_R_tree.png
new file mode 100644
index 00000000..a26f373c
Binary files /dev/null and b/agglomeration_poisson/doc/images/MBR_R_tree.png differ
diff --git a/agglomeration_poisson/doc/images/Tree_A_F.png b/agglomeration_poisson/doc/images/Tree_A_F.png
deleted file mode 100644
index 9d832944..00000000
Binary files a/agglomeration_poisson/doc/images/Tree_A_F.png and /dev/null differ
diff --git a/agglomeration_poisson/doc/images/agglomerates_comparison.png b/agglomeration_poisson/doc/images/agglomerates_comparison.png
new file mode 100644
index 00000000..edc27b22
Binary files /dev/null and b/agglomeration_poisson/doc/images/agglomerates_comparison.png differ
diff --git a/agglomeration_poisson/doc/images/final_solution_metis.png b/agglomeration_poisson/doc/images/final_solution_metis.png
deleted file mode 100644
index a8bc5be4..00000000
Binary files a/agglomeration_poisson/doc/images/final_solution_metis.png and /dev/null differ
diff --git a/agglomeration_poisson/doc/images/final_solution_rtree.png b/agglomeration_poisson/doc/images/final_solution_rtree.png
deleted file mode 100644
index 9281d795..00000000
Binary files a/agglomeration_poisson/doc/images/final_solution_rtree.png and /dev/null differ
diff --git a/agglomeration_poisson/doc/images/hierarchy.png b/agglomeration_poisson/doc/images/hierarchy.png
new file mode 100644
index 00000000..7fbb3e46
Binary files /dev/null and b/agglomeration_poisson/doc/images/hierarchy.png differ
diff --git a/agglomeration_poisson/doc/images/input_mesh.png b/agglomeration_poisson/doc/images/input_mesh.png
deleted file mode 100644
index 87052b6b..00000000
Binary files a/agglomeration_poisson/doc/images/input_mesh.png and /dev/null differ
diff --git a/agglomeration_poisson/doc/images/input_refine_mesh.png b/agglomeration_poisson/doc/images/input_refine_mesh.png
new file mode 100644
index 00000000..062e7603
Binary files /dev/null and b/agglomeration_poisson/doc/images/input_refine_mesh.png differ
diff --git a/agglomeration_poisson/doc/images/mesh_refined_5times.png b/agglomeration_poisson/doc/images/mesh_refined_5times.png
deleted file mode 100644
index 0971017a..00000000
Binary files a/agglomeration_poisson/doc/images/mesh_refined_5times.png and /dev/null differ
diff --git a/agglomeration_poisson/doc/images/numerical_solution_comparison.png b/agglomeration_poisson/doc/images/numerical_solution_comparison.png
new file mode 100644
index 00000000..7eed62a4
Binary files /dev/null and b/agglomeration_poisson/doc/images/numerical_solution_comparison.png differ
diff --git a/agglomeration_poisson/doc/images/polygonmetis_364.png b/agglomeration_poisson/doc/images/polygonmetis_364.png
deleted file mode 100644
index a3cf42bb..00000000
Binary files a/agglomeration_poisson/doc/images/polygonmetis_364.png and /dev/null differ
diff --git a/agglomeration_poisson/doc/images/polygonmetis_91.png b/agglomeration_poisson/doc/images/polygonmetis_91.png
deleted file mode 100644
index fc197fc3..00000000
Binary files a/agglomeration_poisson/doc/images/polygonmetis_91.png and /dev/null differ
diff --git a/agglomeration_poisson/doc/images/polygonrtree_364.png b/agglomeration_poisson/doc/images/polygonrtree_364.png
deleted file mode 100644
index 9f87510b..00000000
Binary files a/agglomeration_poisson/doc/images/polygonrtree_364.png and /dev/null differ
diff --git a/agglomeration_poisson/doc/images/polygonrtree_91.png b/agglomeration_poisson/doc/images/polygonrtree_91.png
deleted file mode 100644
index 6e28e269..00000000
Binary files a/agglomeration_poisson/doc/images/polygonrtree_91.png and /dev/null differ
diff --git a/agglomeration_poisson/doc/images/refined_mesh_internal_layer.png b/agglomeration_poisson/doc/images/refined_mesh_internal_layer.png
deleted file mode 100644
index bd38f0ec..00000000
Binary files a/agglomeration_poisson/doc/images/refined_mesh_internal_layer.png and /dev/null differ
diff --git a/agglomeration_poisson/doc/images/rtree_example.png b/agglomeration_poisson/doc/images/rtree_example.png
deleted file mode 100644
index 9c28a9f3..00000000
Binary files a/agglomeration_poisson/doc/images/rtree_example.png and /dev/null differ
diff --git a/agglomeration_poisson/doc/images/tree_structure.png b/agglomeration_poisson/doc/images/tree_structure.png
deleted file mode 100644
index e9ba43c7..00000000
Binary files a/agglomeration_poisson/doc/images/tree_structure.png and /dev/null differ
diff --git a/agglomeration_poisson/doc/images/warp_by_scalar_solution_layer.png b/agglomeration_poisson/doc/images/warp_by_scalar_solution_layer.png
deleted file mode 100644
index f0c30f3e..00000000
Binary files a/agglomeration_poisson/doc/images/warp_by_scalar_solution_layer.png and /dev/null differ