Line data Source code
1 1 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : /// \file
5 : /// Defines class CoordinateMap
6 :
7 : #pragma once
8 :
9 : #include <cstddef>
10 : #include <limits>
11 : #include <memory>
12 : #include <optional>
13 : #include <pup.h>
14 : #include <string>
15 : #include <tuple>
16 : #include <type_traits>
17 : #include <typeinfo>
18 : #include <unordered_map>
19 : #include <unordered_set>
20 : #include <utility>
21 : #include <vector>
22 :
23 : #include "DataStructures/Tensor/Tensor.hpp"
24 : #include "Domain/FunctionsOfTime/FunctionOfTime.hpp"
25 : #include "Utilities/Serialization/CharmPupable.hpp"
26 : #include "Utilities/TMPL.hpp"
27 : #include "Utilities/TypeTraits/CreateIsCallable.hpp"
28 :
29 : /// \cond
30 : class DataVector;
31 : /// \endcond
32 :
33 : namespace domain {
34 : /// Contains all coordinate maps.
35 : namespace CoordinateMaps {
36 : /// Contains the time-dependent coordinate maps
37 1 : namespace TimeDependent {}
38 : template <typename FirstMap, typename... Maps>
39 0 : constexpr size_t map_dim = FirstMap::dim;
40 : } // namespace CoordinateMaps
41 :
42 : namespace CoordinateMap_detail {
43 : CREATE_IS_CALLABLE(function_of_time_names)
44 : CREATE_IS_CALLABLE_V(function_of_time_names)
45 :
46 : template <typename T>
47 : struct map_type {
48 : using type = T;
49 : };
50 :
51 : template <typename T>
52 : struct map_type<std::unique_ptr<T>> {
53 : using type = T;
54 : };
55 :
56 : template <typename T>
57 : using map_type_t = typename map_type<T>::type;
58 :
59 : template <typename... Maps, size_t... Is>
60 : std::unordered_set<std::string> initialize_names(
61 : const std::tuple<Maps...>& maps, std::index_sequence<Is...> /*meta*/) {
62 : std::unordered_set<std::string> function_of_time_names{};
63 : const auto add_names = [&function_of_time_names, &maps](auto index) {
64 : const auto& map = std::get<decltype(index)::value>(maps);
65 : using TupleMap = std::decay_t<decltype(map)>;
66 : constexpr bool map_is_unique_ptr = tt::is_a_v<std::unique_ptr, TupleMap>;
67 : using Map = map_type_t<TupleMap>;
68 : if constexpr (is_function_of_time_names_callable_v<Map>) {
69 : if constexpr (map_is_unique_ptr) {
70 : const auto& names = map->function_of_time_names();
71 : function_of_time_names.insert(names.begin(), names.end());
72 : } else {
73 : const auto& names = map.function_of_time_names();
74 : function_of_time_names.insert(names.begin(), names.end());
75 : }
76 : } else {
77 : (void)function_of_time_names;
78 : }
79 : };
80 : EXPAND_PACK_LEFT_TO_RIGHT(add_names(std::integral_constant<size_t, Is>{}));
81 :
82 : return function_of_time_names;
83 : }
84 : } // namespace CoordinateMap_detail
85 :
86 : /*!
87 : * \ingroup CoordinateMapsGroup
88 : * \brief Abstract base class for CoordinateMap
89 : */
90 : template <typename SourceFrame, typename TargetFrame, size_t Dim>
91 1 : class CoordinateMapBase : public PUP::able {
92 : public:
93 0 : static constexpr size_t dim = Dim;
94 0 : using source_frame = SourceFrame;
95 0 : using target_frame = TargetFrame;
96 :
97 0 : WRAPPED_PUPable_abstract(CoordinateMapBase); // NOLINT
98 :
99 0 : CoordinateMapBase() = default;
100 0 : CoordinateMapBase(const CoordinateMapBase& /*rhs*/) = default;
101 0 : CoordinateMapBase& operator=(const CoordinateMapBase& /*rhs*/) = default;
102 0 : CoordinateMapBase(CoordinateMapBase&& /*rhs*/) = default;
103 0 : CoordinateMapBase& operator=(CoordinateMapBase&& /*rhs*/) = default;
104 0 : ~CoordinateMapBase() override = default;
105 :
106 : virtual std::unique_ptr<CoordinateMapBase<SourceFrame, TargetFrame, Dim>>
107 0 : get_clone() const = 0;
108 :
109 : /// \brief Retrieve the same map but going from `SourceFrame` to
110 : /// `Frame::Grid`.
111 : ///
112 : /// This functionality is needed when composing time-dependent maps with
113 : /// time-independent maps, where the target frame of the time-independent map
114 : /// is `Frame::Grid`.
115 : virtual std::unique_ptr<CoordinateMapBase<SourceFrame, Frame::Grid, Dim>>
116 1 : get_to_grid_frame() const = 0;
117 :
118 : /// Returns `true` if the map is the identity
119 1 : virtual bool is_identity() const = 0;
120 :
121 : /// Returns `true` if the inverse Jacobian depends on time.
122 1 : virtual bool inv_jacobian_is_time_dependent() const = 0;
123 :
124 : /// Returns `true` if the Jacobian depends on time.
125 1 : virtual bool jacobian_is_time_dependent() const = 0;
126 :
127 : /// Get a set of all FunctionOfTime names used in this mapping
128 1 : virtual const std::unordered_set<std::string>& function_of_time_names()
129 : const = 0;
130 :
131 : /// @{
132 : /// Apply the `Maps` to the point(s) `source_point`
133 1 : virtual tnsr::I<double, Dim, TargetFrame> operator()(
134 : tnsr::I<double, Dim, SourceFrame> source_point,
135 : double time = std::numeric_limits<double>::signaling_NaN(),
136 : const FunctionsOfTimeMap& functions_of_time = {}) const = 0;
137 1 : virtual tnsr::I<DataVector, Dim, TargetFrame> operator()(
138 : tnsr::I<DataVector, Dim, SourceFrame> source_point,
139 : double time = std::numeric_limits<double>::signaling_NaN(),
140 : const FunctionsOfTimeMap& functions_of_time = {}) const = 0;
141 : /// @}
142 :
143 : /// @{
144 : /// Apply the inverse `Maps` to the point(s) `target_point`.
145 : /// The returned std::optional is invalid if the map is not invertible
146 : /// at `target_point`, or if `target_point` can be easily determined to not
147 : /// make sense for the map. An example of the latter is passing a
148 : /// point with a negative value of z into a positive-z Wedge<3> inverse map.
149 : /// The inverse function is only callable with doubles because the inverse
150 : /// might fail if called for a point out of range, and it is unclear
151 : /// what should happen if the inverse were to succeed for some points in a
152 : /// DataVector but fail for other points.
153 1 : virtual std::optional<tnsr::I<double, Dim, SourceFrame>> inverse(
154 : tnsr::I<double, Dim, TargetFrame> target_point,
155 : double time = std::numeric_limits<double>::signaling_NaN(),
156 : const FunctionsOfTimeMap& functions_of_time = {}) const = 0;
157 : /// @}
158 :
159 : /// @{
160 : /// Compute the inverse Jacobian of the `Maps` at the point(s)
161 : /// `source_point`
162 1 : virtual InverseJacobian<double, Dim, SourceFrame, TargetFrame> inv_jacobian(
163 : tnsr::I<double, Dim, SourceFrame> source_point,
164 : double time = std::numeric_limits<double>::signaling_NaN(),
165 : const FunctionsOfTimeMap& functions_of_time = {}) const = 0;
166 : virtual InverseJacobian<DataVector, Dim, SourceFrame, TargetFrame>
167 1 : inv_jacobian(tnsr::I<DataVector, Dim, SourceFrame> source_point,
168 : double time = std::numeric_limits<double>::signaling_NaN(),
169 : const FunctionsOfTimeMap& functions_of_time = {}) const = 0;
170 : /// @}
171 :
172 : /// @{
173 : /// Compute the Jacobian of the `Maps` at the point(s) `source_point`
174 1 : virtual Jacobian<double, Dim, SourceFrame, TargetFrame> jacobian(
175 : tnsr::I<double, Dim, SourceFrame> source_point,
176 : double time = std::numeric_limits<double>::signaling_NaN(),
177 : const FunctionsOfTimeMap& functions_of_time = {}) const = 0;
178 1 : virtual Jacobian<DataVector, Dim, SourceFrame, TargetFrame> jacobian(
179 : tnsr::I<DataVector, Dim, SourceFrame> source_point,
180 : double time = std::numeric_limits<double>::signaling_NaN(),
181 : const FunctionsOfTimeMap& functions_of_time = {}) const = 0;
182 : /// @}
183 :
184 : /// @{
185 : /// Compute the mapped coordinates, frame velocity, Jacobian, and inverse
186 : /// Jacobian
187 : virtual std::tuple<tnsr::I<double, Dim, TargetFrame>,
188 : InverseJacobian<double, Dim, SourceFrame, TargetFrame>,
189 : Jacobian<double, Dim, SourceFrame, TargetFrame>,
190 : tnsr::I<double, Dim, TargetFrame>>
191 1 : coords_frame_velocity_jacobians(
192 : tnsr::I<double, Dim, SourceFrame> source_point,
193 : double time = std::numeric_limits<double>::signaling_NaN(),
194 : const FunctionsOfTimeMap& functions_of_time = {}) const = 0;
195 : virtual std::tuple<tnsr::I<DataVector, Dim, TargetFrame>,
196 : InverseJacobian<DataVector, Dim, SourceFrame, TargetFrame>,
197 : Jacobian<DataVector, Dim, SourceFrame, TargetFrame>,
198 : tnsr::I<DataVector, Dim, TargetFrame>>
199 1 : coords_frame_velocity_jacobians(
200 : tnsr::I<DataVector, Dim, SourceFrame> source_point,
201 : double time = std::numeric_limits<double>::signaling_NaN(),
202 : const FunctionsOfTimeMap& functions_of_time = {}) const = 0;
203 : /// @}
204 :
205 : private:
206 0 : virtual bool is_equal_to(const CoordinateMapBase& other) const = 0;
207 0 : friend bool operator==(const CoordinateMapBase& lhs,
208 : const CoordinateMapBase& rhs) {
209 : return typeid(lhs) == typeid(rhs) and lhs.is_equal_to(rhs);
210 : }
211 0 : friend bool operator!=(const CoordinateMapBase& lhs,
212 : const CoordinateMapBase& rhs) {
213 : return not(lhs == rhs);
214 : }
215 : };
216 :
217 : /*!
218 : * \ingroup CoordinateMapsGroup
219 : * \brief A coordinate map or composition of coordinate maps
220 : *
221 : * Maps coordinates from the `SourceFrame` to the `TargetFrame` using the
222 : * coordinate maps `Maps...`. The individual maps are applied left to right
223 : * from the source to the target Frame. The inverse map, as well as Jacobian
224 : * and inverse Jacobian are also provided. The `CoordinateMap` class must
225 : * be used even if just wrapping a single coordinate map. It is designed to
226 : * be an extremely minimal interface to the underlying coordinate maps. For
227 : * a list of all coordinate maps see the CoordinateMaps group or namespace.
228 : *
229 : * Each coordinate map must contain a `static constexpr size_t dim` variable
230 : * that is equal to the dimensionality of the map. The Coordinatemap class
231 : * contains a member `static constexpr size_t dim`, a type alias `source_frame`,
232 : * a type alias `target_frame` and `typelist of the `Maps...`.
233 : */
234 : template <typename SourceFrame, typename TargetFrame, typename... Maps>
235 1 : class CoordinateMap
236 : : public CoordinateMapBase<SourceFrame, TargetFrame,
237 : CoordinateMaps::map_dim<Maps...>> {
238 : static_assert(sizeof...(Maps) > 0, "Must have at least one map");
239 : static_assert(
240 : tmpl::all<tmpl::integral_list<size_t, Maps::dim...>,
241 : std::is_same<tmpl::integral_constant<
242 : size_t, CoordinateMaps::map_dim<Maps...>>,
243 : tmpl::_1>>::value,
244 : "All Maps passed to CoordinateMap must be of the same dimensionality.");
245 :
246 : public:
247 0 : static constexpr size_t dim = CoordinateMaps::map_dim<Maps...>;
248 0 : using source_frame = SourceFrame;
249 0 : using target_frame = TargetFrame;
250 0 : using maps_list = tmpl::list<Maps...>;
251 :
252 : /// Used for Charm++ serialization
253 1 : CoordinateMap() = default;
254 :
255 0 : CoordinateMap(const CoordinateMap& /*rhs*/) = default;
256 0 : CoordinateMap& operator=(const CoordinateMap& /*rhs*/) = default;
257 0 : CoordinateMap(CoordinateMap&& /*rhs*/) = default;
258 0 : CoordinateMap& operator=(CoordinateMap&& /*rhs*/) = default;
259 0 : ~CoordinateMap() override = default;
260 :
261 0 : explicit CoordinateMap(Maps... maps);
262 :
263 0 : std::unique_ptr<CoordinateMapBase<SourceFrame, TargetFrame, dim>> get_clone()
264 : const override {
265 : return std::make_unique<CoordinateMap>(*this);
266 : }
267 :
268 : std::unique_ptr<CoordinateMapBase<SourceFrame, Frame::Grid, dim>>
269 1 : get_to_grid_frame() const override {
270 : return get_to_grid_frame_impl(std::make_index_sequence<sizeof...(Maps)>{});
271 : }
272 :
273 : /// Returns `true` if the map is the identity
274 1 : bool is_identity() const override;
275 :
276 : /// Returns `true` if the inverse Jacobian depends on time.
277 1 : bool inv_jacobian_is_time_dependent() const override;
278 :
279 : /// Returns `true` if the Jacobian depends on time.
280 1 : bool jacobian_is_time_dependent() const override;
281 :
282 : /// Get a set of all FunctionOfTime names from `Maps`
283 1 : const std::unordered_set<std::string>& function_of_time_names()
284 : const override {
285 : return function_of_time_names_;
286 : }
287 :
288 : /// @{
289 : /// Apply the `Maps...` to the point(s) `source_point`
290 1 : tnsr::I<double, dim, TargetFrame> operator()(
291 : tnsr::I<double, dim, SourceFrame> source_point,
292 : const double time = std::numeric_limits<double>::signaling_NaN(),
293 : const FunctionsOfTimeMap& functions_of_time = {}) const override {
294 : return call_impl(std::move(source_point), time, functions_of_time,
295 : std::make_index_sequence<sizeof...(Maps)>{});
296 : }
297 1 : tnsr::I<DataVector, dim, TargetFrame> operator()(
298 : tnsr::I<DataVector, dim, SourceFrame> source_point,
299 : const double time = std::numeric_limits<double>::signaling_NaN(),
300 : const FunctionsOfTimeMap& functions_of_time = {}) const override {
301 : return call_impl(std::move(source_point), time, functions_of_time,
302 : std::make_index_sequence<sizeof...(Maps)>{});
303 : }
304 : /// @}
305 :
306 : /// @{
307 : /// Apply the inverse `Maps...` to the point(s) `target_point`
308 1 : std::optional<tnsr::I<double, dim, SourceFrame>> inverse(
309 : tnsr::I<double, dim, TargetFrame> target_point,
310 : const double time = std::numeric_limits<double>::signaling_NaN(),
311 : const FunctionsOfTimeMap& functions_of_time = {}) const override {
312 : return inverse_impl(std::move(target_point), time, functions_of_time,
313 : std::make_index_sequence<sizeof...(Maps)>{});
314 : }
315 : /// @}
316 :
317 : /// @{
318 : /// Compute the inverse Jacobian of the `Maps...` at the point(s)
319 : /// `source_point`
320 1 : InverseJacobian<double, dim, SourceFrame, TargetFrame> inv_jacobian(
321 : tnsr::I<double, dim, SourceFrame> source_point,
322 : const double time = std::numeric_limits<double>::signaling_NaN(),
323 : const FunctionsOfTimeMap& functions_of_time = {}) const override {
324 : return inv_jacobian_impl(std::move(source_point), time, functions_of_time);
325 : }
326 1 : InverseJacobian<DataVector, dim, SourceFrame, TargetFrame> inv_jacobian(
327 : tnsr::I<DataVector, dim, SourceFrame> source_point,
328 : const double time = std::numeric_limits<double>::signaling_NaN(),
329 : const FunctionsOfTimeMap& functions_of_time = {}) const override {
330 : return inv_jacobian_impl(std::move(source_point), time, functions_of_time);
331 : }
332 : /// @}
333 :
334 : /// @{
335 : /// Compute the Jacobian of the `Maps...` at the point(s) `source_point`
336 1 : Jacobian<double, dim, SourceFrame, TargetFrame> jacobian(
337 : tnsr::I<double, dim, SourceFrame> source_point,
338 : const double time = std::numeric_limits<double>::signaling_NaN(),
339 : const FunctionsOfTimeMap& functions_of_time = {}) const override {
340 : return jacobian_impl(std::move(source_point), time, functions_of_time);
341 : }
342 1 : Jacobian<DataVector, dim, SourceFrame, TargetFrame> jacobian(
343 : tnsr::I<DataVector, dim, SourceFrame> source_point,
344 : const double time = std::numeric_limits<double>::signaling_NaN(),
345 : const FunctionsOfTimeMap& functions_of_time = {}) const override {
346 : return jacobian_impl(std::move(source_point), time, functions_of_time);
347 : }
348 : /// @}
349 :
350 : /// @{
351 : /// Compute the mapped coordinates, frame velocity, Jacobian, and inverse
352 : /// Jacobian. The inverse Jacobian is computed by numerically inverting the
353 : /// Jacobian as this was measured to be quicker than computing it directly for
354 : /// more complex map concatenations.
355 : std::tuple<tnsr::I<double, dim, TargetFrame>,
356 : InverseJacobian<double, dim, SourceFrame, TargetFrame>,
357 : Jacobian<double, dim, SourceFrame, TargetFrame>,
358 : tnsr::I<double, dim, TargetFrame>>
359 1 : coords_frame_velocity_jacobians(
360 : tnsr::I<double, dim, SourceFrame> source_point,
361 : const double time = std::numeric_limits<double>::signaling_NaN(),
362 : const FunctionsOfTimeMap& functions_of_time = {}) const override {
363 : return coords_frame_velocity_jacobians_impl(std::move(source_point), time,
364 : functions_of_time);
365 : }
366 : std::tuple<tnsr::I<DataVector, dim, TargetFrame>,
367 : InverseJacobian<DataVector, dim, SourceFrame, TargetFrame>,
368 : Jacobian<DataVector, dim, SourceFrame, TargetFrame>,
369 : tnsr::I<DataVector, dim, TargetFrame>>
370 1 : coords_frame_velocity_jacobians(
371 : tnsr::I<DataVector, dim, SourceFrame> source_point,
372 : const double time = std::numeric_limits<double>::signaling_NaN(),
373 : const FunctionsOfTimeMap& functions_of_time = {}) const override {
374 : return coords_frame_velocity_jacobians_impl(std::move(source_point), time,
375 : functions_of_time);
376 : }
377 : /// @}
378 :
379 0 : WRAPPED_PUPable_decl_base_template( // NOLINT
380 : SINGLE_ARG(CoordinateMapBase<SourceFrame, TargetFrame, dim>),
381 : CoordinateMap);
382 :
383 0 : explicit CoordinateMap(CkMigrateMessage* /*unused*/) {}
384 :
385 : // NOLINTNEXTLINE(google-runtime-references)
386 0 : void pup(PUP::er& p) override {
387 : size_t version = 0;
388 : p | version;
389 : // Remember to increment the version number when making changes to this
390 : // function. Retain support for unpacking data written by previous versions
391 : // whenever possible. See `Domain` docs for details.
392 : if (version >= 0) {
393 : CoordinateMapBase<SourceFrame, TargetFrame, dim>::pup(p);
394 : p | maps_;
395 : }
396 :
397 : // No need to pup this because it is uniquely determined by the maps
398 : if (p.isUnpacking()) {
399 : function_of_time_names_ = CoordinateMap_detail::initialize_names(
400 : maps_, std::make_index_sequence<sizeof...(Maps)>{});
401 : }
402 : }
403 :
404 : private:
405 0 : friend bool operator==(const CoordinateMap& lhs, const CoordinateMap& rhs) {
406 : return lhs.maps_ == rhs.maps_;
407 : }
408 :
409 : template <typename NewMap, typename LocalSourceFrame,
410 : typename LocalTargetFrame, typename... LocalMaps, size_t... Is>
411 : friend CoordinateMap<LocalSourceFrame, LocalTargetFrame, LocalMaps..., NewMap>
412 : // NOLINTNEXTLINE(readability-redundant-declaration,-warnings-as-errors)
413 0 : push_back_impl(
414 : CoordinateMap<LocalSourceFrame, LocalTargetFrame, LocalMaps...>&& old_map,
415 : NewMap new_map, std::index_sequence<Is...> /*meta*/);
416 :
417 : template <typename... NewMaps, typename LocalSourceFrame,
418 : typename LocalTargetFrame, typename... LocalMaps, size_t... Is,
419 : size_t... Js>
420 : friend CoordinateMap<LocalSourceFrame, LocalTargetFrame, LocalMaps...,
421 : NewMaps...>
422 : // NOLINTNEXTLINE(readability-redundant-declaration,-warnings-as-errors)
423 0 : push_back_impl(
424 : CoordinateMap<LocalSourceFrame, LocalTargetFrame, LocalMaps...>&& old_map,
425 : CoordinateMap<LocalSourceFrame, LocalTargetFrame, NewMaps...> new_map,
426 : std::index_sequence<Is...> /*meta*/, std::index_sequence<Js...> /*meta*/);
427 :
428 : template <typename NewMap, typename LocalSourceFrame,
429 : typename LocalTargetFrame, typename... LocalMaps, size_t... Is>
430 : friend CoordinateMap<LocalSourceFrame, LocalTargetFrame, NewMap, LocalMaps...>
431 : // NOLINTNEXTLINE(readability-redundant-declaration,-warnings-as-errors)
432 0 : push_front_impl(
433 : CoordinateMap<LocalSourceFrame, LocalTargetFrame, LocalMaps...>&& old_map,
434 : NewMap new_map, std::index_sequence<Is...> /*meta*/);
435 :
436 : template <size_t... Is>
437 : std::unique_ptr<CoordinateMapBase<SourceFrame, Frame::Grid, dim>>
438 0 : get_to_grid_frame_impl(std::index_sequence<Is...> /*meta*/) const;
439 :
440 0 : bool is_equal_to(const CoordinateMapBase<SourceFrame, TargetFrame, dim>&
441 : other) const override {
442 : const auto& cast_of_other = dynamic_cast<const CoordinateMap&>(other);
443 : return *this == cast_of_other;
444 : }
445 :
446 0 : void check_functions_of_time(
447 : const FunctionsOfTimeMap& functions_of_time) const;
448 :
449 : template <typename T, size_t... Is>
450 0 : tnsr::I<T, dim, TargetFrame> call_impl(
451 : tnsr::I<T, dim, SourceFrame>&& source_point, double time,
452 : const FunctionsOfTimeMap& functions_of_time,
453 : std::index_sequence<Is...> /*meta*/) const;
454 :
455 : template <typename T, size_t... Is>
456 0 : std::optional<tnsr::I<T, dim, SourceFrame>> inverse_impl(
457 : tnsr::I<T, dim, TargetFrame>&& target_point, double time,
458 : const FunctionsOfTimeMap& functions_of_time,
459 : std::index_sequence<Is...> /*meta*/) const;
460 :
461 : template <typename T>
462 0 : InverseJacobian<T, dim, SourceFrame, TargetFrame> inv_jacobian_impl(
463 : tnsr::I<T, dim, SourceFrame>&& source_point, double time,
464 : const FunctionsOfTimeMap& functions_of_time) const;
465 :
466 : template <typename T>
467 0 : Jacobian<T, dim, SourceFrame, TargetFrame> jacobian_impl(
468 : tnsr::I<T, dim, SourceFrame>&& source_point, double time,
469 : const FunctionsOfTimeMap& functions_of_time) const;
470 :
471 : template <typename T>
472 : std::tuple<tnsr::I<T, dim, TargetFrame>,
473 : InverseJacobian<T, dim, SourceFrame, TargetFrame>,
474 : Jacobian<T, dim, SourceFrame, TargetFrame>,
475 : tnsr::I<T, dim, TargetFrame>>
476 0 : coords_frame_velocity_jacobians_impl(
477 : tnsr::I<T, dim, SourceFrame> source_point, double time,
478 : const FunctionsOfTimeMap& functions_of_time) const;
479 :
480 0 : std::tuple<Maps...> maps_;
481 0 : std::unordered_set<std::string> function_of_time_names_;
482 : };
483 :
484 : /// \ingroup ComputationalDomainGroup
485 : /// \brief Creates a `CoordinateMap` of `maps...`
486 : template <typename SourceFrame, typename TargetFrame, typename... Maps>
487 1 : auto make_coordinate_map(Maps&&... maps)
488 : -> CoordinateMap<SourceFrame, TargetFrame, std::decay_t<Maps>...>;
489 :
490 : /// \ingroup ComputationalDomainGroup
491 : /// \brief Creates a `std::unique_ptr<CoordinateMapBase>` of `maps...`
492 : template <typename SourceFrame, typename TargetFrame, typename... Maps>
493 1 : auto make_coordinate_map_base(Maps&&... maps)
494 : -> std::unique_ptr<CoordinateMapBase<
495 : SourceFrame, TargetFrame,
496 : CoordinateMap<SourceFrame, TargetFrame, std::decay_t<Maps>...>::dim>>;
497 :
498 : /// \ingroup ComputationalDomainGroup
499 : /// \brief Creates a `std::vector<std::unique_ptr<CoordinateMapBase>>`
500 : /// containing the result of `make_coordinate_map_base` applied to each
501 : /// argument passed in.
502 : template <typename SourceFrame, typename TargetFrame, typename Arg0,
503 : typename... Args>
504 1 : auto make_vector_coordinate_map_base(Arg0&& arg_0, Args&&... remaining_args)
505 : -> std::vector<std::unique_ptr<
506 : CoordinateMapBase<SourceFrame, TargetFrame, std::decay_t<Arg0>::dim>>>;
507 :
508 : /// \ingroup ComputationalDomainGroup
509 : /// \brief Creates a `std::vector<std::unique_ptr<CoordinateMapBase>>`
510 : /// containing the result of `make_coordinate_map_base` applied to each
511 : /// element of the vector of maps composed with the rest of the arguments
512 : /// passed in.
513 : template <typename SourceFrame, typename TargetFrame, size_t Dim, typename Map,
514 : typename... Maps>
515 1 : auto make_vector_coordinate_map_base(std::vector<Map> maps,
516 : const Maps&... remaining_maps)
517 : -> std::vector<
518 : std::unique_ptr<CoordinateMapBase<SourceFrame, TargetFrame, Dim>>>;
519 :
520 : /// \ingroup ComputationalDomainGroup
521 : /// \brief Creates a `CoordinateMap` by appending the new map to the end of the
522 : /// old maps
523 : template <typename SourceFrame, typename TargetFrame, typename... Maps,
524 : typename NewMap>
525 1 : CoordinateMap<SourceFrame, TargetFrame, Maps..., NewMap> push_back(
526 : CoordinateMap<SourceFrame, TargetFrame, Maps...> old_map, NewMap new_map);
527 :
528 : /// \ingroup ComputationalDomainGroup
529 : /// \brief Creates a `CoordinateMap` by prepending the new map to the beginning
530 : /// of the old maps
531 : template <typename SourceFrame, typename TargetFrame, typename... Maps,
532 : typename NewMap>
533 1 : CoordinateMap<SourceFrame, TargetFrame, NewMap, Maps...> push_front(
534 : CoordinateMap<SourceFrame, TargetFrame, Maps...> old_map, NewMap new_map);
535 :
536 : /// \cond
537 : template <typename SourceFrame, typename TargetFrame, typename... Maps>
538 : PUP::able::PUP_ID
539 : CoordinateMap<SourceFrame, TargetFrame, Maps...>::my_PUP_ID = // NOLINT
540 : 0;
541 : /// \endcond
542 : } // namespace domain
|