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 : static constexpr bool supports_hessian{Map1::supports_hessian and
108 : Map2::supports_hessian};
109 :
110 0 : const std::unordered_set<std::string>& function_of_time_names() const {
111 : return f_of_t_names_;
112 : }
113 :
114 : private:
115 0 : friend bool operator==(const ProductOf2Maps& lhs, const ProductOf2Maps& rhs) {
116 : return lhs.map1_ == rhs.map1_ and lhs.map2_ == rhs.map2_;
117 : }
118 :
119 0 : Map1 map1_;
120 0 : Map2 map2_;
121 0 : std::unordered_set<std::string> f_of_t_names_;
122 : };
123 :
124 : template <typename Map1, typename Map2>
125 0 : bool operator!=(const ProductOf2Maps<Map1, Map2>& lhs,
126 : const ProductOf2Maps<Map1, Map2>& rhs);
127 :
128 : /// \ingroup CoordinateMapsGroup
129 : /// \brief Product of three one-dimensional CoordinateMaps.
130 : template <typename Map1, typename Map2, typename Map3>
131 1 : class ProductOf3Maps {
132 : public:
133 0 : static constexpr size_t dim = Map1::dim + Map2::dim + Map3::dim;
134 0 : using map_list = tmpl::list<Map1, Map2, Map3>;
135 : static_assert(dim == 3, "Only 3D maps are implemented for ProductOf3Maps");
136 : static_assert(
137 : domain::is_map_time_dependent_v<Map1> or
138 : domain::is_map_time_dependent_v<Map2> or
139 : domain::is_map_time_dependent_v<Map3>,
140 : "Either Map1, Map2, or Map3 must be time-dependent for time-dependent "
141 : "product maps. A time-independent product map exists in "
142 : "domain::CoordinateMaps.");
143 :
144 : // Needed for Charm++ serialization
145 0 : ProductOf3Maps() = default;
146 :
147 0 : ProductOf3Maps(Map1 map1, Map2 map2, Map3 map3);
148 :
149 : template <typename T>
150 0 : std::array<tt::remove_cvref_wrap_t<T>, dim> operator()(
151 : const std::array<T, dim>& source_coords, double time,
152 : const std::unordered_map<
153 : std::string,
154 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
155 : functions_of_time) const;
156 :
157 0 : std::optional<std::array<double, dim>> inverse(
158 : const std::array<double, dim>& target_coords, double time,
159 : const std::unordered_map<
160 : std::string,
161 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
162 : functions_of_time) const;
163 :
164 : template <typename T>
165 0 : std::array<tt::remove_cvref_wrap_t<T>, dim> frame_velocity(
166 : const std::array<T, dim>& source_coords, double time,
167 : const std::unordered_map<
168 : std::string,
169 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
170 : functions_of_time) const;
171 :
172 : template <typename T>
173 0 : tnsr::Ij<tt::remove_cvref_wrap_t<T>, dim, Frame::NoFrame> inv_jacobian(
174 : const std::array<T, dim>& source_coords, double time,
175 : const std::unordered_map<
176 : std::string,
177 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
178 : functions_of_time) const;
179 :
180 : template <typename T>
181 0 : tnsr::Ij<tt::remove_cvref_wrap_t<T>, dim, Frame::NoFrame> jacobian(
182 : const std::array<T, dim>& source_coords, double time,
183 : const std::unordered_map<
184 : std::string,
185 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
186 : functions_of_time) const;
187 :
188 : // NOLINTNEXTLINE(google-runtime-references)
189 0 : void pup(PUP::er& p);
190 :
191 0 : bool is_identity() const {
192 : return map1_.is_identity() and map2_.is_identity() and map3_.is_identity();
193 : }
194 :
195 0 : static constexpr bool supports_hessian{Map1::supports_hessian and
196 : Map2::supports_hessian and
197 : Map3::supports_hessian};
198 :
199 0 : const std::unordered_set<std::string>& function_of_time_names() const {
200 : return f_of_t_names_;
201 : }
202 :
203 : private:
204 0 : friend bool operator==(const ProductOf3Maps& lhs, const ProductOf3Maps& rhs) {
205 : return lhs.map1_ == rhs.map1_ and lhs.map2_ == rhs.map2_ and
206 : lhs.map3_ == rhs.map3_;
207 : }
208 :
209 0 : Map1 map1_;
210 0 : Map2 map2_;
211 0 : Map3 map3_;
212 0 : std::unordered_set<std::string> f_of_t_names_;
213 : };
214 :
215 : template <typename Map1, typename Map2, typename Map3>
216 0 : bool operator!=(const ProductOf3Maps<Map1, Map2, Map3>& lhs,
217 : const ProductOf3Maps<Map1, Map2, Map3>& rhs);
218 : } // namespace TimeDependent
219 : } // namespace CoordinateMaps
220 : } // namespace domain
|