diff --git a/src/mesh/ConnectivityToDiamondDualConnectivityDataMapper.hpp b/src/mesh/ConnectivityToDiamondDualConnectivityDataMapper.hpp
index 8d35d2ff9541fbfab7e8e6e30976bd5f88970f56..ae67abf3c10b977b2ecaac8e8eda71cf4f99492e 100644
--- a/src/mesh/ConnectivityToDiamondDualConnectivityDataMapper.hpp
+++ b/src/mesh/ConnectivityToDiamondDualConnectivityDataMapper.hpp
@@ -2,23 +2,14 @@
 #define CONNECTIVITY_TO_DIAMOND_DUAL_CONNECTIVITY_DATA_MAPPER_HPP
 
 #include <mesh/Connectivity.hpp>
+#include <mesh/IConnectivityToDualConnectivityDataMapper.hpp>
 #include <mesh/ItemIdToItemIdMap.hpp>
 #include <mesh/ItemValue.hpp>
 #include <utils/Array.hpp>
 #include <utils/PugsAssert.hpp>
 
-class IConnectivityToDiamondDualConnectivityDataMapper
-{
- public:
-  IConnectivityToDiamondDualConnectivityDataMapper(const IConnectivityToDiamondDualConnectivityDataMapper&) = delete;
-  IConnectivityToDiamondDualConnectivityDataMapper(IConnectivityToDiamondDualConnectivityDataMapper&&)      = delete;
-
-  IConnectivityToDiamondDualConnectivityDataMapper()          = default;
-  virtual ~IConnectivityToDiamondDualConnectivityDataMapper() = default;
-};
-
 template <size_t Dimension>
