From 1da6dd433c82ab5619e025afd652b0ea023ae9c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Del=20Pino?= <stephane.delpino44@gmail.com> Date: Wed, 31 Mar 2021 15:21:49 +0200 Subject: [PATCH] Add tests for ItemValue (at last) --- src/mesh/Connectivity.hpp | 10 ++- src/mesh/ItemValue.hpp | 15 +--- src/output/VTKWriter.cpp | 4 +- tests/CMakeLists.txt | 1 + tests/test_ItemValue.cpp | 175 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 190 insertions(+), 15 deletions(-) create mode 100644 tests/test_ItemValue.cpp diff --git a/src/mesh/Connectivity.hpp b/src/mesh/Connectivity.hpp index 2b25c6e9b..0caec821a 100644 --- a/src/mesh/Connectivity.hpp +++ b/src/mesh/Connectivity.hpp @@ -589,8 +589,14 @@ class Connectivity final : public IConnectivity size_t numberOfEdges() const final { - const auto& edge_to_node_matrix = this->_getMatrix(ItemType::edge, ItemType::node); - return edge_to_node_matrix.numRows(); + if constexpr (Dimension == 1) { + return this->numberOfNodes(); + } else if constexpr (Dimension == 2) { + return this->numberOfFaces(); + } else { + const auto& edge_to_node_matrix = this->_getMatrix(ItemType::edge, ItemType::node); + return edge_to_node_matrix.numRows(); + } } PUGS_INLINE diff --git a/src/mesh/ItemValue.hpp b/src/mesh/ItemValue.hpp index a9049a394..32ce896e5 100644 --- a/src/mesh/ItemValue.hpp +++ b/src/mesh/ItemValue.hpp @@ -84,26 +84,20 @@ class ItemValue // Following Kokkos logic, these classes are view and const view does allow // changes in data PUGS_FORCEINLINE - DataType& operator[](const ItemId& i) const noexcept(NO_ASSERT) + DataType& + operator[](const ItemId& i) const noexcept(NO_ASSERT) { Assert(this->isBuilt()); return m_values[i]; } template <typename IndexType> - DataType& operator[](const IndexType&) const noexcept(NO_ASSERT) + DataType& + operator[](const IndexType&) const noexcept(NO_ASSERT) { static_assert(std::is_same_v<IndexType, ItemId>, "ItemValue must be indexed by ItemId"); } - PUGS_INLINE - size_t - numberOfItems() const noexcept(NO_ASSERT) - { - Assert(this->isBuilt()); - return m_values.size(); - } - template <typename DataType2> PUGS_INLINE ItemValue& operator=(const Array<DataType2>& values) noexcept(NO_ASSERT) @@ -162,7 +156,6 @@ class ItemValue { static_assert(not std::is_const_v<DataType>, "Cannot allocate ItemValue of const data: only view is " "supported"); - ; } PUGS_INLINE diff --git a/src/output/VTKWriter.cpp b/src/output/VTKWriter.cpp index f65a4acfa..5da7dd6fb 100644 --- a/src/output/VTKWriter.cpp +++ b/src/output/VTKWriter.cpp @@ -88,9 +88,9 @@ class VTKWriter::SerializedDataList void add(const ItemValue<DataT, item_type, ConnectivityT>& item_value) { - Array<std::remove_const_t<DataT>> array(item_value.numberOfItems()); + Array<std::remove_const_t<DataT>> array(item_value.size()); parallel_for( - item_value.numberOfItems(), PUGS_LAMBDA(ItemIdT<item_type> item_id) { array[item_id] = item_value[item_id]; }); + item_value.size(), PUGS_LAMBDA(ItemIdT<item_type> item_id) { array[item_id] = item_value[item_id]; }); this->add(array); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c8df103aa..8cd540c76 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -100,6 +100,7 @@ add_executable (mpi_unit_tests mpi_test_main.cpp test_Messenger.cpp test_Partitioner.cpp + test_ItemValue.cpp ) add_library(test_Pugs_MeshDataBase diff --git a/tests/test_ItemValue.cpp b/tests/test_ItemValue.cpp new file mode 100644 index 000000000..ef1451264 --- /dev/null +++ b/tests/test_ItemValue.cpp @@ -0,0 +1,175 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <MeshDataBaseForTests.hpp> +#include <mesh/Connectivity.hpp> +#include <mesh/ItemValue.hpp> +#include <mesh/Mesh.hpp> +#include <utils/Messenger.hpp> + +// Instantiate to ensure full coverage is performed +template class ItemValue<int, ItemType::cell>; + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("ItemValue", "[mesh]") +{ + SECTION("default constructors") + { + REQUIRE_NOTHROW(NodeValue<int>{}); + REQUIRE_NOTHROW(EdgeValue<int>{}); + REQUIRE_NOTHROW(FaceValue<int>{}); + REQUIRE_NOTHROW(CellValue<int>{}); + + REQUIRE(not NodeValue<int>{}.isBuilt()); + REQUIRE(not EdgeValue<int>{}.isBuilt()); + REQUIRE(not FaceValue<int>{}.isBuilt()); + REQUIRE(not CellValue<int>{}.isBuilt()); + } + + SECTION("1D") + { + const Mesh<Connectivity<1>>& mesh_1d = MeshDataBaseForTests::get().cartesianMesh<1>(); + const Connectivity<1>& connectivity = mesh_1d.connectivity(); + + EdgeValue<int>{connectivity}; + + REQUIRE_NOTHROW(NodeValue<int>{connectivity}); + REQUIRE_NOTHROW(EdgeValue<int>{connectivity}); + REQUIRE_NOTHROW(FaceValue<int>{connectivity}); + REQUIRE_NOTHROW(CellValue<int>{connectivity}); + + REQUIRE(NodeValue<int>{connectivity}.isBuilt()); + REQUIRE(EdgeValue<int>{connectivity}.isBuilt()); + REQUIRE(FaceValue<int>{connectivity}.isBuilt()); + REQUIRE(CellValue<int>{connectivity}.isBuilt()); + + NodeValue<int> node_value{connectivity}; + EdgeValue<int> edge_value{connectivity}; + FaceValue<int> face_value{connectivity}; + CellValue<int> cell_value{connectivity}; + + REQUIRE(edge_value.size() == node_value.size()); + REQUIRE(face_value.size() == node_value.size()); + REQUIRE(cell_value.size() + 1 == node_value.size()); + } + + SECTION("2D") + { + const Mesh<Connectivity<2>>& mesh_2d = MeshDataBaseForTests::get().cartesianMesh<2>(); + const Connectivity<2>& connectivity = mesh_2d.connectivity(); + + EdgeValue<int>{connectivity}; + + REQUIRE_NOTHROW(NodeValue<int>{connectivity}); + REQUIRE_NOTHROW(EdgeValue<int>{connectivity}); + REQUIRE_NOTHROW(FaceValue<int>{connectivity}); + REQUIRE_NOTHROW(CellValue<int>{connectivity}); + + REQUIRE(NodeValue<int>{connectivity}.isBuilt()); + REQUIRE(EdgeValue<int>{connectivity}.isBuilt()); + REQUIRE(FaceValue<int>{connectivity}.isBuilt()); + REQUIRE(CellValue<int>{connectivity}.isBuilt()); + + EdgeValue<int> edge_value{connectivity}; + FaceValue<int> face_value{connectivity}; + + REQUIRE(edge_value.size() == face_value.size()); + } + + SECTION("3D") + { + const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Connectivity<3>& connectivity = mesh_3d.connectivity(); + + EdgeValue<int>{connectivity}; + + REQUIRE_NOTHROW(NodeValue<int>{connectivity}); + REQUIRE_NOTHROW(EdgeValue<int>{connectivity}); + REQUIRE_NOTHROW(FaceValue<int>{connectivity}); + REQUIRE_NOTHROW(CellValue<int>{connectivity}); + + REQUIRE(NodeValue<int>{connectivity}.isBuilt()); + REQUIRE(EdgeValue<int>{connectivity}.isBuilt()); + REQUIRE(FaceValue<int>{connectivity}.isBuilt()); + REQUIRE(CellValue<int>{connectivity}.isBuilt()); + } + + SECTION("copy") + { + const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Connectivity<3>& connectivity = mesh_3d.connectivity(); + + CellValue<int> cell_value{connectivity}; + cell_value.fill(parallel::rank()); + + CellValue<const int> const_cell_value; + const_cell_value = copy(cell_value); + + cell_value.fill(0); + + for (CellId i_cell = 0; i_cell < mesh_3d.numberOfCells(); ++i_cell) { + REQUIRE(cell_value[i_cell] == 0); + } + + for (CellId i_cell = 0; i_cell < mesh_3d.numberOfCells(); ++i_cell) { + REQUIRE(const_cell_value[i_cell] == static_cast<std::int64_t>(parallel::rank())); + } + } + + SECTION("WeakItemValue") + { + const Mesh<Connectivity<2>>& mesh_2d = MeshDataBaseForTests::get().cartesianMesh<2>(); + const Connectivity<2>& connectivity = mesh_2d.connectivity(); + + WeakFaceValue<int> weak_face_value{connectivity}; + + weak_face_value.fill(parallel::rank()); + + FaceValue<const int> face_value{weak_face_value}; + + REQUIRE(face_value.connectivity_ptr() == weak_face_value.connectivity_ptr()); + } + +#ifndef NDEBUG + SECTION("error") + { + SECTION("checking for build ItemValue") + { + CellValue<int> cell_value; + REQUIRE_THROWS_AS(cell_value[CellId{0}], AssertError); + + FaceValue<int> face_value; + REQUIRE_THROWS_AS(face_value[FaceId{0}], AssertError); + + EdgeValue<int> edge_value; + REQUIRE_THROWS_AS(edge_value[EdgeId{0}], AssertError); + + NodeValue<int> node_value; + REQUIRE_THROWS_AS(node_value[NodeId{0}], AssertError); + } + + SECTION("checking for bounds violation") + { + const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Connectivity<3>& connectivity = mesh_3d.connectivity(); + + CellValue<int> cell_value{connectivity}; + CellId invalid_cell_id = connectivity.numberOfCells(); + REQUIRE_THROWS_AS(cell_value[invalid_cell_id], AssertError); + + FaceValue<int> face_value{connectivity}; + FaceId invalid_face_id = connectivity.numberOfFaces(); + REQUIRE_THROWS_AS(face_value[invalid_face_id], AssertError); + + EdgeValue<int> edge_value{connectivity}; + EdgeId invalid_edge_id = connectivity.numberOfEdges(); + REQUIRE_THROWS_AS(edge_value[invalid_edge_id], AssertError); + + NodeValue<int> node_value{connectivity}; + NodeId invalid_node_id = connectivity.numberOfNodes(); + REQUIRE_THROWS_AS(node_value[invalid_node_id], AssertError); + } + } +#endif // NDEBUG +} -- GitLab