SpECTRE  v2026.06.30
Loading...
Searching...
No Matches
Spectral::filtering Namespace Reference

Matrices for filtering spectral coefficients. More...

Functions

Matrix exponential_filter (const Mesh< 1 > &mesh, double alpha, unsigned half_power, Parity parity=Parity::Uninitialized)
 Returns a Matrix by which to multiply the nodal coefficients to apply a stable exponential filter.
const Matrixzero_lowest_modes (const Mesh< 1 > &mesh, size_t number_of_modes_to_zero, Spectral::Parity parity=Spectral::Parity::Uninitialized)
 Zeros the lowest number_of_modes_to_zero modal coefficients. Note that the matrix must be applied to a nodal representation.
const Matrixzero_highest_modes (const Mesh< 1 > &mesh, size_t number_of_modes_to_zero)
 Zeros the highest number_of_modes_to_zero modal coefficients. Note that the matrix must be applied to a nodal representation.
template<typename VariablesTags>
void zernike_b1_exponential_filter (gsl::not_null< Variables< VariablesTags > * > u, const Mesh< 3 > &mesh, double alpha, unsigned half_power)
 Filters the tensors stored within a Variables being represented by ZernikeB1 basis functions in their first dimension.
template<typename TagsList>
void zernike_b2_disk_filter (gsl::not_null< Variables< TagsList > * > u, const Mesh< 2 > &mesh, double alpha, std::optional< unsigned > half_power, size_t num_modes_to_kill)
 Filters the tensors stored within a Variables being represented by ZernikeB2 basis functions, with an optional exponential roll-off and an optional top-mode cutoff.
template<typename TagsList>
void zernike_b2_disk_filter (gsl::not_null< Variables< TagsList > * > u, gsl::not_null< DataVector * > buf, const Mesh< 2 > &mesh, double alpha, std::optional< unsigned > half_power, size_t num_modes_to_kill)
 Filters the tensors stored within a Variables being represented by ZernikeB2 basis functions, with an optional exponential roll-off and an optional top-mode cutoff.
template<typename TagsList>
void zernike_b2_disk_exponential_filter (gsl::not_null< Variables< TagsList > * > u, const Mesh< 2 > &mesh, double alpha, unsigned half_power)
 Filters the tensors stored within a Variables being represented by ZernikeB2 basis functions.
template<typename TagsList>
void zernike_b2_cylinder_filter (gsl::not_null< Variables< TagsList > * > u, const Mesh< 3 > &mesh, double alpha, std::optional< unsigned > radial_angular_half_power, std::optional< unsigned > z_half_power, size_t num_modes_to_kill)
 Filters the tensors stored within a Variables being represented by ZernikeB2 \(\times\) Legendre basis functions, with optional independent roll-offs for the combined radial-angular disk modes and the axial \(z\) modes plus an optional angular top-mode cutoff.
template<typename TagsList>
void zernike_b2_cylinder_filter (gsl::not_null< Variables< TagsList > * > u, gsl::not_null< DataVector * > buf, const Mesh< 3 > &mesh, double alpha, std::optional< unsigned > radial_angular_half_power, std::optional< unsigned > z_half_power, size_t num_modes_to_kill, const std::optional< Matrix > &z_filter)
 Filters the tensors stored within a Variables being represented by ZernikeB2 \(\times\) Legendre basis functions, with optional independent roll-offs for the combined radial-angular disk modes and the axial \(z\) modes plus an optional angular top-mode cutoff.
template<typename TagsList>
void zernike_b2_cylinder_exponential_filter (gsl::not_null< Variables< TagsList > * > u, const Mesh< 3 > &mesh, double alpha, unsigned half_power)
 Filters the tensors stored within a Variables being represented by ZernikeB2 \(\times\) Legendre basis functions.
template<typename VariablesTags>
void zernike_b3_ball_radial_exponential_filter (gsl::not_null< Variables< VariablesTags > * > u, const Mesh< 3 > &mesh, double alpha, unsigned half_power)
 Filters the radial components of tensors stored within a Variables represented by ZernikeB3 basis functions on a filled ball.
