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 <unordered_set>
14 :
15 : #include "DataStructures/Tensor/TypeAliases.hpp"
16 :
17 : /// \cond
18 : namespace domain {
19 : namespace FunctionsOfTime {
20 : class FunctionOfTime;
21 : } // namespace FunctionsOfTime
22 : } // namespace domain
23 : namespace PUP {
24 : class er;
25 : } // namespace PUP
26 : /// \endcond
27 :
28 : namespace domain {
29 : namespace CoordinateMaps {
30 : namespace TimeDependent {
31 : /*!
32 : * \ingroup CoordMapsTimeDependentGroup
33 : * \brief Maps the radius as \f$r(t) = a(t)\rho + \left(b(t) - a(t)\right)
34 : * \frac{\rho^3} {R^2}\f$ where \f$\rho\f$ is the radius of the source
35 : * coordinates.
36 : *
37 : * The map scales the radius \f$\rho\f$ in the source coordinates
38 : * \f$\xi^{\hat{i}}\f$ by a factor \f$a(t)\f$, while the coordinates near the
39 : * outer boundary \f$R\f$, are scaled by a factor \f$b(t)\f$. Here \f$a(t)\f$
40 : * and \f$b(t)\f$ are FunctionsOfTime. The target/mapped coordinates are denoted
41 : * by \f$x^i\f$.
42 : *
43 : * The mapped coordinates are given by:
44 : *
45 : * \f{align}{
46 : * x^i = \left[a + (b-a) \frac{\rho^2}{R^2}\right] \xi^{\hat{i}}
47 : * \delta^i_{\hat{i}},
48 : * \f}
49 : *
50 : * where \f$\xi^{\hat{i}}\f$ are the source coordinates, \f$a\f$ and \f$b\f$ are
51 : * functions of time, \f$\rho\f$ is the radius in the source coordinates, and
52 : * \f$R\f$ is the outer boundary.
53 : *
54 : * The inverse map is computed by solving the cubic equation:
55 : *
56 : * \f{align}{
57 : * (b-a)\frac{\rho^3}{R^2} + a \rho - r = 0,
58 : * \f}
59 : *
60 : * which is done by defining \f$q=\rho/R\f$, and solving
61 : *
62 : * \f{align}{
63 : * q \left[(b-a) q^2 + a\right] - \frac{r}{R} = 0.
64 : * \f}
65 : *
66 : * The source coordinates are obtained using:
67 : *
68 : * \f{align}{
69 : * \xi^{\hat{i}} = \frac{qR}{r} x^i(t) \delta^{\hat{i}}_i
70 : * \f}
71 : *
72 : * The Jacobian is given by:
73 : *
74 : * \f{align}{
75 : * \frac{\partial x^i}{\partial \xi^{\hat{i}}}=
76 : * \left[a + (b-a) \frac{\rho^2}{R^2}\right] \delta^i_{\hat{i}}
77 : * + \frac{2 (b-a)}{R^2} \xi^{\hat{j}} \delta^i_{\hat{j}} \xi^{\hat{k}}
78 : * \delta_{\hat{k}\hat{i}}
79 : * \f}
80 : *
81 : * The inverse Jacobian is given by:
82 : *
83 : * \f{align}{
84 : * \frac{\partial \xi^{\hat{i}}}{\partial x^i}=
85 : * \frac{1}{\left[a + (b-a)\rho^2/R^2\right]}
86 : * \left[\delta^{\hat{i}}_i -
87 : * \frac{2 (b-a)}{\left[a R^2 + 3(b-a)\rho^2\right]}
88 : * \xi^{\hat{i}}\xi^{\hat{j}}\delta_{\hat{j}i}\right]
89 : * \f}
90 : *
91 : * The mesh velocity \f$v_g^i\f$ is given by:
92 : *
93 : * \f{align}{
94 : * v_g^i = \left[\frac{da}{dt} + \left(\frac{db}{dt}-\frac{da}{dt}\right)
95 : * \frac{\rho^2}{R^2}\right] \xi^{\hat{i}} \delta^i_{\hat{i}}.
96 : * \f}
97 : */
98 : template <size_t Dim>
99 1 : class CubicScale {
100 : public:
101 0 : static constexpr size_t dim = Dim;
102 :
103 0 : explicit CubicScale(double outer_boundary,
104 : std::string function_of_time_name_a,
105 : std::string function_of_time_name_b);
106 0 : CubicScale() = default;
107 :
108 : template <typename T>
109 0 : std::array<T, Dim> operator()(
110 : const std::array<T, Dim>& source_coords, double time,
111 : const std::unordered_map<
112 : std::string,
113 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
114 : functions_of_time) const;
115 :
116 : /// Returns std::nullopt if the point is outside the range of the map.
117 : /// The inverse function is only callable with doubles because the inverse
118 : /// might fail if called for a point out of range, and it is unclear
119 : /// what should happen if the inverse were to succeed for some points in a
120 : /// DataVector but fail for other points.
121 1 : std::optional<std::array<double, Dim>> inverse(
122 : const std::array<double, Dim>& target_coords, double time,
123 : const std::unordered_map<
124 : std::string,
125 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
126 : functions_of_time) const;
127 :
128 : template <typename T>
129 0 : std::array<T, Dim> frame_velocity(
130 : const std::array<T, Dim>& source_coords, double time,
131 : const std::unordered_map<
132 : std::string,
133 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
134 : functions_of_time) const;
135 :
136 : template <typename T>
137 0 : tnsr::Ij<T, Dim, Frame::NoFrame> inv_jacobian(
138 : const std::array<T, Dim>& source_coords, double time,
139 : const std::unordered_map<
140 : std::string,
141 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
142 : functions_of_time) const;
143 :
144 : template <typename T>
145 0 : tnsr::Ij<T, Dim, Frame::NoFrame> jacobian(
146 : const std::array<T, Dim>& source_coords, double time,
147 : const std::unordered_map<
148 : std::string,
149 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
150 : functions_of_time) const;
151 :
152 : // NOLINTNEXTLINE(google-runtime-references)
153 0 : void pup(PUP::er& p);
154 :
155 0 : static bool is_identity() { return false; }
156 :
157 0 : static constexpr bool supports_hessian{false};
158 :
159 0 : const std::unordered_set<std::string>& function_of_time_names() const {
160 : return f_of_t_names_;
161 : }
162 :
163 : private:
164 : template <size_t LocalDim>
165 : // NOLINTNEXTLINE(readability-redundant-declaration)
166 0 : friend bool operator==(const CubicScale<LocalDim>& lhs,
167 : const CubicScale<LocalDim>& rhs);
168 :
169 0 : std::string f_of_t_a_{};
170 0 : std::string f_of_t_b_{};
171 0 : std::unordered_set<std::string> f_of_t_names_;
172 0 : double one_over_outer_boundary_{std::numeric_limits<double>::signaling_NaN()};
173 0 : bool functions_of_time_equal_{false};
174 : };
175 :
176 : template <size_t Dim>
177 0 : bool operator!=(const CubicScale<Dim>& lhs, const CubicScale<Dim>& rhs) {
178 : return not(lhs == rhs);
179 : }
180 :
181 : } // namespace TimeDependent
182 : } // namespace CoordinateMaps
183 : } // namespace domain
|