From 6a5fcd4b13b81249de3d1f752908a732dc8d3772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Del=20Pino?= <stephane.delpino44@gmail.com> Date: Wed, 30 Apr 2025 18:50:56 +0200 Subject: [PATCH] Begin code clean-up --- src/scheme/PolynomialReconstruction.cpp | 937 +++++++++++++++--------- src/scheme/PolynomialReconstruction.hpp | 9 + 2 files changed, 585 insertions(+), 361 deletions(-) diff --git a/src/scheme/PolynomialReconstruction.cpp b/src/scheme/PolynomialReconstruction.cpp index 2201e5f0f..661630187 100644 --- a/src/scheme/PolynomialReconstruction.cpp +++ b/src/scheme/PolynomialReconstruction.cpp @@ -49,126 +49,64 @@ symmetrize_coordinates(const TinyVector<Dimension>& origin, return u - 2 * dot(u - origin, normal) * normal; } -class PolynomialReconstruction::MutableDiscreteFunctionDPkVariant +template <MeshConcept MeshType> +class PolynomialReconstruction::CellCenterReconstructionMatrixBuilder { - public: - using Variant = std::variant<DiscreteFunctionDPk<1, double>, - DiscreteFunctionDPk<1, TinyVector<1>>, - DiscreteFunctionDPk<1, TinyVector<2>>, - DiscreteFunctionDPk<1, TinyVector<3>>, - DiscreteFunctionDPk<1, TinyMatrix<1>>, - DiscreteFunctionDPk<1, TinyMatrix<2>>, - DiscreteFunctionDPk<1, TinyMatrix<3>>, - - DiscreteFunctionDPk<2, double>, - DiscreteFunctionDPk<2, TinyVector<1>>, - DiscreteFunctionDPk<2, TinyVector<2>>, - DiscreteFunctionDPk<2, TinyVector<3>>, - DiscreteFunctionDPk<2, TinyMatrix<1>>, - DiscreteFunctionDPk<2, TinyMatrix<2>>, - DiscreteFunctionDPk<2, TinyMatrix<3>>, - - DiscreteFunctionDPk<3, double>, - DiscreteFunctionDPk<3, TinyVector<1>>, - DiscreteFunctionDPk<3, TinyVector<2>>, - DiscreteFunctionDPk<3, TinyVector<3>>, - DiscreteFunctionDPk<3, TinyMatrix<1>>, - DiscreteFunctionDPk<3, TinyMatrix<2>>, - DiscreteFunctionDPk<3, TinyMatrix<3>>, - - DiscreteFunctionDPkVector<1, double>, - DiscreteFunctionDPkVector<1, TinyVector<1>>, - DiscreteFunctionDPkVector<1, TinyVector<2>>, - DiscreteFunctionDPkVector<1, TinyVector<3>>, - DiscreteFunctionDPkVector<1, TinyMatrix<1>>, - DiscreteFunctionDPkVector<1, TinyMatrix<2>>, - DiscreteFunctionDPkVector<1, TinyMatrix<3>>, - - DiscreteFunctionDPkVector<2, double>, - DiscreteFunctionDPkVector<2, TinyVector<1>>, - DiscreteFunctionDPkVector<2, TinyVector<2>>, - DiscreteFunctionDPkVector<2, TinyVector<3>>, - DiscreteFunctionDPkVector<2, TinyMatrix<1>>, - DiscreteFunctionDPkVector<2, TinyMatrix<2>>, - DiscreteFunctionDPkVector<2, TinyMatrix<3>>, + private: + using Rd = TinyVector<MeshType::Dimension>; - DiscreteFunctionDPkVector<3, double>, - DiscreteFunctionDPkVector<3, TinyVector<1>>, - DiscreteFunctionDPkVector<3, TinyVector<2>>, - DiscreteFunctionDPkVector<3, TinyVector<3>>, - DiscreteFunctionDPkVector<3, TinyMatrix<1>>, - DiscreteFunctionDPkVector<3, TinyMatrix<2>>, - DiscreteFunctionDPkVector<3, TinyMatrix<3>>>; + const size_t m_basis_dimension; + const SmallArray<const Rd> m_symmetry_origin_list; + const SmallArray<const Rd> m_symmetry_normal_list; - private: - Variant m_mutable_discrete_function_dpk; + const CellToCellStencilArray& m_stencil_array; + const CellValue<const Rd> m_xj; public: - PUGS_INLINE - const Variant& - mutableDiscreteFunctionDPk() const - { - return m_mutable_discrete_function_dpk; - } - - template <typename DiscreteFunctionDPkT> - PUGS_INLINE auto&& - get() const + template <typename MatrixType> + void + build(const CellId cell_j_id, ShrinkMatrixView<MatrixType>& A) { - static_assert(is_discrete_function_dpk_v<DiscreteFunctionDPkT>, "invalid template argument"); - -#ifndef NDEBUG - if (not std::holds_alternative<DiscreteFunctionDPkT>(this->m_mutable_discrete_function_dpk)) { - std::ostringstream error_msg; - error_msg << "invalid discrete function type\n"; - error_msg << "- required " << rang::fgB::red << demangle<DiscreteFunctionDPkT>() << rang::fg::reset << '\n'; - error_msg << "- contains " << rang::fgB::yellow - << std::visit([](auto&& f) -> std::string { return demangle<decltype(f)>(); }, - this->m_mutable_discrete_function_dpk) - << rang::fg::reset; - throw NormalError(error_msg.str()); + const auto& stencil_cell_list = m_stencil_array[cell_j_id]; + + const Rd& Xj = m_xj[cell_j_id]; + size_t index = 0; + for (size_t i = 0; i < stencil_cell_list.size(); ++i, ++index) { + const CellId cell_i_id = stencil_cell_list[i]; + const Rd Xi_Xj = m_xj[cell_i_id] - Xj; + for (size_t l = 0; l < m_basis_dimension - 1; ++l) { + A(index, l) = Xi_Xj[l]; + } + } + for (size_t i_symmetry = 0; i_symmetry < m_stencil_array.symmetryBoundaryStencilArrayList().size(); ++i_symmetry) { + auto& ghost_stencil = m_stencil_array.symmetryBoundaryStencilArrayList()[i_symmetry].stencilArray(); + auto ghost_cell_list = ghost_stencil[cell_j_id]; + + const Rd& origin = m_symmetry_origin_list[i_symmetry]; + const Rd& normal = m_symmetry_normal_list[i_symmetry]; + + for (size_t i = 0; i < ghost_cell_list.size(); ++i, ++index) { + const CellId cell_i_id = ghost_cell_list[i]; + const Rd Xi_Xj = symmetrize_coordinates(origin, normal, m_xj[cell_i_id]) - Xj; + for (size_t l = 0; l < m_basis_dimension - 1; ++l) { + A(index, l) = Xi_Xj[l]; + } + } } -#endif // NDEBUG - - return std::get<DiscreteFunctionDPkT>(this->mutableDiscreteFunctionDPk()); - } - - template <size_t Dimension, typename DataType> - MutableDiscreteFunctionDPkVariant(const DiscreteFunctionDPk<Dimension, DataType>& discrete_function_dpk) - : m_mutable_discrete_function_dpk{discrete_function_dpk} - { - static_assert(std::is_same_v<DataType, double> or // - std::is_same_v<DataType, TinyVector<1, double>> or // - std::is_same_v<DataType, TinyVector<2, double>> or // - std::is_same_v<DataType, TinyVector<3, double>> or // - std::is_same_v<DataType, TinyMatrix<1, 1, double>> or // - std::is_same_v<DataType, TinyMatrix<2, 2, double>> or // - std::is_same_v<DataType, TinyMatrix<3, 3, double>>, - "DiscreteFunctionDPk with this DataType is not allowed in variant"); - } - - template <size_t Dimension, typename DataType> - MutableDiscreteFunctionDPkVariant(const DiscreteFunctionDPkVector<Dimension, DataType>& discrete_function_dpk) - : m_mutable_discrete_function_dpk{discrete_function_dpk} - { - static_assert(std::is_same_v<DataType, double> or // - std::is_same_v<DataType, TinyVector<1, double>> or // - std::is_same_v<DataType, TinyVector<2, double>> or // - std::is_same_v<DataType, TinyVector<3, double>> or // - std::is_same_v<DataType, TinyMatrix<1, 1, double>> or // - std::is_same_v<DataType, TinyMatrix<2, 2, double>> or // - std::is_same_v<DataType, TinyMatrix<3, 3, double>>, - "DiscreteFunctionDPkVector with this DataType is not allowed in variant"); } - MutableDiscreteFunctionDPkVariant& operator=(MutableDiscreteFunctionDPkVariant&&) = default; - MutableDiscreteFunctionDPkVariant& operator=(const MutableDiscreteFunctionDPkVariant&) = default; - - MutableDiscreteFunctionDPkVariant(const MutableDiscreteFunctionDPkVariant&) = default; - MutableDiscreteFunctionDPkVariant(MutableDiscreteFunctionDPkVariant&&) = default; - - MutableDiscreteFunctionDPkVariant() = delete; - ~MutableDiscreteFunctionDPkVariant() = default; + CellCenterReconstructionMatrixBuilder(const SmallArray<const Rd>& symmetry_origin_list, + const SmallArray<const Rd>& symmetry_normal_list, + const CellToCellStencilArray& stencil_array, + const CellValue<const Rd>& xj) + : m_basis_dimension{DiscreteFunctionDPk<MeshType::Dimension, double>::BasisViewType::dimensionFromDegree(1)}, + m_symmetry_origin_list{symmetry_origin_list}, + m_symmetry_normal_list{symmetry_normal_list}, + m_stencil_array{stencil_array}, + m_xj{xj} + {} + + ~CellCenterReconstructionMatrixBuilder() = default; }; template <typename ConformTransformationT> @@ -179,7 +117,7 @@ _computeEjkMean(const QuadratureFormula<1>& quadrature, const double Vi, const size_t degree, const size_t dimension, - SmallArray<double>& inv_Vj_wq_detJ_ek, + const SmallArray<double>& inv_Vj_wq_detJ_ek, SmallArray<double>& mean_of_ejk) { using Rd = TinyVector<1>; @@ -216,7 +154,7 @@ _computeEjkMean(const QuadratureFormula<2>& quadrature, const double Vi, const size_t degree, const size_t dimension, - SmallArray<double>& inv_Vj_wq_detJ_ek, + const SmallArray<double>& inv_Vj_wq_detJ_ek, SmallArray<double>& mean_of_ejk) { using Rd = TinyVector<2>; @@ -269,7 +207,7 @@ _computeEjkMean(const QuadratureFormula<3>& quadrature, const double Vi, const size_t degree, const size_t dimension, - SmallArray<double>& inv_Vj_wq_detJ_ek, + const SmallArray<double>& inv_Vj_wq_detJ_ek, SmallArray<double>& mean_of_ejk) { #warning Compute this one for all and rework design @@ -358,7 +296,7 @@ void _computeEjkMean(const TinyVector<Dimension>& Xj, const double Vi, const size_t degree, const size_t basis_dimension, - SmallArray<double>& inv_Vj_wq_detJ_ek, + const SmallArray<double>& inv_Vj_wq_detJ_ek, SmallArray<double>& mean_of_ejk); template <typename NodeListT> @@ -370,7 +308,7 @@ _computeEjkMean(const TinyVector<1>& Xj, const double Vi, const size_t degree, const size_t basis_dimension, - SmallArray<double>& inv_Vj_wq_detJ_ek, + const SmallArray<double>& inv_Vj_wq_detJ_ek, SmallArray<double>& mean_of_ejk) { if (cell_type == CellType::Line) { @@ -396,7 +334,7 @@ _computeEjkMeanInSymmetricCell(const TinyVector<1>& origin, const double Vi, const size_t degree, const size_t basis_dimension, - SmallArray<double>& inv_Vj_wq_detJ_ek, + const SmallArray<double>& inv_Vj_wq_detJ_ek, SmallArray<double>& mean_of_ejk) { if (cell_type == CellType::Line) { @@ -414,6 +352,308 @@ _computeEjkMeanInSymmetricCell(const TinyVector<1>& origin, } } +template <typename NodeListT> +void +_computeEjkMean(const TinyVector<2>& Xj, + const NodeValue<const TinyVector<2>>& xr, + const NodeListT& node_list, + const CellType& cell_type, + const double Vi, + const size_t degree, + const size_t basis_dimension, + const SmallArray<double>& inv_Vj_wq_detJ_ek, + SmallArray<double>& mean_of_ejk) +{ + switch (cell_type) { + case CellType::Triangle: { + const TriangleTransformation<2> T{xr[node_list[0]], xr[node_list[1]], xr[node_list[2]]}; + const auto& quadrature = QuadratureManager::instance().getTriangleFormula(GaussQuadratureDescriptor{degree}); + + _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + break; + } + case CellType::Quadrangle: { + const SquareTransformation<2> T{xr[node_list[0]], xr[node_list[1]], xr[node_list[2]], xr[node_list[3]]}; + const auto& quadrature = + QuadratureManager::instance().getSquareFormula(GaussLegendreQuadratureDescriptor{degree + 1}); + + _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + break; + } + default: { + throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type)}); + } + } +} + +template <typename NodeListT> +void +_computeEjkMeanInSymmetricCell(const TinyVector<2>& origin, + const TinyVector<2>& normal, + const TinyVector<2>& Xj, + const NodeValue<const TinyVector<2>>& xr, + const NodeListT& node_list, + const CellType& cell_type, + const double Vi, + const size_t degree, + const size_t basis_dimension, + const SmallArray<double>& inv_Vj_wq_detJ_ek, + SmallArray<double>& mean_of_ejk) +{ + switch (cell_type) { + case CellType::Triangle: { + const auto x0 = symmetrize_coordinates(origin, normal, xr[node_list[2]]); + const auto x1 = symmetrize_coordinates(origin, normal, xr[node_list[1]]); + const auto x2 = symmetrize_coordinates(origin, normal, xr[node_list[0]]); + + const TriangleTransformation<2> T{x0, x1, x2}; + const auto& quadrature = QuadratureManager::instance().getTriangleFormula(GaussQuadratureDescriptor{degree}); + + _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + break; + } + case CellType::Quadrangle: { + const auto x0 = symmetrize_coordinates(origin, normal, xr[node_list[3]]); + const auto x1 = symmetrize_coordinates(origin, normal, xr[node_list[2]]); + const auto x2 = symmetrize_coordinates(origin, normal, xr[node_list[1]]); + const auto x3 = symmetrize_coordinates(origin, normal, xr[node_list[0]]); + + const SquareTransformation<2> T{x0, x1, x2, x3}; + const auto& quadrature = + QuadratureManager::instance().getSquareFormula(GaussLegendreQuadratureDescriptor{degree + 1}); + + _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + break; + } + default: { + throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type)}); + } + } +} + +template <typename NodeListT> +void +_computeEjkMean(const TinyVector<3>& Xj, + const NodeValue<const TinyVector<3>>& xr, + const NodeListT& node_list, + const CellType& cell_type, + const double Vi, + const size_t degree, + const size_t basis_dimension, + const SmallArray<double>& inv_Vj_wq_detJ_ek, + SmallArray<double>& mean_of_ejk) +{ + if (cell_type == CellType::Tetrahedron) { + const TetrahedronTransformation T{xr[node_list[0]], xr[node_list[1]], xr[node_list[2]], xr[node_list[3]]}; + + const auto& quadrature = QuadratureManager::instance().getTetrahedronFormula(GaussQuadratureDescriptor{degree}); + + _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + + } else if (cell_type == CellType::Prism) { + const PrismTransformation T{xr[node_list[0]], xr[node_list[1]], xr[node_list[2]], // + xr[node_list[3]], xr[node_list[4]], xr[node_list[5]]}; + + const auto& quadrature = QuadratureManager::instance().getPrismFormula(GaussQuadratureDescriptor{degree + 1}); + + _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + + } else if (cell_type == CellType::Pyramid) { + const PyramidTransformation T{xr[node_list[0]], xr[node_list[1]], xr[node_list[2]], xr[node_list[3]], + xr[node_list[4]]}; + + const auto& quadrature = QuadratureManager::instance().getPyramidFormula(GaussQuadratureDescriptor{degree + 1}); + + _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + + } else if (cell_type == CellType::Hexahedron) { + const CubeTransformation T{xr[node_list[0]], xr[node_list[1]], xr[node_list[2]], xr[node_list[3]], + xr[node_list[4]], xr[node_list[5]], xr[node_list[6]], xr[node_list[7]]}; + + const auto& quadrature = + QuadratureManager::instance().getCubeFormula(GaussLegendreQuadratureDescriptor{degree + 1}); + + _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + + } else { + throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type)}); + } +} + +template <typename NodeListT> +void +_computeEjkMeanInSymmetricCell(const TinyVector<3>& origin, + const TinyVector<3>& normal, + const TinyVector<3>& Xj, + const NodeValue<const TinyVector<3>>& xr, + const NodeListT& node_list, + const CellType& cell_type, + const double Vi, + const size_t degree, + const size_t basis_dimension, + const SmallArray<double>& inv_Vj_wq_detJ_ek, + SmallArray<double>& mean_of_ejk) +{ + if (cell_type == CellType::Tetrahedron) { + const auto x0 = symmetrize_coordinates(origin, normal, xr[node_list[1]]); + const auto x1 = symmetrize_coordinates(origin, normal, xr[node_list[0]]); + const auto x2 = symmetrize_coordinates(origin, normal, xr[node_list[2]]); + const auto x3 = symmetrize_coordinates(origin, normal, xr[node_list[3]]); + + const TetrahedronTransformation T{x0, x1, x2, x3}; + + const auto& quadrature = QuadratureManager::instance().getTetrahedronFormula(GaussQuadratureDescriptor{degree}); + + _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + + } else if (cell_type == CellType::Prism) { + const auto x0 = symmetrize_coordinates(origin, normal, xr[node_list[1]]); + const auto x1 = symmetrize_coordinates(origin, normal, xr[node_list[0]]); + const auto x2 = symmetrize_coordinates(origin, normal, xr[node_list[2]]); + const auto x3 = symmetrize_coordinates(origin, normal, xr[node_list[4]]); + const auto x4 = symmetrize_coordinates(origin, normal, xr[node_list[3]]); + const auto x5 = symmetrize_coordinates(origin, normal, xr[node_list[5]]); + + const PrismTransformation T{x0, x1, x2, // + x3, x4, x5}; + + const auto& quadrature = QuadratureManager::instance().getPrismFormula(GaussQuadratureDescriptor{degree + 1}); + + _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + + } else if (cell_type == CellType::Pyramid) { + const auto x0 = symmetrize_coordinates(origin, normal, xr[node_list[3]]); + const auto x1 = symmetrize_coordinates(origin, normal, xr[node_list[2]]); + const auto x2 = symmetrize_coordinates(origin, normal, xr[node_list[1]]); + const auto x3 = symmetrize_coordinates(origin, normal, xr[node_list[0]]); + const auto x4 = symmetrize_coordinates(origin, normal, xr[node_list[4]]); + const PyramidTransformation T{x0, x1, x2, x3, x4}; + + const auto& quadrature = QuadratureManager::instance().getPyramidFormula(GaussQuadratureDescriptor{degree + 1}); + + _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + + } else if (cell_type == CellType::Hexahedron) { + const auto x0 = symmetrize_coordinates(origin, normal, xr[node_list[3]]); + const auto x1 = symmetrize_coordinates(origin, normal, xr[node_list[2]]); + const auto x2 = symmetrize_coordinates(origin, normal, xr[node_list[1]]); + const auto x3 = symmetrize_coordinates(origin, normal, xr[node_list[0]]); + const auto x4 = symmetrize_coordinates(origin, normal, xr[node_list[7]]); + const auto x5 = symmetrize_coordinates(origin, normal, xr[node_list[6]]); + const auto x6 = symmetrize_coordinates(origin, normal, xr[node_list[5]]); + const auto x7 = symmetrize_coordinates(origin, normal, xr[node_list[4]]); + + const CubeTransformation T{x0, x1, x2, x3, x4, x5, x6, x7}; + + const auto& quadrature = + QuadratureManager::instance().getCubeFormula(GaussLegendreQuadratureDescriptor{degree + 1}); + + _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + + } else { + throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type)}); + } +} + +template <MeshConcept MeshType> +class PolynomialReconstruction::ElementIntegralReconstructionMatrixBuilder +{ + private: + using Rd = TinyVector<MeshType::Dimension>; + + const size_t m_basis_dimension; + const size_t m_polynomial_degree; + + const SmallArray<double> m_inv_Vj_wq_detJ_ek; + SmallArray<double> m_mean_j_of_ejk; + SmallArray<double> m_mean_i_of_ejk; + + const ItemToItemMatrix<ItemType::cell, ItemType::node> m_cell_to_node_matrix; + const CellToCellStencilArray& m_stencil_array; + + const SmallArray<const Rd> m_symmetry_origin_list; + const SmallArray<const Rd> m_symmetry_normal_list; + + const CellValue<const CellType> m_cell_type; + const CellValue<const double> m_Vj; + const CellValue<const Rd> m_xj; + const NodeValue<const Rd> m_xr; + + public: + template <typename MatrixType> + void + build(const CellId cell_j_id, ShrinkMatrixView<MatrixType>& A) + { + const auto& stencil_cell_list = m_stencil_array[cell_j_id]; + + const Rd& Xj = m_xj[cell_j_id]; + + _computeEjkMean(Xj, m_xr, m_cell_to_node_matrix[cell_j_id], m_cell_type[cell_j_id], m_Vj[cell_j_id], + m_polynomial_degree, m_basis_dimension, m_inv_Vj_wq_detJ_ek, m_mean_j_of_ejk); + + size_t index = 0; + for (size_t i = 0; i < stencil_cell_list.size(); ++i, ++index) { + const CellId cell_i_id = stencil_cell_list[i]; + + _computeEjkMean(Xj, m_xr, m_cell_to_node_matrix[cell_i_id], m_cell_type[cell_i_id], m_Vj[cell_i_id], + m_polynomial_degree, m_basis_dimension, m_inv_Vj_wq_detJ_ek, m_mean_i_of_ejk); + + for (size_t l = 0; l < m_basis_dimension - 1; ++l) { + A(index, l) = m_mean_i_of_ejk[l] - m_mean_j_of_ejk[l]; + } + } + + for (size_t i_symmetry = 0; i_symmetry < m_stencil_array.symmetryBoundaryStencilArrayList().size(); ++i_symmetry) { + auto& ghost_stencil = m_stencil_array.symmetryBoundaryStencilArrayList()[i_symmetry].stencilArray(); + auto ghost_cell_list = ghost_stencil[cell_j_id]; + + const Rd& origin = m_symmetry_origin_list[i_symmetry]; + const Rd& normal = m_symmetry_normal_list[i_symmetry]; + + for (size_t i = 0; i < ghost_cell_list.size(); ++i, ++index) { + const CellId cell_i_id = ghost_cell_list[i]; + + _computeEjkMeanInSymmetricCell(origin, normal, // + Xj, m_xr, m_cell_to_node_matrix[cell_i_id], m_cell_type[cell_i_id], + m_Vj[cell_i_id], m_polynomial_degree, m_basis_dimension, m_inv_Vj_wq_detJ_ek, + m_mean_i_of_ejk); + + for (size_t l = 0; l < m_basis_dimension - 1; ++l) { + A(index, l) = m_mean_i_of_ejk[l] - m_mean_j_of_ejk[l]; + } + } + } + } + + ElementIntegralReconstructionMatrixBuilder(const MeshType& mesh, + const size_t polynomial_degree, + const SmallArray<double>& inv_Vj_wq_detJ_ek, + const SmallArray<double>& mean_j_of_ejk, + const SmallArray<double>& mean_i_of_ejk, + const SmallArray<const Rd>& symmetry_origin_list, + const SmallArray<const Rd>& symmetry_normal_list, + const CellToCellStencilArray& stencil_array) + : m_basis_dimension{DiscreteFunctionDPk<MeshType::Dimension, double>::BasisViewType::dimensionFromDegree( + polynomial_degree)}, + m_polynomial_degree{polynomial_degree}, + + m_inv_Vj_wq_detJ_ek{inv_Vj_wq_detJ_ek}, + m_mean_j_of_ejk{mean_j_of_ejk}, + m_mean_i_of_ejk{mean_i_of_ejk}, + + m_cell_to_node_matrix{mesh.connectivity().cellToNodeMatrix()}, + m_stencil_array{stencil_array}, + m_symmetry_origin_list{symmetry_origin_list}, + m_symmetry_normal_list{symmetry_normal_list}, + m_cell_type{mesh.connectivity().cellType()}, + m_Vj{MeshDataManager::instance().getMeshData(mesh).Vj()}, + m_xj{MeshDataManager::instance().getMeshData(mesh).xj()}, + m_xr{mesh.xr()} + {} + + ~ElementIntegralReconstructionMatrixBuilder() = default; +}; + template <typename ConformTransformationT> void _computeEjkBoundaryMean(const QuadratureFormula<1>& quadrature, const ConformTransformationT& T, @@ -421,7 +661,7 @@ void _computeEjkBoundaryMean(const QuadratureFormula<1>& quadrature, const double Vi, const size_t degree, const size_t dimension, - SmallArray<double>& inv_Vj_alpha_p_1_wq_X_prime_orth_ek, + const SmallArray<double>& inv_Vj_alpha_p_1_wq_X_prime_orth_ek, SmallArray<double>& mean_of_ejk); template <> @@ -432,7 +672,7 @@ _computeEjkBoundaryMean(const QuadratureFormula<1>& quadrature, const double Vi, const size_t degree, const size_t dimension, - SmallArray<double>& inv_Vj_alpha_p_1_wq_X_prime_orth_ek, + const SmallArray<double>& inv_Vj_alpha_p_1_wq_X_prime_orth_ek, SmallArray<double>& mean_of_ejk) { using Rd = TinyVector<2>; @@ -481,7 +721,7 @@ _computeEjkMeanByBoundary(const MeshType& mesh, const CellValue<const double>& Vi, const size_t degree, const size_t basis_dimension, - SmallArray<double>& inv_Vj_alpha_p_1_wq_X_prime_orth_ek, + const SmallArray<double>& inv_Vj_alpha_p_1_wq_X_prime_orth_ek, SmallArray<double>& mean_of_ejk) { const auto& quadrature = QuadratureManager::instance().getLineFormula(GaussLegendreQuadratureDescriptor(degree + 1)); @@ -518,7 +758,7 @@ _computeEjkMeanByBoundaryInSymmetricCell(const TinyVector<2>& origin, const CellValue<const double>& Vi, const size_t degree, const size_t basis_dimension, - SmallArray<double>& inv_Vj_alpha_p_1_wq_X_prime_orth_ek, + const SmallArray<double>& inv_Vj_alpha_p_1_wq_X_prime_orth_ek, SmallArray<double>& mean_of_ejk) { const auto& quadrature = QuadratureManager::instance().getLineFormula(GaussLegendreQuadratureDescriptor(degree + 1)); @@ -540,214 +780,234 @@ _computeEjkMeanByBoundaryInSymmetricCell(const TinyVector<2>& origin, inv_Vj_alpha_p_1_wq_X_prime_orth_ek, mean_of_ejk); } else { const LineTransformation<2> T{x0, x1}; - _computeEjkBoundaryMean(quadrature, T, Xj, Vi[cell_id], degree, basis_dimension, - inv_Vj_alpha_p_1_wq_X_prime_orth_ek, mean_of_ejk); - } - } -} - -template <typename NodeListT> -void -_computeEjkMean(const TinyVector<2>& Xj, - const NodeValue<const TinyVector<2>>& xr, - const NodeListT& node_list, - const CellType& cell_type, - const double Vi, - const size_t degree, - const size_t basis_dimension, - SmallArray<double>& inv_Vj_wq_detJ_ek, - SmallArray<double>& mean_of_ejk) -{ - switch (cell_type) { - case CellType::Triangle: { - const TriangleTransformation<2> T{xr[node_list[0]], xr[node_list[1]], xr[node_list[2]]}; - const auto& quadrature = QuadratureManager::instance().getTriangleFormula(GaussQuadratureDescriptor{degree}); - - _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); - break; - } - case CellType::Quadrangle: { - const SquareTransformation<2> T{xr[node_list[0]], xr[node_list[1]], xr[node_list[2]], xr[node_list[3]]}; - const auto& quadrature = - QuadratureManager::instance().getSquareFormula(GaussLegendreQuadratureDescriptor{degree + 1}); - - _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); - break; - } - default: { - throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type)}); - } - } -} - -template <typename NodeListT> -void -_computeEjkMeanInSymmetricCell(const TinyVector<2>& origin, - const TinyVector<2>& normal, - const TinyVector<2>& Xj, - const NodeValue<const TinyVector<2>>& xr, - const NodeListT& node_list, - const CellType& cell_type, - const double Vi, - const size_t degree, - const size_t basis_dimension, - SmallArray<double>& inv_Vj_wq_detJ_ek, - SmallArray<double>& mean_of_ejk) -{ - switch (cell_type) { - case CellType::Triangle: { - const auto x0 = symmetrize_coordinates(origin, normal, xr[node_list[2]]); - const auto x1 = symmetrize_coordinates(origin, normal, xr[node_list[1]]); - const auto x2 = symmetrize_coordinates(origin, normal, xr[node_list[0]]); - - const TriangleTransformation<2> T{x0, x1, x2}; - const auto& quadrature = QuadratureManager::instance().getTriangleFormula(GaussQuadratureDescriptor{degree}); - - _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); - break; - } - case CellType::Quadrangle: { - const auto x0 = symmetrize_coordinates(origin, normal, xr[node_list[3]]); - const auto x1 = symmetrize_coordinates(origin, normal, xr[node_list[2]]); - const auto x2 = symmetrize_coordinates(origin, normal, xr[node_list[1]]); - const auto x3 = symmetrize_coordinates(origin, normal, xr[node_list[0]]); - - const SquareTransformation<2> T{x0, x1, x2, x3}; - const auto& quadrature = - QuadratureManager::instance().getSquareFormula(GaussLegendreQuadratureDescriptor{degree + 1}); - - _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); - break; - } - default: { - throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type)}); - } + _computeEjkBoundaryMean(quadrature, T, Xj, Vi[cell_id], degree, basis_dimension, + inv_Vj_alpha_p_1_wq_X_prime_orth_ek, mean_of_ejk); + } } } -template <typename NodeListT> -void -_computeEjkMean(const TinyVector<3>& Xj, - const NodeValue<const TinyVector<3>>& xr, - const NodeListT& node_list, - const CellType& cell_type, - const double Vi, - const size_t degree, - const size_t basis_dimension, - SmallArray<double>& inv_Vj_wq_detJ_ek, - SmallArray<double>& mean_of_ejk) +template <MeshConcept MeshType> +class PolynomialReconstruction::BoundaryIntegralReconstructionMatrixBuilder { - if (cell_type == CellType::Tetrahedron) { - const TetrahedronTransformation T{xr[node_list[0]], xr[node_list[1]], xr[node_list[2]], xr[node_list[3]]}; + private: + using Rd = TinyVector<MeshType::Dimension>; - const auto& quadrature = QuadratureManager::instance().getTetrahedronFormula(GaussQuadratureDescriptor{degree}); + const MeshType& m_mesh; + const size_t m_basis_dimension; + const size_t m_polynomial_degree; - _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + const SmallArray<double> m_inv_Vj_alpha_p_1_wq_X_prime_orth_ek; + SmallArray<double> m_mean_j_of_ejk; + SmallArray<double> m_mean_i_of_ejk; - } else if (cell_type == CellType::Prism) { - const PrismTransformation T{xr[node_list[0]], xr[node_list[1]], xr[node_list[2]], // - xr[node_list[3]], xr[node_list[4]], xr[node_list[5]]}; + const ItemToItemMatrix<ItemType::cell, ItemType::face> m_cell_to_face_matrix; + const CellToCellStencilArray& m_stencil_array; - const auto& quadrature = QuadratureManager::instance().getPrismFormula(GaussQuadratureDescriptor{degree + 1}); + const SmallArray<const Rd> m_symmetry_origin_list; + const SmallArray<const Rd> m_symmetry_normal_list; - _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + const CellValue<const double> m_Vj; + const CellValue<const Rd> m_xj; + const NodeValue<const Rd> m_xr; - } else if (cell_type == CellType::Pyramid) { - const PyramidTransformation T{xr[node_list[0]], xr[node_list[1]], xr[node_list[2]], xr[node_list[3]], - xr[node_list[4]]}; + public: + template <typename MatrixType> + void + build(const CellId cell_j_id, ShrinkMatrixView<MatrixType>& A) + { + const auto& stencil_cell_list = m_stencil_array[cell_j_id]; - const auto& quadrature = QuadratureManager::instance().getPyramidFormula(GaussQuadratureDescriptor{degree + 1}); + auto face_to_node_matrix = m_mesh.connectivity().faceToNodeMatrix(); + auto cell_face_is_reversed = m_mesh.connectivity().cellFaceIsReversed(); + const Rd& Xj = m_xj[cell_j_id]; - _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + _computeEjkMeanByBoundary(m_mesh, Xj, cell_j_id, m_cell_to_face_matrix, face_to_node_matrix, cell_face_is_reversed, + m_Vj, m_polynomial_degree, m_basis_dimension, m_inv_Vj_alpha_p_1_wq_X_prime_orth_ek, + m_mean_j_of_ejk); - } else if (cell_type == CellType::Hexahedron) { - const CubeTransformation T{xr[node_list[0]], xr[node_list[1]], xr[node_list[2]], xr[node_list[3]], - xr[node_list[4]], xr[node_list[5]], xr[node_list[6]], xr[node_list[7]]}; + size_t index = 0; + for (size_t i = 0; i < stencil_cell_list.size(); ++i, ++index) { + const CellId cell_i_id = stencil_cell_list[i]; - const auto& quadrature = - QuadratureManager::instance().getCubeFormula(GaussLegendreQuadratureDescriptor{degree + 1}); + _computeEjkMeanByBoundary(m_mesh, Xj, cell_i_id, m_cell_to_face_matrix, face_to_node_matrix, + cell_face_is_reversed, m_Vj, m_polynomial_degree, m_basis_dimension, + m_inv_Vj_alpha_p_1_wq_X_prime_orth_ek, m_mean_i_of_ejk); - _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + for (size_t l = 0; l < m_basis_dimension - 1; ++l) { + A(index, l) = m_mean_i_of_ejk[l] - m_mean_j_of_ejk[l]; + } + } + for (size_t i_symmetry = 0; i_symmetry < m_stencil_array.symmetryBoundaryStencilArrayList().size(); ++i_symmetry) { + auto& ghost_stencil = m_stencil_array.symmetryBoundaryStencilArrayList()[i_symmetry].stencilArray(); + auto ghost_cell_list = ghost_stencil[cell_j_id]; - } else { - throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type)}); - } -} + const Rd& origin = m_symmetry_origin_list[i_symmetry]; + const Rd& normal = m_symmetry_normal_list[i_symmetry]; -template <typename NodeListT> -void -_computeEjkMeanInSymmetricCell(const TinyVector<3>& origin, - const TinyVector<3>& normal, - const TinyVector<3>& Xj, - const NodeValue<const TinyVector<3>>& xr, - const NodeListT& node_list, - const CellType& cell_type, - const double Vi, - const size_t degree, - const size_t basis_dimension, - SmallArray<double>& inv_Vj_wq_detJ_ek, - SmallArray<double>& mean_of_ejk) -{ - if (cell_type == CellType::Tetrahedron) { - const auto x0 = symmetrize_coordinates(origin, normal, xr[node_list[1]]); - const auto x1 = symmetrize_coordinates(origin, normal, xr[node_list[0]]); - const auto x2 = symmetrize_coordinates(origin, normal, xr[node_list[2]]); - const auto x3 = symmetrize_coordinates(origin, normal, xr[node_list[3]]); + for (size_t i = 0; i < ghost_cell_list.size(); ++i, ++index) { + const CellId cell_i_id = ghost_cell_list[i]; - const TetrahedronTransformation T{x0, x1, x2, x3}; + _computeEjkMeanByBoundaryInSymmetricCell(origin, normal, // + Xj, cell_i_id, m_xr, m_cell_to_face_matrix, face_to_node_matrix, + cell_face_is_reversed, m_Vj, m_polynomial_degree, m_basis_dimension, + m_inv_Vj_alpha_p_1_wq_X_prime_orth_ek, m_mean_i_of_ejk); - const auto& quadrature = QuadratureManager::instance().getTetrahedronFormula(GaussQuadratureDescriptor{degree}); + for (size_t l = 0; l < m_basis_dimension - 1; ++l) { + A(index, l) = m_mean_i_of_ejk[l] - m_mean_j_of_ejk[l]; + } + } + } + } - _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + BoundaryIntegralReconstructionMatrixBuilder(const MeshType& mesh, + const size_t polynomial_degree, + const SmallArray<double>& inv_Vj_alpha_p_1_wq_X_prime_orth_ek, + const SmallArray<double>& mean_j_of_ejk, + const SmallArray<double>& mean_i_of_ejk, + const SmallArray<const Rd>& symmetry_origin_list, + const SmallArray<const Rd>& symmetry_normal_list, + const CellToCellStencilArray& stencil_array) + : m_mesh{mesh}, + m_basis_dimension{ + DiscreteFunctionDPk<MeshType::Dimension, double>::BasisViewType::dimensionFromDegree(polynomial_degree)}, + m_polynomial_degree{polynomial_degree}, + + m_inv_Vj_alpha_p_1_wq_X_prime_orth_ek{inv_Vj_alpha_p_1_wq_X_prime_orth_ek}, + m_mean_j_of_ejk{mean_j_of_ejk}, + m_mean_i_of_ejk{mean_i_of_ejk}, + + m_cell_to_face_matrix{mesh.connectivity().cellToFaceMatrix()}, + m_stencil_array{stencil_array}, + m_symmetry_origin_list{symmetry_origin_list}, + m_symmetry_normal_list{symmetry_normal_list}, + m_Vj{MeshDataManager::instance().getMeshData(mesh).Vj()}, + m_xj{MeshDataManager::instance().getMeshData(mesh).xj()}, + m_xr{mesh.xr()} + {} + BoundaryIntegralReconstructionMatrixBuilder() = default; + ~BoundaryIntegralReconstructionMatrixBuilder() = default; +}; - } else if (cell_type == CellType::Prism) { - const auto x0 = symmetrize_coordinates(origin, normal, xr[node_list[1]]); - const auto x1 = symmetrize_coordinates(origin, normal, xr[node_list[0]]); - const auto x2 = symmetrize_coordinates(origin, normal, xr[node_list[2]]); - const auto x3 = symmetrize_coordinates(origin, normal, xr[node_list[4]]); - const auto x4 = symmetrize_coordinates(origin, normal, xr[node_list[3]]); - const auto x5 = symmetrize_coordinates(origin, normal, xr[node_list[5]]); +class PolynomialReconstruction::MutableDiscreteFunctionDPkVariant +{ + public: + using Variant = std::variant<DiscreteFunctionDPk<1, double>, + DiscreteFunctionDPk<1, TinyVector<1>>, + DiscreteFunctionDPk<1, TinyVector<2>>, + DiscreteFunctionDPk<1, TinyVector<3>>, + DiscreteFunctionDPk<1, TinyMatrix<1>>, + DiscreteFunctionDPk<1, TinyMatrix<2>>, + DiscreteFunctionDPk<1, TinyMatrix<3>>, - const PrismTransformation T{x0, x1, x2, // - x3, x4, x5}; + DiscreteFunctionDPk<2, double>, + DiscreteFunctionDPk<2, TinyVector<1>>, + DiscreteFunctionDPk<2, TinyVector<2>>, + DiscreteFunctionDPk<2, TinyVector<3>>, + DiscreteFunctionDPk<2, TinyMatrix<1>>, + DiscreteFunctionDPk<2, TinyMatrix<2>>, + DiscreteFunctionDPk<2, TinyMatrix<3>>, - const auto& quadrature = QuadratureManager::instance().getPrismFormula(GaussQuadratureDescriptor{degree + 1}); + DiscreteFunctionDPk<3, double>, + DiscreteFunctionDPk<3, TinyVector<1>>, + DiscreteFunctionDPk<3, TinyVector<2>>, + DiscreteFunctionDPk<3, TinyVector<3>>, + DiscreteFunctionDPk<3, TinyMatrix<1>>, + DiscreteFunctionDPk<3, TinyMatrix<2>>, + DiscreteFunctionDPk<3, TinyMatrix<3>>, - _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + DiscreteFunctionDPkVector<1, double>, + DiscreteFunctionDPkVector<1, TinyVector<1>>, + DiscreteFunctionDPkVector<1, TinyVector<2>>, + DiscreteFunctionDPkVector<1, TinyVector<3>>, + DiscreteFunctionDPkVector<1, TinyMatrix<1>>, + DiscreteFunctionDPkVector<1, TinyMatrix<2>>, + DiscreteFunctionDPkVector<1, TinyMatrix<3>>, - } else if (cell_type == CellType::Pyramid) { - const auto x0 = symmetrize_coordinates(origin, normal, xr[node_list[3]]); - const auto x1 = symmetrize_coordinates(origin, normal, xr[node_list[2]]); - const auto x2 = symmetrize_coordinates(origin, normal, xr[node_list[1]]); - const auto x3 = symmetrize_coordinates(origin, normal, xr[node_list[0]]); - const auto x4 = symmetrize_coordinates(origin, normal, xr[node_list[4]]); - const PyramidTransformation T{x0, x1, x2, x3, x4}; + DiscreteFunctionDPkVector<2, double>, + DiscreteFunctionDPkVector<2, TinyVector<1>>, + DiscreteFunctionDPkVector<2, TinyVector<2>>, + DiscreteFunctionDPkVector<2, TinyVector<3>>, + DiscreteFunctionDPkVector<2, TinyMatrix<1>>, + DiscreteFunctionDPkVector<2, TinyMatrix<2>>, + DiscreteFunctionDPkVector<2, TinyMatrix<3>>, - const auto& quadrature = QuadratureManager::instance().getPyramidFormula(GaussQuadratureDescriptor{degree + 1}); + DiscreteFunctionDPkVector<3, double>, + DiscreteFunctionDPkVector<3, TinyVector<1>>, + DiscreteFunctionDPkVector<3, TinyVector<2>>, + DiscreteFunctionDPkVector<3, TinyVector<3>>, + DiscreteFunctionDPkVector<3, TinyMatrix<1>>, + DiscreteFunctionDPkVector<3, TinyMatrix<2>>, + DiscreteFunctionDPkVector<3, TinyMatrix<3>>>; - _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + private: + Variant m_mutable_discrete_function_dpk; - } else if (cell_type == CellType::Hexahedron) { - const auto x0 = symmetrize_coordinates(origin, normal, xr[node_list[3]]); - const auto x1 = symmetrize_coordinates(origin, normal, xr[node_list[2]]); - const auto x2 = symmetrize_coordinates(origin, normal, xr[node_list[1]]); - const auto x3 = symmetrize_coordinates(origin, normal, xr[node_list[0]]); - const auto x4 = symmetrize_coordinates(origin, normal, xr[node_list[7]]); - const auto x5 = symmetrize_coordinates(origin, normal, xr[node_list[6]]); - const auto x6 = symmetrize_coordinates(origin, normal, xr[node_list[5]]); - const auto x7 = symmetrize_coordinates(origin, normal, xr[node_list[4]]); + public: + PUGS_INLINE + const Variant& + mutableDiscreteFunctionDPk() const + { + return m_mutable_discrete_function_dpk; + } - const CubeTransformation T{x0, x1, x2, x3, x4, x5, x6, x7}; + template <typename DiscreteFunctionDPkT> + PUGS_INLINE auto&& + get() const + { + static_assert(is_discrete_function_dpk_v<DiscreteFunctionDPkT>, "invalid template argument"); +#ifndef NDEBUG + if (not std::holds_alternative<DiscreteFunctionDPkT>(this->m_mutable_discrete_function_dpk)) { + std::ostringstream error_msg; + error_msg << "invalid discrete function type\n"; + error_msg << "- required " << rang::fgB::red << demangle<DiscreteFunctionDPkT>() << rang::fg::reset << '\n'; + error_msg << "- contains " << rang::fgB::yellow + << std::visit([](auto&& f) -> std::string { return demangle<decltype(f)>(); }, + this->m_mutable_discrete_function_dpk) + << rang::fg::reset; + throw NormalError(error_msg.str()); + } +#endif // NDEBUG - const auto& quadrature = - QuadratureManager::instance().getCubeFormula(GaussLegendreQuadratureDescriptor{degree + 1}); + return std::get<DiscreteFunctionDPkT>(this->mutableDiscreteFunctionDPk()); + } - _computeEjkMean(quadrature, T, Xj, Vi, degree, basis_dimension, inv_Vj_wq_detJ_ek, mean_of_ejk); + template <size_t Dimension, typename DataType> + MutableDiscreteFunctionDPkVariant(const DiscreteFunctionDPk<Dimension, DataType>& discrete_function_dpk) + : m_mutable_discrete_function_dpk{discrete_function_dpk} + { + static_assert(std::is_same_v<DataType, double> or // + std::is_same_v<DataType, TinyVector<1, double>> or // + std::is_same_v<DataType, TinyVector<2, double>> or // + std::is_same_v<DataType, TinyVector<3, double>> or // + std::is_same_v<DataType, TinyMatrix<1, 1, double>> or // + std::is_same_v<DataType, TinyMatrix<2, 2, double>> or // + std::is_same_v<DataType, TinyMatrix<3, 3, double>>, + "DiscreteFunctionDPk with this DataType is not allowed in variant"); + } - } else { - throw NotImplementedError("unexpected cell type: " + std::string{name(cell_type)}); + template <size_t Dimension, typename DataType> + MutableDiscreteFunctionDPkVariant(const DiscreteFunctionDPkVector<Dimension, DataType>& discrete_function_dpk) + : m_mutable_discrete_function_dpk{discrete_function_dpk} + { + static_assert(std::is_same_v<DataType, double> or // + std::is_same_v<DataType, TinyVector<1, double>> or // + std::is_same_v<DataType, TinyVector<2, double>> or // + std::is_same_v<DataType, TinyVector<3, double>> or // + std::is_same_v<DataType, TinyMatrix<1, 1, double>> or // + std::is_same_v<DataType, TinyMatrix<2, 2, double>> or // + std::is_same_v<DataType, TinyMatrix<3, 3, double>>, + "DiscreteFunctionDPkVector with this DataType is not allowed in variant"); } -} + + MutableDiscreteFunctionDPkVariant& operator=(MutableDiscreteFunctionDPkVariant&&) = default; + MutableDiscreteFunctionDPkVariant& operator=(const MutableDiscreteFunctionDPkVariant&) = default; + + MutableDiscreteFunctionDPkVariant(const MutableDiscreteFunctionDPkVariant&) = default; + MutableDiscreteFunctionDPkVariant(MutableDiscreteFunctionDPkVariant&&) = default; + + MutableDiscreteFunctionDPkVariant() = delete; + ~MutableDiscreteFunctionDPkVariant() = default; +}; size_t PolynomialReconstruction::_getNumberOfColumns( @@ -893,7 +1153,6 @@ PolynomialReconstruction::_build( auto cell_is_owned = mesh.connectivity().cellIsOwned(); auto cell_type = mesh.connectivity().cellType(); - auto cell_to_node_matrix = mesh.connectivity().cellToNodeMatrix(); auto cell_to_face_matrix = mesh.connectivity().cellToFaceMatrix(); auto full_stencil_size = [&](const CellId cell_id) { @@ -959,7 +1218,6 @@ PolynomialReconstruction::_build( SmallArray<SmallArray<double>> mean_i_of_ejk_pool(Kokkos::DefaultExecutionSpace::concurrency()); SmallArray<SmallArray<double>> inv_Vj_alpha_p_1_wq_X_prime_orth_ek_pool(Kokkos::DefaultExecutionSpace::concurrency()); - SmallArray<SmallArray<double>> mean_l_of_ejk_pool(Kokkos::DefaultExecutionSpace::concurrency()); for (size_t i = 0; i < A_pool.size(); ++i) { A_pool[i] = SmallMatrix<double>(max_stencil_size, basis_dimension - 1); @@ -974,6 +1232,10 @@ PolynomialReconstruction::_build( inv_Vj_alpha_p_1_wq_X_prime_orth_ek_pool[i] = SmallArray<double>(basis_dimension); } + std::shared_ptr p_cell_center_reconstruction_matrix_builder = + std::make_shared<CellCenterReconstructionMatrixBuilder<MeshType>>(symmetry_origin_list, symmetry_normal_list, + stencil_array, xj); + parallel_for( mesh.numberOfCells(), PUGS_CLASS_LAMBDA(const CellId cell_j_id) { if (cell_is_owned[cell_j_id]) { @@ -1215,32 +1477,7 @@ PolynomialReconstruction::_build( if ((m_descriptor.degree() == 1) and (m_descriptor.integrationMethodType() == IntegrationMethodType::cell_center)) { - const Rd& Xj = xj[cell_j_id]; - size_t index = 0; - for (size_t i = 0; i < stencil_cell_list.size(); ++i, ++index) { - const CellId cell_i_id = stencil_cell_list[i]; - const Rd Xi_Xj = xj[cell_i_id] - Xj; - for (size_t l = 0; l < basis_dimension - 1; ++l) { - A(index, l) = Xi_Xj[l]; - } - } - for (size_t i_symmetry = 0; i_symmetry < stencil_array.symmetryBoundaryStencilArrayList().size(); - ++i_symmetry) { - auto& ghost_stencil = stencil_array.symmetryBoundaryStencilArrayList()[i_symmetry].stencilArray(); - auto ghost_cell_list = ghost_stencil[cell_j_id]; - - const Rd& origin = symmetry_origin_list[i_symmetry]; - const Rd& normal = symmetry_normal_list[i_symmetry]; - - for (size_t i = 0; i < ghost_cell_list.size(); ++i, ++index) { - const CellId cell_i_id = ghost_cell_list[i]; - const Rd Xi_Xj = symmetrize_coordinates(origin, normal, xj[cell_i_id]) - Xj; - for (size_t l = 0; l < basis_dimension - 1; ++l) { - A(index, l) = Xi_Xj[l]; - } - } - } - + p_cell_center_reconstruction_matrix_builder->build(cell_j_id, A); } else if ((m_descriptor.integrationMethodType() == IntegrationMethodType::element) or (m_descriptor.integrationMethodType() == IntegrationMethodType::boundary)) { #warning implement boundary based reconstruction for 1d and 3d @@ -1251,6 +1488,14 @@ PolynomialReconstruction::_build( SmallArray<double>& mean_j_of_ejk = mean_j_of_ejk_pool[t]; SmallArray<double>& mean_i_of_ejk = mean_i_of_ejk_pool[t]; + BoundaryIntegralReconstructionMatrixBuilder + boundary_integral_reconstruction_matrix_builder(*p_mesh, m_descriptor.degree(), + inv_Vj_alpha_p_1_wq_X_prime_orth_ek, mean_j_of_ejk, + mean_i_of_ejk, symmetry_origin_list, + symmetry_normal_list, stencil_array); + + boundary_integral_reconstruction_matrix_builder.build(cell_j_id, A); + auto face_to_node_matrix = p_mesh->connectivity().faceToNodeMatrix(); auto cell_face_is_reversed = p_mesh->connectivity().cellFaceIsReversed(); const Rd& Xj = xj[cell_j_id]; @@ -1297,48 +1542,18 @@ PolynomialReconstruction::_build( throw UnexpectedError("invalid mesh dimension"); } } else { + +#warning incorporate in reconstruction_matrix_builder 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]; - const Rd& Xj = xj[cell_j_id]; + ElementIntegralReconstructionMatrixBuilder + element_integral_reconstruction_matrix_builder(*p_mesh, m_descriptor.degree(), inv_Vj_wq_detJ_ek, + mean_j_of_ejk, mean_i_of_ejk, symmetry_origin_list, + symmetry_normal_list, stencil_array); - _computeEjkMean(Xj, xr, cell_to_node_matrix[cell_j_id], cell_type[cell_j_id], Vj[cell_j_id], - m_descriptor.degree(), basis_dimension, inv_Vj_wq_detJ_ek, mean_j_of_ejk); - - size_t index = 0; - for (size_t i = 0; i < stencil_cell_list.size(); ++i, ++index) { - const CellId cell_i_id = stencil_cell_list[i]; - - _computeEjkMean(Xj, xr, cell_to_node_matrix[cell_i_id], cell_type[cell_i_id], Vj[cell_i_id], - m_descriptor.degree(), basis_dimension, inv_Vj_wq_detJ_ek, mean_i_of_ejk); - - for (size_t l = 0; l < basis_dimension - 1; ++l) { - A(index, l) = mean_i_of_ejk[l] - mean_j_of_ejk[l]; - } - } - - for (size_t i_symmetry = 0; i_symmetry < stencil_array.symmetryBoundaryStencilArrayList().size(); - ++i_symmetry) { - auto& ghost_stencil = stencil_array.symmetryBoundaryStencilArrayList()[i_symmetry].stencilArray(); - auto ghost_cell_list = ghost_stencil[cell_j_id]; - - const Rd& origin = symmetry_origin_list[i_symmetry]; - const Rd& normal = symmetry_normal_list[i_symmetry]; - - for (size_t i = 0; i < ghost_cell_list.size(); ++i, ++index) { - const CellId cell_i_id = ghost_cell_list[i]; - - _computeEjkMeanInSymmetricCell(origin, normal, // - Xj, xr, cell_to_node_matrix[cell_i_id], cell_type[cell_i_id], - Vj[cell_i_id], m_descriptor.degree(), basis_dimension, inv_Vj_wq_detJ_ek, - mean_i_of_ejk); - - for (size_t l = 0; l < basis_dimension - 1; ++l) { - A(index, l) = mean_i_of_ejk[l] - mean_j_of_ejk[l]; - } - } - } + element_integral_reconstruction_matrix_builder.build(cell_j_id, A); } } else { throw UnexpectedError("invalid integration strategy"); diff --git a/src/scheme/PolynomialReconstruction.hpp b/src/scheme/PolynomialReconstruction.hpp index bf6013639..349ae4577 100644 --- a/src/scheme/PolynomialReconstruction.hpp +++ b/src/scheme/PolynomialReconstruction.hpp @@ -12,6 +12,15 @@ class PolynomialReconstruction private: class MutableDiscreteFunctionDPkVariant; + template <MeshConcept MeshType> + class CellCenterReconstructionMatrixBuilder; + + template <MeshConcept MeshType> + class ElementIntegralReconstructionMatrixBuilder; + + template <MeshConcept MeshType> + class BoundaryIntegralReconstructionMatrixBuilder; + const PolynomialReconstructionDescriptor m_descriptor; size_t _getNumberOfColumns( -- GitLab