diff --git a/src/utils/checkpointing/ReadIBoundaryConditionDescriptor.cpp b/src/utils/checkpointing/ReadIBoundaryConditionDescriptor.cpp index 1439b8b1ef04a2cdc73cda7a40c152b5e6fbcd37..671a9e7ece3198f766f5ceea45b27a4372e5dcc3 100644 --- a/src/utils/checkpointing/ReadIBoundaryConditionDescriptor.cpp +++ b/src/utils/checkpointing/ReadIBoundaryConditionDescriptor.cpp @@ -47,11 +47,13 @@ readIBoundaryConditionDescriptor(const HighFive::Group& iboundaryconditiondecrip *ResumingData::instance().functionSymbolId(rhs_id)); break; } + // LCOV_EXCL_START case IBoundaryConditionDescriptor::Type::external: { throw NotImplementedError("checkpoint/resume with sockets"); break; } + // LCOV_EXCL_STOP case IBoundaryConditionDescriptor::Type::fourier: { const std::string name = iboundaryconditiondecriptor_group.getAttribute("name").read<std::string>(); const size_t rhs_id = iboundaryconditiondecriptor_group.getAttribute("rhs_function_id").read<size_t>(); diff --git a/src/utils/checkpointing/WriteIBoundaryConditionDescriptor.cpp b/src/utils/checkpointing/WriteIBoundaryConditionDescriptor.cpp index ad99b31934b88bdff44e6f4780c1bd334fe875b0..ca26fdf359c51050b5edc0f82818a2522b8dfb1e 100644 --- a/src/utils/checkpointing/WriteIBoundaryConditionDescriptor.cpp +++ b/src/utils/checkpointing/WriteIBoundaryConditionDescriptor.cpp @@ -46,11 +46,13 @@ writeIBoundaryConditionDescriptor(HighFive::Group& variable_group, variable_group.createAttribute("rhs_function_id", dirichlet_bc_descriptor.rhsSymbolId().id()); break; } + // LCOV_EXCL_START case IBoundaryConditionDescriptor::Type::external: { throw NotImplementedError("checkpoint/resume with sockets"); break; } + // LCOV_EXCL_STOP case IBoundaryConditionDescriptor::Type::fourier: { const FourierBoundaryConditionDescriptor& fourier_bc_descriptor = dynamic_cast<const FourierBoundaryConditionDescriptor&>(iboundary_condition_descriptor); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 95b6b15d1d349505c052f573273e9cd608337cd5..a3048e7c854018c0476f2796ed981f2a0ba3d1b7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -162,6 +162,7 @@ if(PUGS_HAS_HDF5) list(APPEND checkpointing_TESTS test_checkpointing_HFTypes.cpp test_checkpointing_IBoundaryDescriptor.cpp + test_checkpointing_IBoundaryConditionDescriptor.cpp test_checkpointing_IInterfaceDescriptor.cpp test_checkpointing_IZoneDescriptor.cpp ) diff --git a/tests/test_checkpointing_IBoundaryConditionDescriptor.cpp b/tests/test_checkpointing_IBoundaryConditionDescriptor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..abbe5151f1aa4e132adbae667f3b90b4d7a010eb --- /dev/null +++ b/tests/test_checkpointing_IBoundaryConditionDescriptor.cpp @@ -0,0 +1,311 @@ +#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/NamedBoundaryDescriptor.hpp> +#include <mesh/NumberedBoundaryDescriptor.hpp> +#include <scheme/AxisBoundaryConditionDescriptor.hpp> +#include <scheme/DirichletBoundaryConditionDescriptor.hpp> +#include <scheme/ExternalBoundaryConditionDescriptor.hpp> +#include <scheme/FixedBoundaryConditionDescriptor.hpp> +#include <scheme/FourierBoundaryConditionDescriptor.hpp> +#include <scheme/FreeBoundaryConditionDescriptor.hpp> +#include <scheme/InflowBoundaryConditionDescriptor.hpp> +#include <scheme/NeumannBoundaryConditionDescriptor.hpp> +#include <scheme/OutflowBoundaryConditionDescriptor.hpp> +#include <scheme/SymmetryBoundaryConditionDescriptor.hpp> +#include <utils/checkpointing/ReadIBoundaryConditionDescriptor.hpp> +#include <utils/checkpointing/ResumingData.hpp> +#include <utils/checkpointing/WriteIBoundaryConditionDescriptor.hpp> + +#include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> +#include <language/ast/ASTNodeDataTypeBuilder.hpp> +#include <language/ast/ASTNodeExpressionBuilder.hpp> +#include <language/ast/ASTNodeFunctionEvaluationExpressionBuilder.hpp> +#include <language/ast/ASTNodeFunctionExpressionBuilder.hpp> +#include <language/ast/ASTNodeTypeCleaner.hpp> +#include <language/ast/ASTSymbolTableBuilder.hpp> +#include <language/utils/ASTNodeDataTypeTraits.hpp> +#include <language/utils/BasicAffectationRegistrerFor.hpp> +#include <language/utils/TypeDescriptor.hpp> +#include <utils/GlobalVariableManager.hpp> + +// #include <utils/Demangle.hpp> + +#include <pegtl/string_input.hpp> + +#include <filesystem> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("checkpointing_IBoundaryConditionDescriptor", "[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); + + SECTION("IBoundaryConditionDescriptor") + { + std::shared_ptr<SymbolTable> symbol_table; + + std::string data = + R"( +let f: R -> R, x -> 2*x; +let g: R -> R, x -> 2*x+1; +let h: R -> R, x -> -x; +let i: R -> R, x -> x+3; +)"; + + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + BasicAffectationRegisterFor<EmbeddedData>{ASTNodeDataType::build<ASTNodeDataType::type_id_t>("builtin_t")}; + + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + symbol_table = ast->m_symbol_table; + + HighFive::Group checkpoint_group = file.createGroup("checkpoint"); + + 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()); + + HighFive::Group function_group = checkpoint_group.createGroup("functions"); + + { + HighFive::Group f = function_group.createGroup("f"); + f.createAttribute("id", size_t{0}); + f.createAttribute("symbol_table_id", size_t{0}); + + HighFive::Group g = function_group.createGroup("g"); + g.createAttribute("id", size_t{1}); + g.createAttribute("symbol_table_id", size_t{0}); + + HighFive::Group h = function_group.createGroup("h"); + h.createAttribute("id", size_t{2}); + h.createAttribute("symbol_table_id", size_t{0}); + + HighFive::Group i = function_group.createGroup("i"); + i.createAttribute("id", size_t{3}); + i.createAttribute("symbol_table_id", size_t{0}); + } + + HighFive::Group symbol_table_group = checkpoint_group.createGroup("symbol_table"); + + auto p_boundary_1 = std::make_shared<NamedBoundaryDescriptor>("bd1"); + auto p_boundary_2 = std::make_shared<NumberedBoundaryDescriptor>(2); + + HighFive::Group useless_group; + + auto p_axis_bc_descriptor = std::make_shared<const AxisBoundaryConditionDescriptor>(p_boundary_1); + checkpointing::writeIBoundaryConditionDescriptor("axis_bc_descriptor", + EmbeddedData{std::make_shared< + DataHandler<const IBoundaryConditionDescriptor>>( + p_axis_bc_descriptor)}, + file, useless_group, symbol_table_group); + + auto p_sym_bc_descriptor = std::make_shared<const SymmetryBoundaryConditionDescriptor>(p_boundary_1); + checkpointing::writeIBoundaryConditionDescriptor("sym_bc_descriptor", + EmbeddedData{std::make_shared< + DataHandler<const IBoundaryConditionDescriptor>>( + p_sym_bc_descriptor)}, + file, useless_group, symbol_table_group); + + auto p_outflow_bc_descriptor = std::make_shared<const OutflowBoundaryConditionDescriptor>(p_boundary_2); + checkpointing::writeIBoundaryConditionDescriptor("outflow_bc_descriptor", + EmbeddedData{std::make_shared< + DataHandler<const IBoundaryConditionDescriptor>>( + p_outflow_bc_descriptor)}, + file, useless_group, symbol_table_group); + + auto p_free_bc_descriptor = std::make_shared<const FreeBoundaryConditionDescriptor>(p_boundary_2); + checkpointing::writeIBoundaryConditionDescriptor("free_bc_descriptor", + EmbeddedData{std::make_shared< + DataHandler<const IBoundaryConditionDescriptor>>( + p_free_bc_descriptor)}, + file, useless_group, symbol_table_group); + + auto p_fixed_bc_descriptor = std::make_shared<const FixedBoundaryConditionDescriptor>(p_boundary_2); + checkpointing::writeIBoundaryConditionDescriptor("fixed_bc_descriptor", + EmbeddedData{std::make_shared< + DataHandler<const IBoundaryConditionDescriptor>>( + p_fixed_bc_descriptor)}, + file, useless_group, symbol_table_group); + + const FunctionSymbolId dirichlet_function_id{3, symbol_table}; + auto p_dirichlet_bc_descriptor = + std::make_shared<const DirichletBoundaryConditionDescriptor>("dirichlet_name", p_boundary_1, + dirichlet_function_id); + checkpointing::writeIBoundaryConditionDescriptor("dirichlet_bc_descriptor", + EmbeddedData{std::make_shared< + DataHandler<const IBoundaryConditionDescriptor>>( + p_dirichlet_bc_descriptor)}, + file, useless_group, symbol_table_group); + + const FunctionSymbolId neumann_function_id{1, symbol_table}; + auto p_neumann_bc_descriptor = + std::make_shared<const NeumannBoundaryConditionDescriptor>("neumann_name", p_boundary_1, neumann_function_id); + checkpointing::writeIBoundaryConditionDescriptor("neumann_bc_descriptor", + EmbeddedData{std::make_shared< + DataHandler<const IBoundaryConditionDescriptor>>( + p_neumann_bc_descriptor)}, + file, useless_group, symbol_table_group); + + const FunctionSymbolId fourier_mass_function_id{0, symbol_table}; + const FunctionSymbolId fourier_rhs_function_id{2, symbol_table}; + auto p_fourier_bc_descriptor = + std::make_shared<const FourierBoundaryConditionDescriptor>("fourier_name", p_boundary_2, + fourier_mass_function_id, fourier_rhs_function_id); + checkpointing::writeIBoundaryConditionDescriptor("fourier_bc_descriptor", + EmbeddedData{std::make_shared< + DataHandler<const IBoundaryConditionDescriptor>>( + p_fourier_bc_descriptor)}, + file, useless_group, symbol_table_group); + + const FunctionSymbolId inflow_function_id{3, symbol_table}; + auto p_inflow_bc_descriptor = + std::make_shared<const InflowBoundaryConditionDescriptor>(p_boundary_2, inflow_function_id); + checkpointing::writeIBoundaryConditionDescriptor("inflow_bc_descriptor", + EmbeddedData{std::make_shared< + DataHandler<const IBoundaryConditionDescriptor>>( + p_inflow_bc_descriptor)}, + file, useless_group, symbol_table_group); + + file.flush(); + + checkpointing::ResumingData::create(); + + checkpointing::ResumingData::instance().readData(checkpoint_group, symbol_table); + + EmbeddedData read_axis_bc_descriptor = + checkpointing::readIBoundaryConditionDescriptor("axis_bc_descriptor", symbol_table_group); + + EmbeddedData read_sym_bc_descriptor = + checkpointing::readIBoundaryConditionDescriptor("sym_bc_descriptor", symbol_table_group); + + EmbeddedData read_outflow_bc_descriptor = + checkpointing::readIBoundaryConditionDescriptor("outflow_bc_descriptor", symbol_table_group); + + EmbeddedData read_free_bc_descriptor = + checkpointing::readIBoundaryConditionDescriptor("free_bc_descriptor", symbol_table_group); + + EmbeddedData read_fixed_bc_descriptor = + checkpointing::readIBoundaryConditionDescriptor("fixed_bc_descriptor", symbol_table_group); + + EmbeddedData read_dirichlet_bc_descriptor = + checkpointing::readIBoundaryConditionDescriptor("dirichlet_bc_descriptor", symbol_table_group); + + EmbeddedData read_neumann_bc_descriptor = + checkpointing::readIBoundaryConditionDescriptor("neumann_bc_descriptor", symbol_table_group); + + EmbeddedData read_fourier_bc_descriptor = + checkpointing::readIBoundaryConditionDescriptor("fourier_bc_descriptor", symbol_table_group); + + EmbeddedData read_inflow_bc_descriptor = + checkpointing::readIBoundaryConditionDescriptor("inflow_bc_descriptor", symbol_table_group); + + auto get_value = [](const EmbeddedData& embedded_data) -> const IBoundaryConditionDescriptor& { + return *dynamic_cast<const DataHandler<const IBoundaryConditionDescriptor>&>(embedded_data.get()).data_ptr(); + }; + + REQUIRE_NOTHROW(get_value(read_axis_bc_descriptor)); + REQUIRE_NOTHROW(get_value(read_sym_bc_descriptor)); + REQUIRE_NOTHROW(get_value(read_outflow_bc_descriptor)); + REQUIRE_NOTHROW(get_value(read_free_bc_descriptor)); + REQUIRE_NOTHROW(get_value(read_fixed_bc_descriptor)); + REQUIRE_NOTHROW(get_value(read_dirichlet_bc_descriptor)); + REQUIRE_NOTHROW(get_value(read_neumann_bc_descriptor)); + REQUIRE_NOTHROW(get_value(read_fourier_bc_descriptor)); + REQUIRE_NOTHROW(get_value(read_inflow_bc_descriptor)); + + REQUIRE(get_value(read_axis_bc_descriptor).type() == IBoundaryConditionDescriptor::Type::axis); + REQUIRE(get_value(read_sym_bc_descriptor).type() == IBoundaryConditionDescriptor::Type::symmetry); + REQUIRE(get_value(read_outflow_bc_descriptor).type() == IBoundaryConditionDescriptor::Type::outflow); + REQUIRE(get_value(read_free_bc_descriptor).type() == IBoundaryConditionDescriptor::Type::free); + REQUIRE(get_value(read_fixed_bc_descriptor).type() == IBoundaryConditionDescriptor::Type::fixed); + REQUIRE(get_value(read_dirichlet_bc_descriptor).type() == IBoundaryConditionDescriptor::Type::dirichlet); + REQUIRE(get_value(read_neumann_bc_descriptor).type() == IBoundaryConditionDescriptor::Type::neumann); + REQUIRE(get_value(read_fourier_bc_descriptor).type() == IBoundaryConditionDescriptor::Type::fourier); + REQUIRE(get_value(read_inflow_bc_descriptor).type() == IBoundaryConditionDescriptor::Type::inflow); + + REQUIRE_NOTHROW(dynamic_cast<const AxisBoundaryConditionDescriptor&>(get_value(read_axis_bc_descriptor))); + REQUIRE_NOTHROW(dynamic_cast<const SymmetryBoundaryConditionDescriptor&>(get_value(read_sym_bc_descriptor))); + REQUIRE_NOTHROW(dynamic_cast<const OutflowBoundaryConditionDescriptor&>(get_value(read_outflow_bc_descriptor))); + REQUIRE_NOTHROW(dynamic_cast<const FreeBoundaryConditionDescriptor&>(get_value(read_free_bc_descriptor))); + REQUIRE_NOTHROW(dynamic_cast<const FixedBoundaryConditionDescriptor&>(get_value(read_fixed_bc_descriptor))); + REQUIRE_NOTHROW( + dynamic_cast<const DirichletBoundaryConditionDescriptor&>(get_value(read_dirichlet_bc_descriptor))); + REQUIRE_NOTHROW(dynamic_cast<const NeumannBoundaryConditionDescriptor&>(get_value(read_neumann_bc_descriptor))); + REQUIRE_NOTHROW(dynamic_cast<const FourierBoundaryConditionDescriptor&>(get_value(read_fourier_bc_descriptor))); + REQUIRE_NOTHROW(dynamic_cast<const InflowBoundaryConditionDescriptor&>(get_value(read_inflow_bc_descriptor))); + + auto& read_axis_bc = dynamic_cast<const AxisBoundaryConditionDescriptor&>(get_value(read_axis_bc_descriptor)); + auto& read_sym_bc = dynamic_cast<const SymmetryBoundaryConditionDescriptor&>(get_value(read_sym_bc_descriptor)); + auto& read_outflow_bc = + dynamic_cast<const OutflowBoundaryConditionDescriptor&>(get_value(read_outflow_bc_descriptor)); + auto& read_free_bc = dynamic_cast<const FreeBoundaryConditionDescriptor&>(get_value(read_free_bc_descriptor)); + auto& read_fixed_bc = dynamic_cast<const FixedBoundaryConditionDescriptor&>(get_value(read_fixed_bc_descriptor)); + auto& read_dirichlet_bc = + dynamic_cast<const DirichletBoundaryConditionDescriptor&>(get_value(read_dirichlet_bc_descriptor)); + auto& read_neumann_bc = + dynamic_cast<const NeumannBoundaryConditionDescriptor&>(get_value(read_neumann_bc_descriptor)); + auto& read_fourier_bc = + dynamic_cast<const FourierBoundaryConditionDescriptor&>(get_value(read_fourier_bc_descriptor)); + auto& read_inflow_bc = + dynamic_cast<const InflowBoundaryConditionDescriptor&>(get_value(read_inflow_bc_descriptor)); + + REQUIRE(read_axis_bc.boundaryDescriptor().type() == p_axis_bc_descriptor->boundaryDescriptor().type()); + REQUIRE(read_sym_bc.boundaryDescriptor().type() == p_sym_bc_descriptor->boundaryDescriptor().type()); + REQUIRE(read_outflow_bc.boundaryDescriptor().type() == p_outflow_bc_descriptor->boundaryDescriptor().type()); + REQUIRE(read_free_bc.boundaryDescriptor().type() == p_free_bc_descriptor->boundaryDescriptor().type()); + REQUIRE(read_fixed_bc.boundaryDescriptor().type() == p_fixed_bc_descriptor->boundaryDescriptor().type()); + REQUIRE(read_dirichlet_bc.boundaryDescriptor().type() == p_dirichlet_bc_descriptor->boundaryDescriptor().type()); + REQUIRE(read_dirichlet_bc.name() == p_dirichlet_bc_descriptor->name()); + REQUIRE(read_dirichlet_bc.rhsSymbolId().id() == p_dirichlet_bc_descriptor->rhsSymbolId().id()); + REQUIRE(read_neumann_bc.boundaryDescriptor().type() == p_neumann_bc_descriptor->boundaryDescriptor().type()); + REQUIRE(read_neumann_bc.name() == p_neumann_bc_descriptor->name()); + REQUIRE(read_neumann_bc.rhsSymbolId().id() == p_neumann_bc_descriptor->rhsSymbolId().id()); + REQUIRE(read_fourier_bc.boundaryDescriptor().type() == p_fourier_bc_descriptor->boundaryDescriptor().type()); + REQUIRE(read_fourier_bc.name() == p_fourier_bc_descriptor->name()); + REQUIRE(read_fourier_bc.massSymbolId().id() == p_fourier_bc_descriptor->massSymbolId().id()); + REQUIRE(read_fourier_bc.rhsSymbolId().id() == p_fourier_bc_descriptor->rhsSymbolId().id()); + REQUIRE(read_inflow_bc.boundaryDescriptor().type() == p_inflow_bc_descriptor->boundaryDescriptor().type()); + REQUIRE(read_inflow_bc.functionSymbolId().id() == p_inflow_bc_descriptor->functionSymbolId().id()); + + checkpointing::ResumingData::destroy(); + } + } + + parallel::barrier(); + if (parallel::rank() == 0) { + std::filesystem::remove_all(std::filesystem::path{tmp_dirname}); + } +}