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 : /// This domain creator offers one grid anchor "Center" at the origin.
55 : ///
56 : /// #### Time dependent maps
57 : /// There are two ways to add time dependent maps to the SphericalShells domain
58 : /// creator. In the input file, these are specified under the
59 : /// `TimeDependentMaps:` block.
60 : ///
61 : /// ##### TimeDependence
62 : /// You can use a simple TimeDependence (e.g.
63 : /// `domain::creators::time_dependence::UniformTranslation` or
64 : /// `domain::creators::time_dependence::RotationAboutZAxis`) to add time
65 : /// dependent maps. This method will add the same maps to all blocks in the
66 : /// domain.
67 : ///
68 : /// ##### Hard-coded time dependent maps
69 : /// The SphericalShells domain creator also has the option to use some hard
70 : /// coded time dependent maps that may be useful in certain scenarios. This
71 : /// method adds the maps in `domain::creators::sphere::TimeDependentMapOptions`
72 : /// to the domain. Currently, the first (inner-most) shell has maps between
73 : /// `Frame::Grid`, `Frame::Distorted`, and `Frame::Inertial` while all
74 : /// subsequent shells only have maps between `Frame::Grid` and
75 : /// `Frame::Inertial`.
76 : ///
77 : /// ##### None
78 : /// To not have any time dependent maps, pass a `std::nullopt` as the
79 : /// appropriate argument in the constructor. In the input file, simply have
80 : /// `TimeDependentMaps: None`.
81 1 : class SphericalShells : public DomainCreator<3> {
82 : public:
83 0 : using maps_list =
84 : tmpl::append<tmpl::list<domain::CoordinateMap<
85 : Frame::BlockLogical, Frame::Inertial,
86 : domain::CoordinateMaps::ProductOf2Maps<
87 : domain::CoordinateMaps::Interval,
88 : domain::CoordinateMaps::Identity<2>>,
89 : domain::CoordinateMaps::SphericalToCartesianPfaffian>>,
90 : typename sphere::TimeDependentMapOptions::maps_list>;
91 :
92 0 : struct InnerRadius {
93 0 : using type = double;
94 0 : static constexpr Options::String help = {
95 : "Inner radius of the spherical shells."};
96 : };
97 :
98 0 : struct OuterRadius {
99 0 : using type = double;
100 0 : static constexpr Options::String help = {
101 : "Outer radius of the spherical shells."};
102 : };
103 :
104 0 : struct InitialRadialRefinement {
105 0 : using type = size_t;
106 0 : static constexpr Options::String help = {
107 : "Initial radial refinement level."};
108 : };
109 :
110 0 : struct InitialNumberOfRadialGridPoints {
111 0 : using type = size_t;
112 0 : static constexpr Options::String help = {
113 : "Initial number of radial grid points."};
114 : };
115 :
116 0 : struct InitialSphericalHarmonicL {
117 0 : using type = size_t;
118 0 : static size_t lower_bound() { return 6; }
119 0 : static constexpr Options::String help = {
120 : "Initial spherical harmonic resolution specified as the highest "
121 : "spherical harmonic represented on the grid. Minimum value is 6."};
122 : };
123 :
124 0 : struct RadialPartitioning {
125 0 : using type = std::vector<double>;
126 0 : static constexpr Options::String help = {
127 : "Radial coordinates of the boundaries splitting the spherical shell "
128 : "between InnerRadius and OuterRadius. They must be given in ascending "
129 : "order. This should be used if boundaries need to be set at specific "
130 : "radii. If the number but not the specific locations of the boundaries "
131 : "are important, use InitialRefinement instead."};
132 : };
133 :
134 0 : struct RadialDistribution {
135 0 : using type =
136 : std::variant<domain::CoordinateMaps::Distribution,
137 : std::vector<domain::CoordinateMaps::Distribution>>;
138 0 : static constexpr Options::String help = {
139 : "Select the radial distribution of grid points in each spherical "
140 : "shell. There must be N+1 radial distributions specified for N radial "
141 : "partitions. You can also specify just a single radial distribution "
142 : "(not in a vector) which will use the same distribution for all "
143 : "partitions."};
144 : };
145 :
146 0 : using TimeDepOptionType = std::variant<
147 : sphere::TimeDependentMapOptions,
148 : std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>>;
149 :
150 0 : struct TimeDependentMaps {
151 0 : using type = Options::Auto<TimeDepOptionType, Options::AutoLabel::None>;
152 0 : static constexpr Options::String help = {
153 : "The options for time dependent maps. This can either be a "
154 : "TimeDependence or hard coded time dependent options. Specify `None` "
155 : "for no time dependent maps."};
156 : };
157 :
158 : template <typename BoundaryConditionsBase>
159 0 : struct InnerBoundaryCondition {
160 0 : static constexpr Options::String help =
161 : "Options for the boundary conditions at the inner radius.";
162 0 : using type = std::unique_ptr<BoundaryConditionsBase>;
163 : };
164 :
165 : template <typename BoundaryConditionsBase>
166 0 : struct OuterBoundaryCondition {
167 0 : static constexpr Options::String help =
168 : "Options for the boundary conditions at the outer radius.";
169 0 : using type = std::unique_ptr<BoundaryConditionsBase>;
170 : };
171 :
172 0 : using basic_options =
173 : tmpl::list<InnerRadius, OuterRadius, InitialRadialRefinement,
174 : InitialNumberOfRadialGridPoints, InitialSphericalHarmonicL,
175 : RadialPartitioning, RadialDistribution, TimeDependentMaps>;
176 :
177 : template <typename Metavariables>
178 0 : using options = tmpl::conditional_t<
179 : domain::BoundaryConditions::has_boundary_conditions_base_v<
180 : typename Metavariables::system>,
181 : tmpl::push_back<
182 : basic_options,
183 : InnerBoundaryCondition<
184 : domain::BoundaryConditions::get_boundary_conditions_base<
185 : typename Metavariables::system>>,
186 : OuterBoundaryCondition<
187 : domain::BoundaryConditions::get_boundary_conditions_base<
188 : typename Metavariables::system>>>,
189 : basic_options>;
190 :
191 0 : static constexpr Options::String help{
192 : "A set of concentric spherical shells centered at the origin."};
193 :
194 0 : SphericalShells(
195 : double inner_radius, double outer_radius,
196 : size_t initial_radial_refinement,
197 : size_t initial_number_of_radial_grid_points,
198 : size_t initial_spherical_harmonic_l,
199 : std::vector<double> radial_partitioning = {},
200 : const typename RadialDistribution::type& radial_distribution =
201 : domain::CoordinateMaps::Distribution::Linear,
202 : std::optional<TimeDepOptionType> time_dependent_options = std::nullopt,
203 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
204 : inner_boundary_condition = nullptr,
205 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
206 : outer_boundary_condition = nullptr,
207 : const Options::Context& context = {});
208 :
209 0 : SphericalShells() = default;
210 0 : SphericalShells(const SphericalShells&) = delete;
211 0 : SphericalShells(SphericalShells&&) = default;
212 0 : SphericalShells& operator=(const SphericalShells&) = delete;
213 0 : SphericalShells& operator=(SphericalShells&&) = default;
214 0 : ~SphericalShells() override = default;
215 :
216 0 : Domain<3> create_domain() const override;
217 :
218 : /// A single grid anchor "Center" at the origin.
219 : std::unordered_map<std::string, tnsr::I<double, 3, Frame::Grid>>
220 1 : grid_anchors() const override;
221 :
222 : std::vector<DirectionMap<
223 : 3, std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>>>
224 1 : external_boundary_conditions() const override;
225 :
226 1 : std::vector<std::array<size_t, 3>> initial_extents() const override;
227 :
228 1 : std::vector<std::array<size_t, 3>> initial_refinement_levels() const override;
229 :
230 : /// The block names are Shell0, Shell1, ..., starting with the innermost
231 : /// Block.
232 1 : std::vector<std::string> block_names() const override;
233 :
234 : /// The block groups are Shell0, Shell1, ..., starting with the innermost
235 : /// Block.
236 : std::unordered_map<std::string, std::unordered_set<std::string>>
237 1 : block_groups() const override;
238 :
239 1 : auto functions_of_time(const std::unordered_map<std::string, double>&
240 : initial_expiration_times = {}) const
241 : -> std::unordered_map<
242 : std::string,
243 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>> override;
244 :
245 : private:
246 0 : double inner_radius_{};
247 0 : double outer_radius_{};
248 0 : size_t initial_radial_refinement_{};
249 0 : size_t initial_number_of_radial_grid_points_{};
250 0 : size_t initial_spherical_harmonic_l_{};
251 0 : std::vector<double> radial_partitioning_{};
252 0 : std::vector<domain::CoordinateMaps::Distribution> radial_distribution_{};
253 0 : std::optional<TimeDepOptionType> time_dependent_options_{};
254 0 : bool use_hard_coded_maps_{false};
255 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
256 0 : inner_boundary_condition_{};
257 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
258 0 : outer_boundary_condition_{};
259 0 : size_t num_blocks_{};
260 0 : std::vector<std::string> block_names_{};
261 : std::unordered_map<std::string, std::unordered_set<std::string>>
262 0 : block_groups_{};
263 : std::unordered_map<std::string, tnsr::I<double, 3, Frame::Grid>>
264 0 : grid_anchors_{};
265 : };
266 : } // namespace domain::creators
|