SpECTRE Documentation Coverage Report
Current view: top level - Evolution/DgSubcell/Actions - ReconstructionCommunication.hpp Hit Total Coverage
Commit: 3c072f0ce967e2e56649d3fa12aa2a0e4fe2a42e Lines: 2 6 33.3 %
Date: 2024-04-23 20:50:18
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 <algorithm>
       7             : #include <array>
       8             : #include <cstddef>
       9             : #include <iterator>
      10             : #include <limits>
      11             : #include <map>
      12             : #include <optional>
      13             : #include <tuple>
      14             : #include <unordered_set>
      15             : #include <utility>
      16             : 
      17             : #include "DataStructures/DataBox/DataBox.hpp"
      18             : #include "DataStructures/DataBox/Prefixes.hpp"
      19             : #include "DataStructures/DataVector.hpp"
      20             : #include "DataStructures/Index.hpp"
      21             : #include "DataStructures/Tensor/Tensor.hpp"
      22             : #include "DataStructures/Variables.hpp"
      23             : #include "DataStructures/VariablesTag.hpp"
      24             : #include "Domain/Structure/Direction.hpp"
      25             : #include "Domain/Structure/DirectionalId.hpp"
      26             : #include "Domain/Structure/DirectionalIdMap.hpp"
      27             : #include "Domain/Structure/Element.hpp"
      28             : #include "Domain/Structure/ElementId.hpp"
      29             : #include "Domain/Structure/OrientationMapHelpers.hpp"
      30             : #include "Domain/Structure/TrimMap.hpp"
      31             : #include "Domain/Tags.hpp"
      32             : #include "Domain/Tags/NeighborMesh.hpp"
      33             : #include "Evolution/DgSubcell/ActiveGrid.hpp"
      34             : #include "Evolution/DgSubcell/GhostData.hpp"
      35             : #include "Evolution/DgSubcell/NeighborRdmpAndVolumeData.hpp"
      36             : #include "Evolution/DgSubcell/Projection.hpp"
      37             : #include "Evolution/DgSubcell/RdmpTci.hpp"
      38             : #include "Evolution/DgSubcell/RdmpTciData.hpp"
      39             : #include "Evolution/DgSubcell/SliceData.hpp"
      40             : #include "Evolution/DgSubcell/Tags/ActiveGrid.hpp"
      41             : #include "Evolution/DgSubcell/Tags/CellCenteredFlux.hpp"
      42             : #include "Evolution/DgSubcell/Tags/DataForRdmpTci.hpp"
      43             : #include "Evolution/DgSubcell/Tags/GhostDataForReconstruction.hpp"
      44             : #include "Evolution/DgSubcell/Tags/Interpolators.hpp"
      45             : #include "Evolution/DgSubcell/Tags/Mesh.hpp"
      46             : #include "Evolution/DgSubcell/Tags/Reconstructor.hpp"
      47             : #include "Evolution/DgSubcell/Tags/TciStatus.hpp"
      48             : #include "Evolution/DiscontinuousGalerkin/InboxTags.hpp"
      49             : #include "Evolution/DiscontinuousGalerkin/MortarData.hpp"
      50             : #include "Evolution/DiscontinuousGalerkin/MortarTags.hpp"
      51             : #include "NumericalAlgorithms/Interpolation/IrregularInterpolant.hpp"
      52             : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
      53             : #include "NumericalAlgorithms/Spectral/Spectral.hpp"
      54             : #include "Parallel/AlgorithmExecution.hpp"
      55             : #include "Parallel/GlobalCache.hpp"
      56             : #include "Time/TimeStepId.hpp"
      57             : #include "Utilities/ErrorHandling/Assert.hpp"
      58             : #include "Utilities/Gsl.hpp"
      59             : #include "Utilities/Literals.hpp"
      60             : #include "Utilities/MakeArray.hpp"
      61             : #include "Utilities/TMPL.hpp"
      62             : 
      63             : /// \cond
      64             : namespace Tags {
      65             : struct TimeStepId;
      66             : }  // namespace Tags
      67             : /// \endcond
      68             : 
      69             : namespace evolution::dg::subcell::Actions {
      70             : /*!
      71             :  * \brief Sets the local data from the relaxed discrete maximum principle
      72             :  * troubled-cell indicator and sends ghost zone data to neighboring elements.
      73             :  *
      74             :  * The action proceeds as follows:
      75             :  *
      76             :  * 1. Determine in which directions we have neighbors
      77             :  * 2. Slice the variables provided by GhostDataMutator to send to our neighbors
      78             :  *    for ghost zones
      79             :  * 3. Send the ghost zone data, appending the max/min for the TCI at the end of
      80             :  *    the `DataVector` we are sending.
      81             :  *
      82             :  * \warning This assumes the RDMP TCI data in the DataBox has been set, it does
      83             :  * not calculate it automatically. The reason is this way we can only calculate
      84             :  * the RDMP data when it's needed since computing it can be pretty expensive.
      85             :  *
      86             :  * Some notes:
      87             :  * - In the future we will need to send the cell-centered fluxes to do
      88             :  *   high-order FD without additional reconstruction being necessary.
      89             :  *
      90             :  * GlobalCache:
      91             :  * - Uses:
      92             :  *   - `ParallelComponent` proxy
      93             :  *
      94             :  * DataBox:
      95             :  * - Uses:
      96             :  *   - `domain::Tags::Mesh<Dim>`
      97             :  *   - `subcell::Tags::Mesh<Dim>`
      98             :  *   - `domain::Tags::Element<Dim>`
      99             :  *   - `Tags::TimeStepId`
     100             :  *   - `Tags::Next<Tags::TimeStepId>`
     101             :  *   - `subcell::Tags::ActiveGrid`
     102             :  *   - `System::variables_tag`
     103             :  *   - `subcell::Tags::DataForRdmpTci`
     104             :  * - Adds: nothing
     105             :  * - Removes: nothing
     106             :  * - Modifies:
     107             :  *   - `subcell::Tags::GhostDataForReconstruction<Dim>`
     108             :  */
     109             : template <size_t Dim, typename GhostDataMutator, bool LocalTimeStepping>
     110           1 : struct SendDataForReconstruction {
     111           0 :   using inbox_tags = tmpl::list<
     112             :       evolution::dg::Tags::BoundaryCorrectionAndGhostCellsInbox<Dim>>;
     113             : 
     114             :   template <typename DbTags, typename... InboxTags, typename ArrayIndex,
     115             :             typename ActionList, typename ParallelComponent,
     116             :             typename Metavariables>
     117           0 :   static Parallel::iterable_action_return_t apply(
     118             :       db::DataBox<DbTags>& box, tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
     119             :       Parallel::GlobalCache<Metavariables>& cache,
     120             :       const ArrayIndex& /*array_index*/, const ActionList /*meta*/,
     121             :       const ParallelComponent* const /*meta*/) {
     122             :     static_assert(
     123             :         not LocalTimeStepping,
     124             :         "DG-subcell does not yet support local time stepping. The "
     125             :         "reconstruction data must be sent using dense output sometimes, and "
     126             :         "not at all other times. However, the data for the RDMP TCI should be "
     127             :         "sent along with the data for reconstruction each time.");
     128             : 
     129             :     ASSERT(db::get<Tags::ActiveGrid>(box) == ActiveGrid::Subcell,
     130             :            "The SendDataForReconstruction action can only be called when "
     131             :            "Subcell is the active scheme.");
     132             :     using flux_variables = typename Metavariables::system::flux_variables;
     133             : 
     134             :     db::mutate<Tags::GhostDataForReconstruction<Dim>>(
     135             :         [](const auto ghost_data_ptr) {
     136             :           // Clear the previous neighbor data and add current local data
     137             :           ghost_data_ptr->clear();
     138             :         },
     139             :         make_not_null(&box));
     140             : 
     141             :     const Mesh<Dim>& dg_mesh = db::get<::domain::Tags::Mesh<Dim>>(box);
     142             :     const Mesh<Dim>& subcell_mesh = db::get<Tags::Mesh<Dim>>(box);
     143             :     const Element<Dim>& element = db::get<::domain::Tags::Element<Dim>>(box);
     144             :     const size_t ghost_zone_size =
     145             :         db::get<evolution::dg::subcell::Tags::Reconstructor>(box)
     146             :             .ghost_zone_size();
     147             : 
     148             :     // Optimization note: could save a copy+allocation if we moved
     149             :     // all_sliced_data when possible before sending.
     150             :     //
     151             :     // Note: RDMP size doesn't help here since we need to slice data after
     152             :     // anyway, so no way to save an allocation through that.
     153             :     const auto& cell_centered_flux =
     154             :         db::get<Tags::CellCenteredFlux<flux_variables, Dim>>(box);
     155             :     DataVector volume_data_to_slice = db::mutate_apply(
     156             :         GhostDataMutator{}, make_not_null(&box),
     157             :         cell_centered_flux.has_value() ? cell_centered_flux.value().size()
     158             :                                        : 0_st);
     159             :     if (cell_centered_flux.has_value()) {
     160             :       std::copy(
     161             :           cell_centered_flux.value().data(),
     162             :           std::next(
     163             :               cell_centered_flux.value().data(),
     164             :               static_cast<std::ptrdiff_t>(cell_centered_flux.value().size())),
     165             :           std::next(
     166             :               volume_data_to_slice.data(),
     167             :               static_cast<std::ptrdiff_t>(volume_data_to_slice.size() -
     168             :                                           cell_centered_flux.value().size())));
     169             :     }
     170             :     const DirectionMap<Dim, DataVector> all_sliced_data = slice_data(
     171             :         volume_data_to_slice, subcell_mesh.extents(), ghost_zone_size,
     172             :         element.internal_boundaries(), 0,
     173             :         db::get<
     174             :             evolution::dg::subcell::Tags::InterpolatorsFromFdToNeighborFd<Dim>>(
     175             :             box));
     176             : 
     177             :     auto& receiver_proxy =
     178             :         Parallel::get_parallel_component<ParallelComponent>(cache);
     179             :     const RdmpTciData& rdmp_tci_data = db::get<Tags::DataForRdmpTci>(box);
     180             :     const TimeStepId& time_step_id = db::get<::Tags::TimeStepId>(box);
     181             :     const TimeStepId& next_time_step_id = [&box]() {
     182             :       if (LocalTimeStepping) {
     183             :         return db::get<::Tags::Next<::Tags::TimeStepId>>(box);
     184             :       } else {
     185             :         return db::get<::Tags::TimeStepId>(box);
     186             :       }
     187             :     }();
     188             : 
     189             :     const int tci_decision =
     190             :         db::get<evolution::dg::subcell::Tags::TciDecision>(box);
     191             :     // Compute and send actual variables
     192             :     for (const auto& [direction, neighbors_in_direction] :
     193             :          element.neighbors()) {
     194             :       const auto& orientation = neighbors_in_direction.orientation();
     195             :       const auto direction_from_neighbor = orientation(direction.opposite());
     196             :       ASSERT(neighbors_in_direction.size() == 1,
     197             :              "AMR is not yet supported when using DG-subcell. Note that this "
     198             :              "condition could be relaxed to support AMR only where the "
     199             :              "evolution is using DG without any changes to subcell.");
     200             : 
     201             :       for (const ElementId<Dim>& neighbor : neighbors_in_direction) {
     202             :         const size_t rdmp_size = rdmp_tci_data.max_variables_values.size() +
     203             :                                  rdmp_tci_data.min_variables_values.size();
     204             :         const auto& sliced_data_in_direction = all_sliced_data.at(direction);
     205             :         // Allocate with subcell data and rdmp data
     206             :         DataVector subcell_data_to_send{sliced_data_in_direction.size() +
     207             :                                         rdmp_size};
     208             :         // Note: Currently we interpolate our solution to our neighbor FD grid
     209             :         // even when grid points align but are oriented differently. There's a
     210             :         // possible optimization for the rare (almost never?) edge case where
     211             :         // two blocks have the same ghost zone coordinates but have different
     212             :         // orientations (e.g. RotatedBricks). Since this shouldn't ever happen
     213             :         // outside of tests, we currently don't bother with it. If we wanted to,
     214             :         // here's the code:
     215             :         //
     216             :         // if (not orientation.is_aligned()) {
     217             :         //   std::array<size_t, Dim> slice_extents{};
     218             :         //   for (size_t d = 0; d < Dim; ++d) {
     219             :         //     gsl::at(slice_extents, d) = subcell_mesh.extents(d);
     220             :         //   }
     221             :         //   gsl::at(slice_extents, direction.dimension()) = ghost_zone_size;
     222             :         //   // Need a view so we only get the subcell data and not the rdmp
     223             :         //   // data
     224             :         //   DataVector subcell_data_to_send_view{
     225             :         //       subcell_data_to_send.data(),
     226             :         //       subcell_data_to_send.size() - rdmp_size};
     227             :         //   orient_variables(make_not_null(&subcell_data_to_send_view),
     228             :         //                  sliced_data_in_direction, Index<Dim>{slice_extents},
     229             :         //                  orientation);
     230             :         // } else { std::copy(...); }
     231             :         //
     232             :         // Copy over data since it's already oriented from interpolation
     233             :         std::copy(sliced_data_in_direction.begin(),
     234             :                   sliced_data_in_direction.end(), subcell_data_to_send.begin());
     235             :         // Copy rdmp data to end of subcell_data_to_send
     236             :         std::copy(
     237             :             rdmp_tci_data.max_variables_values.cbegin(),
     238             :             rdmp_tci_data.max_variables_values.cend(),
     239             :             std::prev(subcell_data_to_send.end(), static_cast<int>(rdmp_size)));
     240             :         std::copy(rdmp_tci_data.min_variables_values.cbegin(),
     241             :                   rdmp_tci_data.min_variables_values.cend(),
     242             :                   std::prev(subcell_data_to_send.end(),
     243             :                             static_cast<int>(
     244             :                                 rdmp_tci_data.min_variables_values.size())));
     245             : 
     246             :         std::tuple<Mesh<Dim>, Mesh<Dim - 1>, std::optional<DataVector>,
     247             :                    std::optional<DataVector>, ::TimeStepId, int>
     248             :             data{subcell_mesh,
     249             :                  dg_mesh.slice_away(direction.dimension()),
     250             :                  std::move(subcell_data_to_send),
     251             :                  std::nullopt,
     252             :                  next_time_step_id,
     253             :                  tci_decision};
     254             : 
     255             :         Parallel::receive_data<
     256             :             evolution::dg::Tags::BoundaryCorrectionAndGhostCellsInbox<Dim>>(
     257             :             receiver_proxy[neighbor], time_step_id,
     258             :             std::pair{DirectionalId<Dim>{direction_from_neighbor, element.id()},
     259             :                       std::move(data)});
     260             :       }
     261             :     }
     262             :     return {Parallel::AlgorithmExecution::Continue, std::nullopt};
     263             :   }
     264             : };
     265             : 
     266             : /*!
     267             :  * \brief Receive the subcell data from our neighbor, and accumulate the data
     268             :  * from the relaxed discrete maximum principle troubled-cell indicator.
     269             :  *
     270             :  * Note:
     271             :  * - Since we only care about the min/max over all neighbors and ourself at the
     272             :  *   past time, we accumulate all data immediately into the `RdmpTciData`.
     273             :  * - If the neighbor is using DG and therefore sends boundary correction data
     274             :  *   then that is added into the `evolution::dg::Tags::MortarData` tag
     275             :  * - The next `TimeStepId` is recorded, but we do not yet support local time
     276             :  *   stepping.
     277             :  * - This action will never care about what variables are sent for
     278             :  *   reconstruction. It is only responsible for receiving the data and storing
     279             :  *   it in the `NeighborData`.
     280             :  *
     281             :  * GlobalCache:
     282             :  * -Uses: nothing
     283             :  *
     284             :  * DataBox:
     285             :  * - Uses:
     286             :  *   - `domain::Tags::Element<Dim>`
     287             :  *   - `Tags::TimeStepId`
     288             :  *   - `domain::Tags::Mesh<Dim>`
     289             :  *   - `subcell::Tags::Mesh<Dim>`
     290             :  *   - `domain::Tags::Element<Dim>`
     291             :  *   - `Tags::Next<Tags::TimeStepId>`
     292             :  *   - `subcell::Tags::ActiveGrid`
     293             :  *   - `System::variables_tag`
     294             :  * - Adds: nothing
     295             :  * - Removes: nothing
     296             :  * - Modifies:
     297             :  *   - `subcell::Tags::GhostDataForReconstruction<Dim>`
     298             :  *   - `subcell::Tags::DataForRdmpTci`
     299             :  *   - `evolution::dg::Tags::MortarData`
     300             :  *   - `evolution::dg::Tags::MortarNextTemporalId`
     301             :  */
     302             : template <size_t Dim>
     303           1 : struct ReceiveDataForReconstruction {
     304             :   template <typename DbTags, typename... InboxTags, typename ArrayIndex,
     305             :             typename ActionList, typename ParallelComponent,
     306             :             typename Metavariables>
     307           0 :   static Parallel::iterable_action_return_t apply(
     308             :       db::DataBox<DbTags>& box, tuples::TaggedTuple<InboxTags...>& inboxes,
     309             :       const Parallel::GlobalCache<Metavariables>& /*cache*/,
     310             :       const ArrayIndex& /*array_index*/, const ActionList /*meta*/,
     311             :       const ParallelComponent* const /*meta*/) {
     312             :     const Element<Dim>& element = db::get<::domain::Tags::Element<Dim>>(box);
     313             :     const auto number_of_expected_messages = element.neighbors().size();
     314             :     if (UNLIKELY(number_of_expected_messages == 0)) {
     315             :       // We have no neighbors, so just continue without doing any work
     316             :       return {Parallel::AlgorithmExecution::Continue, std::nullopt};
     317             :     }
     318             : 
     319             :     using ::operator<<;
     320             :     using Key = DirectionalId<Dim>;
     321             :     const auto& current_time_step_id = db::get<::Tags::TimeStepId>(box);
     322             :     std::map<TimeStepId,
     323             :              DirectionalIdMap<Dim, std::tuple<Mesh<Dim>, Mesh<Dim - 1>,
     324             :                                               std::optional<DataVector>,
     325             :                                               std::optional<DataVector>,
     326             :                                               ::TimeStepId, int>>>& inbox =
     327             :         tuples::get<evolution::dg::Tags::BoundaryCorrectionAndGhostCellsInbox<
     328             :             Metavariables::volume_dim>>(inboxes);
     329             :     const auto& received = inbox.find(current_time_step_id);
     330             :     // Check we have at least some data from correct time, and then check that
     331             :     // we have received all data
     332             :     if (received == inbox.end() or
     333             :         received->second.size() != number_of_expected_messages) {
     334             :       return {Parallel::AlgorithmExecution::Retry, std::nullopt};
     335             :     }
     336             : 
     337             :     // Now that we have received all the data, copy it over as needed.
     338             :     DirectionalIdMap<
     339             :         Dim, std::tuple<Mesh<Dim>, Mesh<Dim - 1>, std::optional<DataVector>,
     340             :                         std::optional<DataVector>, ::TimeStepId, int>>
     341             :         received_data = std::move(inbox[current_time_step_id]);
     342             :     inbox.erase(current_time_step_id);
     343             : 
     344             :     const Mesh<Dim>& subcell_mesh = db::get<Tags::Mesh<Dim>>(box);
     345             : 
     346             :     db::mutate<Tags::GhostDataForReconstruction<Dim>, Tags::DataForRdmpTci,
     347             :                evolution::dg::Tags::MortarData<Dim>,
     348             :                evolution::dg::Tags::MortarNextTemporalId<Dim>,
     349             :                domain::Tags::NeighborMesh<Dim>,
     350             :                evolution::dg::subcell::Tags::NeighborTciDecisions<Dim>>(
     351             :         [&current_time_step_id, &element,
     352             :          ghost_zone_size =
     353             :              db::get<evolution::dg::subcell::Tags::Reconstructor>(box)
     354             :                  .ghost_zone_size(),
     355             :          &received_data, &subcell_mesh](
     356             :             const gsl::not_null<DirectionalIdMap<Dim, GhostData>*>
     357             :                 ghost_data_ptr,
     358             :             const gsl::not_null<RdmpTciData*> rdmp_tci_data_ptr,
     359             :             const gsl::not_null<std::unordered_map<
     360             :                 Key, evolution::dg::MortarData<Dim>, boost::hash<Key>>*>
     361             :                 mortar_data,
     362             :             const gsl::not_null<
     363             :                 std::unordered_map<Key, TimeStepId, boost::hash<Key>>*>
     364             :                 mortar_next_time_step_id,
     365             :             const gsl::not_null<DirectionalIdMap<Dim, Mesh<Dim>>*>
     366             :                 neighbor_mesh,
     367             :             const auto neighbor_tci_decisions,
     368             :             const DirectionalIdMap<Dim, std::optional<intrp::Irregular<Dim>>>&
     369             :                 neighbor_dg_to_fd_interpolants) {
     370             :           // Remove neighbor meshes for neighbors that don't exist anymore
     371             :           domain::remove_nonexistent_neighbors(neighbor_mesh, element);
     372             : 
     373             :           // Get the next time step id, and also the fluxes data if the neighbor
     374             :           // is doing DG.
     375             :           for (auto& received_mortar_data : received_data) {
     376             :             const auto& mortar_id = received_mortar_data.first;
     377             :             try {
     378             :               mortar_next_time_step_id->at(mortar_id) =
     379             :                   std::get<4>(received_mortar_data.second);
     380             :             } catch (std::exception& e) {
     381             :               ERROR("Failed retrieving the MortarId: ("
     382             :                     << mortar_id.direction << ',' << mortar_id.id
     383             :                     << ") from the mortar_next_time_step_id. Got exception: "
     384             :                     << e.what());
     385             :             }
     386             :             if (std::get<3>(received_mortar_data.second).has_value()) {
     387             :               mortar_data->at(mortar_id).insert_neighbor_mortar_data(
     388             :                   current_time_step_id,
     389             :                   std::get<1>(received_mortar_data.second),
     390             :                   std::move(*std::get<3>(received_mortar_data.second)));
     391             :             }
     392             :             // Set new neighbor mesh
     393             :             neighbor_mesh->insert_or_assign(
     394             :                 mortar_id, std::get<0>(received_mortar_data.second));
     395             :           }
     396             : 
     397             :           ASSERT(ghost_data_ptr->empty(),
     398             :                  "Should have no elements in the neighbor data when "
     399             :                  "receiving neighbor data");
     400             :           const size_t number_of_rdmp_vars =
     401             :               rdmp_tci_data_ptr->max_variables_values.size();
     402             :           ASSERT(rdmp_tci_data_ptr->min_variables_values.size() ==
     403             :                      number_of_rdmp_vars,
     404             :                  "The number of RDMP variables for which we have a maximum "
     405             :                  "and minimum should be the same, but we have "
     406             :                      << number_of_rdmp_vars << " for the max and "
     407             :                      << rdmp_tci_data_ptr->min_variables_values.size()
     408             :                      << " for the min.");
     409             : 
     410             :           for (const auto& [direction, neighbors_in_direction] :
     411             :                element.neighbors()) {
     412             :             for (const auto& neighbor : neighbors_in_direction) {
     413             :               DirectionalId<Dim> directional_element_id{direction, neighbor};
     414             :               ASSERT(ghost_data_ptr->count(directional_element_id) == 0,
     415             :                      "Found neighbor already inserted in direction "
     416             :                          << direction << " with ElementId " << neighbor);
     417             :               ASSERT(std::get<2>(received_data[directional_element_id])
     418             :                          .has_value(),
     419             :                      "Received subcell data message that does not contain any "
     420             :                      "actual subcell data for reconstruction.");
     421             :               // Collect the max/min of u(t^n) for the RDMP as we receive data.
     422             :               // This reduces the memory footprint.
     423             : 
     424             :               evolution::dg::subcell::insert_neighbor_rdmp_and_volume_data(
     425             :                   rdmp_tci_data_ptr, ghost_data_ptr,
     426             :                   *std::get<2>(received_data[directional_element_id]),
     427             :                   number_of_rdmp_vars, directional_element_id,
     428             :                   neighbor_mesh->at(directional_element_id), element,
     429             :                   subcell_mesh, ghost_zone_size,
     430             :                   neighbor_dg_to_fd_interpolants);
     431             :               ASSERT(neighbor_tci_decisions->contains(directional_element_id),
     432             :                      "The NeighorTciDecisions should contain the neighbor ("
     433             :                          << directional_element_id.direction << ", "
     434             :                          << directional_element_id.id << ") but doesn't");
     435             :               neighbor_tci_decisions->at(directional_element_id) =
     436             :                   std::get<5>(received_data[directional_element_id]);
     437             :             }
     438             :           }
     439             :         },
     440             :         make_not_null(&box),
     441             :         db::get<
     442             :             evolution::dg::subcell::Tags::InterpolatorsFromNeighborDgToFd<Dim>>(
     443             :             box));
     444             :     return {Parallel::AlgorithmExecution::Continue, std::nullopt};
     445             :   }
     446             : };
     447             : }  // namespace evolution::dg::subcell::Actions

Generated by: LCOV version 1.14