From a34db2949c30bfa1f7167a4d8e3370e1de9cc8a9 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Fri, 17 Jul 2020 18:11:11 +0200
Subject: [PATCH] Cleanup data mapper

Rename
`MeshToDiamondDualMeshDataMapper` as
`ConnectivityToDiamondDualConnectivityDataMapper`
which is correct

This data mapper is now available through the
DiamondDualConnectivityManager and is built when connectivity is
constructed

The construction of this mapper is still completely independent of the
mesh construction itself which is bad since same assumptions are made
twice...

It should be actually constructed at the same time allowing for
instance easy renumbering. This should be done soon... hopefully...
---
 ...ityToDiamondDualConnectivityDataMapper.hpp | 204 ++++++++++++++++++
 src/mesh/DiamondDualConnectivityManager.cpp   |  65 +++++-
 src/mesh/DiamondDualConnectivityManager.hpp   |  52 ++++-
 src/mesh/DiamondDualMeshBuilder.cpp           | 197 +----------------
 4 files changed, 314 insertions(+), 204 deletions(-)
 create mode 100644 src/mesh/ConnectivityToDiamondDualConnectivityDataMapper.hpp

diff --git a/src/mesh/ConnectivityToDiamondDualConnectivityDataMapper.hpp b/src/mesh/ConnectivityToDiamondDualConnectivityDataMapper.hpp
new file mode 100644
index 000000000..577bad4c4
--- /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 2f0ff4019..aed409bda 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 6c45d6462..3b7eb2cea 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 482920f1c..df4157c9c 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);
 }
-- 
GitLab