SpECTRE Documentation Coverage Report
Current view: top level - Domain/FunctionsOfTime - QuaternionFunctionOfTime.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 47.4 % 38 18
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 <boost/math/quaternion.hpp>
       8              : #include <cstddef>
       9              : #include <map>
      10              : #include <memory>
      11              : #include <ostream>
      12              : #include <pup.h>
      13              : #include <vector>
      14              : 
      15              : #include "DataStructures/DataVector.hpp"
      16              : #include "Domain/FunctionsOfTime/FunctionOfTime.hpp"
      17              : #include "Domain/FunctionsOfTime/PiecewisePolynomial.hpp"
      18              : #include "Domain/FunctionsOfTime/ThreadsafeList.hpp"
      19              : #include "Utilities/Gsl.hpp"
      20              : #include "Utilities/Serialization/CharmPupable.hpp"
      21              : 
      22              : namespace domain::FunctionsOfTime {
      23              : /*!
      24              :  * \ingroup ComputationalDomainGroup
      25              :  * \brief A FunctionOfTime that stores quaternions for the rotation map
      26              :  *
      27              :  * \details This FunctionOfTime stores quaternions that will be used in the
      28              :  * time-dependent rotation map as well as the orbital angular velocity that
      29              :  * will be controlled by the rotation control sytem. To get the quaternion, an
      30              :  * ODE is solved of the form \f$ \dot{q} = \frac{1}{2} q \times \omega \f$
      31              :  * where \f$ \omega \f$ is the orbital angular velocity which is stored
      32              :  * internally as the derivative of an angle `PiecewisePolynomial`, and
      33              :  * \f$ \times \f$ here is quaternion multiplication.
      34              :  *
      35              :  * Different from a `PiecewisePolynomial`, only the quaternion
      36              :  * itself is stored, not any of the derivatives because the derivatives must be
      37              :  * calculated from the solved ODE at every function call. Because
      38              :  * derivatives of the quaternion are not stored, the template parameter
      39              :  * `MaxDeriv` refers to both the max derivative of the stored angle
      40              :  * PiecewisePolynomial and the max derivative returned by the
      41              :  * QuaternionFunctionOfTime. The `update` function is then just a wrapper
      42              :  * around the internal `PiecewisePolynomial::update` function with the addition
      43              :  * that it then updates the stored quaternions as well.
      44              :  *
      45              :  * \note The initial rotation angles passed to the angle PiecewisePolynomial
      46              :  * don't matter as we never actually use the angles themselves. We only use
      47              :  * their derivatives (angular velocity) to determine map parameters. In theory
      48              :  * we could determine each initial angle from the input axis-angle
      49              :  * representation, but we don't need to.
      50              :  *
      51              :  * The angle PiecewisePolynomial is accessible through the `angle_func`,
      52              :  * `angle_func_and_deriv`, and `angle_func_and_2_derivs` functions which
      53              :  * correspond to the function calls of a normal PiecewisePolynomial except
      54              :  * without the `angle_` prefix.
      55              :  *
      56              :  * It is encouraged to use `quat_func` and `angle_func` when you want the
      57              :  * specific values of the functions to avoid ambiguity in what you are
      58              :  * calling. However, the original three `func` functions inherited from the
      59              :  * FunctionOfTime base class are necessary because the maps use the generic
      60              :  * `func` functions, thus they return the quaternion and its derivatives (which
      61              :  * are needed for the map). This is all to keep the symmetry of naming
      62              :  * `angle_func` and `quat_func` so that function calls won't be ambiguous.
      63              :  *
      64              :  * \note This class conforms to the requirements of the
      65              :  * `Parallel::GlobalCache` for objects held by mutable global cache tags.
      66              :  */
      67              : template <size_t MaxDeriv>
      68            1 : class QuaternionFunctionOfTime : public FunctionOfTime {
      69              :  public:
      70            0 :   QuaternionFunctionOfTime();
      71            0 :   QuaternionFunctionOfTime(QuaternionFunctionOfTime&&);
      72            0 :   QuaternionFunctionOfTime(const QuaternionFunctionOfTime&);
      73            0 :   QuaternionFunctionOfTime& operator=(QuaternionFunctionOfTime&&);
      74            0 :   QuaternionFunctionOfTime& operator=(const QuaternionFunctionOfTime&);
      75            0 :   ~QuaternionFunctionOfTime() override;
      76              : 
      77            0 :   QuaternionFunctionOfTime(
      78              :       double t, const std::array<DataVector, 1>& initial_quat_func,
      79              :       std::array<DataVector, MaxDeriv + 1> initial_angle_func,
      80              :       double expiration_time);
      81              : 
      82              :   // LCOV_EXCL_START
      83            0 :   explicit QuaternionFunctionOfTime(CkMigrateMessage* /*unused*/);
      84              :   // LCOV_EXCL_STOP
      85              : 
      86            0 :   auto get_clone() const -> std::unique_ptr<FunctionOfTime> override;
      87              : 
      88            1 :   std::unique_ptr<FunctionOfTime> create_at_time(
      89              :       double t, double expiration_time) const override;
      90              : 
      91              :   // clang-tidy: google-runtime-references
      92              :   // clang-tidy: cppcoreguidelines-owning-memory,-warnings-as-errors
      93            0 :   WRAPPED_PUPable_decl_template(QuaternionFunctionOfTime<MaxDeriv>);  // NOLINT
      94              : 
      95              :   /// Returns domain of validity for the function of time
      96            1 :   std::array<double, 2> time_bounds() const override;
      97              : 
      98            1 :   double expiration_after(double time) const override;
      99              : 
     100              :   /// Updates the `MaxDeriv`th derivative of the angle piecewisepolynomial at
     101              :   /// the given time, then updates the stored quaternions.
     102              :   ///
     103              :   /// `updated_max_deriv` is a datavector of the `MaxDeriv`s for each component.
     104              :   /// `next_expiration_time` is the next expiration time.
     105              :   ///
     106              :   /// The \p time_of_update must be the same as the old expiration
     107              :   /// time.  It is passed as a check that the calling code is
     108              :   /// computing the other arguments with the correct value.
     109            1 :   void update(double time_of_update, DataVector updated_max_deriv,
     110              :               double next_expiration_time) override;
     111              : 
     112            1 :   void truncate_at_time(double time) override;
     113              : 
     114              :   // NOLINTNEXTLINE(google-runtime-references)
     115            0 :   void pup(PUP::er& p) override;
     116              : 
     117              :   /// Returns the quaternion at an arbitrary time `t`.
     118            1 :   std::array<DataVector, 1> func(const double t) const override {
     119              :     return quat_func(t);
     120              :   }
     121              : 
     122              :   /// Returns the quaternion and its first derivative at an arbitrary time `t`.
     123            1 :   std::array<DataVector, 2> func_and_deriv(const double t) const override {
     124              :     return quat_func_and_deriv(t);
     125              :   }
     126              : 
     127              :   /// Returns the quaternion and the first two derivatives at an arbitrary
     128              :   /// time `t`.
     129            1 :   std::array<DataVector, 3> func_and_2_derivs(const double t) const override {
     130              :     return quat_func_and_2_derivs(t);
     131              :   }
     132              : 
     133              :   /// Returns the quaternion at an arbitrary time `t`.
     134            1 :   std::array<DataVector, 1> quat_func(double t) const;
     135              : 
     136              :   /// Returns the quaternion and its first derivative at an arbitrary time `t`.
     137            1 :   std::array<DataVector, 2> quat_func_and_deriv(double t) const;
     138              : 
     139              :   /// Returns the quaternion and the first two derivatives at an arbitrary
     140              :   /// time `t`.
     141            1 :   std::array<DataVector, 3> quat_func_and_2_derivs(double t) const;
     142              : 
     143              :   /// Returns the quaternion and the first three derivatives at an arbitrary
     144              :   /// time `t`.
     145            1 :   std::array<DataVector, 4> quat_func_and_3_derivs(double t) const;
     146              : 
     147              :   /// Returns stored angle at an arbitrary time `t`.
     148            1 :   std::array<DataVector, 1> angle_func(const double t) const {
     149              :     return angle_f_of_t_.func(t);
     150              :   }
     151              : 
     152              :   /// Returns stored angle and its first derivative (omega) at an arbitrary time
     153              :   /// `t`.
     154            1 :   std::array<DataVector, 2> angle_func_and_deriv(const double t) const {
     155              :     return angle_f_of_t_.func_and_deriv(t);
     156              :   }
     157              : 
     158              :   /// Returns stored angle and the first two derivatives at an arbitrary
     159              :   /// time `t`.
     160            1 :   std::array<DataVector, 3> angle_func_and_2_derivs(const double t) const {
     161              :     return angle_f_of_t_.func_and_2_derivs(t);
     162              :   }
     163              : 
     164            0 :   std::vector<DataVector> angle_func_and_all_derivs(const double t) const {
     165              :     return angle_f_of_t_.func_and_all_derivs(t);
     166              :   }
     167              : 
     168              :  private:
     169              :   template <size_t LocalMaxDeriv>
     170            0 :   friend bool operator==(  // NOLINT(readability-redundant-declaration)
     171              :       const QuaternionFunctionOfTime<LocalMaxDeriv>& lhs,
     172              :       const QuaternionFunctionOfTime<LocalMaxDeriv>& rhs);
     173              : 
     174              :   template <size_t LocalMaxDeriv>
     175            0 :   friend std::ostream& operator<<(  // NOLINT(readability-redundant-declaration)
     176              :       std::ostream& os,
     177              :       const QuaternionFunctionOfTime<LocalMaxDeriv>& quaternion_f_of_t);
     178              : 
     179              :   FunctionOfTimeHelpers::ThreadsafeList<boost::math::quaternion<double>>
     180            0 :       stored_quaternions_and_times_{};
     181            0 :   domain::FunctionsOfTime::PiecewisePolynomial<MaxDeriv> angle_f_of_t_{};
     182            0 :   std::map<double, double> update_backlog_{};
     183              : 
     184            0 :   void unpack_old_version(PUP::er& p, size_t version);
     185              : 
     186              :   /// Integrates the ODE \f$ \dot{q} = \frac{1}{2} q \times \omega \f$ from time
     187              :   /// `t0` to time `t`. On input, `quaternion_to_integrate` is the initial
     188              :   /// quaternion at time `t0` and on output, it stores the result at time `t`
     189            1 :   void solve_quaternion_ode(
     190              :       gsl::not_null<boost::math::quaternion<double>*> quaternion_to_integrate,
     191              :       double t0, double t) const;
     192              : 
     193              :   /// Does common operations to all the `func` functions such as updating stored
     194              :   /// info, solving the ODE, and returning the normalized quaternion as a boost
     195              :   /// quaternion for easy calculations
     196            1 :   boost::math::quaternion<double> setup_func(double t) const;
     197              : };
     198              : 
     199              : template <size_t MaxDeriv>
     200            0 : bool operator!=(const QuaternionFunctionOfTime<MaxDeriv>& lhs,
     201              :                 const QuaternionFunctionOfTime<MaxDeriv>& rhs);
     202              : 
     203              : /// \cond
     204              : template <size_t MaxDeriv>
     205              : PUP::able::PUP_ID QuaternionFunctionOfTime<MaxDeriv>::my_PUP_ID = 0;  // NOLINT
     206              : /// \endcond
     207              : }  // namespace domain::FunctionsOfTime
        

Generated by: LCOV version 2.0-1