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 "NumericalAlgorithms/DiscontinuousGalerkin/BoundarySchemes/FirstOrder/BoundaryFlux.hpp"
17 #include "NumericalAlgorithms/DiscontinuousGalerkin/BoundarySchemes/FirstOrder/FirstOrderScheme.hpp"
18 #include "NumericalAlgorithms/DiscontinuousGalerkin/MortarHelpers.hpp"
19 #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 = typename NumericalFluxComputerTag::type,
32  typename ArgsTagsList = typename NumericalFlux::argument_tags>
33 struct boundary_data_computer_lts_impl;
34 
35 template <size_t Dim, typename VariablesTag, typename NumericalFluxComputerTag,
36  typename BoundaryData, typename NumericalFlux, typename... ArgsTags>
37 struct boundary_data_computer_lts_impl<Dim, VariablesTag,
38  NumericalFluxComputerTag, BoundaryData,
39  NumericalFlux, tmpl::list<ArgsTags...>> {
40  using n_dot_fluxes_tag =
42  using magnitude_of_face_normal_tag =
44  using argument_tags = tmpl::list<NumericalFluxComputerTag, n_dot_fluxes_tag,
45  magnitude_of_face_normal_tag, ArgsTags...>;
46  using volume_tags = tmpl::append<tmpl::list<NumericalFluxComputerTag>,
47  get_volume_tags<NumericalFlux>>;
48  static auto apply(const NumericalFlux& numerical_flux_computer,
49  const typename n_dot_fluxes_tag::type& normal_dot_fluxes,
50  const Scalar<DataVector>& face_normal_magnitude,
51  const typename ArgsTags::type&... args) noexcept {
52  BoundaryData boundary_data{normal_dot_fluxes.number_of_grid_points()};
53  boundary_data.field_data.assign_subset(normal_dot_fluxes);
54  dg::NumericalFluxes::package_data(make_not_null(&boundary_data),
55  numerical_flux_computer, args...);
56  get<magnitude_of_face_normal_tag>(boundary_data.extra_data) =
57  face_normal_magnitude;
58  return boundary_data;
59  }
60 };
61 
62 } // namespace detail
63 
64 /*!
65  * \ingroup DiscontinuousGalerkinGroup
66  * \brief Boundary contributions for a first-order DG scheme with local
67  * time-stepping
68  *
69  * This class is the local time-stepping equivalent to the
70  * `dg::FirstOrderScheme::FirstOrderScheme`. Notable differences are:
71  *
72  * - Boundary contributions are added to the `VariablesTag` directly.
73  * - We use the `Tags::BoundaryHistory` on mortars.
74  * - We need to store the face-normal magnitude in the boundary history, as
75  * opposed to the non-LTS case where we can retrieve it when needed.
76  */
77 template <size_t Dim, typename VariablesTag, typename NumericalFluxComputerTag,
78  typename TemporalIdTag, typename TimeStepperTag>
80  private:
81  using base = FirstOrderScheme<Dim, VariablesTag, NumericalFluxComputerTag,
82  TemporalIdTag>;
83 
84  public:
85  static constexpr size_t volume_dim = Dim;
86  using variables_tag = VariablesTag;
87  using numerical_flux_computer_tag = NumericalFluxComputerTag;
88  using NumericalFlux = typename NumericalFluxComputerTag::type;
89  using temporal_id_tag = TemporalIdTag;
91  using time_stepper_tag = TimeStepperTag;
92 
96  typename base::BoundaryData::field_tags,
97  tmpl::push_back<typename base::BoundaryData::extra_data_tags,
99  using boundary_data_computer = detail::boundary_data_computer_lts_impl<
100  volume_dim, variables_tag, numerical_flux_computer_tag, BoundaryData>;
101 
103  typename variables_tag::type>;
104 
105  using return_tags =
106  tmpl::list<variables_tag, ::Tags::Mortars<mortar_data_tag, Dim>>;
107  using argument_tags =
108  tmpl::list<domain::Tags::Mesh<Dim>,
109  ::Tags::Mortars<domain::Tags::Mesh<Dim - 1>, Dim>,
110  ::Tags::Mortars<::Tags::MortarSize<Dim - 1>, Dim>,
111  NumericalFluxComputerTag, time_stepper_tag, ::Tags::TimeStep>;
112 
113  static void apply(
115  const gsl::not_null<typename ::Tags::Mortars<mortar_data_tag, Dim>::type*>
116  all_mortar_data,
117  const Mesh<Dim>& volume_mesh,
118  const typename ::Tags::Mortars<domain::Tags::Mesh<Dim - 1>, Dim>::type&
119  mortar_meshes,
120  const typename ::Tags::Mortars<::Tags::MortarSize<Dim - 1>, Dim>::type&
121  mortar_sizes,
122  const NumericalFlux& normal_dot_numerical_flux_computer,
123  const typename time_stepper_tag::type::element_type& time_stepper,
124  const TimeDelta& time_step) noexcept {
125  // Iterate over all mortars
126  for (auto& mortar_id_and_data : *all_mortar_data) {
127  // Retrieve mortar data
128  const auto& mortar_id = mortar_id_and_data.first;
129  auto& mortar_data = mortar_id_and_data.second;
130  const auto& direction = mortar_id.first;
131  const size_t dimension = direction.dimension();
132 
133  const auto& mortar_mesh = mortar_meshes.at(mortar_id);
134  const auto& mortar_size = mortar_sizes.at(mortar_id);
135  const auto face_mesh = volume_mesh.slice_away(dimension);
136  const size_t extent_perpendicular_to_face =
137  volume_mesh.extents(dimension);
138 
139  // This lambda must only capture quantities that are
140  // independent of the simulation state.
141  const auto coupling = [&face_mesh, &mortar_mesh, &mortar_size,
142  &extent_perpendicular_to_face,
143  &normal_dot_numerical_flux_computer](
144  const BoundaryData& local_data,
145  const BoundaryData& remote_data) noexcept {
146  return boundary_flux(
147  local_data, remote_data, normal_dot_numerical_flux_computer,
148  get<magnitude_of_face_normal_tag>(local_data.extra_data),
149  extent_perpendicular_to_face, face_mesh, mortar_mesh, mortar_size);
150  };
151 
152  const auto lifted_data = time_stepper.compute_boundary_delta(
153  coupling, make_not_null(&mortar_data), time_step);
154 
155  // Add the flux contribution to the volume data
156  add_slice_to_data(variables, lifted_data, volume_mesh.extents(),
157  dimension,
158  index_to_slice_at(volume_mesh.extents(), direction));
159  }
160  }
161 };
162 
163 } // namespace FirstOrderScheme
164 } // 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:17
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:49
FaceNormal.hpp
Tags::TimeStep
Tag for step size.
Definition: Tags.hpp:43
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
Tags::Next
Prefix indicating the value a quantity will take on the next iteration of the algorithm.
Definition: Prefixes.hpp:118
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:79
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::SimpleBoundaryData
Distinguishes between field data, which can be projected to a mortar, and extra data,...
Definition: SimpleBoundaryData.hpp:35
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
TimeDelta
Definition: Time.hpp:88
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
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:110
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:111
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
TMPL.hpp
gsl::not_null
Require a pointer to not be a nullptr
Definition: Gsl.hpp:183
Tags::Mortars
Definition: Tags.hpp:38