diff --git a/src/mesh/ConnectivityToDiamondDualConnectivityDataMapper.hpp b/src/mesh/ConnectivityToDiamondDualConnectivityDataMapper.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..577bad4c499cd3aa91e6dd498c033b51ab0aac76
--- /dev/null
+++ b/src/mesh/ConnectivityToDiamondDualConnectivityDataMapper.hpp
@@ -0,0 +1,204 @@
+#ifndef CONNECTIVITY_TO_DIAMOND_DUAL_CONNECTIVITY_DATA_MAPPER_HPP
+#define CONNECTIVITY_TO_DIAMOND_DUAL_CONNECTIVITY_DATA_MAPPER_HPP
+
+#include <mesh/Connectivity.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
+{
+ private:
+  const IConnectivity* m_primal_connectivity;
+  const IConnectivity* m_dual_connectivity;
+
+  using NodeIdToNodeIdMap = Array<std::pair<NodeId, NodeId>>;
+  NodeIdToNodeIdMap m_primal_node_to_dual_node_map;
+
+  using CellIdToNodeIdMap = Array<std::pair<CellId, NodeId>>;
+  CellIdToNodeIdMap m_primal_cell_to_dual_node_map;
+
+  using FaceIdToCellIdMap = Array<std::pair<FaceId, CellId>>;
+  FaceIdToCellIdMap m_primal_face_to_dual_cell_map;
+
+ public:
+  template <typename OriginDataType1, typename OriginDataType2, typename DestinationDataType>
+  void
+  toDualNode(const NodeValue<OriginDataType1>& primal_node_value,
+             const CellValue<OriginDataType2>& primal_cell_value,
+             const NodeValue<DestinationDataType>& dual_node_value) const
+  {
+    static_assert(not std::is_const_v<DestinationDataType>, "destination data type must not be constant");
+    static_assert(std::is_same_v<std::remove_const_t<OriginDataType1>, DestinationDataType>, "incompatible types");
+    static_assert(std::is_same_v<std::remove_const_t<OriginDataType2>, DestinationDataType>, "incompatible types");
+
+    Assert(m_primal_connectivity == primal_cell_value.connectivity_ptr().get());
+    Assert(m_primal_connectivity == primal_node_value.connectivity_ptr().get());
+    Assert(m_dual_connectivity == dual_node_value.connectivity_ptr().get());
+
+    parallel_for(
+      m_primal_node_to_dual_node_map.size(), PUGS_LAMBDA(size_t i) {
+        const auto [primal_node_id, dual_node_id] = m_primal_node_to_dual_node_map[i];
+
+        dual_node_value[dual_node_id] = primal_node_value[primal_node_id];
+      });
+
+    parallel_for(
+      m_primal_cell_to_dual_node_map.size(), PUGS_LAMBDA(size_t i) {
+        const auto [primal_cell_id, dual_node_id] = m_primal_cell_to_dual_node_map[i];
+        dual_node_value[dual_node_id]             = primal_cell_value[primal_cell_id];
+      });
+  }
+
+  template <typename OriginDataType, typename DestinationDataType1, typename DestinationDataType2>
+  void
+  fromDualNode(const NodeValue<OriginDataType>& dual_node_value,
+               const NodeValue<DestinationDataType1>& primal_node_value,
+               const CellValue<DestinationDataType2>& primal_cell_value) const
+  {
+    static_assert(not std::is_const_v<DestinationDataType1>, "destination data type must not be constant");
+    static_assert(not std::is_const_v<DestinationDataType2>, "destination data type must not be constant");
+    static_assert(std::is_same_v<std::remove_const_t<OriginDataType>, DestinationDataType1>, "incompatible types");
+    static_assert(std::is_same_v<std::remove_const_t<OriginDataType>, DestinationDataType2>, "incompatible types");
+
+    Assert(m_primal_connectivity == primal_cell_value.connectivity_ptr().get());
+    Assert(m_primal_connectivity == primal_node_value.connectivity_ptr().get());
+    Assert(m_dual_connectivity == dual_node_value.connectivity_ptr().get());
+
+    parallel_for(
+      m_primal_node_to_dual_node_map.size(), PUGS_LAMBDA(size_t i) {
+        const auto [primal_node_id, dual_node_id] = m_primal_node_to_dual_node_map[i];
+
+        primal_node_value[primal_node_id] = dual_node_value[dual_node_id];
+      });
+
+    parallel_for(
+      m_primal_cell_to_dual_node_map.size(), PUGS_LAMBDA(size_t i) {
+        const auto [primal_cell_id, dual_node_id] = m_primal_cell_to_dual_node_map[i];
+        primal_cell_value[primal_cell_id]         = dual_node_value[dual_node_id];
+      });
+  }
+
+  template <typename OriginDataType, typename DestinationDataType>
+  void
+  toDualCell(const FaceValue<OriginDataType>& primal_face_value,
+             const CellValue<DestinationDataType>& dual_cell_value) const
+  {
+    static_assert(not std::is_const_v<DestinationDataType>, "destination data type must not be constant");
+    static_assert(std::is_same_v<std::remove_const_t<OriginDataType>, DestinationDataType>, "incompatible types");
+
+    Assert(m_primal_connectivity == primal_face_value.connectivity_ptr().get());
+    Assert(m_dual_connectivity == dual_cell_value.connectivity_ptr().get());
+
+    parallel_for(
+      m_primal_face_to_dual_cell_map.size(), PUGS_LAMBDA(size_t i) {
+        const auto [primal_face_id, dual_cell_id] = m_primal_face_to_dual_cell_map[i];
+
+        dual_cell_value[dual_cell_id] = primal_face_value[primal_face_id];
+      });
+
+    parallel_for(
+      m_primal_cell_to_dual_node_map.size(), PUGS_LAMBDA(size_t i) {
+        const auto [primal_face_id, dual_cell_id] = m_primal_face_to_dual_cell_map[i];
+
+        dual_cell_value[dual_cell_id] = primal_face_value[primal_face_id];
+      });
+  }
+
+  template <typename OriginDataType, typename DestinationDataType>
+  void
+  fromDualCell(const CellValue<DestinationDataType>& dual_cell_value,
+               const FaceValue<OriginDataType>& primal_face_value) const
+  {
+    static_assert(not std::is_const_v<DestinationDataType>, "destination data type must not be constant");
+    static_assert(std::is_same_v<std::remove_const_t<OriginDataType>, DestinationDataType>, "incompatible types");
+
+    Assert(m_primal_connectivity == primal_face_value.connectivity_ptr().get());
+    Assert(m_dual_connectivity == dual_cell_value.connectivity_ptr().get());
+
+    parallel_for(
+      m_primal_face_to_dual_cell_map.size(), PUGS_LAMBDA(size_t i) {
+        const auto [primal_face_id, dual_cell_id] = m_primal_face_to_dual_cell_map[i];
+
+        primal_face_value[primal_face_id] = dual_cell_value[dual_cell_id];
+      });
+
+    parallel_for(
+      m_primal_cell_to_dual_node_map.size(), PUGS_LAMBDA(size_t i) {
+        const auto [primal_face_id, dual_cell_id] = m_primal_face_to_dual_cell_map[i];
+        primal_face_value[primal_face_id]         = dual_cell_value[dual_cell_id];
+      });
+  }
+
+  ConnectivityToDiamondDualConnectivityDataMapper(const Connectivity<Dimension>& primal_connectivity,
+                                                  const Connectivity<Dimension>& dual_connectivity)
+    : m_primal_connectivity{&primal_connectivity}, m_dual_connectivity{&dual_connectivity}
+  {
+    if constexpr (Dimension == 1) {
+      const auto& node_to_cell_matrix = primal_connectivity.nodeToCellMatrix();
+
+      NodeId dual_node_id            = 0;
+      m_primal_node_to_dual_node_map = [&]() {
+        std::vector<std::pair<NodeId, NodeId>> primal_node_to_dual_node_vector;
+        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) {
+            primal_node_to_dual_node_vector.push_back(std::make_pair(primal_node_id, dual_node_id++));
+          }
+        }
+        return convert_to_array(primal_node_to_dual_node_vector);
+      }();
+
+      m_primal_cell_to_dual_node_map = [&]() {
+        CellIdToNodeIdMap primal_cell_to_dual_node_map{primal_connectivity.numberOfCells()};
+        for (CellId primal_cell_id = 0; primal_cell_id < primal_cell_to_dual_node_map.size(); ++primal_cell_id) {
+          primal_cell_to_dual_node_map[primal_cell_id] = std::make_pair(primal_cell_id, dual_node_id++);
+        }
+        return primal_cell_to_dual_node_map;
+      }();
+
+    } else {
+      m_primal_node_to_dual_node_map = [&]() {
+        NodeIdToNodeIdMap primal_node_to_dual_node_map{primal_connectivity.numberOfNodes()};
+        for (NodeId primal_node_id = 0; primal_node_id < primal_node_to_dual_node_map.size(); ++primal_node_id) {
+          const NodeId dual_node_id = primal_node_id;
+
+          primal_node_to_dual_node_map[primal_node_id] = std::make_pair(primal_node_id, dual_node_id);
+        }
+        return primal_node_to_dual_node_map;
+      }();
+
+      m_primal_cell_to_dual_node_map = [&]() {
+        CellIdToNodeIdMap primal_cell_to_dual_node_map{primal_connectivity.numberOfCells()};
+        NodeId dual_node_id = m_primal_node_to_dual_node_map.size();
+        for (CellId primal_cell_id = 0; primal_cell_id < primal_cell_to_dual_node_map.size(); ++primal_cell_id) {
+          primal_cell_to_dual_node_map[primal_cell_id] = std::make_pair(primal_cell_id, dual_node_id++);
+        }
+        return primal_cell_to_dual_node_map;
+      }();
+    }
+
+    m_primal_face_to_dual_cell_map = [&]() {
+      FaceIdToCellIdMap primal_face_to_dual_cell_map{primal_connectivity.numberOfFaces()};
+      for (size_t id = 0; id < primal_face_to_dual_cell_map.size(); ++id) {
+        const CellId dual_cell_id   = id;
+        const FaceId primal_face_id = id;
+
+        primal_face_to_dual_cell_map[id] = std::make_pair(primal_face_id, dual_cell_id);
+      }
+      return primal_face_to_dual_cell_map;
+    }();
+  }
+};
+
+#endif   // CONNECTIVITY_TO_DIAMOND_DUAL_CONNECTIVITY_DATA_MAPPER_HPP
diff --git a/src/mesh/DiamondDualConnectivityManager.cpp b/src/mesh/DiamondDualConnectivityManager.cpp
index 2f0ff4019f90a6db20a6ad75abda52df289fd243..aed409bdaf6fb6e0f60b71f9d77f1a94ec238fc1 100644
--- a/src/mesh/DiamondDualConnectivityManager.cpp
+++ b/src/mesh/DiamondDualConnectivityManager.cpp
@@ -1,6 +1,7 @@
 #include <utils/PugsAssert.hpp>
 
 #include <mesh/Connectivity.hpp>
