SpECTRE Documentation Coverage Report
Current view: top level - Domain/CoordinateMaps/TimeDependent/ShapeMapTransitionFunctions - ShapeMapTransitionFunction.hpp Hit Total Coverage
Commit: 1f2210958b4f38fdc0400907ee7c6d5af5111418 Lines: 6 13 46.2 %
Date: 2025-12-05 05:03:31
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 <optional>
       8             : #include <pup.h>
       9             : 
      10             : #include "DataStructures/DataVector.hpp"
      11             : #include "Utilities/Serialization/CharmPupable.hpp"
      12             : 
      13             : namespace domain::CoordinateMaps::ShapeMapTransitionFunctions {
      14             : 
      15             : /*!
      16             :  * \brief Abstract base class for the transition function $G(r,\theta,\phi)$
      17             :  * used by the domain::CoordinateMaps::TimeDependent::Shape map.
      18             :  *
      19             :  * \details This base class defines the required methods of a transition
      20             :  * function that is defined as
      21             :  *
      22             :  * \begin{equation}
      23             :  * G(r,\theta,\phi) = \frac{f(r,\theta,\phi)}{r}
      24             :  * \end{equation}
      25             :  *
      26             :  * where $0 <= f(r,\theta,\phi) <= 1$. Different domains may require the shape
      27             :  * map to fall off towards the boundary in different ways. This behavior is
      28             :  * controlled by the transition function. It is also needed to find the inverse
      29             :  * of the shape map. Since the shape map preserves angles, the problem of
      30             :  * finding its inverse reduces to the 1-dimensional problem of finding the
      31             :  * original radius from the mapped radius. The mapped radius $\tilde{r}$ is
      32             :  * related to the original $r$ radius by:
      33             :  * \begin{equation}
      34             :  * \label{eq:shape_map_radius}
      35             :  * \tilde{r} = r \left(1 - G(r,\theta,\phi)\sum_{lm}
      36             :  *     \lambda_{lm}(t)Y_{lm}(\theta,\phi)\right),
      37             :  * \end{equation}
      38             :  * Depending on the format of the transition function, it should be possible to
      39             :  * analytically derive this map's inverse because it preserves angles and shifts
      40             :  * only the radius of each point. Otherwise the inverse has to be computed
      41             :  * numerically.
      42             :  *
      43             :  * The transition function must also be able to compute the gradient and the
      44             :  * value of the function divided by the radius. Care must be taken that this
      45             :  * does not divide by zero.
      46             :  *
      47             :  * All member functions with the exception of `original_radius_over_radius`
      48             :  * exist as overloads for types `double` and `DataVector` so that they work with
      49             :  * the templated shape map methods calling them. To avoid code duplication these
      50             :  * can be forwarded to templated implementation methods held by the derived
      51             :  * classes only.
      52             :  *
      53             :  * For an example, see SphereTransition.
      54             :  *
      55             :  * #### Design Decisions:
      56             :  *
      57             :  * It was decided to make the ShapeMapTransitionFunction an abstract base class
      58             :  * with overloads for types `double` and `DataVector` corresponding to the
      59             :  * template parameter `T` of the shape map's methods. The shape map holds a
      60             :  * `unique_ptr` to this abstract class using a common dynamic dispatch design
      61             :  * pattern. This approach avoids templating the shape map all together.
      62             :  *
      63             :  * An alternative approach would be to directly template the transition
      64             :  * functions onto the shape map so that no abstract base class is necessary.
      65             :  * These approaches can also be combined by making the transition function an
      66             :  * abstract base class but also templating it onto the shape map. In this way
      67             :  * the shape map does not need to hold a `unique_ptr` but can hold the
      68             :  * transition function directly as a member.
      69             :  */
      70           1 : class ShapeMapTransitionFunction : public PUP::able {
      71             :  public:
      72           0 :   ShapeMapTransitionFunction() = default;
      73             : 
      74             :   /// @{
      75             :   /*!
      76             :    * Evaluate the transition function $G(r,\theta,\phi)$ at the
      77             :    * Cartesian coordinates `source_coords` and possibly divide by the radius
      78             :    * $r$.
      79             :    *
      80             :    * \details If \p one_over_radius_power has a value, then divide $G$ by $r$ to
      81             :    * that power. This is done here because the transition function knows how to
      82             :    * handle points in various regions of the map.
      83             :    */
      84           1 :   virtual double operator()(
      85             :       const std::array<double, 3>& source_coords,
      86             :       const std::optional<size_t>& one_over_radius_power) const = 0;
      87           1 :   virtual DataVector operator()(
      88             :       const std::array<DataVector, 3>& source_coords,
      89             :       const std::optional<size_t>& one_over_radius_power) const = 0;
      90             :   /// @}
      91             : 
      92             :   /*!
      93             :    * \brief The inverse of the transition function
      94             :    *
      95             :    * This method returns $r/\tilde{r}$ given the mapped coordinates
      96             :    * $\tilde{x}^i$ (`target_coords`) and the spherical harmonic expansion
      97             :    * $\Sigma(t, \theta, \phi) = \sum_{lm} \lambda_{lm}(t)Y_{lm}(\theta, \phi)$
      98             :    * (`radial_distortion`). See domain::CoordinateMaps::TimeDependent::Shape for
      99             :    * details on how this quantity is used to compute the inverse of the Shape
     100             :    * map.
     101             :    *
     102             :    * To derive the expression for this inverse, solve Eq.
     103             :    * ($\ref{eq:shape_map_radius}$) for $r$ after substituting
     104             :    * $G(r,\theta,\phi)$.
     105             :    *
     106             :    * \param target_coords The mapped Cartesian coordinates $\tilde{x}^i$.
     107             :    * \param radial_distortion The spherical harmonic expansion
     108             :    * $\Sigma(t, \theta, \phi)$.
     109             :    * \return The quantity $r/\tilde{r}$.
     110             :    */
     111           1 :   virtual std::optional<double> original_radius_over_radius(
     112             :       const std::array<double, 3>& target_coords,
     113             :       double radial_distortion) const = 0;
     114             : 
     115             :   /*!
     116             :    * Evaluate the gradient of the transition function with respect to the
     117             :    * Cartesian coordinates x, y and z at the Cartesian coordinates
     118             :    * `source_coords`.
     119             :    */
     120             :   /// @{
     121           1 :   virtual std::array<double, 3> gradient(
     122             :       const std::array<double, 3>& source_coords) const = 0;
     123           1 :   virtual std::array<DataVector, 3> gradient(
     124             :       const std::array<DataVector, 3>& source_coords) const = 0;
     125             :   /// @}
     126             : 
     127           0 :   virtual std::unique_ptr<ShapeMapTransitionFunction> get_clone() const = 0;
     128             : 
     129           0 :   virtual bool operator==(const ShapeMapTransitionFunction& other) const = 0;
     130           0 :   virtual bool operator!=(const ShapeMapTransitionFunction& other) const = 0;
     131             : 
     132           0 :   WRAPPED_PUPable_abstract(ShapeMapTransitionFunction);
     133           0 :   explicit ShapeMapTransitionFunction(CkMigrateMessage* m) : PUP::able(m) {}
     134             : };
     135             : }  // namespace domain::CoordinateMaps::ShapeMapTransitionFunctions

Generated by: LCOV version 1.14