SpECTRE Documentation Coverage Report
Current view: top level - Domain/CoordinateMaps - CoordinateMapHelpers.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 0.0 % 1 0
Test Date: 2026-10-22 17:29:42
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 2.0-1