BoundaryConditions.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"
22 
23 /// \cond
24 namespace Frame {
25 struct Inertial;
26 } // namespace Frame
27 /// \endcond
28 
29 namespace Elliptic {
30 namespace Initialization {
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  * - `sources_tag` = `db::add_tag_prefix<Tags::Source, system::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  * - `impose_boundary_conditions_on_fields`
53  * - DataBox:
54  * - `Tags::Mesh<volume_dim>`
55  * - `Tags::Coordinates<volume_dim, Frame::Inertial>`
56  * - `Tags::BoundaryDirectionsInterior<volume_dim>`
57  * - `Tags::Interface<Tags::BoundaryDirectionsInterior<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  * - `sources_tag`
67  */
68 template <typename Metavariables>
70  using system = typename Metavariables::system;
71 
72  using sources_tag =
74 
75  using simple_tags = db::AddSimpleTags<>;
76  using compute_tags = db::AddComputeTags<>;
77 
78  template <typename NormalDotNumericalFluxComputer,
79  typename... NumericalFluxTags, typename... BoundaryDataTags>
80  static void compute_dirichlet_boundary_normal_dot_numerical_flux(
81  const gsl::not_null<Variables<tmpl::list<NumericalFluxTags...>>*>
82  numerical_fluxes,
83  const NormalDotNumericalFluxComputer& normal_dot_numerical_flux_computer,
84  const Variables<tmpl::list<BoundaryDataTags...>>& boundary_data,
85  const tnsr::i<DataVector, system::volume_dim, Frame::Inertial>&
86  normalized_face_normal) noexcept {
87  normal_dot_numerical_flux_computer.compute_dirichlet_boundary(
88  make_not_null(&get<NumericalFluxTags>(*numerical_fluxes))...,
89  get<BoundaryDataTags>(boundary_data)..., normalized_face_normal);
90  }
91 
92  template <typename TagsList>
93  static auto initialize(
95  const Parallel::ConstGlobalCache<Metavariables>& cache) noexcept {
96  static constexpr const size_t volume_dim = system::volume_dim;
97 
98  const auto& analytic_solution =
99  Parallel::get<typename Metavariables::analytic_solution_tag>(cache);
100  const auto& normal_dot_numerical_flux_computer =
101  Parallel::get<typename Metavariables::normal_dot_numerical_flux>(cache);
102 
103  db::mutate<sources_tag>(
104  make_not_null(&box),
105  [
106  &analytic_solution, &normal_dot_numerical_flux_computer
108  const Mesh<volume_dim>& mesh,
110  boundary_directions,
111  const db::item_type<
114  boundary_coordinates,
118  normalized_face_normals,
120  Tags::BoundaryDirectionsInterior<volume_dim>,
122  magnitude_of_face_normals) noexcept {
123  // Impose Dirichlet boundary conditions as contributions to the source
124  for (const auto& direction : boundary_directions) {
125  const size_t dimension = direction.dimension();
126  const auto mortar_mesh = mesh.slice_away(dimension);
127  // Compute Dirichlet data on mortar
128  Variables<typename system::impose_boundary_conditions_on_fields>
129  dirichlet_boundary_data{mortar_mesh.number_of_grid_points(),
130  0.};
131  dirichlet_boundary_data.assign_subset(analytic_solution.variables(
132  boundary_coordinates.at(direction),
133  typename system::impose_boundary_conditions_on_fields{}));
134  // Compute the numerical flux contribution from the Dirichlet data
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<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(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),
157  get<Tags::BoundaryDirectionsInterior<volume_dim>>(box),
158  get<Tags::Interface<Tags::BoundaryDirectionsInterior<volume_dim>,
160  box),
161  get<Tags::Interface<
162  Tags::BoundaryDirectionsInterior<volume_dim>,
164  get<Tags::Interface<
165  Tags::BoundaryDirectionsInterior<volume_dim>,
167 
168  return std::move(box);
169  }
170 };
171 } // namespace Initialization
172 } // 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:533
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
Defines DataBox tags for the linear solver.
Items for initializing the DataBoxes of parallel components.
Definition: ConservativeSystem.hpp:21
The normalized (co)vector represented by Tag.
Definition: Magnitude.hpp:93
The unnormalized face normal one form.
Definition: FaceNormal.hpp:63
Definition: ComputeOperatorAction.hpp:28
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:163
Adds boundary contributions to the sources.
Definition: BoundaryConditions.hpp:69
Defines classes and functions used for manipulating DataBox&#39;s.
tmpl::flatten< tmpl::list< Tags... > > AddSimpleTags
List of Tags to add to the DataBox.
Definition: DataBox.hpp:1227
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:76
Defines the class template Mesh.
Declares function unnormalized_face_normal.
The coordinates in a given frame.
Definition: Tags.hpp:95
The Poisson equation formulated as a set of coupled first-order PDEs.
Definition: FirstOrderSystem.hpp:55
typename DataBox_detail::item_type_impl< TagList, Tag >::type item_type
Get the type that is returned by the Tag. If it is a base tag then a TagList must be passed as a seco...
Definition: DataBoxTag.hpp:410
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:863
Defines tags related to domain quantities.
The magnitude of a (co)vector.
Definition: Magnitude.hpp:53
Defines helper functions for use with Variables class.
Defines classes SimpleTag, PrefixTag, ComputeTag and several functions for retrieving tag info...
Defines class template ConstGlobalCache.
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
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:156
Tag which is either a SimpleTag for quantities on an interface, base tag to a compute item which acts...
Definition: Tags.hpp:217
Require a pointer to not be a nullptr
Definition: ConservativeFromPrimitive.hpp:12
Defines class IterationId.
tmpl::flatten< tmpl::list< Tags... > > AddComputeTags
List of Compute Item Tags to add to the DataBox.
Definition: DataBox.hpp:1234