diff --git a/src/scheme/PolynomialReconstruction.cpp b/src/scheme/PolynomialReconstruction.cpp
index f9e55f19c2073b4e814ee3740603ae4d924f2322..c20fbc897c060fa182eb30683b109160938d68c6 100644
--- a/src/scheme/PolynomialReconstruction.cpp
+++ b/src/scheme/PolynomialReconstruction.cpp
@@ -1,18 +1,26 @@
 #include <scheme/PolynomialReconstruction.hpp>
 
-#include <scheme/DiscreteFunctionUtils.hpp>
-#include <scheme/DiscreteFunctionVariant.hpp>
-
+#include <algebra/Givens.hpp>
+#include <algebra/ShrinkMatrixView.hpp>
+#include <algebra/ShrinkVectorView.hpp>
+#include <algebra/SmallMatrix.hpp>
 #include <analysis/GaussLegendreQuadratureDescriptor.hpp>
 #include <analysis/GaussQuadratureDescriptor.hpp>
 #include <analysis/QuadratureFormula.hpp>
 #include <analysis/QuadratureManager.hpp>
 #include <geometry/CubeTransformation.hpp>
+#include <geometry/LineTransformation.hpp>
 #include <geometry/PrismTransformation.hpp>
 #include <geometry/PyramidTransformation.hpp>
 #include <geometry/SquareTransformation.hpp>
 #include <geometry/TetrahedronTransformation.hpp>
 #include <geometry/TriangleTransformation.hpp>
+#include <mesh/MeshData.hpp>
+#include <mesh/MeshDataManager.hpp>
+#include <mesh/StencilManager.hpp>
+#include <scheme/DiscreteFunctionDPkVariant.hpp>
+#include <scheme/DiscreteFunctionUtils.hpp>
+#include <scheme/DiscreteFunctionVariant.hpp>
 
 class PolynomialReconstruction::MutableDiscreteFunctionDPkVariant
 {
@@ -261,6 +269,126 @@ _computeEjkMean(const QuadratureFormula<3>& quadrature,
   }
 }
 
+template <typename NodeListT, size_t Dimension>
+void
+_computeEjkMean(const TinyVector<Dimension>& Xj,
+                const NodeValue<const TinyVector<Dimension>>& xr,
+                const NodeListT& node_list,
+                const CellType& cell_type,
+                const double Vi,
+                const size_t degree,
+                const size_t basis_dimension,
+                SmallArray<double>& inv_Vj_wq_detJ_ek,
+                SmallArray<double>& mean_of_ejk)
+{}
+
+template <typename NodeListT>
+void
+_computeEjkMean(const TinyVector<1>& Xj,
+                const NodeValue<const TinyVector<1>>& xr,
+                const NodeListT& node_list,
+                const CellType& cell_type,
+                const double Vi,
+                const size_t degree,
+                const size_t basis_dimension,
+                SmallArray<double>& inv_Vj_wq_detJ_ek,
+                SmallArray<double>& mean_of_ejk)
+{
+  if (cell_type == CellType::Line) {
+    const LineTransformation<1> T{xr[node_list[0]], xr[node_list[1]]};
+
+    const auto& quadrature = QuadratureManager::instance().getLineFormula(GaussLegendreQuadratureDescriptor{degree});
+
+    _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk);
+
+  } else {
+    throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type)});
+  }
+}
+
+template <typename NodeListT>
+void
+_computeEjkMean(const TinyVector<2>& Xj,
+                const NodeValue<const TinyVector<2>>& xr,
+                const NodeListT& node_list,
+                const CellType& cell_type,
+                const double Vi,
+                const size_t degree,
+                const size_t basis_dimension,
+                SmallArray<double>& inv_Vj_wq_detJ_ek,
+                SmallArray<double>& mean_of_ejk)
+{
+  switch (cell_type) {
+  case CellType::Triangle: {
+    const TriangleTransformation<2> T{xr[node_list[0]], xr[node_list[1]], xr[node_list[2]]};
+    const auto& quadrature = QuadratureManager::instance().getTriangleFormula(GaussQuadratureDescriptor{degree});
+
+    _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk);
+    break;
+  }
+  case CellType::Quadrangle: {
+    const SquareTransformation<2> T{xr[node_list[0]], xr[node_list[1]], xr[node_list[2]], xr[node_list[3]]};
+    const auto& quadrature =
+      QuadratureManager::instance().getSquareFormula(GaussLegendreQuadratureDescriptor{degree + 1});
+
+    _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk);
+    break;
+  }
+  default: {
+    throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type)});
+  }
+  }
+}
+
+template <typename NodeListT>
+void
+_computeEjkMean(const TinyVector<3>& Xj,
+                const NodeValue<const TinyVector<3>>& xr,
+                const NodeListT& node_list,
+                const CellType& cell_type,
+                const double Vi,
+                const size_t degree,
+                const size_t basis_dimension,
+                SmallArray<double>& inv_Vj_wq_detJ_ek,
+                SmallArray<double>& mean_of_ejk)
+{
+  if (cell_type == CellType::Tetrahedron) {
+    const TetrahedronTransformation T{xr[node_list[0]], xr[node_list[1]], xr[node_list[2]], xr[node_list[3]]};
+
+    const auto& quadrature = QuadratureManager::instance().getTetrahedronFormula(GaussQuadratureDescriptor{degree});
+
+    _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk);
+
+  } else if (cell_type == CellType::Prism) {
+    const PrismTransformation T{xr[node_list[0]], xr[node_list[1]], xr[node_list[2]],   //
+                                xr[node_list[3]], xr[node_list[4]], xr[node_list[5]]};
+
+    const auto& quadrature = QuadratureManager::instance().getPrismFormula(GaussQuadratureDescriptor{degree + 1});
+
+    _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk);
+
+  } else if (cell_type == CellType::Pyramid) {
+    const PyramidTransformation T{xr[node_list[0]], xr[node_list[1]], xr[node_list[2]], xr[node_list[3]],
+                                  xr[node_list[4]]};
+
+    const auto& quadrature = QuadratureManager::instance().getPyramidFormula(GaussQuadratureDescriptor{degree + 1});
+
+    _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk);
+
+  } else if (cell_type == CellType::Hexahedron) {
+    const CubeTransformation T{xr[node_list[0]], xr[node_list[1]], xr[node_list[2]], xr[node_list[3]],
+                               xr[node_list[4]], xr[node_list[5]], xr[node_list[6]], xr[node_list[7]]};
+
+    const auto& quadrature =
+      QuadratureManager::instance().getCubeFormula(GaussLegendreQuadratureDescriptor{degree + 1});
+
+    _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk);
+
+  } else {
+    throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type)});
+  }
+}
+
 size_t
 PolynomialReconstruction::_getNumberOfColumns(
   const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list) const
