diff --git a/src/mesh/Stencil.hpp b/src/mesh/Stencil.hpp
index 5dc20dc326fe0ebc716df1b85fb766f50cc790e0..900c1b4d2e5dad1ff338c7c7714fcbe5f498cfb7 100644
--- a/src/mesh/Stencil.hpp
+++ b/src/mesh/Stencil.hpp
@@ -2,21 +2,26 @@
 #define STENCIL_HPP
 
 #include <mesh/ConnectivityMatrix.hpp>
+#include <mesh/IBoundaryDescriptor.hpp>
 #include <mesh/ItemId.hpp>
 
 class Stencil
 {
+ public:
+  using BoundaryDescriptorStencilList =
+    std::vector<std::pair<std::shared_ptr<const IBoundaryDescriptor>, ConnectivityMatrix>>;
+
  private:
   ConnectivityMatrix m_stencil;
-#warning TEMPORARY IMPLEMENTATION
-  std::vector<std::pair<std::string, ConnectivityMatrix>> m_symmetry_name_stencil;
+  BoundaryDescriptorStencilList m_symmetry_boundary_stencil_list;
 
  public:
+#warning REWORK INTERFACE
   PUGS_INLINE
   const auto&
-  symmetryNameStencil() const
+  symmetryBoundaryStencilList() const
   {
-    return m_symmetry_name_stencil;
+    return m_symmetry_boundary_stencil_list;
   }
 
   PUGS_INLINE
@@ -26,13 +31,14 @@ class Stencil
     return m_stencil[cell_id];
   }
 
-  Stencil(const ConnectivityMatrix& stencil,
-          const std::vector<std::pair<std::string, ConnectivityMatrix>>& symmetry_name_stencil)
-    : m_stencil{stencil}, m_symmetry_name_stencil{symmetry_name_stencil}
+  Stencil(const ConnectivityMatrix& stencil, const BoundaryDescriptorStencilList& symmetry_name_stencil)
+    : m_stencil{stencil}, m_symmetry_boundary_stencil_list{symmetry_name_stencil}
   {}
+
   Stencil(const Stencil&) = default;
   Stencil(Stencil&&)      = default;
-  ~Stencil()              = default;
+
+  ~Stencil() = default;
 };
 
 #endif   // STENCIL_HPP
