From 16d445be8e63c65c4003ad9498e8f65bdd69d7af Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Thu, 10 Oct 2024 09:21:37 +0200 Subject: [PATCH] Add tests for VariableBCDescriptor checkpointing --- tests/CMakeLists.txt | 1 + .../test_checkpointing_INamedDiscreteData.cpp | 2 - ...est_checkpointing_VariableBCDescriptor.cpp | 259 ++++++++++++++++++ 3 files changed, 260 insertions(+), 2 deletions(-) create mode 100644 tests/test_checkpointing_VariableBCDescriptor.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 14727109e..aafe42013 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -183,6 +183,7 @@ if(PUGS_HAS_HDF5) test_checkpointing_SubItemArrayPerItemVariant.cpp test_checkpointing_SubItemValuePerItemVariant.cpp test_checkpointing_Table.cpp + test_checkpointing_VariableBCDescriptor.cpp ) endif(PUGS_HAS_HDF5) diff --git a/tests/test_checkpointing_INamedDiscreteData.cpp b/tests/test_checkpointing_INamedDiscreteData.cpp index d11e29dca..be8bd252c 100644 --- a/tests/test_checkpointing_INamedDiscreteData.cpp +++ b/tests/test_checkpointing_INamedDiscreteData.cpp @@ -217,8 +217,6 @@ TEST_CASE("checkpointing_INamedDiscreteData", "[utils/checkpointing]") using R2x2 = TinyMatrix<2>; using R3x3 = TinyMatrix<3>; - NamedDiscreteFunction ndf; - HighFive::Group checkpoint_group = file.createGroup("checkpoint"); HighFive::Group symbol_table_group = checkpoint_group.createGroup("symbol_table"); diff --git a/tests/test_checkpointing_VariableBCDescriptor.cpp b/tests/test_checkpointing_VariableBCDescriptor.cpp new file mode 100644 index 000000000..e2d08dda0 --- /dev/null +++ b/tests/test_checkpointing_VariableBCDescriptor.cpp @@ -0,0 +1,259 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <utils/Messenger.hpp> + +#include <language/utils/DataHandler.hpp> +#include <language/utils/EmbeddedData.hpp> +#include <mesh/Mesh.hpp> +#include <mesh/NamedBoundaryDescriptor.hpp> +#include <mesh/NumberedBoundaryDescriptor.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> +#include <scheme/OutflowBoundaryConditionDescriptor.hpp> +#include <scheme/SymmetryBoundaryConditionDescriptor.hpp> +#include <scheme/VariableBCDescriptor.hpp> +#include <utils/GlobalVariableManager.hpp> +#include <utils/checkpointing/ReadVariableBCDescriptor.hpp> +#include <utils/checkpointing/ResumingData.hpp> +#include <utils/checkpointing/WriteVariableBCDescriptor.hpp> + +#include <MeshDataBaseForTests.hpp> +#include <checkpointing_Connectivity_utilities.hpp> +#include <checkpointing_Mesh_utilities.hpp> + +#include <filesystem> + +// clazy:excludeall=non-pod-global-static + +namespace test_only +{ + +template <typename DataType> +PUGS_INLINE void +VariableBCDescriptor_check_is_same_data(const DiscreteFunctionP0<DataType>& reference, const EmbeddedData& e_read_data) +{ + auto same_value = [](const auto& a, const auto& b) -> bool { + bool same = true; + for (size_t i = 0; i < a.size(); ++i) { + same &= (a[i] == b[i]); + } + return parallel::allReduceAnd(same); + }; + + REQUIRE_NOTHROW(dynamic_cast<const DataHandler<const VariableBCDescriptor>&>(e_read_data.get())); + + const VariableBCDescriptor& var_bc_desc_discrete_data = + *dynamic_cast<const DataHandler<const VariableBCDescriptor>&>(e_read_data.get()).data_ptr(); + + using DiscreteFunctionT = DiscreteFunctionP0<const DataType>; + + DiscreteFunctionT read_data = var_bc_desc_discrete_data.discreteFunctionVariant()->get<DiscreteFunctionT>(); + + REQUIRE(test_only::isSameMesh(read_data.meshVariant(), reference.meshVariant())); + + REQUIRE(same_value(reference.cellValues().arrayView(), read_data.cellValues().arrayView())); +} + +PUGS_INLINE void +VariableBCDescriptor_check_is_bc_list( + const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& reference_bc_list, + const EmbeddedData& e_read_data) +{ + REQUIRE_NOTHROW(dynamic_cast<const DataHandler<const VariableBCDescriptor>&>(e_read_data.get())); + + const VariableBCDescriptor& var_bc_desc_discrete_data = + *dynamic_cast<const DataHandler<const VariableBCDescriptor>&>(e_read_data.get()).data_ptr(); + + auto read_bc_list = var_bc_desc_discrete_data.bcDescriptorList(); + + REQUIRE(read_bc_list.size() == reference_bc_list.size()); + for (size_t i = 0; i < read_bc_list.size(); ++i) { + const auto reference_bc = reference_bc_list[i]; + const auto read_bc = read_bc_list[i]; + REQUIRE(read_bc->type() == reference_bc->type()); + REQUIRE(read_bc->boundaryDescriptor().type() == reference_bc->boundaryDescriptor().type()); + + switch (read_bc->boundaryDescriptor().type()) { + case IBoundaryDescriptor::Type::named: { + const NamedBoundaryDescriptor& ref_named_bc = + dynamic_cast<const NamedBoundaryDescriptor&>(reference_bc->boundaryDescriptor()); + const NamedBoundaryDescriptor& read_named_bc = + dynamic_cast<const NamedBoundaryDescriptor&>(read_bc->boundaryDescriptor()); + REQUIRE(ref_named_bc.name() == read_named_bc.name()); + break; + } + case IBoundaryDescriptor::Type::numbered: { + const NumberedBoundaryDescriptor& ref_numbered_bc = + dynamic_cast<const NumberedBoundaryDescriptor&>(reference_bc->boundaryDescriptor()); + const NumberedBoundaryDescriptor& read_numbered_bc = + dynamic_cast<const NumberedBoundaryDescriptor&>(read_bc->boundaryDescriptor()); + REQUIRE(ref_numbered_bc.number() == read_numbered_bc.number()); + break; + } + } + } +} + +} // namespace test_only + +TEST_CASE("checkpointing_VariableBCDescriptor", "[utils/checkpointing]") +{ + std::string tmp_dirname; + { + { + if (parallel::rank() == 0) { + tmp_dirname = [&]() -> std::string { + std::string temp_filename = std::filesystem::temp_directory_path() / "pugs_checkpointing_XXXXXX"; + return std::string{mkdtemp(&temp_filename[0])}; + }(); + } + parallel::broadcast(tmp_dirname, 0); + } + std::filesystem::path path = tmp_dirname; + const std::string filename = path / "checkpoint.h5"; + + HighFive::FileAccessProps fapl; + fapl.add(HighFive::MPIOFileAccess{MPI_COMM_WORLD, MPI_INFO_NULL}); + fapl.add(HighFive::MPIOCollectiveMetadata{}); + HighFive::File file = HighFive::File(filename, HighFive::File::Truncate, fapl); + + const size_t initial_connectivity_id = GlobalVariableManager::instance().getConnectivityId(); + const size_t initial_mesh_id = GlobalVariableManager::instance().getMeshId(); + + SECTION("Mesh") + { + using R2 = TinyVector<2>; + using R3 = TinyVector<3>; + + HighFive::Group checkpoint_group = file.createGroup("checkpoint"); + HighFive::Group symbol_table_group = checkpoint_group.createGroup("symbol_table"); + + auto mesh_1d = MeshDataBaseForTests::get().unordered1DMesh()->get<Mesh<1>>(); + + DiscreteFunctionP0<R2> df_R2_1d{mesh_1d}; + for (CellId cell_id = 0; cell_id < mesh_1d->numberOfCells(); ++cell_id) { + df_R2_1d[cell_id] = R2{std::rand() / (1. * RAND_MAX / mesh_1d->numberOfCells()), + std::rand() / (1. * RAND_MAX / mesh_1d->numberOfCells())}; + } + + std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>> bc_1d = + {std::make_shared<SymmetryBoundaryConditionDescriptor>(std::make_shared<NamedBoundaryDescriptor>("XMIN")), + std::make_shared<OutflowBoundaryConditionDescriptor>(std::make_shared<NamedBoundaryDescriptor>("XMAX"))}; + + auto mesh_2d = MeshDataBaseForTests::get().hybrid2DMesh()->get<Mesh<2>>(); + + DiscreteFunctionP0<R3> df_R3_2d{mesh_2d}; + for (CellId cell_id = 0; cell_id < mesh_2d->numberOfCells(); ++cell_id) { + df_R3_2d[cell_id] = R3{std::rand() / (1. * RAND_MAX / mesh_2d->numberOfCells()), + std::rand() / (1. * RAND_MAX / mesh_2d->numberOfCells()), + std::rand() / (1. * RAND_MAX / mesh_2d->numberOfCells())}; + } + + std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>> bc_2d = + {std::make_shared<SymmetryBoundaryConditionDescriptor>(std::make_shared<NamedBoundaryDescriptor>("XMIN")), + std::make_shared<OutflowBoundaryConditionDescriptor>(std::make_shared<NamedBoundaryDescriptor>("XMAX")), + std::make_shared<SymmetryBoundaryConditionDescriptor>(std::make_shared<NamedBoundaryDescriptor>("YMIN")), + std::make_shared<SymmetryBoundaryConditionDescriptor>(std::make_shared<NamedBoundaryDescriptor>("YMAX"))}; + + auto mesh_3d = MeshDataBaseForTests::get().hybrid3DMesh()->get<Mesh<3>>(); + + DiscreteFunctionP0<R3> df_R3_3d{mesh_3d}; + for (CellId cell_id = 0; cell_id < mesh_3d->numberOfCells(); ++cell_id) { + df_R3_3d[cell_id] = R3{std::rand() / (1. * RAND_MAX / mesh_3d->numberOfCells()), + std::rand() / (1. * RAND_MAX / mesh_3d->numberOfCells()), + std::rand() / (1. * RAND_MAX / mesh_3d->numberOfCells())}; + } + + std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>> bc_3d = + {std::make_shared<SymmetryBoundaryConditionDescriptor>(std::make_shared<NamedBoundaryDescriptor>("XMIN")), + std::make_shared<OutflowBoundaryConditionDescriptor>(std::make_shared<NamedBoundaryDescriptor>("XMAX")), + std::make_shared<SymmetryBoundaryConditionDescriptor>(std::make_shared<NamedBoundaryDescriptor>("YMIN")), + std::make_shared<SymmetryBoundaryConditionDescriptor>(std::make_shared<NamedBoundaryDescriptor>("YMAX")), + std::make_shared<SymmetryBoundaryConditionDescriptor>(std::make_shared<NamedBoundaryDescriptor>("ZMIN")), + std::make_shared<SymmetryBoundaryConditionDescriptor>(std::make_shared<NamedBoundaryDescriptor>("ZMAX"))}; + + { // Write + using DataHandlerT = DataHandler<const VariableBCDescriptor>; + + auto new_mesh_1d_v = test_only::duplicateMesh(std::make_shared<MeshVariant>(mesh_1d)); + auto new_mesh_1d = new_mesh_1d_v->get<const Mesh<1>>(); + const auto& new_connectivity_1d = new_mesh_1d->connectivity(); + + DiscreteFunctionP0<const R2> df_R2_1d_new{new_mesh_1d_v, + CellValue<const R2>{new_connectivity_1d, + df_R2_1d.cellValues().arrayView()}}; + std::shared_ptr<const VariableBCDescriptor> var_bc_desc_1d = + std::make_shared<VariableBCDescriptor>(std::make_shared<const DiscreteFunctionVariant>(df_R2_1d_new), bc_1d); + + checkpointing::writeVariableBCDescriptor("var_bc_desc_1d", + EmbeddedData{std::make_shared<DataHandlerT>(var_bc_desc_1d)}, file, + checkpoint_group, symbol_table_group); + + auto new_mesh_2d_v = test_only::duplicateMesh(std::make_shared<MeshVariant>(mesh_2d)); + auto new_mesh_2d = new_mesh_2d_v->get<const Mesh<2>>(); + const auto& new_connectivity_2d = new_mesh_2d->connectivity(); + + DiscreteFunctionP0<const R3> df_R3_2d_new{new_mesh_2d_v, + CellValue<const R3>{new_connectivity_2d, + df_R3_2d.cellValues().arrayView()}}; + + std::shared_ptr<const VariableBCDescriptor> var_bc_desc_2d = + std::make_shared<VariableBCDescriptor>(std::make_shared<const DiscreteFunctionVariant>(df_R3_2d_new), bc_2d); + + checkpointing::writeVariableBCDescriptor("var_bc_desc_2d", + EmbeddedData{std::make_shared<DataHandlerT>(var_bc_desc_2d)}, file, + checkpoint_group, symbol_table_group); + + auto new_mesh_3d_v = test_only::duplicateMesh(std::make_shared<MeshVariant>(mesh_3d)); + auto new_mesh_3d = new_mesh_3d_v->get<const Mesh<3>>(); + const auto& new_connectivity_3d = new_mesh_3d->connectivity(); + + DiscreteFunctionP0<const R3> df_R3_3d_new{new_mesh_3d, CellValue<const R3>{new_connectivity_3d, + df_R3_3d.cellValues().arrayView()}}; + + std::shared_ptr<const VariableBCDescriptor> var_bc_desc_3d = + std::make_shared<VariableBCDescriptor>(std::make_shared<const DiscreteFunctionVariant>(df_R3_3d_new), bc_3d); + + checkpointing::writeVariableBCDescriptor("var_bc_desc_3d", + EmbeddedData{std::make_shared<DataHandlerT>(var_bc_desc_3d)}, file, + checkpoint_group, symbol_table_group); + + HighFive::Group global_variables_group = checkpoint_group.createGroup("singleton/global_variables"); + global_variables_group.createAttribute("connectivity_id", + GlobalVariableManager::instance().getConnectivityId()); + global_variables_group.createAttribute("mesh_id", GlobalVariableManager::instance().getMeshId()); + } + + // reset to reuse after resuming + GlobalVariableManager::instance().setConnectivityId(initial_connectivity_id); + GlobalVariableManager::instance().setMeshId(initial_mesh_id); + + file.flush(); + + checkpointing::ResumingData::create(); + checkpointing::ResumingData::instance().readData(checkpoint_group, nullptr); + + GlobalVariableManager::instance().setConnectivityId(initial_connectivity_id); + GlobalVariableManager::instance().setMeshId(initial_mesh_id); + { // Read + auto e_var_bc_desc_1d = checkpointing::readVariableBCDescriptor("var_bc_desc_1d", symbol_table_group); + test_only::VariableBCDescriptor_check_is_bc_list(bc_1d, e_var_bc_desc_1d); + test_only::VariableBCDescriptor_check_is_same_data(df_R2_1d, e_var_bc_desc_1d); + + auto e_var_bc_desc_2d = checkpointing::readVariableBCDescriptor("var_bc_desc_2d", symbol_table_group); + test_only::VariableBCDescriptor_check_is_bc_list(bc_2d, e_var_bc_desc_2d); + test_only::VariableBCDescriptor_check_is_same_data(df_R3_2d, e_var_bc_desc_2d); + + auto e_var_bc_desc_3d = checkpointing::readVariableBCDescriptor("var_bc_desc_3d", symbol_table_group); + test_only::VariableBCDescriptor_check_is_bc_list(bc_3d, e_var_bc_desc_3d); + test_only::VariableBCDescriptor_check_is_same_data(df_R3_3d, e_var_bc_desc_3d); + } + checkpointing::ResumingData::destroy(); + } + } + + parallel::barrier(); + if (parallel::rank() == 0) { + std::filesystem::remove_all(std::filesystem::path{tmp_dirname}); + } +} -- GitLab