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

Generated by: LCOV version 1.14