diff --git a/src/scheme/PolynomialReconstruction.cpp b/src/scheme/PolynomialReconstruction.cpp
index e3fe0193092fa5daccda3009c5c65d97b5afb31e..7557c284e1fa86fd65d21480642850ea6f5a3504 100644
--- a/src/scheme/PolynomialReconstruction.cpp
+++ b/src/scheme/PolynomialReconstruction.cpp
@@ -102,12 +102,11 @@ class PolynomialReconstruction::MutableDiscreteFunctionDPkVariant
 template <MeshConcept MeshType>
 [[nodiscard]] std::vector<std::shared_ptr<const DiscreteFunctionDPkVariant>>
 PolynomialReconstruction::_build(
-  const size_t degree,
-  const bool preconditioning,
-  const bool row_weighting,
   const std::shared_ptr<const MeshType>& p_mesh,
   const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list) const
 {
+  const size_t degree = m_descriptor.degree();
+
   if (degree != 1) {
     throw NotImplementedError("only degree 1 is available");
   }
@@ -282,7 +281,7 @@ PolynomialReconstruction::_build(
           }
         }
 
-        if (row_weighting) {
+        if (m_descriptor.rowWeighting()) {
           // Add row weighting (give more importance to cells that are
           // closer to j)
           for (size_t i = 0; i < stencil_cell_list.size(); ++i) {
@@ -299,7 +298,7 @@ PolynomialReconstruction::_build(
 
         const SmallMatrix<double>& X = X_pool[t];
 
-        if (preconditioning) {
+        if (m_descriptor.preconditioning()) {
           // Add column  weighting preconditioning (increase the presition)
           SmallArray<double>& G = G_pool[t];
 
@@ -447,9 +446,6 @@ PolynomialReconstruction::_build(
 
 std::vector<std::shared_ptr<const DiscreteFunctionDPkVariant>>
 PolynomialReconstruction::build(
-  const size_t degree,
-  const bool preconditioning,
-  const bool row_weighting,
   const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list) const
 {
   if (not hasSameMesh(discrete_function_variant_list)) {
@@ -458,9 +454,6 @@ PolynomialReconstruction::build(
 
   auto mesh_v = getCommonMesh(discrete_function_variant_list);
 
-  return std::visit(
-    [&](auto&& p_mesh) {
-      return this->_build(degree, preconditioning, row_weighting, p_mesh, discrete_function_variant_list);
-    },
-    mesh_v->variant());
+  return std::visit([&](auto&& p_mesh) { return this->_build(p_mesh, discrete_function_variant_list); },
+                    mesh_v->variant());
 }
diff --git a/src/scheme/PolynomialReconstruction.hpp b/src/scheme/PolynomialReconstruction.hpp
index 74bb827854facd86fc7e51191468908b72d6b481..c0da0f26074cce3e38457d9fa1901ed6ef194e43 100644
--- a/src/scheme/PolynomialReconstruction.hpp
+++ b/src/scheme/PolynomialReconstruction.hpp
@@ -7,6 +7,7 @@
 #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>
@@ -26,11 +27,10 @@ class PolynomialReconstruction
  private:
   class MutableDiscreteFunctionDPkVariant;
 
+  const PolynomialReconstructionDescriptor m_descriptor;
+
   template <MeshConcept MeshType>
   [[nodiscard]] std::vector<std::shared_ptr<const DiscreteFunctionDPkVariant>> _build(
-    const size_t degree,
-    const bool preconditioning,
-    const bool row_weighting,
     const std::shared_ptr<const MeshType>& p_mesh,
     const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list) const;
 
@@ -266,15 +266,11 @@ class PolynomialReconstruction
   }
 
   [[nodiscard]] std::vector<std::shared_ptr<const DiscreteFunctionDPkVariant>> build(
-    const size_t degree,
-    const bool preconditioning,
-    const bool row_weighting,
     const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list) const;
 
-#warning add reconstruction descriptor/option to handle the options to be used for reconstruction
   template <typename... DiscreteFunctionT>
   [[nodiscard]] std::vector<std::shared_ptr<const DiscreteFunctionDPkVariant>>
-  build(const size_t degree, const bool preconditioning, const bool row_weighting, DiscreteFunctionT... input) const
+  build(DiscreteFunctionT... input) const
   {
     std::vector<std::shared_ptr<const DiscreteFunctionVariant>> variant_vector;
     auto convert = [&variant_vector](auto&& df) {
@@ -294,10 +290,11 @@ class PolynomialReconstruction
     };
 
     (convert(std::forward<DiscreteFunctionT>(input)), ...);
-    return this->build(degree, preconditioning, row_weighting, variant_vector);
+    return this->build(variant_vector);
   }
 
-  PolynomialReconstruction() {}
+  PolynomialReconstruction(const PolynomialReconstructionDescriptor& descriptor) : m_descriptor{descriptor} {}
+  ~PolynomialReconstruction() = default;
 };
 
 #endif   // POLYNOMIAL_RECONSTRUCTION_HPP
diff --git a/src/scheme/PolynomialReconstructionDescriptor.hpp b/src/scheme/PolynomialReconstructionDescriptor.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a7394500106b2f8a43c5e62f9ee74912b4d8fee5
--- /dev/null
+++ b/src/scheme/PolynomialReconstructionDescriptor.hpp
@@ -0,0 +1,68 @@
+#ifndef POLYNOMIAL_RECONSTRUCTION_DESCRIPTOR_HPP
+#define POLYNOMIAL_RECONSTRUCTION_DESCRIPTOR_HPP
+
+#include <utils/PugsMacros.hpp>
+
+#include <cstddef>
+
+class PolynomialReconstructionDescriptor
+{
+ private:
+  size_t m_degree;
+  bool m_preconditioning = true;
+  bool m_row_weighting   = true;
+
+ public:
+  PUGS_INLINE
+  size_t
+  degree() const
+  {
+    return m_degree;
+  }
+
+  PUGS_INLINE
+  bool
+  preconditioning() const
+  {
+    return m_preconditioning;
+  }
+
+  PUGS_INLINE
+  bool
+  rowWeighting() const
+  {
+    return m_row_weighting;
+  }
+
+  PUGS_INLINE
+  void
+  setDegree(const size_t degree)
+  {
+    m_degree = degree;
+  }
+
+  PUGS_INLINE
+  void
+  setPreconditioning(const bool preconditioning)
+  {
+    m_preconditioning = preconditioning;
+  }
+
+  PUGS_INLINE
+  void
+  setRowWeighting(const bool row_weighting)
+  {
+    m_row_weighting = row_weighting;
+  }
+
+  PolynomialReconstructionDescriptor(const size_t degree) : m_degree{degree} {}
+
+  PolynomialReconstructionDescriptor() = delete;
+
+  PolynomialReconstructionDescriptor(const PolynomialReconstructionDescriptor&) = default;
+  PolynomialReconstructionDescriptor(PolynomialReconstructionDescriptor&&)      = default;
+
+  ~PolynomialReconstructionDescriptor() = default;
+};
+
+#endif   // POLYNOMIAL_RECONSTRUCTION_DESCRIPTOR_HPP
diff --git a/src/scheme/test_reconstruction.cpp b/src/scheme/test_reconstruction.cpp
index 1267aabecc233fc3b042b026e2dd6897afe2b1c6..6639b84938fc94609b8d7ccf98f50389ece9f37d 100644
--- a/src/scheme/test_reconstruction.cpp
+++ b/src/scheme/test_reconstruction.cpp
@@ -8,13 +8,14 @@ test_reconstruction(const std::shared_ptr<const MeshVariant>& mesh_v,
                     const std::shared_ptr<const DiscreteFunctionVariant>& discrete_function_v)
 {
   std::cout << "** one variable at a time (30 times)\n";
+  PolynomialReconstructionDescriptor descriptor{1};
 
   std::visit(
     [&](auto&& p_mesh) {
       std::visit(
         [&](auto&& discrete_function) {
           using DiscreteFunctionT = std::decay_t<decltype(discrete_function)>;
-          PolynomialReconstruction reconstruction;
+          PolynomialReconstruction reconstruction{descriptor};
           if constexpr (is_discrete_function_P0_v<DiscreteFunctionT>) {
             Timer t;
             for (size_t i = 0; i < 30; ++i) {
@@ -35,12 +36,13 @@ void
 test_reconstruction_one(const std::shared_ptr<const MeshVariant>& mesh_v,
                         const std::shared_ptr<const DiscreteFunctionVariant>& discrete_function_v)
 {
+  PolynomialReconstructionDescriptor descriptor{1};
   std::visit(
     [&](auto&& p_mesh) {
       std::visit(
         [&](auto&& discrete_function) {
           using DiscreteFunctionT = std::decay_t<decltype(discrete_function)>;
-          PolynomialReconstruction reconstruction;
+          PolynomialReconstruction reconstruction{descriptor};
           if constexpr (is_discrete_function_P0_v<DiscreteFunctionT>) {
             for (size_t i = 0; i < 30; ++i) {
               auto res = reconstruction.build(*p_mesh, discrete_function);
@@ -55,6 +57,7 @@ test_reconstruction_one(const std::shared_ptr<const MeshVariant>& mesh_v,
 void
 test_reconstruction(const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list)
 {
+  PolynomialReconstructionDescriptor descriptor{1};
   {
     std::cout << "** variable list one by one (50 times)\n";
     Timer t;
@@ -65,7 +68,7 @@ test_reconstruction(const std::vector<std::shared_ptr<const DiscreteFunctionVari
           std::visit(
             [&](auto&& p_mesh) {
               using DiscreteFunctionT = std::decay_t<decltype(discrete_function)>;
-              PolynomialReconstruction reconstruction;
+              PolynomialReconstruction reconstruction{descriptor};
               if constexpr (is_discrete_function_P0_v<DiscreteFunctionT>) {
                 for (size_t i = 0; i < 50; ++i) {
                   auto res = reconstruction.build(*p_mesh, discrete_function);
@@ -84,10 +87,11 @@ test_reconstruction(const std::vector<std::shared_ptr<const DiscreteFunctionVari
 
   {
     std::cout << "** variable list at once (50 times)\n";
-    PolynomialReconstruction reconstruction;
+
+    PolynomialReconstruction reconstruction{descriptor};
     Timer t;
     for (size_t i = 0; i < 50; ++i) {
-      auto res = reconstruction.build(1, true, true, discrete_function_variant_list);
+      auto res = reconstruction.build(discrete_function_variant_list);
     }
     t.pause();
     std::cout << "t = " << t << '\n';
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 4c94f8a3974de5399bbeee7ea7f79eeb13d94aa2..b242c06dc5ff8c5d0882b46f962926890b51e433 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -206,6 +206,7 @@ add_executable (mpi_unit_tests
   test_ParallelChecker_read.cpp
   test_Partitioner.cpp
   test_PolynomialReconstruction.cpp
+  test_PolynomialReconstructionDescriptor.cpp
   test_RandomEngine.cpp
   test_StencilBuilder.cpp
   test_SubItemArrayPerItemVariant.cpp
diff --git a/tests/test_PolynomialReconstruction.cpp b/tests/test_PolynomialReconstruction.cpp
index 2f25f0168cd8f390e0baa129eb3fa0070cf1222e..d9b33b9111aa0e17175a84b4e0406d89f4f218e8 100644
--- a/tests/test_PolynomialReconstruction.cpp
+++ b/tests/test_PolynomialReconstruction.cpp
@@ -23,6 +23,8 @@ TEST_CASE("PolynomialReconstruction", "[scheme]")
 {
   SECTION("degree 1")
   {
+    PolynomialReconstructionDescriptor descriptor{1};
+
     SECTION("1D")
     {
       using R1 = TinyVector<1>;
@@ -43,7 +45,7 @@ TEST_CASE("PolynomialReconstruction", "[scheme]")
             parallel_for(
               mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { fh[cell_id] = R_affine(xj[cell_id]); });
 
-            auto reconstructions = PolynomialReconstruction{}.build(1, true, true, fh);
+            auto reconstructions = PolynomialReconstruction{descriptor}.build(fh);
 
             auto dpk_fh = reconstructions[0]->get<DiscreteFunctionDPk<1, const double>>();
 
@@ -92,7 +94,7 @@ TEST_CASE("PolynomialReconstruction", "[scheme]")
             parallel_for(
               mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { uh[cell_id] = R3_affine(xj[cell_id]); });
 
-            auto reconstructions = PolynomialReconstruction{}.build(1, true, true, uh);
+            auto reconstructions = PolynomialReconstruction{descriptor}.build(uh);
 
             auto dpk_uh = reconstructions[0]->get<DiscreteFunctionDPk<1, const R3>>();
 
@@ -143,7 +145,7 @@ TEST_CASE("PolynomialReconstruction", "[scheme]")
             parallel_for(
               mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { Ah[cell_id] = R3x3_affine(xj[cell_id]); });
 
-            auto reconstructions = PolynomialReconstruction{}.build(1, true, true, Ah);
+            auto reconstructions = PolynomialReconstruction{descriptor}.build(Ah);
 
             auto dpk_Ah = reconstructions[0]->get<DiscreteFunctionDPk<1, const R3x3>>();
 
@@ -200,7 +202,7 @@ TEST_CASE("PolynomialReconstruction", "[scheme]")
                 }
               });
 
-            auto reconstructions = PolynomialReconstruction{}.build(1, true, true, Vh);
+            auto reconstructions = PolynomialReconstruction{descriptor}.build(Vh);
 
             auto dpk_Vh = reconstructions[0]->get<DiscreteFunctionDPkVector<1, const double>>();
 
@@ -288,9 +290,9 @@ TEST_CASE("PolynomialReconstruction", "[scheme]")
               });
 
             auto reconstructions =
-              PolynomialReconstruction{}.build(1, true, true, std::make_shared<DiscreteFunctionVariant>(fh), uh,
-                                               std::make_shared<DiscreteFunctionP0<R3x3>>(Ah),
-                                               DiscreteFunctionVariant(Vh));
+              PolynomialReconstruction{descriptor}.build(std::make_shared<DiscreteFunctionVariant>(fh), uh,
+                                                         std::make_shared<DiscreteFunctionP0<R3x3>>(Ah),
+                                                         DiscreteFunctionVariant(Vh));
 
             auto dpk_fh = reconstructions[0]->get<DiscreteFunctionDPk<1, const double>>();
 
@@ -415,7 +417,7 @@ TEST_CASE("PolynomialReconstruction", "[scheme]")
             parallel_for(
               mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { fh[cell_id] = R_affine(xj[cell_id]); });
 
-            auto reconstructions = PolynomialReconstruction{}.build(1, true, true, fh);
+            auto reconstructions = PolynomialReconstruction{descriptor}.build(fh);
 
             auto dpk_fh = reconstructions[0]->get<DiscreteFunctionDPk<2, const double>>();
 
@@ -475,7 +477,7 @@ TEST_CASE("PolynomialReconstruction", "[scheme]")
             parallel_for(
               mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { uh[cell_id] = R3_affine(xj[cell_id]); });
 
-            auto reconstructions = PolynomialReconstruction{}.build(1, true, true, uh);
+            auto reconstructions = PolynomialReconstruction{descriptor}.build(uh);
 
             auto dpk_uh = reconstructions[0]->get<DiscreteFunctionDPk<2, const R3>>();
 
@@ -534,7 +536,7 @@ TEST_CASE("PolynomialReconstruction", "[scheme]")
             parallel_for(
               mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { Ah[cell_id] = R2x2_affine(xj[cell_id]); });
 
-            auto reconstructions = PolynomialReconstruction{}.build(1, true, true, Ah);
+            auto reconstructions = PolynomialReconstruction{descriptor}.build(Ah);
 
             auto dpk_Ah = reconstructions[0]->get<DiscreteFunctionDPk<2, const R2x2>>();
 
@@ -602,7 +604,7 @@ TEST_CASE("PolynomialReconstruction", "[scheme]")
                 }
               });
 
-            auto reconstructions = PolynomialReconstruction{}.build(1, true, true, Vh);
+            auto reconstructions = PolynomialReconstruction{descriptor}.build(Vh);
 
             auto dpk_Vh = reconstructions[0]->get<DiscreteFunctionDPkVector<2, const double>>();
 
@@ -669,7 +671,7 @@ TEST_CASE("PolynomialReconstruction", "[scheme]")
             parallel_for(
               mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { fh[cell_id] = R_affine(xj[cell_id]); });
 
-            auto reconstructions = PolynomialReconstruction{}.build(1, true, true, fh);
+            auto reconstructions = PolynomialReconstruction{descriptor}.build(fh);
 
             auto dpk_fh = reconstructions[0]->get<DiscreteFunctionDPk<3, const double>>();
 
@@ -738,7 +740,7 @@ TEST_CASE("PolynomialReconstruction", "[scheme]")
             parallel_for(
               mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { uh[cell_id] = R3_affine(xj[cell_id]); });
 
-            auto reconstructions = PolynomialReconstruction{}.build(1, true, true, uh);
+            auto reconstructions = PolynomialReconstruction{descriptor}.build(uh);
 
             auto dpk_uh = reconstructions[0]->get<DiscreteFunctionDPk<3, const R3>>();
 
@@ -809,7 +811,8 @@ TEST_CASE("PolynomialReconstruction", "[scheme]")
             parallel_for(
               mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { Ah[cell_id] = R2x2_affine(xj[cell_id]); });
 
-            auto reconstructions = PolynomialReconstruction{}.build(1, true, true, Ah);
+            descriptor.setRowWeighting(false);
+            auto reconstructions = PolynomialReconstruction{descriptor}.build(Ah);
 
             auto dpk_Ah = reconstructions[0]->get<DiscreteFunctionDPk<3, const R2x2>>();
 
@@ -890,7 +893,8 @@ TEST_CASE("PolynomialReconstruction", "[scheme]")
                 }
               });
 
-            auto reconstructions = PolynomialReconstruction{}.build(1, true, true, Vh);
+            descriptor.setPreconditioning(false);
+            auto reconstructions = PolynomialReconstruction{descriptor}.build(Vh);
 
             auto dpk_Vh = reconstructions[0]->get<DiscreteFunctionDPkVector<3, const double>>();
 
@@ -959,7 +963,7 @@ TEST_CASE("PolynomialReconstruction", "[scheme]")
       auto p_mesh2 = MeshDataBaseForTests::get().cartesian1DMesh()->get<Mesh<1>>();
       DiscreteFunctionP0<double> f2{p_mesh2};
 
-      REQUIRE_THROWS_WITH(PolynomialReconstruction{}.build(1, true, true, f1, f2),
+      REQUIRE_THROWS_WITH(PolynomialReconstruction{descriptor}.build(f1, f2),
                           "error: cannot reconstruct functions living of different meshes simultaneously");
     }
   }
diff --git a/tests/test_PolynomialReconstructionDescriptor.cpp b/tests/test_PolynomialReconstructionDescriptor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6b7cd2853c783449f8b8f9167c06241a47b00b38
--- /dev/null
+++ b/tests/test_PolynomialReconstructionDescriptor.cpp
@@ -0,0 +1,82 @@
+#include <catch2/catch_approx.hpp>
+#include <catch2/catch_test_macros.hpp>
+#include <catch2/matchers/catch_matchers_all.hpp>
+
+#include <scheme/PolynomialReconstructionDescriptor.hpp>
+
+// clazy:excludeall=non-pod-global-static
+
+TEST_CASE("PolynomialReconstructionDescriptor", "[scheme]")
+{
+  SECTION("degree 1")
+  {
+    PolynomialReconstructionDescriptor descriptor{1};
+
+    REQUIRE(descriptor.degree() == 1);
+    REQUIRE(descriptor.preconditioning() == true);
+    REQUIRE(descriptor.rowWeighting() == true);
+  }
+
+  SECTION("degree 4")
+  {
+    PolynomialReconstructionDescriptor descriptor{4};
+
+    REQUIRE(descriptor.degree() == 4);
+    REQUIRE(descriptor.preconditioning() == true);
+    REQUIRE(descriptor.rowWeighting() == true);
+  }
+
+  SECTION("utlities")
+  {
+    PolynomialReconstructionDescriptor descriptor{3};
+
+    REQUIRE(descriptor.degree() == 3);
+    REQUIRE(descriptor.preconditioning() == true);
+    REQUIRE(descriptor.rowWeighting() == true);
+
+    SECTION("set degree")
+    {
+      descriptor.setDegree(2);
+
+      REQUIRE(descriptor.degree() == 2);
+      REQUIRE(descriptor.preconditioning() == true);
+      REQUIRE(descriptor.rowWeighting() == true);
+
+      descriptor.setDegree(4);
+
+      REQUIRE(descriptor.degree() == 4);
+      REQUIRE(descriptor.preconditioning() == true);
+      REQUIRE(descriptor.rowWeighting() == true);
+    }
+
+    SECTION("set preconditioning")
+    {
+      descriptor.setPreconditioning(false);
+
+      REQUIRE(descriptor.degree() == 3);
+      REQUIRE(descriptor.preconditioning() == false);
+      REQUIRE(descriptor.rowWeighting() == true);
+
+      descriptor.setPreconditioning(true);
+
+      REQUIRE(descriptor.degree() == 3);
+      REQUIRE(descriptor.preconditioning() == true);
+      REQUIRE(descriptor.rowWeighting() == true);
+    }
+
+    SECTION("set row weighting")
+    {
+      descriptor.setRowWeighting(false);
+
+      REQUIRE(descriptor.degree() == 3);
+      REQUIRE(descriptor.preconditioning() == true);
+      REQUIRE(descriptor.rowWeighting() == false);
+
+      descriptor.setRowWeighting(true);
+
+      REQUIRE(descriptor.degree() == 3);
+      REQUIRE(descriptor.preconditioning() == true);
+      REQUIRE(descriptor.rowWeighting() == true);
+    }
+  }
+}