-class ConnectivityToDiamondDualConnectivityDataMapper : public IConnectivityToDiamondDualConnectivityDataMapper
+class ConnectivityToDiamondDualConnectivityDataMapper : public IConnectivityToDualConnectivityDataMapper
 {
  private:
   const IConnectivity* m_primal_connectivity;
diff --git a/src/mesh/DiamondDualConnectivityBuilder.hpp b/src/mesh/DiamondDualConnectivityBuilder.hpp
index f6768af63fd7c4ab9f03370acdb9dcdeb64e864c..1ce888e24d9aaff77a60ad68cfafe4f74fe0b678 100644
--- a/src/mesh/DiamondDualConnectivityBuilder.hpp
+++ b/src/mesh/DiamondDualConnectivityBuilder.hpp
@@ -2,6 +2,7 @@
 #define DIAMOND_DUAL_CONNECTIVITY_BUILDER_HPP
 
 #include <mesh/ConnectivityBuilderBase.hpp>
+#include <mesh/IConnectivityToDualConnectivityDataMapper.hpp>
 #include <mesh/ItemIdToItemIdMap.hpp>
 
 #include <memory>
@@ -10,8 +11,6 @@ template <size_t>
 class Connectivity;
 class ConnectivityDescriptor;
 
-class IConnectivityToDiamondDualConnectivityDataMapper;
-
 class DiamondDualConnectivityBuilder : public ConnectivityBuilderBase
 {
  private:
@@ -19,7 +18,7 @@ class DiamondDualConnectivityBuilder : public ConnectivityBuilderBase
   CellIdToNodeIdMap m_primal_cell_to_dual_node_map;
   FaceIdToCellIdMap m_primal_face_to_dual_cell_map;
 
-  std::shared_ptr<IConnectivityToDiamondDualConnectivityDataMapper> m_mapper;
+  std::shared_ptr<IConnectivityToDualConnectivityDataMapper> m_mapper;
 
   template <size_t Dimension>
   void _buildDiamondConnectivityDescriptor(const Connectivity<Dimension>&, ConnectivityDescriptor&);
@@ -31,7 +30,7 @@ class DiamondDualConnectivityBuilder : public ConnectivityBuilderBase
   DiamondDualConnectivityBuilder(const IConnectivity&);
 
  public:
-  std::shared_ptr<IConnectivityToDiamondDualConnectivityDataMapper>
+  std::shared_ptr<IConnectivityToDualConnectivityDataMapper>
   mapper() const
   {
     return m_mapper;
diff --git a/src/mesh/DualConnectivityManager.cpp b/src/mesh/DualConnectivityManager.cpp
index c3a2011d8b2f8517cf9072edf6dbbf75e4a4e2e3..60a4279810ccdb19c3ff6f160a87839e09fb872b 100644
--- a/src/mesh/DualConnectivityManager.cpp
+++ b/src/mesh/DualConnectivityManager.cpp
@@ -22,12 +22,13 @@ DualConnectivityManager::destroy()
 {
   Assert(m_instance != nullptr, "DualConnectivityManager was not created!");
 
-  if (m_instance->m_connectivity_to_diamond_dual_connectivity_info_map.size() > 0) {
+  if (m_instance->m_connectivity_to_dual_connectivity_info_map.size() > 0) {
     std::stringstream error;
     error << ": some connectivities are still registered\n";
-    for (const auto& [connectivity, diamond_dual_connectivity_info] :
-         m_instance->m_connectivity_to_diamond_dual_connectivity_info_map) {
-      error << " - connectivity " << rang::fgB::magenta << connectivity << rang::style::reset << '\n';
+    for (const auto& [key, diamond_dual_connectivity_info] : m_instance->m_connectivity_to_dual_connectivity_info_map) {
+      error << " - connectivity " << rang::fgB::magenta << key.second << rang::style::reset << ": " << name(key.first)
+            << " dual connectivity of " << rang::fgB::yellow << diamond_dual_connectivity_info.dualConnectivity().get()
+            << rang::style::reset << '\n';
     }
     throw UnexpectedError(error.str());
   }
@@ -38,23 +39,35 @@ DualConnectivityManager::destroy()
 void
 DualConnectivityManager::deleteConnectivity(const IConnectivity* p_connectivity)
 {
-  m_connectivity_to_diamond_dual_connectivity_info_map.erase(p_connectivity);
+  bool has_removed = false;
+  do {
+    has_removed = false;
+    for (const auto& [key, dual_connectivity] : m_connectivity_to_dual_connectivity_info_map) {
+      const auto& [type, p_parent_connectivity] = key;
+      if (p_connectivity == p_parent_connectivity) {
+        m_connectivity_to_dual_connectivity_info_map.erase(key);
+        has_removed = true;
+        break;
+      }
+    }
+  } while (has_removed);
 }
 
-DualConnectivityManager::DiamondDualConnectivityInfo
-DualConnectivityManager::_getDiamondDualConnectivityInfo(const IConnectivity& connectivity)
+DualConnectivityManager::DualConnectivityInfo
+DualConnectivityManager::_getDualConnectivityInfo(const DualMeshType& type, const IConnectivity& connectivity)
 {
   const IConnectivity* p_connectivity = &connectivity;
 
-  if (auto i_connectivity = m_connectivity_to_diamond_dual_connectivity_info_map.find(p_connectivity);
-      i_connectivity != m_connectivity_to_diamond_dual_connectivity_info_map.end()) {
+  auto key = std::make_pair(type, p_connectivity);
+  if (auto i_connectivity = m_connectivity_to_dual_connectivity_info_map.find(key);
+      i_connectivity != m_connectivity_to_dual_connectivity_info_map.end()) {
     return i_connectivity->second;
   } else {
     DiamondDualConnectivityBuilder builder{connectivity};
 
-    DiamondDualConnectivityInfo connectivity_info{builder.connectivity(), builder.mapper()};
+    DualConnectivityInfo connectivity_info{builder.connectivity(), builder.mapper()};
 
-    m_connectivity_to_diamond_dual_connectivity_info_map[p_connectivity] = connectivity_info;
+    m_connectivity_to_dual_connectivity_info_map[key] = connectivity_info;
 
     return connectivity_info;
   }
@@ -65,15 +78,23 @@ std::shared_ptr<const Connectivity<Dimension>>
 DualConnectivityManager::getDiamondDualConnectivity(const Connectivity<Dimension>& connectivity)
 {
   return std::dynamic_pointer_cast<const Connectivity<Dimension>>(
-    this->_getDiamondDualConnectivityInfo(connectivity).diamondDualConnectivity());
+    this->_getDualConnectivityInfo(DualMeshType::Diamond, connectivity).dualConnectivity());
 }
 
 template <size_t Dimension>
 std::shared_ptr<const ConnectivityToDiamondDualConnectivityDataMapper<Dimension>>
 DualConnectivityManager::getConnectivityToDiamondDualConnectivityDataMapper(const Connectivity<Dimension>& connectivity)
 {
-  return std::dynamic_pointer_cast<const ConnectivityToDiamondDualConnectivityDataMapper<Dimension>>(
-    this->_getDiamondDualConnectivityInfo(connectivity).connectivityToDiamondDualConnectivityDataMapper());
+  auto i_data_mapper =
+    this->_getDualConnectivityInfo(DualMeshType::Diamond, connectivity).connectivityToDualConnectivityDataMapper();
+  auto diamond_data_mapper =
+    std::dynamic_pointer_cast<const ConnectivityToDiamondDualConnectivityDataMapper<Dimension>>(i_data_mapper);
+
+  if (diamond_data_mapper.use_count() > 0) {
+    return diamond_data_mapper;
+  } else {
+    throw UnexpectedError("invalid connectivity data mapper type");
+  }
 }
 
 template std::shared_ptr<const Connectivity<1>> DualConnectivityManager::getDiamondDualConnectivity(
diff --git a/src/mesh/DualConnectivityManager.hpp b/src/mesh/DualConnectivityManager.hpp
index ef2812ea75c9271c3607d55d2414a7e45e27a245..eb6e0cad10862df32bf330deefab00b5c7aaf658 100644
--- a/src/mesh/DualConnectivityManager.hpp
+++ b/src/mesh/DualConnectivityManager.hpp
@@ -1,7 +1,9 @@
 #ifndef DUAL_CONNECTIVITY_MANAGER_HPP
 #define DUAL_CONNECTIVITY_MANAGER_HPP
 
+#include <mesh/DualMeshType.hpp>
 #include <mesh/IConnectivity.hpp>
+#include <mesh/IConnectivityToDualConnectivityDataMapper.hpp>
 
 #include <memory>
 #include <unordered_map>
@@ -9,57 +11,63 @@
 template <size_t Dimension>
 class Connectivity;
 
-class IConnectivityToDiamondDualConnectivityDataMapper;
-
 template <size_t Dimension>
 class ConnectivityToDiamondDualConnectivityDataMapper;
 
 class DualConnectivityManager
 {
  private:
-  class DiamondDualConnectivityInfo
+  class DualConnectivityInfo
   {
    private:
-    std::shared_ptr<const IConnectivity> m_diamond_dual_connectivity;
-    std::shared_ptr<const IConnectivityToDiamondDualConnectivityDataMapper>
-      m_connectivity_to_diamond_dual_connectivity_data_mapper;
+    std::shared_ptr<const IConnectivity> m_dual_connectivity;
+    std::shared_ptr<const IConnectivityToDualConnectivityDataMapper> m_connectivity_to_dual_connectivity_data_mapper;
 
    public:
     PUGS_INLINE
     std::shared_ptr<const IConnectivity>
-    diamondDualConnectivity() const
+    dualConnectivity() const
     {
-      return m_diamond_dual_connectivity;
+      return m_dual_connectivity;
     }
 
     PUGS_INLINE
-    std::shared_ptr<const IConnectivityToDiamondDualConnectivityDataMapper>
-    connectivityToDiamondDualConnectivityDataMapper()
+    std::shared_ptr<const IConnectivityToDualConnectivityDataMapper>
+    connectivityToDualConnectivityDataMapper()
     {
-      return m_connectivity_to_diamond_dual_connectivity_data_mapper;
+      return m_connectivity_to_dual_connectivity_data_mapper;
     }
 
-    DiamondDualConnectivityInfo& operator=(const DiamondDualConnectivityInfo&) = default;
-    DiamondDualConnectivityInfo& operator=(DiamondDualConnectivityInfo&&) = default;
+    DualConnectivityInfo& operator=(const DualConnectivityInfo&) = default;
+    DualConnectivityInfo& operator=(DualConnectivityInfo&&) = default;
 
-    DiamondDualConnectivityInfo()                                   = default;
-    DiamondDualConnectivityInfo(const DiamondDualConnectivityInfo&) = default;
-    DiamondDualConnectivityInfo(DiamondDualConnectivityInfo&&)      = default;
+    DualConnectivityInfo()                            = default;
+    DualConnectivityInfo(const DualConnectivityInfo&) = default;
+    DualConnectivityInfo(DualConnectivityInfo&&)      = default;
 
-    DiamondDualConnectivityInfo(const std::shared_ptr<const IConnectivity>& diamond_dual_connectivity,
-                                const std::shared_ptr<const IConnectivityToDiamondDualConnectivityDataMapper>&
-                                  connectivity_to_diamond_dual_connectivity_data_mapper)
-      : m_diamond_dual_connectivity{diamond_dual_connectivity},
-        m_connectivity_to_diamond_dual_connectivity_data_mapper{connectivity_to_diamond_dual_connectivity_data_mapper}
+    DualConnectivityInfo(const std::shared_ptr<const IConnectivity>& dual_connectivity,
+                         const std::shared_ptr<const IConnectivityToDualConnectivityDataMapper>&
+                           connectivity_to_dual_connectivity_data_mapper)
+      : m_dual_connectivity{dual_connectivity},
+        m_connectivity_to_dual_connectivity_data_mapper{connectivity_to_dual_connectivity_data_mapper}
     {}
 
-    ~DiamondDualConnectivityInfo() = default;
+    ~DualConnectivityInfo() = default;
   };
 
-  DiamondDualConnectivityInfo _getDiamondDualConnectivityInfo(const IConnectivity& connectivity);
+  DualConnectivityInfo _getDualConnectivityInfo(const DualMeshType& type, const IConnectivity& connectivity);
+
+  using Key = std::pair<DualMeshType, const IConnectivity*>;
+  struct HashKey
+  {
+    size_t
+    operator()(const Key& key) const
+    {
+      return (std::hash<typename Key::first_type>()(key.first)) ^ (std::hash<typename Key::second_type>()(key.second));
+    }
+  };
 
-  std::unordered_map<const IConnectivity*, DiamondDualConnectivityInfo>
-    m_connectivity_to_diamond_dual_connectivity_info_map;
+  std::unordered_map<Key, DualConnectivityInfo, HashKey> m_connectivity_to_dual_connectivity_info_map;
 
   static DualConnectivityManager* m_instance;
 
diff --git a/src/mesh/DualMeshManager.cpp b/src/mesh/DualMeshManager.cpp
index 683cfbfb9c79af995c333b9b39ca05145f4bbe3c..cf903145b65709d53aec0210b731c57e51fe878d 100644
--- a/src/mesh/DualMeshManager.cpp
+++ b/src/mesh/DualMeshManager.cpp
@@ -22,11 +22,12 @@ DualMeshManager::destroy()
 {
   Assert(m_instance != nullptr, "DualMeshManager was not created!");
 
-  if (m_instance->m_mesh_to_diamond_dual_mesh_map.size() > 0) {
+  if (m_instance->m_mesh_to_dual_mesh_map.size() > 0) {
     std::stringstream error;
     error << ": some meshes are still registered\n";
-    for (const auto& i_mesh_data : m_instance->m_mesh_to_diamond_dual_mesh_map) {
-      error << " - mesh " << rang::fgB::magenta << i_mesh_data.first << rang::style::reset << '\n';
+    for (const auto& [key, parent_mesh] : m_instance->m_mesh_to_dual_mesh_map) {
+      error << " - mesh " << rang::fgB::magenta << key.second << rang::style::reset << ": " << name(key.first)
+            << " dual mesh of " << rang::fgB::yellow << parent_mesh.get() << rang::style::reset << '\n';
     }
     throw UnexpectedError(error.str());
   }
@@ -37,7 +38,18 @@ DualMeshManager::destroy()
 void
 DualMeshManager::deleteMesh(const IMesh* p_mesh)
 {
-  m_mesh_to_diamond_dual_mesh_map.erase(p_mesh);
+  bool has_removed = false;
+  do {
+    has_removed = false;
+    for (const auto& [key, dual_mesh] : m_mesh_to_dual_mesh_map) {
+      const auto& [type, p_parent_mesh] = key;
+      if (p_mesh == p_parent_mesh) {
+        m_mesh_to_dual_mesh_map.erase(key);
+        has_removed = true;
+        break;
+      }
+    }
+  } while (has_removed);
 }
 
 template <size_t Dimension>
@@ -46,13 +58,13 @@ DualMeshManager::getDiamondDualMesh(std::shared_ptr<const Mesh<Connectivity<Dime
 {
   const IMesh* p_mesh = mesh.get();
 
-  if (auto i_mesh_data = m_mesh_to_diamond_dual_mesh_map.find(p_mesh);
-      i_mesh_data != m_mesh_to_diamond_dual_mesh_map.end()) {
+  auto key = std::make_pair(DualMeshType::Diamond, p_mesh);
+  if (auto i_mesh_data = m_mesh_to_dual_mesh_map.find(key); i_mesh_data != m_mesh_to_dual_mesh_map.end()) {
     return std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(i_mesh_data->second);
   } else {
     DiamondDualMeshBuilder builder{mesh};
 
-    m_mesh_to_diamond_dual_mesh_map[p_mesh] = builder.mesh();
+    m_mesh_to_dual_mesh_map[key] = builder.mesh();
     return std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(builder.mesh());
   }
 }
diff --git a/src/mesh/DualMeshManager.hpp b/src/mesh/DualMeshManager.hpp
index 5ae476ff314a00186a0dcc6bea12b87258508117..e2b92b599254bbac404478fd590df6747281ae29 100644
--- a/src/mesh/DualMeshManager.hpp
+++ b/src/mesh/DualMeshManager.hpp
@@ -1,6 +1,7 @@
 #ifndef DUAL_MESH_MANAGER_HPP
 #define DUAL_MESH_MANAGER_HPP
 
+#include <mesh/DualMeshType.hpp>
 #include <mesh/IMesh.hpp>
 #include <utils/PugsAssert.hpp>
 #include <utils/PugsMacros.hpp>
@@ -14,16 +15,20 @@ class Connectivity;
 template <typename ConnectivityType>
 class Mesh;
 
-enum class DualMeshType
-{
-  Diamond,
-  Classic
-};
-
 class DualMeshManager
 {
  private:
-  std::unordered_map<const IMesh*, std::shared_ptr<const IMesh>> m_mesh_to_diamond_dual_mesh_map;
+  using Key = std::pair<DualMeshType, const IMesh*>;
+  struct HashKey
+  {
+    size_t
+    operator()(const Key& key) const
+    {
+      return (std::hash<typename Key::first_type>()(key.first)) ^ (std::hash<typename Key::second_type>()(key.second));
+    }
+  };
+
+  std::unordered_map<Key, std::shared_ptr<const IMesh>, HashKey> m_mesh_to_dual_mesh_map;
 
   static DualMeshManager* m_instance;
 
diff --git a/src/mesh/DualMeshType.hpp b/src/mesh/DualMeshType.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..5e599a0004fd44a1ab9375d07315f3bd8225c797
--- /dev/null
+++ b/src/mesh/DualMeshType.hpp
@@ -0,0 +1,32 @@
+#ifndef DUAL_MESH_TYPE_HPP
+#define DUAL_MESH_TYPE_HPP
+
+#include <utils/Exceptions.hpp>
+#include <utils/PugsMacros.hpp>
+
+#include <string>
+
+enum class DualMeshType
+{
+  Classic,
+  Diamond
+};
+
+PUGS_INLINE
+std::string
+name(DualMeshType type)
+{
+  switch (type) {
+  case DualMeshType::Classic: {
+    return "classic";
+  }
+  case DualMeshType::Diamond: {
+    return "diamond";
+  }
+  default: {
+    throw UnexpectedError("unexpected dual mesh type");
+  }
+  }
+}
+
+#endif   // DUAL_MESH_TYPE_HPP
diff --git a/src/mesh/IConnectivityToDualConnectivityDataMapper.hpp b/src/mesh/IConnectivityToDualConnectivityDataMapper.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..4248a15665d2e3acd6dafc4f2081f8bec7f03dfd
--- /dev/null
+++ b/src/mesh/IConnectivityToDualConnectivityDataMapper.hpp
@@ -0,0 +1,14 @@
+#ifndef I_CONNECTIVITY_TO_DUAL_CONNECTIVITY_DATA_MAPPER_HPP
+#define I_CONNECTIVITY_TO_DUAL_CONNECTIVITY_DATA_MAPPER_HPP
+
+class IConnectivityToDualConnectivityDataMapper
+{
+ public:
+  IConnectivityToDualConnectivityDataMapper(const IConnectivityToDualConnectivityDataMapper&) = delete;
+  IConnectivityToDualConnectivityDataMapper(IConnectivityToDualConnectivityDataMapper&&)      = delete;
+
+  IConnectivityToDualConnectivityDataMapper()          = default;
+  virtual ~IConnectivityToDualConnectivityDataMapper() = default;
+};
+
+#endif   // I_CONNECTIVITY_TO_DUAL_CONNECTIVITY_DATA_MAPPER_HPP