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 
9 #include "DataStructures/DataBox/PrefixHelpers.hpp"
10 #include "DataStructures/DataVector.hpp"
11 #include "DataStructures/Tensor/EagerMath/Magnitude.hpp"
14 #include "Domain/FaceNormal.hpp"
15 #include "Domain/InterfaceHelpers.hpp"
17 #include "NumericalAlgorithms/DiscontinuousGalerkin/BoundarySchemes/FirstOrder/BoundaryData.hpp"
18 #include "NumericalAlgorithms/DiscontinuousGalerkin/BoundarySchemes/FirstOrder/BoundaryFlux.hpp"
19 #include "NumericalAlgorithms/DiscontinuousGalerkin/MortarHelpers.hpp"
20 #include "NumericalAlgorithms/DiscontinuousGalerkin/Protocols.hpp"
21 #include "NumericalAlgorithms/DiscontinuousGalerkin/SimpleMortarData.hpp"
22 #include "NumericalAlgorithms/DiscontinuousGalerkin/Tags.hpp"
24 #include "Utilities/ProtocolHelpers.hpp"
25 #include "Utilities/TMPL.hpp"
26 
27 namespace dg {
28 namespace FirstOrderScheme {
29 
30 namespace detail {
31 
32 template <size_t Dim, typename VariablesTag, typename NumericalFluxComputerTag>
33 struct boundary_data_computer_impl {
34  using NumericalFlux = typename NumericalFluxComputerTag::type;
35  using n_dot_fluxes_tag =
37  using argument_tags =
38  tmpl::push_front<typename NumericalFlux::argument_tags,
39  NumericalFluxComputerTag, domain::Tags::Mesh<Dim - 1>,
40  n_dot_fluxes_tag>;
41  using volume_tags = tmpl::push_front<get_volume_tags<NumericalFlux>,
42  NumericalFluxComputerTag>;
43  template <typename... Args>
44  static auto apply(const NumericalFlux& numerical_flux_computer,
45  const Mesh<Dim - 1>& face_mesh,
46  const typename n_dot_fluxes_tag::type& normal_dot_fluxes,
47  const Args&... args) noexcept {
49  numerical_flux_computer, face_mesh, normal_dot_fluxes, args...);
50  }
51 };
52 
53 } // namespace detail
54 
55 /*!
56  * \ingroup DiscontinuousGalerkinGroup
57  * \brief Boundary contributions for a first-order DG scheme
58  *
59  * Computes Eq. (2.20) in \cite Teukolsky2015ega and lifts it to the
60  * volume (see `dg::lift_flux`) on all mortars that touch an element. The
61  * resulting boundary contributions are added to the DG operator data in the
62  * `DtVariablesTag`.
63  */
64 template <size_t Dim, typename VariablesTag, typename DtVariablesTag,
65  typename NumericalFluxComputerTag, typename TemporalIdTag>
67  static constexpr size_t volume_dim = Dim;
68  using variables_tag = VariablesTag;
69  using numerical_flux_computer_tag = NumericalFluxComputerTag;
70  using NumericalFlux = typename NumericalFluxComputerTag::type;
71  using temporal_id_tag = TemporalIdTag;
72  using receive_temporal_id_tag = temporal_id_tag;
73  using dt_variables_tag = DtVariablesTag;
74 
75  static_assert(
76  tt::assert_conforms_to<NumericalFlux, dg::protocols::NumericalFlux>);
77  // We need the `VariablesTag` as an explicit template parameter only because
78  // it may be prefixed.
79  static_assert(std::is_same_v<typename NumericalFlux::variables_tags,
80  typename variables_tag::tags_list>,
81  "The 'VariablesTag' and the 'NumericalFluxComputerTag' must "
82  "have the same list of variables.");
83 
85  using boundary_data_computer =
86  detail::boundary_data_computer_impl<Dim, VariablesTag,
87  NumericalFluxComputerTag>;
88 
89  using mortar_data_tag = ::Tags::SimpleMortarData<typename TemporalIdTag::type,
90  BoundaryData, BoundaryData>;
91 
92  // Only a shortcut
95 
96  using return_tags =
97  tmpl::list<dt_variables_tag, ::Tags::Mortars<mortar_data_tag, Dim>>;
98  using argument_tags = tmpl::list<
100  ::Tags::Mortars<domain::Tags::Mesh<Dim - 1>, Dim>,
101  ::Tags::Mortars<::Tags::MortarSize<Dim - 1>, Dim>,
102  NumericalFluxComputerTag,
107 
108  static void apply(
110  const gsl::not_null<typename ::Tags::Mortars<mortar_data_tag, Dim>::type*>
111  all_mortar_data,
112  const Mesh<Dim>& volume_mesh,
113  const MortarMap<Dim, Mesh<Dim - 1>>& mortar_meshes,
114  const MortarMap<Dim, MortarSize<Dim - 1>>& mortar_sizes,
115  const NumericalFlux& normal_dot_numerical_flux_computer,
117  face_normal_magnitudes_internal,
119  face_normal_magnitudes_boundary) noexcept {
120  // Iterate over all mortars
121  for (auto& mortar_id_and_data : *all_mortar_data) {
122  // Retrieve mortar data
123  const auto& mortar_id = mortar_id_and_data.first;
124  auto& mortar_data = mortar_id_and_data.second;
125  const auto& direction = mortar_id.first;
126  const size_t dimension = direction.dimension();
127 
128  // Extract local and remote data
129  const auto extracted_mortar_data = mortar_data.extract();
130  const auto& local_data = extracted_mortar_data.first;
131  const auto& remote_data = extracted_mortar_data.second;
132 
133  const auto& magnitude_of_face_normal =
134  mortar_id.second == ElementId<Dim>::external_boundary_id()
135  ? face_normal_magnitudes_boundary.at(direction)
136  : face_normal_magnitudes_internal.at(direction);
137 
138  auto boundary_flux_on_slice =
139  typename dt_variables_tag::type(boundary_flux(
140  local_data, remote_data, normal_dot_numerical_flux_computer,
141  magnitude_of_face_normal, volume_mesh.extents(dimension),
142  volume_mesh.slice_away(dimension), mortar_meshes.at(mortar_id),
143  mortar_sizes.at(mortar_id)));
144 
145  // Add the flux contribution to the volume data
146  add_slice_to_data(dt_variables, std::move(boundary_flux_on_slice),
147  volume_mesh.extents(), dimension,
148  index_to_slice_at(volume_mesh.extents(), direction));
149  }
150  }
151 };
152 
153 } // namespace FirstOrderScheme
154 } // 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.
std::apply
T apply(T... args)
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:18
utility
index_to_slice_at
size_t index_to_slice_at(const Index< Dim > &extents, const Direction< Dim > &direction, const size_t offset=0) noexcept
Finds the index in the perpendicular dimension of an element boundary.
Definition: IndexToSliceAt.hpp:18
Tags::MortarSize
Definition: Tags.hpp:48
FaceNormal.hpp
db::add_tag_prefix
typename detail::add_tag_prefix_impl< Prefix, Tag, Args... >::type add_tag_prefix
Definition: PrefixHelpers.hpp:51
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
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
add_slice_to_data
void add_slice_to_data(const gsl::not_null< Variables< tmpl::list< VolumeTags... >> * > volume_vars, const Variables< tmpl::list< SliceTags... >> &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
std::array
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:98
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:365
dg::FirstOrderScheme::FirstOrderScheme
Boundary contributions for a first-order DG scheme.
Definition: FirstOrderScheme.hpp:66
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:29
std::unordered_map
TMPL.hpp
gsl::not_null
Require a pointer to not be a nullptr
Definition: Gsl.hpp:183
Tags::Mortars
Definition: Tags.hpp:37