diff --git a/src/main.cpp b/src/main.cpp
index a0ab842a3ca1b0961ce64fddfeb1fb04d68cf714..e351d6471a50bb133286a1b53bbd9bc7ee12f1dc 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -122,7 +122,9 @@ int main(int argc, char *argv[])
           while((t<tmax) and (iteration<itermax)) {
             vtk_writer.write(mesh, {NamedItemValue{"density", rhoj},
                                     NamedItemValue{"velocity", unknowns.uj()},
-                                    NamedItemValue{"coords", mesh.xr()}}, t);
+                                    NamedItemValue{"coords", mesh.xr()},
+                                    NamedItemValue{"cell_owner", mesh.connectivity().cellOwner()},
+                                    NamedItemValue{"node_owner", mesh.connectivity().nodeOwner()}},t);
             double dt = 0.4*acoustic_solver.acoustic_dt(Vj, cj);
             if (t+dt>tmax) {
               dt=tmax-t;
@@ -136,7 +138,9 @@ int main(int argc, char *argv[])
           }
           vtk_writer.write(mesh, {NamedItemValue{"density", rhoj},
                                   NamedItemValue{"velocity", unknowns.uj()},
-                                  NamedItemValue{"coords", mesh.xr()}}, t, true); // forces last output
+                                  NamedItemValue{"coords", mesh.xr()},
+                                  NamedItemValue{"cell_owner", mesh.connectivity().cellOwner()},
+                                  NamedItemValue{"node_owner", mesh.connectivity().nodeOwner()}}, t, true); // forces last output
 
           pout() << "* " << rang::style::underline << "Final time" << rang::style::reset
                     << ":  " << rang::fgB::green << t << rang::fg::reset << " (" << iteration << " iterations)\n";
@@ -233,7 +237,9 @@ int main(int argc, char *argv[])
           while((t<tmax) and (iteration<itermax)) {
             vtk_writer.write(mesh, {NamedItemValue{"density", rhoj},
                                     NamedItemValue{"velocity", unknowns.uj()},
-                                    NamedItemValue{"coords", mesh.xr()}}, t);
+                                    NamedItemValue{"coords", mesh.xr()},
+                                    NamedItemValue{"cell_owner", mesh.connectivity().cellOwner()},
+                                    NamedItemValue{"node_owner", mesh.connectivity().nodeOwner()}}, t);
             double dt = 0.4*acoustic_solver.acoustic_dt(Vj, cj);
             if (t+dt>tmax) {
               dt=tmax-t;
@@ -247,7 +253,9 @@ int main(int argc, char *argv[])
           }
           vtk_writer.write(mesh, {NamedItemValue{"density", rhoj},
                                   NamedItemValue{"velocity", unknowns.uj()},
-                                  NamedItemValue{"coords", mesh.xr()}}, t, true); // forces last output
+                                  NamedItemValue{"coords", mesh.xr()},
+                                  NamedItemValue{"cell_owner", mesh.connectivity().cellOwner()},
+                                  NamedItemValue{"node_owner", mesh.connectivity().nodeOwner()}}, t, true); // forces last output
 
           pout() << "* " << rang::style::underline << "Final time" << rang::style::reset
                     << ":  " << rang::fgB::green << t << rang::fg::reset << " (" << iteration << " iterations)\n";
@@ -333,7 +341,9 @@ int main(int argc, char *argv[])
           while((t<tmax) and (iteration<itermax)) {
             vtk_writer.write(mesh, {NamedItemValue{"density", rhoj},
                                     NamedItemValue{"velocity", unknowns.uj()},
-                                    NamedItemValue{"coords", mesh.xr()}}, t);
+                                    NamedItemValue{"coords", mesh.xr()},
+                                    NamedItemValue{"cell_owner", mesh.connectivity().cellOwner()},
+                                    NamedItemValue{"node_owner", mesh.connectivity().nodeOwner()}}, t);
             double dt = 0.4*acoustic_solver.acoustic_dt(Vj, cj);
             if (t+dt>tmax) {
               dt=tmax-t;
@@ -346,7 +356,9 @@ int main(int argc, char *argv[])
           }
           vtk_writer.write(mesh, {NamedItemValue{"density", rhoj},
                                   NamedItemValue{"velocity", unknowns.uj()},
-                                  NamedItemValue{"coords", mesh.xr()}}, t, true); // forces last output
+                                  NamedItemValue{"coords", mesh.xr()},
+                                  NamedItemValue{"cell_owner", mesh.connectivity().cellOwner()},
+                                  NamedItemValue{"node_owner", mesh.connectivity().nodeOwner()}}, t, true); // forces last output
 
           pout() << "* " << rang::style::underline << "Final time" << rang::style::reset
                     << ":  " << rang::fgB::green << t << rang::fg::reset << " (" << iteration << " iterations)\n";
