SpECTRE Documentation Coverage Report
Current view: top level - Evolution/DgSubcell - PrepareNeighborData.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 50.0 % 2 1
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 <array>
       7              : #include <cstddef>
       8              : #include <optional>
       9              : #include <utility>
      10              : 
      11              : #include "DataStructures/DataBox/DataBox.hpp"
      12              : #include "DataStructures/DataBox/PrefixHelpers.hpp"
      13              : #include "DataStructures/DataBox/Prefixes.hpp"
      14              : #include "DataStructures/DataVector.hpp"
      15              : #include "DataStructures/Index.hpp"
      16              : #include "Domain/Structure/Direction.hpp"
      17              : #include "Domain/Structure/DirectionMap.hpp"
      18              : #include "Domain/Structure/Element.hpp"
      19              : #include "Domain/Structure/ElementId.hpp"
      20              : #include "Domain/Structure/OrientationMapHelpers.hpp"
      21              : #include "Domain/Tags.hpp"
      22              : #include "Domain/Tags/NeighborMesh.hpp"
      23              : #include "Evolution/DgSubcell/Mesh.hpp"
      24              : #include "Evolution/DgSubcell/Projection.hpp"
      25              : #include "Evolution/DgSubcell/RdmpTci.hpp"
      26              : #include "Evolution/DgSubcell/RdmpTciData.hpp"
      27              : #include "Evolution/DgSubcell/SliceData.hpp"
      28              : #include "Evolution/DgSubcell/SubcellOptions.hpp"
      29              : #include "Evolution/DgSubcell/Tags/DataForRdmpTci.hpp"
      30              : #include "Evolution/DgSubcell/Tags/Interpolators.hpp"
      31              : #include "Evolution/DgSubcell/Tags/Mesh.hpp"
      32              : #include "Evolution/DgSubcell/Tags/SubcellOptions.hpp"
      33              : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
      34              : #include "Utilities/Algorithm.hpp"
      35              : #include "Utilities/ErrorHandling/Assert.hpp"
      36              : #include "Utilities/Gsl.hpp"
      37              : #include "Utilities/TMPL.hpp"
      38              : 
      39              : namespace evolution::dg::subcell {
      40              : /*!
      41              :  * \brief Add local data for our and our neighbor's relaxed discrete maximum
      42              :  * principle troubled-cell indicator, and for reconstruction.
      43              :  *
      44              :  * The local maximum and minimum of the evolved variables is added to
      45              :  * `Tags::DataForRdmpTci` for the RDMP TCI. Then the
      46              :  * data needed by neighbor elements to do reconstruction on the FD grid is sent.
      47              :  * The data to be sent is computed in the mutator
      48              :  * `Metavariables::SubcellOptions::GhostVariables`, which returns a
      49              :  * `Variables` of the tensors to send to the neighbors. The main reason for
      50              :  * having the mutator `GhostVariables` is to allow sending primitive or
      51              :  * characteristic variables for reconstruction.
      52              :  *
      53              :  * \note If all neighbors are using DG (i.e. none of their meshes is an FD mesh)
      54              :  * then we send our DG volume data _without_ orienting it. This elides the
      55              :  * expense of projection and slicing. If any
      56              :  * neighbors are doing FD, we project and slice to all neighbors. A future
      57              :  * optimization would be to measure the cost of slicing data, and figure out how
      58              :  * many neighbors need to be doing FD before it's worth projecting and slicing
      59              :  * vs. just projecting to the ghost cells. Another optimization is to always
      60              :  * send DG volume data to neighbors that we think are doing DG, so that we can
      61              :  * elide any slicing or projection cost in that direction.
      62              :  */
      63              : template <typename Metavariables, typename DbTagsList, size_t Dim>
      64            1 : void prepare_neighbor_data(
      65              :     const gsl::not_null<DirectionMap<Dim, DataVector>*>
      66              :         all_neighbor_data_for_reconstruction,
      67              :     const gsl::not_null<std::optional<Mesh<Dim>>*> ghost_data_mesh,
      68              :     const gsl::not_null<db::DataBox<DbTagsList>*> box,
      69              :     [[maybe_unused]] const Variables<db::wrap_tags_in<
      70              :         ::Tags::Flux, typename Metavariables::system::flux_variables,
      71              :         tmpl::size_t<Dim>, Frame::Inertial>>& volume_fluxes) {
      72              :   const Mesh<Dim>& dg_mesh = db::get<::domain::Tags::Mesh<Dim>>(*box);
      73              :   const Mesh<Dim>& subcell_mesh =
      74              :       db::get<::evolution::dg::subcell::Tags::Mesh<Dim>>(*box);
      75              :   const auto& element = db::get<::domain::Tags::Element<Dim>>(*box);
      76              : 
      77              :   const std::unordered_set<Direction<Dim>>& directions_to_slice =
      78              :       element.internal_boundaries();
      79              : 
      80              :   const auto& neighbor_meshes = db::get<domain::Tags::NeighborMesh<Dim>>(*box);
      81              :   const subcell::RdmpTciData& rdmp_data =
      82              :       db::get<subcell::Tags::DataForRdmpTci>(*box);
      83              :   const ::fd::DerivativeOrder fd_derivative_order =
      84              :       get<evolution::dg::subcell::Tags::SubcellOptions<Dim>>(*box)
      85              :           .finite_difference_derivative_order();
      86              :   const size_t rdmp_size = rdmp_data.max_variables_values.size() +
      87              :                            rdmp_data.min_variables_values.size();
      88              :   const size_t extra_size_for_ghost_data =
      89              :       (fd_derivative_order == ::fd::DerivativeOrder::Two
      90              :            ? 0
      91              :            : volume_fluxes.size());
      92              : 
      93              :   if (DataVector ghost_variables =
      94              :           [&box, &extra_size_for_ghost_data, &rdmp_size, &volume_fluxes]() {
      95              :             if (extra_size_for_ghost_data == 0) {
      96              :               return db::mutate_apply(
      97              :                   typename Metavariables::SubcellOptions::GhostVariables{}, box,
      98              :                   rdmp_size);
      99              :             } else {
     100              :               DataVector ghost_vars = db::mutate_apply(
     101              :                   typename Metavariables::SubcellOptions::GhostVariables{}, box,
     102              :                   rdmp_size + extra_size_for_ghost_data);
     103              :               std::copy(
     104              :                   volume_fluxes.data(),
     105              :                   std::next(volume_fluxes.data(),
     106              :                             static_cast<std::ptrdiff_t>(volume_fluxes.size())),
     107              :                   std::prev(ghost_vars.end(),
     108              :                             static_cast<std::ptrdiff_t>(
     109              :                                 rdmp_size + extra_size_for_ghost_data)));
     110              :               return ghost_vars;
     111              :             }
     112              :           }();
     113              :       (not fd::dg_mesh_supports_subcell(dg_mesh) or
     114              :        alg::all_of(neighbor_meshes,
     115              :                    [](const auto& directional_element_id_and_mesh) {
     116              :                      ASSERT(directional_element_id_and_mesh.second.basis(0) !=
     117              :                                 Spectral::Basis::Chebyshev,
     118              :                             "Don't yet support Chebyshev basis with DG-FD");
     119              :                      return directional_element_id_and_mesh.second.basis(0) !=
     120              :                             Spectral::Basis::FiniteDifference;
     121              :                    }))) {
     122              :     *ghost_data_mesh = dg_mesh;
     123              :     const size_t total_to_slice = directions_to_slice.size();
     124              :     size_t slice_count = 0;
     125              :     for (const auto& direction : directions_to_slice) {
     126              :       ++slice_count;
     127              :       // Move instead of copy on the last iteration. Elides a memory
     128              :       // allocation and copy.
     129              :       [[maybe_unused]] const auto insert_result =
     130              :           UNLIKELY(slice_count == total_to_slice)
     131              :               ? all_neighbor_data_for_reconstruction->insert_or_assign(
     132              :                     direction, std::move(ghost_variables))
     133              :               : all_neighbor_data_for_reconstruction->insert_or_assign(
     134              :                     direction, ghost_variables);
     135              :       ASSERT(all_neighbor_data_for_reconstruction->size() == total_to_slice or
     136              :                  insert_result.second,
     137              :              "Failed to insert the neighbor data in direction " << direction);
     138              :     }
     139              :   } else {
     140              :     *ghost_data_mesh = subcell_mesh;
     141              :     const size_t ghost_zone_size =
     142              :         Metavariables::SubcellOptions::ghost_zone_size(*box);
     143              : 
     144              :     const DataVector data_to_project{};
     145              :     make_const_view(make_not_null(&data_to_project), ghost_variables, 0,
     146              :                     ghost_variables.size() - rdmp_size);
     147              :     const DataVector projected_data = evolution::dg::subcell::fd::project(
     148              :         data_to_project, dg_mesh, subcell_mesh.extents(),
     149              :         typename Metavariables::SubcellOptions::GhostVariables::
     150              :             ghost_variables_tag_list{});
     151              :     typename evolution::dg::subcell::Tags::InterpolatorsFromFdToNeighborFd<
     152              :         Dim>::type directions_not_to_slice{};
     153              :     for (const auto& [directional_element_id, _] :
     154              :          db::get<evolution::dg::subcell::Tags::InterpolatorsFromFdToNeighborFd<
     155              :              Dim>>(*box)) {
     156              :       directions_not_to_slice[directional_element_id] = std::nullopt;
     157              :     }
     158              :     *all_neighbor_data_for_reconstruction = subcell::slice_data(
     159              :         projected_data, db::get<subcell::Tags::Mesh<Dim>>(*box).extents(),
     160              :         ghost_zone_size, directions_to_slice, rdmp_size,
     161              :         directions_not_to_slice);
     162              :     for (const auto& [directional_element_id, interpolator] :
     163              :          db::get<evolution::dg::subcell::Tags::InterpolatorsFromDgToNeighborFd<
     164              :              Dim>>(*box)) {
     165              :       // NOTE: no orienting is needed, that's done by the interpolation.
     166              :       ASSERT(interpolator.has_value(),
     167              :              "All interpolators must have values. The std::optional is used "
     168              :              "for some local optimizations.");
     169              :       DataVector& data_in_direction = all_neighbor_data_for_reconstruction->at(
     170              :           directional_element_id.direction());
     171              :       gsl::span result_in_direction{data_in_direction.data(),
     172              :                                     data_in_direction.size() - rdmp_size};
     173              :       interpolator->interpolate(
     174              :           make_not_null(&result_in_direction),
     175              :           {data_to_project.data(), data_to_project.size()});
     176              :     }
     177              :   }
     178              : 
     179              :   // Note: The RDMP TCI data must be filled by the TCIs before getting to this
     180              :   // call. That means once in the initial data and then in both the DG and FD
     181              :   // TCIs.
     182              :   for (const auto& [direction, neighbors] : element.neighbors()) {
     183              :     // Add the RDMP TCI data to what we will be sending.
     184              :     // Note that this is added _after_ the reconstruction data has been
     185              :     // re-oriented (in the case where we have neighbors doing FD).
     186              :     DataVector& neighbor_data =
     187              :         all_neighbor_data_for_reconstruction->at(direction);
     188              :     std::copy(rdmp_data.max_variables_values.begin(),
     189              :               rdmp_data.max_variables_values.end(),
     190              :               std::prev(neighbor_data.end(), static_cast<int>(rdmp_size)));
     191              :     std::copy(
     192              :         rdmp_data.min_variables_values.begin(),
     193              :         rdmp_data.min_variables_values.end(),
     194              :         std::prev(neighbor_data.end(),
     195              :                   static_cast<int>(rdmp_data.min_variables_values.size())));
     196              :   }
     197              : }
     198              : }  // namespace evolution::dg::subcell
        

Generated by: LCOV version 2.0-1