diff --git a/tests/test_DiscreteFunctionInterpoler.cpp b/tests/test_DiscreteFunctionInterpoler.cpp index c697af1eeaa1c4a39ae3104d226ac173caceb475..d0f9f274f3ff95580a810d62718631198dd2ad86 100644 --- a/tests/test_DiscreteFunctionInterpoler.cpp +++ b/tests/test_DiscreteFunctionInterpoler.cpp @@ -43,10 +43,14 @@ TEST_CASE("DiscreteFunctionInterpoler", "[scheme]") { constexpr size_t Dimension = 1; - const auto& mesh_1d = MeshDataBaseForTests::get().cartesian1DMesh(); - auto xj = MeshDataManager::instance().getMeshData(*mesh_1d).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - std::string_view data = R"( + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh_1d).xj(); + + std::string_view data = R"( import math; let B_scalar_non_linear_1d: R^1 -> B, x -> (exp(2 * x[0]) + 3 > 4); let N_scalar_non_linear_1d: R^1 -> N, x -> floor(3 * x[0] * x[0] + 2); @@ -59,274 +63,276 @@ let R1x1_non_linear_1d: R^1 -> R^1x1, x -> (2 * exp(x[0]) * sin(x[0]) + 3); let R2x2_non_linear_1d: R^1 -> R^2x2, x -> (2 * exp(x[0]) * sin(x[0]) + 3, sin(x[0] - 2 * x[0]), 3, x[0] * x[0]); let R3x3_non_linear_1d: R^1 -> R^3x3, x -> (2 * exp(x[0]) * sin(x[0]) + 3, sin(x[0] - 2 * x[0]), 3, x[0] * x[0], -4*x[0], 2*x[0]+1, 3, -6*x[0], exp(x[0])); )"; - TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; - auto ast = ASTBuilder::build(input); + auto ast = ASTBuilder::build(input); - ASTModulesImporter{*ast}; - ASTNodeTypeCleaner<language::import_instruction>{*ast}; + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; - ASTSymbolTableBuilder{*ast}; - ASTNodeDataTypeBuilder{*ast}; + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; - ASTNodeTypeCleaner<language::var_declaration>{*ast}; - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; - ASTNodeExpressionBuilder{*ast}; + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; - std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; - TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point - SECTION("B_scalar_non_linear_1d") - { - auto [i_symbol, found] = symbol_table->find("B_scalar_non_linear_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + SECTION("B_scalar_non_linear_1d") + { + auto [i_symbol, found] = symbol_table->find("B_scalar_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - CellValue<double> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = std::exp(2 * x[0]) + 3 > 4; - }); + CellValue<double> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = std::exp(2 * x[0]) + 3 > 4; + }); - DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), - function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), + function_symbol_id); + std::shared_ptr discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); - } + REQUIRE(same_cell_value(cell_value, + dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + } - SECTION("N_scalar_non_linear_1d") - { - auto [i_symbol, found] = symbol_table->find("N_scalar_non_linear_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + SECTION("N_scalar_non_linear_1d") + { + auto [i_symbol, found] = symbol_table->find("N_scalar_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - CellValue<double> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = std::floor(3 * x[0] * x[0] + 2); - }); + CellValue<double> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = std::floor(3 * x[0] * x[0] + 2); + }); - DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), - function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), + function_symbol_id); + std::shared_ptr discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); - } + REQUIRE(same_cell_value(cell_value, + dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + } - SECTION("Z_scalar_non_linear_1d") - { - auto [i_symbol, found] = symbol_table->find("Z_scalar_non_linear_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + SECTION("Z_scalar_non_linear_1d") + { + auto [i_symbol, found] = symbol_table->find("Z_scalar_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - CellValue<double> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = std::floor(std::exp(2 * x[0]) - 1); - }); + CellValue<double> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = std::floor(std::exp(2 * x[0]) - 1); + }); - DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), - function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), + function_symbol_id); + std::shared_ptr discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); - } + REQUIRE(same_cell_value(cell_value, + dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + } - SECTION("R_scalar_non_linear_1d") - { - auto [i_symbol, found] = symbol_table->find("R_scalar_non_linear_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + SECTION("R_scalar_non_linear_1d") + { + auto [i_symbol, found] = symbol_table->find("R_scalar_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - CellValue<double> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = 2 * std::exp(x[0]) + 3; - }); + CellValue<double> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = 2 * std::exp(x[0]) + 3; + }); - DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), - function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), + function_symbol_id); + std::shared_ptr discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); - } + REQUIRE(same_cell_value(cell_value, + dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + } - SECTION("R1_non_linear_1d") - { - using DataType = TinyVector<1>; + SECTION("R1_non_linear_1d") + { + using DataType = TinyVector<1>; - auto [i_symbol, found] = symbol_table->find("R1_non_linear_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + auto [i_symbol, found] = symbol_table->find("R1_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - CellValue<DataType> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = DataType{2 * std::exp(x[0])}; - }); + CellValue<DataType> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = DataType{2 * std::exp(x[0])}; + }); - DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), - function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), + function_symbol_id); + std::shared_ptr discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); - } + REQUIRE(same_cell_value(cell_value, + dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + } - SECTION("R2_non_linear_1d") - { - using DataType = TinyVector<2>; + SECTION("R2_non_linear_1d") + { + using DataType = TinyVector<2>; - auto [i_symbol, found] = symbol_table->find("R2_non_linear_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + auto [i_symbol, found] = symbol_table->find("R2_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - CellValue<DataType> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = DataType{2 * std::exp(x[0]), -3 * x[0]}; - }); + CellValue<DataType> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = DataType{2 * std::exp(x[0]), -3 * x[0]}; + }); - DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), - function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), + function_symbol_id); + std::shared_ptr discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); - } + REQUIRE(same_cell_value(cell_value, + dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + } - SECTION("R3_non_linear_1d") - { - using DataType = TinyVector<3>; + SECTION("R3_non_linear_1d") + { + using DataType = TinyVector<3>; - auto [i_symbol, found] = symbol_table->find("R3_non_linear_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + auto [i_symbol, found] = symbol_table->find("R3_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - CellValue<DataType> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = DataType{2 * std::exp(x[0]) + 3, x[0] - 2, 3}; - }); + CellValue<DataType> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = DataType{2 * std::exp(x[0]) + 3, x[0] - 2, 3}; + }); - DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), - function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), + function_symbol_id); + std::shared_ptr discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); - } + REQUIRE(same_cell_value(cell_value, + dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + } - SECTION("R1x1_non_linear_1d") - { - using DataType = TinyMatrix<1>; + SECTION("R1x1_non_linear_1d") + { + using DataType = TinyMatrix<1>; - auto [i_symbol, found] = symbol_table->find("R1x1_non_linear_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + auto [i_symbol, found] = symbol_table->find("R1x1_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - CellValue<DataType> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = DataType{2 * std::exp(x[0]) * std::sin(x[0]) + 3}; - }); + CellValue<DataType> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = DataType{2 * std::exp(x[0]) * std::sin(x[0]) + 3}; + }); - DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), - function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), + function_symbol_id); + std::shared_ptr discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); - } + REQUIRE(same_cell_value(cell_value, + dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + } - SECTION("R2x2_non_linear_1d") - { - using DataType = TinyMatrix<2>; + SECTION("R2x2_non_linear_1d") + { + using DataType = TinyMatrix<2>; - auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<DataType> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = + DataType{2 * std::exp(x[0]) * std::sin(x[0]) + 3, std::sin(x[0] - 2 * x[0]), 3, x[0] * x[0]}; + }); - CellValue<DataType> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = - DataType{2 * std::exp(x[0]) * std::sin(x[0]) + 3, std::sin(x[0] - 2 * x[0]), 3, x[0] * x[0]}; - }); + DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), + function_symbol_id); + std::shared_ptr discrete_function = interpoler.interpolate(); - DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), - function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + REQUIRE(same_cell_value(cell_value, + dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + } - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); - } + SECTION("R3x3_non_linear_1d") + { + using DataType = TinyMatrix<3>; - SECTION("R3x3_non_linear_1d") - { - using DataType = TinyMatrix<3>; - - auto [i_symbol, found] = symbol_table->find("R3x3_non_linear_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - CellValue<DataType> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = DataType{2 * exp(x[0]) * std::sin(x[0]) + 3, - std::sin(x[0] - 2 * x[0]), - 3, - x[0] * x[0], - -4 * x[0], - 2 * x[0] + 1, - 3, - -6 * x[0], - std::exp(x[0])}; - }); - - DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), - function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); - - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + auto [i_symbol, found] = symbol_table->find("R3x3_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<DataType> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = DataType{2 * exp(x[0]) * std::sin(x[0]) + 3, + std::sin(x[0] - 2 * x[0]), + 3, + x[0] * x[0], + -4 * x[0], + 2 * x[0] + 1, + 3, + -6 * x[0], + std::exp(x[0])}; + }); + + DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), + function_symbol_id); + std::shared_ptr discrete_function = interpoler.interpolate(); + + REQUIRE(same_cell_value(cell_value, + dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + } + } } } @@ -334,15 +340,12 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> (2 * exp(x[0]) * sin(x[0]) + 3, sin(x { constexpr size_t Dimension = 2; - std::array mesh_list = // - {std::make_pair(std::string{"cartesian grid"}, MeshDataBaseForTests::get().cartesian2DMesh()), - std::make_pair(std::string{"hybrid grid"}, MeshDataBaseForTests::get().hybrid2DMesh())}; + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - for (auto [section_name, mesh_3d] : mesh_list) { + for (auto [section_name, mesh_2d] : mesh_list) { SECTION(section_name) { - const auto& mesh_2d = MeshDataBaseForTests::get().cartesian2DMesh(); - auto xj = MeshDataManager::instance().getMeshData(*mesh_2d).xj(); + auto xj = MeshDataManager::instance().getMeshData(*mesh_2d).xj(); std::string_view data = R"( import math; @@ -635,9 +638,7 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> (2 * exp(x[0]) * sin(x[1]) + 3, sin(x { constexpr size_t Dimension = 3; - std::array mesh_list = // - {std::make_pair(std::string{"cartesian grid"}, MeshDataBaseForTests::get().cartesian3DMesh()), - std::make_pair(std::string{"hybrid grid"}, MeshDataBaseForTests::get().hybrid3DMesh())}; + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); for (auto [section_name, mesh_3d] : mesh_list) { SECTION(section_name) diff --git a/tests/test_DiscreteFunctionP0.cpp b/tests/test_DiscreteFunctionP0.cpp index ce9644d8b485689f5e3790097f1e28f2c80dc764..f57093c851fc7d95f83f988092df456d4321c775 100644 --- a/tests/test_DiscreteFunctionP0.cpp +++ b/tests/test_DiscreteFunctionP0.cpp @@ -22,128 +22,143 @@ TEST_CASE("DiscreteFunctionP0", "[scheme]") { SECTION("1D") { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian1DMesh(); - constexpr size_t Dimension = 1; - DiscreteFunctionP0<Dimension, double> f{mesh}; - REQUIRE(f.dataType() == ASTNodeDataType::double_t); - REQUIRE(f.descriptor().type() == DiscreteFunctionType::P0); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); + + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + DiscreteFunctionP0<Dimension, double> f{mesh}; + REQUIRE(f.dataType() == ASTNodeDataType::double_t); + REQUIRE(f.descriptor().type() == DiscreteFunctionType::P0); - REQUIRE(f.mesh().get() == mesh.get()); + REQUIRE(f.mesh().get() == mesh.get()); - DiscreteFunctionP0 g{f}; - REQUIRE(g.dataType() == ASTNodeDataType::double_t); - REQUIRE(g.descriptor().type() == DiscreteFunctionType::P0); + DiscreteFunctionP0 g{f}; + REQUIRE(g.dataType() == ASTNodeDataType::double_t); + REQUIRE(g.descriptor().type() == DiscreteFunctionType::P0); - CellValue<TinyVector<Dimension>> h_values{mesh->connectivity()}; - h_values.fill(ZeroType{}); + CellValue<TinyVector<Dimension>> h_values{mesh->connectivity()}; + h_values.fill(ZeroType{}); - DiscreteFunctionP0 zero{mesh, [&] { - CellValue<TinyVector<Dimension>> cell_value{mesh->connectivity()}; - cell_value.fill(ZeroType{}); - return cell_value; - }()}; + DiscreteFunctionP0 zero{mesh, [&] { + CellValue<TinyVector<Dimension>> cell_value{mesh->connectivity()}; + cell_value.fill(ZeroType{}); + return cell_value; + }()}; - DiscreteFunctionP0 h{mesh, h_values}; - REQUIRE(same_values(h, zero)); - REQUIRE(same_values(h, h_values)); + DiscreteFunctionP0 h{mesh, h_values}; + REQUIRE(same_values(h, zero)); + REQUIRE(same_values(h, h_values)); - DiscreteFunctionP0<Dimension, TinyVector<Dimension>> shallow_h{mesh}; - shallow_h = h; + DiscreteFunctionP0<Dimension, TinyVector<Dimension>> shallow_h{mesh}; + shallow_h = h; - copy_to(MeshDataManager::instance().getMeshData(*mesh).xj(), h_values); + copy_to(MeshDataManager::instance().getMeshData(*mesh).xj(), h_values); - REQUIRE(same_values(shallow_h, h_values)); - REQUIRE(same_values(h, h_values)); - REQUIRE(not same_values(h, zero)); + REQUIRE(same_values(shallow_h, h_values)); + REQUIRE(same_values(h, h_values)); + REQUIRE(not same_values(h, zero)); - DiscreteFunctionP0 moved_h{std::move(h)}; - REQUIRE(same_values(moved_h, h_values)); + DiscreteFunctionP0 moved_h{std::move(h)}; + REQUIRE(same_values(moved_h, h_values)); + } + } } SECTION("2D") { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian2DMesh(); - constexpr size_t Dimension = 2; - DiscreteFunctionP0<Dimension, double> f{mesh}; - REQUIRE(f.dataType() == ASTNodeDataType::double_t); - REQUIRE(f.descriptor().type() == DiscreteFunctionType::P0); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); + + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + DiscreteFunctionP0<Dimension, double> f{mesh}; + REQUIRE(f.dataType() == ASTNodeDataType::double_t); + REQUIRE(f.descriptor().type() == DiscreteFunctionType::P0); - REQUIRE(f.mesh().get() == mesh.get()); + REQUIRE(f.mesh().get() == mesh.get()); - DiscreteFunctionP0 g{f}; - REQUIRE(g.dataType() == ASTNodeDataType::double_t); - REQUIRE(g.descriptor().type() == DiscreteFunctionType::P0); + DiscreteFunctionP0 g{f}; + REQUIRE(g.dataType() == ASTNodeDataType::double_t); + REQUIRE(g.descriptor().type() == DiscreteFunctionType::P0); - CellValue<TinyVector<Dimension>> h_values{mesh->connectivity()}; - h_values.fill(ZeroType{}); + CellValue<TinyVector<Dimension>> h_values{mesh->connectivity()}; + h_values.fill(ZeroType{}); - DiscreteFunctionP0 zero{mesh, [&] { - CellValue<TinyVector<Dimension>> cell_value{mesh->connectivity()}; - cell_value.fill(ZeroType{}); - return cell_value; - }()}; + DiscreteFunctionP0 zero{mesh, [&] { + CellValue<TinyVector<Dimension>> cell_value{mesh->connectivity()}; + cell_value.fill(ZeroType{}); + return cell_value; + }()}; - DiscreteFunctionP0 h{mesh, h_values}; - REQUIRE(same_values(h, zero)); - REQUIRE(same_values(h, h_values)); + DiscreteFunctionP0 h{mesh, h_values}; + REQUIRE(same_values(h, zero)); + REQUIRE(same_values(h, h_values)); - DiscreteFunctionP0<Dimension, TinyVector<Dimension>> shallow_h{mesh}; - shallow_h = h; + DiscreteFunctionP0<Dimension, TinyVector<Dimension>> shallow_h{mesh}; + shallow_h = h; - copy_to(MeshDataManager::instance().getMeshData(*mesh).xj(), h_values); + copy_to(MeshDataManager::instance().getMeshData(*mesh).xj(), h_values); - REQUIRE(same_values(shallow_h, h_values)); - REQUIRE(same_values(h, h_values)); - REQUIRE(not same_values(h, zero)); + REQUIRE(same_values(shallow_h, h_values)); + REQUIRE(same_values(h, h_values)); + REQUIRE(not same_values(h, zero)); - DiscreteFunctionP0 moved_h{std::move(h)}; - REQUIRE(same_values(moved_h, h_values)); + DiscreteFunctionP0 moved_h{std::move(h)}; + REQUIRE(same_values(moved_h, h_values)); + } + } } SECTION("3D") { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian3DMesh(); - constexpr size_t Dimension = 3; - DiscreteFunctionP0<Dimension, double> f{mesh}; - REQUIRE(f.dataType() == ASTNodeDataType::double_t); - REQUIRE(f.descriptor().type() == DiscreteFunctionType::P0); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); + + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + DiscreteFunctionP0<Dimension, double> f{mesh}; + REQUIRE(f.dataType() == ASTNodeDataType::double_t); + REQUIRE(f.descriptor().type() == DiscreteFunctionType::P0); - REQUIRE(f.mesh().get() == mesh.get()); + REQUIRE(f.mesh().get() == mesh.get()); - DiscreteFunctionP0 g{f}; - REQUIRE(g.dataType() == ASTNodeDataType::double_t); - REQUIRE(g.descriptor().type() == DiscreteFunctionType::P0); + DiscreteFunctionP0 g{f}; + REQUIRE(g.dataType() == ASTNodeDataType::double_t); + REQUIRE(g.descriptor().type() == DiscreteFunctionType::P0); - CellValue<TinyVector<Dimension>> h_values{mesh->connectivity()}; - h_values.fill(ZeroType{}); + CellValue<TinyVector<Dimension>> h_values{mesh->connectivity()}; + h_values.fill(ZeroType{}); - DiscreteFunctionP0 zero{mesh, [&] { - CellValue<TinyVector<Dimension>> cell_value{mesh->connectivity()}; - cell_value.fill(ZeroType{}); - return cell_value; - }()}; + DiscreteFunctionP0 zero{mesh, [&] { + CellValue<TinyVector<Dimension>> cell_value{mesh->connectivity()}; + cell_value.fill(ZeroType{}); + return cell_value; + }()}; - DiscreteFunctionP0 h{mesh, h_values}; - REQUIRE(same_values(h, zero)); - REQUIRE(same_values(h, h_values)); + DiscreteFunctionP0 h{mesh, h_values}; + REQUIRE(same_values(h, zero)); + REQUIRE(same_values(h, h_values)); - DiscreteFunctionP0<Dimension, TinyVector<Dimension>> shallow_h{mesh}; - shallow_h = h; + DiscreteFunctionP0<Dimension, TinyVector<Dimension>> shallow_h{mesh}; + shallow_h = h; - copy_to(MeshDataManager::instance().getMeshData(*mesh).xj(), h_values); + copy_to(MeshDataManager::instance().getMeshData(*mesh).xj(), h_values); - REQUIRE(same_values(shallow_h, h_values)); - REQUIRE(same_values(h, h_values)); - REQUIRE(not same_values(h, zero)); + REQUIRE(same_values(shallow_h, h_values)); + REQUIRE(same_values(h, h_values)); + REQUIRE(not same_values(h, zero)); - DiscreteFunctionP0 moved_h{std::move(h)}; - REQUIRE(same_values(moved_h, h_values)); + DiscreteFunctionP0 moved_h{std::move(h)}; + REQUIRE(same_values(moved_h, h_values)); + } + } } } @@ -161,65 +176,83 @@ TEST_CASE("DiscreteFunctionP0", "[scheme]") SECTION("1D") { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian1DMesh(); constexpr size_t Dimension = 1; - DiscreteFunctionP0<Dimension, double> f{mesh}; - f.fill(3); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); + + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + DiscreteFunctionP0<Dimension, double> f{mesh}; + f.fill(3); - REQUIRE(all_values_equal(f, 3)); + REQUIRE(all_values_equal(f, 3)); - DiscreteFunctionP0<Dimension, TinyVector<3>> v{mesh}; - v.fill(TinyVector<3>{1, 2, 3}); + DiscreteFunctionP0<Dimension, TinyVector<3>> v{mesh}; + v.fill(TinyVector<3>{1, 2, 3}); - REQUIRE(all_values_equal(v, TinyVector<3>{1, 2, 3})); + REQUIRE(all_values_equal(v, TinyVector<3>{1, 2, 3})); - DiscreteFunctionP0<Dimension, TinyMatrix<3>> A{mesh}; - A.fill(TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9}); + DiscreteFunctionP0<Dimension, TinyMatrix<3>> A{mesh}; + A.fill(TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9}); - REQUIRE(all_values_equal(A, TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9})); + REQUIRE(all_values_equal(A, TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9})); + } + } } SECTION("2D") { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian2DMesh(); constexpr size_t Dimension = 2; - DiscreteFunctionP0<Dimension, double> f{mesh}; - f.fill(3); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); + + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + DiscreteFunctionP0<Dimension, double> f{mesh}; + f.fill(3); - REQUIRE(all_values_equal(f, 3)); + REQUIRE(all_values_equal(f, 3)); - DiscreteFunctionP0<Dimension, TinyVector<3>> v{mesh}; - v.fill(TinyVector<3>{1, 2, 3}); + DiscreteFunctionP0<Dimension, TinyVector<3>> v{mesh}; + v.fill(TinyVector<3>{1, 2, 3}); - REQUIRE(all_values_equal(v, TinyVector<3>{1, 2, 3})); + REQUIRE(all_values_equal(v, TinyVector<3>{1, 2, 3})); - DiscreteFunctionP0<Dimension, TinyMatrix<3>> A{mesh}; - A.fill(TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9}); + DiscreteFunctionP0<Dimension, TinyMatrix<3>> A{mesh}; + A.fill(TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9}); - REQUIRE(all_values_equal(A, TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9})); + REQUIRE(all_values_equal(A, TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9})); + } + } } SECTION("3D") { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian3DMesh(); constexpr size_t Dimension = 3; - DiscreteFunctionP0<Dimension, double> f{mesh}; - f.fill(3); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - REQUIRE(all_values_equal(f, 3)); + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + DiscreteFunctionP0<Dimension, double> f{mesh}; + f.fill(3); - DiscreteFunctionP0<Dimension, TinyVector<3>> v{mesh}; - v.fill(TinyVector<3>{1, 2, 3}); + REQUIRE(all_values_equal(f, 3)); - REQUIRE(all_values_equal(v, TinyVector<3>{1, 2, 3})); + DiscreteFunctionP0<Dimension, TinyVector<3>> v{mesh}; + v.fill(TinyVector<3>{1, 2, 3}); - DiscreteFunctionP0<Dimension, TinyMatrix<3>> A{mesh}; - A.fill(TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9}); + REQUIRE(all_values_equal(v, TinyVector<3>{1, 2, 3})); - REQUIRE(all_values_equal(A, TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9})); + DiscreteFunctionP0<Dimension, TinyMatrix<3>> A{mesh}; + A.fill(TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9}); + + REQUIRE(all_values_equal(A, TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9})); + } + } } } @@ -237,286 +270,301 @@ TEST_CASE("DiscreteFunctionP0", "[scheme]") SECTION("1D") { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian1DMesh(); - constexpr size_t Dimension = 1; - SECTION("scalar") - { - const size_t value = parallel::rank() + 1; - const size_t zero = 0; + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - DiscreteFunctionP0<Dimension, size_t> f{mesh}; - f.fill(value); + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + SECTION("scalar") + { + const size_t value = parallel::rank() + 1; + const size_t zero = 0; - REQUIRE(all_values_equal(f, value)); + DiscreteFunctionP0<Dimension, size_t> f{mesh}; + f.fill(value); - DiscreteFunctionP0 g = copy(f); - f.fill(zero); + REQUIRE(all_values_equal(f, value)); - REQUIRE(all_values_equal(f, zero)); - REQUIRE(all_values_equal(g, value)); + DiscreteFunctionP0 g = copy(f); + f.fill(zero); - copy_to(g, f); - g.fill(zero); + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); - DiscreteFunctionP0<Dimension, const size_t> h = copy(f); + copy_to(g, f); + g.fill(zero); - REQUIRE(all_values_equal(f, value)); - REQUIRE(all_values_equal(g, zero)); - REQUIRE(all_values_equal(h, value)); + DiscreteFunctionP0<Dimension, const size_t> h = copy(f); - copy_to(h, g); + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); - REQUIRE(all_values_equal(g, value)); - } + copy_to(h, g); - SECTION("vector") - { - const TinyVector<2, size_t> value{parallel::rank() + 1, 3}; - const TinyVector<2, size_t> zero{ZeroType{}}; - DiscreteFunctionP0<Dimension, TinyVector<2, size_t>> f{mesh}; - f.fill(value); + REQUIRE(all_values_equal(g, value)); + } - REQUIRE(all_values_equal(f, value)); + SECTION("vector") + { + const TinyVector<2, size_t> value{parallel::rank() + 1, 3}; + const TinyVector<2, size_t> zero{ZeroType{}}; + DiscreteFunctionP0<Dimension, TinyVector<2, size_t>> f{mesh}; + f.fill(value); - DiscreteFunctionP0 g = copy(f); - f.fill(zero); + REQUIRE(all_values_equal(f, value)); - REQUIRE(all_values_equal(f, zero)); - REQUIRE(all_values_equal(g, value)); + DiscreteFunctionP0 g = copy(f); + f.fill(zero); - copy_to(g, f); - g.fill(zero); + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); - DiscreteFunctionP0<Dimension, const TinyVector<2, size_t>> h = copy(f); + copy_to(g, f); + g.fill(zero); - REQUIRE(all_values_equal(f, value)); - REQUIRE(all_values_equal(g, zero)); - REQUIRE(all_values_equal(h, value)); + DiscreteFunctionP0<Dimension, const TinyVector<2, size_t>> h = copy(f); - copy_to(h, g); + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); - REQUIRE(all_values_equal(g, value)); - } + copy_to(h, g); - SECTION("matrix") - { - const TinyMatrix<3, 3, size_t> value{1, 2, 3, 4, 5, 6, 7, 8, 9}; - const TinyMatrix<3, 3, size_t> zero{ZeroType{}}; - DiscreteFunctionP0<Dimension, TinyMatrix<3, 3, size_t>> f{mesh}; - f.fill(value); + REQUIRE(all_values_equal(g, value)); + } - REQUIRE(all_values_equal(f, value)); + SECTION("matrix") + { + const TinyMatrix<3, 3, size_t> value{1, 2, 3, 4, 5, 6, 7, 8, 9}; + const TinyMatrix<3, 3, size_t> zero{ZeroType{}}; + DiscreteFunctionP0<Dimension, TinyMatrix<3, 3, size_t>> f{mesh}; + f.fill(value); + + REQUIRE(all_values_equal(f, value)); - DiscreteFunctionP0 g = copy(f); - f.fill(zero); + DiscreteFunctionP0 g = copy(f); + f.fill(zero); - REQUIRE(all_values_equal(f, zero)); - REQUIRE(all_values_equal(g, value)); + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); - copy_to(g, f); - g.fill(zero); + copy_to(g, f); + g.fill(zero); - DiscreteFunctionP0<Dimension, const TinyMatrix<3, 3, size_t>> h = copy(f); + DiscreteFunctionP0<Dimension, const TinyMatrix<3, 3, size_t>> h = copy(f); - REQUIRE(all_values_equal(f, value)); - REQUIRE(all_values_equal(g, zero)); - REQUIRE(all_values_equal(h, value)); + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); - copy_to(h, g); + copy_to(h, g); - REQUIRE(all_values_equal(g, value)); + REQUIRE(all_values_equal(g, value)); + } + } } } SECTION("2D") { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian2DMesh(); - constexpr size_t Dimension = 2; - SECTION("scalar") - { - const size_t value = parallel::rank() + 1; - const size_t zero = 0; + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); + + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + SECTION("scalar") + { + const size_t value = parallel::rank() + 1; + const size_t zero = 0; - DiscreteFunctionP0<Dimension, size_t> f{mesh}; - f.fill(value); + DiscreteFunctionP0<Dimension, size_t> f{mesh}; + f.fill(value); - REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(f, value)); - DiscreteFunctionP0 g = copy(f); - f.fill(zero); + DiscreteFunctionP0 g = copy(f); + f.fill(zero); - REQUIRE(all_values_equal(f, zero)); - REQUIRE(all_values_equal(g, value)); + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); - copy_to(g, f); - g.fill(zero); + copy_to(g, f); + g.fill(zero); - DiscreteFunctionP0<Dimension, const size_t> h = copy(f); + DiscreteFunctionP0<Dimension, const size_t> h = copy(f); - REQUIRE(all_values_equal(f, value)); - REQUIRE(all_values_equal(g, zero)); - REQUIRE(all_values_equal(h, value)); + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); - copy_to(h, g); + copy_to(h, g); - REQUIRE(all_values_equal(g, value)); - } + REQUIRE(all_values_equal(g, value)); + } - SECTION("vector") - { - const TinyVector<2, size_t> value{parallel::rank() + 1, 3}; - const TinyVector<2, size_t> zero{ZeroType{}}; - DiscreteFunctionP0<Dimension, TinyVector<2, size_t>> f{mesh}; - f.fill(value); + SECTION("vector") + { + const TinyVector<2, size_t> value{parallel::rank() + 1, 3}; + const TinyVector<2, size_t> zero{ZeroType{}}; + DiscreteFunctionP0<Dimension, TinyVector<2, size_t>> f{mesh}; + f.fill(value); - REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(f, value)); - DiscreteFunctionP0 g = copy(f); - f.fill(zero); + DiscreteFunctionP0 g = copy(f); + f.fill(zero); - REQUIRE(all_values_equal(f, zero)); - REQUIRE(all_values_equal(g, value)); + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); - copy_to(g, f); - g.fill(zero); + copy_to(g, f); + g.fill(zero); - DiscreteFunctionP0<Dimension, const TinyVector<2, size_t>> h = copy(f); + DiscreteFunctionP0<Dimension, const TinyVector<2, size_t>> h = copy(f); - REQUIRE(all_values_equal(f, value)); - REQUIRE(all_values_equal(g, zero)); - REQUIRE(all_values_equal(h, value)); + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); - copy_to(h, g); + copy_to(h, g); - REQUIRE(all_values_equal(g, value)); - } + REQUIRE(all_values_equal(g, value)); + } - SECTION("matrix") - { - const TinyMatrix<3, 3, size_t> value{1, 2, 3, 4, 5, 6, 7, 8, 9}; - const TinyMatrix<3, 3, size_t> zero{ZeroType{}}; - DiscreteFunctionP0<Dimension, TinyMatrix<3, 3, size_t>> f{mesh}; - f.fill(value); + SECTION("matrix") + { + const TinyMatrix<3, 3, size_t> value{1, 2, 3, 4, 5, 6, 7, 8, 9}; + const TinyMatrix<3, 3, size_t> zero{ZeroType{}}; + DiscreteFunctionP0<Dimension, TinyMatrix<3, 3, size_t>> f{mesh}; + f.fill(value); - REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(f, value)); - DiscreteFunctionP0 g = copy(f); - f.fill(zero); + DiscreteFunctionP0 g = copy(f); + f.fill(zero); - REQUIRE(all_values_equal(f, zero)); - REQUIRE(all_values_equal(g, value)); + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); - copy_to(g, f); - g.fill(zero); + copy_to(g, f); + g.fill(zero); - DiscreteFunctionP0<Dimension, const TinyMatrix<3, 3, size_t>> h = copy(f); + DiscreteFunctionP0<Dimension, const TinyMatrix<3, 3, size_t>> h = copy(f); - REQUIRE(all_values_equal(f, value)); - REQUIRE(all_values_equal(g, zero)); - REQUIRE(all_values_equal(h, value)); + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); - copy_to(h, g); + copy_to(h, g); - REQUIRE(all_values_equal(g, value)); + REQUIRE(all_values_equal(g, value)); + } + } } } SECTION("3D") { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian3DMesh(); - constexpr size_t Dimension = 3; - SECTION("scalar") - { - const size_t value = parallel::rank() + 1; - const size_t zero = 0; + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - DiscreteFunctionP0<Dimension, size_t> f{mesh}; - f.fill(value); + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + SECTION("scalar") + { + const size_t value = parallel::rank() + 1; + const size_t zero = 0; - REQUIRE(all_values_equal(f, value)); + DiscreteFunctionP0<Dimension, size_t> f{mesh}; + f.fill(value); - DiscreteFunctionP0 g = copy(f); - f.fill(zero); + REQUIRE(all_values_equal(f, value)); - REQUIRE(all_values_equal(f, zero)); - REQUIRE(all_values_equal(g, value)); + DiscreteFunctionP0 g = copy(f); + f.fill(zero); - copy_to(g, f); - g.fill(zero); + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); - DiscreteFunctionP0<Dimension, const size_t> h = copy(f); + copy_to(g, f); + g.fill(zero); - REQUIRE(all_values_equal(f, value)); - REQUIRE(all_values_equal(g, zero)); - REQUIRE(all_values_equal(h, value)); + DiscreteFunctionP0<Dimension, const size_t> h = copy(f); - copy_to(h, g); + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); - REQUIRE(all_values_equal(g, value)); - } + copy_to(h, g); - SECTION("vector") - { - const TinyVector<2, size_t> value{parallel::rank() + 1, 3}; - const TinyVector<2, size_t> zero{ZeroType{}}; - DiscreteFunctionP0<Dimension, TinyVector<2, size_t>> f{mesh}; - f.fill(value); + REQUIRE(all_values_equal(g, value)); + } - REQUIRE(all_values_equal(f, value)); + SECTION("vector") + { + const TinyVector<2, size_t> value{parallel::rank() + 1, 3}; + const TinyVector<2, size_t> zero{ZeroType{}}; + DiscreteFunctionP0<Dimension, TinyVector<2, size_t>> f{mesh}; + f.fill(value); - DiscreteFunctionP0 g = copy(f); - f.fill(zero); + REQUIRE(all_values_equal(f, value)); - REQUIRE(all_values_equal(f, zero)); - REQUIRE(all_values_equal(g, value)); + DiscreteFunctionP0 g = copy(f); + f.fill(zero); - copy_to(g, f); - g.fill(zero); + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); - DiscreteFunctionP0<Dimension, const TinyVector<2, size_t>> h = copy(f); + copy_to(g, f); + g.fill(zero); - REQUIRE(all_values_equal(f, value)); - REQUIRE(all_values_equal(g, zero)); - REQUIRE(all_values_equal(h, value)); + DiscreteFunctionP0<Dimension, const TinyVector<2, size_t>> h = copy(f); - copy_to(h, g); + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); - REQUIRE(all_values_equal(g, value)); - } + copy_to(h, g); - SECTION("matrix") - { - const TinyMatrix<3, 3, size_t> value{1, 2, 3, 4, 5, 6, 7, 8, 9}; - const TinyMatrix<3, 3, size_t> zero{ZeroType{}}; - DiscreteFunctionP0<Dimension, TinyMatrix<3, 3, size_t>> f{mesh}; - f.fill(value); + REQUIRE(all_values_equal(g, value)); + } + + SECTION("matrix") + { + const TinyMatrix<3, 3, size_t> value{1, 2, 3, 4, 5, 6, 7, 8, 9}; + const TinyMatrix<3, 3, size_t> zero{ZeroType{}}; + DiscreteFunctionP0<Dimension, TinyMatrix<3, 3, size_t>> f{mesh}; + f.fill(value); - REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(f, value)); - DiscreteFunctionP0 g = copy(f); - f.fill(zero); + DiscreteFunctionP0 g = copy(f); + f.fill(zero); - REQUIRE(all_values_equal(f, zero)); - REQUIRE(all_values_equal(g, value)); + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); - copy_to(g, f); - g.fill(zero); + copy_to(g, f); + g.fill(zero); - DiscreteFunctionP0<Dimension, const TinyMatrix<3, 3, size_t>> h = copy(f); + DiscreteFunctionP0<Dimension, const TinyMatrix<3, 3, size_t>> h = copy(f); - REQUIRE(all_values_equal(f, value)); - REQUIRE(all_values_equal(g, zero)); - REQUIRE(all_values_equal(h, value)); + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); - copy_to(h, g); + copy_to(h, g); - REQUIRE(all_values_equal(g, value)); + REQUIRE(all_values_equal(g, value)); + } + } } } } @@ -525,75 +573,79 @@ TEST_CASE("DiscreteFunctionP0", "[scheme]") { SECTION("1D") { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian1DMesh(); - constexpr size_t Dimension = 1; + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - SECTION("unary minus") - { - SECTION("scalar functions") + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) { - DiscreteFunctionP0<Dimension, double> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - f[cell_id] = 2 * x + 1; - }); + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - DiscreteFunctionP0<Dimension, const double> const_f = f; + SECTION("unary minus") + { + SECTION("scalar functions") + { + DiscreteFunctionP0<Dimension, double> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + f[cell_id] = 2 * x + 1; + }); - Array<double> minus_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { minus_values[cell_id] = -f[cell_id]; }); + DiscreteFunctionP0<Dimension, const double> const_f = f; - REQUIRE(same_values(-f, minus_values)); - REQUIRE(same_values(-const_f, minus_values)); - } + Array<double> minus_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { minus_values[cell_id] = -f[cell_id]; }); - SECTION("vector functions") - { - constexpr std::uint64_t VectorDimension = 2; + REQUIRE(same_values(-f, minus_values)); + REQUIRE(same_values(-const_f, minus_values)); + } - DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const TinyVector<VectorDimension> X{x, 2 - x}; - f[cell_id] = 2 * X + TinyVector<2>{1, 2}; - }); + SECTION("vector functions") + { + constexpr std::uint64_t VectorDimension = 2; - DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyVector<VectorDimension> X{x, 2 - x}; + f[cell_id] = 2 * X + TinyVector<2>{1, 2}; + }); - Array<TinyVector<VectorDimension>> minus_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { minus_values[cell_id] = -f[cell_id]; }); + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; - REQUIRE(same_values(-f, minus_values)); - REQUIRE(same_values(-const_f, minus_values)); - } + Array<TinyVector<VectorDimension>> minus_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { minus_values[cell_id] = -f[cell_id]; }); - SECTION("matrix functions") - { - constexpr std::uint64_t MatrixDimension = 2; + REQUIRE(same_values(-f, minus_values)); + REQUIRE(same_values(-const_f, minus_values)); + } - DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const TinyMatrix<MatrixDimension> A{x, 2 - x, 2 * x, x * x - 3}; - f[cell_id] = 2 * A + TinyMatrix<2>{1, 2, 3, 4}; - }); + SECTION("matrix functions") + { + constexpr std::uint64_t MatrixDimension = 2; + + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyMatrix<MatrixDimension> A{x, 2 - x, 2 * x, x * x - 3}; + f[cell_id] = 2 * A + TinyMatrix<2>{1, 2, 3, 4}; + }); - DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; - Array<TinyMatrix<MatrixDimension>> minus_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { minus_values[cell_id] = -f[cell_id]; }); + Array<TinyMatrix<MatrixDimension>> minus_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { minus_values[cell_id] = -f[cell_id]; }); - REQUIRE(same_values(-f, minus_values)); - REQUIRE(same_values(-const_f, minus_values)); + REQUIRE(same_values(-f, minus_values)); + REQUIRE(same_values(-const_f, minus_values)); + } + } } } } @@ -603,2839 +655,2919 @@ TEST_CASE("DiscreteFunctionP0", "[scheme]") { SECTION("1D") { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian1DMesh(); - constexpr size_t Dimension = 1; - auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - SECTION("inner operators") - { - SECTION("scalar functions") + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) { - DiscreteFunctionP0<Dimension, double> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - f[cell_id] = 2 * x + 1; - }); - - DiscreteFunctionP0<Dimension, double> g{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - g[cell_id] = std::abs((x + 1) * (x - 2)) + 1; - }); - - DiscreteFunctionP0<Dimension, const double> const_f = f; - DiscreteFunctionP0<Dimension, const double> const_g{g}; + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - SECTION("sum") + SECTION("inner operators") { - Array<double> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); - - REQUIRE(same_values(f + g, sum_values)); - REQUIRE(same_values(const_f + g, sum_values)); - REQUIRE(same_values(f + const_g, sum_values)); - REQUIRE(same_values(const_f + const_g, sum_values)); - } + SECTION("scalar functions") + { + DiscreteFunctionP0<Dimension, double> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + f[cell_id] = 2 * x + 1; + }); - SECTION("difference") - { - Array<double> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + DiscreteFunctionP0<Dimension, double> g{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + g[cell_id] = std::abs((x + 1) * (x - 2)) + 1; + }); - REQUIRE(same_values(f - g, difference_values)); - REQUIRE(same_values(const_f - g, difference_values)); - REQUIRE(same_values(f - const_g, difference_values)); - REQUIRE(same_values(const_f - const_g, difference_values)); - } + DiscreteFunctionP0<Dimension, const double> const_f = f; + DiscreteFunctionP0<Dimension, const double> const_g{g}; + + SECTION("sum") + { + Array<double> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Array<double> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + + SECTION("product") + { + Array<double> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * g[cell_id]; }); + + REQUIRE(same_values(f * g, product_values)); + REQUIRE(same_values(const_f * g, product_values)); + REQUIRE(same_values(f * const_g, product_values)); + REQUIRE(same_values(const_f * const_g, product_values)); + } + + SECTION("ratio") + { + Array<double> ratio_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = f[cell_id] / g[cell_id]; }); + + REQUIRE(same_values(f / g, ratio_values)); + REQUIRE(same_values(const_f / g, ratio_values)); + REQUIRE(same_values(f / const_g, ratio_values)); + REQUIRE(same_values(const_f / const_g, ratio_values)); + } + } + + SECTION("vector functions") + { + constexpr std::uint64_t VectorDimension = 2; + + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyVector<VectorDimension> X{x, 2 - x}; + f[cell_id] = 2 * X + TinyVector<2>{1, 2}; + }); - SECTION("product") - { - Array<double> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * g[cell_id]; }); + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> g{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyVector<VectorDimension> X{3 * x + 1, 2 + x}; + g[cell_id] = X; + }); - REQUIRE(same_values(f * g, product_values)); - REQUIRE(same_values(const_f * g, product_values)); - REQUIRE(same_values(f * const_g, product_values)); - REQUIRE(same_values(const_f * const_g, product_values)); - } + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_g{g}; - SECTION("ratio") - { - Array<double> ratio_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = f[cell_id] / g[cell_id]; }); + SECTION("sum") + { + Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); - REQUIRE(same_values(f / g, ratio_values)); - REQUIRE(same_values(const_f / g, ratio_values)); - REQUIRE(same_values(f / const_g, ratio_values)); - REQUIRE(same_values(const_f / const_g, ratio_values)); - } - } + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } - SECTION("vector functions") - { - constexpr std::uint64_t VectorDimension = 2; + SECTION("difference") + { + Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); - DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const TinyVector<VectorDimension> X{x, 2 - x}; - f[cell_id] = 2 * X + TinyVector<2>{1, 2}; - }); + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + } - DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> g{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const TinyVector<VectorDimension> X{3 * x + 1, 2 + x}; - g[cell_id] = X; - }); + SECTION("matrix functions") + { + constexpr std::uint64_t MatrixDimension = 2; - DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; - DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_g{g}; + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyMatrix<MatrixDimension> A{x, 2 - x, 2 * x, x * x - 3}; + f[cell_id] = 2 * A + TinyMatrix<2>{1, 2, 3, 4}; + }); - SECTION("sum") - { - Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> g{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyMatrix<MatrixDimension> A{3 * x + 1, 2 + x, 1 - 2 * x, 2 * x * x}; + g[cell_id] = A; + }); - REQUIRE(same_values(f + g, sum_values)); - REQUIRE(same_values(const_f + g, sum_values)); - REQUIRE(same_values(f + const_g, sum_values)); - REQUIRE(same_values(const_f + const_g, sum_values)); + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_g{g}; + + SECTION("sum") + { + Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + + SECTION("product") + { + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * g[cell_id]; }); + + REQUIRE(same_values(f * g, product_values)); + REQUIRE(same_values(const_f * g, product_values)); + REQUIRE(same_values(f * const_g, product_values)); + REQUIRE(same_values(const_f * const_g, product_values)); + } + } } - SECTION("difference") + SECTION("external operators") { - Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + SECTION("scalar functions") + { + DiscreteFunctionP0<Dimension, double> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + f[cell_id] = std::abs(2 * x) + 1; + }); + + const double a = 3; + + DiscreteFunctionP0<Dimension, const double> const_f = f; + + SECTION("sum") + { + { + Array<double> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = a + f[cell_id]; }); + + REQUIRE(same_values(a + f, sum_values)); + REQUIRE(same_values(a + const_f, sum_values)); + } + { + Array<double> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + a; }); + + REQUIRE(same_values(f + a, sum_values)); + REQUIRE(same_values(const_f + a, sum_values)); + } + } + + SECTION("difference") + { + { + Array<double> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = a - f[cell_id]; }); + REQUIRE(same_values(a - f, difference_values)); + REQUIRE(same_values(a - const_f, difference_values)); + } + + { + Array<double> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - a; }); + REQUIRE(same_values(f - a, difference_values)); + REQUIRE(same_values(const_f - a, difference_values)); + } + } + + SECTION("product") + { + { + Array<double> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + { + Array<double> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * a; }); + + REQUIRE(same_values(f * a, product_values)); + REQUIRE(same_values(const_f * a, product_values)); + } + + { + Array<TinyVector<3>> product_values{mesh->numberOfCells()}; + const TinyVector<3> v{1, 2, 3}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * v; }); + + REQUIRE(same_values(f * v, product_values)); + REQUIRE(same_values(const_f * v, product_values)); + } + + { + Array<TinyVector<3>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyVector<3>> v{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + v[cell_id] = TinyVector<3>{x, 2 * x, 1 - x}; + }); + + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * v[cell_id]; }); + + REQUIRE(same_values(f * v, product_values)); + REQUIRE(same_values(const_f * v, product_values)); + } + + { + Array<TinyMatrix<2>> product_values{mesh->numberOfCells()}; + const TinyMatrix<2> A{1, 2, 3, 4}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * A; }); + + REQUIRE(same_values(f * A, product_values)); + REQUIRE(same_values(const_f * A, product_values)); + } + + { + Array<TinyMatrix<2>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyMatrix<2>> M{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + M[cell_id] = TinyMatrix<2>{x, 2 * x, 1 - x, 2 - x * x}; + }); + + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * M[cell_id]; }); + + REQUIRE(same_values(f * M, product_values)); + REQUIRE(same_values(const_f * M, product_values)); + } + } + + SECTION("ratio") + { + { + Array<double> ratio_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = a / f[cell_id]; }); + + REQUIRE(same_values(a / f, ratio_values)); + REQUIRE(same_values(a / const_f, ratio_values)); + } + { + Array<double> ratio_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = f[cell_id] / a; }); + + REQUIRE(same_values(f / a, ratio_values)); + REQUIRE(same_values(const_f / a, ratio_values)); + } + } + } + + SECTION("vector functions") + { + constexpr std::uint64_t VectorDimension = 2; + + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyVector<VectorDimension> X{x, 2 - x}; + f[cell_id] = 2 * X + TinyVector<2>{1, 2}; + }); + + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; + + SECTION("sum") + { + const TinyVector<VectorDimension> v{1, 2}; + { + Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = v + f[cell_id]; }); + + REQUIRE(same_values(v + f, sum_values)); + REQUIRE(same_values(v + const_f, sum_values)); + } + { + Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + v; }); + + REQUIRE(same_values(f + v, sum_values)); + REQUIRE(same_values(const_f + v, sum_values)); + } + } + + SECTION("difference") + { + const TinyVector<VectorDimension> v{1, 2}; + { + Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = v - f[cell_id]; }); + + REQUIRE(same_values(v - f, difference_values)); + REQUIRE(same_values(v - const_f, difference_values)); + } + { + Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - v; }); + + REQUIRE(same_values(f - v, difference_values)); + REQUIRE(same_values(const_f - v, difference_values)); + } + } + + SECTION("product") + { + { + const double a = 2.3; + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + DiscreteFunctionP0<Dimension, double> a{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + a[cell_id] = 2 * x * x - 1; + }); + + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a[cell_id] * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + const TinyMatrix<VectorDimension> A{1, 2, 3, 4}; + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = A * f[cell_id]; }); + + REQUIRE(same_values(A * f, product_values)); + REQUIRE(same_values(A * const_f, product_values)); + } + + { + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyMatrix<VectorDimension>> M{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + M[cell_id] = TinyMatrix<2>{x, 2 * x, 1 - x, 2 - x * x}; + }); + + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = M[cell_id] * f[cell_id]; }); + + REQUIRE(same_values(M * f, product_values)); + REQUIRE(same_values(M * const_f, product_values)); + } + } + } + + SECTION("matrix functions") + { + constexpr std::uint64_t MatrixDimension = 2; + + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyMatrix<MatrixDimension> X{x, 2 - x, x * x, x * 3}; + f[cell_id] = 2 * X + TinyMatrix<2>{1, 2, 3, 4}; + }); - REQUIRE(same_values(f - g, difference_values)); - REQUIRE(same_values(const_f - g, difference_values)); - REQUIRE(same_values(f - const_g, difference_values)); - REQUIRE(same_values(const_f - const_g, difference_values)); + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; + + SECTION("sum") + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + { + Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = A + f[cell_id]; }); + + REQUIRE(same_values(A + f, sum_values)); + REQUIRE(same_values(A + const_f, sum_values)); + } + { + Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + A; }); + + REQUIRE(same_values(f + A, sum_values)); + REQUIRE(same_values(const_f + A, sum_values)); + } + } + + SECTION("difference") + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + { + Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = A - f[cell_id]; }); + + REQUIRE(same_values(A - f, difference_values)); + REQUIRE(same_values(A - const_f, difference_values)); + } + { + Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - A; }); + + REQUIRE(same_values(f - A, difference_values)); + REQUIRE(same_values(const_f - A, difference_values)); + } + } + + SECTION("product") + { + { + const double a = 2.3; + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + DiscreteFunctionP0<Dimension, double> a{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + a[cell_id] = 2 * x * x - 1; + }); + + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a[cell_id] * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = A * f[cell_id]; }); + + REQUIRE(same_values(A * f, product_values)); + REQUIRE(same_values(A * const_f, product_values)); + } + + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * A; }); + + REQUIRE(same_values(f * A, product_values)); + REQUIRE(same_values(const_f * A, product_values)); + } + } + } } } + } + } - SECTION("matrix functions") - { - constexpr std::uint64_t MatrixDimension = 2; - - DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const TinyMatrix<MatrixDimension> A{x, 2 - x, 2 * x, x * x - 3}; - f[cell_id] = 2 * A + TinyMatrix<2>{1, 2, 3, 4}; - }); + SECTION("2D") + { + constexpr size_t Dimension = 2; - DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> g{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const TinyMatrix<MatrixDimension> A{3 * x + 1, 2 + x, 1 - 2 * x, 2 * x * x}; - g[cell_id] = A; - }); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; - DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_g{g}; + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - SECTION("sum") + SECTION("inner operators") { - Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + SECTION("scalar functions") + { + DiscreteFunctionP0<Dimension, double> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + f[cell_id] = 2 * x + y + 1; + }); - REQUIRE(same_values(f + g, sum_values)); - REQUIRE(same_values(const_f + g, sum_values)); - REQUIRE(same_values(f + const_g, sum_values)); - REQUIRE(same_values(const_f + const_g, sum_values)); - } + DiscreteFunctionP0<Dimension, double> g{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + g[cell_id] = std::abs((x + 1) * (x - 2) + y * (1 + y)) + 1; + }); - SECTION("difference") - { - Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + DiscreteFunctionP0<Dimension, const double> const_f = f; + DiscreteFunctionP0<Dimension, const double> const_g{g}; + + SECTION("sum") + { + Array<double> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Array<double> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + + SECTION("product") + { + Array<double> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * g[cell_id]; }); + + REQUIRE(same_values(f * g, product_values)); + REQUIRE(same_values(const_f * g, product_values)); + REQUIRE(same_values(f * const_g, product_values)); + REQUIRE(same_values(const_f * const_g, product_values)); + } + + SECTION("ratio") + { + Array<double> ratio_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = f[cell_id] / g[cell_id]; }); + + REQUIRE(same_values(f / g, ratio_values)); + REQUIRE(same_values(const_f / g, ratio_values)); + REQUIRE(same_values(f / const_g, ratio_values)); + REQUIRE(same_values(const_f / const_g, ratio_values)); + } + } + + SECTION("vector functions") + { + constexpr std::uint64_t VectorDimension = 2; + + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyVector<VectorDimension> X{x, 2 - x}; + f[cell_id] = 2 * X + TinyVector<2>{1, 2}; + }); - REQUIRE(same_values(f - g, difference_values)); - REQUIRE(same_values(const_f - g, difference_values)); - REQUIRE(same_values(f - const_g, difference_values)); - REQUIRE(same_values(const_f - const_g, difference_values)); - } + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> g{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyVector<VectorDimension> X{3 * x + 1, 2 + x}; + g[cell_id] = X; + }); - SECTION("product") - { - Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * g[cell_id]; }); + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_g{g}; - REQUIRE(same_values(f * g, product_values)); - REQUIRE(same_values(const_f * g, product_values)); - REQUIRE(same_values(f * const_g, product_values)); - REQUIRE(same_values(const_f * const_g, product_values)); - } - } - } + SECTION("sum") + { + Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); - SECTION("external operators") - { - SECTION("scalar functions") - { - DiscreteFunctionP0<Dimension, double> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - f[cell_id] = std::abs(2 * x) + 1; - }); + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } - const double a = 3; + SECTION("difference") + { + Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); - DiscreteFunctionP0<Dimension, const double> const_f = f; + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + } - SECTION("sum") - { + SECTION("matrix functions") { - Array<double> sum_values{mesh->numberOfCells()}; + constexpr std::uint64_t MatrixDimension = 2; + + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = a + f[cell_id]; }); + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyMatrix<MatrixDimension> A{x, 2 - x, 2 * x, x * x - 3}; + f[cell_id] = 2 * A + TinyMatrix<2>{1, 2, 3, 4}; + }); - REQUIRE(same_values(a + f, sum_values)); - REQUIRE(same_values(a + const_f, sum_values)); - } - { - Array<double> sum_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> g{mesh}; parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + a; }); + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyMatrix<MatrixDimension> A{3 * x + 1, 2 + x, 1 - 2 * x, 2 * x * x}; + g[cell_id] = A; + }); - REQUIRE(same_values(f + a, sum_values)); - REQUIRE(same_values(const_f + a, sum_values)); + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_g{g}; + + SECTION("sum") + { + Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + + SECTION("product") + { + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * g[cell_id]; }); + + REQUIRE(same_values(f * g, product_values)); + REQUIRE(same_values(const_f * g, product_values)); + REQUIRE(same_values(f * const_g, product_values)); + REQUIRE(same_values(const_f * const_g, product_values)); + } } } - SECTION("difference") + SECTION("external operators") { + SECTION("scalar functions") { - Array<double> difference_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, double> f{mesh}; parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = a - f[cell_id]; }); - REQUIRE(same_values(a - f, difference_values)); - REQUIRE(same_values(a - const_f, difference_values)); - } - - { - Array<double> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - a; }); - REQUIRE(same_values(f - a, difference_values)); - REQUIRE(same_values(const_f - a, difference_values)); - } - } + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + f[cell_id] = std::abs(2 * x + y) + 1; + }); - SECTION("product") - { - { - Array<double> product_values{mesh->numberOfCells()}; + const double a = 3; + + DiscreteFunctionP0<Dimension, const double> const_f = f; + + SECTION("sum") + { + { + Array<double> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = a + f[cell_id]; }); + + REQUIRE(same_values(a + f, sum_values)); + REQUIRE(same_values(a + const_f, sum_values)); + } + { + Array<double> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + a; }); + + REQUIRE(same_values(f + a, sum_values)); + REQUIRE(same_values(const_f + a, sum_values)); + } + } + + SECTION("difference") + { + { + Array<double> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = a - f[cell_id]; }); + REQUIRE(same_values(a - f, difference_values)); + REQUIRE(same_values(a - const_f, difference_values)); + } + + { + Array<double> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - a; }); + REQUIRE(same_values(f - a, difference_values)); + REQUIRE(same_values(const_f - a, difference_values)); + } + } + + SECTION("product") + { + { + Array<double> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + { + Array<double> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * a; }); + + REQUIRE(same_values(f * a, product_values)); + REQUIRE(same_values(const_f * a, product_values)); + } + + { + Array<TinyVector<3>> product_values{mesh->numberOfCells()}; + const TinyVector<3> v{1, 2, 3}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * v; }); + + REQUIRE(same_values(f * v, product_values)); + REQUIRE(same_values(const_f * v, product_values)); + } + + { + Array<TinyVector<3>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyVector<3>> v{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + v[cell_id] = TinyVector<3>{x, 2 * x, 1 - x}; + }); + + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * v[cell_id]; }); + + REQUIRE(same_values(f * v, product_values)); + REQUIRE(same_values(const_f * v, product_values)); + } + + { + Array<TinyMatrix<2>> product_values{mesh->numberOfCells()}; + const TinyMatrix<2> A{1, 2, 3, 4}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * A; }); + + REQUIRE(same_values(f * A, product_values)); + REQUIRE(same_values(const_f * A, product_values)); + } + + { + Array<TinyMatrix<2>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyMatrix<2>> M{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + M[cell_id] = TinyMatrix<2>{x, 2 * x, 1 - x, 2 - x * x}; + }); + + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * M[cell_id]; }); + + REQUIRE(same_values(f * M, product_values)); + REQUIRE(same_values(const_f * M, product_values)); + } + } + + SECTION("ratio") + { + { + Array<double> ratio_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = a / f[cell_id]; }); + + REQUIRE(same_values(a / f, ratio_values)); + REQUIRE(same_values(a / const_f, ratio_values)); + } + { + Array<double> ratio_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = f[cell_id] / a; }); + + REQUIRE(same_values(f / a, ratio_values)); + REQUIRE(same_values(const_f / a, ratio_values)); + } + } + } + + SECTION("vector functions") + { + constexpr std::uint64_t VectorDimension = 2; + + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const TinyVector<VectorDimension> X{x + y, 2 - x * y}; + f[cell_id] = 2 * X + TinyVector<2>{1, 2}; + }); - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); - } - { - Array<double> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; + + SECTION("sum") + { + const TinyVector<VectorDimension> v{1, 2}; + { + Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = v + f[cell_id]; }); + + REQUIRE(same_values(v + f, sum_values)); + REQUIRE(same_values(v + const_f, sum_values)); + } + { + Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + v; }); + + REQUIRE(same_values(f + v, sum_values)); + REQUIRE(same_values(const_f + v, sum_values)); + } + } + + SECTION("difference") + { + const TinyVector<VectorDimension> v{1, 2}; + { + Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = v - f[cell_id]; }); + + REQUIRE(same_values(v - f, difference_values)); + REQUIRE(same_values(v - const_f, difference_values)); + } + { + Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - v; }); + + REQUIRE(same_values(f - v, difference_values)); + REQUIRE(same_values(const_f - v, difference_values)); + } + } + + SECTION("product") + { + { + const double a = 2.3; + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + DiscreteFunctionP0<Dimension, double> a{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + a[cell_id] = 2 * x * x - 1; + }); + + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a[cell_id] * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + const TinyMatrix<VectorDimension> A{1, 2, 3, 4}; + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = A * f[cell_id]; }); + + REQUIRE(same_values(A * f, product_values)); + REQUIRE(same_values(A * const_f, product_values)); + } + + { + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyMatrix<VectorDimension>> M{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + M[cell_id] = TinyMatrix<2>{x, 2 * x, 1 - x, 2 - x * x}; + }); + + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = M[cell_id] * f[cell_id]; }); + + REQUIRE(same_values(M * f, product_values)); + REQUIRE(same_values(M * const_f, product_values)); + } + } + } + + SECTION("matrix functions") + { + constexpr std::uint64_t MatrixDimension = 2; + + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * a; }); + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const TinyMatrix<MatrixDimension> X{x, 2 - y, x * y, y * 3}; + f[cell_id] = 2 * X + TinyMatrix<2>{1, 2, 3, 4}; + }); - REQUIRE(same_values(f * a, product_values)); - REQUIRE(same_values(const_f * a, product_values)); + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; + + SECTION("sum") + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + { + Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = A + f[cell_id]; }); + + REQUIRE(same_values(A + f, sum_values)); + REQUIRE(same_values(A + const_f, sum_values)); + } + { + Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + A; }); + + REQUIRE(same_values(f + A, sum_values)); + REQUIRE(same_values(const_f + A, sum_values)); + } + } + + SECTION("difference") + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + { + Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = A - f[cell_id]; }); + + REQUIRE(same_values(A - f, difference_values)); + REQUIRE(same_values(A - const_f, difference_values)); + } + { + Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - A; }); + + REQUIRE(same_values(f - A, difference_values)); + REQUIRE(same_values(const_f - A, difference_values)); + } + } + + SECTION("product") + { + { + const double a = 2.3; + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + DiscreteFunctionP0<Dimension, double> a{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + a[cell_id] = 2 * x * x - 1; + }); + + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a[cell_id] * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = A * f[cell_id]; }); + + REQUIRE(same_values(A * f, product_values)); + REQUIRE(same_values(A * const_f, product_values)); + } + + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * A; }); + + REQUIRE(same_values(f * A, product_values)); + REQUIRE(same_values(const_f * A, product_values)); + } + } } + } + } + } + } - { - Array<TinyVector<3>> product_values{mesh->numberOfCells()}; - const TinyVector<3> v{1, 2, 3}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * v; }); + SECTION("3D") + { + constexpr size_t Dimension = 3; - REQUIRE(same_values(f * v, product_values)); - REQUIRE(same_values(const_f * v, product_values)); - } + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); + + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + SECTION("inner operators") + { + SECTION("scalar functions") { - Array<TinyVector<3>> product_values{mesh->numberOfCells()}; - DiscreteFunctionP0<Dimension, TinyVector<3>> v{mesh}; + DiscreteFunctionP0<Dimension, double> f{mesh}; parallel_for( mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { const double x = xj[cell_id][0]; - v[cell_id] = TinyVector<3>{x, 2 * x, 1 - x}; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; + f[cell_id] = 2 * x + y - z; }); + DiscreteFunctionP0<Dimension, double> g{mesh}; parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * v[cell_id]; }); - - REQUIRE(same_values(f * v, product_values)); - REQUIRE(same_values(const_f * v, product_values)); - } + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; + g[cell_id] = std::abs((x + 1) * (x - 2) + y * (1 + y) + 2 * z) + 1; + }); - { - Array<TinyMatrix<2>> product_values{mesh->numberOfCells()}; - const TinyMatrix<2> A{1, 2, 3, 4}; + DiscreteFunctionP0<Dimension, const double> const_f = f; + DiscreteFunctionP0<Dimension, const double> const_g{g}; + + SECTION("sum") + { + Array<double> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Array<double> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + + SECTION("product") + { + Array<double> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * g[cell_id]; }); + + REQUIRE(same_values(f * g, product_values)); + REQUIRE(same_values(const_f * g, product_values)); + REQUIRE(same_values(f * const_g, product_values)); + REQUIRE(same_values(const_f * const_g, product_values)); + } + + SECTION("ratio") + { + Array<double> ratio_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = f[cell_id] / g[cell_id]; }); + + REQUIRE(same_values(f / g, ratio_values)); + REQUIRE(same_values(const_f / g, ratio_values)); + REQUIRE(same_values(f / const_g, ratio_values)); + REQUIRE(same_values(const_f / const_g, ratio_values)); + } + } + + SECTION("vector functions") + { + constexpr std::uint64_t VectorDimension = 2; + + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * A; }); - - REQUIRE(same_values(f * A, product_values)); - REQUIRE(same_values(const_f * A, product_values)); - } + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyVector<VectorDimension> X{x, 2 - x}; + f[cell_id] = 2 * X + TinyVector<2>{1, 2}; + }); - { - Array<TinyMatrix<2>> product_values{mesh->numberOfCells()}; - DiscreteFunctionP0<Dimension, TinyMatrix<2>> M{mesh}; + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> g{mesh}; parallel_for( mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { const double x = xj[cell_id][0]; - M[cell_id] = TinyMatrix<2>{x, 2 * x, 1 - x, 2 - x * x}; + const TinyVector<VectorDimension> X{3 * x + 1, 2 + x}; + g[cell_id] = X; }); - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * M[cell_id]; }); + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_g{g}; - REQUIRE(same_values(f * M, product_values)); - REQUIRE(same_values(const_f * M, product_values)); - } - } + SECTION("sum") + { + Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); - SECTION("ratio") - { - { - Array<double> ratio_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = a / f[cell_id]; }); + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } - REQUIRE(same_values(a / f, ratio_values)); - REQUIRE(same_values(a / const_f, ratio_values)); - } - { - Array<double> ratio_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = f[cell_id] / a; }); + SECTION("difference") + { + Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); - REQUIRE(same_values(f / a, ratio_values)); - REQUIRE(same_values(const_f / a, ratio_values)); + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } } - } - } - - SECTION("vector functions") - { - constexpr std::uint64_t VectorDimension = 2; - - DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const TinyVector<VectorDimension> X{x, 2 - x}; - f[cell_id] = 2 * X + TinyVector<2>{1, 2}; - }); - - DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; - - SECTION("sum") - { - const TinyVector<VectorDimension> v{1, 2}; - { - Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = v + f[cell_id]; }); - REQUIRE(same_values(v + f, sum_values)); - REQUIRE(same_values(v + const_f, sum_values)); - } + SECTION("matrix functions") { - Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + v; }); + constexpr std::uint64_t MatrixDimension = 2; - REQUIRE(same_values(f + v, sum_values)); - REQUIRE(same_values(const_f + v, sum_values)); - } - } - - SECTION("difference") - { - const TinyVector<VectorDimension> v{1, 2}; - { - Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = v - f[cell_id]; }); + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyMatrix<MatrixDimension> A{x, 2 - x, 2 * x, x * x - 3}; + f[cell_id] = 2 * A + TinyMatrix<2>{1, 2, 3, 4}; + }); - REQUIRE(same_values(v - f, difference_values)); - REQUIRE(same_values(v - const_f, difference_values)); - } - { - Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> g{mesh}; parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - v; }); + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyMatrix<MatrixDimension> A{3 * x + 1, 2 + x, 1 - 2 * x, 2 * x * x}; + g[cell_id] = A; + }); - REQUIRE(same_values(f - v, difference_values)); - REQUIRE(same_values(const_f - v, difference_values)); + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_g{g}; + + SECTION("sum") + { + Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + + SECTION("product") + { + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * g[cell_id]; }); + + REQUIRE(same_values(f * g, product_values)); + REQUIRE(same_values(const_f * g, product_values)); + REQUIRE(same_values(f * const_g, product_values)); + REQUIRE(same_values(const_f * const_g, product_values)); + } } } - SECTION("product") + SECTION("external operators") { + SECTION("scalar functions") { - const double a = 2.3; - Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); - - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); - } - - { - DiscreteFunctionP0<Dimension, double> a{mesh}; + DiscreteFunctionP0<Dimension, double> f{mesh}; parallel_for( mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { const double x = xj[cell_id][0]; - a[cell_id] = 2 * x * x - 1; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; + f[cell_id] = std::abs(2 * x + y * z) + 1; }); - Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a[cell_id] * f[cell_id]; }); - - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); - } - - { - const TinyMatrix<VectorDimension> A{1, 2, 3, 4}; - Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = A * f[cell_id]; }); - - REQUIRE(same_values(A * f, product_values)); - REQUIRE(same_values(A * const_f, product_values)); - } - - { - Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; - DiscreteFunctionP0<Dimension, TinyMatrix<VectorDimension>> M{mesh}; + const double a = 3; + + DiscreteFunctionP0<Dimension, const double> const_f = f; + + SECTION("sum") + { + { + Array<double> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = a + f[cell_id]; }); + + REQUIRE(same_values(a + f, sum_values)); + REQUIRE(same_values(a + const_f, sum_values)); + } + { + Array<double> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + a; }); + + REQUIRE(same_values(f + a, sum_values)); + REQUIRE(same_values(const_f + a, sum_values)); + } + } + + SECTION("difference") + { + { + Array<double> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = a - f[cell_id]; }); + REQUIRE(same_values(a - f, difference_values)); + REQUIRE(same_values(a - const_f, difference_values)); + } + + { + Array<double> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - a; }); + REQUIRE(same_values(f - a, difference_values)); + REQUIRE(same_values(const_f - a, difference_values)); + } + } + + SECTION("product") + { + { + Array<double> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + { + Array<double> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * a; }); + + REQUIRE(same_values(f * a, product_values)); + REQUIRE(same_values(const_f * a, product_values)); + } + + { + Array<TinyVector<3>> product_values{mesh->numberOfCells()}; + const TinyVector<3> v{1, 2, 3}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * v; }); + + REQUIRE(same_values(f * v, product_values)); + REQUIRE(same_values(const_f * v, product_values)); + } + + { + Array<TinyVector<3>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyVector<3>> v{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + v[cell_id] = TinyVector<3>{x, 2 * x, 1 - x}; + }); + + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * v[cell_id]; }); + + REQUIRE(same_values(f * v, product_values)); + REQUIRE(same_values(const_f * v, product_values)); + } + + { + Array<TinyMatrix<2>> product_values{mesh->numberOfCells()}; + const TinyMatrix<2> A{1, 2, 3, 4}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * A; }); + + REQUIRE(same_values(f * A, product_values)); + REQUIRE(same_values(const_f * A, product_values)); + } + + { + Array<TinyMatrix<2>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyMatrix<2>> M{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + M[cell_id] = TinyMatrix<2>{x, 2 * x, 1 - x, 2 - x * x}; + }); + + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * M[cell_id]; }); + + REQUIRE(same_values(f * M, product_values)); + REQUIRE(same_values(const_f * M, product_values)); + } + } + + SECTION("ratio") + { + { + Array<double> ratio_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = a / f[cell_id]; }); + + REQUIRE(same_values(a / f, ratio_values)); + REQUIRE(same_values(a / const_f, ratio_values)); + } + { + Array<double> ratio_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = f[cell_id] / a; }); + + REQUIRE(same_values(f / a, ratio_values)); + REQUIRE(same_values(const_f / a, ratio_values)); + } + } + } + + SECTION("vector functions") + { + constexpr std::uint64_t VectorDimension = 2; + + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; parallel_for( mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { const double x = xj[cell_id][0]; - M[cell_id] = TinyMatrix<2>{x, 2 * x, 1 - x, 2 - x * x}; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; + const TinyVector<VectorDimension> X{x + y - z, 2 - x * y}; + f[cell_id] = 2 * X + TinyVector<2>{1, 2}; }); + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; + + SECTION("sum") + { + const TinyVector<VectorDimension> v{1, 2}; + { + Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = v + f[cell_id]; }); + + REQUIRE(same_values(v + f, sum_values)); + REQUIRE(same_values(v + const_f, sum_values)); + } + { + Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + v; }); + + REQUIRE(same_values(f + v, sum_values)); + REQUIRE(same_values(const_f + v, sum_values)); + } + } + + SECTION("difference") + { + const TinyVector<VectorDimension> v{1, 2}; + { + Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = v - f[cell_id]; }); + + REQUIRE(same_values(v - f, difference_values)); + REQUIRE(same_values(v - const_f, difference_values)); + } + { + Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - v; }); + + REQUIRE(same_values(f - v, difference_values)); + REQUIRE(same_values(const_f - v, difference_values)); + } + } + + SECTION("product") + { + { + const double a = 2.3; + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + DiscreteFunctionP0<Dimension, double> a{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + a[cell_id] = 2 * x * x - 1; + }); + + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a[cell_id] * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + const TinyMatrix<VectorDimension> A{1, 2, 3, 4}; + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = A * f[cell_id]; }); + + REQUIRE(same_values(A * f, product_values)); + REQUIRE(same_values(A * const_f, product_values)); + } + + { + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyMatrix<VectorDimension>> M{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + M[cell_id] = TinyMatrix<2>{x, 2 * x, 1 - x, 2 - x * x}; + }); + + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = M[cell_id] * f[cell_id]; }); + + REQUIRE(same_values(M * f, product_values)); + REQUIRE(same_values(M * const_f, product_values)); + } + } + } + + SECTION("matrix functions") + { + constexpr std::uint64_t MatrixDimension = 2; + + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = M[cell_id] * f[cell_id]; }); + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; + const TinyMatrix<MatrixDimension> X{x, 2 - y, x * y, y * z + 3}; + f[cell_id] = 2 * X + TinyMatrix<2>{1, 2, 3, 4}; + }); - REQUIRE(same_values(M * f, product_values)); - REQUIRE(same_values(M * const_f, product_values)); + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; + + SECTION("sum") + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + { + Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = A + f[cell_id]; }); + + REQUIRE(same_values(A + f, sum_values)); + REQUIRE(same_values(A + const_f, sum_values)); + } + { + Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + A; }); + + REQUIRE(same_values(f + A, sum_values)); + REQUIRE(same_values(const_f + A, sum_values)); + } + } + + SECTION("difference") + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + { + Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = A - f[cell_id]; }); + + REQUIRE(same_values(A - f, difference_values)); + REQUIRE(same_values(A - const_f, difference_values)); + } + { + Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - A; }); + + REQUIRE(same_values(f - A, difference_values)); + REQUIRE(same_values(const_f - A, difference_values)); + } + } + + SECTION("product") + { + { + const double a = 2.3; + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + DiscreteFunctionP0<Dimension, double> a{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + a[cell_id] = 2 * x * x - 1; + }); + + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a[cell_id] * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = A * f[cell_id]; }); + + REQUIRE(same_values(A * f, product_values)); + REQUIRE(same_values(A * const_f, product_values)); + } + + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * A; }); + + REQUIRE(same_values(f * A, product_values)); + REQUIRE(same_values(const_f * A, product_values)); + } + } } } } + } + } + } - SECTION("matrix functions") - { - constexpr std::uint64_t MatrixDimension = 2; + SECTION("math functions") + { +#define CHECK_STD_MATH_FUNCTION(data_expression, FCT) \ + { \ + DiscreteFunctionP0 data = data_expression; \ + DiscreteFunctionP0 result = FCT(data); \ + bool is_same = true; \ + parallel_for(data.cellValues().numberOfItems(), [&](const CellId cell_id) { \ + if (result[cell_id] != std::FCT(data[cell_id])) { \ + is_same = false; \ + } \ + }); \ + REQUIRE(is_same); \ + } - DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const TinyMatrix<MatrixDimension> X{x, 2 - x, x * x, x * 3}; - f[cell_id] = 2 * X + TinyMatrix<2>{1, 2, 3, 4}; - }); +#define CHECK_STD_BINARY_MATH_FUNCTION(lhs_expression, rhs_expression, FCT) \ + { \ + DiscreteFunctionP0 lhs = lhs_expression; \ + DiscreteFunctionP0 rhs = rhs_expression; \ + DiscreteFunctionP0 result = FCT(lhs, rhs); \ + using namespace std; \ + bool is_same = true; \ + parallel_for(lhs.cellValues().numberOfItems(), [&](const CellId cell_id) { \ + if (result[cell_id] != FCT(lhs[cell_id], rhs[cell_id])) { \ + is_same = false; \ + } \ + }); \ + REQUIRE(is_same); \ + } - DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; +#define CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(lhs, rhs_expression, FCT) \ + { \ + DiscreteFunctionP0 rhs = rhs_expression; \ + DiscreteFunctionP0 result = FCT(lhs, rhs); \ + bool is_same = true; \ + using namespace std; \ + parallel_for(rhs.cellValues().numberOfItems(), [&](const CellId cell_id) { \ + if (result[cell_id] != FCT(lhs, rhs[cell_id])) { \ + is_same = false; \ + } \ + }); \ + REQUIRE(is_same); \ + } - SECTION("sum") - { - const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; - { - Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = A + f[cell_id]; }); +#define CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(lhs_expression, rhs, FCT) \ + { \ + DiscreteFunctionP0 lhs = lhs_expression; \ + DiscreteFunctionP0 result = FCT(lhs, rhs); \ + bool is_same = true; \ + using namespace std; \ + parallel_for(lhs.cellValues().numberOfItems(), [&](const CellId cell_id) { \ + if (result[cell_id] != FCT(lhs[cell_id], rhs)) { \ + is_same = false; \ + } \ + }); \ + REQUIRE(is_same); \ + } - REQUIRE(same_values(A + f, sum_values)); - REQUIRE(same_values(A + const_f, sum_values)); - } - { - Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + A; }); + SECTION("1D") + { + constexpr size_t Dimension = 1; + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - REQUIRE(same_values(f + A, sum_values)); - REQUIRE(same_values(const_f + A, sum_values)); - } - } + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - SECTION("difference") - { - const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; - { - Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = A - f[cell_id]; }); + DiscreteFunctionP0<Dimension, double> positive_function{mesh}; - REQUIRE(same_values(A - f, difference_values)); - REQUIRE(same_values(A - const_f, difference_values)); - } - { - Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - A; }); + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(const CellId cell_id) { positive_function[cell_id] = 1 + std::abs(xj[cell_id][0]); }); - REQUIRE(same_values(f - A, difference_values)); - REQUIRE(same_values(const_f - A, difference_values)); + const double min_value = min(positive_function); + SECTION("min") + { + double local_min = std::numeric_limits<double>::max(); + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + local_min = std::min(local_min, positive_function[cell_id]); } + REQUIRE(min_value == parallel::allReduceMin(local_min)); } - SECTION("product") + const double max_value = max(positive_function); + SECTION("max") { - { - const double a = 2.3; - Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); - - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); - } - - { - DiscreteFunctionP0<Dimension, double> a{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - a[cell_id] = 2 * x * x - 1; - }); - - Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a[cell_id] * f[cell_id]; }); - - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); + double local_max = -std::numeric_limits<double>::max(); + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + local_max = std::max(local_max, positive_function[cell_id]); } + REQUIRE(max_value == parallel::allReduceMax(local_max)); + } - { - const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; - Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = A * f[cell_id]; }); + REQUIRE(min_value < max_value); - REQUIRE(same_values(A * f, product_values)); - REQUIRE(same_values(A * const_f, product_values)); - } + DiscreteFunctionP0 unsigned_function = positive_function - 0.5 * (min_value + max_value); - { - const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; - Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * A; }); + SECTION("sqrt") + { + CHECK_STD_MATH_FUNCTION(positive_function, sqrt); + } - REQUIRE(same_values(f * A, product_values)); - REQUIRE(same_values(const_f * A, product_values)); - } + SECTION("abs") + { + CHECK_STD_MATH_FUNCTION(positive_function, abs); } - } - } - } - SECTION("2D") - { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian2DMesh(); + SECTION("cos") + { + CHECK_STD_MATH_FUNCTION(positive_function, cos); + } - constexpr size_t Dimension = 2; + SECTION("sin") + { + CHECK_STD_MATH_FUNCTION(positive_function, sin); + } - auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + SECTION("tan") + { + CHECK_STD_MATH_FUNCTION(positive_function, tan); + } - SECTION("inner operators") - { - SECTION("scalar functions") - { - DiscreteFunctionP0<Dimension, double> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - f[cell_id] = 2 * x + y + 1; - }); + DiscreteFunctionP0<Dimension, double> unit_function{mesh}; - DiscreteFunctionP0<Dimension, double> g{mesh}; parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - g[cell_id] = std::abs((x + 1) * (x - 2) + y * (1 + y)) + 1; + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + unit_function[cell_id] = + (2 * (positive_function[cell_id] - min_value) / (max_value - min_value) - 1) * 0.95; }); - DiscreteFunctionP0<Dimension, const double> const_f = f; - DiscreteFunctionP0<Dimension, const double> const_g{g}; + SECTION("acos") + { + CHECK_STD_MATH_FUNCTION(unit_function, acos); + } - SECTION("sum") + SECTION("asin") { - Array<double> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + CHECK_STD_MATH_FUNCTION(unit_function, asin); + } - REQUIRE(same_values(f + g, sum_values)); - REQUIRE(same_values(const_f + g, sum_values)); - REQUIRE(same_values(f + const_g, sum_values)); - REQUIRE(same_values(const_f + const_g, sum_values)); + SECTION("atan") + { + CHECK_STD_MATH_FUNCTION(unit_function, atan); } - SECTION("difference") + SECTION("cosh") { - Array<double> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + CHECK_STD_MATH_FUNCTION(positive_function, cosh); + } - REQUIRE(same_values(f - g, difference_values)); - REQUIRE(same_values(const_f - g, difference_values)); - REQUIRE(same_values(f - const_g, difference_values)); - REQUIRE(same_values(const_f - const_g, difference_values)); + SECTION("sinh") + { + CHECK_STD_MATH_FUNCTION(positive_function, sinh); } - SECTION("product") + SECTION("tanh") { - Array<double> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * g[cell_id]; }); + CHECK_STD_MATH_FUNCTION(positive_function, tanh); + } - REQUIRE(same_values(f * g, product_values)); - REQUIRE(same_values(const_f * g, product_values)); - REQUIRE(same_values(f * const_g, product_values)); - REQUIRE(same_values(const_f * const_g, product_values)); + SECTION("acosh") + { + CHECK_STD_MATH_FUNCTION(positive_function, acosh); } - SECTION("ratio") + SECTION("asinh") { - Array<double> ratio_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = f[cell_id] / g[cell_id]; }); + CHECK_STD_MATH_FUNCTION(positive_function, asinh); + } - REQUIRE(same_values(f / g, ratio_values)); - REQUIRE(same_values(const_f / g, ratio_values)); - REQUIRE(same_values(f / const_g, ratio_values)); - REQUIRE(same_values(const_f / const_g, ratio_values)); + SECTION("atanh") + { + CHECK_STD_MATH_FUNCTION(unit_function, atanh); } - } - SECTION("vector functions") - { - constexpr std::uint64_t VectorDimension = 2; + SECTION("exp") + { + CHECK_STD_MATH_FUNCTION(positive_function, exp); + } - DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const TinyVector<VectorDimension> X{x, 2 - x}; - f[cell_id] = 2 * X + TinyVector<2>{1, 2}; - }); + SECTION("log") + { + CHECK_STD_MATH_FUNCTION(positive_function, log); + } - DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> g{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const TinyVector<VectorDimension> X{3 * x + 1, 2 + x}; - g[cell_id] = X; - }); + SECTION("max(uh,hv)") + { + CHECK_STD_BINARY_MATH_FUNCTION(cos(positive_function), sin(positive_function), max); + } - DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; - DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_g{g}; + SECTION("max(0.2,vh)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.2, sin(positive_function), max); + } - SECTION("sum") + SECTION("max(uh,0.2)") { - Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(cos(positive_function), 0.2, max); + } - REQUIRE(same_values(f + g, sum_values)); - REQUIRE(same_values(const_f + g, sum_values)); - REQUIRE(same_values(f + const_g, sum_values)); - REQUIRE(same_values(const_f + const_g, sum_values)); + SECTION("atan2(uh,hv)") + { + CHECK_STD_BINARY_MATH_FUNCTION(positive_function, 2 + positive_function, atan2); } - SECTION("difference") + SECTION("atan2(0.5,uh)") { - Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.5, 2 + positive_function, atan2); + } - REQUIRE(same_values(f - g, difference_values)); - REQUIRE(same_values(const_f - g, difference_values)); - REQUIRE(same_values(f - const_g, difference_values)); - REQUIRE(same_values(const_f - const_g, difference_values)); + SECTION("atan2(uh,0.2)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(2 + cos(positive_function), 0.2, atan2); } - } - SECTION("matrix functions") - { - constexpr std::uint64_t MatrixDimension = 2; + SECTION("pow(uh,hv)") + { + CHECK_STD_BINARY_MATH_FUNCTION(positive_function, 0.5 * positive_function, pow); + } - DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const TinyMatrix<MatrixDimension> A{x, 2 - x, 2 * x, x * x - 3}; - f[cell_id] = 2 * A + TinyMatrix<2>{1, 2, 3, 4}; - }); - - DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> g{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const TinyMatrix<MatrixDimension> A{3 * x + 1, 2 + x, 1 - 2 * x, 2 * x * x}; - g[cell_id] = A; - }); + SECTION("pow(uh,0.5)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.5, positive_function, pow); + } - DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; - DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_g{g}; + SECTION("pow(uh,0.2)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(positive_function, 1.3, pow); + } - SECTION("sum") + SECTION("min(uh,hv)") { - Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + CHECK_STD_BINARY_MATH_FUNCTION(sin(positive_function), cos(positive_function), min); + } - REQUIRE(same_values(f + g, sum_values)); - REQUIRE(same_values(const_f + g, sum_values)); - REQUIRE(same_values(f + const_g, sum_values)); - REQUIRE(same_values(const_f + const_g, sum_values)); + SECTION("min(uh,0.5)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.5, cos(positive_function), min); } - SECTION("difference") + SECTION("min(uh,0.2)") { - Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(sin(positive_function), 0.5, min); + } - REQUIRE(same_values(f - g, difference_values)); - REQUIRE(same_values(const_f - g, difference_values)); - REQUIRE(same_values(f - const_g, difference_values)); - REQUIRE(same_values(const_f - const_g, difference_values)); + SECTION("max(uh,hv)") + { + CHECK_STD_BINARY_MATH_FUNCTION(sin(positive_function), cos(positive_function), max); } - SECTION("product") + SECTION("min(uh,0.5)") { - Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * g[cell_id]; }); + CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.1, cos(positive_function), max); + } - REQUIRE(same_values(f * g, product_values)); - REQUIRE(same_values(const_f * g, product_values)); - REQUIRE(same_values(f * const_g, product_values)); - REQUIRE(same_values(const_f * const_g, product_values)); + SECTION("min(uh,0.2)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(sin(positive_function), 0.1, max); } - } - } - SECTION("external operators") - { - SECTION("scalar functions") - { - DiscreteFunctionP0<Dimension, double> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - f[cell_id] = std::abs(2 * x + y) + 1; - }); + SECTION("dot(uh,hv)") + { + DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; + }); - const double a = 3; + DiscreteFunctionP0<Dimension, TinyVector<2>> vh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + vh[cell_id] = TinyVector<2>{2.3 * x, 1 - x}; + }); - DiscreteFunctionP0<Dimension, const double> const_f = f; + CHECK_STD_BINARY_MATH_FUNCTION(uh, vh, dot); + } - SECTION("sum") + SECTION("dot(uh,v)") { - { - Array<double> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = a + f[cell_id]; }); + DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; + }); - REQUIRE(same_values(a + f, sum_values)); - REQUIRE(same_values(a + const_f, sum_values)); - } - { - Array<double> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + a; }); + const TinyVector<2> v{1, 2}; - REQUIRE(same_values(f + a, sum_values)); - REQUIRE(same_values(const_f + a, sum_values)); - } + CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(uh, v, dot); } - SECTION("difference") + SECTION("dot(u,hv)") { - { - Array<double> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = a - f[cell_id]; }); - REQUIRE(same_values(a - f, difference_values)); - REQUIRE(same_values(a - const_f, difference_values)); - } + const TinyVector<2> u{3, -2}; - { - Array<double> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - a; }); - REQUIRE(same_values(f - a, difference_values)); - REQUIRE(same_values(const_f - a, difference_values)); - } + DiscreteFunctionP0<Dimension, TinyVector<2>> vh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + vh[cell_id] = TinyVector<2>{2.3 * x, 1 - x}; + }); + + CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(u, vh, dot); } - SECTION("product") + SECTION("scalar sum") { - { - Array<double> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + const CellValue<const double> cell_value = positive_function.cellValues(); - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); - } - { - Array<double> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * a; }); + REQUIRE(sum(cell_value) == sum(positive_function)); + } - REQUIRE(same_values(f * a, product_values)); - REQUIRE(same_values(const_f * a, product_values)); - } + SECTION("vector sum") + { + DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; + }); + const CellValue<const TinyVector<2>> cell_value = uh.cellValues(); - { - Array<TinyVector<3>> product_values{mesh->numberOfCells()}; - const TinyVector<3> v{1, 2, 3}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * v; }); + REQUIRE(sum(cell_value) == sum(uh)); + } - REQUIRE(same_values(f * v, product_values)); - REQUIRE(same_values(const_f * v, product_values)); - } + SECTION("matrix sum") + { + DiscreteFunctionP0<Dimension, TinyMatrix<2>> uh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + uh[cell_id] = TinyMatrix<2>{x + 1, 2 * x - 3, 2 * x, 3 * x - 1}; + }); + const CellValue<const TinyMatrix<2>> cell_value = uh.cellValues(); - { - Array<TinyVector<3>> product_values{mesh->numberOfCells()}; - DiscreteFunctionP0<Dimension, TinyVector<3>> v{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - v[cell_id] = TinyVector<3>{x, 2 * x, 1 - x}; - }); + REQUIRE(sum(cell_value) == sum(uh)); + } - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * v[cell_id]; }); + SECTION("integrate scalar") + { + const CellValue<const double> cell_volume = MeshDataManager::instance().getMeshData(*mesh).Vj(); - REQUIRE(same_values(f * v, product_values)); - REQUIRE(same_values(const_f * v, product_values)); - } + CellValue<double> cell_value{mesh->connectivity()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + cell_value[cell_id] = cell_volume[cell_id] * positive_function[cell_id]; + }); - { - Array<TinyMatrix<2>> product_values{mesh->numberOfCells()}; - const TinyMatrix<2> A{1, 2, 3, 4}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * A; }); + REQUIRE(integrate(positive_function) == Catch::Approx(sum(cell_value))); + } - REQUIRE(same_values(f * A, product_values)); - REQUIRE(same_values(const_f * A, product_values)); - } + SECTION("integrate vector") + { + DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; + }); - { - Array<TinyMatrix<2>> product_values{mesh->numberOfCells()}; - DiscreteFunctionP0<Dimension, TinyMatrix<2>> M{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - M[cell_id] = TinyMatrix<2>{x, 2 * x, 1 - x, 2 - x * x}; - }); + const CellValue<const double> cell_volume = MeshDataManager::instance().getMeshData(*mesh).Vj(); - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * M[cell_id]; }); + CellValue<TinyVector<2>> cell_value{mesh->connectivity()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(const CellId cell_id) { cell_value[cell_id] = cell_volume[cell_id] * uh[cell_id]; }); - REQUIRE(same_values(f * M, product_values)); - REQUIRE(same_values(const_f * M, product_values)); - } + REQUIRE(integrate(uh)[0] == Catch::Approx(sum(cell_value)[0])); + REQUIRE(integrate(uh)[1] == Catch::Approx(sum(cell_value)[1])); } - SECTION("ratio") + SECTION("integrate matrix") { - { - Array<double> ratio_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = a / f[cell_id]; }); + DiscreteFunctionP0<Dimension, TinyMatrix<2>> uh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + uh[cell_id] = TinyMatrix<2>{x + 1, 2 * x - 3, 2 * x, 1 - x}; + }); - REQUIRE(same_values(a / f, ratio_values)); - REQUIRE(same_values(a / const_f, ratio_values)); - } - { - Array<double> ratio_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = f[cell_id] / a; }); + const CellValue<const double> cell_volume = MeshDataManager::instance().getMeshData(*mesh).Vj(); - REQUIRE(same_values(f / a, ratio_values)); - REQUIRE(same_values(const_f / a, ratio_values)); - } + CellValue<TinyMatrix<2>> cell_value{mesh->connectivity()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(const CellId cell_id) { cell_value[cell_id] = cell_volume[cell_id] * uh[cell_id]; }); + + REQUIRE(integrate(uh)(0, 0) == Catch::Approx(sum(cell_value)(0, 0))); + REQUIRE(integrate(uh)(0, 1) == Catch::Approx(sum(cell_value)(0, 1))); + REQUIRE(integrate(uh)(1, 0) == Catch::Approx(sum(cell_value)(1, 0))); + REQUIRE(integrate(uh)(1, 1) == Catch::Approx(sum(cell_value)(1, 1))); } } + } + } - SECTION("vector functions") - { - constexpr std::uint64_t VectorDimension = 2; - - DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - const TinyVector<VectorDimension> X{x + y, 2 - x * y}; - f[cell_id] = 2 * X + TinyVector<2>{1, 2}; - }); + SECTION("2D") + { + constexpr size_t Dimension = 2; - DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - SECTION("sum") - { - const TinyVector<VectorDimension> v{1, 2}; - { - Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = v + f[cell_id]; }); + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - REQUIRE(same_values(v + f, sum_values)); - REQUIRE(same_values(v + const_f, sum_values)); - } - { - Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + v; }); + DiscreteFunctionP0<Dimension, double> positive_function{mesh}; - REQUIRE(same_values(f + v, sum_values)); - REQUIRE(same_values(const_f + v, sum_values)); - } - } + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(const CellId cell_id) { positive_function[cell_id] = 1 + std::abs(xj[cell_id][0]); }); - SECTION("difference") + const double min_value = min(positive_function); + SECTION("min") { - const TinyVector<VectorDimension> v{1, 2}; - { - Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = v - f[cell_id]; }); - - REQUIRE(same_values(v - f, difference_values)); - REQUIRE(same_values(v - const_f, difference_values)); - } - { - Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - v; }); - - REQUIRE(same_values(f - v, difference_values)); - REQUIRE(same_values(const_f - v, difference_values)); + double local_min = std::numeric_limits<double>::max(); + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + local_min = std::min(local_min, positive_function[cell_id]); } + REQUIRE(min_value == parallel::allReduceMin(local_min)); } - SECTION("product") + const double max_value = max(positive_function); + SECTION("max") { - { - const double a = 2.3; - Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); - - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); + double local_max = -std::numeric_limits<double>::max(); + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + local_max = std::max(local_max, positive_function[cell_id]); } + REQUIRE(max_value == parallel::allReduceMax(local_max)); + } - { - DiscreteFunctionP0<Dimension, double> a{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - a[cell_id] = 2 * x * x - 1; - }); - - Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a[cell_id] * f[cell_id]; }); + REQUIRE(min_value < max_value); - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); - } + DiscreteFunctionP0 unsigned_function = positive_function - 0.5 * (min_value + max_value); - { - const TinyMatrix<VectorDimension> A{1, 2, 3, 4}; - Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = A * f[cell_id]; }); + SECTION("sqrt") + { + CHECK_STD_MATH_FUNCTION(positive_function, sqrt); + } - REQUIRE(same_values(A * f, product_values)); - REQUIRE(same_values(A * const_f, product_values)); - } + SECTION("abs") + { + CHECK_STD_MATH_FUNCTION(positive_function, abs); + } - { - Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; - DiscreteFunctionP0<Dimension, TinyMatrix<VectorDimension>> M{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - M[cell_id] = TinyMatrix<2>{x, 2 * x, 1 - x, 2 - x * x}; - }); + SECTION("cos") + { + CHECK_STD_MATH_FUNCTION(positive_function, cos); + } - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = M[cell_id] * f[cell_id]; }); + SECTION("sin") + { + CHECK_STD_MATH_FUNCTION(positive_function, sin); + } - REQUIRE(same_values(M * f, product_values)); - REQUIRE(same_values(M * const_f, product_values)); - } + SECTION("tan") + { + CHECK_STD_MATH_FUNCTION(positive_function, tan); } - } - SECTION("matrix functions") - { - constexpr std::uint64_t MatrixDimension = 2; + DiscreteFunctionP0<Dimension, double> unit_function{mesh}; - DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - const TinyMatrix<MatrixDimension> X{x, 2 - y, x * y, y * 3}; - f[cell_id] = 2 * X + TinyMatrix<2>{1, 2, 3, 4}; + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + unit_function[cell_id] = + (2 * (positive_function[cell_id] - min_value) / (max_value - min_value) - 1) * 0.95; }); - DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; + SECTION("acos") + { + CHECK_STD_MATH_FUNCTION(unit_function, acos); + } - SECTION("sum") + SECTION("asin") { - const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; - { - Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = A + f[cell_id]; }); + CHECK_STD_MATH_FUNCTION(unit_function, asin); + } - REQUIRE(same_values(A + f, sum_values)); - REQUIRE(same_values(A + const_f, sum_values)); - } - { - Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + A; }); + SECTION("atan") + { + CHECK_STD_MATH_FUNCTION(unit_function, atan); + } - REQUIRE(same_values(f + A, sum_values)); - REQUIRE(same_values(const_f + A, sum_values)); - } + SECTION("cosh") + { + CHECK_STD_MATH_FUNCTION(positive_function, cosh); } - SECTION("difference") + SECTION("sinh") { - const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; - { - Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = A - f[cell_id]; }); + CHECK_STD_MATH_FUNCTION(positive_function, sinh); + } - REQUIRE(same_values(A - f, difference_values)); - REQUIRE(same_values(A - const_f, difference_values)); - } - { - Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - A; }); + SECTION("tanh") + { + CHECK_STD_MATH_FUNCTION(positive_function, tanh); + } - REQUIRE(same_values(f - A, difference_values)); - REQUIRE(same_values(const_f - A, difference_values)); - } + SECTION("acosh") + { + CHECK_STD_MATH_FUNCTION(positive_function, acosh); } - SECTION("product") + SECTION("asinh") { - { - const double a = 2.3; - Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + CHECK_STD_MATH_FUNCTION(positive_function, asinh); + } - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); - } + SECTION("atanh") + { + CHECK_STD_MATH_FUNCTION(unit_function, atanh); + } - { - DiscreteFunctionP0<Dimension, double> a{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - a[cell_id] = 2 * x * x - 1; - }); + SECTION("exp") + { + CHECK_STD_MATH_FUNCTION(positive_function, exp); + } - Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a[cell_id] * f[cell_id]; }); + SECTION("log") + { + CHECK_STD_MATH_FUNCTION(positive_function, log); + } - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); - } + SECTION("max(uh,hv)") + { + CHECK_STD_BINARY_MATH_FUNCTION(cos(positive_function), sin(positive_function), max); + } - { - const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; - Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = A * f[cell_id]; }); + SECTION("max(0.2,vh)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.2, sin(positive_function), max); + } - REQUIRE(same_values(A * f, product_values)); - REQUIRE(same_values(A * const_f, product_values)); - } + SECTION("max(uh,0.2)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(cos(positive_function), 0.2, max); + } - { - const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; - Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * A; }); + SECTION("atan2(uh,hv)") + { + CHECK_STD_BINARY_MATH_FUNCTION(positive_function, 2 + positive_function, atan2); + } - REQUIRE(same_values(f * A, product_values)); - REQUIRE(same_values(const_f * A, product_values)); - } + SECTION("atan2(0.5,uh)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.5, 2 + positive_function, atan2); } - } - } - } - SECTION("3D") - { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian3DMesh(); + SECTION("atan2(uh,0.2)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(2 + cos(positive_function), 0.2, atan2); + } - constexpr size_t Dimension = 3; + SECTION("pow(uh,hv)") + { + CHECK_STD_BINARY_MATH_FUNCTION(positive_function, 0.5 * positive_function, pow); + } - auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + SECTION("pow(uh,0.5)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.5, positive_function, pow); + } - SECTION("inner operators") - { - SECTION("scalar functions") - { - DiscreteFunctionP0<Dimension, double> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - const double z = xj[cell_id][2]; - f[cell_id] = 2 * x + y - z; - }); + SECTION("pow(uh,0.2)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(positive_function, 1.3, pow); + } - DiscreteFunctionP0<Dimension, double> g{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - const double z = xj[cell_id][2]; - g[cell_id] = std::abs((x + 1) * (x - 2) + y * (1 + y) + 2 * z) + 1; - }); + SECTION("min(uh,hv)") + { + CHECK_STD_BINARY_MATH_FUNCTION(sin(positive_function), cos(positive_function), min); + } - DiscreteFunctionP0<Dimension, const double> const_f = f; - DiscreteFunctionP0<Dimension, const double> const_g{g}; + SECTION("min(uh,0.5)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.5, cos(positive_function), min); + } - SECTION("sum") + SECTION("min(uh,0.2)") { - Array<double> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(sin(positive_function), 0.5, min); + } - REQUIRE(same_values(f + g, sum_values)); - REQUIRE(same_values(const_f + g, sum_values)); - REQUIRE(same_values(f + const_g, sum_values)); - REQUIRE(same_values(const_f + const_g, sum_values)); + SECTION("max(uh,hv)") + { + CHECK_STD_BINARY_MATH_FUNCTION(sin(positive_function), cos(positive_function), max); } - SECTION("difference") + SECTION("min(uh,0.5)") { - Array<double> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.1, cos(positive_function), max); + } - REQUIRE(same_values(f - g, difference_values)); - REQUIRE(same_values(const_f - g, difference_values)); - REQUIRE(same_values(f - const_g, difference_values)); - REQUIRE(same_values(const_f - const_g, difference_values)); + SECTION("min(uh,0.2)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(sin(positive_function), 0.1, max); } - SECTION("product") + SECTION("dot(uh,hv)") { - Array<double> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * g[cell_id]; }); + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; + }); + + DiscreteFunctionP0<Dimension, TinyVector<2>> vh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + vh[cell_id] = TinyVector<2>{2.3 * x, 1 - x}; + }); - REQUIRE(same_values(f * g, product_values)); - REQUIRE(same_values(const_f * g, product_values)); - REQUIRE(same_values(f * const_g, product_values)); - REQUIRE(same_values(const_f * const_g, product_values)); + CHECK_STD_BINARY_MATH_FUNCTION(uh, vh, dot); } - SECTION("ratio") + SECTION("dot(uh,v)") { - Array<double> ratio_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = f[cell_id] / g[cell_id]; }); + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; + }); - REQUIRE(same_values(f / g, ratio_values)); - REQUIRE(same_values(const_f / g, ratio_values)); - REQUIRE(same_values(f / const_g, ratio_values)); - REQUIRE(same_values(const_f / const_g, ratio_values)); - } - } + const TinyVector<2> v{1, 2}; - SECTION("vector functions") - { - constexpr std::uint64_t VectorDimension = 2; + CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(uh, v, dot); + } - DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const TinyVector<VectorDimension> X{x, 2 - x}; - f[cell_id] = 2 * X + TinyVector<2>{1, 2}; - }); + SECTION("dot(u,hv)") + { + const TinyVector<2> u{3, -2}; - DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> g{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const TinyVector<VectorDimension> X{3 * x + 1, 2 + x}; - g[cell_id] = X; - }); + DiscreteFunctionP0<Dimension, TinyVector<2>> vh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + vh[cell_id] = TinyVector<2>{2.3 * x, 1 - x}; + }); - DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; - DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_g{g}; + CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(u, vh, dot); + } - SECTION("sum") + SECTION("scalar sum") { - Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + const CellValue<const double> cell_value = positive_function.cellValues(); - REQUIRE(same_values(f + g, sum_values)); - REQUIRE(same_values(const_f + g, sum_values)); - REQUIRE(same_values(f + const_g, sum_values)); - REQUIRE(same_values(const_f + const_g, sum_values)); + REQUIRE(sum(cell_value) == sum(positive_function)); } - SECTION("difference") + SECTION("vector sum") { - Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; + }); + const CellValue<const TinyVector<2>> cell_value = uh.cellValues(); - REQUIRE(same_values(f - g, difference_values)); - REQUIRE(same_values(const_f - g, difference_values)); - REQUIRE(same_values(f - const_g, difference_values)); - REQUIRE(same_values(const_f - const_g, difference_values)); + REQUIRE(sum(cell_value) == sum(uh)); } - } - - SECTION("matrix functions") - { - constexpr std::uint64_t MatrixDimension = 2; - DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const TinyMatrix<MatrixDimension> A{x, 2 - x, 2 * x, x * x - 3}; - f[cell_id] = 2 * A + TinyMatrix<2>{1, 2, 3, 4}; - }); - - DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> g{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const TinyMatrix<MatrixDimension> A{3 * x + 1, 2 + x, 1 - 2 * x, 2 * x * x}; - g[cell_id] = A; - }); + SECTION("matrix sum") + { + DiscreteFunctionP0<Dimension, TinyMatrix<2>> uh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + uh[cell_id] = TinyMatrix<2>{x + 1, 2 * x - 3, 2 * x, 3 * x - 1}; + }); + const CellValue<const TinyMatrix<2>> cell_value = uh.cellValues(); - DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; - DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_g{g}; + REQUIRE(sum(cell_value) == sum(uh)); + } - SECTION("sum") + SECTION("integrate scalar") { - Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + const CellValue<const double> cell_volume = MeshDataManager::instance().getMeshData(*mesh).Vj(); + + CellValue<double> cell_value{mesh->connectivity()}; parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + cell_value[cell_id] = cell_volume[cell_id] * positive_function[cell_id]; + }); - REQUIRE(same_values(f + g, sum_values)); - REQUIRE(same_values(const_f + g, sum_values)); - REQUIRE(same_values(f + const_g, sum_values)); - REQUIRE(same_values(const_f + const_g, sum_values)); + REQUIRE(integrate(positive_function) == Catch::Approx(sum(cell_value))); } - SECTION("difference") + SECTION("integrate vector") { - Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; + }); + + const CellValue<const double> cell_volume = MeshDataManager::instance().getMeshData(*mesh).Vj(); + + CellValue<TinyVector<2>> cell_value{mesh->connectivity()}; parallel_for( mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + PUGS_LAMBDA(const CellId cell_id) { cell_value[cell_id] = cell_volume[cell_id] * uh[cell_id]; }); - REQUIRE(same_values(f - g, difference_values)); - REQUIRE(same_values(const_f - g, difference_values)); - REQUIRE(same_values(f - const_g, difference_values)); - REQUIRE(same_values(const_f - const_g, difference_values)); + REQUIRE(integrate(uh)[0] == Catch::Approx(sum(cell_value)[0])); + REQUIRE(integrate(uh)[1] == Catch::Approx(sum(cell_value)[1])); } - SECTION("product") + SECTION("integrate matrix") { - Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyMatrix<2>> uh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + uh[cell_id] = TinyMatrix<2>{x + 1, 2 * x - 3, 2 * x, 1 - x}; + }); + + const CellValue<const double> cell_volume = MeshDataManager::instance().getMeshData(*mesh).Vj(); + + CellValue<TinyMatrix<2>> cell_value{mesh->connectivity()}; parallel_for( mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * g[cell_id]; }); + PUGS_LAMBDA(const CellId cell_id) { cell_value[cell_id] = cell_volume[cell_id] * uh[cell_id]; }); - REQUIRE(same_values(f * g, product_values)); - REQUIRE(same_values(const_f * g, product_values)); - REQUIRE(same_values(f * const_g, product_values)); - REQUIRE(same_values(const_f * const_g, product_values)); + REQUIRE(integrate(uh)(0, 0) == Catch::Approx(sum(cell_value)(0, 0))); + REQUIRE(integrate(uh)(0, 1) == Catch::Approx(sum(cell_value)(0, 1))); + REQUIRE(integrate(uh)(1, 0) == Catch::Approx(sum(cell_value)(1, 0))); + REQUIRE(integrate(uh)(1, 1) == Catch::Approx(sum(cell_value)(1, 1))); } } } + } - SECTION("external operators") - { - SECTION("scalar functions") - { - DiscreteFunctionP0<Dimension, double> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - const double z = xj[cell_id][2]; - f[cell_id] = std::abs(2 * x + y * z) + 1; - }); + SECTION("3D") + { + constexpr size_t Dimension = 3; - const double a = 3; + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - DiscreteFunctionP0<Dimension, const double> const_f = f; + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - SECTION("sum") - { - { - Array<double> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = a + f[cell_id]; }); + DiscreteFunctionP0<Dimension, double> positive_function{mesh}; - REQUIRE(same_values(a + f, sum_values)); - REQUIRE(same_values(a + const_f, sum_values)); - } - { - Array<double> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + a; }); + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(const CellId cell_id) { positive_function[cell_id] = 1 + std::abs(xj[cell_id][0]); }); - REQUIRE(same_values(f + a, sum_values)); - REQUIRE(same_values(const_f + a, sum_values)); + const double min_value = min(positive_function); + SECTION("min") + { + double local_min = std::numeric_limits<double>::max(); + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + local_min = std::min(local_min, positive_function[cell_id]); } + REQUIRE(min_value == parallel::allReduceMin(local_min)); } - SECTION("difference") + const double max_value = max(positive_function); + SECTION("max") { - { - Array<double> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = a - f[cell_id]; }); - REQUIRE(same_values(a - f, difference_values)); - REQUIRE(same_values(a - const_f, difference_values)); + double local_max = -std::numeric_limits<double>::max(); + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + local_max = std::max(local_max, positive_function[cell_id]); } + REQUIRE(max_value == parallel::allReduceMax(local_max)); + } - { - Array<double> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - a; }); - REQUIRE(same_values(f - a, difference_values)); - REQUIRE(same_values(const_f - a, difference_values)); - } + REQUIRE(min_value < max_value); + + DiscreteFunctionP0 unsigned_function = positive_function - 0.5 * (min_value + max_value); + + SECTION("sqrt") + { + CHECK_STD_MATH_FUNCTION(positive_function, sqrt); } - SECTION("product") + SECTION("abs") { - { - Array<double> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + CHECK_STD_MATH_FUNCTION(positive_function, abs); + } - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); - } - { - Array<double> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * a; }); + SECTION("cos") + { + CHECK_STD_MATH_FUNCTION(positive_function, cos); + } - REQUIRE(same_values(f * a, product_values)); - REQUIRE(same_values(const_f * a, product_values)); - } + SECTION("sin") + { + CHECK_STD_MATH_FUNCTION(positive_function, sin); + } - { - Array<TinyVector<3>> product_values{mesh->numberOfCells()}; - const TinyVector<3> v{1, 2, 3}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * v; }); + SECTION("tan") + { + CHECK_STD_MATH_FUNCTION(positive_function, tan); + } - REQUIRE(same_values(f * v, product_values)); - REQUIRE(same_values(const_f * v, product_values)); - } + DiscreteFunctionP0<Dimension, double> unit_function{mesh}; - { - Array<TinyVector<3>> product_values{mesh->numberOfCells()}; - DiscreteFunctionP0<Dimension, TinyVector<3>> v{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - v[cell_id] = TinyVector<3>{x, 2 * x, 1 - x}; - }); + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + unit_function[cell_id] = + (2 * (positive_function[cell_id] - min_value) / (max_value - min_value) - 1) * 0.95; + }); - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * v[cell_id]; }); + SECTION("acos") + { + CHECK_STD_MATH_FUNCTION(unit_function, acos); + } - REQUIRE(same_values(f * v, product_values)); - REQUIRE(same_values(const_f * v, product_values)); - } + SECTION("asin") + { + CHECK_STD_MATH_FUNCTION(unit_function, asin); + } - { - Array<TinyMatrix<2>> product_values{mesh->numberOfCells()}; - const TinyMatrix<2> A{1, 2, 3, 4}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * A; }); + SECTION("atan") + { + CHECK_STD_MATH_FUNCTION(unit_function, atan); + } - REQUIRE(same_values(f * A, product_values)); - REQUIRE(same_values(const_f * A, product_values)); - } + SECTION("cosh") + { + CHECK_STD_MATH_FUNCTION(positive_function, cosh); + } - { - Array<TinyMatrix<2>> product_values{mesh->numberOfCells()}; - DiscreteFunctionP0<Dimension, TinyMatrix<2>> M{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - M[cell_id] = TinyMatrix<2>{x, 2 * x, 1 - x, 2 - x * x}; - }); + SECTION("sinh") + { + CHECK_STD_MATH_FUNCTION(positive_function, sinh); + } - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * M[cell_id]; }); + SECTION("tanh") + { + CHECK_STD_MATH_FUNCTION(positive_function, tanh); + } - REQUIRE(same_values(f * M, product_values)); - REQUIRE(same_values(const_f * M, product_values)); - } + SECTION("acosh") + { + CHECK_STD_MATH_FUNCTION(positive_function, acosh); } - SECTION("ratio") + SECTION("asinh") { - { - Array<double> ratio_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = a / f[cell_id]; }); + CHECK_STD_MATH_FUNCTION(positive_function, asinh); + } - REQUIRE(same_values(a / f, ratio_values)); - REQUIRE(same_values(a / const_f, ratio_values)); - } - { - Array<double> ratio_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = f[cell_id] / a; }); + SECTION("atanh") + { + CHECK_STD_MATH_FUNCTION(unit_function, atanh); + } - REQUIRE(same_values(f / a, ratio_values)); - REQUIRE(same_values(const_f / a, ratio_values)); - } + SECTION("exp") + { + CHECK_STD_MATH_FUNCTION(positive_function, exp); } - } - SECTION("vector functions") - { - constexpr std::uint64_t VectorDimension = 2; + SECTION("log") + { + CHECK_STD_MATH_FUNCTION(positive_function, log); + } - DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - const double z = xj[cell_id][2]; - const TinyVector<VectorDimension> X{x + y - z, 2 - x * y}; - f[cell_id] = 2 * X + TinyVector<2>{1, 2}; - }); + SECTION("max(uh,hv)") + { + CHECK_STD_BINARY_MATH_FUNCTION(cos(positive_function), sin(positive_function), max); + } - DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; + SECTION("max(0.2,vh)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.2, sin(positive_function), max); + } - SECTION("sum") + SECTION("max(uh,0.2)") { - const TinyVector<VectorDimension> v{1, 2}; - { - Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = v + f[cell_id]; }); + CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(cos(positive_function), 0.2, max); + } - REQUIRE(same_values(v + f, sum_values)); - REQUIRE(same_values(v + const_f, sum_values)); - } - { - Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + v; }); + SECTION("atan2(uh,hv)") + { + CHECK_STD_BINARY_MATH_FUNCTION(positive_function, 2 + positive_function, atan2); + } - REQUIRE(same_values(f + v, sum_values)); - REQUIRE(same_values(const_f + v, sum_values)); - } + SECTION("atan2(0.5,uh)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.5, 2 + positive_function, atan2); } - SECTION("difference") + SECTION("atan2(uh,0.2)") { - const TinyVector<VectorDimension> v{1, 2}; - { - Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = v - f[cell_id]; }); + CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(2 + cos(positive_function), 0.2, atan2); + } - REQUIRE(same_values(v - f, difference_values)); - REQUIRE(same_values(v - const_f, difference_values)); - } - { - Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - v; }); + SECTION("pow(uh,hv)") + { + CHECK_STD_BINARY_MATH_FUNCTION(positive_function, 0.5 * positive_function, pow); + } - REQUIRE(same_values(f - v, difference_values)); - REQUIRE(same_values(const_f - v, difference_values)); - } + SECTION("pow(uh,0.5)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.5, positive_function, pow); } - SECTION("product") + SECTION("pow(uh,0.2)") { - { - const double a = 2.3; - Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(positive_function, 1.3, pow); + } - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); - } + SECTION("min(uh,hv)") + { + CHECK_STD_BINARY_MATH_FUNCTION(sin(positive_function), cos(positive_function), min); + } - { - DiscreteFunctionP0<Dimension, double> a{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - a[cell_id] = 2 * x * x - 1; - }); + SECTION("min(uh,0.5)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.5, cos(positive_function), min); + } - Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a[cell_id] * f[cell_id]; }); + SECTION("min(uh,0.2)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(sin(positive_function), 0.5, min); + } - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); - } + SECTION("max(uh,hv)") + { + CHECK_STD_BINARY_MATH_FUNCTION(sin(positive_function), cos(positive_function), max); + } - { - const TinyMatrix<VectorDimension> A{1, 2, 3, 4}; - Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = A * f[cell_id]; }); + SECTION("min(uh,0.5)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.1, cos(positive_function), max); + } - REQUIRE(same_values(A * f, product_values)); - REQUIRE(same_values(A * const_f, product_values)); - } + SECTION("min(uh,0.2)") + { + CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(sin(positive_function), 0.1, max); + } - { - Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; - DiscreteFunctionP0<Dimension, TinyMatrix<VectorDimension>> M{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - M[cell_id] = TinyMatrix<2>{x, 2 * x, 1 - x, 2 - x * x}; - }); + SECTION("dot(uh,hv)") + { + DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; + }); - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = M[cell_id] * f[cell_id]; }); + DiscreteFunctionP0<Dimension, TinyVector<2>> vh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + vh[cell_id] = TinyVector<2>{2.3 * x, 1 - x}; + }); - REQUIRE(same_values(M * f, product_values)); - REQUIRE(same_values(M * const_f, product_values)); - } + CHECK_STD_BINARY_MATH_FUNCTION(uh, vh, dot); } - } - SECTION("matrix functions") - { - constexpr std::uint64_t MatrixDimension = 2; + SECTION("dot(uh,v)") + { + DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; + }); - DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - const double z = xj[cell_id][2]; - const TinyMatrix<MatrixDimension> X{x, 2 - y, x * y, y * z + 3}; - f[cell_id] = 2 * X + TinyMatrix<2>{1, 2, 3, 4}; - }); + const TinyVector<2> v{1, 2}; - DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; + CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(uh, v, dot); + } - SECTION("sum") + SECTION("dot(u,hv)") { - const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; - { - Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = A + f[cell_id]; }); + const TinyVector<2> u{3, -2}; - REQUIRE(same_values(A + f, sum_values)); - REQUIRE(same_values(A + const_f, sum_values)); - } - { - Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + A; }); + DiscreteFunctionP0<Dimension, TinyVector<2>> vh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + vh[cell_id] = TinyVector<2>{2.3 * x, 1 - x}; + }); - REQUIRE(same_values(f + A, sum_values)); - REQUIRE(same_values(const_f + A, sum_values)); - } + CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(u, vh, dot); } - SECTION("difference") + SECTION("scalar sum") { - const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; - { - Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = A - f[cell_id]; }); + const CellValue<const double> cell_value = positive_function.cellValues(); - REQUIRE(same_values(A - f, difference_values)); - REQUIRE(same_values(A - const_f, difference_values)); - } - { - Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - A; }); + REQUIRE(sum(cell_value) == sum(positive_function)); + } - REQUIRE(same_values(f - A, difference_values)); - REQUIRE(same_values(const_f - A, difference_values)); - } + SECTION("vector sum") + { + DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; + }); + const CellValue<const TinyVector<2>> cell_value = uh.cellValues(); + + REQUIRE(sum(cell_value) == sum(uh)); } - SECTION("product") + SECTION("matrix sum") { - { - const double a = 2.3; - Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + DiscreteFunctionP0<Dimension, TinyMatrix<2>> uh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + uh[cell_id] = TinyMatrix<2>{x + 1, 2 * x - 3, 2 * x, 3 * x - 1}; + }); + const CellValue<const TinyMatrix<2>> cell_value = uh.cellValues(); - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); - } + REQUIRE(sum(cell_value) == sum(uh)); + } - { - DiscreteFunctionP0<Dimension, double> a{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - a[cell_id] = 2 * x * x - 1; - }); + SECTION("integrate scalar") + { + const CellValue<const double> cell_volume = MeshDataManager::instance().getMeshData(*mesh).Vj(); - Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a[cell_id] * f[cell_id]; }); + CellValue<double> cell_value{mesh->connectivity()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + cell_value[cell_id] = cell_volume[cell_id] * positive_function[cell_id]; + }); - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); - } + REQUIRE(integrate(positive_function) == Catch::Approx(sum(cell_value))); + } - { - const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; - Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = A * f[cell_id]; }); + SECTION("integrate vector") + { + DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; + }); - REQUIRE(same_values(A * f, product_values)); - REQUIRE(same_values(A * const_f, product_values)); - } + const CellValue<const double> cell_volume = MeshDataManager::instance().getMeshData(*mesh).Vj(); - { - const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; - Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * A; }); + CellValue<TinyVector<2>> cell_value{mesh->connectivity()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(const CellId cell_id) { cell_value[cell_id] = cell_volume[cell_id] * uh[cell_id]; }); - REQUIRE(same_values(f * A, product_values)); - REQUIRE(same_values(const_f * A, product_values)); - } + REQUIRE(integrate(uh)[0] == Catch::Approx(sum(cell_value)[0])); + REQUIRE(integrate(uh)[1] == Catch::Approx(sum(cell_value)[1])); + } + + SECTION("integrate matrix") + { + DiscreteFunctionP0<Dimension, TinyMatrix<2>> uh{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double x = xj[cell_id][0]; + uh[cell_id] = TinyMatrix<2>{x + 1, 2 * x - 3, 2 * x, 1 - x}; + }); + + const CellValue<const double> cell_volume = MeshDataManager::instance().getMeshData(*mesh).Vj(); + + CellValue<TinyMatrix<2>> cell_value{mesh->connectivity()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(const CellId cell_id) { cell_value[cell_id] = cell_volume[cell_id] * uh[cell_id]; }); + + REQUIRE(integrate(uh)(0, 0) == Catch::Approx(sum(cell_value)(0, 0))); + REQUIRE(integrate(uh)(0, 1) == Catch::Approx(sum(cell_value)(0, 1))); + REQUIRE(integrate(uh)(1, 0) == Catch::Approx(sum(cell_value)(1, 0))); + REQUIRE(integrate(uh)(1, 1) == Catch::Approx(sum(cell_value)(1, 1))); } } } } } - SECTION("math functions") +#ifndef NDEBUG + SECTION("error") { -#define CHECK_STD_MATH_FUNCTION(data_expression, FCT) \ - { \ - DiscreteFunctionP0 data = data_expression; \ - DiscreteFunctionP0 result = FCT(data); \ - bool is_same = true; \ - parallel_for(data.cellValues().numberOfItems(), [&](const CellId cell_id) { \ - if (result[cell_id] != std::FCT(data[cell_id])) { \ - is_same = false; \ - } \ - }); \ - REQUIRE(is_same); \ - } + SECTION("different meshes") + { + SECTION("1D") + { + constexpr size_t Dimension = 1; -#define CHECK_STD_BINARY_MATH_FUNCTION(lhs_expression, rhs_expression, FCT) \ - { \ - DiscreteFunctionP0 lhs = lhs_expression; \ - DiscreteFunctionP0 rhs = rhs_expression; \ - DiscreteFunctionP0 result = FCT(lhs, rhs); \ - using namespace std; \ - bool is_same = true; \ - parallel_for(lhs.cellValues().numberOfItems(), [&](const CellId cell_id) { \ - if (result[cell_id] != FCT(lhs[cell_id], rhs[cell_id])) { \ - is_same = false; \ - } \ - }); \ - REQUIRE(is_same); \ - } - -#define CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(lhs, rhs_expression, FCT) \ - { \ - DiscreteFunctionP0 rhs = rhs_expression; \ - DiscreteFunctionP0 result = FCT(lhs, rhs); \ - bool is_same = true; \ - using namespace std; \ - parallel_for(rhs.cellValues().numberOfItems(), [&](const CellId cell_id) { \ - if (result[cell_id] != FCT(lhs, rhs[cell_id])) { \ - is_same = false; \ - } \ - }); \ - REQUIRE(is_same); \ - } - -#define CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(lhs_expression, rhs, FCT) \ - { \ - DiscreteFunctionP0 lhs = lhs_expression; \ - DiscreteFunctionP0 result = FCT(lhs, rhs); \ - bool is_same = true; \ - using namespace std; \ - parallel_for(lhs.cellValues().numberOfItems(), [&](const CellId cell_id) { \ - if (result[cell_id] != FCT(lhs[cell_id], rhs)) { \ - is_same = false; \ - } \ - }); \ - REQUIRE(is_same); \ - } - - SECTION("1D") - { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian1DMesh(); - - constexpr size_t Dimension = 1; - - auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - DiscreteFunctionP0<Dimension, double> positive_function{mesh}; - - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(const CellId cell_id) { positive_function[cell_id] = 1 + std::abs(xj[cell_id][0]); }); - - const double min_value = min(positive_function); - SECTION("min") - { - double local_min = std::numeric_limits<double>::max(); - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - local_min = std::min(local_min, positive_function[cell_id]); - } - REQUIRE(min_value == parallel::allReduceMin(local_min)); - } - - const double max_value = max(positive_function); - SECTION("max") - { - double local_max = -std::numeric_limits<double>::max(); - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - local_max = std::max(local_max, positive_function[cell_id]); - } - REQUIRE(max_value == parallel::allReduceMax(local_max)); - } - - REQUIRE(min_value < max_value); - - DiscreteFunctionP0 unsigned_function = positive_function - 0.5 * (min_value + max_value); - - SECTION("sqrt") - { - CHECK_STD_MATH_FUNCTION(positive_function, sqrt); - } - - SECTION("abs") - { - CHECK_STD_MATH_FUNCTION(positive_function, abs); - } - - SECTION("cos") - { - CHECK_STD_MATH_FUNCTION(positive_function, cos); - } - - SECTION("sin") - { - CHECK_STD_MATH_FUNCTION(positive_function, sin); - } - - SECTION("tan") - { - CHECK_STD_MATH_FUNCTION(positive_function, tan); - } - - DiscreteFunctionP0<Dimension, double> unit_function{mesh}; - - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - unit_function[cell_id] = (2 * (positive_function[cell_id] - min_value) / (max_value - min_value) - 1) * 0.95; - }); - - SECTION("acos") - { - CHECK_STD_MATH_FUNCTION(unit_function, acos); - } - - SECTION("asin") - { - CHECK_STD_MATH_FUNCTION(unit_function, asin); - } - - SECTION("atan") - { - CHECK_STD_MATH_FUNCTION(unit_function, atan); - } - - SECTION("cosh") - { - CHECK_STD_MATH_FUNCTION(positive_function, cosh); - } - - SECTION("sinh") - { - CHECK_STD_MATH_FUNCTION(positive_function, sinh); - } - - SECTION("tanh") - { - CHECK_STD_MATH_FUNCTION(positive_function, tanh); - } - - SECTION("acosh") - { - CHECK_STD_MATH_FUNCTION(positive_function, acosh); - } - - SECTION("asinh") - { - CHECK_STD_MATH_FUNCTION(positive_function, asinh); - } - - SECTION("atanh") - { - CHECK_STD_MATH_FUNCTION(unit_function, atanh); - } - - SECTION("exp") - { - CHECK_STD_MATH_FUNCTION(positive_function, exp); - } - - SECTION("log") - { - CHECK_STD_MATH_FUNCTION(positive_function, log); - } - - SECTION("max(uh,hv)") - { - CHECK_STD_BINARY_MATH_FUNCTION(cos(positive_function), sin(positive_function), max); - } - - SECTION("max(0.2,vh)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.2, sin(positive_function), max); - } - - SECTION("max(uh,0.2)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(cos(positive_function), 0.2, max); - } - - SECTION("atan2(uh,hv)") - { - CHECK_STD_BINARY_MATH_FUNCTION(positive_function, 2 + positive_function, atan2); - } - - SECTION("atan2(0.5,uh)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.5, 2 + positive_function, atan2); - } - - SECTION("atan2(uh,0.2)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(2 + cos(positive_function), 0.2, atan2); - } - - SECTION("pow(uh,hv)") - { - CHECK_STD_BINARY_MATH_FUNCTION(positive_function, 0.5 * positive_function, pow); - } - - SECTION("pow(uh,0.5)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.5, positive_function, pow); - } - - SECTION("pow(uh,0.2)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(positive_function, 1.3, pow); - } - - SECTION("min(uh,hv)") - { - CHECK_STD_BINARY_MATH_FUNCTION(sin(positive_function), cos(positive_function), min); - } - - SECTION("min(uh,0.5)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.5, cos(positive_function), min); - } - - SECTION("min(uh,0.2)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(sin(positive_function), 0.5, min); - } - - SECTION("max(uh,hv)") - { - CHECK_STD_BINARY_MATH_FUNCTION(sin(positive_function), cos(positive_function), max); - } - - SECTION("min(uh,0.5)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.1, cos(positive_function), max); - } - - SECTION("min(uh,0.2)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(sin(positive_function), 0.1, max); - } - - SECTION("dot(uh,hv)") - { - DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; - }); - - DiscreteFunctionP0<Dimension, TinyVector<2>> vh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - vh[cell_id] = TinyVector<2>{2.3 * x, 1 - x}; - }); - - CHECK_STD_BINARY_MATH_FUNCTION(uh, vh, dot); - } - - SECTION("dot(uh,v)") - { - DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; - }); - - const TinyVector<2> v{1, 2}; - - CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(uh, v, dot); - } - - SECTION("dot(u,hv)") - { - const TinyVector<2> u{3, -2}; - - DiscreteFunctionP0<Dimension, TinyVector<2>> vh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - vh[cell_id] = TinyVector<2>{2.3 * x, 1 - x}; - }); - - CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(u, vh, dot); - } - - SECTION("scalar sum") - { - const CellValue<const double> cell_value = positive_function.cellValues(); - - REQUIRE(sum(cell_value) == sum(positive_function)); - } - - SECTION("vector sum") - { - DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; - }); - const CellValue<const TinyVector<2>> cell_value = uh.cellValues(); - - REQUIRE(sum(cell_value) == sum(uh)); - } - - SECTION("matrix sum") - { - DiscreteFunctionP0<Dimension, TinyMatrix<2>> uh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - uh[cell_id] = TinyMatrix<2>{x + 1, 2 * x - 3, 2 * x, 3 * x - 1}; - }); - const CellValue<const TinyMatrix<2>> cell_value = uh.cellValues(); - - REQUIRE(sum(cell_value) == sum(uh)); - } - - SECTION("integrate scalar") - { - const CellValue<const double> cell_volume = MeshDataManager::instance().getMeshData(*mesh).Vj(); - - CellValue<double> cell_value{mesh->connectivity()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - cell_value[cell_id] = cell_volume[cell_id] * positive_function[cell_id]; - }); - - REQUIRE(integrate(positive_function) == Catch::Approx(sum(cell_value))); - } - - SECTION("integrate vector") - { - DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; - }); - - const CellValue<const double> cell_volume = MeshDataManager::instance().getMeshData(*mesh).Vj(); - - CellValue<TinyVector<2>> cell_value{mesh->connectivity()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(const CellId cell_id) { cell_value[cell_id] = cell_volume[cell_id] * uh[cell_id]; }); - - REQUIRE(integrate(uh)[0] == Catch::Approx(sum(cell_value)[0])); - REQUIRE(integrate(uh)[1] == Catch::Approx(sum(cell_value)[1])); - } - - SECTION("integrate matrix") - { - DiscreteFunctionP0<Dimension, TinyMatrix<2>> uh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - uh[cell_id] = TinyMatrix<2>{x + 1, 2 * x - 3, 2 * x, 1 - x}; - }); - - const CellValue<const double> cell_volume = MeshDataManager::instance().getMeshData(*mesh).Vj(); - - CellValue<TinyMatrix<2>> cell_value{mesh->connectivity()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(const CellId cell_id) { cell_value[cell_id] = cell_volume[cell_id] * uh[cell_id]; }); - - REQUIRE(integrate(uh)(0, 0) == Catch::Approx(sum(cell_value)(0, 0))); - REQUIRE(integrate(uh)(0, 1) == Catch::Approx(sum(cell_value)(0, 1))); - REQUIRE(integrate(uh)(1, 0) == Catch::Approx(sum(cell_value)(1, 0))); - REQUIRE(integrate(uh)(1, 1) == Catch::Approx(sum(cell_value)(1, 1))); - } - } - - SECTION("2D") - { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian2DMesh(); - - constexpr size_t Dimension = 2; - - auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - DiscreteFunctionP0<Dimension, double> positive_function{mesh}; - - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(const CellId cell_id) { positive_function[cell_id] = 1 + std::abs(xj[cell_id][0]); }); - - const double min_value = min(positive_function); - SECTION("min") - { - double local_min = std::numeric_limits<double>::max(); - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - local_min = std::min(local_min, positive_function[cell_id]); - } - REQUIRE(min_value == parallel::allReduceMin(local_min)); - } - - const double max_value = max(positive_function); - SECTION("max") - { - double local_max = -std::numeric_limits<double>::max(); - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - local_max = std::max(local_max, positive_function[cell_id]); - } - REQUIRE(max_value == parallel::allReduceMax(local_max)); - } - - REQUIRE(min_value < max_value); - - DiscreteFunctionP0 unsigned_function = positive_function - 0.5 * (min_value + max_value); - - SECTION("sqrt") - { - CHECK_STD_MATH_FUNCTION(positive_function, sqrt); - } - - SECTION("abs") - { - CHECK_STD_MATH_FUNCTION(positive_function, abs); - } - - SECTION("cos") - { - CHECK_STD_MATH_FUNCTION(positive_function, cos); - } - - SECTION("sin") - { - CHECK_STD_MATH_FUNCTION(positive_function, sin); - } - - SECTION("tan") - { - CHECK_STD_MATH_FUNCTION(positive_function, tan); - } - - DiscreteFunctionP0<Dimension, double> unit_function{mesh}; - - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - unit_function[cell_id] = (2 * (positive_function[cell_id] - min_value) / (max_value - min_value) - 1) * 0.95; - }); - - SECTION("acos") - { - CHECK_STD_MATH_FUNCTION(unit_function, acos); - } - - SECTION("asin") - { - CHECK_STD_MATH_FUNCTION(unit_function, asin); - } - - SECTION("atan") - { - CHECK_STD_MATH_FUNCTION(unit_function, atan); - } - - SECTION("cosh") - { - CHECK_STD_MATH_FUNCTION(positive_function, cosh); - } - - SECTION("sinh") - { - CHECK_STD_MATH_FUNCTION(positive_function, sinh); - } - - SECTION("tanh") - { - CHECK_STD_MATH_FUNCTION(positive_function, tanh); - } - - SECTION("acosh") - { - CHECK_STD_MATH_FUNCTION(positive_function, acosh); - } - - SECTION("asinh") - { - CHECK_STD_MATH_FUNCTION(positive_function, asinh); - } - - SECTION("atanh") - { - CHECK_STD_MATH_FUNCTION(unit_function, atanh); - } - - SECTION("exp") - { - CHECK_STD_MATH_FUNCTION(positive_function, exp); - } - - SECTION("log") - { - CHECK_STD_MATH_FUNCTION(positive_function, log); - } + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - SECTION("max(uh,hv)") - { - CHECK_STD_BINARY_MATH_FUNCTION(cos(positive_function), sin(positive_function), max); - } - - SECTION("max(0.2,vh)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.2, sin(positive_function), max); - } - - SECTION("max(uh,0.2)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(cos(positive_function), 0.2, max); - } - - SECTION("atan2(uh,hv)") - { - CHECK_STD_BINARY_MATH_FUNCTION(positive_function, 2 + positive_function, atan2); - } - - SECTION("atan2(0.5,uh)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.5, 2 + positive_function, atan2); - } - - SECTION("atan2(uh,0.2)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(2 + cos(positive_function), 0.2, atan2); - } - - SECTION("pow(uh,hv)") - { - CHECK_STD_BINARY_MATH_FUNCTION(positive_function, 0.5 * positive_function, pow); - } - - SECTION("pow(uh,0.5)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.5, positive_function, pow); - } - - SECTION("pow(uh,0.2)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(positive_function, 1.3, pow); - } - - SECTION("min(uh,hv)") - { - CHECK_STD_BINARY_MATH_FUNCTION(sin(positive_function), cos(positive_function), min); - } - - SECTION("min(uh,0.5)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.5, cos(positive_function), min); - } - - SECTION("min(uh,0.2)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(sin(positive_function), 0.5, min); - } - - SECTION("max(uh,hv)") - { - CHECK_STD_BINARY_MATH_FUNCTION(sin(positive_function), cos(positive_function), max); - } - - SECTION("min(uh,0.5)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.1, cos(positive_function), max); - } - - SECTION("min(uh,0.2)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(sin(positive_function), 0.1, max); - } - - SECTION("dot(uh,hv)") - { - DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; - }); - - DiscreteFunctionP0<Dimension, TinyVector<2>> vh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - vh[cell_id] = TinyVector<2>{2.3 * x, 1 - x}; - }); - - CHECK_STD_BINARY_MATH_FUNCTION(uh, vh, dot); - } - - SECTION("dot(uh,v)") - { - DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; - }); - - const TinyVector<2> v{1, 2}; - - CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(uh, v, dot); - } - - SECTION("dot(u,hv)") - { - const TinyVector<2> u{3, -2}; - - DiscreteFunctionP0<Dimension, TinyVector<2>> vh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - vh[cell_id] = TinyVector<2>{2.3 * x, 1 - x}; - }); - - CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(u, vh, dot); - } - - SECTION("scalar sum") - { - const CellValue<const double> cell_value = positive_function.cellValues(); - - REQUIRE(sum(cell_value) == sum(positive_function)); - } - - SECTION("vector sum") - { - DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; - }); - const CellValue<const TinyVector<2>> cell_value = uh.cellValues(); - - REQUIRE(sum(cell_value) == sum(uh)); - } - - SECTION("matrix sum") - { - DiscreteFunctionP0<Dimension, TinyMatrix<2>> uh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - uh[cell_id] = TinyMatrix<2>{x + 1, 2 * x - 3, 2 * x, 3 * x - 1}; - }); - const CellValue<const TinyMatrix<2>> cell_value = uh.cellValues(); - - REQUIRE(sum(cell_value) == sum(uh)); - } - - SECTION("integrate scalar") - { - const CellValue<const double> cell_volume = MeshDataManager::instance().getMeshData(*mesh).Vj(); - - CellValue<double> cell_value{mesh->connectivity()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - cell_value[cell_id] = cell_volume[cell_id] * positive_function[cell_id]; - }); - - REQUIRE(integrate(positive_function) == Catch::Approx(sum(cell_value))); - } - - SECTION("integrate vector") - { - DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; - }); - - const CellValue<const double> cell_volume = MeshDataManager::instance().getMeshData(*mesh).Vj(); - - CellValue<TinyVector<2>> cell_value{mesh->connectivity()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(const CellId cell_id) { cell_value[cell_id] = cell_volume[cell_id] * uh[cell_id]; }); - - REQUIRE(integrate(uh)[0] == Catch::Approx(sum(cell_value)[0])); - REQUIRE(integrate(uh)[1] == Catch::Approx(sum(cell_value)[1])); - } - - SECTION("integrate matrix") - { - DiscreteFunctionP0<Dimension, TinyMatrix<2>> uh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - uh[cell_id] = TinyMatrix<2>{x + 1, 2 * x - 3, 2 * x, 1 - x}; - }); - - const CellValue<const double> cell_volume = MeshDataManager::instance().getMeshData(*mesh).Vj(); - - CellValue<TinyMatrix<2>> cell_value{mesh->connectivity()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(const CellId cell_id) { cell_value[cell_id] = cell_volume[cell_id] * uh[cell_id]; }); - - REQUIRE(integrate(uh)(0, 0) == Catch::Approx(sum(cell_value)(0, 0))); - REQUIRE(integrate(uh)(0, 1) == Catch::Approx(sum(cell_value)(0, 1))); - REQUIRE(integrate(uh)(1, 0) == Catch::Approx(sum(cell_value)(1, 0))); - REQUIRE(integrate(uh)(1, 1) == Catch::Approx(sum(cell_value)(1, 1))); - } - } - - SECTION("3D") - { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian3DMesh(); - - constexpr size_t Dimension = 3; - - auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - DiscreteFunctionP0<Dimension, double> positive_function{mesh}; - - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(const CellId cell_id) { positive_function[cell_id] = 1 + std::abs(xj[cell_id][0]); }); - - const double min_value = min(positive_function); - SECTION("min") - { - double local_min = std::numeric_limits<double>::max(); - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - local_min = std::min(local_min, positive_function[cell_id]); - } - REQUIRE(min_value == parallel::allReduceMin(local_min)); - } - - const double max_value = max(positive_function); - SECTION("max") - { - double local_max = -std::numeric_limits<double>::max(); - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - local_max = std::max(local_max, positive_function[cell_id]); + for (auto [section_name, mesh_1] : mesh_list) { + SECTION(section_name) + { + std::shared_ptr mesh_2 = + std::make_shared<Mesh<Connectivity<Dimension>>>(mesh_1->shared_connectivity(), mesh_1->xr()); + + DiscreteFunctionP0<Dimension, double> f1{mesh_1}; + DiscreteFunctionP0<Dimension, double> f2{mesh_2}; + + REQUIRE_THROWS_AS(f1 = f2, AssertError); + REQUIRE_THROWS_AS(copy_to(f1, f2), AssertError); + REQUIRE_THROWS_AS(f1 + f2, AssertError); + REQUIRE_THROWS_AS(f1 - f2, AssertError); + REQUIRE_THROWS_AS(f1 * f2, AssertError); + REQUIRE_THROWS_AS(f1 / f2, AssertError); + } } - REQUIRE(max_value == parallel::allReduceMax(local_max)); - } - - REQUIRE(min_value < max_value); - - DiscreteFunctionP0 unsigned_function = positive_function - 0.5 * (min_value + max_value); - - SECTION("sqrt") - { - CHECK_STD_MATH_FUNCTION(positive_function, sqrt); - } - - SECTION("abs") - { - CHECK_STD_MATH_FUNCTION(positive_function, abs); - } - - SECTION("cos") - { - CHECK_STD_MATH_FUNCTION(positive_function, cos); - } - - SECTION("sin") - { - CHECK_STD_MATH_FUNCTION(positive_function, sin); - } - - SECTION("tan") - { - CHECK_STD_MATH_FUNCTION(positive_function, tan); - } - - DiscreteFunctionP0<Dimension, double> unit_function{mesh}; - - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - unit_function[cell_id] = (2 * (positive_function[cell_id] - min_value) / (max_value - min_value) - 1) * 0.95; - }); - - SECTION("acos") - { - CHECK_STD_MATH_FUNCTION(unit_function, acos); - } - - SECTION("asin") - { - CHECK_STD_MATH_FUNCTION(unit_function, asin); - } - - SECTION("atan") - { - CHECK_STD_MATH_FUNCTION(unit_function, atan); - } - - SECTION("cosh") - { - CHECK_STD_MATH_FUNCTION(positive_function, cosh); - } - - SECTION("sinh") - { - CHECK_STD_MATH_FUNCTION(positive_function, sinh); - } - - SECTION("tanh") - { - CHECK_STD_MATH_FUNCTION(positive_function, tanh); - } - - SECTION("acosh") - { - CHECK_STD_MATH_FUNCTION(positive_function, acosh); - } - - SECTION("asinh") - { - CHECK_STD_MATH_FUNCTION(positive_function, asinh); - } - - SECTION("atanh") - { - CHECK_STD_MATH_FUNCTION(unit_function, atanh); - } - - SECTION("exp") - { - CHECK_STD_MATH_FUNCTION(positive_function, exp); - } - - SECTION("log") - { - CHECK_STD_MATH_FUNCTION(positive_function, log); - } - - SECTION("max(uh,hv)") - { - CHECK_STD_BINARY_MATH_FUNCTION(cos(positive_function), sin(positive_function), max); - } - - SECTION("max(0.2,vh)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.2, sin(positive_function), max); - } - - SECTION("max(uh,0.2)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(cos(positive_function), 0.2, max); - } - - SECTION("atan2(uh,hv)") - { - CHECK_STD_BINARY_MATH_FUNCTION(positive_function, 2 + positive_function, atan2); - } - - SECTION("atan2(0.5,uh)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.5, 2 + positive_function, atan2); - } - - SECTION("atan2(uh,0.2)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(2 + cos(positive_function), 0.2, atan2); - } - - SECTION("pow(uh,hv)") - { - CHECK_STD_BINARY_MATH_FUNCTION(positive_function, 0.5 * positive_function, pow); - } - - SECTION("pow(uh,0.5)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.5, positive_function, pow); - } - - SECTION("pow(uh,0.2)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(positive_function, 1.3, pow); - } - - SECTION("min(uh,hv)") - { - CHECK_STD_BINARY_MATH_FUNCTION(sin(positive_function), cos(positive_function), min); - } - - SECTION("min(uh,0.5)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.5, cos(positive_function), min); - } - - SECTION("min(uh,0.2)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(sin(positive_function), 0.5, min); - } - - SECTION("max(uh,hv)") - { - CHECK_STD_BINARY_MATH_FUNCTION(sin(positive_function), cos(positive_function), max); - } - - SECTION("min(uh,0.5)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(0.1, cos(positive_function), max); - } - - SECTION("min(uh,0.2)") - { - CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(sin(positive_function), 0.1, max); - } - - SECTION("dot(uh,hv)") - { - DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; - }); - - DiscreteFunctionP0<Dimension, TinyVector<2>> vh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - vh[cell_id] = TinyVector<2>{2.3 * x, 1 - x}; - }); - - CHECK_STD_BINARY_MATH_FUNCTION(uh, vh, dot); - } - - SECTION("dot(uh,v)") - { - DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; - }); - - const TinyVector<2> v{1, 2}; - - CHECK_STD_BINARY_MATH_FUNCTION_WITH_RHS_VALUE(uh, v, dot); - } - - SECTION("dot(u,hv)") - { - const TinyVector<2> u{3, -2}; - - DiscreteFunctionP0<Dimension, TinyVector<2>> vh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - vh[cell_id] = TinyVector<2>{2.3 * x, 1 - x}; - }); - - CHECK_STD_BINARY_MATH_FUNCTION_WITH_LHS_VALUE(u, vh, dot); - } - - SECTION("scalar sum") - { - const CellValue<const double> cell_value = positive_function.cellValues(); - - REQUIRE(sum(cell_value) == sum(positive_function)); - } - - SECTION("vector sum") - { - DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; - }); - const CellValue<const TinyVector<2>> cell_value = uh.cellValues(); - - REQUIRE(sum(cell_value) == sum(uh)); - } - - SECTION("matrix sum") - { - DiscreteFunctionP0<Dimension, TinyMatrix<2>> uh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - uh[cell_id] = TinyMatrix<2>{x + 1, 2 * x - 3, 2 * x, 3 * x - 1}; - }); - const CellValue<const TinyMatrix<2>> cell_value = uh.cellValues(); - - REQUIRE(sum(cell_value) == sum(uh)); - } - - SECTION("integrate scalar") - { - const CellValue<const double> cell_volume = MeshDataManager::instance().getMeshData(*mesh).Vj(); - - CellValue<double> cell_value{mesh->connectivity()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - cell_value[cell_id] = cell_volume[cell_id] * positive_function[cell_id]; - }); - - REQUIRE(integrate(positive_function) == Catch::Approx(sum(cell_value))); - } - - SECTION("integrate vector") - { - DiscreteFunctionP0<Dimension, TinyVector<2>> uh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - uh[cell_id] = TinyVector<2>{x + 1, 2 * x - 3}; - }); - - const CellValue<const double> cell_volume = MeshDataManager::instance().getMeshData(*mesh).Vj(); - - CellValue<TinyVector<2>> cell_value{mesh->connectivity()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(const CellId cell_id) { cell_value[cell_id] = cell_volume[cell_id] * uh[cell_id]; }); - - REQUIRE(integrate(uh)[0] == Catch::Approx(sum(cell_value)[0])); - REQUIRE(integrate(uh)[1] == Catch::Approx(sum(cell_value)[1])); - } - - SECTION("integrate matrix") - { - DiscreteFunctionP0<Dimension, TinyMatrix<2>> uh{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { - const double x = xj[cell_id][0]; - uh[cell_id] = TinyMatrix<2>{x + 1, 2 * x - 3, 2 * x, 1 - x}; - }); - - const CellValue<const double> cell_volume = MeshDataManager::instance().getMeshData(*mesh).Vj(); - - CellValue<TinyMatrix<2>> cell_value{mesh->connectivity()}; - parallel_for( - mesh->numberOfCells(), - PUGS_LAMBDA(const CellId cell_id) { cell_value[cell_id] = cell_volume[cell_id] * uh[cell_id]; }); - - REQUIRE(integrate(uh)(0, 0) == Catch::Approx(sum(cell_value)(0, 0))); - REQUIRE(integrate(uh)(0, 1) == Catch::Approx(sum(cell_value)(0, 1))); - REQUIRE(integrate(uh)(1, 0) == Catch::Approx(sum(cell_value)(1, 0))); - REQUIRE(integrate(uh)(1, 1) == Catch::Approx(sum(cell_value)(1, 1))); - } - } - } - -#ifndef NDEBUG - SECTION("error") - { - SECTION("different meshes") - { - SECTION("1D") - { - constexpr size_t Dimension = 1; - - std::shared_ptr mesh_1 = MeshDataBaseForTests::get().cartesian1DMesh(); - std::shared_ptr mesh_2 = - std::make_shared<Mesh<Connectivity<Dimension>>>(mesh_1->shared_connectivity(), mesh_1->xr()); - - DiscreteFunctionP0<Dimension, double> f1{mesh_1}; - DiscreteFunctionP0<Dimension, double> f2{mesh_2}; - - REQUIRE_THROWS_AS(f1 = f2, AssertError); - REQUIRE_THROWS_AS(copy_to(f1, f2), AssertError); - REQUIRE_THROWS_AS(f1 + f2, AssertError); - REQUIRE_THROWS_AS(f1 - f2, AssertError); - REQUIRE_THROWS_AS(f1 * f2, AssertError); - REQUIRE_THROWS_AS(f1 / f2, AssertError); } SECTION("2D") { constexpr size_t Dimension = 2; - std::shared_ptr mesh_1 = MeshDataBaseForTests::get().cartesian2DMesh(); - std::shared_ptr mesh_2 = - std::make_shared<Mesh<Connectivity<Dimension>>>(mesh_1->shared_connectivity(), mesh_1->xr()); - - DiscreteFunctionP0<Dimension, double> f1{mesh_1}; - DiscreteFunctionP0<Dimension, double> f2{mesh_2}; + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - REQUIRE_THROWS_AS(f1 = f2, AssertError); - REQUIRE_THROWS_AS(copy_to(f1, f2), AssertError); - REQUIRE_THROWS_AS(f1 + f2, AssertError); - REQUIRE_THROWS_AS(f1 - f2, AssertError); - REQUIRE_THROWS_AS(f1 * f2, AssertError); - REQUIRE_THROWS_AS(f1 / f2, AssertError); + for (auto [section_name, mesh_1] : mesh_list) { + SECTION(section_name) + { + std::shared_ptr mesh_2 = + std::make_shared<Mesh<Connectivity<Dimension>>>(mesh_1->shared_connectivity(), mesh_1->xr()); + + DiscreteFunctionP0<Dimension, double> f1{mesh_1}; + DiscreteFunctionP0<Dimension, double> f2{mesh_2}; + + REQUIRE_THROWS_AS(f1 = f2, AssertError); + REQUIRE_THROWS_AS(copy_to(f1, f2), AssertError); + REQUIRE_THROWS_AS(f1 + f2, AssertError); + REQUIRE_THROWS_AS(f1 - f2, AssertError); + REQUIRE_THROWS_AS(f1 * f2, AssertError); + REQUIRE_THROWS_AS(f1 / f2, AssertError); + } + } } SECTION("3D") { constexpr size_t Dimension = 3; - std::shared_ptr mesh_1 = MeshDataBaseForTests::get().cartesian3DMesh(); - std::shared_ptr mesh_2 = - std::make_shared<Mesh<Connectivity<Dimension>>>(mesh_1->shared_connectivity(), mesh_1->xr()); - - DiscreteFunctionP0<Dimension, double> f1{mesh_1}; - DiscreteFunctionP0<Dimension, double> f2{mesh_2}; + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - REQUIRE_THROWS_AS(f1 = f2, AssertError); - REQUIRE_THROWS_AS(copy_to(f1, f2), AssertError); - REQUIRE_THROWS_AS(f1 + f2, AssertError); - REQUIRE_THROWS_AS(f1 - f2, AssertError); - REQUIRE_THROWS_AS(f1 * f2, AssertError); - REQUIRE_THROWS_AS(f1 / f2, AssertError); + for (auto [section_name, mesh_1] : mesh_list) { + SECTION(section_name) + { + std::shared_ptr mesh_2 = + std::make_shared<Mesh<Connectivity<Dimension>>>(mesh_1->shared_connectivity(), mesh_1->xr()); + + DiscreteFunctionP0<Dimension, double> f1{mesh_1}; + DiscreteFunctionP0<Dimension, double> f2{mesh_2}; + + REQUIRE_THROWS_AS(f1 = f2, AssertError); + REQUIRE_THROWS_AS(copy_to(f1, f2), AssertError); + REQUIRE_THROWS_AS(f1 + f2, AssertError); + REQUIRE_THROWS_AS(f1 - f2, AssertError); + REQUIRE_THROWS_AS(f1 * f2, AssertError); + REQUIRE_THROWS_AS(f1 / f2, AssertError); + } + } } } } diff --git a/tests/test_DiscreteFunctionP0Vector.cpp b/tests/test_DiscreteFunctionP0Vector.cpp index 72daecc2901162b1712c41f421a49d7bbe9cee7f..217418fe5db664fdc8ae85dd8f1baa0f461ca409 100644 --- a/tests/test_DiscreteFunctionP0Vector.cpp +++ b/tests/test_DiscreteFunctionP0Vector.cpp @@ -27,123 +27,141 @@ TEST_CASE("DiscreteFunctionP0Vector", "[scheme]") { const size_t size = 3; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian1DMesh(); constexpr size_t Dimension = 1; - DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; - REQUIRE(f.dataType() == ASTNodeDataType::double_t); - REQUIRE(f.descriptor().type() == DiscreteFunctionType::P0Vector); - REQUIRE(f.size() == size); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - REQUIRE(f.mesh().get() == mesh.get()); + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + REQUIRE(f.dataType() == ASTNodeDataType::double_t); + REQUIRE(f.descriptor().type() == DiscreteFunctionType::P0Vector); + REQUIRE(f.size() == size); + + REQUIRE(f.mesh().get() == mesh.get()); - DiscreteFunctionP0Vector g{f}; - REQUIRE(g.dataType() == ASTNodeDataType::double_t); - REQUIRE(g.descriptor().type() == DiscreteFunctionType::P0Vector); - REQUIRE(g.size() == size); + DiscreteFunctionP0Vector g{f}; + REQUIRE(g.dataType() == ASTNodeDataType::double_t); + REQUIRE(g.descriptor().type() == DiscreteFunctionType::P0Vector); + REQUIRE(g.size() == size); - CellArray<double> h_arrays{mesh->connectivity(), size}; - h_arrays.fill(0); + CellArray<double> h_arrays{mesh->connectivity(), size}; + h_arrays.fill(0); - DiscreteFunctionP0Vector zero{mesh, [&] { - CellArray<double> cell_array{mesh->connectivity(), size}; - cell_array.fill(0); - return cell_array; - }()}; + DiscreteFunctionP0Vector zero{mesh, [&] { + CellArray<double> cell_array{mesh->connectivity(), size}; + cell_array.fill(0); + return cell_array; + }()}; - DiscreteFunctionP0Vector h{mesh, h_arrays}; - REQUIRE(same_values(h, zero)); - REQUIRE(same_values(h, h_arrays)); + DiscreteFunctionP0Vector h{mesh, h_arrays}; + REQUIRE(same_values(h, zero)); + REQUIRE(same_values(h, h_arrays)); - h_arrays.fill(1); + h_arrays.fill(1); - REQUIRE(same_values(h, h_arrays)); - REQUIRE(not same_values(h, zero)); + REQUIRE(same_values(h, h_arrays)); + REQUIRE(not same_values(h, zero)); - DiscreteFunctionP0Vector moved_h{std::move(h)}; - REQUIRE(same_values(moved_h, h_arrays)); + DiscreteFunctionP0Vector moved_h{std::move(h)}; + REQUIRE(same_values(moved_h, h_arrays)); + } + } } SECTION("2D") { const size_t size = 3; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian2DMesh(); constexpr size_t Dimension = 2; - DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; - REQUIRE(f.dataType() == ASTNodeDataType::double_t); - REQUIRE(f.descriptor().type() == DiscreteFunctionType::P0Vector); - REQUIRE(f.size() == size); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); + + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + REQUIRE(f.dataType() == ASTNodeDataType::double_t); + REQUIRE(f.descriptor().type() == DiscreteFunctionType::P0Vector); + REQUIRE(f.size() == size); - REQUIRE(f.mesh().get() == mesh.get()); + REQUIRE(f.mesh().get() == mesh.get()); - DiscreteFunctionP0Vector g{f}; - REQUIRE(g.dataType() == ASTNodeDataType::double_t); - REQUIRE(g.descriptor().type() == DiscreteFunctionType::P0Vector); - REQUIRE(g.size() == size); + DiscreteFunctionP0Vector g{f}; + REQUIRE(g.dataType() == ASTNodeDataType::double_t); + REQUIRE(g.descriptor().type() == DiscreteFunctionType::P0Vector); + REQUIRE(g.size() == size); - CellArray<double> h_arrays{mesh->connectivity(), size}; - h_arrays.fill(0); + CellArray<double> h_arrays{mesh->connectivity(), size}; + h_arrays.fill(0); - DiscreteFunctionP0Vector zero{mesh, [&] { - CellArray<double> cell_array{mesh->connectivity(), size}; - cell_array.fill(0); - return cell_array; - }()}; + DiscreteFunctionP0Vector zero{mesh, [&] { + CellArray<double> cell_array{mesh->connectivity(), size}; + cell_array.fill(0); + return cell_array; + }()}; - DiscreteFunctionP0Vector h{mesh, h_arrays}; - REQUIRE(same_values(h, zero)); - REQUIRE(same_values(h, h_arrays)); + DiscreteFunctionP0Vector h{mesh, h_arrays}; + REQUIRE(same_values(h, zero)); + REQUIRE(same_values(h, h_arrays)); - h_arrays.fill(1); + h_arrays.fill(1); - REQUIRE(same_values(h, h_arrays)); - REQUIRE(not same_values(h, zero)); + REQUIRE(same_values(h, h_arrays)); + REQUIRE(not same_values(h, zero)); - DiscreteFunctionP0Vector moved_h{std::move(h)}; - REQUIRE(same_values(moved_h, h_arrays)); + DiscreteFunctionP0Vector moved_h{std::move(h)}; + REQUIRE(same_values(moved_h, h_arrays)); + } + } } SECTION("3D") { const size_t size = 2; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian3DMesh(); constexpr size_t Dimension = 3; - DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; - REQUIRE(f.dataType() == ASTNodeDataType::double_t); - REQUIRE(f.descriptor().type() == DiscreteFunctionType::P0Vector); - REQUIRE(f.size() == size); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); + + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + REQUIRE(f.dataType() == ASTNodeDataType::double_t); + REQUIRE(f.descriptor().type() == DiscreteFunctionType::P0Vector); + REQUIRE(f.size() == size); - REQUIRE(f.mesh().get() == mesh.get()); + REQUIRE(f.mesh().get() == mesh.get()); - DiscreteFunctionP0Vector g{f}; - REQUIRE(g.dataType() == ASTNodeDataType::double_t); - REQUIRE(g.descriptor().type() == DiscreteFunctionType::P0Vector); - REQUIRE(g.size() == size); + DiscreteFunctionP0Vector g{f}; + REQUIRE(g.dataType() == ASTNodeDataType::double_t); + REQUIRE(g.descriptor().type() == DiscreteFunctionType::P0Vector); + REQUIRE(g.size() == size); - CellArray<double> h_arrays{mesh->connectivity(), size}; - h_arrays.fill(0); + CellArray<double> h_arrays{mesh->connectivity(), size}; + h_arrays.fill(0); - DiscreteFunctionP0Vector zero{mesh, [&] { - CellArray<double> cell_array{mesh->connectivity(), size}; - cell_array.fill(0); - return cell_array; - }()}; + DiscreteFunctionP0Vector zero{mesh, [&] { + CellArray<double> cell_array{mesh->connectivity(), size}; + cell_array.fill(0); + return cell_array; + }()}; - DiscreteFunctionP0Vector h{mesh, h_arrays}; - REQUIRE(same_values(h, zero)); - REQUIRE(same_values(h, h_arrays)); + DiscreteFunctionP0Vector h{mesh, h_arrays}; + REQUIRE(same_values(h, zero)); + REQUIRE(same_values(h, h_arrays)); - h_arrays.fill(1); + h_arrays.fill(1); - REQUIRE(same_values(h, h_arrays)); - REQUIRE(not same_values(h, zero)); + REQUIRE(same_values(h, h_arrays)); + REQUIRE(not same_values(h, zero)); - DiscreteFunctionP0Vector moved_h{std::move(h)}; - REQUIRE(same_values(moved_h, h_arrays)); + DiscreteFunctionP0Vector moved_h{std::move(h)}; + REQUIRE(same_values(moved_h, h_arrays)); + } + } } } @@ -166,39 +184,57 @@ TEST_CASE("DiscreteFunctionP0Vector", "[scheme]") { const size_t size = 3; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian1DMesh(); - constexpr size_t Dimension = 1; + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); + + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + constexpr size_t Dimension = 1; - DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; - f.fill(3); + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + f.fill(3); - REQUIRE(all_values_equal(f, 3)); + REQUIRE(all_values_equal(f, 3)); + } + } } SECTION("2D") { const size_t size = 3; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian2DMesh(); constexpr size_t Dimension = 2; - DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; - f.fill(2.3); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); + + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + f.fill(2.3); - REQUIRE(all_values_equal(f, 2.3)); + REQUIRE(all_values_equal(f, 2.3)); + } + } } SECTION("3D") { const size_t size = 2; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian3DMesh(); constexpr size_t Dimension = 3; - DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; - f.fill(3.2); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); + + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + f.fill(3.2); - REQUIRE(all_values_equal(f, 3.2)); + REQUIRE(all_values_equal(f, 3.2)); + } + } } } @@ -220,623 +256,670 @@ TEST_CASE("DiscreteFunctionP0Vector", "[scheme]") SECTION("1D") { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian1DMesh(); - constexpr size_t Dimension = 1; - const size_t size = 3; - const size_t value = parallel::rank() + 1; - const size_t zero = 0; + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); + + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + const size_t size = 3; + const size_t value = parallel::rank() + 1; + const size_t zero = 0; - DiscreteFunctionP0Vector<Dimension, size_t> f{mesh, size}; - f.fill(value); + DiscreteFunctionP0Vector<Dimension, size_t> f{mesh, size}; + f.fill(value); - REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(f, value)); - DiscreteFunctionP0Vector g = copy(f); - f.fill(zero); + DiscreteFunctionP0Vector g = copy(f); + f.fill(zero); - REQUIRE(all_values_equal(f, zero)); - REQUIRE(all_values_equal(g, value)); + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); - copy_to(g, f); - g.fill(zero); + copy_to(g, f); + g.fill(zero); - DiscreteFunctionP0Vector<Dimension, const size_t> h = copy(f); + DiscreteFunctionP0Vector<Dimension, const size_t> h = copy(f); - DiscreteFunctionP0Vector<Dimension, size_t> shallow_g{mesh, size}; - shallow_g = g; + DiscreteFunctionP0Vector<Dimension, size_t> shallow_g{mesh, size}; + shallow_g = g; - REQUIRE(all_values_equal(f, value)); - REQUIRE(all_values_equal(g, zero)); - REQUIRE(all_values_equal(shallow_g, zero)); - REQUIRE(all_values_equal(h, value)); + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(shallow_g, zero)); + REQUIRE(all_values_equal(h, value)); - copy_to(h, g); + copy_to(h, g); - REQUIRE(all_values_equal(g, value)); - REQUIRE(all_values_equal(shallow_g, value)); + REQUIRE(all_values_equal(g, value)); + REQUIRE(all_values_equal(shallow_g, value)); + } + } } SECTION("2D") { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian2DMesh(); - constexpr size_t Dimension = 2; + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - const size_t size = 3; - const size_t value = parallel::rank() + 1; - const size_t zero = 0; + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + const size_t size = 3; + const size_t value = parallel::rank() + 1; + const size_t zero = 0; - DiscreteFunctionP0Vector<Dimension, size_t> f{mesh, size}; - f.fill(value); + DiscreteFunctionP0Vector<Dimension, size_t> f{mesh, size}; + f.fill(value); - REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(f, value)); - DiscreteFunctionP0Vector g = copy(f); - f.fill(zero); + DiscreteFunctionP0Vector g = copy(f); + f.fill(zero); - REQUIRE(all_values_equal(f, zero)); - REQUIRE(all_values_equal(g, value)); + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); - copy_to(g, f); - g.fill(zero); + copy_to(g, f); + g.fill(zero); - DiscreteFunctionP0Vector<Dimension, const size_t> h = copy(f); + DiscreteFunctionP0Vector<Dimension, const size_t> h = copy(f); - DiscreteFunctionP0Vector<Dimension, size_t> shallow_g{mesh, size}; - shallow_g = g; + DiscreteFunctionP0Vector<Dimension, size_t> shallow_g{mesh, size}; + shallow_g = g; - REQUIRE(all_values_equal(f, value)); - REQUIRE(all_values_equal(g, zero)); - REQUIRE(all_values_equal(shallow_g, zero)); - REQUIRE(all_values_equal(h, value)); + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(shallow_g, zero)); + REQUIRE(all_values_equal(h, value)); - copy_to(h, g); + copy_to(h, g); - REQUIRE(all_values_equal(g, value)); - REQUIRE(all_values_equal(shallow_g, value)); + REQUIRE(all_values_equal(g, value)); + REQUIRE(all_values_equal(shallow_g, value)); + } + } } SECTION("3D") { - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian3DMesh(); - constexpr size_t Dimension = 3; - const size_t size = 3; - const size_t value = parallel::rank() + 1; - const size_t zero = 0; - - DiscreteFunctionP0Vector<Dimension, size_t> f{mesh, size}; - f.fill(value); - - REQUIRE(all_values_equal(f, value)); - - DiscreteFunctionP0Vector g = copy(f); - f.fill(zero); - - REQUIRE(all_values_equal(f, zero)); - REQUIRE(all_values_equal(g, value)); - - copy_to(g, f); - g.fill(zero); - - DiscreteFunctionP0Vector<Dimension, const size_t> h = copy(f); - - DiscreteFunctionP0Vector<Dimension, size_t> shallow_g{mesh, size}; - shallow_g = g; + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - REQUIRE(all_values_equal(f, value)); - REQUIRE(all_values_equal(g, zero)); - REQUIRE(all_values_equal(h, value)); - - copy_to(h, g); - - REQUIRE(all_values_equal(g, value)); - REQUIRE(all_values_equal(shallow_g, value)); - } - } - - SECTION("unary operators") - { - SECTION("1D") - { - const size_t size = 3; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian1DMesh(); - - constexpr size_t Dimension = 1; - - auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - SECTION("unary minus") - { - DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - for (size_t i = 0; i < size; ++i) { - f[cell_id][i] = 2 * x + i; - } - }); - - DiscreteFunctionP0Vector<Dimension, const double> const_f = f; - - Table<double> minus_values{mesh->numberOfCells(), size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - for (size_t i = 0; i < size; ++i) { - minus_values[cell_id][i] = -f[cell_id][i]; - } - }); - - REQUIRE(same_values(-f, minus_values)); - REQUIRE(same_values(-const_f, minus_values)); - } - } - - SECTION("2D") - { - const size_t size = 3; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian2DMesh(); - - constexpr size_t Dimension = 2; + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + const size_t size = 3; + const size_t value = parallel::rank() + 1; + const size_t zero = 0; - auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - SECTION("unary minus") - { - DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - for (size_t i = 0; i < size; ++i) { - f[cell_id][i] = 2 * x + i * y; - } - }); + DiscreteFunctionP0Vector<Dimension, size_t> f{mesh, size}; + f.fill(value); - DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + REQUIRE(all_values_equal(f, value)); - Table<double> minus_values{mesh->numberOfCells(), size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - for (size_t i = 0; i < size; ++i) { - minus_values[cell_id][i] = -f[cell_id][i]; - } - }); + DiscreteFunctionP0Vector g = copy(f); + f.fill(zero); - REQUIRE(same_values(-f, minus_values)); - REQUIRE(same_values(-const_f, minus_values)); - } - } + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); - SECTION("3D") - { - const size_t size = 2; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian3DMesh(); + copy_to(g, f); + g.fill(zero); - constexpr size_t Dimension = 3; + DiscreteFunctionP0Vector<Dimension, const size_t> h = copy(f); - auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - SECTION("unary minus") - { - DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - const double z = xj[cell_id][2]; - for (size_t i = 0; i < size; ++i) { - f[cell_id][i] = 2 * x + i * y - z; - } - }); + DiscreteFunctionP0Vector<Dimension, size_t> shallow_g{mesh, size}; + shallow_g = g; - DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); - Table<double> minus_values{mesh->numberOfCells(), size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - for (size_t i = 0; i < size; ++i) { - minus_values[cell_id][i] = -f[cell_id][i]; - } - }); + copy_to(h, g); - REQUIRE(same_values(-f, minus_values)); - REQUIRE(same_values(-const_f, minus_values)); + REQUIRE(all_values_equal(g, value)); + REQUIRE(all_values_equal(shallow_g, value)); + } } } } - SECTION("binary operators") + SECTION("unary operators") { SECTION("1D") { const size_t size = 3; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian1DMesh(); - constexpr size_t Dimension = 1; - auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - SECTION("inner operators") - { - SECTION("scalar functions") + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) { - DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - f[cell_id][0] = 2 * x + 1; - f[cell_id][1] = x * x - 1; - f[cell_id][2] = 2 + x; - }); - - DiscreteFunctionP0Vector<Dimension, double> g{mesh, size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - g[cell_id][0] = (x + 1) * (x - 2) + 1; - g[cell_id][1] = 3 * (x + 2) - 1; - g[cell_id][2] = (x + 3) * 5; - }); - - DiscreteFunctionP0Vector<Dimension, const double> const_f = f; - DiscreteFunctionP0Vector<Dimension, const double> const_g{g}; - - SECTION("sum") + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + SECTION("unary minus") { - Table<double> sum_values{mesh->numberOfCells(), size}; + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; parallel_for( mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; for (size_t i = 0; i < size; ++i) { - sum_values[cell_id][i] = f[cell_id][i] + g[cell_id][i]; + f[cell_id][i] = 2 * x + i; } }); - REQUIRE(same_values(f + g, sum_values)); - REQUIRE(same_values(const_f + g, sum_values)); - REQUIRE(same_values(f + const_g, sum_values)); - REQUIRE(same_values(const_f + const_g, sum_values)); - } + DiscreteFunctionP0Vector<Dimension, const double> const_f = f; - SECTION("difference") - { - Table<double> difference_values{mesh->numberOfCells(), size}; + Table<double> minus_values{mesh->numberOfCells(), size}; parallel_for( mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { for (size_t i = 0; i < size; ++i) { - difference_values[cell_id][i] = f[cell_id][i] - g[cell_id][i]; + minus_values[cell_id][i] = -f[cell_id][i]; } }); - REQUIRE(same_values(f - g, difference_values)); - REQUIRE(same_values(const_f - g, difference_values)); - REQUIRE(same_values(f - const_g, difference_values)); - REQUIRE(same_values(const_f - const_g, difference_values)); + REQUIRE(same_values(-f, minus_values)); + REQUIRE(same_values(-const_f, minus_values)); } } } + } - SECTION("external operators") - { - DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - for (size_t i = 0; i < size; ++i) { - f[cell_id][i] = std::abs(2 * x) + i; - } - }); + SECTION("2D") + { + const size_t size = 3; + + constexpr size_t Dimension = 2; - DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - SECTION("product") + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) { - SECTION("scalar lhs") + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + SECTION("unary minus") { - const double a = 3.2; - Table<double> product_values{mesh->numberOfCells(), size}; + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; parallel_for( mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; for (size_t i = 0; i < size; ++i) { - product_values[cell_id][i] = a * f[cell_id][i]; + f[cell_id][i] = 2 * x + i * y; } }); - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); - } - - SECTION("DiscreteFunctionP0 lhs") - { - DiscreteFunctionP0<Dimension, double> a{mesh}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - a[cell_id] = 2 * x + 1; - }); + DiscreteFunctionP0Vector<Dimension, const double> const_f = f; - Table<double> product_values{mesh->numberOfCells(), size}; + Table<double> minus_values{mesh->numberOfCells(), size}; parallel_for( mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { for (size_t i = 0; i < size; ++i) { - product_values[cell_id][i] = a[cell_id] * f[cell_id][i]; + minus_values[cell_id][i] = -f[cell_id][i]; } }); - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); - - DiscreteFunctionP0<Dimension, const double> const_a = a; - REQUIRE(same_values(const_a * f, product_values)); - REQUIRE(same_values(const_a * const_f, product_values)); + REQUIRE(same_values(-f, minus_values)); + REQUIRE(same_values(-const_f, minus_values)); } } } } - SECTION("2D") + SECTION("3D") { - const size_t size = 3; - - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian2DMesh(); + const size_t size = 2; - constexpr size_t Dimension = 2; + constexpr size_t Dimension = 3; - auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - SECTION("inner operators") - { - SECTION("scalar functions") + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) { - DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - f[cell_id][0] = 2 * x + 1; - f[cell_id][1] = x * x - y; - f[cell_id][2] = 2 + x * y; - }); - - DiscreteFunctionP0Vector<Dimension, double> g{mesh, size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - g[cell_id][0] = (x + 1) * (y - 2) + 1; - g[cell_id][1] = 3 * (x + 2) - y; - g[cell_id][2] = (x + 3) + 5 * y; - }); - - DiscreteFunctionP0Vector<Dimension, const double> const_f = f; - DiscreteFunctionP0Vector<Dimension, const double> const_g{g}; - - SECTION("sum") + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + SECTION("unary minus") { - Table<double> sum_values{mesh->numberOfCells(), size}; + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; parallel_for( mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; for (size_t i = 0; i < size; ++i) { - sum_values[cell_id][i] = f[cell_id][i] + g[cell_id][i]; + f[cell_id][i] = 2 * x + i * y - z; } }); - REQUIRE(same_values(f + g, sum_values)); - REQUIRE(same_values(const_f + g, sum_values)); - REQUIRE(same_values(f + const_g, sum_values)); - REQUIRE(same_values(const_f + const_g, sum_values)); - } + DiscreteFunctionP0Vector<Dimension, const double> const_f = f; - SECTION("difference") - { - Table<double> difference_values{mesh->numberOfCells(), size}; + Table<double> minus_values{mesh->numberOfCells(), size}; parallel_for( mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { for (size_t i = 0; i < size; ++i) { - difference_values[cell_id][i] = f[cell_id][i] - g[cell_id][i]; + minus_values[cell_id][i] = -f[cell_id][i]; } }); - REQUIRE(same_values(f - g, difference_values)); - REQUIRE(same_values(const_f - g, difference_values)); - REQUIRE(same_values(f - const_g, difference_values)); - REQUIRE(same_values(const_f - const_g, difference_values)); + REQUIRE(same_values(-f, minus_values)); + REQUIRE(same_values(-const_f, minus_values)); } } } + } + } - SECTION("external operators") - { - DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - for (size_t i = 0; i < size; ++i) { - f[cell_id][i] = std::abs(2 * x) + i * y; - } - }); + SECTION("binary operators") + { + SECTION("1D") + { + const size_t size = 3; + + constexpr size_t Dimension = 1; - DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - SECTION("product") + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) { - SECTION("scalar lhs") - { - const double a = 3.2; - Table<double> product_values{mesh->numberOfCells(), size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - for (size_t i = 0; i < size; ++i) { - product_values[cell_id][i] = a * f[cell_id][i]; - } - }); + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); + SECTION("inner operators") + { + SECTION("scalar functions") + { + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + f[cell_id][0] = 2 * x + 1; + f[cell_id][1] = x * x - 1; + f[cell_id][2] = 2 + x; + }); + + DiscreteFunctionP0Vector<Dimension, double> g{mesh, size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + g[cell_id][0] = (x + 1) * (x - 2) + 1; + g[cell_id][1] = 3 * (x + 2) - 1; + g[cell_id][2] = (x + 3) * 5; + }); + + DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + DiscreteFunctionP0Vector<Dimension, const double> const_g{g}; + + SECTION("sum") + { + Table<double> sum_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + sum_values[cell_id][i] = f[cell_id][i] + g[cell_id][i]; + } + }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Table<double> difference_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + difference_values[cell_id][i] = f[cell_id][i] - g[cell_id][i]; + } + }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + } } - SECTION("DiscreteFunctionP0 lhs") + SECTION("external operators") { - DiscreteFunctionP0<Dimension, double> a{mesh}; + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; parallel_for( mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - a[cell_id] = 2 * x + 1 - y; - }); - - Table<double> product_values{mesh->numberOfCells(), size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { for (size_t i = 0; i < size; ++i) { - product_values[cell_id][i] = a[cell_id] * f[cell_id][i]; + f[cell_id][i] = std::abs(2 * x) + i; } }); - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); - - DiscreteFunctionP0<Dimension, const double> const_a = a; - REQUIRE(same_values(const_a * f, product_values)); - REQUIRE(same_values(const_a * const_f, product_values)); + DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + + SECTION("product") + { + SECTION("scalar lhs") + { + const double a = 3.2; + Table<double> product_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + product_values[cell_id][i] = a * f[cell_id][i]; + } + }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + SECTION("DiscreteFunctionP0 lhs") + { + DiscreteFunctionP0<Dimension, double> a{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + a[cell_id] = 2 * x + 1; + }); + + Table<double> product_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + product_values[cell_id][i] = a[cell_id] * f[cell_id][i]; + } + }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + + DiscreteFunctionP0<Dimension, const double> const_a = a; + REQUIRE(same_values(const_a * f, product_values)); + REQUIRE(same_values(const_a * const_f, product_values)); + } + } } } } } - SECTION("3D") + SECTION("2D") { - const size_t size = 2; - - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian3DMesh(); + const size_t size = 3; - constexpr size_t Dimension = 3; + constexpr size_t Dimension = 2; - auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - SECTION("inner operators") - { - SECTION("scalar functions") + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) { - DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - const double z = xj[cell_id][2]; - f[cell_id][0] = 2 * x * z + 1; - f[cell_id][1] = x * z - y; - }); - - DiscreteFunctionP0Vector<Dimension, double> g{mesh, size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - const double z = xj[cell_id][2]; - g[cell_id][0] = (x + 1) * (y - 2) + 1 - z; - g[cell_id][1] = 3 * (x + 2) - y * z; - }); - - DiscreteFunctionP0Vector<Dimension, const double> const_f = f; - DiscreteFunctionP0Vector<Dimension, const double> const_g{g}; - - SECTION("sum") - { - Table<double> sum_values{mesh->numberOfCells(), size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - for (size_t i = 0; i < size; ++i) { - sum_values[cell_id][i] = f[cell_id][i] + g[cell_id][i]; - } - }); + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - REQUIRE(same_values(f + g, sum_values)); - REQUIRE(same_values(const_f + g, sum_values)); - REQUIRE(same_values(f + const_g, sum_values)); - REQUIRE(same_values(const_f + const_g, sum_values)); + SECTION("inner operators") + { + SECTION("scalar functions") + { + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + f[cell_id][0] = 2 * x + 1; + f[cell_id][1] = x * x - y; + f[cell_id][2] = 2 + x * y; + }); + + DiscreteFunctionP0Vector<Dimension, double> g{mesh, size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + g[cell_id][0] = (x + 1) * (y - 2) + 1; + g[cell_id][1] = 3 * (x + 2) - y; + g[cell_id][2] = (x + 3) + 5 * y; + }); + + DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + DiscreteFunctionP0Vector<Dimension, const double> const_g{g}; + + SECTION("sum") + { + Table<double> sum_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + sum_values[cell_id][i] = f[cell_id][i] + g[cell_id][i]; + } + }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Table<double> difference_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + difference_values[cell_id][i] = f[cell_id][i] - g[cell_id][i]; + } + }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + } } - SECTION("difference") + SECTION("external operators") { - Table<double> difference_values{mesh->numberOfCells(), size}; + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; parallel_for( mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; for (size_t i = 0; i < size; ++i) { - difference_values[cell_id][i] = f[cell_id][i] - g[cell_id][i]; + f[cell_id][i] = std::abs(2 * x) + i * y; } }); - REQUIRE(same_values(f - g, difference_values)); - REQUIRE(same_values(const_f - g, difference_values)); - REQUIRE(same_values(f - const_g, difference_values)); - REQUIRE(same_values(const_f - const_g, difference_values)); + DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + + SECTION("product") + { + SECTION("scalar lhs") + { + const double a = 3.2; + Table<double> product_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + product_values[cell_id][i] = a * f[cell_id][i]; + } + }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + SECTION("DiscreteFunctionP0 lhs") + { + DiscreteFunctionP0<Dimension, double> a{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + a[cell_id] = 2 * x + 1 - y; + }); + + Table<double> product_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + product_values[cell_id][i] = a[cell_id] * f[cell_id][i]; + } + }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + + DiscreteFunctionP0<Dimension, const double> const_a = a; + REQUIRE(same_values(const_a * f, product_values)); + REQUIRE(same_values(const_a * const_f, product_values)); + } + } } } } + } - SECTION("external operators") - { - DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double x = xj[cell_id][0]; - const double y = xj[cell_id][1]; - const double z = xj[cell_id][2]; - for (size_t i = 0; i < size; ++i) { - f[cell_id][i] = std::abs(2 * x) + i * y + z; - } - }); + SECTION("3D") + { + const size_t size = 2; + + constexpr size_t Dimension = 3; - DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - SECTION("product") + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) { - SECTION("scalar lhs") - { - const double a = 3.2; - Table<double> product_values{mesh->numberOfCells(), size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - for (size_t i = 0; i < size; ++i) { - product_values[cell_id][i] = a * f[cell_id][i]; - } - }); + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); + SECTION("inner operators") + { + SECTION("scalar functions") + { + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; + f[cell_id][0] = 2 * x * z + 1; + f[cell_id][1] = x * z - y; + }); + + DiscreteFunctionP0Vector<Dimension, double> g{mesh, size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; + g[cell_id][0] = (x + 1) * (y - 2) + 1 - z; + g[cell_id][1] = 3 * (x + 2) - y * z; + }); + + DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + DiscreteFunctionP0Vector<Dimension, const double> const_g{g}; + + SECTION("sum") + { + Table<double> sum_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + sum_values[cell_id][i] = f[cell_id][i] + g[cell_id][i]; + } + }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Table<double> difference_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + difference_values[cell_id][i] = f[cell_id][i] - g[cell_id][i]; + } + }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + } } - SECTION("DiscreteFunctionP0 lhs") + SECTION("external operators") { - DiscreteFunctionP0<Dimension, double> a{mesh}; + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; parallel_for( mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { const double x = xj[cell_id][0]; const double y = xj[cell_id][1]; const double z = xj[cell_id][2]; - a[cell_id] = 2 * x + 1 - y * z; - }); - - Table<double> product_values{mesh->numberOfCells(), size}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { for (size_t i = 0; i < size; ++i) { - product_values[cell_id][i] = a[cell_id] * f[cell_id][i]; + f[cell_id][i] = std::abs(2 * x) + i * y + z; } }); - REQUIRE(same_values(a * f, product_values)); - REQUIRE(same_values(a * const_f, product_values)); - - DiscreteFunctionP0<Dimension, const double> const_a = a; - REQUIRE(same_values(const_a * f, product_values)); - REQUIRE(same_values(const_a * const_f, product_values)); + DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + + SECTION("product") + { + SECTION("scalar lhs") + { + const double a = 3.2; + Table<double> product_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + product_values[cell_id][i] = a * f[cell_id][i]; + } + }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + SECTION("DiscreteFunctionP0 lhs") + { + DiscreteFunctionP0<Dimension, double> a{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; + a[cell_id] = 2 * x + 1 - y * z; + }); + + Table<double> product_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + product_values[cell_id][i] = a[cell_id] * f[cell_id][i]; + } + }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + + DiscreteFunctionP0<Dimension, const double> const_a = a; + REQUIRE(same_values(const_a * f, product_values)); + REQUIRE(same_values(const_a * const_f, product_values)); + } + } } } } diff --git a/tests/test_DiscreteFunctionUtils.cpp b/tests/test_DiscreteFunctionUtils.cpp index 511714ed72e367dad950959953199c0f3cba05e3..88ddd4025980c0edafe28966b78a8612e8360a80 100644 --- a/tests/test_DiscreteFunctionUtils.cpp +++ b/tests/test_DiscreteFunctionUtils.cpp @@ -16,144 +16,150 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") { constexpr size_t Dimension = 1; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian1DMesh(); - std::shared_ptr mesh_copy = - std::make_shared<std::decay_t<decltype(*mesh)>>(mesh->shared_connectivity(), mesh->xr()); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - SECTION("common mesh") - { - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr vh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr wh = std::make_shared<DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh); + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + std::shared_ptr mesh_copy = + std::make_shared<std::decay_t<decltype(*mesh)>>(mesh->shared_connectivity(), mesh->xr()); - std::shared_ptr qh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_copy); + SECTION("common mesh") + { + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); + std::shared_ptr vh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); + std::shared_ptr wh = std::make_shared<DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh); - REQUIRE(getCommonMesh({uh, vh, wh}).get() == mesh.get()); - REQUIRE(getCommonMesh({uh, vh, wh, qh}).use_count() == 0); - } + std::shared_ptr qh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_copy); - SECTION("check discretization type") - { - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr vh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - - std::shared_ptr qh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_copy); - - std::shared_ptr Uh = std::make_shared<DiscreteFunctionP0Vector<Dimension, double>>(mesh, 3); - std::shared_ptr Vh = std::make_shared<DiscreteFunctionP0Vector<Dimension, double>>(mesh, 3); - - REQUIRE(checkDiscretizationType({uh}, DiscreteFunctionType::P0)); - REQUIRE(checkDiscretizationType({uh, vh, qh}, DiscreteFunctionType::P0)); - REQUIRE(not checkDiscretizationType({uh}, DiscreteFunctionType::P0Vector)); - REQUIRE(not checkDiscretizationType({uh, vh, qh}, DiscreteFunctionType::P0Vector)); - REQUIRE(checkDiscretizationType({Uh}, DiscreteFunctionType::P0Vector)); - REQUIRE(checkDiscretizationType({Uh, Vh}, DiscreteFunctionType::P0Vector)); - REQUIRE(not checkDiscretizationType({Uh, Vh}, DiscreteFunctionType::P0)); - REQUIRE(not checkDiscretizationType({Uh}, DiscreteFunctionType::P0)); - } + REQUIRE(getCommonMesh({uh, vh, wh}).get() == mesh.get()); + REQUIRE(getCommonMesh({uh, vh, wh, qh}).use_count() == 0); + } - SECTION("scalar function shallow copy") - { - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("check discretization type") + { + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); + std::shared_ptr vh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - REQUIRE(uh == vh); + std::shared_ptr qh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_copy); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + std::shared_ptr Uh = std::make_shared<DiscreteFunctionP0Vector<Dimension, double>>(mesh, 3); + std::shared_ptr Vh = std::make_shared<DiscreteFunctionP0Vector<Dimension, double>>(mesh, 3); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*wh).cellValues()[CellId{0}])); - } + REQUIRE(checkDiscretizationType({uh}, DiscreteFunctionType::P0)); + REQUIRE(checkDiscretizationType({uh, vh, qh}, DiscreteFunctionType::P0)); + REQUIRE(not checkDiscretizationType({uh}, DiscreteFunctionType::P0Vector)); + REQUIRE(not checkDiscretizationType({uh, vh, qh}, DiscreteFunctionType::P0Vector)); + REQUIRE(checkDiscretizationType({Uh}, DiscreteFunctionType::P0Vector)); + REQUIRE(checkDiscretizationType({Uh, Vh}, DiscreteFunctionType::P0Vector)); + REQUIRE(not checkDiscretizationType({Uh, Vh}, DiscreteFunctionType::P0)); + REQUIRE(not checkDiscretizationType({Uh}, DiscreteFunctionType::P0)); + } - SECTION("R^1 function shallow copy") - { - using DataType = TinyVector<1>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("scalar function shallow copy") + { + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); - REQUIRE(uh == vh); + REQUIRE(uh == vh); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + std::shared_ptr wh = shallowCopy(mesh_copy, uh); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); - } + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*wh).cellValues()[CellId{0}])); + } - SECTION("R^2 function shallow copy") - { - using DataType = TinyVector<2>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("R^1 function shallow copy") + { + using DataType = TinyVector<1>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); - REQUIRE(uh == vh); + REQUIRE(uh == vh); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + std::shared_ptr wh = shallowCopy(mesh_copy, uh); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); - } + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + } - SECTION("R^3 function shallow copy") - { - using DataType = TinyVector<3>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("R^2 function shallow copy") + { + using DataType = TinyVector<2>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); - REQUIRE(uh == vh); + REQUIRE(uh == vh); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + std::shared_ptr wh = shallowCopy(mesh_copy, uh); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); - } + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + } - SECTION("R^1x1 function shallow copy") - { - using DataType = TinyMatrix<1>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("R^3 function shallow copy") + { + using DataType = TinyVector<3>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); - REQUIRE(uh == vh); + REQUIRE(uh == vh); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + std::shared_ptr wh = shallowCopy(mesh_copy, uh); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); - } + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + } - SECTION("R^2x2 function shallow copy") - { - using DataType = TinyMatrix<2>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("R^1x1 function shallow copy") + { + using DataType = TinyMatrix<1>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); - REQUIRE(uh == vh); + REQUIRE(uh == vh); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + std::shared_ptr wh = shallowCopy(mesh_copy, uh); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); - } + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + } - SECTION("R^3x3 function shallow copy") - { - using DataType = TinyMatrix<3>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("R^2x2 function shallow copy") + { + using DataType = TinyMatrix<2>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); + + REQUIRE(uh == vh); + + std::shared_ptr wh = shallowCopy(mesh_copy, uh); + + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + } - REQUIRE(uh == vh); + SECTION("R^3x3 function shallow copy") + { + using DataType = TinyMatrix<3>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + REQUIRE(uh == vh); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + std::shared_ptr wh = shallowCopy(mesh_copy, uh); + + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + } + } } } @@ -161,144 +167,150 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") { constexpr size_t Dimension = 2; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian2DMesh(); - std::shared_ptr mesh_copy = - std::make_shared<std::decay_t<decltype(*mesh)>>(mesh->shared_connectivity(), mesh->xr()); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - SECTION("common mesh") - { - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr vh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr wh = std::make_shared<DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh); + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + std::shared_ptr mesh_copy = + std::make_shared<std::decay_t<decltype(*mesh)>>(mesh->shared_connectivity(), mesh->xr()); - std::shared_ptr qh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_copy); + SECTION("common mesh") + { + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); + std::shared_ptr vh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); + std::shared_ptr wh = std::make_shared<DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh); - REQUIRE(getCommonMesh({uh, vh, wh}).get() == mesh.get()); - REQUIRE(getCommonMesh({uh, vh, wh, qh}).use_count() == 0); - } + std::shared_ptr qh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_copy); - SECTION("check discretization type") - { - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr vh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - - std::shared_ptr qh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_copy); - - std::shared_ptr Uh = std::make_shared<DiscreteFunctionP0Vector<Dimension, double>>(mesh, 3); - std::shared_ptr Vh = std::make_shared<DiscreteFunctionP0Vector<Dimension, double>>(mesh, 3); - - REQUIRE(checkDiscretizationType({uh}, DiscreteFunctionType::P0)); - REQUIRE(checkDiscretizationType({uh, vh, qh}, DiscreteFunctionType::P0)); - REQUIRE(not checkDiscretizationType({uh}, DiscreteFunctionType::P0Vector)); - REQUIRE(not checkDiscretizationType({uh, vh, qh}, DiscreteFunctionType::P0Vector)); - REQUIRE(checkDiscretizationType({Uh}, DiscreteFunctionType::P0Vector)); - REQUIRE(checkDiscretizationType({Uh, Vh}, DiscreteFunctionType::P0Vector)); - REQUIRE(not checkDiscretizationType({Uh, Vh}, DiscreteFunctionType::P0)); - REQUIRE(not checkDiscretizationType({Uh}, DiscreteFunctionType::P0)); - } + REQUIRE(getCommonMesh({uh, vh, wh}).get() == mesh.get()); + REQUIRE(getCommonMesh({uh, vh, wh, qh}).use_count() == 0); + } - SECTION("scalar function shallow copy") - { - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("check discretization type") + { + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); + std::shared_ptr vh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - REQUIRE(uh == vh); + std::shared_ptr qh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_copy); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + std::shared_ptr Uh = std::make_shared<DiscreteFunctionP0Vector<Dimension, double>>(mesh, 3); + std::shared_ptr Vh = std::make_shared<DiscreteFunctionP0Vector<Dimension, double>>(mesh, 3); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*wh).cellValues()[CellId{0}])); - } + REQUIRE(checkDiscretizationType({uh}, DiscreteFunctionType::P0)); + REQUIRE(checkDiscretizationType({uh, vh, qh}, DiscreteFunctionType::P0)); + REQUIRE(not checkDiscretizationType({uh}, DiscreteFunctionType::P0Vector)); + REQUIRE(not checkDiscretizationType({uh, vh, qh}, DiscreteFunctionType::P0Vector)); + REQUIRE(checkDiscretizationType({Uh}, DiscreteFunctionType::P0Vector)); + REQUIRE(checkDiscretizationType({Uh, Vh}, DiscreteFunctionType::P0Vector)); + REQUIRE(not checkDiscretizationType({Uh, Vh}, DiscreteFunctionType::P0)); + REQUIRE(not checkDiscretizationType({Uh}, DiscreteFunctionType::P0)); + } - SECTION("R^1 function shallow copy") - { - using DataType = TinyVector<1>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("scalar function shallow copy") + { + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); - REQUIRE(uh == vh); + REQUIRE(uh == vh); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + std::shared_ptr wh = shallowCopy(mesh_copy, uh); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); - } + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*wh).cellValues()[CellId{0}])); + } - SECTION("R^2 function shallow copy") - { - using DataType = TinyVector<2>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("R^1 function shallow copy") + { + using DataType = TinyVector<1>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); - REQUIRE(uh == vh); + REQUIRE(uh == vh); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + std::shared_ptr wh = shallowCopy(mesh_copy, uh); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); - } + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + } - SECTION("R^3 function shallow copy") - { - using DataType = TinyVector<3>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("R^2 function shallow copy") + { + using DataType = TinyVector<2>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); - REQUIRE(uh == vh); + REQUIRE(uh == vh); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + std::shared_ptr wh = shallowCopy(mesh_copy, uh); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); - } + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + } - SECTION("R^1x1 function shallow copy") - { - using DataType = TinyMatrix<1>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("R^3 function shallow copy") + { + using DataType = TinyVector<3>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); - REQUIRE(uh == vh); + REQUIRE(uh == vh); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + std::shared_ptr wh = shallowCopy(mesh_copy, uh); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); - } + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + } - SECTION("R^2x2 function shallow copy") - { - using DataType = TinyMatrix<2>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("R^1x1 function shallow copy") + { + using DataType = TinyMatrix<1>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); - REQUIRE(uh == vh); + REQUIRE(uh == vh); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + std::shared_ptr wh = shallowCopy(mesh_copy, uh); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); - } + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + } - SECTION("R^3x3 function shallow copy") - { - using DataType = TinyMatrix<3>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("R^2x2 function shallow copy") + { + using DataType = TinyMatrix<2>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); + + REQUIRE(uh == vh); + + std::shared_ptr wh = shallowCopy(mesh_copy, uh); - REQUIRE(uh == vh); + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + } - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + SECTION("R^3x3 function shallow copy") + { + using DataType = TinyMatrix<3>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(uh == vh); + + std::shared_ptr wh = shallowCopy(mesh_copy, uh); + + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + } + } } } @@ -306,144 +318,150 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") { constexpr size_t Dimension = 3; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian3DMesh(); - std::shared_ptr mesh_copy = - std::make_shared<std::decay_t<decltype(*mesh)>>(mesh->shared_connectivity(), mesh->xr()); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - SECTION("common mesh") - { - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr vh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr wh = std::make_shared<DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh); + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + std::shared_ptr mesh_copy = + std::make_shared<std::decay_t<decltype(*mesh)>>(mesh->shared_connectivity(), mesh->xr()); - std::shared_ptr qh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_copy); + SECTION("common mesh") + { + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); + std::shared_ptr vh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); + std::shared_ptr wh = std::make_shared<DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh); - REQUIRE(getCommonMesh({uh, vh, wh}).get() == mesh.get()); - REQUIRE(getCommonMesh({uh, vh, wh, qh}).use_count() == 0); - } + std::shared_ptr qh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_copy); - SECTION("check discretization type") - { - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr vh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - - std::shared_ptr qh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_copy); - - std::shared_ptr Uh = std::make_shared<DiscreteFunctionP0Vector<Dimension, double>>(mesh, 3); - std::shared_ptr Vh = std::make_shared<DiscreteFunctionP0Vector<Dimension, double>>(mesh, 3); - - REQUIRE(checkDiscretizationType({uh}, DiscreteFunctionType::P0)); - REQUIRE(checkDiscretizationType({uh, vh, qh}, DiscreteFunctionType::P0)); - REQUIRE(not checkDiscretizationType({uh}, DiscreteFunctionType::P0Vector)); - REQUIRE(not checkDiscretizationType({uh, vh, qh}, DiscreteFunctionType::P0Vector)); - REQUIRE(checkDiscretizationType({Uh}, DiscreteFunctionType::P0Vector)); - REQUIRE(checkDiscretizationType({Uh, Vh}, DiscreteFunctionType::P0Vector)); - REQUIRE(not checkDiscretizationType({Uh, Vh}, DiscreteFunctionType::P0)); - REQUIRE(not checkDiscretizationType({Uh}, DiscreteFunctionType::P0)); - } + REQUIRE(getCommonMesh({uh, vh, wh}).get() == mesh.get()); + REQUIRE(getCommonMesh({uh, vh, wh, qh}).use_count() == 0); + } - SECTION("scalar function shallow copy") - { - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("check discretization type") + { + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); + std::shared_ptr vh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - REQUIRE(uh == vh); + std::shared_ptr qh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_copy); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + std::shared_ptr Uh = std::make_shared<DiscreteFunctionP0Vector<Dimension, double>>(mesh, 3); + std::shared_ptr Vh = std::make_shared<DiscreteFunctionP0Vector<Dimension, double>>(mesh, 3); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*wh).cellValues()[CellId{0}])); - } + REQUIRE(checkDiscretizationType({uh}, DiscreteFunctionType::P0)); + REQUIRE(checkDiscretizationType({uh, vh, qh}, DiscreteFunctionType::P0)); + REQUIRE(not checkDiscretizationType({uh}, DiscreteFunctionType::P0Vector)); + REQUIRE(not checkDiscretizationType({uh, vh, qh}, DiscreteFunctionType::P0Vector)); + REQUIRE(checkDiscretizationType({Uh}, DiscreteFunctionType::P0Vector)); + REQUIRE(checkDiscretizationType({Uh, Vh}, DiscreteFunctionType::P0Vector)); + REQUIRE(not checkDiscretizationType({Uh, Vh}, DiscreteFunctionType::P0)); + REQUIRE(not checkDiscretizationType({Uh}, DiscreteFunctionType::P0)); + } - SECTION("R^1 function shallow copy") - { - using DataType = TinyVector<1>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("scalar function shallow copy") + { + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); - REQUIRE(uh == vh); + REQUIRE(uh == vh); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + std::shared_ptr wh = shallowCopy(mesh_copy, uh); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); - } + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*wh).cellValues()[CellId{0}])); + } - SECTION("R^2 function shallow copy") - { - using DataType = TinyVector<2>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("R^1 function shallow copy") + { + using DataType = TinyVector<1>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); - REQUIRE(uh == vh); + REQUIRE(uh == vh); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + std::shared_ptr wh = shallowCopy(mesh_copy, uh); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); - } + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + } - SECTION("R^3 function shallow copy") - { - using DataType = TinyVector<3>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("R^2 function shallow copy") + { + using DataType = TinyVector<2>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); - REQUIRE(uh == vh); + REQUIRE(uh == vh); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + std::shared_ptr wh = shallowCopy(mesh_copy, uh); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); - } + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + } - SECTION("R^1x1 function shallow copy") - { - using DataType = TinyMatrix<1>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("R^3 function shallow copy") + { + using DataType = TinyVector<3>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); - REQUIRE(uh == vh); + REQUIRE(uh == vh); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + std::shared_ptr wh = shallowCopy(mesh_copy, uh); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); - } + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + } - SECTION("R^2x2 function shallow copy") - { - using DataType = TinyMatrix<2>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("R^1x1 function shallow copy") + { + using DataType = TinyMatrix<1>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); - REQUIRE(uh == vh); + REQUIRE(uh == vh); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + std::shared_ptr wh = shallowCopy(mesh_copy, uh); - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); - } + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + } - SECTION("R^3x3 function shallow copy") - { - using DataType = TinyMatrix<3>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); - std::shared_ptr vh = shallowCopy(mesh, uh); + SECTION("R^2x2 function shallow copy") + { + using DataType = TinyMatrix<2>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); + + REQUIRE(uh == vh); - REQUIRE(uh == vh); + std::shared_ptr wh = shallowCopy(mesh_copy, uh); - std::shared_ptr wh = shallowCopy(mesh_copy, uh); + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + } - REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + SECTION("R^3x3 function shallow copy") + { + using DataType = TinyMatrix<3>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + std::shared_ptr vh = shallowCopy(mesh, uh); + + REQUIRE(uh == vh); + + std::shared_ptr wh = shallowCopy(mesh_copy, uh); + + REQUIRE(uh != wh); + REQUIRE(&(uh->cellValues()[CellId{0}]) == + &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + } + } } } @@ -453,13 +471,19 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") { constexpr size_t Dimension = 1; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian1DMesh(); - std::shared_ptr other_mesh = - CartesianMeshBuilder{TinyVector<1>{-1}, TinyVector<1>{3}, TinyVector<1, size_t>{19}}.mesh(); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); + + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + std::shared_ptr other_mesh = + CartesianMeshBuilder{TinyVector<1>{-1}, TinyVector<1>{3}, TinyVector<1, size_t>{19}}.mesh(); - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); + std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - REQUIRE_THROWS_WITH(shallowCopy(other_mesh, uh), "error: cannot shallow copy when connectivity changes"); + REQUIRE_THROWS_WITH(shallowCopy(other_mesh, uh), "error: cannot shallow copy when connectivity changes"); + } + } } SECTION("incompatible mesh dimension") diff --git a/tests/test_DiscreteFunctionVectorInterpoler.cpp b/tests/test_DiscreteFunctionVectorInterpoler.cpp index 95d5ce5d8401e2c9b5c04002aac17129aa5668e9..c0f28f11409dcf89bd3c8bffbfcff8e8be7fb0a8 100644 --- a/tests/test_DiscreteFunctionVectorInterpoler.cpp +++ b/tests/test_DiscreteFunctionVectorInterpoler.cpp @@ -53,296 +53,330 @@ TEST_CASE("DiscreteFunctionVectorInterpoler", "[scheme]") { constexpr size_t Dimension = 1; - const auto& mesh_1d = MeshDataBaseForTests::get().cartesian1DMesh(); - auto xj = MeshDataManager::instance().getMeshData(*mesh_1d).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - std::string_view data = R"( + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh_1d).xj(); + + std::string_view data = R"( import math; let B_scalar_non_linear_1d: R^1 -> B, x -> (exp(2 * x[0]) + 3 > 4); let N_scalar_non_linear_1d: R^1 -> N, x -> floor(3 * x[0] * x[0] + 2); let Z_scalar_non_linear_1d: R^1 -> Z, x -> floor(exp(2 * x[0]) - 1); let R_scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; )"; - 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}; - - ASTNodeTypeCleaner<language::var_declaration>{*ast}; - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; - ASTNodeExpressionBuilder{*ast}; - - TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point - - std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; - - std::vector<FunctionSymbolId> function_id_list; - register_function(position, symbol_table, "B_scalar_non_linear_1d", function_id_list); - register_function(position, symbol_table, "N_scalar_non_linear_1d", function_id_list); - register_function(position, symbol_table, "Z_scalar_non_linear_1d", function_id_list); - register_function(position, symbol_table, "R_scalar_non_linear_1d", function_id_list); - - DiscreteFunctionVectorInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), - function_id_list); - std::shared_ptr discrete_function = interpoler.interpolate(); - - size_t i = 0; - - { - CellValue<double> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = std::exp(2 * x[0]) + 3 > 4; - }); - - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); - } - - { - CellValue<double> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = std::floor(3 * x[0] * x[0] + 2); - }); - - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); - } - - { - CellValue<double> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = std::floor(std::exp(2 * x[0]) - 1); - }); - - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); - } - - { - CellValue<double> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = 2 * std::exp(x[0]) + 3; - }); - - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + 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}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + std::vector<FunctionSymbolId> function_id_list; + register_function(position, symbol_table, "B_scalar_non_linear_1d", function_id_list); + register_function(position, symbol_table, "N_scalar_non_linear_1d", function_id_list); + register_function(position, symbol_table, "Z_scalar_non_linear_1d", function_id_list); + register_function(position, symbol_table, "R_scalar_non_linear_1d", function_id_list); + + DiscreteFunctionVectorInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), + function_id_list); + std::shared_ptr discrete_function = interpoler.interpolate(); + + size_t i = 0; + + { + CellValue<double> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = std::exp(2 * x[0]) + 3 > 4; + }); + + REQUIRE( + same_cell_value(cell_value, i++, + dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + } + + { + CellValue<double> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = std::floor(3 * x[0] * x[0] + 2); + }); + + REQUIRE( + same_cell_value(cell_value, i++, + dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + } + + { + CellValue<double> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = std::floor(std::exp(2 * x[0]) - 1); + }); + + REQUIRE( + same_cell_value(cell_value, i++, + dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + } + + { + CellValue<double> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = 2 * std::exp(x[0]) + 3; + }); + + REQUIRE( + same_cell_value(cell_value, i++, + dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + } + + REQUIRE(i == function_id_list.size()); + } } - - REQUIRE(i == function_id_list.size()); } SECTION("2D") { constexpr size_t Dimension = 2; - const auto& mesh_2d = MeshDataBaseForTests::get().cartesian2DMesh(); - auto xj = MeshDataManager::instance().getMeshData(*mesh_2d).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); + + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh_2d).xj(); - std::string_view data = R"( + std::string_view data = R"( import math; let B_scalar_non_linear_2d: R^2 -> B, x -> (exp(2 * x[0]) + 3 > 4); let N_scalar_non_linear_2d: R^2 -> N, x -> floor(3 * (x[0] * x[1]) * (x[0] * x[1]) + 2); let Z_scalar_non_linear_2d: R^2 -> Z, x -> floor(exp(2 * x[1]) - 1); let R_scalar_non_linear_2d: R^2 -> R, x -> 2 * exp(x[0] + x[1]) + 3; )"; - 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}; - - ASTNodeTypeCleaner<language::var_declaration>{*ast}; - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; - ASTNodeExpressionBuilder{*ast}; - - TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point - - std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; - - std::vector<FunctionSymbolId> function_id_list; - register_function(position, symbol_table, "B_scalar_non_linear_2d", function_id_list); - register_function(position, symbol_table, "N_scalar_non_linear_2d", function_id_list); - register_function(position, symbol_table, "Z_scalar_non_linear_2d", function_id_list); - register_function(position, symbol_table, "R_scalar_non_linear_2d", function_id_list); - - DiscreteFunctionVectorInterpoler interpoler(mesh_2d, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), - function_id_list); - std::shared_ptr discrete_function = interpoler.interpolate(); - - size_t i = 0; - - { - CellValue<double> cell_value{mesh_2d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = std::exp(2 * x[0]) + 3 > 4; - }); - - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); - } - - { - CellValue<double> cell_value{mesh_2d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = std::floor(3 * (x[0] * x[1]) * (x[0] * x[1]) + 2); - }); - - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); - } - - { - CellValue<double> cell_value{mesh_2d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = std::floor(std::exp(2 * x[1]) - 1); - }); - - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); - } - - { - CellValue<double> cell_value{mesh_2d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = 2 * std::exp(x[0] + x[1]) + 3; - }); - - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + 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}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + std::vector<FunctionSymbolId> function_id_list; + register_function(position, symbol_table, "B_scalar_non_linear_2d", function_id_list); + register_function(position, symbol_table, "N_scalar_non_linear_2d", function_id_list); + register_function(position, symbol_table, "Z_scalar_non_linear_2d", function_id_list); + register_function(position, symbol_table, "R_scalar_non_linear_2d", function_id_list); + + DiscreteFunctionVectorInterpoler interpoler(mesh_2d, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), + function_id_list); + std::shared_ptr discrete_function = interpoler.interpolate(); + + size_t i = 0; + + { + CellValue<double> cell_value{mesh_2d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = std::exp(2 * x[0]) + 3 > 4; + }); + + REQUIRE( + same_cell_value(cell_value, i++, + dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + } + + { + CellValue<double> cell_value{mesh_2d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = std::floor(3 * (x[0] * x[1]) * (x[0] * x[1]) + 2); + }); + + REQUIRE( + same_cell_value(cell_value, i++, + dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + } + + { + CellValue<double> cell_value{mesh_2d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = std::floor(std::exp(2 * x[1]) - 1); + }); + + REQUIRE( + same_cell_value(cell_value, i++, + dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + } + + { + CellValue<double> cell_value{mesh_2d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = 2 * std::exp(x[0] + x[1]) + 3; + }); + + REQUIRE( + same_cell_value(cell_value, i++, + dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + } + + REQUIRE(i == function_id_list.size()); + } } - - REQUIRE(i == function_id_list.size()); } SECTION("3D") { constexpr size_t Dimension = 3; - const auto& mesh_3d = MeshDataBaseForTests::get().cartesian3DMesh(); - auto xj = MeshDataManager::instance().getMeshData(*mesh_3d).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - std::string_view data = R"( + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh_3d).xj(); + + std::string_view data = R"( import math; let B_scalar_non_linear_3d: R^3 -> B, x -> (exp(2 * x[0] + x[2]) + 3 > 4); let N_scalar_non_linear_3d: R^3 -> N, x -> floor(3 * (x[0] * x[1]) * (x[0] * x[1]) + 2); let Z_scalar_non_linear_3d: R^3 -> Z, x -> floor(exp(2 * x[1]) - x[2]); let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; )"; - 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}; - - ASTNodeTypeCleaner<language::var_declaration>{*ast}; - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; - ASTNodeExpressionBuilder{*ast}; - - TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point - - std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; - - std::vector<FunctionSymbolId> function_id_list; - register_function(position, symbol_table, "B_scalar_non_linear_3d", function_id_list); - register_function(position, symbol_table, "N_scalar_non_linear_3d", function_id_list); - register_function(position, symbol_table, "Z_scalar_non_linear_3d", function_id_list); - register_function(position, symbol_table, "R_scalar_non_linear_3d", function_id_list); - - DiscreteFunctionVectorInterpoler interpoler(mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), - function_id_list); - std::shared_ptr discrete_function = interpoler.interpolate(); - - size_t i = 0; - - { - CellValue<double> cell_value{mesh_3d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = std::exp(2 * x[0] + x[2]) + 3 > 4; - }); - - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); - } - - { - CellValue<double> cell_value{mesh_3d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = std::floor(3 * (x[0] * x[1]) * (x[0] * x[1]) + 2); - }); - - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); - } - - { - CellValue<double> cell_value{mesh_3d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = std::floor(std::exp(2 * x[1]) - x[2]); - }); - - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); - } - - { - CellValue<double> cell_value{mesh_3d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = 2 * std::exp(x[0] + x[1]) + 3 * x[2]; - }); - - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + 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}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + std::vector<FunctionSymbolId> function_id_list; + register_function(position, symbol_table, "B_scalar_non_linear_3d", function_id_list); + register_function(position, symbol_table, "N_scalar_non_linear_3d", function_id_list); + register_function(position, symbol_table, "Z_scalar_non_linear_3d", function_id_list); + register_function(position, symbol_table, "R_scalar_non_linear_3d", function_id_list); + + DiscreteFunctionVectorInterpoler interpoler(mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), + function_id_list); + std::shared_ptr discrete_function = interpoler.interpolate(); + + size_t i = 0; + + { + CellValue<double> cell_value{mesh_3d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = std::exp(2 * x[0] + x[2]) + 3 > 4; + }); + + REQUIRE( + same_cell_value(cell_value, i++, + dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + } + + { + CellValue<double> cell_value{mesh_3d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = std::floor(3 * (x[0] * x[1]) * (x[0] * x[1]) + 2); + }); + + REQUIRE( + same_cell_value(cell_value, i++, + dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + } + + { + CellValue<double> cell_value{mesh_3d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = std::floor(std::exp(2 * x[1]) - x[2]); + }); + + REQUIRE( + same_cell_value(cell_value, i++, + dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + } + + { + CellValue<double> cell_value{mesh_3d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = 2 * std::exp(x[0] + x[1]) + 3 * x[2]; + }); + + REQUIRE( + same_cell_value(cell_value, i++, + dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + } + + REQUIRE(i == function_id_list.size()); + } } - - REQUIRE(i == function_id_list.size()); } SECTION("errors") { - const auto& mesh_3d = MeshDataBaseForTests::get().cartesian3DMesh(); - auto xj = MeshDataManager::instance().getMeshData(*mesh_3d).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - std::string_view data = R"( + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh_3d).xj(); + + std::string_view data = R"( import math; let B_scalar_non_linear_2d: R^2 -> B, x -> (exp(2 * x[0] + x[1]) + 3 > 4); let N_scalar_non_linear_1d: R^1 -> N, x -> floor(3 * x[0] * x[0] + 2); @@ -350,65 +384,67 @@ let Z_scalar_non_linear_3d: R^3 -> Z, x -> floor(exp(2 * x[1]) - x[2]); let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; let R2_scalar_non_linear_3d: R^3 -> R^2, x -> (2 * exp(x[0] + x[1]) + 3 * x[2], x[0] - x[1]); )"; - TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; - auto ast = ASTBuilder::build(input); + auto ast = ASTBuilder::build(input); - ASTModulesImporter{*ast}; - ASTNodeTypeCleaner<language::import_instruction>{*ast}; + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; - ASTSymbolTableBuilder{*ast}; - ASTNodeDataTypeBuilder{*ast}; + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; - ASTNodeTypeCleaner<language::var_declaration>{*ast}; - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; - ASTNodeExpressionBuilder{*ast}; + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; - TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point - std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; - SECTION("invalid function type") - { - std::vector<FunctionSymbolId> function_id_list; - register_function(position, symbol_table, "B_scalar_non_linear_2d", function_id_list); - register_function(position, symbol_table, "N_scalar_non_linear_1d", function_id_list); - register_function(position, symbol_table, "Z_scalar_non_linear_3d", function_id_list); - register_function(position, symbol_table, "R_scalar_non_linear_3d", function_id_list); + SECTION("invalid function type") + { + std::vector<FunctionSymbolId> function_id_list; + register_function(position, symbol_table, "B_scalar_non_linear_2d", function_id_list); + register_function(position, symbol_table, "N_scalar_non_linear_1d", function_id_list); + register_function(position, symbol_table, "Z_scalar_non_linear_3d", function_id_list); + register_function(position, symbol_table, "R_scalar_non_linear_3d", function_id_list); - DiscreteFunctionVectorInterpoler interpoler(mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), - function_id_list); + DiscreteFunctionVectorInterpoler interpoler(mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), + function_id_list); - const std::string error_msg = R"(error: invalid function type + const std::string error_msg = R"(error: invalid function type note: expecting R^3 -> R note: provided function B_scalar_non_linear_2d: R^2 -> B)"; - REQUIRE_THROWS_WITH(interpoler.interpolate(), error_msg); - } + REQUIRE_THROWS_WITH(interpoler.interpolate(), error_msg); + } - SECTION("invalid value type") - { - std::vector<FunctionSymbolId> function_id_list; - register_function(position, symbol_table, "Z_scalar_non_linear_3d", function_id_list); - register_function(position, symbol_table, "R_scalar_non_linear_3d", function_id_list); - register_function(position, symbol_table, "R2_scalar_non_linear_3d", function_id_list); + SECTION("invalid value type") + { + std::vector<FunctionSymbolId> function_id_list; + register_function(position, symbol_table, "Z_scalar_non_linear_3d", function_id_list); + register_function(position, symbol_table, "R_scalar_non_linear_3d", function_id_list); + register_function(position, symbol_table, "R2_scalar_non_linear_3d", function_id_list); - DiscreteFunctionVectorInterpoler interpoler(mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), - function_id_list); + DiscreteFunctionVectorInterpoler interpoler(mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), + function_id_list); - const std::string error_msg = R"(error: vector functions require scalar value type. + const std::string error_msg = R"(error: vector functions require scalar value type. Invalid interpolation value type: R^2)"; - REQUIRE_THROWS_WITH(interpoler.interpolate(), error_msg); - } + REQUIRE_THROWS_WITH(interpoler.interpolate(), error_msg); + } - SECTION("invalid discrete function type") - { - const std::string error_msg = "error: invalid discrete function type for vector interpolation"; + SECTION("invalid discrete function type") + { + const std::string error_msg = "error: invalid discrete function type for vector interpolation"; - DiscreteFunctionVectorInterpoler interpoler{mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0>(), {}}; - REQUIRE_THROWS_WITH(interpoler.interpolate(), error_msg); + DiscreteFunctionVectorInterpoler interpoler{mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0>(), {}}; + REQUIRE_THROWS_WITH(interpoler.interpolate(), error_msg); + } + } } } } diff --git a/tests/test_EmbeddedIDiscreteFunctionMathFunctions.cpp b/tests/test_EmbeddedIDiscreteFunctionMathFunctions.cpp index f835d1597389b456f90f3e236eec5c25f78e0475..76dae30b70ce901a94b158df6a04437b1ca1f92b 100644 --- a/tests/test_EmbeddedIDiscreteFunctionMathFunctions.cpp +++ b/tests/test_EmbeddedIDiscreteFunctionMathFunctions.cpp @@ -109,494 +109,504 @@ TEST_CASE("EmbeddedIDiscreteFunctionMathFunctions", "[scheme]") using Rd = TinyVector<Dimension>; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian1DMesh(); - - std::shared_ptr other_mesh = - std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); - - CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - CellValue<double> values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - CellValue<double> positive_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 2 + std::sin(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - CellValue<double> bounded_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.9 * std::sin(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - std::shared_ptr p_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, values); - std::shared_ptr p_other_mesh_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(other_mesh, values); - std::shared_ptr p_positive_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, positive_values); - std::shared_ptr p_bounded_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, bounded_values); - - std::shared_ptr p_R1_u = [=] { - CellValue<TinyVector<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R1_v = [=] { - CellValue<TinyVector<1>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R1_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(other_mesh, p_R1_u->cellValues()); - - constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { - if constexpr (Dimension == 1) { - return {x[0], 1 + x[0] * x[0]}; - } else if constexpr (Dimension == 2) { - return {x[0], x[1]}; - } else if constexpr (Dimension == 3) { - return {x[0], x[1] + x[2]}; - } - }; - - std::shared_ptr p_R2_u = [=] { - CellValue<TinyVector<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - uj[cell_id] = {2 * x[0] + 1, 1 - x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R2_v = [=] { - CellValue<TinyVector<2>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R2_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(other_mesh, p_R2_u->cellValues()); - - constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { - if constexpr (Dimension == 1) { - return {x[0], 1 + x[0] * x[0], 2 - x[0]}; - } else if constexpr (Dimension == 2) { - return {x[0], x[1], x[0] + x[1]}; - } else if constexpr (Dimension == 3) { - return {x[0], x[1], x[2]}; - } - }; - - std::shared_ptr p_R3_u = [=] { - CellValue<TinyVector<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj[cell_id] = {2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); - }(); - - std::shared_ptr p_R3_v = [=] { - CellValue<TinyVector<3>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R3_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(other_mesh, p_R3_u->cellValues()); - - std::shared_ptr p_R1x1_u = [=] { - CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = {2 * xj[cell_id][0] + 1}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R2x2_u = [=] { - CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - uj[cell_id] = {2 * x[0] + 1, 1 - x[1], // - 2 * x[1], -x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R3x3_u = [=] { - CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - uj[cell_id] = {2 * x[0] + 1, 1 - x[1], 3, // - 2 * x[1], -x[0], x[0] - x[1], // - 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); - }(); - - std::shared_ptr p_Vector3_u = [=] { - CellArray<double> uj_vector{mesh->connectivity(), 3}; - parallel_for( - uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj_vector[cell_id][0] = 2 * x[0] + 1; - uj_vector[cell_id][1] = 1 - x[1] * x[2]; - uj_vector[cell_id][2] = x[0] + x[2]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); - }(); - - std::shared_ptr p_Vector3_v = [=] { - CellArray<double> vj_vector{mesh->connectivity(), 3}; - parallel_for( - vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj_vector[cell_id][0] = x[0] * x[1] + 1; - vj_vector[cell_id][1] = 2 * x[1]; - vj_vector[cell_id][2] = x[2] * x[0]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, vj_vector); - }(); - - std::shared_ptr p_Vector2_w = [=] { - CellArray<double> wj_vector{mesh->connectivity(), 2}; - parallel_for( - wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - wj_vector[cell_id][0] = x[0] + x[1] * 2; - wj_vector[cell_id][1] = x[0] * x[1]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, wj_vector); - }(); - - SECTION("sqrt Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, sqrt); - REQUIRE_THROWS_WITH(sqrt(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - SECTION("abs Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, abs); - REQUIRE_THROWS_WITH(abs(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + std::shared_ptr other_mesh = + std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); + + CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + CellValue<double> values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + CellValue<double> positive_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 2 + std::sin(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + CellValue<double> bounded_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.9 * std::sin(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + std::shared_ptr p_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, values); + std::shared_ptr p_other_mesh_u = + std::make_shared<const DiscreteFunctionP0<Dimension, double>>(other_mesh, values); + std::shared_ptr p_positive_u = + std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, positive_values); + std::shared_ptr p_bounded_u = + std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, bounded_values); + + std::shared_ptr p_R1_u = [=] { + CellValue<TinyVector<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); + }(); + + std::shared_ptr p_R1_v = [=] { + CellValue<TinyVector<1>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, vj); + }(); + + std::shared_ptr p_other_mesh_R1_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(other_mesh, p_R1_u->cellValues()); + + constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { + if constexpr (Dimension == 1) { + return {x[0], 1 + x[0] * x[0]}; + } else if constexpr (Dimension == 2) { + return {x[0], x[1]}; + } else if constexpr (Dimension == 3) { + return {x[0], x[1] + x[2]}; + } + }; + + std::shared_ptr p_R2_u = [=] { + CellValue<TinyVector<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + uj[cell_id] = {2 * x[0] + 1, 1 - x[1]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); + }(); + + std::shared_ptr p_R2_v = [=] { + CellValue<TinyVector<2>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, vj); + }(); + + std::shared_ptr p_other_mesh_R2_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(other_mesh, p_R2_u->cellValues()); + + constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { + if constexpr (Dimension == 1) { + return {x[0], 1 + x[0] * x[0], 2 - x[0]}; + } else if constexpr (Dimension == 2) { + return {x[0], x[1], x[0] + x[1]}; + } else if constexpr (Dimension == 3) { + return {x[0], x[1], x[2]}; + } + }; + + std::shared_ptr p_R3_u = [=] { + CellValue<TinyVector<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj[cell_id] = {2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); + }(); + + std::shared_ptr p_R3_v = [=] { + CellValue<TinyVector<3>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, vj); + }(); + + std::shared_ptr p_other_mesh_R3_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(other_mesh, p_R3_u->cellValues()); + + std::shared_ptr p_R1x1_u = [=] { + CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = {2 * xj[cell_id][0] + 1}; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); + }(); + + std::shared_ptr p_R2x2_u = [=] { + CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + uj[cell_id] = {2 * x[0] + 1, 1 - x[1], // + 2 * x[1], -x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); + }(); + + std::shared_ptr p_R3x3_u = [=] { + CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + uj[cell_id] = {2 * x[0] + 1, 1 - x[1], 3, // + 2 * x[1], -x[0], x[0] - x[1], // + 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); + }(); + + std::shared_ptr p_Vector3_u = [=] { + CellArray<double> uj_vector{mesh->connectivity(), 3}; + parallel_for( + uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj_vector[cell_id][0] = 2 * x[0] + 1; + uj_vector[cell_id][1] = 1 - x[1] * x[2]; + uj_vector[cell_id][2] = x[0] + x[2]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); + }(); + + std::shared_ptr p_Vector3_v = [=] { + CellArray<double> vj_vector{mesh->connectivity(), 3}; + parallel_for( + vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj_vector[cell_id][0] = x[0] * x[1] + 1; + vj_vector[cell_id][1] = 2 * x[1]; + vj_vector[cell_id][2] = x[2] * x[0]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, vj_vector); + }(); + + std::shared_ptr p_Vector2_w = [=] { + CellArray<double> wj_vector{mesh->connectivity(), 2}; + parallel_for( + wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + wj_vector[cell_id][0] = x[0] + x[1] * 2; + wj_vector[cell_id][1] = x[0] * x[1]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, wj_vector); + }(); + + SECTION("sqrt Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, sqrt); + REQUIRE_THROWS_WITH(sqrt(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("sin Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, sin); - REQUIRE_THROWS_WITH(sin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("abs Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, abs); + REQUIRE_THROWS_WITH(abs(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("cos Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, cos); - REQUIRE_THROWS_WITH(cos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("sin Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, sin); + REQUIRE_THROWS_WITH(sin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("tan Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, tan); - REQUIRE_THROWS_WITH(tan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("cos Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, cos); + REQUIRE_THROWS_WITH(cos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("asin Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, asin); - REQUIRE_THROWS_WITH(asin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("tan Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, tan); + REQUIRE_THROWS_WITH(tan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("acos Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, acos); - REQUIRE_THROWS_WITH(acos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("asin Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, asin); + REQUIRE_THROWS_WITH(asin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("atan Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, atan); - REQUIRE_THROWS_WITH(atan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("acos Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, acos); + REQUIRE_THROWS_WITH(acos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("sinh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, sinh); - REQUIRE_THROWS_WITH(sinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("atan Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, atan); + REQUIRE_THROWS_WITH(atan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("cosh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, cosh); - REQUIRE_THROWS_WITH(cosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("sinh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, sinh); + REQUIRE_THROWS_WITH(sinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("tanh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, tanh); - REQUIRE_THROWS_WITH(tanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("cosh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, cosh); + REQUIRE_THROWS_WITH(cosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("asinh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, asinh); - REQUIRE_THROWS_WITH(asinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("tanh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, tanh); + REQUIRE_THROWS_WITH(tanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("acosh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, acosh); - REQUIRE_THROWS_WITH(acosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("asinh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, asinh); + REQUIRE_THROWS_WITH(asinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("atanh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, atanh); - REQUIRE_THROWS_WITH(atanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("acosh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, acosh); + REQUIRE_THROWS_WITH(acosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("exp Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, exp); - REQUIRE_THROWS_WITH(exp(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("atanh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, atanh); + REQUIRE_THROWS_WITH(atanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("log Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, log); - REQUIRE_THROWS_WITH(log(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("exp Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, exp); + REQUIRE_THROWS_WITH(exp(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("atan2 Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, atan2); - REQUIRE_THROWS_WITH(atan2(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(atan2(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(atan2(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - } + SECTION("log Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, log); + REQUIRE_THROWS_WITH(log(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("atan2 Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 3.6, atan2); - REQUIRE_THROWS_WITH(atan2(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } + SECTION("atan2 Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, atan2); + REQUIRE_THROWS_WITH(atan2(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(atan2(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(atan2(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + } - SECTION("atan2 R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.4, p_u, atan2); - REQUIRE_THROWS_WITH(atan2(2.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } + SECTION("atan2 Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 3.6, atan2); + REQUIRE_THROWS_WITH(atan2(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } - SECTION("min Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, min); - REQUIRE_THROWS_WITH(::min(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(::min(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(::min(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - } + SECTION("atan2 R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.4, p_u, atan2); + REQUIRE_THROWS_WITH(atan2(2.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } - SECTION("min Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, min); - REQUIRE_THROWS_WITH(min(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } + SECTION("min Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, min); + REQUIRE_THROWS_WITH(::min(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(::min(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(::min(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + } - SECTION("min R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, min); - REQUIRE_THROWS_WITH(min(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } + SECTION("min Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, min); + REQUIRE_THROWS_WITH(min(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } - SECTION("min Vh -> R") - { - REQUIRE(min(std::shared_ptr<const IDiscreteFunction>{p_u}) == min(p_u->cellValues())); - REQUIRE_THROWS_WITH(min(std::shared_ptr<const IDiscreteFunction>{p_R1_u}), - "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("min R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, min); + REQUIRE_THROWS_WITH(min(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } - SECTION("max Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, max); - REQUIRE_THROWS_WITH(::max(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(::max(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(::max(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - } + SECTION("min Vh -> R") + { + REQUIRE(min(std::shared_ptr<const IDiscreteFunction>{p_u}) == min(p_u->cellValues())); + REQUIRE_THROWS_WITH(min(std::shared_ptr<const IDiscreteFunction>{p_R1_u}), + "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("max Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, max); - REQUIRE_THROWS_WITH(max(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } + SECTION("max Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, max); + REQUIRE_THROWS_WITH(::max(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(::max(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(::max(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + } - SECTION("max Vh -> R") - { - REQUIRE(max(std::shared_ptr<const IDiscreteFunction>{p_u}) == max(p_u->cellValues())); - REQUIRE_THROWS_WITH(max(std::shared_ptr<const IDiscreteFunction>{p_R1_u}), - "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("max Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, max); + REQUIRE_THROWS_WITH(max(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } - SECTION("max R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, max); - REQUIRE_THROWS_WITH(max(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } + SECTION("max Vh -> R") + { + REQUIRE(max(std::shared_ptr<const IDiscreteFunction>{p_u}) == max(p_u->cellValues())); + REQUIRE_THROWS_WITH(max(std::shared_ptr<const IDiscreteFunction>{p_R1_u}), + "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("pow Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, pow); - REQUIRE_THROWS_WITH(pow(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(pow(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(pow(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - } + SECTION("max R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, max); + REQUIRE_THROWS_WITH(max(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } - SECTION("pow Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_positive_u, 3.3, pow); - REQUIRE_THROWS_WITH(pow(p_R1_u, 3.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } + SECTION("pow Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, pow); + REQUIRE_THROWS_WITH(pow(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(pow(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(pow(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + } - SECTION("pow R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.1, p_u, pow); - REQUIRE_THROWS_WITH(pow(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } + SECTION("pow Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_positive_u, 3.3, pow); + REQUIRE_THROWS_WITH(pow(p_R1_u, 3.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } - SECTION("dot Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R1_u, p_R1_v, dot); - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R2_u, p_R2_v, dot); - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R3_u, p_R3_v, dot); + SECTION("pow R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.1, p_u, pow); + REQUIRE_THROWS_WITH(pow(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } - { - auto p_UV = dot(p_Vector3_u, p_Vector3_v); - REQUIRE(p_UV.use_count() == 1); + SECTION("dot Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R1_u, p_R1_v, dot); + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R2_u, p_R2_v, dot); + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R3_u, p_R3_v, dot); - auto UV = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_UV); - auto direct_UV = dot(*p_Vector3_u, *p_Vector3_v); + { + auto p_UV = dot(p_Vector3_u, p_Vector3_v); + REQUIRE(p_UV.use_count() == 1); - bool is_same = true; - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - if (UV[cell_id] != direct_UV[cell_id]) { - is_same = false; - break; - } - } + auto UV = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_UV); + auto direct_UV = dot(*p_Vector3_u, *p_Vector3_v); - REQUIRE(is_same); - } + bool is_same = true; + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + if (UV[cell_id] != direct_UV[cell_id]) { + is_same = false; + break; + } + } - REQUIRE_THROWS_WITH(dot(p_R1_u, p_other_mesh_R1_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(dot(p_R2_u, p_other_mesh_R2_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(dot(p_R3_u, p_other_mesh_R3_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(dot(p_R1_u, p_R3_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(dot(p_Vector3_u, p_Vector2_w), "error: operands have different dimension"); - } + REQUIRE(is_same); + } - SECTION("dot Vh*Rd -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R1_u, (TinyVector<1>{3}), dot); - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R2_u, (TinyVector<2>{-6, 2}), dot); - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R3_u, (TinyVector<3>{-1, 5, 2}), dot); - REQUIRE_THROWS_WITH(dot(p_R1_u, (TinyVector<2>{-6, 2})), "error: incompatible operand types Vh(P0:R^1) and R^2"); - REQUIRE_THROWS_WITH(dot(p_R2_u, (TinyVector<3>{-1, 5, 2})), - "error: incompatible operand types Vh(P0:R^2) and R^3"); - REQUIRE_THROWS_WITH(dot(p_R3_u, (TinyVector<1>{-1})), "error: incompatible operand types Vh(P0:R^3) and R^1"); - } + REQUIRE_THROWS_WITH(dot(p_R1_u, p_other_mesh_R1_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(dot(p_R2_u, p_other_mesh_R2_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(dot(p_R3_u, p_other_mesh_R3_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(dot(p_R1_u, p_R3_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(dot(p_Vector3_u, p_Vector2_w), "error: operands have different dimension"); + } - SECTION("dot Rd*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<1>{3}), p_R1_u, dot); - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<2>{-6, 2}), p_R2_u, dot); - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<3>{-1, 5, 2}), p_R3_u, dot); - REQUIRE_THROWS_WITH(dot((TinyVector<2>{-6, 2}), p_R1_u), "error: incompatible operand types R^2 and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(dot((TinyVector<3>{-1, 5, 2}), p_R2_u), - "error: incompatible operand types R^3 and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(dot((TinyVector<1>{-1}), p_R3_u), "error: incompatible operand types R^1 and Vh(P0:R^3)"); - } + SECTION("dot Vh*Rd -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R1_u, (TinyVector<1>{3}), dot); + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R2_u, (TinyVector<2>{-6, 2}), dot); + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R3_u, (TinyVector<3>{-1, 5, 2}), dot); + REQUIRE_THROWS_WITH(dot(p_R1_u, (TinyVector<2>{-6, 2})), + "error: incompatible operand types Vh(P0:R^1) and R^2"); + REQUIRE_THROWS_WITH(dot(p_R2_u, (TinyVector<3>{-1, 5, 2})), + "error: incompatible operand types Vh(P0:R^2) and R^3"); + REQUIRE_THROWS_WITH(dot(p_R3_u, (TinyVector<1>{-1})), "error: incompatible operand types Vh(P0:R^3) and R^1"); + } - SECTION("sum_of_R* Vh -> R*") - { - REQUIRE(sum_of<double>(p_u) == sum(p_u->cellValues())); - REQUIRE(sum_of<TinyVector<1>>(p_R1_u) == sum(p_R1_u->cellValues())); - REQUIRE(sum_of<TinyVector<2>>(p_R2_u) == sum(p_R2_u->cellValues())); - REQUIRE(sum_of<TinyVector<3>>(p_R3_u) == sum(p_R3_u->cellValues())); - REQUIRE(sum_of<TinyMatrix<1>>(p_R1x1_u) == sum(p_R1x1_u->cellValues())); - REQUIRE(sum_of<TinyMatrix<2>>(p_R2x2_u) == sum(p_R2x2_u->cellValues())); - REQUIRE(sum_of<TinyMatrix<3>>(p_R3x3_u) == sum(p_R3x3_u->cellValues())); - - REQUIRE_THROWS_WITH(sum_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); - } + SECTION("dot Rd*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<1>{3}), p_R1_u, dot); + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<2>{-6, 2}), p_R2_u, dot); + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<3>{-1, 5, 2}), p_R3_u, dot); + REQUIRE_THROWS_WITH(dot((TinyVector<2>{-6, 2}), p_R1_u), + "error: incompatible operand types R^2 and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(dot((TinyVector<3>{-1, 5, 2}), p_R2_u), + "error: incompatible operand types R^3 and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(dot((TinyVector<1>{-1}), p_R3_u), "error: incompatible operand types R^1 and Vh(P0:R^3)"); + } - SECTION("integral_of_R* Vh -> R*") - { - auto integrate_locally = [&](const auto& cell_values) { - const auto& Vj = MeshDataManager::instance().getMeshData(*mesh).Vj(); - using DataType = decltype(double{} * cell_values[CellId{0}]); - CellValue<DataType> local_integral{mesh->connectivity()}; - parallel_for( - local_integral.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { local_integral[cell_id] = Vj[cell_id] * cell_values[cell_id]; }); - return local_integral; - }; - - REQUIRE(integral_of<double>(p_u) == sum(integrate_locally(p_u->cellValues()))); - REQUIRE(integral_of<TinyVector<1>>(p_R1_u) == sum(integrate_locally(p_R1_u->cellValues()))); - REQUIRE(integral_of<TinyVector<2>>(p_R2_u) == sum(integrate_locally(p_R2_u->cellValues()))); - REQUIRE(integral_of<TinyVector<3>>(p_R3_u) == sum(integrate_locally(p_R3_u->cellValues()))); - REQUIRE(integral_of<TinyMatrix<1>>(p_R1x1_u) == sum(integrate_locally(p_R1x1_u->cellValues()))); - REQUIRE(integral_of<TinyMatrix<2>>(p_R2x2_u) == sum(integrate_locally(p_R2x2_u->cellValues()))); - REQUIRE(integral_of<TinyMatrix<3>>(p_R3x3_u) == sum(integrate_locally(p_R3x3_u->cellValues()))); - - REQUIRE_THROWS_WITH(integral_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + SECTION("sum_of_R* Vh -> R*") + { + REQUIRE(sum_of<double>(p_u) == sum(p_u->cellValues())); + REQUIRE(sum_of<TinyVector<1>>(p_R1_u) == sum(p_R1_u->cellValues())); + REQUIRE(sum_of<TinyVector<2>>(p_R2_u) == sum(p_R2_u->cellValues())); + REQUIRE(sum_of<TinyVector<3>>(p_R3_u) == sum(p_R3_u->cellValues())); + REQUIRE(sum_of<TinyMatrix<1>>(p_R1x1_u) == sum(p_R1x1_u->cellValues())); + REQUIRE(sum_of<TinyMatrix<2>>(p_R2x2_u) == sum(p_R2x2_u->cellValues())); + REQUIRE(sum_of<TinyMatrix<3>>(p_R3x3_u) == sum(p_R3x3_u->cellValues())); + + REQUIRE_THROWS_WITH(sum_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + } + + SECTION("integral_of_R* Vh -> R*") + { + auto integrate_locally = [&](const auto& cell_values) { + const auto& Vj = MeshDataManager::instance().getMeshData(*mesh).Vj(); + using DataType = decltype(double{} * cell_values[CellId{0}]); + CellValue<DataType> local_integral{mesh->connectivity()}; + parallel_for( + local_integral.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { local_integral[cell_id] = Vj[cell_id] * cell_values[cell_id]; }); + return local_integral; + }; + + REQUIRE(integral_of<double>(p_u) == sum(integrate_locally(p_u->cellValues()))); + REQUIRE(integral_of<TinyVector<1>>(p_R1_u) == sum(integrate_locally(p_R1_u->cellValues()))); + REQUIRE(integral_of<TinyVector<2>>(p_R2_u) == sum(integrate_locally(p_R2_u->cellValues()))); + REQUIRE(integral_of<TinyVector<3>>(p_R3_u) == sum(integrate_locally(p_R3_u->cellValues()))); + REQUIRE(integral_of<TinyMatrix<1>>(p_R1x1_u) == sum(integrate_locally(p_R1x1_u->cellValues()))); + REQUIRE(integral_of<TinyMatrix<2>>(p_R2x2_u) == sum(integrate_locally(p_R2x2_u->cellValues()))); + REQUIRE(integral_of<TinyMatrix<3>>(p_R3x3_u) == sum(integrate_locally(p_R3x3_u->cellValues()))); + + REQUIRE_THROWS_WITH(integral_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + } + } } } @@ -606,494 +616,504 @@ TEST_CASE("EmbeddedIDiscreteFunctionMathFunctions", "[scheme]") using Rd = TinyVector<Dimension>; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian2DMesh(); - - std::shared_ptr other_mesh = - std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); - - CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - CellValue<double> values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - CellValue<double> positive_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 2 + std::sin(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - CellValue<double> bounded_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.9 * std::sin(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - std::shared_ptr p_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, values); - std::shared_ptr p_other_mesh_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(other_mesh, values); - std::shared_ptr p_positive_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, positive_values); - std::shared_ptr p_bounded_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, bounded_values); - - std::shared_ptr p_R1_u = [=] { - CellValue<TinyVector<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R1_v = [=] { - CellValue<TinyVector<1>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R1_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(other_mesh, p_R1_u->cellValues()); - - constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { - if constexpr (Dimension == 1) { - return {x[0], 1 + x[0] * x[0]}; - } else if constexpr (Dimension == 2) { - return {x[0], x[1]}; - } else if constexpr (Dimension == 3) { - return {x[0], x[1] + x[2]}; - } - }; - - std::shared_ptr p_R2_u = [=] { - CellValue<TinyVector<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - uj[cell_id] = {2 * x[0] + 1, 1 - x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R2_v = [=] { - CellValue<TinyVector<2>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R2_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(other_mesh, p_R2_u->cellValues()); - - constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { - if constexpr (Dimension == 1) { - return {x[0], 1 + x[0] * x[0], 2 - x[0]}; - } else if constexpr (Dimension == 2) { - return {x[0], x[1], x[0] + x[1]}; - } else if constexpr (Dimension == 3) { - return {x[0], x[1], x[2]}; - } - }; - - std::shared_ptr p_R3_u = [=] { - CellValue<TinyVector<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj[cell_id] = {2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); - }(); - - std::shared_ptr p_R3_v = [=] { - CellValue<TinyVector<3>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R3_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(other_mesh, p_R3_u->cellValues()); - - std::shared_ptr p_R1x1_u = [=] { - CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = {2 * xj[cell_id][0] + 1}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R2x2_u = [=] { - CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - uj[cell_id] = {2 * x[0] + 1, 1 - x[1], // - 2 * x[1], -x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R3x3_u = [=] { - CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - uj[cell_id] = {2 * x[0] + 1, 1 - x[1], 3, // - 2 * x[1], -x[0], x[0] - x[1], // - 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); - }(); - - std::shared_ptr p_Vector3_u = [=] { - CellArray<double> uj_vector{mesh->connectivity(), 3}; - parallel_for( - uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj_vector[cell_id][0] = 2 * x[0] + 1; - uj_vector[cell_id][1] = 1 - x[1] * x[2]; - uj_vector[cell_id][2] = x[0] + x[2]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); - }(); - - std::shared_ptr p_Vector3_v = [=] { - CellArray<double> vj_vector{mesh->connectivity(), 3}; - parallel_for( - vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj_vector[cell_id][0] = x[0] * x[1] + 1; - vj_vector[cell_id][1] = 2 * x[1]; - vj_vector[cell_id][2] = x[2] * x[0]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, vj_vector); - }(); - - std::shared_ptr p_Vector2_w = [=] { - CellArray<double> wj_vector{mesh->connectivity(), 2}; - parallel_for( - wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - wj_vector[cell_id][0] = x[0] + x[1] * 2; - wj_vector[cell_id][1] = x[0] * x[1]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, wj_vector); - }(); - - SECTION("sqrt Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, sqrt); - REQUIRE_THROWS_WITH(sqrt(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - SECTION("abs Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, abs); - REQUIRE_THROWS_WITH(abs(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + std::shared_ptr other_mesh = + std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); + + CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + CellValue<double> values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + CellValue<double> positive_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 2 + std::sin(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + CellValue<double> bounded_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.9 * std::sin(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + std::shared_ptr p_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, values); + std::shared_ptr p_other_mesh_u = + std::make_shared<const DiscreteFunctionP0<Dimension, double>>(other_mesh, values); + std::shared_ptr p_positive_u = + std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, positive_values); + std::shared_ptr p_bounded_u = + std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, bounded_values); + + std::shared_ptr p_R1_u = [=] { + CellValue<TinyVector<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); + }(); + + std::shared_ptr p_R1_v = [=] { + CellValue<TinyVector<1>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, vj); + }(); + + std::shared_ptr p_other_mesh_R1_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(other_mesh, p_R1_u->cellValues()); + + constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { + if constexpr (Dimension == 1) { + return {x[0], 1 + x[0] * x[0]}; + } else if constexpr (Dimension == 2) { + return {x[0], x[1]}; + } else if constexpr (Dimension == 3) { + return {x[0], x[1] + x[2]}; + } + }; + + std::shared_ptr p_R2_u = [=] { + CellValue<TinyVector<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + uj[cell_id] = {2 * x[0] + 1, 1 - x[1]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); + }(); + + std::shared_ptr p_R2_v = [=] { + CellValue<TinyVector<2>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, vj); + }(); + + std::shared_ptr p_other_mesh_R2_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(other_mesh, p_R2_u->cellValues()); + + constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { + if constexpr (Dimension == 1) { + return {x[0], 1 + x[0] * x[0], 2 - x[0]}; + } else if constexpr (Dimension == 2) { + return {x[0], x[1], x[0] + x[1]}; + } else if constexpr (Dimension == 3) { + return {x[0], x[1], x[2]}; + } + }; + + std::shared_ptr p_R3_u = [=] { + CellValue<TinyVector<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj[cell_id] = {2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); + }(); + + std::shared_ptr p_R3_v = [=] { + CellValue<TinyVector<3>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, vj); + }(); + + std::shared_ptr p_other_mesh_R3_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(other_mesh, p_R3_u->cellValues()); + + std::shared_ptr p_R1x1_u = [=] { + CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = {2 * xj[cell_id][0] + 1}; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); + }(); + + std::shared_ptr p_R2x2_u = [=] { + CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + uj[cell_id] = {2 * x[0] + 1, 1 - x[1], // + 2 * x[1], -x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); + }(); + + std::shared_ptr p_R3x3_u = [=] { + CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + uj[cell_id] = {2 * x[0] + 1, 1 - x[1], 3, // + 2 * x[1], -x[0], x[0] - x[1], // + 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); + }(); + + std::shared_ptr p_Vector3_u = [=] { + CellArray<double> uj_vector{mesh->connectivity(), 3}; + parallel_for( + uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj_vector[cell_id][0] = 2 * x[0] + 1; + uj_vector[cell_id][1] = 1 - x[1] * x[2]; + uj_vector[cell_id][2] = x[0] + x[2]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); + }(); + + std::shared_ptr p_Vector3_v = [=] { + CellArray<double> vj_vector{mesh->connectivity(), 3}; + parallel_for( + vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj_vector[cell_id][0] = x[0] * x[1] + 1; + vj_vector[cell_id][1] = 2 * x[1]; + vj_vector[cell_id][2] = x[2] * x[0]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, vj_vector); + }(); + + std::shared_ptr p_Vector2_w = [=] { + CellArray<double> wj_vector{mesh->connectivity(), 2}; + parallel_for( + wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + wj_vector[cell_id][0] = x[0] + x[1] * 2; + wj_vector[cell_id][1] = x[0] * x[1]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, wj_vector); + }(); + + SECTION("sqrt Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, sqrt); + REQUIRE_THROWS_WITH(sqrt(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("sin Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, sin); - REQUIRE_THROWS_WITH(sin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("abs Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, abs); + REQUIRE_THROWS_WITH(abs(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("cos Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, cos); - REQUIRE_THROWS_WITH(cos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("sin Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, sin); + REQUIRE_THROWS_WITH(sin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("tan Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, tan); - REQUIRE_THROWS_WITH(tan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("cos Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, cos); + REQUIRE_THROWS_WITH(cos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("asin Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, asin); - REQUIRE_THROWS_WITH(asin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("tan Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, tan); + REQUIRE_THROWS_WITH(tan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("acos Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, acos); - REQUIRE_THROWS_WITH(acos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("asin Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, asin); + REQUIRE_THROWS_WITH(asin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("atan Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, atan); - REQUIRE_THROWS_WITH(atan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("acos Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, acos); + REQUIRE_THROWS_WITH(acos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("sinh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, sinh); - REQUIRE_THROWS_WITH(sinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("atan Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, atan); + REQUIRE_THROWS_WITH(atan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("cosh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, cosh); - REQUIRE_THROWS_WITH(cosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("sinh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, sinh); + REQUIRE_THROWS_WITH(sinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("tanh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, tanh); - REQUIRE_THROWS_WITH(tanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("cosh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, cosh); + REQUIRE_THROWS_WITH(cosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("asinh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, asinh); - REQUIRE_THROWS_WITH(asinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("tanh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, tanh); + REQUIRE_THROWS_WITH(tanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("acosh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, acosh); - REQUIRE_THROWS_WITH(acosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("asinh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, asinh); + REQUIRE_THROWS_WITH(asinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("atanh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, atanh); - REQUIRE_THROWS_WITH(atanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("acosh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, acosh); + REQUIRE_THROWS_WITH(acosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("exp Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, exp); - REQUIRE_THROWS_WITH(exp(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("atanh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, atanh); + REQUIRE_THROWS_WITH(atanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("log Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, log); - REQUIRE_THROWS_WITH(log(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("exp Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, exp); + REQUIRE_THROWS_WITH(exp(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("atan2 Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, atan2); - REQUIRE_THROWS_WITH(atan2(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(atan2(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(atan2(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - } + SECTION("log Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, log); + REQUIRE_THROWS_WITH(log(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("atan2 Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 3.6, atan2); - REQUIRE_THROWS_WITH(atan2(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } + SECTION("atan2 Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, atan2); + REQUIRE_THROWS_WITH(atan2(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(atan2(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(atan2(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + } - SECTION("atan2 R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.4, p_u, atan2); - REQUIRE_THROWS_WITH(atan2(2.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } + SECTION("atan2 Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 3.6, atan2); + REQUIRE_THROWS_WITH(atan2(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } - SECTION("min Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, min); - REQUIRE_THROWS_WITH(::min(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(::min(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(::min(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - } + SECTION("atan2 R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.4, p_u, atan2); + REQUIRE_THROWS_WITH(atan2(2.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } - SECTION("min Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, min); - REQUIRE_THROWS_WITH(min(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } + SECTION("min Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, min); + REQUIRE_THROWS_WITH(::min(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(::min(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(::min(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + } - SECTION("min R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, min); - REQUIRE_THROWS_WITH(min(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } + SECTION("min Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, min); + REQUIRE_THROWS_WITH(min(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } - SECTION("min Vh -> R") - { - REQUIRE(min(std::shared_ptr<const IDiscreteFunction>{p_u}) == min(p_u->cellValues())); - REQUIRE_THROWS_WITH(min(std::shared_ptr<const IDiscreteFunction>{p_R1_u}), - "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("min R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, min); + REQUIRE_THROWS_WITH(min(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } - SECTION("max Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, max); - REQUIRE_THROWS_WITH(::max(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(::max(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(::max(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - } + SECTION("min Vh -> R") + { + REQUIRE(min(std::shared_ptr<const IDiscreteFunction>{p_u}) == min(p_u->cellValues())); + REQUIRE_THROWS_WITH(min(std::shared_ptr<const IDiscreteFunction>{p_R1_u}), + "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("max Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, max); - REQUIRE_THROWS_WITH(max(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } + SECTION("max Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, max); + REQUIRE_THROWS_WITH(::max(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(::max(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(::max(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + } - SECTION("max Vh -> R") - { - REQUIRE(max(std::shared_ptr<const IDiscreteFunction>{p_u}) == max(p_u->cellValues())); - REQUIRE_THROWS_WITH(max(std::shared_ptr<const IDiscreteFunction>{p_R1_u}), - "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("max Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, max); + REQUIRE_THROWS_WITH(max(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } - SECTION("max R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, max); - REQUIRE_THROWS_WITH(max(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } + SECTION("max Vh -> R") + { + REQUIRE(max(std::shared_ptr<const IDiscreteFunction>{p_u}) == max(p_u->cellValues())); + REQUIRE_THROWS_WITH(max(std::shared_ptr<const IDiscreteFunction>{p_R1_u}), + "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("pow Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, pow); - REQUIRE_THROWS_WITH(pow(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(pow(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(pow(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - } + SECTION("max R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, max); + REQUIRE_THROWS_WITH(max(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } - SECTION("pow Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_positive_u, 3.3, pow); - REQUIRE_THROWS_WITH(pow(p_R1_u, 3.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } + SECTION("pow Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, pow); + REQUIRE_THROWS_WITH(pow(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(pow(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(pow(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + } - SECTION("pow R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.1, p_u, pow); - REQUIRE_THROWS_WITH(pow(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } + SECTION("pow Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_positive_u, 3.3, pow); + REQUIRE_THROWS_WITH(pow(p_R1_u, 3.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } - SECTION("dot Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R1_u, p_R1_v, dot); - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R2_u, p_R2_v, dot); - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R3_u, p_R3_v, dot); + SECTION("pow R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.1, p_u, pow); + REQUIRE_THROWS_WITH(pow(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } - { - auto p_UV = dot(p_Vector3_u, p_Vector3_v); - REQUIRE(p_UV.use_count() == 1); + SECTION("dot Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R1_u, p_R1_v, dot); + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R2_u, p_R2_v, dot); + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R3_u, p_R3_v, dot); - auto UV = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_UV); - auto direct_UV = dot(*p_Vector3_u, *p_Vector3_v); + { + auto p_UV = dot(p_Vector3_u, p_Vector3_v); + REQUIRE(p_UV.use_count() == 1); - bool is_same = true; - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - if (UV[cell_id] != direct_UV[cell_id]) { - is_same = false; - break; - } - } + auto UV = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_UV); + auto direct_UV = dot(*p_Vector3_u, *p_Vector3_v); - REQUIRE(is_same); - } + bool is_same = true; + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + if (UV[cell_id] != direct_UV[cell_id]) { + is_same = false; + break; + } + } - REQUIRE_THROWS_WITH(dot(p_R1_u, p_other_mesh_R1_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(dot(p_R2_u, p_other_mesh_R2_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(dot(p_R3_u, p_other_mesh_R3_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(dot(p_R1_u, p_R3_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(dot(p_Vector3_u, p_Vector2_w), "error: operands have different dimension"); - } + REQUIRE(is_same); + } - SECTION("dot Vh*Rd -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R1_u, (TinyVector<1>{3}), dot); - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R2_u, (TinyVector<2>{-6, 2}), dot); - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R3_u, (TinyVector<3>{-1, 5, 2}), dot); - REQUIRE_THROWS_WITH(dot(p_R1_u, (TinyVector<2>{-6, 2})), "error: incompatible operand types Vh(P0:R^1) and R^2"); - REQUIRE_THROWS_WITH(dot(p_R2_u, (TinyVector<3>{-1, 5, 2})), - "error: incompatible operand types Vh(P0:R^2) and R^3"); - REQUIRE_THROWS_WITH(dot(p_R3_u, (TinyVector<1>{-1})), "error: incompatible operand types Vh(P0:R^3) and R^1"); - } + REQUIRE_THROWS_WITH(dot(p_R1_u, p_other_mesh_R1_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(dot(p_R2_u, p_other_mesh_R2_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(dot(p_R3_u, p_other_mesh_R3_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(dot(p_R1_u, p_R3_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(dot(p_Vector3_u, p_Vector2_w), "error: operands have different dimension"); + } - SECTION("dot Rd*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<1>{3}), p_R1_u, dot); - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<2>{-6, 2}), p_R2_u, dot); - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<3>{-1, 5, 2}), p_R3_u, dot); - REQUIRE_THROWS_WITH(dot((TinyVector<2>{-6, 2}), p_R1_u), "error: incompatible operand types R^2 and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(dot((TinyVector<3>{-1, 5, 2}), p_R2_u), - "error: incompatible operand types R^3 and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(dot((TinyVector<1>{-1}), p_R3_u), "error: incompatible operand types R^1 and Vh(P0:R^3)"); - } + SECTION("dot Vh*Rd -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R1_u, (TinyVector<1>{3}), dot); + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R2_u, (TinyVector<2>{-6, 2}), dot); + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R3_u, (TinyVector<3>{-1, 5, 2}), dot); + REQUIRE_THROWS_WITH(dot(p_R1_u, (TinyVector<2>{-6, 2})), + "error: incompatible operand types Vh(P0:R^1) and R^2"); + REQUIRE_THROWS_WITH(dot(p_R2_u, (TinyVector<3>{-1, 5, 2})), + "error: incompatible operand types Vh(P0:R^2) and R^3"); + REQUIRE_THROWS_WITH(dot(p_R3_u, (TinyVector<1>{-1})), "error: incompatible operand types Vh(P0:R^3) and R^1"); + } - SECTION("sum_of_R* Vh -> R*") - { - REQUIRE(sum_of<double>(p_u) == sum(p_u->cellValues())); - REQUIRE(sum_of<TinyVector<1>>(p_R1_u) == sum(p_R1_u->cellValues())); - REQUIRE(sum_of<TinyVector<2>>(p_R2_u) == sum(p_R2_u->cellValues())); - REQUIRE(sum_of<TinyVector<3>>(p_R3_u) == sum(p_R3_u->cellValues())); - REQUIRE(sum_of<TinyMatrix<1>>(p_R1x1_u) == sum(p_R1x1_u->cellValues())); - REQUIRE(sum_of<TinyMatrix<2>>(p_R2x2_u) == sum(p_R2x2_u->cellValues())); - REQUIRE(sum_of<TinyMatrix<3>>(p_R3x3_u) == sum(p_R3x3_u->cellValues())); - - REQUIRE_THROWS_WITH(sum_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); - } + SECTION("dot Rd*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<1>{3}), p_R1_u, dot); + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<2>{-6, 2}), p_R2_u, dot); + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<3>{-1, 5, 2}), p_R3_u, dot); + REQUIRE_THROWS_WITH(dot((TinyVector<2>{-6, 2}), p_R1_u), + "error: incompatible operand types R^2 and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(dot((TinyVector<3>{-1, 5, 2}), p_R2_u), + "error: incompatible operand types R^3 and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(dot((TinyVector<1>{-1}), p_R3_u), "error: incompatible operand types R^1 and Vh(P0:R^3)"); + } + + SECTION("sum_of_R* Vh -> R*") + { + REQUIRE(sum_of<double>(p_u) == sum(p_u->cellValues())); + REQUIRE(sum_of<TinyVector<1>>(p_R1_u) == sum(p_R1_u->cellValues())); + REQUIRE(sum_of<TinyVector<2>>(p_R2_u) == sum(p_R2_u->cellValues())); + REQUIRE(sum_of<TinyVector<3>>(p_R3_u) == sum(p_R3_u->cellValues())); + REQUIRE(sum_of<TinyMatrix<1>>(p_R1x1_u) == sum(p_R1x1_u->cellValues())); + REQUIRE(sum_of<TinyMatrix<2>>(p_R2x2_u) == sum(p_R2x2_u->cellValues())); + REQUIRE(sum_of<TinyMatrix<3>>(p_R3x3_u) == sum(p_R3x3_u->cellValues())); + + REQUIRE_THROWS_WITH(sum_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + } - SECTION("integral_of_R* Vh -> R*") - { - auto integrate_locally = [&](const auto& cell_values) { - const auto& Vj = MeshDataManager::instance().getMeshData(*mesh).Vj(); - using DataType = decltype(double{} * cell_values[CellId{0}]); - CellValue<DataType> local_integral{mesh->connectivity()}; - parallel_for( - local_integral.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { local_integral[cell_id] = Vj[cell_id] * cell_values[cell_id]; }); - return local_integral; - }; - - REQUIRE(integral_of<double>(p_u) == sum(integrate_locally(p_u->cellValues()))); - REQUIRE(integral_of<TinyVector<1>>(p_R1_u) == sum(integrate_locally(p_R1_u->cellValues()))); - REQUIRE(integral_of<TinyVector<2>>(p_R2_u) == sum(integrate_locally(p_R2_u->cellValues()))); - REQUIRE(integral_of<TinyVector<3>>(p_R3_u) == sum(integrate_locally(p_R3_u->cellValues()))); - REQUIRE(integral_of<TinyMatrix<1>>(p_R1x1_u) == sum(integrate_locally(p_R1x1_u->cellValues()))); - REQUIRE(integral_of<TinyMatrix<2>>(p_R2x2_u) == sum(integrate_locally(p_R2x2_u->cellValues()))); - REQUIRE(integral_of<TinyMatrix<3>>(p_R3x3_u) == sum(integrate_locally(p_R3x3_u->cellValues()))); - - REQUIRE_THROWS_WITH(integral_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + SECTION("integral_of_R* Vh -> R*") + { + auto integrate_locally = [&](const auto& cell_values) { + const auto& Vj = MeshDataManager::instance().getMeshData(*mesh).Vj(); + using DataType = decltype(double{} * cell_values[CellId{0}]); + CellValue<DataType> local_integral{mesh->connectivity()}; + parallel_for( + local_integral.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { local_integral[cell_id] = Vj[cell_id] * cell_values[cell_id]; }); + return local_integral; + }; + + REQUIRE(integral_of<double>(p_u) == sum(integrate_locally(p_u->cellValues()))); + REQUIRE(integral_of<TinyVector<1>>(p_R1_u) == sum(integrate_locally(p_R1_u->cellValues()))); + REQUIRE(integral_of<TinyVector<2>>(p_R2_u) == sum(integrate_locally(p_R2_u->cellValues()))); + REQUIRE(integral_of<TinyVector<3>>(p_R3_u) == sum(integrate_locally(p_R3_u->cellValues()))); + REQUIRE(integral_of<TinyMatrix<1>>(p_R1x1_u) == sum(integrate_locally(p_R1x1_u->cellValues()))); + REQUIRE(integral_of<TinyMatrix<2>>(p_R2x2_u) == sum(integrate_locally(p_R2x2_u->cellValues()))); + REQUIRE(integral_of<TinyMatrix<3>>(p_R3x3_u) == sum(integrate_locally(p_R3x3_u->cellValues()))); + + REQUIRE_THROWS_WITH(integral_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + } + } } } @@ -1103,494 +1123,504 @@ TEST_CASE("EmbeddedIDiscreteFunctionMathFunctions", "[scheme]") using Rd = TinyVector<Dimension>; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian3DMesh(); - - std::shared_ptr other_mesh = - std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); - - CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - CellValue<double> values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - CellValue<double> positive_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 2 + std::sin(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - CellValue<double> bounded_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.9 * std::sin(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - std::shared_ptr p_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, values); - std::shared_ptr p_other_mesh_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(other_mesh, values); - std::shared_ptr p_positive_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, positive_values); - std::shared_ptr p_bounded_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, bounded_values); - - std::shared_ptr p_R1_u = [=] { - CellValue<TinyVector<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R1_v = [=] { - CellValue<TinyVector<1>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R1_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(other_mesh, p_R1_u->cellValues()); - - constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { - if constexpr (Dimension == 1) { - return {x[0], 1 + x[0] * x[0]}; - } else if constexpr (Dimension == 2) { - return {x[0], x[1]}; - } else if constexpr (Dimension == 3) { - return {x[0], x[1] + x[2]}; - } - }; - - std::shared_ptr p_R2_u = [=] { - CellValue<TinyVector<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - uj[cell_id] = {2 * x[0] + 1, 1 - x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R2_v = [=] { - CellValue<TinyVector<2>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R2_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(other_mesh, p_R2_u->cellValues()); - - constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { - if constexpr (Dimension == 1) { - return {x[0], 1 + x[0] * x[0], 2 - x[0]}; - } else if constexpr (Dimension == 2) { - return {x[0], x[1], x[0] + x[1]}; - } else if constexpr (Dimension == 3) { - return {x[0], x[1], x[2]}; - } - }; - - std::shared_ptr p_R3_u = [=] { - CellValue<TinyVector<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj[cell_id] = {2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); - }(); - - std::shared_ptr p_R3_v = [=] { - CellValue<TinyVector<3>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R3_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(other_mesh, p_R3_u->cellValues()); - - std::shared_ptr p_R1x1_u = [=] { - CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = {2 * xj[cell_id][0] + 1}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R2x2_u = [=] { - CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - uj[cell_id] = {2 * x[0] + 1, 1 - x[1], // - 2 * x[1], -x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R3x3_u = [=] { - CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - uj[cell_id] = {2 * x[0] + 1, 1 - x[1], 3, // - 2 * x[1], -x[0], x[0] - x[1], // - 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); - }(); - - std::shared_ptr p_Vector3_u = [=] { - CellArray<double> uj_vector{mesh->connectivity(), 3}; - parallel_for( - uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj_vector[cell_id][0] = 2 * x[0] + 1; - uj_vector[cell_id][1] = 1 - x[1] * x[2]; - uj_vector[cell_id][2] = x[0] + x[2]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); - }(); - - std::shared_ptr p_Vector3_v = [=] { - CellArray<double> vj_vector{mesh->connectivity(), 3}; - parallel_for( - vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj_vector[cell_id][0] = x[0] * x[1] + 1; - vj_vector[cell_id][1] = 2 * x[1]; - vj_vector[cell_id][2] = x[2] * x[0]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, vj_vector); - }(); - - std::shared_ptr p_Vector2_w = [=] { - CellArray<double> wj_vector{mesh->connectivity(), 2}; - parallel_for( - wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - wj_vector[cell_id][0] = x[0] + x[1] * 2; - wj_vector[cell_id][1] = x[0] * x[1]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, wj_vector); - }(); - - SECTION("sqrt Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, sqrt); - REQUIRE_THROWS_WITH(sqrt(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - SECTION("abs Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, abs); - REQUIRE_THROWS_WITH(abs(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) + { + std::shared_ptr other_mesh = + std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); + + CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + CellValue<double> values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + CellValue<double> positive_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 2 + std::sin(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + CellValue<double> bounded_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.9 * std::sin(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + std::shared_ptr p_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, values); + std::shared_ptr p_other_mesh_u = + std::make_shared<const DiscreteFunctionP0<Dimension, double>>(other_mesh, values); + std::shared_ptr p_positive_u = + std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, positive_values); + std::shared_ptr p_bounded_u = + std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, bounded_values); + + std::shared_ptr p_R1_u = [=] { + CellValue<TinyVector<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); + }(); + + std::shared_ptr p_R1_v = [=] { + CellValue<TinyVector<1>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, vj); + }(); + + std::shared_ptr p_other_mesh_R1_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(other_mesh, p_R1_u->cellValues()); + + constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { + if constexpr (Dimension == 1) { + return {x[0], 1 + x[0] * x[0]}; + } else if constexpr (Dimension == 2) { + return {x[0], x[1]}; + } else if constexpr (Dimension == 3) { + return {x[0], x[1] + x[2]}; + } + }; + + std::shared_ptr p_R2_u = [=] { + CellValue<TinyVector<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + uj[cell_id] = {2 * x[0] + 1, 1 - x[1]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); + }(); + + std::shared_ptr p_R2_v = [=] { + CellValue<TinyVector<2>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, vj); + }(); + + std::shared_ptr p_other_mesh_R2_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(other_mesh, p_R2_u->cellValues()); + + constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { + if constexpr (Dimension == 1) { + return {x[0], 1 + x[0] * x[0], 2 - x[0]}; + } else if constexpr (Dimension == 2) { + return {x[0], x[1], x[0] + x[1]}; + } else if constexpr (Dimension == 3) { + return {x[0], x[1], x[2]}; + } + }; + + std::shared_ptr p_R3_u = [=] { + CellValue<TinyVector<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj[cell_id] = {2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); + }(); + + std::shared_ptr p_R3_v = [=] { + CellValue<TinyVector<3>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, vj); + }(); + + std::shared_ptr p_other_mesh_R3_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(other_mesh, p_R3_u->cellValues()); + + std::shared_ptr p_R1x1_u = [=] { + CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = {2 * xj[cell_id][0] + 1}; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); + }(); + + std::shared_ptr p_R2x2_u = [=] { + CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + uj[cell_id] = {2 * x[0] + 1, 1 - x[1], // + 2 * x[1], -x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); + }(); + + std::shared_ptr p_R3x3_u = [=] { + CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + uj[cell_id] = {2 * x[0] + 1, 1 - x[1], 3, // + 2 * x[1], -x[0], x[0] - x[1], // + 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); + }(); + + std::shared_ptr p_Vector3_u = [=] { + CellArray<double> uj_vector{mesh->connectivity(), 3}; + parallel_for( + uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj_vector[cell_id][0] = 2 * x[0] + 1; + uj_vector[cell_id][1] = 1 - x[1] * x[2]; + uj_vector[cell_id][2] = x[0] + x[2]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); + }(); + + std::shared_ptr p_Vector3_v = [=] { + CellArray<double> vj_vector{mesh->connectivity(), 3}; + parallel_for( + vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj_vector[cell_id][0] = x[0] * x[1] + 1; + vj_vector[cell_id][1] = 2 * x[1]; + vj_vector[cell_id][2] = x[2] * x[0]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, vj_vector); + }(); + + std::shared_ptr p_Vector2_w = [=] { + CellArray<double> wj_vector{mesh->connectivity(), 2}; + parallel_for( + wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + wj_vector[cell_id][0] = x[0] + x[1] * 2; + wj_vector[cell_id][1] = x[0] * x[1]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, wj_vector); + }(); + + SECTION("sqrt Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, sqrt); + REQUIRE_THROWS_WITH(sqrt(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("sin Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, sin); - REQUIRE_THROWS_WITH(sin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("abs Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, abs); + REQUIRE_THROWS_WITH(abs(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("cos Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, cos); - REQUIRE_THROWS_WITH(cos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("sin Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, sin); + REQUIRE_THROWS_WITH(sin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("tan Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, tan); - REQUIRE_THROWS_WITH(tan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("cos Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, cos); + REQUIRE_THROWS_WITH(cos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("asin Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, asin); - REQUIRE_THROWS_WITH(asin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("tan Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, tan); + REQUIRE_THROWS_WITH(tan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("acos Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, acos); - REQUIRE_THROWS_WITH(acos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("asin Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, asin); + REQUIRE_THROWS_WITH(asin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("atan Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, atan); - REQUIRE_THROWS_WITH(atan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("acos Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, acos); + REQUIRE_THROWS_WITH(acos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("sinh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, sinh); - REQUIRE_THROWS_WITH(sinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("atan Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, atan); + REQUIRE_THROWS_WITH(atan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("cosh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, cosh); - REQUIRE_THROWS_WITH(cosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("sinh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, sinh); + REQUIRE_THROWS_WITH(sinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("tanh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, tanh); - REQUIRE_THROWS_WITH(tanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("cosh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, cosh); + REQUIRE_THROWS_WITH(cosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("asinh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, asinh); - REQUIRE_THROWS_WITH(asinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("tanh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, tanh); + REQUIRE_THROWS_WITH(tanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("acosh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, acosh); - REQUIRE_THROWS_WITH(acosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("asinh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, asinh); + REQUIRE_THROWS_WITH(asinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("atanh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, atanh); - REQUIRE_THROWS_WITH(atanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("acosh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, acosh); + REQUIRE_THROWS_WITH(acosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("exp Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, exp); - REQUIRE_THROWS_WITH(exp(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("atanh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, atanh); + REQUIRE_THROWS_WITH(atanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("log Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, log); - REQUIRE_THROWS_WITH(log(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("exp Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, exp); + REQUIRE_THROWS_WITH(exp(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("atan2 Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, atan2); - REQUIRE_THROWS_WITH(atan2(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(atan2(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(atan2(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - } + SECTION("log Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, log); + REQUIRE_THROWS_WITH(log(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("atan2 Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 3.6, atan2); - REQUIRE_THROWS_WITH(atan2(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } + SECTION("atan2 Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, atan2); + REQUIRE_THROWS_WITH(atan2(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(atan2(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(atan2(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + } - SECTION("atan2 R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.4, p_u, atan2); - REQUIRE_THROWS_WITH(atan2(2.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } + SECTION("atan2 Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 3.6, atan2); + REQUIRE_THROWS_WITH(atan2(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } - SECTION("min Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, min); - REQUIRE_THROWS_WITH(::min(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(::min(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(::min(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - } + SECTION("atan2 R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.4, p_u, atan2); + REQUIRE_THROWS_WITH(atan2(2.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } - SECTION("min Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, min); - REQUIRE_THROWS_WITH(min(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } + SECTION("min Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, min); + REQUIRE_THROWS_WITH(::min(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(::min(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(::min(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + } - SECTION("min R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, min); - REQUIRE_THROWS_WITH(min(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } + SECTION("min Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, min); + REQUIRE_THROWS_WITH(min(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } - SECTION("min Vh -> R") - { - REQUIRE(min(std::shared_ptr<const IDiscreteFunction>{p_u}) == min(p_u->cellValues())); - REQUIRE_THROWS_WITH(min(std::shared_ptr<const IDiscreteFunction>{p_R1_u}), - "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("min R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, min); + REQUIRE_THROWS_WITH(min(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } - SECTION("max Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, max); - REQUIRE_THROWS_WITH(::max(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(::max(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(::max(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - } + SECTION("min Vh -> R") + { + REQUIRE(min(std::shared_ptr<const IDiscreteFunction>{p_u}) == min(p_u->cellValues())); + REQUIRE_THROWS_WITH(min(std::shared_ptr<const IDiscreteFunction>{p_R1_u}), + "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("max Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, max); - REQUIRE_THROWS_WITH(max(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } + SECTION("max Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, max); + REQUIRE_THROWS_WITH(::max(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(::max(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(::max(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + } - SECTION("max Vh -> R") - { - REQUIRE(max(std::shared_ptr<const IDiscreteFunction>{p_u}) == max(p_u->cellValues())); - REQUIRE_THROWS_WITH(max(std::shared_ptr<const IDiscreteFunction>{p_R1_u}), - "error: invalid operand type Vh(P0:R^1)"); - } + SECTION("max Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, max); + REQUIRE_THROWS_WITH(max(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } - SECTION("max R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, max); - REQUIRE_THROWS_WITH(max(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } + SECTION("max Vh -> R") + { + REQUIRE(max(std::shared_ptr<const IDiscreteFunction>{p_u}) == max(p_u->cellValues())); + REQUIRE_THROWS_WITH(max(std::shared_ptr<const IDiscreteFunction>{p_R1_u}), + "error: invalid operand type Vh(P0:R^1)"); + } - SECTION("pow Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, pow); - REQUIRE_THROWS_WITH(pow(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(pow(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(pow(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - } + SECTION("max R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, max); + REQUIRE_THROWS_WITH(max(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } - SECTION("pow Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_positive_u, 3.3, pow); - REQUIRE_THROWS_WITH(pow(p_R1_u, 3.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } + SECTION("pow Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, pow); + REQUIRE_THROWS_WITH(pow(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(pow(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(pow(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + } - SECTION("pow R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.1, p_u, pow); - REQUIRE_THROWS_WITH(pow(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } + SECTION("pow Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_positive_u, 3.3, pow); + REQUIRE_THROWS_WITH(pow(p_R1_u, 3.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } - SECTION("dot Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R1_u, p_R1_v, dot); - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R2_u, p_R2_v, dot); - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R3_u, p_R3_v, dot); + SECTION("pow R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.1, p_u, pow); + REQUIRE_THROWS_WITH(pow(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } - { - auto p_UV = dot(p_Vector3_u, p_Vector3_v); - REQUIRE(p_UV.use_count() == 1); + SECTION("dot Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R1_u, p_R1_v, dot); + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R2_u, p_R2_v, dot); + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R3_u, p_R3_v, dot); - auto UV = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_UV); - auto direct_UV = dot(*p_Vector3_u, *p_Vector3_v); + { + auto p_UV = dot(p_Vector3_u, p_Vector3_v); + REQUIRE(p_UV.use_count() == 1); - bool is_same = true; - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - if (UV[cell_id] != direct_UV[cell_id]) { - is_same = false; - break; - } - } + auto UV = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_UV); + auto direct_UV = dot(*p_Vector3_u, *p_Vector3_v); - REQUIRE(is_same); - } + bool is_same = true; + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + if (UV[cell_id] != direct_UV[cell_id]) { + is_same = false; + break; + } + } - REQUIRE_THROWS_WITH(dot(p_R1_u, p_other_mesh_R1_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(dot(p_R2_u, p_other_mesh_R2_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(dot(p_R3_u, p_other_mesh_R3_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(dot(p_R1_u, p_R3_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(dot(p_Vector3_u, p_Vector2_w), "error: operands have different dimension"); - } + REQUIRE(is_same); + } - SECTION("dot Vh*Rd -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R1_u, (TinyVector<1>{3}), dot); - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R2_u, (TinyVector<2>{-6, 2}), dot); - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R3_u, (TinyVector<3>{-1, 5, 2}), dot); - REQUIRE_THROWS_WITH(dot(p_R1_u, (TinyVector<2>{-6, 2})), "error: incompatible operand types Vh(P0:R^1) and R^2"); - REQUIRE_THROWS_WITH(dot(p_R2_u, (TinyVector<3>{-1, 5, 2})), - "error: incompatible operand types Vh(P0:R^2) and R^3"); - REQUIRE_THROWS_WITH(dot(p_R3_u, (TinyVector<1>{-1})), "error: incompatible operand types Vh(P0:R^3) and R^1"); - } + REQUIRE_THROWS_WITH(dot(p_R1_u, p_other_mesh_R1_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(dot(p_R2_u, p_other_mesh_R2_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(dot(p_R3_u, p_other_mesh_R3_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(dot(p_R1_u, p_R3_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(dot(p_Vector3_u, p_Vector2_w), "error: operands have different dimension"); + } - SECTION("dot Rd*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<1>{3}), p_R1_u, dot); - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<2>{-6, 2}), p_R2_u, dot); - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<3>{-1, 5, 2}), p_R3_u, dot); - REQUIRE_THROWS_WITH(dot((TinyVector<2>{-6, 2}), p_R1_u), "error: incompatible operand types R^2 and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(dot((TinyVector<3>{-1, 5, 2}), p_R2_u), - "error: incompatible operand types R^3 and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(dot((TinyVector<1>{-1}), p_R3_u), "error: incompatible operand types R^1 and Vh(P0:R^3)"); - } + SECTION("dot Vh*Rd -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R1_u, (TinyVector<1>{3}), dot); + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R2_u, (TinyVector<2>{-6, 2}), dot); + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R3_u, (TinyVector<3>{-1, 5, 2}), dot); + REQUIRE_THROWS_WITH(dot(p_R1_u, (TinyVector<2>{-6, 2})), + "error: incompatible operand types Vh(P0:R^1) and R^2"); + REQUIRE_THROWS_WITH(dot(p_R2_u, (TinyVector<3>{-1, 5, 2})), + "error: incompatible operand types Vh(P0:R^2) and R^3"); + REQUIRE_THROWS_WITH(dot(p_R3_u, (TinyVector<1>{-1})), "error: incompatible operand types Vh(P0:R^3) and R^1"); + } - SECTION("sum_of_R* Vh -> R*") - { - REQUIRE(sum_of<double>(p_u) == sum(p_u->cellValues())); - REQUIRE(sum_of<TinyVector<1>>(p_R1_u) == sum(p_R1_u->cellValues())); - REQUIRE(sum_of<TinyVector<2>>(p_R2_u) == sum(p_R2_u->cellValues())); - REQUIRE(sum_of<TinyVector<3>>(p_R3_u) == sum(p_R3_u->cellValues())); - REQUIRE(sum_of<TinyMatrix<1>>(p_R1x1_u) == sum(p_R1x1_u->cellValues())); - REQUIRE(sum_of<TinyMatrix<2>>(p_R2x2_u) == sum(p_R2x2_u->cellValues())); - REQUIRE(sum_of<TinyMatrix<3>>(p_R3x3_u) == sum(p_R3x3_u->cellValues())); - - REQUIRE_THROWS_WITH(sum_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); - } + SECTION("dot Rd*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<1>{3}), p_R1_u, dot); + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<2>{-6, 2}), p_R2_u, dot); + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<3>{-1, 5, 2}), p_R3_u, dot); + REQUIRE_THROWS_WITH(dot((TinyVector<2>{-6, 2}), p_R1_u), + "error: incompatible operand types R^2 and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(dot((TinyVector<3>{-1, 5, 2}), p_R2_u), + "error: incompatible operand types R^3 and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(dot((TinyVector<1>{-1}), p_R3_u), "error: incompatible operand types R^1 and Vh(P0:R^3)"); + } - SECTION("integral_of_R* Vh -> R*") - { - auto integrate_locally = [&](const auto& cell_values) { - const auto& Vj = MeshDataManager::instance().getMeshData(*mesh).Vj(); - using DataType = decltype(double{} * cell_values[CellId{0}]); - CellValue<DataType> local_integral{mesh->connectivity()}; - parallel_for( - local_integral.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { local_integral[cell_id] = Vj[cell_id] * cell_values[cell_id]; }); - return local_integral; - }; - - REQUIRE(integral_of<double>(p_u) == sum(integrate_locally(p_u->cellValues()))); - REQUIRE(integral_of<TinyVector<1>>(p_R1_u) == sum(integrate_locally(p_R1_u->cellValues()))); - REQUIRE(integral_of<TinyVector<2>>(p_R2_u) == sum(integrate_locally(p_R2_u->cellValues()))); - REQUIRE(integral_of<TinyVector<3>>(p_R3_u) == sum(integrate_locally(p_R3_u->cellValues()))); - REQUIRE(integral_of<TinyMatrix<1>>(p_R1x1_u) == sum(integrate_locally(p_R1x1_u->cellValues()))); - REQUIRE(integral_of<TinyMatrix<2>>(p_R2x2_u) == sum(integrate_locally(p_R2x2_u->cellValues()))); - REQUIRE(integral_of<TinyMatrix<3>>(p_R3x3_u) == sum(integrate_locally(p_R3x3_u->cellValues()))); - - REQUIRE_THROWS_WITH(integral_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + SECTION("sum_of_R* Vh -> R*") + { + REQUIRE(sum_of<double>(p_u) == sum(p_u->cellValues())); + REQUIRE(sum_of<TinyVector<1>>(p_R1_u) == sum(p_R1_u->cellValues())); + REQUIRE(sum_of<TinyVector<2>>(p_R2_u) == sum(p_R2_u->cellValues())); + REQUIRE(sum_of<TinyVector<3>>(p_R3_u) == sum(p_R3_u->cellValues())); + REQUIRE(sum_of<TinyMatrix<1>>(p_R1x1_u) == sum(p_R1x1_u->cellValues())); + REQUIRE(sum_of<TinyMatrix<2>>(p_R2x2_u) == sum(p_R2x2_u->cellValues())); + REQUIRE(sum_of<TinyMatrix<3>>(p_R3x3_u) == sum(p_R3x3_u->cellValues())); + + REQUIRE_THROWS_WITH(sum_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + } + + SECTION("integral_of_R* Vh -> R*") + { + auto integrate_locally = [&](const auto& cell_values) { + const auto& Vj = MeshDataManager::instance().getMeshData(*mesh).Vj(); + using DataType = decltype(double{} * cell_values[CellId{0}]); + CellValue<DataType> local_integral{mesh->connectivity()}; + parallel_for( + local_integral.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { local_integral[cell_id] = Vj[cell_id] * cell_values[cell_id]; }); + return local_integral; + }; + + REQUIRE(integral_of<double>(p_u) == sum(integrate_locally(p_u->cellValues()))); + REQUIRE(integral_of<TinyVector<1>>(p_R1_u) == sum(integrate_locally(p_R1_u->cellValues()))); + REQUIRE(integral_of<TinyVector<2>>(p_R2_u) == sum(integrate_locally(p_R2_u->cellValues()))); + REQUIRE(integral_of<TinyVector<3>>(p_R3_u) == sum(integrate_locally(p_R3_u->cellValues()))); + REQUIRE(integral_of<TinyMatrix<1>>(p_R1x1_u) == sum(integrate_locally(p_R1x1_u->cellValues()))); + REQUIRE(integral_of<TinyMatrix<2>>(p_R2x2_u) == sum(integrate_locally(p_R2x2_u->cellValues()))); + REQUIRE(integral_of<TinyMatrix<3>>(p_R3x3_u) == sum(integrate_locally(p_R3x3_u->cellValues()))); + + REQUIRE_THROWS_WITH(integral_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + } + } } } } diff --git a/tests/test_EmbeddedIDiscreteFunctionOperators.cpp b/tests/test_EmbeddedIDiscreteFunctionOperators.cpp index 0b0db97f811afb1682679240d7d2240986f2d4d1..a20047a27a420027aff9a39fa24c3189e1a72b0b 100644 --- a/tests/test_EmbeddedIDiscreteFunctionOperators.cpp +++ b/tests/test_EmbeddedIDiscreteFunctionOperators.cpp @@ -195,668 +195,691 @@ TEST_CASE("EmbeddedIDiscreteFunctionOperators", "[scheme]") using Rd = TinyVector<Dimension>; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian1DMesh(); - - std::shared_ptr other_mesh = - std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); - - CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - CellValue<double> u_R_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - CellValue<double> v_R_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.6 + std::sin(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - std::shared_ptr p_R_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, u_R_values); - std::shared_ptr p_other_mesh_R_u = - std::make_shared<const DiscreteFunctionP0<Dimension, double>>(other_mesh, u_R_values); - std::shared_ptr p_R_v = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, v_R_values); - - std::shared_ptr p_R1_u = [=] { - CellValue<TinyVector<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R1_v = [=] { - CellValue<TinyVector<1>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R1_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(other_mesh, p_R1_u->cellValues()); - - constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { - if constexpr (Dimension == 1) { - return {x[0], 1 + x[0] * x[0]}; - } else if constexpr (Dimension == 2) { - return {x[0], x[1]}; - } else if constexpr (Dimension == 3) { - return {x[0], x[1] + x[2]}; - } - }; - - std::shared_ptr p_R2_u = [=] { - CellValue<TinyVector<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - uj[cell_id] = {2 * x[0] + 1, 1 - x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R2_v = [=] { - CellValue<TinyVector<2>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R2_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(other_mesh, p_R2_u->cellValues()); - - constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { - if constexpr (Dimension == 1) { - return {x[0], 1 + x[0] * x[0], 2 - x[0]}; - } else if constexpr (Dimension == 2) { - return {x[0], x[1], x[0] + x[1]}; - } else if constexpr (Dimension == 3) { - return {x[0], x[1], x[2]}; - } - }; - - std::shared_ptr p_R3_u = [=] { - CellValue<TinyVector<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj[cell_id] = {2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); - }(); - - std::shared_ptr p_R3_v = [=] { - CellValue<TinyVector<3>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R3_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(other_mesh, p_R3_u->cellValues()); - - std::shared_ptr p_R1x1_u = [=] { - CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = {2 * xj[cell_id][0] + 1}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); - }(); - - std::shared_ptr p_other_mesh_R1x1_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(other_mesh, p_R1x1_u->cellValues()); - - std::shared_ptr p_R1x1_v = [=] { - CellValue<TinyMatrix<1>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { vj[cell_id] = {0.3 - xj[cell_id][0]}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, vj); - }(); - - std::shared_ptr p_R2x2_u = [=] { - CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - uj[cell_id] = {2 * x[0] + 1, 1 - x[1], // - 2 * x[1], -x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); - }(); - - std::shared_ptr p_other_mesh_R2x2_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(other_mesh, p_R2x2_u->cellValues()); - - std::shared_ptr p_R2x2_v = [=] { - CellValue<TinyMatrix<2>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - vj[cell_id] = {x[0] + 0.3, 1 - x[1] - x[0], // - 2 * x[1] + x[0], x[1] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, vj); - }(); - - std::shared_ptr p_R3x3_u = [=] { - CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - uj[cell_id] = {2 * x[0] + 1, 1 - x[1], 3, // - 2 * x[1], -x[0], x[0] - x[1], // - 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); - }(); - - std::shared_ptr p_other_mesh_R3x3_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(other_mesh, p_R3x3_u->cellValues()); - - std::shared_ptr p_R3x3_v = [=] { - CellValue<TinyMatrix<3>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - vj[cell_id] = {0.2 * x[0] + 1, 2 + x[1], 3 - x[2], // - 2.3 * x[2], x[1] - x[0], x[2] - x[1], // - 2 * x[2] + x[0], x[1] + 0.2 * x[2], x[2] - 2 * x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, vj); - }(); - - std::shared_ptr p_Vector3_u = [=] { - CellArray<double> uj_vector{mesh->connectivity(), 3}; - parallel_for( - uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj_vector[cell_id][0] = 2 * x[0] + 1; - uj_vector[cell_id][1] = 1 - x[1] * x[2]; - uj_vector[cell_id][2] = x[0] + x[2]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); - }(); - - std::shared_ptr p_other_mesh_Vector3_u = - std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(other_mesh, p_Vector3_u->cellArrays()); - - std::shared_ptr p_Vector3_v = [=] { - CellArray<double> vj_vector{mesh->connectivity(), 3}; - parallel_for( - vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj_vector[cell_id][0] = x[0] * x[1] + 1; - vj_vector[cell_id][1] = 2 * x[1]; - vj_vector[cell_id][2] = x[2] * x[0]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, vj_vector); - }(); - - std::shared_ptr p_Vector2_w = [=] { - CellArray<double> wj_vector{mesh->connectivity(), 2}; - parallel_for( - wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - wj_vector[cell_id][0] = x[0] + x[1] * 2; - wj_vector[cell_id][1] = x[0] * x[1]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, wj_vector); - }(); - - SECTION("sum") - { - SECTION("Vh + Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, +, p_R_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1_u, +, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2_u, +, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3_u, +, p_R3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, +, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, +, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, +, p_R3x3_v); - - CHECK_VECTOR_VH2_TO_VH(p_Vector3_u, +, p_Vector3_v); - - REQUIRE_THROWS_WITH(p_R_u + p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u + p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u + p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_Vector3_u + p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(p_Vector3_u + p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); - - REQUIRE_THROWS_WITH(p_R_u + p_other_mesh_R_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1_u + p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2_u + p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3_u + p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1x1_u + p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2x2_u + p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3x3_u + p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_Vector3_u + p_other_mesh_Vector3_u, "error: operands are defined on different meshes"); - } - - SECTION("Vh + X -> Vh") - { - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, bool{true}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, uint64_t{1}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, int64_t{2}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, double{1.3}); - - CHECK_SCALAR_VHxX_TO_VH(p_R1_u, +, (TinyVector<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2_u, +, (TinyVector<2>{1.2, 2.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R3_u, +, (TinyVector<3>{3.2, 7.1, 5.2})); - - CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, +, (TinyMatrix<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, +, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); - CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, +, - (TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8})); - - REQUIRE_THROWS_WITH(p_R_u + (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); - REQUIRE_THROWS_WITH(p_R_u + (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); - REQUIRE_THROWS_WITH(p_R_u + (TinyVector<3>{2, 3, 2}), "error: incompatible operand types Vh(P0:R) and R^3"); - REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); - REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R) and R^2x2"); - REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R) and R^3x3"); - - REQUIRE_THROWS_WITH(p_Vector3_u + (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); - REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<1>{1}), - "error: incompatible operand types Vh(P0Vector:R) and R^1"); - REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<2>{1, 2}), - "error: incompatible operand types Vh(P0Vector:R) and R^2"); - } - - SECTION("X + Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, +, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, +, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, +, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, +, p_R_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyVector<1>{1.3}), +, p_R1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), +, p_R2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), +, p_R3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), +, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), +, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8}), - +, p_R3x3_u); - - REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) + p_R_u, "error: incompatible operand types R^3 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) + p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) + p_R_u, - "error: incompatible operand types R^2x2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) + p_R_u, - "error: incompatible operand types R^3x3 and Vh(P0:R)"); - - REQUIRE_THROWS_WITH((double{1}) + p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_Vector3_u, - "error: incompatible operand types R^1 and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_Vector3_u, - "error: incompatible operand types R^2 and Vh(P0Vector:R)"); - } - } - - SECTION("difference") - { - SECTION("Vh - Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, -, p_R_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1_u, -, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2_u, -, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3_u, -, p_R3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, -, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, -, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, -, p_R3x3_v); - - CHECK_VECTOR_VH2_TO_VH(p_Vector3_u, -, p_Vector3_v); - - REQUIRE_THROWS_WITH(p_R_u - p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u - p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u - p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R_u - p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_Vector3_u - p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(p_Vector3_u - p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); - - REQUIRE_THROWS_WITH(p_R_u - p_other_mesh_R_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1_u - p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2_u - p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3_u - p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1x1_u - p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2x2_u - p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3x3_u - p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_Vector3_u - p_other_mesh_Vector3_u, "error: operands are defined on different meshes"); - } - - SECTION("Vh - X -> Vh") - { - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, bool{true}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, uint64_t{1}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, int64_t{2}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, double{1.3}); - - CHECK_SCALAR_VHxX_TO_VH(p_R1_u, -, (TinyVector<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2_u, -, (TinyVector<2>{1.2, 2.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R3_u, -, (TinyVector<3>{3.2, 7.1, 5.2})); - - CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, -, (TinyMatrix<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, -, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); - CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, -, - (TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8})); - - REQUIRE_THROWS_WITH(p_R_u - (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); - REQUIRE_THROWS_WITH(p_R_u - (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); - REQUIRE_THROWS_WITH(p_R_u - (TinyVector<3>{2, 3, 2}), "error: incompatible operand types Vh(P0:R) and R^3"); - REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); - REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R) and R^2x2"); - REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R) and R^3x3"); - - REQUIRE_THROWS_WITH(p_Vector3_u - (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); - REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<1>{1}), - "error: incompatible operand types Vh(P0Vector:R) and R^1"); - REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<2>{1, 2}), - "error: incompatible operand types Vh(P0Vector:R) and R^2"); - } + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - SECTION("X - Vh -> Vh") + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, -, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, -, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, -, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, -, p_R_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyVector<1>{1.3}), -, p_R1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), -, p_R2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), -, p_R3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), -, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), -, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8}), - -, p_R3x3_u); - - REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) - p_R_u, "error: incompatible operand types R^3 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) - p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) - p_R_u, - "error: incompatible operand types R^2x2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) - p_R_u, - "error: incompatible operand types R^3x3 and Vh(P0:R)"); - - REQUIRE_THROWS_WITH((double{1}) - p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_Vector3_u, - "error: incompatible operand types R^1 and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_Vector3_u, - "error: incompatible operand types R^2 and Vh(P0Vector:R)"); - } - } - - SECTION("product") - { - SECTION("Vh * Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, *, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, *, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, *, p_R3x3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R3_v); + std::shared_ptr other_mesh = + std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); + + CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + CellValue<double> u_R_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + CellValue<double> v_R_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.6 + std::sin(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + std::shared_ptr p_R_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, u_R_values); + std::shared_ptr p_other_mesh_R_u = + std::make_shared<const DiscreteFunctionP0<Dimension, double>>(other_mesh, u_R_values); + std::shared_ptr p_R_v = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, v_R_values); + + std::shared_ptr p_R1_u = [=] { + CellValue<TinyVector<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); + }(); + + std::shared_ptr p_R1_v = [=] { + CellValue<TinyVector<1>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, vj); + }(); + + std::shared_ptr p_other_mesh_R1_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(other_mesh, p_R1_u->cellValues()); + + constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { + if constexpr (Dimension == 1) { + return {x[0], 1 + x[0] * x[0]}; + } else if constexpr (Dimension == 2) { + return {x[0], x[1]}; + } else if constexpr (Dimension == 3) { + return {x[0], x[1] + x[2]}; + } + }; + + std::shared_ptr p_R2_u = [=] { + CellValue<TinyVector<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + uj[cell_id] = {2 * x[0] + 1, 1 - x[1]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); + }(); + + std::shared_ptr p_R2_v = [=] { + CellValue<TinyVector<2>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, vj); + }(); + + std::shared_ptr p_other_mesh_R2_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(other_mesh, p_R2_u->cellValues()); + + constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { + if constexpr (Dimension == 1) { + return {x[0], 1 + x[0] * x[0], 2 - x[0]}; + } else if constexpr (Dimension == 2) { + return {x[0], x[1], x[0] + x[1]}; + } else if constexpr (Dimension == 3) { + return {x[0], x[1], x[2]}; + } + }; + + std::shared_ptr p_R3_u = [=] { + CellValue<TinyVector<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj[cell_id] = {2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); + }(); + + std::shared_ptr p_R3_v = [=] { + CellValue<TinyVector<3>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, vj); + }(); + + std::shared_ptr p_other_mesh_R3_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(other_mesh, p_R3_u->cellValues()); + + std::shared_ptr p_R1x1_u = [=] { + CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = {2 * xj[cell_id][0] + 1}; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); + }(); + + std::shared_ptr p_other_mesh_R1x1_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(other_mesh, p_R1x1_u->cellValues()); + + std::shared_ptr p_R1x1_v = [=] { + CellValue<TinyMatrix<1>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { vj[cell_id] = {0.3 - xj[cell_id][0]}; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, vj); + }(); + + std::shared_ptr p_R2x2_u = [=] { + CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + uj[cell_id] = {2 * x[0] + 1, 1 - x[1], // + 2 * x[1], -x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); + }(); + + std::shared_ptr p_other_mesh_R2x2_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(other_mesh, p_R2x2_u->cellValues()); + + std::shared_ptr p_R2x2_v = [=] { + CellValue<TinyMatrix<2>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + vj[cell_id] = {x[0] + 0.3, 1 - x[1] - x[0], // + 2 * x[1] + x[0], x[1] - x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, vj); + }(); + + std::shared_ptr p_R3x3_u = [=] { + CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + uj[cell_id] = {2 * x[0] + 1, 1 - x[1], 3, // + 2 * x[1], -x[0], x[0] - x[1], // + 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); + }(); + + std::shared_ptr p_other_mesh_R3x3_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(other_mesh, p_R3x3_u->cellValues()); + + std::shared_ptr p_R3x3_v = [=] { + CellValue<TinyMatrix<3>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + vj[cell_id] = {0.2 * x[0] + 1, 2 + x[1], 3 - x[2], // + 2.3 * x[2], x[1] - x[0], x[2] - x[1], // + 2 * x[2] + x[0], x[1] + 0.2 * x[2], x[2] - 2 * x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, vj); + }(); + + std::shared_ptr p_Vector3_u = [=] { + CellArray<double> uj_vector{mesh->connectivity(), 3}; + parallel_for( + uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj_vector[cell_id][0] = 2 * x[0] + 1; + uj_vector[cell_id][1] = 1 - x[1] * x[2]; + uj_vector[cell_id][2] = x[0] + x[2]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); + }(); + + std::shared_ptr p_other_mesh_Vector3_u = + std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(other_mesh, p_Vector3_u->cellArrays()); + + std::shared_ptr p_Vector3_v = [=] { + CellArray<double> vj_vector{mesh->connectivity(), 3}; + parallel_for( + vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj_vector[cell_id][0] = x[0] * x[1] + 1; + vj_vector[cell_id][1] = 2 * x[1]; + vj_vector[cell_id][2] = x[2] * x[0]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, vj_vector); + }(); + + std::shared_ptr p_Vector2_w = [=] { + CellArray<double> wj_vector{mesh->connectivity(), 2}; + parallel_for( + wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + wj_vector[cell_id][0] = x[0] + x[1] * 2; + wj_vector[cell_id][1] = x[0] * x[1]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, wj_vector); + }(); + + SECTION("sum") + { + SECTION("Vh + Vh -> Vh") + { + CHECK_SCALAR_VH2_TO_VH(p_R_u, +, p_R_v); + + CHECK_SCALAR_VH2_TO_VH(p_R1_u, +, p_R1_v); + CHECK_SCALAR_VH2_TO_VH(p_R2_u, +, p_R2_v); + CHECK_SCALAR_VH2_TO_VH(p_R3_u, +, p_R3_v); + + CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, +, p_R1x1_v); + CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, +, p_R2x2_v); + CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, +, p_R3x3_v); + + CHECK_VECTOR_VH2_TO_VH(p_Vector3_u, +, p_Vector3_v); + + REQUIRE_THROWS_WITH(p_R_u + p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u + p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u + p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_Vector3_u + p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(p_Vector3_u + p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); + + REQUIRE_THROWS_WITH(p_R_u + p_other_mesh_R_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1_u + p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2_u + p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3_u + p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1x1_u + p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2x2_u + p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3x3_u + p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_Vector3_u + p_other_mesh_Vector3_u, + "error: operands are defined on different meshes"); + } - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R3x3_v); + SECTION("Vh + X -> Vh") + { + CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, bool{true}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, uint64_t{1}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, int64_t{2}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, double{1.3}); + + CHECK_SCALAR_VHxX_TO_VH(p_R1_u, +, (TinyVector<1>{1.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R2_u, +, (TinyVector<2>{1.2, 2.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R3_u, +, (TinyVector<3>{3.2, 7.1, 5.2})); + + CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, +, (TinyMatrix<1>{1.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, +, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); + CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, +, + (TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8})); + + REQUIRE_THROWS_WITH(p_R_u + (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); + REQUIRE_THROWS_WITH(p_R_u + (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); + REQUIRE_THROWS_WITH(p_R_u + (TinyVector<3>{2, 3, 2}), + "error: incompatible operand types Vh(P0:R) and R^3"); + REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); + REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R) and R^2x2"); + REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R) and R^3x3"); + + REQUIRE_THROWS_WITH(p_Vector3_u + (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); + REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<1>{1}), + "error: incompatible operand types Vh(P0Vector:R) and R^1"); + REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<2>{1, 2}), + "error: incompatible operand types Vh(P0Vector:R) and R^2"); + } - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, *, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, *, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, *, p_R3_v); + SECTION("X + Vh -> Vh") + { + CHECK_SCALAR_XxVH_TO_VH(bool{true}, +, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, +, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, +, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, +, p_R_u); + + CHECK_SCALAR_XxVH_TO_VH((TinyVector<1>{1.3}), +, p_R1_u); + CHECK_SCALAR_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), +, p_R2_u); + CHECK_SCALAR_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), +, p_R3_u); + + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), +, p_R1x1_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), +, p_R2x2_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), + +, p_R3x3_u); + + REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) + p_R_u, + "error: incompatible operand types R^3 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) + p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) + p_R_u, + "error: incompatible operand types R^2x2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) + p_R_u, + "error: incompatible operand types R^3x3 and Vh(P0:R)"); + + REQUIRE_THROWS_WITH((double{1}) + p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_Vector3_u, + "error: incompatible operand types R^1 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_Vector3_u, + "error: incompatible operand types R^2 and Vh(P0Vector:R)"); + } + } + SECTION("difference") { - std::shared_ptr p_fuv = p_R_u * p_Vector3_v; + SECTION("Vh - Vh -> Vh") + { + CHECK_SCALAR_VH2_TO_VH(p_R_u, -, p_R_v); + + CHECK_SCALAR_VH2_TO_VH(p_R1_u, -, p_R1_v); + CHECK_SCALAR_VH2_TO_VH(p_R2_u, -, p_R2_v); + CHECK_SCALAR_VH2_TO_VH(p_R3_u, -, p_R3_v); + + CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, -, p_R1x1_v); + CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, -, p_R2x2_v); + CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, -, p_R3x3_v); + + CHECK_VECTOR_VH2_TO_VH(p_Vector3_u, -, p_Vector3_v); + + REQUIRE_THROWS_WITH(p_R_u - p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u - p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u - p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R_u - p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_Vector3_u - p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(p_Vector3_u - p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); + + REQUIRE_THROWS_WITH(p_R_u - p_other_mesh_R_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1_u - p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2_u - p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3_u - p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1x1_u - p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2x2_u - p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3x3_u - p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_Vector3_u - p_other_mesh_Vector3_u, + "error: operands are defined on different meshes"); + } - REQUIRE(p_fuv.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_fuv)); + SECTION("Vh - X -> Vh") + { + CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, bool{true}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, uint64_t{1}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, int64_t{2}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, double{1.3}); + + CHECK_SCALAR_VHxX_TO_VH(p_R1_u, -, (TinyVector<1>{1.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R2_u, -, (TinyVector<2>{1.2, 2.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R3_u, -, (TinyVector<3>{3.2, 7.1, 5.2})); + + CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, -, (TinyMatrix<1>{1.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, -, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); + CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, -, + (TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8})); + + REQUIRE_THROWS_WITH(p_R_u - (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); + REQUIRE_THROWS_WITH(p_R_u - (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); + REQUIRE_THROWS_WITH(p_R_u - (TinyVector<3>{2, 3, 2}), + "error: incompatible operand types Vh(P0:R) and R^3"); + REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); + REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R) and R^2x2"); + REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R) and R^3x3"); + + REQUIRE_THROWS_WITH(p_Vector3_u - (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); + REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<1>{1}), + "error: incompatible operand types Vh(P0Vector:R) and R^1"); + REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<2>{1, 2}), + "error: incompatible operand types Vh(P0Vector:R) and R^2"); + } - const auto& fuv = dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_fuv); + SECTION("X - Vh -> Vh") + { + CHECK_SCALAR_XxVH_TO_VH(bool{true}, -, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, -, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, -, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, -, p_R_u); + + CHECK_SCALAR_XxVH_TO_VH((TinyVector<1>{1.3}), -, p_R1_u); + CHECK_SCALAR_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), -, p_R2_u); + CHECK_SCALAR_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), -, p_R3_u); + + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), -, p_R1x1_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), -, p_R2x2_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), + -, p_R3x3_u); + + REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) - p_R_u, + "error: incompatible operand types R^3 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) - p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) - p_R_u, + "error: incompatible operand types R^2x2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) - p_R_u, + "error: incompatible operand types R^3x3 and Vh(P0:R)"); + + REQUIRE_THROWS_WITH((double{1}) - p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_Vector3_u, + "error: incompatible operand types R^1 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_Vector3_u, + "error: incompatible operand types R^2 and Vh(P0Vector:R)"); + } + } - auto lhs_values = p_R_u->cellValues(); - auto rhs_arrays = p_Vector3_v->cellArrays(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < lhs_values.numberOfItems(); ++cell_id) { - for (size_t i = 0; i < fuv.size(); ++i) { - if (fuv[cell_id][i] != (lhs_values[cell_id] * rhs_arrays[cell_id][i])) { - is_same = false; - break; + SECTION("product") + { + SECTION("Vh * Vh -> Vh") + { + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R_v); + + CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, *, p_R1x1_v); + CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, *, p_R2x2_v); + CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, *, p_R3x3_v); + + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R1_v); + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R2_v); + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R3_v); + + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R1x1_v); + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R2x2_v); + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R3x3_v); + + CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, *, p_R1_v); + CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, *, p_R2_v); + CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, *, p_R3_v); + + { + std::shared_ptr p_fuv = p_R_u * p_Vector3_v; + + REQUIRE(p_fuv.use_count() > 0); + REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_fuv)); + + const auto& fuv = dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_fuv); + + auto lhs_values = p_R_u->cellValues(); + auto rhs_arrays = p_Vector3_v->cellArrays(); + bool is_same = true; + for (CellId cell_id = 0; cell_id < lhs_values.numberOfItems(); ++cell_id) { + for (size_t i = 0; i < fuv.size(); ++i) { + if (fuv[cell_id][i] != (lhs_values[cell_id] * rhs_arrays[cell_id][i])) { + is_same = false; + break; + } + } } - } - } - REQUIRE(is_same); - } + REQUIRE(is_same); + } - REQUIRE_THROWS_WITH(p_R1_u * p_R1_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u * p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u * p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R1_u * p_R2x2_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^2x2)"); - - REQUIRE_THROWS_WITH(p_R1x1_u * p_R2x2_v, "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_R3x3_v, "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3x3)"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_R1x1_v, "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1x1)"); - - REQUIRE_THROWS_WITH(p_R1x1_u * p_R2_v, "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_R3_v, "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_R1_v, "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1)"); - - REQUIRE_THROWS_WITH(p_R1_u * p_Vector3_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R2_u * p_Vector3_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R3_u * p_Vector3_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R1x1_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_Vector3_u * p_Vector3_v, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0Vector:R)"); - - REQUIRE_THROWS_WITH(p_Vector3_v * p_R_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R1_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R2_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R3_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R1x1_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R2x2_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R3x3_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3x3)"); - - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1x1_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_Vector3_u, "error: operands are defined on different meshes"); - } + REQUIRE_THROWS_WITH(p_R1_u * p_R1_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u * p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u * p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R1_u * p_R2x2_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^2x2)"); + + REQUIRE_THROWS_WITH(p_R1x1_u * p_R2x2_v, + "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_R3x3_v, + "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3x3)"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_R1x1_v, + "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1x1)"); + + REQUIRE_THROWS_WITH(p_R1x1_u * p_R2_v, "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_R3_v, "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_R1_v, "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1)"); + + REQUIRE_THROWS_WITH(p_R1_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^1) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R2_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^2) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R3_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^3) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R1x1_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_Vector3_u * p_Vector3_v, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0Vector:R)"); + + REQUIRE_THROWS_WITH(p_Vector3_v * p_R_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R1_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R2_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R3_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R1x1_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R2x2_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R3x3_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3x3)"); + + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1x1_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_Vector3_u, "error: operands are defined on different meshes"); + } - SECTION("Vh * X -> Vh") - { - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, bool{true}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, uint64_t{1}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, int64_t{2}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, double{1.3}); - - CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, *, (TinyMatrix<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, *, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); - CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, *, - (TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8})); - - REQUIRE_THROWS_WITH(p_R1_u * (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R^1) and R^1"); - REQUIRE_THROWS_WITH(p_R2_u * (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R^2) and R^2"); - REQUIRE_THROWS_WITH(p_R3_u * (TinyVector<3>{2, 3, 2}), - "error: incompatible operand types Vh(P0:R^3) and R^3"); - REQUIRE_THROWS_WITH(p_R1_u * (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R^1) and R^1x1"); - REQUIRE_THROWS_WITH(p_R2_u * (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R^2) and R^2x2"); - REQUIRE_THROWS_WITH(p_R3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R^3) and R^3x3"); - REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<1>{2}), - "error: incompatible operand types Vh(P0:R^2x2) and R^1x1"); - REQUIRE_THROWS_WITH(p_R1x1_u * (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R^1x1) and R^2x2"); - REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R^2x2) and R^3x3"); - - REQUIRE_THROWS_WITH(p_Vector3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0Vector:R) and R^3x3"); - REQUIRE_THROWS_WITH(p_Vector3_u * (double{2}), "error: incompatible operand types Vh(P0Vector:R) and R"); - } + SECTION("Vh * X -> Vh") + { + CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, bool{true}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, uint64_t{1}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, int64_t{2}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, double{1.3}); + + CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, *, (TinyMatrix<1>{1.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, *, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); + CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, *, + (TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8})); + + REQUIRE_THROWS_WITH(p_R1_u * (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R^1) and R^1"); + REQUIRE_THROWS_WITH(p_R2_u * (TinyVector<2>{1, 2}), + "error: incompatible operand types Vh(P0:R^2) and R^2"); + REQUIRE_THROWS_WITH(p_R3_u * (TinyVector<3>{2, 3, 2}), + "error: incompatible operand types Vh(P0:R^3) and R^3"); + REQUIRE_THROWS_WITH(p_R1_u * (TinyMatrix<1>{2}), + "error: incompatible operand types Vh(P0:R^1) and R^1x1"); + REQUIRE_THROWS_WITH(p_R2_u * (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R^2) and R^2x2"); + REQUIRE_THROWS_WITH(p_R3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R^3) and R^3x3"); + REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<1>{2}), + "error: incompatible operand types Vh(P0:R^2x2) and R^1x1"); + REQUIRE_THROWS_WITH(p_R1x1_u * (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R^1x1) and R^2x2"); + REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R^2x2) and R^3x3"); + + REQUIRE_THROWS_WITH(p_Vector3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0Vector:R) and R^3x3"); + REQUIRE_THROWS_WITH(p_Vector3_u * (double{2}), "error: incompatible operand types Vh(P0Vector:R) and R"); + } - SECTION("X * Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R_u); - - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R1x1_u); - - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R2x2_u); - - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R3x3_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R3x3_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R3x3_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R3x3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + SECTION("X * Vh -> Vh") + { + CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R_u); + + CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R1x1_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R1x1_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R1x1_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R1x1_u); + + CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R2x2_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R2x2_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R2x2_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R2x2_u); + + CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R3x3_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R3x3_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R3x3_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R3x3_u); + + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // 4.7, 2.3, 7.1, // 9.7, 3.2, 6.8}), *, p_R3_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1x1_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2x2_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // 4.7, 2.3, 7.1, // 9.7, 3.2, 6.8}), *, p_R3x3_u); - CHECK_VECTOR_XxVH_TO_VH(bool{true}, *, p_Vector3_u); - CHECK_VECTOR_XxVH_TO_VH(uint64_t{1}, *, p_Vector3_u); - CHECK_VECTOR_XxVH_TO_VH(int64_t{2}, *, p_Vector3_u); - CHECK_VECTOR_XxVH_TO_VH(double{1.3}, *, p_Vector3_u); - - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R_u, - "error: incompatible operand types R^2x2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R_u, - "error: incompatible operand types R^3x3 and Vh(P0:R)"); - - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2_u, "error: incompatible operand types R^1x1 and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3_u, - "error: incompatible operand types R^2x2 and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2_u, - "error: incompatible operand types R^3x3 and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R1_u, - "error: incompatible operand types R^3x3 and Vh(P0:R^1)"); - - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2x2_u, - "error: incompatible operand types R^1x1 and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3x3_u, - "error: incompatible operand types R^2x2 and Vh(P0:R^3x3)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2x2_u, - "error: incompatible operand types R^3x3 and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R1x1_u, - "error: incompatible operand types R^2x2 and Vh(P0:R^1x1)"); - - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_Vector3_u, - "error: incompatible operand types R^3x3 and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_Vector3_u, - "error: incompatible operand types R^1x1 and Vh(P0Vector:R)"); - } - } + CHECK_VECTOR_XxVH_TO_VH(bool{true}, *, p_Vector3_u); + CHECK_VECTOR_XxVH_TO_VH(uint64_t{1}, *, p_Vector3_u); + CHECK_VECTOR_XxVH_TO_VH(int64_t{2}, *, p_Vector3_u); + CHECK_VECTOR_XxVH_TO_VH(double{1.3}, *, p_Vector3_u); + + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R_u, + "error: incompatible operand types R^2x2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R_u, + "error: incompatible operand types R^3x3 and Vh(P0:R)"); + + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2_u, + "error: incompatible operand types R^1x1 and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3_u, + "error: incompatible operand types R^2x2 and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2_u, + "error: incompatible operand types R^3x3 and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R1_u, + "error: incompatible operand types R^3x3 and Vh(P0:R^1)"); + + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2x2_u, + "error: incompatible operand types R^1x1 and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3x3_u, + "error: incompatible operand types R^2x2 and Vh(P0:R^3x3)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2x2_u, + "error: incompatible operand types R^3x3 and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R1x1_u, + "error: incompatible operand types R^2x2 and Vh(P0:R^1x1)"); + + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_Vector3_u, + "error: incompatible operand types R^3x3 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_Vector3_u, + "error: incompatible operand types R^1x1 and Vh(P0Vector:R)"); + } + } - SECTION("ratio") - { - SECTION("Vh / Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, /, p_R_v); + SECTION("ratio") + { + SECTION("Vh / Vh -> Vh") + { + CHECK_SCALAR_VH2_TO_VH(p_R_u, /, p_R_v); - REQUIRE_THROWS_WITH(p_R_u / p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u / p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u / p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R_u / p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_R_u / p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u / p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u / p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R_u / p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_R_u / p_other_mesh_R_u, "error: operands are defined on different meshes"); - } + REQUIRE_THROWS_WITH(p_R_u / p_other_mesh_R_u, "error: operands are defined on different meshes"); + } - SECTION("X / Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, /, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, /, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, /, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, /, p_R_u); + SECTION("X / Vh -> Vh") + { + CHECK_SCALAR_XxVH_TO_VH(bool{true}, /, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, /, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, /, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, /, p_R_u); + } + } } } } @@ -867,668 +890,691 @@ TEST_CASE("EmbeddedIDiscreteFunctionOperators", "[scheme]") using Rd = TinyVector<Dimension>; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian2DMesh(); - - std::shared_ptr other_mesh = - std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); - - CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - CellValue<double> u_R_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - CellValue<double> v_R_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.6 + std::sin(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - std::shared_ptr p_R_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, u_R_values); - std::shared_ptr p_other_mesh_R_u = - std::make_shared<const DiscreteFunctionP0<Dimension, double>>(other_mesh, u_R_values); - std::shared_ptr p_R_v = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, v_R_values); - - std::shared_ptr p_R1_u = [=] { - CellValue<TinyVector<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R1_v = [=] { - CellValue<TinyVector<1>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R1_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(other_mesh, p_R1_u->cellValues()); - - constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { - if constexpr (Dimension == 1) { - return {x[0], 1 + x[0] * x[0]}; - } else if constexpr (Dimension == 2) { - return {x[0], x[1]}; - } else if constexpr (Dimension == 3) { - return {x[0], x[1] + x[2]}; - } - }; - - std::shared_ptr p_R2_u = [=] { - CellValue<TinyVector<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - uj[cell_id] = {2 * x[0] + 1, 1 - x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R2_v = [=] { - CellValue<TinyVector<2>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R2_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(other_mesh, p_R2_u->cellValues()); - - constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { - if constexpr (Dimension == 1) { - return {x[0], 1 + x[0] * x[0], 2 - x[0]}; - } else if constexpr (Dimension == 2) { - return {x[0], x[1], x[0] + x[1]}; - } else if constexpr (Dimension == 3) { - return {x[0], x[1], x[2]}; - } - }; - - std::shared_ptr p_R3_u = [=] { - CellValue<TinyVector<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj[cell_id] = {2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); - }(); - - std::shared_ptr p_R3_v = [=] { - CellValue<TinyVector<3>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R3_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(other_mesh, p_R3_u->cellValues()); - - std::shared_ptr p_R1x1_u = [=] { - CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = {2 * xj[cell_id][0] + 1}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); - }(); - - std::shared_ptr p_other_mesh_R1x1_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(other_mesh, p_R1x1_u->cellValues()); - - std::shared_ptr p_R1x1_v = [=] { - CellValue<TinyMatrix<1>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { vj[cell_id] = {0.3 - xj[cell_id][0]}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, vj); - }(); - - std::shared_ptr p_R2x2_u = [=] { - CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - uj[cell_id] = {2 * x[0] + 1, 1 - x[1], // - 2 * x[1], -x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); - }(); - - std::shared_ptr p_other_mesh_R2x2_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(other_mesh, p_R2x2_u->cellValues()); - - std::shared_ptr p_R2x2_v = [=] { - CellValue<TinyMatrix<2>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - vj[cell_id] = {x[0] + 0.3, 1 - x[1] - x[0], // - 2 * x[1] + x[0], x[1] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, vj); - }(); - - std::shared_ptr p_R3x3_u = [=] { - CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - uj[cell_id] = {2 * x[0] + 1, 1 - x[1], 3, // - 2 * x[1], -x[0], x[0] - x[1], // - 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); - }(); - - std::shared_ptr p_other_mesh_R3x3_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(other_mesh, p_R3x3_u->cellValues()); - - std::shared_ptr p_R3x3_v = [=] { - CellValue<TinyMatrix<3>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - vj[cell_id] = {0.2 * x[0] + 1, 2 + x[1], 3 - x[2], // - 2.3 * x[2], x[1] - x[0], x[2] - x[1], // - 2 * x[2] + x[0], x[1] + 0.2 * x[2], x[2] - 2 * x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, vj); - }(); - - std::shared_ptr p_Vector3_u = [=] { - CellArray<double> uj_vector{mesh->connectivity(), 3}; - parallel_for( - uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj_vector[cell_id][0] = 2 * x[0] + 1; - uj_vector[cell_id][1] = 1 - x[1] * x[2]; - uj_vector[cell_id][2] = x[0] + x[2]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); - }(); - - std::shared_ptr p_other_mesh_Vector3_u = - std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(other_mesh, p_Vector3_u->cellArrays()); - - std::shared_ptr p_Vector3_v = [=] { - CellArray<double> vj_vector{mesh->connectivity(), 3}; - parallel_for( - vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj_vector[cell_id][0] = x[0] * x[1] + 1; - vj_vector[cell_id][1] = 2 * x[1]; - vj_vector[cell_id][2] = x[2] * x[0]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, vj_vector); - }(); - - std::shared_ptr p_Vector2_w = [=] { - CellArray<double> wj_vector{mesh->connectivity(), 2}; - parallel_for( - wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - wj_vector[cell_id][0] = x[0] + x[1] * 2; - wj_vector[cell_id][1] = x[0] * x[1]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, wj_vector); - }(); - - SECTION("sum") - { - SECTION("Vh + Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, +, p_R_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1_u, +, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2_u, +, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3_u, +, p_R3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, +, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, +, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, +, p_R3x3_v); - - CHECK_VECTOR_VH2_TO_VH(p_Vector3_u, +, p_Vector3_v); - - REQUIRE_THROWS_WITH(p_R_u + p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u + p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u + p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_Vector3_u + p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(p_Vector3_u + p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); - - REQUIRE_THROWS_WITH(p_R_u + p_other_mesh_R_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1_u + p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2_u + p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3_u + p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1x1_u + p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2x2_u + p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3x3_u + p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_Vector3_u + p_other_mesh_Vector3_u, "error: operands are defined on different meshes"); - } - - SECTION("Vh + X -> Vh") - { - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, bool{true}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, uint64_t{1}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, int64_t{2}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, double{1.3}); - - CHECK_SCALAR_VHxX_TO_VH(p_R1_u, +, (TinyVector<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2_u, +, (TinyVector<2>{1.2, 2.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R3_u, +, (TinyVector<3>{3.2, 7.1, 5.2})); - - CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, +, (TinyMatrix<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, +, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); - CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, +, - (TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8})); - - REQUIRE_THROWS_WITH(p_R_u + (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); - REQUIRE_THROWS_WITH(p_R_u + (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); - REQUIRE_THROWS_WITH(p_R_u + (TinyVector<3>{2, 3, 2}), "error: incompatible operand types Vh(P0:R) and R^3"); - REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); - REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R) and R^2x2"); - REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R) and R^3x3"); - - REQUIRE_THROWS_WITH(p_Vector3_u + (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); - REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<1>{1}), - "error: incompatible operand types Vh(P0Vector:R) and R^1"); - REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<2>{1, 2}), - "error: incompatible operand types Vh(P0Vector:R) and R^2"); - } - - SECTION("X + Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, +, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, +, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, +, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, +, p_R_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyVector<1>{1.3}), +, p_R1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), +, p_R2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), +, p_R3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), +, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), +, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8}), - +, p_R3x3_u); - - REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) + p_R_u, "error: incompatible operand types R^3 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) + p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) + p_R_u, - "error: incompatible operand types R^2x2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) + p_R_u, - "error: incompatible operand types R^3x3 and Vh(P0:R)"); - - REQUIRE_THROWS_WITH((double{1}) + p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_Vector3_u, - "error: incompatible operand types R^1 and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_Vector3_u, - "error: incompatible operand types R^2 and Vh(P0Vector:R)"); - } - } - - SECTION("difference") - { - SECTION("Vh - Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, -, p_R_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1_u, -, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2_u, -, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3_u, -, p_R3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, -, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, -, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, -, p_R3x3_v); - - CHECK_VECTOR_VH2_TO_VH(p_Vector3_u, -, p_Vector3_v); - - REQUIRE_THROWS_WITH(p_R_u - p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u - p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u - p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R_u - p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_Vector3_u - p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(p_Vector3_u - p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); - - REQUIRE_THROWS_WITH(p_R_u - p_other_mesh_R_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1_u - p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2_u - p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3_u - p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1x1_u - p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2x2_u - p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3x3_u - p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_Vector3_u - p_other_mesh_Vector3_u, "error: operands are defined on different meshes"); - } - - SECTION("Vh - X -> Vh") - { - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, bool{true}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, uint64_t{1}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, int64_t{2}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, double{1.3}); - - CHECK_SCALAR_VHxX_TO_VH(p_R1_u, -, (TinyVector<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2_u, -, (TinyVector<2>{1.2, 2.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R3_u, -, (TinyVector<3>{3.2, 7.1, 5.2})); - - CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, -, (TinyMatrix<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, -, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); - CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, -, - (TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8})); - - REQUIRE_THROWS_WITH(p_R_u - (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); - REQUIRE_THROWS_WITH(p_R_u - (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); - REQUIRE_THROWS_WITH(p_R_u - (TinyVector<3>{2, 3, 2}), "error: incompatible operand types Vh(P0:R) and R^3"); - REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); - REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R) and R^2x2"); - REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R) and R^3x3"); - - REQUIRE_THROWS_WITH(p_Vector3_u - (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); - REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<1>{1}), - "error: incompatible operand types Vh(P0Vector:R) and R^1"); - REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<2>{1, 2}), - "error: incompatible operand types Vh(P0Vector:R) and R^2"); - } - - SECTION("X - Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, -, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, -, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, -, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, -, p_R_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyVector<1>{1.3}), -, p_R1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), -, p_R2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), -, p_R3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), -, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), -, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8}), - -, p_R3x3_u); - - REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) - p_R_u, "error: incompatible operand types R^3 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) - p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) - p_R_u, - "error: incompatible operand types R^2x2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) - p_R_u, - "error: incompatible operand types R^3x3 and Vh(P0:R)"); - - REQUIRE_THROWS_WITH((double{1}) - p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_Vector3_u, - "error: incompatible operand types R^1 and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_Vector3_u, - "error: incompatible operand types R^2 and Vh(P0Vector:R)"); - } - } + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - SECTION("product") - { - SECTION("Vh * Vh -> Vh") + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) { - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, *, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, *, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, *, p_R3x3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R3_v); + std::shared_ptr other_mesh = + std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); + + CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + CellValue<double> u_R_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + CellValue<double> v_R_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.6 + std::sin(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + std::shared_ptr p_R_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, u_R_values); + std::shared_ptr p_other_mesh_R_u = + std::make_shared<const DiscreteFunctionP0<Dimension, double>>(other_mesh, u_R_values); + std::shared_ptr p_R_v = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, v_R_values); + + std::shared_ptr p_R1_u = [=] { + CellValue<TinyVector<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); + }(); + + std::shared_ptr p_R1_v = [=] { + CellValue<TinyVector<1>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, vj); + }(); + + std::shared_ptr p_other_mesh_R1_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(other_mesh, p_R1_u->cellValues()); + + constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { + if constexpr (Dimension == 1) { + return {x[0], 1 + x[0] * x[0]}; + } else if constexpr (Dimension == 2) { + return {x[0], x[1]}; + } else if constexpr (Dimension == 3) { + return {x[0], x[1] + x[2]}; + } + }; + + std::shared_ptr p_R2_u = [=] { + CellValue<TinyVector<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + uj[cell_id] = {2 * x[0] + 1, 1 - x[1]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); + }(); + + std::shared_ptr p_R2_v = [=] { + CellValue<TinyVector<2>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, vj); + }(); + + std::shared_ptr p_other_mesh_R2_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(other_mesh, p_R2_u->cellValues()); + + constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { + if constexpr (Dimension == 1) { + return {x[0], 1 + x[0] * x[0], 2 - x[0]}; + } else if constexpr (Dimension == 2) { + return {x[0], x[1], x[0] + x[1]}; + } else if constexpr (Dimension == 3) { + return {x[0], x[1], x[2]}; + } + }; + + std::shared_ptr p_R3_u = [=] { + CellValue<TinyVector<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj[cell_id] = {2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); + }(); + + std::shared_ptr p_R3_v = [=] { + CellValue<TinyVector<3>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, vj); + }(); + + std::shared_ptr p_other_mesh_R3_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(other_mesh, p_R3_u->cellValues()); + + std::shared_ptr p_R1x1_u = [=] { + CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = {2 * xj[cell_id][0] + 1}; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); + }(); + + std::shared_ptr p_other_mesh_R1x1_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(other_mesh, p_R1x1_u->cellValues()); + + std::shared_ptr p_R1x1_v = [=] { + CellValue<TinyMatrix<1>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { vj[cell_id] = {0.3 - xj[cell_id][0]}; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, vj); + }(); + + std::shared_ptr p_R2x2_u = [=] { + CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + uj[cell_id] = {2 * x[0] + 1, 1 - x[1], // + 2 * x[1], -x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); + }(); + + std::shared_ptr p_other_mesh_R2x2_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(other_mesh, p_R2x2_u->cellValues()); + + std::shared_ptr p_R2x2_v = [=] { + CellValue<TinyMatrix<2>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + vj[cell_id] = {x[0] + 0.3, 1 - x[1] - x[0], // + 2 * x[1] + x[0], x[1] - x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, vj); + }(); + + std::shared_ptr p_R3x3_u = [=] { + CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + uj[cell_id] = {2 * x[0] + 1, 1 - x[1], 3, // + 2 * x[1], -x[0], x[0] - x[1], // + 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); + }(); + + std::shared_ptr p_other_mesh_R3x3_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(other_mesh, p_R3x3_u->cellValues()); + + std::shared_ptr p_R3x3_v = [=] { + CellValue<TinyMatrix<3>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + vj[cell_id] = {0.2 * x[0] + 1, 2 + x[1], 3 - x[2], // + 2.3 * x[2], x[1] - x[0], x[2] - x[1], // + 2 * x[2] + x[0], x[1] + 0.2 * x[2], x[2] - 2 * x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, vj); + }(); + + std::shared_ptr p_Vector3_u = [=] { + CellArray<double> uj_vector{mesh->connectivity(), 3}; + parallel_for( + uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj_vector[cell_id][0] = 2 * x[0] + 1; + uj_vector[cell_id][1] = 1 - x[1] * x[2]; + uj_vector[cell_id][2] = x[0] + x[2]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); + }(); + + std::shared_ptr p_other_mesh_Vector3_u = + std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(other_mesh, p_Vector3_u->cellArrays()); + + std::shared_ptr p_Vector3_v = [=] { + CellArray<double> vj_vector{mesh->connectivity(), 3}; + parallel_for( + vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj_vector[cell_id][0] = x[0] * x[1] + 1; + vj_vector[cell_id][1] = 2 * x[1]; + vj_vector[cell_id][2] = x[2] * x[0]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, vj_vector); + }(); + + std::shared_ptr p_Vector2_w = [=] { + CellArray<double> wj_vector{mesh->connectivity(), 2}; + parallel_for( + wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + wj_vector[cell_id][0] = x[0] + x[1] * 2; + wj_vector[cell_id][1] = x[0] * x[1]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, wj_vector); + }(); + + SECTION("sum") + { + SECTION("Vh + Vh -> Vh") + { + CHECK_SCALAR_VH2_TO_VH(p_R_u, +, p_R_v); + + CHECK_SCALAR_VH2_TO_VH(p_R1_u, +, p_R1_v); + CHECK_SCALAR_VH2_TO_VH(p_R2_u, +, p_R2_v); + CHECK_SCALAR_VH2_TO_VH(p_R3_u, +, p_R3_v); + + CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, +, p_R1x1_v); + CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, +, p_R2x2_v); + CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, +, p_R3x3_v); + + CHECK_VECTOR_VH2_TO_VH(p_Vector3_u, +, p_Vector3_v); + + REQUIRE_THROWS_WITH(p_R_u + p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u + p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u + p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_Vector3_u + p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(p_Vector3_u + p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); + + REQUIRE_THROWS_WITH(p_R_u + p_other_mesh_R_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1_u + p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2_u + p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3_u + p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1x1_u + p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2x2_u + p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3x3_u + p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_Vector3_u + p_other_mesh_Vector3_u, + "error: operands are defined on different meshes"); + } - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R3x3_v); + SECTION("Vh + X -> Vh") + { + CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, bool{true}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, uint64_t{1}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, int64_t{2}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, double{1.3}); + + CHECK_SCALAR_VHxX_TO_VH(p_R1_u, +, (TinyVector<1>{1.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R2_u, +, (TinyVector<2>{1.2, 2.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R3_u, +, (TinyVector<3>{3.2, 7.1, 5.2})); + + CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, +, (TinyMatrix<1>{1.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, +, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); + CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, +, + (TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8})); + + REQUIRE_THROWS_WITH(p_R_u + (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); + REQUIRE_THROWS_WITH(p_R_u + (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); + REQUIRE_THROWS_WITH(p_R_u + (TinyVector<3>{2, 3, 2}), + "error: incompatible operand types Vh(P0:R) and R^3"); + REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); + REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R) and R^2x2"); + REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R) and R^3x3"); + + REQUIRE_THROWS_WITH(p_Vector3_u + (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); + REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<1>{1}), + "error: incompatible operand types Vh(P0Vector:R) and R^1"); + REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<2>{1, 2}), + "error: incompatible operand types Vh(P0Vector:R) and R^2"); + } - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, *, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, *, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, *, p_R3_v); + SECTION("X + Vh -> Vh") + { + CHECK_SCALAR_XxVH_TO_VH(bool{true}, +, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, +, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, +, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, +, p_R_u); + + CHECK_SCALAR_XxVH_TO_VH((TinyVector<1>{1.3}), +, p_R1_u); + CHECK_SCALAR_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), +, p_R2_u); + CHECK_SCALAR_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), +, p_R3_u); + + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), +, p_R1x1_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), +, p_R2x2_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), + +, p_R3x3_u); + + REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) + p_R_u, + "error: incompatible operand types R^3 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) + p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) + p_R_u, + "error: incompatible operand types R^2x2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) + p_R_u, + "error: incompatible operand types R^3x3 and Vh(P0:R)"); + + REQUIRE_THROWS_WITH((double{1}) + p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_Vector3_u, + "error: incompatible operand types R^1 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_Vector3_u, + "error: incompatible operand types R^2 and Vh(P0Vector:R)"); + } + } + SECTION("difference") { - std::shared_ptr p_fuv = p_R_u * p_Vector3_v; + SECTION("Vh - Vh -> Vh") + { + CHECK_SCALAR_VH2_TO_VH(p_R_u, -, p_R_v); + + CHECK_SCALAR_VH2_TO_VH(p_R1_u, -, p_R1_v); + CHECK_SCALAR_VH2_TO_VH(p_R2_u, -, p_R2_v); + CHECK_SCALAR_VH2_TO_VH(p_R3_u, -, p_R3_v); + + CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, -, p_R1x1_v); + CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, -, p_R2x2_v); + CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, -, p_R3x3_v); + + CHECK_VECTOR_VH2_TO_VH(p_Vector3_u, -, p_Vector3_v); + + REQUIRE_THROWS_WITH(p_R_u - p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u - p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u - p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R_u - p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_Vector3_u - p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(p_Vector3_u - p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); + + REQUIRE_THROWS_WITH(p_R_u - p_other_mesh_R_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1_u - p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2_u - p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3_u - p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1x1_u - p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2x2_u - p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3x3_u - p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_Vector3_u - p_other_mesh_Vector3_u, + "error: operands are defined on different meshes"); + } - REQUIRE(p_fuv.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_fuv)); + SECTION("Vh - X -> Vh") + { + CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, bool{true}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, uint64_t{1}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, int64_t{2}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, double{1.3}); + + CHECK_SCALAR_VHxX_TO_VH(p_R1_u, -, (TinyVector<1>{1.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R2_u, -, (TinyVector<2>{1.2, 2.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R3_u, -, (TinyVector<3>{3.2, 7.1, 5.2})); + + CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, -, (TinyMatrix<1>{1.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, -, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); + CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, -, + (TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8})); + + REQUIRE_THROWS_WITH(p_R_u - (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); + REQUIRE_THROWS_WITH(p_R_u - (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); + REQUIRE_THROWS_WITH(p_R_u - (TinyVector<3>{2, 3, 2}), + "error: incompatible operand types Vh(P0:R) and R^3"); + REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); + REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R) and R^2x2"); + REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R) and R^3x3"); + + REQUIRE_THROWS_WITH(p_Vector3_u - (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); + REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<1>{1}), + "error: incompatible operand types Vh(P0Vector:R) and R^1"); + REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<2>{1, 2}), + "error: incompatible operand types Vh(P0Vector:R) and R^2"); + } - const auto& fuv = dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_fuv); + SECTION("X - Vh -> Vh") + { + CHECK_SCALAR_XxVH_TO_VH(bool{true}, -, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, -, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, -, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, -, p_R_u); + + CHECK_SCALAR_XxVH_TO_VH((TinyVector<1>{1.3}), -, p_R1_u); + CHECK_SCALAR_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), -, p_R2_u); + CHECK_SCALAR_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), -, p_R3_u); + + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), -, p_R1x1_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), -, p_R2x2_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), + -, p_R3x3_u); + + REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) - p_R_u, + "error: incompatible operand types R^3 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) - p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) - p_R_u, + "error: incompatible operand types R^2x2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) - p_R_u, + "error: incompatible operand types R^3x3 and Vh(P0:R)"); + + REQUIRE_THROWS_WITH((double{1}) - p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_Vector3_u, + "error: incompatible operand types R^1 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_Vector3_u, + "error: incompatible operand types R^2 and Vh(P0Vector:R)"); + } + } - auto lhs_values = p_R_u->cellValues(); - auto rhs_arrays = p_Vector3_v->cellArrays(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < lhs_values.numberOfItems(); ++cell_id) { - for (size_t i = 0; i < fuv.size(); ++i) { - if (fuv[cell_id][i] != (lhs_values[cell_id] * rhs_arrays[cell_id][i])) { - is_same = false; - break; + SECTION("product") + { + SECTION("Vh * Vh -> Vh") + { + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R_v); + + CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, *, p_R1x1_v); + CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, *, p_R2x2_v); + CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, *, p_R3x3_v); + + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R1_v); + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R2_v); + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R3_v); + + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R1x1_v); + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R2x2_v); + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R3x3_v); + + CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, *, p_R1_v); + CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, *, p_R2_v); + CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, *, p_R3_v); + + { + std::shared_ptr p_fuv = p_R_u * p_Vector3_v; + + REQUIRE(p_fuv.use_count() > 0); + REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_fuv)); + + const auto& fuv = dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_fuv); + + auto lhs_values = p_R_u->cellValues(); + auto rhs_arrays = p_Vector3_v->cellArrays(); + bool is_same = true; + for (CellId cell_id = 0; cell_id < lhs_values.numberOfItems(); ++cell_id) { + for (size_t i = 0; i < fuv.size(); ++i) { + if (fuv[cell_id][i] != (lhs_values[cell_id] * rhs_arrays[cell_id][i])) { + is_same = false; + break; + } + } } - } - } - REQUIRE(is_same); - } + REQUIRE(is_same); + } - REQUIRE_THROWS_WITH(p_R1_u * p_R1_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u * p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u * p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R1_u * p_R2x2_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^2x2)"); - - REQUIRE_THROWS_WITH(p_R1x1_u * p_R2x2_v, "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_R3x3_v, "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3x3)"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_R1x1_v, "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1x1)"); - - REQUIRE_THROWS_WITH(p_R1x1_u * p_R2_v, "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_R3_v, "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_R1_v, "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1)"); - - REQUIRE_THROWS_WITH(p_R1_u * p_Vector3_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R2_u * p_Vector3_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R3_u * p_Vector3_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R1x1_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_Vector3_u * p_Vector3_v, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0Vector:R)"); - - REQUIRE_THROWS_WITH(p_Vector3_v * p_R_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R1_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R2_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R3_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R1x1_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R2x2_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R3x3_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3x3)"); - - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1x1_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_Vector3_u, "error: operands are defined on different meshes"); - } + REQUIRE_THROWS_WITH(p_R1_u * p_R1_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u * p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u * p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R1_u * p_R2x2_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^2x2)"); + + REQUIRE_THROWS_WITH(p_R1x1_u * p_R2x2_v, + "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_R3x3_v, + "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3x3)"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_R1x1_v, + "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1x1)"); + + REQUIRE_THROWS_WITH(p_R1x1_u * p_R2_v, "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_R3_v, "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_R1_v, "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1)"); + + REQUIRE_THROWS_WITH(p_R1_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^1) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R2_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^2) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R3_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^3) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R1x1_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_Vector3_u * p_Vector3_v, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0Vector:R)"); + + REQUIRE_THROWS_WITH(p_Vector3_v * p_R_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R1_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R2_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R3_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R1x1_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R2x2_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R3x3_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3x3)"); + + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1x1_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_Vector3_u, "error: operands are defined on different meshes"); + } - SECTION("Vh * X -> Vh") - { - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, bool{true}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, uint64_t{1}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, int64_t{2}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, double{1.3}); - - CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, *, (TinyMatrix<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, *, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); - CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, *, - (TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8})); - - REQUIRE_THROWS_WITH(p_R1_u * (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R^1) and R^1"); - REQUIRE_THROWS_WITH(p_R2_u * (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R^2) and R^2"); - REQUIRE_THROWS_WITH(p_R3_u * (TinyVector<3>{2, 3, 2}), - "error: incompatible operand types Vh(P0:R^3) and R^3"); - REQUIRE_THROWS_WITH(p_R1_u * (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R^1) and R^1x1"); - REQUIRE_THROWS_WITH(p_R2_u * (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R^2) and R^2x2"); - REQUIRE_THROWS_WITH(p_R3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R^3) and R^3x3"); - REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<1>{2}), - "error: incompatible operand types Vh(P0:R^2x2) and R^1x1"); - REQUIRE_THROWS_WITH(p_R1x1_u * (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R^1x1) and R^2x2"); - REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R^2x2) and R^3x3"); - - REQUIRE_THROWS_WITH(p_Vector3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0Vector:R) and R^3x3"); - REQUIRE_THROWS_WITH(p_Vector3_u * (double{2}), "error: incompatible operand types Vh(P0Vector:R) and R"); - } + SECTION("Vh * X -> Vh") + { + CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, bool{true}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, uint64_t{1}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, int64_t{2}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, double{1.3}); + + CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, *, (TinyMatrix<1>{1.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, *, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); + CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, *, + (TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8})); + + REQUIRE_THROWS_WITH(p_R1_u * (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R^1) and R^1"); + REQUIRE_THROWS_WITH(p_R2_u * (TinyVector<2>{1, 2}), + "error: incompatible operand types Vh(P0:R^2) and R^2"); + REQUIRE_THROWS_WITH(p_R3_u * (TinyVector<3>{2, 3, 2}), + "error: incompatible operand types Vh(P0:R^3) and R^3"); + REQUIRE_THROWS_WITH(p_R1_u * (TinyMatrix<1>{2}), + "error: incompatible operand types Vh(P0:R^1) and R^1x1"); + REQUIRE_THROWS_WITH(p_R2_u * (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R^2) and R^2x2"); + REQUIRE_THROWS_WITH(p_R3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R^3) and R^3x3"); + REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<1>{2}), + "error: incompatible operand types Vh(P0:R^2x2) and R^1x1"); + REQUIRE_THROWS_WITH(p_R1x1_u * (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R^1x1) and R^2x2"); + REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R^2x2) and R^3x3"); + + REQUIRE_THROWS_WITH(p_Vector3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0Vector:R) and R^3x3"); + REQUIRE_THROWS_WITH(p_Vector3_u * (double{2}), "error: incompatible operand types Vh(P0Vector:R) and R"); + } - SECTION("X * Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R_u); - - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R1x1_u); - - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R2x2_u); - - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R3x3_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R3x3_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R3x3_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R3x3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + SECTION("X * Vh -> Vh") + { + CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R_u); + + CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R1x1_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R1x1_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R1x1_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R1x1_u); + + CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R2x2_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R2x2_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R2x2_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R2x2_u); + + CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R3x3_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R3x3_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R3x3_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R3x3_u); + + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // 4.7, 2.3, 7.1, // 9.7, 3.2, 6.8}), *, p_R3_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1x1_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2x2_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // 4.7, 2.3, 7.1, // 9.7, 3.2, 6.8}), *, p_R3x3_u); - CHECK_VECTOR_XxVH_TO_VH(bool{true}, *, p_Vector3_u); - CHECK_VECTOR_XxVH_TO_VH(uint64_t{1}, *, p_Vector3_u); - CHECK_VECTOR_XxVH_TO_VH(int64_t{2}, *, p_Vector3_u); - CHECK_VECTOR_XxVH_TO_VH(double{1.3}, *, p_Vector3_u); - - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R_u, - "error: incompatible operand types R^2x2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R_u, - "error: incompatible operand types R^3x3 and Vh(P0:R)"); - - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2_u, "error: incompatible operand types R^1x1 and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3_u, - "error: incompatible operand types R^2x2 and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2_u, - "error: incompatible operand types R^3x3 and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R1_u, - "error: incompatible operand types R^3x3 and Vh(P0:R^1)"); - - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2x2_u, - "error: incompatible operand types R^1x1 and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3x3_u, - "error: incompatible operand types R^2x2 and Vh(P0:R^3x3)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2x2_u, - "error: incompatible operand types R^3x3 and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R1x1_u, - "error: incompatible operand types R^2x2 and Vh(P0:R^1x1)"); - - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_Vector3_u, - "error: incompatible operand types R^3x3 and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_Vector3_u, - "error: incompatible operand types R^1x1 and Vh(P0Vector:R)"); - } - } + CHECK_VECTOR_XxVH_TO_VH(bool{true}, *, p_Vector3_u); + CHECK_VECTOR_XxVH_TO_VH(uint64_t{1}, *, p_Vector3_u); + CHECK_VECTOR_XxVH_TO_VH(int64_t{2}, *, p_Vector3_u); + CHECK_VECTOR_XxVH_TO_VH(double{1.3}, *, p_Vector3_u); + + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R_u, + "error: incompatible operand types R^2x2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R_u, + "error: incompatible operand types R^3x3 and Vh(P0:R)"); + + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2_u, + "error: incompatible operand types R^1x1 and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3_u, + "error: incompatible operand types R^2x2 and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2_u, + "error: incompatible operand types R^3x3 and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R1_u, + "error: incompatible operand types R^3x3 and Vh(P0:R^1)"); + + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2x2_u, + "error: incompatible operand types R^1x1 and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3x3_u, + "error: incompatible operand types R^2x2 and Vh(P0:R^3x3)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2x2_u, + "error: incompatible operand types R^3x3 and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R1x1_u, + "error: incompatible operand types R^2x2 and Vh(P0:R^1x1)"); + + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_Vector3_u, + "error: incompatible operand types R^3x3 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_Vector3_u, + "error: incompatible operand types R^1x1 and Vh(P0Vector:R)"); + } + } - SECTION("ratio") - { - SECTION("Vh / Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, /, p_R_v); + SECTION("ratio") + { + SECTION("Vh / Vh -> Vh") + { + CHECK_SCALAR_VH2_TO_VH(p_R_u, /, p_R_v); - REQUIRE_THROWS_WITH(p_R_u / p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u / p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u / p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R_u / p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_R_u / p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u / p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u / p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R_u / p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_R_u / p_other_mesh_R_u, "error: operands are defined on different meshes"); - } + REQUIRE_THROWS_WITH(p_R_u / p_other_mesh_R_u, "error: operands are defined on different meshes"); + } - SECTION("X / Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, /, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, /, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, /, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, /, p_R_u); + SECTION("X / Vh -> Vh") + { + CHECK_SCALAR_XxVH_TO_VH(bool{true}, /, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, /, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, /, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, /, p_R_u); + } + } } } } @@ -1539,668 +1585,691 @@ TEST_CASE("EmbeddedIDiscreteFunctionOperators", "[scheme]") using Rd = TinyVector<Dimension>; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian3DMesh(); - - std::shared_ptr other_mesh = - std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); - - CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - CellValue<double> u_R_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - CellValue<double> v_R_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.6 + std::sin(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - std::shared_ptr p_R_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, u_R_values); - std::shared_ptr p_other_mesh_R_u = - std::make_shared<const DiscreteFunctionP0<Dimension, double>>(other_mesh, u_R_values); - std::shared_ptr p_R_v = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, v_R_values); - - std::shared_ptr p_R1_u = [=] { - CellValue<TinyVector<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R1_v = [=] { - CellValue<TinyVector<1>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R1_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(other_mesh, p_R1_u->cellValues()); - - constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { - if constexpr (Dimension == 1) { - return {x[0], 1 + x[0] * x[0]}; - } else if constexpr (Dimension == 2) { - return {x[0], x[1]}; - } else if constexpr (Dimension == 3) { - return {x[0], x[1] + x[2]}; - } - }; - - std::shared_ptr p_R2_u = [=] { - CellValue<TinyVector<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - uj[cell_id] = {2 * x[0] + 1, 1 - x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R2_v = [=] { - CellValue<TinyVector<2>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R2_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(other_mesh, p_R2_u->cellValues()); - - constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { - if constexpr (Dimension == 1) { - return {x[0], 1 + x[0] * x[0], 2 - x[0]}; - } else if constexpr (Dimension == 2) { - return {x[0], x[1], x[0] + x[1]}; - } else if constexpr (Dimension == 3) { - return {x[0], x[1], x[2]}; - } - }; - - std::shared_ptr p_R3_u = [=] { - CellValue<TinyVector<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj[cell_id] = {2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); - }(); - - std::shared_ptr p_R3_v = [=] { - CellValue<TinyVector<3>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R3_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(other_mesh, p_R3_u->cellValues()); - - std::shared_ptr p_R1x1_u = [=] { - CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = {2 * xj[cell_id][0] + 1}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); - }(); - - std::shared_ptr p_other_mesh_R1x1_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(other_mesh, p_R1x1_u->cellValues()); - - std::shared_ptr p_R1x1_v = [=] { - CellValue<TinyMatrix<1>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { vj[cell_id] = {0.3 - xj[cell_id][0]}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, vj); - }(); - - std::shared_ptr p_R2x2_u = [=] { - CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - uj[cell_id] = {2 * x[0] + 1, 1 - x[1], // - 2 * x[1], -x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); - }(); - - std::shared_ptr p_other_mesh_R2x2_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(other_mesh, p_R2x2_u->cellValues()); - - std::shared_ptr p_R2x2_v = [=] { - CellValue<TinyMatrix<2>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - vj[cell_id] = {x[0] + 0.3, 1 - x[1] - x[0], // - 2 * x[1] + x[0], x[1] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, vj); - }(); - - std::shared_ptr p_R3x3_u = [=] { - CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - uj[cell_id] = {2 * x[0] + 1, 1 - x[1], 3, // - 2 * x[1], -x[0], x[0] - x[1], // - 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); - }(); - - std::shared_ptr p_other_mesh_R3x3_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(other_mesh, p_R3x3_u->cellValues()); - - std::shared_ptr p_R3x3_v = [=] { - CellValue<TinyMatrix<3>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - vj[cell_id] = {0.2 * x[0] + 1, 2 + x[1], 3 - x[2], // - 2.3 * x[2], x[1] - x[0], x[2] - x[1], // - 2 * x[2] + x[0], x[1] + 0.2 * x[2], x[2] - 2 * x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, vj); - }(); - - std::shared_ptr p_Vector3_u = [=] { - CellArray<double> uj_vector{mesh->connectivity(), 3}; - parallel_for( - uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj_vector[cell_id][0] = 2 * x[0] + 1; - uj_vector[cell_id][1] = 1 - x[1] * x[2]; - uj_vector[cell_id][2] = x[0] + x[2]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); - }(); - - std::shared_ptr p_other_mesh_Vector3_u = - std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(other_mesh, p_Vector3_u->cellArrays()); - - std::shared_ptr p_Vector3_v = [=] { - CellArray<double> vj_vector{mesh->connectivity(), 3}; - parallel_for( - vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj_vector[cell_id][0] = x[0] * x[1] + 1; - vj_vector[cell_id][1] = 2 * x[1]; - vj_vector[cell_id][2] = x[2] * x[0]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, vj_vector); - }(); - - std::shared_ptr p_Vector2_w = [=] { - CellArray<double> wj_vector{mesh->connectivity(), 2}; - parallel_for( - wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - wj_vector[cell_id][0] = x[0] + x[1] * 2; - wj_vector[cell_id][1] = x[0] * x[1]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, wj_vector); - }(); - - SECTION("sum") - { - SECTION("Vh + Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, +, p_R_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1_u, +, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2_u, +, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3_u, +, p_R3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, +, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, +, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, +, p_R3x3_v); - - CHECK_VECTOR_VH2_TO_VH(p_Vector3_u, +, p_Vector3_v); - - REQUIRE_THROWS_WITH(p_R_u + p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u + p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u + p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_Vector3_u + p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(p_Vector3_u + p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); - - REQUIRE_THROWS_WITH(p_R_u + p_other_mesh_R_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1_u + p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2_u + p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3_u + p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1x1_u + p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2x2_u + p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3x3_u + p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_Vector3_u + p_other_mesh_Vector3_u, "error: operands are defined on different meshes"); - } - - SECTION("Vh + X -> Vh") - { - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, bool{true}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, uint64_t{1}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, int64_t{2}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, double{1.3}); - - CHECK_SCALAR_VHxX_TO_VH(p_R1_u, +, (TinyVector<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2_u, +, (TinyVector<2>{1.2, 2.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R3_u, +, (TinyVector<3>{3.2, 7.1, 5.2})); - - CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, +, (TinyMatrix<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, +, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); - CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, +, - (TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8})); - - REQUIRE_THROWS_WITH(p_R_u + (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); - REQUIRE_THROWS_WITH(p_R_u + (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); - REQUIRE_THROWS_WITH(p_R_u + (TinyVector<3>{2, 3, 2}), "error: incompatible operand types Vh(P0:R) and R^3"); - REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); - REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R) and R^2x2"); - REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R) and R^3x3"); - - REQUIRE_THROWS_WITH(p_Vector3_u + (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); - REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<1>{1}), - "error: incompatible operand types Vh(P0Vector:R) and R^1"); - REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<2>{1, 2}), - "error: incompatible operand types Vh(P0Vector:R) and R^2"); - } + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - SECTION("X + Vh -> Vh") + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, +, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, +, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, +, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, +, p_R_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyVector<1>{1.3}), +, p_R1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), +, p_R2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), +, p_R3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), +, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), +, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8}), - +, p_R3x3_u); - - REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) + p_R_u, "error: incompatible operand types R^3 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) + p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) + p_R_u, - "error: incompatible operand types R^2x2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) + p_R_u, - "error: incompatible operand types R^3x3 and Vh(P0:R)"); - - REQUIRE_THROWS_WITH((double{1}) + p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_Vector3_u, - "error: incompatible operand types R^1 and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_Vector3_u, - "error: incompatible operand types R^2 and Vh(P0Vector:R)"); - } - } - - SECTION("difference") - { - SECTION("Vh - Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, -, p_R_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1_u, -, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2_u, -, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3_u, -, p_R3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, -, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, -, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, -, p_R3x3_v); - - CHECK_VECTOR_VH2_TO_VH(p_Vector3_u, -, p_Vector3_v); - - REQUIRE_THROWS_WITH(p_R_u - p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u - p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u - p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R_u - p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_Vector3_u - p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(p_Vector3_u - p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); - - REQUIRE_THROWS_WITH(p_R_u - p_other_mesh_R_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1_u - p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2_u - p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3_u - p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1x1_u - p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2x2_u - p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3x3_u - p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_Vector3_u - p_other_mesh_Vector3_u, "error: operands are defined on different meshes"); - } - - SECTION("Vh - X -> Vh") - { - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, bool{true}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, uint64_t{1}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, int64_t{2}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, double{1.3}); - - CHECK_SCALAR_VHxX_TO_VH(p_R1_u, -, (TinyVector<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2_u, -, (TinyVector<2>{1.2, 2.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R3_u, -, (TinyVector<3>{3.2, 7.1, 5.2})); - - CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, -, (TinyMatrix<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, -, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); - CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, -, - (TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8})); - - REQUIRE_THROWS_WITH(p_R_u - (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); - REQUIRE_THROWS_WITH(p_R_u - (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); - REQUIRE_THROWS_WITH(p_R_u - (TinyVector<3>{2, 3, 2}), "error: incompatible operand types Vh(P0:R) and R^3"); - REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); - REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R) and R^2x2"); - REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R) and R^3x3"); - - REQUIRE_THROWS_WITH(p_Vector3_u - (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); - REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<1>{1}), - "error: incompatible operand types Vh(P0Vector:R) and R^1"); - REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<2>{1, 2}), - "error: incompatible operand types Vh(P0Vector:R) and R^2"); - } - - SECTION("X - Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, -, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, -, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, -, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, -, p_R_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyVector<1>{1.3}), -, p_R1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), -, p_R2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), -, p_R3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), -, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), -, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8}), - -, p_R3x3_u); - - REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) - p_R_u, "error: incompatible operand types R^3 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) - p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) - p_R_u, - "error: incompatible operand types R^2x2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) - p_R_u, - "error: incompatible operand types R^3x3 and Vh(P0:R)"); - - REQUIRE_THROWS_WITH((double{1}) - p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_Vector3_u, - "error: incompatible operand types R^1 and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_Vector3_u, - "error: incompatible operand types R^2 and Vh(P0Vector:R)"); - } - } - - SECTION("product") - { - SECTION("Vh * Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, *, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, *, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, *, p_R3x3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R3_v); + std::shared_ptr other_mesh = + std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); + + CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + CellValue<double> u_R_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + CellValue<double> v_R_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.6 + std::sin(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + std::shared_ptr p_R_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, u_R_values); + std::shared_ptr p_other_mesh_R_u = + std::make_shared<const DiscreteFunctionP0<Dimension, double>>(other_mesh, u_R_values); + std::shared_ptr p_R_v = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, v_R_values); + + std::shared_ptr p_R1_u = [=] { + CellValue<TinyVector<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); + }(); + + std::shared_ptr p_R1_v = [=] { + CellValue<TinyVector<1>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, vj); + }(); + + std::shared_ptr p_other_mesh_R1_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(other_mesh, p_R1_u->cellValues()); + + constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { + if constexpr (Dimension == 1) { + return {x[0], 1 + x[0] * x[0]}; + } else if constexpr (Dimension == 2) { + return {x[0], x[1]}; + } else if constexpr (Dimension == 3) { + return {x[0], x[1] + x[2]}; + } + }; + + std::shared_ptr p_R2_u = [=] { + CellValue<TinyVector<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + uj[cell_id] = {2 * x[0] + 1, 1 - x[1]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); + }(); + + std::shared_ptr p_R2_v = [=] { + CellValue<TinyVector<2>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, vj); + }(); + + std::shared_ptr p_other_mesh_R2_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(other_mesh, p_R2_u->cellValues()); + + constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { + if constexpr (Dimension == 1) { + return {x[0], 1 + x[0] * x[0], 2 - x[0]}; + } else if constexpr (Dimension == 2) { + return {x[0], x[1], x[0] + x[1]}; + } else if constexpr (Dimension == 3) { + return {x[0], x[1], x[2]}; + } + }; + + std::shared_ptr p_R3_u = [=] { + CellValue<TinyVector<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj[cell_id] = {2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); + }(); + + std::shared_ptr p_R3_v = [=] { + CellValue<TinyVector<3>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj[cell_id] = {x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, vj); + }(); + + std::shared_ptr p_other_mesh_R3_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(other_mesh, p_R3_u->cellValues()); + + std::shared_ptr p_R1x1_u = [=] { + CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = {2 * xj[cell_id][0] + 1}; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); + }(); + + std::shared_ptr p_other_mesh_R1x1_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(other_mesh, p_R1x1_u->cellValues()); + + std::shared_ptr p_R1x1_v = [=] { + CellValue<TinyMatrix<1>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { vj[cell_id] = {0.3 - xj[cell_id][0]}; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, vj); + }(); + + std::shared_ptr p_R2x2_u = [=] { + CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + uj[cell_id] = {2 * x[0] + 1, 1 - x[1], // + 2 * x[1], -x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); + }(); + + std::shared_ptr p_other_mesh_R2x2_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(other_mesh, p_R2x2_u->cellValues()); + + std::shared_ptr p_R2x2_v = [=] { + CellValue<TinyMatrix<2>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + vj[cell_id] = {x[0] + 0.3, 1 - x[1] - x[0], // + 2 * x[1] + x[0], x[1] - x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, vj); + }(); + + std::shared_ptr p_R3x3_u = [=] { + CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + uj[cell_id] = {2 * x[0] + 1, 1 - x[1], 3, // + 2 * x[1], -x[0], x[0] - x[1], // + 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); + }(); + + std::shared_ptr p_other_mesh_R3x3_u = + std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(other_mesh, p_R3x3_u->cellValues()); + + std::shared_ptr p_R3x3_v = [=] { + CellValue<TinyMatrix<3>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + vj[cell_id] = {0.2 * x[0] + 1, 2 + x[1], 3 - x[2], // + 2.3 * x[2], x[1] - x[0], x[2] - x[1], // + 2 * x[2] + x[0], x[1] + 0.2 * x[2], x[2] - 2 * x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, vj); + }(); + + std::shared_ptr p_Vector3_u = [=] { + CellArray<double> uj_vector{mesh->connectivity(), 3}; + parallel_for( + uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj_vector[cell_id][0] = 2 * x[0] + 1; + uj_vector[cell_id][1] = 1 - x[1] * x[2]; + uj_vector[cell_id][2] = x[0] + x[2]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); + }(); + + std::shared_ptr p_other_mesh_Vector3_u = + std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(other_mesh, p_Vector3_u->cellArrays()); + + std::shared_ptr p_Vector3_v = [=] { + CellArray<double> vj_vector{mesh->connectivity(), 3}; + parallel_for( + vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj_vector[cell_id][0] = x[0] * x[1] + 1; + vj_vector[cell_id][1] = 2 * x[1]; + vj_vector[cell_id][2] = x[2] * x[0]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, vj_vector); + }(); + + std::shared_ptr p_Vector2_w = [=] { + CellArray<double> wj_vector{mesh->connectivity(), 2}; + parallel_for( + wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + wj_vector[cell_id][0] = x[0] + x[1] * 2; + wj_vector[cell_id][1] = x[0] * x[1]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, wj_vector); + }(); + + SECTION("sum") + { + SECTION("Vh + Vh -> Vh") + { + CHECK_SCALAR_VH2_TO_VH(p_R_u, +, p_R_v); + + CHECK_SCALAR_VH2_TO_VH(p_R1_u, +, p_R1_v); + CHECK_SCALAR_VH2_TO_VH(p_R2_u, +, p_R2_v); + CHECK_SCALAR_VH2_TO_VH(p_R3_u, +, p_R3_v); + + CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, +, p_R1x1_v); + CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, +, p_R2x2_v); + CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, +, p_R3x3_v); + + CHECK_VECTOR_VH2_TO_VH(p_Vector3_u, +, p_Vector3_v); + + REQUIRE_THROWS_WITH(p_R_u + p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u + p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u + p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_Vector3_u + p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(p_Vector3_u + p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); + + REQUIRE_THROWS_WITH(p_R_u + p_other_mesh_R_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1_u + p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2_u + p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3_u + p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1x1_u + p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2x2_u + p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3x3_u + p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_Vector3_u + p_other_mesh_Vector3_u, + "error: operands are defined on different meshes"); + } - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R3x3_v); + SECTION("Vh + X -> Vh") + { + CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, bool{true}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, uint64_t{1}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, int64_t{2}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, double{1.3}); + + CHECK_SCALAR_VHxX_TO_VH(p_R1_u, +, (TinyVector<1>{1.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R2_u, +, (TinyVector<2>{1.2, 2.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R3_u, +, (TinyVector<3>{3.2, 7.1, 5.2})); + + CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, +, (TinyMatrix<1>{1.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, +, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); + CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, +, + (TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8})); + + REQUIRE_THROWS_WITH(p_R_u + (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); + REQUIRE_THROWS_WITH(p_R_u + (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); + REQUIRE_THROWS_WITH(p_R_u + (TinyVector<3>{2, 3, 2}), + "error: incompatible operand types Vh(P0:R) and R^3"); + REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); + REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R) and R^2x2"); + REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R) and R^3x3"); + + REQUIRE_THROWS_WITH(p_Vector3_u + (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); + REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<1>{1}), + "error: incompatible operand types Vh(P0Vector:R) and R^1"); + REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<2>{1, 2}), + "error: incompatible operand types Vh(P0Vector:R) and R^2"); + } - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, *, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, *, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, *, p_R3_v); + SECTION("X + Vh -> Vh") + { + CHECK_SCALAR_XxVH_TO_VH(bool{true}, +, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, +, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, +, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, +, p_R_u); + + CHECK_SCALAR_XxVH_TO_VH((TinyVector<1>{1.3}), +, p_R1_u); + CHECK_SCALAR_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), +, p_R2_u); + CHECK_SCALAR_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), +, p_R3_u); + + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), +, p_R1x1_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), +, p_R2x2_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), + +, p_R3x3_u); + + REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) + p_R_u, + "error: incompatible operand types R^3 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) + p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) + p_R_u, + "error: incompatible operand types R^2x2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) + p_R_u, + "error: incompatible operand types R^3x3 and Vh(P0:R)"); + + REQUIRE_THROWS_WITH((double{1}) + p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_Vector3_u, + "error: incompatible operand types R^1 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_Vector3_u, + "error: incompatible operand types R^2 and Vh(P0Vector:R)"); + } + } + SECTION("difference") { - std::shared_ptr p_fuv = p_R_u * p_Vector3_v; + SECTION("Vh - Vh -> Vh") + { + CHECK_SCALAR_VH2_TO_VH(p_R_u, -, p_R_v); + + CHECK_SCALAR_VH2_TO_VH(p_R1_u, -, p_R1_v); + CHECK_SCALAR_VH2_TO_VH(p_R2_u, -, p_R2_v); + CHECK_SCALAR_VH2_TO_VH(p_R3_u, -, p_R3_v); + + CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, -, p_R1x1_v); + CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, -, p_R2x2_v); + CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, -, p_R3x3_v); + + CHECK_VECTOR_VH2_TO_VH(p_Vector3_u, -, p_Vector3_v); + + REQUIRE_THROWS_WITH(p_R_u - p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u - p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u - p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R_u - p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_Vector3_u - p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(p_Vector3_u - p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); + + REQUIRE_THROWS_WITH(p_R_u - p_other_mesh_R_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1_u - p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2_u - p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3_u - p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1x1_u - p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2x2_u - p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3x3_u - p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_Vector3_u - p_other_mesh_Vector3_u, + "error: operands are defined on different meshes"); + } - REQUIRE(p_fuv.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_fuv)); + SECTION("Vh - X -> Vh") + { + CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, bool{true}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, uint64_t{1}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, int64_t{2}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, double{1.3}); + + CHECK_SCALAR_VHxX_TO_VH(p_R1_u, -, (TinyVector<1>{1.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R2_u, -, (TinyVector<2>{1.2, 2.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R3_u, -, (TinyVector<3>{3.2, 7.1, 5.2})); + + CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, -, (TinyMatrix<1>{1.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, -, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); + CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, -, + (TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8})); + + REQUIRE_THROWS_WITH(p_R_u - (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); + REQUIRE_THROWS_WITH(p_R_u - (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); + REQUIRE_THROWS_WITH(p_R_u - (TinyVector<3>{2, 3, 2}), + "error: incompatible operand types Vh(P0:R) and R^3"); + REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); + REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R) and R^2x2"); + REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R) and R^3x3"); + + REQUIRE_THROWS_WITH(p_Vector3_u - (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); + REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<1>{1}), + "error: incompatible operand types Vh(P0Vector:R) and R^1"); + REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<2>{1, 2}), + "error: incompatible operand types Vh(P0Vector:R) and R^2"); + } - const auto& fuv = dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_fuv); + SECTION("X - Vh -> Vh") + { + CHECK_SCALAR_XxVH_TO_VH(bool{true}, -, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, -, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, -, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, -, p_R_u); + + CHECK_SCALAR_XxVH_TO_VH((TinyVector<1>{1.3}), -, p_R1_u); + CHECK_SCALAR_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), -, p_R2_u); + CHECK_SCALAR_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), -, p_R3_u); + + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), -, p_R1x1_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), -, p_R2x2_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), + -, p_R3x3_u); + + REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) - p_R_u, + "error: incompatible operand types R^3 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) - p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) - p_R_u, + "error: incompatible operand types R^2x2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) - p_R_u, + "error: incompatible operand types R^3x3 and Vh(P0:R)"); + + REQUIRE_THROWS_WITH((double{1}) - p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_Vector3_u, + "error: incompatible operand types R^1 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_Vector3_u, + "error: incompatible operand types R^2 and Vh(P0Vector:R)"); + } + } - auto lhs_values = p_R_u->cellValues(); - auto rhs_arrays = p_Vector3_v->cellArrays(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < lhs_values.numberOfItems(); ++cell_id) { - for (size_t i = 0; i < fuv.size(); ++i) { - if (fuv[cell_id][i] != (lhs_values[cell_id] * rhs_arrays[cell_id][i])) { - is_same = false; - break; + SECTION("product") + { + SECTION("Vh * Vh -> Vh") + { + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R_v); + + CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, *, p_R1x1_v); + CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, *, p_R2x2_v); + CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, *, p_R3x3_v); + + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R1_v); + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R2_v); + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R3_v); + + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R1x1_v); + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R2x2_v); + CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R3x3_v); + + CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, *, p_R1_v); + CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, *, p_R2_v); + CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, *, p_R3_v); + + { + std::shared_ptr p_fuv = p_R_u * p_Vector3_v; + + REQUIRE(p_fuv.use_count() > 0); + REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_fuv)); + + const auto& fuv = dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_fuv); + + auto lhs_values = p_R_u->cellValues(); + auto rhs_arrays = p_Vector3_v->cellArrays(); + bool is_same = true; + for (CellId cell_id = 0; cell_id < lhs_values.numberOfItems(); ++cell_id) { + for (size_t i = 0; i < fuv.size(); ++i) { + if (fuv[cell_id][i] != (lhs_values[cell_id] * rhs_arrays[cell_id][i])) { + is_same = false; + break; + } + } } - } - } - REQUIRE(is_same); - } + REQUIRE(is_same); + } - REQUIRE_THROWS_WITH(p_R1_u * p_R1_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u * p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u * p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R1_u * p_R2x2_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^2x2)"); - - REQUIRE_THROWS_WITH(p_R1x1_u * p_R2x2_v, "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_R3x3_v, "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3x3)"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_R1x1_v, "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1x1)"); - - REQUIRE_THROWS_WITH(p_R1x1_u * p_R2_v, "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_R3_v, "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_R1_v, "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1)"); - - REQUIRE_THROWS_WITH(p_R1_u * p_Vector3_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R2_u * p_Vector3_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R3_u * p_Vector3_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R1x1_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_Vector3_u * p_Vector3_v, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0Vector:R)"); - - REQUIRE_THROWS_WITH(p_Vector3_v * p_R_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R1_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R2_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R3_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R1x1_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R2x2_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R3x3_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3x3)"); - - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1x1_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_Vector3_u, "error: operands are defined on different meshes"); - } + REQUIRE_THROWS_WITH(p_R1_u * p_R1_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u * p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u * p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R1_u * p_R2x2_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^2x2)"); + + REQUIRE_THROWS_WITH(p_R1x1_u * p_R2x2_v, + "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_R3x3_v, + "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3x3)"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_R1x1_v, + "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1x1)"); + + REQUIRE_THROWS_WITH(p_R1x1_u * p_R2_v, "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_R3_v, "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_R1_v, "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1)"); + + REQUIRE_THROWS_WITH(p_R1_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^1) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R2_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^2) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R3_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^3) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R1x1_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_Vector3_u * p_Vector3_v, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0Vector:R)"); + + REQUIRE_THROWS_WITH(p_Vector3_v * p_R_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R1_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R2_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R3_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R1x1_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R2x2_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R3x3_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3x3)"); + + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1x1_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_Vector3_u, "error: operands are defined on different meshes"); + } - SECTION("Vh * X -> Vh") - { - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, bool{true}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, uint64_t{1}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, int64_t{2}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, double{1.3}); - - CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, *, (TinyMatrix<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, *, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); - CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, *, - (TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8})); - - REQUIRE_THROWS_WITH(p_R1_u * (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R^1) and R^1"); - REQUIRE_THROWS_WITH(p_R2_u * (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R^2) and R^2"); - REQUIRE_THROWS_WITH(p_R3_u * (TinyVector<3>{2, 3, 2}), - "error: incompatible operand types Vh(P0:R^3) and R^3"); - REQUIRE_THROWS_WITH(p_R1_u * (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R^1) and R^1x1"); - REQUIRE_THROWS_WITH(p_R2_u * (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R^2) and R^2x2"); - REQUIRE_THROWS_WITH(p_R3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R^3) and R^3x3"); - REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<1>{2}), - "error: incompatible operand types Vh(P0:R^2x2) and R^1x1"); - REQUIRE_THROWS_WITH(p_R1x1_u * (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R^1x1) and R^2x2"); - REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R^2x2) and R^3x3"); - - REQUIRE_THROWS_WITH(p_Vector3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0Vector:R) and R^3x3"); - REQUIRE_THROWS_WITH(p_Vector3_u * (double{2}), "error: incompatible operand types Vh(P0Vector:R) and R"); - } + SECTION("Vh * X -> Vh") + { + CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, bool{true}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, uint64_t{1}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, int64_t{2}); + CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, double{1.3}); + + CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, *, (TinyMatrix<1>{1.3})); + CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, *, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); + CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, *, + (TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8})); + + REQUIRE_THROWS_WITH(p_R1_u * (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R^1) and R^1"); + REQUIRE_THROWS_WITH(p_R2_u * (TinyVector<2>{1, 2}), + "error: incompatible operand types Vh(P0:R^2) and R^2"); + REQUIRE_THROWS_WITH(p_R3_u * (TinyVector<3>{2, 3, 2}), + "error: incompatible operand types Vh(P0:R^3) and R^3"); + REQUIRE_THROWS_WITH(p_R1_u * (TinyMatrix<1>{2}), + "error: incompatible operand types Vh(P0:R^1) and R^1x1"); + REQUIRE_THROWS_WITH(p_R2_u * (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R^2) and R^2x2"); + REQUIRE_THROWS_WITH(p_R3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R^3) and R^3x3"); + REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<1>{2}), + "error: incompatible operand types Vh(P0:R^2x2) and R^1x1"); + REQUIRE_THROWS_WITH(p_R1x1_u * (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R^1x1) and R^2x2"); + REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R^2x2) and R^3x3"); + + REQUIRE_THROWS_WITH(p_Vector3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0Vector:R) and R^3x3"); + REQUIRE_THROWS_WITH(p_Vector3_u * (double{2}), "error: incompatible operand types Vh(P0Vector:R) and R"); + } - SECTION("X * Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R_u); - - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R1x1_u); - - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R2x2_u); - - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R3x3_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R3x3_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R3x3_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R3x3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + SECTION("X * Vh -> Vh") + { + CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R_u); + + CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R1x1_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R1x1_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R1x1_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R1x1_u); + + CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R2x2_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R2x2_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R2x2_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R2x2_u); + + CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R3x3_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R3x3_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R3x3_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R3x3_u); + + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // 4.7, 2.3, 7.1, // 9.7, 3.2, 6.8}), *, p_R3_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1x1_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2x2_u); + CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // 4.7, 2.3, 7.1, // 9.7, 3.2, 6.8}), *, p_R3x3_u); - CHECK_VECTOR_XxVH_TO_VH(bool{true}, *, p_Vector3_u); - CHECK_VECTOR_XxVH_TO_VH(uint64_t{1}, *, p_Vector3_u); - CHECK_VECTOR_XxVH_TO_VH(int64_t{2}, *, p_Vector3_u); - CHECK_VECTOR_XxVH_TO_VH(double{1.3}, *, p_Vector3_u); - - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R_u, - "error: incompatible operand types R^2x2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R_u, - "error: incompatible operand types R^3x3 and Vh(P0:R)"); - - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2_u, "error: incompatible operand types R^1x1 and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3_u, - "error: incompatible operand types R^2x2 and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2_u, - "error: incompatible operand types R^3x3 and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R1_u, - "error: incompatible operand types R^3x3 and Vh(P0:R^1)"); - - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2x2_u, - "error: incompatible operand types R^1x1 and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3x3_u, - "error: incompatible operand types R^2x2 and Vh(P0:R^3x3)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2x2_u, - "error: incompatible operand types R^3x3 and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R1x1_u, - "error: incompatible operand types R^2x2 and Vh(P0:R^1x1)"); - - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_Vector3_u, - "error: incompatible operand types R^3x3 and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_Vector3_u, - "error: incompatible operand types R^1x1 and Vh(P0Vector:R)"); - } - } + CHECK_VECTOR_XxVH_TO_VH(bool{true}, *, p_Vector3_u); + CHECK_VECTOR_XxVH_TO_VH(uint64_t{1}, *, p_Vector3_u); + CHECK_VECTOR_XxVH_TO_VH(int64_t{2}, *, p_Vector3_u); + CHECK_VECTOR_XxVH_TO_VH(double{1.3}, *, p_Vector3_u); + + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R_u, + "error: incompatible operand types R^2x2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R_u, + "error: incompatible operand types R^3x3 and Vh(P0:R)"); + + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2_u, + "error: incompatible operand types R^1x1 and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3_u, + "error: incompatible operand types R^2x2 and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2_u, + "error: incompatible operand types R^3x3 and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R1_u, + "error: incompatible operand types R^3x3 and Vh(P0:R^1)"); + + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2x2_u, + "error: incompatible operand types R^1x1 and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3x3_u, + "error: incompatible operand types R^2x2 and Vh(P0:R^3x3)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2x2_u, + "error: incompatible operand types R^3x3 and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R1x1_u, + "error: incompatible operand types R^2x2 and Vh(P0:R^1x1)"); + + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_Vector3_u, + "error: incompatible operand types R^3x3 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_Vector3_u, + "error: incompatible operand types R^1x1 and Vh(P0Vector:R)"); + } + } - SECTION("ratio") - { - SECTION("Vh / Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, /, p_R_v); + SECTION("ratio") + { + SECTION("Vh / Vh -> Vh") + { + CHECK_SCALAR_VH2_TO_VH(p_R_u, /, p_R_v); - REQUIRE_THROWS_WITH(p_R_u / p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u / p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u / p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R_u / p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_R_u / p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u / p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u / p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R_u / p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_R_u / p_other_mesh_R_u, "error: operands are defined on different meshes"); - } + REQUIRE_THROWS_WITH(p_R_u / p_other_mesh_R_u, "error: operands are defined on different meshes"); + } - SECTION("X / Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, /, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, /, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, /, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, /, p_R_u); + SECTION("X / Vh -> Vh") + { + CHECK_SCALAR_XxVH_TO_VH(bool{true}, /, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, /, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, /, p_R_u); + CHECK_SCALAR_XxVH_TO_VH(double{1.3}, /, p_R_u); + } + } } } } @@ -2214,133 +2283,138 @@ TEST_CASE("EmbeddedIDiscreteFunctionOperators", "[scheme]") using Rd = TinyVector<Dimension>; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian1DMesh(); - - CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - CellValue<double> u_R_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - std::shared_ptr p_R_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, u_R_values); - - std::shared_ptr p_R1_u = [=] { - CellValue<TinyVector<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); - }(); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { - if constexpr (Dimension == 1) { - return {x[0], 1 + x[0] * x[0]}; - } else if constexpr (Dimension == 2) { - return {x[0], x[1]}; - } else if constexpr (Dimension == 3) { - return {x[0], x[1] + x[2]}; - } - }; - - std::shared_ptr p_R2_u = [=] { - CellValue<TinyVector<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - uj[cell_id] = {2 * x[0] + 1, 1 - x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); - }(); - - constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { - if constexpr (Dimension == 1) { - return {x[0], 1 + x[0] * x[0], 2 - x[0]}; - } else if constexpr (Dimension == 2) { - return {x[0], x[1], x[0] + x[1]}; - } else if constexpr (Dimension == 3) { - return {x[0], x[1], x[2]}; - } - }; - - std::shared_ptr p_R3_u = [=] { - CellValue<TinyVector<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj[cell_id] = {2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); - }(); - - std::shared_ptr p_R1x1_u = [=] { - CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = {2 * xj[cell_id][0] + 1}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R2x2_u = [=] { - CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - uj[cell_id] = {2 * x[0] + 1, 1 - x[1], // - 2 * x[1], -x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R3x3_u = [=] { - CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - uj[cell_id] = {2 * x[0] + 1, 1 - x[1], 3, // - 2 * x[1], -x[0], x[0] - x[1], // - 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); - }(); - - std::shared_ptr p_Vector3_u = [=] { - CellArray<double> uj_vector{mesh->connectivity(), 3}; - parallel_for( - uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj_vector[cell_id][0] = 2 * x[0] + 1; - uj_vector[cell_id][1] = 1 - x[1] * x[2]; - uj_vector[cell_id][2] = x[0] + x[2]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); - }(); - - SECTION("unary minus") - { - SECTION("- Vh -> Vh") + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) { - CHECK_SCALAR_VH_TO_VH(-, p_R_u); + CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + CellValue<double> u_R_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + std::shared_ptr p_R_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, u_R_values); + + std::shared_ptr p_R1_u = [=] { + CellValue<TinyVector<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); + }(); + + constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { + if constexpr (Dimension == 1) { + return {x[0], 1 + x[0] * x[0]}; + } else if constexpr (Dimension == 2) { + return {x[0], x[1]}; + } else if constexpr (Dimension == 3) { + return {x[0], x[1] + x[2]}; + } + }; + + std::shared_ptr p_R2_u = [=] { + CellValue<TinyVector<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + uj[cell_id] = {2 * x[0] + 1, 1 - x[1]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); + }(); + + constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { + if constexpr (Dimension == 1) { + return {x[0], 1 + x[0] * x[0], 2 - x[0]}; + } else if constexpr (Dimension == 2) { + return {x[0], x[1], x[0] + x[1]}; + } else if constexpr (Dimension == 3) { + return {x[0], x[1], x[2]}; + } + }; + + std::shared_ptr p_R3_u = [=] { + CellValue<TinyVector<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj[cell_id] = {2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); + }(); + + std::shared_ptr p_R1x1_u = [=] { + CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = {2 * xj[cell_id][0] + 1}; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); + }(); + + std::shared_ptr p_R2x2_u = [=] { + CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + uj[cell_id] = {2 * x[0] + 1, 1 - x[1], // + 2 * x[1], -x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); + }(); + + std::shared_ptr p_R3x3_u = [=] { + CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + uj[cell_id] = {2 * x[0] + 1, 1 - x[1], 3, // + 2 * x[1], -x[0], x[0] - x[1], // + 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); + }(); + + std::shared_ptr p_Vector3_u = [=] { + CellArray<double> uj_vector{mesh->connectivity(), 3}; + parallel_for( + uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj_vector[cell_id][0] = 2 * x[0] + 1; + uj_vector[cell_id][1] = 1 - x[1] * x[2]; + uj_vector[cell_id][2] = x[0] + x[2]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); + }(); + + SECTION("unary minus") + { + SECTION("- Vh -> Vh") + { + CHECK_SCALAR_VH_TO_VH(-, p_R_u); - CHECK_SCALAR_VH_TO_VH(-, p_R1_u); - CHECK_SCALAR_VH_TO_VH(-, p_R2_u); - CHECK_SCALAR_VH_TO_VH(-, p_R3_u); + CHECK_SCALAR_VH_TO_VH(-, p_R1_u); + CHECK_SCALAR_VH_TO_VH(-, p_R2_u); + CHECK_SCALAR_VH_TO_VH(-, p_R3_u); - CHECK_SCALAR_VH_TO_VH(-, p_R1x1_u); - CHECK_SCALAR_VH_TO_VH(-, p_R2x2_u); - CHECK_SCALAR_VH_TO_VH(-, p_R3x3_u); + CHECK_SCALAR_VH_TO_VH(-, p_R1x1_u); + CHECK_SCALAR_VH_TO_VH(-, p_R2x2_u); + CHECK_SCALAR_VH_TO_VH(-, p_R3x3_u); - CHECK_VECTOR_VH_TO_VH(-, p_Vector3_u); + CHECK_VECTOR_VH_TO_VH(-, p_Vector3_u); + } + } } } } @@ -2351,133 +2425,138 @@ TEST_CASE("EmbeddedIDiscreteFunctionOperators", "[scheme]") using Rd = TinyVector<Dimension>; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian2DMesh(); - - CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - CellValue<double> u_R_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - std::shared_ptr p_R_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, u_R_values); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - std::shared_ptr p_R1_u = [=] { - CellValue<TinyVector<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); - }(); - - constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { - if constexpr (Dimension == 1) { - return {x[0], 1 + x[0] * x[0]}; - } else if constexpr (Dimension == 2) { - return {x[0], x[1]}; - } else if constexpr (Dimension == 3) { - return {x[0], x[1] + x[2]}; - } - }; - - std::shared_ptr p_R2_u = [=] { - CellValue<TinyVector<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - uj[cell_id] = {2 * x[0] + 1, 1 - x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); - }(); - - constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { - if constexpr (Dimension == 1) { - return {x[0], 1 + x[0] * x[0], 2 - x[0]}; - } else if constexpr (Dimension == 2) { - return {x[0], x[1], x[0] + x[1]}; - } else if constexpr (Dimension == 3) { - return {x[0], x[1], x[2]}; - } - }; - - std::shared_ptr p_R3_u = [=] { - CellValue<TinyVector<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj[cell_id] = {2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); - }(); - - std::shared_ptr p_R1x1_u = [=] { - CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = {2 * xj[cell_id][0] + 1}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R2x2_u = [=] { - CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - uj[cell_id] = {2 * x[0] + 1, 1 - x[1], // - 2 * x[1], -x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R3x3_u = [=] { - CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - uj[cell_id] = {2 * x[0] + 1, 1 - x[1], 3, // - 2 * x[1], -x[0], x[0] - x[1], // - 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); - }(); - - std::shared_ptr p_Vector3_u = [=] { - CellArray<double> uj_vector{mesh->connectivity(), 3}; - parallel_for( - uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj_vector[cell_id][0] = 2 * x[0] + 1; - uj_vector[cell_id][1] = 1 - x[1] * x[2]; - uj_vector[cell_id][2] = x[0] + x[2]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); - }(); - - SECTION("unary minus") - { - SECTION("- Vh -> Vh") + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) { - CHECK_SCALAR_VH_TO_VH(-, p_R_u); + CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + CellValue<double> u_R_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + std::shared_ptr p_R_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, u_R_values); + + std::shared_ptr p_R1_u = [=] { + CellValue<TinyVector<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); + }(); + + constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { + if constexpr (Dimension == 1) { + return {x[0], 1 + x[0] * x[0]}; + } else if constexpr (Dimension == 2) { + return {x[0], x[1]}; + } else if constexpr (Dimension == 3) { + return {x[0], x[1] + x[2]}; + } + }; + + std::shared_ptr p_R2_u = [=] { + CellValue<TinyVector<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + uj[cell_id] = {2 * x[0] + 1, 1 - x[1]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); + }(); + + constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { + if constexpr (Dimension == 1) { + return {x[0], 1 + x[0] * x[0], 2 - x[0]}; + } else if constexpr (Dimension == 2) { + return {x[0], x[1], x[0] + x[1]}; + } else if constexpr (Dimension == 3) { + return {x[0], x[1], x[2]}; + } + }; + + std::shared_ptr p_R3_u = [=] { + CellValue<TinyVector<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj[cell_id] = {2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); + }(); + + std::shared_ptr p_R1x1_u = [=] { + CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = {2 * xj[cell_id][0] + 1}; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); + }(); + + std::shared_ptr p_R2x2_u = [=] { + CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + uj[cell_id] = {2 * x[0] + 1, 1 - x[1], // + 2 * x[1], -x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); + }(); + + std::shared_ptr p_R3x3_u = [=] { + CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + uj[cell_id] = {2 * x[0] + 1, 1 - x[1], 3, // + 2 * x[1], -x[0], x[0] - x[1], // + 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); + }(); + + std::shared_ptr p_Vector3_u = [=] { + CellArray<double> uj_vector{mesh->connectivity(), 3}; + parallel_for( + uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj_vector[cell_id][0] = 2 * x[0] + 1; + uj_vector[cell_id][1] = 1 - x[1] * x[2]; + uj_vector[cell_id][2] = x[0] + x[2]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); + }(); + + SECTION("unary minus") + { + SECTION("- Vh -> Vh") + { + CHECK_SCALAR_VH_TO_VH(-, p_R_u); - CHECK_SCALAR_VH_TO_VH(-, p_R1_u); - CHECK_SCALAR_VH_TO_VH(-, p_R2_u); - CHECK_SCALAR_VH_TO_VH(-, p_R3_u); + CHECK_SCALAR_VH_TO_VH(-, p_R1_u); + CHECK_SCALAR_VH_TO_VH(-, p_R2_u); + CHECK_SCALAR_VH_TO_VH(-, p_R3_u); - CHECK_SCALAR_VH_TO_VH(-, p_R1x1_u); - CHECK_SCALAR_VH_TO_VH(-, p_R2x2_u); - CHECK_SCALAR_VH_TO_VH(-, p_R3x3_u); + CHECK_SCALAR_VH_TO_VH(-, p_R1x1_u); + CHECK_SCALAR_VH_TO_VH(-, p_R2x2_u); + CHECK_SCALAR_VH_TO_VH(-, p_R3x3_u); - CHECK_VECTOR_VH_TO_VH(-, p_Vector3_u); + CHECK_VECTOR_VH_TO_VH(-, p_Vector3_u); + } + } } } } @@ -2488,133 +2567,138 @@ TEST_CASE("EmbeddedIDiscreteFunctionOperators", "[scheme]") using Rd = TinyVector<Dimension>; - std::shared_ptr mesh = MeshDataBaseForTests::get().cartesian3DMesh(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - CellValue<double> u_R_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - std::shared_ptr p_R_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, u_R_values); - - std::shared_ptr p_R1_u = [=] { - CellValue<TinyVector<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); - }(); - - constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { - if constexpr (Dimension == 1) { - return {x[0], 1 + x[0] * x[0]}; - } else if constexpr (Dimension == 2) { - return {x[0], x[1]}; - } else if constexpr (Dimension == 3) { - return {x[0], x[1] + x[2]}; - } - }; - - std::shared_ptr p_R2_u = [=] { - CellValue<TinyVector<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - uj[cell_id] = {2 * x[0] + 1, 1 - x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); - }(); - - constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { - if constexpr (Dimension == 1) { - return {x[0], 1 + x[0] * x[0], 2 - x[0]}; - } else if constexpr (Dimension == 2) { - return {x[0], x[1], x[0] + x[1]}; - } else if constexpr (Dimension == 3) { - return {x[0], x[1], x[2]}; - } - }; - - std::shared_ptr p_R3_u = [=] { - CellValue<TinyVector<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj[cell_id] = {2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); - }(); - - std::shared_ptr p_R1x1_u = [=] { - CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = {2 * xj[cell_id][0] + 1}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R2x2_u = [=] { - CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - uj[cell_id] = {2 * x[0] + 1, 1 - x[1], // - 2 * x[1], -x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R3x3_u = [=] { - CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - uj[cell_id] = {2 * x[0] + 1, 1 - x[1], 3, // - 2 * x[1], -x[0], x[0] - x[1], // - 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); - }(); - - std::shared_ptr p_Vector3_u = [=] { - CellArray<double> uj_vector{mesh->connectivity(), 3}; - parallel_for( - uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj_vector[cell_id][0] = 2 * x[0] + 1; - uj_vector[cell_id][1] = 1 - x[1] * x[2]; - uj_vector[cell_id][2] = x[0] + x[2]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); - }(); - - SECTION("unary minus") - { - SECTION("- Vh -> Vh") + for (auto [section_name, mesh] : mesh_list) { + SECTION(section_name) { - CHECK_SCALAR_VH_TO_VH(-, p_R_u); + CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + CellValue<double> u_R_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + std::shared_ptr p_R_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, u_R_values); + + std::shared_ptr p_R1_u = [=] { + CellValue<TinyVector<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); + }(); + + constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { + if constexpr (Dimension == 1) { + return {x[0], 1 + x[0] * x[0]}; + } else if constexpr (Dimension == 2) { + return {x[0], x[1]}; + } else if constexpr (Dimension == 3) { + return {x[0], x[1] + x[2]}; + } + }; + + std::shared_ptr p_R2_u = [=] { + CellValue<TinyVector<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + uj[cell_id] = {2 * x[0] + 1, 1 - x[1]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); + }(); + + constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { + if constexpr (Dimension == 1) { + return {x[0], 1 + x[0] * x[0], 2 - x[0]}; + } else if constexpr (Dimension == 2) { + return {x[0], x[1], x[0] + x[1]}; + } else if constexpr (Dimension == 3) { + return {x[0], x[1], x[2]}; + } + }; + + std::shared_ptr p_R3_u = [=] { + CellValue<TinyVector<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj[cell_id] = {2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); + }(); + + std::shared_ptr p_R1x1_u = [=] { + CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = {2 * xj[cell_id][0] + 1}; }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); + }(); + + std::shared_ptr p_R2x2_u = [=] { + CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + uj[cell_id] = {2 * x[0] + 1, 1 - x[1], // + 2 * x[1], -x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); + }(); + + std::shared_ptr p_R3x3_u = [=] { + CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + uj[cell_id] = {2 * x[0] + 1, 1 - x[1], 3, // + 2 * x[1], -x[0], x[0] - x[1], // + 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; + }); + + return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); + }(); + + std::shared_ptr p_Vector3_u = [=] { + CellArray<double> uj_vector{mesh->connectivity(), 3}; + parallel_for( + uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj_vector[cell_id][0] = 2 * x[0] + 1; + uj_vector[cell_id][1] = 1 - x[1] * x[2]; + uj_vector[cell_id][2] = x[0] + x[2]; + }); + + return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); + }(); + + SECTION("unary minus") + { + SECTION("- Vh -> Vh") + { + CHECK_SCALAR_VH_TO_VH(-, p_R_u); - CHECK_SCALAR_VH_TO_VH(-, p_R1_u); - CHECK_SCALAR_VH_TO_VH(-, p_R2_u); - CHECK_SCALAR_VH_TO_VH(-, p_R3_u); + CHECK_SCALAR_VH_TO_VH(-, p_R1_u); + CHECK_SCALAR_VH_TO_VH(-, p_R2_u); + CHECK_SCALAR_VH_TO_VH(-, p_R3_u); - CHECK_SCALAR_VH_TO_VH(-, p_R1x1_u); - CHECK_SCALAR_VH_TO_VH(-, p_R2x2_u); - CHECK_SCALAR_VH_TO_VH(-, p_R3x3_u); + CHECK_SCALAR_VH_TO_VH(-, p_R1x1_u); + CHECK_SCALAR_VH_TO_VH(-, p_R2x2_u); + CHECK_SCALAR_VH_TO_VH(-, p_R3x3_u); - CHECK_VECTOR_VH_TO_VH(-, p_Vector3_u); + CHECK_VECTOR_VH_TO_VH(-, p_Vector3_u); + } + } } } } diff --git a/tests/test_EmbeddedIDiscreteFunctionUtils.cpp b/tests/test_EmbeddedIDiscreteFunctionUtils.cpp index b0227a356f067992a6451266e92833222c50a8fb..8a64813728fcc205ea09d26af27eb6bca976e9d5 100644 --- a/tests/test_EmbeddedIDiscreteFunctionUtils.cpp +++ b/tests/test_EmbeddedIDiscreteFunctionUtils.cpp @@ -29,28 +29,42 @@ TEST_CASE("EmbeddedIDiscreteFunctionUtils", "[language]") SECTION("discrete P0 function") { - std::shared_ptr mesh_1d = MeshDataBaseForTests::get().cartesian1DMesh(); - - REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, double>{mesh_1d}) == "Vh(P0:R)"); - - REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R1>{mesh_1d}) == "Vh(P0:R^1)"); - REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R2>{mesh_1d}) == "Vh(P0:R^2)"); - REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R3>{mesh_1d}) == "Vh(P0:R^3)"); - - REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R1x1>{mesh_1d}) == - "Vh(P0:R^1x1)"); - REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R2x2>{mesh_1d}) == - "Vh(P0:R^2x2)"); - REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R3x3>{mesh_1d}) == - "Vh(P0:R^3x3)"); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); + + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) + { + REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, double>{mesh_1d}) == + "Vh(P0:R)"); + + REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R1>{mesh_1d}) == + "Vh(P0:R^1)"); + REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R2>{mesh_1d}) == + "Vh(P0:R^2)"); + REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R3>{mesh_1d}) == + "Vh(P0:R^3)"); + + REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R1x1>{mesh_1d}) == + "Vh(P0:R^1x1)"); + REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R2x2>{mesh_1d}) == + "Vh(P0:R^2x2)"); + REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R3x3>{mesh_1d}) == + "Vh(P0:R^3x3)"); + } + } } SECTION("discrete P0Vector function") { - std::shared_ptr mesh_1d = MeshDataBaseForTests::get().cartesian1DMesh(); - - REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0Vector<1, double>{mesh_1d, 2}) == - "Vh(P0Vector:R)"); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); + + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) + { + REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0Vector<1, double>{mesh_1d, 2}) == + "Vh(P0Vector:R)"); + } + } } } @@ -58,59 +72,77 @@ TEST_CASE("EmbeddedIDiscreteFunctionUtils", "[language]") { SECTION("from shared_ptr") { - std::shared_ptr mesh_1d = MeshDataBaseForTests::get().cartesian1DMesh(); - - REQUIRE( - EmbeddedIDiscreteFunctionUtils::isSameDiscretization(std::make_shared<DiscreteFunctionP0<1, double>>(mesh_1d), - std::make_shared<DiscreteFunctionP0<1, double>>(mesh_1d))); - - REQUIRE(not EmbeddedIDiscreteFunctionUtils:: - isSameDiscretization(std::make_shared<DiscreteFunctionP0<1, double>>(mesh_1d), - std::make_shared<DiscreteFunctionP0Vector<1, double>>(mesh_1d, 1))); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); + + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) + { + REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(std::make_shared<DiscreteFunctionP0<1, double>>( + mesh_1d), + std::make_shared<DiscreteFunctionP0<1, double>>( + mesh_1d))); + + REQUIRE(not EmbeddedIDiscreteFunctionUtils:: + isSameDiscretization(std::make_shared<DiscreteFunctionP0<1, double>>(mesh_1d), + std::make_shared<DiscreteFunctionP0Vector<1, double>>(mesh_1d, 1))); + } + } } SECTION("from value") { - std::shared_ptr mesh_1d = MeshDataBaseForTests::get().cartesian1DMesh(); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, double>{mesh_1d}, - DiscreteFunctionP0<1, double>{mesh_1d})); + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) + { + REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, double>{mesh_1d}, + DiscreteFunctionP0<1, double>{mesh_1d})); - REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R1>{mesh_1d}, - DiscreteFunctionP0<1, R1>{mesh_1d})); + REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R1>{mesh_1d}, + DiscreteFunctionP0<1, R1>{mesh_1d})); - REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R2>{mesh_1d}, - DiscreteFunctionP0<1, R2>{mesh_1d})); + REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R2>{mesh_1d}, + DiscreteFunctionP0<1, R2>{mesh_1d})); - REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R3>{mesh_1d}, - DiscreteFunctionP0<1, R3>{mesh_1d})); + REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R3>{mesh_1d}, + DiscreteFunctionP0<1, R3>{mesh_1d})); - REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R1x1>{mesh_1d}, - DiscreteFunctionP0<1, R1x1>{mesh_1d})); + REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R1x1>{mesh_1d}, + DiscreteFunctionP0<1, R1x1>{mesh_1d})); - REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R2x2>{mesh_1d}, - DiscreteFunctionP0<1, R2x2>{mesh_1d})); + REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R2x2>{mesh_1d}, + DiscreteFunctionP0<1, R2x2>{mesh_1d})); - REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R3x3>{mesh_1d}, - DiscreteFunctionP0<1, R3x3>{mesh_1d})); + REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R3x3>{mesh_1d}, + DiscreteFunctionP0<1, R3x3>{mesh_1d})); - REQUIRE(not EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, double>{mesh_1d}, - DiscreteFunctionP0<1, R1>{mesh_1d})); + REQUIRE(not EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, double>{mesh_1d}, + DiscreteFunctionP0<1, R1>{mesh_1d})); - REQUIRE(not EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R2>{mesh_1d}, - DiscreteFunctionP0<1, R2x2>{mesh_1d})); + REQUIRE(not EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R2>{mesh_1d}, + DiscreteFunctionP0<1, R2x2>{mesh_1d})); - REQUIRE(not EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R3x3>{mesh_1d}, - DiscreteFunctionP0<1, R2x2>{mesh_1d})); + REQUIRE(not EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R3x3>{mesh_1d}, + DiscreteFunctionP0<1, R2x2>{mesh_1d})); + } + } } SECTION("invalid data type") { - std::shared_ptr mesh_1d = MeshDataBaseForTests::get().cartesian1DMesh(); - - REQUIRE_THROWS_WITH(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, int64_t>{mesh_1d}, - DiscreteFunctionP0<1, int64_t>{mesh_1d}), - "unexpected error: invalid data type Vh(P0:Z)"); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); + + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) + { + REQUIRE_THROWS_WITH(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, + int64_t>{mesh_1d}, + DiscreteFunctionP0<1, int64_t>{ + mesh_1d}), + "unexpected error: invalid data type Vh(P0:Z)"); + } + } } } diff --git a/tests/test_InterpolateItemArray.cpp b/tests/test_InterpolateItemArray.cpp index 90047e886f72dfe27b56fce2320e772a43f18adf..df01d8130ccfc52d1b69c67722bc5c5c06a3be00 100644 --- a/tests/test_InterpolateItemArray.cpp +++ b/tests/test_InterpolateItemArray.cpp @@ -46,195 +46,213 @@ TEST_CASE("InterpolateItemArray", "[language]") { constexpr size_t Dimension = 1; - const auto& mesh_1d = MeshDataBaseForTests::get().cartesian1DMesh(); - auto xj = MeshDataManager::instance().getMeshData(*mesh_1d).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - std::string_view data = R"( + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh_1d).xj(); + + std::string_view data = R"( import math; let scalar_affine_1d: R^1 -> R, x -> 2*x[0] + 2; let scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; )"; - TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; - auto ast = ASTBuilder::build(input); + auto ast = ASTBuilder::build(input); - ASTModulesImporter{*ast}; - ASTNodeTypeCleaner<language::import_instruction>{*ast}; + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; - ASTSymbolTableBuilder{*ast}; - ASTNodeDataTypeBuilder{*ast}; + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; - ASTNodeTypeCleaner<language::var_declaration>{*ast}; - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; - ASTNodeExpressionBuilder{*ast}; + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; - std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; - TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point - std::vector<FunctionSymbolId> function_symbol_id_list; + std::vector<FunctionSymbolId> function_symbol_id_list; - { - auto [i_symbol, found] = symbol_table->find("scalar_affine_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - function_symbol_id_list.push_back( - FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); - } + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } - { - auto [i_symbol, found] = symbol_table->find("scalar_non_linear_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - function_symbol_id_list.push_back( - FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); - } + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } - CellArray<double> cell_array{mesh_1d->connectivity(), 2}; - parallel_for( - cell_array.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_array[cell_id][0] = 2 * x[0] + 2; - cell_array[cell_id][1] = 2 * exp(x[0]) + 3; - }); + CellArray<double> cell_array{mesh_1d->connectivity(), 2}; + parallel_for( + cell_array.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_array[cell_id][0] = 2 * x[0] + 2; + cell_array[cell_id][1] = 2 * exp(x[0]) + 3; + }); - CellArray<const double> interpolate_array = - InterpolateItemArray<double(TinyVector<Dimension>)>::interpolate(function_symbol_id_list, xj); + CellArray<const double> interpolate_array = + InterpolateItemArray<double(TinyVector<Dimension>)>::interpolate(function_symbol_id_list, xj); - REQUIRE(same_cell_array(cell_array, interpolate_array)); + REQUIRE(same_cell_array(cell_array, interpolate_array)); + } + } } SECTION("2D") { constexpr size_t Dimension = 2; - const auto& mesh_2d = MeshDataBaseForTests::get().cartesian2DMesh(); - auto xj = MeshDataManager::instance().getMeshData(*mesh_2d).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); + + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh_2d).xj(); - std::string_view data = R"( + std::string_view data = R"( import math; let scalar_affine_2d: R^2 -> R, x -> 2*x[0] + 3*x[1] + 2; let scalar_non_linear_2d: R^2 -> R, x -> 2*exp(x[0])*sin(x[1])+3; )"; - TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; - auto ast = ASTBuilder::build(input); + auto ast = ASTBuilder::build(input); - ASTModulesImporter{*ast}; - ASTNodeTypeCleaner<language::import_instruction>{*ast}; + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; - ASTSymbolTableBuilder{*ast}; - ASTNodeDataTypeBuilder{*ast}; + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; - ASTNodeTypeCleaner<language::var_declaration>{*ast}; - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; - ASTNodeExpressionBuilder{*ast}; + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; - std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; - TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point - std::vector<FunctionSymbolId> function_symbol_id_list; + std::vector<FunctionSymbolId> function_symbol_id_list; - { - auto [i_symbol, found] = symbol_table->find("scalar_affine_2d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - function_symbol_id_list.push_back( - FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); - } + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } - { - auto [i_symbol, found] = symbol_table->find("scalar_non_linear_2d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - function_symbol_id_list.push_back( - FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); - } + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } - CellArray<double> cell_array{mesh_2d->connectivity(), 2}; - parallel_for( - cell_array.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_array[cell_id][0] = 2 * x[0] + 3 * x[1] + 2; - cell_array[cell_id][1] = 2 * exp(x[0]) * sin(x[1]) + 3; - }); + CellArray<double> cell_array{mesh_2d->connectivity(), 2}; + parallel_for( + cell_array.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_array[cell_id][0] = 2 * x[0] + 3 * x[1] + 2; + cell_array[cell_id][1] = 2 * exp(x[0]) * sin(x[1]) + 3; + }); - CellArray<const double> interpolate_array = - InterpolateItemArray<double(TinyVector<Dimension>)>::interpolate(function_symbol_id_list, xj); + CellArray<const double> interpolate_array = + InterpolateItemArray<double(TinyVector<Dimension>)>::interpolate(function_symbol_id_list, xj); - REQUIRE(same_cell_array(cell_array, interpolate_array)); + REQUIRE(same_cell_array(cell_array, interpolate_array)); + } + } } SECTION("3D") { constexpr size_t Dimension = 3; - const auto& mesh_3d = MeshDataBaseForTests::get().cartesian3DMesh(); - auto xj = MeshDataManager::instance().getMeshData(*mesh_3d).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); + + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh_3d).xj(); - std::string_view data = R"( + std::string_view data = R"( import math; let scalar_affine_3d: R^3 -> R, x -> 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; let scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; )"; - TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; - auto ast = ASTBuilder::build(input); + auto ast = ASTBuilder::build(input); - ASTModulesImporter{*ast}; - ASTNodeTypeCleaner<language::import_instruction>{*ast}; + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; - ASTSymbolTableBuilder{*ast}; - ASTNodeDataTypeBuilder{*ast}; + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; - ASTNodeTypeCleaner<language::var_declaration>{*ast}; - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; - ASTNodeExpressionBuilder{*ast}; + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; - std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; - TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point - std::vector<FunctionSymbolId> function_symbol_id_list; + std::vector<FunctionSymbolId> function_symbol_id_list; - { - auto [i_symbol, found] = symbol_table->find("scalar_affine_3d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - function_symbol_id_list.push_back( - FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); - } + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } - { - auto [i_symbol, found] = symbol_table->find("scalar_non_linear_3d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - function_symbol_id_list.push_back( - FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); - } + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } - CellArray<double> cell_array{mesh_3d->connectivity(), 2}; - parallel_for( - cell_array.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_array[cell_id][0] = 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; - cell_array[cell_id][1] = 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; - }); + CellArray<double> cell_array{mesh_3d->connectivity(), 2}; + parallel_for( + cell_array.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_array[cell_id][0] = 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; + cell_array[cell_id][1] = 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; + }); - CellArray<const double> interpolate_array = - InterpolateItemArray<double(TinyVector<Dimension>)>::interpolate(function_symbol_id_list, xj); + CellArray<const double> interpolate_array = + InterpolateItemArray<double(TinyVector<Dimension>)>::interpolate(function_symbol_id_list, xj); - REQUIRE(same_cell_array(cell_array, interpolate_array)); + REQUIRE(same_cell_array(cell_array, interpolate_array)); + } + } } } @@ -255,213 +273,231 @@ let scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; { constexpr size_t Dimension = 1; - const auto& mesh_1d = MeshDataBaseForTests::get().cartesian1DMesh(); - auto xj = MeshDataManager::instance().getMeshData(*mesh_1d).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - Array<const CellId> cell_id_list = [&] { - Array<CellId> cell_ids{mesh_1d->numberOfCells() / 2}; - for (size_t i_cell = 0; i_cell < cell_ids.size(); ++i_cell) { - cell_ids[i_cell] = static_cast<CellId>(2 * i_cell); - } - return cell_ids; - }(); + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh_1d).xj(); + + Array<const CellId> cell_id_list = [&] { + Array<CellId> cell_ids{mesh_1d->numberOfCells() / 2}; + for (size_t i_cell = 0; i_cell < cell_ids.size(); ++i_cell) { + cell_ids[i_cell] = static_cast<CellId>(2 * i_cell); + } + return cell_ids; + }(); - std::string_view data = R"( + std::string_view data = R"( import math; let scalar_affine_1d: R^1 -> R, x -> 2*x[0] + 2; let scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; )"; - TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; - auto ast = ASTBuilder::build(input); + auto ast = ASTBuilder::build(input); - ASTModulesImporter{*ast}; - ASTNodeTypeCleaner<language::import_instruction>{*ast}; + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; - ASTSymbolTableBuilder{*ast}; - ASTNodeDataTypeBuilder{*ast}; + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; - ASTNodeTypeCleaner<language::var_declaration>{*ast}; - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; - ASTNodeExpressionBuilder{*ast}; + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; - std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; - TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point - std::vector<FunctionSymbolId> function_symbol_id_list; + std::vector<FunctionSymbolId> function_symbol_id_list; - { - auto [i_symbol, found] = symbol_table->find("scalar_affine_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - function_symbol_id_list.push_back( - FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); - } + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } - { - auto [i_symbol, found] = symbol_table->find("scalar_non_linear_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - function_symbol_id_list.push_back( - FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); - } + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } - Table<double> cell_array{cell_id_list.size(), 2}; - parallel_for( - cell_id_list.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_array[i][0] = 2 * x[0] + 2; - cell_array[i][1] = 2 * exp(x[0]) + 3; - }); + Table<double> cell_array{cell_id_list.size(), 2}; + parallel_for( + cell_id_list.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_array[i][0] = 2 * x[0] + 2; + cell_array[i][1] = 2 * exp(x[0]) + 3; + }); - Table<const double> interpolate_array = - InterpolateItemArray<double(TinyVector<Dimension>)>::interpolate(function_symbol_id_list, xj, cell_id_list); + Table<const double> interpolate_array = + InterpolateItemArray<double(TinyVector<Dimension>)>::interpolate(function_symbol_id_list, xj, cell_id_list); - REQUIRE(same_cell_value(cell_array, interpolate_array)); + REQUIRE(same_cell_value(cell_array, interpolate_array)); + } + } } SECTION("2D") { constexpr size_t Dimension = 2; - const auto& mesh_2d = MeshDataBaseForTests::get().cartesian2DMesh(); - auto xj = MeshDataManager::instance().getMeshData(*mesh_2d).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - Array<CellId> cell_id_list{mesh_2d->numberOfCells() / 2}; - for (size_t i_cell = 0; i_cell < cell_id_list.size(); ++i_cell) { - cell_id_list[i_cell] = static_cast<CellId>(2 * i_cell); - } + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh_2d).xj(); - std::string_view data = R"( + Array<CellId> cell_id_list{mesh_2d->numberOfCells() / 2}; + for (size_t i_cell = 0; i_cell < cell_id_list.size(); ++i_cell) { + cell_id_list[i_cell] = static_cast<CellId>(2 * i_cell); + } + + std::string_view data = R"( import math; let scalar_affine_2d: R^2 -> R, x -> 2*x[0] + 3*x[1] + 2; let scalar_non_linear_2d: R^2 -> R, x -> 2*exp(x[0])*sin(x[1])+3; )"; - TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; - auto ast = ASTBuilder::build(input); + auto ast = ASTBuilder::build(input); - ASTModulesImporter{*ast}; - ASTNodeTypeCleaner<language::import_instruction>{*ast}; + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; - ASTSymbolTableBuilder{*ast}; - ASTNodeDataTypeBuilder{*ast}; + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; - ASTNodeTypeCleaner<language::var_declaration>{*ast}; - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; - ASTNodeExpressionBuilder{*ast}; + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; - std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; - TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point - std::vector<FunctionSymbolId> function_symbol_id_list; + std::vector<FunctionSymbolId> function_symbol_id_list; - { - auto [i_symbol, found] = symbol_table->find("scalar_affine_2d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - function_symbol_id_list.push_back( - FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); - } + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } - { - auto [i_symbol, found] = symbol_table->find("scalar_non_linear_2d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - function_symbol_id_list.push_back( - FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); - } + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } - Table<double> cell_array{cell_id_list.size(), 2}; - parallel_for( - cell_id_list.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_array[i][0] = 2 * x[0] + 3 * x[1] + 2; - cell_array[i][1] = 2 * exp(x[0]) * sin(x[1]) + 3; - }); + Table<double> cell_array{cell_id_list.size(), 2}; + parallel_for( + cell_id_list.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_array[i][0] = 2 * x[0] + 3 * x[1] + 2; + cell_array[i][1] = 2 * exp(x[0]) * sin(x[1]) + 3; + }); - Table<const double> interpolate_array = - InterpolateItemArray<double(TinyVector<Dimension>)>::interpolate(function_symbol_id_list, xj, cell_id_list); + Table<const double> interpolate_array = + InterpolateItemArray<double(TinyVector<Dimension>)>::interpolate(function_symbol_id_list, xj, cell_id_list); - REQUIRE(same_cell_value(cell_array, interpolate_array)); + REQUIRE(same_cell_value(cell_array, interpolate_array)); + } + } } SECTION("3D") { constexpr size_t Dimension = 3; - const auto& mesh_3d = MeshDataBaseForTests::get().cartesian3DMesh(); - auto xj = MeshDataManager::instance().getMeshData(*mesh_3d).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - Array<CellId> cell_id_list{mesh_3d->numberOfCells() / 2}; - for (size_t i_cell = 0; i_cell < cell_id_list.size(); ++i_cell) { - cell_id_list[i_cell] = static_cast<CellId>(2 * i_cell); - } + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh_3d).xj(); - std::string_view data = R"( + Array<CellId> cell_id_list{mesh_3d->numberOfCells() / 2}; + for (size_t i_cell = 0; i_cell < cell_id_list.size(); ++i_cell) { + cell_id_list[i_cell] = static_cast<CellId>(2 * i_cell); + } + + std::string_view data = R"( import math; let scalar_affine_3d: R^3 -> R, x -> 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; let scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; )"; - TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; - auto ast = ASTBuilder::build(input); + auto ast = ASTBuilder::build(input); - ASTModulesImporter{*ast}; - ASTNodeTypeCleaner<language::import_instruction>{*ast}; + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; - ASTSymbolTableBuilder{*ast}; - ASTNodeDataTypeBuilder{*ast}; + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; - ASTNodeTypeCleaner<language::var_declaration>{*ast}; - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; - ASTNodeExpressionBuilder{*ast}; + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; - std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; - TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point - std::vector<FunctionSymbolId> function_symbol_id_list; + std::vector<FunctionSymbolId> function_symbol_id_list; - { - auto [i_symbol, found] = symbol_table->find("scalar_affine_3d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - function_symbol_id_list.push_back( - FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); - } + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } - { - auto [i_symbol, found] = symbol_table->find("scalar_non_linear_3d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - function_symbol_id_list.push_back( - FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); - } + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } - Table<double> cell_array{cell_id_list.size(), 2}; - parallel_for( - cell_id_list.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_array[i][0] = 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; - cell_array[i][1] = 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; - }); + Table<double> cell_array{cell_id_list.size(), 2}; + parallel_for( + cell_id_list.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_array[i][0] = 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; + cell_array[i][1] = 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; + }); - Table<const double> interpolate_array = - InterpolateItemArray<double(TinyVector<Dimension>)>::interpolate(function_symbol_id_list, xj, cell_id_list); + Table<const double> interpolate_array = + InterpolateItemArray<double(TinyVector<Dimension>)>::interpolate(function_symbol_id_list, xj, cell_id_list); - REQUIRE(same_cell_value(cell_array, interpolate_array)); + REQUIRE(same_cell_value(cell_array, interpolate_array)); + } + } } } } diff --git a/tests/test_InterpolateItemValue.cpp b/tests/test_InterpolateItemValue.cpp index 0cb4621874bc837b4d397920a048b6b7da2de083..202eee282d2a65d3f2d8eb0f1a771f14115ed94b 100644 --- a/tests/test_InterpolateItemValue.cpp +++ b/tests/test_InterpolateItemValue.cpp @@ -43,10 +43,14 @@ TEST_CASE("InterpolateItemValue", "[language]") { constexpr size_t Dimension = 1; - const auto& mesh_1d = MeshDataBaseForTests::get().cartesian1DMesh(); - auto xj = MeshDataManager::instance().getMeshData(*mesh_1d).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - std::string_view data = R"( + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh_1d).xj(); + + std::string_view data = R"( import math; let scalar_affine_1d: R^1 -> R, x -> 2*x[0] + 2; let scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; @@ -55,149 +59,152 @@ let R3_non_linear_1d: R^1 -> R^3, x -> (2 * exp(x[0]) + 3, x[0] - 2, 3); let R2x2_affine_1d: R^1 -> R^2x2, x -> (2 * x[0] + 3 + 2, 3 * x[0], 2 * x[0], 2); let R2x2_non_linear_1d: R^1 -> R^2x2, x -> (2 * exp(x[0]) * sin(x[0]) + 3, sin(x[0] - 2 * x[0]), 3, x[0] * x[0]); )"; - 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}; - - ASTNodeTypeCleaner<language::var_declaration>{*ast}; - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; - ASTNodeExpressionBuilder{*ast}; - - std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; - TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point + auto ast = ASTBuilder::build(input); - SECTION("scalar_affine_1d") - { - auto [i_symbol, found] = symbol_table->find("scalar_affine_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; - CellValue<double> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = 2 * x[0] + 2; - }); + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; - CellValue<const double> interpolate_value = - InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("scalar_non_linear_1d") - { - auto [i_symbol, found] = symbol_table->find("scalar_non_linear_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point - CellValue<double> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = 2 * exp(x[0]) + 3; - }); - - CellValue<const double> interpolate_value = - InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } + SECTION("scalar_affine_1d") + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - SECTION("R3_affine_1d") - { - auto [i_symbol, found] = symbol_table->find("R3_affine_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + CellValue<double> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = 2 * x[0] + 2; + }); - CellValue<TinyVector<3>> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = TinyVector<3>{2 * x[0] + 2, 3 * x[0], 2}; - }); + CellValue<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); - CellValue<const TinyVector<3>> interpolate_value = - InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } + SECTION("scalar_non_linear_1d") + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - SECTION("R3_non_linear_1d") - { - auto [i_symbol, found] = symbol_table->find("R3_non_linear_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + CellValue<double> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = 2 * exp(x[0]) + 3; + }); - CellValue<TinyVector<3>> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = TinyVector<3>{2 * exp(x[0]) + 3, x[0] - 2, 3}; - }); + CellValue<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); - CellValue<const TinyVector<3>> interpolate_value = - InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } + SECTION("R3_affine_1d") + { + auto [i_symbol, found] = symbol_table->find("R3_affine_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - SECTION("R2x2_affine_1d") - { - auto [i_symbol, found] = symbol_table->find("R2x2_affine_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + CellValue<TinyVector<3>> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyVector<3>{2 * x[0] + 2, 3 * x[0], 2}; + }); - CellValue<TinyMatrix<2>> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = TinyMatrix<2>{2 * x[0] + 3 + 2, 3 * x[0], 2 * x[0], 2}; - }); + CellValue<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); - CellValue<const TinyMatrix<2>> interpolate_value = - InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } + SECTION("R3_non_linear_1d") + { + auto [i_symbol, found] = symbol_table->find("R3_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - SECTION("R2x2_non_linear_1d") - { - auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + CellValue<TinyVector<3>> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyVector<3>{2 * exp(x[0]) + 3, x[0] - 2, 3}; + }); - CellValue<TinyMatrix<2>> cell_value{mesh_1d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = TinyMatrix<2>{2 * exp(x[0]) * sin(x[0]) + 3, sin(x[0] - 2 * x[0]), 3, x[0] * x[0]}; - }); + CellValue<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); - CellValue<const TinyMatrix<2>> interpolate_value = - InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } - REQUIRE(same_cell_value(cell_value, interpolate_value)); + SECTION("R2x2_affine_1d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_affine_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyMatrix<2>> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyMatrix<2>{2 * x[0] + 3 + 2, 3 * x[0], 2 * x[0], 2}; + }); + + CellValue<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_non_linear_1d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyMatrix<2>> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = + TinyMatrix<2>{2 * exp(x[0]) * sin(x[0]) + 3, sin(x[0] - 2 * x[0]), 3, x[0] * x[0]}; + }); + + CellValue<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + } } } @@ -205,10 +212,14 @@ let R2x2_non_linear_1d: R^1 -> R^2x2, x -> (2 * exp(x[0]) * sin(x[0]) + 3, sin(x { constexpr size_t Dimension = 2; - const auto& mesh_2d = MeshDataBaseForTests::get().cartesian2DMesh(); - auto xj = MeshDataManager::instance().getMeshData(*mesh_2d).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); + + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh_2d).xj(); - std::string_view data = R"( + std::string_view data = R"( import math; let scalar_affine_2d: R^2 -> R, x -> 2*x[0] + 3*x[1] + 2; let scalar_non_linear_2d: R^2 -> R, x -> 2*exp(x[0])*sin(x[1])+3; @@ -217,143 +228,146 @@ let R3_non_linear_2d: R^2 -> R^3, x -> (2*exp(x[0])*sin(x[1])+3, x[0]-2*x[1], 3) let R2x2_affine_2d: R^2 -> R^2x2, x -> (2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1], 2 * x[0] + x[1], 2); let R2x2_non_linear_2d: R^2 -> R^2x2, x -> (2*exp(x[0])*sin(x[1])+3, sin(x[0]-2*x[1]), 3, x[0]*x[1]); )"; - 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}; - - ASTNodeTypeCleaner<language::var_declaration>{*ast}; - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; - ASTNodeExpressionBuilder{*ast}; - - std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; - - TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point - - SECTION("scalar_affine_2d") - { - auto [i_symbol, found] = symbol_table->find("scalar_affine_2d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - CellValue<double> cell_value{mesh_2d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = 2 * x[0] + 3 * x[1] + 2; - }); - CellValue<const double> interpolate_value = - InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("scalar_non_linear_2d") - { - auto [i_symbol, found] = symbol_table->find("scalar_non_linear_2d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - CellValue<double> cell_value{mesh_2d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = 2 * exp(x[0]) * sin(x[1]) + 3; - }); - CellValue<const double> interpolate_value = - InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R3_affine_2d") - { - auto [i_symbol, found] = symbol_table->find("R3_affine_2d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - CellValue<TinyVector<3>> cell_value{mesh_2d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = TinyVector<3>{2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1], 2 * x[1]}; - }); - CellValue<const TinyVector<3>> interpolate_value = - InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R3_non_linear_2d") - { - auto [i_symbol, found] = symbol_table->find("R3_non_linear_2d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - CellValue<TinyVector<3>> cell_value{mesh_2d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = TinyVector<3>{2 * exp(x[0]) * sin(x[1]) + 3, x[0] - 2 * x[1], 3}; - }); - CellValue<const TinyVector<3>> interpolate_value = - InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R2x2_affine_2d") - { - auto [i_symbol, found] = symbol_table->find("R2x2_affine_2d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - CellValue<TinyMatrix<2>> cell_value{mesh_2d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = TinyMatrix<2>{2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1], 2 * x[0] + x[1], 2}; - }); - CellValue<const TinyMatrix<2>> interpolate_value = - InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R2x2_non_linear_2d") - { - auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_2d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - CellValue<TinyMatrix<2>> cell_value{mesh_2d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = TinyMatrix<2>{2 * exp(x[0]) * sin(x[1]) + 3, sin(x[0] - 2 * x[1]), 3, x[0] * x[1]}; - }); - CellValue<const TinyMatrix<2>> interpolate_value = - InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); + 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}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + SECTION("scalar_affine_2d") + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<double> cell_value{mesh_2d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = 2 * x[0] + 3 * x[1] + 2; + }); + CellValue<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("scalar_non_linear_2d") + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<double> cell_value{mesh_2d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = 2 * exp(x[0]) * sin(x[1]) + 3; + }); + CellValue<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_affine_2d") + { + auto [i_symbol, found] = symbol_table->find("R3_affine_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyVector<3>> cell_value{mesh_2d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyVector<3>{2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1], 2 * x[1]}; + }); + CellValue<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_non_linear_2d") + { + auto [i_symbol, found] = symbol_table->find("R3_non_linear_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyVector<3>> cell_value{mesh_2d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyVector<3>{2 * exp(x[0]) * sin(x[1]) + 3, x[0] - 2 * x[1], 3}; + }); + CellValue<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_affine_2d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_affine_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyMatrix<2>> cell_value{mesh_2d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyMatrix<2>{2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1], 2 * x[0] + x[1], 2}; + }); + CellValue<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_non_linear_2d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyMatrix<2>> cell_value{mesh_2d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = + TinyMatrix<2>{2 * exp(x[0]) * sin(x[1]) + 3, sin(x[0] - 2 * x[1]), 3, x[0] * x[1]}; + }); + CellValue<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + } } } @@ -361,10 +375,14 @@ let R2x2_non_linear_2d: R^2 -> R^2x2, x -> (2*exp(x[0])*sin(x[1])+3, sin(x[0]-2* { constexpr size_t Dimension = 3; - const auto& mesh_3d = MeshDataBaseForTests::get().cartesian3DMesh(); - auto xj = MeshDataManager::instance().getMeshData(*mesh_3d).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - std::string_view data = R"( + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh_3d).xj(); + + std::string_view data = R"( import math; let scalar_affine_3d: R^3 -> R, x -> 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; let scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; @@ -373,145 +391,147 @@ let R3_non_linear_3d: R^3 -> R^3, x -> (2 * exp(x[0]) * sin(x[1]) + x[2] + 3, x[ let R2x2_affine_3d: R^3 -> R^2x2, x -> (2 * x[0] + 3 * x[1] + 2 * x[2] + 1, 3 * x[0] + x[1] + 2 * x[2], 2 * x[0] + x[1] + x[2], 2); let R2x2_non_linear_3d: R^3 -> R^2x2, x -> (2 * exp(x[0]) * sin(x[1]) + 3 * cos(x[2]), sin(x[0] - 2 * x[1] * x[2]), 3, x[0] * x[1] * x[2]); )"; - 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}; - - ASTNodeTypeCleaner<language::var_declaration>{*ast}; - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; - ASTNodeExpressionBuilder{*ast}; - - std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; - - TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point - - SECTION("scalar_affine_3d") - { - auto [i_symbol, found] = symbol_table->find("scalar_affine_3d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - CellValue<double> cell_value{mesh_3d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; - }); - CellValue<const double> interpolate_value = - InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("scalar_non_linear_3d") - { - auto [i_symbol, found] = symbol_table->find("scalar_non_linear_3d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - CellValue<double> cell_value{mesh_3d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; - }); - CellValue<const double> interpolate_value = - InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R3_affine_3d") - { - auto [i_symbol, found] = symbol_table->find("R3_affine_3d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - CellValue<TinyVector<3>> cell_value{mesh_3d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = TinyVector<3>{2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1] + 2 * x[2], 2 * x[2]}; - }); - CellValue<const TinyVector<3>> interpolate_value = - InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R3_non_linear_3d") - { - auto [i_symbol, found] = symbol_table->find("R3_non_linear_3d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - CellValue<TinyVector<3>> cell_value{mesh_3d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = TinyVector<3>{2 * exp(x[0]) * sin(x[1]) + x[2] + 3, x[0] * x[2] - 2 * x[1], 3}; - }); - CellValue<const TinyVector<3>> interpolate_value = - InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R2x2_affine_3d") - { - auto [i_symbol, found] = symbol_table->find("R2x2_affine_3d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - CellValue<TinyMatrix<2>> cell_value{mesh_3d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = - TinyMatrix<2>{2 * x[0] + 3 * x[1] + 2 * x[2] + 1, 3 * x[0] + x[1] + 2 * x[2], 2 * x[0] + x[1] + x[2], 2}; - }); - CellValue<const TinyMatrix<2>> interpolate_value = - InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R2x2_non_linear_3d") - { - auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_3d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - CellValue<TinyMatrix<2>> cell_value{mesh_3d->connectivity()}; - parallel_for( - cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<Dimension>& x = xj[cell_id]; - cell_value[cell_id] = TinyMatrix<2>{2 * exp(x[0]) * sin(x[1]) + 3 * cos(x[2]), sin(x[0] - 2 * x[1] * x[2]), - 3, x[0] * x[1] * x[2]}; - }); - CellValue<const TinyMatrix<2>> interpolate_value = - InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); + 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}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + SECTION("scalar_affine_3d") + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<double> cell_value{mesh_3d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; + }); + CellValue<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("scalar_non_linear_3d") + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<double> cell_value{mesh_3d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; + }); + CellValue<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_affine_3d") + { + auto [i_symbol, found] = symbol_table->find("R3_affine_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyVector<3>> cell_value{mesh_3d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyVector<3>{2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1] + 2 * x[2], 2 * x[2]}; + }); + CellValue<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_non_linear_3d") + { + auto [i_symbol, found] = symbol_table->find("R3_non_linear_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyVector<3>> cell_value{mesh_3d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyVector<3>{2 * exp(x[0]) * sin(x[1]) + x[2] + 3, x[0] * x[2] - 2 * x[1], 3}; + }); + CellValue<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_affine_3d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_affine_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyMatrix<2>> cell_value{mesh_3d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyMatrix<2>{2 * x[0] + 3 * x[1] + 2 * x[2] + 1, 3 * x[0] + x[1] + 2 * x[2], + 2 * x[0] + x[1] + x[2], 2}; + }); + CellValue<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_non_linear_3d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyMatrix<2>> cell_value{mesh_3d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyMatrix<2>{2 * exp(x[0]) * sin(x[1]) + 3 * cos(x[2]), + sin(x[0] - 2 * x[1] * x[2]), 3, x[0] * x[1] * x[2]}; + }); + CellValue<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + } } } } @@ -532,18 +552,22 @@ let R2x2_non_linear_3d: R^3 -> R^2x2, x -> (2 * exp(x[0]) * sin(x[1]) + 3 * cos( { constexpr size_t Dimension = 1; - const auto& mesh_1d = MeshDataBaseForTests::get().cartesian1DMesh(); - auto xj = MeshDataManager::instance().getMeshData(*mesh_1d).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - Array<const CellId> cell_id_list = [&] { - Array<CellId> cell_ids{mesh_1d->numberOfCells() / 2}; - for (size_t i_cell = 0; i_cell < cell_ids.size(); ++i_cell) { - cell_ids[i_cell] = static_cast<CellId>(2 * i_cell); - } - return cell_ids; - }(); + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh_1d).xj(); - std::string_view data = R"( + Array<const CellId> cell_id_list = [&] { + Array<CellId> cell_ids{mesh_1d->numberOfCells() / 2}; + for (size_t i_cell = 0; i_cell < cell_ids.size(); ++i_cell) { + cell_ids[i_cell] = static_cast<CellId>(2 * i_cell); + } + return cell_ids; + }(); + + std::string_view data = R"( import math; let scalar_affine_1d: R^1 -> R, x -> 2*x[0] + 2; let scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; @@ -552,149 +576,155 @@ let R3_non_linear_1d: R^1 -> R^3, x -> (2 * exp(x[0]) + 3, x[0] - 2, 3); let R2x2_affine_1d: R^1 -> R^2x2, x -> (2 * x[0] + 3 + 2, 3 * x[0], 2 * x[0], 2); let R2x2_non_linear_1d: R^1 -> R^2x2, x -> (2 * exp(x[0]) * sin(x[0]) + 3, sin(x[0] - 2 * x[0]), 3, x[0] * x[0]); )"; - 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}; - - ASTNodeTypeCleaner<language::var_declaration>{*ast}; - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; - ASTNodeExpressionBuilder{*ast}; - - std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; - - TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point - - SECTION("scalar_affine_1d") - { - auto [i_symbol, found] = symbol_table->find("scalar_affine_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + auto ast = ASTBuilder::build(input); - Array<double> cell_value{cell_id_list.size()}; - parallel_for( - cell_value.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_value[i] = 2 * x[0] + 2; - }); + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; - Array<const double> interpolate_value = - InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("scalar_non_linear_1d") - { - auto [i_symbol, found] = symbol_table->find("scalar_non_linear_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - Array<double> cell_value{cell_id_list.size()}; - parallel_for( - cell_value.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_value[i] = 2 * exp(x[0]) + 3; - }); - - Array<const double> interpolate_value = - InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R3_affine_1d") - { - auto [i_symbol, found] = symbol_table->find("R3_affine_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - Array<TinyVector<3>> cell_value{cell_id_list.size()}; - parallel_for( - cell_value.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_value[i] = TinyVector<3>{2 * x[0] + 2, 3 * x[0], 2}; - }); - - Array<const TinyVector<3>> interpolate_value = - InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R3_non_linear_1d") - { - auto [i_symbol, found] = symbol_table->find("R3_non_linear_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - Array<TinyVector<3>> cell_value{cell_id_list.size()}; - parallel_for( - cell_value.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_value[i] = TinyVector<3>{2 * exp(x[0]) + 3, x[0] - 2, 3}; - }); - - Array<const TinyVector<3>> interpolate_value = - InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R2x2_affine_1d") - { - auto [i_symbol, found] = symbol_table->find("R2x2_affine_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; - Array<TinyMatrix<2>> cell_value{cell_id_list.size()}; - parallel_for( - cell_value.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_value[i] = TinyMatrix<2>{2 * x[0] + 3 + 2, 3 * x[0], 2 * x[0], 2}; - }); + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point - Array<const TinyMatrix<2>> interpolate_value = - InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + SECTION("scalar_affine_1d") + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - SECTION("R2x2_non_linear_1d") - { - auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_1d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + Array<double> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = 2 * x[0] + 2; + }); - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + Array<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); - Array<TinyMatrix<2>> cell_value{cell_id_list.size()}; - parallel_for( - cell_value.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_value[i] = TinyMatrix<2>{2 * exp(x[0]) * sin(x[0]) + 3, sin(x[0] - 2 * x[0]), 3, x[0] * x[0]}; - }); + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("scalar_non_linear_1d") + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - Array<const TinyMatrix<2>> interpolate_value = - InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<double> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = 2 * exp(x[0]) + 3; + }); + + Array<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_affine_1d") + { + auto [i_symbol, found] = symbol_table->find("R3_affine_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyVector<3>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyVector<3>{2 * x[0] + 2, 3 * x[0], 2}; + }); + + Array<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, + cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_non_linear_1d") + { + auto [i_symbol, found] = symbol_table->find("R3_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyVector<3>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyVector<3>{2 * exp(x[0]) + 3, x[0] - 2, 3}; + }); + + Array<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, + cell_id_list); - REQUIRE(same_cell_value(cell_value, interpolate_value)); + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_affine_1d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_affine_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyMatrix<2>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyMatrix<2>{2 * x[0] + 3 + 2, 3 * x[0], 2 * x[0], 2}; + }); + + Array<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, + cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_non_linear_1d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyMatrix<2>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyMatrix<2>{2 * exp(x[0]) * sin(x[0]) + 3, sin(x[0] - 2 * x[0]), 3, x[0] * x[0]}; + }); + + Array<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, + cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + } } } @@ -702,15 +732,19 @@ let R2x2_non_linear_1d: R^1 -> R^2x2, x -> (2 * exp(x[0]) * sin(x[0]) + 3, sin(x { constexpr size_t Dimension = 2; - const auto& mesh_2d = MeshDataBaseForTests::get().cartesian2DMesh(); - auto xj = MeshDataManager::instance().getMeshData(*mesh_2d).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - Array<CellId> cell_id_list{mesh_2d->numberOfCells() / 2}; - for (size_t i_cell = 0; i_cell < cell_id_list.size(); ++i_cell) { - cell_id_list[i_cell] = static_cast<CellId>(2 * i_cell); - } + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh_2d).xj(); + + Array<CellId> cell_id_list{mesh_2d->numberOfCells() / 2}; + for (size_t i_cell = 0; i_cell < cell_id_list.size(); ++i_cell) { + cell_id_list[i_cell] = static_cast<CellId>(2 * i_cell); + } - std::string_view data = R"( + std::string_view data = R"( import math; let scalar_affine_2d: R^2 -> R, x -> 2*x[0] + 3*x[1] + 2; let scalar_non_linear_2d: R^2 -> R, x -> 2*exp(x[0])*sin(x[1])+3; @@ -719,144 +753,150 @@ let R3_non_linear_2d: R^2 -> R^3, x -> (2*exp(x[0])*sin(x[1])+3, x[0]-2*x[1], 3) let R2x2_affine_2d: R^2 -> R^2x2, x -> (2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1], 2 * x[0] + x[1], 2); let R2x2_non_linear_2d: R^2 -> R^2x2, x -> (2*exp(x[0])*sin(x[1])+3, sin(x[0]-2*x[1]), 3, x[0]*x[1]); )"; - 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}; - - ASTNodeTypeCleaner<language::var_declaration>{*ast}; - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; - ASTNodeExpressionBuilder{*ast}; - - std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; - - TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point - - SECTION("scalar_affine_2d") - { - auto [i_symbol, found] = symbol_table->find("scalar_affine_2d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - Array<double> cell_value{cell_id_list.size()}; - parallel_for( - cell_value.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_value[i] = 2 * x[0] + 3 * x[1] + 2; - }); - - Array<const double> interpolate_value = - InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("scalar_non_linear_2d") - { - auto [i_symbol, found] = symbol_table->find("scalar_non_linear_2d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - Array<double> cell_value{cell_id_list.size()}; - parallel_for( - cell_value.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_value[i] = 2 * exp(x[0]) * sin(x[1]) + 3; - }); - Array<const double> interpolate_value = - InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R3_affine_2d") - { - auto [i_symbol, found] = symbol_table->find("R3_affine_2d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - Array<TinyVector<3>> cell_value{cell_id_list.size()}; - parallel_for( - cell_value.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_value[i] = TinyVector<3>{2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1], 2 * x[1]}; - }); - Array<const TinyVector<3>> interpolate_value = - InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R3_non_linear_2d") - { - auto [i_symbol, found] = symbol_table->find("R3_non_linear_2d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - Array<TinyVector<3>> cell_value{cell_id_list.size()}; - parallel_for( - cell_value.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_value[i] = TinyVector<3>{2 * exp(x[0]) * sin(x[1]) + 3, x[0] - 2 * x[1], 3}; - }); - Array<const TinyVector<3>> interpolate_value = - InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R2x2_affine_2d") - { - auto [i_symbol, found] = symbol_table->find("R2x2_affine_2d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - Array<TinyMatrix<2>> cell_value{cell_id_list.size()}; - parallel_for( - cell_value.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_value[i] = TinyMatrix<2>{2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1], 2 * x[0] + x[1], 2}; - }); - Array<const TinyMatrix<2>> interpolate_value = - InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R2x2_non_linear_2d") - { - auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_2d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - Array<TinyMatrix<2>> cell_value{cell_id_list.size()}; - parallel_for( - cell_value.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_value[i] = TinyMatrix<2>{2 * exp(x[0]) * sin(x[1]) + 3, sin(x[0] - 2 * x[1]), 3, x[0] * x[1]}; - }); - Array<const TinyMatrix<2>> interpolate_value = - InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); + 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}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + SECTION("scalar_affine_2d") + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<double> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = 2 * x[0] + 3 * x[1] + 2; + }); + + Array<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("scalar_non_linear_2d") + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<double> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = 2 * exp(x[0]) * sin(x[1]) + 3; + }); + Array<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_affine_2d") + { + auto [i_symbol, found] = symbol_table->find("R3_affine_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyVector<3>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyVector<3>{2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1], 2 * x[1]}; + }); + Array<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, + cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_non_linear_2d") + { + auto [i_symbol, found] = symbol_table->find("R3_non_linear_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyVector<3>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyVector<3>{2 * exp(x[0]) * sin(x[1]) + 3, x[0] - 2 * x[1], 3}; + }); + Array<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, + cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_affine_2d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_affine_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyMatrix<2>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyMatrix<2>{2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1], 2 * x[0] + x[1], 2}; + }); + Array<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, + cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_non_linear_2d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyMatrix<2>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyMatrix<2>{2 * exp(x[0]) * sin(x[1]) + 3, sin(x[0] - 2 * x[1]), 3, x[0] * x[1]}; + }); + Array<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, + cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + } } } @@ -864,15 +904,19 @@ let R2x2_non_linear_2d: R^2 -> R^2x2, x -> (2*exp(x[0])*sin(x[1])+3, sin(x[0]-2* { constexpr size_t Dimension = 3; - const auto& mesh_3d = MeshDataBaseForTests::get().cartesian3DMesh(); - auto xj = MeshDataManager::instance().getMeshData(*mesh_3d).xj(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - Array<CellId> cell_id_list{mesh_3d->numberOfCells() / 2}; - for (size_t i_cell = 0; i_cell < cell_id_list.size(); ++i_cell) { - cell_id_list[i_cell] = static_cast<CellId>(2 * i_cell); - } + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + auto xj = MeshDataManager::instance().getMeshData(*mesh_3d).xj(); - std::string_view data = R"( + Array<CellId> cell_id_list{mesh_3d->numberOfCells() / 2}; + for (size_t i_cell = 0; i_cell < cell_id_list.size(); ++i_cell) { + cell_id_list[i_cell] = static_cast<CellId>(2 * i_cell); + } + + std::string_view data = R"( import math; let scalar_affine_3d: R^3 -> R, x -> 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; let scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; @@ -881,145 +925,151 @@ let R3_non_linear_3d: R^3 -> R^3, x -> (2 * exp(x[0]) * sin(x[1]) + x[2] + 3, x[ let R2x2_affine_3d: R^3 -> R^2x2, x -> (2 * x[0] + 3 * x[1] + 2 * x[2] + 1, 3 * x[0] + x[1] + 2 * x[2], 2 * x[0] + x[1] + x[2], 2); let R2x2_non_linear_3d: R^3 -> R^2x2, x -> (2 * exp(x[0]) * sin(x[1]) + 3 * cos(x[2]), sin(x[0] - 2 * x[1] * x[2]), 3, x[0] * x[1] * x[2]); )"; - 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}; - - ASTNodeTypeCleaner<language::var_declaration>{*ast}; - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; - ASTNodeExpressionBuilder{*ast}; - - std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; - - TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point - - SECTION("scalar_affine_3d") - { - auto [i_symbol, found] = symbol_table->find("scalar_affine_3d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - Array<double> cell_value{cell_id_list.size()}; - parallel_for( - cell_value.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_value[i] = 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; - }); - Array<const double> interpolate_value = - InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("scalar_non_linear_3d") - { - auto [i_symbol, found] = symbol_table->find("scalar_non_linear_3d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - Array<double> cell_value{cell_id_list.size()}; - parallel_for( - cell_value.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_value[i] = 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; - }); - Array<const double> interpolate_value = - InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R3_affine_3d") - { - auto [i_symbol, found] = symbol_table->find("R3_affine_3d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - Array<TinyVector<3>> cell_value{cell_id_list.size()}; - parallel_for( - cell_value.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_value[i] = TinyVector<3>{2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1] + 2 * x[2], 2 * x[2]}; - }); - Array<const TinyVector<3>> interpolate_value = - InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R3_non_linear_3d") - { - auto [i_symbol, found] = symbol_table->find("R3_non_linear_3d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - Array<TinyVector<3>> cell_value{cell_id_list.size()}; - parallel_for( - cell_value.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_value[i] = TinyVector<3>{2 * exp(x[0]) * sin(x[1]) + x[2] + 3, x[0] * x[2] - 2 * x[1], 3}; - }); - Array<const TinyVector<3>> interpolate_value = - InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R2x2_affine_3d") - { - auto [i_symbol, found] = symbol_table->find("R2x2_affine_3d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - Array<TinyMatrix<2>> cell_value{cell_id_list.size()}; - parallel_for( - cell_value.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_value[i] = - TinyMatrix<2>{2 * x[0] + 3 * x[1] + 2 * x[2] + 1, 3 * x[0] + x[1] + 2 * x[2], 2 * x[0] + x[1] + x[2], 2}; - }); - Array<const TinyMatrix<2>> interpolate_value = - InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); - } - - SECTION("R2x2_non_linear_3d") - { - auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_3d", position); - REQUIRE(found); - REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); - - FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); - - Array<TinyMatrix<2>> cell_value{cell_id_list.size()}; - parallel_for( - cell_value.size(), PUGS_LAMBDA(const size_t i) { - const TinyVector<Dimension>& x = xj[cell_id_list[i]]; - cell_value[i] = TinyMatrix<2>{2 * exp(x[0]) * sin(x[1]) + 3 * cos(x[2]), sin(x[0] - 2 * x[1] * x[2]), 3, - x[0] * x[1] * x[2]}; - }); - Array<const TinyMatrix<2>> interpolate_value = - InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); - - REQUIRE(same_cell_value(cell_value, interpolate_value)); + 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}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + SECTION("scalar_affine_3d") + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<double> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; + }); + Array<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("scalar_non_linear_3d") + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<double> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; + }); + Array<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_affine_3d") + { + auto [i_symbol, found] = symbol_table->find("R3_affine_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyVector<3>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyVector<3>{2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1] + 2 * x[2], 2 * x[2]}; + }); + Array<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, + cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_non_linear_3d") + { + auto [i_symbol, found] = symbol_table->find("R3_non_linear_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyVector<3>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyVector<3>{2 * exp(x[0]) * sin(x[1]) + x[2] + 3, x[0] * x[2] - 2 * x[1], 3}; + }); + Array<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, + cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_affine_3d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_affine_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyMatrix<2>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyMatrix<2>{2 * x[0] + 3 * x[1] + 2 * x[2] + 1, 3 * x[0] + x[1] + 2 * x[2], + 2 * x[0] + x[1] + x[2], 2}; + }); + Array<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, + cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_non_linear_3d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyMatrix<2>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyMatrix<2>{2 * exp(x[0]) * sin(x[1]) + 3 * cos(x[2]), sin(x[0] - 2 * x[1] * x[2]), 3, + x[0] * x[1] * x[2]}; + }); + Array<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, + cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + } } } } diff --git a/tests/test_ItemArray.cpp b/tests/test_ItemArray.cpp index 2cb868465d8b7144a9b325a364afd43fbde2d52f..c8a4bd8555f3b75e4b3179474142208507159b80 100644 --- a/tests/test_ItemArray.cpp +++ b/tests/test_ItemArray.cpp @@ -28,118 +28,142 @@ TEST_CASE("ItemArray", "[mesh]") SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesian1DMesh(); - const Connectivity<1>& connectivity = mesh_1d.connectivity(); - - REQUIRE_NOTHROW(NodeArray<int>{connectivity, 3}); - REQUIRE_NOTHROW(EdgeArray<int>{connectivity, 3}); - REQUIRE_NOTHROW(FaceArray<int>{connectivity, 3}); - REQUIRE_NOTHROW(CellArray<int>{connectivity, 3}); - - REQUIRE(NodeArray<int>{connectivity, 3}.isBuilt()); - REQUIRE(EdgeArray<int>{connectivity, 3}.isBuilt()); - REQUIRE(FaceArray<int>{connectivity, 3}.isBuilt()); - REQUIRE(CellArray<int>{connectivity, 3}.isBuilt()); - - NodeArray<int> node_value{connectivity, 3}; - EdgeArray<int> edge_value{connectivity, 3}; - FaceArray<int> face_value{connectivity, 3}; - CellArray<int> cell_value{connectivity, 3}; - - REQUIRE(edge_value.numberOfItems() == node_value.numberOfItems()); - REQUIRE(face_value.numberOfItems() == node_value.numberOfItems()); - REQUIRE(cell_value.numberOfItems() + 1 == node_value.numberOfItems()); - - REQUIRE(node_value.sizeOfArrays() == 3); - REQUIRE(edge_value.sizeOfArrays() == 3); - REQUIRE(face_value.sizeOfArrays() == 3); - REQUIRE(cell_value.sizeOfArrays() == 3); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); + + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<1>& connectivity = mesh_1d->connectivity(); + + REQUIRE_NOTHROW(NodeArray<int>{connectivity, 3}); + REQUIRE_NOTHROW(EdgeArray<int>{connectivity, 3}); + REQUIRE_NOTHROW(FaceArray<int>{connectivity, 3}); + REQUIRE_NOTHROW(CellArray<int>{connectivity, 3}); + + REQUIRE(NodeArray<int>{connectivity, 3}.isBuilt()); + REQUIRE(EdgeArray<int>{connectivity, 3}.isBuilt()); + REQUIRE(FaceArray<int>{connectivity, 3}.isBuilt()); + REQUIRE(CellArray<int>{connectivity, 3}.isBuilt()); + + NodeArray<int> node_value{connectivity, 3}; + EdgeArray<int> edge_value{connectivity, 3}; + FaceArray<int> face_value{connectivity, 3}; + CellArray<int> cell_value{connectivity, 3}; + + REQUIRE(edge_value.numberOfItems() == node_value.numberOfItems()); + REQUIRE(face_value.numberOfItems() == node_value.numberOfItems()); + REQUIRE(cell_value.numberOfItems() + 1 == node_value.numberOfItems()); + + REQUIRE(node_value.sizeOfArrays() == 3); + REQUIRE(edge_value.sizeOfArrays() == 3); + REQUIRE(face_value.sizeOfArrays() == 3); + REQUIRE(cell_value.sizeOfArrays() == 3); + } + } } SECTION("2D") { - const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesian2DMesh(); - const Connectivity<2>& connectivity = mesh_2d.connectivity(); - - REQUIRE_NOTHROW(NodeArray<int>{connectivity, 2}); - REQUIRE_NOTHROW(EdgeArray<int>{connectivity, 2}); - REQUIRE_NOTHROW(FaceArray<int>{connectivity, 2}); - REQUIRE_NOTHROW(CellArray<int>{connectivity, 2}); - - REQUIRE(NodeArray<int>{connectivity, 2}.isBuilt()); - REQUIRE(EdgeArray<int>{connectivity, 2}.isBuilt()); - REQUIRE(FaceArray<int>{connectivity, 2}.isBuilt()); - REQUIRE(CellArray<int>{connectivity, 2}.isBuilt()); - - NodeArray<int> node_value{connectivity, 2}; - EdgeArray<int> edge_value{connectivity, 2}; - FaceArray<int> face_value{connectivity, 2}; - CellArray<int> cell_value{connectivity, 2}; - - REQUIRE(edge_value.numberOfItems() == face_value.numberOfItems()); - - REQUIRE(node_value.sizeOfArrays() == 2); - REQUIRE(edge_value.sizeOfArrays() == 2); - REQUIRE(face_value.sizeOfArrays() == 2); - REQUIRE(cell_value.sizeOfArrays() == 2); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); + + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<2>& connectivity = mesh_2d->connectivity(); + + REQUIRE_NOTHROW(NodeArray<int>{connectivity, 2}); + REQUIRE_NOTHROW(EdgeArray<int>{connectivity, 2}); + REQUIRE_NOTHROW(FaceArray<int>{connectivity, 2}); + REQUIRE_NOTHROW(CellArray<int>{connectivity, 2}); + + REQUIRE(NodeArray<int>{connectivity, 2}.isBuilt()); + REQUIRE(EdgeArray<int>{connectivity, 2}.isBuilt()); + REQUIRE(FaceArray<int>{connectivity, 2}.isBuilt()); + REQUIRE(CellArray<int>{connectivity, 2}.isBuilt()); + + NodeArray<int> node_value{connectivity, 2}; + EdgeArray<int> edge_value{connectivity, 2}; + FaceArray<int> face_value{connectivity, 2}; + CellArray<int> cell_value{connectivity, 2}; + + REQUIRE(edge_value.numberOfItems() == face_value.numberOfItems()); + + REQUIRE(node_value.sizeOfArrays() == 2); + REQUIRE(edge_value.sizeOfArrays() == 2); + REQUIRE(face_value.sizeOfArrays() == 2); + REQUIRE(cell_value.sizeOfArrays() == 2); + } + } } SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); - - REQUIRE_NOTHROW(NodeArray<int>{connectivity, 3}); - REQUIRE_NOTHROW(EdgeArray<int>{connectivity, 3}); - REQUIRE_NOTHROW(FaceArray<int>{connectivity, 3}); - REQUIRE_NOTHROW(CellArray<int>{connectivity, 3}); - - REQUIRE(NodeArray<int>{connectivity, 3}.isBuilt()); - REQUIRE(EdgeArray<int>{connectivity, 3}.isBuilt()); - REQUIRE(FaceArray<int>{connectivity, 3}.isBuilt()); - REQUIRE(CellArray<int>{connectivity, 3}.isBuilt()); - - NodeArray<int> node_value{connectivity, 3}; - EdgeArray<int> edge_value{connectivity, 3}; - FaceArray<int> face_value{connectivity, 3}; - CellArray<int> cell_value{connectivity, 3}; - - REQUIRE(node_value.sizeOfArrays() == 3); - REQUIRE(edge_value.sizeOfArrays() == 3); - REQUIRE(face_value.sizeOfArrays() == 3); - REQUIRE(cell_value.sizeOfArrays() == 3); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); + + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<3>& connectivity = mesh_3d->connectivity(); + + REQUIRE_NOTHROW(NodeArray<int>{connectivity, 3}); + REQUIRE_NOTHROW(EdgeArray<int>{connectivity, 3}); + REQUIRE_NOTHROW(FaceArray<int>{connectivity, 3}); + REQUIRE_NOTHROW(CellArray<int>{connectivity, 3}); + + REQUIRE(NodeArray<int>{connectivity, 3}.isBuilt()); + REQUIRE(EdgeArray<int>{connectivity, 3}.isBuilt()); + REQUIRE(FaceArray<int>{connectivity, 3}.isBuilt()); + REQUIRE(CellArray<int>{connectivity, 3}.isBuilt()); + + NodeArray<int> node_value{connectivity, 3}; + EdgeArray<int> edge_value{connectivity, 3}; + FaceArray<int> face_value{connectivity, 3}; + CellArray<int> cell_value{connectivity, 3}; + + REQUIRE(node_value.sizeOfArrays() == 3); + REQUIRE(edge_value.sizeOfArrays() == 3); + REQUIRE(face_value.sizeOfArrays() == 3); + REQUIRE(cell_value.sizeOfArrays() == 3); + } + } } SECTION("set values from array") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); - - CellArray<size_t> cell_array{connectivity, 3}; - - Table<size_t> table{cell_array.numberOfItems(), cell_array.sizeOfArrays()}; - { - size_t k = 0; - for (size_t i = 0; i < table.numberOfRows(); ++i) { - for (size_t j = 0; j < table.numberOfColumns(); ++j) { - table(i, j) = k++; + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); + + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<3>& connectivity = mesh_3d->connectivity(); + + CellArray<size_t> cell_array{connectivity, 3}; + + Table<size_t> table{cell_array.numberOfItems(), cell_array.sizeOfArrays()}; + { + size_t k = 0; + for (size_t i = 0; i < table.numberOfRows(); ++i) { + for (size_t j = 0; j < table.numberOfColumns(); ++j) { + table(i, j) = k++; + } + } } + cell_array = table; + + auto is_same = [](const CellArray<size_t>& cell_array, const Table<size_t>& table) { + bool is_same = true; + for (CellId cell_id = 0; cell_id < cell_array.numberOfItems(); ++cell_id) { + Array sub_array = cell_array[cell_id]; + for (size_t i = 0; i < sub_array.size(); ++i) { + is_same &= (sub_array[i] == table(cell_id, i)); + } + } + return is_same; + }; + + REQUIRE(is_same(cell_array, table)); } } - cell_array = table; - - auto is_same = [](const CellArray<size_t>& cell_array, const Table<size_t>& table) { - bool is_same = true; - for (CellId cell_id = 0; cell_id < cell_array.numberOfItems(); ++cell_id) { - Array sub_array = cell_array[cell_id]; - for (size_t i = 0; i < sub_array.size(); ++i) { - is_same &= (sub_array[i] == table(cell_id, i)); - } - } - return is_same; - }; - - REQUIRE(is_same(cell_array, table)); } SECTION("copy") @@ -155,43 +179,55 @@ TEST_CASE("ItemArray", "[mesh]") return is_same; }; - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); + + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<3>& connectivity = mesh_3d->connectivity(); - CellArray<int> cell_array{connectivity, 4}; - cell_array.fill(parallel::rank()); + CellArray<int> cell_array{connectivity, 4}; + cell_array.fill(parallel::rank()); - CellArray<const int> cell_array_const_view{cell_array}; - REQUIRE(cell_array.numberOfItems() == cell_array_const_view.numberOfItems()); - REQUIRE(cell_array.sizeOfArrays() == cell_array_const_view.sizeOfArrays()); - REQUIRE(is_same(cell_array_const_view, static_cast<std::int64_t>(parallel::rank()))); + CellArray<const int> cell_array_const_view{cell_array}; + REQUIRE(cell_array.numberOfItems() == cell_array_const_view.numberOfItems()); + REQUIRE(cell_array.sizeOfArrays() == cell_array_const_view.sizeOfArrays()); + REQUIRE(is_same(cell_array_const_view, static_cast<std::int64_t>(parallel::rank()))); - CellArray<const int> const_cell_array; - const_cell_array = copy(cell_array); + CellArray<const int> const_cell_array; + const_cell_array = copy(cell_array); - CellArray<int> duplicated_cell_array{connectivity, cell_array.sizeOfArrays()}; - copy_to(const_cell_array, duplicated_cell_array); + CellArray<int> duplicated_cell_array{connectivity, cell_array.sizeOfArrays()}; + copy_to(const_cell_array, duplicated_cell_array); - cell_array.fill(0); + cell_array.fill(0); - REQUIRE(is_same(cell_array, 0)); - REQUIRE(is_same(cell_array_const_view, 0)); - REQUIRE(is_same(const_cell_array, static_cast<std::int64_t>(parallel::rank()))); - REQUIRE(is_same(duplicated_cell_array, static_cast<std::int64_t>(parallel::rank()))); + REQUIRE(is_same(cell_array, 0)); + REQUIRE(is_same(cell_array_const_view, 0)); + REQUIRE(is_same(const_cell_array, static_cast<std::int64_t>(parallel::rank()))); + REQUIRE(is_same(duplicated_cell_array, static_cast<std::int64_t>(parallel::rank()))); + } + } } SECTION("WeakItemArray") { - const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesian2DMesh(); - const Connectivity<2>& connectivity = mesh_2d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - WeakFaceArray<int> weak_face_array{connectivity, 5}; + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<2>& connectivity = mesh_2d->connectivity(); - weak_face_array.fill(parallel::rank()); + WeakFaceArray<int> weak_face_array{connectivity, 5}; - FaceArray<const int> face_array{weak_face_array}; + weak_face_array.fill(parallel::rank()); - REQUIRE(face_array.connectivity_ptr() == weak_face_array.connectivity_ptr()); + FaceArray<const int> face_array{weak_face_array}; + + REQUIRE(face_array.connectivity_ptr() == weak_face_array.connectivity_ptr()); + } + } } #ifndef NDEBUG @@ -214,35 +250,47 @@ TEST_CASE("ItemArray", "[mesh]") SECTION("checking for bounds violation") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); + + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<3>& connectivity = mesh_3d->connectivity(); - CellArray<int> cell_array{connectivity, 1}; - CellId invalid_cell_id = connectivity.numberOfCells(); - REQUIRE_THROWS_AS(cell_array[invalid_cell_id], AssertError); + CellArray<int> cell_array{connectivity, 1}; + CellId invalid_cell_id = connectivity.numberOfCells(); + REQUIRE_THROWS_AS(cell_array[invalid_cell_id], AssertError); - FaceArray<int> face_array{connectivity, 2}; - FaceId invalid_face_id = connectivity.numberOfFaces(); - REQUIRE_THROWS_AS(face_array[invalid_face_id], AssertError); + FaceArray<int> face_array{connectivity, 2}; + FaceId invalid_face_id = connectivity.numberOfFaces(); + REQUIRE_THROWS_AS(face_array[invalid_face_id], AssertError); - EdgeArray<int> edge_array{connectivity, 1}; - EdgeId invalid_edge_id = connectivity.numberOfEdges(); - REQUIRE_THROWS_AS(edge_array[invalid_edge_id], AssertError); + EdgeArray<int> edge_array{connectivity, 1}; + EdgeId invalid_edge_id = connectivity.numberOfEdges(); + REQUIRE_THROWS_AS(edge_array[invalid_edge_id], AssertError); - NodeArray<int> node_array{connectivity, 0}; - NodeId invalid_node_id = connectivity.numberOfNodes(); - REQUIRE_THROWS_AS(node_array[invalid_node_id], AssertError); + NodeArray<int> node_array{connectivity, 0}; + NodeId invalid_node_id = connectivity.numberOfNodes(); + REQUIRE_THROWS_AS(node_array[invalid_node_id], AssertError); + } + } } SECTION("set values from invalid array size") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - CellArray<size_t> cell_array{connectivity, 2}; + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<3>& connectivity = mesh_3d->connectivity(); - Table<size_t> values{3, connectivity.numberOfCells() + 3}; - REQUIRE_THROWS_AS(cell_array = values, AssertError); + CellArray<size_t> cell_array{connectivity, 2}; + + Table<size_t> values{3, connectivity.numberOfCells() + 3}; + REQUIRE_THROWS_AS(cell_array = values, AssertError); + } + } } } #endif // NDEBUG diff --git a/tests/test_ItemArrayUtils.cpp b/tests/test_ItemArrayUtils.cpp index c746a22f5937a1d6180466c3b2333536002d29e5..204986ce6f3ad9e88565559a8558e9dbf42faeb2 100644 --- a/tests/test_ItemArrayUtils.cpp +++ b/tests/test_ItemArrayUtils.cpp @@ -19,750 +19,773 @@ TEST_CASE("ItemArrayUtils", "[mesh]") { SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesian1DMesh(); - const Connectivity<1>& connectivity = mesh_1d.connectivity(); - - SECTION("node") - { - WeakNodeArray<size_t> weak_node_array{connectivity, 4}; - auto node_number = connectivity.nodeNumber(); - - for (NodeId i_node = 0; i_node < mesh_1d.numberOfNodes(); ++i_node) { - Array array = weak_node_array[i_node]; - const size_t number = node_number[i_node]; - for (size_t i = 0; i < array.size(); ++i) { - array[i] = number + (parallel::rank() + 1) * i; - } - } + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - NodeArray<const size_t> node_array{weak_node_array}; + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<1>& connectivity = mesh_1d->connectivity(); - REQUIRE(node_array.connectivity_ptr() == weak_node_array.connectivity_ptr()); + SECTION("node") + { + WeakNodeArray<size_t> weak_node_array{connectivity, 4}; + auto node_number = connectivity.nodeNumber(); - { // before synchronization - auto node_owner = connectivity.nodeOwner(); - auto node_is_owned = connectivity.nodeIsOwned(); - - bool is_synchronized = (parallel::size() > 1); - bool is_valid = true; - for (NodeId i_node = 0; i_node < mesh_1d.numberOfNodes(); ++i_node) { - Array array = node_array[i_node]; - const size_t number = node_number[i_node]; - const size_t owner = node_owner[i_node]; - if (node_is_owned[i_node]) { + for (NodeId i_node = 0; i_node < mesh_1d->numberOfNodes(); ++i_node) { + Array array = weak_node_array[i_node]; + const size_t number = node_number[i_node]; for (size_t i = 0; i < array.size(); ++i) { - is_valid &= (array[i] == number + (owner + 1) * i); - } - } else { - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + array[i] = number + (parallel::rank() + 1) * i; } } - } - REQUIRE(is_valid); - REQUIRE(not is_synchronized); - } - - synchronize(weak_node_array); - - { // after synchronization - auto node_owner = connectivity.nodeOwner(); + NodeArray<const size_t> node_array{weak_node_array}; + + REQUIRE(node_array.connectivity_ptr() == weak_node_array.connectivity_ptr()); + + { // before synchronization + auto node_owner = connectivity.nodeOwner(); + auto node_is_owned = connectivity.nodeIsOwned(); + + bool is_synchronized = (parallel::size() > 1); + bool is_valid = true; + for (NodeId i_node = 0; i_node < mesh_1d->numberOfNodes(); ++i_node) { + Array array = node_array[i_node]; + const size_t number = node_number[i_node]; + const size_t owner = node_owner[i_node]; + if (node_is_owned[i_node]) { + for (size_t i = 0; i < array.size(); ++i) { + is_valid &= (array[i] == number + (owner + 1) * i); + } + } else { + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } + } - bool is_synchronized = true; - for (NodeId i_node = 0; i_node < mesh_1d.numberOfNodes(); ++i_node) { - Array array = node_array[i_node]; - const size_t number = node_number[i_node]; - const size_t owner = node_owner[i_node]; - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + REQUIRE(is_valid); + REQUIRE(not is_synchronized); } - } - REQUIRE(is_synchronized); - } - } + synchronize(weak_node_array); - SECTION("edge") - { - WeakEdgeArray<size_t> weak_edge_array{connectivity, 4}; - auto edge_number = connectivity.edgeNumber(); + { // after synchronization + auto node_owner = connectivity.nodeOwner(); - for (EdgeId i_edge = 0; i_edge < mesh_1d.numberOfEdges(); ++i_edge) { - Array array = weak_edge_array[i_edge]; - const size_t number = edge_number[i_edge]; - for (size_t i = 0; i < array.size(); ++i) { - array[i] = number + (parallel::rank() + 1) * i; - } - } - - EdgeArray<const size_t> edge_array{weak_edge_array}; - - REQUIRE(edge_array.connectivity_ptr() == weak_edge_array.connectivity_ptr()); - - { // before synchronization - auto edge_owner = connectivity.edgeOwner(); - auto edge_is_owned = connectivity.edgeIsOwned(); - - bool is_synchronized = (parallel::size() > 1); - bool is_valid = true; - for (EdgeId i_edge = 0; i_edge < mesh_1d.numberOfEdges(); ++i_edge) { - Array array = edge_array[i_edge]; - const size_t number = edge_number[i_edge]; - const size_t owner = edge_owner[i_edge]; - if (edge_is_owned[i_edge]) { - for (size_t i = 0; i < array.size(); ++i) { - is_valid &= (array[i] == number + (owner + 1) * i); - } - } else { - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + bool is_synchronized = true; + for (NodeId i_node = 0; i_node < mesh_1d->numberOfNodes(); ++i_node) { + Array array = node_array[i_node]; + const size_t number = node_number[i_node]; + const size_t owner = node_owner[i_node]; + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } } - } - } - REQUIRE(is_valid); - REQUIRE(not is_synchronized); - } - - synchronize(weak_edge_array); - - { // after synchronization - auto edge_owner = connectivity.edgeOwner(); - - bool is_synchronized = true; - for (EdgeId i_edge = 0; i_edge < mesh_1d.numberOfEdges(); ++i_edge) { - Array array = edge_array[i_edge]; - const size_t number = edge_number[i_edge]; - const size_t owner = edge_owner[i_edge]; - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + REQUIRE(is_synchronized); } } - REQUIRE(is_synchronized); - } - } - - SECTION("face") - { - WeakFaceArray<size_t> weak_face_array{connectivity, 4}; - auto face_number = connectivity.faceNumber(); - - for (FaceId i_face = 0; i_face < mesh_1d.numberOfFaces(); ++i_face) { - Array array = weak_face_array[i_face]; - const size_t number = face_number[i_face]; - for (size_t i = 0; i < array.size(); ++i) { - array[i] = number + (parallel::rank() + 1) * i; - } - } - - FaceArray<const size_t> face_array{weak_face_array}; - - REQUIRE(face_array.connectivity_ptr() == weak_face_array.connectivity_ptr()); - - { // before synchronization - auto face_owner = connectivity.faceOwner(); - auto face_is_owned = connectivity.faceIsOwned(); + SECTION("edge") + { + WeakEdgeArray<size_t> weak_edge_array{connectivity, 4}; + auto edge_number = connectivity.edgeNumber(); - bool is_synchronized = (parallel::size() > 1); - bool is_valid = true; - for (FaceId i_face = 0; i_face < mesh_1d.numberOfFaces(); ++i_face) { - Array array = face_array[i_face]; - const size_t number = face_number[i_face]; - const size_t owner = face_owner[i_face]; - if (face_is_owned[i_face]) { + for (EdgeId i_edge = 0; i_edge < mesh_1d->numberOfEdges(); ++i_edge) { + Array array = weak_edge_array[i_edge]; + const size_t number = edge_number[i_edge]; for (size_t i = 0; i < array.size(); ++i) { - is_valid &= (array[i] == number + (owner + 1) * i); - } - } else { - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + array[i] = number + (parallel::rank() + 1) * i; } } - } - - REQUIRE(is_valid); - REQUIRE(not is_synchronized); - } - - synchronize(weak_face_array); - { // after synchronization - auto face_owner = connectivity.faceOwner(); + EdgeArray<const size_t> edge_array{weak_edge_array}; + + REQUIRE(edge_array.connectivity_ptr() == weak_edge_array.connectivity_ptr()); + + { // before synchronization + auto edge_owner = connectivity.edgeOwner(); + auto edge_is_owned = connectivity.edgeIsOwned(); + + bool is_synchronized = (parallel::size() > 1); + bool is_valid = true; + for (EdgeId i_edge = 0; i_edge < mesh_1d->numberOfEdges(); ++i_edge) { + Array array = edge_array[i_edge]; + const size_t number = edge_number[i_edge]; + const size_t owner = edge_owner[i_edge]; + if (edge_is_owned[i_edge]) { + for (size_t i = 0; i < array.size(); ++i) { + is_valid &= (array[i] == number + (owner + 1) * i); + } + } else { + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } + } - bool is_synchronized = true; - for (FaceId i_face = 0; i_face < mesh_1d.numberOfFaces(); ++i_face) { - Array array = face_array[i_face]; - const size_t number = face_number[i_face]; - const size_t owner = face_owner[i_face]; - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + REQUIRE(is_valid); + REQUIRE(not is_synchronized); } - } - - REQUIRE(is_synchronized); - } - } - - SECTION("cell") - { - WeakCellArray<size_t> weak_cell_array{connectivity, 4}; - auto cell_number = connectivity.cellNumber(); - for (CellId i_cell = 0; i_cell < mesh_1d.numberOfCells(); ++i_cell) { - Array array = weak_cell_array[i_cell]; - const size_t number = cell_number[i_cell]; - for (size_t i = 0; i < array.size(); ++i) { - array[i] = number + (parallel::rank() + 1) * i; - } - } - - CellArray<const size_t> cell_array{weak_cell_array}; - - REQUIRE(cell_array.connectivity_ptr() == weak_cell_array.connectivity_ptr()); + synchronize(weak_edge_array); - { // before synchronization - auto cell_owner = connectivity.cellOwner(); - auto cell_is_owned = connectivity.cellIsOwned(); + { // after synchronization + auto edge_owner = connectivity.edgeOwner(); - bool is_synchronized = (parallel::size() > 1); - bool is_valid = true; - for (CellId i_cell = 0; i_cell < mesh_1d.numberOfCells(); ++i_cell) { - Array array = cell_array[i_cell]; - const size_t number = cell_number[i_cell]; - const size_t owner = cell_owner[i_cell]; - if (cell_is_owned[i_cell]) { - for (size_t i = 0; i < array.size(); ++i) { - is_valid &= (array[i] == number + (owner + 1) * i); - } - } else { - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + bool is_synchronized = true; + for (EdgeId i_edge = 0; i_edge < mesh_1d->numberOfEdges(); ++i_edge) { + Array array = edge_array[i_edge]; + const size_t number = edge_number[i_edge]; + const size_t owner = edge_owner[i_edge]; + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } } - } - } - - REQUIRE(is_valid); - REQUIRE(not is_synchronized); - } - - synchronize(weak_cell_array); - - { // after synchronization - auto cell_owner = connectivity.cellOwner(); - bool is_synchronized = true; - for (CellId i_cell = 0; i_cell < mesh_1d.numberOfCells(); ++i_cell) { - Array array = cell_array[i_cell]; - const size_t number = cell_number[i_cell]; - const size_t owner = cell_owner[i_cell]; - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + REQUIRE(is_synchronized); } } - REQUIRE(is_synchronized); - } - } - } - - SECTION("2D") - { - const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesian2DMesh(); - const Connectivity<2>& connectivity = mesh_2d.connectivity(); - - SECTION("node") - { - WeakNodeArray<size_t> weak_node_array{connectivity, 3}; - auto node_number = connectivity.nodeNumber(); - - for (NodeId i_node = 0; i_node < mesh_2d.numberOfNodes(); ++i_node) { - Array array = weak_node_array[i_node]; - const size_t number = node_number[i_node]; - for (size_t i = 0; i < array.size(); ++i) { - array[i] = number + (parallel::rank() + 1) * i; - } - } - - NodeArray<const size_t> node_array{weak_node_array}; + SECTION("face") + { + WeakFaceArray<size_t> weak_face_array{connectivity, 4}; + auto face_number = connectivity.faceNumber(); - REQUIRE(node_array.connectivity_ptr() == weak_node_array.connectivity_ptr()); - - { // before synchronization - auto node_owner = connectivity.nodeOwner(); - auto node_is_owned = connectivity.nodeIsOwned(); - - bool is_synchronized = (parallel::size() > 1); - bool is_valid = true; - for (NodeId i_node = 0; i_node < mesh_2d.numberOfNodes(); ++i_node) { - Array array = node_array[i_node]; - const size_t number = node_number[i_node]; - const size_t owner = node_owner[i_node]; - if (node_is_owned[i_node]) { + for (FaceId i_face = 0; i_face < mesh_1d->numberOfFaces(); ++i_face) { + Array array = weak_face_array[i_face]; + const size_t number = face_number[i_face]; for (size_t i = 0; i < array.size(); ++i) { - is_valid &= (array[i] == number + (owner + 1) * i); - } - } else { - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + array[i] = number + (parallel::rank() + 1) * i; } } - } - - REQUIRE(is_valid); - REQUIRE(not is_synchronized); - } - - synchronize(weak_node_array); - { // after synchronization - auto node_owner = connectivity.nodeOwner(); + FaceArray<const size_t> face_array{weak_face_array}; + + REQUIRE(face_array.connectivity_ptr() == weak_face_array.connectivity_ptr()); + + { // before synchronization + auto face_owner = connectivity.faceOwner(); + auto face_is_owned = connectivity.faceIsOwned(); + + bool is_synchronized = (parallel::size() > 1); + bool is_valid = true; + for (FaceId i_face = 0; i_face < mesh_1d->numberOfFaces(); ++i_face) { + Array array = face_array[i_face]; + const size_t number = face_number[i_face]; + const size_t owner = face_owner[i_face]; + if (face_is_owned[i_face]) { + for (size_t i = 0; i < array.size(); ++i) { + is_valid &= (array[i] == number + (owner + 1) * i); + } + } else { + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } + } - bool is_synchronized = true; - for (NodeId i_node = 0; i_node < mesh_2d.numberOfNodes(); ++i_node) { - Array array = node_array[i_node]; - const size_t number = node_number[i_node]; - const size_t owner = node_owner[i_node]; - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + REQUIRE(is_valid); + REQUIRE(not is_synchronized); } - } - - REQUIRE(is_synchronized); - } - } - - SECTION("edge") - { - WeakEdgeArray<size_t> weak_edge_array{connectivity, 3}; - auto edge_number = connectivity.edgeNumber(); - - for (EdgeId i_edge = 0; i_edge < mesh_2d.numberOfEdges(); ++i_edge) { - Array array = weak_edge_array[i_edge]; - const size_t number = edge_number[i_edge]; - for (size_t i = 0; i < array.size(); ++i) { - array[i] = number + (parallel::rank() + 1) * i; - } - } - - EdgeArray<const size_t> edge_array{weak_edge_array}; - REQUIRE(edge_array.connectivity_ptr() == weak_edge_array.connectivity_ptr()); + synchronize(weak_face_array); - { // before synchronization - auto edge_owner = connectivity.edgeOwner(); - auto edge_is_owned = connectivity.edgeIsOwned(); + { // after synchronization + auto face_owner = connectivity.faceOwner(); - bool is_synchronized = (parallel::size() > 1); - bool is_valid = true; - for (EdgeId i_edge = 0; i_edge < mesh_2d.numberOfEdges(); ++i_edge) { - Array array = edge_array[i_edge]; - const size_t number = edge_number[i_edge]; - const size_t owner = edge_owner[i_edge]; - if (edge_is_owned[i_edge]) { - for (size_t i = 0; i < array.size(); ++i) { - is_valid &= (array[i] == number + (owner + 1) * i); - } - } else { - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + bool is_synchronized = true; + for (FaceId i_face = 0; i_face < mesh_1d->numberOfFaces(); ++i_face) { + Array array = face_array[i_face]; + const size_t number = face_number[i_face]; + const size_t owner = face_owner[i_face]; + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } } - } - } - - REQUIRE(is_valid); - REQUIRE(not is_synchronized); - } - - synchronize(weak_edge_array); - - { // after synchronization - auto edge_owner = connectivity.edgeOwner(); - bool is_synchronized = true; - for (EdgeId i_edge = 0; i_edge < mesh_2d.numberOfEdges(); ++i_edge) { - Array array = edge_array[i_edge]; - const size_t number = edge_number[i_edge]; - const size_t owner = edge_owner[i_edge]; - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + REQUIRE(is_synchronized); } } - REQUIRE(is_synchronized); - } - } - - SECTION("face") - { - WeakFaceArray<size_t> weak_face_array{connectivity, 3}; - auto face_number = connectivity.faceNumber(); - - for (FaceId i_face = 0; i_face < mesh_2d.numberOfFaces(); ++i_face) { - Array array = weak_face_array[i_face]; - const size_t number = face_number[i_face]; - for (size_t i = 0; i < array.size(); ++i) { - array[i] = number + (parallel::rank() + 1) * i; - } - } - - FaceArray<const size_t> face_array{weak_face_array}; + SECTION("cell") + { + WeakCellArray<size_t> weak_cell_array{connectivity, 4}; + auto cell_number = connectivity.cellNumber(); - REQUIRE(face_array.connectivity_ptr() == weak_face_array.connectivity_ptr()); - - { // before synchronization - auto face_owner = connectivity.faceOwner(); - auto face_is_owned = connectivity.faceIsOwned(); - - bool is_synchronized = (parallel::size() > 1); - bool is_valid = true; - for (FaceId i_face = 0; i_face < mesh_2d.numberOfFaces(); ++i_face) { - Array array = face_array[i_face]; - const size_t number = face_number[i_face]; - const size_t owner = face_owner[i_face]; - if (face_is_owned[i_face]) { + for (CellId i_cell = 0; i_cell < mesh_1d->numberOfCells(); ++i_cell) { + Array array = weak_cell_array[i_cell]; + const size_t number = cell_number[i_cell]; for (size_t i = 0; i < array.size(); ++i) { - is_valid &= (array[i] == number + (owner + 1) * i); + array[i] = number + (parallel::rank() + 1) * i; } - } else { - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + } + + CellArray<const size_t> cell_array{weak_cell_array}; + + REQUIRE(cell_array.connectivity_ptr() == weak_cell_array.connectivity_ptr()); + + { // before synchronization + auto cell_owner = connectivity.cellOwner(); + auto cell_is_owned = connectivity.cellIsOwned(); + + bool is_synchronized = (parallel::size() > 1); + bool is_valid = true; + for (CellId i_cell = 0; i_cell < mesh_1d->numberOfCells(); ++i_cell) { + Array array = cell_array[i_cell]; + const size_t number = cell_number[i_cell]; + const size_t owner = cell_owner[i_cell]; + if (cell_is_owned[i_cell]) { + for (size_t i = 0; i < array.size(); ++i) { + is_valid &= (array[i] == number + (owner + 1) * i); + } + } else { + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } } + + REQUIRE(is_valid); + REQUIRE(not is_synchronized); } - } - REQUIRE(is_valid); - REQUIRE(not is_synchronized); - } + synchronize(weak_cell_array); - synchronize(weak_face_array); + { // after synchronization + auto cell_owner = connectivity.cellOwner(); - { // after synchronization - auto face_owner = connectivity.faceOwner(); + bool is_synchronized = true; + for (CellId i_cell = 0; i_cell < mesh_1d->numberOfCells(); ++i_cell) { + Array array = cell_array[i_cell]; + const size_t number = cell_number[i_cell]; + const size_t owner = cell_owner[i_cell]; + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } - bool is_synchronized = true; - for (FaceId i_face = 0; i_face < mesh_2d.numberOfFaces(); ++i_face) { - Array array = face_array[i_face]; - const size_t number = face_number[i_face]; - const size_t owner = face_owner[i_face]; - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + REQUIRE(is_synchronized); } } - - REQUIRE(is_synchronized); } } + } - SECTION("cell") - { - WeakCellArray<size_t> weak_cell_array{connectivity, 3}; - auto cell_number = connectivity.cellNumber(); - - for (CellId i_cell = 0; i_cell < mesh_2d.numberOfCells(); ++i_cell) { - Array array = weak_cell_array[i_cell]; - const size_t number = cell_number[i_cell]; - for (size_t i = 0; i < array.size(); ++i) { - array[i] = number + (parallel::rank() + 1) * i; - } - } - - CellArray<const size_t> cell_array{weak_cell_array}; - - REQUIRE(cell_array.connectivity_ptr() == weak_cell_array.connectivity_ptr()); - - { // before synchronization - auto cell_owner = connectivity.cellOwner(); - auto cell_is_owned = connectivity.cellIsOwned(); - - bool is_synchronized = (parallel::size() > 1); - bool is_valid = true; - for (CellId i_cell = 0; i_cell < mesh_2d.numberOfCells(); ++i_cell) { - Array array = cell_array[i_cell]; - const size_t number = cell_number[i_cell]; - const size_t owner = cell_owner[i_cell]; - if (cell_is_owned[i_cell]) { - for (size_t i = 0; i < array.size(); ++i) { - is_valid &= (array[i] == number + (owner + 1) * i); - } - } else { - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + SECTION("2D") + { + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); + + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) + { + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<2>& connectivity = mesh_2d->connectivity(); + + SECTION("node") + { + WeakNodeArray<size_t> weak_node_array{connectivity, 3}; + auto node_number = connectivity.nodeNumber(); + + for (NodeId i_node = 0; i_node < mesh_2d->numberOfNodes(); ++i_node) { + Array array = weak_node_array[i_node]; + const size_t number = node_number[i_node]; + for (size_t i = 0; i < array.size(); ++i) { + array[i] = number + (parallel::rank() + 1) * i; + } + } + + NodeArray<const size_t> node_array{weak_node_array}; + + REQUIRE(node_array.connectivity_ptr() == weak_node_array.connectivity_ptr()); + + { // before synchronization + auto node_owner = connectivity.nodeOwner(); + auto node_is_owned = connectivity.nodeIsOwned(); + + bool is_synchronized = (parallel::size() > 1); + bool is_valid = true; + for (NodeId i_node = 0; i_node < mesh_2d->numberOfNodes(); ++i_node) { + Array array = node_array[i_node]; + const size_t number = node_number[i_node]; + const size_t owner = node_owner[i_node]; + if (node_is_owned[i_node]) { + for (size_t i = 0; i < array.size(); ++i) { + is_valid &= (array[i] == number + (owner + 1) * i); + } + } else { + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } + } + + REQUIRE(is_valid); + REQUIRE(not is_synchronized); + } + + synchronize(weak_node_array); + + { // after synchronization + auto node_owner = connectivity.nodeOwner(); + + bool is_synchronized = true; + for (NodeId i_node = 0; i_node < mesh_2d->numberOfNodes(); ++i_node) { + Array array = node_array[i_node]; + const size_t number = node_number[i_node]; + const size_t owner = node_owner[i_node]; + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } + + REQUIRE(is_synchronized); + } } - } - } - - REQUIRE(is_valid); - REQUIRE(not is_synchronized); - } - synchronize(weak_cell_array); + SECTION("edge") + { + WeakEdgeArray<size_t> weak_edge_array{connectivity, 3}; + auto edge_number = connectivity.edgeNumber(); + + for (EdgeId i_edge = 0; i_edge < mesh_2d->numberOfEdges(); ++i_edge) { + Array array = weak_edge_array[i_edge]; + const size_t number = edge_number[i_edge]; + for (size_t i = 0; i < array.size(); ++i) { + array[i] = number + (parallel::rank() + 1) * i; + } + } + + EdgeArray<const size_t> edge_array{weak_edge_array}; + + REQUIRE(edge_array.connectivity_ptr() == weak_edge_array.connectivity_ptr()); + + { // before synchronization + auto edge_owner = connectivity.edgeOwner(); + auto edge_is_owned = connectivity.edgeIsOwned(); + + bool is_synchronized = (parallel::size() > 1); + bool is_valid = true; + for (EdgeId i_edge = 0; i_edge < mesh_2d->numberOfEdges(); ++i_edge) { + Array array = edge_array[i_edge]; + const size_t number = edge_number[i_edge]; + const size_t owner = edge_owner[i_edge]; + if (edge_is_owned[i_edge]) { + for (size_t i = 0; i < array.size(); ++i) { + is_valid &= (array[i] == number + (owner + 1) * i); + } + } else { + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } + } + + REQUIRE(is_valid); + REQUIRE(not is_synchronized); + } + + synchronize(weak_edge_array); + + { // after synchronization + auto edge_owner = connectivity.edgeOwner(); + + bool is_synchronized = true; + for (EdgeId i_edge = 0; i_edge < mesh_2d->numberOfEdges(); ++i_edge) { + Array array = edge_array[i_edge]; + const size_t number = edge_number[i_edge]; + const size_t owner = edge_owner[i_edge]; + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } + + REQUIRE(is_synchronized); + } + } - { // after synchronization - auto cell_owner = connectivity.cellOwner(); + SECTION("face") + { + WeakFaceArray<size_t> weak_face_array{connectivity, 3}; + auto face_number = connectivity.faceNumber(); + + for (FaceId i_face = 0; i_face < mesh_2d->numberOfFaces(); ++i_face) { + Array array = weak_face_array[i_face]; + const size_t number = face_number[i_face]; + for (size_t i = 0; i < array.size(); ++i) { + array[i] = number + (parallel::rank() + 1) * i; + } + } + + FaceArray<const size_t> face_array{weak_face_array}; + + REQUIRE(face_array.connectivity_ptr() == weak_face_array.connectivity_ptr()); + + { // before synchronization + auto face_owner = connectivity.faceOwner(); + auto face_is_owned = connectivity.faceIsOwned(); + + bool is_synchronized = (parallel::size() > 1); + bool is_valid = true; + for (FaceId i_face = 0; i_face < mesh_2d->numberOfFaces(); ++i_face) { + Array array = face_array[i_face]; + const size_t number = face_number[i_face]; + const size_t owner = face_owner[i_face]; + if (face_is_owned[i_face]) { + for (size_t i = 0; i < array.size(); ++i) { + is_valid &= (array[i] == number + (owner + 1) * i); + } + } else { + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } + } + + REQUIRE(is_valid); + REQUIRE(not is_synchronized); + } + + synchronize(weak_face_array); + + { // after synchronization + auto face_owner = connectivity.faceOwner(); + + bool is_synchronized = true; + for (FaceId i_face = 0; i_face < mesh_2d->numberOfFaces(); ++i_face) { + Array array = face_array[i_face]; + const size_t number = face_number[i_face]; + const size_t owner = face_owner[i_face]; + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } + + REQUIRE(is_synchronized); + } + } - bool is_synchronized = true; - for (CellId i_cell = 0; i_cell < mesh_2d.numberOfCells(); ++i_cell) { - Array array = cell_array[i_cell]; - const size_t number = cell_number[i_cell]; - const size_t owner = cell_owner[i_cell]; - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + SECTION("cell") + { + WeakCellArray<size_t> weak_cell_array{connectivity, 3}; + auto cell_number = connectivity.cellNumber(); + + for (CellId i_cell = 0; i_cell < mesh_2d->numberOfCells(); ++i_cell) { + Array array = weak_cell_array[i_cell]; + const size_t number = cell_number[i_cell]; + for (size_t i = 0; i < array.size(); ++i) { + array[i] = number + (parallel::rank() + 1) * i; + } + } + + CellArray<const size_t> cell_array{weak_cell_array}; + + REQUIRE(cell_array.connectivity_ptr() == weak_cell_array.connectivity_ptr()); + + { // before synchronization + auto cell_owner = connectivity.cellOwner(); + auto cell_is_owned = connectivity.cellIsOwned(); + + bool is_synchronized = (parallel::size() > 1); + bool is_valid = true; + for (CellId i_cell = 0; i_cell < mesh_2d->numberOfCells(); ++i_cell) { + Array array = cell_array[i_cell]; + const size_t number = cell_number[i_cell]; + const size_t owner = cell_owner[i_cell]; + if (cell_is_owned[i_cell]) { + for (size_t i = 0; i < array.size(); ++i) { + is_valid &= (array[i] == number + (owner + 1) * i); + } + } else { + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } + } + + REQUIRE(is_valid); + REQUIRE(not is_synchronized); + } + + synchronize(weak_cell_array); + + { // after synchronization + auto cell_owner = connectivity.cellOwner(); + + bool is_synchronized = true; + for (CellId i_cell = 0; i_cell < mesh_2d->numberOfCells(); ++i_cell) { + Array array = cell_array[i_cell]; + const size_t number = cell_number[i_cell]; + const size_t owner = cell_owner[i_cell]; + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } + + REQUIRE(is_synchronized); + } + } } } - - REQUIRE(is_synchronized); } } } SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); - - SECTION("node") - { - WeakNodeArray<size_t> weak_node_array{connectivity, 4}; - auto node_number = connectivity.nodeNumber(); - - for (NodeId i_node = 0; i_node < mesh_3d.numberOfNodes(); ++i_node) { - Array array = weak_node_array[i_node]; - const size_t number = node_number[i_node]; - for (size_t i = 0; i < array.size(); ++i) { - array[i] = number + (parallel::rank() + 1) * i; - } - } + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - NodeArray<const size_t> node_array{weak_node_array}; + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<3>& connectivity = mesh_3d->connectivity(); - REQUIRE(node_array.connectivity_ptr() == weak_node_array.connectivity_ptr()); + SECTION("node") + { + WeakNodeArray<size_t> weak_node_array{connectivity, 4}; + auto node_number = connectivity.nodeNumber(); - { // before synchronization - auto node_owner = connectivity.nodeOwner(); - auto node_is_owned = connectivity.nodeIsOwned(); - - bool is_synchronized = (parallel::size() > 1); - bool is_valid = true; - for (NodeId i_node = 0; i_node < mesh_3d.numberOfNodes(); ++i_node) { - Array array = node_array[i_node]; - const size_t number = node_number[i_node]; - const size_t owner = node_owner[i_node]; - if (node_is_owned[i_node]) { - for (size_t i = 0; i < array.size(); ++i) { - is_valid &= (array[i] == number + (owner + 1) * i); - } - } else { + for (NodeId i_node = 0; i_node < mesh_3d->numberOfNodes(); ++i_node) { + Array array = weak_node_array[i_node]; + const size_t number = node_number[i_node]; for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + array[i] = number + (parallel::rank() + 1) * i; } } - } - - REQUIRE(is_valid); - REQUIRE(not is_synchronized); - } - synchronize(weak_node_array); - - { // after synchronization - auto node_owner = connectivity.nodeOwner(); + NodeArray<const size_t> node_array{weak_node_array}; + + REQUIRE(node_array.connectivity_ptr() == weak_node_array.connectivity_ptr()); + + { // before synchronization + auto node_owner = connectivity.nodeOwner(); + auto node_is_owned = connectivity.nodeIsOwned(); + + bool is_synchronized = (parallel::size() > 1); + bool is_valid = true; + for (NodeId i_node = 0; i_node < mesh_3d->numberOfNodes(); ++i_node) { + Array array = node_array[i_node]; + const size_t number = node_number[i_node]; + const size_t owner = node_owner[i_node]; + if (node_is_owned[i_node]) { + for (size_t i = 0; i < array.size(); ++i) { + is_valid &= (array[i] == number + (owner + 1) * i); + } + } else { + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } + } - bool is_synchronized = true; - for (NodeId i_node = 0; i_node < mesh_3d.numberOfNodes(); ++i_node) { - Array array = node_array[i_node]; - const size_t number = node_number[i_node]; - const size_t owner = node_owner[i_node]; - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + REQUIRE(is_valid); + REQUIRE(not is_synchronized); } - } - REQUIRE(is_synchronized); - } - } - - SECTION("edge") - { - WeakEdgeArray<size_t> weak_edge_array{connectivity, 4}; - auto edge_number = connectivity.edgeNumber(); + synchronize(weak_node_array); - for (EdgeId i_edge = 0; i_edge < mesh_3d.numberOfEdges(); ++i_edge) { - Array array = weak_edge_array[i_edge]; - const size_t number = edge_number[i_edge]; - for (size_t i = 0; i < array.size(); ++i) { - array[i] = number + (parallel::rank() + 1) * i; - } - } + { // after synchronization + auto node_owner = connectivity.nodeOwner(); - EdgeArray<const size_t> edge_array{weak_edge_array}; + bool is_synchronized = true; + for (NodeId i_node = 0; i_node < mesh_3d->numberOfNodes(); ++i_node) { + Array array = node_array[i_node]; + const size_t number = node_number[i_node]; + const size_t owner = node_owner[i_node]; + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } - REQUIRE(edge_array.connectivity_ptr() == weak_edge_array.connectivity_ptr()); + REQUIRE(is_synchronized); + } + } - { // before synchronization - auto edge_owner = connectivity.edgeOwner(); - auto edge_is_owned = connectivity.edgeIsOwned(); + SECTION("edge") + { + WeakEdgeArray<size_t> weak_edge_array{connectivity, 4}; + auto edge_number = connectivity.edgeNumber(); - bool is_synchronized = (parallel::size() > 1); - bool is_valid = true; - for (EdgeId i_edge = 0; i_edge < mesh_3d.numberOfEdges(); ++i_edge) { - Array array = edge_array[i_edge]; - const size_t number = edge_number[i_edge]; - const size_t owner = edge_owner[i_edge]; - if (edge_is_owned[i_edge]) { - for (size_t i = 0; i < array.size(); ++i) { - is_valid &= (array[i] == number + (owner + 1) * i); - } - } else { + for (EdgeId i_edge = 0; i_edge < mesh_3d->numberOfEdges(); ++i_edge) { + Array array = weak_edge_array[i_edge]; + const size_t number = edge_number[i_edge]; for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + array[i] = number + (parallel::rank() + 1) * i; } } - } - - REQUIRE(is_valid); - REQUIRE(not is_synchronized); - } - - synchronize(weak_edge_array); - { // after synchronization - auto edge_owner = connectivity.edgeOwner(); + EdgeArray<const size_t> edge_array{weak_edge_array}; + + REQUIRE(edge_array.connectivity_ptr() == weak_edge_array.connectivity_ptr()); + + { // before synchronization + auto edge_owner = connectivity.edgeOwner(); + auto edge_is_owned = connectivity.edgeIsOwned(); + + bool is_synchronized = (parallel::size() > 1); + bool is_valid = true; + for (EdgeId i_edge = 0; i_edge < mesh_3d->numberOfEdges(); ++i_edge) { + Array array = edge_array[i_edge]; + const size_t number = edge_number[i_edge]; + const size_t owner = edge_owner[i_edge]; + if (edge_is_owned[i_edge]) { + for (size_t i = 0; i < array.size(); ++i) { + is_valid &= (array[i] == number + (owner + 1) * i); + } + } else { + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } + } - bool is_synchronized = true; - for (EdgeId i_edge = 0; i_edge < mesh_3d.numberOfEdges(); ++i_edge) { - Array array = edge_array[i_edge]; - const size_t number = edge_number[i_edge]; - const size_t owner = edge_owner[i_edge]; - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + REQUIRE(is_valid); + REQUIRE(not is_synchronized); } - } - - REQUIRE(is_synchronized); - } - } - SECTION("face") - { - WeakFaceArray<size_t> weak_face_array{connectivity, 4}; - auto face_number = connectivity.faceNumber(); + synchronize(weak_edge_array); - for (FaceId i_face = 0; i_face < mesh_3d.numberOfFaces(); ++i_face) { - Array array = weak_face_array[i_face]; - const size_t number = face_number[i_face]; - for (size_t i = 0; i < array.size(); ++i) { - array[i] = number + (parallel::rank() + 1) * i; - } - } + { // after synchronization + auto edge_owner = connectivity.edgeOwner(); - FaceArray<const size_t> face_array{weak_face_array}; + bool is_synchronized = true; + for (EdgeId i_edge = 0; i_edge < mesh_3d->numberOfEdges(); ++i_edge) { + Array array = edge_array[i_edge]; + const size_t number = edge_number[i_edge]; + const size_t owner = edge_owner[i_edge]; + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } - REQUIRE(face_array.connectivity_ptr() == weak_face_array.connectivity_ptr()); + REQUIRE(is_synchronized); + } + } - { // before synchronization - auto face_owner = connectivity.faceOwner(); - auto face_is_owned = connectivity.faceIsOwned(); + SECTION("face") + { + WeakFaceArray<size_t> weak_face_array{connectivity, 4}; + auto face_number = connectivity.faceNumber(); - bool is_synchronized = (parallel::size() > 1); - bool is_valid = true; - for (FaceId i_face = 0; i_face < mesh_3d.numberOfFaces(); ++i_face) { - Array array = face_array[i_face]; - const size_t number = face_number[i_face]; - const size_t owner = face_owner[i_face]; - if (face_is_owned[i_face]) { + for (FaceId i_face = 0; i_face < mesh_3d->numberOfFaces(); ++i_face) { + Array array = weak_face_array[i_face]; + const size_t number = face_number[i_face]; for (size_t i = 0; i < array.size(); ++i) { - is_valid &= (array[i] == number + (owner + 1) * i); - } - } else { - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + array[i] = number + (parallel::rank() + 1) * i; } } - } - - REQUIRE(is_valid); - REQUIRE(not is_synchronized); - } - - synchronize(weak_face_array); - { // after synchronization - auto face_owner = connectivity.faceOwner(); + FaceArray<const size_t> face_array{weak_face_array}; + + REQUIRE(face_array.connectivity_ptr() == weak_face_array.connectivity_ptr()); + + { // before synchronization + auto face_owner = connectivity.faceOwner(); + auto face_is_owned = connectivity.faceIsOwned(); + + bool is_synchronized = (parallel::size() > 1); + bool is_valid = true; + for (FaceId i_face = 0; i_face < mesh_3d->numberOfFaces(); ++i_face) { + Array array = face_array[i_face]; + const size_t number = face_number[i_face]; + const size_t owner = face_owner[i_face]; + if (face_is_owned[i_face]) { + for (size_t i = 0; i < array.size(); ++i) { + is_valid &= (array[i] == number + (owner + 1) * i); + } + } else { + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } + } - bool is_synchronized = true; - for (FaceId i_face = 0; i_face < mesh_3d.numberOfFaces(); ++i_face) { - Array array = face_array[i_face]; - const size_t number = face_number[i_face]; - const size_t owner = face_owner[i_face]; - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + REQUIRE(is_valid); + REQUIRE(not is_synchronized); } - } - - REQUIRE(is_synchronized); - } - } - SECTION("cell") - { - WeakCellArray<size_t> weak_cell_array{connectivity, 4}; - auto cell_number = connectivity.cellNumber(); + synchronize(weak_face_array); - for (CellId i_cell = 0; i_cell < mesh_3d.numberOfCells(); ++i_cell) { - Array array = weak_cell_array[i_cell]; - const size_t number = cell_number[i_cell]; - for (size_t i = 0; i < array.size(); ++i) { - array[i] = number + (parallel::rank() + 1) * i; - } - } + { // after synchronization + auto face_owner = connectivity.faceOwner(); - CellArray<const size_t> cell_array{weak_cell_array}; + bool is_synchronized = true; + for (FaceId i_face = 0; i_face < mesh_3d->numberOfFaces(); ++i_face) { + Array array = face_array[i_face]; + const size_t number = face_number[i_face]; + const size_t owner = face_owner[i_face]; + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } - REQUIRE(cell_array.connectivity_ptr() == weak_cell_array.connectivity_ptr()); + REQUIRE(is_synchronized); + } + } - { // before synchronization - auto cell_owner = connectivity.cellOwner(); - auto cell_is_owned = connectivity.cellIsOwned(); + SECTION("cell") + { + WeakCellArray<size_t> weak_cell_array{connectivity, 4}; + auto cell_number = connectivity.cellNumber(); - bool is_synchronized = (parallel::size() > 1); - bool is_valid = true; - for (CellId i_cell = 0; i_cell < mesh_3d.numberOfCells(); ++i_cell) { - Array array = cell_array[i_cell]; - const size_t number = cell_number[i_cell]; - const size_t owner = cell_owner[i_cell]; - if (cell_is_owned[i_cell]) { + for (CellId i_cell = 0; i_cell < mesh_3d->numberOfCells(); ++i_cell) { + Array array = weak_cell_array[i_cell]; + const size_t number = cell_number[i_cell]; for (size_t i = 0; i < array.size(); ++i) { - is_valid &= (array[i] == number + (owner + 1) * i); + array[i] = number + (parallel::rank() + 1) * i; } - } else { - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + } + + CellArray<const size_t> cell_array{weak_cell_array}; + + REQUIRE(cell_array.connectivity_ptr() == weak_cell_array.connectivity_ptr()); + + { // before synchronization + auto cell_owner = connectivity.cellOwner(); + auto cell_is_owned = connectivity.cellIsOwned(); + + bool is_synchronized = (parallel::size() > 1); + bool is_valid = true; + for (CellId i_cell = 0; i_cell < mesh_3d->numberOfCells(); ++i_cell) { + Array array = cell_array[i_cell]; + const size_t number = cell_number[i_cell]; + const size_t owner = cell_owner[i_cell]; + if (cell_is_owned[i_cell]) { + for (size_t i = 0; i < array.size(); ++i) { + is_valid &= (array[i] == number + (owner + 1) * i); + } + } else { + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } } + + REQUIRE(is_valid); + REQUIRE(not is_synchronized); } - } - REQUIRE(is_valid); - REQUIRE(not is_synchronized); - } + synchronize(weak_cell_array); - synchronize(weak_cell_array); + { // after synchronization + auto cell_owner = connectivity.cellOwner(); - { // after synchronization - auto cell_owner = connectivity.cellOwner(); + bool is_synchronized = true; + for (CellId i_cell = 0; i_cell < mesh_3d->numberOfCells(); ++i_cell) { + Array array = cell_array[i_cell]; + const size_t number = cell_number[i_cell]; + const size_t owner = cell_owner[i_cell]; + for (size_t i = 0; i < array.size(); ++i) { + is_synchronized &= (array[i] == number + (owner + 1) * i); + } + } - bool is_synchronized = true; - for (CellId i_cell = 0; i_cell < mesh_3d.numberOfCells(); ++i_cell) { - Array array = cell_array[i_cell]; - const size_t number = cell_number[i_cell]; - const size_t owner = cell_owner[i_cell]; - for (size_t i = 0; i < array.size(); ++i) { - is_synchronized &= (array[i] == number + (owner + 1) * i); + REQUIRE(is_synchronized); } } - - REQUIRE(is_synchronized); } } } diff --git a/tests/test_ItemValue.cpp b/tests/test_ItemValue.cpp index cf0fe9f62eaa7f9816eab66e1859721ccc5d76be..a51f65f0b9c70af2b8d73554da8e52f8d2405926 100644 --- a/tests/test_ItemValue.cpp +++ b/tests/test_ItemValue.cpp @@ -26,119 +26,155 @@ TEST_CASE("ItemValue", "[mesh]") SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesian1DMesh(); - const Connectivity<1>& connectivity = mesh_1d.connectivity(); - - REQUIRE_NOTHROW(NodeValue<int>{connectivity}); - REQUIRE_NOTHROW(EdgeValue<int>{connectivity}); - REQUIRE_NOTHROW(FaceValue<int>{connectivity}); - REQUIRE_NOTHROW(CellValue<int>{connectivity}); - - REQUIRE(NodeValue<int>{connectivity}.isBuilt()); - REQUIRE(EdgeValue<int>{connectivity}.isBuilt()); - REQUIRE(FaceValue<int>{connectivity}.isBuilt()); - REQUIRE(CellValue<int>{connectivity}.isBuilt()); - - NodeValue<int> node_value{connectivity}; - EdgeValue<int> edge_value{connectivity}; - FaceValue<int> face_value{connectivity}; - CellValue<int> cell_value{connectivity}; - - REQUIRE(edge_value.numberOfItems() == node_value.numberOfItems()); - REQUIRE(face_value.numberOfItems() == node_value.numberOfItems()); - REQUIRE(cell_value.numberOfItems() + 1 == node_value.numberOfItems()); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); + + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<1>& connectivity = mesh_1d->connectivity(); + + REQUIRE_NOTHROW(NodeValue<int>{connectivity}); + REQUIRE_NOTHROW(EdgeValue<int>{connectivity}); + REQUIRE_NOTHROW(FaceValue<int>{connectivity}); + REQUIRE_NOTHROW(CellValue<int>{connectivity}); + + REQUIRE(NodeValue<int>{connectivity}.isBuilt()); + REQUIRE(EdgeValue<int>{connectivity}.isBuilt()); + REQUIRE(FaceValue<int>{connectivity}.isBuilt()); + REQUIRE(CellValue<int>{connectivity}.isBuilt()); + + NodeValue<int> node_value{connectivity}; + EdgeValue<int> edge_value{connectivity}; + FaceValue<int> face_value{connectivity}; + CellValue<int> cell_value{connectivity}; + + REQUIRE(edge_value.numberOfItems() == node_value.numberOfItems()); + REQUIRE(face_value.numberOfItems() == node_value.numberOfItems()); + REQUIRE(cell_value.numberOfItems() + 1 == node_value.numberOfItems()); + } + } } SECTION("2D") { - const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesian2DMesh(); - const Connectivity<2>& connectivity = mesh_2d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); + + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<2>& connectivity = mesh_2d->connectivity(); - REQUIRE_NOTHROW(NodeValue<int>{connectivity}); - REQUIRE_NOTHROW(EdgeValue<int>{connectivity}); - REQUIRE_NOTHROW(FaceValue<int>{connectivity}); - REQUIRE_NOTHROW(CellValue<int>{connectivity}); + REQUIRE_NOTHROW(NodeValue<int>{connectivity}); + REQUIRE_NOTHROW(EdgeValue<int>{connectivity}); + REQUIRE_NOTHROW(FaceValue<int>{connectivity}); + REQUIRE_NOTHROW(CellValue<int>{connectivity}); - REQUIRE(NodeValue<int>{connectivity}.isBuilt()); - REQUIRE(EdgeValue<int>{connectivity}.isBuilt()); - REQUIRE(FaceValue<int>{connectivity}.isBuilt()); - REQUIRE(CellValue<int>{connectivity}.isBuilt()); + REQUIRE(NodeValue<int>{connectivity}.isBuilt()); + REQUIRE(EdgeValue<int>{connectivity}.isBuilt()); + REQUIRE(FaceValue<int>{connectivity}.isBuilt()); + REQUIRE(CellValue<int>{connectivity}.isBuilt()); - EdgeValue<int> edge_value{connectivity}; - FaceValue<int> face_value{connectivity}; + EdgeValue<int> edge_value{connectivity}; + FaceValue<int> face_value{connectivity}; - REQUIRE(edge_value.numberOfItems() == face_value.numberOfItems()); + REQUIRE(edge_value.numberOfItems() == face_value.numberOfItems()); + } + } } SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); - - REQUIRE_NOTHROW(NodeValue<int>{connectivity}); - REQUIRE_NOTHROW(EdgeValue<int>{connectivity}); - REQUIRE_NOTHROW(FaceValue<int>{connectivity}); - REQUIRE_NOTHROW(CellValue<int>{connectivity}); - - REQUIRE(NodeValue<int>{connectivity}.isBuilt()); - REQUIRE(EdgeValue<int>{connectivity}.isBuilt()); - REQUIRE(FaceValue<int>{connectivity}.isBuilt()); - REQUIRE(CellValue<int>{connectivity}.isBuilt()); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); + + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<3>& connectivity = mesh_3d->connectivity(); + + REQUIRE_NOTHROW(NodeValue<int>{connectivity}); + REQUIRE_NOTHROW(EdgeValue<int>{connectivity}); + REQUIRE_NOTHROW(FaceValue<int>{connectivity}); + REQUIRE_NOTHROW(CellValue<int>{connectivity}); + + REQUIRE(NodeValue<int>{connectivity}.isBuilt()); + REQUIRE(EdgeValue<int>{connectivity}.isBuilt()); + REQUIRE(FaceValue<int>{connectivity}.isBuilt()); + REQUIRE(CellValue<int>{connectivity}.isBuilt()); + } + } } SECTION("set values from array") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - CellValue<size_t> cell_value{connectivity}; + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<3>& connectivity = mesh_3d->connectivity(); - Array<size_t> values{cell_value.numberOfItems()}; - for (size_t i = 0; i < values.size(); ++i) { - values[i] = i; - } + CellValue<size_t> cell_value{connectivity}; - cell_value = values; + Array<size_t> values{cell_value.numberOfItems()}; + for (size_t i = 0; i < values.size(); ++i) { + values[i] = i; + } - for (CellId i_cell = 0; i_cell < mesh_3d.numberOfCells(); ++i_cell) { - REQUIRE(cell_value[i_cell] == i_cell); + cell_value = values; + + for (CellId i_cell = 0; i_cell < mesh_3d->numberOfCells(); ++i_cell) { + REQUIRE(cell_value[i_cell] == i_cell); + } + } } } SECTION("copy") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - CellValue<int> cell_value{connectivity}; - cell_value.fill(parallel::rank()); + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<3>& connectivity = mesh_3d->connectivity(); - CellValue<const int> const_cell_value; - const_cell_value = copy(cell_value); + CellValue<int> cell_value{connectivity}; + cell_value.fill(parallel::rank()); - cell_value.fill(0); + CellValue<const int> const_cell_value; + const_cell_value = copy(cell_value); - for (CellId i_cell = 0; i_cell < mesh_3d.numberOfCells(); ++i_cell) { - REQUIRE(cell_value[i_cell] == 0); - } + cell_value.fill(0); - for (CellId i_cell = 0; i_cell < mesh_3d.numberOfCells(); ++i_cell) { - REQUIRE(const_cell_value[i_cell] == static_cast<std::int64_t>(parallel::rank())); + for (CellId i_cell = 0; i_cell < mesh_3d->numberOfCells(); ++i_cell) { + REQUIRE(cell_value[i_cell] == 0); + } + + for (CellId i_cell = 0; i_cell < mesh_3d->numberOfCells(); ++i_cell) { + REQUIRE(const_cell_value[i_cell] == static_cast<std::int64_t>(parallel::rank())); + } + } } } SECTION("WeakItemValue") { - const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesian2DMesh(); - const Connectivity<2>& connectivity = mesh_2d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); + + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<2>& connectivity = mesh_2d->connectivity(); - WeakFaceValue<int> weak_face_value{connectivity}; + WeakFaceValue<int> weak_face_value{connectivity}; - weak_face_value.fill(parallel::rank()); + weak_face_value.fill(parallel::rank()); - FaceValue<const int> face_value{weak_face_value}; + FaceValue<const int> face_value{weak_face_value}; - REQUIRE(face_value.connectivity_ptr() == weak_face_value.connectivity_ptr()); + REQUIRE(face_value.connectivity_ptr() == weak_face_value.connectivity_ptr()); + } + } } #ifndef NDEBUG @@ -161,48 +197,72 @@ TEST_CASE("ItemValue", "[mesh]") SECTION("checking for bounds violation") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); - - CellValue<int> cell_value{connectivity}; - CellId invalid_cell_id = connectivity.numberOfCells(); - REQUIRE_THROWS_AS(cell_value[invalid_cell_id], AssertError); - - FaceValue<int> face_value{connectivity}; - FaceId invalid_face_id = connectivity.numberOfFaces(); - REQUIRE_THROWS_AS(face_value[invalid_face_id], AssertError); - - EdgeValue<int> edge_value{connectivity}; - EdgeId invalid_edge_id = connectivity.numberOfEdges(); - REQUIRE_THROWS_AS(edge_value[invalid_edge_id], AssertError); - - NodeValue<int> node_value{connectivity}; - NodeId invalid_node_id = connectivity.numberOfNodes(); - REQUIRE_THROWS_AS(node_value[invalid_node_id], AssertError); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); + + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<3>& connectivity = mesh_3d->connectivity(); + + CellValue<int> cell_value{connectivity}; + CellId invalid_cell_id = connectivity.numberOfCells(); + REQUIRE_THROWS_AS(cell_value[invalid_cell_id], AssertError); + + FaceValue<int> face_value{connectivity}; + FaceId invalid_face_id = connectivity.numberOfFaces(); + REQUIRE_THROWS_AS(face_value[invalid_face_id], AssertError); + + EdgeValue<int> edge_value{connectivity}; + EdgeId invalid_edge_id = connectivity.numberOfEdges(); + REQUIRE_THROWS_AS(edge_value[invalid_edge_id], AssertError); + + NodeValue<int> node_value{connectivity}; + NodeId invalid_node_id = connectivity.numberOfNodes(); + REQUIRE_THROWS_AS(node_value[invalid_node_id], AssertError); + } + } } SECTION("set values from invalid array size") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); + + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<3>& connectivity = mesh_3d->connectivity(); - CellValue<size_t> cell_value{connectivity}; + CellValue<size_t> cell_value{connectivity}; - Array<size_t> values{3 + cell_value.numberOfItems()}; - REQUIRE_THROWS_AS(cell_value = values, AssertError); + Array<size_t> values{3 + cell_value.numberOfItems()}; + REQUIRE_THROWS_AS(cell_value = values, AssertError); + } + } } SECTION("invalid copy_to") { - const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesian2DMesh(); - const Connectivity<2>& connectivity_2d = mesh_2d.connectivity(); - - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity_3d = mesh_3d.connectivity(); - - CellValue<int> cell_2d_value{connectivity_2d}; - CellValue<int> cell_3d_value{connectivity_3d}; - REQUIRE_THROWS_AS(copy_to(cell_2d_value, cell_3d_value), AssertError); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); + + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<2>& connectivity_2d = mesh_2d->connectivity(); + + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); + + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<3>& connectivity_3d = mesh_3d->connectivity(); + + CellValue<int> cell_2d_value{connectivity_2d}; + CellValue<int> cell_3d_value{connectivity_3d}; + REQUIRE_THROWS_AS(copy_to(cell_2d_value, cell_3d_value), AssertError); + } + } + } + } } } #endif // NDEBUG diff --git a/tests/test_ItemValueUtils.cpp b/tests/test_ItemValueUtils.cpp index 5c02d764da7798d6a74092ef12889797fa881e63..b818aee299c51269d6b5710c884bfc6d202f135e 100644 --- a/tests/test_ItemValueUtils.cpp +++ b/tests/test_ItemValueUtils.cpp @@ -17,38 +17,44 @@ TEST_CASE("ItemValueUtils", "[mesh]") { SECTION("Synchronize") { - const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesian2DMesh(); - const Connectivity<2>& connectivity = mesh_2d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - WeakFaceValue<int> weak_face_value{connectivity}; + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<2>& connectivity = mesh_2d->connectivity(); - weak_face_value.fill(parallel::rank()); + WeakFaceValue<int> weak_face_value{connectivity}; - FaceValue<const int> face_value{weak_face_value}; + weak_face_value.fill(parallel::rank()); - REQUIRE(face_value.connectivity_ptr() == weak_face_value.connectivity_ptr()); + FaceValue<const int> face_value{weak_face_value}; - { // before synchronization - auto face_owner = connectivity.faceOwner(); - auto face_is_owned = connectivity.faceIsOwned(); + REQUIRE(face_value.connectivity_ptr() == weak_face_value.connectivity_ptr()); - for (FaceId i_face = 0; i_face < mesh_2d.numberOfFaces(); ++i_face) { - if (face_is_owned[i_face]) { - REQUIRE(face_owner[i_face] == face_value[i_face]); - } else { - REQUIRE(face_owner[i_face] != face_value[i_face]); + { // before synchronization + auto face_owner = connectivity.faceOwner(); + auto face_is_owned = connectivity.faceIsOwned(); + + for (FaceId i_face = 0; i_face < mesh_2d->numberOfFaces(); ++i_face) { + if (face_is_owned[i_face]) { + REQUIRE(face_owner[i_face] == face_value[i_face]); + } else { + REQUIRE(face_owner[i_face] != face_value[i_face]); + } + } } - } - } - synchronize(weak_face_value); + synchronize(weak_face_value); - { // after synchronization - auto face_owner = connectivity.faceOwner(); - auto face_is_owned = connectivity.faceIsOwned(); + { // after synchronization + auto face_owner = connectivity.faceOwner(); + auto face_is_owned = connectivity.faceIsOwned(); - for (FaceId i_face = 0; i_face < mesh_2d.numberOfFaces(); ++i_face) { - REQUIRE(face_owner[i_face] == face_value[i_face]); + for (FaceId i_face = 0; i_face < mesh_2d->numberOfFaces(); ++i_face) { + REQUIRE(face_owner[i_face] == face_value[i_face]); + } + } } } } @@ -57,59 +63,77 @@ TEST_CASE("ItemValueUtils", "[mesh]") { SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesian1DMesh(); - const Connectivity<1>& connectivity = mesh_1d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - CellValue<int> cell_value{connectivity}; - cell_value.fill(-1); + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<1>& connectivity = mesh_1d->connectivity(); - auto cell_is_owned = connectivity.cellIsOwned(); - parallel_for( - mesh_1d.numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - if (cell_is_owned[cell_id]) { - cell_value[cell_id] = 10 + parallel::rank(); - } - }); + CellValue<int> cell_value{connectivity}; + cell_value.fill(-1); + + auto cell_is_owned = connectivity.cellIsOwned(); + parallel_for( + mesh_1d->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + if (cell_is_owned[cell_id]) { + cell_value[cell_id] = 10 + parallel::rank(); + } + }); - REQUIRE(min(cell_value) == 10); + REQUIRE(min(cell_value) == 10); + } + } } SECTION("2D") { - const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesian2DMesh(); - const Connectivity<2>& connectivity = mesh_2d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - CellValue<int> cell_value{connectivity}; - cell_value.fill(-1); + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<2>& connectivity = mesh_2d->connectivity(); - auto cell_is_owned = connectivity.cellIsOwned(); - parallel_for( - mesh_2d.numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - if (cell_is_owned[cell_id]) { - cell_value[cell_id] = 10 + parallel::rank(); - } - }); + CellValue<int> cell_value{connectivity}; + cell_value.fill(-1); - REQUIRE(min(cell_value) == 10); + auto cell_is_owned = connectivity.cellIsOwned(); + parallel_for( + mesh_2d->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + if (cell_is_owned[cell_id]) { + cell_value[cell_id] = 10 + parallel::rank(); + } + }); + + REQUIRE(min(cell_value) == 10); + } + } } SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - CellValue<int> cell_value{connectivity}; - cell_value.fill(-1); + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<3>& connectivity = mesh_3d->connectivity(); - auto cell_is_owned = connectivity.cellIsOwned(); - parallel_for( - mesh_3d.numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - if (cell_is_owned[cell_id]) { - cell_value[cell_id] = 10 + parallel::rank(); - } - }); + CellValue<int> cell_value{connectivity}; + cell_value.fill(-1); + + auto cell_is_owned = connectivity.cellIsOwned(); + parallel_for( + mesh_3d->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + if (cell_is_owned[cell_id]) { + cell_value[cell_id] = 10 + parallel::rank(); + } + }); - REQUIRE(min(cell_value) == 10); + REQUIRE(min(cell_value) == 10); + } + } } } @@ -117,59 +141,77 @@ TEST_CASE("ItemValueUtils", "[mesh]") { SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesian1DMesh(); - const Connectivity<1>& connectivity = mesh_1d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - CellValue<size_t> cell_value{connectivity}; - cell_value.fill(std::numeric_limits<size_t>::max()); + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<1>& connectivity = mesh_1d->connectivity(); - auto cell_is_owned = connectivity.cellIsOwned(); - parallel_for( - mesh_1d.numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - if (cell_is_owned[cell_id]) { - cell_value[cell_id] = parallel::rank() + 1; - } - }); + CellValue<size_t> cell_value{connectivity}; + cell_value.fill(std::numeric_limits<size_t>::max()); - REQUIRE(max(cell_value) == parallel::size()); + auto cell_is_owned = connectivity.cellIsOwned(); + parallel_for( + mesh_1d->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + if (cell_is_owned[cell_id]) { + cell_value[cell_id] = parallel::rank() + 1; + } + }); + + REQUIRE(max(cell_value) == parallel::size()); + } + } } SECTION("2D") { - const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesian2DMesh(); - const Connectivity<2>& connectivity = mesh_2d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - CellValue<size_t> cell_value{connectivity}; - cell_value.fill(std::numeric_limits<size_t>::max()); + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<2>& connectivity = mesh_2d->connectivity(); - auto cell_is_owned = connectivity.cellIsOwned(); - parallel_for( - mesh_2d.numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - if (cell_is_owned[cell_id]) { - cell_value[cell_id] = parallel::rank() + 1; - } - }); + CellValue<size_t> cell_value{connectivity}; + cell_value.fill(std::numeric_limits<size_t>::max()); + + auto cell_is_owned = connectivity.cellIsOwned(); + parallel_for( + mesh_2d->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + if (cell_is_owned[cell_id]) { + cell_value[cell_id] = parallel::rank() + 1; + } + }); - REQUIRE(max(cell_value) == parallel::size()); + REQUIRE(max(cell_value) == parallel::size()); + } + } } SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - CellValue<size_t> cell_value{connectivity}; - cell_value.fill(std::numeric_limits<size_t>::max()); + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<3>& connectivity = mesh_3d->connectivity(); - auto cell_is_owned = connectivity.cellIsOwned(); - parallel_for( - mesh_3d.numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - if (cell_is_owned[cell_id]) { - cell_value[cell_id] = parallel::rank() + 1; - } - }); + CellValue<size_t> cell_value{connectivity}; + cell_value.fill(std::numeric_limits<size_t>::max()); - REQUIRE(max(cell_value) == parallel::size()); + auto cell_is_owned = connectivity.cellIsOwned(); + parallel_for( + mesh_3d->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + if (cell_is_owned[cell_id]) { + cell_value[cell_id] = parallel::rank() + 1; + } + }); + + REQUIRE(max(cell_value) == parallel::size()); + } + } } } @@ -177,65 +219,83 @@ TEST_CASE("ItemValueUtils", "[mesh]") { SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesian1DMesh(); - const Connectivity<1>& connectivity = mesh_1d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - CellValue<size_t> cell_value{connectivity}; - cell_value.fill(5); + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<1>& connectivity = mesh_1d->connectivity(); - auto cell_is_owned = connectivity.cellIsOwned(); + CellValue<size_t> cell_value{connectivity}; + cell_value.fill(5); - const size_t global_number_of_cells = [&] { - size_t number_of_cells = 0; - for (CellId cell_id = 0; cell_id < cell_is_owned.numberOfItems(); ++cell_id) { - number_of_cells += cell_is_owned[cell_id]; - } - return parallel::allReduceSum(number_of_cells); - }(); + auto cell_is_owned = connectivity.cellIsOwned(); + + const size_t global_number_of_cells = [&] { + size_t number_of_cells = 0; + for (CellId cell_id = 0; cell_id < cell_is_owned.numberOfItems(); ++cell_id) { + number_of_cells += cell_is_owned[cell_id]; + } + return parallel::allReduceSum(number_of_cells); + }(); - REQUIRE(sum(cell_value) == 5 * global_number_of_cells); + REQUIRE(sum(cell_value) == 5 * global_number_of_cells); + } + } } SECTION("2D") { - const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesian2DMesh(); - const Connectivity<2>& connectivity = mesh_2d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - FaceValue<size_t> face_value{connectivity}; - face_value.fill(2); + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<2>& connectivity = mesh_2d->connectivity(); - auto face_is_owned = connectivity.faceIsOwned(); + FaceValue<size_t> face_value{connectivity}; + face_value.fill(2); - const size_t global_number_of_faces = [&] { - size_t number_of_faces = 0; - for (FaceId face_id = 0; face_id < face_is_owned.numberOfItems(); ++face_id) { - number_of_faces += face_is_owned[face_id]; - } - return parallel::allReduceSum(number_of_faces); - }(); + auto face_is_owned = connectivity.faceIsOwned(); - REQUIRE(sum(face_value) == 2 * global_number_of_faces); + const size_t global_number_of_faces = [&] { + size_t number_of_faces = 0; + for (FaceId face_id = 0; face_id < face_is_owned.numberOfItems(); ++face_id) { + number_of_faces += face_is_owned[face_id]; + } + return parallel::allReduceSum(number_of_faces); + }(); + + REQUIRE(sum(face_value) == 2 * global_number_of_faces); + } + } } SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - NodeValue<size_t> node_value{connectivity}; - node_value.fill(3); + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<3>& connectivity = mesh_3d->connectivity(); - auto node_is_owned = connectivity.nodeIsOwned(); + NodeValue<size_t> node_value{connectivity}; + node_value.fill(3); - const size_t global_number_of_nodes = [&] { - size_t number_of_nodes = 0; - for (NodeId node_id = 0; node_id < node_is_owned.numberOfItems(); ++node_id) { - number_of_nodes += node_is_owned[node_id]; - } - return parallel::allReduceSum(number_of_nodes); - }(); + auto node_is_owned = connectivity.nodeIsOwned(); + + const size_t global_number_of_nodes = [&] { + size_t number_of_nodes = 0; + for (NodeId node_id = 0; node_id < node_is_owned.numberOfItems(); ++node_id) { + number_of_nodes += node_is_owned[node_id]; + } + return parallel::allReduceSum(number_of_nodes); + }(); - REQUIRE(sum(node_value) == 3 * global_number_of_nodes); + REQUIRE(sum(node_value) == 3 * global_number_of_nodes); + } + } } } } diff --git a/tests/test_SubItemArrayPerItem.cpp b/tests/test_SubItemArrayPerItem.cpp index 3caa8a5b957fd9f4a37f565d9826bee71b0d52a3..01b1b721913d57f80d51efeab2b5f74f62f13c38 100644 --- a/tests/test_SubItemArrayPerItem.cpp +++ b/tests/test_SubItemArrayPerItem.cpp @@ -64,457 +64,477 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesian1DMesh(); - const Connectivity<1>& connectivity = mesh_1d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - SECTION("per cell") - { - NodeArrayPerCell<int> node_array_per_cell{connectivity, 3}; - REQUIRE(node_array_per_cell.numberOfItems() == connectivity.numberOfCells()); - REQUIRE(node_array_per_cell.numberOfArrays() == number_of_arrays(node_array_per_cell)); - REQUIRE(node_array_per_cell.sizeOfArrays() == 3); - - auto cell_to_node_matrix = connectivity.cellToNodeMatrix(); - { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= - (cell_to_node_matrix[cell_id].size() == node_array_per_cell.numberOfSubArrays(cell_id)) and - (node_array_per_cell.itemTable(cell_id).numberOfRows() == node_array_per_cell.numberOfSubArrays(cell_id)); - } - REQUIRE(is_correct); - } - - const NodeArrayPerCell<const int> const_node_array_per_cell = node_array_per_cell; + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= (const_node_array_per_cell.itemTable(cell_id).numberOfRows() == - node_array_per_cell.numberOfSubArrays(cell_id)); - } - REQUIRE(is_correct); - } - - EdgeArrayPerCell<int> edge_array_per_cell{connectivity, 4}; - REQUIRE(edge_array_per_cell.numberOfItems() == connectivity.numberOfCells()); - REQUIRE(edge_array_per_cell.numberOfArrays() == number_of_arrays(edge_array_per_cell)); - REQUIRE(edge_array_per_cell.sizeOfArrays() == 4); + const Connectivity<1>& connectivity = mesh_1d->connectivity(); + + SECTION("per cell") + { + NodeArrayPerCell<int> node_array_per_cell{connectivity, 3}; + REQUIRE(node_array_per_cell.numberOfItems() == connectivity.numberOfCells()); + REQUIRE(node_array_per_cell.numberOfArrays() == number_of_arrays(node_array_per_cell)); + REQUIRE(node_array_per_cell.sizeOfArrays() == 3); + + auto cell_to_node_matrix = connectivity.cellToNodeMatrix(); + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= + (cell_to_node_matrix[cell_id].size() == node_array_per_cell.numberOfSubArrays(cell_id)) and + (node_array_per_cell.itemTable(cell_id).numberOfRows() == + node_array_per_cell.numberOfSubArrays(cell_id)); + } + REQUIRE(is_correct); + } - auto cell_to_edge_matrix = connectivity.cellToEdgeMatrix(); - { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= (cell_to_edge_matrix[cell_id].size() == edge_array_per_cell.numberOfSubArrays(cell_id)); - } - REQUIRE(is_correct); - } + const NodeArrayPerCell<const int> const_node_array_per_cell = node_array_per_cell; + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= (const_node_array_per_cell.itemTable(cell_id).numberOfRows() == + node_array_per_cell.numberOfSubArrays(cell_id)); + } + REQUIRE(is_correct); + } - FaceArrayPerCell<int> face_array_per_cell{connectivity, 2}; - REQUIRE(face_array_per_cell.numberOfItems() == connectivity.numberOfCells()); - REQUIRE(face_array_per_cell.numberOfArrays() == number_of_arrays(face_array_per_cell)); - REQUIRE(face_array_per_cell.sizeOfArrays() == 2); + EdgeArrayPerCell<int> edge_array_per_cell{connectivity, 4}; + REQUIRE(edge_array_per_cell.numberOfItems() == connectivity.numberOfCells()); + REQUIRE(edge_array_per_cell.numberOfArrays() == number_of_arrays(edge_array_per_cell)); + REQUIRE(edge_array_per_cell.sizeOfArrays() == 4); + + auto cell_to_edge_matrix = connectivity.cellToEdgeMatrix(); + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= (cell_to_edge_matrix[cell_id].size() == edge_array_per_cell.numberOfSubArrays(cell_id)); + } + REQUIRE(is_correct); + } - auto cell_to_face_matrix = connectivity.cellToFaceMatrix(); - { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= (cell_to_face_matrix[cell_id].size() == face_array_per_cell.numberOfSubArrays(cell_id)); + FaceArrayPerCell<int> face_array_per_cell{connectivity, 2}; + REQUIRE(face_array_per_cell.numberOfItems() == connectivity.numberOfCells()); + REQUIRE(face_array_per_cell.numberOfArrays() == number_of_arrays(face_array_per_cell)); + REQUIRE(face_array_per_cell.sizeOfArrays() == 2); + + auto cell_to_face_matrix = connectivity.cellToFaceMatrix(); + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= (cell_to_face_matrix[cell_id].size() == face_array_per_cell.numberOfSubArrays(cell_id)); + } + REQUIRE(is_correct); + } } - REQUIRE(is_correct); - } - } - SECTION("per face") - { - CellArrayPerFace<int> cell_array_per_face{connectivity, 2}; - REQUIRE(cell_array_per_face.numberOfItems() == connectivity.numberOfFaces()); - REQUIRE(cell_array_per_face.numberOfArrays() == number_of_arrays(cell_array_per_face)); - REQUIRE(cell_array_per_face.sizeOfArrays() == 2); - - auto face_to_cell_matrix = connectivity.faceToCellMatrix(); - { - bool is_correct = true; - for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { - is_correct &= (face_to_cell_matrix[face_id].size() == cell_array_per_face.numberOfSubArrays(face_id)); + SECTION("per face") + { + CellArrayPerFace<int> cell_array_per_face{connectivity, 2}; + REQUIRE(cell_array_per_face.numberOfItems() == connectivity.numberOfFaces()); + REQUIRE(cell_array_per_face.numberOfArrays() == number_of_arrays(cell_array_per_face)); + REQUIRE(cell_array_per_face.sizeOfArrays() == 2); + + auto face_to_cell_matrix = connectivity.faceToCellMatrix(); + { + bool is_correct = true; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + is_correct &= (face_to_cell_matrix[face_id].size() == cell_array_per_face.numberOfSubArrays(face_id)); + } + REQUIRE(is_correct); + } } - REQUIRE(is_correct); - } - } - - SECTION("per edge") - { - CellArrayPerEdge<int> cell_array_per_edge{connectivity, 3}; - REQUIRE(cell_array_per_edge.numberOfItems() == connectivity.numberOfEdges()); - REQUIRE(cell_array_per_edge.numberOfArrays() == number_of_arrays(cell_array_per_edge)); - REQUIRE(cell_array_per_edge.sizeOfArrays() == 3); - auto edge_to_cell_matrix = connectivity.edgeToCellMatrix(); - { - bool is_correct = true; - for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { - is_correct &= (edge_to_cell_matrix[edge_id].size() == cell_array_per_edge.numberOfSubArrays(edge_id)); + SECTION("per edge") + { + CellArrayPerEdge<int> cell_array_per_edge{connectivity, 3}; + REQUIRE(cell_array_per_edge.numberOfItems() == connectivity.numberOfEdges()); + REQUIRE(cell_array_per_edge.numberOfArrays() == number_of_arrays(cell_array_per_edge)); + REQUIRE(cell_array_per_edge.sizeOfArrays() == 3); + + auto edge_to_cell_matrix = connectivity.edgeToCellMatrix(); + { + bool is_correct = true; + for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { + is_correct &= (edge_to_cell_matrix[edge_id].size() == cell_array_per_edge.numberOfSubArrays(edge_id)); + } + REQUIRE(is_correct); + } } - REQUIRE(is_correct); - } - } - - SECTION("per node") - { - CellArrayPerNode<int> cell_array_per_node{connectivity, 4}; - REQUIRE(cell_array_per_node.numberOfItems() == connectivity.numberOfNodes()); - REQUIRE(cell_array_per_node.numberOfArrays() == number_of_arrays(cell_array_per_node)); - REQUIRE(cell_array_per_node.sizeOfArrays() == 4); - auto node_to_cell_matrix = connectivity.nodeToCellMatrix(); - { - bool is_correct = true; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - is_correct &= (node_to_cell_matrix[node_id].size() == cell_array_per_node.numberOfSubArrays(node_id)); + SECTION("per node") + { + CellArrayPerNode<int> cell_array_per_node{connectivity, 4}; + REQUIRE(cell_array_per_node.numberOfItems() == connectivity.numberOfNodes()); + REQUIRE(cell_array_per_node.numberOfArrays() == number_of_arrays(cell_array_per_node)); + REQUIRE(cell_array_per_node.sizeOfArrays() == 4); + + auto node_to_cell_matrix = connectivity.nodeToCellMatrix(); + { + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + is_correct &= (node_to_cell_matrix[node_id].size() == cell_array_per_node.numberOfSubArrays(node_id)); + } + REQUIRE(is_correct); + } } - REQUIRE(is_correct); } } } SECTION("2D") { - const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesian2DMesh(); - const Connectivity<2>& connectivity = mesh_2d.connectivity(); - - SECTION("per cell") - { - NodeArrayPerCell<int> node_array_per_cell{connectivity, 5}; - REQUIRE(node_array_per_cell.numberOfItems() == connectivity.numberOfCells()); - REQUIRE(node_array_per_cell.numberOfArrays() == number_of_arrays(node_array_per_cell)); - REQUIRE(node_array_per_cell.sizeOfArrays() == 5); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - auto cell_to_node_matrix = connectivity.cellToNodeMatrix(); + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= (cell_to_node_matrix[cell_id].size() == node_array_per_cell.numberOfSubArrays(cell_id)); - } - REQUIRE(is_correct); - } - - EdgeArrayPerCell<int> edge_array_per_cell{connectivity, 4}; - REQUIRE(edge_array_per_cell.numberOfItems() == connectivity.numberOfCells()); - REQUIRE(edge_array_per_cell.numberOfArrays() == number_of_arrays(edge_array_per_cell)); - REQUIRE(edge_array_per_cell.sizeOfArrays() == 4); - - auto cell_to_edge_matrix = connectivity.cellToEdgeMatrix(); - { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= (cell_to_edge_matrix[cell_id].size() == edge_array_per_cell.numberOfSubArrays(cell_id)); - } - REQUIRE(is_correct); - } - - FaceArrayPerCell<int> face_array_per_cell{connectivity, 3}; - REQUIRE(face_array_per_cell.numberOfItems() == connectivity.numberOfCells()); - REQUIRE(face_array_per_cell.numberOfArrays() == number_of_arrays(face_array_per_cell)); - REQUIRE(face_array_per_cell.sizeOfArrays() == 3); - - auto cell_to_face_matrix = connectivity.cellToFaceMatrix(); - { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= (cell_to_face_matrix[cell_id].size() == face_array_per_cell.numberOfSubArrays(cell_id)); - } - REQUIRE(is_correct); - } - } - - SECTION("per face") - { - CellArrayPerFace<int> cell_array_per_face{connectivity, 3}; - REQUIRE(cell_array_per_face.numberOfItems() == connectivity.numberOfFaces()); - REQUIRE(cell_array_per_face.numberOfArrays() == number_of_arrays(cell_array_per_face)); - REQUIRE(cell_array_per_face.sizeOfArrays() == 3); - - auto face_to_cell_matrix = connectivity.faceToCellMatrix(); - { - bool is_correct = true; - for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { - is_correct &= (face_to_cell_matrix[face_id].size() == cell_array_per_face.numberOfSubArrays(face_id)); - } - REQUIRE(is_correct); - } - - NodeArrayPerFace<int> node_array_per_face{connectivity, 2}; - REQUIRE(node_array_per_face.numberOfItems() == connectivity.numberOfFaces()); - REQUIRE(node_array_per_face.numberOfArrays() == number_of_arrays(node_array_per_face)); - REQUIRE(node_array_per_face.sizeOfArrays() == 2); - - auto face_to_node_matrix = connectivity.faceToNodeMatrix(); - { - bool is_correct = true; - for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { - is_correct &= (face_to_node_matrix[face_id].size() == node_array_per_face.numberOfSubArrays(face_id)); - } - REQUIRE(is_correct); - } - } + const Connectivity<2>& connectivity = mesh_2d->connectivity(); + + SECTION("per cell") + { + NodeArrayPerCell<int> node_array_per_cell{connectivity, 5}; + REQUIRE(node_array_per_cell.numberOfItems() == connectivity.numberOfCells()); + REQUIRE(node_array_per_cell.numberOfArrays() == number_of_arrays(node_array_per_cell)); + REQUIRE(node_array_per_cell.sizeOfArrays() == 5); + + auto cell_to_node_matrix = connectivity.cellToNodeMatrix(); + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= (cell_to_node_matrix[cell_id].size() == node_array_per_cell.numberOfSubArrays(cell_id)); + } + REQUIRE(is_correct); + } - SECTION("per edge") - { - CellArrayPerEdge<int> cell_array_per_edge{connectivity, 3}; - REQUIRE(cell_array_per_edge.numberOfItems() == connectivity.numberOfEdges()); - REQUIRE(cell_array_per_edge.numberOfArrays() == number_of_arrays(cell_array_per_edge)); - REQUIRE(cell_array_per_edge.sizeOfArrays() == 3); + EdgeArrayPerCell<int> edge_array_per_cell{connectivity, 4}; + REQUIRE(edge_array_per_cell.numberOfItems() == connectivity.numberOfCells()); + REQUIRE(edge_array_per_cell.numberOfArrays() == number_of_arrays(edge_array_per_cell)); + REQUIRE(edge_array_per_cell.sizeOfArrays() == 4); + + auto cell_to_edge_matrix = connectivity.cellToEdgeMatrix(); + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= (cell_to_edge_matrix[cell_id].size() == edge_array_per_cell.numberOfSubArrays(cell_id)); + } + REQUIRE(is_correct); + } - auto edge_to_cell_matrix = connectivity.edgeToCellMatrix(); - { - bool is_correct = true; - for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { - is_correct &= (edge_to_cell_matrix[edge_id].size() == cell_array_per_edge.numberOfSubArrays(edge_id)); + FaceArrayPerCell<int> face_array_per_cell{connectivity, 3}; + REQUIRE(face_array_per_cell.numberOfItems() == connectivity.numberOfCells()); + REQUIRE(face_array_per_cell.numberOfArrays() == number_of_arrays(face_array_per_cell)); + REQUIRE(face_array_per_cell.sizeOfArrays() == 3); + + auto cell_to_face_matrix = connectivity.cellToFaceMatrix(); + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= (cell_to_face_matrix[cell_id].size() == face_array_per_cell.numberOfSubArrays(cell_id)); + } + REQUIRE(is_correct); + } } - REQUIRE(is_correct); - } - NodeArrayPerEdge<int> node_array_per_edge{connectivity, 5}; - REQUIRE(node_array_per_edge.numberOfItems() == connectivity.numberOfEdges()); - REQUIRE(node_array_per_edge.numberOfArrays() == number_of_arrays(node_array_per_edge)); - REQUIRE(node_array_per_edge.sizeOfArrays() == 5); + SECTION("per face") + { + CellArrayPerFace<int> cell_array_per_face{connectivity, 3}; + REQUIRE(cell_array_per_face.numberOfItems() == connectivity.numberOfFaces()); + REQUIRE(cell_array_per_face.numberOfArrays() == number_of_arrays(cell_array_per_face)); + REQUIRE(cell_array_per_face.sizeOfArrays() == 3); + + auto face_to_cell_matrix = connectivity.faceToCellMatrix(); + { + bool is_correct = true; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + is_correct &= (face_to_cell_matrix[face_id].size() == cell_array_per_face.numberOfSubArrays(face_id)); + } + REQUIRE(is_correct); + } - auto edge_to_node_matrix = connectivity.edgeToNodeMatrix(); - { - bool is_correct = true; - for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { - is_correct &= (edge_to_node_matrix[edge_id].size() == node_array_per_edge.numberOfSubArrays(edge_id)); + NodeArrayPerFace<int> node_array_per_face{connectivity, 2}; + REQUIRE(node_array_per_face.numberOfItems() == connectivity.numberOfFaces()); + REQUIRE(node_array_per_face.numberOfArrays() == number_of_arrays(node_array_per_face)); + REQUIRE(node_array_per_face.sizeOfArrays() == 2); + + auto face_to_node_matrix = connectivity.faceToNodeMatrix(); + { + bool is_correct = true; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + is_correct &= (face_to_node_matrix[face_id].size() == node_array_per_face.numberOfSubArrays(face_id)); + } + REQUIRE(is_correct); + } } - REQUIRE(is_correct); - } - } - SECTION("per node") - { - EdgeArrayPerNode<int> edge_array_per_node{connectivity, 4}; - REQUIRE(edge_array_per_node.numberOfItems() == connectivity.numberOfNodes()); - REQUIRE(edge_array_per_node.numberOfArrays() == number_of_arrays(edge_array_per_node)); - REQUIRE(edge_array_per_node.sizeOfArrays() == 4); + SECTION("per edge") + { + CellArrayPerEdge<int> cell_array_per_edge{connectivity, 3}; + REQUIRE(cell_array_per_edge.numberOfItems() == connectivity.numberOfEdges()); + REQUIRE(cell_array_per_edge.numberOfArrays() == number_of_arrays(cell_array_per_edge)); + REQUIRE(cell_array_per_edge.sizeOfArrays() == 3); + + auto edge_to_cell_matrix = connectivity.edgeToCellMatrix(); + { + bool is_correct = true; + for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { + is_correct &= (edge_to_cell_matrix[edge_id].size() == cell_array_per_edge.numberOfSubArrays(edge_id)); + } + REQUIRE(is_correct); + } - auto node_to_edge_matrix = connectivity.nodeToEdgeMatrix(); - { - bool is_correct = true; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - is_correct &= (node_to_edge_matrix[node_id].size() == edge_array_per_node.numberOfSubArrays(node_id)); + NodeArrayPerEdge<int> node_array_per_edge{connectivity, 5}; + REQUIRE(node_array_per_edge.numberOfItems() == connectivity.numberOfEdges()); + REQUIRE(node_array_per_edge.numberOfArrays() == number_of_arrays(node_array_per_edge)); + REQUIRE(node_array_per_edge.sizeOfArrays() == 5); + + auto edge_to_node_matrix = connectivity.edgeToNodeMatrix(); + { + bool is_correct = true; + for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { + is_correct &= (edge_to_node_matrix[edge_id].size() == node_array_per_edge.numberOfSubArrays(edge_id)); + } + REQUIRE(is_correct); + } } - REQUIRE(is_correct); - } - - FaceArrayPerNode<int> face_array_per_node{connectivity, 3}; - REQUIRE(face_array_per_node.numberOfItems() == connectivity.numberOfNodes()); - REQUIRE(face_array_per_node.numberOfArrays() == number_of_arrays(face_array_per_node)); - REQUIRE(face_array_per_node.sizeOfArrays() == 3); - auto node_to_face_matrix = connectivity.nodeToFaceMatrix(); - { - bool is_correct = true; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - is_correct &= (node_to_face_matrix[node_id].size() == face_array_per_node.numberOfSubArrays(node_id)); - } - REQUIRE(is_correct); - } + SECTION("per node") + { + EdgeArrayPerNode<int> edge_array_per_node{connectivity, 4}; + REQUIRE(edge_array_per_node.numberOfItems() == connectivity.numberOfNodes()); + REQUIRE(edge_array_per_node.numberOfArrays() == number_of_arrays(edge_array_per_node)); + REQUIRE(edge_array_per_node.sizeOfArrays() == 4); + + auto node_to_edge_matrix = connectivity.nodeToEdgeMatrix(); + { + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + is_correct &= (node_to_edge_matrix[node_id].size() == edge_array_per_node.numberOfSubArrays(node_id)); + } + REQUIRE(is_correct); + } - CellArrayPerNode<int> cell_array_per_node{connectivity, 2}; - REQUIRE(cell_array_per_node.numberOfItems() == connectivity.numberOfNodes()); - REQUIRE(cell_array_per_node.numberOfArrays() == number_of_arrays(cell_array_per_node)); - REQUIRE(cell_array_per_node.sizeOfArrays() == 2); + FaceArrayPerNode<int> face_array_per_node{connectivity, 3}; + REQUIRE(face_array_per_node.numberOfItems() == connectivity.numberOfNodes()); + REQUIRE(face_array_per_node.numberOfArrays() == number_of_arrays(face_array_per_node)); + REQUIRE(face_array_per_node.sizeOfArrays() == 3); + + auto node_to_face_matrix = connectivity.nodeToFaceMatrix(); + { + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + is_correct &= (node_to_face_matrix[node_id].size() == face_array_per_node.numberOfSubArrays(node_id)); + } + REQUIRE(is_correct); + } - auto node_to_cell_matrix = connectivity.nodeToCellMatrix(); - { - bool is_correct = true; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - is_correct &= (node_to_cell_matrix[node_id].size() == cell_array_per_node.numberOfSubArrays(node_id)); + CellArrayPerNode<int> cell_array_per_node{connectivity, 2}; + REQUIRE(cell_array_per_node.numberOfItems() == connectivity.numberOfNodes()); + REQUIRE(cell_array_per_node.numberOfArrays() == number_of_arrays(cell_array_per_node)); + REQUIRE(cell_array_per_node.sizeOfArrays() == 2); + + auto node_to_cell_matrix = connectivity.nodeToCellMatrix(); + { + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + is_correct &= (node_to_cell_matrix[node_id].size() == cell_array_per_node.numberOfSubArrays(node_id)); + } + REQUIRE(is_correct); + } } - REQUIRE(is_correct); } } } + SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); - - SECTION("per cell") - { - NodeArrayPerCell<int> node_array_per_cell{connectivity, 3}; - REQUIRE(node_array_per_cell.numberOfItems() == connectivity.numberOfCells()); - REQUIRE(node_array_per_cell.numberOfArrays() == number_of_arrays(node_array_per_cell)); - REQUIRE(node_array_per_cell.sizeOfArrays() == 3); - - auto cell_to_node_matrix = connectivity.cellToNodeMatrix(); - { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= (cell_to_node_matrix[cell_id].size() == node_array_per_cell.numberOfSubArrays(cell_id)); - } - REQUIRE(is_correct); - } - - EdgeArrayPerCell<int> edge_array_per_cell{connectivity, 4}; - REQUIRE(edge_array_per_cell.numberOfItems() == connectivity.numberOfCells()); - REQUIRE(edge_array_per_cell.numberOfArrays() == number_of_arrays(edge_array_per_cell)); - REQUIRE(edge_array_per_cell.sizeOfArrays() == 4); - - auto cell_to_edge_matrix = connectivity.cellToEdgeMatrix(); - { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= (cell_to_edge_matrix[cell_id].size() == edge_array_per_cell.numberOfSubArrays(cell_id)); - } - REQUIRE(is_correct); - } - - FaceArrayPerCell<int> face_array_per_cell{connectivity, 3}; - REQUIRE(face_array_per_cell.numberOfItems() == connectivity.numberOfCells()); - REQUIRE(face_array_per_cell.numberOfArrays() == number_of_arrays(face_array_per_cell)); - REQUIRE(face_array_per_cell.sizeOfArrays() == 3); - - auto cell_to_face_matrix = connectivity.cellToFaceMatrix(); - { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= (cell_to_face_matrix[cell_id].size() == face_array_per_cell.numberOfSubArrays(cell_id)); - } - REQUIRE(is_correct); - } - } - - SECTION("per face") - { - CellArrayPerFace<int> cell_array_per_face{connectivity, 5}; - REQUIRE(cell_array_per_face.numberOfItems() == connectivity.numberOfFaces()); - REQUIRE(cell_array_per_face.numberOfArrays() == number_of_arrays(cell_array_per_face)); - REQUIRE(cell_array_per_face.sizeOfArrays() == 5); - - auto face_to_cell_matrix = connectivity.faceToCellMatrix(); - { - bool is_correct = true; - for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { - is_correct &= (face_to_cell_matrix[face_id].size() == cell_array_per_face.numberOfSubArrays(face_id)); - } - REQUIRE(is_correct); - } - - EdgeArrayPerFace<int> edge_array_per_face{connectivity, 3}; - REQUIRE(edge_array_per_face.numberOfItems() == connectivity.numberOfFaces()); - REQUIRE(edge_array_per_face.numberOfArrays() == number_of_arrays(edge_array_per_face)); - REQUIRE(edge_array_per_face.sizeOfArrays() == 3); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - auto face_to_edge_matrix = connectivity.faceToEdgeMatrix(); + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) { - bool is_correct = true; - for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { - is_correct &= (face_to_edge_matrix[face_id].size() == edge_array_per_face.numberOfSubArrays(face_id)); - } - REQUIRE(is_correct); - } + const Connectivity<3>& connectivity = mesh_3d->connectivity(); + + SECTION("per cell") + { + NodeArrayPerCell<int> node_array_per_cell{connectivity, 3}; + REQUIRE(node_array_per_cell.numberOfItems() == connectivity.numberOfCells()); + REQUIRE(node_array_per_cell.numberOfArrays() == number_of_arrays(node_array_per_cell)); + REQUIRE(node_array_per_cell.sizeOfArrays() == 3); + + auto cell_to_node_matrix = connectivity.cellToNodeMatrix(); + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= (cell_to_node_matrix[cell_id].size() == node_array_per_cell.numberOfSubArrays(cell_id)); + } + REQUIRE(is_correct); + } - NodeArrayPerFace<int> node_array_per_face{connectivity, 2}; - REQUIRE(node_array_per_face.numberOfItems() == connectivity.numberOfFaces()); - REQUIRE(node_array_per_face.numberOfArrays() == number_of_arrays(node_array_per_face)); - REQUIRE(node_array_per_face.sizeOfArrays() == 2); + EdgeArrayPerCell<int> edge_array_per_cell{connectivity, 4}; + REQUIRE(edge_array_per_cell.numberOfItems() == connectivity.numberOfCells()); + REQUIRE(edge_array_per_cell.numberOfArrays() == number_of_arrays(edge_array_per_cell)); + REQUIRE(edge_array_per_cell.sizeOfArrays() == 4); + + auto cell_to_edge_matrix = connectivity.cellToEdgeMatrix(); + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= (cell_to_edge_matrix[cell_id].size() == edge_array_per_cell.numberOfSubArrays(cell_id)); + } + REQUIRE(is_correct); + } - auto face_to_node_matrix = connectivity.faceToNodeMatrix(); - { - bool is_correct = true; - for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { - is_correct &= (face_to_node_matrix[face_id].size() == node_array_per_face.numberOfSubArrays(face_id)); + FaceArrayPerCell<int> face_array_per_cell{connectivity, 3}; + REQUIRE(face_array_per_cell.numberOfItems() == connectivity.numberOfCells()); + REQUIRE(face_array_per_cell.numberOfArrays() == number_of_arrays(face_array_per_cell)); + REQUIRE(face_array_per_cell.sizeOfArrays() == 3); + + auto cell_to_face_matrix = connectivity.cellToFaceMatrix(); + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= (cell_to_face_matrix[cell_id].size() == face_array_per_cell.numberOfSubArrays(cell_id)); + } + REQUIRE(is_correct); + } } - REQUIRE(is_correct); - } - } - - SECTION("per edge") - { - CellArrayPerEdge<int> cell_array_per_edge{connectivity, 3}; - REQUIRE(cell_array_per_edge.numberOfItems() == connectivity.numberOfEdges()); - REQUIRE(cell_array_per_edge.numberOfArrays() == number_of_arrays(cell_array_per_edge)); - REQUIRE(cell_array_per_edge.sizeOfArrays() == 3); - auto edge_to_cell_matrix = connectivity.edgeToCellMatrix(); - { - bool is_correct = true; - for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { - is_correct &= (edge_to_cell_matrix[edge_id].size() == cell_array_per_edge.numberOfSubArrays(edge_id)); - } - REQUIRE(is_correct); - } + SECTION("per face") + { + CellArrayPerFace<int> cell_array_per_face{connectivity, 5}; + REQUIRE(cell_array_per_face.numberOfItems() == connectivity.numberOfFaces()); + REQUIRE(cell_array_per_face.numberOfArrays() == number_of_arrays(cell_array_per_face)); + REQUIRE(cell_array_per_face.sizeOfArrays() == 5); + + auto face_to_cell_matrix = connectivity.faceToCellMatrix(); + { + bool is_correct = true; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + is_correct &= (face_to_cell_matrix[face_id].size() == cell_array_per_face.numberOfSubArrays(face_id)); + } + REQUIRE(is_correct); + } - FaceArrayPerEdge<int> face_array_per_edge{connectivity, 5}; - REQUIRE(face_array_per_edge.numberOfItems() == connectivity.numberOfEdges()); - REQUIRE(face_array_per_edge.numberOfArrays() == number_of_arrays(face_array_per_edge)); - REQUIRE(face_array_per_edge.sizeOfArrays() == 5); + EdgeArrayPerFace<int> edge_array_per_face{connectivity, 3}; + REQUIRE(edge_array_per_face.numberOfItems() == connectivity.numberOfFaces()); + REQUIRE(edge_array_per_face.numberOfArrays() == number_of_arrays(edge_array_per_face)); + REQUIRE(edge_array_per_face.sizeOfArrays() == 3); + + auto face_to_edge_matrix = connectivity.faceToEdgeMatrix(); + { + bool is_correct = true; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + is_correct &= (face_to_edge_matrix[face_id].size() == edge_array_per_face.numberOfSubArrays(face_id)); + } + REQUIRE(is_correct); + } - auto edge_to_face_matrix = connectivity.edgeToFaceMatrix(); - { - bool is_correct = true; - for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { - is_correct &= (edge_to_face_matrix[edge_id].size() == face_array_per_edge.numberOfSubArrays(edge_id)); + NodeArrayPerFace<int> node_array_per_face{connectivity, 2}; + REQUIRE(node_array_per_face.numberOfItems() == connectivity.numberOfFaces()); + REQUIRE(node_array_per_face.numberOfArrays() == number_of_arrays(node_array_per_face)); + REQUIRE(node_array_per_face.sizeOfArrays() == 2); + + auto face_to_node_matrix = connectivity.faceToNodeMatrix(); + { + bool is_correct = true; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + is_correct &= (face_to_node_matrix[face_id].size() == node_array_per_face.numberOfSubArrays(face_id)); + } + REQUIRE(is_correct); + } } - REQUIRE(is_correct); - } - NodeArrayPerEdge<int> node_array_per_edge{connectivity, 3}; - REQUIRE(node_array_per_edge.numberOfItems() == connectivity.numberOfEdges()); - REQUIRE(node_array_per_edge.numberOfArrays() == number_of_arrays(node_array_per_edge)); - REQUIRE(node_array_per_edge.sizeOfArrays() == 3); - - auto edge_to_node_matrix = connectivity.edgeToNodeMatrix(); - { - bool is_correct = true; - for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { - is_correct &= (edge_to_node_matrix[edge_id].size() == node_array_per_edge.numberOfSubArrays(edge_id)); - } - REQUIRE(is_correct); - } - } + SECTION("per edge") + { + CellArrayPerEdge<int> cell_array_per_edge{connectivity, 3}; + REQUIRE(cell_array_per_edge.numberOfItems() == connectivity.numberOfEdges()); + REQUIRE(cell_array_per_edge.numberOfArrays() == number_of_arrays(cell_array_per_edge)); + REQUIRE(cell_array_per_edge.sizeOfArrays() == 3); + + auto edge_to_cell_matrix = connectivity.edgeToCellMatrix(); + { + bool is_correct = true; + for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { + is_correct &= (edge_to_cell_matrix[edge_id].size() == cell_array_per_edge.numberOfSubArrays(edge_id)); + } + REQUIRE(is_correct); + } - SECTION("per node") - { - EdgeArrayPerNode<int> edge_array_per_node{connectivity, 3}; - REQUIRE(edge_array_per_node.numberOfItems() == connectivity.numberOfNodes()); - REQUIRE(edge_array_per_node.numberOfArrays() == number_of_arrays(edge_array_per_node)); - REQUIRE(edge_array_per_node.sizeOfArrays() == 3); + FaceArrayPerEdge<int> face_array_per_edge{connectivity, 5}; + REQUIRE(face_array_per_edge.numberOfItems() == connectivity.numberOfEdges()); + REQUIRE(face_array_per_edge.numberOfArrays() == number_of_arrays(face_array_per_edge)); + REQUIRE(face_array_per_edge.sizeOfArrays() == 5); + + auto edge_to_face_matrix = connectivity.edgeToFaceMatrix(); + { + bool is_correct = true; + for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { + is_correct &= (edge_to_face_matrix[edge_id].size() == face_array_per_edge.numberOfSubArrays(edge_id)); + } + REQUIRE(is_correct); + } - auto node_to_edge_matrix = connectivity.nodeToEdgeMatrix(); - { - bool is_correct = true; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - is_correct &= (node_to_edge_matrix[node_id].size() == edge_array_per_node.numberOfSubArrays(node_id)); + NodeArrayPerEdge<int> node_array_per_edge{connectivity, 3}; + REQUIRE(node_array_per_edge.numberOfItems() == connectivity.numberOfEdges()); + REQUIRE(node_array_per_edge.numberOfArrays() == number_of_arrays(node_array_per_edge)); + REQUIRE(node_array_per_edge.sizeOfArrays() == 3); + + auto edge_to_node_matrix = connectivity.edgeToNodeMatrix(); + { + bool is_correct = true; + for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { + is_correct &= (edge_to_node_matrix[edge_id].size() == node_array_per_edge.numberOfSubArrays(edge_id)); + } + REQUIRE(is_correct); + } } - REQUIRE(is_correct); - } - - FaceArrayPerNode<int> face_array_per_node{connectivity, 4}; - REQUIRE(face_array_per_node.numberOfItems() == connectivity.numberOfNodes()); - REQUIRE(face_array_per_node.numberOfArrays() == number_of_arrays(face_array_per_node)); - REQUIRE(face_array_per_node.sizeOfArrays() == 4); - auto node_to_face_matrix = connectivity.nodeToFaceMatrix(); - { - bool is_correct = true; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - is_correct &= (node_to_face_matrix[node_id].size() == face_array_per_node.numberOfSubArrays(node_id)); - } - REQUIRE(is_correct); - } + SECTION("per node") + { + EdgeArrayPerNode<int> edge_array_per_node{connectivity, 3}; + REQUIRE(edge_array_per_node.numberOfItems() == connectivity.numberOfNodes()); + REQUIRE(edge_array_per_node.numberOfArrays() == number_of_arrays(edge_array_per_node)); + REQUIRE(edge_array_per_node.sizeOfArrays() == 3); + + auto node_to_edge_matrix = connectivity.nodeToEdgeMatrix(); + { + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + is_correct &= (node_to_edge_matrix[node_id].size() == edge_array_per_node.numberOfSubArrays(node_id)); + } + REQUIRE(is_correct); + } - CellArrayPerNode<int> cell_array_per_node{connectivity, 5}; - REQUIRE(cell_array_per_node.numberOfItems() == connectivity.numberOfNodes()); - REQUIRE(cell_array_per_node.numberOfArrays() == number_of_arrays(cell_array_per_node)); - REQUIRE(cell_array_per_node.sizeOfArrays() == 5); + FaceArrayPerNode<int> face_array_per_node{connectivity, 4}; + REQUIRE(face_array_per_node.numberOfItems() == connectivity.numberOfNodes()); + REQUIRE(face_array_per_node.numberOfArrays() == number_of_arrays(face_array_per_node)); + REQUIRE(face_array_per_node.sizeOfArrays() == 4); + + auto node_to_face_matrix = connectivity.nodeToFaceMatrix(); + { + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + is_correct &= (node_to_face_matrix[node_id].size() == face_array_per_node.numberOfSubArrays(node_id)); + } + REQUIRE(is_correct); + } - auto node_to_cell_matrix = connectivity.nodeToCellMatrix(); - { - bool is_correct = true; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - is_correct &= (node_to_cell_matrix[node_id].size() == cell_array_per_node.numberOfSubArrays(node_id)); + CellArrayPerNode<int> cell_array_per_node{connectivity, 5}; + REQUIRE(cell_array_per_node.numberOfItems() == connectivity.numberOfNodes()); + REQUIRE(cell_array_per_node.numberOfArrays() == number_of_arrays(cell_array_per_node)); + REQUIRE(cell_array_per_node.sizeOfArrays() == 5); + + auto node_to_cell_matrix = connectivity.nodeToCellMatrix(); + { + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + is_correct &= (node_to_cell_matrix[node_id].size() == cell_array_per_node.numberOfSubArrays(node_id)); + } + REQUIRE(is_correct); + } } - REQUIRE(is_correct); } } } @@ -524,325 +544,355 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") { SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesian1DMesh(); - const Connectivity<1>& connectivity = mesh_1d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - EdgeArrayPerCell<size_t> edge_arrays_per_cell{connectivity, 3}; - { - size_t array = 0; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - for (size_t i_edge = 0; i_edge < edge_arrays_per_cell.numberOfSubArrays(cell_id); ++i_edge) { - for (size_t i = 0; i < edge_arrays_per_cell(cell_id, i_edge).size(); ++i) { - edge_arrays_per_cell(cell_id, i_edge)[i] = array++; + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<1>& connectivity = mesh_1d->connectivity(); + + EdgeArrayPerCell<size_t> edge_arrays_per_cell{connectivity, 3}; + { + size_t array = 0; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + for (size_t i_edge = 0; i_edge < edge_arrays_per_cell.numberOfSubArrays(cell_id); ++i_edge) { + for (size_t i = 0; i < edge_arrays_per_cell(cell_id, i_edge).size(); ++i) { + edge_arrays_per_cell(cell_id, i_edge)[i] = array++; + } + } } } - } - } - { - bool is_same = true; - size_t k = 0; - for (size_t i = 0; i < edge_arrays_per_cell.numberOfArrays(); ++i) { - for (size_t j = 0; j < edge_arrays_per_cell.sizeOfArrays(); ++j, ++k) { - is_same &= (edge_arrays_per_cell[i][j] == k); + { + bool is_same = true; + size_t k = 0; + for (size_t i = 0; i < edge_arrays_per_cell.numberOfArrays(); ++i) { + for (size_t j = 0; j < edge_arrays_per_cell.sizeOfArrays(); ++j, ++k) { + is_same &= (edge_arrays_per_cell[i][j] == k); + } + } + REQUIRE(is_same); } - } - REQUIRE(is_same); - } - { - size_t k = 0; - for (size_t i = 0; i < edge_arrays_per_cell.numberOfArrays(); ++i) { - for (size_t j = 0; j < edge_arrays_per_cell.sizeOfArrays(); ++j, ++k) { - edge_arrays_per_cell[i][j] = k * k + 1; - } - } - } - { - bool is_same = true; - size_t i = 0; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - for (size_t i_edge = 0; i_edge < edge_arrays_per_cell.numberOfSubArrays(cell_id); ++i_edge) { - for (size_t l = 0; l < edge_arrays_per_cell(cell_id, i_edge).size(); ++l, ++i) { - is_same &= (edge_arrays_per_cell(cell_id, i_edge)[l] == i * i + 1); + { + size_t k = 0; + for (size_t i = 0; i < edge_arrays_per_cell.numberOfArrays(); ++i) { + for (size_t j = 0; j < edge_arrays_per_cell.sizeOfArrays(); ++j, ++k) { + edge_arrays_per_cell[i][j] = k * k + 1; + } } } - } - REQUIRE(is_same); - } - - const EdgeArrayPerCell<const size_t> const_edge_arrays_per_cell = edge_arrays_per_cell; - { - bool is_same = true; - size_t i = 0; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - const auto& cell_table = const_edge_arrays_per_cell.itemTable(cell_id); - for (size_t i_edge = 0; i_edge < cell_table.numberOfRows(); ++i_edge) { - const auto& array = cell_table[i_edge]; - for (size_t l = 0; l < array.size(); ++l, ++i) { - is_same &= (array[l] == i * i + 1); + { + bool is_same = true; + size_t i = 0; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + for (size_t i_edge = 0; i_edge < edge_arrays_per_cell.numberOfSubArrays(cell_id); ++i_edge) { + for (size_t l = 0; l < edge_arrays_per_cell(cell_id, i_edge).size(); ++l, ++i) { + is_same &= (edge_arrays_per_cell(cell_id, i_edge)[l] == i * i + 1); + } + } + } + REQUIRE(is_same); + } + + const EdgeArrayPerCell<const size_t> const_edge_arrays_per_cell = edge_arrays_per_cell; + { + bool is_same = true; + size_t i = 0; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + const auto& cell_table = const_edge_arrays_per_cell.itemTable(cell_id); + for (size_t i_edge = 0; i_edge < cell_table.numberOfRows(); ++i_edge) { + const auto& array = cell_table[i_edge]; + for (size_t l = 0; l < array.size(); ++l, ++i) { + is_same &= (array[l] == i * i + 1); + } + } } + REQUIRE(is_same); } } - REQUIRE(is_same); } } SECTION("2D") { - const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesian2DMesh(); - const Connectivity<2>& connectivity = mesh_2d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - CellArrayPerFace<size_t> cell_arrays_per_face{connectivity, 3}; - { - size_t array = 0; - for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { - for (size_t i_cell = 0; i_cell < cell_arrays_per_face.numberOfSubArrays(face_id); ++i_cell) { - for (size_t i = 0; i < cell_arrays_per_face(face_id, i_cell).size(); ++i) { - cell_arrays_per_face(face_id, i_cell)[i] = array++; + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<2>& connectivity = mesh_2d->connectivity(); + + CellArrayPerFace<size_t> cell_arrays_per_face{connectivity, 3}; + { + size_t array = 0; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + for (size_t i_cell = 0; i_cell < cell_arrays_per_face.numberOfSubArrays(face_id); ++i_cell) { + for (size_t i = 0; i < cell_arrays_per_face(face_id, i_cell).size(); ++i) { + cell_arrays_per_face(face_id, i_cell)[i] = array++; + } + } } } - } - } - { - bool is_same = true; - size_t k = 0; - for (size_t i = 0; i < cell_arrays_per_face.numberOfArrays(); ++i) { - for (size_t j = 0; j < cell_arrays_per_face.sizeOfArrays(); ++j, ++k) { - is_same &= (cell_arrays_per_face[i][j] == k); - } - } - REQUIRE(is_same); - } - { - size_t k = 0; - for (size_t i = 0; i < cell_arrays_per_face.numberOfArrays(); ++i) { - for (size_t j = 0; j < cell_arrays_per_face.sizeOfArrays(); ++j, ++k) { - cell_arrays_per_face[i][j] = 3 * k + 1; - } - } - } - { - bool is_same = true; - size_t i = 0; - for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { - for (size_t i_cell = 0; i_cell < cell_arrays_per_face.numberOfSubArrays(face_id); ++i_cell) { - for (size_t l = 0; l < cell_arrays_per_face(face_id, i_cell).size(); ++l, ++i) { - is_same &= (cell_arrays_per_face(face_id, i_cell)[l] == 3 * i + 1); + { + bool is_same = true; + size_t k = 0; + for (size_t i = 0; i < cell_arrays_per_face.numberOfArrays(); ++i) { + for (size_t j = 0; j < cell_arrays_per_face.sizeOfArrays(); ++j, ++k) { + is_same &= (cell_arrays_per_face[i][j] == k); + } + } + REQUIRE(is_same); + } + { + size_t k = 0; + for (size_t i = 0; i < cell_arrays_per_face.numberOfArrays(); ++i) { + for (size_t j = 0; j < cell_arrays_per_face.sizeOfArrays(); ++j, ++k) { + cell_arrays_per_face[i][j] = 3 * k + 1; + } } } - } - REQUIRE(is_same); - } - - const CellArrayPerFace<const size_t> const_cell_arrays_per_face = cell_arrays_per_face; - { - bool is_same = true; - size_t i = 0; - for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { - const auto& face_table = const_cell_arrays_per_face.itemTable(face_id); - for (size_t i_cell = 0; i_cell < face_table.numberOfRows(); ++i_cell) { - const auto& array = face_table[i_cell]; - for (size_t l = 0; l < array.size(); ++l, ++i) { - is_same &= (array[l] == 3 * i + 1); + { + bool is_same = true; + size_t i = 0; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + for (size_t i_cell = 0; i_cell < cell_arrays_per_face.numberOfSubArrays(face_id); ++i_cell) { + for (size_t l = 0; l < cell_arrays_per_face(face_id, i_cell).size(); ++l, ++i) { + is_same &= (cell_arrays_per_face(face_id, i_cell)[l] == 3 * i + 1); + } + } + } + REQUIRE(is_same); + } + + const CellArrayPerFace<const size_t> const_cell_arrays_per_face = cell_arrays_per_face; + { + bool is_same = true; + size_t i = 0; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + const auto& face_table = const_cell_arrays_per_face.itemTable(face_id); + for (size_t i_cell = 0; i_cell < face_table.numberOfRows(); ++i_cell) { + const auto& array = face_table[i_cell]; + for (size_t l = 0; l < array.size(); ++l, ++i) { + is_same &= (array[l] == 3 * i + 1); + } + } } + REQUIRE(is_same); } } - REQUIRE(is_same); } } SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - FaceArrayPerNode<size_t> face_arrays_per_node{connectivity, 3}; - { - size_t array = 0; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - for (size_t i_face = 0; i_face < face_arrays_per_node.numberOfSubArrays(node_id); ++i_face) { - for (size_t i = 0; i < face_arrays_per_node(node_id, i_face).size(); ++i) - face_arrays_per_node(node_id, i_face)[i] = array++; - } - } - } - { - bool is_same = true; - size_t k = 0; - for (size_t i = 0; i < face_arrays_per_node.numberOfArrays(); ++i) { - for (size_t j = 0; j < face_arrays_per_node.sizeOfArrays(); ++j, ++k) { - is_same &= (face_arrays_per_node[i][j] == k); + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<3>& connectivity = mesh_3d->connectivity(); + + FaceArrayPerNode<size_t> face_arrays_per_node{connectivity, 3}; + { + size_t array = 0; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + for (size_t i_face = 0; i_face < face_arrays_per_node.numberOfSubArrays(node_id); ++i_face) { + for (size_t i = 0; i < face_arrays_per_node(node_id, i_face).size(); ++i) + face_arrays_per_node(node_id, i_face)[i] = array++; + } + } } - REQUIRE(is_same); - } - } - { - size_t k = 0; - for (size_t i = 0; i < face_arrays_per_node.numberOfArrays(); ++i) { - for (size_t j = 0; j < face_arrays_per_node.sizeOfArrays(); ++j, ++k) { - face_arrays_per_node[i][j] = 3 + k * k; + { + bool is_same = true; + size_t k = 0; + for (size_t i = 0; i < face_arrays_per_node.numberOfArrays(); ++i) { + for (size_t j = 0; j < face_arrays_per_node.sizeOfArrays(); ++j, ++k) { + is_same &= (face_arrays_per_node[i][j] == k); + } + REQUIRE(is_same); + } } - } - } - { - bool is_same = true; - size_t i = 0; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - for (size_t i_face = 0; i_face < face_arrays_per_node.numberOfSubArrays(node_id); ++i_face) { - for (size_t l = 0; l < face_arrays_per_node(node_id, i_face).size(); ++l, ++i) { - is_same &= (face_arrays_per_node(node_id, i_face)[l] == 3 + i * i); + { + size_t k = 0; + for (size_t i = 0; i < face_arrays_per_node.numberOfArrays(); ++i) { + for (size_t j = 0; j < face_arrays_per_node.sizeOfArrays(); ++j, ++k) { + face_arrays_per_node[i][j] = 3 + k * k; + } } } - } - REQUIRE(is_same); - } - - const FaceArrayPerNode<const size_t> const_face_arrays_per_node = face_arrays_per_node; - { - bool is_same = true; - size_t i = 0; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - const auto& node_table = const_face_arrays_per_node.itemTable(node_id); - for (size_t i_face = 0; i_face < node_table.numberOfRows(); ++i_face) { - const auto& array = node_table[i_face]; - for (size_t l = 0; l < array.size(); ++l, ++i) { - is_same &= (array[l] == 3 + i * i); + { + bool is_same = true; + size_t i = 0; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + for (size_t i_face = 0; i_face < face_arrays_per_node.numberOfSubArrays(node_id); ++i_face) { + for (size_t l = 0; l < face_arrays_per_node(node_id, i_face).size(); ++l, ++i) { + is_same &= (face_arrays_per_node(node_id, i_face)[l] == 3 + i * i); + } + } } + REQUIRE(is_same); + } + + const FaceArrayPerNode<const size_t> const_face_arrays_per_node = face_arrays_per_node; + { + bool is_same = true; + size_t i = 0; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + const auto& node_table = const_face_arrays_per_node.itemTable(node_id); + for (size_t i_face = 0; i_face < node_table.numberOfRows(); ++i_face) { + const auto& array = node_table[i_face]; + for (size_t l = 0; l < array.size(); ++l, ++i) { + is_same &= (array[l] == 3 + i * i); + } + } + } + REQUIRE(is_same); } } - REQUIRE(is_same); } } } SECTION("copy") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - SECTION("classic") - { - NodeArrayPerCell<size_t> node_array_per_cell{connectivity, 3}; + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) { - size_t k = 0; - for (size_t i = 0; i < node_array_per_cell.numberOfArrays(); ++i) { - for (size_t j = 0; j < node_array_per_cell.sizeOfArrays(); ++j, ++k) { - node_array_per_cell[i][j] = k; + const Connectivity<3>& connectivity = mesh_3d->connectivity(); + + SECTION("classic") + { + NodeArrayPerCell<size_t> node_array_per_cell{connectivity, 3}; + { + size_t k = 0; + for (size_t i = 0; i < node_array_per_cell.numberOfArrays(); ++i) { + for (size_t j = 0; j < node_array_per_cell.sizeOfArrays(); ++j, ++k) { + node_array_per_cell[i][j] = k; + } + } } - } - } - NodeArrayPerCell<size_t> copy_node_array_per_cell = copy(node_array_per_cell); - { - bool is_same = true; - for (size_t i = 0; i < copy_node_array_per_cell.numberOfArrays(); ++i) { - for (size_t j = 0; j < node_array_per_cell.sizeOfArrays(); ++j) { - is_same &= (copy_node_array_per_cell[i][j] == node_array_per_cell[i][j]); + NodeArrayPerCell<size_t> copy_node_array_per_cell = copy(node_array_per_cell); + { + bool is_same = true; + for (size_t i = 0; i < copy_node_array_per_cell.numberOfArrays(); ++i) { + for (size_t j = 0; j < node_array_per_cell.sizeOfArrays(); ++j) { + is_same &= (copy_node_array_per_cell[i][j] == node_array_per_cell[i][j]); + } + } + + REQUIRE(is_same); } - } - REQUIRE(is_same); - } + { + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + auto cell_table = node_array_per_cell.itemTable(cell_id); + for (size_t i_node = 0; i_node < node_array_per_cell.numberOfSubArrays(cell_id); ++i_node) { + auto node_array = cell_table[i_node]; + for (size_t i = 0; i < node_array.size(); ++i) { + node_array[i] = cell_id + i_node + i; + } + } + } + } - { - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - auto cell_table = node_array_per_cell.itemTable(cell_id); - for (size_t i_node = 0; i_node < node_array_per_cell.numberOfSubArrays(cell_id); ++i_node) { - auto node_array = cell_table[i_node]; - for (size_t i = 0; i < node_array.size(); ++i) { - node_array[i] = cell_id + i_node + i; + { + bool is_same = true; + for (size_t i = 0; i < copy_node_array_per_cell.numberOfArrays(); ++i) { + for (size_t j = 0; j < copy_node_array_per_cell.sizeOfArrays(); ++j) { + is_same &= (copy_node_array_per_cell[i][j] == node_array_per_cell[i][j]); + } } + + REQUIRE(not is_same); } } - } - { - bool is_same = true; - for (size_t i = 0; i < copy_node_array_per_cell.numberOfArrays(); ++i) { - for (size_t j = 0; j < copy_node_array_per_cell.sizeOfArrays(); ++j) { - is_same &= (copy_node_array_per_cell[i][j] == node_array_per_cell[i][j]); + SECTION("from weak") + { + WeakNodeArrayPerCell<size_t> node_array_per_cell{connectivity, 3}; + { + size_t k = 0; + for (size_t i = 0; i < node_array_per_cell.numberOfArrays(); ++i) { + for (size_t j = 0; j < node_array_per_cell.sizeOfArrays(); ++j, ++k) { + node_array_per_cell[i][j] = k; + } + } } - } - REQUIRE(not is_same); - } - } + NodeArrayPerCell<size_t> copy_node_array_per_cell = copy(node_array_per_cell); + { + bool is_same = true; + for (size_t i = 0; i < copy_node_array_per_cell.numberOfArrays(); ++i) { + for (size_t j = 0; j < node_array_per_cell.sizeOfArrays(); ++j) { + is_same &= (copy_node_array_per_cell[i][j] == node_array_per_cell[i][j]); + } + } - SECTION("from weak") - { - WeakNodeArrayPerCell<size_t> node_array_per_cell{connectivity, 3}; - { - size_t k = 0; - for (size_t i = 0; i < node_array_per_cell.numberOfArrays(); ++i) { - for (size_t j = 0; j < node_array_per_cell.sizeOfArrays(); ++j, ++k) { - node_array_per_cell[i][j] = k; + REQUIRE(is_same); } - } - } - NodeArrayPerCell<size_t> copy_node_array_per_cell = copy(node_array_per_cell); - { - bool is_same = true; - for (size_t i = 0; i < copy_node_array_per_cell.numberOfArrays(); ++i) { - for (size_t j = 0; j < node_array_per_cell.sizeOfArrays(); ++j) { - is_same &= (copy_node_array_per_cell[i][j] == node_array_per_cell[i][j]); + { + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + auto cell_table = node_array_per_cell.itemTable(cell_id); + for (size_t i_node = 0; i_node < node_array_per_cell.numberOfSubArrays(cell_id); ++i_node) { + auto node_array = cell_table[i_node]; + for (size_t i = 0; i < node_array.size(); ++i) { + node_array[i] = cell_id + i_node + i; + } + } + } } - } - - REQUIRE(is_same); - } - { - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - auto cell_table = node_array_per_cell.itemTable(cell_id); - for (size_t i_node = 0; i_node < node_array_per_cell.numberOfSubArrays(cell_id); ++i_node) { - auto node_array = cell_table[i_node]; - for (size_t i = 0; i < node_array.size(); ++i) { - node_array[i] = cell_id + i_node + i; + { + bool is_same = true; + for (size_t i = 0; i < copy_node_array_per_cell.numberOfArrays(); ++i) { + for (size_t j = 0; j < node_array_per_cell.sizeOfArrays(); ++j) { + is_same &= (copy_node_array_per_cell[i][j] == node_array_per_cell[i][j]); + } } - } - } - } - { - bool is_same = true; - for (size_t i = 0; i < copy_node_array_per_cell.numberOfArrays(); ++i) { - for (size_t j = 0; j < node_array_per_cell.sizeOfArrays(); ++j) { - is_same &= (copy_node_array_per_cell[i][j] == node_array_per_cell[i][j]); + REQUIRE(not is_same); } } - - REQUIRE(not is_same); } } } SECTION("WeakSubItemArrayPerItem") { - const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesian2DMesh(); - const Connectivity<2>& connectivity = mesh_2d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - WeakFaceArrayPerCell<int> weak_face_array_per_cell{connectivity, 3}; - { - size_t k = 0; - for (size_t i = 0; i < weak_face_array_per_cell.numberOfArrays(); ++i) { - for (size_t j = 0; j < weak_face_array_per_cell.sizeOfArrays(); ++j, ++k) { - weak_face_array_per_cell[i][j] = k; + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<2>& connectivity = mesh_2d->connectivity(); + + WeakFaceArrayPerCell<int> weak_face_array_per_cell{connectivity, 3}; + { + size_t k = 0; + for (size_t i = 0; i < weak_face_array_per_cell.numberOfArrays(); ++i) { + for (size_t j = 0; j < weak_face_array_per_cell.sizeOfArrays(); ++j, ++k) { + weak_face_array_per_cell[i][j] = k; + } + } } - } - } - FaceArrayPerCell<const int> face_array_per_cell{weak_face_array_per_cell}; + FaceArrayPerCell<const int> face_array_per_cell{weak_face_array_per_cell}; - REQUIRE(face_array_per_cell.connectivity_ptr() == weak_face_array_per_cell.connectivity_ptr()); - REQUIRE(face_array_per_cell.sizeOfArrays() == weak_face_array_per_cell.sizeOfArrays()); + REQUIRE(face_array_per_cell.connectivity_ptr() == weak_face_array_per_cell.connectivity_ptr()); + REQUIRE(face_array_per_cell.sizeOfArrays() == weak_face_array_per_cell.sizeOfArrays()); - bool is_same = true; - for (size_t i = 0; i < weak_face_array_per_cell.numberOfArrays(); ++i) { - for (size_t j = 0; j < weak_face_array_per_cell.sizeOfArrays(); ++j) { - is_same &= (face_array_per_cell[i][j] == weak_face_array_per_cell[i][j]); + bool is_same = true; + for (size_t i = 0; i < weak_face_array_per_cell.numberOfArrays(); ++i) { + for (size_t j = 0; j < weak_face_array_per_cell.sizeOfArrays(); ++j) { + is_same &= (face_array_per_cell[i][j] == weak_face_array_per_cell[i][j]); + } + } + REQUIRE(is_same); } } - REQUIRE(is_same); } #ifndef NDEBUG @@ -889,71 +939,81 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") SECTION("checking for bounds violation") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); - - CellArrayPerFace<int> cell_array_per_face{connectivity, 3}; - { - FaceId invalid_face_id = connectivity.numberOfFaces(); - REQUIRE_THROWS_AS(cell_array_per_face(invalid_face_id, 0), AssertError); - } - if (connectivity.numberOfFaces() > 0) { - FaceId face_id = 0; - const auto& face_table = cell_array_per_face.itemTable(face_id); - REQUIRE_THROWS_AS(cell_array_per_face(face_id, face_table.numberOfRows()), AssertError); - REQUIRE_THROWS_AS(face_table[face_table.numberOfRows()], AssertError); - REQUIRE_THROWS_AS(cell_array_per_face.itemTable(face_id)[face_table.numberOfRows()], AssertError); - REQUIRE_THROWS_AS(cell_array_per_face.itemTable(face_id)[0][cell_array_per_face.sizeOfArrays()], AssertError); - REQUIRE_THROWS_AS(cell_array_per_face.itemTable(face_id)[0][cell_array_per_face.sizeOfArrays()] = 2, - AssertError); - } - - FaceArrayPerNode<int> face_array_per_node{connectivity, 5}; - { - NodeId invalid_node_id = connectivity.numberOfNodes(); - REQUIRE_THROWS_AS(face_array_per_node(invalid_node_id, 0), AssertError); - } - if (connectivity.numberOfNodes() > 0) { - NodeId node_id = 0; - const auto& node_table = face_array_per_node.itemTable(node_id); - REQUIRE_THROWS_AS(face_array_per_node(node_id, node_table.numberOfRows()), AssertError); - REQUIRE_THROWS_AS(node_table[node_table.numberOfRows()], AssertError); - REQUIRE_THROWS_AS(face_array_per_node.itemTable(node_id)[node_table.numberOfRows()], AssertError); - REQUIRE_THROWS_AS(face_array_per_node.itemTable(node_id)[0][face_array_per_node.sizeOfArrays()], AssertError); - REQUIRE_THROWS_AS(face_array_per_node.itemTable(node_id)[0][face_array_per_node.sizeOfArrays()] = 2, - AssertError); - } + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - EdgeArrayPerCell<int> edge_array_per_cell{connectivity, 3}; - { - CellId invalid_cell_id = connectivity.numberOfCells(); - REQUIRE_THROWS_AS(edge_array_per_cell(invalid_cell_id, 0), AssertError); - } - if (connectivity.numberOfCells() > 0) { - CellId cell_id = 0; - const auto& cell_table = edge_array_per_cell.itemTable(cell_id); - REQUIRE_THROWS_AS(edge_array_per_cell(cell_id, cell_table.numberOfRows()), AssertError); - REQUIRE_THROWS_AS(cell_table[cell_table.numberOfRows()], AssertError); - REQUIRE_THROWS_AS(edge_array_per_cell.itemTable(cell_id)[cell_table.numberOfRows()], AssertError); - REQUIRE_THROWS_AS(edge_array_per_cell.itemTable(cell_id)[0][edge_array_per_cell.sizeOfArrays()], AssertError); - REQUIRE_THROWS_AS(edge_array_per_cell.itemTable(cell_id)[0][edge_array_per_cell.sizeOfArrays()] == 2, - AssertError); - } - - NodeArrayPerEdge<int> node_array_per_edge{connectivity, 3}; - { - EdgeId invalid_edge_id = connectivity.numberOfEdges(); - REQUIRE_THROWS_AS(node_array_per_edge(invalid_edge_id, 0), AssertError); - } - if (connectivity.numberOfEdges() > 0) { - EdgeId edge_id = 0; - const auto& edge_table = node_array_per_edge.itemTable(edge_id); - REQUIRE_THROWS_AS(node_array_per_edge(edge_id, edge_table.numberOfRows()), AssertError); - REQUIRE_THROWS_AS(edge_table[edge_table.numberOfRows()], AssertError); - REQUIRE_THROWS_AS(node_array_per_edge.itemTable(edge_id)[edge_table.numberOfRows()], AssertError); - REQUIRE_THROWS_AS(node_array_per_edge.itemTable(edge_id)[0][node_array_per_edge.sizeOfArrays()], AssertError); - REQUIRE_THROWS_AS(node_array_per_edge.itemTable(edge_id)[0][node_array_per_edge.sizeOfArrays()] = 2, - AssertError); + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<3>& connectivity = mesh_3d->connectivity(); + + CellArrayPerFace<int> cell_array_per_face{connectivity, 3}; + { + FaceId invalid_face_id = connectivity.numberOfFaces(); + REQUIRE_THROWS_AS(cell_array_per_face(invalid_face_id, 0), AssertError); + } + if (connectivity.numberOfFaces() > 0) { + FaceId face_id = 0; + const auto& face_table = cell_array_per_face.itemTable(face_id); + REQUIRE_THROWS_AS(cell_array_per_face(face_id, face_table.numberOfRows()), AssertError); + REQUIRE_THROWS_AS(face_table[face_table.numberOfRows()], AssertError); + REQUIRE_THROWS_AS(cell_array_per_face.itemTable(face_id)[face_table.numberOfRows()], AssertError); + REQUIRE_THROWS_AS(cell_array_per_face.itemTable(face_id)[0][cell_array_per_face.sizeOfArrays()], + AssertError); + REQUIRE_THROWS_AS(cell_array_per_face.itemTable(face_id)[0][cell_array_per_face.sizeOfArrays()] = 2, + AssertError); + } + + FaceArrayPerNode<int> face_array_per_node{connectivity, 5}; + { + NodeId invalid_node_id = connectivity.numberOfNodes(); + REQUIRE_THROWS_AS(face_array_per_node(invalid_node_id, 0), AssertError); + } + if (connectivity.numberOfNodes() > 0) { + NodeId node_id = 0; + const auto& node_table = face_array_per_node.itemTable(node_id); + REQUIRE_THROWS_AS(face_array_per_node(node_id, node_table.numberOfRows()), AssertError); + REQUIRE_THROWS_AS(node_table[node_table.numberOfRows()], AssertError); + REQUIRE_THROWS_AS(face_array_per_node.itemTable(node_id)[node_table.numberOfRows()], AssertError); + REQUIRE_THROWS_AS(face_array_per_node.itemTable(node_id)[0][face_array_per_node.sizeOfArrays()], + AssertError); + REQUIRE_THROWS_AS(face_array_per_node.itemTable(node_id)[0][face_array_per_node.sizeOfArrays()] = 2, + AssertError); + } + + EdgeArrayPerCell<int> edge_array_per_cell{connectivity, 3}; + { + CellId invalid_cell_id = connectivity.numberOfCells(); + REQUIRE_THROWS_AS(edge_array_per_cell(invalid_cell_id, 0), AssertError); + } + if (connectivity.numberOfCells() > 0) { + CellId cell_id = 0; + const auto& cell_table = edge_array_per_cell.itemTable(cell_id); + REQUIRE_THROWS_AS(edge_array_per_cell(cell_id, cell_table.numberOfRows()), AssertError); + REQUIRE_THROWS_AS(cell_table[cell_table.numberOfRows()], AssertError); + REQUIRE_THROWS_AS(edge_array_per_cell.itemTable(cell_id)[cell_table.numberOfRows()], AssertError); + REQUIRE_THROWS_AS(edge_array_per_cell.itemTable(cell_id)[0][edge_array_per_cell.sizeOfArrays()], + AssertError); + REQUIRE_THROWS_AS(edge_array_per_cell.itemTable(cell_id)[0][edge_array_per_cell.sizeOfArrays()] == 2, + AssertError); + } + + NodeArrayPerEdge<int> node_array_per_edge{connectivity, 3}; + { + EdgeId invalid_edge_id = connectivity.numberOfEdges(); + REQUIRE_THROWS_AS(node_array_per_edge(invalid_edge_id, 0), AssertError); + } + if (connectivity.numberOfEdges() > 0) { + EdgeId edge_id = 0; + const auto& edge_table = node_array_per_edge.itemTable(edge_id); + REQUIRE_THROWS_AS(node_array_per_edge(edge_id, edge_table.numberOfRows()), AssertError); + REQUIRE_THROWS_AS(edge_table[edge_table.numberOfRows()], AssertError); + REQUIRE_THROWS_AS(node_array_per_edge.itemTable(edge_id)[edge_table.numberOfRows()], AssertError); + REQUIRE_THROWS_AS(node_array_per_edge.itemTable(edge_id)[0][node_array_per_edge.sizeOfArrays()], + AssertError); + REQUIRE_THROWS_AS(node_array_per_edge.itemTable(edge_id)[0][node_array_per_edge.sizeOfArrays()] = 2, + AssertError); + } + } } } } diff --git a/tests/test_SubItemValuePerItem.cpp b/tests/test_SubItemValuePerItem.cpp index 7521eb7c1c9e4c5cf6596cd0d3f4ea5abc4f071f..eeae28a821338687d0923669dc48817dc8e73060 100644 --- a/tests/test_SubItemValuePerItem.cpp +++ b/tests/test_SubItemValuePerItem.cpp @@ -64,660 +64,708 @@ TEST_CASE("SubItemValuePerItem", "[mesh]") SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesian1DMesh(); - const Connectivity<1>& connectivity = mesh_1d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - SECTION("per cell") - { - NodeValuePerCell<int> node_value_per_cell{connectivity}; - REQUIRE(node_value_per_cell.numberOfItems() == connectivity.numberOfCells()); - REQUIRE(node_value_per_cell.numberOfValues() == number_of_values(node_value_per_cell)); - - auto cell_to_node_matrix = connectivity.cellToNodeMatrix(); + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= - (cell_to_node_matrix[cell_id].size() == node_value_per_cell.numberOfSubValues(cell_id)) and - (node_value_per_cell.itemValues(cell_id).size() == node_value_per_cell.numberOfSubValues(cell_id)); + const Connectivity<1>& connectivity = mesh_1d->connectivity(); + + SECTION("per cell") + { + NodeValuePerCell<int> node_value_per_cell{connectivity}; + REQUIRE(node_value_per_cell.numberOfItems() == connectivity.numberOfCells()); + REQUIRE(node_value_per_cell.numberOfValues() == number_of_values(node_value_per_cell)); + + auto cell_to_node_matrix = connectivity.cellToNodeMatrix(); + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= + (cell_to_node_matrix[cell_id].size() == node_value_per_cell.numberOfSubValues(cell_id)) and + (node_value_per_cell.itemValues(cell_id).size() == node_value_per_cell.numberOfSubValues(cell_id)); + } + REQUIRE(is_correct); + } + + const NodeValuePerCell<const int> const_node_value_per_cell = node_value_per_cell; + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= (const_node_value_per_cell.itemValues(cell_id).size() == + node_value_per_cell.numberOfSubValues(cell_id)); + } + REQUIRE(is_correct); + } + + EdgeValuePerCell<int> edge_value_per_cell{connectivity}; + REQUIRE(edge_value_per_cell.numberOfItems() == connectivity.numberOfCells()); + REQUIRE(edge_value_per_cell.numberOfValues() == number_of_values(edge_value_per_cell)); + + auto cell_to_edge_matrix = connectivity.cellToEdgeMatrix(); + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= (cell_to_edge_matrix[cell_id].size() == edge_value_per_cell.numberOfSubValues(cell_id)); + } + REQUIRE(is_correct); + } + + FaceValuePerCell<int> face_value_per_cell{connectivity}; + REQUIRE(face_value_per_cell.numberOfItems() == connectivity.numberOfCells()); + REQUIRE(face_value_per_cell.numberOfValues() == number_of_values(face_value_per_cell)); + + auto cell_to_face_matrix = connectivity.cellToFaceMatrix(); + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= (cell_to_face_matrix[cell_id].size() == face_value_per_cell.numberOfSubValues(cell_id)); + } + REQUIRE(is_correct); + } + } + + SECTION("per face") + { + CellValuePerFace<int> cell_value_per_face{connectivity}; + REQUIRE(cell_value_per_face.numberOfItems() == connectivity.numberOfFaces()); + REQUIRE(cell_value_per_face.numberOfValues() == number_of_values(cell_value_per_face)); + + auto face_to_cell_matrix = connectivity.faceToCellMatrix(); + { + bool is_correct = true; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + is_correct &= (face_to_cell_matrix[face_id].size() == cell_value_per_face.numberOfSubValues(face_id)); + } + REQUIRE(is_correct); + } + } + + SECTION("per edge") + { + CellValuePerEdge<int> cell_value_per_edge{connectivity}; + REQUIRE(cell_value_per_edge.numberOfItems() == connectivity.numberOfEdges()); + REQUIRE(cell_value_per_edge.numberOfValues() == number_of_values(cell_value_per_edge)); + + auto edge_to_cell_matrix = connectivity.edgeToCellMatrix(); + { + bool is_correct = true; + for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { + is_correct &= (edge_to_cell_matrix[edge_id].size() == cell_value_per_edge.numberOfSubValues(edge_id)); + } + REQUIRE(is_correct); + } + } + + SECTION("per node") + { + CellValuePerNode<int> cell_value_per_node{connectivity}; + REQUIRE(cell_value_per_node.numberOfItems() == connectivity.numberOfNodes()); + REQUIRE(cell_value_per_node.numberOfValues() == number_of_values(cell_value_per_node)); + + auto node_to_cell_matrix = connectivity.nodeToCellMatrix(); + { + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + is_correct &= (node_to_cell_matrix[node_id].size() == cell_value_per_node.numberOfSubValues(node_id)); + } + REQUIRE(is_correct); + } } - REQUIRE(is_correct); - } - - const NodeValuePerCell<const int> const_node_value_per_cell = node_value_per_cell; - { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= - (const_node_value_per_cell.itemValues(cell_id).size() == node_value_per_cell.numberOfSubValues(cell_id)); - } - REQUIRE(is_correct); - } - - EdgeValuePerCell<int> edge_value_per_cell{connectivity}; - REQUIRE(edge_value_per_cell.numberOfItems() == connectivity.numberOfCells()); - REQUIRE(edge_value_per_cell.numberOfValues() == number_of_values(edge_value_per_cell)); - - auto cell_to_edge_matrix = connectivity.cellToEdgeMatrix(); - { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= (cell_to_edge_matrix[cell_id].size() == edge_value_per_cell.numberOfSubValues(cell_id)); - } - REQUIRE(is_correct); - } - - FaceValuePerCell<int> face_value_per_cell{connectivity}; - REQUIRE(face_value_per_cell.numberOfItems() == connectivity.numberOfCells()); - REQUIRE(face_value_per_cell.numberOfValues() == number_of_values(face_value_per_cell)); - - auto cell_to_face_matrix = connectivity.cellToFaceMatrix(); - { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= (cell_to_face_matrix[cell_id].size() == face_value_per_cell.numberOfSubValues(cell_id)); - } - REQUIRE(is_correct); - } - } - - SECTION("per face") - { - CellValuePerFace<int> cell_value_per_face{connectivity}; - REQUIRE(cell_value_per_face.numberOfItems() == connectivity.numberOfFaces()); - REQUIRE(cell_value_per_face.numberOfValues() == number_of_values(cell_value_per_face)); - - auto face_to_cell_matrix = connectivity.faceToCellMatrix(); - { - bool is_correct = true; - for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { - is_correct &= (face_to_cell_matrix[face_id].size() == cell_value_per_face.numberOfSubValues(face_id)); - } - REQUIRE(is_correct); } } + } - SECTION("per edge") - { - CellValuePerEdge<int> cell_value_per_edge{connectivity}; - REQUIRE(cell_value_per_edge.numberOfItems() == connectivity.numberOfEdges()); - REQUIRE(cell_value_per_edge.numberOfValues() == number_of_values(cell_value_per_edge)); + SECTION("2D") + { + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - auto edge_to_cell_matrix = connectivity.edgeToCellMatrix(); + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) { - bool is_correct = true; - for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { - is_correct &= (edge_to_cell_matrix[edge_id].size() == cell_value_per_edge.numberOfSubValues(edge_id)); + const Connectivity<2>& connectivity = mesh_2d->connectivity(); + + SECTION("per cell") + { + NodeValuePerCell<int> node_value_per_cell{connectivity}; + REQUIRE(node_value_per_cell.numberOfItems() == connectivity.numberOfCells()); + REQUIRE(node_value_per_cell.numberOfValues() == number_of_values(node_value_per_cell)); + + auto cell_to_node_matrix = connectivity.cellToNodeMatrix(); + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= (cell_to_node_matrix[cell_id].size() == node_value_per_cell.numberOfSubValues(cell_id)); + } + REQUIRE(is_correct); + } + + EdgeValuePerCell<int> edge_value_per_cell{connectivity}; + REQUIRE(edge_value_per_cell.numberOfItems() == connectivity.numberOfCells()); + REQUIRE(edge_value_per_cell.numberOfValues() == number_of_values(edge_value_per_cell)); + + auto cell_to_edge_matrix = connectivity.cellToEdgeMatrix(); + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= (cell_to_edge_matrix[cell_id].size() == edge_value_per_cell.numberOfSubValues(cell_id)); + } + REQUIRE(is_correct); + } + + FaceValuePerCell<int> face_value_per_cell{connectivity}; + REQUIRE(face_value_per_cell.numberOfItems() == connectivity.numberOfCells()); + REQUIRE(face_value_per_cell.numberOfValues() == number_of_values(face_value_per_cell)); + + auto cell_to_face_matrix = connectivity.cellToFaceMatrix(); + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= (cell_to_face_matrix[cell_id].size() == face_value_per_cell.numberOfSubValues(cell_id)); + } + REQUIRE(is_correct); + } + } + + SECTION("per face") + { + CellValuePerFace<int> cell_value_per_face{connectivity}; + REQUIRE(cell_value_per_face.numberOfItems() == connectivity.numberOfFaces()); + REQUIRE(cell_value_per_face.numberOfValues() == number_of_values(cell_value_per_face)); + + auto face_to_cell_matrix = connectivity.faceToCellMatrix(); + { + bool is_correct = true; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + is_correct &= (face_to_cell_matrix[face_id].size() == cell_value_per_face.numberOfSubValues(face_id)); + } + REQUIRE(is_correct); + } + + NodeValuePerFace<int> node_value_per_face{connectivity}; + REQUIRE(node_value_per_face.numberOfItems() == connectivity.numberOfFaces()); + REQUIRE(node_value_per_face.numberOfValues() == number_of_values(node_value_per_face)); + + auto face_to_node_matrix = connectivity.faceToNodeMatrix(); + { + bool is_correct = true; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + is_correct &= (face_to_node_matrix[face_id].size() == node_value_per_face.numberOfSubValues(face_id)); + } + REQUIRE(is_correct); + } + } + + SECTION("per edge") + { + CellValuePerEdge<int> cell_value_per_edge{connectivity}; + REQUIRE(cell_value_per_edge.numberOfItems() == connectivity.numberOfEdges()); + REQUIRE(cell_value_per_edge.numberOfValues() == number_of_values(cell_value_per_edge)); + + auto edge_to_cell_matrix = connectivity.edgeToCellMatrix(); + { + bool is_correct = true; + for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { + is_correct &= (edge_to_cell_matrix[edge_id].size() == cell_value_per_edge.numberOfSubValues(edge_id)); + } + REQUIRE(is_correct); + } + + NodeValuePerEdge<int> node_value_per_edge{connectivity}; + REQUIRE(node_value_per_edge.numberOfItems() == connectivity.numberOfEdges()); + REQUIRE(node_value_per_edge.numberOfValues() == number_of_values(node_value_per_edge)); + + auto edge_to_node_matrix = connectivity.edgeToNodeMatrix(); + { + bool is_correct = true; + for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { + is_correct &= (edge_to_node_matrix[edge_id].size() == node_value_per_edge.numberOfSubValues(edge_id)); + } + REQUIRE(is_correct); + } + } + + SECTION("per node") + { + EdgeValuePerNode<int> edge_value_per_node{connectivity}; + REQUIRE(edge_value_per_node.numberOfItems() == connectivity.numberOfNodes()); + REQUIRE(edge_value_per_node.numberOfValues() == number_of_values(edge_value_per_node)); + + auto node_to_edge_matrix = connectivity.nodeToEdgeMatrix(); + { + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + is_correct &= (node_to_edge_matrix[node_id].size() == edge_value_per_node.numberOfSubValues(node_id)); + } + REQUIRE(is_correct); + } + + FaceValuePerNode<int> face_value_per_node{connectivity}; + REQUIRE(face_value_per_node.numberOfItems() == connectivity.numberOfNodes()); + REQUIRE(face_value_per_node.numberOfValues() == number_of_values(face_value_per_node)); + + auto node_to_face_matrix = connectivity.nodeToFaceMatrix(); + { + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + is_correct &= (node_to_face_matrix[node_id].size() == face_value_per_node.numberOfSubValues(node_id)); + } + REQUIRE(is_correct); + } + + CellValuePerNode<int> cell_value_per_node{connectivity}; + REQUIRE(cell_value_per_node.numberOfItems() == connectivity.numberOfNodes()); + REQUIRE(cell_value_per_node.numberOfValues() == number_of_values(cell_value_per_node)); + + auto node_to_cell_matrix = connectivity.nodeToCellMatrix(); + { + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + is_correct &= (node_to_cell_matrix[node_id].size() == cell_value_per_node.numberOfSubValues(node_id)); + } + REQUIRE(is_correct); + } } - REQUIRE(is_correct); } } + } - SECTION("per node") - { - CellValuePerNode<int> cell_value_per_node{connectivity}; - REQUIRE(cell_value_per_node.numberOfItems() == connectivity.numberOfNodes()); - REQUIRE(cell_value_per_node.numberOfValues() == number_of_values(cell_value_per_node)); + SECTION("3D") + { + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - auto node_to_cell_matrix = connectivity.nodeToCellMatrix(); + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) { - bool is_correct = true; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - is_correct &= (node_to_cell_matrix[node_id].size() == cell_value_per_node.numberOfSubValues(node_id)); + const Connectivity<3>& connectivity = mesh_3d->connectivity(); + + SECTION("per cell") + { + NodeValuePerCell<int> node_value_per_cell{connectivity}; + REQUIRE(node_value_per_cell.numberOfItems() == connectivity.numberOfCells()); + REQUIRE(node_value_per_cell.numberOfValues() == number_of_values(node_value_per_cell)); + + auto cell_to_node_matrix = connectivity.cellToNodeMatrix(); + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= (cell_to_node_matrix[cell_id].size() == node_value_per_cell.numberOfSubValues(cell_id)); + } + REQUIRE(is_correct); + } + + EdgeValuePerCell<int> edge_value_per_cell{connectivity}; + REQUIRE(edge_value_per_cell.numberOfItems() == connectivity.numberOfCells()); + REQUIRE(edge_value_per_cell.numberOfValues() == number_of_values(edge_value_per_cell)); + + auto cell_to_edge_matrix = connectivity.cellToEdgeMatrix(); + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= (cell_to_edge_matrix[cell_id].size() == edge_value_per_cell.numberOfSubValues(cell_id)); + } + REQUIRE(is_correct); + } + + FaceValuePerCell<int> face_value_per_cell{connectivity}; + REQUIRE(face_value_per_cell.numberOfItems() == connectivity.numberOfCells()); + REQUIRE(face_value_per_cell.numberOfValues() == number_of_values(face_value_per_cell)); + + auto cell_to_face_matrix = connectivity.cellToFaceMatrix(); + { + bool is_correct = true; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + is_correct &= (cell_to_face_matrix[cell_id].size() == face_value_per_cell.numberOfSubValues(cell_id)); + } + REQUIRE(is_correct); + } + } + + SECTION("per face") + { + CellValuePerFace<int> cell_value_per_face{connectivity}; + REQUIRE(cell_value_per_face.numberOfItems() == connectivity.numberOfFaces()); + REQUIRE(cell_value_per_face.numberOfValues() == number_of_values(cell_value_per_face)); + + auto face_to_cell_matrix = connectivity.faceToCellMatrix(); + { + bool is_correct = true; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + is_correct &= (face_to_cell_matrix[face_id].size() == cell_value_per_face.numberOfSubValues(face_id)); + } + REQUIRE(is_correct); + } + + EdgeValuePerFace<int> edge_value_per_face{connectivity}; + REQUIRE(edge_value_per_face.numberOfItems() == connectivity.numberOfFaces()); + REQUIRE(edge_value_per_face.numberOfValues() == number_of_values(edge_value_per_face)); + + auto face_to_edge_matrix = connectivity.faceToEdgeMatrix(); + { + bool is_correct = true; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + is_correct &= (face_to_edge_matrix[face_id].size() == edge_value_per_face.numberOfSubValues(face_id)); + } + REQUIRE(is_correct); + } + + NodeValuePerFace<int> node_value_per_face{connectivity}; + REQUIRE(node_value_per_face.numberOfItems() == connectivity.numberOfFaces()); + REQUIRE(node_value_per_face.numberOfValues() == number_of_values(node_value_per_face)); + + auto face_to_node_matrix = connectivity.faceToNodeMatrix(); + { + bool is_correct = true; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + is_correct &= (face_to_node_matrix[face_id].size() == node_value_per_face.numberOfSubValues(face_id)); + } + REQUIRE(is_correct); + } + } + + SECTION("per edge") + { + CellValuePerEdge<int> cell_value_per_edge{connectivity}; + REQUIRE(cell_value_per_edge.numberOfItems() == connectivity.numberOfEdges()); + REQUIRE(cell_value_per_edge.numberOfValues() == number_of_values(cell_value_per_edge)); + + auto edge_to_cell_matrix = connectivity.edgeToCellMatrix(); + { + bool is_correct = true; + for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { + is_correct &= (edge_to_cell_matrix[edge_id].size() == cell_value_per_edge.numberOfSubValues(edge_id)); + } + REQUIRE(is_correct); + } + + FaceValuePerEdge<int> face_value_per_edge{connectivity}; + REQUIRE(face_value_per_edge.numberOfItems() == connectivity.numberOfEdges()); + REQUIRE(face_value_per_edge.numberOfValues() == number_of_values(face_value_per_edge)); + + auto edge_to_face_matrix = connectivity.edgeToFaceMatrix(); + { + bool is_correct = true; + for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { + is_correct &= (edge_to_face_matrix[edge_id].size() == face_value_per_edge.numberOfSubValues(edge_id)); + } + REQUIRE(is_correct); + } + + NodeValuePerEdge<int> node_value_per_edge{connectivity}; + REQUIRE(node_value_per_edge.numberOfItems() == connectivity.numberOfEdges()); + REQUIRE(node_value_per_edge.numberOfValues() == number_of_values(node_value_per_edge)); + + auto edge_to_node_matrix = connectivity.edgeToNodeMatrix(); + { + bool is_correct = true; + for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { + is_correct &= (edge_to_node_matrix[edge_id].size() == node_value_per_edge.numberOfSubValues(edge_id)); + } + REQUIRE(is_correct); + } + } + + SECTION("per node") + { + EdgeValuePerNode<int> edge_value_per_node{connectivity}; + REQUIRE(edge_value_per_node.numberOfItems() == connectivity.numberOfNodes()); + REQUIRE(edge_value_per_node.numberOfValues() == number_of_values(edge_value_per_node)); + + auto node_to_edge_matrix = connectivity.nodeToEdgeMatrix(); + { + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + is_correct &= (node_to_edge_matrix[node_id].size() == edge_value_per_node.numberOfSubValues(node_id)); + } + REQUIRE(is_correct); + } + + FaceValuePerNode<int> face_value_per_node{connectivity}; + REQUIRE(face_value_per_node.numberOfItems() == connectivity.numberOfNodes()); + REQUIRE(face_value_per_node.numberOfValues() == number_of_values(face_value_per_node)); + + auto node_to_face_matrix = connectivity.nodeToFaceMatrix(); + { + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + is_correct &= (node_to_face_matrix[node_id].size() == face_value_per_node.numberOfSubValues(node_id)); + } + REQUIRE(is_correct); + } + + CellValuePerNode<int> cell_value_per_node{connectivity}; + REQUIRE(cell_value_per_node.numberOfItems() == connectivity.numberOfNodes()); + REQUIRE(cell_value_per_node.numberOfValues() == number_of_values(cell_value_per_node)); + + auto node_to_cell_matrix = connectivity.nodeToCellMatrix(); + { + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + is_correct &= (node_to_cell_matrix[node_id].size() == cell_value_per_node.numberOfSubValues(node_id)); + } + REQUIRE(is_correct); + } } - REQUIRE(is_correct); } } } + } - SECTION("2D") + SECTION("array view") + { + SECTION("1D") { - const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesian2DMesh(); - const Connectivity<2>& connectivity = mesh_2d.connectivity(); - - SECTION("per cell") - { - NodeValuePerCell<int> node_value_per_cell{connectivity}; - REQUIRE(node_value_per_cell.numberOfItems() == connectivity.numberOfCells()); - REQUIRE(node_value_per_cell.numberOfValues() == number_of_values(node_value_per_cell)); + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - auto cell_to_node_matrix = connectivity.cellToNodeMatrix(); + for (auto [section_name, mesh_1d] : mesh_list) { + SECTION(section_name) { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= (cell_to_node_matrix[cell_id].size() == node_value_per_cell.numberOfSubValues(cell_id)); - } - REQUIRE(is_correct); - } + const Connectivity<1>& connectivity = mesh_1d->connectivity(); - EdgeValuePerCell<int> edge_value_per_cell{connectivity}; - REQUIRE(edge_value_per_cell.numberOfItems() == connectivity.numberOfCells()); - REQUIRE(edge_value_per_cell.numberOfValues() == number_of_values(edge_value_per_cell)); - - auto cell_to_edge_matrix = connectivity.cellToEdgeMatrix(); - { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= (cell_to_edge_matrix[cell_id].size() == edge_value_per_cell.numberOfSubValues(cell_id)); + EdgeValuePerCell<size_t> edge_values_per_cell{connectivity}; + { + size_t value = 0; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + for (size_t i_edge = 0; i_edge < edge_values_per_cell.numberOfSubValues(cell_id); ++i_edge) { + edge_values_per_cell(cell_id, i_edge) = value++; + } + } } - REQUIRE(is_correct); - } - - FaceValuePerCell<int> face_value_per_cell{connectivity}; - REQUIRE(face_value_per_cell.numberOfItems() == connectivity.numberOfCells()); - REQUIRE(face_value_per_cell.numberOfValues() == number_of_values(face_value_per_cell)); - - auto cell_to_face_matrix = connectivity.cellToFaceMatrix(); - { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= (cell_to_face_matrix[cell_id].size() == face_value_per_cell.numberOfSubValues(cell_id)); + { + bool is_same = true; + for (size_t i = 0; i < edge_values_per_cell.numberOfValues(); ++i) { + is_same &= (edge_values_per_cell[i] == i); + } + REQUIRE(is_same); } - REQUIRE(is_correct); - } - } - - SECTION("per face") - { - CellValuePerFace<int> cell_value_per_face{connectivity}; - REQUIRE(cell_value_per_face.numberOfItems() == connectivity.numberOfFaces()); - REQUIRE(cell_value_per_face.numberOfValues() == number_of_values(cell_value_per_face)); - auto face_to_cell_matrix = connectivity.faceToCellMatrix(); - { - bool is_correct = true; - for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { - is_correct &= (face_to_cell_matrix[face_id].size() == cell_value_per_face.numberOfSubValues(face_id)); + for (size_t i = 0; i < edge_values_per_cell.numberOfValues(); ++i) { + edge_values_per_cell[i] = i * i + 1; } - REQUIRE(is_correct); - } - - NodeValuePerFace<int> node_value_per_face{connectivity}; - REQUIRE(node_value_per_face.numberOfItems() == connectivity.numberOfFaces()); - REQUIRE(node_value_per_face.numberOfValues() == number_of_values(node_value_per_face)); - - auto face_to_node_matrix = connectivity.faceToNodeMatrix(); - { - bool is_correct = true; - for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { - is_correct &= (face_to_node_matrix[face_id].size() == node_value_per_face.numberOfSubValues(face_id)); + { + bool is_same = true; + size_t i = 0; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + for (size_t i_edge = 0; i_edge < edge_values_per_cell.numberOfSubValues(cell_id); ++i_edge, ++i) { + is_same &= (edge_values_per_cell(cell_id, i_edge) == i * i + 1); + } + } + REQUIRE(is_same); } - REQUIRE(is_correct); } } + } - SECTION("per edge") - { - CellValuePerEdge<int> cell_value_per_edge{connectivity}; - REQUIRE(cell_value_per_edge.numberOfItems() == connectivity.numberOfEdges()); - REQUIRE(cell_value_per_edge.numberOfValues() == number_of_values(cell_value_per_edge)); - - auto edge_to_cell_matrix = connectivity.edgeToCellMatrix(); - { - bool is_correct = true; - for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { - is_correct &= (edge_to_cell_matrix[edge_id].size() == cell_value_per_edge.numberOfSubValues(edge_id)); - } - REQUIRE(is_correct); - } - - NodeValuePerEdge<int> node_value_per_edge{connectivity}; - REQUIRE(node_value_per_edge.numberOfItems() == connectivity.numberOfEdges()); - REQUIRE(node_value_per_edge.numberOfValues() == number_of_values(node_value_per_edge)); - - auto edge_to_node_matrix = connectivity.edgeToNodeMatrix(); - { - bool is_correct = true; - for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { - is_correct &= (edge_to_node_matrix[edge_id].size() == node_value_per_edge.numberOfSubValues(edge_id)); - } - REQUIRE(is_correct); - } - } - - SECTION("per node") - { - EdgeValuePerNode<int> edge_value_per_node{connectivity}; - REQUIRE(edge_value_per_node.numberOfItems() == connectivity.numberOfNodes()); - REQUIRE(edge_value_per_node.numberOfValues() == number_of_values(edge_value_per_node)); - - auto node_to_edge_matrix = connectivity.nodeToEdgeMatrix(); - { - bool is_correct = true; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - is_correct &= (node_to_edge_matrix[node_id].size() == edge_value_per_node.numberOfSubValues(node_id)); - } - REQUIRE(is_correct); - } - - FaceValuePerNode<int> face_value_per_node{connectivity}; - REQUIRE(face_value_per_node.numberOfItems() == connectivity.numberOfNodes()); - REQUIRE(face_value_per_node.numberOfValues() == number_of_values(face_value_per_node)); - - auto node_to_face_matrix = connectivity.nodeToFaceMatrix(); - { - bool is_correct = true; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - is_correct &= (node_to_face_matrix[node_id].size() == face_value_per_node.numberOfSubValues(node_id)); - } - REQUIRE(is_correct); - } - - CellValuePerNode<int> cell_value_per_node{connectivity}; - REQUIRE(cell_value_per_node.numberOfItems() == connectivity.numberOfNodes()); - REQUIRE(cell_value_per_node.numberOfValues() == number_of_values(cell_value_per_node)); + SECTION("2D") + { + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - auto node_to_cell_matrix = connectivity.nodeToCellMatrix(); + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) { - bool is_correct = true; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - is_correct &= (node_to_cell_matrix[node_id].size() == cell_value_per_node.numberOfSubValues(node_id)); + const Connectivity<2>& connectivity = mesh_2d->connectivity(); + + CellValuePerFace<size_t> cell_values_per_face{connectivity}; + { + size_t value = 0; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + for (size_t i_cell = 0; i_cell < cell_values_per_face.numberOfSubValues(face_id); ++i_cell) { + cell_values_per_face(face_id, i_cell) = value++; + } + } + } + { + bool is_same = true; + for (size_t i = 0; i < cell_values_per_face.numberOfValues(); ++i) { + is_same &= (cell_values_per_face[i] == i); + } + REQUIRE(is_same); + } + for (size_t i = 0; i < cell_values_per_face.numberOfValues(); ++i) { + cell_values_per_face[i] = 3 * i + 1; + } + { + bool is_same = true; + size_t i = 0; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + for (size_t i_cell = 0; i_cell < cell_values_per_face.numberOfSubValues(face_id); ++i_cell, ++i) { + is_same &= (cell_values_per_face(face_id, i_cell) == 3 * i + 1); + } + } + REQUIRE(is_same); } - REQUIRE(is_correct); } } } SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); - - SECTION("per cell") - { - NodeValuePerCell<int> node_value_per_cell{connectivity}; - REQUIRE(node_value_per_cell.numberOfItems() == connectivity.numberOfCells()); - REQUIRE(node_value_per_cell.numberOfValues() == number_of_values(node_value_per_cell)); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - auto cell_to_node_matrix = connectivity.cellToNodeMatrix(); + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= (cell_to_node_matrix[cell_id].size() == node_value_per_cell.numberOfSubValues(cell_id)); - } - REQUIRE(is_correct); - } + const Connectivity<3>& connectivity = mesh_3d->connectivity(); - EdgeValuePerCell<int> edge_value_per_cell{connectivity}; - REQUIRE(edge_value_per_cell.numberOfItems() == connectivity.numberOfCells()); - REQUIRE(edge_value_per_cell.numberOfValues() == number_of_values(edge_value_per_cell)); - - auto cell_to_edge_matrix = connectivity.cellToEdgeMatrix(); - { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= (cell_to_edge_matrix[cell_id].size() == edge_value_per_cell.numberOfSubValues(cell_id)); + FaceValuePerNode<size_t> face_values_per_node{connectivity}; + { + size_t value = 0; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + for (size_t i_face = 0; i_face < face_values_per_node.numberOfSubValues(node_id); ++i_face) { + face_values_per_node.itemValues(node_id)[i_face] = value++; + } + } } - REQUIRE(is_correct); - } - - FaceValuePerCell<int> face_value_per_cell{connectivity}; - REQUIRE(face_value_per_cell.numberOfItems() == connectivity.numberOfCells()); - REQUIRE(face_value_per_cell.numberOfValues() == number_of_values(face_value_per_cell)); - - auto cell_to_face_matrix = connectivity.cellToFaceMatrix(); - { - bool is_correct = true; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= (cell_to_face_matrix[cell_id].size() == face_value_per_cell.numberOfSubValues(cell_id)); + { + bool is_same = true; + for (size_t i = 0; i < face_values_per_node.numberOfValues(); ++i) { + is_same &= (face_values_per_node[i] == i); + } + REQUIRE(is_same); } - REQUIRE(is_correct); - } - } - - SECTION("per face") - { - CellValuePerFace<int> cell_value_per_face{connectivity}; - REQUIRE(cell_value_per_face.numberOfItems() == connectivity.numberOfFaces()); - REQUIRE(cell_value_per_face.numberOfValues() == number_of_values(cell_value_per_face)); - auto face_to_cell_matrix = connectivity.faceToCellMatrix(); - { - bool is_correct = true; - for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { - is_correct &= (face_to_cell_matrix[face_id].size() == cell_value_per_face.numberOfSubValues(face_id)); + for (size_t i = 0; i < face_values_per_node.numberOfValues(); ++i) { + face_values_per_node[i] = 3 + i * i; } - REQUIRE(is_correct); - } - - EdgeValuePerFace<int> edge_value_per_face{connectivity}; - REQUIRE(edge_value_per_face.numberOfItems() == connectivity.numberOfFaces()); - REQUIRE(edge_value_per_face.numberOfValues() == number_of_values(edge_value_per_face)); - - auto face_to_edge_matrix = connectivity.faceToEdgeMatrix(); - { - bool is_correct = true; - for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { - is_correct &= (face_to_edge_matrix[face_id].size() == edge_value_per_face.numberOfSubValues(face_id)); - } - REQUIRE(is_correct); - } - - NodeValuePerFace<int> node_value_per_face{connectivity}; - REQUIRE(node_value_per_face.numberOfItems() == connectivity.numberOfFaces()); - REQUIRE(node_value_per_face.numberOfValues() == number_of_values(node_value_per_face)); - - auto face_to_node_matrix = connectivity.faceToNodeMatrix(); - { - bool is_correct = true; - for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { - is_correct &= (face_to_node_matrix[face_id].size() == node_value_per_face.numberOfSubValues(face_id)); + { + bool is_same = true; + size_t i = 0; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + for (size_t i_face = 0; i_face < face_values_per_node.numberOfSubValues(node_id); ++i_face, ++i) { + is_same &= (face_values_per_node.itemValues(node_id)[i_face] == 3 + i * i); + } + } + REQUIRE(is_same); } - REQUIRE(is_correct); } } + } + } - SECTION("per edge") + SECTION("copy") + { + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); + + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) { - CellValuePerEdge<int> cell_value_per_edge{connectivity}; - REQUIRE(cell_value_per_edge.numberOfItems() == connectivity.numberOfEdges()); - REQUIRE(cell_value_per_edge.numberOfValues() == number_of_values(cell_value_per_edge)); + const Connectivity<3>& connectivity = mesh_3d->connectivity(); - auto edge_to_cell_matrix = connectivity.edgeToCellMatrix(); + SECTION("classic") { - bool is_correct = true; - for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { - is_correct &= (edge_to_cell_matrix[edge_id].size() == cell_value_per_edge.numberOfSubValues(edge_id)); - } - REQUIRE(is_correct); - } - - FaceValuePerEdge<int> face_value_per_edge{connectivity}; - REQUIRE(face_value_per_edge.numberOfItems() == connectivity.numberOfEdges()); - REQUIRE(face_value_per_edge.numberOfValues() == number_of_values(face_value_per_edge)); + NodeValuePerCell<size_t> node_value_per_cell{connectivity}; - auto edge_to_face_matrix = connectivity.edgeToFaceMatrix(); - { - bool is_correct = true; - for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { - is_correct &= (edge_to_face_matrix[edge_id].size() == face_value_per_edge.numberOfSubValues(edge_id)); + { + size_t value = 0; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + for (size_t i_node = 0; i_node < node_value_per_cell.numberOfSubValues(cell_id); ++i_node) { + node_value_per_cell.itemValues(cell_id)[i_node] = value++; + } + } } - REQUIRE(is_correct); - } - NodeValuePerEdge<int> node_value_per_edge{connectivity}; - REQUIRE(node_value_per_edge.numberOfItems() == connectivity.numberOfEdges()); - REQUIRE(node_value_per_edge.numberOfValues() == number_of_values(node_value_per_edge)); + NodeValuePerCell<size_t> copy_node_value_per_cell = copy(node_value_per_cell); - auto edge_to_node_matrix = connectivity.edgeToNodeMatrix(); - { - bool is_correct = true; - for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { - is_correct &= (edge_to_node_matrix[edge_id].size() == node_value_per_edge.numberOfSubValues(edge_id)); - } - REQUIRE(is_correct); - } - } + { + bool is_same = true; + for (size_t i = 0; i < copy_node_value_per_cell.numberOfValues(); ++i) { + is_same &= (copy_node_value_per_cell[i] == node_value_per_cell[i]); + } - SECTION("per node") - { - EdgeValuePerNode<int> edge_value_per_node{connectivity}; - REQUIRE(edge_value_per_node.numberOfItems() == connectivity.numberOfNodes()); - REQUIRE(edge_value_per_node.numberOfValues() == number_of_values(edge_value_per_node)); - - auto node_to_edge_matrix = connectivity.nodeToEdgeMatrix(); - { - bool is_correct = true; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - is_correct &= (node_to_edge_matrix[node_id].size() == edge_value_per_node.numberOfSubValues(node_id)); + REQUIRE(is_same); } - REQUIRE(is_correct); - } - FaceValuePerNode<int> face_value_per_node{connectivity}; - REQUIRE(face_value_per_node.numberOfItems() == connectivity.numberOfNodes()); - REQUIRE(face_value_per_node.numberOfValues() == number_of_values(face_value_per_node)); - - auto node_to_face_matrix = connectivity.nodeToFaceMatrix(); - { - bool is_correct = true; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - is_correct &= (node_to_face_matrix[node_id].size() == face_value_per_node.numberOfSubValues(node_id)); + { + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + for (size_t i_node = 0; i_node < node_value_per_cell.numberOfSubValues(cell_id); ++i_node) { + node_value_per_cell.itemValues(cell_id)[i_node] = i_node; + } + } } - REQUIRE(is_correct); - } - CellValuePerNode<int> cell_value_per_node{connectivity}; - REQUIRE(cell_value_per_node.numberOfItems() == connectivity.numberOfNodes()); - REQUIRE(cell_value_per_node.numberOfValues() == number_of_values(cell_value_per_node)); + { + bool is_same = true; + for (size_t i = 0; i < copy_node_value_per_cell.numberOfValues(); ++i) { + is_same &= (copy_node_value_per_cell[i] == node_value_per_cell[i]); + } - auto node_to_cell_matrix = connectivity.nodeToCellMatrix(); - { - bool is_correct = true; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - is_correct &= (node_to_cell_matrix[node_id].size() == cell_value_per_node.numberOfSubValues(node_id)); + REQUIRE(not is_same); } - REQUIRE(is_correct); } - } - } - } - SECTION("array view") - { - SECTION("1D") - { - const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesian1DMesh(); - const Connectivity<1>& connectivity = mesh_1d.connectivity(); + SECTION("from weak") + { + WeakNodeValuePerCell<size_t> node_value_per_cell{connectivity}; - EdgeValuePerCell<size_t> edge_values_per_cell{connectivity}; - { - size_t value = 0; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - for (size_t i_edge = 0; i_edge < edge_values_per_cell.numberOfSubValues(cell_id); ++i_edge) { - edge_values_per_cell(cell_id, i_edge) = value++; + { + size_t value = 0; + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + for (size_t i_node = 0; i_node < node_value_per_cell.numberOfSubValues(cell_id); ++i_node) { + node_value_per_cell.itemValues(cell_id)[i_node] = value++; + } + } } - } - } - { - bool is_same = true; - for (size_t i = 0; i < edge_values_per_cell.numberOfValues(); ++i) { - is_same &= (edge_values_per_cell[i] == i); - } - REQUIRE(is_same); - } - for (size_t i = 0; i < edge_values_per_cell.numberOfValues(); ++i) { - edge_values_per_cell[i] = i * i + 1; - } - { - bool is_same = true; - size_t i = 0; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - for (size_t i_edge = 0; i_edge < edge_values_per_cell.numberOfSubValues(cell_id); ++i_edge, ++i) { - is_same &= (edge_values_per_cell(cell_id, i_edge) == i * i + 1); - } - } - REQUIRE(is_same); - } - } + NodeValuePerCell<size_t> copy_node_value_per_cell = copy(node_value_per_cell); - SECTION("2D") - { - const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesian2DMesh(); - const Connectivity<2>& connectivity = mesh_2d.connectivity(); + { + bool is_same = true; + for (size_t i = 0; i < copy_node_value_per_cell.numberOfValues(); ++i) { + is_same &= (copy_node_value_per_cell[i] == node_value_per_cell[i]); + } - CellValuePerFace<size_t> cell_values_per_face{connectivity}; - { - size_t value = 0; - for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { - for (size_t i_cell = 0; i_cell < cell_values_per_face.numberOfSubValues(face_id); ++i_cell) { - cell_values_per_face(face_id, i_cell) = value++; + REQUIRE(is_same); } - } - } - { - bool is_same = true; - for (size_t i = 0; i < cell_values_per_face.numberOfValues(); ++i) { - is_same &= (cell_values_per_face[i] == i); - } - REQUIRE(is_same); - } - for (size_t i = 0; i < cell_values_per_face.numberOfValues(); ++i) { - cell_values_per_face[i] = 3 * i + 1; - } - { - bool is_same = true; - size_t i = 0; - for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { - for (size_t i_cell = 0; i_cell < cell_values_per_face.numberOfSubValues(face_id); ++i_cell, ++i) { - is_same &= (cell_values_per_face(face_id, i_cell) == 3 * i + 1); - } - } - REQUIRE(is_same); - } - } - - SECTION("3D") - { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); - FaceValuePerNode<size_t> face_values_per_node{connectivity}; - { - size_t value = 0; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - for (size_t i_face = 0; i_face < face_values_per_node.numberOfSubValues(node_id); ++i_face) { - face_values_per_node.itemValues(node_id)[i_face] = value++; + { + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + for (size_t i_node = 0; i_node < node_value_per_cell.numberOfSubValues(cell_id); ++i_node) { + node_value_per_cell.itemValues(cell_id)[i_node] = i_node; + } + } } - } - } - { - bool is_same = true; - for (size_t i = 0; i < face_values_per_node.numberOfValues(); ++i) { - is_same &= (face_values_per_node[i] == i); - } - REQUIRE(is_same); - } - for (size_t i = 0; i < face_values_per_node.numberOfValues(); ++i) { - face_values_per_node[i] = 3 + i * i; - } - { - bool is_same = true; - size_t i = 0; - for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { - for (size_t i_face = 0; i_face < face_values_per_node.numberOfSubValues(node_id); ++i_face, ++i) { - is_same &= (face_values_per_node.itemValues(node_id)[i_face] == 3 + i * i); + { + bool is_same = true; + for (size_t i = 0; i < copy_node_value_per_cell.numberOfValues(); ++i) { + is_same &= (copy_node_value_per_cell[i] == node_value_per_cell[i]); + } + + REQUIRE(not is_same); } } - REQUIRE(is_same); } } } - SECTION("copy") + SECTION("WeakSubItemValuePerItem") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); - - SECTION("classic") - { - NodeValuePerCell<size_t> node_value_per_cell{connectivity}; - - { - size_t value = 0; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - for (size_t i_node = 0; i_node < node_value_per_cell.numberOfSubValues(cell_id); ++i_node) { - node_value_per_cell.itemValues(cell_id)[i_node] = value++; - } - } - } - - NodeValuePerCell<size_t> copy_node_value_per_cell = copy(node_value_per_cell); + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); + for (auto [section_name, mesh_2d] : mesh_list) { + SECTION(section_name) { - bool is_same = true; - for (size_t i = 0; i < copy_node_value_per_cell.numberOfValues(); ++i) { - is_same &= (copy_node_value_per_cell[i] == node_value_per_cell[i]); - } + const Connectivity<2>& connectivity = mesh_2d->connectivity(); - REQUIRE(is_same); - } + WeakFaceValuePerCell<int> weak_face_value_per_cell{connectivity}; - { - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - for (size_t i_node = 0; i_node < node_value_per_cell.numberOfSubValues(cell_id); ++i_node) { - node_value_per_cell.itemValues(cell_id)[i_node] = i_node; - } + for (size_t i = 0; i < weak_face_value_per_cell.numberOfValues(); ++i) { + weak_face_value_per_cell[i] = i; } - } - { - bool is_same = true; - for (size_t i = 0; i < copy_node_value_per_cell.numberOfValues(); ++i) { - is_same &= (copy_node_value_per_cell[i] == node_value_per_cell[i]); - } + FaceValuePerCell<const int> face_value_per_cell{weak_face_value_per_cell}; - REQUIRE(not is_same); - } - } - - SECTION("from weak") - { - WeakNodeValuePerCell<size_t> node_value_per_cell{connectivity}; + REQUIRE(face_value_per_cell.connectivity_ptr() == weak_face_value_per_cell.connectivity_ptr()); - { - size_t value = 0; - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - for (size_t i_node = 0; i_node < node_value_per_cell.numberOfSubValues(cell_id); ++i_node) { - node_value_per_cell.itemValues(cell_id)[i_node] = value++; - } - } - } - - NodeValuePerCell<size_t> copy_node_value_per_cell = copy(node_value_per_cell); - - { bool is_same = true; - for (size_t i = 0; i < copy_node_value_per_cell.numberOfValues(); ++i) { - is_same &= (copy_node_value_per_cell[i] == node_value_per_cell[i]); + for (size_t i = 0; i < weak_face_value_per_cell.numberOfValues(); ++i) { + is_same &= (face_value_per_cell[i] == weak_face_value_per_cell[i]); } - REQUIRE(is_same); } - - { - for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - for (size_t i_node = 0; i_node < node_value_per_cell.numberOfSubValues(cell_id); ++i_node) { - node_value_per_cell.itemValues(cell_id)[i_node] = i_node; - } - } - } - - { - bool is_same = true; - for (size_t i = 0; i < copy_node_value_per_cell.numberOfValues(); ++i) { - is_same &= (copy_node_value_per_cell[i] == node_value_per_cell[i]); - } - - REQUIRE(not is_same); - } } } - SECTION("WeakSubItemValuePerItem") - { - const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesian2DMesh(); - const Connectivity<2>& connectivity = mesh_2d.connectivity(); - - WeakFaceValuePerCell<int> weak_face_value_per_cell{connectivity}; - - for (size_t i = 0; i < weak_face_value_per_cell.numberOfValues(); ++i) { - weak_face_value_per_cell[i] = i; - } - - FaceValuePerCell<const int> face_value_per_cell{weak_face_value_per_cell}; - - REQUIRE(face_value_per_cell.connectivity_ptr() == weak_face_value_per_cell.connectivity_ptr()); - - bool is_same = true; - for (size_t i = 0; i < weak_face_value_per_cell.numberOfValues(); ++i) { - is_same &= (face_value_per_cell[i] == weak_face_value_per_cell[i]); - } - REQUIRE(is_same); - } - #ifndef NDEBUG SECTION("error") { @@ -758,59 +806,65 @@ TEST_CASE("SubItemValuePerItem", "[mesh]") SECTION("checking for bounds violation") { - const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesian3DMesh(); - const Connectivity<3>& connectivity = mesh_3d.connectivity(); + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - CellValuePerFace<int> cell_value_per_face{connectivity}; - { - FaceId invalid_face_id = connectivity.numberOfFaces(); - REQUIRE_THROWS_AS(cell_value_per_face(invalid_face_id, 0), AssertError); - } - if (connectivity.numberOfFaces() > 0) { - FaceId face_id = 0; - const auto& cell_values = cell_value_per_face.itemValues(face_id); - REQUIRE_THROWS_AS(cell_value_per_face(face_id, cell_values.size()), AssertError); - REQUIRE_THROWS_AS(cell_values[cell_values.size()], AssertError); - REQUIRE_THROWS_AS(cell_value_per_face.itemValues(face_id)[cell_values.size()] = 2, AssertError); - } + for (auto [section_name, mesh_3d] : mesh_list) { + SECTION(section_name) + { + const Connectivity<3>& connectivity = mesh_3d->connectivity(); - FaceValuePerNode<int> face_value_per_node{connectivity}; - { - NodeId invalid_node_id = connectivity.numberOfNodes(); - REQUIRE_THROWS_AS(face_value_per_node(invalid_node_id, 0), AssertError); - } - if (connectivity.numberOfNodes() > 0) { - NodeId node_id = 0; - const auto& face_values = face_value_per_node.itemValues(node_id); - REQUIRE_THROWS_AS(face_value_per_node(node_id, face_values.size()), AssertError); - REQUIRE_THROWS_AS(face_values[face_values.size()], AssertError); - REQUIRE_THROWS_AS(face_value_per_node.itemValues(node_id)[face_values.size()] = 2, AssertError); - } + CellValuePerFace<int> cell_value_per_face{connectivity}; + { + FaceId invalid_face_id = connectivity.numberOfFaces(); + REQUIRE_THROWS_AS(cell_value_per_face(invalid_face_id, 0), AssertError); + } + if (connectivity.numberOfFaces() > 0) { + FaceId face_id = 0; + const auto& cell_values = cell_value_per_face.itemValues(face_id); + REQUIRE_THROWS_AS(cell_value_per_face(face_id, cell_values.size()), AssertError); + REQUIRE_THROWS_AS(cell_values[cell_values.size()], AssertError); + REQUIRE_THROWS_AS(cell_value_per_face.itemValues(face_id)[cell_values.size()] = 2, AssertError); + } - EdgeValuePerCell<int> edge_value_per_cell{connectivity}; - { - CellId invalid_cell_id = connectivity.numberOfCells(); - REQUIRE_THROWS_AS(edge_value_per_cell(invalid_cell_id, 0), AssertError); - } - if (connectivity.numberOfCells() > 0) { - CellId cell_id = 0; - const auto& edge_values = edge_value_per_cell.itemValues(cell_id); - REQUIRE_THROWS_AS(edge_value_per_cell(cell_id, edge_values.size()), AssertError); - REQUIRE_THROWS_AS(edge_values[edge_values.size()], AssertError); - REQUIRE_THROWS_AS(edge_value_per_cell.itemValues(cell_id)[edge_values.size()] = 2, AssertError); - } + FaceValuePerNode<int> face_value_per_node{connectivity}; + { + NodeId invalid_node_id = connectivity.numberOfNodes(); + REQUIRE_THROWS_AS(face_value_per_node(invalid_node_id, 0), AssertError); + } + if (connectivity.numberOfNodes() > 0) { + NodeId node_id = 0; + const auto& face_values = face_value_per_node.itemValues(node_id); + REQUIRE_THROWS_AS(face_value_per_node(node_id, face_values.size()), AssertError); + REQUIRE_THROWS_AS(face_values[face_values.size()], AssertError); + REQUIRE_THROWS_AS(face_value_per_node.itemValues(node_id)[face_values.size()] = 2, AssertError); + } - NodeValuePerEdge<int> node_value_per_edge{connectivity}; - { - EdgeId invalid_edge_id = connectivity.numberOfEdges(); - REQUIRE_THROWS_AS(node_value_per_edge(invalid_edge_id, 0), AssertError); - } - if (connectivity.numberOfEdges() > 0) { - EdgeId edge_id = 0; - const auto& node_values = node_value_per_edge.itemValues(edge_id); - REQUIRE_THROWS_AS(node_value_per_edge(edge_id, node_values.size()), AssertError); - REQUIRE_THROWS_AS(node_values[node_values.size()], AssertError); - REQUIRE_THROWS_AS(node_value_per_edge.itemValues(edge_id)[node_values.size()] = 2, AssertError); + EdgeValuePerCell<int> edge_value_per_cell{connectivity}; + { + CellId invalid_cell_id = connectivity.numberOfCells(); + REQUIRE_THROWS_AS(edge_value_per_cell(invalid_cell_id, 0), AssertError); + } + if (connectivity.numberOfCells() > 0) { + CellId cell_id = 0; + const auto& edge_values = edge_value_per_cell.itemValues(cell_id); + REQUIRE_THROWS_AS(edge_value_per_cell(cell_id, edge_values.size()), AssertError); + REQUIRE_THROWS_AS(edge_values[edge_values.size()], AssertError); + REQUIRE_THROWS_AS(edge_value_per_cell.itemValues(cell_id)[edge_values.size()] = 2, AssertError); + } + + NodeValuePerEdge<int> node_value_per_edge{connectivity}; + { + EdgeId invalid_edge_id = connectivity.numberOfEdges(); + REQUIRE_THROWS_AS(node_value_per_edge(invalid_edge_id, 0), AssertError); + } + if (connectivity.numberOfEdges() > 0) { + EdgeId edge_id = 0; + const auto& node_values = node_value_per_edge.itemValues(edge_id); + REQUIRE_THROWS_AS(node_value_per_edge(edge_id, node_values.size()), AssertError); + REQUIRE_THROWS_AS(node_values[node_values.size()], AssertError); + REQUIRE_THROWS_AS(node_value_per_edge.itemValues(edge_id)[node_values.size()] = 2, AssertError); + } + } } } }