diff --git a/src/mesh/Connectivity.cpp b/src/mesh/Connectivity.cpp
index bc8e7093aabf110b3bcebab71fddd5f2585883e5..07701bbb950f6d1cf6ecccff9982b54a86146b67 100644
--- a/src/mesh/Connectivity.cpp
+++ b/src/mesh/Connectivity.cpp
@@ -218,7 +218,9 @@ Connectivity<Dimension>::
 Connectivity(const std::vector<std::vector<unsigned int>>& cell_by_node_vector,
              const std::vector<CellType>& cell_type_vector,
              const std::vector<int>& cell_number_vector,
-             const std::vector<int>& node_number_vector)
+             const std::vector<int>& node_number_vector,
+             const std::vector<int>& cell_owner_vector,
+             const std::vector<int>& node_owner_vector)
 {
   Assert(cell_by_node_vector.size() == cell_type_vector.size());
   Assert(cell_number_vector.size() == cell_type_vector.size());
@@ -268,6 +270,18 @@ Connectivity(const std::vector<std::vector<unsigned int>>& cell_by_node_vector,
     m_inv_cell_nb_nodes = inv_cell_nb_nodes;
   }
 
+  {
+    CellValue<int> cell_owner(*this);
+    cell_owner = convert_to_array(cell_owner_vector);
+    m_cell_owner = cell_owner;
+  }
+
+  {
+    NodeValue<int> node_owner(*this);
+    node_owner = convert_to_array(node_owner_vector);
+    m_node_owner = node_owner;
+  }
+
   if constexpr (Dimension>1) {
     this->_computeCellFaceAndFaceNodeConnectivities();
   }
@@ -278,16 +292,22 @@ template Connectivity1D::
 Connectivity(const std::vector<std::vector<unsigned int>>& cell_by_node_vector,
              const std::vector<CellType>& cell_type_vector,
              const std::vector<int>& cell_number_vector,
-             const std::vector<int>& node_number_vector);
+             const std::vector<int>& node_number_vector,
+             const std::vector<int>& cell_owner_vector,
+             const std::vector<int>& node_owner_vector);
 
 template Connectivity2D::
 Connectivity(const std::vector<std::vector<unsigned int>>& cell_by_node_vector,
              const std::vector<CellType>& cell_type_vector,
              const std::vector<int>& cell_number_vector,
-             const std::vector<int>& node_number_vector);
+             const std::vector<int>& node_number_vector,
+             const std::vector<int>& cell_owner_vector,
+             const std::vector<int>& node_owner_vector);
 
 template Connectivity3D::
 Connectivity(const std::vector<std::vector<unsigned int>>& cell_by_node_vector,
              const std::vector<CellType>& cell_type_vector,
              const std::vector<int>& cell_number_vector,
-             const std::vector<int>& node_number_vector);
+             const std::vector<int>& node_number_vector,
+             const std::vector<int>& cell_owner_vector,
+             const std::vector<int>& node_owner_vector);
diff --git a/src/mesh/Connectivity.hpp b/src/mesh/Connectivity.hpp
index c786eb6c316ef8f110e2f5521378fc829f5ce35b..b8783f321c82f0eaa8d5c215b4dec0aefbe9c460 100644
--- a/src/mesh/Connectivity.hpp
+++ b/src/mesh/Connectivity.hpp
@@ -251,6 +251,9 @@ class Connectivity final
 
   NodeValue<const int> m_node_number;
 
