CoordinateMap.hpp
Go to the documentation of this file.
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 <algorithm>
10 #include <array>
11 #include <boost/optional.hpp>
12 #include <cstddef>
13 #include <cstdint>
14 #include <initializer_list>
15 #include <memory>
16 #include <pup.h>
17 #include <tuple>
18 #include <type_traits>
19 #include <typeinfo>
20 #include <unordered_map>
21 #include <vector>
22 
23 #include "DataStructures/Tensor/Identity.hpp"
26 #include "Parallel/PupStlCpp11.hpp"
28 #include "Utilities/Gsl.hpp"
29 #include "Utilities/MakeArray.hpp"
30 #include "Utilities/TMPL.hpp"
31 #include "Utilities/Tuple.hpp"
32 
33 /// \cond
34 class DataVector;
35 class FunctionOfTime;
36 /// \endcond
37 
38 /// Contains all coordinate maps.
39 namespace CoordinateMaps {
40 template <typename FirstMap, typename... Maps>
41 constexpr size_t map_dim = FirstMap::dim;
42 } // namespace CoordinateMaps
43 
44 /*!
45  * \ingroup CoordinateMapsGroup
46  * \brief Abstract base class for CoordinateMap
47  */
48 template <typename SourceFrame, typename TargetFrame, size_t Dim>
49 class CoordinateMapBase : public PUP::able {
50  public:
51  static constexpr size_t dim = Dim;
52  using source_frame = SourceFrame;
53  using target_frame = TargetFrame;
54 
56 
57  CoordinateMapBase() = default;
58  CoordinateMapBase(const CoordinateMapBase& /*rhs*/) = default;
59  CoordinateMapBase& operator=(const CoordinateMapBase& /*rhs*/) = default;
60  CoordinateMapBase(CoordinateMapBase&& /*rhs*/) = default;
61  CoordinateMapBase& operator=(CoordinateMapBase&& /*rhs*/) = default;
62  ~CoordinateMapBase() override = default;
63 
65  get_clone() const = 0;
66 
67  // @{
68  /// Apply the `Maps` to the point(s) `source_point`
69  virtual tnsr::I<double, Dim, TargetFrame> operator()(
70  tnsr::I<double, Dim, SourceFrame> source_point,
74  noexcept = 0;
75  virtual tnsr::I<DataVector, Dim, TargetFrame> operator()(
76  tnsr::I<DataVector, Dim, SourceFrame> source_point,
80  noexcept = 0;
81  // @}
82 
83  // @{
84  /// Apply the inverse `Maps` to the point(s) `target_point`.
85  /// The returned boost::optional is invalid if the map is not invertible
86  /// at `target_point`, or if `target_point` can be easily determined to not
87  /// make sense for the map. An example of the latter is passing a
88  /// point with a negative value of z into a positive-z Wedge3D inverse map.
89  virtual boost::optional<tnsr::I<double, Dim, SourceFrame>> inverse(
90  tnsr::I<double, Dim, TargetFrame> target_point,
94  noexcept = 0;
95  // @}
96 
97  // @{
98  /// Compute the inverse Jacobian of the `Maps` at the point(s)
99  /// `source_point`
100  virtual InverseJacobian<double, Dim, SourceFrame, TargetFrame> inv_jacobian(
101  tnsr::I<double, Dim, SourceFrame> source_point,
105  noexcept = 0;
106  virtual InverseJacobian<DataVector, Dim, SourceFrame, TargetFrame>
107  inv_jacobian(
108  tnsr::I<DataVector, Dim, SourceFrame> source_point,
112  noexcept = 0;
113  // @}
114 
115  // @{
116  /// Compute the Jacobian of the `Maps` at the point(s) `source_point`
117  virtual Jacobian<double, Dim, SourceFrame, TargetFrame> jacobian(
118  tnsr::I<double, Dim, SourceFrame> source_point,
122  noexcept = 0;
123  virtual Jacobian<DataVector, Dim, SourceFrame, TargetFrame> jacobian(
124  tnsr::I<DataVector, Dim, SourceFrame> source_point,
128  noexcept = 0;
129  // @}
130  private:
131  virtual bool is_equal_to(const CoordinateMapBase& other) const = 0;
132  friend bool operator==(const CoordinateMapBase& lhs,
133  const CoordinateMapBase& rhs) noexcept {
134  return typeid(lhs) == typeid(rhs) and lhs.is_equal_to(rhs);
135  }
136  friend bool operator!=(const CoordinateMapBase& lhs,
137  const CoordinateMapBase& rhs) noexcept {
138  return not(lhs == rhs);
139  }
140 };
141 
142 /*!
143  * \ingroup CoordinateMapsGroup
144  * \brief A coordinate map or composition of coordinate maps
145  *
146  * Maps coordinates from the `SourceFrame` to the `TargetFrame` using the
147  * coordinate maps `Maps...`. The individual maps are applied left to right
148  * from the source to the target Frame. The inverse map, as well as Jacobian
149  * and inverse Jacobian are also provided. The `CoordinateMap` class must
150  * be used even if just wrapping a single coordinate map. It is designed to
151  * be an extremely minimal interface to the underlying coordinate maps. For
152  * a list of all coordinate maps see the CoordinateMaps group or namespace.
153  *
154  * Each coordinate map must contain a `static constexpr size_t dim` variable
155  * that is equal to the dimensionality of the map. The Coordinatemap class
156  * contains a member `static constexpr size_t dim`, a type alias `source_frame`,
157  * a type alias `target_frame` and `typelist of the `Maps...`.
158  */
159 template <typename SourceFrame, typename TargetFrame, typename... Maps>
161  : public CoordinateMapBase<SourceFrame, TargetFrame,
162  CoordinateMaps::map_dim<Maps...>> {
163  static_assert(sizeof...(Maps) > 0, "Must have at least one map");
164  static_assert(
165  tmpl::all<tmpl::integral_list<size_t, Maps::dim...>,
166  std::is_same<tmpl::integral_constant<
167  size_t, CoordinateMaps::map_dim<Maps...>>,
168  tmpl::_1>>::value,
169  "All Maps passed to CoordinateMap must be of the same dimensionality.");
170 
171  public:
172  static constexpr size_t dim = CoordinateMaps::map_dim<Maps...>;
173  using source_frame = SourceFrame;
174  using target_frame = TargetFrame;
175  using maps_list = tmpl::list<Maps...>;
176 
177  /// Used for Charm++ serialization
178  CoordinateMap() = default;
179 
180  CoordinateMap(const CoordinateMap& /*rhs*/) = default;
181  CoordinateMap& operator=(const CoordinateMap& /*rhs*/) = default;
182  CoordinateMap(CoordinateMap&& /*rhs*/) = default;
183  CoordinateMap& operator=(CoordinateMap&& /*rhs*/) = default;
184  ~CoordinateMap() override = default;
185 
186  constexpr explicit CoordinateMap(Maps... maps);
187 
189  const override {
190  return std::make_unique<CoordinateMap>(*this);
191  }
192 
193  // @{
194  /// Apply the `Maps...` to the point(s) `source_point`
195  constexpr tnsr::I<double, dim, TargetFrame> operator()(
196  tnsr::I<double, dim, SourceFrame> source_point,
197  const double time = std::numeric_limits<double>::signaling_NaN(),
200  noexcept override {
201  return call_impl(std::move(source_point), time, f_of_t_list,
202  std::make_index_sequence<sizeof...(Maps)>{});
203  }
204  constexpr tnsr::I<DataVector, dim, TargetFrame> operator()(
205  tnsr::I<DataVector, dim, SourceFrame> source_point,
206  const double time = std::numeric_limits<double>::signaling_NaN(),
209  noexcept override {
210  return call_impl(std::move(source_point), time, f_of_t_list,
211  std::make_index_sequence<sizeof...(Maps)>{});
212  }
213  // @}
214 
215  // @{
216  /// Apply the inverse `Maps...` to the point(s) `target_point`
217  constexpr boost::optional<tnsr::I<double, dim, SourceFrame>> inverse(
218  tnsr::I<double, dim, TargetFrame> target_point,
219  const double time = std::numeric_limits<double>::signaling_NaN(),
222  noexcept override {
223  return inverse_impl(std::move(target_point), time, f_of_t_list,
224  std::make_index_sequence<sizeof...(Maps)>{});
225  }
226  // @}
227 
228  // @{
229  /// Compute the inverse Jacobian of the `Maps...` at the point(s)
230  /// `source_point`
231  constexpr InverseJacobian<double, dim, SourceFrame, TargetFrame> inv_jacobian(
232  tnsr::I<double, dim, SourceFrame> source_point,
233  const double time = std::numeric_limits<double>::signaling_NaN(),
236  noexcept override {
237  return inv_jacobian_impl(std::move(source_point), time, f_of_t_list);
238  }
239  constexpr InverseJacobian<DataVector, dim, SourceFrame, TargetFrame>
241  tnsr::I<DataVector, dim, SourceFrame> source_point,
242  const double time = std::numeric_limits<double>::signaling_NaN(),
245  noexcept override {
246  return inv_jacobian_impl(std::move(source_point), time, f_of_t_list);
247  }
248  // @}
249 
250  // @{
251  /// Compute the Jacobian of the `Maps...` at the point(s) `source_point`
252  constexpr Jacobian<double, dim, SourceFrame, TargetFrame> jacobian(
253  tnsr::I<double, dim, SourceFrame> source_point,
254  const double time = std::numeric_limits<double>::signaling_NaN(),
257  noexcept override {
258  return jacobian_impl(std::move(source_point), time, f_of_t_list);
259  }
260  constexpr Jacobian<DataVector, dim, SourceFrame, TargetFrame> jacobian(
261  tnsr::I<DataVector, dim, SourceFrame> source_point,
262  const double time = std::numeric_limits<double>::signaling_NaN(),
265  noexcept override {
266  return jacobian_impl(std::move(source_point), time, f_of_t_list);
267  }
268  // @}
269 
272  CoordinateMap);
273 
274  explicit CoordinateMap(CkMigrateMessage* /*unused*/) {}
275 
276  // clang-tidy: google-runtime-references
277  void pup(PUP::er& p) override { // NOLINT
279  PUP::pup(p, maps_);
280  }
281 
282  private:
283  friend bool operator==(const CoordinateMap& lhs,
284  const CoordinateMap& rhs) noexcept {
285  return lhs.maps_ == rhs.maps_;
286  }
287 
289  other) const override {
290  const auto& cast_of_other = dynamic_cast<const CoordinateMap&>(other);
291  return *this == cast_of_other;
292  }
293 
294  template <typename T, size_t... Is>
295  constexpr SPECTRE_ALWAYS_INLINE tnsr::I<T, dim, TargetFrame> call_impl(
296  tnsr::I<T, dim, SourceFrame>&& source_point, double time,
298  std::index_sequence<Is...> /*meta*/) const noexcept;
299 
300  template <typename T, size_t... Is>
301  constexpr SPECTRE_ALWAYS_INLINE boost::optional<tnsr::I<T, dim, SourceFrame>>
302  inverse_impl(
303  tnsr::I<T, dim, TargetFrame>&& target_point, double time,
305  std::index_sequence<Is...> /*meta*/) const noexcept;
306 
307  template <typename T>
308  constexpr SPECTRE_ALWAYS_INLINE InverseJacobian<T, dim, SourceFrame,
309  TargetFrame>
310  inv_jacobian_impl(
311  tnsr::I<T, dim, SourceFrame>&& source_point, double time,
312  const std::unordered_map<std::string, FunctionOfTime&>& f_of_t_list) const
313  noexcept;
314 
315  template <typename T>
316  constexpr SPECTRE_ALWAYS_INLINE Jacobian<T, dim, SourceFrame, TargetFrame>
317  jacobian_impl(
318  tnsr::I<T, dim, SourceFrame>&& source_point, double time,
319  const std::unordered_map<std::string, FunctionOfTime&>& f_of_t_list) const
320  noexcept;
321 
322  std::tuple<Maps...> maps_;
323 };
324 
325 ////////////////////////////////////////////////////////////////
326 // CoordinateMap definitions
327 ////////////////////////////////////////////////////////////////
328 
329 // define type-trait to check for time-dependent mapping
330 namespace CoordinateMap_detail {
331 template <typename T>
332 using is_map_time_dependent_t =
335 } // namespace CoordinateMap_detail
336 
337 template <typename SourceFrame, typename TargetFrame, typename... Maps>
339  Maps... maps)
340  : maps_(std::move(maps)...) {}
341 
342 template <typename SourceFrame, typename TargetFrame, typename... Maps>
343 template <typename T, size_t... Is>
344 constexpr SPECTRE_ALWAYS_INLINE tnsr::I<
345  T, CoordinateMap<SourceFrame, TargetFrame, Maps...>::dim, TargetFrame>
347  tnsr::I<T, dim, SourceFrame>&& source_point, const double time,
349  std::index_sequence<Is...> /*meta*/) const noexcept {
350  std::array<T, dim> mapped_point = make_array<T, dim>(std::move(source_point));
351 
353  [](const auto& the_map, std::array<T, dim>& point, const double /*t*/,
355  /*f_of_ts*/,
356  const std::false_type /*is_time_independent*/) noexcept {
357  if (LIKELY(not the_map.is_identity())) {
358  point = the_map(point);
359  }
360  return '0';
361  },
362  [](const auto& the_map, std::array<T, dim>& point, const double t,
364  const std::true_type /*is_time_dependent*/) noexcept {
365  point = the_map(point, t, f_of_ts);
366  return '0';
367  })(std::get<Is>(maps_), mapped_point, time, f_of_t_list,
368  CoordinateMap_detail::is_map_time_dependent_t<Maps>{})...};
369 
370  return tnsr::I<T, dim, TargetFrame>(std::move(mapped_point));
371 }
372 
373 template <typename SourceFrame, typename TargetFrame, typename... Maps>
374 template <typename T, size_t... Is>
375 constexpr SPECTRE_ALWAYS_INLINE boost::optional<tnsr::I<
376  T, CoordinateMap<SourceFrame, TargetFrame, Maps...>::dim, SourceFrame>>
378  tnsr::I<T, dim, TargetFrame>&& target_point, const double time,
380  std::index_sequence<Is...> /*meta*/) const noexcept {
381  boost::optional<std::array<T, dim>> mapped_point(
382  make_array<T, dim>(std::move(target_point)));
383 
385  [](const auto& the_map, boost::optional<std::array<T, dim>>& point,
386  const double /*t*/,
388  /*f_of_ts*/,
389  const std::false_type /*is_time_independent*/) noexcept {
390  if (point) {
391  if (LIKELY(not the_map.is_identity())) {
392  point = the_map.inverse(point.get());
393  }
394  }
395  return '0';
396  },
397  [](const auto& the_map, boost::optional<std::array<T, dim>>& point,
398  const double t,
400  const std::true_type /*is_time_dependent*/) noexcept {
401  if (point) {
402  point = the_map.inverse(point.get(), t, f_of_ts);
403  }
404  return '0';
405  // this is the inverse function, so the iterator sequence below is
406  // reversed
407  })(std::get<sizeof...(Maps) - 1 - Is>(maps_), mapped_point, time,
408  f_of_t_list,
409  CoordinateMap_detail::is_map_time_dependent_t<Maps>{})...};
410 
411  return mapped_point
412  ? tnsr::I<T, dim, SourceFrame>(std::move(mapped_point.get()))
413  : boost::optional<tnsr::I<T, dim, SourceFrame>>{};
414 }
415 
416 // define type-trait to check for time-dependent jacobian
417 namespace CoordinateMap_detail {
418 CREATE_IS_CALLABLE(jacobian)
419 template <typename Map, typename T>
420 using is_jacobian_time_dependent_t =
421  CoordinateMap_detail::is_jacobian_callable_t<
424 } // namespace CoordinateMap_detail
425 
426 template <typename SourceFrame, typename TargetFrame, typename... Maps>
427 template <typename T>
428 constexpr SPECTRE_ALWAYS_INLINE auto
430  tnsr::I<T, dim, SourceFrame>&& source_point, const double time,
431  const std::unordered_map<std::string, FunctionOfTime&>& f_of_t_list) const
432  noexcept -> InverseJacobian<T, dim, SourceFrame, TargetFrame> {
433  std::array<T, dim> mapped_point = make_array<T, dim>(std::move(source_point));
434 
435  InverseJacobian<T, dim, SourceFrame, TargetFrame> inv_jac{};
436 
438  maps_,
439  [&inv_jac, &mapped_point, time, &f_of_t_list](
440  const auto& map, auto index, const std::tuple<Maps...>& maps) {
441  constexpr const size_t count = decltype(index)::value;
442 
443  tnsr::Ij<T, dim, Frame::NoFrame> temp_inv_jac{};
444 
445  // chooses the correct call based on time-dependence of jacobian
446  auto inv_jac_overload = make_overloader(
447  [](const gsl::not_null<tnsr::Ij<T, dim, Frame::NoFrame>*> t_inv_jac,
448  const auto& the_map, const std::array<T, dim>& point,
449  const double /*t*/,
451  /*f_of_ts*/,
452  const std::false_type /*is_time_independent*/) {
453  if (LIKELY(not the_map.is_identity())) {
454  *t_inv_jac = the_map.inv_jacobian(point);
455  } else {
456  *t_inv_jac = identity<dim>(point[0]);
457  }
458  return nullptr;
459  },
461  const auto& the_map, const std::array<T, dim>& point,
462  const double t,
464  const std::true_type /*is_time_dependent*/) {
465  *t_inv_jac = the_map.inv_jacobian(point, t, f_of_ts);
466  return nullptr;
467  });
468 
469  if (LIKELY(count != 0)) {
470  const auto& map_in_loop =
471  std::get<(count != 0 ? count - 1 : 0)>(maps);
472  if (LIKELY(not map_in_loop.is_identity())) {
473  mapped_point = map_in_loop(mapped_point);
474  inv_jac_overload(&temp_inv_jac, map, mapped_point, time,
475  f_of_t_list,
476  CoordinateMap_detail::is_jacobian_time_dependent_t<
477  decltype(map), T>{});
478  std::array<T, dim> temp{};
479  for (size_t source = 0; source < dim; ++source) {
480  for (size_t target = 0; target < dim; ++target) {
481  gsl::at(temp, target) =
482  inv_jac.get(source, 0) * temp_inv_jac.get(0, target);
483  for (size_t dummy = 1; dummy < dim; ++dummy) {
484  gsl::at(temp, target) += inv_jac.get(source, dummy) *
485  temp_inv_jac.get(dummy, target);
486  }
487  }
488  for (size_t target = 0; target < dim; ++target) {
489  inv_jac.get(source, target) = std::move(gsl::at(temp, target));
490  }
491  }
492  }
493  } else {
494  inv_jac_overload(
495  &temp_inv_jac, map, mapped_point, time, f_of_t_list,
496  CoordinateMap_detail::is_jacobian_time_dependent_t<decltype(map),
497  T>{});
498  for (size_t source = 0; source < dim; ++source) {
499  for (size_t target = 0; target < dim; ++target) {
500  inv_jac.get(source, target) =
501  std::move(temp_inv_jac.get(source, target));
502  }
503  }
504  }
505  },
506  maps_);
507  return inv_jac;
508 }
509 
510 template <typename SourceFrame, typename TargetFrame, typename... Maps>
511 template <typename T>
512 constexpr SPECTRE_ALWAYS_INLINE auto
514  tnsr::I<T, dim, SourceFrame>&& source_point, const double time,
515  const std::unordered_map<std::string, FunctionOfTime&>& f_of_t_list) const
516  noexcept -> Jacobian<T, dim, SourceFrame, TargetFrame> {
517  std::array<T, dim> mapped_point = make_array<T, dim>(std::move(source_point));
518  Jacobian<T, dim, SourceFrame, TargetFrame> jac{};
519 
521  maps_,
522  [&jac, &mapped_point, time, &f_of_t_list](
523  const auto& map, auto index, const std::tuple<Maps...>& maps) {
524  constexpr const size_t count = decltype(index)::value;
525 
526  tnsr::Ij<T, dim, Frame::NoFrame> noframe_jac{};
527 
528  // chooses the correct call based on time-dependence of jacobian
529  auto jac_overload = make_overloader(
530  [](const gsl::not_null<tnsr::Ij<T, dim, Frame::NoFrame>*>
531  no_frame_jac,
532  const auto& the_map, const std::array<T, dim>& point,
533  const double /*t*/,
535  /*f_of_ts*/,
536  const std::false_type /*is_time_independent*/) {
537  if (LIKELY(not the_map.is_identity())) {
538  *no_frame_jac = the_map.jacobian(point);
539  } else {
540  *no_frame_jac = identity<dim>(point[0]);
541  }
542  return nullptr;
543  },
545  no_frame_jac,
546  const auto& the_map, const std::array<T, dim>& point,
547  const double t,
549  const std::true_type /*is_time_dependent*/) {
550  *no_frame_jac = the_map.jacobian(point, t, f_of_ts);
551  return nullptr;
552  });
553 
554  if (LIKELY(count != 0)) {
555  const auto& map_in_loop =
556  std::get<(count != 0 ? count - 1 : 0)>(maps);
557  if (LIKELY(not map_in_loop.is_identity())) {
558  mapped_point = map_in_loop(mapped_point);
559  jac_overload(&noframe_jac, map, mapped_point, time, f_of_t_list,
560  CoordinateMap_detail::is_jacobian_time_dependent_t<
561  decltype(map), T>{});
562  std::array<T, dim> temp{};
563  for (size_t source = 0; source < dim; ++source) {
564  for (size_t target = 0; target < dim; ++target) {
565  gsl::at(temp, target) =
566  noframe_jac.get(target, 0) * jac.get(0, source);
567  for (size_t dummy = 1; dummy < dim; ++dummy) {
568  gsl::at(temp, target) +=
569  noframe_jac.get(target, dummy) * jac.get(dummy, source);
570  }
571  }
572  for (size_t target = 0; target < dim; ++target) {
573  jac.get(target, source) = std::move(gsl::at(temp, target));
574  }
575  }
576  }
577  } else {
578  jac_overload(
579  &noframe_jac, map, mapped_point, time, f_of_t_list,
580  CoordinateMap_detail::is_jacobian_time_dependent_t<decltype(map),
581  T>{});
582  for (size_t target = 0; target < dim; ++target) {
583  for (size_t source = 0; source < dim; ++source) {
584  jac.get(target, source) =
585  std::move(noframe_jac.get(target, source));
586  }
587  }
588  }
589  },
590  maps_);
591  return jac;
592 }
593 
594 template <typename SourceFrame, typename TargetFrame, typename... Maps>
595 bool operator!=(
598  return not(lhs == rhs);
599 }
600 
601 /// \ingroup ComputationalDomainGroup
602 /// \brief Creates a `CoordinateMap` of `maps...`
603 template <typename SourceFrame, typename TargetFrame, typename... Maps>
604 constexpr auto make_coordinate_map(Maps&&... maps)
607  std::forward<Maps>(maps)...);
608 }
609 
610 /// \ingroup ComputationalDomainGroup
611 /// \brief Creates a `std::unique_ptr<CoordinateMapBase>` of `maps...`
612 template <typename SourceFrame, typename TargetFrame, typename... Maps>
613 auto make_coordinate_map_base(Maps&&... maps) noexcept
615  SourceFrame, TargetFrame,
617  return std::make_unique<
619  std::forward<Maps>(maps)...);
620 }
621 
622 /// \ingroup ComputationalDomainGroup
623 /// \brief Creates a `std::vector<std::unique_ptr<CoordinateMapBase>>`
624 /// containing the result of `make_coordinate_map_base` applied to each
625 /// argument passed in.
626 template <typename SourceFrame, typename TargetFrame, typename Arg0,
627  typename... Args>
629  Args&&... remaining_args) noexcept
634  return_vector;
635  return_vector.reserve(sizeof...(Args) + 1);
636  return_vector.emplace_back(make_coordinate_map_base<SourceFrame, TargetFrame>(
637  std::forward<Arg0>(arg_0)));
639  (((void)return_vector.emplace_back(
640  make_coordinate_map_base<SourceFrame, TargetFrame>(
641  std::forward<Args>(remaining_args)))),
642  0)...};
643  return return_vector;
644 }
645 
646 /// \ingroup ComputationalDomainGroup
647 /// \brief Creates a `std::vector<std::unique_ptr<CoordinateMapBase>>`
648 /// containing the result of `make_coordinate_map_base` applied to each
649 /// element of the vector of maps composed with the rest of the arguments
650 /// passed in.
651 template <typename SourceFrame, typename TargetFrame, size_t Dim, typename Map,
652  typename... Maps>
654  const Maps&... remaining_maps) noexcept
655  -> std::vector<
658  return_vector;
659  return_vector.reserve(sizeof...(Maps) + 1);
660  for (auto& map : maps) {
661  return_vector.emplace_back(
662  make_coordinate_map_base<SourceFrame, TargetFrame>(std::move(map),
663  remaining_maps...));
664  }
665  return return_vector;
666 }
667 
668 /// \cond
669 template <typename SourceFrame, typename TargetFrame, typename... Maps>
670 PUP::able::PUP_ID
671  CoordinateMap<SourceFrame, TargetFrame, Maps...>::my_PUP_ID = // NOLINT
672  0;
673 /// \endcond
constexpr void tuple_transform(const std::tuple< Elements... > &tuple, N_aryOp &&op, Args &&... args) noexcept(noexcept(tuple_impl_detail::tuple_transform_impl< ReverseIteration >(tuple, std::forward< N_aryOp >(op), std::make_index_sequence< sizeof...(Elements)>{}, args...)))
Perform a transform over a std::tuple.
Definition: Tuple.hpp:164
#define CREATE_IS_CALLABLE(METHOD_NAME)
Generate a type trait to check if a class has a member function that can be invoked with arguments of...
Definition: TypeTraits.hpp:870
Overloader< Fs... > make_overloader(Fs... fs)
Create Overloader<Fs...>, see Overloader for details.
Definition: Overloader.hpp:109
constexpr tnsr::I< double, dim, TargetFrame > operator()(tnsr::I< double, dim, SourceFrame > source_point, const double time=std::numeric_limits< double >::signaling_NaN(), const std::unordered_map< std::string, FunctionOfTime &> &f_of_t_list=std::unordered_map< std::string, FunctionOfTime &>{}) const noexcept override
Apply the Maps... to the point(s) source_point
Definition: CoordinateMap.hpp:195
constexpr Tag::type & get(Variables< TagList > &v) noexcept
Return Tag::type pointing into the contiguous array.
Definition: Variables.hpp:649
Defines function make_array.
Abstract base class for CoordinateMap.
Definition: CoordinateMap.hpp:49
Defines macros to allow serialization of abstract template base classes.
A coordinate map or composition of coordinate maps.
Definition: CoordinateMap.hpp:160
Contains all coordinate maps.
Definition: Affine.cpp:14
typename is_callable< T, Args... >::type is_callable_t
Definition: TypeTraits.hpp:848
auto make_coordinate_map_base(Maps &&... maps) noexcept -> std::unique_ptr< CoordinateMapBase< SourceFrame, TargetFrame, CoordinateMap< SourceFrame, TargetFrame, std::decay_t< Maps >... >::dim >>
Creates a std::unique_ptr<CoordinateMapBase> of maps...
Definition: CoordinateMap.hpp:613
auto make_vector_coordinate_map_base(Arg0 &&arg_0, Args &&... remaining_args) noexcept -> std::vector< std::unique_ptr< CoordinateMapBase< SourceFrame, TargetFrame, std::decay_t< Arg0 >::dim >>>
Creates a std::vector<std::unique_ptr<CoordinateMapBase>> containing the result of make_coordinate_ma...
Definition: CoordinateMap.hpp:628
constexpr tnsr::I< DataVector, dim, TargetFrame > operator()(tnsr::I< DataVector, dim, SourceFrame > source_point, const double time=std::numeric_limits< double >::signaling_NaN(), const std::unordered_map< std::string, FunctionOfTime &> &f_of_t_list=std::unordered_map< std::string, FunctionOfTime &>{}) const noexcept override
Apply the Maps... to the point(s) source_point
Definition: CoordinateMap.hpp:204
#define SPECTRE_ALWAYS_INLINE
Always inline a function. Only use this if you benchmarked the code.
Definition: ForceInline.hpp:20
#define WRAPPED_PUPable_decl_base_template(baseClassName, className)
Mark derived template classes as serializable.
Definition: CharmPupable.hpp:32
PUP routines for new C+11 STL containers and other standard library objects Charm does not provide im...
constexpr InverseJacobian< DataVector, dim, SourceFrame, TargetFrame > inv_jacobian(tnsr::I< DataVector, dim, SourceFrame > source_point, const double time=std::numeric_limits< double >::signaling_NaN(), const std::unordered_map< std::string, FunctionOfTime &> &f_of_t_list=std::unordered_map< std::string, FunctionOfTime &>{}) const noexcept override
Compute the inverse Jacobian of the Maps... at the point(s) source_point
Definition: CoordinateMap.hpp:240
Defines macro to always inline a function.
constexpr InverseJacobian< double, dim, SourceFrame, TargetFrame > inv_jacobian(tnsr::I< double, dim, SourceFrame > source_point, const double time=std::numeric_limits< double >::signaling_NaN(), const std::unordered_map< std::string, FunctionOfTime &> &f_of_t_list=std::unordered_map< std::string, FunctionOfTime &>{}) const noexcept override
Compute the inverse Jacobian of the Maps... at the point(s) source_point
Definition: CoordinateMap.hpp:231
CoordinateMap()=default
Used for Charm++ serialization.
Defines functions for manipulating tuples.
Defines classes for Tensor.
#define WRAPPED_PUPable_abstract(className)
Wraps the Charm++ macro, see the Charm++ documentation.
Definition: CharmPupable.hpp:39
Stores a collection of function values.
Definition: DataVector.hpp:46
Wraps the template metaprogramming library used (brigand)
constexpr Jacobian< double, dim, SourceFrame, TargetFrame > jacobian(tnsr::I< double, dim, SourceFrame > source_point, const double time=std::numeric_limits< double >::signaling_NaN(), const std::unordered_map< std::string, FunctionOfTime &> &f_of_t_list=std::unordered_map< std::string, FunctionOfTime &>{}) const noexcept override
Compute the Jacobian of the Maps... at the point(s) source_point
Definition: CoordinateMap.hpp:252
Base class for FunctionsOfTime.
Definition: FunctionOfTime.hpp:13
Defines functions and classes from the GSL.
#define LIKELY(x)
Definition: Gsl.hpp:66
constexpr boost::optional< tnsr::I< double, dim, SourceFrame > > inverse(tnsr::I< double, dim, TargetFrame > target_point, const double time=std::numeric_limits< double >::signaling_NaN(), const std::unordered_map< std::string, FunctionOfTime &> &f_of_t_list=std::unordered_map< std::string, FunctionOfTime &>{}) const noexcept override
Apply the inverse Maps... to the point(s) target_point
Definition: CoordinateMap.hpp:217
constexpr Jacobian< DataVector, dim, SourceFrame, TargetFrame > jacobian(tnsr::I< DataVector, dim, SourceFrame > source_point, const double time=std::numeric_limits< double >::signaling_NaN(), const std::unordered_map< std::string, FunctionOfTime &> &f_of_t_list=std::unordered_map< std::string, FunctionOfTime &>{}) const noexcept override
Compute the Jacobian of the Maps... at the point(s) source_point
Definition: CoordinateMap.hpp:260
Require a pointer to not be a nullptr
Definition: ConservativeFromPrimitive.hpp:12
Definition: CoordinateMap.hpp:330
constexpr auto make_coordinate_map(Maps &&... maps) -> CoordinateMap< SourceFrame, TargetFrame, std::decay_t< Maps >... >
Creates a CoordinateMap of maps...
Definition: CoordinateMap.hpp:604
constexpr T & at(std::array< T, N > &arr, Size index)
Retrieve a entry from a container, with checks in Debug mode that the index being retrieved is valid...
Definition: Gsl.hpp:124