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 <optional>
10 : #include <string>
11 : #include <unordered_map>
12 : #include <unordered_set>
13 : #include <utility>
14 :
15 : #include "DataStructures/Tensor/Tensor.hpp"
16 : #include "Domain/CoordinateMaps/TimeDependentHelpers.hpp"
17 : #include "Domain/FunctionsOfTime/FunctionOfTime.hpp"
18 : #include "Utilities/MakeWithValue.hpp"
19 : #include "Utilities/TMPL.hpp"
20 :
21 : /// \cond
22 : namespace PUP {
23 : class er;
24 : } // namespace PUP
25 : /// \endcond
26 :
27 : namespace domain {
28 : namespace CoordinateMaps {
29 : namespace TimeDependent {
30 : /// \ingroup CoordMapsTimeDependentGroup
31 : /// \brief Product of two codimension=0 CoordinateMaps, where one or both must
32 : /// be time-dependent.
33 : ///
34 : /// \tparam Map1 the map for the first coordinate(s)
35 : /// \tparam Map2 the map for the second coordinate(s)
36 : template <typename Map1, typename Map2>
37 1 : class ProductOf2Maps {
38 : public:
39 0 : static constexpr size_t dim = Map1::dim + Map2::dim;
40 0 : using map_list = tmpl::list<Map1, Map2>;
41 : static_assert(dim == 2 or dim == 3,
42 : "Only 2D and 3D maps are supported by ProductOf2Maps");
43 : static_assert(
44 : domain::is_map_time_dependent_v<Map1> or
45 : domain::is_map_time_dependent_v<Map2>,
46 : "Either Map1 or Map2 must be time-dependent for time-dependent product "
47 : "maps. A time-independent product map exists in domain::CoordinateMaps.");
48 :
49 : // Needed for Charm++ serialization
50 0 : ProductOf2Maps() = default;
51 :
52 0 : ProductOf2Maps(Map1 map1, Map2 map2);
53 :
54 : template <typename T>
55 0 : std::array<T, dim> operator()(
56 : const std::array<T, dim>& source_coords, double time,
57 : const std::unordered_map<
58 : std::string,
59 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
60 : functions_of_time) const;
61 :
62 : /// The inverse function is only callable with doubles because the inverse
63 : /// might fail if called for a point out of range, and it is unclear
64 : /// what should happen if the inverse were to succeed for some points in a
65 : /// DataVector but fail for other points.
66 1 : std::optional<std::array<double, dim>> inverse(
67 : const std::array<double, dim>& target_coords, double time,
68 : const std::unordered_map<
69 : std::string,
70 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
71 : functions_of_time) const;
72 :
73 : template <typename T>
74 0 : std::array<T, dim> frame_velocity(
75 : const std::array<T, dim>& source_coords, double time,
76 : const std::unordered_map<
77 : std::string,
78 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
79 : functions_of_time) const;
80 :
81 : template <typename T>
82 0 : tnsr::Ij<T, dim, Frame::NoFrame> inv_jacobian(
83 : const std::array<T, dim>& source_coords, double time,
84 : const std::unordered_map<
85 : std::string,
86 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
87 : functions_of_time) const;
88 :
89 : template <typename T>
90 0 : tnsr::Ij<T, dim, Frame::NoFrame> jacobian(
91 : const std::array<T, dim>& source_coords, double time,
92 : const std::unordered_map<
93 : std::string,
94 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
95 : functions_of_time) const;
96 :
97 : // NOLINTNEXTLINE(google-runtime-references)
98 0 : void pup(PUP::er& p);
99 :
100 0 : bool is_identity() const {
101 : return map1_.is_identity() and map2_.is_identity();
102 : }
103 :
104 0 : static constexpr bool supports_hessian{Map1::supports_hessian and
105 : Map2::supports_hessian};
106 :
107 0 : const std::unordered_set<std::string>& function_of_time_names() const {
108 : return f_of_t_names_;
109 : }
110 :
111 : private:
112 0 : friend bool operator==(const ProductOf2Maps& lhs, const ProductOf2Maps& rhs) {
113 : return lhs.map1_ == rhs.map1_ and lhs.map2_ == rhs.map2_;
114 : }
115 :
116 0 : Map1 map1_;
117 0 : Map2 map2_;
118 0 : std::unordered_set<std::string> f_of_t_names_;
119 : };
120 :
121 : template <typename Map1, typename Map2>
122 0 : bool operator!=(const ProductOf2Maps<Map1, Map2>& lhs,
123 : const ProductOf2Maps<Map1, Map2>& rhs);
124 :
125 : /// \ingroup CoordinateMapsGroup
126 : /// \brief Product of three one-dimensional CoordinateMaps.
127 : template <typename Map1, typename Map2, typename Map3>
128 1 : class ProductOf3Maps {
129 : public:
130 0 : static constexpr size_t dim = Map1::dim + Map2::dim + Map3::dim;
131 0 : using map_list = tmpl::list<Map1, Map2, Map3>;
132 : static_assert(dim == 3, "Only 3D maps are implemented for ProductOf3Maps");
133 : static_assert(
134 : domain::is_map_time_dependent_v<Map1> or
135 : domain::is_map_time_dependent_v<Map2> or
136 : domain::is_map_time_dependent_v<Map3>,
137 : "Either Map1, Map2, or Map3 must be time-dependent for time-dependent "
138 : "product maps. A time-independent product map exists in "
139 : "domain::CoordinateMaps.");
140 :
141 : // Needed for Charm++ serialization
142 0 : ProductOf3Maps() = default;
143 :
144 0 : ProductOf3Maps(Map1 map1, Map2 map2, Map3 map3);
145 :
146 : template <typename T>
147 0 : std::array<T, dim> operator()(
148 : const std::array<T, dim>& source_coords, double time,
149 : const std::unordered_map<
150 : std::string,
151 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
152 : functions_of_time) const;
153 :
154 0 : std::optional<std::array<double, dim>> inverse(
155 : const std::array<double, dim>& target_coords, double time,
156 : const std::unordered_map<
157 : std::string,
158 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
159 : functions_of_time) const;
160 :
161 : template <typename T>
162 0 : std::array<T, dim> frame_velocity(
163 : const std::array<T, dim>& source_coords, double time,
164 : const std::unordered_map<
165 : std::string,
166 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
167 : functions_of_time) const;
168 :
169 : template <typename T>
170 0 : tnsr::Ij<T, dim, Frame::NoFrame> inv_jacobian(
171 : const std::array<T, dim>& source_coords, double time,
172 : const std::unordered_map<
173 : std::string,
174 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
175 : functions_of_time) const;
176 :
177 : template <typename T>
178 0 : tnsr::Ij<T, dim, Frame::NoFrame> jacobian(
179 : const std::array<T, dim>& source_coords, double time,
180 : const std::unordered_map<
181 : std::string,
182 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
183 : functions_of_time) const;
184 :
185 : // NOLINTNEXTLINE(google-runtime-references)
186 0 : void pup(PUP::er& p);
187 :
188 0 : bool is_identity() const {
189 : return map1_.is_identity() and map2_.is_identity() and map3_.is_identity();
190 : }
191 :
192 0 : static constexpr bool supports_hessian{Map1::supports_hessian and
193 : Map2::supports_hessian and
194 : Map3::supports_hessian};
195 :
196 0 : const std::unordered_set<std::string>& function_of_time_names() const {
197 : return f_of_t_names_;
198 : }
199 :
200 : private:
201 0 : friend bool operator==(const ProductOf3Maps& lhs, const ProductOf3Maps& rhs) {
202 : return lhs.map1_ == rhs.map1_ and lhs.map2_ == rhs.map2_ and
203 : lhs.map3_ == rhs.map3_;
204 : }
205 :
206 0 : Map1 map1_;
207 0 : Map2 map2_;
208 0 : Map3 map3_;
209 0 : std::unordered_set<std::string> f_of_t_names_;
210 : };
211 :
212 : template <typename Map1, typename Map2, typename Map3>
213 0 : bool operator!=(const ProductOf3Maps<Map1, Map2, Map3>& lhs,
214 : const ProductOf3Maps<Map1, Map2, Map3>& rhs);
215 : } // namespace TimeDependent
216 : } // namespace CoordinateMaps
217 : } // namespace domain
|