ImposeInhomogeneousBoundaryConditionsOnSource.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 
12 #include "DataStructures/Tensor/EagerMath/Magnitude.hpp"
15 #include "Domain/FaceNormal.hpp"
16 #include "Domain/Mesh.hpp"
17 #include "Domain/Tags.hpp"
21 
22 /// \cond
23 namespace Frame {
24 struct Inertial;
25 } // namespace Frame
26 /// \endcond
27 
28 namespace elliptic {
29 namespace dg {
30 namespace Actions {
31 
32 /*!
33  * \brief Adds boundary contributions to the sources
34  *
35  * Imposes boundary conditions by adding contributions to the sources of the
36  * elliptic equations. With the source modified, we may then assume homogeneous
37  * (i.e. zero) Dirichlet boundary conditions throughout the elliptic solve.
38  *
39  * \note Only Dirichlet boundary conditions retrieved from the analytic solution
40  * are currently supported.
41  *
42  * With:
43  * - `fixed_sources_tag` = `db::add_tag_prefix<Tags::FixedSource, fields_tag>`
44  *
45  * Uses:
46  * - Metavariables:
47  * - `analytic_solution_tag`
48  * - `normal_dot_numerical_flux`
49  * - System:
50  * - `volume_dim`
51  * - `fields_tag`
52  * - `primal_fields`
53  * - DataBox:
54  * - `Tags::Mesh<volume_dim>`
55  * - `Tags::Coordinates<volume_dim, Frame::Inertial>`
56  * - `Tags::BoundaryDirectionsInterior<volume_dim>`
57  * - `Tags::Interface<Tags::BoundaryDirectionsExterior<volume_dim>,
58  * Tags::Coordinates<volume_dim, Frame::Inertial>>`
59  * - `Tags::Interface<Tags::BoundaryDirectionsInterior<volume_dim>,
60  * Tags::Normalized<Tags::UnnormalizedFaceNormal<volume_dim>>>`
61  * - `Tags::Interface<Tags::BoundaryDirectionsInterior<volume_dim>,
62  * Tags::Magnitude<Tags::UnnormalizedFaceNormal<volume_dim>>>`
63  *
64  * DataBox:
65  * - Modifies:
66  * - `fixed_sources_tag`
67  */
68 template <typename Metavariables>
70  using system = typename Metavariables::system;
71 
72  using fixed_sources_tag =
74 
75  template <typename NormalDotNumericalFluxComputer,
76  typename... NumericalFluxTags, typename... BoundaryDataTags>
77  static void compute_dirichlet_boundary_normal_dot_numerical_flux(
78  const gsl::not_null<Variables<tmpl::list<NumericalFluxTags...>>*>
79  numerical_fluxes,
80  const NormalDotNumericalFluxComputer& normal_dot_numerical_flux_computer,
81  const Variables<tmpl::list<BoundaryDataTags...>>& boundary_data,
82  const tnsr::i<DataVector, system::volume_dim, Frame::Inertial>&
83  normalized_face_normal) noexcept {
84  normal_dot_numerical_flux_computer.compute_dirichlet_boundary(
85  make_not_null(&get<NumericalFluxTags>(*numerical_fluxes))...,
86  get<BoundaryDataTags>(boundary_data)..., normalized_face_normal);
87  }
88 
89  template <typename DbTagsList, typename... InboxTags, typename ArrayIndex,
90  typename ActionList, typename ParallelComponent>
93  const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
95  const ArrayIndex& /*array_index*/, const ActionList /*meta*/,
96  const ParallelComponent* const /*meta*/) noexcept {
97  static constexpr const size_t volume_dim = system::volume_dim;
98 
99  const auto& analytic_solution =
100  Parallel::get<typename Metavariables::analytic_solution_tag>(cache);
101  const auto& normal_dot_numerical_flux_computer =
102  Parallel::get<typename Metavariables::normal_dot_numerical_flux>(cache);
103 
104  db::mutate<fixed_sources_tag>(
105  make_not_null(&box),
106  [
107  &analytic_solution, &normal_dot_numerical_flux_computer
108  ](const gsl::not_null<db::item_type<fixed_sources_tag>*> fixed_sources,
109  const Mesh<volume_dim>& mesh,
111  volume_dim>>& boundary_directions,
115  boundary_coordinates,
119  normalized_face_normals,
121  ::Tags::BoundaryDirectionsInterior<volume_dim>,
123  magnitude_of_face_normals) noexcept {
124  // Impose Dirichlet boundary conditions as contributions to the source
125  for (const auto& direction : boundary_directions) {
126  const size_t dimension = direction.dimension();
127  const auto mortar_mesh = mesh.slice_away(dimension);
128  // Compute Dirichlet data on mortar
129  Variables<typename system::primal_fields> dirichlet_boundary_data{
130  mortar_mesh.number_of_grid_points(), 0.};
131  dirichlet_boundary_data.assign_subset(
132  analytic_solution.variables(boundary_coordinates.at(direction),
133  typename system::primal_fields{}));
134  // Compute the numerical flux contribution from the Dirichlet data
136  fixed_sources_tag>>
137  boundary_normal_dot_numerical_fluxes{
138  mortar_mesh.number_of_grid_points(), 0.};
139  compute_dirichlet_boundary_normal_dot_numerical_flux(
140  make_not_null(&boundary_normal_dot_numerical_fluxes),
141  normal_dot_numerical_flux_computer,
142  std::move(dirichlet_boundary_data),
143  normalized_face_normals.at(direction));
144  // Flip sign of the boundary contributions, making them
145  // contributions to the source
146  db::item_type<fixed_sources_tag> lifted_boundary_data{
147  -1. *
148  ::dg::lift_flux(std::move(boundary_normal_dot_numerical_fluxes),
149  mesh.extents(dimension),
150  magnitude_of_face_normals.at(direction))};
151  add_slice_to_data(fixed_sources, std::move(lifted_boundary_data),
152  mesh.extents(), dimension,
153  index_to_slice_at(mesh.extents(), direction));
154  }
155  },
156  get<::Tags::Mesh<volume_dim>>(box),
158  get<::Tags::Interface<
159  ::Tags::BoundaryDirectionsExterior<volume_dim>,
161  get<::Tags::Interface<
164  box),
165  get<::Tags::Interface<
166  ::Tags::BoundaryDirectionsInterior<volume_dim>,
168  box));
169 
170  return {std::move(box)};
171  }
172 };
173 } // namespace Actions
174 } // namespace dg
175 } // namespace elliptic
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: DataBoxTag.hpp:616
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
Adds boundary contributions to the sources.
Definition: ImposeInhomogeneousBoundaryConditionsOnSource.hpp:69
The normalized (co)vector represented by Tag.
Definition: Magnitude.hpp:104
The unnormalized face normal one form.
Definition: FaceNormal.hpp:69
Definition: InitializeAnalyticSolution.hpp:27
Definition: ApplyBoundaryFluxesLocalTimeStepping.hpp:33
Holds the number of grid points, basis, and quadrature in each direction of the computational grid...
Definition: Mesh.hpp:49
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.
The set of directions which correspond to external boundaries. Used for representing data on the inte...
Definition: Tags.hpp:208
An associative container that is indexed by structs.
Definition: TaggedTuple.hpp:273
Defines classes and functions used for manipulating DataBox&#39;s.
Defines function lift_flux.
Indicates the Frame that a TensorIndexType is in.
Definition: IndexType.hpp:36
Definition: InterpolationTargetWedgeSectionTorus.hpp:24
Defines class Variables.
A Charm++ chare that caches constant data once per Charm++ node.
Definition: ConstGlobalCache.hpp:135
Defines the class template Mesh.
Declares function unnormalized_face_normal.
The coordinates in a given frame.
Definition: Tags.hpp:139
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:1623
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:461
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
Defines tags related to domain quantities.
The magnitude of a (co)vector.
Definition: Magnitude.hpp:63
Defines helper functions for use with Variables class.
Defines classes SimpleTag, PrefixTag, ComputeTag and several functions for retrieving tag info...
Defines class template ConstGlobalCache.
Defines DataBox tags for the linear solver.
auto lift_flux(Variables< tmpl::list< FluxTags... >> flux, const size_t extent_perpendicular_to_boundary, Scalar< DataVector > magnitude_of_face_normal) noexcept -> Variables< tmpl::list< db::remove_tag_prefix< FluxTags >... >>
Lifts the flux contribution from an interface to the volume.
Definition: LiftFlux.hpp:40
The set of directions which correspond to external boundaries. To be used to represent data which exi...
Definition: Tags.hpp:223
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: VariablesHelpers.hpp:205
Tag which is either a SimpleTag for quantities on an interface, base tag to a compute item which acts...
Definition: Tags.hpp:263
Prefix indicating a boundary unit normal vector dotted into the numerical flux.
Definition: Prefixes.hpp:136
Definition: ComputeTimeDerivative.hpp:28
Require a pointer to not be a nullptr
Definition: ConservativeFromPrimitive.hpp:12