template<typename VariablesTags>
void zernike_b3_ball_radial_exponential_filter (gsl::not_null< Variables< VariablesTags > * > u, gsl::not_null< DataVector * > buf, const Mesh< 3 > &mesh, double alpha, unsigned half_power)
 Filters the radial components of tensors stored within a Variables represented by ZernikeB3 basis functions on a filled ball.

Detailed Description

Matrices for filtering spectral coefficients.

Function Documentation

◆ exponential_filter()

Matrix Spectral::filtering::exponential_filter ( const Mesh< 1 > & mesh,
double alpha,
unsigned half_power,
Parity parity = Parity::Uninitialized )

Returns a Matrix by which to multiply the nodal coefficients to apply a stable exponential filter.

The exponential filter rescales the modal coefficients according to:

\begin{align*} c_i\to c_i \exp\left[-\alpha \left(\frac{i}{N}\right)^{2m}\right] \end{align*}

where \(c_i\) are the zero-indexed modal coefficients, \(N\) is the basis degree (number of grid points per element per dimension minus one), \(\alpha\) determines how much the coefficients are rescaled, and \(m\) determines how aggressive/broad the filter is (lower values means filtering more coefficients). Setting \(\alpha=36\) results in setting the highest coefficient to machine precision, effectively zeroing it out.

For filtering the Fourier basis, both \(\cos\) and \(\sin\) contributions to a given \(m\)-mode are equally weighted.

The Parity argument is only used for ZernikeB1 bases, where the modal space is parity dependent.

Note
The filter matrix is not cached by the function because it depends on a double, an integer, and the mesh, which could make caching very memory intensive. The caller of this function is responsible for determining whether or not the matrix should be cached.

◆ zernike_b1_exponential_filter()

template<typename VariablesTags>
void Spectral::filtering::zernike_b1_exponential_filter ( gsl::not_null< Variables< VariablesTags > * > u,
const Mesh< 3 > & mesh,
double alpha,
unsigned half_power )

Filters the tensors stored within a Variables being represented by ZernikeB1 basis functions in their first dimension.

Details

The Cartoon method with spectral bases can be unstable for small \(x\), so we use ZernikeB1 bases with GaussRadauUpper quadrature to push collocation points to higher inertial coordinates. This basis has parity-dependent spectral space, so we must go to the proper modal space, apply the exponential filter, and transform back.

See also
exponential_filter()

◆ zernike_b2_cylinder_exponential_filter()

template<typename TagsList>
void Spectral::filtering::zernike_b2_cylinder_exponential_filter ( gsl::not_null< Variables< TagsList > * > u,
const Mesh< 3 > & mesh,
double alpha,
unsigned half_power )

Filters the tensors stored within a Variables being represented by ZernikeB2 \(\times\) Legendre basis functions.

Details

Equivalent to zernike_b2_cylinder_filter() with both the disk and axial half-powers set to half_power and no top-mode cutoff. Kept for callers that only want a single exponential filter applied everywhere.

See also
exponential_filter()

◆ zernike_b2_cylinder_filter() [1/2]

template<typename TagsList>
void Spectral::filtering::zernike_b2_cylinder_filter ( gsl::not_null< Variables< TagsList > * > u,
const Mesh< 3 > & mesh,
double alpha,
std::optional< unsigned > radial_angular_half_power,
std::optional< unsigned > z_half_power,
size_t num_modes_to_kill )

Filters the tensors stored within a Variables being represented by ZernikeB2 \(\times\) Legendre basis functions, with optional independent roll-offs for the combined radial-angular disk modes and the axial \(z\) modes plus an optional angular top-mode cutoff.

Details

Representing functions on a filled cylinder requires special basis functions, namely a filled disk with ZernikeB2 cross Legendre. This requires inherently two-dimensional basis functions, meaning the radial and angular spectral spaces are intertwined. This function goes to that combined modal space, applies the disk filter, transforms back, and then filters the third I1 dimension.

The combined radial-angular (disk) modes are filtered with an exponential roll-off when radial_angular_half_power has a value and with a top-mode cutoff of the highest num_modes_to_kill angular (Fourier \(m\)) modes when num_modes_to_kill is nonzero (the \(m=0\) mode is always retained). The axial \(z\) direction is filtered with an independent exponential roll-off when z_half_power has a value. The coefficient alpha is shared by all exponential roll-offs. Any direction whose half-power is std::nullopt (and, for the disk, with num_modes_to_kill zero) is left untouched.