@@ -374,7 +502,7 @@ PolynomialReconstruction::_build(
 
   SmallArray<SmallMatrix<double>> A_pool(Kokkos::DefaultExecutionSpace::concurrency());
   SmallArray<SmallMatrix<double>> B_pool(Kokkos::DefaultExecutionSpace::concurrency());
-  SmallArray<SmallArray<double>> G_pool(Kokkos::DefaultExecutionSpace::concurrency());
+  SmallArray<SmallVector<double>> G_pool(Kokkos::DefaultExecutionSpace::concurrency());
   SmallArray<SmallMatrix<double>> X_pool(Kokkos::DefaultExecutionSpace::concurrency());
 
   SmallArray<SmallArray<double>> inv_Vj_wq_detJ_ek_pool(Kokkos::DefaultExecutionSpace::concurrency());
@@ -384,7 +512,7 @@ PolynomialReconstruction::_build(
   for (size_t i = 0; i < A_pool.size(); ++i) {
     A_pool[i] = SmallMatrix<double>(max_stencil_size, basis_dimension - 1);
     B_pool[i] = SmallMatrix<double>(max_stencil_size, number_of_columns);
-    G_pool[i] = SmallArray<double>(basis_dimension - 1);
+    G_pool[i] = SmallVector<double>(basis_dimension - 1);
     X_pool[i] = SmallMatrix<double>(basis_dimension - 1, number_of_columns);
 
     inv_Vj_wq_detJ_ek_pool[i] = SmallArray<double>(basis_dimension);
@@ -482,217 +610,20 @@ PolynomialReconstruction::_build(
           SmallArray<double>& mean_j_of_ejk     = mean_j_of_ejk_pool[t];
           SmallArray<double>& mean_i_of_ejk     = mean_i_of_ejk_pool[t];
 
-          if constexpr (MeshType::Dimension == 1) {
-            const Rd& Xj = xj[cell_j_id];
-
-            if (cell_type[cell_j_id] == CellType::Line) {
-              auto cell_node = cell_to_node_matrix[cell_j_id];
-
-              const LineTransformation<1> T{xr[cell_node[0]], xr[cell_node[1]]};
-
-              const auto& quadrature =
-                QuadratureManager::instance().getLineFormula(GaussLegendreQuadratureDescriptor{m_descriptor.degree()});
-
-              _computeEjkMean(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension,
-                              inv_Vj_wq_detJ_ek, mean_j_of_ejk);
-
-            } else {
-              throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type[cell_j_id])});
-            }
-
-            for (size_t i = 0; i < stencil_cell_list.size(); ++i) {
-              const CellId cell_i_id = stencil_cell_list[i];
-
-              auto cell_node = cell_to_node_matrix[cell_i_id];
-
-              if (cell_type[cell_i_id] == CellType::Line) {
-                const LineTransformation<1> T{xr[cell_node[0]], xr[cell_node[1]]};
-
-                const auto& quadrature =
-                  QuadratureManager::instance().getLineFormula(GaussQuadratureDescriptor{m_descriptor.degree()});
-
-                _computeEjkMean(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension,
-                                inv_Vj_wq_detJ_ek, mean_i_of_ejk);
-
-              } else {
-                throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type[cell_i_id])});
-              }
-
-              for (size_t l = 0; l < basis_dimension - 1; ++l) {
-                A(i, l) = mean_i_of_ejk[l] - mean_j_of_ejk[l];
-              }
-            }
-          } else if constexpr (MeshType::Dimension == 2) {
-            const Rd& Xj = xj[cell_j_id];
-
-            if (cell_type[cell_j_id] == CellType::Triangle) {
-              auto cell_node = cell_to_node_matrix[cell_j_id];
-
-              const TriangleTransformation<2> T{xr[cell_node[0]], xr[cell_node[1]], xr[cell_node[2]]};
-
-              const auto& quadrature =
-                QuadratureManager::instance().getTriangleFormula(GaussQuadratureDescriptor{m_descriptor.degree()});
-
-              _computeEjkMean(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension,
-                              inv_Vj_wq_detJ_ek, mean_j_of_ejk);
-
-            } else if (cell_type[cell_j_id] == CellType::Quadrangle) {
-              auto cell_node = cell_to_node_matrix[cell_j_id];
-
-              const SquareTransformation<2> T{xr[cell_node[0]], xr[cell_node[1]], xr[cell_node[2]], xr[cell_node[3]]};
-
-              const auto& quadrature = QuadratureManager::instance().getSquareFormula(
-                GaussLegendreQuadratureDescriptor{m_descriptor.degree() + 1});
-
-              _computeEjkMean(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension,
-                              inv_Vj_wq_detJ_ek, mean_j_of_ejk);
-
-            } else {
-              throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type[cell_j_id])});
-            }
-
-            for (size_t i = 0; i < stencil_cell_list.size(); ++i) {
-              const CellId cell_i_id = stencil_cell_list[i];
-
-              auto cell_node = cell_to_node_matrix[cell_i_id];
-
-              if (cell_type[cell_i_id] == CellType::Triangle) {
-                const TriangleTransformation<2> T{xr[cell_node[0]], xr[cell_node[1]], xr[cell_node[2]]};
-
-                const auto& quadrature =
-                  QuadratureManager::instance().getTriangleFormula(GaussQuadratureDescriptor{m_descriptor.degree()});
-
-                _computeEjkMean(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension,
-                                inv_Vj_wq_detJ_ek, mean_i_of_ejk);
-
-              } else if (cell_type[cell_i_id] == CellType::Quadrangle) {
-                const SquareTransformation<2> T{xr[cell_node[0]], xr[cell_node[1]], xr[cell_node[2]], xr[cell_node[3]]};
-
-                const auto& quadrature = QuadratureManager::instance().getSquareFormula(
-                  GaussLegendreQuadratureDescriptor{m_descriptor.degree() + 1});
-
-                _computeEjkMean(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension,
-                                inv_Vj_wq_detJ_ek, mean_i_of_ejk);
-
-              } else {
-                throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type[cell_i_id])});
-              }
-
-              for (size_t l = 0; l < basis_dimension - 1; ++l) {
-                A(i, l) = mean_i_of_ejk[l] - mean_j_of_ejk[l];
-              }
-            }
-
-          } else if constexpr (MeshType::Dimension == 3) {
-            const Rd& Xj = xj[cell_j_id];
-
-            if (cell_type[cell_j_id] == CellType::Tetrahedron) {
-              auto cell_node = cell_to_node_matrix[cell_j_id];
-
-              const TetrahedronTransformation T{xr[cell_node[0]], xr[cell_node[1]], xr[cell_node[2]], xr[cell_node[3]]};
-
-              const auto& quadrature =
-                QuadratureManager::instance().getTetrahedronFormula(GaussQuadratureDescriptor{m_descriptor.degree()});
-
-              _computeEjkMean(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension,
-                              inv_Vj_wq_detJ_ek, mean_j_of_ejk);
-
-            } else if (cell_type[cell_j_id] == CellType::Prism) {
-              auto cell_node = cell_to_node_matrix[cell_j_id];
-
-              const PrismTransformation T{xr[cell_node[0]], xr[cell_node[1]], xr[cell_node[2]],   //
-                                          xr[cell_node[3]], xr[cell_node[4]], xr[cell_node[5]]};
-
-              const auto& quadrature =
-                QuadratureManager::instance().getPrismFormula(GaussQuadratureDescriptor{m_descriptor.degree() + 1});
-
-              _computeEjkMean(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension,
-                              inv_Vj_wq_detJ_ek, mean_j_of_ejk);
-
-            } else if (cell_type[cell_j_id] == CellType::Pyramid) {
-              auto cell_node = cell_to_node_matrix[cell_j_id];
-
-              const PyramidTransformation T{xr[cell_node[0]], xr[cell_node[1]], xr[cell_node[2]], xr[cell_node[3]],
-                                            xr[cell_node[4]]};
-
-              const auto& quadrature =
-                QuadratureManager::instance().getPyramidFormula(GaussQuadratureDescriptor{m_descriptor.degree() + 1});
-
-              _computeEjkMean(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension,
-                              inv_Vj_wq_detJ_ek, mean_j_of_ejk);
-
-            } else if (cell_type[cell_j_id] == CellType::Hexahedron) {
-              auto cell_node = cell_to_node_matrix[cell_j_id];
-
-              const CubeTransformation T{xr[cell_node[0]], xr[cell_node[1]], xr[cell_node[2]], xr[cell_node[3]],
-                                         xr[cell_node[4]], xr[cell_node[5]], xr[cell_node[6]], xr[cell_node[7]]};
-
-              const auto& quadrature = QuadratureManager::instance().getCubeFormula(
-                GaussLegendreQuadratureDescriptor{m_descriptor.degree() + 1});
-
-              _computeEjkMean(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension,
-                              inv_Vj_wq_detJ_ek, mean_j_of_ejk);
-
-            } else {
-              throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type[cell_j_id])});
-            }
-
-            for (size_t i = 0; i < stencil_cell_list.size(); ++i) {
-              const CellId cell_i_id = stencil_cell_list[i];
-
-              auto cell_node = cell_to_node_matrix[cell_i_id];
-
-              if (cell_type[cell_i_id] == CellType::Tetrahedron) {
-                const TetrahedronTransformation T{xr[cell_node[0]], xr[cell_node[1]], xr[cell_node[2]],
-                                                  xr[cell_node[3]]};
-
-                const auto& quadrature =
-                  QuadratureManager::instance().getTetrahedronFormula(GaussQuadratureDescriptor{m_descriptor.degree()});
-
-                _computeEjkMean(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension,
-                                inv_Vj_wq_detJ_ek, mean_i_of_ejk);
-
-              } else if (cell_type[cell_i_id] == CellType::Prism) {
-                const PrismTransformation T{xr[cell_node[0]], xr[cell_node[1]], xr[cell_node[2]],   //
-                                            xr[cell_node[3]], xr[cell_node[4]], xr[cell_node[5]]};
-
-                const auto& quadrature =
-                  QuadratureManager::instance().getPrismFormula(GaussQuadratureDescriptor{m_descriptor.degree() + 1});
-
-                _computeEjkMean(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension,
-                                inv_Vj_wq_detJ_ek, mean_i_of_ejk);
-
-              } else if (cell_type[cell_i_id] == CellType::Pyramid) {
-                const PyramidTransformation T{xr[cell_node[0]], xr[cell_node[1]], xr[cell_node[2]], xr[cell_node[3]],
-                                              xr[cell_node[4]]};
-
-                const auto& quadrature =
-                  QuadratureManager::instance().getPyramidFormula(GaussQuadratureDescriptor{m_descriptor.degree() + 1});
-
-                _computeEjkMean(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension,
-                                inv_Vj_wq_detJ_ek, mean_i_of_ejk);
-
-              } else if (cell_type[cell_i_id] == CellType::Hexahedron) {
-                const CubeTransformation T{xr[cell_node[0]], xr[cell_node[1]], xr[cell_node[2]], xr[cell_node[3]],
-                                           xr[cell_node[4]], xr[cell_node[5]], xr[cell_node[6]], xr[cell_node[7]]};
+          const Rd& Xj = xj[cell_j_id];
 
-                const auto& quadrature = QuadratureManager::instance().getCubeFormula(
-                  GaussLegendreQuadratureDescriptor{m_descriptor.degree() + 1});
+          _computeEjkMean(Xj, xr, cell_to_node_matrix[cell_j_id], cell_type[cell_j_id], Vj[cell_j_id],
+                          m_descriptor.degree(), basis_dimension, inv_Vj_wq_detJ_ek, mean_j_of_ejk);
 
-                _computeEjkMean(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension,
-                                inv_Vj_wq_detJ_ek, mean_i_of_ejk);
+          for (size_t i = 0; i < stencil_cell_list.size(); ++i) {
+            const CellId cell_i_id = stencil_cell_list[i];
 
-              } else {
-                throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type[cell_i_id])});
-              }
+            _computeEjkMean(Xj, xr, cell_to_node_matrix[cell_i_id], cell_type[cell_i_id], Vj[cell_i_id],
+                            m_descriptor.degree(), basis_dimension, inv_Vj_wq_detJ_ek, mean_i_of_ejk);
 
