From b3e38a7edff059c9f07e3af6cc08166e6e0bed7c Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Mon, 13 Feb 2023 01:04:32 +0100
Subject: [PATCH] Redesign of ConnectivityDescriptor

Fixes #10
---
 src/mesh/Connectivity.cpp                   |  71 ++--
 src/mesh/ConnectivityBuilderBase.cpp        | 148 ++++-----
 src/mesh/ConnectivityDescriptor.hpp         | 348 +++++++++++++++++---
 src/mesh/ConnectivityDispatcher.cpp         |  71 +++-
 src/mesh/DiamondDualConnectivityBuilder.cpp | 154 +++++----
 src/mesh/Dual1DConnectivityBuilder.cpp      |  60 ++--
 src/mesh/GmshReader.cpp                     | 315 +++++++++++-------
 src/mesh/LogicalConnectivityBuilder.cpp     | 177 ++++++----
 src/mesh/MedianDualConnectivityBuilder.cpp  | 131 ++++----
 9 files changed, 959 insertions(+), 516 deletions(-)

diff --git a/src/mesh/Connectivity.cpp b/src/mesh/Connectivity.cpp
index 4cb11d443..dc03c1ee6 100644
--- a/src/mesh/Connectivity.cpp
+++ b/src/mesh/Connectivity.cpp
@@ -13,43 +13,36 @@ template <size_t Dimension>
 void
 Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor)
 {
-  Assert(descriptor.cell_to_node_matrix.numberOfRows() == descriptor.cell_type_vector.size());
-  Assert(descriptor.cell_number_vector.size() == descriptor.cell_type_vector.size());
+  Assert(descriptor.cellToNodeMatrix().numberOfRows() == descriptor.cellTypeVector().size());
+  Assert(descriptor.cellNumberVector().size() == descriptor.cellTypeVector().size());
   if constexpr (Dimension > 1) {
-    Assert(descriptor.cell_to_face_matrix.numberOfRows() == descriptor.cell_type_vector.size());
-    Assert(descriptor.face_to_node_matrix.numberOfRows() == descriptor.face_number_vector.size());
-    Assert(descriptor.face_owner_vector.size() == descriptor.face_number_vector.size());
+    Assert(descriptor.cellToFaceMatrix().numberOfRows() == descriptor.cellTypeVector().size());
+    Assert(descriptor.faceToNodeMatrix().numberOfRows() == descriptor.faceNumberVector().size());
+    Assert(descriptor.faceOwnerVector().size() == descriptor.faceNumberVector().size());
   }
 
-  m_number_of_cells = descriptor.cell_number_vector.size();
-  m_number_of_nodes = descriptor.node_number_vector.size();
+  m_number_of_cells = descriptor.cellNumberVector().size();
+  m_number_of_nodes = descriptor.nodeNumberVector().size();
 
   if constexpr (Dimension == 1) {
     m_number_of_edges = m_number_of_nodes;
     m_number_of_faces = m_number_of_nodes;
   } else {
-    m_number_of_faces = descriptor.face_number_vector.size();
+    m_number_of_faces = descriptor.faceNumberVector().size();
     if constexpr (Dimension == 2) {
       m_number_of_edges = m_number_of_faces;
     } else {
       static_assert(Dimension == 3, "unexpected dimension");
-      m_number_of_edges = descriptor.edge_number_vector.size();
+      m_number_of_edges = descriptor.edgeNumberVector().size();
     }
   }
 
   auto& cell_to_node_matrix = m_item_to_item_matrix[itemTId(ItemType::cell)][itemTId(ItemType::node)];
-  cell_to_node_matrix       = descriptor.cell_to_node_matrix;
+  cell_to_node_matrix       = descriptor.cellToNodeMatrix();
 
-  {
-    WeakCellValue<CellType> cell_type(*this);
-    parallel_for(
-      this->numberOfCells(), PUGS_LAMBDA(CellId j) { cell_type[j] = descriptor.cell_type_vector[j]; });
-    m_cell_type = cell_type;
-  }
-
-  m_cell_number = WeakCellValue<int>(*this, descriptor.cell_number_vector);
-
-  m_node_number = WeakNodeValue<int>(*this, descriptor.node_number_vector);
+  m_cell_type   = WeakCellValue<const CellType>(*this, descriptor.cellTypeVector());
+  m_cell_number = WeakCellValue<const int>(*this, descriptor.cellNumberVector());
+  m_node_number = WeakNodeValue<const int>(*this, descriptor.nodeNumberVector());
 
   {
     WeakCellValue<int> cell_global_index(*this);
@@ -59,7 +52,7 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor)
     m_cell_global_index = cell_global_index;
   }
 
-  m_cell_owner = WeakCellValue<int>(*this, descriptor.cell_owner_vector);
+  m_cell_owner = WeakCellValue<const int>(*this, descriptor.cellOwnerVector());
 
   {
     const int rank = parallel::rank();
@@ -69,7 +62,7 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor)
     m_cell_is_owned = cell_is_owned;
   }
 
