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/Tag.hpp"
10 : #include "Utilities/NoSuchType.hpp"
11 : #include "Utilities/TMPL.hpp"
12 : #include "Utilities/TypeTraits/CreateGetStaticMemberVariableOrDefault.hpp"
13 : #include "Utilities/TypeTraits/CreateGetTypeAliasOrDefault.hpp"
14 : #include "Utilities/TypeTraits/IsA.hpp"
15 :
16 : /// \cond
17 : namespace Tags {
18 : template <size_t Dim, typename TagsList>
19 : struct BoundaryVariables;
20 : } // namespace Tags
21 : /// \endcond
22 :
23 : namespace evolution::dg {
24 1 : namespace Tags {
25 : /// \ingroup DiscontinuousGalerkinGroup
26 : /// \brief The boundary-evolved twin of an interior source field.
27 : ///
28 : /// A boundary-evolved field is stored and time-integrated only on external
29 : /// boundary faces (a pointwise per-face-node ODE); it has no volume extent.
30 : /// This is a prefix tag wrapping the interior source, so its type matches the
31 : /// source.
32 : ///
33 : /// \note Boundary evolved fields cannot currently be used with AMR or LTS.
34 : template <typename Source>
35 1 : struct BoundaryValue : db::PrefixTag, db::SimpleTag {
36 0 : using type = typename Source::type;
37 : /// The interior source field this boundary field is the twin of.
38 1 : using tag = Source;
39 : };
40 : } // namespace Tags
41 :
42 : namespace detail {
43 : template <typename Tag>
44 : struct is_boundary_variables_tag : std::false_type {};
45 : template <size_t Dim, typename TagsList>
46 : struct is_boundary_variables_tag<::Tags::BoundaryVariables<Dim, TagsList>>
47 : : std::true_type {};
48 :
49 : template <typename VariablesTag>
50 : struct boundary_variables_tag_impl : std::false_type {
51 : using type = NoSuchType;
52 : };
53 : template <typename VariablesTag>
54 : requires tt::is_a_v<tmpl::list, VariablesTag>
55 : struct boundary_variables_tag_impl<VariablesTag> {
56 : private:
57 : using back = tmpl::back<VariablesTag>;
58 :
59 : public:
60 : static constexpr bool value = is_boundary_variables_tag<back>::value;
61 : static_assert(
62 : tmpl::count_if<VariablesTag,
63 : tmpl::bind<is_boundary_variables_tag, tmpl::_1>>::value ==
64 : (value ? 1 : 0),
65 : "A list-valued variables_tag must contain at most one "
66 : "::Tags::BoundaryVariables entry, and it must be the last entry.");
67 : static_assert(not value or tmpl::size<VariablesTag>::value == 2,
68 : "A list-valued variables_tag with a ::Tags::BoundaryVariables "
69 : "entry must contain exactly two entries: the volume variables "
70 : "followed by the boundary variables.");
71 : using type = tmpl::conditional_t<value, back, NoSuchType>;
72 : };
73 : } // namespace detail
74 :
75 : /// \ingroup DiscontinuousGalerkinGroup
76 : /// \brief Whether the system declares boundary-evolved variables, i.e.
77 : /// whether `System::variables_tag` is a `tmpl::list` whose last entry is a
78 : /// `::Tags::BoundaryVariables`. Such a list has exactly two entries, the first
79 : /// holding the volume variables.
80 : template <typename System>
81 1 : constexpr bool system_has_boundary_variables_v =
82 : detail::boundary_variables_tag_impl<typename System::variables_tag>::value;
83 :
84 : /// \ingroup DiscontinuousGalerkinGroup
85 : /// \brief The `::Tags::BoundaryVariables` entry of the system's list-valued
86 : /// `variables_tag`, or `NoSuchType` if the system does not declare
87 : /// boundary-evolved variables.
88 : template <typename System>
89 1 : using boundary_variables_tag = typename detail::boundary_variables_tag_impl<
90 : typename System::variables_tag>::type;
91 :
92 : /// @{
93 : /// \ingroup DiscontinuousGalerkinGroup
94 : /// \brief The projected interior inputs to a boundary condition's
95 : /// `boundary_field_time_derivatives` method, in the order evolved,
96 : /// primitive, temporary.
97 : ///
98 : /// They are declared separately from the `dg_ghost` interior inputs
99 : /// (`dg_interior_evolved_variables_tags` etc.) so that a boundary condition
100 : /// can request a different projected interior state for its boundary-field
101 : /// time derivative. The boundary-condition pass projects the requested
102 : /// fields onto the face exactly as it does for the `dg_ghost` inputs.
103 1 : CREATE_GET_TYPE_ALIAS_OR_DEFAULT(
104 : boundary_field_time_derivatives_evolved_variables_tags)
105 : CREATE_GET_TYPE_ALIAS_OR_DEFAULT(boundary_field_time_derivatives_primitive_tags)
106 : CREATE_GET_TYPE_ALIAS_OR_DEFAULT(boundary_field_time_derivatives_temporary_tags)
107 :
108 : template <typename BoundaryCondition>
109 : using boundary_field_time_derivatives_interior_tags = tmpl::append<
110 : get_boundary_field_time_derivatives_evolved_variables_tags_or_default_t<
111 : BoundaryCondition, tmpl::list<>>,
112 : get_boundary_field_time_derivatives_primitive_tags_or_default_t<
113 : BoundaryCondition, tmpl::list<>>,
114 : get_boundary_field_time_derivatives_temporary_tags_or_default_t<
115 : BoundaryCondition, tmpl::list<>>>;
116 : /// @}
117 :
118 : namespace detail {
119 : CREATE_GET_STATIC_MEMBER_VARIABLE_OR_DEFAULT(evolves_boundary_variables)
120 :
121 : // Detect if the boundary condition declares a `boundary_field_time_derivatives`
122 : // method.
123 : //
124 : // Detection takes the member's address, which does not resolve for an
125 : // overloaded or templated method, so those are reported as absent.
126 : template <typename BoundaryCondition>
127 : constexpr bool has_boundary_field_time_derivatives_v = requires {
128 : &BoundaryCondition::boundary_field_time_derivatives;
129 : };
130 : } // namespace detail
131 :
132 : /// @{
133 : /// \ingroup DiscontinuousGalerkinGroup
134 : /// \brief Whether a boundary condition evolves the system's boundary-evolved
135 : /// variables: the opt-in is the marker
136 : /// `static constexpr bool evolves_boundary_variables = true;` on the
137 : /// boundary condition. An opt-in boundary condition must declare
138 : /// the method `boundary_field_time_derivatives`.
139 : template <typename BoundaryCondition>
140 1 : constexpr bool evolves_boundary_variables_v =
141 : detail::get_evolves_boundary_variables_or_default_v<BoundaryCondition,
142 : false>;
143 : /// @}
144 : } // namespace evolution::dg
|