Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <cstddef>
7 : #include <type_traits>
8 :
9 : #include "DataStructures/DataBox/DataBox.hpp"
10 : #include "DataStructures/DataBox/MetavariablesTag.hpp"
11 : #include "Domain/Structure/Direction.hpp"
12 : #include "Domain/Tags.hpp"
13 : #include "Domain/Tags/Faces.hpp"
14 : #include "Elliptic/BoundaryConditions/BoundaryCondition.hpp"
15 : #include "Elliptic/Utilities/ApplyAt.hpp"
16 : #include "Utilities/CallWithDynamicType.hpp"
17 : #include "Utilities/Gsl.hpp"
18 : #include "Utilities/TMPL.hpp"
19 :
20 : namespace elliptic {
21 :
22 : namespace detail {
23 : // Return the `BoundaryConditionClasses`, or get the list of derived classes
24 : // from `Metavariables::factory_creation` if `BoundaryConditionClasses` is
25 : // empty.
26 : template <typename Base, typename BoundaryConditionClasses, typename DbTagsList>
27 : struct GetBoundaryConditionClasses {
28 : using type = BoundaryConditionClasses;
29 : };
30 : template <typename Base, typename DbTagsList>
31 : struct GetBoundaryConditionClasses<Base, tmpl::list<>, DbTagsList> {
32 : using type = tmpl::at<
33 : typename std::decay_t<decltype(db::get<Parallel::Tags::Metavariables>(
34 : std::declval<db::DataBox<DbTagsList>>()))>::factory_creation::
35 : factory_classes,
36 : Base>;
37 : };
38 : } // namespace detail
39 :
40 : /*!
41 : * \brief Apply the `boundary_condition` to the `fields_and_fluxes` with
42 : * arguments from interface tags in the DataBox.
43 : *
44 : * This functions assumes the arguments for the `boundary_condition` are stored
45 : * in the DataBox in tags `domain::Tags::Faces<Dim, Tag>`.
46 : * This may turn out not to be the most efficient setup, so code that
47 : * uses the boundary conditions doesn't have to use this function but can
48 : * procure the arguments differently. For example, future optimizations may
49 : * involve storing a subset of arguments that don't change during an elliptic
50 : * solve in direction-maps in the DataBox, and slicing other arguments to the
51 : * interface every time the boundary conditions are applied.
52 : *
53 : * The `ArgsTransform` template parameter can be used to transform the set of
54 : * argument tags for the boundary conditions further. It must be compatible with
55 : * `tmpl::transform`. For example, it may wrap the tags in another prefix. Set
56 : * it to `void` (default) to apply no transformation.
57 : *
58 : * The `BoundaryConditionClasses` can be used to list a set of classes derived
59 : * from `elliptic::BoundaryConditions::BoundaryCondition` that are iterated to
60 : * determine the concrete type of `boundary_condition`. It can be `tmpl::list<>`
61 : * (default) to use the classes listed in `Metavariables::factory_creation`
62 : * instead.
63 : */
64 : template <bool Linearized, typename ArgsTransform = void,
65 : typename BoundaryConditionClasses = tmpl::list<>, size_t Dim,
66 : typename DbTagsList, typename MapKeys, typename... FieldsAndFluxes>
67 1 : void apply_boundary_condition(
68 : const elliptic::BoundaryConditions::BoundaryCondition<Dim>&
69 : boundary_condition,
70 : const db::DataBox<DbTagsList>& box, const MapKeys& map_keys_to_direction,
71 : FieldsAndFluxes&&... fields_and_fluxes) {
72 : using boundary_condition_classes =
73 : typename detail::GetBoundaryConditionClasses<
74 : elliptic::BoundaryConditions::BoundaryCondition<Dim>,
75 : BoundaryConditionClasses, DbTagsList>::type;
76 : call_with_dynamic_type<void, boundary_condition_classes>(
77 : &boundary_condition,
78 : []<typename... LocalFieldsAndFluxes>(
79 : const auto* const derived, const MapKeys& local_map_keys_to_direction,
80 : const db::DataBox<DbTagsList>& local_box,
81 : const LocalFieldsAndFluxes&... local_fields_and_fluxes) {
82 : using Derived = std::decay_t<std::remove_pointer_t<decltype(derived)>>;
83 : using volume_tags =
84 : tmpl::conditional_t<Linearized,
85 : typename Derived::volume_tags_linearized,
86 : typename Derived::volume_tags>;
87 : using argument_tags = domain::make_faces_tags<
88 : Dim,
89 : tmpl::conditional_t<Linearized,
90 : typename Derived::argument_tags_linearized,
91 : typename Derived::argument_tags>,
92 : volume_tags>;
93 : using argument_tags_transformed =
94 : tmpl::conditional_t<std::is_same_v<ArgsTransform, void>,
95 : argument_tags,
96 : tmpl::transform<argument_tags, ArgsTransform>>;
97 : using volume_tags_transformed =
98 : tmpl::conditional_t<std::is_same_v<ArgsTransform, void>,
99 : volume_tags,
100 : tmpl::transform<volume_tags, ArgsTransform>>;
101 : elliptic::util::apply_at<argument_tags_transformed,
102 : volume_tags_transformed>(
103 : [&](const auto&... args) {
104 : if constexpr (Linearized) {
105 : derived->apply_linearized(
106 : local_fields_and_fluxes...,
107 : args...);
108 : } else {
109 : derived->apply(local_fields_and_fluxes..., args...);
110 : }
111 : },
112 : local_box, local_map_keys_to_direction);
113 : },
114 : map_keys_to_direction, box,
115 : std::forward<FieldsAndFluxes>(fields_and_fluxes)...);
116 : }
117 : } // namespace elliptic
|