Skip to content
Snippets Groups Projects
Commit d77a2cf7 authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Add tests for Mesh checkpointing

parent 92c34b1a
No related branches found
No related tags found
1 merge request!199Integrate checkpointing
...@@ -154,9 +154,11 @@ ResumingData::_getConnectivityList(const HighFive::Group& checkpoint) ...@@ -154,9 +154,11 @@ ResumingData::_getConnectivityList(const HighFive::Group& checkpoint)
m_id_to_iconnectivity_map.insert({id, Connectivity<3>::build(descriptor)}); m_id_to_iconnectivity_map.insert({id, Connectivity<3>::build(descriptor)});
break; break;
} }
// LCOV_EXCL_START
default: { default: {
throw UnexpectedError("invalid dimension " + std::to_string(dimension)); throw UnexpectedError("invalid dimension " + std::to_string(dimension));
} }
// LCOV_EXCL_STOP
} }
} else if (type == "dual_connectivity") { } else if (type == "dual_connectivity") {
const DualMeshType type_of_dual = connectivity_data.getAttribute("type_of_dual").read<DualMeshType>(); const DualMeshType type_of_dual = connectivity_data.getAttribute("type_of_dual").read<DualMeshType>();
...@@ -168,7 +170,9 @@ ResumingData::_getConnectivityList(const HighFive::Group& checkpoint) ...@@ -168,7 +170,9 @@ ResumingData::_getConnectivityList(const HighFive::Group& checkpoint)
switch (iprimal_connectivity->dimension()) { switch (iprimal_connectivity->dimension()) {
case 1: { case 1: {
if (type_of_dual != DualMeshType::Dual1D) { if (type_of_dual != DualMeshType::Dual1D) {
// LCOV_EXCL_START
throw UnexpectedError("unexpected dual mesh type"); throw UnexpectedError("unexpected dual mesh type");
// LCOV_EXCL_STOP
} }
const Connectivity<1>& primal_connectivity = dynamic_cast<const Connectivity<1>&>(*iprimal_connectivity); const Connectivity<1>& primal_connectivity = dynamic_cast<const Connectivity<1>&>(*iprimal_connectivity);
...@@ -186,7 +190,9 @@ ResumingData::_getConnectivityList(const HighFive::Group& checkpoint) ...@@ -186,7 +190,9 @@ ResumingData::_getConnectivityList(const HighFive::Group& checkpoint)
m_id_to_iconnectivity_map.insert( m_id_to_iconnectivity_map.insert(
{id, DualConnectivityManager::instance().getMedianDualConnectivity(primal_connectivity)}); {id, DualConnectivityManager::instance().getMedianDualConnectivity(primal_connectivity)});
} else { } else {
// LCOV_EXCL_START
throw UnexpectedError("unexpected dual mesh type"); throw UnexpectedError("unexpected dual mesh type");
// LCOV_EXCL_STOP
} }
break; break;
} }
...@@ -200,16 +206,22 @@ ResumingData::_getConnectivityList(const HighFive::Group& checkpoint) ...@@ -200,16 +206,22 @@ ResumingData::_getConnectivityList(const HighFive::Group& checkpoint)
m_id_to_iconnectivity_map.insert( m_id_to_iconnectivity_map.insert(
{id, DualConnectivityManager::instance().getMedianDualConnectivity(primal_connectivity)}); {id, DualConnectivityManager::instance().getMedianDualConnectivity(primal_connectivity)});
} else { } else {
// LCOV_EXCL_START
throw UnexpectedError("unexpected dual mesh type"); throw UnexpectedError("unexpected dual mesh type");
// LCOV_EXCL_STOP
} }
break; break;
} }
// LCOV_EXCL_START
default: { default: {
throw UnexpectedError("unexpected dimension"); throw UnexpectedError("unexpected dimension");
} }
// LCOV_EXCL_STOP
} }
} else { } else {
// LCOV_EXCL_START
throw UnexpectedError("invalid connectivity type: " + type); throw UnexpectedError("invalid connectivity type: " + type);
// LCOV_EXCL_STOP
} }
} }
} }
...@@ -229,11 +241,15 @@ ResumingData::_readPolygonalMesh(const HighFive::Group& mesh_data) ...@@ -229,11 +241,15 @@ ResumingData::_readPolygonalMesh(const HighFive::Group& mesh_data)
const uint64_t connectivity_id = mesh_data.getAttribute("connectivity").read<uint64_t>(); const uint64_t connectivity_id = mesh_data.getAttribute("connectivity").read<uint64_t>();
auto i_id_to_iconnectivity = m_id_to_iconnectivity_map.find(connectivity_id); auto i_id_to_iconnectivity = m_id_to_iconnectivity_map.find(connectivity_id);
if (i_id_to_iconnectivity == m_id_to_iconnectivity_map.end()) { if (i_id_to_iconnectivity == m_id_to_iconnectivity_map.end()) {
// LCOV_EXCL_START
throw UnexpectedError("cannot find connectivity " + std::to_string(connectivity_id)); throw UnexpectedError("cannot find connectivity " + std::to_string(connectivity_id));
// LCOV_EXCL_STOP
} }
std::shared_ptr<const IConnectivity> i_connectivity = i_id_to_iconnectivity->second; std::shared_ptr<const IConnectivity> i_connectivity = i_id_to_iconnectivity->second;
if (i_connectivity->dimension() != Dimension) { if (i_connectivity->dimension() != Dimension) {
// LCOV_EXCL_START
throw UnexpectedError("invalid connectivity dimension " + std::to_string(i_connectivity->dimension())); throw UnexpectedError("invalid connectivity dimension " + std::to_string(i_connectivity->dimension()));
// LCOV_EXCL_STOP
} }
std::shared_ptr<const Connectivity<Dimension>> connectivity = std::shared_ptr<const Connectivity<Dimension>> connectivity =
...@@ -288,9 +304,11 @@ ResumingData::_getMeshVariantList(const HighFive::Group& checkpoint) ...@@ -288,9 +304,11 @@ ResumingData::_getMeshVariantList(const HighFive::Group& checkpoint)
m_id_to_mesh_variant_map.insert({id, this->_readPolygonalMesh<3>(mesh_data)}); m_id_to_mesh_variant_map.insert({id, this->_readPolygonalMesh<3>(mesh_data)});
break; break;
} }
// LCOV_EXCL_START
default: { default: {
throw UnexpectedError("invalid mesh dimension " + std::to_string(dimension)); throw UnexpectedError("invalid mesh dimension " + std::to_string(dimension));
} }
// LCOV_EXCL_STOP
} }
} else if (type == "dual_mesh") { } else if (type == "dual_mesh") {
const DualMeshType type_of_dual = mesh_data.getAttribute("type_of_dual").read<DualMeshType>(); const DualMeshType type_of_dual = mesh_data.getAttribute("type_of_dual").read<DualMeshType>();
...@@ -305,7 +323,9 @@ ResumingData::_getMeshVariantList(const HighFive::Group& checkpoint) ...@@ -305,7 +323,9 @@ ResumingData::_getMeshVariantList(const HighFive::Group& checkpoint)
if (type_of_dual == DualMeshType::Dual1D) { if (type_of_dual == DualMeshType::Dual1D) {
m_id_to_mesh_variant_map.insert({id, DualMeshManager::instance().getDual1DMesh(primal_mesh_variant)}); m_id_to_mesh_variant_map.insert({id, DualMeshManager::instance().getDual1DMesh(primal_mesh_variant)});
} else { } else {
// LCOV_EXCL_START
throw UnexpectedError("unexpected dual mesh type"); throw UnexpectedError("unexpected dual mesh type");
// LCOV_EXCL_STOP
} }
} else if constexpr (std::is_same_v<MeshType, Mesh<2>> or std::is_same_v<MeshType, Mesh<3>>) { } else if constexpr (std::is_same_v<MeshType, Mesh<2>> or std::is_same_v<MeshType, Mesh<3>>) {
if (type_of_dual == DualMeshType::Diamond) { if (type_of_dual == DualMeshType::Diamond) {
...@@ -315,14 +335,18 @@ ResumingData::_getMeshVariantList(const HighFive::Group& checkpoint) ...@@ -315,14 +335,18 @@ ResumingData::_getMeshVariantList(const HighFive::Group& checkpoint)
m_id_to_mesh_variant_map.insert( m_id_to_mesh_variant_map.insert(
{id, DualMeshManager::instance().getMedianDualMesh(primal_mesh_variant)}); {id, DualMeshManager::instance().getMedianDualMesh(primal_mesh_variant)});
} else { } else {
// LCOV_EXCL_START
throw UnexpectedError("unexpected dual mesh type"); throw UnexpectedError("unexpected dual mesh type");
// LCOV_EXCL_STOP
} }
} }
}, },
primal_mesh_variant->variant()); primal_mesh_variant->variant());
} else { } else {
// LCOV_EXCL_START
throw UnexpectedError("invalid mesh type"); throw UnexpectedError("invalid mesh type");
// LCOV_EXCL_STOP
} }
} }
} }
......
...@@ -174,6 +174,7 @@ if(PUGS_HAS_HDF5) ...@@ -174,6 +174,7 @@ if(PUGS_HAS_HDF5)
test_checkpointing_ItemType.cpp test_checkpointing_ItemType.cpp
test_checkpointing_IWriter.cpp test_checkpointing_IWriter.cpp
test_checkpointing_IZoneDescriptor.cpp test_checkpointing_IZoneDescriptor.cpp
test_checkpointing_Mesh.cpp
test_checkpointing_Table.cpp test_checkpointing_Table.cpp
) )
endif(PUGS_HAS_HDF5) endif(PUGS_HAS_HDF5)
......
#ifndef CHECKPOINTING_MESH_UTILITIES_HPP
#define CHECKPOINTING_MESH_UTILITIES_HPP
#include <checkpointing_Connectivity_utilities.hpp>
#include <mesh/Mesh.hpp>
#include <mesh/MeshTraits.hpp>
#include <mesh/MeshVariant.hpp>
namespace test_only
{
PUGS_INLINE
std::shared_ptr<const MeshVariant>
duplicateMesh(std::shared_ptr<const MeshVariant> mesh_v)
{
std::shared_ptr<const MeshVariant> new_mesh_v;
std::visit(
[&](auto&& mesh) {
using MeshType = mesh_type_t<decltype(mesh)>;
if constexpr (is_polygonal_mesh_v<MeshType>) {
using Rd = TinyVector<MeshType::Dimension>;
auto new_connectivity =
std::dynamic_pointer_cast<const typename MeshType::Connectivity>(duplicateConnectivity(mesh->connectivity()));
NodeValue<const Rd> new_xr{*new_connectivity, mesh->xr().arrayView()};
new_mesh_v = std::make_shared<MeshVariant>(std::make_shared<const MeshType>(new_connectivity, new_xr));
} else {
throw NotImplementedError("unexpected mesh type");
}
},
mesh_v->variant());
return new_mesh_v;
}
PUGS_INLINE bool
isSameMesh(std::shared_ptr<const MeshVariant> mesh_v, std::shared_ptr<const MeshVariant> read_mesh_v)
{
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);
};
bool same = true;
std::visit(
[&](auto&& mesh, auto&& read_mesh) {
using MeshType = mesh_type_t<decltype(mesh)>;
using ReadMeshType = mesh_type_t<decltype(read_mesh)>;
if constexpr (std::is_same_v<MeshType, ReadMeshType>) {
same &= test_only::isSameConnectivity(mesh->connectivity(), read_mesh->connectivity());
same &= same_value(mesh->xr().arrayView(), read_mesh->xr().arrayView());
} else {
throw UnexpectedError("mesh of different kind");
}
},
mesh_v->variant(), read_mesh_v->variant());
return same;
}
} // namespace test_only
#endif // CHECKPOINTING_MESH_UTILITIES_HPP
#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/MeshVariant.hpp>
#include <utils/GlobalVariableManager.hpp>
#include <utils/checkpointing/ReadMesh.hpp>
#include <utils/checkpointing/ResumingData.hpp>
#include <utils/checkpointing/WriteMesh.hpp>
#include <MeshDataBaseForTests.hpp>
#include <checkpointing_Mesh_utilities.hpp>
#include <filesystem>
// clazy:excludeall=non-pod-global-static
TEST_CASE("checkpointing_Mesh", "[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")
{
HighFive::Group checkpoint_group_0 = file.createGroup("checkpoint_0");
HighFive::Group symbol_table_0 = checkpoint_group_0.createGroup("symbol_table");
HighFive::Group checkpoint_group_1 = file.createGroup("checkpoint_1");
HighFive::Group symbol_table_1 = checkpoint_group_1.createGroup("symbol_table");
{ // Write
auto mesh_1d = MeshDataBaseForTests::get().unordered1DMesh();
// creates artificially holes in numbering
test_only::duplicateMesh(mesh_1d);
auto new_mesh_1d = test_only::duplicateMesh(mesh_1d);
using DataHandlerT = DataHandler<const MeshVariant>;
checkpointing::writeMesh("mesh_1d", EmbeddedData{std::make_shared<DataHandlerT>(new_mesh_1d)}, file,
checkpoint_group_0, symbol_table_0);
checkpointing::writeMesh("mesh_1d", EmbeddedData{std::make_shared<DataHandlerT>(new_mesh_1d)}, file,
checkpoint_group_1, symbol_table_1);
auto mesh_2d = MeshDataBaseForTests::get().hybrid2DMesh();
// creates artificially holes in numbering
test_only::duplicateMesh(mesh_2d);
auto new_mesh_2d = test_only::duplicateMesh(mesh_2d);
checkpointing::writeMesh("mesh_2d", EmbeddedData{std::make_shared<DataHandlerT>(new_mesh_2d)}, file,
checkpoint_group_0, symbol_table_0);
checkpointing::writeMesh("mesh_2d", EmbeddedData{std::make_shared<DataHandlerT>(new_mesh_2d)}, file,
checkpoint_group_1, symbol_table_1);
HighFive::Group global_variables_group_0 = checkpoint_group_0.createGroup("singleton/global_variables");
global_variables_group_0.createAttribute("connectivity_id",
GlobalVariableManager::instance().getConnectivityId());
global_variables_group_0.createAttribute("mesh_id", GlobalVariableManager::instance().getMeshId());
auto mesh_3d = MeshDataBaseForTests::get().hybrid3DMesh();
// creates artificially holes in numbering
test_only::duplicateMesh(mesh_3d);
auto new_mesh_3d = test_only::duplicateMesh(mesh_3d);
checkpointing::writeMesh("mesh_3d", EmbeddedData{std::make_shared<DataHandlerT>(new_mesh_3d)}, file,
checkpoint_group_1, symbol_table_1);
// creates artificially holes in numbering
test_only::duplicateMesh(mesh_3d);
test_only::duplicateMesh(mesh_3d);
test_only::duplicateMesh(mesh_3d);
HighFive::Group global_variables_group_1 = checkpoint_group_1.createGroup("singleton/global_variables");
global_variables_group_1.createAttribute("connectivity_id",
GlobalVariableManager::instance().getConnectivityId());
global_variables_group_1.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_1, nullptr);
GlobalVariableManager::instance().setConnectivityId(initial_connectivity_id);
GlobalVariableManager::instance().setMeshId(initial_mesh_id);
{ // Read
auto mesh_1d = MeshDataBaseForTests::get().unordered1DMesh();
EmbeddedData e_mesh_1d = checkpointing::readMesh("mesh_1d", symbol_table_1);
REQUIRE_NOTHROW(dynamic_cast<const DataHandler<const MeshVariant>&>(e_mesh_1d.get()));
std::shared_ptr<const MeshVariant> read_mesh_1d =
dynamic_cast<const DataHandler<const MeshVariant>&>(e_mesh_1d.get()).data_ptr();
REQUIRE(test_only::isSameMesh(mesh_1d, read_mesh_1d));
auto mesh_2d = MeshDataBaseForTests::get().hybrid2DMesh();
EmbeddedData e_mesh_2d = checkpointing::readMesh("mesh_2d", symbol_table_1);
REQUIRE_NOTHROW(dynamic_cast<const DataHandler<const MeshVariant>&>(e_mesh_2d.get()));
std::shared_ptr<const MeshVariant> read_mesh_2d =
dynamic_cast<const DataHandler<const MeshVariant>&>(e_mesh_2d.get()).data_ptr();
REQUIRE(test_only::isSameMesh(mesh_2d, read_mesh_2d));
auto mesh_3d = MeshDataBaseForTests::get().hybrid3DMesh();
EmbeddedData e_mesh_3d = checkpointing::readMesh("mesh_3d", symbol_table_1);
REQUIRE_NOTHROW(dynamic_cast<const DataHandler<const MeshVariant>&>(e_mesh_3d.get()));
std::shared_ptr<const MeshVariant> read_mesh_3d =
dynamic_cast<const DataHandler<const MeshVariant>&>(e_mesh_3d.get()).data_ptr();
REQUIRE(test_only::isSameMesh(mesh_3d, read_mesh_3d));
}
checkpointing::ResumingData::destroy();
}
}
parallel::barrier();
if (parallel::rank() == 0) {
std::filesystem::remove_all(std::filesystem::path{tmp_dirname});
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment