From 823551961d09cf0e6b0617e5108fd7b7becf9808 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Del=20Pino?= <stephane.delpino44@gmail.com>
Date: Tue, 11 Jan 2022 20:24:10 +0100
Subject: [PATCH] Add tests for MedianDualMeshBuilder

---
 src/mesh/MedianDualMeshBuilder.cpp   |  2 +
 tests/CMakeLists.txt                 |  1 +
 tests/test_MedianDualMeshBuilder.cpp | 91 ++++++++++++++++++++++++++++
 3 files changed, 94 insertions(+)
 create mode 100644 tests/test_MedianDualMeshBuilder.cpp

diff --git a/src/mesh/MedianDualMeshBuilder.cpp b/src/mesh/MedianDualMeshBuilder.cpp
index 1dde88902..aae78311e 100644
--- a/src/mesh/MedianDualMeshBuilder.cpp
+++ b/src/mesh/MedianDualMeshBuilder.cpp
@@ -52,8 +52,10 @@ MedianDualMeshBuilder::MedianDualMeshBuilder(const IMesh& i_mesh)
     throw NotImplementedError("median dual mesh");
     break;
   }
+    // LCOV_EXCL_START
   default: {
     throw UnexpectedError("invalid mesh dimension: " + std::to_string(i_mesh.dimension()));
   }
+    // LCOV_EXCL_STOP
   }
 }
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 7b3cdf773..96729d8ac 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -101,6 +101,7 @@ add_executable (unit_tests
   test_ListAffectationProcessor.cpp
   test_MathModule.cpp
   test_MedianDualConnectivityBuilder.cpp
+  test_MedianDualMeshBuilder.cpp
   test_NameProcessor.cpp
   test_NaNHelper.cpp
   test_OStream.cpp
diff --git a/tests/test_MedianDualMeshBuilder.cpp b/tests/test_MedianDualMeshBuilder.cpp
new file mode 100644
index 000000000..062c48264
--- /dev/null
+++ b/tests/test_MedianDualMeshBuilder.cpp
@@ -0,0 +1,91 @@
+#include <catch2/catch_test_macros.hpp>
+#include <catch2/matchers/catch_matchers_all.hpp>
+
+#include <MeshDataBaseForTests.hpp>
+#include <mesh/DualMeshManager.hpp>
+#include <mesh/MeshData.hpp>
+#include <mesh/MeshDataManager.hpp>
+
+#include <mesh/Connectivity.hpp>
+#include <mesh/ItemValueUtils.hpp>
+#include <mesh/Mesh.hpp>
+
+// clazy:excludeall=non-pod-global-static
+
+TEST_CASE("MedianDualMeshBuilder", "[mesh]")
+{
+  SECTION("2D")
+  {
+    constexpr static size_t Dimension = 2;
+
+    using ConnectivityType = Connectivity<Dimension>;
+    using MeshType         = Mesh<ConnectivityType>;
+
+    std::shared_ptr p_mesh      = MeshDataBaseForTests::get().hybrid2DMesh();
+    const MeshType& primal_mesh = *p_mesh;
+
+    REQUIRE(primal_mesh.numberOfNodes() == 53);
+    REQUIRE(primal_mesh.numberOfFaces() == 110);
+    REQUIRE(primal_mesh.numberOfCells() == 58);
+
+    std::shared_ptr p_diamond_dual_mesh = DualMeshManager::instance().getMedianDualMesh(primal_mesh);
+    const MeshType& dual_mesh           = *p_diamond_dual_mesh;
+
+    REQUIRE(dual_mesh.numberOfNodes() == 192);
+    REQUIRE(dual_mesh.numberOfFaces() == 244);
+    REQUIRE(dual_mesh.numberOfCells() == 53);
+
+    auto dual_cell_volume = MeshDataManager::instance().getMeshData(dual_mesh).Vj();
+
+    REQUIRE(sum(dual_cell_volume) == Catch::Approx(2));
+
+    auto coord_comp = [](const TinyVector<Dimension>& a, const TinyVector<Dimension>& b) -> bool {
+      return (a[0] < b[0]) or ((a[0] == b[0]) and (a[1] < b[1]));
+    };
+
+    auto dual_cell_to_node    = dual_mesh.connectivity().cellToNodeMatrix();
+    auto primal_node_to_face  = primal_mesh.connectivity().nodeToFaceMatrix();
+    auto primal_node_to_cell  = primal_mesh.connectivity().nodeToCellMatrix();
+    auto primal_face_is_owned = primal_mesh.connectivity().faceIsOwned();
+
+    auto dual_xr   = dual_mesh.xr();
+    auto primal_xr = primal_mesh.xr();
+    auto primal_xl = MeshDataManager::instance().getMeshData(primal_mesh).xl();
+    auto primal_xj = MeshDataManager::instance().getMeshData(primal_mesh).xj();
+
+    using CoordSet = std::set<TinyVector<Dimension>,
+                              std::function<bool(const TinyVector<Dimension>& a, const TinyVector<Dimension>& b)>>;
+
+    auto primal_face_to_cell_matrix = primal_mesh.connectivity().faceToCellMatrix();
+
+    CellId dual_cell_id   = 0;
+    NodeId primal_node_id = 0;
+    for (; dual_cell_id < dual_mesh.numberOfCells(); ++dual_cell_id, ++primal_node_id) {
+      CoordSet dual_cell_node_coords{coord_comp};
+      {
+        auto dual_cell_node_list = dual_cell_to_node[dual_cell_id];
+        for (size_t i_node = 0; i_node < dual_cell_node_list.size(); ++i_node) {
+          dual_cell_node_coords.insert(dual_xr[dual_cell_node_list[i_node]]);
+        }
+      }
+
+      CoordSet primal_coords{coord_comp};
+      {
+        auto primal_node_face_list = primal_node_to_face[primal_node_id];
+        for (size_t i_face = 0; i_face < primal_node_face_list.size(); ++i_face) {
+          const FaceId face_id = primal_node_face_list[i_face];
+          primal_coords.insert(primal_xl[face_id]);
+          if (primal_face_is_owned[face_id] and (primal_face_to_cell_matrix[face_id].size() == 1)) {
+            primal_coords.insert(primal_xr[primal_node_id]);
+          }
+        }
+        auto primal_node_cell_list = primal_node_to_cell[primal_node_id];
+        for (size_t i_cell = 0; i_cell < primal_node_cell_list.size(); ++i_cell) {
+          primal_coords.insert(primal_xj[primal_node_cell_list[i_cell]]);
+        }
+      }
+
+      REQUIRE(primal_coords == dual_cell_node_coords);
+    }
+  }
+}
-- 
GitLab