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 <functional>
9 : #include <limits>
10 : #include <optional>
11 : #include <string>
12 : #include <unordered_map>
13 : #include <unordered_set>
14 : #include <utility>
15 :
16 : #include "DataStructures/Tensor/Tensor.hpp"
17 : #include "Domain/CoordinateMaps/TimeDependentHelpers.hpp"
18 : #include "Domain/FunctionsOfTime/FunctionOfTime.hpp"
19 : #include "Utilities/DereferenceWrapper.hpp"
20 : #include "Utilities/MakeWithValue.hpp"
21 : #include "Utilities/TMPL.hpp"
22 : #include "Utilities/TypeTraits/RemoveReferenceWrapper.hpp"
23 :
24 : /// \cond
25 : namespace PUP {
26 : class er;
27 : } // namespace PUP
28 : /// \endcond
29 :
30 : namespace domain {
31 : namespace CoordinateMaps {
32 : namespace TimeDependent {
33 : /// \ingroup CoordMapsTimeDependentGroup
34 : /// \brief Product of two codimension=0 CoordinateMaps, where one or both must
35 : /// be time-dependent.
36 : ///
37 : /// \tparam Map1 the map for the first coordinate(s)
38 : /// \tparam Map2 the map for the second coordinate(s)
39 : template <typename Map1, typename Map2>
40 1 : class ProductOf2Maps {
41 : public:
42 0 : static constexpr size_t dim = Map1::dim + Map2::dim;
43 0 : using map_list = tmpl::list<Map1, Map2>;
44 : static_assert(dim == 2 or dim == 3,
45 : "Only 2D and 3D maps are supported by ProductOf2Maps");
46 : static_assert(
47 : domain::is_map_time_dependent_v<Map1> or
48 : domain::is_map_time_dependent_v<Map2>,
49 : "Either Map1 or Map2 must be time-dependent for time-dependent product "
50 : "maps. A time-independent product map exists in domain::CoordinateMaps.");
51 :
52 : // Needed for Charm++ serialization
53 0 : ProductOf2Maps() = default;
54 :
55 0 : ProductOf2Maps(Map1 map1, Map2 map2);
56 :
57 : template <typename T>
58 0 : std::array<tt::remove_cvref_wrap_t<T>, dim> operator()(
59 : const std::array<T, dim>& source_coords, double time,
60 : const std::unordered_map<
61 : std::string,
62 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
63 : functions_of_time) const;
64 :
65 : /// The inverse function is only callable with doubles because the inverse
66 : /// might fail if called for a point out of range, and it is unclear
67 : /// what should happen if the inverse were to succeed for some points in a
68 : /// DataVector but fail for other points.
69 1 : std::optional<std::array<double, dim>> inverse(
70 : const std::array<double, dim>& target_coords, double time,
71 : const std::unordered_map<
72 : std::string,
73 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
74 : functions_of_time) const;
75 :
76 : template <typename T>
77 0 : std::array<tt::remove_cvref_wrap_t<T>, dim> frame_velocity(
78 : const std::array<T, dim>& source_coords, double time,
79 : const std::unordered_map<
80 : std::string,
81 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
82 : functions_of_time) const;
83 :
84 : template <typename T>
85 0 : tnsr::Ij<tt::remove_cvref_wrap_t<T>, dim, Frame::NoFrame> inv_jacobian(
86 : const std::array<T, dim>& source_coords, double time,
87 : const std::unordered_map<
88 : std::string,
89 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
90 : functions_of_time) const;
91 :
92 : template <typename T>
93 0 : tnsr::Ij<tt::remove_cvref_wrap_t<T>, dim, Frame::NoFrame> jacobian(
94 : const std::array<T, dim>& source_coords, double time,
95 : const std::unordered_map<
96 : std::string,
97 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
98 : functions_of_time) const;
99 :
100 : // NOLINTNEXTLINE(google-runtime-references)
101 0 : void pup(PUP::er& p);
102 :
103 0 : bool is_identity() const {
104 : return map1_.is_identity() and map2_.is_identity();
105 : }
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<tt::remove_cvref_wrap_t<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<tt::remove_cvref_wrap_t<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<tt::remove_cvref_wrap_t<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<tt::remove_cvref_wrap_t<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 : const std::unordered_set<std::string>& function_of_time_names() const {
193 : return f_of_t_names_;
194 : }
195 :
196 : private:
197 0 : friend bool operator==(const ProductOf3Maps& lhs, const ProductOf3Maps& rhs) {
198 : return lhs.map1_ == rhs.map1_ and lhs.map2_ == rhs.map2_ and
199 : lhs.map3_ == rhs.map3_;
200 : }
201 :
202 0 : Map1 map1_;
203 0 : Map2 map2_;
204 0 : Map3 map3_;
205 0 : std::unordered_set<std::string> f_of_t_names_;
206 : };
207 :
208 : template <typename Map1, typename Map2, typename Map3>
209 0 : bool operator!=(const ProductOf3Maps<Map1, Map2, Map3>& lhs,
210 : const ProductOf3Maps<Map1, Map2, Map3>& rhs);
211 : } // namespace TimeDependent
212 : } // namespace CoordinateMaps
213 : } // namespace domain
|