-              for (size_t l = 0; l < basis_dimension - 1; ++l) {
-                A(i, l) = mean_i_of_ejk[l] - mean_j_of_ejk[l];
-              }
+            for (size_t l = 0; l < basis_dimension - 1; ++l) {
+              A(i, l) = mean_i_of_ejk[l] - mean_j_of_ejk[l];
             }
-
-          } else {
-            throw NotImplementedError("unexpected dimension");
           }
         }
 
@@ -717,7 +648,7 @@ PolynomialReconstruction::_build(
 
         if (m_descriptor.preconditioning()) {
           // Add column  weighting preconditioning (increase the presition)
-          SmallArray<double>& G = G_pool[t];
+          SmallVector<double>& G = G_pool[t];
 
           for (size_t l = 0; l < basis_dimension - 1; ++l) {
             double g = 0;
diff --git a/src/scheme/PolynomialReconstruction.hpp b/src/scheme/PolynomialReconstruction.hpp
index f523148728712bdf6cb29af45686d3db9b0a0bae..b2b855271d1ed4140ebb51d1b21314602caa0dc6 100644
--- a/src/scheme/PolynomialReconstruction.hpp
+++ b/src/scheme/PolynomialReconstruction.hpp
@@ -1,24 +1,9 @@
 #ifndef POLYNOMIAL_RECONSTRUCTION_HPP
 #define POLYNOMIAL_RECONSTRUCTION_HPP
 
-#include <algebra/ShrinkMatrixView.hpp>
-#include <algebra/ShrinkVectorView.hpp>
-#include <algebra/SmallMatrix.hpp>
-#include <algebra/SmallVector.hpp>
 #include <mesh/MeshTraits.hpp>
-#include <scheme/DiscreteFunctionDPkVariant.hpp>
 #include <scheme/PolynomialReconstructionDescriptor.hpp>
 
-#warning MOVE TO .cpp WHEN FINISHED
-#include <algebra/Givens.hpp>
-#include <analysis/GaussLegendreQuadratureDescriptor.hpp>
-#include <analysis/QuadratureFormula.hpp>
-#include <analysis/QuadratureManager.hpp>
-#include <geometry/LineTransformation.hpp>
-#include <mesh/MeshData.hpp>
-#include <mesh/MeshDataManager.hpp>
-#include <mesh/StencilManager.hpp>
-
 class DiscreteFunctionDPkVariant;
 class DiscreteFunctionVariant;
 
diff --git a/tests/test_PolynomialReconstruction.cpp b/tests/test_PolynomialReconstruction.cpp
index 47a538f0d1f4e32d8367616739b878ddbe728cb7..b7c7019f57e6227de20f746900d87416e0a400ff 100644
--- a/tests/test_PolynomialReconstruction.cpp
+++ b/tests/test_PolynomialReconstruction.cpp
@@ -11,6 +11,7 @@
 #include <algebra/SmallVector.hpp>
 #include <mesh/Mesh.hpp>
 #include <mesh/MeshDataManager.hpp>
+#include <scheme/DiscreteFunctionDPkVariant.hpp>
 #include <scheme/DiscreteFunctionP0.hpp>
 #include <scheme/DiscreteFunctionVariant.hpp>
 #include <scheme/PolynomialReconstruction.hpp>