SpECTRE Documentation Coverage Report
Current view: top level - NumericalAlgorithms/Spectral - Filtering.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 80.0 % 5 4
Test Date: 2026-10-22 17:29:42
Legend: Lines:     hit not hit

            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 and HalfFourier bases, where
      43              :  * the modal space is parity dependent.
      44              :  *
      45              :  * For the HalfFourier basis, \f$\cos(k\phi)\f$ and \f$\sin(k\phi)\f$ with the
      46              :  * same wavenumber \f$k\f$ are weighted equally, and the odd-parity Nyquist mode
      47              :  * \f$\sin(N\phi)\f$ is removed.
      48              :  *
      49              :  * \note The filter matrix is not cached by the function because it depends on a
      50              :  * double, an integer, and the mesh, which could make caching very memory
      51              :  * intensive. The caller of this function is responsible for determining whether
      52              :  * or not the matrix should be cached.
      53              :  */
      54            1 : Matrix exponential_filter(const Mesh<1>& mesh, double alpha,
      55              :                           unsigned half_power,
      56              :                           Parity parity = Parity::Uninitialized);
      57              : 
      58              : /*!
      59              :  * \brief Zeros the lowest `number_of_modes_to_zero` modal coefficients. Note
      60              :  * that the matrix must be applied to a nodal representation.
      61              :  *
      62              :  * Given a function \f$u\f$
      63              :  *
      64              :  * \f{align}{
      65              :  *   u(x)=\sum_{i=0}^N c_i P_i(x),
      66              :  * \f}
      67              :  *
      68              :  * where \f$c_i\f$ are the modal coefficients and \f$P_i(x)\f$ is the basis
      69              :  * (e.g. Legendre polynomials), the filter matrix will take the *nodal*
      70              :  * representation of \f$u\f$ and zero out the lowest `number_of_modes_to_zero`
      71              :  * modal coefficients. That is, after the filter is applied \f$u\to\bar{u}\f$ is
      72              :  *
      73              :  * \f{align}{
      74              :  *   \bar{u}(x)=\sum_{i=k}^N c_i P_i(x),
      75              :  * \f}
      76              :  *
      77              :  * where \f$k\f$ is the number of modes set to zero. The output \f$\bar{u}\f$ is
      78              :  * also in the *nodal* representation.
      79              :  *
      80              :  * The Parity argument is only used for ZernikeB1 bases, where the modal space
      81              :  * is parity dependent.
      82              :  */
      83            1 : const Matrix& zero_lowest_modes(
      84              :     const Mesh<1>& mesh, size_t number_of_modes_to_zero,
      85              :     Spectral::Parity parity = Spectral::Parity::Uninitialized);
      86              : 
      87              : /*!
      88              :  * \brief Zeros the highest `number_of_modes_to_zero` modal coefficients. Note
      89              :  * that the matrix must be applied to a nodal representation.
      90              :  *
      91              :  * Given a function \f$u\f$
      92              :  *
      93              :  * \f{align}{
      94              :  *   u(x)=\sum_{i=0}^N c_i P_i(x),
      95              :  * \f}
      96              :  *
      97              :  * where \f$c_i\f$ are the modal coefficients and \f$P_i(x)\f$ is the basis
      98              :  * (e.g. Legendre polynomials), the filter matrix will take the *nodal*
      99              :  * representation of \f$u\f$ and zero out the highest `number_of_modes_to_zero`
     100              :  * modal coefficients. That is, after the filter is applied \f$u\to\bar{u}\f$ is
     101              :  *
     102              :  * \f{align}{
     103              :  *   \bar{u}(x)=\sum_{i=0}^{N-k} c_i P_i(x),
     104              :  * \f}
     105              :  *
     106              :  * where \f$k\f$ is the number of modes set to zero. The output \f$\bar{u}\f$ is
     107              :  * also in the *nodal* representation. The constant (\f$i=0\f$) mode is never
     108              :  * removed for any basis.
     109              :  *
     110              :  * For the Fourier basis the "modes" are the \f$m\f$-modes: the highest
     111              :  * `number_of_modes_to_zero` \f$m\f$-modes are zeroed, with both the \f$\cos\f$
     112              :  * and \f$\sin\f$ contributions to a given \f$m\f$-mode treated identically.
     113              :  *
     114              :  * \note Only the Legendre, Chebyshev, and Fourier bases are supported. Unlike
     115              :  * `zero_lowest_modes`, there is no parity argument and the ZernikeB1 basis is
     116              :  * not supported.
     117              :  */
     118            1 : const Matrix& zero_highest_modes(const Mesh<1>& mesh,
     119              :                                  size_t number_of_modes_to_zero);
     120              : }  // namespace filtering
     121              : }  // namespace Spectral
        

Generated by: LCOV version 2.0-1