#ifndef CELL_CENTER_RECONSTRUCTION_MATRIX_BUILDER_HPP #define CELL_CENTER_RECONSTRUCTION_MATRIX_BUILDER_HPP #include <algebra/ShrinkMatrixView.hpp> #include <mesh/Connectivity.hpp> #include <mesh/StencilArray.hpp> #include <scheme/DiscreteFunctionDPk.hpp> #include <scheme/PolynomialReconstruction.hpp> #include <utils/SmallArray.hpp> template <MeshConcept MeshTypeT> class PolynomialReconstruction::CellCenterReconstructionMatrixBuilder { public: using MeshType = MeshTypeT; constexpr static bool handles_high_degrees = false; private: using Rd = TinyVector<MeshType::Dimension>; const size_t m_basis_dimension; const SmallArray<const Rd> m_symmetry_origin_list; const SmallArray<const Rd> m_symmetry_normal_list; const CellToCellStencilArray& m_stencil_array; const CellValue<const Rd> m_xj; 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]; 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]; } } } } CellCenterReconstructionMatrixBuilder(const MeshType& mesh, const size_t polynomial_degree, 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_symmetry_origin_list{symmetry_origin_list}, m_symmetry_normal_list{symmetry_normal_list}, m_stencil_array{stencil_array}, m_xj{MeshDataManager::instance().getMeshData(mesh).xj()} { if (polynomial_degree != 1) { throw NormalError("cell center based reconstruction is only valid for first order"); } } ~CellCenterReconstructionMatrixBuilder() = default; }; #endif // CELL_CENTER_RECONSTRUCTION_MATRIX_BUILDER_HPP