ImposeBoundaryConditions.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <algorithm>
7 #include <cstddef>
8 #include <tuple>
9 #include <utility>
10 
12 #include "Domain/Tags.hpp"
13 #include "NumericalAlgorithms/DiscontinuousGalerkin/Actions/InterfaceActionHelpers.hpp"
14 #include "NumericalAlgorithms/DiscontinuousGalerkin/FluxCommunicationTypes.hpp"
15 #include "NumericalAlgorithms/DiscontinuousGalerkin/MortarHelpers.hpp"
16 #include "NumericalAlgorithms/DiscontinuousGalerkin/Tags.hpp"
19 #include "Utilities/Gsl.hpp"
20 #include "Utilities/TMPL.hpp"
22 
23 /// \cond
24 namespace Tags {
25 template <typename Tag>
26 struct Magnitude;
27 } // namespace Tags
28 // IWYU pragma: no_forward_declare db::DataBox
29 /// \endcond
30 
31 namespace Elliptic {
32 namespace dg {
33 namespace Actions {
34 
35 /*!
36  * \brief Packages data on external boundaries so that they represent
37  * homogeneous (zero) Dirichlet boundary conditions.
38  *
39  * This action imposes homogeneous boundary conditions on all fields in
40  * `system::impose_boundary_conditions_on_fields`. The fields are wrapped in
41  * `LinearSolver::Tags::Operand`. The result should be a subset of the
42  * `system::variables`. Because we are working with the linear solver operand,
43  * we cannot impose non-zero boundary conditions here. Instead, non-zero
44  * boundary conditions are handled as contributions to the linear solver source
45  * during initialization.
46  *
47  * \warning This actions works only for scalar fields right now. It should be
48  * considered a temporary solution and will have to be reworked for more
49  * involved boundary conditions.
50  *
51  * With:
52  * - `interior<Tag> =
53  * Tags::Interface<Tags::BoundaryDirectionsInterior<volume_dim>, Tag>`
54  * - `exterior<Tag> =
55  * Tags::Interface<Tags::BoundaryDirectionsExterior<volume_dim>, Tag>`
56  *
57  * Uses:
58  * - Metavariables:
59  * - `normal_dot_numerical_flux`
60  * - `temporal_id`
61  * - System:
62  * - `volume_dim`
63  * - `variables_tag`
64  * - `impose_boundary_conditions_on_fields`
65  * - ConstGlobalCache:
66  * - `normal_dot_numerical_flux`
67  * - DataBox:
68  * - `Tags::Element<volume_dim>`
69  * - `temporal_id`
70  * - `Tags::BoundaryDirectionsInterior<volume_dim>`
71  * - `Tags::BoundaryDirectionsExterior<volume_dim>`
72  * - `interior<variables_tag>`
73  * - `exterior<variables_tag>`
74  * - `interior<normal_dot_numerical_flux::type::argument_tags>`
75  * - `exterior<normal_dot_numerical_flux::type::argument_tags>`
76  *
77  * DataBox changes:
78  * - Modifies:
79  * - `exterior<variables_tag>`
80  * - `Tags::VariablesBoundaryData`
81  */
82 template <typename Metavariables>
84  using const_global_cache_tags =
85  tmpl::list<typename Metavariables::normal_dot_numerical_flux>;
86 
87  template <typename DbTags, typename... InboxTags, typename ArrayIndex,
88  typename ActionList, typename ParallelComponent>
89  static auto apply(db::DataBox<DbTags>& box,
90  const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
92  const ArrayIndex& /*array_index*/,
93  const ActionList /*meta*/,
94  const ParallelComponent* const /*meta*/) noexcept {
95  using system = typename Metavariables::system;
96  using dirichlet_tags =
97  typename system::impose_boundary_conditions_on_fields;
98  constexpr size_t volume_dim = system::volume_dim;
99 
100  // Set the data on exterior (ghost) faces to impose the boundary conditions
101  db::mutate<Tags::Interface<Tags::BoundaryDirectionsExterior<volume_dim>,
102  typename system::variables_tag>>(
103  make_not_null(&box),
104  // Need to use system::volume_dim below instead of just
105  // volume_dim to avoid an ICE on gcc 7.
108  typename system::variables_tag>>*>
109  exterior_boundary_vars,
112  typename system::variables_tag>>& interior_vars) noexcept {
113  for (auto& exterior_direction_and_vars : *exterior_boundary_vars) {
114  auto& direction = exterior_direction_and_vars.first;
115  auto& exterior_vars = exterior_direction_and_vars.second;
116 
117  // By default, use the variables on the external boundary for the
118  // exterior
119  exterior_vars = interior_vars.at(direction);
120 
121  // For those variables where we have boundary conditions, impose
122  // zero Dirichlet b.c. here. The non-zero boundary conditions are
123  // handled as contributions to the source in InitializeElement.
124  // Imposing them here would not work because we are working with the
125  // linear solver operand.
126  tmpl::for_each<dirichlet_tags>([
127  &interior_vars, &exterior_vars, &direction
128  ](auto dirichlet_tag_val) noexcept {
129  using dirichlet_tag =
130  tmpl::type_from<decltype(dirichlet_tag_val)>;
131  using dirichlet_operand_tag =
133  // Use mirror principle. This only works for scalars right now.
134  get(get<dirichlet_operand_tag>(exterior_vars)) =
135  -1. *
136  get<dirichlet_operand_tag>(interior_vars.at(direction)).get();
137  });
138  }
139  },
140  get<Tags::Interface<Tags::BoundaryDirectionsInterior<volume_dim>,
141  typename system::variables_tag>>(box));
142 
143  const auto& element = db::get<Tags::Element<volume_dim>>(box);
144  const auto& temporal_id = db::get<typename Metavariables::temporal_id>(box);
145 
146  const auto& normal_dot_numerical_flux_computer =
147  get<typename Metavariables::normal_dot_numerical_flux>(cache);
148 
149  // Store local and packaged data on the mortars
150  for (const auto& direction : element.external_boundaries()) {
151  const auto mortar_id = std::make_pair(
153 
154  auto interior_data = DgActions_detail::compute_local_mortar_data(
155  box, direction, normal_dot_numerical_flux_computer,
157 
158  auto exterior_data = DgActions_detail::compute_packaged_data(
159  box, direction, normal_dot_numerical_flux_computer,
161 
162  db::mutate<Tags::VariablesBoundaryData>(
163  make_not_null(&box),
164  [&mortar_id, &temporal_id, &interior_data,
165  &exterior_data ](const gsl::not_null<
167  mortar_data) noexcept {
168  mortar_data->at(mortar_id).local_insert(temporal_id,
169  std::move(interior_data));
170  mortar_data->at(mortar_id).remote_insert(temporal_id,
171  std::move(exterior_data));
172  });
173  }
174  return std::forward_as_tuple(std::move(box));
175  }
176 };
177 
178 } // namespace Actions
179 } // namespace dg
180 } // namespace Elliptic
Defines class tuples::TaggedTuple.
Defines DataBox tags for the linear solver.
Definition: ComputeOperatorAction.hpp:28
Definition: InitializeElement.hpp:63
An ElementId uniquely labels an Element. It is constructed from the BlockId of the Block to which the...
Definition: ElementId.hpp:36
The set of directions which correspond to external boundaries. Used for representing data on the inte...
Definition: Tags.hpp:163
constexpr auto apply(F &&f, const DataBox< BoxTags > &box, Args &&... args)
Apply the function f with argument Tags TagsList from DataBox box
Definition: DataBox.hpp:1595
The operand that the local linear operator is applied to.
Definition: Tags.hpp:40
An associative container that is indexed by structs.
Definition: TaggedTuple.hpp:272
Defines classes and functions used for manipulating DataBox&#39;s.
Packages data on external boundaries so that they represent homogeneous (zero) Dirichlet boundary con...
Definition: ImposeBoundaryConditions.hpp:83
Definition: InterpolationTargetWedgeSectionTorus.hpp:24
Definition: DataBoxTag.hpp:29
A Charm++ chare that caches constant data once per Charm++ node.
Definition: ConstGlobalCache.hpp:76
The Poisson equation formulated as a set of coupled first-order PDEs.
Definition: FirstOrderSystem.hpp:55
Wraps the template metaprogramming library used (brigand)
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
Defines functions and classes from the GSL.
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.
Definition: SolvePoissonProblem.hpp:38
Defines class template ConstGlobalCache.
The set of directions which correspond to external boundaries. To be used to represent data which exi...
Definition: Tags.hpp:177
Tag which is either a SimpleTag for quantities on an interface, base tag to a compute item which acts...
Definition: Tags.hpp:217
Definition: ComputeTimeDerivative.hpp:28
Require a pointer to not be a nullptr
Definition: ConservativeFromPrimitive.hpp:12