While the radial-angular plane is fixed to ZernikeB2 \(\times\) Fourier, the axial \(z\) filter is applied with exponential_filter() in whatever 1D spectral basis the mesh uses in the \(z\) direction, so both Legendre and Chebyshev (with any quadrature) are supported there.

See also
exponential_filter()

◆ zernike_b2_cylinder_filter() [2/2]

template<typename TagsList>
void Spectral::filtering::zernike_b2_cylinder_filter ( gsl::not_null< Variables< TagsList > * > u,
gsl::not_null< DataVector * > buf,
const Mesh< 3 > & mesh,
double alpha,
std::optional< unsigned > radial_angular_half_power,
std::optional< unsigned > z_half_power,
size_t num_modes_to_kill,
const std::optional< Matrix > & z_filter )

Filters the tensors stored within a Variables being represented by ZernikeB2 \(\times\) Legendre basis functions, with optional independent roll-offs for the combined radial-angular disk modes and the axial \(z\) modes plus an optional angular top-mode cutoff.

Details

Overload taking a caller-managed working buffer. Avoids heap allocation when the filter is applied repeatedly (e.g. in Filters::FilledCylinder). One can optionally pass the exponential filter to apply in the z direction, otherwise it will be computed.

◆ zernike_b2_disk_exponential_filter()

template<typename TagsList>
void Spectral::filtering::zernike_b2_disk_exponential_filter ( gsl::not_null< Variables< TagsList > * > u,
const Mesh< 2 > & mesh,
double alpha,
unsigned half_power )

Filters the tensors stored within a Variables being represented by ZernikeB2 basis functions.

Details

Equivalent to zernike_b2_disk_filter() with half_power set and no top-mode cutoff. Kept for callers that only want the exponential filter.

See also
exponential_filter()

◆ zernike_b2_disk_filter() [1/2]

template<typename TagsList>
void Spectral::filtering::zernike_b2_disk_filter ( gsl::not_null< Variables< TagsList > * > u,
const Mesh< 2 > & mesh,
double alpha,
std::optional< unsigned > half_power,
size_t num_modes_to_kill )

Filters the tensors stored within a Variables being represented by ZernikeB2 basis functions, with an optional exponential roll-off and an optional top-mode cutoff.

Details

Representing functions on a filled disk requires special basis functions, namely ZernikeB2. These are inherently two-dimensional, meaning the radial and angular spectral spaces are intertwined. This function goes to that combined modal space, applies the filter, and transforms back.

When half_power has a value, a smooth exponential roll-off (see exponential_filter()) is applied to the combined radial-angular modes using the coefficient alpha. When num_modes_to_kill is nonzero, the highest num_modes_to_kill angular (Fourier \(m\)) modes are additionally set to zero, with the \(m=0\) mode always retained. If half_power is std::nullopt and num_modes_to_kill is zero this function is a no-op.

See also
exponential_filter()

◆ zernike_b2_disk_filter() [2/2]

template<typename TagsList>
void Spectral::filtering::zernike_b2_disk_filter ( gsl::not_null< Variables< TagsList > * > u,
gsl::not_null< DataVector * > buf,
const Mesh< 2 > & mesh,
double alpha,
std::optional< unsigned > half_power,
size_t num_modes_to_kill )

Filters the tensors stored within a Variables being represented by ZernikeB2 basis functions, with an optional exponential roll-off and an optional top-mode cutoff.

Details

Overload taking a caller-managed working buffer. Avoids heap allocation when the filter is applied repeatedly (e.g. in Filters::FilledCylinder).

◆ zernike_b3_ball_radial_exponential_filter() [1/2]

template<typename VariablesTags>
void Spectral::filtering::zernike_b3_ball_radial_exponential_filter ( gsl::not_null< Variables< VariablesTags > * > u,
const Mesh< 3 > & mesh,
double alpha,
unsigned half_power )

