diff --git a/src/mesh/GmshReader.cpp b/src/mesh/GmshReader.cpp
index 84aae75e82367f4e1efed5aae5b219216b63285d..a636f61898530080cd25bc9d5ac7701ef0d6c977 100644
--- a/src/mesh/GmshReader.cpp
+++ b/src/mesh/GmshReader.cpp
@@ -141,6 +141,96 @@ ErrorHandler(const std::string& filename,
   ;
 }
 
+template <int Dimension>
+class MeshDispatcher
+{
+ public:
+  using MeshType = Mesh<Connectivity<Dimension>>;
+
+ private:
+  const MeshType& m_mesh;
+  using CellListToSendByProc = std::vector<Array<const CellId>>;
+  const CellListToSendByProc m_cell_list_to_send_by_proc;
+
+  Array<int> m_nb_cell_to_send_by_proc;
+  Array<int> m_nb_cell_to_recv_by_proc;
+
+  const CellListToSendByProc
+  _buildCellListToSend() const
+  {
+    CSRGraph mesh_graph = m_mesh.cellToCellGraph();
+
+    Partitioner P;
+    Array<int> cell_new_owner = P.partition(mesh_graph);
+
+    std::vector<std::vector<CellId>> cell_vector_to_send_by_proc(commSize());
+    for (size_t i=0; i<cell_new_owner.size(); ++i) {
+      cell_vector_to_send_by_proc[cell_new_owner[i]].push_back(CellId{i});
+    }
+
+    std::vector<Array<const CellId>> cell_list_to_send_by_proc(commSize());
+    for (size_t i=0; i<commSize(); ++i) {
+      cell_list_to_send_by_proc[i] = convert_to_array(cell_vector_to_send_by_proc[i]);
+    }
+
+    return std::move(cell_list_to_send_by_proc);
+  }
+
+  Array<int> _buildNbCellToSend()
+  {
+    Array<int> nb_cell_to_send_by_proc(commSize());
+    for (size_t i=0; i<commSize(); ++i) {
+      nb_cell_to_send_by_proc[i] = m_cell_list_to_send_by_proc[i].size();
+    }
+    return nb_cell_to_send_by_proc;
+  }
+
+ public:
+
+  template<typename DataType>
+  std::vector<Array<std::remove_const_t<DataType>>>
+  exchange(const CellValue<DataType>& cell_value) const
+  {
+    using MutableDataType = std::remove_const_t<DataType>;
+    std::vector<Array<DataType>> cell_value_to_send_by_proc(commSize());
+    for (size_t i=0; i<commSize(); ++i) {
+      const Array<const CellId>& cell_list = m_cell_list_to_send_by_proc[i];
+      Array<MutableDataType> cell_value_list(cell_list.size());
+      parallel_for (cell_list.size(), PASTIS_LAMBDA(const CellId& cell_id) {
+          cell_value_list[cell_id] = cell_value[cell_list[cell_id]];
+        });
+      cell_value_to_send_by_proc[i] = cell_value_list;
+    }
+
+    std::vector<Array<MutableDataType>> recv_cell_value_by_proc(commSize());
+    for (size_t i=0; i<commSize(); ++i) {
+      recv_cell_value_by_proc[i] = Array<MutableDataType>(m_nb_cell_to_recv_by_proc[i]);
+    }
+
+    ::exchange(cell_value_to_send_by_proc, recv_cell_value_by_proc);
+    return std::move(recv_cell_value_by_proc);
+  }
+
+  [[deprecated]]
+  const CellListToSendByProc& cell_list_to_send_by_proc() const
+  {
+    return m_cell_list_to_send_by_proc;
+  }
+
+  MeshDispatcher(const MeshType& mesh)
+      : m_mesh(mesh),
+        m_cell_list_to_send_by_proc(_buildCellListToSend()),
+        m_nb_cell_to_send_by_proc(_buildNbCellToSend()),
+        m_nb_cell_to_recv_by_proc(allToAll(m_nb_cell_to_send_by_proc))
+  {
+    ;
+  }
+
+  MeshDispatcher(const MeshDispatcher&) = delete;
+  ~MeshDispatcher() = default;
+};
+
+
 
 template <int Dimension>
 void GmshReader::_dispatch()
@@ -154,77 +244,48 @@ void GmshReader::_dispatch()
     NodeValue<Rd> xr;
     m_mesh = std::shared_ptr<IMesh>(new MeshType(connectivity, xr));
   }
-
   const MeshType& mesh = static_cast<const MeshType&>(*m_mesh);
 
-  CSRGraph mesh_graph = mesh.cellToCellGraph();
+  MeshDispatcher<Dimension> dispatcher(mesh);
 
-  const int reader_rank
-      = [&]() {
-          Array<int> parts = allGather(static_cast<int>(mesh.numberOfCells()));
-          std::set<int> part_set;
-          for (size_t i=0; i<parts.size(); ++i) {
-            if (parts[i] != 0) { part_set.insert(i); }
-          }
-          if (part_set.size() != 1) {
-            perr() << "mesh should be read by one processor\n";
-          }
-          return *begin(part_set);
-        } ();
-
-  pout() << "Mesh read by process " << rang::style::bold << reader_rank << rang::style::reset << '\n';
+  std::vector<Array<int>> recv_cell_number_by_proc
+      = dispatcher.exchange(mesh.connectivity().cellNumber());
 
