diff --git a/src/mesh/Synchronizer.hpp b/src/mesh/Synchronizer.hpp index adf127f238fc201a11ba5b503aed4b926e772a4d..dc0773ace208cc83e863df0ffada54e1db33f936 100644 --- a/src/mesh/Synchronizer.hpp +++ b/src/mesh/Synchronizer.hpp @@ -7,9 +7,13 @@ #include <utils/Exceptions.hpp> #include <utils/Messenger.hpp> +#include <utils/pugs_config.hpp> + #include <iostream> #include <map> +#ifdef PUGS_HAS_MPI + class Synchronizer { template <ItemType item_type> @@ -289,4 +293,28 @@ class Synchronizer } }; +#else // PUGS_HAS_MPI + +class Synchronizer +{ + public: + template <typename DataType, ItemType item_type, typename ConnectivityPtr> + PUGS_INLINE void + synchronize(ItemValue<DataType, item_type, ConnectivityPtr>&) + {} + + template <typename DataType, ItemType item_type, typename ConnectivityPtr> + PUGS_INLINE void + synchronize(ItemArray<DataType, item_type, ConnectivityPtr>&) + {} + + PUGS_INLINE + Synchronizer() + { + ; + } +}; + +#endif // PUGS_HAS_MPI + #endif // SYNCHRONIZER_HPP diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ea44f119d6096cbd1b304c39c00400eefec16ca2..ddfa977a6ef8ca76df9f27bbdc2bda86395cc67f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -174,6 +174,7 @@ add_executable (mpi_unit_tests test_RandomEngine.cpp test_SubItemValuePerItem.cpp test_SubItemArrayPerItem.cpp + test_Synchronizer.cpp ) add_library(test_Pugs_MeshDataBase diff --git a/tests/test_Synchronizer.cpp b/tests/test_Synchronizer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6a4a9b52a6ce05a4a0b2758c868a49dc758d3e3d --- /dev/null +++ b/tests/test_Synchronizer.cpp @@ -0,0 +1,450 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <MeshDataBaseForTests.hpp> +#include <mesh/Connectivity.hpp> +#include <mesh/Mesh.hpp> +#include <mesh/Synchronizer.hpp> +#include <utils/pugs_config.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("Synchronizer", "[mesh]") +{ + auto is_same_item_value = [](auto a, auto b) { + using IndexT = typename decltype(a)::index_type; + bool is_same = true; + for (IndexT i = 0; i < a.numberOfItems(); ++i) { + is_same &= (a[i] == b[i]); + } + return parallel::allReduceAnd(is_same); + }; + + auto is_same_item_array = [](auto a, auto b) { + using IndexT = typename decltype(a)::index_type; + bool is_same = true; + for (IndexT i = 0; i < a.numberOfItems(); ++i) { + for (size_t j = 0; j < a.sizeOfArrays(); ++j) { + is_same &= (a[i][j] == b[i][j]); + } + } + return parallel::allReduceAnd(is_same); + }; + + SECTION("1D") + { + constexpr size_t Dimension = 1; + using ConnectivityType = Connectivity<Dimension>; + + const ConnectivityType& connectivity = MeshDataBaseForTests::get().unordered1DMesh()->connectivity(); + + SECTION("synchonize NodeValue") + { + const auto node_owner = connectivity.nodeOwner(); + const auto node_number = connectivity.nodeNumber(); + + NodeValue<int> node_value_ref{connectivity}; + parallel_for( + connectivity.numberOfNodes(), + PUGS_LAMBDA(const NodeId node_id) { node_value_ref[node_id] = node_owner[node_id] + node_number[node_id]; }); + + NodeValue<int> node_value{connectivity}; + parallel_for( + connectivity.numberOfNodes(), + PUGS_LAMBDA(const NodeId node_id) { node_value[node_id] = parallel::rank() + node_number[node_id]; }); + + if (parallel::size() > 1) { + REQUIRE(not is_same_item_value(node_value, node_value_ref)); + } + + Synchronizer synchronizer; + synchronizer.synchronize(node_value); + + REQUIRE(is_same_item_value(node_value, node_value_ref)); + } + + SECTION("synchonize EdgeValue") + { + const auto edge_owner = connectivity.edgeOwner(); + const auto edge_number = connectivity.edgeNumber(); + + EdgeValue<int> edge_value_ref{connectivity}; + parallel_for( + connectivity.numberOfEdges(), + PUGS_LAMBDA(const EdgeId edge_id) { edge_value_ref[edge_id] = edge_owner[edge_id] + edge_number[edge_id]; }); + + EdgeValue<int> edge_value{connectivity}; + parallel_for( + connectivity.numberOfEdges(), + PUGS_LAMBDA(const EdgeId edge_id) { edge_value[edge_id] = parallel::rank() + edge_number[edge_id]; }); + + if (parallel::size() > 1) { + REQUIRE(not is_same_item_value(edge_value, edge_value_ref)); + } + + Synchronizer synchronizer; + synchronizer.synchronize(edge_value); + + REQUIRE(is_same_item_value(edge_value, edge_value_ref)); + } + + SECTION("synchonize FaceValue") + { + const auto face_owner = connectivity.faceOwner(); + const auto face_number = connectivity.faceNumber(); + + FaceValue<int> face_value_ref{connectivity}; + parallel_for( + connectivity.numberOfFaces(), + PUGS_LAMBDA(const FaceId face_id) { face_value_ref[face_id] = face_owner[face_id] + face_number[face_id]; }); + + FaceValue<int> face_value{connectivity}; + parallel_for( + connectivity.numberOfFaces(), + PUGS_LAMBDA(const FaceId face_id) { face_value[face_id] = parallel::rank() + face_number[face_id]; }); + + if (parallel::size() > 1) { + REQUIRE(not is_same_item_value(face_value, face_value_ref)); + } + + Synchronizer synchronizer; + synchronizer.synchronize(face_value); + + REQUIRE(is_same_item_value(face_value, face_value_ref)); + } + + SECTION("synchonize CellValue") + { + const auto cell_owner = connectivity.cellOwner(); + const auto cell_number = connectivity.cellNumber(); + + CellValue<int> cell_value_ref{connectivity}; + parallel_for( + connectivity.numberOfCells(), + PUGS_LAMBDA(const CellId cell_id) { cell_value_ref[cell_id] = cell_owner[cell_id] + cell_number[cell_id]; }); + + CellValue<int> cell_value{connectivity}; + parallel_for( + connectivity.numberOfCells(), + PUGS_LAMBDA(const CellId cell_id) { cell_value[cell_id] = parallel::rank() + cell_number[cell_id]; }); + + if (parallel::size() > 1) { + REQUIRE(not is_same_item_value(cell_value, cell_value_ref)); + } + + Synchronizer synchronizer; + synchronizer.synchronize(cell_value); + + REQUIRE(is_same_item_value(cell_value, cell_value_ref)); + } + + SECTION("synchonize CellArray") + { + const auto cell_owner = connectivity.cellOwner(); + const auto cell_number = connectivity.cellNumber(); + + CellArray<int> cell_array_ref{connectivity, 3}; + parallel_for( + connectivity.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + for (size_t i = 0; i < cell_array_ref.sizeOfArrays(); ++i) { + cell_array_ref[cell_id][i] = (i + 1) * cell_owner[cell_id] + i + cell_number[cell_id]; + } + }); + + CellArray<int> cell_array{connectivity, 3}; + parallel_for( + connectivity.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + for (size_t i = 0; i < cell_array.sizeOfArrays(); ++i) { + cell_array[cell_id][i] = (i + 1) * parallel::rank() + i + cell_number[cell_id]; + } + }); + + if (parallel::size() > 1) { + REQUIRE(not is_same_item_array(cell_array, cell_array_ref)); + } + + Synchronizer synchronizer; + synchronizer.synchronize(cell_array); + + REQUIRE(is_same_item_array(cell_array, cell_array_ref)); + } + } + + SECTION("2D") + { + constexpr size_t Dimension = 2; + using ConnectivityType = Connectivity<Dimension>; + + const ConnectivityType& connectivity = MeshDataBaseForTests::get().hybrid2DMesh()->connectivity(); + + SECTION("synchonize NodeValue") + { + const auto node_owner = connectivity.nodeOwner(); + const auto node_number = connectivity.nodeNumber(); + + NodeValue<int> node_value_ref{connectivity}; + parallel_for( + connectivity.numberOfNodes(), + PUGS_LAMBDA(const NodeId node_id) { node_value_ref[node_id] = node_owner[node_id] + node_number[node_id]; }); + + NodeValue<int> node_value{connectivity}; + parallel_for( + connectivity.numberOfNodes(), + PUGS_LAMBDA(const NodeId node_id) { node_value[node_id] = parallel::rank() + node_number[node_id]; }); + + if (parallel::size() > 1) { + REQUIRE(not is_same_item_value(node_value, node_value_ref)); + } + + Synchronizer synchronizer; + synchronizer.synchronize(node_value); + + REQUIRE(is_same_item_value(node_value, node_value_ref)); + } + + SECTION("synchonize EdgeValue") + { + const auto edge_owner = connectivity.edgeOwner(); + const auto edge_number = connectivity.edgeNumber(); + + EdgeValue<int> edge_value_ref{connectivity}; + parallel_for( + connectivity.numberOfEdges(), + PUGS_LAMBDA(const EdgeId edge_id) { edge_value_ref[edge_id] = edge_owner[edge_id] + edge_number[edge_id]; }); + + EdgeValue<int> edge_value{connectivity}; + parallel_for( + connectivity.numberOfEdges(), + PUGS_LAMBDA(const EdgeId edge_id) { edge_value[edge_id] = parallel::rank() + edge_number[edge_id]; }); + + if (parallel::size() > 1) { + REQUIRE(not is_same_item_value(edge_value, edge_value_ref)); + } + + Synchronizer synchronizer; + synchronizer.synchronize(edge_value); + + REQUIRE(is_same_item_value(edge_value, edge_value_ref)); + } + + SECTION("synchonize FaceValue") + { + const auto face_owner = connectivity.faceOwner(); + const auto face_number = connectivity.faceNumber(); + + FaceValue<int> face_value_ref{connectivity}; + parallel_for( + connectivity.numberOfFaces(), + PUGS_LAMBDA(const FaceId face_id) { face_value_ref[face_id] = face_owner[face_id] + face_number[face_id]; }); + + FaceValue<int> face_value{connectivity}; + parallel_for( + connectivity.numberOfFaces(), + PUGS_LAMBDA(const FaceId face_id) { face_value[face_id] = parallel::rank() + face_number[face_id]; }); + + if (parallel::size() > 1) { + REQUIRE(not is_same_item_value(face_value, face_value_ref)); + } + + Synchronizer synchronizer; + synchronizer.synchronize(face_value); + + REQUIRE(is_same_item_value(face_value, face_value_ref)); + } + + SECTION("synchonize CellValue") + { + const auto cell_owner = connectivity.cellOwner(); + const auto cell_number = connectivity.cellNumber(); + + CellValue<int> cell_value_ref{connectivity}; + parallel_for( + connectivity.numberOfCells(), + PUGS_LAMBDA(const CellId cell_id) { cell_value_ref[cell_id] = cell_owner[cell_id] + cell_number[cell_id]; }); + + CellValue<int> cell_value{connectivity}; + parallel_for( + connectivity.numberOfCells(), + PUGS_LAMBDA(const CellId cell_id) { cell_value[cell_id] = parallel::rank() + cell_number[cell_id]; }); + + if (parallel::size() > 1) { + REQUIRE(not is_same_item_value(cell_value, cell_value_ref)); + } + + Synchronizer synchronizer; + synchronizer.synchronize(cell_value); + + REQUIRE(is_same_item_value(cell_value, cell_value_ref)); + } + + SECTION("synchonize CellArray") + { + const auto cell_owner = connectivity.cellOwner(); + const auto cell_number = connectivity.cellNumber(); + + CellArray<int> cell_array_ref{connectivity, 3}; + parallel_for( + connectivity.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + for (size_t i = 0; i < cell_array_ref.sizeOfArrays(); ++i) { + cell_array_ref[cell_id][i] = (i + 1) * cell_owner[cell_id] + i + cell_number[cell_id]; + } + }); + + CellArray<int> cell_array{connectivity, 3}; + parallel_for( + connectivity.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + for (size_t i = 0; i < cell_array.sizeOfArrays(); ++i) { + cell_array[cell_id][i] = (i + 1) * parallel::rank() + i + cell_number[cell_id]; + } + }); + + if (parallel::size() > 1) { + REQUIRE(not is_same_item_array(cell_array, cell_array_ref)); + } + + Synchronizer synchronizer; + synchronizer.synchronize(cell_array); + + REQUIRE(is_same_item_array(cell_array, cell_array_ref)); + } + } + + SECTION("3D") + { + constexpr size_t Dimension = 3; + using ConnectivityType = Connectivity<Dimension>; + + const ConnectivityType& connectivity = MeshDataBaseForTests::get().hybrid3DMesh()->connectivity(); + + SECTION("synchonize NodeValue") + { + const auto node_owner = connectivity.nodeOwner(); + const auto node_number = connectivity.nodeNumber(); + + NodeValue<int> node_value_ref{connectivity}; + parallel_for( + connectivity.numberOfNodes(), + PUGS_LAMBDA(const NodeId node_id) { node_value_ref[node_id] = node_owner[node_id] + node_number[node_id]; }); + + NodeValue<int> node_value{connectivity}; + parallel_for( + connectivity.numberOfNodes(), + PUGS_LAMBDA(const NodeId node_id) { node_value[node_id] = parallel::rank() + node_number[node_id]; }); + + if (parallel::size() > 1) { + REQUIRE(not is_same_item_value(node_value, node_value_ref)); + } + + Synchronizer synchronizer; + synchronizer.synchronize(node_value); + + REQUIRE(is_same_item_value(node_value, node_value_ref)); + } + + SECTION("synchonize EdgeValue") + { + const auto edge_owner = connectivity.edgeOwner(); + const auto edge_number = connectivity.edgeNumber(); + + EdgeValue<int> edge_value_ref{connectivity}; + parallel_for( + connectivity.numberOfEdges(), + PUGS_LAMBDA(const EdgeId edge_id) { edge_value_ref[edge_id] = edge_owner[edge_id] + edge_number[edge_id]; }); + + EdgeValue<int> edge_value{connectivity}; + parallel_for( + connectivity.numberOfEdges(), + PUGS_LAMBDA(const EdgeId edge_id) { edge_value[edge_id] = parallel::rank() + edge_number[edge_id]; }); + + if (parallel::size() > 1) { + REQUIRE(not is_same_item_value(edge_value, edge_value_ref)); + } + + Synchronizer synchronizer; + synchronizer.synchronize(edge_value); + + REQUIRE(is_same_item_value(edge_value, edge_value_ref)); + } + + SECTION("synchonize FaceValue") + { + const auto face_owner = connectivity.faceOwner(); + const auto face_number = connectivity.faceNumber(); + + FaceValue<int> face_value_ref{connectivity}; + parallel_for( + connectivity.numberOfFaces(), + PUGS_LAMBDA(const FaceId face_id) { face_value_ref[face_id] = face_owner[face_id] + face_number[face_id]; }); + + FaceValue<int> face_value{connectivity}; + parallel_for( + connectivity.numberOfFaces(), + PUGS_LAMBDA(const FaceId face_id) { face_value[face_id] = parallel::rank() + face_number[face_id]; }); + + if (parallel::size() > 1) { + REQUIRE(not is_same_item_value(face_value, face_value_ref)); + } + + Synchronizer synchronizer; + synchronizer.synchronize(face_value); + + REQUIRE(is_same_item_value(face_value, face_value_ref)); + } + + SECTION("synchonize CellValue") + { + const auto cell_owner = connectivity.cellOwner(); + const auto cell_number = connectivity.cellNumber(); + + CellValue<int> cell_value_ref{connectivity}; + parallel_for( + connectivity.numberOfCells(), + PUGS_LAMBDA(const CellId cell_id) { cell_value_ref[cell_id] = cell_owner[cell_id] + cell_number[cell_id]; }); + + CellValue<int> cell_value{connectivity}; + parallel_for( + connectivity.numberOfCells(), + PUGS_LAMBDA(const CellId cell_id) { cell_value[cell_id] = parallel::rank() + cell_number[cell_id]; }); + + if (parallel::size() > 1) { + REQUIRE(not is_same_item_value(cell_value, cell_value_ref)); + } + + Synchronizer synchronizer; + synchronizer.synchronize(cell_value); + + REQUIRE(is_same_item_value(cell_value, cell_value_ref)); + } + + SECTION("synchonize CellArray") + { + const auto cell_owner = connectivity.cellOwner(); + const auto cell_number = connectivity.cellNumber(); + + CellArray<int> cell_array_ref{connectivity, 3}; + parallel_for( + connectivity.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + for (size_t i = 0; i < cell_array_ref.sizeOfArrays(); ++i) { + cell_array_ref[cell_id][i] = (i + 1) * cell_owner[cell_id] + i + cell_number[cell_id]; + } + }); + + CellArray<int> cell_array{connectivity, 3}; + parallel_for( + connectivity.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + for (size_t i = 0; i < cell_array.sizeOfArrays(); ++i) { + cell_array[cell_id][i] = (i + 1) * parallel::rank() + i + cell_number[cell_id]; + } + }); + + if (parallel::size() > 1) { + REQUIRE(not is_same_item_array(cell_array, cell_array_ref)); + } + + Synchronizer synchronizer; + synchronizer.synchronize(cell_array); + + REQUIRE(is_same_item_array(cell_array, cell_array_ref)); + } + } +}