Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <array>
7 : #include <cstddef>
8 : #include <memory>
9 : #include <string>
10 : #include <unordered_map>
11 : #include <vector>
12 :
13 : #include "Domain/BoundaryConditions/BoundaryCondition.hpp"
14 : #include "Domain/BoundaryConditions/Cartoon.hpp"
15 : #include "Domain/BoundaryConditions/GetBoundaryConditionsBase.hpp"
16 : #include "Domain/CoordinateMaps/Distribution.hpp"
17 : #include "Domain/Creators/DomainCreator.hpp"
18 : #include "Domain/Creators/TimeDependence/TimeDependence.hpp"
19 : #include "Domain/Domain.hpp"
20 : #include "Domain/Structure/DirectionMap.hpp"
21 : #include "Options/Context.hpp"
22 : #include "Options/String.hpp"
23 : #include "Utilities/TMPL.hpp"
24 :
25 : /// \cond
26 : namespace domain {
27 : namespace CoordinateMaps {
28 : class Interval;
29 : template <typename Map1, typename Map2, typename Map3>
30 : class ProductOf3Maps;
31 : } // namespace CoordinateMaps
32 :
33 : template <typename SourceFrame, typename TargetFrame, typename... Maps>
34 : class CoordinateMap;
35 : } // namespace domain
36 : /// \endcond
37 :
38 : namespace domain::creators {
39 : /// Create a 3D Domain that is topologically a line. The 2nd and 3rd
40 : /// dimensions use Cartoon bases with Killing vectors along the \f$\theta\f$ and
41 : /// \f$\phi\f$ directions.
42 1 : class CartoonSphere1D : public DomainCreator<3> {
43 : public:
44 0 : using maps_list = tmpl::list<domain::CoordinateMap<
45 : Frame::BlockLogical, Frame::Inertial,
46 : CoordinateMaps::ProductOf3Maps<CoordinateMaps::Interval,
47 : CoordinateMaps::Identity<1>,
48 : CoordinateMaps::Identity<1>>>>;
49 :
50 0 : static std::string name() { return "CartoonSphere1D"; }
51 :
52 0 : struct InnerRadius {
53 0 : using type = double;
54 0 : static constexpr Options::String help = {
55 : "Inner radius of domain, greater than or equal to 0. If the origin is "
56 : "included, the innermost element will use a 1D Zernike basis, "
57 : "otherwise the domain will be a spherical shell."};
58 : };
59 :
60 0 : struct OuterRadius {
61 0 : using type = double;
62 0 : static constexpr Options::String help = {"Outer radius of domain."};
63 : };
64 :
65 0 : struct InitialRadialRefinement {
66 0 : using type = std::variant<size_t, std::vector<size_t>>;
67 0 : static constexpr Options::String help = {
68 : "Initial refinement level for the radial direction. If one value is "
69 : "given, it will be applied to all blocks, or every block can be "
70 : "specified individually."};
71 : };
72 :
73 0 : struct InitialNumberOfRadialGridPoints {
74 0 : using type = std::variant<size_t, std::vector<size_t>>;
75 0 : static constexpr Options::String help = {
76 : "Initial number of radial grid points. If one input is given, it "
77 : "will be applied to all blocks, or every block can be specified "
78 : "individually."};
79 : };
80 :
81 0 : struct RadialPartitioning {
82 0 : using type = std::vector<double>;
83 0 : static constexpr Options::String help = {
84 : "Radial coordinates of the boundaries splitting the radial blocks, "
85 : "strictly between InnerRadius and OuterRadius. They must be given in "
86 : "ascending order."};
87 : };
88 :
89 0 : struct RadialDistributions {
90 0 : using type = std::variant<CoordinateMaps::Distribution,
91 : std::vector<CoordinateMaps::Distribution>>;
92 0 : static constexpr Options::String help = {
93 : "Distribution of grid points along the radial blocks. A single input "
94 : "will be applied to all blocks, or every block can be specified "
95 : "individually, in which case for N partitions, there must be N+1 "
96 : "distributions."};
97 : };
98 :
99 : template <typename BoundaryConditionsBase>
100 0 : struct InnerBoundaryCondition {
101 0 : static constexpr Options::String help =
102 : "Options for the boundary conditions at the inner boundary.";
103 0 : using type = std::unique_ptr<BoundaryConditionsBase>;
104 : };
105 :
106 : template <typename BoundaryConditionsBase>
107 0 : struct OuterBoundaryCondition {
108 0 : static constexpr Options::String help =
109 : "Options for the boundary conditions at the outer boundary.";
110 0 : using type = std::unique_ptr<BoundaryConditionsBase>;
111 : };
112 :
113 : template <typename BoundaryConditionsBase>
114 0 : struct CartoonBoundaryCondition {
115 0 : static constexpr Options::String help =
116 : "Cartoon boundary condition will be automatically applied to "
117 : "internal cartoon boundaries. No user options needed.";
118 0 : using type = std::nullptr_t;
119 0 : static std::string name() { return "CartoonBC"; }
120 : };
121 :
122 0 : struct TimeDependence {
123 0 : using type =
124 : std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>;
125 0 : static constexpr Options::String help = {
126 : "The time dependence of the moving mesh domain. Specify `None` for no "
127 : "time dependant maps."};
128 : };
129 :
130 0 : using basic_options =
131 : tmpl::list<InnerRadius, OuterRadius, InitialRadialRefinement,
132 : InitialNumberOfRadialGridPoints, RadialPartitioning,
133 : RadialDistributions, TimeDependence>;
134 :
135 : template <typename Metavariables>
136 0 : using options = tmpl::conditional_t<
137 : domain::BoundaryConditions::has_boundary_conditions_base_v<
138 : typename Metavariables::system>,
139 : tmpl::push_back<
140 : basic_options,
141 : InnerBoundaryCondition<
142 : domain::BoundaryConditions::get_boundary_conditions_base<
143 : typename Metavariables::system>>,
144 : OuterBoundaryCondition<
145 : domain::BoundaryConditions::get_boundary_conditions_base<
146 : typename Metavariables::system>>>,
147 : basic_options>;
148 :
149 0 : static constexpr Options::String help{
150 : "A sphere domain that requires/enforces spherical symmetry, resulting in "
151 : "a 1D computational domain (the radial axis). It uses Cartoon partial "
152 : "derivatives for the angular directions not in the computational "
153 : "domain. If an element touches the x=0 axis, it uses ZernikeB1 bases and "
154 : "automatically applies a system's Cartoon-type boundary condition."};
155 :
156 0 : CartoonSphere1D(
157 : double inner_bound, double outer_bound,
158 : typename InitialRadialRefinement::type&& initial_refinement_levels,
159 : typename InitialNumberOfRadialGridPoints::type&& initial_num_points,
160 : std::vector<double> radial_partitioning = {},
161 : const typename RadialDistributions::type& radial_distributions =
162 : domain::CoordinateMaps::Distribution::Linear,
163 : std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>
164 : time_dependence = nullptr,
165 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
166 : inner_boundary_condition = nullptr,
167 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
168 : outer_boundary_condition = nullptr,
169 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
170 : cartoon_boundary_condition = nullptr,
171 : const Options::Context& context = {});
172 :
173 0 : CartoonSphere1D() = default;
174 0 : CartoonSphere1D(const CartoonSphere1D&) = delete;
175 0 : CartoonSphere1D(CartoonSphere1D&&) = default;
176 0 : CartoonSphere1D& operator=(const CartoonSphere1D&) = delete;
177 0 : CartoonSphere1D& operator=(CartoonSphere1D&&) = default;
178 0 : ~CartoonSphere1D() override = default;
179 :
180 0 : Domain<3> create_domain() const override;
181 :
182 : std::vector<DirectionMap<
183 : 3, std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>>>
184 1 : external_boundary_conditions() const override;
185 :
186 1 : std::vector<std::array<size_t, 3>> initial_extents() const override;
187 :
188 1 : std::vector<std::array<size_t, 3>> initial_refinement_levels() const override;
189 :
190 : // The block names are Block0, Block1, ..., starting with the innermost
191 : // Block.
192 1 : std::vector<std::string> block_names() const override;
193 :
194 : // The only block group is PositiveBlocks
195 : std::unordered_map<std::string, std::unordered_set<std::string>>
196 1 : block_groups() const override;
197 :
198 1 : auto functions_of_time(const std::unordered_map<std::string, double>&
199 : initial_expiration_times = {}) const
200 : -> std::unordered_map<
201 : std::string,
202 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>> override;
203 :
204 : private:
205 0 : double inner_bound_{};
206 0 : double outer_bound_{};
207 0 : std::vector<size_t> initial_refinement_levels_{};
208 0 : std::vector<size_t> initial_num_points_{};
209 0 : std::vector<double> radial_partitioning_{};
210 0 : std::vector<CoordinateMaps::Distribution> radial_distributions_{};
211 0 : bool use_zernike_{};
212 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
213 0 : inner_boundary_condition_{};
214 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
215 0 : outer_boundary_condition_{};
216 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
217 0 : cartoon_boundary_condition_{};
218 : std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>
219 0 : time_dependence_;
220 0 : size_t num_blocks_{};
221 0 : std::vector<std::string> block_names_{};
222 : std::unordered_map<std::string, std::unordered_set<std::string>>
223 0 : block_groups_{};
224 : };
225 :
226 : } // namespace domain::creators
227 :
228 : namespace domain::creators::detail {
229 : /// \brief Helper struct for CartoonSphere1D options parsing so the internal
230 : /// cartoon boundary condition at $x = 0$ is not a required argument.
231 : ///
232 : /// \details To get the cartoon-type boundary condition from a system we need
233 : /// access to the system's metavariables, which is only present when parsing
234 : /// options. The point of this design is so that the input file does not require
235 : /// a dummy value for an InnerBoundaryCondition that is always the same for a
236 : /// given system.
237 : ///
238 : /// This helper's constructor does not take an InnerBoundaryCondition, which
239 : /// means if we parse a CartoonSphere1D as a CartonSphere1DOptionsHelper
240 : /// by having an options parsing specialization (so the input file values are
241 : /// the helper's construtor, not CartoonSphere1D's), we can detect the
242 : /// cartoon-type boundary condition for the given system and only then call the
243 : /// CartoonSphere1D constructor with the extra information.
244 : struct CartoonSphere1DOptionsHelper {
245 : // Inherit the options template from CartoonSphere1D
246 : template <typename Metavariables>
247 : using options = typename domain::creators::CartoonSphere1D::template options<
248 : Metavariables>;
249 :
250 : using InitialRadialRefinement =
251 : domain::creators::CartoonSphere1D::InitialRadialRefinement;
252 : using InitialNumberOfRadialGridPoints =
253 : domain::creators::CartoonSphere1D::InitialNumberOfRadialGridPoints;
254 : using RadialDistributions =
255 : domain::creators::CartoonSphere1D::RadialDistributions;
256 :
257 : static constexpr Options::String help = {"CartoonSphere1DOptionsHelper"};
258 :
259 : // Default constructor required by Options system
260 : CartoonSphere1DOptionsHelper() = default;
261 :
262 : // Does not take cartoon BC
263 : CartoonSphere1DOptionsHelper(
264 : double inner_bound, double outer_bound,
265 : typename InitialRadialRefinement::type&& initial_refinement_levels,
266 : typename InitialNumberOfRadialGridPoints::type&& initial_num_points,
267 : std::vector<double> radial_partitioning = {},
268 : typename RadialDistributions::type&& radial_distributions =
269 : domain::CoordinateMaps::Distribution::Linear,
270 : std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>
271 : time_dependence = nullptr,
272 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
273 : inner_boundary_condition = nullptr,
274 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
275 : outer_boundary_condition = nullptr,
276 : Options::Context&& context = {});
277 :
278 : // Same members as in CartoonSphere1D; public, to be extracted
279 : double inner_bound_{std::numeric_limits<double>::signaling_NaN()};
280 : double outer_bound_{std::numeric_limits<double>::signaling_NaN()};
281 : typename domain::creators::CartoonSphere1D::InitialRadialRefinement::type
282 : initial_refinement_levels_{};
283 : typename domain::creators::CartoonSphere1D::InitialNumberOfRadialGridPoints::
284 : type initial_num_points_{};
285 : std::vector<double> radial_partitioning_{};
286 : domain::creators::CartoonSphere1D::RadialDistributions::type
287 : radial_distributions_{domain::CoordinateMaps::Distribution::Linear};
288 : std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>
289 : time_dependence_{nullptr};
290 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
291 : inner_boundary_condition_{nullptr};
292 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
293 : outer_boundary_condition_{nullptr};
294 : std::nullptr_t cartoon_boundary_condition_{
295 : nullptr}; // For CartoonBoundaryCondition option
296 : Options::Context context_{};
297 : };
298 : } // namespace domain::creators::detail
299 :
300 : // Options parsing specialization to automate CartoonSphere1D's cartoon
301 : // boundary condition
302 : template <>
303 0 : struct Options::create_from_yaml<domain::creators::CartoonSphere1D> {
304 : template <typename Metavariables>
305 0 : static domain::creators::CartoonSphere1D create(
306 : const Options::Option& options) {
307 : auto helper =
308 : options.parse_as<domain::creators::detail::CartoonSphere1DOptionsHelper,
309 : Metavariables>();
310 :
311 : // Create cartoon BC if system supports it, if not will throw parse error in
312 : // real constructor
313 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
314 : cartoon_boundary_condition = nullptr;
315 : if constexpr (domain::BoundaryConditions::has_boundary_conditions_base_v<
316 : typename Metavariables::system>) {
317 : if constexpr (domain::BoundaryConditions::system_has_cartoon_bc_v<
318 : Metavariables>) {
319 : cartoon_boundary_condition =
320 : domain::BoundaryConditions::make_cartoon_boundary_condition<
321 : Metavariables>();
322 : }
323 : }
324 :
325 : // Construct CartoonSphere1D using the helper's parsed data + cartoon BC
326 : return domain::creators::CartoonSphere1D(
327 : helper.inner_bound_, helper.outer_bound_,
328 : std::move(helper.initial_refinement_levels_),
329 : std::move(helper.initial_num_points_),
330 : std::move(helper.radial_partitioning_), helper.radial_distributions_,
331 : std::move(helper.time_dependence_),
332 : std::move(helper.inner_boundary_condition_),
333 : std::move(helper.outer_boundary_condition_),
334 : std::move(cartoon_boundary_condition), helper.context_);
335 : }
336 : };
|