diff --git a/src/scheme/PolynomialReconstruction.hpp b/src/scheme/PolynomialReconstruction.hpp index b55e84fee171e21b762e4934054f6cb2b04b82e7..4c88d7476b34e92e40971a6962e649358ab5a5b6 100644 --- a/src/scheme/PolynomialReconstruction.hpp +++ b/src/scheme/PolynomialReconstruction.hpp @@ -323,6 +323,31 @@ class PolynomialReconstruction [[nodiscard]] std::vector<std::shared_ptr<const DiscreteFunctionDPkVariant>> build( const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list) const; + template <typename... DiscreteFunctionT> + [[nodiscard]] std::vector<std::shared_ptr<const DiscreteFunctionDPkVariant>> + build(DiscreteFunctionT... input) const + { + std::vector<std::shared_ptr<const DiscreteFunctionVariant>> variant_vector; + auto convert = [&variant_vector](auto&& df) { + using DF_T = std::decay_t<decltype(df)>; + if constexpr (is_discrete_function_v<DF_T> or std::is_same_v<DiscreteFunctionVariant, DF_T>) { + variant_vector.push_back(std::make_shared<DiscreteFunctionVariant>(df)); + } else if constexpr (is_shared_ptr_v<DF_T>) { + using DF_Value_T = std::decay_t<typename DF_T::element_type>; + if constexpr (is_discrete_function_v<DF_Value_T> or std::is_same_v<DiscreteFunctionVariant, DF_Value_T>) { + variant_vector.push_back(std::make_shared<DiscreteFunctionVariant>(*df)); + } else { + static_assert(is_false_v<DF_T>, "unexpected type"); + } + } else { + static_assert(is_false_v<DF_T>, "unexpected type"); + } + }; + + (convert(std::forward<DiscreteFunctionT>(input)), ...); + return this->build(variant_vector); + } + PolynomialReconstruction() {} }; diff --git a/tests/test_PolynomialReconstruction.cpp b/tests/test_PolynomialReconstruction.cpp index 5242b6b041dda5429a6c3509f4b0523e4924b5ac..4099960e31d6a5cbc4dc5b10c0887a8f70178de5 100644 --- a/tests/test_PolynomialReconstruction.cpp +++ b/tests/test_PolynomialReconstruction.cpp @@ -17,31 +17,6 @@ #include <MeshDataBaseForTests.hpp> -template <typename... DiscreteFunctionT> -std::vector<std::shared_ptr<const DiscreteFunctionVariant>> -build_list(DiscreteFunctionT... input) -{ - std::vector<std::shared_ptr<const DiscreteFunctionVariant>> variant_vector; - auto convert = [&variant_vector](auto&& df) { - using DF_T = std::decay_t<decltype(df)>; - if constexpr (is_discrete_function_v<DF_T> or std::is_same_v<DiscreteFunctionVariant, DF_T>) { - variant_vector.push_back(std::make_shared<DiscreteFunctionVariant>(df)); - } else if constexpr (is_shared_ptr_v<DF_T>) { - using DF_Value_T = std::decay_t<typename DF_T::element_type>; - if constexpr (is_discrete_function_v<DF_Value_T> or std::is_same_v<DiscreteFunctionVariant, DF_Value_T>) { - variant_vector.push_back(std::make_shared<DiscreteFunctionVariant>(*df)); - } else { - static_assert(is_false_v<DF_T>, "unexpected type"); - } - } else { - static_assert(is_false_v<DF_T>, "unexpected type"); - } - }; - - (convert(input), ...); - return variant_vector; -} - // clazy:excludeall=non-pod-global-static TEST_CASE("PolynomialReconstruction", "[scheme]") @@ -69,7 +44,10 @@ TEST_CASE("PolynomialReconstruction", "[scheme]") DiscreteFunctionVariant fh_v(fh); std::shared_ptr<const DiscreteFunctionVariant> p_fh_v = std::make_shared<DiscreteFunctionVariant>(fh); - auto reconstructions = PolynomialReconstruction{}.build(build_list(p_fh_v, fh_v, fh)); + std::shared_ptr<DiscreteFunctionP0<const double>> p_fh = + std::make_shared<DiscreteFunctionP0<const double>>(fh); + + auto reconstructions = PolynomialReconstruction{}.build(p_fh, p_fh_v, fh_v, fh); auto dpk = reconstructions[0]->get<DiscreteFunctionDPk<1, const double>>(); @@ -144,7 +122,7 @@ TEST_CASE("PolynomialReconstruction", "[scheme]") SECTION("R^mn data") { - using R32 = TinyMatrix<3, 2>; + using R33 = TinyMatrix<3, 3>; for (auto named_mesh : MeshDataBaseForTests::get().all1DMeshes()) { SECTION(named_mesh.name()) @@ -152,14 +130,16 @@ TEST_CASE("PolynomialReconstruction", "[scheme]") auto p_mesh = named_mesh.mesh()->get<Mesh<1>>(); auto& mesh = *p_mesh; - auto affine = [](const R1& x) -> R32 { - return R32{+2.3 + 1.7 * x[0], -1.7 + 2.1 * x[0], // - +1.4 - 0.6 * x[0], +2.4 - 2.3 * x[0], // - -0.2 + 3.1 * x[0], -3.2 - 3.6 * x[0]}; + auto affine = [](const R1& x) -> R33 { + return R33{ + +2.3 + 1.7 * x[0], -1.7 + 2.1 * x[0], +1.4 - 0.6 * x[0], // + +2.4 - 2.3 * x[0], -0.2 + 3.1 * x[0], -3.2 - 3.6 * x[0], + -4.1 + 3.1 * x[0], +0.8 + 2.9 * x[0], -1.6 + 2.3 * x[0], + }; }; auto xj = MeshDataManager::instance().getMeshData(mesh).xj(); - DiscreteFunctionP0<R32> fh{p_mesh}; + DiscreteFunctionP0<R33> fh{p_mesh}; parallel_for( mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { fh[cell_id] = affine(xj[cell_id]); }); @@ -178,12 +158,15 @@ TEST_CASE("PolynomialReconstruction", "[scheme]") { double max_slope_error = 0; for (CellId cell_id = 0; cell_id < mesh.numberOfCells(); ++cell_id) { - const R32 reconstructed_slope = + const R33 reconstructed_slope = (1 / 0.2) * (dpk[cell_id](R1{0.1} + xj[cell_id]) - dpk[cell_id](xj[cell_id] - R1{0.1})); - max_slope_error = std::max(max_slope_error, frobeniusNorm(reconstructed_slope - R32{+1.7, +2.1, // - -0.6, -2.3, // - +3.1, -3.6})); + R33 slops = R33{+1.7, +2.1, -0.6, // + -2.3, +3.1, -3.6, // + +3.1, +2.9, +2.3}; + + max_slope_error = std::max(max_slope_error, // + frobeniusNorm(reconstructed_slope - slops)); } REQUIRE(max_slope_error == Catch::Approx(0).margin(1E-13)); } @@ -308,7 +291,7 @@ TEST_CASE("PolynomialReconstruction", "[scheme]") SECTION("R^mn data") { - using R32 = TinyMatrix<3, 2>; + using R22 = TinyMatrix<2, 2>; for (auto named_mesh : MeshDataBaseForTests::get().all2DMeshes()) { SECTION(named_mesh.name()) @@ -316,14 +299,13 @@ TEST_CASE("PolynomialReconstruction", "[scheme]") auto p_mesh = named_mesh.mesh()->get<Mesh<2>>(); auto& mesh = *p_mesh; - auto affine = [](const R2& x) -> R32 { - return R32{+2.3 + 1.7 * x[0] + 1.2 * x[1], -1.7 + 2.1 * x[0] - 2.2 * x[1], // - +1.4 - 0.6 * x[0] - 2.1 * x[1], +2.4 - 2.3 * x[0] + 1.3 * x[1], // - -0.2 + 3.1 * x[0] + 0.8 * x[1], -3.2 - 3.6 * x[0] - 1.7 * x[1]}; + auto affine = [](const R2& x) -> R22 { + return R22{+2.3 + 1.7 * x[0] + 1.2 * x[1], -1.7 + 2.1 * x[0] - 2.2 * x[1], // + +1.4 - 0.6 * x[0] - 2.1 * x[1], +2.4 - 2.3 * x[0] + 1.3 * x[1]}; }; auto xj = MeshDataManager::instance().getMeshData(mesh).xj(); - DiscreteFunctionP0<R32> fh{p_mesh}; + DiscreteFunctionP0<R22> fh{p_mesh}; parallel_for( mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { fh[cell_id] = affine(xj[cell_id]); }); @@ -342,12 +324,11 @@ TEST_CASE("PolynomialReconstruction", "[scheme]") { double max_x_slope_error = 0; for (CellId cell_id = 0; cell_id < mesh.numberOfCells(); ++cell_id) { - const R32 reconstructed_slope = + const R22 reconstructed_slope = (1 / 0.2) * (dpk[cell_id](R2{0.1, 0} + xj[cell_id]) - dpk[cell_id](xj[cell_id] - R2{0.1, 0})); - max_x_slope_error = std::max(max_x_slope_error, frobeniusNorm(reconstructed_slope - R32{+1.7, 2.1, // - -0.6, -2.3, // - +3.1, -3.6})); + max_x_slope_error = std::max(max_x_slope_error, frobeniusNorm(reconstructed_slope - R22{+1.7, +2.1, // + -0.6, -2.3})); } REQUIRE(max_x_slope_error == Catch::Approx(0).margin(1E-12)); } @@ -355,12 +336,11 @@ TEST_CASE("PolynomialReconstruction", "[scheme]") { double max_y_slope_error = 0; for (CellId cell_id = 0; cell_id < mesh.numberOfCells(); ++cell_id) { - const R32 reconstructed_slope = + const R22 reconstructed_slope = (1 / 0.2) * (dpk[cell_id](R2{0, 0.1} + xj[cell_id]) - dpk[cell_id](xj[cell_id] - R2{0, 0.1})); - max_y_slope_error = std::max(max_y_slope_error, frobeniusNorm(reconstructed_slope - R32{+1.2, -2.2, // - -2.1, 1.3, // - +0.8, -1.7})); + max_y_slope_error = std::max(max_y_slope_error, frobeniusNorm(reconstructed_slope - R22{+1.2, -2.2, // + -2.1, +1.3})); } REQUIRE(max_y_slope_error == Catch::Approx(0).margin(1E-12)); } @@ -508,7 +488,7 @@ TEST_CASE("PolynomialReconstruction", "[scheme]") SECTION("R^mn data") { - using R32 = TinyMatrix<3, 2>; + using R22 = TinyMatrix<2, 2>; for (auto named_mesh : MeshDataBaseForTests::get().all3DMeshes()) { SECTION(named_mesh.name()) @@ -516,14 +496,14 @@ TEST_CASE("PolynomialReconstruction", "[scheme]") auto p_mesh = named_mesh.mesh()->get<Mesh<3>>(); auto& mesh = *p_mesh; - auto affine = [](const R3& x) -> R32 { - return R32{+2.3 + 1.7 * x[0] + 1.2 * x[1] - 1.3 * x[2], -1.7 + 2.1 * x[0] - 2.2 * x[1] - 2.4 * x[2], // - +1.4 - 0.6 * x[0] - 2.1 * x[1] + 2.9 * x[2], +2.4 - 2.3 * x[0] + 1.3 * x[1] + 1.4 * x[2], // - -0.2 + 3.1 * x[0] + 0.8 * x[1] - 1.8 * x[2], -3.2 - 3.6 * x[0] - 1.7 * x[1] + 0.7 * x[2]}; + auto affine = [](const R3& x) -> R22 { + return R22{+2.3 + 1.7 * x[0] + 1.2 * x[1] - 1.3 * x[2], -1.7 + 2.1 * x[0] - 2.2 * x[1] - 2.4 * x[2], + // + +2.4 - 2.3 * x[0] + 1.3 * x[1] + 1.4 * x[2], -0.2 + 3.1 * x[0] + 0.8 * x[1] - 1.8 * x[2]}; }; auto xj = MeshDataManager::instance().getMeshData(mesh).xj(); - DiscreteFunctionP0<R32> fh{p_mesh}; + DiscreteFunctionP0<R22> fh{p_mesh}; parallel_for( mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { fh[cell_id] = affine(xj[cell_id]); }); @@ -542,12 +522,11 @@ TEST_CASE("PolynomialReconstruction", "[scheme]") { double max_x_slope_error = 0; for (CellId cell_id = 0; cell_id < mesh.numberOfCells(); ++cell_id) { - const R32 reconstructed_slope = + const R22 reconstructed_slope = (1 / 0.2) * (dpk[cell_id](R3{0.1, 0, 0} + xj[cell_id]) - dpk[cell_id](xj[cell_id] - R3{0.1, 0, 0})); - max_x_slope_error = std::max(max_x_slope_error, frobeniusNorm(reconstructed_slope - R32{+1.7, 2.1, // - -0.6, -2.3, // - +3.1, -3.6})); + max_x_slope_error = std::max(max_x_slope_error, frobeniusNorm(reconstructed_slope - R22{+1.7, 2.1, // + -2.3, +3.1})); } REQUIRE(max_x_slope_error == Catch::Approx(0).margin(1E-12)); } @@ -555,12 +534,11 @@ TEST_CASE("PolynomialReconstruction", "[scheme]") { double max_y_slope_error = 0; for (CellId cell_id = 0; cell_id < mesh.numberOfCells(); ++cell_id) { - const R32 reconstructed_slope = + const R22 reconstructed_slope = (1 / 0.2) * (dpk[cell_id](R3{0, 0.1, 0} + xj[cell_id]) - dpk[cell_id](xj[cell_id] - R3{0, 0.1, 0})); - max_y_slope_error = std::max(max_y_slope_error, frobeniusNorm(reconstructed_slope - R32{+1.2, -2.2, // - -2.1, 1.3, // - +0.8, -1.7})); + max_y_slope_error = std::max(max_y_slope_error, frobeniusNorm(reconstructed_slope - R22{+1.2, -2.2, // + 1.3, +0.8})); } REQUIRE(max_y_slope_error == Catch::Approx(0).margin(1E-12)); } @@ -568,12 +546,11 @@ TEST_CASE("PolynomialReconstruction", "[scheme]") { double max_z_slope_error = 0; for (CellId cell_id = 0; cell_id < mesh.numberOfCells(); ++cell_id) { - const R32 reconstructed_slope = + const R22 reconstructed_slope = (1 / 0.2) * (dpk[cell_id](R3{0, 0, 0.1} + xj[cell_id]) - dpk[cell_id](xj[cell_id] - R3{0, 0, 0.1})); - max_z_slope_error = std::max(max_z_slope_error, frobeniusNorm(reconstructed_slope - R32{-1.3, -2.4, // - +2.9, +1.4, // - -1.8, +0.7})); + max_z_slope_error = std::max(max_z_slope_error, frobeniusNorm(reconstructed_slope - R22{-1.3, -2.4, // + +1.4, -1.8})); } REQUIRE(max_z_slope_error == Catch::Approx(0).margin(1E-12)); }