Filters the radial components of tensors stored within a Variables represented by ZernikeB3 basis functions on a filled ball.

Details

Functions on a filled ball with angular degree \(\ell\) behave as \(r^\ell\) near the origin, so their radial profile lies in the even or odd parity ZernikeB3 subspace depending on whether \(\ell\) is even or odd. The combined spectral space is therefore indexed by \((n_\mathrm{jac}, \ell, m)\), where \(n_\mathrm{jac}\) is the radial Jacobi index. The exponential filter weight for mode \((n_\mathrm{jac}, \ell)\) is

\begin{align*} w = \exp\!\left(-\alpha \left(\frac{n_i}{N_r-1}\right)^{2p}\right), \end{align*}

where \(n_i = \lfloor (\ell + 2 n_\mathrm{jac}) / 2 \rfloor\) and \(N_r\) is the number of radial grid points.

The mesh must have basis (ZernikeB3, ZernikeB3, ZernikeB3) with quadrature (GaussRadauUpper, Gauss, Equiangular) and extents (n_r, l_max+1, 2*l_max+1).

See also
exponential_filter()

◆ zernike_b3_ball_radial_exponential_filter() [2/2]

template<typename VariablesTags>
void Spectral::filtering::zernike_b3_ball_radial_exponential_filter ( gsl::not_null< Variables< VariablesTags > * > u,
gsl::not_null< DataVector * > buf,
const Mesh< 3 > & mesh,
double alpha,
unsigned half_power )

Filters the radial components of tensors stored within a Variables represented by ZernikeB3 basis functions on a filled ball.

Details

Overload taking a caller-managed working buffer. Avoids heap allocations when the filter is applied repeatedly (e.g. every volume call inside Filters::Ball).

◆ zero_highest_modes()

const Matrix & Spectral::filtering::zero_highest_modes ( const Mesh< 1 > & mesh,
size_t number_of_modes_to_zero )

Zeros the highest number_of_modes_to_zero modal coefficients. Note that the matrix must be applied to a nodal representation.

Given a function \(u\)

\begin{align} u(x)=\sum_{i=0}^N c_i P_i(x), \end{align}

where \(c_i\) are the modal coefficients and \(P_i(x)\) is the basis (e.g. Legendre polynomials), the filter matrix will take the nodal representation of \(u\) and zero out the highest number_of_modes_to_zero modal coefficients. That is, after the filter is applied \(u\to\bar{u}\) is

\begin{align} \bar{u}(x)=\sum_{i=0}^{N-k} c_i P_i(x), \end{align}

where \(k\) is the number of modes set to zero. The output \(\bar{u}\) is also in the nodal representation. The constant ( \(i=0\)) mode is never removed for any basis.

For the Fourier basis the "modes" are the \(m\)-modes: the highest number_of_modes_to_zero \(m\)-modes are zeroed, with both the \(\cos\) and \(\sin\) contributions to a given \(m\)-mode treated identically.

Note
Only the Legendre, Chebyshev, and Fourier bases are supported. Unlike zero_lowest_modes, there is no parity argument and the ZernikeB1 basis is not supported.

◆ zero_lowest_modes()

const Matrix & Spectral::filtering::zero_lowest_modes ( const Mesh< 1 > & mesh,
size_t number_of_modes_to_zero,
Spectral::Parity parity = Spectral::Parity::Uninitialized )

Zeros the lowest number_of_modes_to_zero modal coefficients. Note that the matrix must be applied to a nodal representation.

Given a function \(u\)

\begin{align} u(x)=\sum_{i=0}^N c_i P_i(x), \end{align}

where \(c_i\) are the modal coefficients and \(P_i(x)\) is the basis (e.g. Legendre polynomials), the filter matrix will take the nodal representation of \(u\) and zero out the lowest number_of_modes_to_zero modal coefficients. That is, after the filter is applied \(u\to\bar{u}\) is

\begin{align} \bar{u}(x)=\sum_{i=k}^N c_i P_i(x), \end{align}

where \(k\) is the number of modes set to zero. The output \(\bar{u}\) is also in the nodal representation.

The Parity argument is only used for ZernikeB1 bases, where the modal space is parity dependent.