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 "NumericalAlgorithms/Spectral/Parity.hpp" 9 : 10 : /// \cond 11 : class Matrix; 12 : template <size_t> 13 : class Mesh; 14 : /// \endcond 15 : 16 : namespace Spectral { 17 : /*! 18 : * \ingroup SpectralGroup 19 : * \brief Matrices for filtering spectral coefficients. 20 : */ 21 1 : namespace filtering { 22 : /*! 23 : * \brief Returns a `Matrix` by which to multiply the nodal coefficients to 24 : * apply a stable exponential filter. 25 : * 26 : * The exponential filter rescales the modal coefficients according to: 27 : * 28 : * \f{align*}{ 29 : * c_i\to c_i \exp\left[-\alpha \left(\frac{i}{N}\right)^{2m}\right] 30 : * \f} 31 : * 32 : * where \f$c_i\f$ are the zero-indexed modal coefficients, \f$N\f$ is the basis 33 : * degree (number of grid points per element per dimension minus one), 34 : * \f$\alpha\f$ determines how much the coefficients are rescaled, and \f$m\f$ 35 : * determines how aggressive/broad the filter is (lower values means filtering 36 : * more coefficients). Setting \f$\alpha=36\f$ results in setting the highest 37 : * coefficient to machine precision, effectively zeroing it out. 38 : * 39 : * For filtering the Fourier basis, both \f$\cos\f$ and \f$\sin\f$ 40 : * contributions to a given \f$m\f$-mode are equally weighted. 41 : * 42 : * The Parity argument is only used for ZernikeB1 bases, where the modal space 43 : * is parity dependent. 44 : * 45 : * \note The filter matrix is not cached by the function because it depends on a 46 : * double, an integer, and the mesh, which could make caching very memory 47 : * intensive. The caller of this function is responsible for determining whether 48 : * or not the matrix should be cached. 49 : */ 50 1 : Matrix exponential_filter(const Mesh<1>& mesh, double alpha, 51 : unsigned half_power, 52 : Parity parity = Parity::Uninitialized); 53 : 54 : /*! 55 : * \brief Zeros the lowest `number_of_modes_to_zero` modal coefficients. Note 56 : * that the matrix must be applied to a nodal representation. 57 : * 58 : * Given a function \f$u\f$ 59 : * 60 : * \f{align}{ 61 : * u(x)=\sum_{i=0}^N c_i P_i(x), 62 : * \f} 63 : * 64 : * where \f$c_i\f$ are the modal coefficients and \f$P_i(x)\f$ is the basis 65 : * (e.g. Legendre polynomials), the filter matrix will take the *nodal* 66 : * representation of \f$u\f$ and zero out the lowest `number_of_modes_to_zero` 67 : * modal coefficients. That is, after the filter is applied \f$u\to\bar{u}\f$ is 68 : * 69 : * \f{align}{ 70 : * \bar{u}(x)=\sum_{i=k}^N c_i P_i(x), 71 : * \f} 72 : * 73 : * where \f$k\f$ is the number of modes set to zero. The output \f$\bar{u}\f$ is 74 : * also in the *nodal* representation. 75 : * 76 : * The Parity argument is only used for ZernikeB1 bases, where the modal space 77 : * is parity dependent. 78 : */ 79 1 : const Matrix& zero_lowest_modes( 80 : const Mesh<1>& mesh, size_t number_of_modes_to_zero, 81 : Spectral::Parity parity = Spectral::Parity::Uninitialized); 82 : } // namespace filtering 83 : } // namespace Spectral