SpECTRE Documentation Coverage Report
Current view: top level - ParallelAlgorithms/Actions - SpectralFilter.hpp Hit Total Coverage
Commit: c3e43f8d41800b0ecefb9d1393f1de1d5a280c8f Lines: 1 4 25.0 %
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             : #include <utility>
       9             : 
      10             : #include "DataStructures/DataBox/DataBox.hpp"
      11             : #include "DataStructures/DataVector.hpp"
      12             : #include "DataStructures/Tensor/Tensor.hpp"
      13             : #include "Domain/Tags.hpp"
      14             : #include "NumericalAlgorithms/LinearOperators/Filters/Filter.hpp"
      15             : #include "NumericalAlgorithms/LinearOperators/Filters/None.hpp"
      16             : #include "NumericalAlgorithms/LinearOperators/Filters/Tag.hpp"
      17             : #include "Parallel/AlgorithmExecution.hpp"
      18             : #include "Parallel/GlobalCache.hpp"
      19             : #include "Time/Tags/StepNumberWithinSlab.hpp"
      20             : #include "Utilities/Gsl.hpp"
      21             : 
      22             : /// \cond
      23             : template <size_t Dim>
      24             : class Mesh;
      25             : namespace tuples {
      26             : template <typename... Tags>
      27             : class TaggedTuple;
      28             : }  // namespace tuples
      29             : /// \endcond
      30             : 
      31           0 : namespace dg::Actions {
      32             : /*!
      33             :  * \ingroup DiscontinuousGalerkinGroup
      34             :  * \brief Applies the element's spectral volume filter to the evolved variables.
      35             :  *
      36             :  * Retrieves the per-element filter from `Filters::Tags::SpectralFilter` from
      37             :  * the DataBox and applies the volume filter.
      38             :  *
      39             :  * The filter is skipped when:
      40             :  * - the filter is `Filters::None` (explicit no-op), or
      41             :  * - both `apply_volume_filter_on_substep()` and
      42             :  *   `apply_volume_filter_on_this_step(step_number)` return `false`.
      43             :  *
      44             :  * The grid-to-inertial Jacobian and its inverse are only retrieved from the
      45             :  * DataBox when `Filters::Filter::need_jacobians()` returns `true`; otherwise
      46             :  * `std::nullopt` is passed for both arguments.
      47             :  *
      48             :  * \note Currently the check for whether to filter on every `N` steps is done
      49             :  * relative to the start of the current Slab. This means that for GTS,
      50             :  * independent of the value of `N` for every `N` steps, every step has a
      51             :  * filter applied since GTS has one step per slab.
      52             :  *
      53             :  * Uses:
      54             :  * - DataBox:
      55             :  *   - `Filters::Tags::SpectralFilter<Dim, TagList>`
      56             :  *   - `Tags::StepNumberWithinSlab`
      57             :  *   - `domain::Tags::Mesh<Dim>`
      58             :  *   - `domain::Tags::InverseJacobian<Dim, Frame::Grid, Frame::Inertial>`
      59             :  *     (only when `need_jacobians()` is `true`)
      60             :  *   - `domain::Tags::Jacobian<Dim, Frame::Grid, Frame::Inertial>`
      61             :  *     (only when `need_jacobians()` is `true`)
      62             :  * - DataBox changes:
      63             :  *   - Modifies: `Metavariables::system::variables_tag`
      64             :  * - System:
      65             :  *   - `volume_dim`
      66             :  *   - `variables_tag`
      67             :  */
      68           1 : struct SpectralFilter {
      69             :   template <typename DbTags, typename... InboxTags, typename ArrayIndex,
      70             :             typename ActionList, typename ParallelComponent,
      71             :             typename Metavariables>
      72           0 :   static Parallel::iterable_action_return_t apply(
      73             :       db::DataBox<DbTags>& box,
      74             :       const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
      75             :       const Parallel::GlobalCache<Metavariables>& /*cache*/,
      76             :       const ArrayIndex& /*array_index*/, const ActionList /*meta*/,
      77             :       const ParallelComponent* const /*meta*/) {
      78             :     constexpr size_t Dim = Metavariables::system::volume_dim;
      79             :     using variables_tag = typename Metavariables::system::variables_tag;
      80             :     using TagList = typename variables_tag::tags_list;
      81             : 
      82             :     const auto& filter =
      83             :         db::get<Filters::Tags::SpectralFilter<Dim, TagList>>(box);
      84             : 
      85             :     const Mesh<Dim>& mesh = db::get<domain::Tags::Mesh<Dim>>(box);
      86             :     if (not filter.supports_mesh(mesh)) {
      87             :       ERROR("The filter '"
      88             :             << filter.name() << "' on element "
      89             :             << db::get<domain::Tags::Element<Dim>>(box).id() << " with mesh "
      90             :             << mesh
      91             :             << " does not support that mesh. This is a bug in initialization "
      92             :                "or if AMR projection during h-refinement incorrectly adjusted "
      93             :                "the filter.");
      94             :     }
      95             : 
      96             :     // None is explicitly a no-op; skip immediately.
      97             :     if (dynamic_cast<const Filters::None<Dim, TagList>*>(&filter) != nullptr) {
      98             :       return {Parallel::AlgorithmExecution::Continue, std::nullopt};
      99             :     }
     100             : 
     101             :     const auto step_number =
     102             :         static_cast<size_t>(db::get<::Tags::StepNumberWithinSlab>(box));
     103             :     if (not(filter.apply_volume_filter_on_substep() or
     104             :             filter.apply_volume_filter_on_this_step(step_number))) {
     105             :       return {Parallel::AlgorithmExecution::Continue, std::nullopt};
     106             :     }
     107             : 
     108             :     const size_t num_pts = mesh.number_of_grid_points();
     109             : 
     110             :     std::optional<
     111             :         InverseJacobian<DataVector, Dim, Frame::Grid, Frame::Inertial>>
     112             :         inv_jac{std::nullopt};
     113             :     std::optional<Jacobian<DataVector, Dim, Frame::Grid, Frame::Inertial>> jac{
     114             :         std::nullopt};
     115             :     if (filter.need_jacobians()) {
     116             :       if constexpr (db::tag_is_retrievable_v<
     117             :                         domain::Tags::InverseJacobian<Dim, Frame::Grid,
     118             :                                                       Frame::Inertial>,
     119             :                         db::DataBox<DbTags>>) {
     120             :         const auto& src = db::get<
     121             :             domain::Tags::InverseJacobian<Dim, Frame::Grid, Frame::Inertial>>(
     122             :             box);
     123             :         inv_jac =
     124             :             InverseJacobian<DataVector, Dim, Frame::Grid, Frame::Inertial>{};
     125             :         for (size_t i = 0; i < src.size(); ++i) {
     126             :           make_const_view(make_not_null(&std::as_const((*inv_jac)[i])), src[i],
     127             :                           0, num_pts);
     128             :         }
     129             :       } else {
     130             :         ERROR(
     131             :             "SpectralFilter: Missing "
     132             :             "domain::Tags::InverseJacobian<Dim, Grid, Inertial> in the "
     133             :             "DataBox. This should be present for both time-dependent and "
     134             :             "time-independent evolutions.");
     135             :       }
     136             :       if constexpr (db::tag_is_retrievable_v<
     137             :                         domain::Tags::Jacobian<Dim, Frame::Grid,
     138             :                                                Frame::Inertial>,
     139             :                         db::DataBox<DbTags>>) {
     140             :         const auto& src =
     141             :             db::get<domain::Tags::Jacobian<Dim, Frame::Grid, Frame::Inertial>>(
     142             :                 box);
     143             :         jac = Jacobian<DataVector, Dim, Frame::Grid, Frame::Inertial>{};
     144             :         for (size_t i = 0; i < src.size(); ++i) {
     145             :           make_const_view(make_not_null(&std::as_const((*jac)[i])), src[i], 0,
     146             :                           num_pts);
     147             :         }
     148             :       } else {
     149             :         ERROR(
     150             :             "SpectralFilter: Missing "
     151             :             "domain::Tags::Jacobian<Dim, Grid, Inertial> in the "
     152             :             "DataBox. This should be present for both time-dependent and "
     153             :             "time-independent evolutions.");
     154             :       }
     155             :     }
     156             : 
     157             :     db::mutate<variables_tag>(
     158             :         [&filter, &mesh, &inv_jac,
     159             :          &jac](const gsl::not_null<typename variables_tag::type*> vars) {
     160             :           filter.apply_in_volume(vars, mesh, inv_jac, jac);
     161             :         },
     162             :         make_not_null(&box));
     163             : 
     164             :     return {Parallel::AlgorithmExecution::Continue, std::nullopt};
     165             :   }
     166             : };
     167             : }  // namespace dg::Actions

Generated by: LCOV version 1.14