Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <cstddef> 7 : 8 : #include "DataStructures/Variables.hpp" 9 : #include "NumericalAlgorithms/Spectral/Mesh.hpp" 10 : #include "Utilities/ErrorHandling/Assert.hpp" 11 : #include "Utilities/Gsl.hpp" 12 : 13 1 : namespace dg { 14 : 15 : namespace detail { 16 : template <typename ValueType, size_t Dim> 17 : void apply_mass_matrix_impl(gsl::not_null<ValueType*> data, 18 : const Mesh<Dim>& mesh); 19 : template <typename ValueType, size_t Dim> 20 : void apply_inverse_mass_matrix_impl(gsl::not_null<ValueType*> data, 21 : const Mesh<Dim>& mesh); 22 : } // namespace detail 23 : 24 : /*! 25 : * \brief Apply the DG mass matrix to the data, in the diagonal mass-matrix 26 : * approximation ("mass-lumping") 27 : * 28 : * The DG mass matrix is: 29 : * 30 : * \f{equation} 31 : * M_{pq} = \int_{\Omega_k} \psi_p(\xi) \psi_q(\xi) \mathrm{d}V 32 : * \f} 33 : * 34 : * where \f$\psi_p(\xi)\f$ are the basis functions on the element 35 : * \f$\Omega_k\f$. In the diagonal mass-matrix approximation ("mass-lumping") we 36 : * evaluate the integral directly on the collocation points, i.e. with a Gauss 37 : * or Gauss-Lobatto quadrature determined by the element mesh. Then it reduces 38 : * to: 39 : * 40 : * \f{equation} 41 : * M_{pq} \approx \delta_{pq} \prod_{i=1}^d w_{p_i} 42 : * \f} 43 : * 44 : * where \f$d\f$ is the spatial dimension and \f$w_{p_i}\f$ are the quadrature 45 : * weights in dimension \f$i\f$. To apply the mass matrix in coordinates 46 : * different than logical, or to account for a curved background metric, the 47 : * data can be pre-multiplied with the Jacobian determinant and/or a metric 48 : * determinant. 49 : * 50 : * \note The mass-lumping is exact on Legendre-Gauss meshes, but omits a 51 : * correction term on Legendre-Gauss-Lobatto meshes. 52 : */ 53 : /// @{ 54 : template <typename DataType, size_t Dim> 55 1 : void apply_mass_matrix(const gsl::not_null<DataType*> data, 56 : const Mesh<Dim>& mesh) { 57 : ASSERT(data->size() == mesh.number_of_grid_points(), 58 : "The data has size " << data->size() << ", but expected size " 59 : << mesh.number_of_grid_points() 60 : << " on the given mesh."); 61 : detail::apply_mass_matrix_impl(make_not_null(data->data()), mesh); 62 : } 63 : 64 : template <size_t Dim, typename TagsList> 65 1 : void apply_mass_matrix(const gsl::not_null<Variables<TagsList>*> data, 66 : const Mesh<Dim>& mesh) { 67 : const size_t num_points = data->number_of_grid_points(); 68 : ASSERT(num_points == mesh.number_of_grid_points(), 69 : "The Variables data has " 70 : << num_points << " grid points, but expected " 71 : << mesh.number_of_grid_points() << " on the given mesh."); 72 : constexpr size_t num_comps = 73 : Variables<TagsList>::number_of_independent_components; 74 : for (size_t i = 0; i < num_comps; ++i) { 75 : detail::apply_mass_matrix_impl(make_not_null(data->data() + i * num_points), 76 : mesh); 77 : } 78 : } 79 : /// @} 80 : 81 : /*! 82 : * \brief Apply the inverse DG mass matrix to the data 83 : * 84 : * \see dg::apply_mass_matrix 85 : */ 86 : /// @{ 87 : template <typename DataType, size_t Dim> 88 1 : void apply_inverse_mass_matrix(const gsl::not_null<DataType*> data, 89 : const Mesh<Dim>& mesh) { 90 : ASSERT(data->size() == mesh.number_of_grid_points(), 91 : "The data has size " << data->size() << ", but expected size " 92 : << mesh.number_of_grid_points() 93 : << " on the given mesh."); 94 : detail::apply_inverse_mass_matrix_impl(make_not_null(data->data()), mesh); 95 : } 96 : 97 : template <size_t Dim, typename TagsList> 98 1 : void apply_inverse_mass_matrix(const gsl::not_null<Variables<TagsList>*> data, 99 : const Mesh<Dim>& mesh) { 100 : const size_t num_points = data->number_of_grid_points(); 101 : ASSERT(num_points == mesh.number_of_grid_points(), 102 : "The Variables data has " 103 : << num_points << " grid points, but expected " 104 : << mesh.number_of_grid_points() << " on the given mesh."); 105 : constexpr size_t num_comps = 106 : Variables<TagsList>::number_of_independent_components; 107 : for (size_t i = 0; i < num_comps; ++i) { 108 : detail::apply_inverse_mass_matrix_impl( 109 : make_not_null(data->data() + i * num_points), mesh); 110 : } 111 : } 112 : /// @} 113 : 114 : } // namespace dg