+#include <mesh/ConnectivityToDiamondDualConnectivityDataMapper.hpp>
 #include <mesh/DiamondDualConnectivityBuilder.hpp>
 #include <mesh/DiamondDualConnectivityManager.hpp>
 #include <utils/Exceptions.hpp>
@@ -21,11 +22,12 @@ DiamondDualConnectivityManager::destroy()
 {
   Assert(m_instance != nullptr, "DiamondDualConnectivityManager was not created!");
 
-  if (m_instance->m_connectivity_to_diamond_dual_connectivity_map.size() > 0) {
+  if (m_instance->m_connectivity_to_diamond_dual_connectivity_info_map.size() > 0) {
     std::stringstream error;
     error << ": some connectivities are still registered\n";
-    for (const auto& i_mesh_data : m_instance->m_connectivity_to_diamond_dual_connectivity_map) {
-      error << " - connectivity " << rang::fgB::magenta << i_mesh_data.first << rang::style::reset << '\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';
     }
     throw UnexpectedError(error.str());
   }
@@ -36,7 +38,7 @@ DiamondDualConnectivityManager::destroy()
 void
 DiamondDualConnectivityManager::deleteConnectivity(const IConnectivity* p_connectivity)
 {
-  m_connectivity_to_diamond_dual_connectivity_map.erase(p_connectivity);
+  m_connectivity_to_diamond_dual_connectivity_info_map.erase(p_connectivity);
 }
 
 template <size_t Dimension>
@@ -45,14 +47,50 @@ DiamondDualConnectivityManager::getDiamondDualConnectivity(const Connectivity<Di
 {
   const IConnectivity* p_connectivity = &connectivity;
 
-  if (auto i_mesh_data = m_connectivity_to_diamond_dual_connectivity_map.find(p_connectivity);
-      i_mesh_data != m_connectivity_to_diamond_dual_connectivity_map.end()) {
-    return std::dynamic_pointer_cast<const Connectivity<Dimension>>(i_mesh_data->second);
+  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& [connectivity, diamond_dual_connectivity_info] = *i_connectivity;
+    return std::dynamic_pointer_cast<const Connectivity<Dimension>>(
+      diamond_dual_connectivity_info.diamondDualConnectivity());
   } else {
     DiamondDualConnectivityBuilder builder{connectivity};
 
-    m_connectivity_to_diamond_dual_connectivity_map[p_connectivity] = builder.connectivity();
-    return std::dynamic_pointer_cast<const Connectivity<Dimension>>(builder.connectivity());
+    std::shared_ptr diamond_connectivity =
+      std::dynamic_pointer_cast<const Connectivity<Dimension>>(builder.connectivity());
+    std::shared_ptr<IConnectivityToDiamondDualConnectivityDataMapper> mapper =
+      std::make_shared<ConnectivityToDiamondDualConnectivityDataMapper<Dimension>>(connectivity, *diamond_connectivity);
+
+    m_connectivity_to_diamond_dual_connectivity_info_map[p_connectivity] =
+      DiamondDualConnectivityInfo{diamond_connectivity, mapper};
+
+    return diamond_connectivity;
+  }
+}
+
+template <size_t Dimension>
+std::shared_ptr<const ConnectivityToDiamondDualConnectivityDataMapper<Dimension>>
+DiamondDualConnectivityManager::getConnectivityToDiamondDualConnectivityDataMapper(
+  const Connectivity<Dimension>& 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& [connectivity, diamond_dual_connectivity_info] = *i_connectivity;
+    return std::dynamic_pointer_cast<const ConnectivityToDiamondDualConnectivityDataMapper<Dimension>>(
+      diamond_dual_connectivity_info.connectivityToDiamondDualConnectivityDataMapper());
+  } else {
+    DiamondDualConnectivityBuilder builder{connectivity};
+
+    std::shared_ptr diamond_connectivity =
+      std::dynamic_pointer_cast<const Connectivity<Dimension>>(builder.connectivity());
+    std::shared_ptr<IConnectivityToDiamondDualConnectivityDataMapper> mapper =
+      std::make_shared<ConnectivityToDiamondDualConnectivityDataMapper<Dimension>>(connectivity, *diamond_connectivity);
+
+    m_connectivity_to_diamond_dual_connectivity_info_map[p_connectivity] =
+      DiamondDualConnectivityInfo{diamond_connectivity, mapper};
+
+    return std::dynamic_pointer_cast<const ConnectivityToDiamondDualConnectivityDataMapper<Dimension>>(mapper);
   }
 }
 
@@ -64,3 +102,12 @@ template std::shared_ptr<const Connectivity<2>> DiamondDualConnectivityManager::
 
 template std::shared_ptr<const Connectivity<3>> DiamondDualConnectivityManager::getDiamondDualConnectivity(
   const Connectivity<3>& connectivity);
+
+template std::shared_ptr<const ConnectivityToDiamondDualConnectivityDataMapper<1>>
+DiamondDualConnectivityManager::getConnectivityToDiamondDualConnectivityDataMapper(const Connectivity<1>&);
+
+template std::shared_ptr<const ConnectivityToDiamondDualConnectivityDataMapper<2>>
+DiamondDualConnectivityManager::getConnectivityToDiamondDualConnectivityDataMapper(const Connectivity<2>&);
+
+template std::shared_ptr<const ConnectivityToDiamondDualConnectivityDataMapper<3>>
+DiamondDualConnectivityManager::getConnectivityToDiamondDualConnectivityDataMapper(const Connectivity<3>&);
diff --git a/src/mesh/DiamondDualConnectivityManager.hpp b/src/mesh/DiamondDualConnectivityManager.hpp
index 6c45d646256c63977be2535e30cf387aa7f6220a..3b7eb2ceaff5c1cacfa26f0bb4194af457e209a2 100644
--- a/src/mesh/DiamondDualConnectivityManager.hpp
+++ b/src/mesh/DiamondDualConnectivityManager.hpp
@@ -9,11 +9,55 @@
 template <size_t Dimension>
 class Connectivity;
 
+class IConnectivityToDiamondDualConnectivityDataMapper;
+
+template <size_t Dimension>
+class ConnectivityToDiamondDualConnectivityDataMapper;
+
 class DiamondDualConnectivityManager
 {
  private:
-  std::unordered_map<const IConnectivity*, std::shared_ptr<const IConnectivity>>
-    m_connectivity_to_diamond_dual_connectivity_map;
+  class DiamondDualConnectivityInfo
+  {
+   private:
+    std::shared_ptr<const IConnectivity> m_diamond_dual_connectivity;
+    std::shared_ptr<const IConnectivityToDiamondDualConnectivityDataMapper>
+      m_connectivity_to_diamond_dual_connectivity_data_mapper;
+
+   public:
+    PUGS_INLINE
+    std::shared_ptr<const IConnectivity>
+    diamondDualConnectivity() const
+    {
+      return m_diamond_dual_connectivity;
+    }
+
+    PUGS_INLINE
+    std::shared_ptr<const IConnectivityToDiamondDualConnectivityDataMapper>
+    connectivityToDiamondDualConnectivityDataMapper()
+    {
+      return m_connectivity_to_diamond_dual_connectivity_data_mapper;
+    }
+
+    DiamondDualConnectivityInfo& operator=(const DiamondDualConnectivityInfo&) = default;
+    DiamondDualConnectivityInfo& operator=(DiamondDualConnectivityInfo&&) = default;
+
+    DiamondDualConnectivityInfo()                                   = default;
+    DiamondDualConnectivityInfo(const DiamondDualConnectivityInfo&) = default;
+    DiamondDualConnectivityInfo(DiamondDualConnectivityInfo&&)      = 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}
+    {}
+
+    ~DiamondDualConnectivityInfo() = default;
+  };
+
+  std::unordered_map<const IConnectivity*, DiamondDualConnectivityInfo>
+    m_connectivity_to_diamond_dual_connectivity_info_map;
 
   static DiamondDualConnectivityManager* m_instance;
 
@@ -39,6 +83,10 @@ class DiamondDualConnectivityManager
 
   template <size_t Dimension>
   std::shared_ptr<const Connectivity<Dimension>> getDiamondDualConnectivity(const Connectivity<Dimension>&);
+
+  template <size_t Dimension>
+  std::shared_ptr<const ConnectivityToDiamondDualConnectivityDataMapper<Dimension>>
+  getConnectivityToDiamondDualConnectivityDataMapper(const Connectivity<Dimension>&);
 };
 
 #endif   // DIAMOND_DUAL_CONNECTIVITY_MANAGER_HPP
diff --git a/src/mesh/DiamondDualMeshBuilder.cpp b/src/mesh/DiamondDualMeshBuilder.cpp
index 482920f1c3382e67e8295e889421ab68022b6a78..df4157c9c19b377f77b754d3f33ac54141539f2f 100644
--- a/src/mesh/DiamondDualMeshBuilder.cpp
+++ b/src/mesh/DiamondDualMeshBuilder.cpp
@@ -1,203 +1,13 @@
 #include <mesh/DiamondDualMeshBuilder.hpp>
 
 #include <mesh/Connectivity.hpp>
-#include <mesh/ConnectivityDescriptor.hpp>
-#include <mesh/ConnectivityDispatcher.hpp>
+#include <mesh/ConnectivityToDiamondDualConnectivityDataMapper.hpp>
 #include <mesh/DiamondDualConnectivityBuilder.hpp>
 #include <mesh/DiamondDualConnectivityManager.hpp>
 #include <mesh/ItemValueUtils.hpp>
 #include <mesh/Mesh.hpp>
 #include <mesh/MeshData.hpp>
 #include <mesh/MeshDataManager.hpp>
-#include <mesh/RefId.hpp>
-#include <utils/Array.hpp>
-#include <utils/CastArray.hpp>
-#include <utils/Messenger.hpp>
-#include <utils/PugsAssert.hpp>
-
-template <size_t Dimension>
-class MeshToDualDataMapper
-{
- private:
-  const IConnectivity* m_primal_connectivity;
-  const IConnectivity* m_dual_connectivity;
-
-  using NodeIdToNodeIdMap = Array<std::pair<NodeId, NodeId>>;
-  NodeIdToNodeIdMap m_primal_node_to_dual_node_map;
-
-  using CellIdToNodeIdMap = Array<std::pair<CellId, NodeId>>;
-  CellIdToNodeIdMap m_primal_cell_to_dual_node_map;
-
-  using FaceIdToCellIdMap = Array<std::pair<FaceId, CellId>>;
-  FaceIdToCellIdMap m_primal_face_to_dual_cell_map;
-
- public:
-  template <typename OriginDataType1, typename OriginDataType2, typename DestinationDataType>
-  void
-  toDualNode(const NodeValue<OriginDataType1>& primal_node_value,
-             const CellValue<OriginDataType2>& primal_cell_value,
-             const NodeValue<DestinationDataType>& dual_node_value)
-  {
-    static_assert(not std::is_const_v<DestinationDataType>, "destination data type must not be constant");
-    static_assert(std::is_same_v<std::remove_const_t<OriginDataType1>, DestinationDataType>, "incompatible types");
-    static_assert(std::is_same_v<std::remove_const_t<OriginDataType2>, DestinationDataType>, "incompatible types");
-
-    Assert(m_primal_connectivity == primal_cell_value.connectivity_ptr().get());
-    Assert(m_primal_connectivity == primal_node_value.connectivity_ptr().get());
-    Assert(m_dual_connectivity == dual_node_value.connectivity_ptr().get());
-
-    parallel_for(
-      m_primal_node_to_dual_node_map.size(), PUGS_LAMBDA(size_t i) {
-        const auto [primal_node_id, dual_node_id] = m_primal_node_to_dual_node_map[i];
-
-        dual_node_value[dual_node_id] = primal_node_value[primal_node_id];
-      });
-
-    parallel_for(
-      m_primal_cell_to_dual_node_map.size(), PUGS_LAMBDA(size_t i) {
-        const auto [primal_cell_id, dual_node_id] = m_primal_cell_to_dual_node_map[i];
-        dual_node_value[dual_node_id]             = primal_cell_value[primal_cell_id];
-      });
-  }
-
-  template <typename OriginDataType, typename DestinationDataType1, typename DestinationDataType2>
-  void
-  fromDualNode(const NodeValue<OriginDataType>& dual_node_value,
-               const NodeValue<DestinationDataType1>& primal_node_value,
-               const CellValue<DestinationDataType2>& primal_cell_value)
-  {
-    static_assert(not std::is_const_v<DestinationDataType1>, "destination data type must not be constant");
-    static_assert(not std::is_const_v<DestinationDataType2>, "destination data type must not be constant");
-    static_assert(std::is_same_v<std::remove_const_t<OriginDataType>, DestinationDataType1>, "incompatible types");
-    static_assert(std::is_same_v<std::remove_const_t<OriginDataType>, DestinationDataType2>, "incompatible types");
-
-    Assert(m_primal_connectivity == primal_cell_value.connectivity_ptr().get());
-    Assert(m_primal_connectivity == primal_node_value.connectivity_ptr().get());
-    Assert(m_dual_connectivity == dual_node_value.connectivity_ptr().get());
-
-    parallel_for(
-      m_primal_node_to_dual_node_map.size(), PUGS_LAMBDA(size_t i) {
-        const auto [primal_node_id, dual_node_id] = m_primal_node_to_dual_node_map[i];
-
-        primal_node_value[primal_node_id] = dual_node_value[dual_node_id];
-      });
-
-    parallel_for(
-      m_primal_cell_to_dual_node_map.size(), PUGS_LAMBDA(size_t i) {
-        const auto [primal_cell_id, dual_node_id] = m_primal_cell_to_dual_node_map[i];
-        primal_cell_value[primal_cell_id]         = dual_node_value[dual_node_id];
-      });
-  }
-
-  template <typename OriginDataType, typename DestinationDataType>
-  void
-  toDualCell(const FaceValue<OriginDataType>& primal_face_value, const CellValue<DestinationDataType>& dual_cell_value)
-  {
-    static_assert(not std::is_const_v<DestinationDataType>, "destination data type must not be constant");
-    static_assert(std::is_same_v<std::remove_const_t<OriginDataType>, DestinationDataType>, "incompatible types");
-
-    Assert(m_primal_connectivity == primal_face_value.connectivity_ptr().get());
-    Assert(m_dual_connectivity == dual_cell_value.connectivity_ptr().get());
-
-    parallel_for(
-      m_primal_face_to_dual_cell_map.size(), PUGS_LAMBDA(size_t i) {
-        const auto [primal_face_id, dual_cell_id] = m_primal_face_to_dual_cell_map[i];
-
-        dual_cell_value[dual_cell_id] = primal_face_value[primal_face_id];
-      });
-
-    parallel_for(
-      m_primal_cell_to_dual_node_map.size(), PUGS_LAMBDA(size_t i) {
-        const auto [primal_face_id, dual_cell_id] = m_primal_face_to_dual_cell_map[i];
-
-        dual_cell_value[dual_cell_id] = primal_face_value[primal_face_id];
-      });
-  }
-
-  template <typename OriginDataType, typename DestinationDataType>
-  void
-  fromDualCell(const CellValue<DestinationDataType>& dual_cell_value,
-               const FaceValue<OriginDataType>& primal_face_value)
-  {
-    static_assert(not std::is_const_v<DestinationDataType>, "destination data type must not be constant");
-    static_assert(std::is_same_v<std::remove_const_t<OriginDataType>, DestinationDataType>, "incompatible types");
-
-    Assert(m_primal_connectivity == primal_face_value.connectivity_ptr().get());
-    Assert(m_dual_connectivity == dual_cell_value.connectivity_ptr().get());
-
-    parallel_for(
-      m_primal_face_to_dual_cell_map.size(), PUGS_LAMBDA(size_t i) {
-        const auto [primal_face_id, dual_cell_id] = m_primal_face_to_dual_cell_map[i];
-
-        primal_face_value[primal_face_id] = dual_cell_value[dual_cell_id];
-      });
-
-    parallel_for(
-      m_primal_cell_to_dual_node_map.size(), PUGS_LAMBDA(size_t i) {
-        const auto [primal_face_id, dual_cell_id] = m_primal_face_to_dual_cell_map[i];
-        primal_face_value[primal_face_id]         = dual_cell_value[dual_cell_id];
-      });
-  }
-
-  MeshToDualDataMapper(const Connectivity<Dimension>& primal_connectivity,
-                       const Connectivity<Dimension>& dual_connectivity)
-    : m_primal_connectivity{&primal_connectivity}, m_dual_connectivity{&dual_connectivity}
-  {
-    if constexpr (Dimension == 1) {
-      const auto& node_to_cell_matrix = primal_connectivity.nodeToCellMatrix();
-
-      NodeId dual_node_id            = 0;
-      m_primal_node_to_dual_node_map = [&]() {
-        std::vector<std::pair<NodeId, NodeId>> primal_node_to_dual_node_vector;
-        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) {
-            primal_node_to_dual_node_vector.push_back(std::make_pair(primal_node_id, dual_node_id++));
-          }
-        }
-        return convert_to_array(primal_node_to_dual_node_vector);
-      }();
-
-      m_primal_cell_to_dual_node_map = [&]() {
-        CellIdToNodeIdMap primal_cell_to_dual_node_map{primal_connectivity.numberOfCells()};
-        for (CellId primal_cell_id = 0; primal_cell_id < primal_cell_to_dual_node_map.size(); ++primal_cell_id) {
-          primal_cell_to_dual_node_map[primal_cell_id] = std::make_pair(primal_cell_id, dual_node_id++);
-        }
-        return primal_cell_to_dual_node_map;
-      }();
-
-    } else {
-      m_primal_node_to_dual_node_map = [&]() {
-        NodeIdToNodeIdMap primal_node_to_dual_node_map{primal_connectivity.numberOfNodes()};
-        for (NodeId primal_node_id = 0; primal_node_id < primal_node_to_dual_node_map.size(); ++primal_node_id) {
-          const NodeId dual_node_id = primal_node_id;
-
-          primal_node_to_dual_node_map[primal_node_id] = std::make_pair(primal_node_id, dual_node_id);
-        }
-        return primal_node_to_dual_node_map;
-      }();
-
-      m_primal_cell_to_dual_node_map = [&]() {
-        CellIdToNodeIdMap primal_cell_to_dual_node_map{primal_connectivity.numberOfCells()};
-        NodeId dual_node_id = m_primal_node_to_dual_node_map.size();
-        for (CellId primal_cell_id = 0; primal_cell_id < primal_cell_to_dual_node_map.size(); ++primal_cell_id) {
-          primal_cell_to_dual_node_map[primal_cell_id] = std::make_pair(primal_cell_id, dual_node_id++);
-        }
-        return primal_cell_to_dual_node_map;
-      }();
-    }
-
-    m_primal_face_to_dual_cell_map = [&]() {
-      FaceIdToCellIdMap primal_face_to_dual_cell_map{primal_connectivity.numberOfFaces()};
-      for (size_t id = 0; id < primal_face_to_dual_cell_map.size(); ++id) {
-        const CellId dual_cell_id   = id;
-        const FaceId primal_face_id = id;
-
-        primal_face_to_dual_cell_map[id] = std::make_pair(primal_face_id, dual_cell_id);
-      }
-      return primal_face_to_dual_cell_map;
-    }();
-  }
-};
 
 template <size_t Dimension>
 void
@@ -221,10 +31,11 @@ DiamondDualMeshBuilder::_buildDualDiamondMeshFrom(const std::shared_ptr<const IM
   MeshData<Dimension>& primal_mesh_data                  = MeshDataManager::instance().getMeshData(primal_mesh);
   const CellValue<const TinyVector<Dimension>> primal_xj = primal_mesh_data.xj();
 
-  MeshToDualDataMapper<Dimension> mesh_to_dual_data_mapper{primal_mesh.connectivity(), diamond_connectivity};
+  std::shared_ptr connectivity_to_diamond_dual_connectivity_data_mapper =
+    manager.getConnectivityToDiamondDualConnectivityDataMapper(primal_mesh.connectivity());
 
   NodeValue<TinyVector<Dimension>> diamond_xr{diamond_connectivity};
-  mesh_to_dual_data_mapper.toDualNode(primal_xr, primal_xj, diamond_xr);
+  connectivity_to_diamond_dual_connectivity_data_mapper->toDualNode(primal_xr, primal_xj, diamond_xr);
 
   m_mesh = std::make_shared<MeshType>(p_diamond_connectivity, diamond_xr);
 }