PrepareNeighborData.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <array>
7 #include <cstddef>
8 #include <utility>
9 #include <vector>
10 
12 #include "DataStructures/Index.hpp"
14 #include "Domain/Structure/DirectionMap.hpp"
17 #include "Domain/Structure/OrientationMapHelpers.hpp"
18 #include "Domain/Tags.hpp"
19 #include "Evolution/DgSubcell/NeighborData.hpp"
20 #include "Evolution/DgSubcell/RdmpTci.hpp"
21 #include "Evolution/DgSubcell/SliceData.hpp"
22 #include "Evolution/DgSubcell/Tags/Inactive.hpp"
23 #include "Evolution/DgSubcell/Tags/Mesh.hpp"
24 #include "Evolution/DgSubcell/Tags/NeighborData.hpp"
27 #include "Utilities/Gsl.hpp"
28 #include "Utilities/TMPL.hpp"
29 
30 namespace evolution::dg::subcell {
31 /*!
32  * \brief Add local data for our and our neighbor's relaxed discrete maximum
33  * principle troubled-cell indicator, and compute and slice data needed for the
34  * neighbor cells.
35  *
36  * The local maximum and minimum of the evolved variables is added to
37  * `Tags::NeighborDataForReconstructionAndRdmpTci` for the RDMP TCI. Then the
38  * data needed by neighbor elements to do reconstruction on the FD grid is sent.
39  * The data to be sent is computed in the mutator
40  * `Metavariables::SubcellOptions::GhostDataToSlice`, which returns a
41  * `Variables` of the tensors to slice and send to the neighbors. Note that the
42  * `Tags::Inactive<variables_tag>` are already projected onto the subcells
43  * before this function is called. This is because the projection needs to be
44  * done anyway for the a posteriori TCI. That is, the evolved variables are
45  * projected at the end of the time step rather than the beginning, while this
46  * function is called at the beginning. The main reason for having the mutator
47  * `GhostDataToSlice` is to allow sending primitive or characteristic variables
48  * for reconstruction.
49  */
50 template <typename Metavariables, typename DbTagsList>
53  const gsl::not_null<db::DataBox<DbTagsList>*> box) noexcept {
54  constexpr size_t volume_dim = Metavariables::volume_dim;
55  using variables_tag = typename Metavariables::system::variables_tag;
58  db::mutate<
60  box,
61  [&self_id](const auto neighbor_data_ptr,
63  max_min_of_vars) noexcept {
64  subcell::NeighborData rdmp_data{};
65  rdmp_data.max_variables_values = std::move(max_min_of_vars.first);
66  rdmp_data.min_variables_values = std::move(max_min_of_vars.second);
67  (*neighbor_data_ptr)[self_id] = std::move(rdmp_data);
68  },
70  db::get<variables_tag>(*box),
72  true));
73 
74  const auto& element = db::get<::domain::Tags::Element<volume_dim>>(*box);
76  all_neighbor_data_for_reconstruction{};
77 
78  DirectionMap<volume_dim, bool> directions_to_slice{};
79  for (const auto& [direction, neighbors_in_direction] : element.neighbors()) {
80  if (neighbors_in_direction.size() == 0) {
81  directions_to_slice[direction] = false;
82  } else {
83  directions_to_slice[direction] = true;
84  }
85  }
86 
87  const size_t ghost_zone_size =
88  Metavariables::SubcellOptions::ghost_zone_size(*box);
89 
90  // We can assume that the inactive tags are projected because if the TCI
91  // passed at the end of the last step, then as part of the RDMP it
92  // projected the data. We require the data be projected during
93  // initialization.
94  all_neighbor_data_for_reconstruction = subcell::slice_data(
96  typename Metavariables::SubcellOptions::GhostDataToSlice{}, box),
97  db::get<subcell::Tags::Mesh<volume_dim>>(*box).extents(), ghost_zone_size,
98  directions_to_slice);
99 
100  ASSERT(
101  db::get<
103  *box)
104  .contains(self_id),
105  "The self info for the RDMP TCI should have been added to the neighbor "
106  "data tag but wasn't.");
107  const subcell::NeighborData& rdmp_data =
108  db::get<
110  *box)
111  .at(self_id);
112 
113  for (const auto& [direction, neighbors] : element.neighbors()) {
114  const auto& orientation = neighbors.orientation();
115  const Mesh<volume_dim>& subcell_mesh =
116  db::get<subcell::Tags::Mesh<volume_dim>>(*box);
117  if (not orientation.is_aligned()) {
118  std::array<size_t, volume_dim> slice_extents{};
119  for (size_t d = 0; d < volume_dim; ++d) {
120  gsl::at(slice_extents, d) = subcell_mesh.extents(d);
121  }
122 
123  gsl::at(slice_extents, direction.dimension()) = ghost_zone_size;
124 
125  all_neighbor_data_for_reconstruction.at(direction) =
126  orient_variables(all_neighbor_data_for_reconstruction.at(direction),
127  Index<volume_dim>{slice_extents}, orientation);
128  }
129 
130  // Add the RDMP TCI data to what we will be sending.
131  // Note that this is added _after_ the reconstruction data has been
132  // re-oriented.
133  std::vector<double>& neighbor_subcell_data =
134  all_neighbor_data_for_reconstruction.at(direction);
135  neighbor_subcell_data.reserve(neighbor_subcell_data.size() +
136  rdmp_data.max_variables_values.size() +
137  rdmp_data.min_variables_values.size());
138  neighbor_subcell_data.insert(neighbor_subcell_data.end(),
139  rdmp_data.max_variables_values.begin(),
140  rdmp_data.max_variables_values.end());
141  neighbor_subcell_data.insert(neighbor_subcell_data.end(),
142  rdmp_data.min_variables_values.begin(),
143  rdmp_data.min_variables_values.end());
144  }
145 
146  return all_neighbor_data_for_reconstruction;
147 }
148 } // namespace evolution::dg::subcell
evolution::dg::subcell::rdmp_max_min
std::pair< std::vector< double >, std::vector< double > > rdmp_max_min(const Variables< tmpl::list< EvolvedVarsTags... >> &active_grid_evolved_vars, const Variables< tmpl::list< Tags::Inactive< EvolvedVarsTags >... >> &inactive_grid_evolved_vars, const bool include_inactive_grid) noexcept
get the max and min of each component of the active and inactive variables. If include_inactive_grid ...
Definition: RdmpTci.hpp:125
gsl::at
constexpr T & at(std::array< T, N > &arr, Size index)
Retrieve a entry from a container, with checks in Debug mode that the index being retrieved is valid.
Definition: Gsl.hpp:125
ElementId::external_boundary_id
static ElementId< VolumeDim > external_boundary_id() noexcept
Returns an ElementId meant for identifying data on external boundaries, which should never correspond...
orient_variables
Variables< TagsList > orient_variables(const Variables< TagsList > &variables, const Index< VolumeDim > &extents, const OrientationMap< VolumeDim > &orientation_of_neighbor) noexcept
Definition: OrientationMapHelpers.hpp:55
utility
std::pair
Tags.hpp
vector
db::get
const auto & get(const DataBox< TagList > &box) noexcept
Retrieve the item with tag Tag from the DataBox.
Definition: DataBox.hpp:791
Index
Definition: Index.hpp:31
Direction::lower_xi
static Direction< VolumeDim > lower_xi() noexcept
Helper functions for creating specific Directions. These are labeled by the logical-coordinate names ...
evolution::dg::subcell::prepare_neighbor_data
DirectionMap< Metavariables::volume_dim, std::vector< double > > prepare_neighbor_data(const gsl::not_null< db::DataBox< DbTagsList > * > box) noexcept
Add local data for our and our neighbor's relaxed discrete maximum principle troubled-cell indicator,...
Definition: PrepareNeighborData.hpp:52
ElementId.hpp
db::mutate
decltype(auto) mutate(const gsl::not_null< DataBox< TagList > * > box, Invokable &&invokable, Args &&... args) noexcept
Allows changing the state of one or more non-computed elements in the DataBox.
Definition: DataBox.hpp:641
evolution::dg::subcell::Tags::NeighborDataForReconstructionAndRdmpTci
The neighbor data for reconstruction and the RDMP troubled-cell indicator.
Definition: NeighborData.hpp:25
DataBox.hpp
cstddef
Assert.hpp
array
Index.hpp
evolution::dg::subcell::Tags::Mesh
The mesh on the subcells.
Definition: Mesh.hpp:18
ASSERT
#define ASSERT(a, m)
Assert that an expression should be true.
Definition: Assert.hpp:49
Element.hpp
Mesh
Holds the number of grid points, basis, and quadrature in each direction of the computational grid.
Definition: Mesh.hpp:49
evolution::dg::subcell::NeighborData
Holds neighbor data needed for the TCI and reconstruction.
Definition: NeighborData.hpp:24
DirectionMap
Definition: DirectionMap.hpp:15
evolution::dg::subcell
Implementation of a generic finite volume/conservative finite difference subcell limiter.
Definition: Actions.hpp:6
Gsl.hpp
db::mutate_apply
constexpr decltype(auto) mutate_apply(F &&f, const gsl::not_null< DataBox< BoxTags > * > box, Args &&... args) noexcept
Apply the invokable f mutating items MutateTags and taking as additional arguments ArgumentTags and a...
Definition: DataBox.hpp:1247
evolution::dg::subcell::slice_data
DirectionMap< Dim, std::vector< double > > slice_data(const Variables< TagList > &volume_subcell_vars, const Index< Dim > &subcell_extents, const size_t number_of_ghost_points, const DirectionMap< Dim, bool > &directions_to_slice) noexcept
Slice the subcell variables needed for neighbors to perform reconstruction.
Definition: SliceData.hpp:45
Direction.hpp
evolution::dg::subcell::Tags::Inactive
Mark a tag as holding data for the inactive grid.
Definition: Inactive.hpp:23
Mesh::extents
const Index< Dim > & extents() const noexcept
The number of grid points in each dimension of the grid.
Definition: Mesh.hpp:148
TMPL.hpp
Mesh.hpp
gsl::not_null
Require a pointer to not be a nullptr
Definition: ReadSpecPiecewisePolynomial.hpp:13