+  CellValue<const int> m_cell_owner;
+  NodeValue<const int> m_node_owner;
+
   FaceValuePerCell<const bool> m_cell_face_is_reversed;
 
   NodeValuePerCell<const unsigned short> m_cell_local_numbers_in_their_nodes;
@@ -332,6 +335,18 @@ class Connectivity final
     return m_node_number;
   }
 
+  PASTIS_INLINE
+  const CellValue<const int>& cellOwner() const
+  {
+    return m_cell_owner;
+  }
+
+  PASTIS_INLINE
+  const NodeValue<const int>& nodeOwner() const
+  {
+    return m_node_owner;
+  }
+
   PASTIS_INLINE
   const bool& isConnectivityMatrixBuilt(const ItemType& item_type_0,
                                         const ItemType& item_type_1) const
@@ -662,7 +677,9 @@ class Connectivity final
   Connectivity(const std::vector<std::vector<unsigned int>>& cell_by_node_vector,
                const std::vector<CellType>& cell_type_vector,
                const std::vector<int>& cell_number_vector,
-               const std::vector<int>& node_number_vector);
+               const std::vector<int>& node_number_vector,
+               const std::vector<int>& cell_owner_vector,
+               const std::vector<int>& node_owner_vector);
 
   ~Connectivity()
   {
diff --git a/src/mesh/GmshReader.cpp b/src/mesh/GmshReader.cpp
index 4ec88d09c1b0dfe091be78282e9784e7885792d8..6a19ba4f2595e5b7c7bb9f5f6ae78e9c9607ce07 100644
--- a/src/mesh/GmshReader.cpp
+++ b/src/mesh/GmshReader.cpp
@@ -33,11 +33,11 @@ class ErrorHandler
   };
 
  private:
-  const std::string __filename;	/**< The source file name where the error occured */
-  const size_t __lineNumber;	/**< The line number where exception was raised */
+  const std::string __filename;     /**< The source file name where the error occured */
+  const size_t __lineNumber;        /**< The line number where exception was raised */
   const std::string __errorMessage; /**< The reporting message */
 
