|
SpECTRE
v2026.06.30
|
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 Matrix & | 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. | |
| const Matrix & | 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. | |
| 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. | |
Matrices for filtering spectral coefficients.
| 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.
| 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.
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.
| 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.
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.
| 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.
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.
| 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.
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.
| 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.
Equivalent to zernike_b2_disk_filter() with half_power set and no top-mode cutoff. Kept for callers that only want the exponential filter.
| 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.
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.
| 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.
Overload taking a caller-managed working buffer. Avoids heap allocation when the filter is applied repeatedly (e.g. in Filters::FilledCylinder).
| 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.
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).
| 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.
Overload taking a caller-managed working buffer. Avoids heap allocations when the filter is applied repeatedly (e.g. every volume call inside Filters::Ball).
| 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.
| 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.