diff --git a/src/mesh/ConnectivityDispatcher.cpp b/src/mesh/ConnectivityDispatcher.cpp
index 69d97399d5b0bb5533758f94593f2703ce8bfcb9..f1744112301e55d1a183cad5aaea4804c79b0348 100644
--- a/src/mesh/ConnectivityDispatcher.cpp
+++ b/src/mesh/ConnectivityDispatcher.cpp
@@ -150,6 +150,61 @@ _gatherFrom(const ItemValue<DataType, item_type, ConnectivityPtr>& data_to_gathe
   }
 }
 
+template <int Dimension>
+template<typename DataType, typename ItemOfItem, typename ConnectivityPtr>
+void ConnectivityDispatcher<Dimension>::
+_gatherFrom(const SubItemValuePerItem<DataType, ItemOfItem, ConnectivityPtr>& data_to_gather,
+            std::vector<std::vector<std::remove_const_t<DataType>>>& gathered_vector)
+{
+  using MutableDataType = std::remove_const_t<DataType>;
+
+  constexpr ItemType item_type = ItemOfItem::item_type;
+  using ItemId = ItemIdT<item_type>;
+
+  std::vector<Array<MutableDataType>> data_to_send_by_proc(parallel::size());
+  {
+    const auto& item_list_to_send_by_proc = this->_dispatchedInfo<item_type>().m_list_to_send_by_proc;
+
+    for (size_t i_rank=0; i_rank < parallel::size(); ++i_rank) {
+      std::vector<MutableDataType> data_by_item_vector;
+      for (size_t j=0; j<item_list_to_send_by_proc[i_rank].size(); ++j) {
+        const ItemId& item_id = item_list_to_send_by_proc[i_rank][j];
+        const auto& item_data = data_to_gather.itemValues(item_id);
+        for (size_t l=0; l<item_data.size(); ++l) {
+          data_by_item_vector.push_back(item_data[l]);
+        }
+      }
+      data_to_send_by_proc[i_rank] = convert_to_array(data_by_item_vector);
+    }
+  }
+
+  const auto& number_of_item_per_item_by_proc =
+      this->_dispatchedInfo<ItemOfItem>().m_recv_number_of_item_per_item_by_proc;
+
+  std::vector<Array<MutableDataType>> recv_data_to_gather_by_proc(parallel::size());
+  for (size_t i_rank=0; i_rank < parallel::size(); ++i_rank) {
+    recv_data_to_gather_by_proc[i_rank]
+        = Array<MutableDataType>(sum(number_of_item_per_item_by_proc[i_rank]));
+  }
+
+  parallel::exchange(data_to_send_by_proc, recv_data_to_gather_by_proc);
+
+  const auto& item_list_to_recv_size_by_proc =
+      this->_dispatchedInfo<item_type>().m_list_to_recv_size_by_proc;
+
+  for (size_t i_rank=0; i_rank < parallel::size(); ++i_rank) {
+    int l=0;
+    for (size_t i=0; i<item_list_to_recv_size_by_proc[i_rank]; ++i) {
+      std::vector<MutableDataType> data_vector;
+      for (int k=0; k<number_of_item_per_item_by_proc[i_rank][i]; ++k) {
+        data_vector.push_back(recv_data_to_gather_by_proc[i_rank][l++]);
+      }
+      gathered_vector.emplace_back(data_vector);
+    }
+  }
+}
+
+
 template <int Dimension>
 void
 ConnectivityDispatcher<Dimension>::
@@ -304,9 +359,12 @@ void
 ConnectivityDispatcher<Dimension>::_dispatchFaces()
 {
   if constexpr (Dimension>1) {
-    std::vector<Array<const int>> recv_number_of_face_per_cell_by_proc =
+    this->_dispatchedInfo<FaceOfCell>().m_recv_number_of_item_per_item_by_proc =
         _getRecvNumberOfSubItemPerItemByProc<FaceOfCell>();
 
+    const auto& recv_number_of_face_per_cell_by_proc =
+        this->_dispatchedInfo<FaceOfCell>().m_recv_number_of_item_per_item_by_proc;
+
     std::vector<Array<const int>> recv_cell_face_numbering_by_proc
       = this->_getRecvItemSubItemNumberingByProc<FaceOfCell>(recv_number_of_face_per_cell_by_proc);
 
@@ -346,47 +404,7 @@ ConnectivityDispatcher<Dimension>::_dispatchFaces()
       }
     }
 
