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 <optional>
10 : #include <string>
11 : #include <unordered_map>
12 : #include <variant>
13 : #include <vector>
14 :
15 : #include "Domain/BoundaryConditions/BoundaryCondition.hpp"
16 : #include "Domain/BoundaryConditions/GetBoundaryConditionsBase.hpp"
17 : #include "Domain/CoordinateMaps/Distribution.hpp"
18 : #include "Domain/Creators/DomainCreator.hpp"
19 : #include "Domain/Creators/TimeDependence/TimeDependence.hpp"
20 : #include "Domain/Creators/TimeDependentOptions/Sphere.hpp"
21 : #include "Options/Auto.hpp"
22 : #include "Options/Context.hpp"
23 : #include "Options/String.hpp"
24 : #include "Utilities/TMPL.hpp"
25 :
26 : /// \cond
27 : template <size_t Dim, typename T>
28 : class DirectionMap;
29 : template <size_t Dim>
30 : class Domain;
31 : namespace domain {
32 : namespace CoordinateMaps {
33 : template <size_t Dim>
34 : class Identity;
35 : class Interval;
36 : template <typename Map1, typename Map2>
37 : class ProductOf2Maps;
38 : class SphericalToCartesianPfaffian;
39 : } // namespace CoordinateMaps
40 :
41 : template <typename SourceFrame, typename TargetFrame, typename... Maps>
42 : class CoordinateMap;
43 : } // namespace domain
44 : /// \endcond
45 :
46 : namespace domain::creators {
47 : /// \brief A set of concentric spherical shells
48 : ///
49 : /// \note This domain will use a spherical harmonic basis in the angular
50 : /// directions. It cannot be used with subcell.
51 : ///
52 : /// \see Sphere for a spherical domain compatible with subcell
53 : ///
54 : /// Setting the inner radius to $0$ will set the inner-most element to be a
55 : /// filled sphere.
56 : ///
57 : /// This domain creator offers one grid anchor "Center" at the origin.
58 : ///
59 : /// #### Time dependent maps
60 : /// There are two ways to add time dependent maps to the SphericalShells domain
61 : /// creator. In the input file, these are specified under the
62 : /// `TimeDependentMaps:` block.
63 : ///
64 : /// ##### TimeDependence
65 : /// You can use a simple TimeDependence (e.g.
66 : /// `domain::creators::time_dependence::UniformTranslation` or
67 : /// `domain::creators::time_dependence::RotationAboutZAxis`) to add time
68 : /// dependent maps. This method will add the same maps to all blocks in the
69 : /// domain.
70 : ///
71 : /// ##### Hard-coded time dependent maps
72 : /// The SphericalShells domain creator also has the option to use some hard
73 : /// coded time dependent maps that may be useful in certain scenarios. This
74 : /// method adds the maps in `domain::creators::sphere::TimeDependentMapOptions`
75 : /// to the domain. Hard-coded time-dependent maps are currently supported only
76 : /// for excised domains, i.e. when `InnerRadius` is positive. When a shape map
77 : /// is specified, the innermost radial shell uses it by default, while
78 : /// subsequent shells have maps only between `Frame::Grid` and
79 : /// `Frame::Inertial`. The `NumberOfRadialShellsWithShapeMap` option can add
80 : /// distorted-frame maps to more inner shells. For domains with multiple radial
81 : /// shells, the final radial shell cannot use the shape map. With only one
82 : /// radial shell, the shape map rolls off at the outer boundary.
83 : ///
84 : /// ##### None
85 : /// To not have any time dependent maps, pass a `std::nullopt` as the
86 : /// appropriate argument in the constructor. In the input file, simply have
87 : /// `TimeDependentMaps: None`.
88 1 : class SphericalShells : public DomainCreator<3> {
89 : public:
90 0 : using maps_list =
91 : tmpl::append<tmpl::list<domain::CoordinateMap<
92 : Frame::BlockLogical, Frame::Inertial,
93 : domain::CoordinateMaps::ProductOf2Maps<
94 : domain::CoordinateMaps::Interval,
95 : domain::CoordinateMaps::Identity<2>>,
96 : domain::CoordinateMaps::SphericalToCartesianPfaffian>>,
97 : typename sphere::TimeDependentMapOptions::maps_list>;
98 :
99 : /*!
100 : * \brief Radius of innermost spherical shell
101 : */
102 1 : struct InnerRadius {
103 0 : using type = double;
104 0 : static constexpr Options::String help = {
105 : "Inner radius of the spherical shells. If set to 0, the innermost "
106 : "element with be a B3 in which case the inner boundary condition is "
107 : "not used"};
108 : };
109 :
110 : /*!
111 : * \brief Radius of outer boundary
112 : */
113 1 : struct OuterRadius {
114 0 : using type = double;
115 0 : static constexpr Options::String help = {
116 : "Outer radius of the spherical shells."};
117 : };
118 :
119 : /*!
120 : * \brief Initial refinement in radial direction
121 : */
122 1 : struct InitialRadialRefinement {
123 0 : using type = size_t;
124 0 : static constexpr Options::String help = {
125 : "Initial radial refinement level."};
126 : };
127 :
128 : /*!
129 : * \brief Initial number of radial grid points
130 : */
131 1 : struct InitialNumberOfRadialGridPoints {
132 0 : using type = size_t;
133 0 : static constexpr Options::String help = {
134 : "Initial number of radial grid points."};
135 : };
136 :
137 : /*!
138 : * \brief Initial spherical harmonic resolution
139 : */
140 1 : struct InitialSphericalHarmonicL {
141 0 : using type = size_t;
142 0 : static size_t lower_bound() { return 6; }
143 0 : static constexpr Options::String help = {
144 : "Initial spherical harmonic resolution specified as the highest "
145 : "spherical harmonic represented on the grid. Minimum value is 6."};
146 : };
147 :
148 : /*!
149 : * \brief Radial coordinates of the boundaries splitting elements
150 : */
151 1 : struct RadialPartitioning {
152 0 : using type = std::vector<double>;
153 0 : static constexpr Options::String help = {
154 : "Radial coordinates of the boundaries splitting the spherical shell "
155 : "between InnerRadius and OuterRadius. They must be given in ascending "
156 : "order. This should be used if boundaries need to be set at specific "
157 : "radii. If the number but not the specific locations of the boundaries "
158 : "are important, use InitialRefinement instead."};
159 : };
160 :
161 : /*!
162 : * \brief Distributions to apply to the radial coordinates
163 : */
164 1 : struct RadialDistribution {
165 0 : using type =
166 : std::variant<domain::CoordinateMaps::Distribution,
167 : std::vector<domain::CoordinateMaps::Distribution>>;
168 0 : static constexpr Options::String help = {
169 : "Select the radial distribution of grid points in each spherical "
170 : "shell. There must be N+1 radial distributions specified for N radial "
171 : "partitions. You can also specify just a single radial distribution "
172 : "(not in a vector) which will use the same distribution for all "
173 : "partitions."};
174 : };
175 :
176 0 : using TimeDepOptionType = std::variant<
177 : sphere::TimeDependentMapOptions,
178 : std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>>;
179 :
180 : /*!
181 : * \brief Time dependence of the domain
182 : */
183 1 : struct TimeDependentMaps {
184 0 : using type = Options::Auto<TimeDepOptionType, Options::AutoLabel::None>;
185 0 : static constexpr Options::String help = {
186 : "The options for time dependent maps. This can either be a "
187 : "TimeDependence or hard coded time dependent options. Specify `None` "
188 : "for no time dependent maps."};
189 : };
190 :
191 : /*!
192 : * \brief Boundary condition to apply to inner boundary when not filled
193 : */
194 : template <typename BoundaryConditionsBase>
195 1 : struct InnerBoundaryCondition {
196 0 : static constexpr Options::String help =
197 : "Options for the boundary conditions at the inner radius.";
198 0 : using type = Options::Auto<std::unique_ptr<BoundaryConditionsBase>,
199 : Options::AutoLabel::None>;
200 : };
201 :
202 : /*!
203 : * \brief Boundary condition to apply to outer boundary
204 : */
205 : template <typename BoundaryConditionsBase>
206 1 : struct OuterBoundaryCondition {
207 0 : static constexpr Options::String help =
208 : "Options for the boundary conditions at the outer radius.";
209 0 : using type = std::unique_ptr<BoundaryConditionsBase>;
210 : };
211 :
212 0 : using basic_options =
213 : tmpl::list<InnerRadius, OuterRadius, InitialRadialRefinement,
214 : InitialNumberOfRadialGridPoints, InitialSphericalHarmonicL,
215 : RadialPartitioning, RadialDistribution, TimeDependentMaps>;
216 :
217 : template <typename Metavariables>
218 0 : using options = tmpl::conditional_t<
219 : domain::BoundaryConditions::has_boundary_conditions_base_v<
220 : typename Metavariables::system>,
221 : tmpl::push_back<
222 : basic_options,
223 : InnerBoundaryCondition<
224 : domain::BoundaryConditions::get_boundary_conditions_base<
225 : typename Metavariables::system>>,
226 : OuterBoundaryCondition<
227 : domain::BoundaryConditions::get_boundary_conditions_base<
228 : typename Metavariables::system>>>,
229 : basic_options>;
230 :
231 0 : static constexpr Options::String help{
232 : "An optional B3 surrounded by a set of concentric spherical shells "
233 : "centered at the origin."};
234 :
235 0 : SphericalShells(
236 : double inner_radius, double outer_radius,
237 : size_t initial_radial_refinement,
238 : size_t initial_number_of_radial_grid_points,
239 : size_t initial_spherical_harmonic_l,
240 : std::vector<double> radial_partitioning = {},
241 : const typename RadialDistribution::type& radial_distribution =
242 : domain::CoordinateMaps::Distribution::Linear,
243 : std::optional<TimeDepOptionType> time_dependent_options = std::nullopt,
244 : std::optional<
245 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>>
246 : inner_boundary_condition = std::nullopt,
247 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
248 : outer_boundary_condition = nullptr,
249 : const Options::Context& context = {});
250 :
251 0 : SphericalShells() = default;
252 0 : SphericalShells(const SphericalShells&) = delete;
253 0 : SphericalShells(SphericalShells&&) = default;
254 0 : SphericalShells& operator=(const SphericalShells&) = delete;
255 0 : SphericalShells& operator=(SphericalShells&&) = default;
256 0 : ~SphericalShells() override = default;
257 :
258 0 : Domain<3> create_domain() const override;
259 :
260 : /// A single grid anchor "Center" at the origin.
261 : std::unordered_map<std::string, tnsr::I<double, 3, Frame::Grid>>
262 1 : grid_anchors() const override;
263 :
264 : std::vector<DirectionMap<
265 : 3, std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>>>
266 1 : external_boundary_conditions() const override;
267 :
268 1 : std::vector<std::array<size_t, 3>> initial_extents() const override;
269 :
270 1 : std::vector<std::array<size_t, 3>> initial_refinement_levels() const override;
271 :
272 : /// The block names are Shell0, Shell1, ..., starting with the innermost
273 : /// Block.
274 1 : std::vector<std::string> block_names() const override;
275 :
276 : /// The block groups are Shell0, Shell1, ..., starting with the innermost
277 : /// Block.
278 : std::unordered_map<std::string, std::unordered_set<std::string>>
279 1 : block_groups() const override;
280 :
281 1 : auto functions_of_time(const std::unordered_map<std::string, double>&
282 : initial_expiration_times = {}) const
283 : -> std::unordered_map<
284 : std::string,
285 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>> override;
286 :
287 : private:
288 0 : double inner_radius_{};
289 0 : double outer_radius_{};
290 0 : size_t initial_radial_refinement_{};
291 0 : size_t initial_number_of_radial_grid_points_{};
292 0 : bool excise_center_{};
293 0 : size_t initial_spherical_harmonic_l_{};
294 0 : std::vector<double> radial_partitioning_{};
295 0 : std::vector<domain::CoordinateMaps::Distribution> radial_distribution_{};
296 0 : std::optional<TimeDepOptionType> time_dependent_options_{};
297 0 : bool use_hard_coded_maps_{false};
298 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
299 0 : inner_boundary_condition_{};
300 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
301 0 : outer_boundary_condition_{};
302 0 : size_t num_blocks_{};
303 0 : std::vector<std::string> block_names_{};
304 : std::unordered_map<std::string, std::unordered_set<std::string>>
305 0 : block_groups_{};
306 : std::unordered_map<std::string, tnsr::I<double, 3, Frame::Grid>>
307 0 : grid_anchors_{};
308 : };
309 : } // namespace domain::creators
|