SpECTRE Documentation Coverage Report
Current view: top level - NumericalAlgorithms/LinearOperators/Filters - Filter.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 73.7 % 19 14
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              : #include <memory>
       8              : #include <optional>
       9              : #include <pup.h>
      10              : #include <string>
      11              : #include <unordered_map>
      12              : #include <unordered_set>
      13              : #include <vector>
      14              : 
      15              : #include "DataStructures/Tensor/TypeAliases.hpp"
      16              : #include "Utilities/Gsl.hpp"
      17              : #include "Utilities/Serialization/CharmPupable.hpp"
      18              : #include "Utilities/TMPL.hpp"
      19              : 
      20              : /// \cond
      21              : class DataVector;
      22              : template <size_t Dim>
      23              : class Mesh;
      24              : template <typename TagsList>
      25              : class Variables;
      26              : /// \endcond
      27              : 
      28              : namespace Filters {
      29              : /*!
      30              :  * \ingroup DiscontinuousGalerkinGroup
      31              :  * \brief Abstract base class for spectral filters.
      32              :  *
      33              :  * Derived classes implement spectral filters that suppress high-frequency
      34              :  * modes in the modal expansion of a discontinuous Galerkin solution. Writing
      35              :  * the 1-D modal coefficients of a tensor component as \f$c_i\f$, a spectral
      36              :  * filter rescales them as
      37              :  *
      38              :  * \f{align*}{
      39              :  *  c_i \to \sigma\!\left(\frac{i}{N}\right) c_i,
      40              :  * \f}
      41              :  *
      42              :  * where \f$N\f$ is the basis degree (number of grid points per element per
      43              :  * dimension minus one) and \f$\sigma\f$ is a derived-class-specific damping
      44              :  * factor (for example, an exponential in `Filters::Hypercube`). For a
      45              :  * discussion of filtering see section 5.3 of \cite HesthavenWarburton.
      46              :  *
      47              :  * The interface is organized along two axes:
      48              :  *
      49              :  * - **Volume vs. boundary.** `apply_in_volume` filters the evolved
      50              :  *   `Variables` on the element's `Dim`-dimensional mesh, while
      51              :  *   `apply_on_boundary` filters data on a `Dim - 1` face mesh. The boundary
      52              :  *   hook is intended for filtering the lifted boundary corrections produced
      53              :  *   by the DG numerical flux before they enter the volume right-hand side.
      54              :  *
      55              :  * - **Substep vs. every-N-steps.** The driving action queries
      56              :  *   `apply_volume_filter_on_substep()` (and the boundary analogue) to decide
      57              :  *   whether to filter inside every Runge-Kutta substep, and
      58              :  *   `apply_volume_filter_on_this_step(step_number)` (and the boundary
      59              :  *   analogue) to gate filtering at coarser cadences such as every `N` full
      60              :  *   steps. The two return values are independent so a derived class may pick
      61              :  *   any combination.
      62              :  *
      63              :  * Derived classes additionally declare via `need_jacobians()` whether they
      64              :  * require the grid-to-inertial Jacobian and its inverse in `apply_in_volume`
      65              :  * / `apply_on_boundary`. When `need_jacobians()` returns `false`, the
      66              :  * driving action passes `std::nullopt` for both Jacobian arguments and skips
      67              :  * computing them.
      68              :  *
      69              :  * The set of domain blocks to which the filter applies is reported by
      70              :  * `blocks_to_filter()`; a `std::nullopt` return value means the filter
      71              :  * applies to every block in the domain.
      72              :  */
      73              : template <size_t Dim, typename TagList>
      74            1 : class Filter : public PUP::able {
      75              :  public:
      76            0 :   Filter() = default;
      77            0 :   ~Filter() noexcept override = default;
      78              : 
      79            0 :   WRAPPED_PUPable_abstract(Filter);  // NOLINT
      80            0 :   explicit Filter(CkMigrateMessage* m) : PUP::able(m) {}
      81              : 
      82              :   /// Return a heap-allocated deep copy of this filter.
      83            1 :   virtual std::unique_ptr<Filter<Dim, TagList>> get_clone() const = 0;
      84              : 
      85              :   /// Whether the volume filter should be applied inside every Runge-Kutta
      86              :   /// substep.
      87            1 :   virtual bool apply_volume_filter_on_substep() const = 0;
      88              : 
      89              :   /// Whether the volume filter should be applied at the given `step_number`.
      90              :   ///
      91              :   /// \note Currently the check for whether to filter on every `N` steps is done
      92              :   /// relative to the start of the current Slab. This means that for GTS,
      93              :   /// independent of the value of `N` for every `N` steps, every step has a
      94              :   /// filter applied since GTS has one step per slab.
      95            1 :   virtual bool apply_volume_filter_on_this_step(size_t step_number) const = 0;
      96              : 
      97              :   /// Whether the boundary filter should be applied inside every Runge-Kutta
      98              :   /// substep.
      99            1 :   virtual bool apply_boundary_filter_on_substep() const = 0;
     100              : 
     101              :   /// Whether the boundary filter should be applied at the given
     102              :   /// `step_number`.
     103              :   ///
     104              :   /// \note Currently the check for whether to filter on every `N` steps is done
     105              :   /// relative to the start of the current Slab. This means that for GTS,
     106              :   /// independent of the value of `N` for every `N` steps, every step has a
     107              :   /// filter applied since GTS has one step per slab.
     108            1 :   virtual bool apply_boundary_filter_on_this_step(size_t step_number) const = 0;
     109              : 
     110              :   /// \brief Whether the filter needs the grid-to-inertial Jacobian and its
     111              :   /// inverse.
     112              :   ///
     113              :   /// When `false`, the driving action passes `std::nullopt` for the Jacobian
     114              :   /// arguments of `apply_in_volume` and `apply_on_boundary` and avoids
     115              :   /// constructing them.
     116            1 :   virtual bool need_jacobians() const = 0;
     117              : 
     118              :   /// \brief Returns `true` if this filter can filter the `mesh`.
     119            1 :   virtual bool supports_mesh(const Mesh<Dim>& mesh) const = 0;
     120              : 
     121              :   /// \brief A human-readable name for the concrete filter type, used in
     122              :   /// diagnostics.
     123            1 :   virtual std::string name() const = 0;
     124              : 
     125              :   /// \brief Returns `true` if `other` is the same concrete filter type and is
     126              :   /// equivalent to `*this`.
     127            1 :   virtual bool is_equal(const Filter& other) const = 0;
     128              : 
     129              :   /// \brief The set of block (or block group) names the filter applies to.
     130              :   ///
     131              :   /// `std::nullopt` means the filter applies to every block in the domain.
     132            1 :   virtual const std::optional<std::vector<size_t>>& blocks_to_filter()
     133              :       const = 0;
     134              : 
     135              :   /// \brief Used after construction to change blocks and groups labeled by
     136              :   /// strings to `size_t`s, which is what is used throughout the code.
     137            1 :   virtual void set_blocks_to_filter(
     138              :       const std::vector<std::string>& all_block_names,
     139              :       const std::unordered_map<std::string, std::unordered_set<std::string>>&
     140              :           block_groups) = 0;
     141              : 
     142              :   /*!
     143              :    * \brief Apply the filter in place to the volume `vars` on the
     144              :    * `Dim`-dimensional `mesh`.
     145              :    *
     146              :    * The grid-to-inertial Jacobian `jac_grid_to_inertial` and its inverse
     147              :    * `inv_jac_grid_to_inertial` are populated only when `need_jacobians()`
     148              :    * returns `true`; otherwise both arguments are `std::nullopt`.
     149              :    */
     150            1 :   virtual void apply_in_volume(
     151              :       gsl::not_null<Variables<TagList>*> vars, const Mesh<Dim>& mesh,
     152              :       const std::optional<
     153              :           InverseJacobian<DataVector, Dim, Frame::Grid, Frame::Inertial>>&
     154              :           inv_jac_grid_to_inertial,
     155              :       const std::optional<
     156              :           Jacobian<DataVector, Dim, Frame::Grid, Frame::Inertial>>&
     157              :           jac_grid_to_inertial) const = 0;
     158              : 
     159              :   /*!
     160              :    * \brief Apply the filter in place to face `vars` on the `Dim - 1` face
     161              :    * `mesh`.
     162              :    *
     163              :    * Used to filter the lifted boundary corrections produced by the DG numerical
     164              :    * flux before they enter the volume right-hand side. The grid-to-inertial
     165              :    * Jacobian `jac_grid_to_inertial` and its inverse `inv_jac_grid_to_inertial`
     166              :    * are populated only when `need_jacobians()` returns `true`; otherwise both
     167              :    * arguments are `std::nullopt`.
     168              :    */
     169            1 :   virtual void apply_on_boundary(
     170              :       gsl::not_null<Variables<TagList>*> vars, const Mesh<Dim - 1>& mesh,
     171              :       const std::optional<
     172              :           InverseJacobian<DataVector, Dim, Frame::Grid, Frame::Inertial>>&
     173              :           inv_jac_grid_to_inertial,
     174              :       const std::optional<
     175              :           Jacobian<DataVector, Dim, Frame::Grid, Frame::Inertial>>&
     176              :           jac_grid_to_inertial) const = 0;
     177              : };
     178              : }  // namespace Filters
        

Generated by: LCOV version 2.0-1