-    {
-      std::vector<Array<bool>> cell_face_is_reversed_to_send_by_proc(parallel::size());
-      {
-        const auto& cell_list_to_send_by_proc = this->_dispatchedInfo<ItemType::cell>().m_list_to_send_by_proc;
-
-        const auto& cell_face_is_reversed = m_connectivity.cellFaceIsReversed();
-        for (size_t i_rank=0; i_rank < parallel::size(); ++i_rank) {
-          std::vector<bool> face_is_reversed_by_cell_vector;
-          for (size_t j=0; j<cell_list_to_send_by_proc[i_rank].size(); ++j) {
-            const CellId& cell_id = cell_list_to_send_by_proc[i_rank][j];
-            const auto& face_is_reversed = cell_face_is_reversed.itemValues(cell_id);
-            for (size_t L=0; L<face_is_reversed.size(); ++L) {
-              face_is_reversed_by_cell_vector.push_back(face_is_reversed[L]);
-            }
-          }
-          cell_face_is_reversed_to_send_by_proc[i_rank] = convert_to_array(face_is_reversed_by_cell_vector);
-        }
-      }
-
-      std::vector<Array<bool>> recv_cell_face_is_reversed_by_proc(parallel::size());
-      for (size_t i_rank=0; i_rank < parallel::size(); ++i_rank) {
-        recv_cell_face_is_reversed_by_proc[i_rank]
-            = Array<bool>(sum(recv_number_of_face_per_cell_by_proc[i_rank]));
-      }
-
-      parallel::exchange(cell_face_is_reversed_to_send_by_proc, recv_cell_face_is_reversed_by_proc);
-
-      const auto& cell_list_to_recv_size_by_proc =
-          this->_dispatchedInfo<ItemType::cell>().m_list_to_recv_size_by_proc;
-
-      for (size_t i_rank=0; i_rank < parallel::size(); ++i_rank) {
-        int l=0;
-        for (size_t i=0; i<cell_list_to_recv_size_by_proc[i_rank]; ++i) {
-          std::vector<bool> face_is_reversed_vector;
-          for (int k=0; k<recv_number_of_face_per_cell_by_proc[i_rank][i]; ++k) {
-            face_is_reversed_vector.push_back(recv_cell_face_is_reversed_by_proc[i_rank][l++]);
-          }
-          m_new_descriptor.cell_face_is_reversed_vector.emplace_back(face_is_reversed_vector);
-        }
-      }
-    }
+    this->_gatherFrom(m_connectivity.cellFaceIsReversed(), m_new_descriptor.cell_face_is_reversed_vector);
 
     this->_gatherFrom(this->_dispatchedInfo<ItemType::face>().m_new_owner, m_new_descriptor.face_owner_vector);
 
diff --git a/src/mesh/ConnectivityDispatcher.hpp b/src/mesh/ConnectivityDispatcher.hpp
index 947821f08c4f7c070d3919651567bb0c60210047..e8d3a159781d2a1667f5bbeb55a17de816995e33 100644
--- a/src/mesh/ConnectivityDispatcher.hpp
+++ b/src/mesh/ConnectivityDispatcher.hpp
@@ -65,6 +65,96 @@ class ConnectivityDispatcher
     }
   }
 
