diff --git a/src/mesh/Connectivity1D.hpp b/src/mesh/Connectivity1D.hpp
index afc9e332cd50b009a428ead260929db68265c3e5..4c56724d8dee5b9713d71afa70c0b3adcafec0eb 100644
--- a/src/mesh/Connectivity1D.hpp
+++ b/src/mesh/Connectivity1D.hpp
@@ -16,10 +16,11 @@ public:
   static constexpr size_t dimension = 1;
   ConnectivityMatrix m_node_to_cell_matrix;
   ConnectivityMatrix m_node_to_cell_local_node_matrix;
+
 private:
   std::vector<RefNodeList> m_ref_node_list;
 
-  const size_t  m_number_of_cells;
+  const size_t m_number_of_cells;
 
   const Kokkos::View<const unsigned int**> m_cell_nodes;
   const Kokkos::View<const unsigned int**>& m_cell_faces = m_cell_nodes;
@@ -28,7 +29,7 @@ private:
   Kokkos::View<double*> m_inv_cell_nb_nodes;
   const Kokkos::View<const unsigned short*>& m_cell_nb_faces = m_cell_nb_nodes;
 
-  size_t  m_max_nb_node_per_cell;
+  size_t m_max_nb_node_per_cell;
 
   const Kokkos::View<const unsigned int**>
   _buildCellNodes(const size_t& number_of_cells)
diff --git a/src/mesh/Connectivity2D.hpp b/src/mesh/Connectivity2D.hpp
index ef2ce6926710807e37b9dd3e7ed3944496b895e6..b0555d9d290a26e2482f02dbebd98a865a564189 100644
--- a/src/mesh/Connectivity2D.hpp
+++ b/src/mesh/Connectivity2D.hpp
@@ -21,6 +21,8 @@ class Connectivity2D
 
   ConnectivityMatrix m_node_to_cell_matrix;
   ConnectivityMatrix m_node_to_cell_local_node_matrix;
+  ConnectivityMatrix m_face_to_cell_matrix;
+  ConnectivityMatrix m_face_to_node_matrix;
 
  private:
   std::vector<RefFaceList> m_ref_face_list;
@@ -36,12 +38,7 @@ class Connectivity2D
   Kokkos::View<const unsigned short*> m_cell_nb_faces;
   Kokkos::View<unsigned int**> m_cell_faces;
 
-  Kokkos::View<unsigned short*> m_face_nb_cells;
-  Kokkos::View<unsigned int**> m_face_cells;
   Kokkos::View<unsigned short**> m_face_cell_local_face;
-
-  Kokkos::View<unsigned short*> m_face_nb_nodes;
-  Kokkos::View<unsigned int**> m_face_nodes;
   Kokkos::View<unsigned short**> m_face_node_local_face;
 
   size_t  m_max_nb_node_per_cell;
@@ -102,48 +99,32 @@ class Connectivity2D
     }
 
     m_number_of_faces = face_cells_map.size();
-    Kokkos::View<unsigned short*> face_nb_nodes("face_nb_nodes", m_number_of_faces);
-    Kokkos::parallel_for(m_number_of_faces, KOKKOS_LAMBDA(const unsigned int& l) {
-        face_nb_nodes[l] = 2;
-      });
-    m_face_nb_nodes = face_nb_nodes;
 
