SpECTRE Documentation Coverage Report
Current view: top level - Domain/CoordinateMaps/TimeDependent - Translation.hpp Hit Total Coverage
Commit: ecb8a275e1aebab77dcce48a5e098ed4e486ab4b Lines: 2 32 6.2 %
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 <cstddef>
       8             : #include <memory>
       9             : #include <optional>
      10             : #include <string>
      11             : #include <unordered_map>
      12             : #include <unordered_set>
      13             : 
      14             : #include "DataStructures/Tensor/TypeAliases.hpp"
      15             : #include "PointwiseFunctions/MathFunctions/MathFunction.hpp"
      16             : 
      17             : /// \cond
      18             : namespace domain::FunctionsOfTime {
      19             : class FunctionOfTime;
      20             : }  // namespace domain::FunctionsOfTime
      21             : namespace PUP {
      22             : class er;
      23             : }  // namespace PUP
      24             : /// \endcond
      25             : 
      26             : namespace domain::CoordinateMaps::TimeDependent {
      27             : /*!
      28             :  * \ingroup CoordMapsTimeDependentGroup
      29             :  * \brief Translation map defined by \f$\vec{x} = \vec{\xi}+F(r)\vec{T}(t)\f$
      30             :  * where $F(r)$ takes on different forms based on which constructor is used.
      31             :  *
      32             :  * \details The map adds a translation to the coordinates $\vec{\xi}$ based on
      33             :  * what type of translation is needed. For the piecewise translation, a
      34             :  * translation $F(r)\vec{T}(t)$ is added to $\vec{\xi}$ based on what region
      35             :  * $|\vec{\xi}|$ is in. For coordinates within the inner radius, $F(r) = 1$
      36             :  * causing a uniform translation. Coordinates in between the inner and outer
      37             :  * radius have a linear radial falloff applied to them. Coordinates beyond the
      38             :  * outer radius have no translation applied to them $F(r) = 0$. The piecewise
      39             :  * translation assumes that the center of your map is at (0., 0., 0.). For the
      40             :  * radial MathFunction translation, a radial translation \f$F(r)\vec{T}(t)\f$ is
      41             :  * added to the coordinates \f$\vec{\xi}\f$, where \f$\vec{T}(t)\f$ is a
      42             :  * FunctionOfTime and\f$F(r)\f$ is a 1D radial MathFunction. The radius of each
      43             :  * point is found by subtracting the center map argument from the coordinates
      44             :  * \f$\vec{\xi}\f$ or the target coordinates \f$\vec{\bar{\xi}}\f$. The
      45             :  * Translation Map class is overloaded so that the user can choose between a
      46             :  * piecewise translation, radial translation or a uniform translation based on
      47             :  * their problem. If a radial dependence is not specified, this sets \f$F(r) =
      48             :  * 1\f$.
      49             :  *
      50             :  * ### Mapped Coordinates
      51             :  * The piecewise translation translates the coordinates $\vec{\xi}$
      52             :  * to the target coordinates $\vec{\bar{\xi}}$ based on the region $\vec{\xi}$
      53             :  * is in.
      54             :  * \f{equation}{
      55             :  * \vec{\bar{\xi}} = \left\{\begin{array}{ll}\vec{\xi} + \vec{T}(t), &
      56             :  * |\vec{\xi}| \leq R_{in}, \\ \vec{\xi} + wT(t), &  R_{in} < |\vec{\xi}| <
      57             :  * R_{out}, \\ \vec{\xi}, & |\vec{\xi}| \geq R_{out} \end{array}\right.
      58             :  * \f}
      59             :  *
      60             :  * Where $R_{in}$ is the inner radius, $R_{out}$ is the outer radius, and $w$ is
      61             :  * the radial falloff factor found through
      62             :  * \f{equation}{
      63             :  * w = \frac{R_{out} - |\vec{\xi}|}{R_{out} - R_{in}}
      64             :  * \f}
      65             :  *
      66             :  * The radial MathFunction translation translates the coordinates
      67             :  * \f$\vec{\xi}\f$ to the target coordinates \f{equation}{\vec{\bar{\xi}} =
      68             :  * \vec{\xi} + F(r)\vec{T}(t) \f}
      69             :  *
      70             :  * If you only supply a FunctionOfTime to the constructor of this class, the
      71             :  * radial function will be set to 1.0 causing a uniform translation for your
      72             :  * coordinates. If a FunctionOfTime, MathFunction, and map center are passed in,
      73             :  * the radius will be found through
      74             :  * \f{equation}{
      75             :  * r = |\vec{\xi} - \vec{c}|
      76             :  * \f}
      77             :  * where r is the radius and \f$\vec{c}\f$ is the center argument.
      78             :  *
      79             :  * ### Inverse Translation
      80             :  * The piecewise inverse translates the coordinates
      81             :  * \f$\vec{\bar{\xi}}\f$ to the original coordinates based on what region
      82             :  * $\vec{\bar{\xi}}$ is in.
      83             :  * \f{equation}{
      84             :  * \vec{\xi} = \left\{\begin{array}{ll}\vec{\bar{\xi}} -
      85             :  * \vec{T}(t), & |\vec{\bar{\xi}}| \leq R_{in}, or, |\vec{\bar{\xi}} - T(t)|
      86             :  * \leq R_{in}, \\
      87             :  * \vec{\bar{\xi}} - wT(t), &  R_{in} < |\vec{\bar{\xi}}| < R_{out}, \\
      88             :  * \vec{\bar{\xi}}, & |\vec{\bar{\xi}}| \geq R_{out}\end{array}\right.
      89             :  * \f}
      90             :  * Where $w$ is the radial falloff factor found through a quadratic solve of the
      91             :  * form
      92             :  * \f{equation}{
      93             :  * w^2(\vec{T}(t)^2 - (R_{out} - R_{in})^2) - 2w(\vec{T}(t)\vec{\bar{\xi}} -
      94             :  * R_{out}(R_{out} - R_{in})) + \vec{\bar{\xi}}^2 - R_{out}^2
      95             :  * \f}
      96             :  * The inverse map also assumes that if $\vec{\bar{\xi}}
      97             :  * - \vec{T}(t) \leq R_{in}$ then the translated point originally came from
      98             :  * within the inner radius so it'll be translated back without a quadratic
      99             :  * solve.
     100             :  *
     101             :  * The radial MathFunction inverse translates the coordinates
     102             :  * \f$\vec{\bar{\xi}}\f$ to the original coordinates using
     103             :  * \f{equation}{
     104             :  * \vec{\xi} = \vec{\bar{\xi}} - F(r)\vec{T}(t)
     105             :  * \f}
     106             :  * where \f$r^2\f$ is found as the root of
     107             :  * \f{equation}{
     108             :  *   r^2 = \Big(\vec{\bar{\xi}} - \vec{c} - F(r) \vec{T}(t)\Big)^2.
     109             :  * \f}
     110             :  *
     111             :  * ### Frame Velocity
     112             :  * For the piecewise translation, the frame velocity is found through
     113             :  * \f{equation}{
     114             :  * \vec{v} = \left\{\begin{array}{ll}\frac{\vec{dT}(t)}{dt}, & |\vec{\xi}| \leq
     115             :  * R_{in}, \\ w\frac{\vec{dT}(t)}{dt}, &  R_{in} < |\vec{\xi}| < R_{out}, \\ 0,
     116             :  * & |\vec{\xi}| \geq R_{out} \end{array}\right.
     117             :  * \f}
     118             :  *
     119             :  * For the radial MathFunction translation, the frame velocity is found through
     120             :  * \f{equation}{
     121             :  * \vec{v} = \frac{\vec{dT}(t)}{dt} F(r)
     122             :  * \f}
     123             :  * where \f$\frac{\vec{dT}(t)}{dt}\f$ is the first derivative of the
     124             :  * FunctionOfTime.
     125             :  *
     126             :  * ### Jacobian
     127             :  * For the piecewise translation, the jacobian is computed based on what region
     128             :  * the coordinates $\vec{\xi}$ is in.
     129             :  * \f{equation}{
     130             :  * {J^{i}}_{j} = \frac{dw}{dr} T(t)^i \frac{\xi_j}{r}, R_{in} <
     131             :  * |\vec{\bar{\xi}}| < R_{out}
     132             :  * \f}
     133             :  * otherwise, it will return the identity matrix.
     134             :  *
     135             :  * For the radial MathFunction translation, the jacobian is computed through the
     136             :  * first derivative when the radius is bigger than 1.e-13:
     137             :  * \f{equation}{
     138             :  * {J^{i}}_{j} = \frac{dF(r)}{dr} T(t)^i \frac{(\xi_j - c_j)}{r}
     139             :  * \f}
     140             :  * Where \f$\frac{dF(r)}{dr}\f$ is the first derivative of the MathFunction,
     141             :  * \f$\vec{\xi_j}\f$ is the source coordinates, \f$\vec{c}\f$ is the center of
     142             :  * your map, and r is the radius.
     143             :  *
     144             :  * At a radius smaller than 1e-13, we ASSERT that the radial MathFunction is
     145             :  * smooth $\frac{dF(r)}{dr} \approx 0$, so return the identity matrix.
     146             :  *
     147             :  *
     148             :  * ### Inverse Jacobian
     149             :  * The inverse jacobian is computed numerically by inverting the jacobian.
     150             :  */
     151             : template <size_t Dim>
     152           1 : class Translation {
     153             :  public:
     154           0 :   static constexpr size_t dim = Dim;
     155             : 
     156           0 :   Translation() = default;
     157           0 :   explicit Translation(std::string function_of_time_name);
     158             : 
     159           0 :   explicit Translation(std::string function_of_time_name, double inner_radius,
     160             :                        double outer_radius);
     161             : 
     162           0 :   explicit Translation(
     163             :       std::string function_of_time_name,
     164             :       std::unique_ptr<MathFunction<1, Frame::Inertial>> radial_function,
     165             :       std::array<double, Dim>& center);
     166             : 
     167           0 :   Translation(const Translation<Dim>& Translation_Map);
     168             : 
     169           0 :   ~Translation() = default;
     170           0 :   Translation(Translation&&) = default;
     171           0 :   Translation& operator=(Translation&&) = default;
     172           0 :   Translation& operator=(const Translation& Translation_Map);
     173             : 
     174             :   template <typename T>
     175           0 :   std::array<T, Dim> operator()(
     176             :       const std::array<T, Dim>& source_coords, double time,
     177             :       const std::unordered_map<
     178             :           std::string,
     179             :           std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
     180             :           functions_of_time) const;
     181             : 
     182             :   /// The inverse function is only callable with doubles because the inverse
     183             :   /// might fail if called for a point out of range, and it is unclear
     184             :   /// what should happen if the inverse were to succeed for some points in a
     185             :   /// DataVector but fail for other points.
     186           1 :   std::optional<std::array<double, Dim>> inverse(
     187             :       const std::array<double, Dim>& target_coords, double time,
     188             :       const std::unordered_map<
     189             :           std::string,
     190             :           std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
     191             :           functions_of_time) const;
     192             : 
     193             :   template <typename T>
     194           0 :   std::array<T, Dim> frame_velocity(
     195             :       const std::array<T, Dim>& source_coords, double time,
     196             :       const std::unordered_map<
     197             :           std::string,
     198             :           std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
     199             :           functions_of_time) const;
     200             : 
     201             :   template <typename T>
     202           0 :   tnsr::Ij<T, Dim, Frame::NoFrame> inv_jacobian(
     203             :       const std::array<T, Dim>& source_coords, double time,
     204             :       const std::unordered_map<
     205             :           std::string,
     206             :           std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
     207             :           functions_of_time) const;
     208             : 
     209             :   template <typename T>
     210           0 :   tnsr::Ij<T, Dim, Frame::NoFrame> jacobian(
     211             :       const std::array<T, Dim>& source_coords, double time,
     212             :       const std::unordered_map<
     213             :           std::string,
     214             :           std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
     215             :           functions_of_time) const;
     216             : 
     217             :   // NOLINTNEXTLINE(google-runtime-references)
     218           0 :   void pup(PUP::er& p);
     219             : 
     220           0 :   static bool is_identity() { return false; }
     221             : 
     222           0 :   static constexpr bool supports_hessian{false};
     223             : 
     224           0 :   const std::unordered_set<std::string>& function_of_time_names() const {
     225             :     return f_of_t_names_;
     226             :   }
     227             : 
     228             :  private:
     229             :   template <size_t LocalDim>
     230           0 :   friend bool operator==(  // NOLINT(readability-redundant-declaration)
     231             :       const Translation<LocalDim>& lhs, const Translation<LocalDim>& rhs);
     232             : 
     233             :   // These 2 helper functions compute the translated coordinates or frame
     234             :   // velocity based on the option passed in, 0 for translated coordinates, and
     235             :   // frame velocity for any other number.
     236             :   template <typename T>
     237           0 :   std::array<T, Dim> math_function_helper(
     238             :       const std::array<T, Dim>& source_coords, double time,
     239             :       const std::unordered_map<
     240             :           std::string,
     241             :           std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
     242             :           functions_of_time,
     243             :       size_t function_or_deriv_index) const;
     244             : 
     245             :   template <typename T>
     246           0 :   std::array<T, Dim> piecewise_helper(
     247             :       const std::array<T, Dim>& source_coords, double time,
     248             :       const std::unordered_map<
     249             :           std::string,
     250             :           std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
     251             :           functions_of_time,
     252             :       size_t function_or_deriv_index) const;
     253             : 
     254           0 :   double root_finder(const std::array<double, Dim>& distance_to_center,
     255             :                      const DataVector& function_of_time) const;
     256             : 
     257           0 :   std::string f_of_t_name_{};
     258           0 :   std::unordered_set<std::string> f_of_t_names_;
     259           0 :   std::optional<double> inner_radius_;
     260           0 :   std::optional<double> outer_radius_;
     261           0 :   std::unique_ptr<MathFunction<1, Frame::Inertial>> f_of_r_{};
     262           0 :   std::array<double, Dim> center_{};
     263             : };
     264             : 
     265             : template <size_t Dim>
     266           0 : inline bool operator!=(const Translation<Dim>& lhs,
     267             :                        const Translation<Dim>& rhs) {
     268             :   return not(lhs == rhs);
     269             : }
     270             : 
     271             : }  // namespace domain::CoordinateMaps::TimeDependent

Generated by: LCOV version 1.14