diff --git a/CMakeLists.txt b/CMakeLists.txt
index efae190259dbe130993eb92eb1bfa43c48a6e967..caeef4763474054fec31ada62b9580db7643f6f6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -264,5 +264,5 @@ target_link_libraries(
   kokkos
   ${PARMETIS_LIBRARIES}
   ${MPI_CXX_LINK_FLAGS} ${MPI_CXX_LIBRARIES}
-  PastisUtils
-  PastisMesh)
+  PastisMesh
+  PastisUtils)
diff --git a/src/mesh/Connectivity.hpp b/src/mesh/Connectivity.hpp
index f876f70e11727c20fb72050da96a41bde8fe2f75..3c0405952f8254344b518e6a4ef72fe5fb0bb2b3 100644
--- a/src/mesh/Connectivity.hpp
+++ b/src/mesh/Connectivity.hpp
@@ -25,6 +25,8 @@
 
 #include <CellType.hpp>
 
+#include <CSRGraph.hpp>
+
 #include <RefId.hpp>
 #include <ItemType.hpp>
 #include <RefNodeList.hpp>
@@ -32,6 +34,7 @@
 
 #include <tuple>
 #include <algorithm>
+#include <set>
 
 template <size_t Dimension>
 class Connectivity;
@@ -530,6 +533,42 @@ class Connectivity final
     return m_ref_node_list[i];
   }
 
+  PASTIS_INLINE
+  CSRGraph cellToCellGraph() const
+  {
+    std::vector<std::set<int>> cell_cells(this->numberOfCells());
+    const auto& face_to_cell_matrix
+        = this->faceToCellMatrix();
+
+    for (FaceId l=0; l<this->numberOfFaces(); ++l) {
+      const auto& face_to_cell = face_to_cell_matrix[l];
+      if (face_to_cell.size() == 2) {
+        const int cell_0 = face_to_cell[0];
+        const int cell_1 = face_to_cell[1];
+
+        cell_cells[cell_0].insert(cell_1);
+        cell_cells[cell_1].insert(cell_0);
+      }
+    }
+
+    Array<int> entries(this->numberOfCells()+1);
+    entries[0]=0;
+    for (size_t j=0; j<this->numberOfCells(); ++j) {
+      entries[j+1] = entries[j]+cell_cells[j].size();
+    }
+    Array<int> neighbors(entries[this->numberOfCells()]);
+    {
+      size_t k=0;
+      for (size_t j=0; j<this->numberOfCells(); ++j) {
+        for (auto cell_id : cell_cells[j]) {
+          neighbors[k] = cell_id;
+          ++k;
+        }
+      }
+    }
+    return CSRGraph(entries, neighbors);
+  }
+
   PASTIS_INLINE
   size_t numberOfNodes() const final
   {
diff --git a/src/mesh/Mesh.hpp b/src/mesh/Mesh.hpp
index c21910e7a5bb24f08ec1106db08793912ee0bc7b..891d55400298eb413e41c3d7ae3372012ff4ae28 100644
--- a/src/mesh/Mesh.hpp
+++ b/src/mesh/Mesh.hpp
@@ -4,11 +4,14 @@
 #include <ItemValue.hpp>
 #include <TinyVector.hpp>
 
+#include <CSRGraph.hpp>
+
 #include <memory>
 
 struct IMesh
 {
   virtual const size_t meshDimension() const = 0;
+  virtual CSRGraph cellToCellGraph() const = 0;
   ~IMesh() = default;
 };
 
@@ -27,6 +30,12 @@ private:
   NodeValue<Rd> m_mutable_xr;
 
 public:
+  PASTIS_INLINE
+  CSRGraph cellToCellGraph() const final
+  {
+    return m_connectivity->cellToCellGraph();
+  }
+
   PASTIS_INLINE
   const size_t meshDimension() const
   {