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 <limits>
8 : #include <memory>
9 : #include <optional>
10 : #include <string>
11 : #include <type_traits>
12 : #include <variant>
13 :
14 : #include "Domain/CoordinateMaps/CoordinateMap.hpp"
15 : #include "Domain/CoordinateMaps/Identity.hpp"
16 : #include "Domain/CoordinateMaps/TimeDependent/RotScaleTrans.hpp"
17 : #include "Domain/CoordinateMaps/TimeDependent/Shape.hpp"
18 : #include "Domain/CoordinateMaps/TimeDependent/Translation.hpp"
19 : #include "Domain/Creators/TimeDependentOptions/ExpansionMap.hpp"
20 : #include "Domain/Creators/TimeDependentOptions/RotationMap.hpp"
21 : #include "Domain/Creators/TimeDependentOptions/ShapeMap.hpp"
22 : #include "Domain/Creators/TimeDependentOptions/TranslationMap.hpp"
23 : #include "Domain/FunctionsOfTime/FunctionOfTime.hpp"
24 : #include "Domain/Structure/ObjectLabel.hpp"
25 : #include "Options/Auto.hpp"
26 : #include "Options/String.hpp"
27 : #include "Utilities/TMPL.hpp"
28 :
29 : /// \cond
30 : namespace Frame {
31 : struct Grid;
32 : struct Distorted;
33 : struct Inertial;
34 : } // namespace Frame
35 : /// \endcond
36 :
37 0 : namespace domain::creators::sphere {
38 : /*!
39 : * \brief This holds all options related to the time dependent maps of the
40 : * domain::creators::Sphere domain creator.
41 : */
42 1 : struct TimeDependentMapOptions {
43 : private:
44 : template <typename SourceFrame, typename TargetFrame>
45 0 : using MapType =
46 : std::unique_ptr<domain::CoordinateMapBase<SourceFrame, TargetFrame, 3>>;
47 0 : using IdentityMap = domain::CoordinateMaps::Identity<3>;
48 : // Time-dependent maps
49 0 : using ShapeMap = domain::CoordinateMaps::TimeDependent::Shape;
50 0 : using RotScaleTransMap =
51 : domain::CoordinateMaps::TimeDependent::RotScaleTrans<3>;
52 :
53 : template <typename SourceFrame, typename TargetFrame>
54 0 : using IdentityForComposition =
55 : domain::CoordinateMap<SourceFrame, TargetFrame, IdentityMap>;
56 0 : using GridToDistortedComposition =
57 : domain::CoordinateMap<Frame::Grid, Frame::Distorted, ShapeMap>;
58 0 : using GridToInertialComposition =
59 : domain::CoordinateMap<Frame::Grid, Frame::Inertial, ShapeMap,
60 : RotScaleTransMap>;
61 0 : using GridToInertialSimple =
62 : domain::CoordinateMap<Frame::Grid, Frame::Inertial, RotScaleTransMap>;
63 0 : using DistortedToInertialComposition =
64 : domain::CoordinateMap<Frame::Distorted, Frame::Inertial,
65 : RotScaleTransMap>;
66 0 : using GridToInertialShapeMap =
67 : domain::CoordinateMap<Frame::Grid, Frame::Inertial, ShapeMap>;
68 :
69 : public:
70 0 : using maps_list =
71 : tmpl::list<IdentityForComposition<Frame::Grid, Frame::Inertial>,
72 : IdentityForComposition<Frame::Grid, Frame::Distorted>,
73 : IdentityForComposition<Frame::Distorted, Frame::Inertial>,
74 : GridToDistortedComposition, GridToInertialShapeMap,
75 : GridToInertialSimple, GridToInertialComposition,
76 : DistortedToInertialComposition>;
77 :
78 : /// \brief The initial time of the functions of time.
79 1 : struct InitialTime {
80 0 : using type = double;
81 0 : static constexpr Options::String help = {
82 : "The initial time of the functions of time"};
83 : };
84 :
85 0 : using ShapeMapOptions =
86 : time_dependent_options::ShapeMapOptions<false, domain::ObjectLabel::None>;
87 0 : using ShapeMapOptionType = typename ShapeMapOptions::type::value_type;
88 :
89 0 : using RotationMapOptions = time_dependent_options::RotationMapOptions<true>;
90 0 : using RotationMapOptionType = typename RotationMapOptions::type::value_type;
91 :
92 0 : using ExpansionMapOptions = time_dependent_options::ExpansionMapOptions<true>;
93 0 : using ExpansionMapOptionType = typename ExpansionMapOptions::type::value_type;
94 :
95 0 : using TranslationMapOptions =
96 : time_dependent_options::TranslationMapOptions<3>;
97 0 : using TranslationMapOptionType =
98 : typename TranslationMapOptions::type::value_type;
99 :
100 0 : struct TransitionRotScaleTrans {
101 0 : using type = bool;
102 0 : static constexpr Options::String help = {
103 : "Transition rotation, expansion, and translation to zero in the outer "
104 : "shell"};
105 : };
106 :
107 0 : struct NumberOfRadialShellsWithShapeMap {
108 0 : using type = Options::Auto<size_t>;
109 0 : static constexpr Options::String help = {
110 : "Number of innermost radial shells that use the shape map. This must "
111 : "be at least one. A filled Sphere with multiple radial shells requires "
112 : "at least two shells with a shape map. For any domain with multiple "
113 : "radial shells, at least one outer shell must remain without a shape "
114 : "map. Specify 'Auto' to use the default for the domain."};
115 : };
116 :
117 0 : using options =
118 : tmpl::list<InitialTime, ShapeMapOptions, RotationMapOptions,
119 : ExpansionMapOptions, TranslationMapOptions,
120 : TransitionRotScaleTrans, NumberOfRadialShellsWithShapeMap>;
121 0 : static constexpr Options::String help{
122 : "The options for all the hard-coded time dependent maps in the "
123 : "Sphere domain."};
124 :
125 0 : TimeDependentMapOptions() = default;
126 :
127 0 : TimeDependentMapOptions(
128 : double initial_time, ShapeMapOptionType shape_map_options,
129 : RotationMapOptionType rotation_map_options,
130 : ExpansionMapOptionType expansion_map_options,
131 : TranslationMapOptionType translation_map_options,
132 : bool transition_rot_scale_trans,
133 : std::optional<size_t> number_of_radial_shells_with_shape_map);
134 :
135 : /*!
136 : * \brief Create the function of time map using the options that were
137 : * provided to this class.
138 : *
139 : * Currently, this will add:
140 : *
141 : * - Size: `PiecewisePolynomial<3>`
142 : * - Shape: `PiecewisePolynomial<2>`
143 : * - Rotation: `SettleToConstantQuaternion`
144 : * - Expansion: `SettleToConstant`
145 : * - ExpansionOuterBoundary: `PiecewisePolynomial<2>`
146 : * - Translation: `PiecewisePolynomial<2>`
147 : */
148 : std::unordered_map<std::string,
149 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>
150 1 : create_functions_of_time(const std::unordered_map<std::string, double>&
151 : initial_expiration_times) const;
152 :
153 : /*!
154 : * \brief Construct the actual maps that will be used.
155 : *
156 : * Currently, this constructs a:
157 : *
158 : * - Shape: `Shape` (with a size function of time)
159 : * - Rotation: `Rotation`
160 : * - Expansion: `Expansion`
161 : * - Expansion outside the transition region: `ExpansionOuterBoundary`
162 : * - Translation: `Translation`
163 : */
164 1 : void build_maps(const std::array<double, 3>& center, bool is_filled,
165 : double inner_radius,
166 : const std::vector<double>& radial_partitions,
167 : double outer_radius);
168 :
169 : /*!
170 : * \brief This will construct the map from `Frame::Distorted` to
171 : * `Frame::Inertial`.
172 : *
173 : * For blocks with a shape map, this will be a RotScaleTrans map. For other
174 : * blocks, this returns `nullptr`.
175 : *
176 : * \param radial_shell Zero-based index specifying a shell in the `Sphere`
177 : * or `SphericalShells` domain, starting at the innermost shell.
178 : * \param is_inner_cube Whether the block is the central cube of a filled
179 : * sphere.
180 : */
181 1 : MapType<Frame::Distorted, Frame::Inertial> distorted_to_inertial_map(
182 : size_t radial_shell, bool is_inner_cube) const;
183 :
184 : /*!
185 : * \brief This will construct the map from `Frame::Grid` to
186 : * `Frame::Distorted`.
187 : *
188 : * For blocks with a shape map, this will return the `Shape` map (with a size
189 : * function of time). For other blocks, this returns `nullptr`.
190 : *
191 : * \param radial_shell Zero-based index specifying a shell in the `Sphere`
192 : * or `SphericalShells` domain, starting at the innermost shell.
193 : * \param shape_map_index Index of the wedge direction in the order returned
194 : * by `orientations_for_sphere_wrappings`. This is only used for filled
195 : * spheres. In that case, the implementation uses the Wedge transition
196 : * function and builds two sets of shape maps for the six canonical wedge
197 : * directions: indices 0..5 deform the innermost shell and indices 6..11 roll
198 : * off the deformation in outer shells. If the sphere is not filled, then
199 : * the implementation uses the SphereTransition function and builds only one
200 : * shape map, leaving this option unused.
201 : * \param is_inner_cube Whether the block is the central cube of a filled
202 : * sphere.
203 : */
204 1 : MapType<Frame::Grid, Frame::Distorted> grid_to_distorted_map(
205 : size_t radial_shell, size_t shape_map_index, bool is_inner_cube) const;
206 :
207 : /*!
208 : * \brief This will construct the map from `Frame::Grid` to `Frame::Inertial`.
209 : *
210 : * For blocks with a shape map, this will return the `Shape` and
211 : * `RotScaleTrans` composition. For other blocks, this returns just the
212 : * `RotScaleTrans` map. In the outer shell, the `RotScaleTrans` map will
213 : * transition to zero.
214 : *
215 : * \param radial_shell Zero-based index specifying a shell in the `Sphere`
216 : * or `SphericalShells` domain, starting at the innermost shell.
217 : * \param shape_map_index Index of the wedge direction in the order returned
218 : * by `orientations_for_sphere_wrappings`. This is only used for filled
219 : * spheres. In that case, the implementation uses the Wedge transition
220 : * function and builds two sets of shape maps for the six canonical wedge
221 : * directions: indices 0..5 deform the innermost shell and indices 6..11 roll
222 : * off the deformation in outer shells. If the sphere is not filled, then
223 : * the implementation uses the SphereTransition function and builds only one
224 : * shape map, leaving this option unused.
225 : * \param is_outer_shell Whether the block is in the outermost radial shell.
226 : * \param is_central_region Whether the map is for the central cube of a
227 : * filled sphere or the excision boundary of an excised sphere.
228 : */
229 1 : MapType<Frame::Grid, Frame::Inertial> grid_to_inertial_map(
230 : size_t radial_shell, size_t shape_map_index, bool is_outer_shell,
231 : bool is_central_region) const;
232 :
233 : /*!
234 : * \brief Whether or not the distorted frame is being used. I.e. whether or
235 : * not shape map options were specified.
236 : */
237 1 : bool using_distorted_frame() const;
238 :
239 0 : inline static const std::string size_name{"Size"};
240 0 : inline static const std::string shape_name{"Shape"};
241 0 : inline static const std::string rotation_name{"Rotation"};
242 0 : inline static const std::string expansion_name{"Expansion"};
243 0 : inline static const std::string expansion_outer_boundary_name{
244 : "ExpansionOuterBoundary"};
245 0 : inline static const std::string translation_name{"Translation"};
246 :
247 : private:
248 0 : double initial_time_{std::numeric_limits<double>::signaling_NaN()};
249 0 : bool filled_{false};
250 0 : double deformed_radius_{std::numeric_limits<double>::signaling_NaN()};
251 0 : std::array<ShapeMap, 12> shape_maps_{};
252 0 : RotScaleTransMap inner_rot_scale_trans_map_{};
253 0 : RotScaleTransMap transition_rot_scale_trans_map_{};
254 :
255 0 : ShapeMapOptionType shape_map_options_;
256 0 : RotationMapOptionType rotation_map_options_;
257 0 : ExpansionMapOptionType expansion_map_options_;
258 0 : TranslationMapOptionType translation_map_options_;
259 0 : bool transition_rot_scale_trans_{false};
260 0 : std::optional<size_t> number_of_radial_shells_with_shape_map_{};
261 : };
262 : } // namespace domain::creators::sphere
|