From ae1cbc1060ac59874c06a058ccdc30ae28575a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Del=20Pino?= <stephane.delpino44@gmail.com> Date: Tue, 16 Jul 2024 19:23:20 +0200 Subject: [PATCH] Begin code clean-up --- src/language/modules/SchemeModule.cpp | 11 - src/scheme/PolynomialReconstruction.cpp | 454 +++++++++++++----------- src/scheme/PolynomialReconstruction.hpp | 238 +------------ src/scheme/test_reconstruction.cpp | 51 --- src/scheme/test_reconstruction.hpp | 3 - 5 files changed, 261 insertions(+), 496 deletions(-) diff --git a/src/language/modules/SchemeModule.cpp b/src/language/modules/SchemeModule.cpp index f96e96f13..0f3dadaad 100644 --- a/src/language/modules/SchemeModule.cpp +++ b/src/language/modules/SchemeModule.cpp @@ -671,17 +671,6 @@ SchemeModule::SchemeModule() )); -#warning REMOVE AFTER TESTS FINISHED - this->_addBuiltinFunction("test_reconstruction", - std::function( - - [](const std::shared_ptr<const MeshVariant> mesh_v, - const std::shared_ptr<const DiscreteFunctionVariant>& discrete_function_v) -> void { - test_reconstruction(mesh_v, discrete_function_v); - } - - )); - #warning REMOVE AFTER TESTS FINISHED this->_addBuiltinFunction("test_reconstruction", std::function( diff --git a/src/scheme/PolynomialReconstruction.cpp b/src/scheme/PolynomialReconstruction.cpp index 69d24b9e5..f9e55f19c 100644 --- a/src/scheme/PolynomialReconstruction.cpp +++ b/src/scheme/PolynomialReconstruction.cpp @@ -110,6 +110,225 @@ class PolynomialReconstruction::MutableDiscreteFunctionDPkVariant ~MutableDiscreteFunctionDPkVariant() = default; }; +template <typename ConformTransformationT> +void +_computeEjkMean(const QuadratureFormula<1>& quadrature, + const ConformTransformationT& T, + const TinyVector<1>& Xj, + const double Vi, + const size_t degree, + const size_t dimension, + SmallArray<double>& inv_Vj_wq_detJ_ek, + SmallArray<double>& mean_of_ejk) +{ + using Rd = TinyVector<1>; + mean_of_ejk.fill(0); + + for (size_t i_q = 0; i_q < quadrature.numberOfPoints(); ++i_q) { + const double wq = quadrature.weight(i_q); + const Rd& xi_q = quadrature.point(i_q); + const double detT = T.jacobianDeterminant(); + + const Rd X_Xj = T(xi_q) - Xj; + + const double x_xj = X_Xj[0]; + + { + size_t k = 0; + inv_Vj_wq_detJ_ek[k++] = wq * detT / Vi; + for (; k <= degree; ++k) { + inv_Vj_wq_detJ_ek[k] = x_xj * inv_Vj_wq_detJ_ek[k - 1]; + } + } + + for (size_t k = 1; k < dimension; ++k) { + mean_of_ejk[k - 1] += inv_Vj_wq_detJ_ek[k]; + } + } +} + +template <typename ConformTransformationT> +void +_computeEjkMean(const QuadratureFormula<2>& quadrature, + const ConformTransformationT& T, + const TinyVector<2>& Xj, + const double Vi, + const size_t degree, + const size_t dimension, + SmallArray<double>& inv_Vj_wq_detJ_ek, + SmallArray<double>& mean_of_ejk) +{ + using Rd = TinyVector<2>; + + mean_of_ejk.fill(0); + + for (size_t i_q = 0; i_q < quadrature.numberOfPoints(); ++i_q) { + const double wq = quadrature.weight(i_q); + const Rd& xi_q = quadrature.point(i_q); + const double detT = [&] { + if constexpr (std::is_same_v<TriangleTransformation<2>, std::decay_t<decltype(T)>>) { + return T.jacobianDeterminant(); + } else { + return T.jacobianDeterminant(xi_q); + } + }(); + + const Rd X_Xj = T(xi_q) - Xj; + + const double x_xj = X_Xj[0]; + const double y_yj = X_Xj[1]; + + { + size_t k = 0; + inv_Vj_wq_detJ_ek[k++] = wq * detT / Vi; + for (; k <= degree; ++k) { + inv_Vj_wq_detJ_ek[k] = x_xj * inv_Vj_wq_detJ_ek[k - 1]; + } + + for (size_t i_y = 1; i_y <= degree; ++i_y) { + const size_t begin_i_y_1 = ((i_y - 1) * (2 * degree - i_y + 4)) / 2; + for (size_t l = 0; l <= degree - i_y; ++l) { + inv_Vj_wq_detJ_ek[k++] = y_yj * inv_Vj_wq_detJ_ek[begin_i_y_1 + l]; + } + } + } + + for (size_t k = 1; k < dimension; ++k) { + mean_of_ejk[k - 1] += inv_Vj_wq_detJ_ek[k]; + } + } +} + +template <typename ConformTransformationT> +void +_computeEjkMean(const QuadratureFormula<3>& quadrature, + const ConformTransformationT& T, + const TinyVector<3>& Xj, + const double Vi, + const size_t degree, + const size_t dimension, + SmallArray<double>& inv_Vj_wq_detJ_ek, + SmallArray<double>& mean_of_ejk) +{ + using Rd = TinyVector<3>; + mean_of_ejk.fill(0); + + for (size_t i_q = 0; i_q < quadrature.numberOfPoints(); ++i_q) { + const double wq = quadrature.weight(i_q); + const Rd& xi_q = quadrature.point(i_q); + const double detT = [&] { + if constexpr (std::is_same_v<TetrahedronTransformation, std::decay_t<decltype(T)>>) { + return T.jacobianDeterminant(); + } else { + return T.jacobianDeterminant(xi_q); + } + }(); + + const Rd X_Xj = T(xi_q) - Xj; + + const double x_xj = X_Xj[0]; + const double y_yj = X_Xj[1]; + const double z_zj = X_Xj[2]; + + { + size_t k = 0; + inv_Vj_wq_detJ_ek[k++] = wq * detT / Vi; + for (; k <= degree; ++k) { + inv_Vj_wq_detJ_ek[k] = x_xj * inv_Vj_wq_detJ_ek[k - 1]; + } + + for (size_t i_y = 1; i_y <= degree; ++i_y) { + const size_t begin_i_y_1 = ((i_y - 1) * (2 * degree - i_y + 4)) / 2; + for (size_t l = 0; l <= degree - i_y; ++l) { + inv_Vj_wq_detJ_ek[k++] = y_yj * inv_Vj_wq_detJ_ek[begin_i_y_1 + l]; + } + } + + for (size_t i_z = 1; i_z <= degree; ++i_z) { + const size_t begin_i_z_1 = i_z * (i_z + 1) * (i_z + 2) / 6 - 1; + for (size_t i_y = 0; i_y <= degree - i_z; ++i_y) { + const size_t begin_i_y_1 = (i_y * (2 * degree - i_y + 3)) / 2 + begin_i_z_1; + for (size_t l = 0; l <= degree - i_y - i_z; ++l) { + inv_Vj_wq_detJ_ek[k++] = z_zj * inv_Vj_wq_detJ_ek[begin_i_y_1 + l]; + } + } + } + } + + for (size_t k = 1; k < dimension; ++k) { + mean_of_ejk[k - 1] += inv_Vj_wq_detJ_ek[k]; + } + } +} + +size_t +PolynomialReconstruction::_getNumberOfColumns( + const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list) const +{ + size_t number_of_columns = 0; + for (auto discrete_function_variant_p : discrete_function_variant_list) { + number_of_columns += std::visit( + [](auto&& discrete_function) -> size_t { + using DiscreteFunctionT = std::decay_t<decltype(discrete_function)>; + if constexpr (is_discrete_function_P0_v<DiscreteFunctionT>) { + using data_type = std::decay_t<typename DiscreteFunctionT::data_type>; + if constexpr (std::is_same_v<data_type, double>) { + return 1; + } else if constexpr (is_tiny_vector_v<data_type> or is_tiny_matrix_v<data_type>) { + return data_type::Dimension; + } else { + // LCOV_EXCL_START + throw UnexpectedError("unexpected data type " + demangle<data_type>()); + // LCOV_EXCL_STOP + } + } else if constexpr (is_discrete_function_P0_vector_v<DiscreteFunctionT>) { + return discrete_function.size(); + } else { + // LCOV_EXCL_START + throw UnexpectedError("unexpected discrete function type"); + // LCOV_EXCL_STOP + } + }, + discrete_function_variant_p->discreteFunction()); + } + return number_of_columns; +} + +template <MeshConcept MeshType> +std::vector<PolynomialReconstruction::MutableDiscreteFunctionDPkVariant> +PolynomialReconstruction::_createMutableDiscreteFunctionDPKVariantList( + const std::shared_ptr<const MeshType>& p_mesh, + const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list) const +{ + std::vector<MutableDiscreteFunctionDPkVariant> mutable_discrete_function_dpk_variant_list; + for (size_t i_discrete_function_variant = 0; i_discrete_function_variant < discrete_function_variant_list.size(); + ++i_discrete_function_variant) { + auto discrete_function_variant = discrete_function_variant_list[i_discrete_function_variant]; + + std::visit( + [&](auto&& discrete_function) { + using DiscreteFunctionT = std::decay_t<decltype(discrete_function)>; + if constexpr (is_discrete_function_P0_v<DiscreteFunctionT>) { + using DataType = std::remove_const_t<std::decay_t<typename DiscreteFunctionT::data_type>>; + mutable_discrete_function_dpk_variant_list.push_back( + DiscreteFunctionDPk<MeshType::Dimension, DataType>(p_mesh, m_descriptor.degree())); + } else if constexpr (is_discrete_function_P0_vector_v<DiscreteFunctionT>) { + using DataType = std::remove_const_t<std::decay_t<typename DiscreteFunctionT::data_type>>; + mutable_discrete_function_dpk_variant_list.push_back( + DiscreteFunctionDPkVector<MeshType::Dimension, DataType>(p_mesh, m_descriptor.degree(), + discrete_function.size())); + } else { + // LCOV_EXCL_START + throw UnexpectedError("unexpected discrete function type"); + // LCOV_EXCL_STOP + } + }, + discrete_function_variant->discreteFunction()); + } + + return mutable_discrete_function_dpk_variant_list; +} + template <MeshConcept MeshType> [[nodiscard]] std::vector<std::shared_ptr<const DiscreteFunctionDPkVariant>> PolynomialReconstruction::_build( @@ -120,35 +339,7 @@ PolynomialReconstruction::_build( using Rd = TinyVector<MeshType::Dimension>; - const size_t number_of_columns = [&]() { - size_t n = 0; - for (auto discrete_function_variant_p : discrete_function_variant_list) { - n += std::visit( - [](auto&& discrete_function) -> size_t { - using DiscreteFunctionT = std::decay_t<decltype(discrete_function)>; - if constexpr (is_discrete_function_P0_v<DiscreteFunctionT>) { - using data_type = std::decay_t<typename DiscreteFunctionT::data_type>; - if constexpr (std::is_same_v<data_type, double>) { - return 1; - } else if constexpr (is_tiny_vector_v<data_type> or is_tiny_matrix_v<data_type>) { - return data_type::Dimension; - } else { - // LCOV_EXCL_START - throw UnexpectedError("unexpected data type " + demangle<data_type>()); - // LCOV_EXCL_STOP - } - } else if constexpr (is_discrete_function_P0_vector_v<DiscreteFunctionT>) { - return discrete_function.size(); - } else { - // LCOV_EXCL_START - throw UnexpectedError("unexpected discrete function type"); - // LCOV_EXCL_STOP - } - }, - discrete_function_variant_p->discreteFunction()); - } - return n; - }(); + const size_t number_of_columns = this->_getNumberOfColumns(discrete_function_variant_list); const size_t basis_dimension = DiscreteFunctionDPk<MeshType::Dimension, double>::BasisViewType::dimensionFromDegree(m_descriptor.degree()); @@ -178,31 +369,8 @@ PolynomialReconstruction::_build( Kokkos::Experimental::UniqueTokenScope::Global> tokens; - std::vector<MutableDiscreteFunctionDPkVariant> mutable_discrete_function_dpk_variant_list; - for (size_t i_discrete_function_variant = 0; i_discrete_function_variant < discrete_function_variant_list.size(); - ++i_discrete_function_variant) { - auto discrete_function_variant = discrete_function_variant_list[i_discrete_function_variant]; - - std::visit( - [&](auto&& discrete_function) { - using DiscreteFunctionT = std::decay_t<decltype(discrete_function)>; - if constexpr (is_discrete_function_P0_v<DiscreteFunctionT>) { - using DataType = std::remove_const_t<std::decay_t<typename DiscreteFunctionT::data_type>>; - mutable_discrete_function_dpk_variant_list.push_back( - DiscreteFunctionDPk<MeshType::Dimension, DataType>(p_mesh, m_descriptor.degree())); - } else if constexpr (is_discrete_function_P0_vector_v<DiscreteFunctionT>) { - using DataType = std::remove_const_t<std::decay_t<typename DiscreteFunctionT::data_type>>; - mutable_discrete_function_dpk_variant_list.push_back( - DiscreteFunctionDPkVector<MeshType::Dimension, DataType>(p_mesh, m_descriptor.degree(), - discrete_function.size())); - } else { - // LCOV_EXCL_START - throw UnexpectedError("unexpected discrete function type"); - // LCOV_EXCL_STOP - } - }, - discrete_function_variant->discreteFunction()); - } + auto mutable_discrete_function_dpk_variant_list = + this->_createMutableDiscreteFunctionDPKVariantList(p_mesh, discrete_function_variant_list); SmallArray<SmallMatrix<double>> A_pool(Kokkos::DefaultExecutionSpace::concurrency()); SmallArray<SmallMatrix<double>> B_pool(Kokkos::DefaultExecutionSpace::concurrency()); @@ -310,39 +478,11 @@ PolynomialReconstruction::_build( } } } else { - SmallArray<double> inv_Vj_wq_detJ_ek = inv_Vj_wq_detJ_ek_pool[t]; - SmallArray<double> mean_j_of_ejk = mean_j_of_ejk_pool[t]; - SmallArray<double> mean_i_of_ejk = mean_i_of_ejk_pool[t]; + SmallArray<double>& inv_Vj_wq_detJ_ek = inv_Vj_wq_detJ_ek_pool[t]; + SmallArray<double>& mean_j_of_ejk = mean_j_of_ejk_pool[t]; + SmallArray<double>& mean_i_of_ejk = mean_i_of_ejk_pool[t]; if constexpr (MeshType::Dimension == 1) { - auto compute_mean_ejk = [&inv_Vj_wq_detJ_ek](const auto& quadrature, const auto& T, const Rd& Xj, - const double Vi, const size_t degree, const size_t dimension, - SmallArray<double>& mean_of_ejk) { - mean_of_ejk.fill(0); - - for (size_t i_q = 0; i_q < quadrature.numberOfPoints(); ++i_q) { - const double wq = quadrature.weight(i_q); - const Rd& xi_q = quadrature.point(i_q); - const double detT = T.jacobianDeterminant(); - - const Rd X_Xj = T(xi_q) - Xj; - - const double x_xj = X_Xj[0]; - - { - size_t k = 0; - inv_Vj_wq_detJ_ek[k++] = wq * detT / Vi; - for (; k <= degree; ++k) { - inv_Vj_wq_detJ_ek[k] = x_xj * inv_Vj_wq_detJ_ek[k - 1]; - } - } - - for (size_t k = 1; k < dimension; ++k) { - mean_of_ejk[k - 1] += inv_Vj_wq_detJ_ek[k]; - } - } - }; - const Rd& Xj = xj[cell_j_id]; if (cell_type[cell_j_id] == CellType::Line) { @@ -353,7 +493,8 @@ PolynomialReconstruction::_build( const auto& quadrature = QuadratureManager::instance().getLineFormula(GaussLegendreQuadratureDescriptor{m_descriptor.degree()}); - compute_mean_ejk(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension, mean_j_of_ejk); + _computeEjkMean(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension, + inv_Vj_wq_detJ_ek, mean_j_of_ejk); } else { throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type[cell_j_id])}); @@ -370,8 +511,8 @@ PolynomialReconstruction::_build( const auto& quadrature = QuadratureManager::instance().getLineFormula(GaussQuadratureDescriptor{m_descriptor.degree()}); - compute_mean_ejk(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension, - mean_i_of_ejk); + _computeEjkMean(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension, + inv_Vj_wq_detJ_ek, mean_i_of_ejk); } else { throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type[cell_i_id])}); @@ -382,48 +523,6 @@ PolynomialReconstruction::_build( } } } else if constexpr (MeshType::Dimension == 2) { - auto compute_mean_ejk = [&inv_Vj_wq_detJ_ek](const auto& quadrature, const auto& T, const Rd& Xj, - const double Vi, const size_t degree, const size_t dimension, - SmallArray<double>& mean_of_ejk) { - mean_of_ejk.fill(0); - - for (size_t i_q = 0; i_q < quadrature.numberOfPoints(); ++i_q) { - const double wq = quadrature.weight(i_q); - const Rd& xi_q = quadrature.point(i_q); - const double detT = [&] { - if constexpr (std::is_same_v<TriangleTransformation<2>, std::decay_t<decltype(T)>>) { - return T.jacobianDeterminant(); - } else { - return T.jacobianDeterminant(xi_q); - } - }(); - - const Rd X_Xj = T(xi_q) - Xj; - - const double x_xj = X_Xj[0]; - const double y_yj = X_Xj[1]; - - { - size_t k = 0; - inv_Vj_wq_detJ_ek[k++] = wq * detT / Vi; - for (; k <= degree; ++k) { - inv_Vj_wq_detJ_ek[k] = x_xj * inv_Vj_wq_detJ_ek[k - 1]; - } - - for (size_t i_y = 1; i_y <= degree; ++i_y) { - const size_t begin_i_y_1 = ((i_y - 1) * (2 * degree - i_y + 4)) / 2; - for (size_t l = 0; l <= degree - i_y; ++l) { - inv_Vj_wq_detJ_ek[k++] = y_yj * inv_Vj_wq_detJ_ek[begin_i_y_1 + l]; - } - } - } - - for (size_t k = 1; k < dimension; ++k) { - mean_of_ejk[k - 1] += inv_Vj_wq_detJ_ek[k]; - } - } - }; - const Rd& Xj = xj[cell_j_id]; if (cell_type[cell_j_id] == CellType::Triangle) { @@ -434,7 +533,8 @@ PolynomialReconstruction::_build( const auto& quadrature = QuadratureManager::instance().getTriangleFormula(GaussQuadratureDescriptor{m_descriptor.degree()}); - compute_mean_ejk(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension, mean_j_of_ejk); + _computeEjkMean(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension, + inv_Vj_wq_detJ_ek, mean_j_of_ejk); } else if (cell_type[cell_j_id] == CellType::Quadrangle) { auto cell_node = cell_to_node_matrix[cell_j_id]; @@ -444,7 +544,8 @@ PolynomialReconstruction::_build( const auto& quadrature = QuadratureManager::instance().getSquareFormula( GaussLegendreQuadratureDescriptor{m_descriptor.degree() + 1}); - compute_mean_ejk(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension, mean_j_of_ejk); + _computeEjkMean(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension, + inv_Vj_wq_detJ_ek, mean_j_of_ejk); } else { throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type[cell_j_id])}); @@ -461,8 +562,8 @@ PolynomialReconstruction::_build( const auto& quadrature = QuadratureManager::instance().getTriangleFormula(GaussQuadratureDescriptor{m_descriptor.degree()}); - compute_mean_ejk(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension, - mean_i_of_ejk); + _computeEjkMean(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension, + inv_Vj_wq_detJ_ek, mean_i_of_ejk); } else if (cell_type[cell_i_id] == CellType::Quadrangle) { const SquareTransformation<2> T{xr[cell_node[0]], xr[cell_node[1]], xr[cell_node[2]], xr[cell_node[3]]}; @@ -470,8 +571,8 @@ PolynomialReconstruction::_build( const auto& quadrature = QuadratureManager::instance().getSquareFormula( GaussLegendreQuadratureDescriptor{m_descriptor.degree() + 1}); - compute_mean_ejk(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension, - mean_i_of_ejk); + _computeEjkMean(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension, + inv_Vj_wq_detJ_ek, mean_i_of_ejk); } else { throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type[cell_i_id])}); @@ -483,59 +584,6 @@ PolynomialReconstruction::_build( } } else if constexpr (MeshType::Dimension == 3) { - auto compute_mean_ejk = [&inv_Vj_wq_detJ_ek](const auto& quadrature, const auto& T, const Rd& Xj, - const double Vi, const size_t degree, const size_t dimension, - SmallArray<double>& mean_of_ejk) { - mean_of_ejk.fill(0); - - for (size_t i_q = 0; i_q < quadrature.numberOfPoints(); ++i_q) { - const double wq = quadrature.weight(i_q); - const Rd& xi_q = quadrature.point(i_q); - const double detT = [&] { - if constexpr (std::is_same_v<TetrahedronTransformation, std::decay_t<decltype(T)>>) { - return T.jacobianDeterminant(); - } else { - return T.jacobianDeterminant(xi_q); - } - }(); - - const Rd X_Xj = T(xi_q) - Xj; - - const double x_xj = X_Xj[0]; - const double y_yj = X_Xj[1]; - const double z_zj = X_Xj[2]; - - { - size_t k = 0; - inv_Vj_wq_detJ_ek[k++] = wq * detT / Vi; - for (; k <= degree; ++k) { - inv_Vj_wq_detJ_ek[k] = x_xj * inv_Vj_wq_detJ_ek[k - 1]; - } - - for (size_t i_y = 1; i_y <= degree; ++i_y) { - const size_t begin_i_y_1 = ((i_y - 1) * (2 * degree - i_y + 4)) / 2; - for (size_t l = 0; l <= degree - i_y; ++l) { - inv_Vj_wq_detJ_ek[k++] = y_yj * inv_Vj_wq_detJ_ek[begin_i_y_1 + l]; - } - } - - for (size_t i_z = 1; i_z <= degree; ++i_z) { - const size_t begin_i_z_1 = i_z * (i_z + 1) * (i_z + 2) / 6 - 1; - for (size_t i_y = 0; i_y <= degree - i_z; ++i_y) { - const size_t begin_i_y_1 = (i_y * (2 * degree - i_y + 3)) / 2 + begin_i_z_1; - for (size_t l = 0; l <= degree - i_y - i_z; ++l) { - inv_Vj_wq_detJ_ek[k++] = z_zj * inv_Vj_wq_detJ_ek[begin_i_y_1 + l]; - } - } - } - } - - for (size_t k = 1; k < dimension; ++k) { - mean_of_ejk[k - 1] += inv_Vj_wq_detJ_ek[k]; - } - } - }; - const Rd& Xj = xj[cell_j_id]; if (cell_type[cell_j_id] == CellType::Tetrahedron) { @@ -546,7 +594,8 @@ PolynomialReconstruction::_build( const auto& quadrature = QuadratureManager::instance().getTetrahedronFormula(GaussQuadratureDescriptor{m_descriptor.degree()}); - compute_mean_ejk(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension, mean_j_of_ejk); + _computeEjkMean(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension, + inv_Vj_wq_detJ_ek, mean_j_of_ejk); } else if (cell_type[cell_j_id] == CellType::Prism) { auto cell_node = cell_to_node_matrix[cell_j_id]; @@ -557,7 +606,8 @@ PolynomialReconstruction::_build( const auto& quadrature = QuadratureManager::instance().getPrismFormula(GaussQuadratureDescriptor{m_descriptor.degree() + 1}); - compute_mean_ejk(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension, mean_j_of_ejk); + _computeEjkMean(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension, + inv_Vj_wq_detJ_ek, mean_j_of_ejk); } else if (cell_type[cell_j_id] == CellType::Pyramid) { auto cell_node = cell_to_node_matrix[cell_j_id]; @@ -568,7 +618,8 @@ PolynomialReconstruction::_build( const auto& quadrature = QuadratureManager::instance().getPyramidFormula(GaussQuadratureDescriptor{m_descriptor.degree() + 1}); - compute_mean_ejk(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension, mean_j_of_ejk); + _computeEjkMean(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension, + inv_Vj_wq_detJ_ek, mean_j_of_ejk); } else if (cell_type[cell_j_id] == CellType::Hexahedron) { auto cell_node = cell_to_node_matrix[cell_j_id]; @@ -579,7 +630,8 @@ PolynomialReconstruction::_build( const auto& quadrature = QuadratureManager::instance().getCubeFormula( GaussLegendreQuadratureDescriptor{m_descriptor.degree() + 1}); - compute_mean_ejk(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension, mean_j_of_ejk); + _computeEjkMean(quadrature, T, Xj, Vj[cell_j_id], m_descriptor.degree(), basis_dimension, + inv_Vj_wq_detJ_ek, mean_j_of_ejk); } else { throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type[cell_j_id])}); @@ -597,8 +649,8 @@ PolynomialReconstruction::_build( const auto& quadrature = QuadratureManager::instance().getTetrahedronFormula(GaussQuadratureDescriptor{m_descriptor.degree()}); - compute_mean_ejk(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension, - mean_i_of_ejk); + _computeEjkMean(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension, + inv_Vj_wq_detJ_ek, mean_i_of_ejk); } else if (cell_type[cell_i_id] == CellType::Prism) { const PrismTransformation T{xr[cell_node[0]], xr[cell_node[1]], xr[cell_node[2]], // @@ -607,8 +659,8 @@ PolynomialReconstruction::_build( const auto& quadrature = QuadratureManager::instance().getPrismFormula(GaussQuadratureDescriptor{m_descriptor.degree() + 1}); - compute_mean_ejk(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension, - mean_i_of_ejk); + _computeEjkMean(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension, + inv_Vj_wq_detJ_ek, mean_i_of_ejk); } else if (cell_type[cell_i_id] == CellType::Pyramid) { const PyramidTransformation T{xr[cell_node[0]], xr[cell_node[1]], xr[cell_node[2]], xr[cell_node[3]], @@ -617,8 +669,8 @@ PolynomialReconstruction::_build( const auto& quadrature = QuadratureManager::instance().getPyramidFormula(GaussQuadratureDescriptor{m_descriptor.degree() + 1}); - compute_mean_ejk(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension, - mean_i_of_ejk); + _computeEjkMean(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension, + inv_Vj_wq_detJ_ek, mean_i_of_ejk); } else if (cell_type[cell_i_id] == CellType::Hexahedron) { const CubeTransformation T{xr[cell_node[0]], xr[cell_node[1]], xr[cell_node[2]], xr[cell_node[3]], @@ -627,8 +679,8 @@ PolynomialReconstruction::_build( const auto& quadrature = QuadratureManager::instance().getCubeFormula( GaussLegendreQuadratureDescriptor{m_descriptor.degree() + 1}); - compute_mean_ejk(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension, - mean_i_of_ejk); + _computeEjkMean(quadrature, T, Xj, Vj[cell_i_id], m_descriptor.degree(), basis_dimension, + inv_Vj_wq_detJ_ek, mean_i_of_ejk); } else { throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type[cell_i_id])}); diff --git a/src/scheme/PolynomialReconstruction.hpp b/src/scheme/PolynomialReconstruction.hpp index c0da0f260..f52314872 100644 --- a/src/scheme/PolynomialReconstruction.hpp +++ b/src/scheme/PolynomialReconstruction.hpp @@ -29,242 +29,20 @@ class PolynomialReconstruction const PolynomialReconstructionDescriptor m_descriptor; + size_t _getNumberOfColumns( + const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list) const; + + template <MeshConcept MeshType> + std::vector<MutableDiscreteFunctionDPkVariant> _createMutableDiscreteFunctionDPKVariantList( + const std::shared_ptr<const MeshType>& p_mesh, + const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list) const; + template <MeshConcept MeshType> [[nodiscard]] std::vector<std::shared_ptr<const DiscreteFunctionDPkVariant>> _build( const std::shared_ptr<const MeshType>& p_mesh, const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list) const; public: - template <MeshConcept MeshType, typename DataType> - PUGS_INLINE DiscreteFunctionDPk<MeshType::Dimension, std::remove_const_t<DataType>> - build(const MeshType& mesh, const DiscreteFunctionP0<DataType> p0_function) const - { - using Rd = TinyVector<MeshType::Dimension>; - - const size_t degree = 1; - const Stencil& stencil = StencilManager::instance().getStencil(mesh.connectivity()); - - auto xj = MeshDataManager::instance().getMeshData(mesh).xj(); - - auto cell_is_owned = mesh.connectivity().cellIsOwned(); - - const size_t max_stencil_size = [&]() { - size_t max_size = 0; - for (CellId cell_id = 0; cell_id < mesh.numberOfCells(); ++cell_id) { - auto stencil_cell_list = stencil[cell_id]; - if (cell_is_owned[cell_id] and stencil_cell_list.size() > max_size) { - max_size = stencil_cell_list.size(); - } - } - return max_size; - }(); - - Kokkos::Experimental::UniqueToken<Kokkos::DefaultExecutionSpace::execution_space, - Kokkos::Experimental::UniqueTokenScope::Global> - tokens; - - DiscreteFunctionDPk<MeshType::Dimension, std::remove_const_t<DataType>> dpk{mesh.meshVariant(), degree}; - - if constexpr (is_polygonal_mesh_v<MeshType>) { - if constexpr (std::is_arithmetic_v<DataType>) { - SmallArray<SmallMatrix<double>> A_pool(Kokkos::DefaultExecutionSpace::concurrency()); - SmallArray<SmallVector<double>> b_pool(Kokkos::DefaultExecutionSpace::concurrency()); - for (size_t i = 0; i < A_pool.size(); ++i) { - A_pool[i] = SmallMatrix<double>(max_stencil_size, MeshType::Dimension); - b_pool[i] = SmallVector<double>(max_stencil_size); - } - - parallel_for( - mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_j_id) { - if (cell_is_owned[cell_j_id]) { - const int32_t t = tokens.acquire(); - - auto stencil_cell_list = stencil[cell_j_id]; - - ShrinkVectorView b(b_pool[t], stencil_cell_list.size()); - - const double pj = p0_function[cell_j_id]; - for (size_t i = 0; i < stencil_cell_list.size(); ++i) { - const CellId cell_i_id = stencil_cell_list[i]; - - b[i] = p0_function[cell_i_id] - pj; - } - - ShrinkMatrixView A(A_pool[t], stencil_cell_list.size()); - - const Rd& Xj = xj[cell_j_id]; - - for (size_t i = 0; i < stencil_cell_list.size(); ++i) { - const CellId cell_i_id = stencil_cell_list[i]; - const Rd Xi_Xj = xj[cell_i_id] - Xj; - for (size_t l = 0; l < MeshType::Dimension; ++l) { - A(i, l) = Xi_Xj[l]; - } - } - - for (size_t i = 0; i < stencil_cell_list.size(); ++i) { - const CellId cell_i_id = stencil_cell_list[i]; - const double weight = 1. / l2Norm(xj[cell_i_id] - Xj); - for (size_t l = 0; l < MeshType::Dimension; ++l) { - A(i, l) *= weight; - } - b[i] *= weight; - } - - SmallVector<double> x(MeshType::Dimension); - Givens::solveInPlace(A, x, b); - - auto dpk_j = dpk.coefficients(cell_j_id); - - dpk_j[0] = pj; - - for (size_t l = 0; l < MeshType::Dimension; ++l) { - dpk_j[1 + l] = x[l]; - } - - tokens.release(t); - } - }); - } else if constexpr (is_tiny_vector_v<DataType>) { - SmallArray<SmallMatrix<double>> A_pool(Kokkos::DefaultExecutionSpace::concurrency()); - SmallArray<SmallMatrix<double>> B_pool(Kokkos::DefaultExecutionSpace::concurrency()); - for (size_t i = 0; i < A_pool.size(); ++i) { - A_pool[i] = SmallMatrix<double>(max_stencil_size, MeshType::Dimension); - B_pool[i] = SmallMatrix<double>(max_stencil_size, DataType::Dimension); - } - - parallel_for( - mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_j_id) { - if (cell_is_owned[cell_j_id]) { - const int32_t t = tokens.acquire(); - - auto stencil_cell_list = stencil[cell_j_id]; - ShrinkMatrixView B(B_pool[t], stencil_cell_list.size()); - - const DataType& pj = p0_function[cell_j_id]; - for (size_t i = 0; i < stencil_cell_list.size(); ++i) { - const CellId cell_i_id = stencil_cell_list[i]; - const DataType& pi_pj = p0_function[cell_i_id] - pj; - for (size_t k = 0; k < DataType::Dimension; ++k) { - B(i, k) = pi_pj[k]; - } - } - - ShrinkMatrixView A(A_pool[t], stencil_cell_list.size()); - - const Rd& Xj = xj[cell_j_id]; - for (size_t i = 0; i < stencil_cell_list.size(); ++i) { - const CellId cell_i_id = stencil_cell_list[i]; - const Rd Xi_Xj = xj[cell_i_id] - Xj; - for (size_t l = 0; l < MeshType::Dimension; ++l) { - A(i, l) = Xi_Xj[l]; - } - } - - for (size_t i = 0; i < stencil_cell_list.size(); ++i) { - const CellId cell_i_id = stencil_cell_list[i]; - const double weight = 1. / l2Norm(xj[cell_i_id] - Xj); - for (size_t l = 0; l < MeshType::Dimension - 1; ++l) { - A(i, l) *= weight; - } - for (size_t l = 0; l < DataType::Dimension; ++l) { - B(i, l) *= weight; - } - } - - TinyMatrix<MeshType::Dimension, DataType::Dimension> X; - Givens::solveCollectionInPlace(A, X, B); - - auto dpk_j = dpk.coefficients(cell_j_id); - - dpk_j[0] = pj; - for (size_t i = 0; i < MeshType::Dimension; ++i) { - auto& dpk_j_ip1 = dpk_j[i + 1]; - for (size_t k = 0; k < DataType::Dimension; ++k) { - dpk_j_ip1[k] = X(i, k); - } - } - - tokens.release(t); - } - }); - } else if constexpr (is_tiny_matrix_v<DataType>) { - SmallArray<SmallMatrix<double>> A_pool(Kokkos::DefaultExecutionSpace::concurrency()); - SmallArray<SmallMatrix<double>> B_pool(Kokkos::DefaultExecutionSpace::concurrency()); - for (size_t i = 0; i < A_pool.size(); ++i) { - A_pool[i] = SmallMatrix<double>(max_stencil_size, MeshType::Dimension); - B_pool[i] = SmallMatrix<double>(max_stencil_size, DataType::Dimension); - } - - parallel_for( - mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_j_id) { - if (cell_is_owned[cell_j_id]) { - const int32_t t = tokens.acquire(); - - auto stencil_cell_list = stencil[cell_j_id]; - ShrinkMatrixView B(B_pool[t], stencil_cell_list.size()); - - const DataType& pj = p0_function[cell_j_id]; - for (size_t i = 0; i < stencil_cell_list.size(); ++i) { - const CellId cell_i_id = stencil_cell_list[i]; - const DataType& pi_pj = p0_function[cell_i_id] - pj; - for (size_t k = 0; k < DataType::NumberOfRows; ++k) { - for (size_t l = 0; l < DataType::NumberOfColumns; ++l) { - B(i, k * DataType::NumberOfColumns + l) = pi_pj(k, l); - } - } - } - - ShrinkMatrixView A(A_pool[t], stencil_cell_list.size()); - - const Rd& Xj = xj[cell_j_id]; - - for (size_t i = 0; i < stencil_cell_list.size(); ++i) { - const CellId cell_i_id = stencil_cell_list[i]; - const Rd Xi_Xj = xj[cell_i_id] - Xj; - for (size_t l = 0; l < MeshType::Dimension; ++l) { - A(i, l) = Xi_Xj[l]; - } - } - - for (size_t i = 0; i < stencil_cell_list.size(); ++i) { - const CellId cell_i_id = stencil_cell_list[i]; - const double weight = 1. / l2Norm(xj[cell_i_id] - Xj); - for (size_t l = 0; l < MeshType::Dimension - 1; ++l) { - A(i, l) *= weight; - } - for (size_t l = 0; l < DataType::Dimension; ++l) { - B(i, l) *= weight; - } - } - - TinyMatrix<MeshType::Dimension, DataType::Dimension> X; - Givens::solveCollectionInPlace(A, X, B); - - auto dpk_j = dpk.coefficients(cell_j_id); - dpk_j[0] = pj; - - for (size_t i = 0; i < MeshType::Dimension; ++i) { - auto& dpk_j_ip1 = dpk_j[i + 1]; - for (size_t k = 0; k < DataType::NumberOfRows; ++k) { - for (size_t l = 0; l < DataType::NumberOfColumns; ++l) { - dpk_j_ip1(k, l) = X(i, k * DataType::NumberOfColumns + l); - } - } - } - - tokens.release(t); - } - }); - } else { - throw NotImplementedError("dealing with " + demangle<DataType>()); - } - } - - synchronize(dpk.cellArrays()); - return dpk; - } - [[nodiscard]] std::vector<std::shared_ptr<const DiscreteFunctionDPkVariant>> build( const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list) const; diff --git a/src/scheme/test_reconstruction.cpp b/src/scheme/test_reconstruction.cpp index 42ec98cc9..3d255a547 100644 --- a/src/scheme/test_reconstruction.cpp +++ b/src/scheme/test_reconstruction.cpp @@ -3,57 +3,6 @@ #include <scheme/PolynomialReconstruction.hpp> #include <utils/Timer.hpp> -void -test_reconstruction(const std::shared_ptr<const MeshVariant>& mesh_v, - const std::shared_ptr<const DiscreteFunctionVariant>& discrete_function_v) -{ - std::cout << "** one variable at a time (30 times)\n"; - PolynomialReconstructionDescriptor descriptor{1}; - - std::visit( - [&](auto&& p_mesh) { - std::visit( - [&](auto&& discrete_function) { - using DiscreteFunctionT = std::decay_t<decltype(discrete_function)>; - PolynomialReconstruction reconstruction{descriptor}; - if constexpr (is_discrete_function_P0_v<DiscreteFunctionT>) { - Timer t; - for (size_t i = 0; i < 30; ++i) { - auto res = reconstruction.build(*p_mesh, discrete_function); - } - t.pause(); - std::cout << "t = " << t << '\n'; - } - }, - discrete_function_v->discreteFunction()); - }, - mesh_v->variant()); - - std::cout << "finished!\n"; -} - -void -test_reconstruction_one(const std::shared_ptr<const MeshVariant>& mesh_v, - const std::shared_ptr<const DiscreteFunctionVariant>& discrete_function_v) -{ - PolynomialReconstructionDescriptor descriptor{1}; - std::visit( - [&](auto&& p_mesh) { - std::visit( - [&](auto&& discrete_function) { - using DiscreteFunctionT = std::decay_t<decltype(discrete_function)>; - PolynomialReconstruction reconstruction{descriptor}; - if constexpr (is_discrete_function_P0_v<DiscreteFunctionT>) { - for (size_t i = 0; i < 30; ++i) { - auto res = reconstruction.build(*p_mesh, discrete_function); - } - } - }, - discrete_function_v->discreteFunction()); - }, - mesh_v->variant()); -} - void test_reconstruction(const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list) { diff --git a/src/scheme/test_reconstruction.hpp b/src/scheme/test_reconstruction.hpp index f74bf0781..6620acd44 100644 --- a/src/scheme/test_reconstruction.hpp +++ b/src/scheme/test_reconstruction.hpp @@ -7,9 +7,6 @@ #include <vector> -void test_reconstruction(const std::shared_ptr<const MeshVariant>& mesh_v, - const std::shared_ptr<const DiscreteFunctionVariant>& discrete_function_variant_list); - void test_reconstruction( const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list); -- GitLab