diff --git a/src/mesh/StencilBuilder.cpp b/src/mesh/StencilBuilder.cpp
index 209007a2dc234a776ef3aee8d958b11942e462dd..ddff37e0cb6a693999701b83eb5418ef35644af8 100644
--- a/src/mesh/StencilBuilder.cpp
+++ b/src/mesh/StencilBuilder.cpp
@@ -111,10 +111,10 @@ template <typename ConnectivityType>
 Stencil
 StencilBuilder::_build(const ConnectivityType& connectivity,
                        size_t number_of_layers,
-                       const std::set<std::string>& symmetry_boundary_names) const
+                       const BoundaryDescriptorList& symmetry_boundary_descriptor_list) const
 {
 #warning TEMPORARY
-  if (symmetry_boundary_names.size() == 0) {
+  if (symmetry_boundary_descriptor_list.size() == 0) {
     if (number_of_layers == 1) {
       Array<const uint32_t> row_map        = this->_getRowMap(connectivity);
       Array<const uint32_t> column_indices = this->_getColumnIndices(connectivity, row_map);
@@ -189,7 +189,7 @@ StencilBuilder::_build(const ConnectivityType& connectivity,
     if constexpr (ConnectivityType::Dimension > 1) {
       std::vector<Array<const FaceId>> boundary_node_list;
 
-      NodeArray<bool> symmetry_node_list(connectivity, symmetry_boundary_names.size());
+      NodeArray<bool> symmetry_node_list(connectivity, symmetry_boundary_descriptor_list.size());
       symmetry_node_list.fill(0);
 
       auto face_to_node_matrix = connectivity.faceToNodeMatrix();
@@ -197,13 +197,15 @@ StencilBuilder::_build(const ConnectivityType& connectivity,
       auto node_to_cell_matrix = connectivity.nodeToCellMatrix();
 
       {
-        size_t i_boundary_name = 0;
-        for (auto boundary_name : symmetry_boundary_names) {
+        size_t i_symmetry_boundary = 0;
+        for (auto p_boundary_descriptor : symmetry_boundary_descriptor_list) {
+          const IBoundaryDescriptor& boundary_descriptor = *p_boundary_descriptor;
+
           bool found = false;
           for (size_t i_ref_node_list = 0;
                i_ref_node_list < connectivity.template numberOfRefItemList<ItemType::face>(); ++i_ref_node_list) {
             const auto& ref_face_list = connectivity.template refItemList<ItemType::face>(i_ref_node_list);
-            if (ref_face_list.refId().tagName() == boundary_name) {
+            if (ref_face_list.refId() == boundary_descriptor) {
               found = true;
               boundary_node_list.push_back(ref_face_list.list());
               for (size_t i_face = 0; i_face < ref_face_list.list().size(); ++i_face) {
@@ -212,16 +214,17 @@ StencilBuilder::_build(const ConnectivityType& connectivity,
                 for (size_t i_node = 0; i_node < node_list.size(); ++i_node) {
                   const NodeId node_id = node_list[i_node];
 
-                  symmetry_node_list[node_id][i_boundary_name] = true;
+                  symmetry_node_list[node_id][i_symmetry_boundary] = true;
                 }
               }
               break;
             }
           }
-          ++i_boundary_name;
+          ++i_symmetry_boundary;
           if (not found) {
             std::ostringstream error_msg;
-            error_msg << "cannot find boundary '" << rang::fgB::yellow << boundary_name << rang::fg::reset << '\'';
+            error_msg << "cannot find boundary '" << rang::fgB::yellow << boundary_descriptor << rang::fg::reset
+                      << '\'';
             throw NormalError(error_msg.str());
           }
         }
@@ -232,18 +235,18 @@ StencilBuilder::_build(const ConnectivityType& connectivity,
 
       Array<uint32_t> row_map{connectivity.numberOfCells() + 1};
       row_map[0] = 0;
-      std::vector<Array<uint32_t>> symmetry_row_map_list(symmetry_boundary_names.size());
+      std::vector<Array<uint32_t>> symmetry_row_map_list(symmetry_boundary_descriptor_list.size());
       for (auto&& symmetry_row_map : symmetry_row_map_list) {
         symmetry_row_map    = Array<uint32_t>{connectivity.numberOfCells() + 1};
         symmetry_row_map[0] = 0;
       }
 
       std::vector<uint32_t> column_indices_vector;
-      std::vector<std::vector<uint32_t>> symmetry_column_indices_vector(symmetry_boundary_names.size());
+      std::vector<std::vector<uint32_t>> symmetry_column_indices_vector(symmetry_boundary_descriptor_list.size());
 
       for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) {
         std::set<CellId> cell_set;
-        std::vector<std::set<CellId>> by_boundary_symmetry_cell(symmetry_boundary_names.size());
+        std::vector<std::set<CellId>> by_boundary_symmetry_cell(symmetry_boundary_descriptor_list.size());
 
         if (cell_is_owned[cell_id]) {
           auto cell_node_list = cell_to_node_matrix[cell_id];
@@ -273,7 +276,7 @@ StencilBuilder::_build(const ConnectivityType& connectivity,
             }
           }
 
-          for (size_t i = 0; i < symmetry_boundary_names.size(); ++i) {
+          for (size_t i = 0; i < symmetry_boundary_descriptor_list.size(); ++i) {
             std::set<CellId> symmetry_cell_set;
             for (size_t i_cell_node = 0; i_cell_node < cell_node_list.size(); ++i_cell_node) {
               const NodeId cell_node_id = cell_node_list[i_cell_node];
@@ -310,18 +313,19 @@ StencilBuilder::_build(const ConnectivityType& connectivity,
       }
       ConnectivityMatrix primal_stencil{row_map, convert_to_array(column_indices_vector)};
 
-      std::vector<std::pair<std::string, ConnectivityMatrix>> symmetry_name_stencil;
+      Stencil::BoundaryDescriptorStencilList symmetry_boundary_stencil_list;
       {
         size_t i = 0;
-        for (auto&& boundary_name : symmetry_boundary_names) {
-          symmetry_name_stencil.emplace_back(
-            std::make_pair(boundary_name, ConnectivityMatrix{symmetry_row_map_list[i],
-                                                             convert_to_array(symmetry_column_indices_vector[i])}));
+        for (auto&& p_boundary_descriptor : symmetry_boundary_descriptor_list) {
+          symmetry_boundary_stencil_list.emplace_back(
+            std::make_pair(p_boundary_descriptor,
+                           ConnectivityMatrix{symmetry_row_map_list[i],
+                                              convert_to_array(symmetry_column_indices_vector[i])}));
           ++i;
         }
       }
 
-      return {{primal_stencil}, {symmetry_name_stencil}};
+      return {{primal_stencil}, {symmetry_boundary_stencil_list}};
 
     } else {
       throw NotImplementedError("Only implemented in 2D/3D");
@@ -332,20 +336,20 @@ StencilBuilder::_build(const ConnectivityType& connectivity,
 Stencil
 StencilBuilder::build(const IConnectivity& connectivity,
                       size_t number_of_layers,
-                      const std::set<std::string>& symmetry_boundary_names) const
+                      const BoundaryDescriptorList& symmetry_boundary_descriptor_list) const
 {
   switch (connectivity.dimension()) {
   case 1: {
     return StencilBuilder::_build(dynamic_cast<const Connectivity<1>&>(connectivity), number_of_layers,
-                                  symmetry_boundary_names);
+                                  symmetry_boundary_descriptor_list);
   }
   case 2: {
     return StencilBuilder::_build(dynamic_cast<const Connectivity<2>&>(connectivity), number_of_layers,
-                                  symmetry_boundary_names);
+                                  symmetry_boundary_descriptor_list);
   }
   case 3: {
     return StencilBuilder::_build(dynamic_cast<const Connectivity<3>&>(connectivity), number_of_layers,
-                                  symmetry_boundary_names);
+                                  symmetry_boundary_descriptor_list);
   }
   default: {
     throw UnexpectedError("invalid connectivity dimension");
diff --git a/src/mesh/StencilBuilder.hpp b/src/mesh/StencilBuilder.hpp
index c52933da26b4969410eba7f8aca090842ba9fdc8..7f11c0686a49adebeb4c7ffd5a0c945c6b6fa07d 100644
--- a/src/mesh/StencilBuilder.hpp
+++ b/src/mesh/StencilBuilder.hpp
@@ -1,14 +1,18 @@
 #ifndef STENCIL_BUILDER_HPP
 #define STENCIL_BUILDER_HPP
 
+#include <mesh/IBoundaryDescriptor.hpp>
 #include <mesh/Stencil.hpp>
 
-#include <set>
 #include <string>
+#include <vector>
 
 class IConnectivity;
 class StencilBuilder
 {
+ public:
+  using BoundaryDescriptorList = std::vector<std::shared_ptr<const IBoundaryDescriptor>>;
+
  private:
   template <typename ConnectivityType>
   Array<const uint32_t> _getRowMap(const ConnectivityType& connectivity) const;
@@ -20,12 +24,12 @@ class StencilBuilder
   template <typename ConnectivityType>
   Stencil _build(const ConnectivityType& connectivity,
                  size_t number_of_layers,
-                 const std::set<std::string>& symmetry_boundary_names) const;
+                 const BoundaryDescriptorList& symmetry_boundary_descriptor_list) const;
 
   friend class StencilManager;
   Stencil build(const IConnectivity& connectivity,
                 size_t number_of_layers,
-                const std::set<std::string>& symmetry_boundary_names) const;
+                const BoundaryDescriptorList& symmetry_boundary_descriptor_list) const;
 
  public:
   StencilBuilder()                      = default;
diff --git a/src/mesh/StencilManager.cpp b/src/mesh/StencilManager.cpp
index 618431ee75dab1696c4500a306dd70a9f99e1e7f..cc99577f23a5d9b85e344d39a1dc0e2260dcb22a 100644
--- a/src/mesh/StencilManager.cpp
+++ b/src/mesh/StencilManager.cpp
@@ -34,14 +34,14 @@ StencilManager::destroy()
 const Stencil&
 StencilManager::getStencil(const IConnectivity& connectivity,
                            size_t degree,
-                           const std::set<std::string>& symmetry_boundary_names)
+                           const BoundaryDescriptorList& symmetry_boundary_descriptor_list)
 {
-  if (not m_stored_stencil_map.contains(Key{connectivity.id(), degree, symmetry_boundary_names})) {
-    m_stored_stencil_map[Key{connectivity.id(), degree, symmetry_boundary_names}] =
-      std::make_shared<Stencil>(StencilBuilder{}.build(connectivity, degree, symmetry_boundary_names));
+  if (not m_stored_stencil_map.contains(Key{connectivity.id(), degree, symmetry_boundary_descriptor_list})) {
+    m_stored_stencil_map[Key{connectivity.id(), degree, symmetry_boundary_descriptor_list}] =
+      std::make_shared<Stencil>(StencilBuilder{}.build(connectivity, degree, symmetry_boundary_descriptor_list));
   }
 
-  return *m_stored_stencil_map.at(Key{connectivity.id(), degree, symmetry_boundary_names});
+  return *m_stored_stencil_map.at(Key{connectivity.id(), degree, symmetry_boundary_descriptor_list});
 }
 
 void
diff --git a/src/mesh/StencilManager.hpp b/src/mesh/StencilManager.hpp
index 8199ce5a324a26879ca2c94c05f8871e9e6d7559..814d8e476d71ada4ec66322e1f3ed80035f808e2 100644
--- a/src/mesh/StencilManager.hpp
+++ b/src/mesh/StencilManager.hpp
@@ -1,15 +1,20 @@
 #ifndef STENCIL_MANAGER_HPP
 #define STENCIL_MANAGER_HPP
 
+#include <mesh/IBoundaryDescriptor.hpp>
 #include <mesh/IConnectivity.hpp>
 #include <mesh/Stencil.hpp>
 
 #include <memory>
 #include <set>
 #include <unordered_map>
+#include <vector>
 
 class StencilManager
 {
+ public:
+  using BoundaryDescriptorList = std::vector<std::shared_ptr<const IBoundaryDescriptor>>;
+
  private:
   StencilManager()  = default;
   ~StencilManager() = default;
@@ -20,26 +25,29 @@ class StencilManager
   {
     size_t connectivity_id;
     size_t degree;
-    std::set<std::string> symmetry_boundary_names;
+    BoundaryDescriptorList symmetry_boundary_descriptor_list;
 
     PUGS_INLINE bool
     operator==(const Key& k) const
     {
       if ((connectivity_id != k.connectivity_id) or (degree != k.degree) or
-          (symmetry_boundary_names.size() != k.symmetry_boundary_names.size())) {
+          (symmetry_boundary_descriptor_list.size() != k.symmetry_boundary_descriptor_list.size())) {
         return false;
       }
 
-      auto i_name   = symmetry_boundary_names.begin();
-      auto i_k_name = k.symmetry_boundary_names.begin();
+      std::set<std::string> boundary_descriptor_set;
+      for (auto&& p_boundary_descriptor : symmetry_boundary_descriptor_list) {
+        const std::string name = stringify(*p_boundary_descriptor);
+        boundary_descriptor_set.insert(name);
+      }
 
-      for (; i_name != symmetry_boundary_names.end(); ++i_name, ++i_k_name) {
-        if (*i_name != *i_k_name) {
-          return false;
-        }
+      std::set<std::string> k_boundary_descriptor_set;
+      for (auto&& p_boundary_descriptor : k.symmetry_boundary_descriptor_list) {
+        const std::string name = stringify(*p_boundary_descriptor);
+        k_boundary_descriptor_set.insert(name);
       }
 
-      return true;
+      return boundary_descriptor_set == k_boundary_descriptor_set;
     }
   };
   struct HashKey
@@ -70,8 +78,8 @@ class StencilManager
   void deleteConnectivity(const size_t connectivity_id);
 
   const Stencil& getStencil(const IConnectivity& i_connectivity,
-                            size_t degree                                        = 1,
-                            const std::set<std::string>& symmetry_boundary_names = {});
+                            size_t degree                                                   = 1,
+                            const BoundaryDescriptorList& symmetry_boundary_descriptor_list = {});
 
   StencilManager(const StencilManager&) = delete;
   StencilManager(StencilManager&&)      = delete;
diff --git a/src/scheme/PolynomialReconstruction.cpp b/src/scheme/PolynomialReconstruction.cpp
index 086583c9f5b5fcca55a9321c00a2f51f13934709..65720b744238abb5023e50de7b4f23babf8bbcce 100644
--- a/src/scheme/PolynomialReconstruction.cpp
+++ b/src/scheme/PolynomialReconstruction.cpp
@@ -758,7 +758,7 @@ PolynomialReconstruction::_build(
     DiscreteFunctionDPk<MeshType::Dimension, double>::BasisViewType::dimensionFromDegree(m_descriptor.degree());
 
   const Stencil& stencil = StencilManager::instance().getStencil(mesh.connectivity(), m_descriptor.degree(),
-                                                                 m_descriptor.symmetryBoundaryNames());
+                                                                 m_descriptor.symmetryBoundaryDescriptorList());
 
   auto xr = mesh.xr();
   auto xj = MeshDataManager::instance().getMeshData(mesh).xj();
@@ -772,8 +772,8 @@ PolynomialReconstruction::_build(
   auto full_stencil_size = [&](const CellId cell_id) {
     auto stencil_cell_list = stencil[cell_id];
     size_t stencil_size    = stencil_cell_list.size();
-    for (size_t i = 0; i < m_descriptor.symmetryBoundaryNames().size(); ++i) {
-      auto& ghost_stencil = stencil.symmetryNameStencil()[i].second;
+    for (size_t i = 0; i < m_descriptor.symmetryBoundaryDescriptorList().size(); ++i) {
+      auto& ghost_stencil = stencil.symmetryBoundaryStencilList()[i].second;
       stencil_size += ghost_stencil[cell_id].size();
     }
 
@@ -793,33 +793,27 @@ PolynomialReconstruction::_build(
   }();
 
   SmallArray<const Rd> symmetry_normal_list = [&] {
-    SmallArray<Rd> normal_list(m_descriptor.symmetryBoundaryNames().size());
+    SmallArray<Rd> normal_list(m_descriptor.symmetryBoundaryDescriptorList().size());
     size_t i_symmetry_boundary = 0;
-    for (auto name : m_descriptor.symmetryBoundaryNames()) {
-      auto symmetry_boundary             = getMeshFlatFaceBoundary(mesh, NamedBoundaryDescriptor(name));
+    for (auto p_boundary_descriptor : m_descriptor.symmetryBoundaryDescriptorList()) {
+      const IBoundaryDescriptor& boundary_descriptor = *p_boundary_descriptor;
+
+      auto symmetry_boundary             = getMeshFlatFaceBoundary(mesh, boundary_descriptor);
       normal_list[i_symmetry_boundary++] = symmetry_boundary.outgoingNormal();
     }
     return normal_list;
   }();
   SmallArray<const Rd> symmetry_origin_list = [&] {
-    SmallArray<Rd> origin_list(m_descriptor.symmetryBoundaryNames().size());
+    SmallArray<Rd> origin_list(m_descriptor.symmetryBoundaryDescriptorList().size());
     size_t i_symmetry_boundary = 0;
-    for (auto name : m_descriptor.symmetryBoundaryNames()) {
-      auto symmetry_boundary             = getMeshFlatFaceBoundary(mesh, NamedBoundaryDescriptor(name));
+    for (auto p_boundary_descriptor : m_descriptor.symmetryBoundaryDescriptorList()) {
+      const IBoundaryDescriptor& boundary_descriptor = *p_boundary_descriptor;
+
+      auto symmetry_boundary             = getMeshFlatFaceBoundary(mesh, boundary_descriptor);
       origin_list[i_symmetry_boundary++] = symmetry_boundary.origin();
     }
     return origin_list;
   }();
-  {
-    size_t i_symmetry_boundary = 0;
-    for (auto name : m_descriptor.symmetryBoundaryNames()) {
-      auto symmetry_boundary = getMeshFlatFaceBoundary(mesh, NamedBoundaryDescriptor(name));
-      std::cout << name << " n=" << symmetry_boundary.outgoingNormal() << " o=" << symmetry_boundary.origin() << '\n';
-      ++i_symmetry_boundary;
-    }
-  }
-  std::cout << "symmetry_origin_list = " << symmetry_origin_list << '\n';
-  std::cout << "symmetry_normal_list = " << symmetry_normal_list << '\n';
 
   Kokkos::Experimental::UniqueToken<Kokkos::DefaultExecutionSpace::execution_space,
                                     Kokkos::Experimental::UniqueTokenScope::Global>
@@ -892,8 +886,8 @@ PolynomialReconstruction::_build(
                   }
                 }
 
-                for (size_t i_symmetry = 0; i_symmetry < stencil.symmetryNameStencil().size(); ++i_symmetry) {
-                  auto& ghost_stencil  = stencil.symmetryNameStencil()[i_symmetry].second;
+                for (size_t i_symmetry = 0; i_symmetry < stencil.symmetryBoundaryStencilList().size(); ++i_symmetry) {
+                  auto& ghost_stencil  = stencil.symmetryBoundaryStencilList()[i_symmetry].second;
                   auto ghost_cell_list = ghost_stencil[cell_j_id];
                   for (size_t i = 0; i < ghost_cell_list.size(); ++i, ++index) {
                     const CellId cell_i_id = ghost_cell_list[i];
@@ -948,8 +942,8 @@ PolynomialReconstruction::_build(
                   }
                 }
 
-                for (size_t i_symmetry = 0; i_symmetry < stencil.symmetryNameStencil().size(); ++i_symmetry) {
-                  auto& ghost_stencil  = stencil.symmetryNameStencil()[i_symmetry].second;
+                for (size_t i_symmetry = 0; i_symmetry < stencil.symmetryBoundaryStencilList().size(); ++i_symmetry) {
+                  auto& ghost_stencil  = stencil.symmetryBoundaryStencilList()[i_symmetry].second;
                   auto ghost_cell_list = ghost_stencil[cell_j_id];
                   for (size_t i = 0; i < ghost_cell_list.size(); ++i, ++index) {
                     const CellId cell_i_id = ghost_cell_list[i];
@@ -983,8 +977,8 @@ PolynomialReconstruction::_build(
               A(index, l) = Xi_Xj[l];
             }
           }
-          for (size_t i_symmetry = 0; i_symmetry < stencil.symmetryNameStencil().size(); ++i_symmetry) {
-            auto& ghost_stencil  = stencil.symmetryNameStencil()[i_symmetry].second;
+          for (size_t i_symmetry = 0; i_symmetry < stencil.symmetryBoundaryStencilList().size(); ++i_symmetry) {
+            auto& ghost_stencil  = stencil.symmetryBoundaryStencilList()[i_symmetry].second;
             auto ghost_cell_list = ghost_stencil[cell_j_id];
 
             const Rd& origin = symmetry_origin_list[i_symmetry];
@@ -1028,8 +1022,8 @@ PolynomialReconstruction::_build(
                   A(index, l) = mean_i_of_ejk[l] - mean_j_of_ejk[l];
                 }
               }
-              for (size_t i_symmetry = 0; i_symmetry < stencil.symmetryNameStencil().size(); ++i_symmetry) {
-                auto& ghost_stencil  = stencil.symmetryNameStencil()[i_symmetry].second;
+              for (size_t i_symmetry = 0; i_symmetry < stencil.symmetryBoundaryStencilList().size(); ++i_symmetry) {
+                auto& ghost_stencil  = stencil.symmetryBoundaryStencilList()[i_symmetry].second;
                 auto ghost_cell_list = ghost_stencil[cell_j_id];
 
                 const Rd& origin = symmetry_origin_list[i_symmetry];
@@ -1073,8 +1067,8 @@ PolynomialReconstruction::_build(
                 A(index, l) = mean_i_of_ejk[l] - mean_j_of_ejk[l];
               }
             }
-            for (size_t i_symmetry = 0; i_symmetry < stencil.symmetryNameStencil().size(); ++i_symmetry) {
-              auto& ghost_stencil  = stencil.symmetryNameStencil()[i_symmetry].second;
+            for (size_t i_symmetry = 0; i_symmetry < stencil.symmetryBoundaryStencilList().size(); ++i_symmetry) {
+              auto& ghost_stencil  = stencil.symmetryBoundaryStencilList()[i_symmetry].second;
               auto ghost_cell_list = ghost_stencil[cell_j_id];
 
               const Rd& origin = symmetry_origin_list[i_symmetry];
diff --git a/src/scheme/PolynomialReconstructionDescriptor.hpp b/src/scheme/PolynomialReconstructionDescriptor.hpp
index 9274a7282ac6347fba0166ea40644db1a75090b0..8a51a85714a0f58749e56cc00e8c31664b2d36f1 100644
--- a/src/scheme/PolynomialReconstructionDescriptor.hpp
+++ b/src/scheme/PolynomialReconstructionDescriptor.hpp
@@ -1,20 +1,24 @@
 #ifndef POLYNOMIAL_RECONSTRUCTION_DESCRIPTOR_HPP
 #define POLYNOMIAL_RECONSTRUCTION_DESCRIPTOR_HPP
 
+#include <mesh/IBoundaryDescriptor.hpp>
 #include <scheme/IntegrationMethodType.hpp>
 #include <utils/PugsMacros.hpp>
 
 #include <cstddef>
-#include <set>
+#include <memory>
+#include <vector>
 
 class PolynomialReconstructionDescriptor
 {
  public:
+  using BoundaryDescriptorList = std::vector<std::shared_ptr<const IBoundaryDescriptor>>;
+
  private:
   IntegrationMethodType m_integration_method;
   size_t m_degree;
 
-  std::set<std::string> m_symmetry_boundary_names;
+  BoundaryDescriptorList m_symmetry_boundary_descriptor_list;
 
   bool m_preconditioning = true;
   bool m_row_weighting   = true;
@@ -34,10 +38,10 @@ class PolynomialReconstructionDescriptor
   }
 
   PUGS_INLINE
-  const std::set<std::string>&
-  symmetryBoundaryNames() const
+  const BoundaryDescriptorList&
+  symmetryBoundaryDescriptorList() const
   {
-    return m_symmetry_boundary_names;
+    return m_symmetry_boundary_descriptor_list;
   }
 
   PUGS_INLINE
@@ -75,11 +79,12 @@ class PolynomialReconstructionDescriptor
     m_row_weighting = row_weighting;
   }
 
-#warning TEMPORARY
   PolynomialReconstructionDescriptor(const IntegrationMethodType integration_method,
                                      const size_t degree,
-                                     const std::set<std::string>& symmetry_boundary_names = {})
-    : m_integration_method{integration_method}, m_degree{degree}, m_symmetry_boundary_names(symmetry_boundary_names)
+                                     const BoundaryDescriptorList& symmetry_boundary_descriptor_list = {})
+    : m_integration_method{integration_method},
+      m_degree{degree},
+      m_symmetry_boundary_descriptor_list(symmetry_boundary_descriptor_list)
   {}
 
   PolynomialReconstructionDescriptor() = delete;
diff --git a/src/scheme/test_reconstruction.cpp b/src/scheme/test_reconstruction.cpp
index a17965ac51af42672fca6b583e50acdc0a995d07..629d1337ebca06a338dd7bf5bdd8417d2316250d 100644
--- a/src/scheme/test_reconstruction.cpp
+++ b/src/scheme/test_reconstruction.cpp
@@ -1,5 +1,6 @@
 #include <scheme/test_reconstruction.hpp>
 
+#include <mesh/NamedBoundaryDescriptor.hpp>
 #include <scheme/IntegrationMethodType.hpp>
 #include <scheme/PolynomialReconstruction.hpp>
 #include <utils/Timer.hpp>
@@ -9,7 +10,12 @@ test_reconstruction(const std::vector<std::shared_ptr<const DiscreteFunctionVari
                     uint64_t degree)
 {
   std::vector descriptor_list = {
-    PolynomialReconstructionDescriptor{IntegrationMethodType::boundary, degree, {"XMIN", "XMAX", "YMIN", "YMAX"}}};
+    PolynomialReconstructionDescriptor{IntegrationMethodType::boundary,
+                                       degree,
+                                       {std::make_shared<NamedBoundaryDescriptor>("XMIN"),
+                                        std::make_shared<NamedBoundaryDescriptor>("XMAX"),
+                                        std::make_shared<NamedBoundaryDescriptor>("YMIN"),
+                                        std::make_shared<NamedBoundaryDescriptor>("YMAX")}}};
 
   for (auto&& descriptor : descriptor_list) {
     const size_t nb_loops = 1;
diff --git a/tests/test_StencilBuilder.cpp b/tests/test_StencilBuilder.cpp
index 32ec498e6bbbc3fa65b73efb31f3af87cedaacb3..0ef8d97ba9ef690ca4420a49905881e5ccbc49b3 100644
--- a/tests/test_StencilBuilder.cpp
+++ b/tests/test_StencilBuilder.cpp
@@ -128,9 +128,9 @@ TEST_CASE("StencilBuilder", "[mesh]")
       for (CellId cell_id = 0; cell_id < connecticity.numberOfCells(); ++cell_id) {
         if (not cell_is_owned[cell_id]) {
           is_empty &= (stencil[cell_id].size() == 0);
-          for (size_t i_symmetry_stencil = 0; i_symmetry_stencil < stencil.symmetryNameStencil().size();
+          for (size_t i_symmetry_stencil = 0; i_symmetry_stencil < stencil.symmetryBoundaryStencilList().size();
                ++i_symmetry_stencil) {
-            is_empty &= (stencil.symmetryNameStencil()[i_symmetry_stencil].second[cell_id].size() == 0);
+            is_empty &= (stencil.symmetryBoundaryStencilList()[i_symmetry_stencil].second[cell_id].size() == 0);
           }
         }
       }
@@ -146,11 +146,13 @@ TEST_CASE("StencilBuilder", "[mesh]")
       auto cell_is_owned       = mesh.connectivity().cellIsOwned();
       auto cell_number         = mesh.connectivity().cellNumber();
 
-      for (size_t i_symmetry_stencil = 0; i_symmetry_stencil < stencil.symmetryNameStencil().size();
+      for (size_t i_symmetry_stencil = 0; i_symmetry_stencil < stencil.symmetryBoundaryStencilList().size();
            ++i_symmetry_stencil) {
-        auto boundary_name      = stencil.symmetryNameStencil()[i_symmetry_stencil].first;
-        auto boundary_stencil   = stencil.symmetryNameStencil()[i_symmetry_stencil].second;
-        auto boundary_node_list = getMeshFlatNodeBoundary(mesh, NamedBoundaryDescriptor(boundary_name));
+        auto p_boundary_descriptor = stencil.symmetryBoundaryStencilList()[i_symmetry_stencil].first;
+        const IBoundaryDescriptor& boundary_descriptor = *p_boundary_descriptor;
+
+        auto boundary_stencil   = stencil.symmetryBoundaryStencilList()[i_symmetry_stencil].second;
+        auto boundary_node_list = getMeshFlatNodeBoundary(mesh, boundary_descriptor);
 
         CellValue<bool> boundary_cell{mesh.connectivity()};
         boundary_cell.fill(false);
@@ -205,14 +207,21 @@ TEST_CASE("StencilBuilder", "[mesh]")
 
     SECTION("2D")
     {
+      StencilManager::BoundaryDescriptorList list;
+      list.emplace_back(std::make_shared<NamedBoundaryDescriptor>("XMIN"));
+      list.emplace_back(std::make_shared<NamedBoundaryDescriptor>("XMAX"));
+      list.emplace_back(std::make_shared<NamedBoundaryDescriptor>("YMIN"));
+      list.emplace_back(std::make_shared<NamedBoundaryDescriptor>("YMAX"));
+
       SECTION("cartesian")
       {
         const auto& mesh = *MeshDataBaseForTests::get().cartesian2DMesh()->get<Mesh<2>>();
 
         const Connectivity<2>& connectivity = mesh.connectivity();
-        auto stencil = StencilManager::instance().getStencil(connectivity, 1, {"XMIN", "XMAX", "YMIN", "YMAX"});
 
-        REQUIRE(stencil.symmetryNameStencil().size() == 4);
+        auto stencil = StencilManager::instance().getStencil(connectivity, 1, list);
+
+        REQUIRE(stencil.symmetryBoundaryStencilList().size() == 4);
         REQUIRE(check_ghost_cells_have_empty_stencils(stencil, connectivity));
         REQUIRE(symmetry_stencils_are_valid(stencil, mesh));
       }
@@ -222,9 +231,9 @@ TEST_CASE("StencilBuilder", "[mesh]")
         const auto& mesh = *MeshDataBaseForTests::get().hybrid2DMesh()->get<Mesh<2>>();
 
         const Connectivity<2>& connectivity = mesh.connectivity();
-        auto stencil = StencilManager::instance().getStencil(connectivity, 1, {"XMIN", "XMAX", "YMIN", "YMAX"});
+        auto stencil                        = StencilManager::instance().getStencil(connectivity, 1, list);
 
-        REQUIRE(stencil.symmetryNameStencil().size() == 4);
+        REQUIRE(stencil.symmetryBoundaryStencilList().size() == 4);
         REQUIRE(check_ghost_cells_have_empty_stencils(stencil, connectivity));
         REQUIRE(symmetry_stencils_are_valid(stencil, mesh));
       }
@@ -232,15 +241,22 @@ TEST_CASE("StencilBuilder", "[mesh]")
 
     SECTION("3D")
     {
+      StencilManager::BoundaryDescriptorList list;
+      list.emplace_back(std::make_shared<NamedBoundaryDescriptor>("XMIN"));
+      list.emplace_back(std::make_shared<NamedBoundaryDescriptor>("XMAX"));
+      list.emplace_back(std::make_shared<NamedBoundaryDescriptor>("YMIN"));
+      list.emplace_back(std::make_shared<NamedBoundaryDescriptor>("YMAX"));
+      list.emplace_back(std::make_shared<NamedBoundaryDescriptor>("ZMIN"));
+      list.emplace_back(std::make_shared<NamedBoundaryDescriptor>("ZMAX"));
+
       SECTION("cartesian")
       {
         const auto& mesh = *MeshDataBaseForTests::get().cartesian3DMesh()->get<Mesh<3>>();
 
         const Connectivity<3>& connectivity = mesh.connectivity();
-        auto stencil =
-          StencilManager::instance().getStencil(connectivity, 1, {"XMIN", "XMAX", "YMIN", "YMAX", "ZMIN", "ZMAX"});
+        auto stencil                        = StencilManager::instance().getStencil(connectivity, 1, list);
 
-        REQUIRE(stencil.symmetryNameStencil().size() == 6);
+        REQUIRE(stencil.symmetryBoundaryStencilList().size() == 6);
         REQUIRE(check_ghost_cells_have_empty_stencils(stencil, connectivity));
         REQUIRE(symmetry_stencils_are_valid(stencil, mesh));
       }
@@ -250,10 +266,9 @@ TEST_CASE("StencilBuilder", "[mesh]")
         const auto& mesh = *MeshDataBaseForTests::get().hybrid3DMesh()->get<Mesh<3>>();
 
         const Connectivity<3>& connectivity = mesh.connectivity();
-        auto stencil =
-          StencilManager::instance().getStencil(connectivity, 1, {"XMIN", "XMAX", "YMIN", "YMAX", "ZMIN", "ZMAX"});
+        auto stencil                        = StencilManager::instance().getStencil(connectivity, 1, list);
 
-        REQUIRE(stencil.symmetryNameStencil().size() == 6);
+        REQUIRE(stencil.symmetryBoundaryStencilList().size() == 6);
         REQUIRE(check_ghost_cells_have_empty_stencils(stencil, connectivity));
         REQUIRE(symmetry_stencils_are_valid(stencil, mesh));
       }