FirstOrderSchemeLts.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 
11 #include "DataStructures/DataVector.hpp"
12 #include "DataStructures/Tensor/EagerMath/Magnitude.hpp"
15 #include "Domain/FaceNormal.hpp"
16 #include "Domain/Mesh.hpp"
17 #include "NumericalAlgorithms/DiscontinuousGalerkin/BoundarySchemes/FirstOrder/BoundaryFlux.hpp"
18 #include "NumericalAlgorithms/DiscontinuousGalerkin/BoundarySchemes/FirstOrder/FirstOrderScheme.hpp"
19 #include "NumericalAlgorithms/DiscontinuousGalerkin/MortarHelpers.hpp"
20 #include "NumericalAlgorithms/DiscontinuousGalerkin/Tags.hpp"
21 #include "Time/Tags.hpp"
22 #include "Utilities/TMPL.hpp"
23 
24 namespace dg {
25 namespace FirstOrderScheme {
26 
27 namespace detail {
28 
29 template <size_t Dim, typename VariablesTag, typename NumericalFluxComputerTag,
30  typename BoundaryData,
31  typename NumericalFlux =
33  typename ArgsTagsList = typename NumericalFlux::argument_tags>
34 struct boundary_data_computer_lts_impl;
35 
36 template <size_t Dim, typename VariablesTag, typename NumericalFluxComputerTag,
37  typename BoundaryData, typename NumericalFlux, typename... ArgsTags>
38 struct boundary_data_computer_lts_impl<Dim, VariablesTag,
39  NumericalFluxComputerTag, BoundaryData,
40  NumericalFlux, tmpl::list<ArgsTags...>> {
41  using n_dot_fluxes_tag =
43  using magnitude_of_face_normal_tag =
45  using argument_tags = tmpl::list<NumericalFluxComputerTag, n_dot_fluxes_tag,
46  magnitude_of_face_normal_tag, ArgsTags...>;
47  using volume_tags = tmpl::append<tmpl::list<NumericalFluxComputerTag>,
48  get_volume_tags<NumericalFlux>>;
49  static auto apply(
50  const NumericalFlux& numerical_flux_computer,
51  const db::const_item_type<n_dot_fluxes_tag>& normal_dot_fluxes,
52  const Scalar<DataVector>& face_normal_magnitude,
53  const db::const_item_type<ArgsTags>&... args) noexcept {
54  BoundaryData boundary_data{normal_dot_fluxes.number_of_grid_points()};
55  boundary_data.field_data.assign_subset(normal_dot_fluxes);
56  dg::NumericalFluxes::package_data(make_not_null(&boundary_data),
57  numerical_flux_computer, args...);
58  get<magnitude_of_face_normal_tag>(boundary_data.extra_data) =
59  face_normal_magnitude;
60  return boundary_data;
61  }
62 };
63 
64 } // namespace detail
65 
66 /*!
67  * \ingroup DiscontinuousGalerkinGroup
68  * \brief Boundary contributions for a first-order DG scheme with local
69  * time-stepping
70  *
71  * This class is the local time-stepping equivalent to the
72  * `dg::FirstOrderScheme::FirstOrderScheme`. Notable differences are:
73  *
74  * - Boundary contributions are added to the `VariablesTag` directly.
75  * - We use the `Tags::BoundaryHistory` on mortars.
76  * - We need to store the face-normal magnitude in the boundary history, as
77  * opposed to the non-LTS case where we can retrieve it when needed.
78  */
79 template <size_t Dim, typename VariablesTag, typename NumericalFluxComputerTag,
80  typename TemporalIdTag, typename TimeStepperTag>
82  private:
83  using base = FirstOrderScheme<Dim, VariablesTag, NumericalFluxComputerTag,
84  TemporalIdTag>;
85 
86  public:
87  static constexpr size_t volume_dim = Dim;
88  using variables_tag = VariablesTag;
89  using numerical_flux_computer_tag = NumericalFluxComputerTag;
91  using temporal_id_tag = TemporalIdTag;
93  using time_stepper_tag = TimeStepperTag;
94 
98  typename base::BoundaryData::field_tags,
99  tmpl::push_back<typename base::BoundaryData::extra_data_tags,
101  using boundary_data_computer = detail::boundary_data_computer_lts_impl<
102  volume_dim, variables_tag, numerical_flux_computer_tag, BoundaryData>;
103 
104  using mortar_data_tag =
107 
108  using return_tags =
109  tmpl::list<variables_tag, ::Tags::Mortars<mortar_data_tag, Dim>>;
110  using argument_tags =
111  tmpl::list<domain::Tags::Mesh<Dim>,
112  ::Tags::Mortars<domain::Tags::Mesh<Dim - 1>, Dim>,
113  ::Tags::Mortars<::Tags::MortarSize<Dim - 1>, Dim>,
114  NumericalFluxComputerTag, time_stepper_tag, ::Tags::TimeStep>;
115 
116  static void apply(
119  all_mortar_data,
120  const Mesh<Dim>& volume_mesh,
121  const db::const_item_type<
122  ::Tags::Mortars<domain::Tags::Mesh<Dim - 1>, Dim>>& mortar_meshes,
123  const db::const_item_type<
124  ::Tags::Mortars<::Tags::MortarSize<Dim - 1>, Dim>>& mortar_sizes,
125  const NumericalFlux& normal_dot_numerical_flux_computer,
126  const db::const_item_type<time_stepper_tag>& time_stepper,
127  const db::const_item_type<Tags::TimeStep>& time_step) noexcept {
128  // Iterate over all mortars
129  for (auto& mortar_id_and_data : *all_mortar_data) {
130  // Retrieve mortar data
131  const auto& mortar_id = mortar_id_and_data.first;
132  auto& mortar_data = mortar_id_and_data.second;
133  const auto& direction = mortar_id.first;
134  const size_t dimension = direction.dimension();
135 
136  const auto& mortar_mesh = mortar_meshes.at(mortar_id);
137  const auto& mortar_size = mortar_sizes.at(mortar_id);
138  const auto face_mesh = volume_mesh.slice_away(dimension);
139  const size_t extent_perpendicular_to_face =
140  volume_mesh.extents(dimension);
141 
142  // This lambda must only capture quantities that are
143  // independent of the simulation state.
144  const auto coupling = [&face_mesh, &mortar_mesh, &mortar_size,
145  &extent_perpendicular_to_face,
146  &normal_dot_numerical_flux_computer](
147  const BoundaryData& local_data,
148  const BoundaryData& remote_data) noexcept {
149  return boundary_flux(
150  local_data, remote_data, normal_dot_numerical_flux_computer,
151  get<magnitude_of_face_normal_tag>(local_data.extra_data),
152  extent_perpendicular_to_face, face_mesh, mortar_mesh, mortar_size);
153  };
154 
155  const auto lifted_data = time_stepper.compute_boundary_delta(
156  coupling, make_not_null(&mortar_data), time_step);
157 
158  // Add the flux contribution to the volume data
159  add_slice_to_data(variables, lifted_data, volume_mesh.extents(),
160  dimension,
161  index_to_slice_at(volume_mesh.extents(), direction));
162  }
163  }
164 };
165 
166 } // namespace FirstOrderScheme
167 } // namespace dg
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:18
utility
Tags::MortarSize
Definition: Tags.hpp:52
FaceNormal.hpp
Tags::TimeStep
Tag for step size.
Definition: Tags.hpp:43
domain::Tags::Mesh
The computational grid of the Element in the DataBox.
Definition: Tags.hpp:106
Tags::Next
Prefix indicating the value a quantity will take on the next iteration of the algorithm.
Definition: Prefixes.hpp:142
db::add_tag_prefix
Prefix< DataBox_detail::dispatch_add_tag_prefix_impl< Prefix, Tag, Args... >, Args... > add_tag_prefix
Definition: PrefixHelpers.hpp:145
dg
Functionality related to discontinuous Galerkin schemes.
Definition: ComputeNonconservativeBoundaryFluxes.hpp:23
domain::push_back
CoordinateMap< SourceFrame, TargetFrame, Maps..., NewMap > push_back(CoordinateMap< SourceFrame, TargetFrame, Maps... > old_map, NewMap new_map) noexcept
Creates a CoordinateMap by appending the new map to the end of the old maps.
dg::FirstOrderScheme::FirstOrderSchemeLts
Boundary contributions for a first-order DG scheme with local time-stepping.
Definition: FirstOrderSchemeLts.hpp:81
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:1443
dg::SimpleBoundaryData
Distinguishes between field data, which can be projected to a mortar, and extra data,...
Definition: SimpleBoundaryData.hpp:35
cstddef
db::item_type
typename DataBox_detail::item_type_impl< TagList, Tag >::type item_type
Get the type that can be written to the Tag. If it is a base tag then a TagList must be passed as a s...
Definition: DataBoxTag.hpp:246
std::decay_t
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:50
Scalar
Tensor< T, Symmetry<>, index_list<> > Scalar
Definition: TypeAliases.hpp:21
Tags::Magnitude
Definition: Magnitude.hpp:101
dg::FirstOrderScheme::FirstOrderScheme
Boundary contributions for a first-order DG scheme.
Definition: FirstOrderScheme.hpp:67
Tensor.hpp
make_not_null
gsl::not_null< T * > make_not_null(T *ptr) noexcept
Construct a not_null from a pointer. Often this will be done as an implicit conversion,...
Definition: Gsl.hpp:880
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:113
dg::mortar_mesh
Mesh< Dim > mortar_mesh(const Mesh< Dim > &face_mesh1, const Mesh< Dim > &face_mesh2) noexcept
Definition: MortarHelpers.cpp:19
Prefixes.hpp
Tags::BoundaryHistory
Definition: Tags.hpp:104
dg::mortar_size
std::array< Spectral::MortarSize, Dim - 1 > mortar_size(const ElementId< Dim > &self, const ElementId< Dim > &neighbor, const size_t dimension, const OrientationMap< Dim > &orientation) noexcept
Definition: MortarHelpers.cpp:36
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