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 <limits>
9 : #include <memory>
10 : #include <optional>
11 : #include <string>
12 : #include <unordered_map>
13 : #include <vector>
14 :
15 : #include "Domain/CoordinateMaps/CoordinateMap.hpp"
16 : #include "Domain/CoordinateMaps/Identity.hpp"
17 : #include "Domain/CoordinateMaps/TimeDependent/CubicScale.hpp"
18 : #include "Domain/CoordinateMaps/TimeDependent/ProductMaps.hpp"
19 : #include "Domain/CoordinateMaps/TimeDependent/Rotation.hpp"
20 : #include "Domain/Creators/TimeDependence/GenerateCoordinateMap.hpp"
21 : #include "Domain/Creators/TimeDependence/TimeDependence.hpp"
22 : #include "Options/String.hpp"
23 : #include "Utilities/ErrorHandling/Assert.hpp"
24 : #include "Utilities/PrettyType.hpp"
25 : #include "Utilities/TMPL.hpp"
26 :
27 : /// \cond
28 : namespace domain::FunctionsOfTime {
29 : class FunctionOfTime;
30 : } // namespace domain::FunctionsOfTime
31 : namespace domain {
32 : template <typename SourceFrame, typename TargetFrame, typename... Maps>
33 : class CoordinateMap;
34 : } // namespace domain
35 :
36 : namespace Frame {
37 : struct Distorted;
38 : struct Grid;
39 : struct Inertial;
40 : } // namespace Frame
41 : /// \endcond
42 :
43 : namespace domain::creators::time_dependence {
44 : /*!
45 : * \brief Cubic scaling, followed by uniform rotation about the \f$z\f$ axis:
46 : * \f{eqnarray*}
47 : * x &\to& x \cos \alpha(t) - y \sin \alpha(t)\text{,} \\
48 : * y &\to& x \sin \alpha(t) + y \cos \alpha(t)\text{,}
49 : * \f}
50 : * where \f$\alpha(t)\f$ is a `domain::FunctionsOfTime::FunctionOfTime`. For 3
51 : * spatial dimensions, \f$z \to z\f$, and the rotation is implemented as a
52 : * product of the 2D rotation and an identity map. The rotation is undefined
53 : * (and therefore unimplemented here) for 1 spatial dimension.
54 : *
55 : * The expansion is done by the
56 : * `domain::CoordinateMaps::TimeDependent::CubicScale` map. A linear
57 : * radial scaling can be used by specifying the `UseLinearScaling` bool.
58 : *
59 : * For this map, the cubic scaling goes from the grid frame to the distorted
60 : * frame, and the rotation goes from the distorted frame to the inertial frame.
61 : * This was chosen as a way of testing composed maps in the distorted frame.
62 : */
63 : template <size_t MeshDim>
64 1 : class ScalingAndZRotation final : public TimeDependence<MeshDim> {
65 : static_assert(
66 : MeshDim > 1,
67 : "ScalingAndZRotation<MeshDim> undefined for MeshDim == 1");
68 :
69 : private:
70 0 : using Identity = domain::CoordinateMaps::Identity<1>;
71 0 : using Rotation = domain::CoordinateMaps::TimeDependent::Rotation<2>;
72 0 : using Rotation3D =
73 : domain::CoordinateMaps::TimeDependent::ProductOf2Maps<Rotation, Identity>;
74 0 : using CubicScaleMap =
75 : domain::CoordinateMaps::TimeDependent::CubicScale<MeshDim>;
76 :
77 : public:
78 0 : using maps_list = tmpl::flatten<tmpl::list<
79 : domain::CoordinateMap<Frame::Grid, Frame::Distorted, CubicScaleMap>,
80 : tmpl::conditional_t<
81 : MeshDim == 2,
82 : tmpl::list<domain::CoordinateMap<Frame::Distorted, Frame::Inertial,
83 : Rotation>,
84 : domain::CoordinateMap<Frame::Grid, Frame::Inertial,
85 : CubicScaleMap, Rotation>>,
86 : tmpl::list<domain::CoordinateMap<Frame::Distorted, Frame::Inertial,
87 : Rotation3D>,
88 : domain::CoordinateMap<Frame::Grid, Frame::Inertial,
89 : CubicScaleMap, Rotation3D>>>>>;
90 :
91 0 : static constexpr size_t mesh_dim = MeshDim;
92 :
93 : /// \brief The initial time of the function of time.
94 1 : struct InitialTime {
95 0 : using type = double;
96 0 : static constexpr Options::String help = {
97 : "The initial time of the function of time"};
98 : };
99 : /// \brief The \f$x\f$-, \f$y\f$-, and \f$z\f$-velocity.
100 1 : struct AngularVelocity {
101 0 : using type = double;
102 0 : static constexpr Options::String help = {
103 : "The angular velocity of the map."};
104 : };
105 :
106 : /// \brief The outer boundary or pivot point of the
107 : /// `domain::CoordinateMaps::TimeDependent::CubicScale` map
108 1 : struct OuterBoundary {
109 0 : using type = double;
110 0 : static constexpr Options::String help = {
111 : "Outer boundary or pivot point of the map"};
112 : };
113 : /// \brief The initial values of the expansion factors.
114 1 : struct InitialExpansion {
115 0 : using type = std::array<double, 2>;
116 0 : static constexpr Options::String help = {
117 : "Expansion values at initial time."};
118 : };
119 : /// \brief The velocity of the expansion factors.
120 1 : struct Velocity {
121 0 : using type = std::array<double, 2>;
122 0 : static constexpr Options::String help = {"The rate of expansion."};
123 : };
124 : /// \brief The acceleration of the expansion factors.
125 1 : struct Acceleration {
126 0 : using type = std::array<double, 2>;
127 0 : static constexpr Options::String help = {"The acceleration of expansion."};
128 : };
129 : /// \brief Whether to use linear scaling or cubic scaling.
130 1 : struct UseLinearScaling {
131 0 : using type = bool;
132 0 : static constexpr Options::String help = {
133 : "Whether or not to turn on cubic scaling."};
134 : };
135 :
136 0 : using GridToInertialMap = detail::generate_coordinate_map_t<
137 : Frame::Grid, Frame::Inertial,
138 : tmpl::list<CubicScaleMap,
139 : tmpl::conditional_t<MeshDim == 2, Rotation,
140 : domain::CoordinateMaps::TimeDependent::
141 : ProductOf2Maps<Rotation, Identity>>>>;
142 0 : using GridToDistortedMap =
143 : domain::CoordinateMap<Frame::Grid, Frame::Distorted, CubicScaleMap>;
144 :
145 0 : using DistortedToInertialMap = detail::generate_coordinate_map_t<
146 : Frame::Distorted, Frame::Inertial,
147 : tmpl::list<tmpl::conditional_t<MeshDim == 2, Rotation,
148 : domain::CoordinateMaps::TimeDependent::
149 : ProductOf2Maps<Rotation, Identity>>>>;
150 0 : using options =
151 : tmpl::list<InitialTime, AngularVelocity, OuterBoundary, UseLinearScaling,
152 : InitialExpansion, Velocity, Acceleration>;
153 :
154 0 : static constexpr Options::String help = {
155 : "A spatial radial scaling followed by a rotation about the z-axis.\n"
156 : "The spatial radial scaling is either based on a cubic scaling or a\n"
157 : "simple linear scaling. If the two expansion functions of time have\n"
158 : "the same name then the scaling is a linear radial scaling.\n"
159 : "The spatially uniform rotation about is initialized with a\n"
160 : "constant angular velocity."};
161 :
162 0 : ScalingAndZRotation() = default;
163 0 : ~ScalingAndZRotation() override = default;
164 0 : ScalingAndZRotation(const ScalingAndZRotation&) = delete;
165 0 : ScalingAndZRotation(ScalingAndZRotation&&) = default;
166 0 : ScalingAndZRotation& operator=(const ScalingAndZRotation&) = delete;
167 0 : ScalingAndZRotation& operator=(ScalingAndZRotation&&) = default;
168 :
169 0 : ScalingAndZRotation(double initial_time, double angular_velocity,
170 : double outer_boundary, bool use_linear_scaling,
171 : const std::array<double, 2>& initial_expansion,
172 : const std::array<double, 2>& velocity,
173 : const std::array<double, 2>& acceleration);
174 :
175 1 : auto get_clone() const -> std::unique_ptr<TimeDependence<MeshDim>> override;
176 :
177 1 : auto block_maps_grid_to_inertial(size_t number_of_blocks) const
178 : -> std::vector<std::unique_ptr<domain::CoordinateMapBase<
179 : Frame::Grid, Frame::Inertial, MeshDim>>> override;
180 :
181 1 : auto block_maps_grid_to_distorted(size_t number_of_blocks) const
182 : -> std::vector<std::unique_ptr<domain::CoordinateMapBase<
183 : Frame::Grid, Frame::Distorted, MeshDim>>> override;
184 :
185 1 : auto block_maps_distorted_to_inertial(size_t number_of_blocks) const
186 : -> std::vector<std::unique_ptr<domain::CoordinateMapBase<
187 : Frame::Distorted, Frame::Inertial, MeshDim>>> override;
188 :
189 1 : auto functions_of_time(const std::unordered_map<std::string, double>&
190 : initial_expiration_times = {}) const
191 : -> std::unordered_map<
192 : std::string,
193 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>> override;
194 :
195 : private:
196 : template <size_t LocalDim>
197 : // NOLINTNEXTLINE(readability-redundant-declaration)
198 0 : friend bool operator==(const ScalingAndZRotation<LocalDim>& lhs,
199 : const ScalingAndZRotation<LocalDim>& rhs);
200 :
201 0 : GridToInertialMap grid_to_inertial_map() const;
202 0 : GridToDistortedMap grid_to_distorted_map() const;
203 0 : DistortedToInertialMap distorted_to_inertial_map() const;
204 :
205 0 : double initial_time_{std::numeric_limits<double>::signaling_NaN()};
206 0 : double angular_velocity_{std::numeric_limits<double>::signaling_NaN()};
207 0 : double outer_boundary_{std::numeric_limits<double>::signaling_NaN()};
208 0 : bool use_linear_scaling_{false};
209 0 : std::array<double, 2> initial_expansion_{};
210 0 : std::array<double, 2> velocity_{};
211 0 : std::array<double, 2> acceleration_{};
212 : // Unlike other TimeDependences, these names aren't inline static const
213 : // because they can potentially be changed by the run-time option
214 : // use_linear_scaling in the constructor
215 0 : std::array<std::string, 3> functions_of_time_names_{
216 : {"CubicScaleA", "CubicScaleB", "Rotation"}};
217 : };
218 :
219 : template <size_t Dim>
220 0 : bool operator==(const ScalingAndZRotation<Dim>& lhs,
221 : const ScalingAndZRotation<Dim>& rhs);
222 :
223 : template <size_t Dim>
224 0 : bool operator!=(const ScalingAndZRotation<Dim>& lhs,
225 : const ScalingAndZRotation<Dim>& rhs);
226 : } // namespace domain::creators::time_dependence
|