diff --git a/src/utils/checkpointing/Resume.cpp b/src/utils/checkpointing/Resume.cpp index 184011049c31febd92f53439bf1389b49fbbd6f2..9d58e1d9dec4050f218d3efad71e5194ccaa5111 100644 --- a/src/utils/checkpointing/Resume.cpp +++ b/src/utils/checkpointing/Resume.cpp @@ -233,15 +233,19 @@ resume() } break; } + // LCOV_EXCL_START default: { throw NotImplementedError(symbol_name + " of type " + dataTypeName(attribute.dataType().contentType())); } + // LCOV_EXCL_STOP } break; } + // LCOV_EXCL_START default: { throw NotImplementedError(symbol_name + " of type " + dataTypeName(attribute.dataType())); } + // LCOV_EXCL_STOP } } @@ -286,9 +290,11 @@ resume() checkpointing::ResumingData::destroy(); } + // LCOV_EXCL_START catch (HighFive::Exception& e) { throw NormalError(e.what()); } + // LCOV_EXCL_STOP } #else // PUGS_HAS_HDF5 diff --git a/src/utils/checkpointing/ResumingData.cpp b/src/utils/checkpointing/ResumingData.cpp index 2fc7996cc09f1d99d2ec827d5ea66ef2abe8b39a..2301f199496df36343dbe301feb5df11d3fcd9f2 100644 --- a/src/utils/checkpointing/ResumingData.cpp +++ b/src/utils/checkpointing/ResumingData.cpp @@ -368,33 +368,41 @@ ResumingData::_getFunctionIds(const HighFive::Group& checkpoint, std::shared_ptr for (auto symbol : p_symbol_table->symbolList()) { if (symbol.attributes().dataType() == ASTNodeDataType::function_t) { if (not function_group.exist(symbol.name())) { + // LCOV_EXCL_START std::ostringstream error_msg; error_msg << "cannot find function " << rang::fgB::yellow << symbol.name() << rang::fg::reset << " in " << rang::fgB::cyan << checkpoint.getFile().getName() << rang::fg::reset; - throw NormalError(error_msg.str()); - } else { + throw UnexpectedError(error_msg.str()); + // LCOV_EXCL_STOP + } else { // LCOV_EXCL_LINE const HighFive::Group function = function_group.getGroup(symbol.name()); const size_t stored_function_id = function.getAttribute("id").read<size_t>(); const size_t function_id = std::get<size_t>(symbol.attributes().value()); if (symbol_table_id != function.getAttribute("symbol_table_id").read<size_t>()) { + // LCOV_EXCL_START std::ostringstream error_msg; error_msg << "symbol table of function " << rang::fgB::yellow << symbol.name() << rang::fg::reset << " does not match the one stored in " << rang::fgB::cyan << checkpoint.getFile().getName() << rang::fg::reset; - throw NormalError(error_msg.str()); + throw UnexpectedError(error_msg.str()); + // LCOV_EXCL_STOP } else if (function_id != stored_function_id) { + // LCOV_EXCL_START std::ostringstream error_msg; error_msg << "id (" << function_id << ") of function " << rang::fgB::yellow << symbol.name() << rang::fg::reset << " does not match the one stored in " << rang::fgB::cyan << checkpoint.getFile().getName() << rang::fg::reset << "(" << stored_function_id << ")"; - throw NormalError(error_msg.str()); - } else { + throw UnexpectedError(error_msg.str()); + // LCOV_EXCL_STOP + } else { // LCOV_EXCL_LINE if (m_id_to_function_symbol_id_map.contains(function_id)) { + // LCOV_EXCL_START std::ostringstream error_msg; error_msg << "id (" << function_id << ") of function " << rang::fgB::yellow << symbol.name() << rang::fg::reset << " is duplicated"; throw UnexpectedError(error_msg.str()); - } + // LCOV_EXCL_STOP + } // LCOV_EXCL_LINE m_id_to_function_symbol_id_map[function_id] = std::make_shared<FunctionSymbolId>(function_id, p_symbol_table); } @@ -420,7 +428,9 @@ ResumingData::iConnectivity(const size_t connectivity_id) const { auto i_id_to_connectivity = m_id_to_iconnectivity_map.find(connectivity_id); if (i_id_to_connectivity == m_id_to_iconnectivity_map.end()) { + // LCOV_EXCL_START throw UnexpectedError("cannot find connectivity of id " + std::to_string(connectivity_id)); + // LCOV_EXCL_STOP } else { return i_id_to_connectivity->second; } @@ -431,7 +441,9 @@ ResumingData::meshVariant(const size_t mesh_id) const { auto i_id_to_mesh = m_id_to_mesh_variant_map.find(mesh_id); if (i_id_to_mesh == m_id_to_mesh_variant_map.end()) { + // LCOV_EXCL_START throw UnexpectedError("cannot find mesh of id " + std::to_string(mesh_id)); + // LCOV_EXCL_STOP } else { return i_id_to_mesh->second; } @@ -442,7 +454,9 @@ ResumingData::functionSymbolId(const size_t function_symbol_id) const { auto i_id_to_function_symbol_id = m_id_to_function_symbol_id_map.find(function_symbol_id); if (i_id_to_function_symbol_id == m_id_to_function_symbol_id_map.end()) { + // LCOV_EXCL_START throw UnexpectedError("cannot find function_symbol_id of id " + std::to_string(function_symbol_id)); + // LCOV_EXCL_STOP } else { return i_id_to_function_symbol_id->second; } diff --git a/src/utils/checkpointing/SetResumeFrom.cpp b/src/utils/checkpointing/SetResumeFrom.cpp index 81502da2f74e9d0e71d812d8692d7318b3135e71..7f040e7caaaf7c4eb8a27017f608127507b59cf0 100644 --- a/src/utils/checkpointing/SetResumeFrom.cpp +++ b/src/utils/checkpointing/SetResumeFrom.cpp @@ -9,13 +9,19 @@ #include <utils/Exceptions.hpp> #include <utils/HighFivePugsUtils.hpp> +#include <utils/Messenger.hpp> void setResumeFrom(const std::string& filename, const uint64_t& checkpoint_number, std::ostream& os) { try { HighFive::SilenceHDF5 m_silence_hdf5{true}; - HighFive::File file(filename, HighFive::File::ReadWrite); + + HighFive::FileAccessProps fapl; + fapl.add(HighFive::MPIOFileAccess{parallel::Messenger::getInstance().comm(), MPI_INFO_NULL}); + fapl.add(HighFive::MPIOCollectiveMetadata{}); + + HighFive::File file(filename, HighFive::File::ReadWrite, fapl); const std::string checkpoint_name = "checkpoint_" + std::to_string(checkpoint_number); if (not file.exist(checkpoint_name)) { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6a7c235ffd1c118f88b60e39e8f81d13290add53..c3a25aec9b243afb7e5bd9b951286f322606099b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,8 +7,7 @@ include_directories(${PUGS_SOURCE_DIR}/tests) set(checkpointing_sequential_TESTS # this one should enventually integrate parallel tests test_checkpointing_Checkpoint_sequential.cpp - - test_checkpointing_SetResumeFrom.cpp + test_checkpointing_Resume_sequential.cpp ) add_executable (unit_tests @@ -171,6 +170,7 @@ add_executable (unit_tests test_checkpointing_PrintScriptFrom.cpp test_checkpointing_ResumingManager.cpp test_checkpointing_ResumingUtils.cpp + test_checkpointing_SetResumeFrom.cpp ) if(PUGS_HAS_HDF5) diff --git a/tests/test_checkpointing_Checkpoint.cpp b/tests/test_checkpointing_Checkpoint.cpp index cfcf67188c2f43261f21e4d9ece28bdc50c9c060..317683b26dfca317b4b6f0059b6a8e55c8d5e4f0 100644 --- a/tests/test_checkpointing_Checkpoint.cpp +++ b/tests/test_checkpointing_Checkpoint.cpp @@ -75,6 +75,9 @@ TEST_CASE("checkpointing_Checkpoint", "[utils/checkpointing]") { #ifdef PUGS_HAS_HDF5 + ResumingManager::destroy(); + ResumingManager::create(); + std::string tmp_dirname; { { diff --git a/tests/test_checkpointing_Checkpoint_sequential.cpp b/tests/test_checkpointing_Checkpoint_sequential.cpp index 23ddd807415ddf2111a6f8e010c60431010f47f9..160404f8835a7fcf6a0c94700ae79d023391b2ca 100644 --- a/tests/test_checkpointing_Checkpoint_sequential.cpp +++ b/tests/test_checkpointing_Checkpoint_sequential.cpp @@ -77,6 +77,9 @@ TEST_CASE("checkpointing_Checkpoint_sequential", "[utils/checkpointing]") { #ifdef PUGS_HAS_HDF5 + ResumingManager::destroy(); + ResumingManager::create(); + std::string tmp_dirname; { { diff --git a/tests/test_checkpointing_Resume_sequential.cpp b/tests/test_checkpointing_Resume_sequential.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e8a3aa1038a3089c5188bfb2dc19f4dc6a4abdbc --- /dev/null +++ b/tests/test_checkpointing_Resume_sequential.cpp @@ -0,0 +1,729 @@ +#include <catch2/catch_approx.hpp> +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_predicate.hpp> + +#include <utils/checkpointing/Resume.hpp> +#include <utils/pugs_config.hpp> + +#ifdef PUGS_HAS_HDF5 + +#include <MeshDataBaseForTests.hpp> +#include <dev/ParallelChecker.hpp> +#include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTExecutionStack.hpp> +#include <language/ast/ASTModulesImporter.hpp> +#include <language/ast/ASTNodeDataTypeBuilder.hpp> +#include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> +#include <language/ast/ASTNodeExpressionBuilder.hpp> +#include <language/ast/ASTNodeTypeCleaner.hpp> +#include <language/ast/ASTSymbolTableBuilder.hpp> +#include <language/modules/MathModule.hpp> +#include <language/utils/ASTCheckpointsInfo.hpp> +#include <language/utils/CheckpointResumeRepository.hpp> +#include <mesh/DualMeshType.hpp> +#include <utils/ExecutionStatManager.hpp> +#include <utils/checkpointing/DualMeshTypeHFType.hpp> +#include <utils/checkpointing/SetResumeFrom.hpp> + +class ASTCheckpointsInfoTester +{ + private: + ASTCheckpointsInfo m_ast_checkpoint_info; + + public: + ASTCheckpointsInfoTester(const ASTNode& root_node) : m_ast_checkpoint_info(root_node) {} + ~ASTCheckpointsInfoTester() = default; +}; + +#define RUN_AST(data) \ + { \ + ExecutionStatManager::create(); \ + ParallelChecker::create(); \ + CheckpointResumeRepository::create(); \ + \ + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ + auto ast = ASTBuilder::build(input); \ + \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ + ASTSymbolTableBuilder{*ast}; \ + ASTNodeDataTypeBuilder{*ast}; \ + \ + ASTNodeDeclarationToAffectationConverter{*ast}; \ + ASTNodeTypeCleaner<language::var_declaration>{*ast}; \ + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; \ + \ + ASTNodeExpressionBuilder{*ast}; \ + ExecutionPolicy exec_policy; \ + ASTExecutionStack::create(); \ + ASTCheckpointsInfoTester ast_cp_info_tester{*ast}; \ + ast->execute(exec_policy); \ + ASTExecutionStack::destroy(); \ + ast->m_symbol_table->clearValues(); \ + \ + CheckpointResumeRepository::destroy(); \ + ParallelChecker::destroy(); \ + ExecutionStatManager::destroy(); \ + ast->m_symbol_table->clearValues(); \ + } + +#endif // PUGS_HAS_HDF5 + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("checkpointing_Resume_sequential", "[utils/checkpointing]") +{ +#ifdef PUGS_HAS_HDF5 + + auto frobeniusNorm = [](const auto& A) { + using A_T = std::decay_t<decltype(A)>; + static_assert(is_tiny_matrix_v<A_T>); + return std::sqrt(trace(transpose(A) * A)); + }; + + using R1 = TinyVector<1>; + using R2 = TinyVector<2>; + using R3 = TinyVector<3>; + + using R11 = TinyMatrix<1>; + using R22 = TinyMatrix<2>; + using R33 = TinyMatrix<3>; + + MeshDataBaseForTests::destroy(); + GlobalVariableManager::instance().setMeshId(0); + GlobalVariableManager::instance().setConnectivityId(0); + + ResumingManager::destroy(); + ResumingManager::create(); + + 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"; + + ResumingManager::getInstance().setFilename(filename); + } + + const std::string filename = ResumingManager::getInstance().filename(); + + std::string data = R"( +import math; +import mesh; +import scheme; + +let f:R*R^3 -> R^3, (a, v) -> a * v; + +let alpha:R, alpha = 3.2; +let u1:R^1, u1 = [0.3]; +let u2:R^2, u2 = [0.3, 1.2]; +let u3:R^3, u3 = [1, 2, 3]; + +let A1:R^1x1, A1 = [[0.7]]; +let A2:R^2x2, A2 = [[1.4, 2.1], [0.6, 3]]; +let A3:R^3x3, A3 = [[1.1, 2.2, 3.3], [0.1, 0.2, 0.3], [1.6, 1.2, 1.4]]; + +let m2d:mesh, m2d = cartesianMesh(0, [1,1], (10,10)); + +let b_tuple:(B), b_tuple = (true, false, true); +let n_tuple:(N), n_tuple = (1, 2, 3, 4); +let z_tuple:(Z), z_tuple = (1, -2, 3, -4); +let r_tuple:(R), r_tuple = (1.2, -2.4, 3.1, -4.3); +let s_tuple:(string), s_tuple = ("foo", "bar"); + +let r1_tuple:(R^1), r1_tuple = ([1], [2]); +let r2_tuple:(R^2), r2_tuple = ([1.2, 3], [2.3, 4], [3.2, 1.4]); +let r3_tuple:(R^3), r3_tuple = ([1.2, 0.2, 3], [2.3, -1, 4], [3.2, 2.1, 1.4]); + +let r11_tuple:(R^1x1), r11_tuple = ([[1.3]], [[2.4]]); +let r22_tuple:(R^2x2), r22_tuple = ([[1.2, 3], [2.3, 4]], [[3.2, 1.4], [1.3, 5.2]]); +let r33_tuple:(R^3x3), r33_tuple = ([[1.2, 0.2, 3], [2.3, -1, 4], [3.2, 2.1, 1.4]]); + +let duals_2d:(mesh), duals_2d = (diamondDual(m2d), medianDual(m2d)); + +let m1d:mesh, m1d = cartesianMesh([0], [1], 10); +let dual_1d:mesh, dual_1d = diamondDual(m1d); + +let m3d:mesh, m3d = cartesianMesh(0, [1,1,1], (6,6,6)); +let dual_3d:mesh, dual_3d = diamondDual(m3d); + +let b:B, b = false; +let z:Z, z = -2; +let s:string, s = "foobar"; + +for(let i:N, i=0; i<3; ++i) { + checkpoint(); + + s = "foobar_"+i; + z += 1; + b = not b; + + let g:R -> R^3, x -> [x, 1.2*x, 3]; + u3 = f(alpha,u3); + + checkpoint(); +} +)"; + + const size_t initial_mesh_id = GlobalVariableManager::instance().getMeshId(); + const size_t initial_connectivity_id = GlobalVariableManager::instance().getConnectivityId(); + + RUN_AST(data); + + GlobalVariableManager::instance().setMeshId(initial_mesh_id); + GlobalVariableManager::instance().setConnectivityId(initial_connectivity_id); + + { // Check checkpoint file + + HighFive::File file(ResumingManager::getInstance().filename(), HighFive::File::ReadOnly); + + HighFive::Group checkpoint = file.getGroup("/resuming_checkpoint"); + + REQUIRE(checkpoint.getAttribute("id").read<uint64_t>() == 1); + REQUIRE(checkpoint.getAttribute("checkpoint_number").read<uint64_t>() == 5); + REQUIRE(checkpoint.getAttribute("name").read<std::string>() == "checkpoint_5"); + + HighFive::Group symbol_table0 = checkpoint.getGroup("symbol table"); + REQUIRE(symbol_table0.getAttribute("i").read<uint64_t>() == 2); + + HighFive::Group symbol_table1 = symbol_table0.getGroup("symbol table"); + REQUIRE(symbol_table1.getAttribute("alpha").read<double>() == 3.2); + REQUIRE(l2Norm(symbol_table1.getAttribute("u1").read<R1>() - R1{0.3}) == Catch::Approx(0).margin(1E-12)); + REQUIRE(l2Norm(symbol_table1.getAttribute("u2").read<R2>() - R2{0.3, 1.2}) == Catch::Approx(0).margin(1E-12)); + REQUIRE(l2Norm(symbol_table1.getAttribute("u3").read<R3>() - R3{32.768, 65.536, 98.304}) == + Catch::Approx(0).margin(1E-12)); + REQUIRE(symbol_table1.getAttribute("b").read<bool>() == true); + REQUIRE(symbol_table1.getAttribute("z").read<int64_t>() == 1); + REQUIRE(symbol_table1.getAttribute("s").read<std::string>() == "foobar_2"); + REQUIRE(symbol_table1.getAttribute("A1").read<R11>()(0, 0) == Catch::Approx(0.7).margin(1E-12)); + REQUIRE(frobeniusNorm(symbol_table1.getAttribute("A2").read<R22>() - R22{1.4, 2.1, 0.6, 3}) == + Catch::Approx(0).margin(1E-12)); + REQUIRE(frobeniusNorm(symbol_table1.getAttribute("A3").read<R33>() - + R33{1.1, 2.2, 3.3, 0.1, 0.2, 0.3, 1.6, 1.2, 1.4}) == Catch::Approx(0).margin(1E-12)); + REQUIRE(symbol_table1.getAttribute("b_tuple").read<std::vector<bool>>() == std::vector<bool>{true, false, true}); + REQUIRE(symbol_table1.getAttribute("n_tuple").read<std::vector<uint64_t>>() == std::vector<uint64_t>{1, 2, 3, 4}); + REQUIRE(symbol_table1.getAttribute("z_tuple").read<std::vector<int64_t>>() == std::vector<int64_t>{1, -2, 3, -4}); + REQUIRE(symbol_table1.getAttribute("r_tuple").read<std::vector<double>>() == + std::vector<double>{1.2, -2.4, 3.1, -4.3}); + REQUIRE(symbol_table1.getAttribute("s_tuple").read<std::vector<std::string>>() == + std::vector<std::string>{"foo", "bar"}); + + REQUIRE(symbol_table1.getAttribute("r1_tuple").read<std::vector<R1>>() == std::vector{R1{1}, R1{2}}); + REQUIRE(symbol_table1.getAttribute("r2_tuple").read<std::vector<R2>>() == + std::vector{R2{1.2, 3}, R2{2.3, 4}, R2{3.2, 1.4}}); + REQUIRE(symbol_table1.getAttribute("r3_tuple").read<std::vector<R3>>() == + std::vector{R3{1.2, 0.2, 3}, R3{2.3, -1, 4}, R3{3.2, 2.1, 1.4}}); + + REQUIRE(symbol_table1.getAttribute("r11_tuple").read<std::vector<R11>>() == std::vector{R11{1.3}, R11{2.4}}); + REQUIRE(symbol_table1.getAttribute("r22_tuple").read<std::vector<R22>>() == + std::vector{R22{1.2, 3, 2.3, 4}, R22{3.2, 1.4, 1.3, 5.2}}); + REQUIRE(symbol_table1.getAttribute("r33_tuple").read<std::vector<R33>>() == + std::vector{R33{1.2, 0.2, 3, 2.3, -1, 4, 3.2, 2.1, 1.4}}); + + HighFive::Group embedded1 = symbol_table1.getGroup("embedded"); + + HighFive::Group m1d = embedded1.getGroup("m1d"); + REQUIRE(m1d.getAttribute("type").read<std::string>() == "mesh"); + REQUIRE(m1d.getAttribute("id").read<uint64_t>() == initial_mesh_id + 3); + + HighFive::Group dual_1d = embedded1.getGroup("dual_1d"); + REQUIRE(dual_1d.getAttribute("type").read<std::string>() == "mesh"); + REQUIRE(dual_1d.getAttribute("id").read<uint64_t>() == initial_mesh_id + 4); + + HighFive::Group m2d = embedded1.getGroup("m2d"); + REQUIRE(m2d.getAttribute("type").read<std::string>() == "mesh"); + REQUIRE(m2d.getAttribute("id").read<uint64_t>() == initial_mesh_id); + + HighFive::Group duals_2d = embedded1.getGroup("duals_2d"); + REQUIRE(duals_2d.getAttribute("type").read<std::string>() == "(mesh)"); + HighFive::Group duals_2d_0 = duals_2d.getGroup("0"); + REQUIRE(duals_2d_0.getAttribute("type").read<std::string>() == "mesh"); + REQUIRE(duals_2d_0.getAttribute("id").read<uint64_t>() == initial_mesh_id + 1); + HighFive::Group duals_2d_1 = duals_2d.getGroup("1"); + REQUIRE(duals_2d_1.getAttribute("type").read<std::string>() == "mesh"); + REQUIRE(duals_2d_1.getAttribute("id").read<uint64_t>() == initial_mesh_id + 2); + + HighFive::Group m3d = embedded1.getGroup("m3d"); + REQUIRE(m3d.getAttribute("type").read<std::string>() == "mesh"); + REQUIRE(m3d.getAttribute("id").read<uint64_t>() == initial_mesh_id + 5); + + HighFive::Group dual_3d = embedded1.getGroup("dual_3d"); + REQUIRE(dual_3d.getAttribute("type").read<std::string>() == "mesh"); + REQUIRE(dual_3d.getAttribute("id").read<uint64_t>() == initial_mesh_id + 6); + + HighFive::Group singleton = checkpoint.getGroup("singleton"); + HighFive::Group global_variables = singleton.getGroup("global_variables"); + REQUIRE(global_variables.getAttribute("connectivity_id").read<uint64_t>() == initial_connectivity_id + 7); + REQUIRE(global_variables.getAttribute("mesh_id").read<uint64_t>() == initial_mesh_id + 7); + HighFive::Group execution_info = singleton.getGroup("execution_info"); + REQUIRE(execution_info.getAttribute("run_number").read<uint64_t>() == 1); + + HighFive::Group connectivity = checkpoint.getGroup("connectivity"); + HighFive::Group connectivity0 = connectivity.getGroup(std::to_string(initial_connectivity_id)); + REQUIRE(connectivity0.getAttribute("dimension").read<uint64_t>() == 2); + REQUIRE(connectivity0.getAttribute("id").read<uint64_t>() == initial_connectivity_id); + REQUIRE(connectivity0.getAttribute("type").read<std::string>() == "unstructured"); + + HighFive::Group connectivity1 = connectivity.getGroup(std::to_string(initial_connectivity_id + 1)); + REQUIRE(connectivity1.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 1); + REQUIRE(connectivity1.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id); + REQUIRE(connectivity1.getAttribute("type").read<std::string>() == "dual_connectivity"); + REQUIRE(connectivity1.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond); + + HighFive::Group connectivity2 = connectivity.getGroup(std::to_string(initial_connectivity_id + 2)); + REQUIRE(connectivity2.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 2); + REQUIRE(connectivity2.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id); + REQUIRE(connectivity2.getAttribute("type").read<std::string>() == "dual_connectivity"); + REQUIRE(connectivity2.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Median); + + HighFive::Group connectivity3 = connectivity.getGroup(std::to_string(initial_connectivity_id + 3)); + REQUIRE(connectivity3.getAttribute("dimension").read<uint64_t>() == 1); + REQUIRE(connectivity3.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 3); + REQUIRE(connectivity3.getAttribute("type").read<std::string>() == "unstructured"); + + HighFive::Group connectivity4 = connectivity.getGroup(std::to_string(initial_connectivity_id + 4)); + REQUIRE(connectivity4.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 4); + REQUIRE(connectivity4.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id + 3); + REQUIRE(connectivity4.getAttribute("type").read<std::string>() == "dual_connectivity"); + REQUIRE(connectivity4.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Dual1D); + + HighFive::Group connectivity5 = connectivity.getGroup(std::to_string(initial_connectivity_id + 5)); + REQUIRE(connectivity5.getAttribute("dimension").read<uint64_t>() == 3); + REQUIRE(connectivity5.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 5); + REQUIRE(connectivity5.getAttribute("type").read<std::string>() == "unstructured"); + + HighFive::Group connectivity6 = connectivity.getGroup(std::to_string(initial_connectivity_id + 6)); + REQUIRE(connectivity6.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 6); + REQUIRE(connectivity6.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id + 5); + REQUIRE(connectivity6.getAttribute("type").read<std::string>() == "dual_connectivity"); + REQUIRE(connectivity6.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond); + + HighFive::Group mesh = checkpoint.getGroup("mesh"); + HighFive::Group mesh0 = mesh.getGroup(std::to_string(initial_mesh_id)); + REQUIRE(mesh0.getAttribute("connectivity").read<uint64_t>() == initial_connectivity_id); + REQUIRE(mesh0.getAttribute("dimension").read<uint64_t>() == 2); + REQUIRE(mesh0.getAttribute("id").read<uint64_t>() == initial_mesh_id); + REQUIRE(mesh0.getAttribute("type").read<std::string>() == "polygonal"); + + HighFive::Group mesh1 = mesh.getGroup(std::to_string(initial_mesh_id + 1)); + REQUIRE(mesh1.getAttribute("id").read<uint64_t>() == initial_mesh_id + 1); + REQUIRE(mesh1.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id); + REQUIRE(mesh1.getAttribute("type").read<std::string>() == "dual_mesh"); + REQUIRE(mesh1.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond); + + HighFive::Group mesh2 = mesh.getGroup(std::to_string(initial_mesh_id + 2)); + REQUIRE(mesh2.getAttribute("id").read<uint64_t>() == initial_mesh_id + 2); + REQUIRE(mesh2.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id); + REQUIRE(mesh2.getAttribute("type").read<std::string>() == "dual_mesh"); + REQUIRE(mesh2.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Median); + + HighFive::Group mesh3 = mesh.getGroup(std::to_string(initial_mesh_id + 3)); + REQUIRE(mesh3.getAttribute("connectivity").read<uint64_t>() == initial_connectivity_id + 3); + REQUIRE(mesh3.getAttribute("dimension").read<uint64_t>() == 1); + REQUIRE(mesh3.getAttribute("id").read<uint64_t>() == initial_mesh_id + 3); + REQUIRE(mesh3.getAttribute("type").read<std::string>() == "polygonal"); + + HighFive::Group mesh4 = mesh.getGroup(std::to_string(initial_mesh_id + 4)); + REQUIRE(mesh4.getAttribute("id").read<uint64_t>() == initial_mesh_id + 4); + REQUIRE(mesh4.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id + 3); + REQUIRE(mesh4.getAttribute("type").read<std::string>() == "dual_mesh"); + REQUIRE(mesh4.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Dual1D); + + HighFive::Group mesh5 = mesh.getGroup(std::to_string(initial_mesh_id + 5)); + REQUIRE(mesh5.getAttribute("connectivity").read<uint64_t>() == initial_connectivity_id + 5); + REQUIRE(mesh5.getAttribute("dimension").read<uint64_t>() == 3); + REQUIRE(mesh5.getAttribute("id").read<uint64_t>() == initial_mesh_id + 5); + REQUIRE(mesh5.getAttribute("type").read<std::string>() == "polygonal"); + + HighFive::Group mesh6 = mesh.getGroup(std::to_string(initial_mesh_id + 6)); + REQUIRE(mesh6.getAttribute("id").read<uint64_t>() == initial_mesh_id + 6); + REQUIRE(mesh6.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id + 5); + REQUIRE(mesh6.getAttribute("type").read<std::string>() == "dual_mesh"); + REQUIRE(mesh6.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond); + + HighFive::Group functions = checkpoint.getGroup("functions"); + HighFive::Group f = functions.getGroup("f"); + REQUIRE(f.getAttribute("id").read<uint64_t>() == 0); + REQUIRE(f.getAttribute("symbol_table_id").read<uint64_t>() == 1); + HighFive::Group g = functions.getGroup("g"); + REQUIRE(g.getAttribute("id").read<uint64_t>() == 1); + REQUIRE(g.getAttribute("symbol_table_id").read<uint64_t>() == 0); + } + + parallel::barrier(); + + setResumeFrom(filename, 3); + + parallel::barrier(); + + { // Check checkpoint file + + HighFive::File file(ResumingManager::getInstance().filename(), HighFive::File::ReadOnly); + + HighFive::Group checkpoint = file.getGroup("/resuming_checkpoint"); + + REQUIRE(checkpoint.getAttribute("id").read<uint64_t>() == 1); + REQUIRE(checkpoint.getAttribute("checkpoint_number").read<uint64_t>() == 3); + REQUIRE(checkpoint.getAttribute("name").read<std::string>() == "checkpoint_3"); + + HighFive::Group symbol_table0 = checkpoint.getGroup("symbol table"); + REQUIRE(symbol_table0.getAttribute("i").read<uint64_t>() == 1); + + HighFive::Group symbol_table1 = symbol_table0.getGroup("symbol table"); + REQUIRE(symbol_table1.getAttribute("alpha").read<double>() == 3.2); + REQUIRE(l2Norm(symbol_table1.getAttribute("u1").read<R1>() - R1{0.3}) == Catch::Approx(0).margin(1E-12)); + REQUIRE(l2Norm(symbol_table1.getAttribute("u2").read<R2>() - R2{0.3, 1.2}) == Catch::Approx(0).margin(1E-12)); + REQUIRE(l2Norm(symbol_table1.getAttribute("u3").read<R3>() - R3{10.24, 20.48, 30.72}) == + Catch::Approx(0).margin(1E-12)); + REQUIRE(symbol_table1.getAttribute("b").read<bool>() == false); + REQUIRE(symbol_table1.getAttribute("z").read<int64_t>() == 0); + REQUIRE(symbol_table1.getAttribute("s").read<std::string>() == "foobar_1"); + REQUIRE(symbol_table1.getAttribute("A1").read<R11>()(0, 0) == Catch::Approx(0.7).margin(1E-12)); + REQUIRE(frobeniusNorm(symbol_table1.getAttribute("A2").read<R22>() - R22{1.4, 2.1, 0.6, 3}) == + Catch::Approx(0).margin(1E-12)); + REQUIRE(frobeniusNorm(symbol_table1.getAttribute("A3").read<R33>() - + R33{1.1, 2.2, 3.3, 0.1, 0.2, 0.3, 1.6, 1.2, 1.4}) == Catch::Approx(0).margin(1E-12)); + + REQUIRE(symbol_table1.getAttribute("b_tuple").read<std::vector<bool>>() == std::vector<bool>{true, false, true}); + REQUIRE(symbol_table1.getAttribute("n_tuple").read<std::vector<uint64_t>>() == std::vector<uint64_t>{1, 2, 3, 4}); + REQUIRE(symbol_table1.getAttribute("z_tuple").read<std::vector<int64_t>>() == std::vector<int64_t>{1, -2, 3, -4}); + REQUIRE(symbol_table1.getAttribute("r_tuple").read<std::vector<double>>() == + std::vector<double>{1.2, -2.4, 3.1, -4.3}); + REQUIRE(symbol_table1.getAttribute("s_tuple").read<std::vector<std::string>>() == + std::vector<std::string>{"foo", "bar"}); + + REQUIRE(symbol_table1.getAttribute("r1_tuple").read<std::vector<R1>>() == std::vector{R1{1}, R1{2}}); + REQUIRE(symbol_table1.getAttribute("r2_tuple").read<std::vector<R2>>() == + std::vector{R2{1.2, 3}, R2{2.3, 4}, R2{3.2, 1.4}}); + REQUIRE(symbol_table1.getAttribute("r3_tuple").read<std::vector<R3>>() == + std::vector{R3{1.2, 0.2, 3}, R3{2.3, -1, 4}, R3{3.2, 2.1, 1.4}}); + + REQUIRE(symbol_table1.getAttribute("r11_tuple").read<std::vector<R11>>() == std::vector{R11{1.3}, R11{2.4}}); + REQUIRE(symbol_table1.getAttribute("r22_tuple").read<std::vector<R22>>() == + std::vector{R22{1.2, 3, 2.3, 4}, R22{3.2, 1.4, 1.3, 5.2}}); + REQUIRE(symbol_table1.getAttribute("r33_tuple").read<std::vector<R33>>() == + std::vector{R33{1.2, 0.2, 3, 2.3, -1, 4, 3.2, 2.1, 1.4}}); + + HighFive::Group embedded1 = symbol_table1.getGroup("embedded"); + + HighFive::Group m2d = embedded1.getGroup("m2d"); + REQUIRE(m2d.getAttribute("type").read<std::string>() == "mesh"); + REQUIRE(m2d.getAttribute("id").read<uint64_t>() == initial_mesh_id); + + HighFive::Group duals_2d = embedded1.getGroup("duals_2d"); + REQUIRE(duals_2d.getAttribute("type").read<std::string>() == "(mesh)"); + HighFive::Group duals_2d_0 = duals_2d.getGroup("0"); + REQUIRE(duals_2d_0.getAttribute("type").read<std::string>() == "mesh"); + REQUIRE(duals_2d_0.getAttribute("id").read<uint64_t>() == initial_mesh_id + 1); + HighFive::Group duals_2d_1 = duals_2d.getGroup("1"); + REQUIRE(duals_2d_1.getAttribute("type").read<std::string>() == "mesh"); + REQUIRE(duals_2d_1.getAttribute("id").read<uint64_t>() == initial_mesh_id + 2); + + HighFive::Group m3d = embedded1.getGroup("m3d"); + REQUIRE(m3d.getAttribute("type").read<std::string>() == "mesh"); + REQUIRE(m3d.getAttribute("id").read<uint64_t>() == initial_mesh_id + 5); + + HighFive::Group dual_3d = embedded1.getGroup("dual_3d"); + REQUIRE(dual_3d.getAttribute("type").read<std::string>() == "mesh"); + REQUIRE(dual_3d.getAttribute("id").read<uint64_t>() == initial_mesh_id + 6); + + HighFive::Group singleton = checkpoint.getGroup("singleton"); + HighFive::Group global_variables = singleton.getGroup("global_variables"); + REQUIRE(global_variables.getAttribute("connectivity_id").read<uint64_t>() == initial_connectivity_id + 7); + REQUIRE(global_variables.getAttribute("mesh_id").read<uint64_t>() == initial_mesh_id + 7); + HighFive::Group execution_info = singleton.getGroup("execution_info"); + REQUIRE(execution_info.getAttribute("run_number").read<uint64_t>() == 1); + + HighFive::Group connectivity = checkpoint.getGroup("connectivity"); + HighFive::Group connectivity0 = connectivity.getGroup(std::to_string(initial_connectivity_id)); + REQUIRE(connectivity0.getAttribute("dimension").read<uint64_t>() == 2); + REQUIRE(connectivity0.getAttribute("id").read<uint64_t>() == initial_connectivity_id); + REQUIRE(connectivity0.getAttribute("type").read<std::string>() == "unstructured"); + + HighFive::Group connectivity1 = connectivity.getGroup(std::to_string(initial_connectivity_id + 1)); + REQUIRE(connectivity1.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 1); + REQUIRE(connectivity1.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id); + REQUIRE(connectivity1.getAttribute("type").read<std::string>() == "dual_connectivity"); + REQUIRE(connectivity1.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond); + + HighFive::Group connectivity2 = connectivity.getGroup(std::to_string(initial_connectivity_id + 2)); + REQUIRE(connectivity2.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 2); + REQUIRE(connectivity2.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id); + REQUIRE(connectivity2.getAttribute("type").read<std::string>() == "dual_connectivity"); + REQUIRE(connectivity2.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Median); + + HighFive::Group connectivity3 = connectivity.getGroup(std::to_string(initial_connectivity_id + 3)); + REQUIRE(connectivity3.getAttribute("dimension").read<uint64_t>() == 1); + REQUIRE(connectivity3.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 3); + REQUIRE(connectivity3.getAttribute("type").read<std::string>() == "unstructured"); + + HighFive::Group connectivity4 = connectivity.getGroup(std::to_string(initial_connectivity_id + 4)); + REQUIRE(connectivity4.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 4); + REQUIRE(connectivity4.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id + 3); + REQUIRE(connectivity4.getAttribute("type").read<std::string>() == "dual_connectivity"); + REQUIRE(connectivity4.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Dual1D); + + HighFive::Group connectivity5 = connectivity.getGroup(std::to_string(initial_connectivity_id + 5)); + REQUIRE(connectivity5.getAttribute("dimension").read<uint64_t>() == 3); + REQUIRE(connectivity5.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 5); + REQUIRE(connectivity5.getAttribute("type").read<std::string>() == "unstructured"); + + HighFive::Group connectivity6 = connectivity.getGroup(std::to_string(initial_connectivity_id + 6)); + REQUIRE(connectivity6.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 6); + REQUIRE(connectivity6.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id + 5); + REQUIRE(connectivity6.getAttribute("type").read<std::string>() == "dual_connectivity"); + REQUIRE(connectivity6.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond); + + HighFive::Group mesh = checkpoint.getGroup("mesh"); + HighFive::Group mesh0 = mesh.getGroup(std::to_string(initial_mesh_id)); + REQUIRE(mesh0.getAttribute("connectivity").read<uint64_t>() == initial_connectivity_id); + REQUIRE(mesh0.getAttribute("dimension").read<uint64_t>() == 2); + REQUIRE(mesh0.getAttribute("id").read<uint64_t>() == initial_mesh_id); + REQUIRE(mesh0.getAttribute("type").read<std::string>() == "polygonal"); + + HighFive::Group mesh1 = mesh.getGroup(std::to_string(initial_mesh_id + 1)); + REQUIRE(mesh1.getAttribute("id").read<uint64_t>() == initial_mesh_id + 1); + REQUIRE(mesh1.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id); + REQUIRE(mesh1.getAttribute("type").read<std::string>() == "dual_mesh"); + REQUIRE(mesh1.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond); + + HighFive::Group mesh2 = mesh.getGroup(std::to_string(initial_mesh_id + 2)); + REQUIRE(mesh2.getAttribute("id").read<uint64_t>() == initial_mesh_id + 2); + REQUIRE(mesh2.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id); + REQUIRE(mesh2.getAttribute("type").read<std::string>() == "dual_mesh"); + REQUIRE(mesh2.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Median); + + HighFive::Group mesh3 = mesh.getGroup(std::to_string(initial_mesh_id + 3)); + REQUIRE(mesh3.getAttribute("connectivity").read<uint64_t>() == initial_connectivity_id + 3); + REQUIRE(mesh3.getAttribute("dimension").read<uint64_t>() == 1); + REQUIRE(mesh3.getAttribute("id").read<uint64_t>() == initial_mesh_id + 3); + REQUIRE(mesh3.getAttribute("type").read<std::string>() == "polygonal"); + + HighFive::Group mesh4 = mesh.getGroup(std::to_string(initial_mesh_id + 4)); + REQUIRE(mesh4.getAttribute("id").read<uint64_t>() == initial_mesh_id + 4); + REQUIRE(mesh4.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id + 3); + REQUIRE(mesh4.getAttribute("type").read<std::string>() == "dual_mesh"); + REQUIRE(mesh4.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Dual1D); + + HighFive::Group mesh5 = mesh.getGroup(std::to_string(initial_mesh_id + 5)); + REQUIRE(mesh5.getAttribute("connectivity").read<uint64_t>() == initial_connectivity_id + 5); + REQUIRE(mesh5.getAttribute("dimension").read<uint64_t>() == 3); + REQUIRE(mesh5.getAttribute("id").read<uint64_t>() == initial_mesh_id + 5); + REQUIRE(mesh5.getAttribute("type").read<std::string>() == "polygonal"); + + HighFive::Group mesh6 = mesh.getGroup(std::to_string(initial_mesh_id + 6)); + REQUIRE(mesh6.getAttribute("id").read<uint64_t>() == initial_mesh_id + 6); + REQUIRE(mesh6.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id + 5); + REQUIRE(mesh6.getAttribute("type").read<std::string>() == "dual_mesh"); + REQUIRE(mesh6.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond); + + HighFive::Group functions = checkpoint.getGroup("functions"); + HighFive::Group f = functions.getGroup("f"); + REQUIRE(f.getAttribute("id").read<uint64_t>() == 0); + REQUIRE(f.getAttribute("symbol_table_id").read<uint64_t>() == 1); + HighFive::Group g = functions.getGroup("g"); + REQUIRE(g.getAttribute("id").read<uint64_t>() == 1); + REQUIRE(g.getAttribute("symbol_table_id").read<uint64_t>() == 0); + } + + ResumingManager::destroy(); + ResumingManager::create(); + ResumingManager::getInstance().setFilename(filename); + ResumingManager::getInstance().setIsResuming(true); + GlobalVariableManager::instance().setMeshId(initial_mesh_id); + GlobalVariableManager::instance().setConnectivityId(initial_connectivity_id); + + RUN_AST(data); + + { // Check checkpoint file + + HighFive::File file(ResumingManager::getInstance().filename(), HighFive::File::ReadOnly); + + HighFive::Group checkpoint = file.getGroup("/resuming_checkpoint"); + + REQUIRE(checkpoint.getAttribute("id").read<uint64_t>() == 1); + REQUIRE(checkpoint.getAttribute("checkpoint_number").read<uint64_t>() == 5); + REQUIRE(checkpoint.getAttribute("name").read<std::string>() == "checkpoint_5"); + + HighFive::Group symbol_table0 = checkpoint.getGroup("symbol table"); + REQUIRE(symbol_table0.getAttribute("i").read<uint64_t>() == 2); + + HighFive::Group symbol_table1 = symbol_table0.getGroup("symbol table"); + REQUIRE(symbol_table1.getAttribute("alpha").read<double>() == 3.2); + REQUIRE(l2Norm(symbol_table1.getAttribute("u1").read<R1>() - R1{0.3}) == Catch::Approx(0).margin(1E-12)); + REQUIRE(l2Norm(symbol_table1.getAttribute("u2").read<R2>() - R2{0.3, 1.2}) == Catch::Approx(0).margin(1E-12)); + REQUIRE(l2Norm(symbol_table1.getAttribute("u3").read<R3>() - R3{32.768, 65.536, 98.304}) == + Catch::Approx(0).margin(1E-12)); + REQUIRE(symbol_table1.getAttribute("b").read<bool>() == true); + REQUIRE(symbol_table1.getAttribute("z").read<int64_t>() == 1); + REQUIRE(symbol_table1.getAttribute("s").read<std::string>() == "foobar_2"); + REQUIRE(symbol_table1.getAttribute("A1").read<R11>()(0, 0) == Catch::Approx(0.7).margin(1E-12)); + REQUIRE(frobeniusNorm(symbol_table1.getAttribute("A2").read<R22>() - R22{1.4, 2.1, 0.6, 3}) == + Catch::Approx(0).margin(1E-12)); + REQUIRE(frobeniusNorm(symbol_table1.getAttribute("A3").read<R33>() - + R33{1.1, 2.2, 3.3, 0.1, 0.2, 0.3, 1.6, 1.2, 1.4}) == Catch::Approx(0).margin(1E-12)); + + REQUIRE(symbol_table1.getAttribute("b_tuple").read<std::vector<bool>>() == std::vector<bool>{true, false, true}); + REQUIRE(symbol_table1.getAttribute("n_tuple").read<std::vector<uint64_t>>() == std::vector<uint64_t>{1, 2, 3, 4}); + REQUIRE(symbol_table1.getAttribute("z_tuple").read<std::vector<int64_t>>() == std::vector<int64_t>{1, -2, 3, -4}); + REQUIRE(symbol_table1.getAttribute("r_tuple").read<std::vector<double>>() == + std::vector<double>{1.2, -2.4, 3.1, -4.3}); + REQUIRE(symbol_table1.getAttribute("s_tuple").read<std::vector<std::string>>() == + std::vector<std::string>{"foo", "bar"}); + + REQUIRE(symbol_table1.getAttribute("r1_tuple").read<std::vector<R1>>() == std::vector{R1{1}, R1{2}}); + REQUIRE(symbol_table1.getAttribute("r2_tuple").read<std::vector<R2>>() == + std::vector{R2{1.2, 3}, R2{2.3, 4}, R2{3.2, 1.4}}); + REQUIRE(symbol_table1.getAttribute("r3_tuple").read<std::vector<R3>>() == + std::vector{R3{1.2, 0.2, 3}, R3{2.3, -1, 4}, R3{3.2, 2.1, 1.4}}); + + REQUIRE(symbol_table1.getAttribute("r11_tuple").read<std::vector<R11>>() == std::vector{R11{1.3}, R11{2.4}}); + REQUIRE(symbol_table1.getAttribute("r22_tuple").read<std::vector<R22>>() == + std::vector{R22{1.2, 3, 2.3, 4}, R22{3.2, 1.4, 1.3, 5.2}}); + REQUIRE(symbol_table1.getAttribute("r33_tuple").read<std::vector<R33>>() == + std::vector{R33{1.2, 0.2, 3, 2.3, -1, 4, 3.2, 2.1, 1.4}}); + + HighFive::Group embedded1 = symbol_table1.getGroup("embedded"); + + HighFive::Group m2d = embedded1.getGroup("m2d"); + REQUIRE(m2d.getAttribute("type").read<std::string>() == "mesh"); + REQUIRE(m2d.getAttribute("id").read<uint64_t>() == initial_mesh_id); + + HighFive::Group duals_2d = embedded1.getGroup("duals_2d"); + REQUIRE(duals_2d.getAttribute("type").read<std::string>() == "(mesh)"); + HighFive::Group duals_2d_0 = duals_2d.getGroup("0"); + REQUIRE(duals_2d_0.getAttribute("type").read<std::string>() == "mesh"); + REQUIRE(duals_2d_0.getAttribute("id").read<uint64_t>() == initial_mesh_id + 1); + HighFive::Group duals_2d_1 = duals_2d.getGroup("1"); + REQUIRE(duals_2d_1.getAttribute("type").read<std::string>() == "mesh"); + REQUIRE(duals_2d_1.getAttribute("id").read<uint64_t>() == initial_mesh_id + 2); + + HighFive::Group m3d = embedded1.getGroup("m3d"); + REQUIRE(m3d.getAttribute("type").read<std::string>() == "mesh"); + REQUIRE(m3d.getAttribute("id").read<uint64_t>() == initial_mesh_id + 5); + + HighFive::Group dual_3d = embedded1.getGroup("dual_3d"); + REQUIRE(dual_3d.getAttribute("type").read<std::string>() == "mesh"); + REQUIRE(dual_3d.getAttribute("id").read<uint64_t>() == initial_mesh_id + 6); + + HighFive::Group singleton = checkpoint.getGroup("singleton"); + HighFive::Group global_variables = singleton.getGroup("global_variables"); + REQUIRE(global_variables.getAttribute("connectivity_id").read<uint64_t>() == initial_connectivity_id + 7); + REQUIRE(global_variables.getAttribute("mesh_id").read<uint64_t>() == initial_mesh_id + 7); + HighFive::Group execution_info = singleton.getGroup("execution_info"); + REQUIRE(execution_info.getAttribute("run_number").read<uint64_t>() == 2); + + HighFive::Group connectivity = checkpoint.getGroup("connectivity"); + HighFive::Group connectivity0 = connectivity.getGroup(std::to_string(initial_connectivity_id)); + REQUIRE(connectivity0.getAttribute("dimension").read<uint64_t>() == 2); + REQUIRE(connectivity0.getAttribute("id").read<uint64_t>() == initial_connectivity_id); + REQUIRE(connectivity0.getAttribute("type").read<std::string>() == "unstructured"); + + HighFive::Group connectivity1 = connectivity.getGroup(std::to_string(initial_connectivity_id + 1)); + REQUIRE(connectivity1.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 1); + REQUIRE(connectivity1.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id); + REQUIRE(connectivity1.getAttribute("type").read<std::string>() == "dual_connectivity"); + REQUIRE(connectivity1.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond); + + HighFive::Group connectivity2 = connectivity.getGroup(std::to_string(initial_connectivity_id + 2)); + REQUIRE(connectivity2.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 2); + REQUIRE(connectivity2.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id); + REQUIRE(connectivity2.getAttribute("type").read<std::string>() == "dual_connectivity"); + REQUIRE(connectivity2.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Median); + + HighFive::Group connectivity3 = connectivity.getGroup(std::to_string(initial_connectivity_id + 3)); + REQUIRE(connectivity3.getAttribute("dimension").read<uint64_t>() == 1); + REQUIRE(connectivity3.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 3); + REQUIRE(connectivity3.getAttribute("type").read<std::string>() == "unstructured"); + + HighFive::Group connectivity4 = connectivity.getGroup(std::to_string(initial_connectivity_id + 4)); + REQUIRE(connectivity4.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 4); + REQUIRE(connectivity4.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id + 3); + REQUIRE(connectivity4.getAttribute("type").read<std::string>() == "dual_connectivity"); + REQUIRE(connectivity4.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Dual1D); + + HighFive::Group connectivity5 = connectivity.getGroup(std::to_string(initial_connectivity_id + 5)); + REQUIRE(connectivity5.getAttribute("dimension").read<uint64_t>() == 3); + REQUIRE(connectivity5.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 5); + REQUIRE(connectivity5.getAttribute("type").read<std::string>() == "unstructured"); + + HighFive::Group connectivity6 = connectivity.getGroup(std::to_string(initial_connectivity_id + 6)); + REQUIRE(connectivity6.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 6); + REQUIRE(connectivity6.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id + 5); + REQUIRE(connectivity6.getAttribute("type").read<std::string>() == "dual_connectivity"); + REQUIRE(connectivity6.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond); + + HighFive::Group mesh = checkpoint.getGroup("mesh"); + HighFive::Group mesh0 = mesh.getGroup(std::to_string(initial_mesh_id)); + REQUIRE(mesh0.getAttribute("connectivity").read<uint64_t>() == initial_connectivity_id); + REQUIRE(mesh0.getAttribute("dimension").read<uint64_t>() == 2); + REQUIRE(mesh0.getAttribute("id").read<uint64_t>() == initial_mesh_id); + REQUIRE(mesh0.getAttribute("type").read<std::string>() == "polygonal"); + + HighFive::Group mesh1 = mesh.getGroup(std::to_string(initial_mesh_id + 1)); + REQUIRE(mesh1.getAttribute("id").read<uint64_t>() == initial_mesh_id + 1); + REQUIRE(mesh1.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id); + REQUIRE(mesh1.getAttribute("type").read<std::string>() == "dual_mesh"); + REQUIRE(mesh1.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond); + + HighFive::Group mesh2 = mesh.getGroup(std::to_string(initial_mesh_id + 2)); + REQUIRE(mesh2.getAttribute("id").read<uint64_t>() == initial_mesh_id + 2); + REQUIRE(mesh2.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id); + REQUIRE(mesh2.getAttribute("type").read<std::string>() == "dual_mesh"); + REQUIRE(mesh2.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Median); + + HighFive::Group mesh3 = mesh.getGroup(std::to_string(initial_mesh_id + 3)); + REQUIRE(mesh3.getAttribute("connectivity").read<uint64_t>() == initial_connectivity_id + 3); + REQUIRE(mesh3.getAttribute("dimension").read<uint64_t>() == 1); + REQUIRE(mesh3.getAttribute("id").read<uint64_t>() == initial_mesh_id + 3); + REQUIRE(mesh3.getAttribute("type").read<std::string>() == "polygonal"); + + HighFive::Group mesh4 = mesh.getGroup(std::to_string(initial_mesh_id + 4)); + REQUIRE(mesh4.getAttribute("id").read<uint64_t>() == initial_mesh_id + 4); + REQUIRE(mesh4.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id + 3); + REQUIRE(mesh4.getAttribute("type").read<std::string>() == "dual_mesh"); + REQUIRE(mesh4.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Dual1D); + + HighFive::Group mesh5 = mesh.getGroup(std::to_string(initial_mesh_id + 5)); + REQUIRE(mesh5.getAttribute("connectivity").read<uint64_t>() == initial_connectivity_id + 5); + REQUIRE(mesh5.getAttribute("dimension").read<uint64_t>() == 3); + REQUIRE(mesh5.getAttribute("id").read<uint64_t>() == initial_mesh_id + 5); + REQUIRE(mesh5.getAttribute("type").read<std::string>() == "polygonal"); + + HighFive::Group mesh6 = mesh.getGroup(std::to_string(initial_mesh_id + 6)); + REQUIRE(mesh6.getAttribute("id").read<uint64_t>() == initial_mesh_id + 6); + REQUIRE(mesh6.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id + 5); + REQUIRE(mesh6.getAttribute("type").read<std::string>() == "dual_mesh"); + REQUIRE(mesh6.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond); + + HighFive::Group functions = checkpoint.getGroup("functions"); + HighFive::Group f = functions.getGroup("f"); + REQUIRE(f.getAttribute("id").read<uint64_t>() == 0); + REQUIRE(f.getAttribute("symbol_table_id").read<uint64_t>() == 1); + HighFive::Group g = functions.getGroup("g"); + REQUIRE(g.getAttribute("id").read<uint64_t>() == 1); + REQUIRE(g.getAttribute("symbol_table_id").read<uint64_t>() == 0); + } + + parallel::barrier(); + if (parallel::rank() == 0) { + std::filesystem::remove_all(std::filesystem::path{tmp_dirname}); + } + + // Revert to default value + ResumingManager::getInstance().setFilename("checkpoint.h5"); + MeshDataBaseForTests::create(); + +#else // PUGS_HAS_HDF5 + REQUIRE_THROWS_WITH(resume(), "error: checkpoint/resume mechanism requires HDF5"); +#endif // PUGS_HAS_HDF5 +}