SpECTRE Documentation Coverage Report
Current view: top level - Domain/CoordinateMaps - CoordinateMapHelpers.hpp Hit Total Coverage
Commit: ecb8a275e1aebab77dcce48a5e098ed4e486ab4b Lines: 0 1 0.0 %
Date: 2026-08-22 01:05:40
Legend: Lines: hit not hit

          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 <memory>
       8             : #include <string>
       9             : #include <type_traits>
      10             : #include <unordered_map>
      11             : 
      12             : #include "DataStructures/DataVector.hpp"
      13             : #include "DataStructures/Tensor/Identity.hpp"
      14             : #include "DataStructures/Tensor/Tensor.hpp"
      15             : #include "Domain/FunctionsOfTime/FunctionOfTime.hpp"
      16             : #include "Utilities/ErrorHandling/FloatingPointExceptions.hpp"
      17             : #include "Utilities/Gsl.hpp"
      18             : 
      19             : namespace domain {
      20             : namespace CoordinateMap_detail {
      21             : /// Returns a value that aliases `x` where that is cheaper than copying: a
      22             : /// non-owning view for `DataVector` and a copy for arithmetic types such as
      23             : /// `double`. Coordinate maps that pass (a subset of) their source coordinates
      24             : /// on to another map use this function to avoid copying the underlying data.
      25             : /// Coordinate maps take their source coordinates by const reference, so the
      26             : /// data is never modified through the view. The view must not outlive `x`.
      27             : template <typename T>
      28             : T view_or_copy(const T& x) {
      29             :   if constexpr (std::is_same_v<T, DataVector>) {
      30             :     return {const_cast<double*>(x.data()), x.size()};  // NOLINT
      31             :   } else {
      32             :     return x;
      33             :   }
      34             : }
      35             : /// @{
      36             : /// Call the map passing in the time and FunctionsOfTime if the map is
      37             : /// time-dependent
      38             : template <typename T, size_t Dim, typename Map>
      39             : void apply_map(
      40             :     const gsl::not_null<std::array<T, Dim>*> t_map_point, const Map& the_map,
      41             :     const double /*t*/,
      42             :     const std::unordered_map<
      43             :         std::string, std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
      44             :     /*functions_of_time*/,
      45             :     const std::false_type /*is_time_independent*/) {
      46             :   if (LIKELY(not the_map.is_identity())) {
      47             :     *t_map_point = the_map(*t_map_point);
      48             :   }
      49             : }
      50             : 
      51             : template <typename T, size_t Dim, typename Map>
      52             : void apply_map(
      53             :     const gsl::not_null<std::array<T, Dim>*> t_map_point, const Map& the_map,
      54             :     const double t,
      55             :     const std::unordered_map<
      56             :         std::string, std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
      57             :         functions_of_time,
      58             :     const std::true_type
      59             :     /*is_time_dependent*/) {
      60             :   ASSERT(not functions_of_time.empty(),
      61             :          "A function of time must be present if the maps are time-dependent.");
      62             :   ASSERT(
      63             :       [t]() {
      64             :         const ScopedFpeState disable_fpes(false);
      65             :         return not std::isnan(t);
      66             :       }(),
      67             :       "The time must not be NaN for time-dependent maps.");
      68             :   *t_map_point = the_map(*t_map_point, t, functions_of_time);
      69             : }
      70             : 
      71             : template <typename T, size_t Dim, typename Map>
      72             : auto apply_map(
      73             :     const Map& the_map, const std::array<T, Dim>& source_points,
      74             :     const double /*t*/,
      75             :     const std::unordered_map<
      76             :         std::string, std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
      77             :     /*functions_of_time*/,
      78             :     const std::false_type /*is_time_independent*/) {
      79             :   if (LIKELY(not the_map.is_identity())) {
      80             :     return the_map(source_points);
      81             :   }
      82             :   std::decay_t<decltype(the_map(source_points))> result{};
      83             :   for (size_t i = 0; i < result.size(); ++i) {
      84             :     gsl::at(result, i) = gsl::at(source_points, i);
      85             :   }
      86             :   return result;
      87             : }
      88             : 
      89             : template <typename T, size_t Dim, typename Map>
      90             : auto apply_map(
      91             :     const Map& the_map, const std::array<T, Dim>& source_points, const double t,
      92             :     const std::unordered_map<
      93             :         std::string, std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
      94             :         functions_of_time,
      95             :     const std::true_type
      96             :     /*is_time_dependent*/) {
      97             :   // Note: We don't forward to the return-by-not-null version to avoid
      98             :   // additional allocations of the target points array. That is, we would
      99             :   // allocate the target points array once here, and then again inside the call
     100             :   // to the coordinate map.
     101             :   ASSERT(not functions_of_time.empty(),
     102             :          "A function of time must be present if the maps are time-dependent.");
     103             :   ASSERT(
     104             :       [t]() {
     105             :         const ScopedFpeState disable_fpes(false);
     106             :         return not std::isnan(t);
     107             :       }(),
     108             :       "The time must not be NaN for time-dependent maps.");
     109             :   return the_map(source_points, t, functions_of_time);
     110             : }
     111             : /// @}
     112             : 
     113             : /// @{
     114             : template <typename T, size_t Dim, typename Map>
     115             : auto apply_inverse_map(
     116             :     const Map& the_map, const std::array<T, Dim>& target_points,
     117             :     const double /*t*/,
     118             :     const std::unordered_map<
     119             :         std::string, std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
     120             :     /*functions_of_time*/,
     121             :     const std::false_type /*is_time_independent*/) {
     122             :   if (LIKELY(not the_map.is_identity())) {
     123             :     return the_map.inverse(target_points);
     124             :   }
     125             :   std::decay_t<decltype(the_map.inverse(target_points))> result{
     126             :       std::array<T, Dim>{}};
     127             :   for (size_t i = 0; i < target_points.size(); ++i) {
     128             :     gsl::at(*result, i) = gsl::at(target_points, i);
     129             :   }
     130             :   return result;
     131             : }
     132             : 
     133             : template <typename T, size_t Dim, typename Map>
     134             : auto apply_inverse_map(
     135             :     const Map& the_map, const std::array<T, Dim>& target_points, const double t,
     136             :     const std::unordered_map<
     137             :         std::string, std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
     138             :         functions_of_time,
     139             :     const std::true_type
     140             :     /*is_time_dependent*/) {
     141             :   ASSERT(not functions_of_time.empty(),
     142             :          "A function of time must be present if the maps are time-dependent.");
     143             :   ASSERT(
     144             :       [t]() {
     145             :         const ScopedFpeState disable_fpes(false);
     146             :         return not std::isnan(t);
     147             :       }(),
     148             :       "The time must not be NaN for time-dependent maps.");
     149             :   return the_map.inverse(target_points, t, functions_of_time);
     150             : }
     151             : /// @}
     152             : 
     153             : /// @{
     154             : /// Compute the frame velocity
     155             : template <typename T, size_t Dim, typename Map>
     156             : auto apply_frame_velocity(
     157             :     const Map& /*the_map*/, const std::array<T, Dim>& source_points,
     158             :     const double /*t*/,
     159             :     const std::unordered_map<
     160             :         std::string, std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
     161             :     /*functions_of_time*/,
     162             :     const std::false_type /*is_time_independent*/) {
     163             :   return make_array<Map::dim, T>(make_with_value<T>(source_points[0], 0.0));
     164             : }
     165             : 
     166             : template <typename T, size_t Dim, typename Map>
     167             : auto apply_frame_velocity(
     168             :     const Map& the_map, const std::array<T, Dim>& source_points, const double t,
     169             :     const std::unordered_map<
     170             :         std::string, std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
     171             :         functions_of_time,
     172             :     const std::true_type
     173             :     /*is_time_dependent*/) {
     174             :   ASSERT(not functions_of_time.empty(),
     175             :          "A function of time must be present if the maps are time-dependent.");
     176             :   ASSERT(
     177             :       [t]() {
     178             :         const ScopedFpeState disable_fpes(false);
     179             :         return not std::isnan(t);
     180             :       }(),
     181             :       "The time must not be NaN for time-dependent maps.");
     182             :   return the_map.frame_velocity(source_points, t, functions_of_time);
     183             : }
     184             : /// @}
     185             : 
     186             : /// @{
     187             : /// Compute the Jacobian
     188             : template <typename T, size_t Dim, typename Map>
     189             : auto apply_jacobian(
     190             :     const Map& the_map, const std::array<T, Dim>& source_points,
     191             :     const double /*t*/,
     192             :     const std::unordered_map<
     193             :         std::string, std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
     194             :     /*functions_of_time*/,
     195             :     const std::false_type /*is_time_independent*/) {
     196             :   if (LIKELY(not the_map.is_identity())) {
     197             :     return the_map.jacobian(source_points);
     198             :   }
     199             :   return identity<Dim>(source_points[0]);
     200             : }
     201             : 
     202             : template <typename T, size_t Dim, typename Map>
     203             : auto apply_jacobian(
     204             :     const Map& the_map, const std::array<T, Dim>& source_points, const double t,
     205             :     const std::unordered_map<
     206             :         std::string, std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
     207             :         functions_of_time,
     208             :     const std::true_type
     209             :     /*is_time_dependent*/) {
     210             :   ASSERT(not functions_of_time.empty(),
     211             :          "A function of time must be present if the maps are time-dependent.");
     212             :   ASSERT(
     213             :       [t]() {
     214             :         const ScopedFpeState disable_fpes(false);
     215             :         return not std::isnan(t);
     216             :       }(),
     217             :       "The time must not be NaN for time-dependent maps.");
     218             :   if (LIKELY(not the_map.is_identity())) {
     219             :     return the_map.jacobian(source_points, t, functions_of_time);
     220             :   }
     221             :   return identity<Dim>(source_points[0]);
     222             : }
     223             : /// @}
     224             : 
     225             : /// @{
     226             : /// Compute the Jacobian
     227             : template <typename T, size_t Dim, typename Map>
     228             : auto apply_inverse_jacobian(
     229             :     const Map& the_map, const std::array<T, Dim>& source_points,
     230             :     const double /*t*/,
     231             :     const std::unordered_map<
     232             :         std::string, std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
     233             :     /*functions_of_time*/,
     234             :     const std::false_type /*is_time_independent*/) {
     235             :   if (LIKELY(not the_map.is_identity())) {
     236             :     return the_map.inv_jacobian(source_points);
     237             :   }
     238             :   return identity<Dim>(source_points[0]);
     239             : }
     240             : 
     241             : template <typename T, size_t Dim, typename Map>
     242             : auto apply_inverse_jacobian(
     243             :     const Map& the_map, const std::array<T, Dim>& source_points, const double t,
     244             :     const std::unordered_map<
     245             :         std::string, std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
     246             :         functions_of_time,
     247             :     const std::true_type
     248             :     /*is_time_dependent*/) {
     249             :   ASSERT(not functions_of_time.empty(),
     250             :          "A function of time must be present if the maps are time-dependent.");
     251             :   ASSERT(
     252             :       [t]() {
     253             :         const ScopedFpeState disable_fpes(false);
     254             :         return not std::isnan(t);
     255             :       }(),
     256             :       "The time must not be NaN for time-dependent maps.");
     257             :   if (LIKELY(not the_map.is_identity())) {
     258             :     return the_map.inv_jacobian(source_points, t, functions_of_time);
     259             :   }
     260             :   return identity<Dim>(source_points[0]);
     261             : }
     262             : /// @}
     263             : }  // namespace CoordinateMap_detail
     264             : }  // namespace domain

Generated by: LCOV version 1.14