-  Partitioner P;
-  Array<int> cell_new_owner = P.partition(mesh_graph);
+  std::vector<Array<CellType>> recv_cell_type_by_proc
+      = dispatcher.exchange(mesh.connectivity().cellType());
 
-  const std::vector<Array<const CellId>> cell_to_send_by_proc
-      = [&] () {
-          std::vector<std::vector<CellId>> cell_vector_to_send_by_proc(commSize());
-          for (size_t i=0; i<cell_new_owner.size(); ++i) {
-            cell_vector_to_send_by_proc[cell_new_owner[i]].push_back(CellId{i});
-          }
+  // const std::vector<Array<const CellId>>& cell_to_send_by_proc
+  //     = dispatcher.cell_list_to_send_by_proc();
 
-          std::vector<Array<const CellId>> cell_to_send_by_proc(commSize());
-          for (size_t i=0; i<commSize(); ++i) {
-            cell_to_send_by_proc[i] = convert_to_array(cell_vector_to_send_by_proc[i]);
-          }
+  // Array<int> nb_cell_to_send_by_proc(commSize());
+  // for (size_t i=0; i<commSize(); ++i) {
+  //   nb_cell_to_send_by_proc[i] = cell_to_send_by_proc[i].size();
+  // }
 
-          return std::move(cell_to_send_by_proc);
-        } ();
-
-  const auto& cell_number = mesh.connectivity().cellNumber();
-  const std::vector<Array<const int>> cell_number_to_send_by_proc
-      = [&] () {
-          std::vector<Array<const int>> cell_number_to_send_by_proc(commSize());
-          for (size_t i=0; i<commSize(); ++i) {
-            const Array<const CellId>& cell_list = cell_to_send_by_proc[i];
-            Array<int> cell_number_list(cell_list.size());
-            parallel_for (cell_list.size(), PASTIS_LAMBDA(const CellId& cell_id) {
-                cell_number_list[cell_id] = cell_number[cell_list[cell_id]];
-              });
-            cell_number_to_send_by_proc[i] = cell_number_list;
-          }
-          return std::move(cell_number_to_send_by_proc);
-        } ();
-
-  Array<int> nb_cell_to_send_by_proc(commSize());
-  for (size_t i=0; i<commSize(); ++i) {
-    nb_cell_to_send_by_proc[i] = cell_to_send_by_proc[i].size();
-  }
+  // Array<int> nb_cell_to_recv_by_proc = allToAll(nb_cell_to_send_by_proc);
 
-  Array<int> nb_cell_to_recv_by_proc = allToAll(nb_cell_to_send_by_proc);
 
-  const size_t new_cell_number
-      = mesh.numberOfCells()
-      + Sum(nb_cell_to_recv_by_proc)
-      - Sum(nb_cell_to_send_by_proc);
+  // const auto& cell_number = mesh.connectivity().cellNumber();
+  // const std::vector<Array<const int>> cell_number_to_send_by_proc
+  //     = [&] () {
+  //         std::vector<Array<const int>> cell_number_to_send_by_proc(commSize());
+  //         for (size_t i=0; i<commSize(); ++i) {
+  //           const Array<const CellId>& cell_list = cell_to_send_by_proc[i];
+  //           Array<int> cell_number_list(cell_list.size());
+  //           parallel_for (cell_list.size(), PASTIS_LAMBDA(const CellId& cell_id) {
+  //               cell_number_list[cell_id] = cell_number[cell_list[cell_id]];
+  //             });
+  //           cell_number_to_send_by_proc[i] = cell_number_list;
+  //         }
+  //         return std::move(cell_number_to_send_by_proc);
+  //       } ();
 
-  std::vector<Array<int>> recv_cell_number_by_proc(commSize());
-  for (size_t i=0; i<commSize(); ++i) {
-    recv_cell_number_by_proc[i] = Array<int>(nb_cell_to_recv_by_proc[i]);
-  }
+  // std::vector<Array<int>> recv_cell_number_by_proc(commSize());
+  // for (size_t i=0; i<commSize(); ++i) {
+  //   recv_cell_number_by_proc[i] = Array<int>(nb_cell_to_recv_by_proc[i]);
+  // }
 
-  exchange(cell_number_to_send_by_proc, recv_cell_number_by_proc);
+  // exchange(cell_number_to_send_by_proc, recv_cell_number_by_proc);
 
   // std::vector<Array<CellType>> cell_type_to_send_by_proc
   //     = [&] () {
@@ -250,6 +311,12 @@ void GmshReader::_dispatch()
     //    barrier();
   }
 
+  // const size_t new_cell_number
+  //     = mesh.numberOfCells()
+  //     + Sum(nb_cell_to_recv_by_proc)
+  //     - Sum(nb_cell_to_send_by_proc);
+
+
   Messenger::destroy();
   std::exit(0);
 }