-    Kokkos::View<unsigned int**> face_nodes("face_nodes", m_number_of_faces, 2);
     {
+      std::vector<std::vector<unsigned int>> face_to_node_vector(face_cells_map.size());
       int l=0;
-      for (const auto& face_cells_vector : face_cells_map) {
-        const Face& face = face_cells_vector.first;
-        face_nodes(l,0) = face.m_node0_id;
-        face_nodes(l,1) = face.m_node1_id;
+      for (const auto& face_info : face_cells_map) {
+        const Face& face = face_info.first;
+        face_to_node_vector[l] = {face.m_node0_id, face.m_node1_id};
         ++l;
       }
+      m_face_to_node_matrix
+          = Kokkos::create_staticcrsgraph<ConnectivityMatrix>("face_to_node_matrix", face_to_node_vector);
     }
-    m_face_nodes = face_nodes;
 
-    Kokkos::View<unsigned short*> face_nb_cells("face_nb_cells", m_number_of_faces);
     {
+      std::vector<std::vector<unsigned int>> face_to_cell_vector(m_number_of_faces);
       int l=0;
       for (const auto& face_cells_vector : face_cells_map) {
-        const auto& cells_vector = face_cells_vector.second;
-        face_nb_cells[l] = cells_vector.size();
-        ++l;
-      }
-    }
-    m_face_nb_cells = face_nb_cells;
-
-    Kokkos::View<unsigned int**> face_cells("face_cells", face_cells_map.size(), 2);
-    {
-      int l=0;
-      for (const auto& face_cells_vector : face_cells_map) {
-        const auto& cells_vector = face_cells_vector.second;
-        for (unsigned short lj=0; lj<cells_vector.size(); ++lj) {
-          unsigned int cell_number = cells_vector[lj].first;
-          face_cells(l,lj) = cell_number;
+        const auto& [face, cell_info_vector] = face_cells_vector;
+        for (const auto& cell_info : cell_info_vector) {
+          face_to_cell_vector[l].push_back(cell_info.second);
         }
         ++l;
       }
+      m_face_to_cell_matrix
+          = Kokkos::create_staticcrsgraph<ConnectivityMatrix>("face_to_cell_matrix", face_to_cell_vector);
     }
-    m_face_cells = face_cells;
 
     // In 2d cell_nb_faces = cell_nb_node
     m_cell_nb_faces = m_cell_nb_nodes;
@@ -254,26 +235,6 @@ class Connectivity2D
     return m_cell_nb_faces;
   }
 
-  const Kokkos::View<const unsigned short*> faceNbCells() const
-  {
-    return m_face_nb_cells;
-  }
-
-  const Kokkos::View<const unsigned short*> faceNbNodes() const
-  {
-    return m_face_nb_nodes;
-  }
-
-  const Kokkos::View<const unsigned int**> faceCells() const
-  {
-    return m_face_cells;
-  }
-
-  const Kokkos::View<const unsigned int**> faceNodes() const
-  {
-    return m_face_nodes;
-  }
-
   const Kokkos::View<const unsigned short**> faceCellLocalFace() const
   {
     return m_face_cell_local_face;
@@ -287,7 +248,8 @@ class Connectivity2D
     const unsigned int n1_id = std::max(node0_id, node1_id);
     // worst code ever
     for (unsigned int l=0; l<m_number_of_faces; ++l) {
-      if ((m_face_nodes(l,0) == n0_id) and (m_face_nodes(l,1) == n1_id)) {
+      const auto& face_nodes = m_face_to_node_matrix.rowConst(l);
+      if ((face_nodes(0) == n0_id) and (face_nodes(1) == n1_id)) {
         return l;
       }
     }
diff --git a/src/mesh/Connectivity3D.hpp b/src/mesh/Connectivity3D.hpp
index 973cbe43024140d91fedf53a4960e5994392257d..fb04e5f968553b22e2e4fabbda94295a5f20bd12 100644
--- a/src/mesh/Connectivity3D.hpp
+++ b/src/mesh/Connectivity3D.hpp
@@ -25,6 +25,7 @@ public:
   ConnectivityMatrix m_node_to_cell_matrix;
   ConnectivityMatrix m_node_to_cell_local_node_matrix;
   ConnectivityMatrix m_face_to_cell_matrix;
+  ConnectivityMatrix m_face_to_node_matrix;
 
 private:
   std::vector<RefFaceList> m_ref_face_list;
@@ -41,17 +42,10 @@ private:
   Kokkos::View<const unsigned int**> m_cell_faces;
   Kokkos::View<const bool**> m_cell_faces_is_reversed;
 
-  Kokkos::View<const unsigned short*> m_face_nb_cells;
-  Kokkos::View<const unsigned int**> m_face_cells;
   Kokkos::View<const unsigned short**> m_face_cell_local_face;
 
-  Kokkos::View<const unsigned short*> m_face_nb_nodes;
-  Kokkos::View<const unsigned int**> m_face_nodes;
-  //  Kokkos::View<unsigned short**> m_face_node_local_face;
-
   Kokkos::View<const unsigned short*> m_node_nb_faces;
   Kokkos::View<const unsigned int**> m_node_faces;
-  //  Kokkos::View<unsigned short**> m_node_face_local_node;
 
   size_t m_max_nb_node_per_cell;
   size_t m_max_nb_face_per_cell;
@@ -168,7 +162,7 @@ private:
     ~Face() = default;
   };
 
-  std::unordered_map<Face,unsigned int, Face::Hash> m_face_number_map;
+  std::unordered_map<Face, unsigned int, Face::Hash> m_face_number_map;
 
   void _computeFaceCellConnectivities()
   {
@@ -267,34 +261,28 @@ private:
 
     std::cerr << __FILE__ << ':' << __LINE__ << ':'
               << rang::fg::red << " m_max_nb_node_per_face forced to 4" << rang::fg::reset << '\n';
-    Kokkos::View<unsigned short*> face_nb_nodes("face_nb_nodes", m_number_of_faces);
-    m_max_nb_node_per_face = 4;
-    Kokkos::View<unsigned int**> face_nodes("face_nodes", m_number_of_faces, m_max_nb_node_per_face);
+
     {
+      std::vector<std::vector<unsigned int>> face_to_node_vector(face_cells_map.size());
       int l=0;
-      for (const auto& face_cells_vector : face_cells_map) {
-        const Face& face = face_cells_vector.first;
-        for(size_t r=0; r<face.nodeIdList().size(); ++r) {
-          face_nodes(l,r) = face.nodeIdList()[r];
-        }
-        face_nb_nodes[l] = face.nodeIdList().size();
-        m_face_number_map[face] = l;
+      for (const auto& face_info : face_cells_map) {
+        const Face& face = face_info.first;
+        face_to_node_vector[l] = face.nodeIdList();
         ++l;
       }
+      m_face_to_node_matrix
+          = Kokkos::create_staticcrsgraph<ConnectivityMatrix>("face_to_node_matrix", face_to_node_vector);
     }
-    m_face_nodes = face_nodes;
-    m_face_nb_nodes = face_nb_nodes;
 
-    Kokkos::View<unsigned short*> face_nb_cells("face_nb_cells", m_number_of_faces);
+    m_max_nb_node_per_face = 4;
     {
       int l=0;
       for (const auto& face_cells_vector : face_cells_map) {
-        const auto& cells_vector = face_cells_vector.second;
-        face_nb_cells[l] = cells_vector.size();
+        const Face& face = face_cells_vector.first;
+        m_face_number_map[face] = l;
         ++l;
       }
     }
-    m_face_nb_cells = face_nb_cells;
 
     std::vector<std::vector<unsigned int>> face_to_cell_vector(m_number_of_faces);
     {
@@ -315,20 +303,6 @@ private:
         = Kokkos::create_staticcrsgraph<ConnectivityMatrix>("face_to_cell_matrix", face_to_cell_vector);
 #warning check that the number of cell per faces is <=2
 
-    Kokkos::View<unsigned int**> face_cells("face_cells", face_cells_map.size(), 2);
-    {
-      int l=0;
-      for (const auto& face_cells_vector : face_cells_map) {
-        const auto& cells_vector = face_cells_vector.second;
-        for (unsigned short lj=0; lj<cells_vector.size(); ++lj) {
-          const unsigned int cell_number = std::get<0>(cells_vector[lj]);
-          face_cells(l,lj) = cell_number;
-        }
-        ++l;
-      }
-    }
-    m_face_cells = face_cells;
-
     std::cerr << __FILE__ << ':' << __LINE__ << ':'
               << rang::fg::red << " m_max_nb_face_per_cell forced to 6" << rang::fg::reset << '\n';
     m_max_nb_face_per_cell = 6;
@@ -376,9 +350,10 @@ private:
     m_face_cell_local_face = face_cell_local_face;
 
     std::unordered_map<unsigned int, std::vector<unsigned int>> node_faces_map;
-    for (size_t l=0; l<m_number_of_faces; ++l) {
-      for (size_t lr=0; lr<face_nb_nodes(l); ++lr) {
-        const unsigned int r = face_nodes(l, lr);
+    for (size_t l=0; l<m_face_to_node_matrix.numRows(); ++l) {
+      const auto& face_nodes = m_face_to_node_matrix.rowConst(l);
+      for (size_t lr=0; lr<face_nodes.length; ++lr) {
+        const unsigned int r = face_nodes(lr);
         node_faces_map[r].push_back(l);
       }
     }
@@ -493,25 +468,15 @@ private:
     return m_cell_nb_faces;
   }
 
-  const Kokkos::View<const unsigned short*> faceNbCells() const
-  {
-    return m_face_nb_cells;
-  }
+  // const Kokkos::View<const unsigned short*> faceNbCells() const
+  // {
+  //   return m_face_nb_cells;
+  // }
 
-  const Kokkos::View<const unsigned short*> faceNbNodes() const
-  {
-    return m_face_nb_nodes;
-  }
-
-  const Kokkos::View<const unsigned int**> faceCells() const
-  {
-    return m_face_cells;
-  }
-
-  const Kokkos::View<const unsigned int**> faceNodes() const
-  {
-    return m_face_nodes;
-  }
+  // const Kokkos::View<const unsigned int**> faceCells() const
+  // {
+  //   return m_face_cells;
+  // }
 
   const Kokkos::View<const unsigned short**> faceCellLocalFace() const
   {
diff --git a/src/mesh/MeshData.hpp b/src/mesh/MeshData.hpp
index 59411b7f984f318e5af1e35745651208a046abd0..32ad3ec8ab8626f812bb1b93e5c2d8d8b72cde11 100644
--- a/src/mesh/MeshData.hpp
+++ b/src/mesh/MeshData.hpp
@@ -120,25 +120,22 @@ private:
 
       Kokkos::View<Rd**> Nlr("Nlr", m_mesh.connectivity().numberOfFaces(), m_mesh.connectivity().maxNbNodePerFace());
 
-      const Kokkos::View<const unsigned int**>& face_nodes
-          = m_mesh.connectivity().faceNodes();
-      const Kokkos::View<const unsigned short*>& face_nb_nodes
-          = m_mesh.connectivity().faceNbNodes();
       Kokkos::parallel_for(m_mesh.numberOfFaces(), KOKKOS_LAMBDA(const int& l) {
-          const size_t nb_nodes = face_nb_nodes[l];
+          const auto& face_nodes = m_mesh.connectivity().m_face_to_node_matrix.rowConst(l);
+          const size_t nb_nodes = face_nodes.length;
           std::vector<Rd> dxr(nb_nodes);
           for (size_t r=0; r<nb_nodes; ++r) {
-            dxr[r] = xr[face_nodes(l,(r+1)%nb_nodes)] - xr[face_nodes(l,(r+nb_nodes-1)%nb_nodes)];
+            dxr[r] = xr[face_nodes((r+1)%nb_nodes)] - xr[face_nodes((r+nb_nodes-1)%nb_nodes)];
           }
           const double inv_12_nb_nodes = 1./(12.*nb_nodes);
           for (size_t r=0; r<nb_nodes; ++r) {
             Rd Nr = zero;
             const Rd two_dxr = 2*dxr[r];
             for (size_t s=0; s<nb_nodes; ++s) {
-              Nr += crossProduct((two_dxr - dxr[s]), xr[face_nodes(l,s)]);
+              Nr += crossProduct((two_dxr - dxr[s]), xr[face_nodes(s)]);
             }
             Nr *= inv_12_nb_nodes;
-            Nr -= (1./6.)*crossProduct(dxr[r], xr[face_nodes(l,r)]);
+            Nr -= (1./6.)*crossProduct(dxr[r], xr[face_nodes(r)]);
             Nlr(l,r) = Nr;
           }
         });
@@ -161,13 +158,14 @@ private:
           }
           for (size_t L=0; L<cell_nb_faces[j]; ++L) {
             const size_t l = cell_faces(j, L);
+            const auto& face_nodes = m_mesh.connectivity().m_face_to_node_matrix.rowConst(l);
             if (cell_faces_is_reversed(j, L)) {
-              for (size_t rl = 0; rl<face_nb_nodes[l]; ++rl) {
-                m_Cjr(j, node_id_to_local[face_nodes(l,rl)]) -= Nlr(l, rl);
+              for (size_t rl = 0; rl<face_nodes.length; ++rl) {
+                m_Cjr(j, node_id_to_local[face_nodes(rl)]) -= Nlr(l,rl);
               }
             } else {
-              for (size_t rl = 0; rl<face_nb_nodes[l]; ++rl) {
-                m_Cjr(j, node_id_to_local[face_nodes(l,rl)]) += Nlr(l, rl);
+              for (size_t rl = 0; rl<face_nodes.length; ++rl) {
+                m_Cjr(j, node_id_to_local[face_nodes(rl)]) += Nlr(l, rl);
               }
             }
           }
diff --git a/src/mesh/MeshNodeBoundary.hpp b/src/mesh/MeshNodeBoundary.hpp
index 7da1a102496dc3ec8226fe31099279edda861f50..4349a0a5b67dc372030603f17dd3d680dde6eae4 100644
--- a/src/mesh/MeshNodeBoundary.hpp
+++ b/src/mesh/MeshNodeBoundary.hpp
@@ -28,26 +28,24 @@ class MeshNodeBoundary
                    const RefFaceList& ref_face_list)
   {
     static_assert(dimension == MeshType::dimension);
-    const Kokkos::View<const unsigned short*> face_nb_cells = mesh.connectivity().faceNbCells();
-
     const Kokkos::View<const unsigned int*>& face_list = ref_face_list.faceList();
     Kokkos::parallel_for(face_list.extent(0), KOKKOS_LAMBDA(const int& l){
-        if (face_nb_cells[face_list[l]]>1) {
+        const auto& face_cells = mesh.connectivity().m_face_to_cell_matrix.rowConst(face_list[l]);
+        if (face_cells.length>1) {
           std::cerr << "internal faces cannot be used to define mesh boundaries\n";
           std::exit(1);
         }
       });
 
-    const Kokkos::View<const unsigned short*> face_nb_nodes = mesh.connectivity().faceNbNodes();
-    const Kokkos::View<const unsigned int**> face_nodes = mesh.connectivity().faceNodes();
-
     std::vector<unsigned int> node_ids;
     // not enough but should reduce significantly the number of resizing
     node_ids.reserve(dimension*face_list.extent(0));
     for (size_t l=0; l<face_list.extent(0); ++l) {
       const size_t face_number = face_list[l];
-      for (size_t r=0; r<face_nb_nodes[face_number]; ++r) {
-        node_ids.push_back(face_nodes(face_number,r));
+      const auto& face_nodes = mesh.connectivity().m_face_to_node_matrix.rowConst(face_number);
+
+      for (size_t r=0; r<face_nodes.length; ++r) {
+        node_ids.push_back(face_nodes(r));
       }
     }
     std::sort(node_ids.begin(), node_ids.end());