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 
95  using magnitude_of_face_normal_tag =
97  using BoundaryData = dg::SimpleBoundaryData<
98  typename base::BoundaryData::field_tags,
99  tmpl::push_back<typename base::BoundaryData::extra_data_tags,
100  magnitude_of_face_normal_tag>>;
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
Prefix< DataBox_detail::dispatch_add_tag_prefix_impl< Prefix, Tag, Args... >, Args... > add_tag_prefix
Wrap Tag in Prefix<_, Args...>, also wrapping variables tags if Tag is a Tags::Variables.
Definition: PrefixHelpers.hpp:145
size_t index_to_slice_at(const Index< Dim > &extents, const Direction< Dim > &direction) noexcept
Finds the index in the perpendicular dimension of an element boundary.
Definition: IndexToSliceAt.hpp:15
The computational grid of the Element in the DataBox.
Definition: Tags.hpp:105
Tag for step size.
Definition: Tags.hpp:43
typename detail::BoundaryDataImpl< NumericalFluxType >::type BoundaryData
The data on element boundaries that&#39;s needed for the (strong) first-order boundary scheme...
Definition: BoundaryData.hpp:47
Definition: Digraph.hpp:11
Functionality related to discontinuous Galerkin schemes.
Definition: ApplyBoundaryFluxesLocalTimeStepping.hpp:33
Holds the number of grid points, basis, and quadrature in each direction of the computational grid...
Definition: Mesh.hpp:50
Mesh< Dim > mortar_mesh(const Mesh< Dim > &face_mesh1, const Mesh< Dim > &face_mesh2) noexcept
Find a mesh for a mortar capable of representing data from either of two faces.
Definition: MortarHelpers.cpp:19
Define prefixes for DataBox tags.
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< Dim - 1 > slice_away(size_t d) const noexcept
Returns a Mesh with dimension d removed (zero-indexed).
Definition: Mesh.cpp:18
Distinguishes between field data, which can be projected to a mortar, and extra data, which will not be projected.
Definition: SimpleBoundaryData.hpp:35
Definition: Determinant.hpp:11
Data on mortars, indexed by (Direction, ElementId) pairs.
Definition: Tags.hpp:38
Boundary contributions for a first-order DG scheme.
Definition: FirstOrderScheme.hpp:72
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
Determine the size of the mortar (i.e., the part of the face it covers) for communicating with a neig...
Definition: MortarHelpers.cpp:36
Defines class Variables.
Size of a mortar, relative to the element face. That is, the part of the face that it covers...
Definition: Tags.hpp:52
Defines the class template Mesh.
Defines classes for Tensor.
Declares function unnormalized_face_normal.
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:1444
std::conditional_t< tmpl2::flat_all_v< detail::has_variables_tags_v< ConformingType >, detail::has_argument_tags_v< ConformingType >, detail::has_package_field_tags_v< ConformingType >, detail::has_package_extra_tags_v< ConformingType > >, cpp17::conjunction< detail::IsPackageDataCallable< ConformingType >, detail::IsNumericalFluxCallable< ConformingType > >, std::false_type > NumericalFlux
Defines the interface for DG numerical fluxes.
Definition: Protocols.hpp:140
const Index< Dim > & extents() const noexcept
The number of grid points in each dimension of the grid.
Definition: Mesh.hpp:113
Wraps the template metaprogramming library used (brigand)
Boundary contributions for a first-order DG scheme with local time-stepping.
Definition: FirstOrderSchemeLts.hpp:81
Prefix indicating the value a quantity will take on the next iteration of the algorithm.
Definition: Prefixes.hpp:152
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
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, but it may be necessary to perform the conversion explicitly when type deduction is desired.
Definition: Gsl.hpp:879
The magnitude of a (co)vector.
Definition: Magnitude.hpp:80
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.
Tag for TimeStepper boundary history.
Definition: Tags.hpp:102
Defines classes SimpleTag, PrefixTag, ComputeTag and several functions for retrieving tag info...
Tensor< T, Symmetry<>, index_list<> > Scalar
Scalar type.
Definition: TypeAliases.hpp:21
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
Require a pointer to not be a nullptr
Definition: Gsl.hpp:182