SpECTRE Documentation Coverage Report
Current view: top level - NumericalAlgorithms/Spectral - FilteringB2.hpp Hit Total Coverage
Commit: c3e43f8d41800b0ecefb9d1393f1de1d5a280c8f Lines: 6 7 85.7 %
Date: 2026-07-24 22:09:25
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             : #include <optional>
       8             : 
       9             : #include "Utilities/Gsl.hpp"
      10             : 
      11             : /// \cond
      12             : class DataVector;
      13             : class Matrix;
      14             : template <size_t>
      15             : class Mesh;
      16             : template <typename TagsList>
      17             : class Variables;
      18             : /// \endcond
      19             : 
      20             : namespace Spectral::filtering {
      21             : /*!
      22             :  * \brief Filters the tensors stored within a `Variables` being represented by
      23             :  * ZernikeB2 basis functions, with an optional exponential roll-off and an
      24             :  * optional top-mode cutoff.
      25             :  *
      26             :  * \details Representing functions on a filled disk requires special basis
      27             :  * functions, namely ZernikeB2. These are inherently two-dimensional, meaning
      28             :  * the radial and angular spectral spaces are intertwined. This function goes
      29             :  * to that combined modal space, applies the filter, and transforms back.
      30             :  *
      31             :  * When `half_power` has a value, a smooth exponential roll-off (see
      32             :  * exponential_filter()) is applied to the combined radial-angular modes using
      33             :  * the coefficient `alpha`. When `num_modes_to_kill` is nonzero, the highest
      34             :  * `num_modes_to_kill` angular (Fourier \f$m\f$) modes are additionally set to
      35             :  * zero, with the \f$m=0\f$ mode always retained. If `half_power` is
      36             :  * `std::nullopt` and `num_modes_to_kill` is zero this function is a no-op.
      37             :  *
      38             :  * \see exponential_filter()
      39             :  */
      40             : template <typename TagsList>
      41           1 : void zernike_b2_disk_filter(gsl::not_null<Variables<TagsList>*> u,
      42             :                             const Mesh<2>& mesh, double alpha,
      43             :                             std::optional<unsigned> half_power,
      44             :                             size_t num_modes_to_kill);
      45             : 
      46             : /*!
      47             :  * \brief Filters the tensors stored within a `Variables` being represented by
      48             :  * ZernikeB2 basis functions, with an optional exponential roll-off and an
      49             :  * optional top-mode cutoff.
      50             :  *
      51             :  * \details Overload taking a caller-managed working buffer. Avoids heap
      52             :  * allocation when the filter is applied repeatedly (e.g. in
      53             :  * `Filters::FilledCylinder`).
      54             :  */
      55             : template <typename TagsList>
      56           1 : void zernike_b2_disk_filter(gsl::not_null<Variables<TagsList>*> u,
      57             :                             gsl::not_null<DataVector*> buf, const Mesh<2>& mesh,
      58             :                             double alpha, std::optional<unsigned> half_power,
      59             :                             size_t num_modes_to_kill);
      60             : 
      61             : /*!
      62             :  * \brief Filters the tensors stored within a `Variables` being represented by
      63             :  * ZernikeB2 basis functions.
      64             :  *
      65             :  * \details Equivalent to `zernike_b2_disk_filter()` with `half_power` set and
      66             :  * no top-mode cutoff. Kept for callers that only want the exponential filter.
      67             :  *
      68             :  * \see exponential_filter()
      69             :  */
      70             : template <typename TagsList>
      71           1 : void zernike_b2_disk_exponential_filter(gsl::not_null<Variables<TagsList>*> u,
      72             :                                         const Mesh<2>& mesh, double alpha,
      73             :                                         unsigned half_power);
      74             : 
      75             : /*!
      76             :  * \brief Filters the tensors stored within a `Variables` being represented by
      77             :  * ZernikeB2 \f$\times\f$ Legendre basis functions, with optional independent
      78             :  * roll-offs for the combined radial-angular disk modes and the axial \f$z\f$
      79             :  * modes plus an optional angular top-mode cutoff.
      80             :  *
      81             :  * \details Representing functions on a filled cylinder requires special basis
      82             :  * functions, namely a filled disk with ZernikeB2 cross Legendre. This requires
      83             :  * inherently two-dimensional basis functions, meaning the radial and angular
      84             :  * spectral spaces are intertwined. This function goes to that combined modal
      85             :  * space, applies the disk filter, transforms back, and then filters the third
      86             :  * I1 dimension.
      87             :  *
      88             :  * The combined radial-angular (disk) modes are filtered with an exponential
      89             :  * roll-off when `radial_angular_half_power` has a value and with a top-mode
      90             :  * cutoff of the highest `num_modes_to_kill` angular (Fourier \f$m\f$) modes
      91             :  * when `num_modes_to_kill` is nonzero (the \f$m=0\f$ mode is always retained).
      92             :  * The axial \f$z\f$ direction is filtered with an independent exponential
      93             :  * roll-off when `z_half_power` has a value. The coefficient `alpha` is shared
      94             :  * by all exponential roll-offs. Any direction whose half-power is
      95             :  * `std::nullopt` (and, for the disk, with `num_modes_to_kill` zero) is left
      96             :  * untouched.
      97             :  *
      98             :  * While the radial-angular plane is fixed to ZernikeB2 \f$\times\f$ Fourier,
      99             :  * the axial \f$z\f$ filter is applied with exponential_filter() in whatever 1D
     100             :  * spectral basis the mesh uses in the \f$z\f$ direction, so both Legendre and
     101             :  * Chebyshev (with any quadrature) are supported there.
     102             :  *
     103             :  * \see exponential_filter()
     104             :  */
     105             : template <typename TagsList>
     106           1 : void zernike_b2_cylinder_filter(
     107             :     gsl::not_null<Variables<TagsList>*> u, const Mesh<3>& mesh, double alpha,
     108             :     std::optional<unsigned> radial_angular_half_power,
     109             :     std::optional<unsigned> z_half_power, size_t num_modes_to_kill);
     110             : 
     111             : /*!
     112             :  * \brief Filters the tensors stored within a `Variables` being represented by
     113             :  * ZernikeB2 \f$\times\f$ Legendre basis functions, with optional independent
     114             :  * roll-offs for the combined radial-angular disk modes and the axial \f$z\f$
     115             :  * modes plus an optional angular top-mode cutoff.
     116             :  *
     117             :  * \details Overload taking a caller-managed working buffer. Avoids heap
     118             :  * allocation when the filter is applied repeatedly (e.g. in
     119             :  * `Filters::FilledCylinder`). One can optionally pass the exponential filter
     120             :  * to apply in the z direction, otherwise it will be computed.
     121             :  *
     122             :  */
     123             : template <typename TagsList>
     124           1 : void zernike_b2_cylinder_filter(
     125             :     gsl::not_null<Variables<TagsList>*> u, gsl::not_null<DataVector*> buf,
     126             :     const Mesh<3>& mesh, double alpha,
     127             :     std::optional<unsigned> radial_angular_half_power,
     128             :     std::optional<unsigned> z_half_power, size_t num_modes_to_kill,
     129             :     const std::optional<Matrix>& z_filter);
     130             : 
     131             : /*!
     132             :  * \brief Filters the tensors stored within a `Variables` being represented by
     133             :  * ZernikeB2 \f$\times\f$ Legendre basis functions.
     134             :  *
     135             :  * \details Equivalent to `zernike_b2_cylinder_filter()` with both the disk and
     136             :  * axial half-powers set to `half_power` and no top-mode cutoff. Kept for
     137             :  * callers that only want a single exponential filter applied everywhere.
     138             :  *
     139             :  * \see exponential_filter()
     140             :  */
     141             : template <typename TagsList>
     142           1 : void zernike_b2_cylinder_exponential_filter(
     143             :     gsl::not_null<Variables<TagsList>*> u, const Mesh<3>& mesh, double alpha,
     144             :     unsigned half_power);
     145             : }  // namespace Spectral::filtering

Generated by: LCOV version 1.14