-  m_node_owner = WeakNodeValue<int>{*this, descriptor.node_owner_vector};
+  m_node_owner = WeakNodeValue<const int>{*this, descriptor.nodeOwnerVector()};
 
   Array<bool> node_is_owned_array(this->numberOfNodes());
   {
@@ -85,13 +78,13 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor)
 
   if constexpr (Dimension == 1) {
     // faces are similar to nodes
-    m_face_number   = WeakFaceValue<int>(*this, descriptor.node_number_vector);
-    m_face_owner    = WeakFaceValue<int>(*this, descriptor.node_owner_vector);
+    m_face_number   = WeakFaceValue<const int>(*this, descriptor.nodeNumberVector());
+    m_face_owner    = WeakFaceValue<const int>(*this, descriptor.nodeOwnerVector());
     m_face_is_owned = WeakFaceValue<bool>(*this, node_is_owned_array);
 
     // edges are similar to nodes
-    m_edge_number   = WeakEdgeValue<int>(*this, descriptor.node_number_vector);
-    m_edge_owner    = WeakEdgeValue<int>(*this, descriptor.node_owner_vector);
+    m_edge_number   = WeakEdgeValue<const int>(*this, descriptor.nodeNumberVector());
+    m_edge_owner    = WeakEdgeValue<const int>(*this, descriptor.nodeOwnerVector());
     m_edge_is_owned = WeakEdgeValue<bool>(*this, node_is_owned_array);
 
     // edge and face references are set equal to node references
@@ -112,15 +105,15 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor)
     }
 
   } else {
-    m_item_to_item_matrix[itemTId(ItemType::face)][itemTId(ItemType::node)] = descriptor.face_to_node_matrix;
+    m_item_to_item_matrix[itemTId(ItemType::face)][itemTId(ItemType::node)] = descriptor.faceToNodeMatrix();
 
-    m_item_to_item_matrix[itemTId(ItemType::cell)][itemTId(ItemType::face)] = descriptor.cell_to_face_matrix;
+    m_item_to_item_matrix[itemTId(ItemType::cell)][itemTId(ItemType::face)] = descriptor.cellToFaceMatrix();
 
-    m_cell_face_is_reversed = FaceValuePerCell<bool>(*this, descriptor.cell_face_is_reversed);
+    m_cell_face_is_reversed = FaceValuePerCell<const bool>(*this, descriptor.cellFaceIsReversed());
 
-    m_face_number = WeakFaceValue<int>(*this, descriptor.face_number_vector);
+    m_face_number = WeakFaceValue<const int>(*this, descriptor.faceNumberVector());
 
-    m_face_owner = WeakFaceValue<int>(*this, descriptor.face_owner_vector);
+    m_face_owner = WeakFaceValue<const int>(*this, descriptor.faceOwnerVector());
 
     Array<bool> face_is_owned_array(this->numberOfFaces());
     {
@@ -135,8 +128,8 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor)
 
     if constexpr (Dimension == 2) {
       // edges are similar to faces
-      m_edge_number   = WeakEdgeValue<int>(*this, descriptor.face_number_vector);
-      m_edge_owner    = WeakEdgeValue<int>(*this, descriptor.face_owner_vector);
+      m_edge_number   = WeakEdgeValue<const int>(*this, descriptor.faceNumberVector());
+      m_edge_owner    = WeakEdgeValue<const int>(*this, descriptor.faceOwnerVector());
       m_edge_is_owned = WeakEdgeValue<bool>(*this, face_is_owned_array);
 
       // edge references are set equal to face references
@@ -153,16 +146,16 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor)
       }
 
     } else {
-      m_item_to_item_matrix[itemTId(ItemType::edge)][itemTId(ItemType::node)] = descriptor.edge_to_node_matrix;
+      m_item_to_item_matrix[itemTId(ItemType::edge)][itemTId(ItemType::node)] = descriptor.edgeToNodeMatrix();
 
-      m_item_to_item_matrix[itemTId(ItemType::face)][itemTId(ItemType::edge)] = descriptor.face_to_edge_matrix;
+      m_item_to_item_matrix[itemTId(ItemType::face)][itemTId(ItemType::edge)] = descriptor.faceToEdgeMatrix();
 
-      m_item_to_item_matrix[itemTId(ItemType::cell)][itemTId(ItemType::edge)] = descriptor.cell_to_edge_matrix;
+      m_item_to_item_matrix[itemTId(ItemType::cell)][itemTId(ItemType::edge)] = descriptor.cellToEdgeMatrix();
 
-      m_face_edge_is_reversed = EdgeValuePerFace<bool>(*this, descriptor.face_edge_is_reversed);
+      m_face_edge_is_reversed = EdgeValuePerFace<const bool>(*this, descriptor.faceEdgeIsReversed());
 
-      m_edge_number = WeakEdgeValue<int>(*this, descriptor.edge_number_vector);
-      m_edge_owner  = WeakEdgeValue<int>(*this, descriptor.edge_owner_vector);
+      m_edge_number = WeakEdgeValue<const int>(*this, descriptor.edgeNumberVector());
+      m_edge_owner  = WeakEdgeValue<const int>(*this, descriptor.edgeOwnerVector());
 
       {
         const int rank = parallel::rank();
diff --git a/src/mesh/ConnectivityBuilderBase.cpp b/src/mesh/ConnectivityBuilderBase.cpp
index a9b99e521..e7eb95fc6 100644
--- a/src/mesh/ConnectivityBuilderBase.cpp
+++ b/src/mesh/ConnectivityBuilderBase.cpp
@@ -15,17 +15,19 @@ ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities(ConnectivityD
 {
   static_assert((Dimension == 2) or (Dimension == 3), "Invalid dimension to compute cell-face connectivities");
 
-  const auto& node_number_vector = descriptor.node_number_vector;
+  const auto& node_number_vector  = descriptor.nodeNumberVector();
+  const auto& cell_to_node_matrix = descriptor.cellToNodeMatrix();
+  const auto& cell_type_vector    = descriptor.cellTypeVector();
 
   size_t total_number_of_faces = 0;
 
-  for (CellId j = 0; j < descriptor.cell_to_node_matrix.numberOfRows(); ++j) {
-    const auto& cell_nodes = descriptor.cell_to_node_matrix[j];
+  for (CellId j = 0; j < cell_to_node_matrix.numberOfRows(); ++j) {
+    const auto& cell_nodes = cell_to_node_matrix[j];
 
     if constexpr (Dimension == 2) {
       total_number_of_faces += cell_nodes.size();
     } else if constexpr (Dimension == 3) {
-      switch (descriptor.cell_type_vector[j]) {
+      switch (cell_type_vector[j]) {
       case CellType::Hexahedron: {
         total_number_of_faces += 6;
         break;
@@ -48,7 +50,7 @@ ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities(ConnectivityD
       }
       default: {
         std::ostringstream error_msg;
-        error_msg << name(descriptor.cell_type_vector[j]) << ": unexpected cell type in dimension 3";
+        error_msg << name(cell_type_vector[j]) << ": unexpected cell type in dimension 3";
         throw UnexpectedError(error_msg.str());
       }
       }
@@ -61,8 +63,8 @@ ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities(ConnectivityD
     } else {
       Assert(Dimension == 3);
       size_t count_number_of_face_by_node = 0;
-      for (CellId j = 0; j < descriptor.cell_to_node_matrix.numberOfRows(); ++j) {
-        switch (descriptor.cell_type_vector[j]) {
+      for (CellId j = 0; j < cell_to_node_matrix.numberOfRows(); ++j) {
+        switch (cell_type_vector[j]) {
         case CellType::Hexahedron: {
           count_number_of_face_by_node += 6 * 4;
           break;
@@ -76,18 +78,18 @@ ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities(ConnectivityD
           break;
         }
         case CellType::Pyramid: {
-          const auto& cell_nodes = descriptor.cell_to_node_matrix[j];
+          const auto& cell_nodes = cell_to_node_matrix[j];
           count_number_of_face_by_node += 1 * cell_nodes.size() + cell_nodes.size() * 3;
           break;
         }
         case CellType::Diamond: {
-          const auto& cell_nodes = descriptor.cell_to_node_matrix[j];
+          const auto& cell_nodes = cell_to_node_matrix[j];
           count_number_of_face_by_node += cell_nodes.size() * 3 * 2;
           break;
         }
         default: {
           std::ostringstream error_msg;
-          error_msg << name(descriptor.cell_type_vector[j]) << ": unexpected cell type in dimension 3";
+          error_msg << name(cell_type_vector[j]) << ": unexpected cell type in dimension 3";
           throw UnexpectedError(error_msg.str());
         }
         }
@@ -101,14 +103,14 @@ ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities(ConnectivityD
   size_t i_face           = 0;
   dup_face_to_node_row[0] = 0;
 
-  Array<unsigned short> cell_nb_faces(descriptor.cell_to_node_matrix.numberOfRows());
+  Array<unsigned short> cell_nb_faces(cell_to_node_matrix.numberOfRows());
   {
     size_t i_face_node = 0;
-    for (CellId j = 0; j < descriptor.cell_to_node_matrix.numberOfRows(); ++j) {
-      const auto& cell_nodes = descriptor.cell_to_node_matrix[j];
+    for (CellId j = 0; j < cell_to_node_matrix.numberOfRows(); ++j) {
+      const auto& cell_nodes = cell_to_node_matrix[j];
 
       if constexpr (Dimension == 2) {
-        switch (descriptor.cell_type_vector[j]) {
+        switch (cell_type_vector[j]) {
         case CellType::Triangle: {
           dup_faces_to_node_list[i_face_node++] = cell_nodes[1];
           dup_faces_to_node_list[i_face_node++] = cell_nodes[2];
@@ -163,12 +165,12 @@ ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities(ConnectivityD
         }
         default: {
           std::ostringstream error_msg;
-          error_msg << name(descriptor.cell_type_vector[j]) << ": unexpected cell type in dimension 2";
+          error_msg << name(cell_type_vector[j]) << ": unexpected cell type in dimension 2";
           throw UnexpectedError(error_msg.str());
         }
         }
       } else if constexpr (Dimension == 3) {
-        switch (descriptor.cell_type_vector[j]) {
+        switch (cell_type_vector[j]) {
         case CellType::Hexahedron: {
           dup_faces_to_node_list[i_face_node++] = cell_nodes[3];
           dup_faces_to_node_list[i_face_node++] = cell_nodes[2];
@@ -352,7 +354,7 @@ ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities(ConnectivityD
         }
         default: {
           std::ostringstream error_msg;
-          error_msg << name(descriptor.cell_type_vector[j]) << ": unexpected cell type in dimension 3";
+          error_msg << name(cell_type_vector[j]) << ": unexpected cell type in dimension 3";
           throw UnexpectedError(error_msg.str());
         }
         }
@@ -528,7 +530,7 @@ ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities(ConnectivityD
     }
   }
 
-  descriptor.node_to_face_matrix = ConnectivityMatrix(node_to_face_row, node_to_face_list);
+  descriptor.setNodeToFaceMatrix(ConnectivityMatrix(node_to_face_row, node_to_face_list));
 
   Array<unsigned int> cell_to_face_row(cell_nb_faces.size() + 1);
   cell_to_face_row[0] = 0;
@@ -546,18 +548,14 @@ ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities(ConnectivityD
     }
   }
 
-  descriptor.cell_to_face_matrix = ConnectivityMatrix(cell_to_face_row, cell_to_face_list);
+  descriptor.setCellToFaceMatrix(ConnectivityMatrix(cell_to_face_row, cell_to_face_list));
 
-  {
-    // Face numbers may change if numbers are provided in the file
-    descriptor.face_number_vector = [&] {
-      Array<int> face_number_vector(total_number_of_faces - nb_dup_faces);
-      for (size_t l = 0; l < face_number_vector.size(); ++l) {
-        face_number_vector[l] = l;
-      }
-      return face_number_vector;
-    }();
-  }
+  descriptor.setFaceNumberVector([&] {
+    Array<int> face_number_vector(total_number_of_faces - nb_dup_faces);
+    parallel_for(
+      face_number_vector.size(), PUGS_LAMBDA(const size_t l) { face_number_vector[l] = l; });
+    return face_number_vector;
+  }());
 
   Array<unsigned int> face_ending(total_number_of_faces - nb_dup_faces + 1);
   {
@@ -590,9 +588,9 @@ ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities(ConnectivityD
     }
   }
 
-  descriptor.face_to_node_matrix = ConnectivityMatrix(face_ending, faces_node_list);
+  descriptor.setFaceToNodeMatrix(ConnectivityMatrix(face_ending, faces_node_list));
 
-  descriptor.cell_face_is_reversed = cell_face_is_reversed;
+  descriptor.setCellFaceIsReversed(cell_face_is_reversed);
 }
 
 template <size_t Dimension>
@@ -601,7 +599,9 @@ ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities(Co
 {
   static_assert(Dimension == 3, "Invalid dimension to compute face-edge connectivities");
 
-  Array<const unsigned int> face_to_edge_row = descriptor.face_to_node_matrix.rowsMap();
+  const auto& face_to_node_matrix = descriptor.faceToNodeMatrix();
+
+  Array<const unsigned int> face_to_edge_row = face_to_node_matrix.rowsMap();
 
   const size_t total_number_of_face_edges = face_to_edge_row[face_to_edge_row.size() - 1];
 
@@ -611,20 +611,21 @@ ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities(Co
   {
     size_t i_edge_node = 0;
     for (size_t i_face = 0; i_face < face_to_edge_row.size() - 1; ++i_face) {
-      for (size_t i_node = 0; i_node < descriptor.face_to_node_matrix[i_face].size() - 1; ++i_node) {
-        face_edge_to_node_list[i_edge_node++] = descriptor.face_to_node_matrix[i_face][i_node];
-        face_edge_to_node_list[i_edge_node++] = descriptor.face_to_node_matrix[i_face][i_node + 1];
+      const auto& face_node_list = face_to_node_matrix[i_face];
+      for (size_t i_node = 0; i_node < face_node_list.size() - 1; ++i_node) {
+        face_edge_to_node_list[i_edge_node++] = face_node_list[i_node];
+        face_edge_to_node_list[i_edge_node++] = face_node_list[i_node + 1];
       }
-      face_edge_to_node_list[i_edge_node++] =
-        descriptor.face_to_node_matrix[i_face][descriptor.face_to_node_matrix[i_face].size() - 1];
-      face_edge_to_node_list[i_edge_node++] = descriptor.face_to_node_matrix[i_face][0];
+      face_edge_to_node_list[i_edge_node++] = face_node_list[face_node_list.size() - 1];
+      face_edge_to_node_list[i_edge_node++] = face_node_list[0];
     }
   }
 
+  auto node_number_vector = descriptor.nodeNumberVector();
   Array<bool> face_edge_is_reversed(total_number_of_face_edges);
   for (size_t i_edge = 0; i_edge < total_number_of_face_edges; ++i_edge) {
-    if (descriptor.node_number_vector[face_edge_to_node_list[2 * i_edge]] >
-        descriptor.node_number_vector[face_edge_to_node_list[2 * i_edge + 1]]) {
+    if (node_number_vector[face_edge_to_node_list[2 * i_edge]] >
+        node_number_vector[face_edge_to_node_list[2 * i_edge + 1]]) {
       std::swap(face_edge_to_node_list[2 * i_edge], face_edge_to_node_list[2 * i_edge + 1]);
       face_edge_is_reversed[i_edge] = true;
     } else {
@@ -633,7 +634,7 @@ ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities(Co
   }
 
   const size_t total_number_of_edges = face_edge_is_reversed.size();
-  Array<unsigned int> node_to_face_edge_row(descriptor.node_number_vector.size() + 1);
+  Array<unsigned int> node_to_face_edge_row(node_number_vector.size() + 1);
   node_to_face_edge_row.fill(0);
   for (size_t i_edge = 0; i_edge < total_number_of_edges; ++i_edge) {
     for (size_t i_edge_node = 0; i_edge_node < 2; ++i_edge_node) {
@@ -647,7 +648,7 @@ ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities(Co
   Array<unsigned int> node_to_face_edge_list(node_to_face_edge_row[node_to_face_edge_row.size() - 1]);
 
   {
-    Array<unsigned int> node_to_face_edge_row_idx(descriptor.node_number_vector.size());
+    Array<unsigned int> node_to_face_edge_row_idx(node_number_vector.size());
     node_to_face_edge_row_idx.fill(0);
 
     for (size_t i_edge = 0; i_edge < total_number_of_edges; ++i_edge) {
@@ -671,8 +672,7 @@ ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities(Co
             (face_edge_to_node_list[i_edge_first_node + 1] == face_edge_to_node_list[j_edge_first_node + 1]));
   };
 
-  const auto& node_number_vector = descriptor.node_number_vector;
-  size_t nb_duplicate_edges      = 0;
+  size_t nb_duplicate_edges = 0;
   for (size_t i_node = 0; i_node < node_number_vector.size(); ++i_node) {
     for (size_t i_node_face = node_to_face_edge_row[i_node]; i_node_face < node_to_face_edge_row[i_node + 1] - 1;
          ++i_node_face) {
@@ -720,30 +720,26 @@ ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities(Co
     }
   }
 
-  {
-    // Edge numbers may change if numbers are provided in the file
-    descriptor.edge_number_vector = [&] {
-      Array<int> edge_number_vector(total_number_of_edges - nb_duplicate_edges);
-      for (size_t i_edge = 0; i_edge < edge_number_vector.size(); ++i_edge) {
-        edge_number_vector[i_edge] = i_edge;
-      }
-      return edge_number_vector;
-    }();
-  }
+  descriptor.setEdgeNumberVector([&] {
+    Array<int> edge_number_vector(total_number_of_edges - nb_duplicate_edges);
+    parallel_for(
+      edge_number_vector.size(), PUGS_LAMBDA(const size_t i_edge) { edge_number_vector[i_edge] = i_edge; });
+    return edge_number_vector;
+  }());
 
   Array<unsigned int> edge_to_node_row(total_number_of_edges - nb_duplicate_edges + 1);
   parallel_for(
     edge_to_node_row.size(), PUGS_LAMBDA(const size_t i_edge) { edge_to_node_row[i_edge] = 2 * i_edge; });
 
-  descriptor.edge_to_node_matrix = ConnectivityMatrix(edge_to_node_row, edge_to_node_list);
+  descriptor.setEdgeToNodeMatrix(ConnectivityMatrix(edge_to_node_row, edge_to_node_list));
 
   // Use real edge ids
   for (size_t i_edge = 0; i_edge < face_edge_to_edge.size(); ++i_edge) {
     face_edge_to_edge[i_edge] = dup_edge_to_edge_id[face_edge_to_edge[i_edge]];
   }
 
-  descriptor.face_to_edge_matrix   = ConnectivityMatrix(face_to_edge_row, face_edge_to_edge);
-  descriptor.face_edge_is_reversed = face_edge_is_reversed;
+  descriptor.setFaceToEdgeMatrix(ConnectivityMatrix(face_to_edge_row, face_edge_to_edge));
+  descriptor.setFaceEdgeIsReversed(face_edge_is_reversed);
 
   Array<size_t> node_to_duplicated_edge_id_list(node_to_face_edge_list.size());
   for (size_t i_node_edge = 0; i_node_edge < node_to_duplicated_edge_id_list.size(); ++i_node_edge) {
@@ -753,10 +749,10 @@ ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities(Co
   Array<bool> node_to_edge_is_duplicated(node_to_face_edge_list.size());
   node_to_edge_is_duplicated.fill(false);
 
-  Array<unsigned int> node_nb_edges(descriptor.node_number_vector.size());
+  Array<unsigned int> node_nb_edges(node_number_vector.size());
   node_nb_edges.fill(0);
 
-  for (size_t node_id = 0; node_id < descriptor.node_number_vector.size(); ++node_id) {
+  for (size_t node_id = 0; node_id < node_number_vector.size(); ++node_id) {
     size_t nb_dup_edges = 0;
     for (EdgeId i_edge = node_to_face_edge_row[node_id]; i_edge < node_to_face_edge_row[node_id + 1] - 1; ++i_edge) {
       if (not node_to_edge_is_duplicated[i_edge]) {
@@ -771,9 +767,9 @@ ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities(Co
     node_nb_edges[node_id] = node_to_face_edge_row[node_id + 1] - node_to_face_edge_row[node_id] - nb_dup_edges;
   }
 
-  Array<unsigned int> node_to_edge_row(descriptor.node_number_vector.size() + 1);
+  Array<unsigned int> node_to_edge_row(node_number_vector.size() + 1);
   node_to_edge_row[0] = 0;
-  for (size_t node_id = 0; node_id < descriptor.node_number_vector.size(); ++node_id) {
+  for (size_t node_id = 0; node_id < node_number_vector.size(); ++node_id) {
     node_to_edge_row[node_id + 1] = node_to_edge_row[node_id] + node_nb_edges[node_id];
   }
 
@@ -787,11 +783,11 @@ ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities(Co
     }
   }
 
-  descriptor.node_to_edge_matrix = ConnectivityMatrix(node_to_edge_row, node_to_edge_list);
+  descriptor.setNodeToEdgeMatrix(ConnectivityMatrix(node_to_edge_row, node_to_edge_list));
 
   auto find_edge = [=](const NodeId& node0_id, const NodeId& node1_id) -> EdgeId {
     auto [first_node_id, second_node_id] = [&] {
-      if (descriptor.node_number_vector[node0_id] < descriptor.node_number_vector[node1_id]) {
+      if (node_number_vector[node0_id] < node_number_vector[node1_id]) {
         return std::make_pair(node0_id, node1_id);
       } else {
         return std::make_pair(node1_id, node0_id);
@@ -808,13 +804,15 @@ ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities(Co
     throw UnexpectedError("Cannot find cell edge in edge list");
   };
 
+  const auto& cell_to_node_matrix = descriptor.cellToNodeMatrix();
+  const auto& cell_type_vector    = descriptor.cellTypeVector();
   {
-    Array<unsigned int> cell_to_edge_row(descriptor.cell_to_node_matrix.numberOfRows() + 1);
+    Array<unsigned int> cell_to_edge_row(cell_to_node_matrix.numberOfRows() + 1);
     {
       cell_to_edge_row[0] = 0;
 
-      for (CellId cell_id = 0; cell_id < descriptor.cell_to_node_matrix.numberOfRows(); ++cell_id) {
-        switch (descriptor.cell_type_vector[cell_id]) {
+      for (CellId cell_id = 0; cell_id < cell_to_node_matrix.numberOfRows(); ++cell_id) {
+        switch (cell_type_vector[cell_id]) {
         case CellType::Tetrahedron: {
           cell_to_edge_row[cell_id + 1] = cell_to_edge_row[cell_id] + 6;
           break;
@@ -828,18 +826,16 @@ ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities(Co
           break;
         }
         case CellType::Pyramid: {
-          cell_to_edge_row[cell_id + 1] =
-            cell_to_edge_row[cell_id] + 2 * (descriptor.cell_to_node_matrix[cell_id].size() - 1);
+          cell_to_edge_row[cell_id + 1] = cell_to_edge_row[cell_id] + 2 * (cell_to_node_matrix[cell_id].size() - 1);
           break;
         }
         case CellType::Diamond: {
-          cell_to_edge_row[cell_id + 1] =
-            cell_to_edge_row[cell_id] + 3 * (descriptor.cell_to_node_matrix[cell_id].size() - 2);
+          cell_to_edge_row[cell_id + 1] = cell_to_edge_row[cell_id] + 3 * (cell_to_node_matrix[cell_id].size() - 2);
           break;
         }
         default: {
           std::stringstream error_msg;
-          error_msg << name(descriptor.cell_type_vector[cell_id]) << ": unexpected cell type in dimension 3";
+          error_msg << name(cell_type_vector[cell_id]) << ": unexpected cell type in dimension 3";
           throw NotImplementedError(error_msg.str());
         }
         }
@@ -849,10 +845,10 @@ ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities(Co
     Array<unsigned int> cell_to_edge_list(cell_to_edge_row[cell_to_edge_row.size() - 1]);
     {
       size_t i_cell_edge = 0;
-      for (CellId cell_id = 0; cell_id < descriptor.cell_to_node_matrix.numberOfRows(); ++cell_id) {
-        const auto& cell_nodes = descriptor.cell_to_node_matrix[cell_id];
+      for (CellId cell_id = 0; cell_id < cell_to_node_matrix.numberOfRows(); ++cell_id) {
+        const auto& cell_nodes = cell_to_node_matrix[cell_id];
 
-        switch (descriptor.cell_type_vector[cell_id]) {
+        switch (cell_type_vector[cell_id]) {
         case CellType::Tetrahedron: {
           constexpr int local_edge[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {2, 3}, {3, 1}};
           for (int i_edge = 0; i_edge < 6; ++i_edge) {
@@ -919,14 +915,14 @@ ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities(Co
         }
         default: {
           std::stringstream error_msg;
-          error_msg << name(descriptor.cell_type_vector[cell_id]) << ": unexpected cell type in dimension 3";
+          error_msg << name(cell_type_vector[cell_id]) << ": unexpected cell type in dimension 3";
           throw NotImplementedError(error_msg.str());
         }
         }
       }
     }
 
-    descriptor.cell_to_edge_matrix = ConnectivityMatrix(cell_to_edge_row, cell_to_edge_list);
+    descriptor.setCellToEdgeMatrix(ConnectivityMatrix(cell_to_edge_row, cell_to_edge_list));
   }
 }
 
diff --git a/src/mesh/ConnectivityDescriptor.hpp b/src/mesh/ConnectivityDescriptor.hpp
index 536345996..dacf84d3c 100644
--- a/src/mesh/ConnectivityDescriptor.hpp
+++ b/src/mesh/ConnectivityDescriptor.hpp
@@ -17,71 +17,337 @@ class ConnectivityDescriptor
   std::vector<RefEdgeList> m_ref_edge_list_vector;
   std::vector<RefNodeList> m_ref_node_list_vector;
 
+  ConnectivityMatrix m_cell_to_face_matrix = ConnectivityMatrix{true};
+  ConnectivityMatrix m_cell_to_edge_matrix = ConnectivityMatrix{true};
+  ConnectivityMatrix m_cell_to_node_matrix = ConnectivityMatrix{true};
+
+  ConnectivityMatrix m_face_to_edge_matrix = ConnectivityMatrix{true};
+  ConnectivityMatrix m_face_to_node_matrix = ConnectivityMatrix{true};
+
+  ConnectivityMatrix m_edge_to_node_matrix = ConnectivityMatrix{true};
+
+  ConnectivityMatrix m_node_to_face_matrix = ConnectivityMatrix{true};
+  ConnectivityMatrix m_node_to_edge_matrix = ConnectivityMatrix{true};
+
+  Array<const bool> m_cell_face_is_reversed;
+  Array<const bool> m_face_edge_is_reversed;
+
+  Array<const CellType> m_cell_type_vector;
+
+  Array<const int> m_cell_number_vector;
+  Array<const int> m_face_number_vector;
+  Array<const int> m_edge_number_vector;
+  Array<const int> m_node_number_vector;
+
+  Array<const int> m_cell_owner_vector;
+  Array<const int> m_face_owner_vector;
+  Array<const int> m_edge_owner_vector;
+  Array<const int> m_node_owner_vector;
+
  public:
-  ConnectivityMatrix cell_to_face_matrix = ConnectivityMatrix{true};
-  ConnectivityMatrix cell_to_edge_matrix = ConnectivityMatrix{true};
-  ConnectivityMatrix cell_to_node_matrix = ConnectivityMatrix{true};
+  void
+  setCellNumberVector(const Array<const int>& cell_number_vector)
+  {
+    // No check since it can change reading file for instance
+    m_cell_number_vector = cell_number_vector;
+  }
 
-  ConnectivityMatrix face_to_edge_matrix = ConnectivityMatrix{true};
-  ConnectivityMatrix face_to_node_matrix = ConnectivityMatrix{true};
+  PUGS_INLINE
+  const Array<const int>&
+  cellNumberVector() const
+  {
+    return m_cell_number_vector;
+  }
 
-  ConnectivityMatrix edge_to_node_matrix = ConnectivityMatrix{true};
+  void
+  setFaceNumberVector(const Array<const int>& face_number_vector)
+  {
+    // No check since it can change reading file for instance
+    m_face_number_vector = face_number_vector;
+  }
 
-  ConnectivityMatrix node_to_face_matrix = ConnectivityMatrix{true};
-  ConnectivityMatrix node_to_edge_matrix = ConnectivityMatrix{true};
+  PUGS_INLINE
+  const Array<const int>&
+  faceNumberVector() const
+  {
+    return m_face_number_vector;
+  }
 
-  template <typename ItemOfItemT>
-  auto&
-  itemOfItemVector()
+  void
+  setEdgeNumberVector(const Array<const int>& edge_number_vector)
   {
-    if constexpr (std::is_same_v<ItemOfItemT, NodeOfCell>) {
-      return cell_to_node_matrix;
-    } else if constexpr (std::is_same_v<ItemOfItemT, FaceOfCell>) {
-      return cell_to_face_matrix;
-    } else if constexpr (std::is_same_v<ItemOfItemT, EdgeOfCell>) {
-      return cell_to_edge_matrix;
-    } else if constexpr (std::is_same_v<ItemOfItemT, EdgeOfFace>) {
-      return face_to_edge_matrix;
-    } else if constexpr (std::is_same_v<ItemOfItemT, NodeOfFace>) {
-      return face_to_node_matrix;
-    } else if constexpr (std::is_same_v<ItemOfItemT, NodeOfEdge>) {
-      return edge_to_node_matrix;
-    } else {
-      static_assert(is_false_v<ItemOfItemT>, "Unexpected item of item type");
-    }
+    // No check since it can change reading file for instance
+    m_edge_number_vector = edge_number_vector;
   }
 
-  Array<bool> cell_face_is_reversed;
-  Array<bool> face_edge_is_reversed;
+  PUGS_INLINE
+  const Array<const int>&
+  edgeNumberVector() const
+  {
+    return m_edge_number_vector;
+  }
 
-  Array<CellType> cell_type_vector;
+  void
+  setNodeNumberVector(const Array<const int>& node_number_vector)
+  {
+    // No check since it can change reading file for instance
+    m_node_number_vector = node_number_vector;
+  }
 
-  Array<int> cell_number_vector;
-  Array<int> face_number_vector;
-  Array<int> edge_number_vector;
-  Array<int> node_number_vector;
+  PUGS_INLINE
+  const Array<const int>&
+  nodeNumberVector() const
+  {
+    return m_node_number_vector;
+  }
 
   template <ItemType item_type>
   Array<const int>
   itemNumberVector() const
   {
     if constexpr (item_type == ItemType::cell) {
-      return cell_number_vector;
+      return m_cell_number_vector;
     } else if constexpr (item_type == ItemType::face) {
-      return face_number_vector;
+      return m_face_number_vector;
     } else if constexpr (item_type == ItemType::edge) {
-      return edge_number_vector;
+      return m_edge_number_vector;
     } else if constexpr (item_type == ItemType::node) {
-      return node_number_vector;
+      return m_node_number_vector;
     } else {
       static_assert(is_false_item_type_v<item_type>, "Unexpected item type");
     }
   }
 
-  Array<int> cell_owner_vector;
-  Array<int> face_owner_vector;
-  Array<int> edge_owner_vector;
-  Array<int> node_owner_vector;
+  void
+  setCellOwnerVector(const Array<const int>& cell_owner_vector)
+  {
+    Assert(m_cell_owner_vector.size() == 0);
+    m_cell_owner_vector = cell_owner_vector;
+  }
+
+  PUGS_INLINE
+  const Array<const int>&
+  cellOwnerVector() const
+  {
+    return m_cell_owner_vector;
+  }
+
+  void
+  setFaceOwnerVector(const Array<const int>& face_owner_vector)
+  {
+    Assert(m_face_owner_vector.size() == 0);
+    m_face_owner_vector = face_owner_vector;
+  }
+
+  PUGS_INLINE
+  const Array<const int>&
+  faceOwnerVector() const
+  {
+    return m_face_owner_vector;
+  }
+
+  void
+  setEdgeOwnerVector(const Array<const int>& edge_owner_vector)
+  {
+    Assert(m_edge_owner_vector.size() == 0);
+    m_edge_owner_vector = edge_owner_vector;
+  }
+
+  PUGS_INLINE
+  const Array<const int>&
+  edgeOwnerVector() const
+  {
+    return m_edge_owner_vector;
+  }
+
+  void
+  setNodeOwnerVector(const Array<const int>& node_owner_vector)
+  {
+    Assert(m_node_owner_vector.size() == 0);
+    m_node_owner_vector = node_owner_vector;
+  }
+
+  PUGS_INLINE
+  const Array<const int>&
+  nodeOwnerVector() const
+  {
+    return m_node_owner_vector;
+  }
+
+  void
+  setCellFaceIsReversed(const Array<const bool>& cell_face_is_reversed)
+  {
+    Assert(m_cell_face_is_reversed.size() == 0);
+    m_cell_face_is_reversed = cell_face_is_reversed;
+  }
+
+  PUGS_INLINE
+  const Array<const bool>&
+  cellFaceIsReversed() const
+  {
+    return m_cell_face_is_reversed;
+  }
+
+  void
+  setFaceEdgeIsReversed(const Array<const bool>& face_edge_is_reversed)
+  {
+    Assert(m_face_edge_is_reversed.size() == 0);
+    m_face_edge_is_reversed = face_edge_is_reversed;
+  }
+
+  PUGS_INLINE
+  const Array<const bool>&
+  faceEdgeIsReversed() const
+  {
+    return m_face_edge_is_reversed;
+  }
+
+  void
+  setCellTypeVector(const Array<const CellType>& cell_type_vector)
+  {
+    Assert(m_face_edge_is_reversed.size() == 0);
+    m_cell_type_vector = cell_type_vector;
+  }
+
+  PUGS_INLINE
+  const Array<const CellType>&
+  cellTypeVector() const
+  {
+    return m_cell_type_vector;
+  }
+
+  void
+  setCellToFaceMatrix(const ConnectivityMatrix& cell_to_face_matrix)
+  {
+    Assert(m_cell_to_face_matrix.numberOfRows() == 0);
+    m_cell_to_face_matrix = cell_to_face_matrix;
+  }
+
+  void
+  setCellToEdgeMatrix(const ConnectivityMatrix& cell_to_edge_matrix)
+  {
+    Assert(m_cell_to_edge_matrix.numberOfRows() == 0);
+    m_cell_to_edge_matrix = cell_to_edge_matrix;
+  }
+
+  void
+  setCellToNodeMatrix(const ConnectivityMatrix& cell_to_node_matrix)
+  {
+    Assert(m_cell_to_node_matrix.numberOfRows() == 0);
+    m_cell_to_node_matrix = cell_to_node_matrix;
+  }
+
+  void
+  setFaceToEdgeMatrix(const ConnectivityMatrix& face_to_edge_matrix)
+  {
+    Assert(m_face_to_edge_matrix.numberOfRows() == 0);
+    m_face_to_edge_matrix = face_to_edge_matrix;
+  }
+
+  void
+  setFaceToNodeMatrix(const ConnectivityMatrix& face_to_node_matrix)
+  {
+    Assert(m_face_to_node_matrix.numberOfRows() == 0);
+    m_face_to_node_matrix = face_to_node_matrix;
+  }
+
+  void
+  setEdgeToNodeMatrix(const ConnectivityMatrix& edge_to_node_matrix)
+  {
+    Assert(m_edge_to_node_matrix.numberOfRows() == 0);
+    m_edge_to_node_matrix = edge_to_node_matrix;
+  }
+
+  void
+  setNodeToFaceMatrix(const ConnectivityMatrix& node_to_face_matrix)
+  {
+    Assert(m_node_to_face_matrix.numberOfRows() == 0);
+    m_node_to_face_matrix = node_to_face_matrix;
+  }
+
+  void
+  setNodeToEdgeMatrix(const ConnectivityMatrix& node_to_edge_matrix)
+  {
+    Assert(m_node_to_edge_matrix.numberOfRows() == 0);
+    m_node_to_edge_matrix = node_to_edge_matrix;
+  }
+
+  PUGS_INLINE
+  const ConnectivityMatrix&
+  cellToFaceMatrix() const
+  {
+    return m_cell_to_face_matrix;
+  }
+
+  PUGS_INLINE
+  const ConnectivityMatrix&
+  cellToEdgeMatrix() const
+  {
+    return m_cell_to_edge_matrix;
+  }
+
+  PUGS_INLINE
+  const ConnectivityMatrix&
+  cellToNodeMatrix() const
+  {
+    return m_cell_to_node_matrix;
+  }
+
+  PUGS_INLINE
+  const ConnectivityMatrix&
+  faceToEdgeMatrix() const
+  {
+    return m_face_to_edge_matrix;
+  }
+
+  PUGS_INLINE
+  const ConnectivityMatrix&
+  faceToNodeMatrix() const
+  {
+    return m_face_to_node_matrix;
+  }
+
+  PUGS_INLINE
+  const ConnectivityMatrix&
+  edgeToNodeMatrix() const
+  {
+    return m_edge_to_node_matrix;
+  }
+
+  PUGS_INLINE
+  const ConnectivityMatrix&
+  nodeToFaceMatrix() const
+  {
+    return m_node_to_face_matrix;
+  }
+
+  PUGS_INLINE
+  const ConnectivityMatrix&
+  nodeToEdgeMatrix() const
+  {
+    return m_node_to_edge_matrix;
+  }
+
+  template <typename ItemOfItemT>
+  auto&
+  itemOfItemVector()
+  {
+    if constexpr (std::is_same_v<ItemOfItemT, NodeOfCell>) {
+      return m_cell_to_node_matrix;
+    } else if constexpr (std::is_same_v<ItemOfItemT, FaceOfCell>) {
+      return m_cell_to_face_matrix;
+    } else if constexpr (std::is_same_v<ItemOfItemT, EdgeOfCell>) {
+      return m_cell_to_edge_matrix;
+    } else if constexpr (std::is_same_v<ItemOfItemT, EdgeOfFace>) {
+      return m_face_to_edge_matrix;
+    } else if constexpr (std::is_same_v<ItemOfItemT, NodeOfFace>) {
+      return m_face_to_node_matrix;
+    } else if constexpr (std::is_same_v<ItemOfItemT, NodeOfEdge>) {
+      return m_edge_to_node_matrix;
+    } else {
+      static_assert(is_false_v<ItemOfItemT>, "Unexpected item of item type");
+    }
+  }
 
   template <ItemType item_type>
   const std::vector<RefItemList<item_type>>&
diff --git a/src/mesh/ConnectivityDispatcher.cpp b/src/mesh/ConnectivityDispatcher.cpp
index 552c4ab95..641d7f866 100644
--- a/src/mesh/ConnectivityDispatcher.cpp
+++ b/src/mesh/ConnectivityDispatcher.cpp
@@ -611,7 +611,11 @@ ConnectivityDispatcher<Dimension>::_dispatchEdges()
     this->_buildSubItemNumberToIdMap<EdgeOfCell>();
     this->_buildItemToExchangeLists<ItemType::edge>();
 
-    this->_gatherFrom(m_connectivity.template number<ItemType::edge>(), m_new_descriptor.edge_number_vector);
+    m_new_descriptor.setEdgeNumberVector([&] {
+      Array<int> edge_number_vector;
+      this->_gatherFrom(m_connectivity.template number<ItemType::edge>(), edge_number_vector);
+      return edge_number_vector;
+    }());
 
     this->_buildItemToSubItemDescriptor<EdgeOfCell>();
 
@@ -623,9 +627,17 @@ ConnectivityDispatcher<Dimension>::_dispatchEdges()
     this->_buildSubItemNumbersToRecvByProc<EdgeOfFace>();
     this->_buildItemToSubItemDescriptor<EdgeOfFace>();
 
-    this->_gatherFrom(m_connectivity.faceEdgeIsReversed(), m_new_descriptor.face_edge_is_reversed);
+    m_new_descriptor.setFaceEdgeIsReversed([&] {
+      Array<bool> face_edge_is_reversed;
+      this->_gatherFrom(m_connectivity.faceEdgeIsReversed(), face_edge_is_reversed);
+      return face_edge_is_reversed;
+    }());
 
-    this->_gatherFrom(this->_dispatchedInfo<ItemType::edge>().m_new_owner, m_new_descriptor.edge_owner_vector);
+    m_new_descriptor.setEdgeOwnerVector([&] {
+      Array<int> edge_owner_vector;
+      this->_gatherFrom(this->_dispatchedInfo<ItemType::edge>().m_new_owner, edge_owner_vector);
+      return edge_owner_vector;
+    }());
 
     this->_buildItemReferenceList<ItemType::edge>();
   }
@@ -645,13 +657,25 @@ ConnectivityDispatcher<Dimension>::_dispatchFaces()
     this->_buildSubItemNumbersToRecvByProc<NodeOfFace>();
     this->_buildItemToSubItemDescriptor<NodeOfFace>();
 
-    this->_gatherFrom(m_connectivity.template number<ItemType::face>(), m_new_descriptor.face_number_vector);
+    m_new_descriptor.setFaceNumberVector([&] {
+      Array<int> face_number_vector;
+      this->_gatherFrom(m_connectivity.template number<ItemType::face>(), face_number_vector);
+      return face_number_vector;
+    }());
 
     this->_buildItemToSubItemDescriptor<FaceOfCell>();
 
-    this->_gatherFrom(m_connectivity.cellFaceIsReversed(), m_new_descriptor.cell_face_is_reversed);
+    m_new_descriptor.setCellFaceIsReversed([&] {
+      Array<bool> cell_face_is_reversed;
+      this->_gatherFrom(m_connectivity.cellFaceIsReversed(), cell_face_is_reversed);
+      return cell_face_is_reversed;
+    }());
 
-    this->_gatherFrom(this->_dispatchedInfo<ItemType::face>().m_new_owner, m_new_descriptor.face_owner_vector);
+    m_new_descriptor.setFaceOwnerVector([&] {
+      Array<int> face_owner_vector;
+      this->_gatherFrom(this->_dispatchedInfo<ItemType::face>().m_new_owner, face_owner_vector);
+      return face_owner_vector;
+    }());
 
     this->_buildItemReferenceList<ItemType::face>();
   }
@@ -676,18 +700,39 @@ ConnectivityDispatcher<Dimension>::ConnectivityDispatcher(const ConnectivityType
 
   this->_buildSubItemNumbersToRecvByProc<NodeOfCell>();
 
-  this->_gatherFrom(m_connectivity.template number<ItemType::cell>(), m_new_descriptor.cell_number_vector);
+  m_new_descriptor.setCellNumberVector([&] {
+    Array<int> cell_number_vector;
+    this->_gatherFrom(m_connectivity.template number<ItemType::cell>(), cell_number_vector);
+    return cell_number_vector;
+  }());
 
   this->_buildSubItemNumberToIdMap<NodeOfCell>();
 
   this->_buildItemToExchangeLists<ItemType::node>();
 
-  // Fill new descriptor
-  this->_gatherFrom(m_connectivity.cellType(), m_new_descriptor.cell_type_vector);
-  this->_gatherFrom(this->_dispatchedInfo<ItemType::cell>().m_new_owner, m_new_descriptor.cell_owner_vector);
-
-  this->_gatherFrom(m_connectivity.template number<ItemType::node>(), m_new_descriptor.node_number_vector);
-  this->_gatherFrom(this->_dispatchedInfo<ItemType::node>().m_new_owner, m_new_descriptor.node_owner_vector);
+  m_new_descriptor.setCellTypeVector([&] {
+    Array<CellType> cell_type_vector;
+    this->_gatherFrom(m_connectivity.cellType(), cell_type_vector);
+    return cell_type_vector;
+  }());
+
+  m_new_descriptor.setCellOwnerVector([&] {
+    Array<int> cell_owner_vector;
+    this->_gatherFrom(this->_dispatchedInfo<ItemType::cell>().m_new_owner, cell_owner_vector);
+    return cell_owner_vector;
+  }());
+
+  m_new_descriptor.setNodeNumberVector([&] {
+    Array<int> node_number_vector;
+    this->_gatherFrom(m_connectivity.template number<ItemType::node>(), node_number_vector);
+    return node_number_vector;
+  }());
+
+  m_new_descriptor.setNodeOwnerVector([&] {
+    Array<int> node_owner_vector;
+    this->_gatherFrom(this->_dispatchedInfo<ItemType::node>().m_new_owner, node_owner_vector);
+    return node_owner_vector;
+  }());
 
   this->_buildItemToSubItemDescriptor<NodeOfCell>();
 
diff --git a/src/mesh/DiamondDualConnectivityBuilder.cpp b/src/mesh/DiamondDualConnectivityBuilder.cpp
index 831246a7e..792e97207 100644
--- a/src/mesh/DiamondDualConnectivityBuilder.cpp
+++ b/src/mesh/DiamondDualConnectivityBuilder.cpp
@@ -45,21 +45,21 @@ DiamondDualConnectivityBuilder::_buildDiamondConnectivityDescriptor(const Connec
     }
   }
 
-  diamond_descriptor.node_number_vector = Array<int>(diamond_number_of_nodes);
+  Array<int> node_number_vector(diamond_number_of_nodes);
 
   parallel_for(m_primal_node_to_dual_node_map.size(), [&](size_t i) {
     const auto [primal_node_id, diamond_dual_node_id] = m_primal_node_to_dual_node_map[i];
 
-    diamond_descriptor.node_number_vector[diamond_dual_node_id] = primal_node_number[primal_node_id];
+    node_number_vector[diamond_dual_node_id] = primal_node_number[primal_node_id];
   });
 
   const size_t cell_number_shift = max(primal_node_number) + 1;
   parallel_for(primal_number_of_cells, [&](size_t i) {
     const auto [primal_cell_id, diamond_dual_node_id] = m_primal_cell_to_dual_node_map[i];
 
-    diamond_descriptor.node_number_vector[diamond_dual_node_id] =
-      primal_cell_number[primal_cell_id] + cell_number_shift;
+    node_number_vector[diamond_dual_node_id] = primal_cell_number[primal_cell_id] + cell_number_shift;
   });
+  diamond_descriptor.setNodeNumberVector(node_number_vector);
 
   {
     m_primal_face_to_dual_cell_map = FaceIdToCellIdMap{primal_number_of_faces};
@@ -69,14 +69,17 @@ DiamondDualConnectivityBuilder::_buildDiamondConnectivityDescriptor(const Connec
     }
   }
 
-  diamond_descriptor.cell_number_vector = Array<int>(diamond_number_of_cells);
-  const auto& primal_face_number        = primal_connectivity.faceNumber();
-  parallel_for(diamond_number_of_cells, [&](size_t i) {
-    const auto [primal_face_id, dual_cell_id]           = m_primal_face_to_dual_cell_map[i];
-    diamond_descriptor.cell_number_vector[dual_cell_id] = primal_face_number[primal_face_id];
-  });
+  diamond_descriptor.setCellNumberVector([&] {
+    Array<int> cell_number_vector(diamond_number_of_cells);
+    const auto& primal_face_number = primal_connectivity.faceNumber();
+    parallel_for(diamond_number_of_cells, [&](size_t i) {
+      const auto [primal_face_id, dual_cell_id] = m_primal_face_to_dual_cell_map[i];
+      cell_number_vector[dual_cell_id]          = primal_face_number[primal_face_id];
+    });
+    return cell_number_vector;
+  }());
 
-  diamond_descriptor.cell_type_vector = Array<CellType>(diamond_number_of_cells);
+  Array<CellType> cell_type_vector(diamond_number_of_cells);
 
   const auto& primal_face_to_cell_matrix = primal_connectivity.faceToCellMatrix();
   const auto& primal_face_to_node_matrix = primal_connectivity.faceToNodeMatrix();
@@ -88,25 +91,27 @@ DiamondDualConnectivityBuilder::_buildDiamondConnectivityDescriptor(const Connec
 
     if constexpr (Dimension == 2) {
       if (primal_face_cell_list.size() == 1) {
-        diamond_descriptor.cell_type_vector[i_cell] = CellType::Triangle;
+        cell_type_vector[i_cell] = CellType::Triangle;
       } else {
         Assert(primal_face_cell_list.size() == 2);
-        diamond_descriptor.cell_type_vector[i_cell] = CellType::Quadrangle;
+        cell_type_vector[i_cell] = CellType::Quadrangle;
       }
     } else if constexpr (Dimension == 3) {
       if (primal_face_cell_list.size() == 1) {
         if (primal_face_to_node_matrix[face_id].size() == 3) {
-          diamond_descriptor.cell_type_vector[i_cell] = CellType::Tetrahedron;
+          cell_type_vector[i_cell] = CellType::Tetrahedron;
         } else {
-          diamond_descriptor.cell_type_vector[i_cell] = CellType::Pyramid;
+          cell_type_vector[i_cell] = CellType::Pyramid;
         }
       } else {
         Assert(primal_face_cell_list.size() == 2);
-        diamond_descriptor.cell_type_vector[i_cell] = CellType::Diamond;
+        cell_type_vector[i_cell] = CellType::Diamond;
       }
     }
   });
 
+  diamond_descriptor.setCellTypeVector(cell_type_vector);
+
   Array<const unsigned int> cell_to_node_row = [&] {
     Array<unsigned int> tmp_cell_to_node_row(primal_number_of_faces + 1);
     tmp_cell_to_node_row[0] = 0;
@@ -187,7 +192,7 @@ DiamondDualConnectivityBuilder::_buildDiamondConnectivityDescriptor(const Connec
     return tmp_cell_to_node_list;
   }();
 
-  diamond_descriptor.cell_to_node_matrix = ConnectivityMatrix(cell_to_node_row, cell_to_node_list);
+  diamond_descriptor.setCellToNodeMatrix(ConnectivityMatrix(cell_to_node_row, cell_to_node_list));
 }
 
 template <size_t Dimension>
@@ -208,11 +213,12 @@ DiamondDualConnectivityBuilder::_buildDiamondConnectivityFrom(const IConnectivit
     ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities<Dimension>(diamond_descriptor);
   }
 
+  const auto& node_number_vector = diamond_descriptor.nodeNumberVector();
   {
     const std::unordered_map<unsigned int, NodeId> node_to_id_map = [&] {
       std::unordered_map<unsigned int, NodeId> node_to_id_map;
-      for (size_t i_node = 0; i_node < diamond_descriptor.node_number_vector.size(); ++i_node) {
-        node_to_id_map[diamond_descriptor.node_number_vector[i_node]] = i_node;
+      for (size_t i_node = 0; i_node < node_number_vector.size(); ++i_node) {
+        node_to_id_map[node_number_vector[i_node]] = i_node;
       }
       return node_to_id_map;
     }();
@@ -248,19 +254,21 @@ DiamondDualConnectivityBuilder::_buildDiamondConnectivityFrom(const IConnectivit
   }
 
   {
-    const auto& primal_face_to_node_matrix = primal_connectivity.faceToNodeMatrix();
+    const auto& primal_face_to_node_matrix  = primal_connectivity.faceToNodeMatrix();
+    const auto& diamond_node_to_face_matrix = diamond_descriptor.nodeToFaceMatrix();
+    const auto& diamond_face_to_node_matrix = diamond_descriptor.faceToNodeMatrix();
 
     const auto find_face = [&](std::vector<uint32_t> node_list) -> std::optional<FaceId> {
       // The node list of already sorted correctly
-      const auto& face_id_vector = diamond_descriptor.node_to_face_matrix[node_list[0]];
+      const auto& face_id_vector = diamond_node_to_face_matrix[node_list[0]];
 
       for (size_t i_face = 0; i_face < face_id_vector.size(); ++i_face) {
         const FaceId face_id          = face_id_vector[i_face];
-        const auto& face_node_id_list = diamond_descriptor.face_to_node_matrix[face_id];
+        const auto& face_node_id_list = diamond_face_to_node_matrix[face_id];
         if (face_node_id_list.size() == node_list.size()) {
           bool is_same = true;
           for (size_t i_node = 1; i_node < face_node_id_list.size(); ++i_node) {
-            is_same &= (diamond_descriptor.face_to_node_matrix[face_id][i_node] == node_list[i_node]);
+            is_same &= (face_node_id_list[i_node] == node_list[i_node]);
           }
           if (is_same) {
             return face_id;
@@ -314,14 +322,13 @@ DiamondDualConnectivityBuilder::_buildDiamondConnectivityFrom(const IConnectivit
     const auto& primal_edge_to_node_matrix = primal_connectivity.edgeToNodeMatrix();
 
     {
-      const size_t number_of_edges          = diamond_descriptor.edge_to_node_matrix.numberOfRows();
-      diamond_descriptor.edge_number_vector = [&] {
+      const size_t number_of_edges = diamond_descriptor.edgeToNodeMatrix().numberOfRows();
+      diamond_descriptor.setEdgeNumberVector([&] {
         Array<int> edge_number_vector(number_of_edges);
-        for (size_t i_edge = 0; i_edge < number_of_edges; ++i_edge) {
-          edge_number_vector[i_edge] = i_edge;
-        }
+        parallel_for(
+          number_of_edges, PUGS_LAMBDA(size_t i_edge) { edge_number_vector[i_edge] = i_edge; });
         return edge_number_vector;
-      }();
+      }());
 
       // LCOV_EXCL_START
       if (parallel::size() > 1) {
@@ -329,16 +336,18 @@ DiamondDualConnectivityBuilder::_buildDiamondConnectivityFrom(const IConnectivit
       }
       // LCOV_EXCL_STOP
     }
+    const auto& diamond_node_to_edge_matrix = diamond_descriptor.nodeToEdgeMatrix();
+    const auto& diamond_edge_to_node_matrix = diamond_descriptor.edgeToNodeMatrix();
 
     const auto find_edge = [&](uint32_t node0, uint32_t node1) -> std::optional<EdgeId> {
-      if (diamond_descriptor.node_number_vector[node0] > diamond_descriptor.node_number_vector[node1]) {
+      if (node_number_vector[node0] > node_number_vector[node1]) {
         std::swap(node0, node1);
       }
-      const auto& edge_id_vector = diamond_descriptor.node_to_edge_matrix[node0];
+      const auto& edge_id_vector = diamond_node_to_edge_matrix[node0];
 
       for (size_t i_edge = 0; i_edge < edge_id_vector.size(); ++i_edge) {
         const EdgeId edge_id = edge_id_vector[i_edge];
-        if (diamond_descriptor.edge_to_node_matrix[edge_id][1] == node1) {
+        if (diamond_edge_to_node_matrix[edge_id][1] == node1) {
           return edge_id;
         }
       }
@@ -382,53 +391,64 @@ DiamondDualConnectivityBuilder::_buildDiamondConnectivityFrom(const IConnectivit
   const size_t primal_number_of_nodes = primal_connectivity.numberOfNodes();
   const size_t primal_number_of_cells = primal_connectivity.numberOfCells();
 
-  diamond_descriptor.node_owner_vector = Array<int>(diamond_descriptor.node_number_vector.size());
-  {
+  diamond_descriptor.setNodeOwnerVector([&] {
+    Array<int> node_owner_vector(node_number_vector.size());
     const auto& primal_node_owner = primal_connectivity.nodeOwner();
     for (NodeId primal_node_id = 0; primal_node_id < primal_connectivity.numberOfNodes(); ++primal_node_id) {
-      diamond_descriptor.node_owner_vector[primal_node_id] = primal_node_owner[primal_node_id];
+      node_owner_vector[primal_node_id] = primal_node_owner[primal_node_id];
     }
     const auto& primal_cell_owner = primal_connectivity.cellOwner();
     for (CellId primal_cell_id = 0; primal_cell_id < primal_number_of_cells; ++primal_cell_id) {
-      diamond_descriptor.node_owner_vector[primal_number_of_nodes + primal_cell_id] = primal_cell_owner[primal_cell_id];
-    }
-  }
-
-  {
-    diamond_descriptor.cell_owner_vector = Array<int>(diamond_descriptor.cell_number_vector.size());
-    const size_t primal_number_of_faces  = primal_connectivity.numberOfFaces();
-    const auto& primal_face_owner        = primal_connectivity.faceOwner();
-    for (FaceId primal_face_id = 0; primal_face_id < primal_number_of_faces; ++primal_face_id) {
-      diamond_descriptor.cell_owner_vector[primal_face_id] = primal_face_owner[primal_face_id];
+      node_owner_vector[primal_number_of_nodes + primal_cell_id] = primal_cell_owner[primal_cell_id];
     }
-  }
-
-  {
-    diamond_descriptor.face_owner_vector = Array<int>(diamond_descriptor.face_number_vector.size());
-    diamond_descriptor.face_owner_vector.fill(parallel::size());
-
-    for (size_t i_cell = 0; i_cell < diamond_descriptor.cell_to_face_matrix.numberOfRows(); ++i_cell) {
-      const auto& cell_face_list = diamond_descriptor.cell_to_face_matrix[i_cell];
+    return node_owner_vector;
+  }());
+
+  diamond_descriptor.setCellOwnerVector([&] {
+    Array<int> cell_owner_vector(diamond_descriptor.cellNumberVector().size());
+    const size_t primal_number_of_faces = primal_connectivity.numberOfFaces();
+    const auto& primal_face_owner       = primal_connectivity.faceOwner();
+    parallel_for(
+      primal_number_of_faces, PUGS_LAMBDA(const FaceId primal_face_id) {
+        cell_owner_vector[primal_face_id] = primal_face_owner[primal_face_id];
+      });
+    return cell_owner_vector;
+  }());
+
+  const auto& diamond_cell_owner_vector   = diamond_descriptor.cellOwnerVector();
+  const auto& diamond_cell_to_face_matrix = diamond_descriptor.cellToFaceMatrix();
+
+  diamond_descriptor.setFaceOwnerVector([&] {
+    Array<int> face_owner_vector(diamond_descriptor.faceNumberVector().size());
+    face_owner_vector.fill(parallel::rank());
+
+    for (size_t i_cell = 0; i_cell < diamond_cell_to_face_matrix.numberOfRows(); ++i_cell) {
+      const auto& cell_face_list = diamond_cell_to_face_matrix[i_cell];
       for (size_t i_face = 0; i_face < cell_face_list.size(); ++i_face) {
-        const size_t face_id = cell_face_list[i_face];
-        diamond_descriptor.face_owner_vector[face_id] =
-          std::min(diamond_descriptor.face_owner_vector[face_id], diamond_descriptor.cell_owner_vector[i_cell]);
+        const size_t face_id       = cell_face_list[i_face];
+        face_owner_vector[face_id] = std::min(face_owner_vector[face_id], diamond_cell_owner_vector[i_cell]);
       }
     }
-  }
+    return face_owner_vector;
+  }());
 
   if constexpr (Dimension == 3) {
-    diamond_descriptor.edge_owner_vector = Array<int>(diamond_descriptor.edge_number_vector.size());
-    diamond_descriptor.edge_owner_vector.fill(parallel::size());
-
-    for (size_t i_cell = 0; i_cell < diamond_descriptor.cell_to_face_matrix.numberOfRows(); ++i_cell) {
-      const auto& cell_edge_list = diamond_descriptor.cell_to_edge_matrix[i_cell];
-      for (size_t i_edge = 0; i_edge < cell_edge_list.size(); ++i_edge) {
-        const size_t edge_id = cell_edge_list[i_edge];
-        diamond_descriptor.edge_owner_vector[edge_id] =
-          std::min(diamond_descriptor.edge_owner_vector[edge_id], diamond_descriptor.cell_owner_vector[i_cell]);
+    const auto& diamond_cell_to_edge_matrix = diamond_descriptor.cellToEdgeMatrix();
+
+    diamond_descriptor.setEdgeOwnerVector([&] {
+      Array<int> edge_owner_vector(diamond_descriptor.edgeNumberVector().size());
+      edge_owner_vector.fill(parallel::rank());
+
+      for (size_t i_cell = 0; i_cell < diamond_cell_to_edge_matrix.numberOfRows(); ++i_cell) {
+        const auto& cell_edge_list = diamond_cell_to_edge_matrix[i_cell];
+        for (size_t i_edge = 0; i_edge < cell_edge_list.size(); ++i_edge) {
+          const size_t edge_id       = cell_edge_list[i_edge];
+          edge_owner_vector[edge_id] = std::min(edge_owner_vector[edge_id], diamond_cell_owner_vector[i_cell]);
+        }
       }
-    }
+
+      return edge_owner_vector;
+    }());
   }
 
   m_connectivity = ConnectivityType::build(diamond_descriptor);
diff --git a/src/mesh/Dual1DConnectivityBuilder.cpp b/src/mesh/Dual1DConnectivityBuilder.cpp
index d5ca12372..52f3ddc97 100644
--- a/src/mesh/Dual1DConnectivityBuilder.cpp
+++ b/src/mesh/Dual1DConnectivityBuilder.cpp
@@ -28,14 +28,14 @@ Dual1DConnectivityBuilder::_buildConnectivityDescriptor(const Connectivity<1>& p
   const auto& primal_node_to_cell_matrix = primal_connectivity.nodeToCellMatrix();
   size_t next_kept_node_id               = 0;
 
-  dual_descriptor.node_number_vector = Array<int>(dual_number_of_nodes);
+  Array<int> node_number_vector(dual_number_of_nodes);
 
   const auto& primal_node_number = primal_connectivity.nodeNumber();
 
   for (NodeId primal_node_id = 0; primal_node_id < primal_connectivity.numberOfNodes(); ++primal_node_id) {
     const auto& primal_node_cell_list = primal_node_to_cell_matrix[primal_node_id];
     if (primal_node_cell_list.size() == 1) {
-      dual_descriptor.node_number_vector[next_kept_node_id++] = primal_node_number[primal_node_id];
+      node_number_vector[next_kept_node_id++] = primal_node_number[primal_node_id];
     }
   }
 
@@ -46,19 +46,25 @@ Dual1DConnectivityBuilder::_buildConnectivityDescriptor(const Connectivity<1>& p
   const size_t cell_number_shift = max(primal_node_number) + 1;
 
   for (CellId primal_cell_id = 0; primal_cell_id < primal_number_of_cells; ++primal_cell_id) {
-    dual_descriptor.node_number_vector[primal_number_of_kept_nodes + primal_cell_id] =
+    node_number_vector[primal_number_of_kept_nodes + primal_cell_id] =
       primal_cell_number[primal_cell_id] + cell_number_shift;
   }
+  dual_descriptor.setNodeNumberVector(node_number_vector);
 
   Assert(number_of_kept_nodes == next_kept_node_id, "unexpected number of kept nodes");
 
-  dual_descriptor.cell_number_vector = Array<int>(dual_number_of_cells);
-  for (NodeId primal_node_id = 0; primal_node_id < primal_number_of_nodes; ++primal_node_id) {
-    dual_descriptor.cell_number_vector[primal_node_id] = primal_node_number[primal_node_id];
-  }
+  dual_descriptor.setCellNumberVector([&] {
+    Array<int> cell_number_vector(dual_number_of_cells);
+    parallel_for(
+      primal_number_of_nodes, PUGS_LAMBDA(const NodeId primal_node_id) {
+        cell_number_vector[primal_node_id] = primal_node_number[primal_node_id];
+      });
+    return cell_number_vector;
+  }());
 
-  dual_descriptor.cell_type_vector = Array<CellType>(dual_number_of_cells);
-  dual_descriptor.cell_type_vector.fill(CellType::Line);
+  Array<CellType> cell_type_vector(dual_number_of_cells);
+  cell_type_vector.fill(CellType::Line);
+  dual_descriptor.setCellTypeVector(cell_type_vector);
 
   const auto& primal_node_local_number_in_their_cells = primal_connectivity.nodeLocalNumbersInTheirCells();
 
@@ -89,7 +95,7 @@ Dual1DConnectivityBuilder::_buildConnectivityDescriptor(const Connectivity<1>& p
     }
   }
 
-  dual_descriptor.cell_to_node_matrix = ConnectivityMatrix(cell_to_node_row, cell_to_node_list);
+  dual_descriptor.setCellToNodeMatrix(ConnectivityMatrix(cell_to_node_row, cell_to_node_list));
 }
 
 void
@@ -104,10 +110,12 @@ Dual1DConnectivityBuilder::_buildConnectivityFrom(const IConnectivity& i_primal_
   this->_buildConnectivityDescriptor(primal_connectivity, dual_descriptor);
 
   {
+    const auto& dual_node_number_vector = dual_descriptor.nodeNumberVector();
+
     const std::unordered_map<unsigned int, NodeId> node_to_id_map = [&] {
       std::unordered_map<unsigned int, NodeId> node_to_id_map;
-      for (size_t i_node = 0; i_node < dual_descriptor.node_number_vector.size(); ++i_node) {
-        node_to_id_map[dual_descriptor.node_number_vector[i_node]] = i_node;
+      for (size_t i_node = 0; i_node < dual_node_number_vector.size(); ++i_node) {
+        node_to_id_map[dual_node_number_vector[i_node]] = i_node;
       }
       return node_to_id_map;
     }();
@@ -145,31 +153,33 @@ Dual1DConnectivityBuilder::_buildConnectivityFrom(const IConnectivity& i_primal_
   const size_t primal_number_of_nodes = primal_connectivity.numberOfNodes();
   const size_t primal_number_of_cells = primal_connectivity.numberOfCells();
 
-  dual_descriptor.node_owner_vector = Array<int>(dual_descriptor.node_number_vector.size());
-
-  {
+  dual_descriptor.setNodeOwnerVector([&] {
+    Array<int> node_owner_vector(dual_descriptor.nodeNumberVector().size());
     const auto& node_to_cell_matrix = primal_connectivity.nodeToCellMatrix();
     const auto& primal_node_owner   = primal_connectivity.nodeOwner();
     size_t next_kept_node_id        = 0;
     for (NodeId primal_node_id = 0; primal_node_id < primal_connectivity.numberOfNodes(); ++primal_node_id) {
       if (node_to_cell_matrix[primal_node_id].size() == 1) {
-        dual_descriptor.node_owner_vector[next_kept_node_id++] = primal_node_owner[primal_node_id];
+        node_owner_vector[next_kept_node_id++] = primal_node_owner[primal_node_id];
       }
     }
     const size_t number_of_kept_nodes = next_kept_node_id;
     const auto& primal_cell_owner     = primal_connectivity.cellOwner();
     for (CellId primal_cell_id = 0; primal_cell_id < primal_number_of_cells; ++primal_cell_id) {
-      dual_descriptor.node_owner_vector[number_of_kept_nodes + primal_cell_id] = primal_cell_owner[primal_cell_id];
+      node_owner_vector[number_of_kept_nodes + primal_cell_id] = primal_cell_owner[primal_cell_id];
     }
-  }
 
-  {
-    dual_descriptor.cell_owner_vector = Array<int>(dual_descriptor.cell_number_vector.size());
-    const auto& primal_node_owner     = primal_connectivity.nodeOwner();
-    for (NodeId primal_node_id = 0; primal_node_id < primal_number_of_nodes; ++primal_node_id) {
-      dual_descriptor.cell_owner_vector[primal_node_id] = primal_node_owner[primal_node_id];
-    }
-  }
+    return node_owner_vector;
+  }());
+
+  dual_descriptor.setCellOwnerVector([&] {
+    Array<int> cell_owner_vector(dual_descriptor.cellNumberVector().size());
+    const auto& primal_node_owner = primal_connectivity.nodeOwner();
+    parallel_for(
+      primal_number_of_nodes,
+      PUGS_LAMBDA(NodeId primal_node_id) { cell_owner_vector[primal_node_id] = primal_node_owner[primal_node_id]; });
+    return cell_owner_vector;
+  }());
 
   m_connectivity = ConnectivityType::build(dual_descriptor);
 
diff --git a/src/mesh/GmshReader.cpp b/src/mesh/GmshReader.cpp
index 95bb289d3..e4ae59ea7 100644
--- a/src/mesh/GmshReader.cpp
+++ b/src/mesh/GmshReader.cpp
@@ -35,9 +35,9 @@ GmshConnectivityBuilder<1>::GmshConnectivityBuilder(const GmshReader::GmshData&
 {
   ConnectivityDescriptor descriptor;
 
-  descriptor.node_number_vector = convert_to_array(gmsh_data.__verticesNumbers);
-  descriptor.cell_type_vector   = Array<CellType>(nb_cells);
-  descriptor.cell_number_vector = Array<int>(nb_cells);
+  descriptor.setNodeNumberVector(convert_to_array(gmsh_data.__verticesNumbers));
+  Array<CellType> cell_type_vector(nb_cells);
+  Array<int> cell_number_vector(nb_cells);
 
   Array<unsigned int> cell_to_node_row(nb_cells + 1);
   parallel_for(
@@ -49,13 +49,15 @@ GmshConnectivityBuilder<1>::GmshConnectivityBuilder(const GmshReader::GmshData&
       cell_to_node_list[2 * cell_id + i_node] = gmsh_data.__edges[cell_id][i_node];
     }
   }
-  descriptor.cell_to_node_matrix = ConnectivityMatrix(cell_to_node_row, cell_to_node_list);
+  descriptor.setCellToNodeMatrix(ConnectivityMatrix(cell_to_node_row, cell_to_node_list));
 
-  descriptor.cell_type_vector.fill(CellType::Line);
+  cell_type_vector.fill(CellType::Line);
+  descriptor.setCellTypeVector(cell_type_vector);
 
   for (size_t j = 0; j < nb_cells; ++j) {
-    descriptor.cell_number_vector[j] = gmsh_data.__edges_number[j];
+    cell_number_vector[j] = gmsh_data.__edges_number[j];
   }
+  descriptor.setCellNumberVector(cell_number_vector);
 
   std::map<unsigned int, std::vector<unsigned int>> ref_points_map;
   for (unsigned int r = 0; r < gmsh_data.__points.size(); ++r) {
@@ -64,12 +66,14 @@ GmshConnectivityBuilder<1>::GmshConnectivityBuilder(const GmshReader::GmshData&
     ref_points_map[ref].push_back(point_number);
   }
 
-  Array<size_t> node_nb_cell(descriptor.node_number_vector.size());
+  Array<size_t> node_nb_cell(descriptor.nodeNumberVector().size());
   node_nb_cell.fill(0);
 
+  const auto& cell_to_node_matrix = descriptor.cellToNodeMatrix();
   for (size_t j = 0; j < nb_cells; ++j) {
+    const auto& cell_node_list = cell_to_node_matrix[j];
     for (int r = 0; r < 2; ++r) {
-      node_nb_cell[descriptor.cell_to_node_matrix[j][r]] += 1;
+      node_nb_cell[cell_node_list[r]] += 1;
     }
   }
 
@@ -124,12 +128,18 @@ GmshConnectivityBuilder<1>::GmshConnectivityBuilder(const GmshReader::GmshData&
     descriptor.addRefItemList(RefCellList(ref_id, cell_list, false));
   }
 
-  descriptor.cell_owner_vector = Array<int>(nb_cells);
-  descriptor.cell_owner_vector.fill(parallel::rank());
-
-  descriptor.node_owner_vector = Array<int>(descriptor.node_number_vector.size());
-  descriptor.node_owner_vector.fill(parallel::rank());
-
+  descriptor.setCellOwnerVector([&] {
+    Array<int> cell_owner_vector(nb_cells);
+    cell_owner_vector.fill(parallel::rank());
+    return cell_owner_vector;
+  }());
+
+  descriptor.setNodeOwnerVector([&] {
+    Array<int> node_owner_vector(descriptor.nodeNumberVector().size());
+    node_owner_vector.fill(parallel::rank());
+    return node_owner_vector;
+  }());
+  ;
   m_connectivity = Connectivity1D::build(descriptor);
 }
 
@@ -138,9 +148,9 @@ GmshConnectivityBuilder<2>::GmshConnectivityBuilder(const GmshReader::GmshData&
 {
   ConnectivityDescriptor descriptor;
 
-  descriptor.node_number_vector = convert_to_array(gmsh_data.__verticesNumbers);
-  descriptor.cell_type_vector   = Array<CellType>(nb_cells);
-  descriptor.cell_number_vector = Array<int>(nb_cells);
+  descriptor.setNodeNumberVector(convert_to_array(gmsh_data.__verticesNumbers));
+  Array<CellType> cell_type_vector(nb_cells);
+  Array<int> cell_number_vector(nb_cells);
 
   Array<unsigned int> cell_to_node_row(gmsh_data.__triangles.size() + gmsh_data.__quadrangles.size() + 1);
   {
@@ -169,22 +179,25 @@ GmshConnectivityBuilder<2>::GmshConnectivityBuilder(const GmshReader::GmshData&
       cell_to_node_list[i_cell_node++] = gmsh_data.__quadrangles[i_quadrangle][3];
     }
   }
-  descriptor.cell_to_node_matrix = ConnectivityMatrix(cell_to_node_row, cell_to_node_list);
+  descriptor.setCellToNodeMatrix(ConnectivityMatrix(cell_to_node_row, cell_to_node_list));
 
   const size_t nb_triangles = gmsh_data.__triangles.size();
   for (size_t i_triangle = 0; i_triangle < nb_triangles; ++i_triangle) {
-    descriptor.cell_type_vector[i_triangle]   = CellType::Triangle;
-    descriptor.cell_number_vector[i_triangle] = gmsh_data.__triangles_number[i_triangle];
+    cell_type_vector[i_triangle]   = CellType::Triangle;
+    cell_number_vector[i_triangle] = gmsh_data.__triangles_number[i_triangle];
   }
 
   const size_t nb_quadrangles = gmsh_data.__quadrangles.size();
   for (size_t i_quadrangle = 0; i_quadrangle < nb_quadrangles; ++i_quadrangle) {
     const size_t i_cell = i_quadrangle + nb_triangles;
 
-    descriptor.cell_type_vector[i_cell]   = CellType::Quadrangle;
-    descriptor.cell_number_vector[i_cell] = gmsh_data.__quadrangles_number[i_quadrangle];
+    cell_type_vector[i_cell]   = CellType::Quadrangle;
+    cell_number_vector[i_cell] = gmsh_data.__quadrangles_number[i_quadrangle];
   }
 
+  descriptor.setCellNumberVector(cell_number_vector);
+  descriptor.setCellTypeVector(cell_type_vector);
+
   std::map<unsigned int, std::vector<unsigned int>> ref_cells_map;
   for (unsigned int j = 0; j < gmsh_data.__triangles_ref.size(); ++j) {
     const unsigned int elem_number = j;
@@ -219,23 +232,28 @@ GmshConnectivityBuilder<2>::GmshConnectivityBuilder(const GmshReader::GmshData&
   ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities<2>(descriptor);
 
   std::unordered_map<int, FaceId> face_number_id_map = [&] {
+    const auto& face_number_vector = descriptor.faceNumberVector();
     std::unordered_map<int, FaceId> face_number_id_map;
-    for (size_t l = 0; l < descriptor.face_number_vector.size(); ++l) {
-      face_number_id_map[descriptor.face_number_vector[l]] = l;
+    for (size_t l = 0; l < face_number_vector.size(); ++l) {
+      face_number_id_map[face_number_vector[l]] = l;
     }
-    Assert(face_number_id_map.size() == descriptor.face_number_vector.size());
+    Assert(face_number_id_map.size() == face_number_vector.size());
     return face_number_id_map;
   }();
 
+  const auto& node_number_vector  = descriptor.nodeNumberVector();
+  const auto& node_to_face_matrix = descriptor.nodeToFaceMatrix();
+  const auto& face_to_node_matrix = descriptor.faceToNodeMatrix();
+
   const auto find_face = [&](uint32_t node0, uint32_t node1) {
-    if (descriptor.node_number_vector[node0] > descriptor.node_number_vector[node1]) {
+    if (node_number_vector[node0] > node_number_vector[node1]) {
       std::swap(node0, node1);
     }
-    const auto& face_id_vector = descriptor.node_to_face_matrix[node0];
+    const auto& face_id_vector = node_to_face_matrix[node0];
 
     for (size_t i_face = 0; i_face < face_id_vector.size(); ++i_face) {
       const FaceId face_id = face_id_vector[i_face];
-      if (descriptor.face_to_node_matrix[face_id][1] == node1) {
+      if (face_to_node_matrix[face_id][1] == node1) {
         return face_id;
       }
     }
@@ -245,6 +263,7 @@ GmshConnectivityBuilder<2>::GmshConnectivityBuilder(const GmshReader::GmshData&
     throw NormalError(error_msg.str());
   };
 
+  Array<int> face_number_vector = copy(descriptor.faceNumberVector());
   std::map<unsigned int, std::vector<unsigned int>> ref_faces_map;
   for (unsigned int e = 0; e < gmsh_data.__edges.size(); ++e) {
     const unsigned int edge_id = find_face(gmsh_data.__edges[e][0], gmsh_data.__edges[e][1]);
@@ -252,30 +271,33 @@ GmshConnectivityBuilder<2>::GmshConnectivityBuilder(const GmshReader::GmshData&
     const unsigned int& ref = gmsh_data.__edges_ref[e];
     ref_faces_map[ref].push_back(edge_id);
 
-    if (descriptor.face_number_vector[edge_id] != gmsh_data.__edges_number[e]) {
+    if (face_number_vector[edge_id] != gmsh_data.__edges_number[e]) {
       if (auto i_face = face_number_id_map.find(gmsh_data.__edges_number[e]); i_face != face_number_id_map.end()) {
         const int other_edge_id = i_face->second;
-        std::swap(descriptor.face_number_vector[edge_id], descriptor.face_number_vector[other_edge_id]);
+        std::swap(face_number_vector[edge_id], face_number_vector[other_edge_id]);
 
-        face_number_id_map.erase(descriptor.face_number_vector[edge_id]);
-        face_number_id_map.erase(descriptor.face_number_vector[other_edge_id]);
+        face_number_id_map.erase(face_number_vector[edge_id]);
+        face_number_id_map.erase(face_number_vector[other_edge_id]);
 
-        face_number_id_map[descriptor.face_number_vector[edge_id]]       = edge_id;
-        face_number_id_map[descriptor.face_number_vector[other_edge_id]] = other_edge_id;
+        face_number_id_map[face_number_vector[edge_id]]       = edge_id;
+        face_number_id_map[face_number_vector[other_edge_id]] = other_edge_id;
       } else {
-        face_number_id_map.erase(descriptor.face_number_vector[edge_id]);
-        descriptor.face_number_vector[edge_id]                     = gmsh_data.__edges_number[e];
-        face_number_id_map[descriptor.face_number_vector[edge_id]] = edge_id;
+        face_number_id_map.erase(face_number_vector[edge_id]);
+        face_number_vector[edge_id]                     = gmsh_data.__edges_number[e];
+        face_number_id_map[face_number_vector[edge_id]] = edge_id;
       }
     }
   }
+  descriptor.setFaceNumberVector(face_number_vector);
 
-  Array<size_t> face_nb_cell(descriptor.face_number_vector.size());
+  Array<size_t> face_nb_cell(descriptor.faceNumberVector().size());
   face_nb_cell.fill(0);
 
-  for (size_t j = 0; j < descriptor.cell_to_face_matrix.numberOfRows(); ++j) {
-    for (size_t l = 0; l < descriptor.cell_to_face_matrix[j].size(); ++l) {
-      face_nb_cell[descriptor.cell_to_face_matrix[j][l]] += 1;
+  const auto& cell_to_face_matrix = descriptor.cellToFaceMatrix();
+  for (size_t j = 0; j < cell_to_face_matrix.numberOfRows(); ++j) {
+    const auto& cell_face_list = cell_to_face_matrix[j];
+    for (size_t l = 0; l < cell_face_list.size(); ++l) {
+      face_nb_cell[cell_face_list[l]] += 1;
     }
   }
 
@@ -305,13 +327,14 @@ GmshConnectivityBuilder<2>::GmshConnectivityBuilder(const GmshReader::GmshData&
     descriptor.addRefItemList(RefFaceList{ref_id, face_list, is_boundary});
   }
 
-  Array<bool> is_boundary_node(descriptor.node_number_vector.size());
+  Array<bool> is_boundary_node(node_number_vector.size());
   is_boundary_node.fill(false);
 
   for (size_t i_face = 0; i_face < face_nb_cell.size(); ++i_face) {
     if (face_nb_cell[i_face] == 1) {
-      for (size_t i_node = 0; i_node < descriptor.face_to_node_matrix[i_face].size(); ++i_node) {
-        is_boundary_node[descriptor.face_to_node_matrix[i_face][i_node]] = true;
+      const auto& face_node_list = face_to_node_matrix[i_face];
+      for (size_t i_node = 0; i_node < face_node_list.size(); ++i_node) {
+        is_boundary_node[face_node_list[i_node]] = true;
       }
     }
   }
@@ -348,14 +371,23 @@ GmshConnectivityBuilder<2>::GmshConnectivityBuilder(const GmshReader::GmshData&
     descriptor.addRefItemList(RefNodeList(ref_id, point_list, is_boundary));
   }
 
-  descriptor.cell_owner_vector = Array<int>(nb_cells);
-  descriptor.cell_owner_vector.fill(parallel::rank());
+  descriptor.setCellOwnerVector([&] {
+    Array<int> cell_owner_vector(nb_cells);
+    cell_owner_vector.fill(parallel::rank());
+    return cell_owner_vector;
+  }());
 
-  descriptor.face_owner_vector = Array<int>(descriptor.face_number_vector.size());
-  descriptor.face_owner_vector.fill(parallel::rank());
+  descriptor.setFaceOwnerVector([&] {
+    Array<int> face_owner_vector(descriptor.faceNumberVector().size());
+    face_owner_vector.fill(parallel::rank());
+    return face_owner_vector;
+  }());
 
-  descriptor.node_owner_vector = Array<int>(descriptor.node_number_vector.size());
-  descriptor.node_owner_vector.fill(parallel::rank());
+  descriptor.setNodeOwnerVector([&] {
+    Array<int> node_owner_vector(node_number_vector.size());
+    node_owner_vector.fill(parallel::rank());
+    return node_owner_vector;
+  }());
 
   m_connectivity = Connectivity2D::build(descriptor);
 }
@@ -365,9 +397,9 @@ GmshConnectivityBuilder<3>::GmshConnectivityBuilder(const GmshReader::GmshData&
 {
   ConnectivityDescriptor descriptor;
 
-  descriptor.node_number_vector = convert_to_array(gmsh_data.__verticesNumbers);
-  descriptor.cell_type_vector   = Array<CellType>(nb_cells);
-  descriptor.cell_number_vector = Array<int>(nb_cells);
+  descriptor.setNodeNumberVector(convert_to_array(gmsh_data.__verticesNumbers));
+  Array<CellType> cell_type_vector(nb_cells);
+  Array<int> cell_number_vector(nb_cells);
 
   const size_t nb_tetrahedra = gmsh_data.__tetrahedra.size();
   const size_t nb_hexahedra  = gmsh_data.__hexahedra.size();
@@ -429,32 +461,34 @@ GmshConnectivityBuilder<3>::GmshConnectivityBuilder(const GmshReader::GmshData&
   }
 
   for (size_t j = 0; j < nb_tetrahedra; ++j) {
-    descriptor.cell_type_vector[j]   = CellType::Tetrahedron;
-    descriptor.cell_number_vector[j] = gmsh_data.__tetrahedra_number[j];
+    cell_type_vector[j]   = CellType::Tetrahedron;
+    cell_number_vector[j] = gmsh_data.__tetrahedra_number[j];
   }
 
   for (size_t j = 0; j < nb_hexahedra; ++j) {
     const size_t jh = nb_tetrahedra + j;
 
-    descriptor.cell_type_vector[jh]   = CellType::Hexahedron;
-    descriptor.cell_number_vector[jh] = gmsh_data.__hexahedra_number[j];
+    cell_type_vector[jh]   = CellType::Hexahedron;
+    cell_number_vector[jh] = gmsh_data.__hexahedra_number[j];
   }
 
   for (size_t j = 0; j < nb_prisms; ++j) {
     const size_t jp = nb_tetrahedra + nb_hexahedra + j;
 
-    descriptor.cell_type_vector[jp]   = CellType::Prism;
-    descriptor.cell_number_vector[jp] = gmsh_data.__prisms_number[j];
+    cell_type_vector[jp]   = CellType::Prism;
+    cell_number_vector[jp] = gmsh_data.__prisms_number[j];
   }
 
   for (size_t j = 0; j < nb_pyramids; ++j) {
     const size_t jh = nb_tetrahedra + nb_hexahedra + nb_prisms + j;
 
-    descriptor.cell_type_vector[jh]   = CellType::Pyramid;
-    descriptor.cell_number_vector[jh] = gmsh_data.__pyramids_number[j];
+    cell_type_vector[jh]   = CellType::Pyramid;
+    cell_number_vector[jh] = gmsh_data.__pyramids_number[j];
   }
 
-  descriptor.cell_to_node_matrix = ConnectivityMatrix(cell_to_node_row, cell_to_node_list);
+  descriptor.setCellNumberVector(cell_number_vector);
+  descriptor.setCellTypeVector(cell_type_vector);
+  descriptor.setCellToNodeMatrix(ConnectivityMatrix(cell_to_node_row, cell_to_node_list));
 
   std::map<unsigned int, std::vector<unsigned int>> ref_cells_map;
   for (unsigned int j = 0; j < gmsh_data.__tetrahedra_ref.size(); ++j) {
@@ -501,27 +535,34 @@ GmshConnectivityBuilder<3>::GmshConnectivityBuilder(const GmshReader::GmshData&
 
   ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities<3>(descriptor);
 
-  const auto& node_number_vector = descriptor.node_number_vector;
+  const auto& node_number_vector = descriptor.nodeNumberVector();
 
-  Array<size_t> face_nb_cell(descriptor.face_number_vector.size());
+  Array<size_t> face_nb_cell(descriptor.faceNumberVector().size());
   face_nb_cell.fill(0);
 
-  for (size_t j = 0; j < descriptor.cell_to_face_matrix.numberOfRows(); ++j) {
-    for (size_t l = 0; l < descriptor.cell_to_face_matrix[j].size(); ++l) {
-      face_nb_cell[descriptor.cell_to_face_matrix[j][l]] += 1;
+  const auto& cell_to_face_matrix = descriptor.cellToFaceMatrix();
+
+  for (size_t j = 0; j < cell_to_face_matrix.numberOfRows(); ++j) {
+    const auto& cell_face_list = cell_to_face_matrix[j];
+    for (size_t l = 0; l < cell_face_list.size(); ++l) {
+      face_nb_cell[cell_face_list[l]] += 1;
     }
   }
 
+  const auto& face_number_vector = descriptor.faceNumberVector();
   {
     std::unordered_map<int, FaceId> face_number_id_map = [&] {
       std::unordered_map<int, FaceId> face_number_id_map;
-      for (size_t l = 0; l < descriptor.face_number_vector.size(); ++l) {
-        face_number_id_map[descriptor.face_number_vector[l]] = l;
+      for (size_t l = 0; l < face_number_vector.size(); ++l) {
+        face_number_id_map[face_number_vector[l]] = l;
       }
-      Assert(face_number_id_map.size() == descriptor.face_number_vector.size());
+      Assert(face_number_id_map.size() == face_number_vector.size());
       return face_number_id_map;
     }();
 
+    const auto& node_to_face_matrix = descriptor.nodeToFaceMatrix();
+    const auto& face_to_node_matrix = descriptor.faceToNodeMatrix();
+
     const auto find_face = [&](std::vector<uint32_t> node_list) {
       size_t i_node_smallest_number = 0;
       for (size_t i_node = 1; i_node < node_list.size(); ++i_node) {
@@ -550,15 +591,15 @@ GmshConnectivityBuilder<3>::GmshConnectivityBuilder(const GmshReader::GmshData&
         }
       }
 
-      const auto& face_id_vector = descriptor.node_to_face_matrix[node_list[0]];
+      const auto& face_id_vector = node_to_face_matrix[node_list[0]];
 
       for (size_t i_face = 0; i_face < face_id_vector.size(); ++i_face) {
         const FaceId face_id          = face_id_vector[i_face];
-        const auto& face_node_id_list = descriptor.face_to_node_matrix[face_id];
+        const auto& face_node_id_list = face_to_node_matrix[face_id];
         if (face_node_id_list.size() == node_list.size()) {
           bool is_same = true;
           for (size_t i_node = 1; i_node < face_node_id_list.size(); ++i_node) {
-            is_same &= (descriptor.face_to_node_matrix[face_id][i_node] == node_list[i_node]);
+            is_same &= (face_node_id_list[i_node] == node_list[i_node]);
           }
           if (is_same) {
             return face_id;
@@ -575,6 +616,7 @@ GmshConnectivityBuilder<3>::GmshConnectivityBuilder(const GmshReader::GmshData&
       throw NormalError(error_msg.str());
     };
 
+    Array<int> face_number_vector = copy(descriptor.faceNumberVector());
     std::map<unsigned int, std::vector<unsigned int>> ref_faces_map;
     for (unsigned int f = 0; f < gmsh_data.__triangles.size(); ++f) {
       const unsigned int face_id =
@@ -583,21 +625,21 @@ GmshConnectivityBuilder<3>::GmshConnectivityBuilder(const GmshReader::GmshData&
       const unsigned int& ref = gmsh_data.__triangles_ref[f];
       ref_faces_map[ref].push_back(face_id);
 
-      if (descriptor.face_number_vector[face_id] != gmsh_data.__triangles_number[f]) {
+      if (face_number_vector[face_id] != gmsh_data.__triangles_number[f]) {
         if (auto i_face = face_number_id_map.find(gmsh_data.__triangles_number[f]);
             i_face != face_number_id_map.end()) {
           const int other_face_id = i_face->second;
-          std::swap(descriptor.face_number_vector[face_id], descriptor.face_number_vector[other_face_id]);
+          std::swap(face_number_vector[face_id], face_number_vector[other_face_id]);
 
-          face_number_id_map.erase(descriptor.face_number_vector[face_id]);
-          face_number_id_map.erase(descriptor.face_number_vector[other_face_id]);
+          face_number_id_map.erase(face_number_vector[face_id]);
+          face_number_id_map.erase(face_number_vector[other_face_id]);
 
-          face_number_id_map[descriptor.face_number_vector[face_id]]       = face_id;
-          face_number_id_map[descriptor.face_number_vector[other_face_id]] = other_face_id;
+          face_number_id_map[face_number_vector[face_id]]       = face_id;
+          face_number_id_map[face_number_vector[other_face_id]] = other_face_id;
         } else {
-          face_number_id_map.erase(descriptor.face_number_vector[face_id]);
-          descriptor.face_number_vector[face_id]                     = gmsh_data.__triangles_number[f];
-          face_number_id_map[descriptor.face_number_vector[face_id]] = face_id;
+          face_number_id_map.erase(face_number_vector[face_id]);
+          face_number_vector[face_id]                     = gmsh_data.__triangles_number[f];
+          face_number_id_map[face_number_vector[face_id]] = face_id;
         }
       }
     }
@@ -608,25 +650,25 @@ GmshConnectivityBuilder<3>::GmshConnectivityBuilder(const GmshReader::GmshData&
 
       const unsigned int& ref = gmsh_data.__quadrangles_ref[f];
       ref_faces_map[ref].push_back(face_id);
-
-      if (descriptor.face_number_vector[face_id] != gmsh_data.__quadrangles_number[f]) {
+      if (face_number_vector[face_id] != gmsh_data.__quadrangles_number[f]) {
         if (auto i_face = face_number_id_map.find(gmsh_data.__quadrangles_number[f]);
             i_face != face_number_id_map.end()) {
           const int other_face_id = i_face->second;
-          std::swap(descriptor.face_number_vector[face_id], descriptor.face_number_vector[other_face_id]);
+          std::swap(face_number_vector[face_id], face_number_vector[other_face_id]);
 
-          face_number_id_map.erase(descriptor.face_number_vector[face_id]);
-          face_number_id_map.erase(descriptor.face_number_vector[other_face_id]);
+          face_number_id_map.erase(face_number_vector[face_id]);
+          face_number_id_map.erase(face_number_vector[other_face_id]);
 
-          face_number_id_map[descriptor.face_number_vector[face_id]]       = face_id;
-          face_number_id_map[descriptor.face_number_vector[other_face_id]] = other_face_id;
+          face_number_id_map[face_number_vector[face_id]]       = face_id;
+          face_number_id_map[face_number_vector[other_face_id]] = other_face_id;
         } else {
-          face_number_id_map.erase(descriptor.face_number_vector[face_id]);
-          descriptor.face_number_vector[face_id]                     = gmsh_data.__quadrangles_number[f];
-          face_number_id_map[descriptor.face_number_vector[face_id]] = face_id;
+          face_number_id_map.erase(face_number_vector[face_id]);
+          face_number_vector[face_id]                     = gmsh_data.__quadrangles_number[f];
+          face_number_id_map[face_number_vector[face_id]] = face_id;
         }
       }
     }
+    descriptor.setFaceNumberVector(face_number_vector);
 
     for (const auto& ref_face_list : ref_faces_map) {
       Array<FaceId> face_list(ref_face_list.second.size());
@@ -657,27 +699,32 @@ GmshConnectivityBuilder<3>::GmshConnectivityBuilder(const GmshReader::GmshData&
   ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities<3>(descriptor);
 
   {
-    Array<bool> is_boundary_edge(descriptor.edge_number_vector.size());
+    Array<bool> is_boundary_edge(descriptor.edgeNumberVector().size());
     is_boundary_edge.fill(false);
 
+    const auto& face_to_edge_matrix = descriptor.faceToEdgeMatrix();
+
     for (size_t i_face = 0; i_face < face_nb_cell.size(); ++i_face) {
       if (face_nb_cell[i_face] == 1) {
-        auto face_edges = descriptor.face_to_edge_matrix[i_face];
-        for (size_t i_edge = 0; i_edge < face_edges.size(); ++i_edge) {
-          is_boundary_edge[face_edges[i_edge]] = true;
+        auto face_edge_list = face_to_edge_matrix[i_face];
+        for (size_t i_edge = 0; i_edge < face_edge_list.size(); ++i_edge) {
+          is_boundary_edge[face_edge_list[i_edge]] = true;
         }
       }
     }
 
+    const auto& node_to_edge_matrix = descriptor.nodeToEdgeMatrix();
+    const auto& edge_to_node_matrix = descriptor.edgeToNodeMatrix();
+
     const auto find_edge = [&](uint32_t node0, uint32_t node1) {
-      if (descriptor.node_number_vector[node0] > descriptor.node_number_vector[node1]) {
+      if (node_number_vector[node0] > node_number_vector[node1]) {
         std::swap(node0, node1);
       }
-      const auto& edge_id_vector = descriptor.node_to_edge_matrix[node0];
+      const auto& edge_id_vector = node_to_edge_matrix[node0];
 
       for (size_t i_edge = 0; i_edge < edge_id_vector.size(); ++i_edge) {
         const EdgeId edge_id = edge_id_vector[i_edge];
-        if (descriptor.edge_to_node_matrix[edge_id][1] == node1) {
+        if (edge_to_node_matrix[edge_id][1] == node1) {
           return edge_id;
         }
       }
@@ -688,37 +735,40 @@ GmshConnectivityBuilder<3>::GmshConnectivityBuilder(const GmshReader::GmshData&
     };
 
     std::unordered_map<int, EdgeId> edge_number_id_map = [&] {
+      const auto& edge_number_vector = descriptor.edgeNumberVector();
       std::unordered_map<int, EdgeId> edge_number_id_map;
-      for (size_t l = 0; l < descriptor.edge_number_vector.size(); ++l) {
-        edge_number_id_map[descriptor.edge_number_vector[l]] = l;
+      for (size_t l = 0; l < edge_number_vector.size(); ++l) {
+        edge_number_id_map[edge_number_vector[l]] = l;
       }
-      Assert(edge_number_id_map.size() == descriptor.edge_number_vector.size());
+      Assert(edge_number_id_map.size() == edge_number_vector.size());
       return edge_number_id_map;
     }();
 
+    Array<int> edge_number_vector = copy(descriptor.edgeNumberVector());
     std::map<unsigned int, std::vector<unsigned int>> ref_edges_map;
     for (unsigned int e = 0; e < gmsh_data.__edges.size(); ++e) {
       const unsigned int edge_id = find_edge(gmsh_data.__edges[e][0], gmsh_data.__edges[e][1]);
       const unsigned int& ref    = gmsh_data.__edges_ref[e];
       ref_edges_map[ref].push_back(edge_id);
 
-      if (descriptor.edge_number_vector[edge_id] != gmsh_data.__edges_number[e]) {
+      if (edge_number_vector[edge_id] != gmsh_data.__edges_number[e]) {
         if (auto i_edge = edge_number_id_map.find(gmsh_data.__edges_number[e]); i_edge != edge_number_id_map.end()) {
           const int other_edge_id = i_edge->second;
-          std::swap(descriptor.edge_number_vector[edge_id], descriptor.edge_number_vector[other_edge_id]);
+          std::swap(edge_number_vector[edge_id], edge_number_vector[other_edge_id]);
 
-          edge_number_id_map.erase(descriptor.edge_number_vector[edge_id]);
-          edge_number_id_map.erase(descriptor.edge_number_vector[other_edge_id]);
+          edge_number_id_map.erase(edge_number_vector[edge_id]);
+          edge_number_id_map.erase(edge_number_vector[other_edge_id]);
 
-          edge_number_id_map[descriptor.edge_number_vector[edge_id]]       = edge_id;
-          edge_number_id_map[descriptor.edge_number_vector[other_edge_id]] = other_edge_id;
+          edge_number_id_map[edge_number_vector[edge_id]]       = edge_id;
+          edge_number_id_map[edge_number_vector[other_edge_id]] = other_edge_id;
         } else {
-          edge_number_id_map.erase(descriptor.edge_number_vector[edge_id]);
-          descriptor.edge_number_vector[edge_id]                     = gmsh_data.__edges_number[e];
-          edge_number_id_map[descriptor.edge_number_vector[edge_id]] = edge_id;
+          edge_number_id_map.erase(edge_number_vector[edge_id]);
+          edge_number_vector[edge_id]                     = gmsh_data.__edges_number[e];
+          edge_number_id_map[edge_number_vector[edge_id]] = edge_id;
         }
       }
     }
+    descriptor.setEdgeNumberVector(edge_number_vector);
 
     for (const auto& ref_edge_list : ref_edges_map) {
       Array<EdgeId> edge_list(ref_edge_list.second.size());
@@ -746,13 +796,16 @@ GmshConnectivityBuilder<3>::GmshConnectivityBuilder(const GmshReader::GmshData&
     }
   }
 
-  Array<bool> is_boundary_node(descriptor.node_number_vector.size());
+  Array<bool> is_boundary_node(node_number_vector.size());
   is_boundary_node.fill(false);
 
+  const auto& face_to_node_matrix = descriptor.faceToNodeMatrix();
+
   for (size_t i_face = 0; i_face < face_nb_cell.size(); ++i_face) {
     if (face_nb_cell[i_face] == 1) {
-      for (size_t i_node = 0; i_node < descriptor.face_to_node_matrix[i_face].size(); ++i_node) {
-        const NodeId node_id      = descriptor.face_to_node_matrix[i_face][i_node];
+      const auto& face_node_list = face_to_node_matrix[i_face];
+      for (size_t i_node = 0; i_node < face_node_list.size(); ++i_node) {
+        const NodeId node_id      = face_node_list[i_node];
         is_boundary_node[node_id] = true;
       }
     }
@@ -790,17 +843,29 @@ GmshConnectivityBuilder<3>::GmshConnectivityBuilder(const GmshReader::GmshData&
     descriptor.addRefItemList(RefNodeList(ref_id, point_list, is_boundary));
   }
 
-  descriptor.cell_owner_vector = Array<int>(nb_cells);
-  descriptor.cell_owner_vector.fill(parallel::rank());
-
-  descriptor.face_owner_vector = Array<int>(descriptor.face_number_vector.size());
-  descriptor.face_owner_vector.fill(parallel::rank());
-
-  descriptor.edge_owner_vector = Array<int>(descriptor.edge_number_vector.size());
-  descriptor.edge_owner_vector.fill(parallel::rank());
-
-  descriptor.node_owner_vector = Array<int>(descriptor.node_number_vector.size());
-  descriptor.node_owner_vector.fill(parallel::rank());
+  descriptor.setCellOwnerVector([&] {
+    Array<int> cell_owner_vector(nb_cells);
+    cell_owner_vector.fill(parallel::rank());
+    return cell_owner_vector;
+  }());
+
+  descriptor.setFaceOwnerVector([&] {
+    Array<int> face_owner_vector(descriptor.faceNumberVector().size());
+    face_owner_vector.fill(parallel::rank());
+    return face_owner_vector;
+  }());
+
+  descriptor.setEdgeOwnerVector([&] {
+    Array<int> edge_owner_vector(descriptor.edgeNumberVector().size());
+    edge_owner_vector.fill(parallel::rank());
+    return edge_owner_vector;
+  }());
+
+  descriptor.setNodeOwnerVector([&] {
+    Array<int> node_owner_vector(node_number_vector.size());
+    node_owner_vector.fill(parallel::rank());
+    return node_owner_vector;
+  }());
 
   m_connectivity = Connectivity3D::build(descriptor);
 }
diff --git a/src/mesh/LogicalConnectivityBuilder.cpp b/src/mesh/LogicalConnectivityBuilder.cpp
index 1fd5a950a..dbc41d068 100644
--- a/src/mesh/LogicalConnectivityBuilder.cpp
+++ b/src/mesh/LogicalConnectivityBuilder.cpp
@@ -141,17 +141,19 @@ void
 LogicalConnectivityBuilder::_buildBoundaryEdgeList(const TinyVector<3, uint64_t>& cell_size,
                                                    ConnectivityDescriptor& descriptor)
 {
-  const auto& node_number_vector = descriptor.node_number_vector;
+  const auto& node_number_vector  = descriptor.nodeNumberVector();
+  const auto& node_to_edge_matrix = descriptor.nodeToEdgeMatrix();
+  const auto& edge_to_node_matrix = descriptor.edgeToNodeMatrix();
 
   const auto find_edge = [&](uint32_t node0, uint32_t node1) {
     if (node_number_vector[node0] > node_number_vector[node1]) {
       std::swap(node0, node1);
     }
-    const auto& edge_id_vector = descriptor.node_to_edge_matrix[node0];
+    const auto& node_edge_list = node_to_edge_matrix[node0];
 
-    for (size_t i_edge = 0; i_edge < edge_id_vector.size(); ++i_edge) {
-      const EdgeId edge_id = edge_id_vector[i_edge];
-      if (descriptor.edge_to_node_matrix[edge_id][1] == node1) {
+    for (size_t i_edge = 0; i_edge < node_edge_list.size(); ++i_edge) {
+      const EdgeId edge_id = node_edge_list[i_edge];
+      if (edge_to_node_matrix[edge_id][1] == node1) {
         return edge_id;
       }
     }
@@ -244,6 +246,8 @@ LogicalConnectivityBuilder::_buildBoundaryFaceList(
     return cell_logic_id[0] * cell_size[1] + cell_logic_id[1];
   };
 
+  const auto& cell_to_face_matrix = descriptor.cellToFaceMatrix();
+
   {   // xmin
     const size_t i = 0;
     Array<FaceId> boundary_faces(cell_size[1]);
@@ -251,7 +255,7 @@ LogicalConnectivityBuilder::_buildBoundaryFaceList(
       constexpr size_t left_face = 3;
 
       const size_t cell_id = cell_number(TinyVector<2, uint64_t>{i, j});
-      const size_t face_id = descriptor.cell_to_face_matrix[cell_id][left_face];
+      const size_t face_id = cell_to_face_matrix[cell_id][left_face];
 
       boundary_faces[j] = face_id;
     }
@@ -265,7 +269,7 @@ LogicalConnectivityBuilder::_buildBoundaryFaceList(
       constexpr size_t right_face = 1;
 
       const size_t cell_id = cell_number(TinyVector<2, uint64_t>{i, j});
-      const size_t face_id = descriptor.cell_to_face_matrix[cell_id][right_face];
+      const size_t face_id = cell_to_face_matrix[cell_id][right_face];
 
       boundary_faces[j] = face_id;
     }
@@ -279,7 +283,7 @@ LogicalConnectivityBuilder::_buildBoundaryFaceList(
       constexpr size_t bottom_face = 0;
 
       const size_t cell_id = cell_number(TinyVector<2, uint64_t>{i, j});
-      const size_t face_id = descriptor.cell_to_face_matrix[cell_id][bottom_face];
+      const size_t face_id = cell_to_face_matrix[cell_id][bottom_face];
 
       boundary_faces[i] = face_id;
     }
@@ -293,7 +297,7 @@ LogicalConnectivityBuilder::_buildBoundaryFaceList(
       constexpr size_t top_face = 2;
 
       const size_t cell_id = cell_number(TinyVector<2, uint64_t>{i, j});
-      const size_t face_id = descriptor.cell_to_face_matrix[cell_id][top_face];
+      const size_t face_id = cell_to_face_matrix[cell_id][top_face];
 
       boundary_faces[i] = face_id;
     }
@@ -306,7 +310,9 @@ void
 LogicalConnectivityBuilder::_buildBoundaryFaceList(const TinyVector<3, uint64_t>& cell_size,
                                                    ConnectivityDescriptor& descriptor)
 {
-  const auto& node_number_vector = descriptor.node_number_vector;
+  const auto& node_number_vector  = descriptor.nodeNumberVector();
+  const auto& face_to_node_matrix = descriptor.faceToNodeMatrix();
+  const auto& node_to_face_matrix = descriptor.nodeToFaceMatrix();
 
   const auto find_face = [&](std::array<uint32_t, 4> node_list) {
     size_t i_node_smallest_number = 0;
@@ -336,13 +342,13 @@ LogicalConnectivityBuilder::_buildBoundaryFaceList(const TinyVector<3, uint64_t>
       }
     }
 
-    const auto& face_id_vector = descriptor.node_to_face_matrix[node_list[0]];
+    const auto& node_face_list = node_to_face_matrix[node_list[0]];
 
-    for (size_t i_face = 0; i_face < face_id_vector.size(); ++i_face) {
-      const FaceId face_id = face_id_vector[i_face];
-      if ((descriptor.face_to_node_matrix[face_id][1] == node_list[1]) and
-          (descriptor.face_to_node_matrix[face_id][2] == node_list[2]) and
-          (descriptor.face_to_node_matrix[face_id][3] == node_list[3])) {
+    for (size_t i_face = 0; i_face < node_face_list.size(); ++i_face) {
+      const FaceId face_id       = node_face_list[i_face];
+      const auto& face_node_list = face_to_node_matrix[face_id];
+      if ((face_node_list[1] == node_list[1]) and (face_node_list[2] == node_list[2]) and
+          (face_node_list[3] == node_list[3])) {
         return face_id;
       }
     }
@@ -430,24 +436,24 @@ LogicalConnectivityBuilder::_buildConnectivity(
   const size_t number_of_nodes = cell_size[0] + 1;
 
   ConnectivityDescriptor descriptor;
-  descriptor.node_number_vector = [&] {
+  descriptor.setNodeNumberVector([&] {
     Array<int> node_number_vector(number_of_nodes);
-    for (size_t i = 0; i < number_of_nodes; ++i) {
-      node_number_vector[i] = i;
-    }
+    parallel_for(
+      number_of_nodes, PUGS_LAMBDA(const size_t i) { node_number_vector[i] = i; });
     return node_number_vector;
-  }();
+  }());
 
-  descriptor.cell_number_vector = [&] {
+  descriptor.setCellNumberVector([&] {
     Array<int> cell_number_vector(number_of_cells);
     for (size_t i = 0; i < number_of_cells; ++i) {
       cell_number_vector[i] = i;
     }
     return cell_number_vector;
-  }();
+  }());
 
-  descriptor.cell_type_vector = Array<CellType>(number_of_cells);
-  descriptor.cell_type_vector.fill(CellType::Line);
+  Array<CellType> cell_type_vector(number_of_cells);
+  cell_type_vector.fill(CellType::Line);
+  descriptor.setCellTypeVector(cell_type_vector);
 
   Array<unsigned int> cell_to_node_row_map(number_of_cells + 1);
   for (size_t i = 0; i < cell_to_node_row_map.size(); ++i) {
@@ -459,15 +465,21 @@ LogicalConnectivityBuilder::_buildConnectivity(
     cell_to_node_list[2 * i + 1] = i + 1;
   }
 
-  descriptor.cell_to_node_matrix = ConnectivityMatrix(cell_to_node_row_map, cell_to_node_list);
+  descriptor.setCellToNodeMatrix(ConnectivityMatrix(cell_to_node_row_map, cell_to_node_list));
 
   this->_buildBoundaryNodeList(cell_size, descriptor);
 
-  descriptor.cell_owner_vector = Array<int>(number_of_cells);
-  descriptor.cell_owner_vector.fill(parallel::rank());
+  descriptor.setCellOwnerVector([&] {
+    Array<int> cell_owner_vector(number_of_cells);
+    cell_owner_vector.fill(parallel::rank());
+    return cell_owner_vector;
+  }());
 
-  descriptor.node_owner_vector = Array<int>(descriptor.node_number_vector.size());
-  descriptor.node_owner_vector.fill(parallel::rank());
+  descriptor.setNodeOwnerVector([&] {
+    Array<int> node_owner_vector(number_of_nodes);
+    node_owner_vector.fill(parallel::rank());
+    return node_owner_vector;
+  }());
 
   m_connectivity = Connectivity1D::build(descriptor);
 }
@@ -485,24 +497,23 @@ LogicalConnectivityBuilder::_buildConnectivity(
   const size_t number_of_nodes = node_size[0] * node_size[1];
 
   ConnectivityDescriptor descriptor;
-  descriptor.node_number_vector = [&] {
+  descriptor.setNodeNumberVector([&] {
     Array<int> node_number_vector(number_of_nodes);
-    for (size_t i = 0; i < number_of_nodes; ++i) {
-      node_number_vector[i] = i;
-    }
+    parallel_for(
+      number_of_nodes, PUGS_LAMBDA(const size_t i) { node_number_vector[i] = i; });
     return node_number_vector;
-  }();
+  }());
 
-  descriptor.cell_number_vector = [&] {
+  descriptor.setCellNumberVector([&] {
     Array<int> cell_number_vector(number_of_cells);
-    for (size_t i = 0; i < number_of_cells; ++i) {
-      cell_number_vector[i] = i;
-    }
+    parallel_for(
+      number_of_cells, PUGS_LAMBDA(size_t i) { cell_number_vector[i] = i; });
     return cell_number_vector;
-  }();
+  }());
 
-  descriptor.cell_type_vector = Array<CellType>(number_of_cells);
-  descriptor.cell_type_vector.fill(CellType::Quadrangle);
+  Array<CellType> cell_type_vector(number_of_cells);
+  cell_type_vector.fill(CellType::Quadrangle);
+  descriptor.setCellTypeVector(cell_type_vector);
 
   const auto node_number = [&](const TinyVector<Dimension, uint64_t> node_logic_id) {
     return node_logic_id[0] * node_size[1] + node_logic_id[1];
@@ -528,21 +539,30 @@ LogicalConnectivityBuilder::_buildConnectivity(
     cell_to_node_list[4 * j + 3] = node_number(cell_index + TinyVector<Dimension, uint64_t>{0, 1});
   }
 
-  descriptor.cell_to_node_matrix = ConnectivityMatrix(cell_to_node_row_map, cell_to_node_list);
+  descriptor.setCellToNodeMatrix(ConnectivityMatrix(cell_to_node_row_map, cell_to_node_list));
 
   ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities<Dimension>(descriptor);
 
   this->_buildBoundaryNodeList(cell_size, descriptor);
   this->_buildBoundaryFaceList(cell_size, descriptor);
 
-  descriptor.cell_owner_vector = Array<int>(number_of_cells);
-  descriptor.cell_owner_vector.fill(parallel::rank());
+  descriptor.setCellOwnerVector([&] {
+    Array<int> cell_owner_vector(number_of_cells);
+    cell_owner_vector.fill(parallel::rank());
+    return cell_owner_vector;
+  }());
 
-  descriptor.face_owner_vector = Array<int>(descriptor.face_number_vector.size());
-  descriptor.face_owner_vector.fill(parallel::rank());
+  descriptor.setFaceOwnerVector([&] {
+    Array<int> face_owner_vector(descriptor.faceNumberVector().size());
+    face_owner_vector.fill(parallel::rank());
+    return face_owner_vector;
+  }());
 
-  descriptor.node_owner_vector = Array<int>(descriptor.node_number_vector.size());
-  descriptor.node_owner_vector.fill(parallel::rank());
+  descriptor.setNodeOwnerVector([&] {
+    Array<int> node_owner_vector(descriptor.nodeNumberVector().size());
+    node_owner_vector.fill(parallel::rank());
+    return node_owner_vector;
+  }());
 
   m_connectivity = Connectivity<Dimension>::build(descriptor);
 }
@@ -576,24 +596,23 @@ LogicalConnectivityBuilder::_buildConnectivity(const TinyVector<3, uint64_t>& ce
   const size_t number_of_nodes = count_items(node_size);
 
   ConnectivityDescriptor descriptor;
-  descriptor.node_number_vector = [&] {
+  descriptor.setNodeNumberVector([&] {
     Array<int> node_number_vector(number_of_nodes);
-    for (size_t i = 0; i < number_of_nodes; ++i) {
-      node_number_vector[i] = i;
-    }
+    parallel_for(
+      number_of_nodes, PUGS_LAMBDA(const size_t i) { node_number_vector[i] = i; });
     return node_number_vector;
-  }();
+  }());
 
-  descriptor.cell_number_vector = [&] {
+  descriptor.setCellNumberVector([&] {
     Array<int> cell_number_vector(number_of_cells);
-    for (size_t i = 0; i < number_of_cells; ++i) {
-      cell_number_vector[i] = i;
-    }
+    parallel_for(
+      number_of_cells, PUGS_LAMBDA(size_t i) { cell_number_vector[i] = i; });
     return cell_number_vector;
-  }();
+  }());
 
-  descriptor.cell_type_vector = Array<CellType>(number_of_cells);
-  descriptor.cell_type_vector.fill(CellType::Hexahedron);
+  Array<CellType> cell_type_vector(number_of_cells);
+  cell_type_vector.fill(CellType::Hexahedron);
+  descriptor.setCellTypeVector(cell_type_vector);
 
   const auto cell_logic_id = [&](size_t j) {
     const size_t slice1  = cell_size[1] * cell_size[2];
@@ -626,7 +645,7 @@ LogicalConnectivityBuilder::_buildConnectivity(const TinyVector<3, uint64_t>& ce
     cell_to_node_list[8 * j + 7] = node_number(cell_index + TinyVector<Dimension, uint64_t>{0, 1, 1});
   }
 
-  descriptor.cell_to_node_matrix = ConnectivityMatrix(cell_to_node_row_map, cell_to_node_list);
+  descriptor.setCellToNodeMatrix(ConnectivityMatrix(cell_to_node_row_map, cell_to_node_list));
 
   ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities<Dimension>(descriptor);
   ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities<Dimension>(descriptor);
@@ -635,17 +654,29 @@ LogicalConnectivityBuilder::_buildConnectivity(const TinyVector<3, uint64_t>& ce
   this->_buildBoundaryEdgeList(cell_size, descriptor);
   this->_buildBoundaryFaceList(cell_size, descriptor);
 
-  descriptor.cell_owner_vector = Array<int>(number_of_cells);
-  descriptor.cell_owner_vector.fill(parallel::rank());
-
-  descriptor.face_owner_vector = Array<int>(descriptor.face_number_vector.size());
-  descriptor.face_owner_vector.fill(parallel::rank());
-
-  descriptor.edge_owner_vector = Array<int>(descriptor.edge_number_vector.size());
-  descriptor.edge_owner_vector.fill(parallel::rank());
-
-  descriptor.node_owner_vector = Array<int>(descriptor.node_number_vector.size());
-  descriptor.node_owner_vector.fill(parallel::rank());
+  descriptor.setCellOwnerVector([&] {
+    Array<int> cell_owner_vector(number_of_cells);
+    cell_owner_vector.fill(parallel::rank());
+    return cell_owner_vector;
+  }());
+
+  descriptor.setFaceOwnerVector([&] {
+    Array<int> face_owner_vector(descriptor.faceNumberVector().size());
+    face_owner_vector.fill(parallel::rank());
+    return face_owner_vector;
+  }());
+
+  descriptor.setEdgeOwnerVector([&] {
+    Array<int> edge_owner_vector(descriptor.edgeNumberVector().size());
+    edge_owner_vector.fill(parallel::rank());
+    return edge_owner_vector;
+  }());
+
+  descriptor.setNodeOwnerVector([&] {
+    Array<int> node_owner_vector(descriptor.nodeNumberVector().size());
+    node_owner_vector.fill(parallel::rank());
+    return node_owner_vector;
+  }());
 
   m_connectivity = Connectivity<Dimension>::build(descriptor);
 }
diff --git a/src/mesh/MedianDualConnectivityBuilder.cpp b/src/mesh/MedianDualConnectivityBuilder.cpp
index fa3490b07..1986c4a82 100644
--- a/src/mesh/MedianDualConnectivityBuilder.cpp
+++ b/src/mesh/MedianDualConnectivityBuilder.cpp
@@ -92,33 +92,37 @@ MedianDualConnectivityBuilder::_buildConnectivityDescriptor<2>(const Connectivit
     Assert(i_boundary_node == primal_number_of_boundary_nodes);
   }
 
-  dual_descriptor.node_number_vector = Array<int>(dual_number_of_nodes);
+  Array<int> node_number_vector(dual_number_of_nodes);
   {
     parallel_for(m_primal_cell_to_dual_node_map.size(), [&](size_t i) {
-      const auto [primal_cell_id, dual_node_id]        = m_primal_cell_to_dual_node_map[i];
-      dual_descriptor.node_number_vector[dual_node_id] = primal_cell_number[primal_cell_id];
+      const auto [primal_cell_id, dual_node_id] = m_primal_cell_to_dual_node_map[i];
+      node_number_vector[dual_node_id]          = primal_cell_number[primal_cell_id];
     });
 
     const size_t face_number_shift = max(primal_cell_number) + 1;
     parallel_for(primal_number_of_faces, [&](size_t i) {
-      const auto [primal_face_id, dual_node_id]        = m_primal_face_to_dual_node_map[i];
-      dual_descriptor.node_number_vector[dual_node_id] = primal_face_number[primal_face_id] + face_number_shift;
+      const auto [primal_face_id, dual_node_id] = m_primal_face_to_dual_node_map[i];
+      node_number_vector[dual_node_id]          = primal_face_number[primal_face_id] + face_number_shift;
     });
 
     const size_t node_number_shift = face_number_shift + max(primal_face_number) + 1;
     parallel_for(m_primal_boundary_node_to_dual_node_map.size(), [&](size_t i) {
-      const auto [primal_node_id, dual_node_id]        = m_primal_boundary_node_to_dual_node_map[i];
-      dual_descriptor.node_number_vector[dual_node_id] = primal_node_number[primal_node_id] + node_number_shift;
+      const auto [primal_node_id, dual_node_id] = m_primal_boundary_node_to_dual_node_map[i];
+      node_number_vector[dual_node_id]          = primal_node_number[primal_node_id] + node_number_shift;
     });
   }
+  dual_descriptor.setNodeNumberVector(node_number_vector);
 
-  dual_descriptor.cell_number_vector = Array<int>(dual_number_of_cells);
-  parallel_for(dual_number_of_cells, [&](size_t i) {
-    const auto [primal_node_id, dual_cell_id]        = m_primal_node_to_dual_cell_map[i];
-    dual_descriptor.cell_number_vector[dual_cell_id] = primal_node_number[primal_node_id];
-  });
+  {
+    Array<int> cell_number_vector(dual_number_of_cells);
+    parallel_for(dual_number_of_cells, [&](size_t i) {
+      const auto [primal_node_id, dual_cell_id] = m_primal_node_to_dual_cell_map[i];
+      cell_number_vector[dual_cell_id]          = primal_node_number[primal_node_id];
+    });
+    dual_descriptor.setCellNumberVector(cell_number_vector);
+  }
 
-  dual_descriptor.cell_type_vector = Array<CellType>(dual_number_of_cells);
+  Array<CellType> cell_type_vector(dual_number_of_cells);
 
   const auto& primal_node_to_cell_matrix = primal_connectivity.nodeToCellMatrix();
 
@@ -127,11 +131,12 @@ MedianDualConnectivityBuilder::_buildConnectivityDescriptor<2>(const Connectivit
     const auto& primal_node_cell_list = primal_node_to_cell_matrix[node_id];
 
     if (primal_node_cell_list.size() == 1) {
-      dual_descriptor.cell_type_vector[i_dual_cell] = CellType::Quadrangle;
+      cell_type_vector[i_dual_cell] = CellType::Quadrangle;
     } else {
-      dual_descriptor.cell_type_vector[i_dual_cell] = CellType::Polygon;
+      cell_type_vector[i_dual_cell] = CellType::Polygon;
     }
   });
+  dual_descriptor.setCellTypeVector(cell_type_vector);
 
   const auto& primal_cell_to_face_matrix               = primal_connectivity.cellToFaceMatrix();
   const auto& primal_node_to_face_matrix               = primal_connectivity.nodeToFaceMatrix();
@@ -264,7 +269,7 @@ MedianDualConnectivityBuilder::_buildConnectivityDescriptor<2>(const Connectivit
     }
   });
 
-  dual_descriptor.cell_to_node_matrix = ConnectivityMatrix(cell_to_node_row, cell_to_node_list);
+  dual_descriptor.setCellToNodeMatrix(ConnectivityMatrix(cell_to_node_row, cell_to_node_list));
 }
 
 template <>
@@ -330,21 +335,23 @@ MedianDualConnectivityBuilder::_buildConnectivityFrom<2>(const IConnectivity& i_
         bounday_face_dual_node_id_list[i_face] = m_primal_face_to_dual_node_map[primal_face_list[i_face]].second;
       }
 
-      std::vector<bool> is_dual_node_from_boundary_face(dual_descriptor.node_number_vector.size(), false);
+      std::vector<bool> is_dual_node_from_boundary_face(dual_descriptor.nodeNumberVector().size(), false);
       for (size_t i_face = 0; i_face < bounday_face_dual_node_id_list.size(); ++i_face) {
         is_dual_node_from_boundary_face[bounday_face_dual_node_id_list[i_face]] = true;
       }
 
-      std::vector<bool> is_dual_node_from_boundary_node(dual_descriptor.node_number_vector.size(), false);
+      std::vector<bool> is_dual_node_from_boundary_node(dual_descriptor.nodeNumberVector().size(), false);
       for (size_t i_node = 0; i_node < m_primal_boundary_node_to_dual_node_map.size(); ++i_node) {
         is_dual_node_from_boundary_node[m_primal_boundary_node_to_dual_node_map[i_node].second] = true;
       }
 
+      const auto& dual_face_to_node_matrix = dual_descriptor.faceToNodeMatrix();
+
       std::vector<FaceId> dual_face_list;
       dual_face_list.reserve(2 * primal_face_list.size());
-      for (size_t i_dual_face = 0; i_dual_face < dual_descriptor.face_to_node_matrix.numberOfRows(); ++i_dual_face) {
-        const NodeId dual_node_0 = dual_descriptor.face_to_node_matrix[i_dual_face][0];
-        const NodeId dual_node_1 = dual_descriptor.face_to_node_matrix[i_dual_face][1];
+      for (size_t i_dual_face = 0; i_dual_face < dual_face_to_node_matrix.numberOfRows(); ++i_dual_face) {
+        const NodeId dual_node_0 = dual_face_to_node_matrix[i_dual_face][0];
+        const NodeId dual_node_1 = dual_face_to_node_matrix[i_dual_face][1];
 
         if ((is_dual_node_from_boundary_face[dual_node_0] and is_dual_node_from_boundary_node[dual_node_1]) or
             (is_dual_node_from_boundary_node[dual_node_0] and is_dual_node_from_boundary_face[dual_node_1])) {
@@ -361,51 +368,61 @@ MedianDualConnectivityBuilder::_buildConnectivityFrom<2>(const IConnectivity& i_
     }
   }
 
-  dual_descriptor.node_owner_vector = Array<int>(dual_descriptor.node_number_vector.size());
-
   const auto& primal_node_owner = primal_connectivity.nodeOwner();
 
-  dual_descriptor.node_owner_vector.fill(-1);
-  for (size_t i_primal_node_to_dual_node = 0;
-       i_primal_node_to_dual_node < m_primal_boundary_node_to_dual_node_map.size(); ++i_primal_node_to_dual_node) {
-    const auto& [primal_node_id, dual_node_id] = m_primal_boundary_node_to_dual_node_map[i_primal_node_to_dual_node];
-    dual_descriptor.node_owner_vector[dual_node_id] = primal_node_owner[primal_node_id];
-  }
+  dual_descriptor.setNodeOwnerVector([&] {
+    Array<int> node_owner_vector(dual_descriptor.nodeNumberVector().size());
 
-  const auto& primal_face_owner = primal_connectivity.faceOwner();
-  for (size_t i_primal_face_to_dual_node = 0; i_primal_face_to_dual_node < m_primal_face_to_dual_node_map.size();
-       ++i_primal_face_to_dual_node) {
-    const auto& [primal_face_id, dual_node_id]      = m_primal_face_to_dual_node_map[i_primal_face_to_dual_node];
-    dual_descriptor.node_owner_vector[dual_node_id] = primal_face_owner[primal_face_id];
-  }
+    node_owner_vector.fill(-1);
+    for (size_t i_primal_node_to_dual_node = 0;
+         i_primal_node_to_dual_node < m_primal_boundary_node_to_dual_node_map.size(); ++i_primal_node_to_dual_node) {
+      const auto& [primal_node_id, dual_node_id] = m_primal_boundary_node_to_dual_node_map[i_primal_node_to_dual_node];
+      node_owner_vector[dual_node_id]            = primal_node_owner[primal_node_id];
+    }
 
-  const auto& primal_cell_owner = primal_connectivity.cellOwner();
-  for (size_t i_primal_cell_to_dual_node = 0; i_primal_cell_to_dual_node < m_primal_cell_to_dual_node_map.size();
-       ++i_primal_cell_to_dual_node) {
-    const auto& [primal_cell_id, dual_node_id]      = m_primal_cell_to_dual_node_map[i_primal_cell_to_dual_node];
-    dual_descriptor.node_owner_vector[dual_node_id] = primal_cell_owner[primal_cell_id];
-  }
+    const auto& primal_face_owner = primal_connectivity.faceOwner();
+    for (size_t i_primal_face_to_dual_node = 0; i_primal_face_to_dual_node < m_primal_face_to_dual_node_map.size();
+         ++i_primal_face_to_dual_node) {
+      const auto& [primal_face_id, dual_node_id] = m_primal_face_to_dual_node_map[i_primal_face_to_dual_node];
+      node_owner_vector[dual_node_id]            = primal_face_owner[primal_face_id];
+    }
 
-  dual_descriptor.cell_owner_vector = Array<int>(dual_descriptor.cell_number_vector.size());
-  dual_descriptor.cell_owner_vector.fill(-1);
-  for (size_t i_primal_cell_to_dual_node = 0; i_primal_cell_to_dual_node < m_primal_node_to_dual_cell_map.size();
-       ++i_primal_cell_to_dual_node) {
-    const auto& [primal_node_id, dual_cell_id]      = m_primal_node_to_dual_cell_map[i_primal_cell_to_dual_node];
-    dual_descriptor.cell_owner_vector[dual_cell_id] = primal_node_owner[primal_node_id];
-  }
+    const auto& primal_cell_owner = primal_connectivity.cellOwner();
+    for (size_t i_primal_cell_to_dual_node = 0; i_primal_cell_to_dual_node < m_primal_cell_to_dual_node_map.size();
+         ++i_primal_cell_to_dual_node) {
+      const auto& [primal_cell_id, dual_node_id] = m_primal_cell_to_dual_node_map[i_primal_cell_to_dual_node];
+      node_owner_vector[dual_node_id]            = primal_cell_owner[primal_cell_id];
+    }
 
-  {
-    dual_descriptor.face_owner_vector = Array<int>(dual_descriptor.face_number_vector.size());
-    dual_descriptor.face_owner_vector.fill(parallel::size());
-    for (size_t i_cell = 0; i_cell < dual_descriptor.cell_to_face_matrix.numberOfRows(); ++i_cell) {
-      const auto& cell_face_list = dual_descriptor.cell_to_face_matrix[i_cell];
+    return node_owner_vector;
+  }());
+
+  dual_descriptor.setCellOwnerVector([&] {
+    Array<int> cell_owner_vector(dual_descriptor.cellNumberVector().size());
+    cell_owner_vector.fill(-1);
+    for (size_t i_primal_cell_to_dual_node = 0; i_primal_cell_to_dual_node < m_primal_node_to_dual_cell_map.size();
+         ++i_primal_cell_to_dual_node) {
+      const auto& [primal_node_id, dual_cell_id] = m_primal_node_to_dual_cell_map[i_primal_cell_to_dual_node];
+      cell_owner_vector[dual_cell_id]            = primal_node_owner[primal_node_id];
+    }
+    return cell_owner_vector;
+  }());
+
+  dual_descriptor.setFaceOwnerVector([&] {
+    const auto& dual_cell_to_face_matrix = dual_descriptor.cellToFaceMatrix();
+    const auto& dual_cell_owner_vector   = dual_descriptor.cellOwnerVector();
+
+    Array<int> face_owner_vector(dual_descriptor.faceNumberVector().size());
+    face_owner_vector.fill(parallel::size());
+    for (size_t i_cell = 0; i_cell < dual_cell_to_face_matrix.numberOfRows(); ++i_cell) {
+      const auto& cell_face_list = dual_cell_to_face_matrix[i_cell];
       for (size_t i_face = 0; i_face < cell_face_list.size(); ++i_face) {
-        const size_t face_id = cell_face_list[i_face];
-        dual_descriptor.face_owner_vector[face_id] =
-          std::min(dual_descriptor.face_owner_vector[face_id], dual_descriptor.cell_owner_vector[i_cell]);
+        const size_t face_id       = cell_face_list[i_face];
+        face_owner_vector[face_id] = std::min(face_owner_vector[face_id], dual_cell_owner_vector[i_cell]);
       }
     }
-  }
+    return face_owner_vector;
+  }());
 
   m_connectivity = ConnectivityType::build(dual_descriptor);
 
-- 
GitLab