Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <memory>
7 : #include <pup.h>
8 :
9 : #include "Domain/BoundaryConditions/BoundaryCondition.hpp"
10 : #include "Options/String.hpp"
11 : #include "Utilities/Serialization/CharmPupable.hpp"
12 : #include "Utilities/TMPL.hpp"
13 :
14 : /// \cond
15 : template <size_t Dim>
16 : class Mesh;
17 : /// \endcond
18 :
19 : namespace domain::BoundaryConditions {
20 : /// Mark a boundary condition as being used as an internal Cartoon boundary.
21 : ///
22 : /// The cartoon method requires a ZernikeB1 basis to be stable at small
23 : /// \f$x\f$, which should not have a boundary condition applied. However, FD
24 : /// does require ghost zones to be filled on this boundary, so `is_cartoon()`
25 : /// can be used to determine whether to treat this boundary condition as
26 : /// something to implement or skip.
27 1 : class MarkAsCartoon {
28 : public:
29 0 : MarkAsCartoon() = default;
30 0 : MarkAsCartoon(MarkAsCartoon&&) = default;
31 0 : MarkAsCartoon& operator=(MarkAsCartoon&&) = default;
32 0 : MarkAsCartoon(const MarkAsCartoon&) = default;
33 0 : MarkAsCartoon& operator=(const MarkAsCartoon&) = default;
34 0 : virtual ~MarkAsCartoon() = 0;
35 : };
36 :
37 : /*!
38 : * \brief Cartoon boundary conditions, to be used as the default placeholder in
39 : * systems without Subcell.
40 : *
41 : * To use with a specific system, add:
42 : *
43 : * \code
44 : * domain::BoundaryConditions::Cartoon<your::system::BoundaryConditionBase>
45 : * \endcode
46 : *
47 : * to the list of creatable classes.
48 : *
49 : * Note: Cartoon boundary conditions should only be specified with systems
50 : * set-up to use the cartoon method. It should not be used as an external
51 : * boundary.
52 : */
53 : template <typename SystemBoundaryConditionBaseClass>
54 1 : struct Cartoon final : public SystemBoundaryConditionBaseClass,
55 : public MarkAsCartoon {
56 : public:
57 0 : static constexpr bool factory_creatable = false;
58 0 : static std::string name() { return "Cartoon"; }
59 :
60 0 : Cartoon() = default;
61 0 : Cartoon(Cartoon&&) = default;
62 0 : Cartoon& operator=(Cartoon&&) = default;
63 0 : Cartoon(const Cartoon&) = default;
64 0 : Cartoon& operator=(const Cartoon&) = default;
65 0 : ~Cartoon() override = default;
66 :
67 0 : explicit Cartoon(CkMigrateMessage* msg);
68 :
69 0 : WRAPPED_PUPable_decl_base_template(
70 : domain::BoundaryConditions::BoundaryCondition, Cartoon);
71 :
72 0 : auto get_clone() const -> std::unique_ptr<
73 : domain::BoundaryConditions::BoundaryCondition> override;
74 :
75 0 : void pup(PUP::er& p) override;
76 : };
77 :
78 : template <typename SystemBoundaryConditionBaseClass>
79 : Cartoon<SystemBoundaryConditionBaseClass>::Cartoon(CkMigrateMessage* const msg)
80 : : SystemBoundaryConditionBaseClass(msg) {}
81 :
82 : template <typename SystemBoundaryConditionBaseClass>
83 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
84 : Cartoon<SystemBoundaryConditionBaseClass>::get_clone() const {
85 : return std::make_unique<Cartoon>(*this);
86 : }
87 :
88 : template <typename SystemBoundaryConditionBaseClass>
89 : void Cartoon<SystemBoundaryConditionBaseClass>::pup(PUP::er& p) {
90 : BoundaryCondition::pup(p);
91 : }
92 :
93 : /// \cond
94 : template <typename SystemBoundaryConditionBaseClass>
95 : // NOLINTNEXTLINE
96 : PUP::able::PUP_ID Cartoon<SystemBoundaryConditionBaseClass>::my_PUP_ID = 0;
97 : /// \endcond
98 :
99 : /// Check if a boundary condition inherits from `MarkAsCartoon`, which
100 : /// constitutes as it being marked as an internal Cartoon boundary condition.
101 1 : bool is_cartoon(const std::unique_ptr<BoundaryCondition>& boundary_condition);
102 :
103 : /// Check if a mesh is compatible with a Cartoon boundary condition, i.e. it is
104 : /// using cartoon bases in a proper way.
105 : template <size_t Dim>
106 1 : bool dg_mesh_is_cartoon_compatible(const Mesh<Dim>& dg_mesh);
107 :
108 : namespace detail {
109 : template <typename T>
110 : struct inherits_from_mark_as_cartoon : std::is_base_of<MarkAsCartoon, T> {};
111 :
112 : template <typename List>
113 : struct find_cartoon_bc_impl {
114 : using filtered_list =
115 : tmpl::filter<List, inherits_from_mark_as_cartoon<tmpl::_1>>;
116 :
117 : // Ensure there's exactly one cartoon BC, not zero or multiple
118 : static_assert(tmpl::size<filtered_list>::value <= 1,
119 : "Multiple cartoon boundary conditions found in factory list. "
120 : "Only one cartoon boundary condition is allowed per system.");
121 :
122 : // Need lazy evaluation in case list is empty
123 : template <typename L>
124 : using get_maybe_first = tmpl::apply<tmpl::apply<
125 : tmpl::if_<std::bool_constant<(tmpl::size<L>::value != 0)>,
126 : tmpl::defer<tmpl::bind<tmpl::front, tmpl::pin<L>>>, void>>>;
127 :
128 : using type = get_maybe_first<filtered_list>;
129 : };
130 :
131 : /// Find the unique type in a tmpl::list that inherits from MarkAsCartoon
132 : template <typename List>
133 : using find_cartoon_bc = typename find_cartoon_bc_impl<List>::type;
134 :
135 : /// Check if a tmpl::list contains any types that inherit from MarkAsCartoon
136 : template <typename List>
137 : constexpr bool has_cartoon_bc_v = not std::is_void_v<find_cartoon_bc<List>>;
138 :
139 : /// Filter out cartoon boundary conditions from a list, leaving only external
140 : /// BCs
141 : template <typename List>
142 : using filter_out_cartoon_bcs =
143 : tmpl::remove_if<List, inherits_from_mark_as_cartoon<tmpl::_1>>;
144 : } // namespace detail
145 :
146 : /// Extract the cartoon boundary condition type from a system's boundary
147 : /// condition list. Returns void if no cartoon boundary condition is found.
148 : template <typename Metavariables>
149 1 : using get_cartoon_boundary_condition_from_system = detail::find_cartoon_bc<
150 : tmpl::at<typename Metavariables::factory_creation::factory_classes,
151 : typename Metavariables::system::boundary_conditions_base>>;
152 :
153 : /// Extract only the external (non-cartoon) boundary conditions from a system's
154 : /// boundary condition list. This should be used for user-selectable boundary
155 : /// condition options to prevent cartoon BCs from being specified as external
156 : /// BCs.
157 : template <typename Metavariables>
158 1 : using get_external_boundary_conditions_from_system =
159 : detail::filter_out_cartoon_bcs<
160 : tmpl::at<typename Metavariables::factory_creation::factory_classes,
161 : typename Metavariables::system::boundary_conditions_base>>;
162 :
163 : /// Check if a system has a cartoon boundary condition available
164 : template <typename Metavariables>
165 1 : constexpr bool system_has_cartoon_bc_v = not std::is_void_v<
166 : get_cartoon_boundary_condition_from_system<Metavariables>>;
167 :
168 : /// Create a cartoon boundary condition for systems that support it.
169 : /// Returns nullptr if the system doesn't have a cartoon boundary condition.
170 : template <typename Metavariables>
171 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
172 1 : make_cartoon_boundary_condition() {
173 : if constexpr (system_has_cartoon_bc_v<Metavariables>) {
174 : using cartoon_bc_type =
175 : get_cartoon_boundary_condition_from_system<Metavariables>;
176 : return std::make_unique<cartoon_bc_type>();
177 : } else {
178 : return nullptr;
179 : }
180 : }
181 : } // namespace domain::BoundaryConditions
|