-  const Type __type;		/**< the type of the error */
+  const Type __type;                /**< the type of the error */
  public:
   /**
    * Prints the error message
@@ -135,23 +135,56 @@ class MeshDispatcher
 
  private:
   const MeshType& m_mesh;
+  CellValue<const int> m_cell_new_owner;
+  NodeValue<const int> m_node_new_owner;
+
   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
+  CellValue<int> _getCellNewOwner()
   {
     CSRGraph mesh_graph = m_mesh.cellToCellGraph();
-
     Partitioner P;
-    Array<int> cell_new_owner = P.partition(mesh_graph);
 
+    CellValue<int> cell_new_owner(m_mesh.connectivity());
+    cell_new_owner = P.partition(mesh_graph);
+    return cell_new_owner;
+  }
+
+  NodeValue<int> _getNodeNewOwner()
+  {
+    const auto& node_to_cell_matrix
+        = m_mesh.connectivity().nodeToCellMatrix();
+
+    pout() << __FILE__ << ':' << __LINE__ << ": use Min function\n";
+#warning could use a better policy
+    NodeValue<int> node_new_owner(m_mesh.connectivity());
+    parallel_for(m_mesh.numberOfNodes(), PASTIS_LAMBDA(const NodeId& r) {
+        const auto& node_to_cell = node_to_cell_matrix[r];
+        CellId Jmin = node_to_cell[0];
+
+        for (size_t j=1; j<node_to_cell.size(); ++j) {
+          const CellId J = node_to_cell[j];
+          if (J<Jmin) {
+            Jmin=J;
+          }
+        }
+        node_new_owner[r] = m_cell_new_owner[Jmin];
+      });
+
+#warning Add missing synchronize
+    return node_new_owner;
+  }
+
+  const CellListToSendByProc
+  _buildCellListToSend() const
+  {
     std::vector<std::vector<CellId>> cell_vector_to_send_by_proc(parallel::size());
-    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});
+    for (CellId j=0; j<m_mesh.numberOfCells(); ++j) {
+      cell_vector_to_send_by_proc[m_cell_new_owner[j]].push_back(j);
     }
 
     std::vector<Array<const CellId>> cell_list_to_send_by_proc(parallel::size());
@@ -173,6 +206,18 @@ class MeshDispatcher
 
  public:
 
+  PASTIS_INLINE
+  const CellValue<const int>& cellNewOwner() const
+  {
+    return m_cell_new_owner;
+  }
+
+  PASTIS_INLINE
+  const NodeValue<const int>& nodeNewOwner() const
+  {
+    return m_node_new_owner;
+  }
+
   template<typename DataType>
   std::vector<Array<std::remove_const_t<DataType>>>
   exchange(const CellValue<DataType>& cell_value) const
@@ -205,6 +250,8 @@ class MeshDispatcher
 
   MeshDispatcher(const MeshType& mesh)
       : m_mesh(mesh),
+        m_cell_new_owner(_getCellNewOwner()),
+        m_node_new_owner(_getNodeNewOwner()),
         m_cell_list_to_send_by_proc(_buildCellListToSend()),
         m_nb_cell_to_send_by_proc(_buildNbCellToSend()),
         m_nb_cell_to_recv_by_proc(parallel::allToAll(m_nb_cell_to_send_by_proc))
@@ -226,7 +273,7 @@ void GmshReader::_dispatch()
   using MeshType = Mesh<ConnectivityType>;
 
   if (not m_mesh) {
-    std::shared_ptr<ConnectivityType> connectivity(new ConnectivityType({},{},{},{}));
+    std::shared_ptr<ConnectivityType> connectivity(new ConnectivityType({},{},{},{}, {}, {}));
     NodeValue<Rd> xr;
     m_mesh = std::shared_ptr<IMesh>(new MeshType(connectivity, xr));
   }
@@ -234,13 +281,15 @@ void GmshReader::_dispatch()
 
   MeshDispatcher<Dimension> dispatcher(mesh);
 
-
   std::vector<Array<int>> recv_cell_number_by_proc
       = dispatcher.exchange(mesh.connectivity().cellNumber());
 
   std::vector<Array<CellType>> recv_cell_type_by_proc
       = dispatcher.exchange(mesh.connectivity().cellType());
 
+  std::vector<Array<int>> recv_cell_new_owner_by_proc
+      = dispatcher.exchange(dispatcher.cellNewOwner());
+
   CellValue<int> number_of_node_per_cell(mesh.connectivity());
 
   const auto& cell_to_node_matrix = mesh.connectivity().cellToNodeMatrix();
@@ -477,11 +526,50 @@ void GmshReader::_dispatch()
 
   using ConnectivityType = Connectivity<Dimension>;
 
+  std::vector<int> cell_new_owner_vector(cell_number_id_map.size());
+  for (size_t i_rank=0; i_rank<parallel::size(); ++i_rank) {
+    for (size_t i=0; i<recv_cell_number_by_proc[i_rank].size(); ++i) {
+      int cell_number = recv_cell_number_by_proc[i_rank][i];
+      const auto& searched_cell_id = cell_number_id_map.find(cell_number);
+      Assert(searched_cell_id != cell_number_id_map.end());
+      cell_new_owner_vector[searched_cell_id->second] = recv_cell_new_owner_by_proc[i_rank][i];
+    }
+  }
+
+
+  const NodeValue<const int>& new_node_owner = dispatcher.nodeNewOwner();
+  std::vector<Array<const int>> send_node_owner_by_proc(parallel::size());
+  for (size_t i_rank=0; i_rank<parallel::size(); ++i_rank) {
+    Array<int> send_node_owner(nb_node_to_send_by_proc[i_rank]);
+    const Array<const NodeId> send_node_id = send_node_id_by_proc[i_rank];
+    parallel_for(send_node_id.size(), PASTIS_LAMBDA(const size_t& r) {
+        const NodeId& node_id = send_node_id[r];
+        send_node_owner[r] = new_node_owner[node_id];
+      });
+    send_node_owner_by_proc[i_rank] = send_node_owner;
+  }
+
+  std::vector<Array<int>> recv_node_owner_by_proc(parallel::size());
+  for (size_t i_rank=0; i_rank<parallel::size(); ++i_rank) {
+    recv_node_owner_by_proc[i_rank] = Array<int>(nb_node_to_recv_by_proc[i_rank]);
+  }
+  parallel::exchange(send_node_owner_by_proc, recv_node_owner_by_proc);
+
+  std::vector<int> node_new_owner_vector(new_node_number.size());
+  for (size_t i_rank=0; i_rank<parallel::size(); ++i_rank) {
+    for (size_t r=0; r<recv_node_owner_by_proc[i_rank].size(); ++r) {
+      const NodeId& node_id = recv_node_id_correspondance_by_proc[i_rank][r];
+      node_new_owner_vector[node_id] = recv_node_owner_by_proc[i_rank][r];
+    }
+  }
+
   std::shared_ptr<ConnectivityType> p_connectivity
       = std::make_shared<ConnectivityType>(cell_by_node_vector,
                                            new_cell_type,
                                            new_cell_number,
-                                           new_node_number);
+                                           new_node_number,
+                                           cell_new_owner_vector,
+                                           node_new_owner_vector);
 
   const NodeValue<const Rd>& xr = mesh.xr();
   std::vector<Array<const Rd>> send_node_coord_by_proc(parallel::size());
@@ -1253,10 +1341,18 @@ GmshReader::__proceedData()
       cell_number_vector[jh] = __hexahedra_number[j];
     }
 
+    std::vector<int> cell_owner_vector(nb_cells);
+    std::fill(cell_owner_vector.begin(), cell_owner_vector.end(), parallel::rank());
+    std::vector<int> node_owner_vector(node_number_vector.size());
+    std::fill(node_owner_vector.begin(), node_owner_vector.end(), parallel::rank());
+
+
     std::shared_ptr<Connectivity3D> p_connectivity(new Connectivity3D(cell_by_node_vector,
                                                                       cell_type_vector,
                                                                       cell_number_vector,
-                                                                      node_number_vector));
+                                                                      node_number_vector,
+                                                                      cell_owner_vector,
+                                                                      node_owner_vector));
     Connectivity3D& connectivity = *p_connectivity;
 
     std::map<unsigned int, std::vector<unsigned int>> ref_faces_map;
@@ -1321,10 +1417,17 @@ GmshReader::__proceedData()
       cell_number_vector[jq] = __quadrangles_number[j];
     }
 
+    std::vector<int> cell_owner_vector(nb_cells);
+    std::fill(cell_owner_vector.begin(), cell_owner_vector.end(), parallel::rank());
+    std::vector<int> node_owner_vector(node_number_vector.size());
+    std::fill(node_owner_vector.begin(), node_owner_vector.end(), parallel::rank());
+
     std::shared_ptr<Connectivity2D> p_connectivity(new Connectivity2D(cell_by_node_vector,
                                                                       cell_type_vector,
                                                                       cell_number_vector,
-                                                                      node_number_vector));
+                                                                      node_number_vector,
+                                                                      cell_owner_vector,
+                                                                      node_owner_vector));
     Connectivity2D& connectivity = *p_connectivity;
 
     std::map<unsigned int, std::vector<unsigned int>> ref_faces_map;
@@ -1385,10 +1488,17 @@ GmshReader::__proceedData()
       cell_number_vector[j] =  __edges_number[j];
     }
 
+    std::vector<int> cell_owner_vector(nb_cells);
+    std::fill(cell_owner_vector.begin(), cell_owner_vector.end(), parallel::rank());
+    std::vector<int> node_owner_vector(node_number_vector.size());
+    std::fill(node_owner_vector.begin(), node_owner_vector.end(), parallel::rank());
+
     std::shared_ptr<Connectivity1D> p_connectivity(new Connectivity1D(cell_by_node_vector,
                                                                       cell_type_vector,
                                                                       cell_number_vector,
-                                                                      node_number_vector));
+                                                                      node_number_vector,
+                                                                      cell_owner_vector,
+                                                                      node_owner_vector));
     Connectivity1D& connectivity = *p_connectivity;
 
     std::map<unsigned int, std::vector<unsigned int>> ref_points_map;