NeighborReconstructedFaceSolution.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <boost/functional/hash.hpp>
7 #include <cstddef>
8 #include <iterator>
9 #include <optional>
10 #include <tuple>
11 #include <utility>
12 #include <vector>
13 
15 #include "DataStructures/FixedHashMap.hpp"
18 #include "Domain/Structure/MaxNumberOfNeighbors.hpp"
19 #include "Evolution/DgSubcell/NeighborData.hpp"
20 #include "Evolution/DgSubcell/Tags/Inactive.hpp"
21 #include "Evolution/DgSubcell/Tags/Mesh.hpp"
22 #include "Evolution/DgSubcell/Tags/NeighborData.hpp"
24 #include "Time/TimeStepId.hpp"
26 #include "Utilities/Gsl.hpp"
27 
28 namespace evolution::dg::subcell {
29 /*!
30  * \brief Invoked in directions where the neighbor is doing subcell, this
31  * function computes the neighbor data on the mortar via reconstruction on
32  * nearest neighbor subcells.
33  *
34  *
35  * The data needed for reconstruction is copied over into
36  * `subcell::Tags::NeighborDataForReconstructionAndRdmpTci`.
37  * Additionally, the max/min of the evolved variables from neighboring elements
38  * that is used for the relaxed discrete maximum principle troubled-cell
39  * indicator is combined with the data from the local element and stored in
40  * `subcell::Tags::NeighborDataForReconstructionAndRdmpTci`. We handle the RDMP
41  * data now because it is sent in the same buffer as the data for
42  * reconstruction.
43  *
44  * A list of all the directions that are doing subcell is created and then
45  * passed to the mutator
46  * `Metavariables::SubcellOptions::DgOuterCorrectionPackageData::apply`, which
47  * must return a
48  *
49  * \code
50  * FixedHashMap<
51  * maximum_number_of_neighbors(volume_dim),
52  * std::pair<Direction<volume_dim>, ElementId<volume_dim>>,
53  * std::vector<double>,
54  * boost::hash<std::pair<Direction<volume_dim>, ElementId<volume_dim>>>>
55  * \endcode
56  *
57  * which holds the reconstructed `dg_packaged_data` on the face (stored in the
58  * `std::vector<double>`) for the boundary correction. A
59  * `std::vector<std::pair<Direction<volume_dim>, ElementId<volume_dim>>>`
60  * holding the list of mortars that need to be reconstructed to is passed in as
61  * the last argument to
62  * `Metavariables::SubcellOptions::DgOuterCorrectionPackageData::apply`.
63  */
64 template <typename Metavariables, typename DbTagsList>
66  const gsl::not_null<db::DataBox<DbTagsList>*> box,
68  const TimeStepId,
70  maximum_number_of_neighbors(Metavariables::volume_dim),
78  received_temporal_id_and_data) noexcept {
79  constexpr size_t volume_dim = Metavariables::volume_dim;
80  db::mutate<
82  box, [&received_temporal_id_and_data](
83  const auto subcell_neighbor_data_ptr) noexcept {
84  subcell::NeighborData& self_neighbor_data =
85  subcell_neighbor_data_ptr->at(
88  const size_t number_of_evolved_vars =
89  self_neighbor_data.max_variables_values.size();
90  for (auto& received_mortar_data :
91  received_temporal_id_and_data->second) {
92  const auto& mortar_id = received_mortar_data.first;
93  ASSERT(std::get<1>(received_mortar_data.second).has_value(),
94  "The subcell mortar data was not sent at TimeStepId "
95  << received_temporal_id_and_data->first
96  << " with mortar id (" << mortar_id.first << ','
97  << mortar_id.second << ")");
98  const std::vector<double>& neighbor_ghost_and_subcell_data =
99  *std::get<1>(received_mortar_data.second);
100  // Compute min and max over neighbors
101  const size_t offset_for_min =
102  neighbor_ghost_and_subcell_data.size() - number_of_evolved_vars;
103  const size_t offset_for_max = offset_for_min - number_of_evolved_vars;
104  for (size_t var_index = 0; var_index < number_of_evolved_vars;
105  ++var_index) {
106  self_neighbor_data.max_variables_values[var_index] = std::max(
107  self_neighbor_data.max_variables_values[var_index],
108  neighbor_ghost_and_subcell_data[offset_for_max + var_index]);
109  self_neighbor_data.min_variables_values[var_index] = std::min(
110  self_neighbor_data.min_variables_values[var_index],
111  neighbor_ghost_and_subcell_data[offset_for_min + var_index]);
112  }
113 
114  ASSERT(subcell_neighbor_data_ptr->find(mortar_id) ==
115  subcell_neighbor_data_ptr->end(),
116  "The subcell neighbor data is already inserted. Direction: "
117  << mortar_id.first
118  << " with ElementId: " << mortar_id.second);
119  // Copy over the neighbor data for reconstruction. We need this
120  // since we might be doing a step unwind and the DG algorithm deletes
121  // the inbox data after lifting the fluxes to the volume.
122  subcell::NeighborData neighbor_data{};
123  // The std::prev avoids copying over the data for the RDMP TCI, which
124  // is both the maximum and minimum of each evolved variable, so
125  // `2*number_of_evolved_vars` components.
126  neighbor_data.data_for_reconstruction.insert(
127  neighbor_data.data_for_reconstruction.end(),
128  neighbor_ghost_and_subcell_data.begin(),
129  std::prev(
130  neighbor_ghost_and_subcell_data.end(),
131  2 * static_cast<std::ptrdiff_t>(number_of_evolved_vars)));
132  (*subcell_neighbor_data_ptr)[mortar_id] = std::move(neighbor_data);
133  }
134  });
136  mortars_to_reconstruct_to{};
137  for (auto& received_mortar_data : received_temporal_id_and_data->second) {
138  const auto& mortar_id = received_mortar_data.first;
139  if (not std::get<2>(received_mortar_data.second).has_value()) {
140  mortars_to_reconstruct_to.push_back(mortar_id);
141  }
142  }
143  FixedHashMap<
144  maximum_number_of_neighbors(volume_dim),
147  boost::hash<std::pair<Direction<volume_dim>, ElementId<volume_dim>>>>
148  neighbor_reconstructed_evolved_vars =
149  Metavariables::SubcellOptions::DgComputeSubcellNeighborPackagedData::
150  apply(*box, mortars_to_reconstruct_to);
151  ASSERT(neighbor_reconstructed_evolved_vars.size() ==
152  mortars_to_reconstruct_to.size(),
153  "Should have reconstructed "
154  << mortars_to_reconstruct_to.size() << " sides but reconstructed "
155  << neighbor_reconstructed_evolved_vars.size() << " sides.");
156  // Now copy over the packaged data _into_ the inbox in order to avoid having
157  // to make other changes to the DG algorithm (code in
158  // src/Evolution/DiscontinuousGalerkin)
159  for (auto& received_mortar_data : received_temporal_id_and_data->second) {
160  const auto& mortar_id = received_mortar_data.first;
161  if (not std::get<2>(received_mortar_data.second).has_value()) {
162  ASSERT(neighbor_reconstructed_evolved_vars.find(mortar_id) !=
163  neighbor_reconstructed_evolved_vars.end(),
164  "Could not find mortar id (" << mortar_id.first << ','
165  << mortar_id.second
166  << ") in reconstructed data map.");
167  std::get<2>(received_mortar_data.second) =
168  std::move(neighbor_reconstructed_evolved_vars.at(mortar_id));
169  }
170  }
171 }
172 } // namespace evolution::dg::subcell
maximum_number_of_neighbors
constexpr size_t maximum_number_of_neighbors(const size_t dim)
Definition: MaxNumberOfNeighbors.hpp:15
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...
utility
std::pair
vector
iterator
tuple
Direction::lower_xi
static Direction< VolumeDim > lower_xi() noexcept
Helper functions for creating specific Directions. These are labeled by the logical-coordinate names ...
Direction
Definition: Direction.hpp:23
ElementId
An ElementId uniquely labels an Element.
Definition: ElementId.hpp:51
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
TimeStepId
Definition: TimeStepId.hpp:25
ASSERT
#define ASSERT(a, m)
Assert that an expression should be true.
Definition: Assert.hpp:49
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
TimeStepId.hpp
evolution::dg::subcell
Implementation of a generic finite volume/conservative finite difference subcell limiter.
Definition: Actions.hpp:6
evolution::dg::subcell::neighbor_reconstructed_face_solution
void neighbor_reconstructed_face_solution(const gsl::not_null< db::DataBox< DbTagsList > * > box, const gsl::not_null< std::pair< const TimeStepId, FixedHashMap< maximum_number_of_neighbors(Metavariables::volume_dim), std::pair< Direction< Metavariables::volume_dim >, ElementId< Metavariables::volume_dim >>, std::tuple< Mesh< Metavariables::volume_dim - 1 >, std::optional< std::vector< double >>, std::optional< std::vector< double >>, ::TimeStepId >, boost::hash< std::pair< Direction< Metavariables::volume_dim >, ElementId< Metavariables::volume_dim >>>>> * > received_temporal_id_and_data) noexcept
Invoked in directions where the neighbor is doing subcell, this function computes the neighbor data o...
Definition: NeighborReconstructedFaceSolution.hpp:65
Gsl.hpp
std::ptrdiff_t
optional
Direction.hpp
FixedHashMap
A hash table with a compile-time specified maximum size and ability to efficiently handle perfect has...
Definition: FixedHashMap.hpp:82
Mesh.hpp
gsl::not_null
Require a pointer to not be a nullptr
Definition: ReadSpecPiecewisePolynomial.hpp:13