FirstOrderScheme.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <utility>
8 
10 #include "DataStructures/DataBox/PrefixHelpers.hpp"
11 #include "DataStructures/DataVector.hpp"
12 #include "DataStructures/Tensor/EagerMath/Magnitude.hpp"
15 #include "Domain/FaceNormal.hpp"
16 #include "Domain/InterfaceHelpers.hpp"
18 #include "NumericalAlgorithms/DiscontinuousGalerkin/BoundarySchemes/FirstOrder/BoundaryData.hpp"
19 #include "NumericalAlgorithms/DiscontinuousGalerkin/BoundarySchemes/FirstOrder/BoundaryFlux.hpp"
20 #include "NumericalAlgorithms/DiscontinuousGalerkin/MortarHelpers.hpp"
21 #include "NumericalAlgorithms/DiscontinuousGalerkin/Protocols.hpp"
22 #include "NumericalAlgorithms/DiscontinuousGalerkin/SimpleMortarData.hpp"
23 #include "NumericalAlgorithms/DiscontinuousGalerkin/Tags.hpp"
25 #include "Utilities/ProtocolHelpers.hpp"
26 #include "Utilities/TMPL.hpp"
27 
28 namespace dg {
29 namespace FirstOrderScheme {
30 
31 namespace detail {
32 
33 template <size_t Dim, typename VariablesTag, typename NumericalFluxComputerTag>
34 struct boundary_data_computer_impl {
35  using NumericalFlux = typename NumericalFluxComputerTag::type;
36  using n_dot_fluxes_tag =
38  using argument_tags =
39  tmpl::push_front<typename NumericalFlux::argument_tags,
40  NumericalFluxComputerTag, domain::Tags::Mesh<Dim - 1>,
41  n_dot_fluxes_tag>;
42  using volume_tags = tmpl::push_front<get_volume_tags<NumericalFlux>,
43  NumericalFluxComputerTag>;
44  template <typename... Args>
45  static auto apply(const NumericalFlux& numerical_flux_computer,
46  const Mesh<Dim - 1>& face_mesh,
47  const typename n_dot_fluxes_tag::type& normal_dot_fluxes,
48  const Args&... args) noexcept {
50  numerical_flux_computer, face_mesh, normal_dot_fluxes, args...);
51  }
52 };
53 
54 } // namespace detail
55 
56 /*!
57  * \ingroup DiscontinuousGalerkinGroup
58  * \brief Boundary contributions for a first-order DG scheme
59  *
60  * Computes Eq. (2.20) in \cite Teukolsky2015ega and lifts it to the
61  * volume (see `dg::lift_flux`) on all mortars that touch an element. The
62  * resulting boundary contributions are added to the DG operator data in
63  * `db::add_tag_prefix<TemporalIdTag::template step_prefix, VariablesTag>`.
64  */
65 template <size_t Dim, typename VariablesTag, typename NumericalFluxComputerTag,
66  typename TemporalIdTag>
68  static constexpr size_t volume_dim = Dim;
69  using variables_tag = VariablesTag;
70  using numerical_flux_computer_tag = NumericalFluxComputerTag;
71  using NumericalFlux = typename NumericalFluxComputerTag::type;
72  using temporal_id_tag = TemporalIdTag;
73  using receive_temporal_id_tag = temporal_id_tag;
74  using dt_variables_tag =
76 
77  static_assert(
78  tt::assert_conforms_to<NumericalFlux, dg::protocols::NumericalFlux>);
79  // We need the `VariablesTag` as an explicit template parameter only because
80  // it may be prefixed.
81  static_assert(std::is_same_v<typename NumericalFlux::variables_tags,
82  typename variables_tag::tags_list>,
83  "The 'VariablesTag' and the 'NumericalFluxComputerTag' must "
84  "have the same list of variables.");
85 
87  using boundary_data_computer =
88  detail::boundary_data_computer_impl<Dim, VariablesTag,
89  NumericalFluxComputerTag>;
90 
91  using mortar_data_tag = Tags::SimpleMortarData<typename TemporalIdTag::type,
92  BoundaryData, BoundaryData>;
93 
94  // Only a shortcut
97 
98  using return_tags =
99  tmpl::list<dt_variables_tag, ::Tags::Mortars<mortar_data_tag, Dim>>;
100  using argument_tags = tmpl::list<
102  ::Tags::Mortars<domain::Tags::Mesh<Dim - 1>, Dim>,
103  ::Tags::Mortars<::Tags::MortarSize<Dim - 1>, Dim>,
104  NumericalFluxComputerTag,
109 
110  static void apply(
112  const gsl::not_null<typename ::Tags::Mortars<mortar_data_tag, Dim>::type*>
113  all_mortar_data,
114  const Mesh<Dim>& volume_mesh,
115  const MortarMap<Dim, Mesh<Dim - 1>>& mortar_meshes,
116  const MortarMap<Dim, MortarSize<Dim - 1>>& mortar_sizes,
117  const NumericalFlux& normal_dot_numerical_flux_computer,
119  face_normal_magnitudes_internal,
121  face_normal_magnitudes_boundary) noexcept {
122  // Iterate over all mortars
123  for (auto& mortar_id_and_data : *all_mortar_data) {
124  // Retrieve mortar data
125  const auto& mortar_id = mortar_id_and_data.first;
126  auto& mortar_data = mortar_id_and_data.second;
127  const auto& direction = mortar_id.first;
128  const size_t dimension = direction.dimension();
129 
130  // Extract local and remote data
131  const auto extracted_mortar_data = mortar_data.extract();
132  const auto& local_data = extracted_mortar_data.first;
133  const auto& remote_data = extracted_mortar_data.second;
134 
135  const auto& magnitude_of_face_normal =
136  mortar_id.second == ElementId<Dim>::external_boundary_id()
137  ? face_normal_magnitudes_boundary.at(direction)
138  : face_normal_magnitudes_internal.at(direction);
139 
140  auto boundary_flux_on_slice =
141  typename dt_variables_tag::type(boundary_flux(
142  local_data, remote_data, normal_dot_numerical_flux_computer,
143  magnitude_of_face_normal, volume_mesh.extents(dimension),
144  volume_mesh.slice_away(dimension), mortar_meshes.at(mortar_id),
145  mortar_sizes.at(mortar_id)));
146 
147  // Add the flux contribution to the volume data
148  add_slice_to_data(dt_variables, std::move(boundary_flux_on_slice),
149  volume_mesh.extents(), dimension,
150  index_to_slice_at(volume_mesh.extents(), direction));
151  }
152  }
153 };
154 
155 } // namespace FirstOrderScheme
156 } // namespace dg
domain::push_front
CoordinateMap< SourceFrame, TargetFrame, NewMap, Maps... > push_front(CoordinateMap< SourceFrame, TargetFrame, Maps... > old_map, NewMap new_map) noexcept
Creates a CoordinateMap by prepending the new map to the beginning of the old maps.
DataBoxTag.hpp
Mesh::slice_away
Mesh< Dim - 1 > slice_away(size_t d) const noexcept
Returns a Mesh with dimension d removed (zero-indexed).
Definition: Mesh.cpp:17
utility
Tags::MortarSize
Definition: Tags.hpp:49
FaceNormal.hpp
db::add_tag_prefix
typename detail::add_tag_prefix_impl< Prefix, Tag, Args... >::type add_tag_prefix
Definition: PrefixHelpers.hpp:52
domain::Tags::Mesh
The computational grid of the Element in the DataBox.
Definition: Tags.hpp:107
Direction
Definition: Direction.hpp:23
dg
Functionality related to discontinuous Galerkin schemes.
Definition: ComputeNonconservativeBoundaryFluxes.hpp:23
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...
Definition: ElementId.cpp:71
db::apply
constexpr auto apply(F &&f, const DataBox< BoxTags > &box, Args &&... args) noexcept
Apply the invokable f with argument Tags TagsList from DataBox box
Definition: DataBox.hpp:1424
dg::FirstOrderScheme::package_boundary_data
auto package_boundary_data(const NumericalFluxType &numerical_flux_computer, const Mesh< FaceDim > &face_mesh, const Variables< db::wrap_tags_in< ::Tags::NormalDotFlux, typename NumericalFluxType::variables_tags >> &normal_dot_fluxes, const NumericalFluxArgs &... args) noexcept
Package the data on element boundaries that's needed for the (strong) first-order boundary scheme.
Definition: BoundaryData.hpp:62
cstddef
std::array
index_to_slice_at
size_t index_to_slice_at(const Index< Dim > &extents, const Direction< Dim > &direction) noexcept
Definition: IndexToSliceAt.hpp:15
Variables.hpp
dg::FirstOrderScheme::BoundaryData
typename detail::BoundaryDataImpl< NumericalFluxType >::type BoundaryData
The data on element boundaries that's needed for the (strong) first-order boundary scheme.
Definition: BoundaryData.hpp:46
Mesh
Holds the number of grid points, basis, and quadrature in each direction of the computational grid.
Definition: Mesh.hpp:47
Scalar
Tensor< T, Symmetry<>, index_list<> > Scalar
Definition: TypeAliases.hpp:21
Tags::Magnitude
Definition: Magnitude.hpp:99
domain::Tags::Interface
Tag which is either a SimpleTag for quantities on an interface, base tag to a compute item which acts...
Definition: Tags.hpp:331
dg::FirstOrderScheme::FirstOrderScheme
Boundary contributions for a first-order DG scheme.
Definition: FirstOrderScheme.hpp:67
Tensor.hpp
Direction.hpp
Mesh.hpp
dg::FirstOrderScheme::boundary_flux
Variables< typename NumericalFluxType::variables_tags > boundary_flux(const dg::SimpleBoundaryData< AllFieldsTags, AllExtraDataTags > &local_boundary_data, const dg::SimpleBoundaryData< AllFieldsTags, AllExtraDataTags > &remote_boundary_data, const NumericalFluxType &numerical_flux_computer, const Scalar< DataVector > &magnitude_of_face_normal, const size_t extent_perpendicular_to_boundary, const Mesh< FaceDim > &face_mesh, const Mesh< FaceDim > &mortar_mesh, const MortarSize< FaceDim > &mortar_size) noexcept
Compute the boundary flux contribution and lift it to the volume.
Definition: BoundaryFlux.hpp:48
Mesh::extents
const Index< Dim > & extents() const noexcept
The number of grid points in each dimension of the grid.
Definition: Mesh.hpp:110
Tags::SimpleMortarData
Simple boundary communication data.
Definition: Tags.hpp:30
std::unordered_map
add_slice_to_data
void add_slice_to_data(const gsl::not_null< Variables< TagsList > * > volume_vars, const Variables< TagsList > &vars_on_slice, const Index< VolumeDim > &extents, const size_t sliced_dim, const size_t fixed_index) noexcept
Adds data on a codimension 1 slice to a volume quantity. The slice has a constant logical coordinate ...
Definition: SliceVariables.hpp:82
TMPL.hpp
gsl::not_null
Require a pointer to not be a nullptr
Definition: Gsl.hpp:183
Tags::Mortars
Definition: Tags.hpp:38