+  template <typename ItemToItem>
+  struct DispatchedItemOfItemInfo
+  {
+    std::vector<Array<const int>> m_recv_number_of_item_per_item_by_proc;
+  };
+
+  DispatchedItemOfItemInfo<NodeOfCell> m_dispatched_node_of_cell_info;
+  DispatchedItemOfItemInfo<EdgeOfCell> m_dispatched_edge_of_cell_info;
+  DispatchedItemOfItemInfo<FaceOfCell> m_dispatched_face_of_cell_info;
+
+  DispatchedItemOfItemInfo<NodeOfEdge> m_dispatched_node_of_edge_info;
+  DispatchedItemOfItemInfo<FaceOfEdge> m_dispatched_face_of_edge_info;
+  DispatchedItemOfItemInfo<CellOfEdge> m_dispatched_cell_of_edge_info;
+
+  DispatchedItemOfItemInfo<NodeOfFace> m_dispatched_node_of_face_info;
+  DispatchedItemOfItemInfo<EdgeOfFace> m_dispatched_edge_of_face_info;
+  DispatchedItemOfItemInfo<CellOfFace> m_dispatched_cell_of_face_info;
+
+  DispatchedItemOfItemInfo<EdgeOfNode> m_dispatched_edge_of_node_info;
+  DispatchedItemOfItemInfo<FaceOfNode> m_dispatched_face_of_node_info;
+  DispatchedItemOfItemInfo<CellOfNode> m_dispatched_cell_of_node_info;
+
+  template <typename ItemOfItem>
+  PASTIS_INLINE
+  DispatchedItemOfItemInfo<ItemOfItem>& _dispatchedInfo()
+  {
+    if constexpr (std::is_same_v<NodeOfCell, ItemOfItem>) {
+      return m_dispatched_node_of_cell_info;
+    } else if constexpr (std::is_same_v<EdgeOfCell, ItemOfItem>) {
+      return m_dispatched_edge_of_cell_info;
+    } else if constexpr (std::is_same_v<FaceOfCell, ItemOfItem>) {
+      return m_dispatched_face_of_cell_info;
+    } else if constexpr (std::is_same_v<NodeOfEdge, ItemOfItem>) {
+      return m_dispatched_node_of_edge_info;
+    } else if constexpr (std::is_same_v<FaceOfEdge, ItemOfItem>) {
+      return m_dispatched_face_of_edge_info;
+    } else if constexpr (std::is_same_v<CellOfEdge, ItemOfItem>) {
+      return m_dispatched_cell_of_edge_info;
+    } else if constexpr (std::is_same_v<NodeOfFace, ItemOfItem>) {
+      return m_dispatched_node_of_face_info;
+    } else if constexpr (std::is_same_v<EdgeOfFace, ItemOfItem>) {
+      return m_dispatched_edge_of_face_info;
+    } else if constexpr (std::is_same_v<CellOfFace, ItemOfItem>) {
+      return m_dispatched_cell_of_face_info;
+    } else if constexpr (std::is_same_v<EdgeOfNode, ItemOfItem>) {
+      return m_dispatched_edge_of_node_info;
+    } else if constexpr (std::is_same_v<FaceOfNode, ItemOfItem>) {
+      return m_dispatched_face_of_node_info;
+    } else if constexpr (std::is_same_v<CellOfNode, ItemOfItem>) {
+      return m_dispatched_cell_of_node_info;
+    } else {
+      static_assert(std::is_same_v<NodeOfCell, ItemOfItem>,
+                    "Unexpected ItemOfItem type");
+    }
+  }
+
+  template <typename ItemOfItem>
+  PASTIS_INLINE
+  const DispatchedItemOfItemInfo<ItemOfItem>& _dispatchedInfo() const
+  {
+    if constexpr (std::is_same_v<NodeOfCell, ItemOfItem>) {
+      return m_dispatched_node_of_cell_info;
+    } else if constexpr (std::is_same_v<EdgeOfCell, ItemOfItem>) {
+      return m_dispatched_edge_of_cell_info;
+    } else if constexpr (std::is_same_v<FaceOfCell, ItemOfItem>) {
+      return m_dispatched_face_of_cell_info;
+    } else if constexpr (std::is_same_v<NodeOfEdge, ItemOfItem>) {
+      return m_dispatched_node_of_edge_info;
+    } else if constexpr (std::is_same_v<FaceOfEdge, ItemOfItem>) {
+      return m_dispatched_face_of_edge_info;
+    } else if constexpr (std::is_same_v<CellOfEdge, ItemOfItem>) {
+      return m_dispatched_cell_of_edge_info;
+    } else if constexpr (std::is_same_v<NodeOfFace, ItemOfItem>) {
+      return m_dispatched_node_of_face_info;
+    } else if constexpr (std::is_same_v<EdgeOfFace, ItemOfItem>) {
+      return m_dispatched_edge_of_face_info;
+    } else if constexpr (std::is_same_v<CellOfFace, ItemOfItem>) {
+      return m_dispatched_cell_of_face_info;
+    } else if constexpr (std::is_same_v<EdgeOfNode, ItemOfItem>) {
+      return m_dispatched_edge_of_node_info;
+    } else if constexpr (std::is_same_v<FaceOfNode, ItemOfItem>) {
+      return m_dispatched_face_of_node_info;
+    } else if constexpr (std::is_same_v<CellOfNode, ItemOfItem>) {
+      return m_dispatched_cell_of_node_info;
+    } else {
+      static_assert(std::is_same_v<NodeOfCell, ItemOfItem>,
+                    "Unexpected ItemOfItem type");
+    }
+  }
+
   template <ItemType item_type>
   void _buildNewOwner();
 
@@ -84,6 +174,10 @@ class ConnectivityDispatcher
   void _gatherFrom(const ItemValue<DataType, item_type, ConnectivityPtr>& data_to_gather,
                    std::vector<std::remove_const_t<DataType>>& gathered_vector);
 
+  template<typename DataType, typename ItemOfItem, typename ConnectivityPtr>
+  void _gatherFrom(const SubItemValuePerItem<DataType, ItemOfItem, ConnectivityPtr>& data_to_gather,
+                   std::vector<std::vector<std::remove_const_t<DataType>>>& gathered_vector);
+
   template <typename SubItemOfItemT>
   std::vector<Array<const int>>
   _getRecvNumberOfSubItemPerItemByProc();
diff --git a/src/mesh/SubItemValuePerItem.hpp b/src/mesh/SubItemValuePerItem.hpp
index 821acbd2b8df2a213b78af085d5115e26827a7f8..450554edfc2fc0d3729f9300bb0d5dc516f91f72 100644
--- a/src/mesh/SubItemValuePerItem.hpp
+++ b/src/mesh/SubItemValuePerItem.hpp
@@ -17,20 +17,10 @@
 
 #include <memory>
 
-// template <typename DataType,
-//           typename ItemOfItem,
-//           typename ConnectivityPtr = std::shared_ptr<const IConnectivity>,
-//           typename Allowed=void>
-// class SubItemValuePerItem;
-
 template <typename DataType,
           typename ItemOfItem,
           typename ConnectivityPtr = std::shared_ptr<const IConnectivity>>
-class SubItemValuePerItem// <DataType,
-                         //  ItemOfItem,
-                         //  ConnectivityPtr// ,
-                         //  // std::enable_if_t<sub_item_type != item_type>
-                         //  >
+class SubItemValuePerItem
 {
  public:
   static constexpr ItemType item_type{ItemOfItem::item_type};