SpECTRE Documentation Coverage Report
Current view: top level - NumericalAlgorithms/SphericalHarmonics - StrahlkorperFunctions.hpp Hit Total Coverage
Commit: 9b01d30df5d2e946e7e38cc43c008be18ae9b1d2 Lines: 26 27 96.3 %
Date: 2024-04-23 04:54:49
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 <deque>
       7             : #include <utility>
       8             : 
       9             : #include "DataStructures/Tensor/IndexType.hpp"
      10             : #include "DataStructures/Tensor/TypeAliases.hpp"
      11             : #include "NumericalAlgorithms/SphericalHarmonics/TagsTypeAliases.hpp"
      12             : 
      13             : /// \cond
      14             : class DataVector;
      15             : namespace ylm {
      16             : template <typename Fr>
      17             : class Strahlkorper;
      18             : }  // namespace ylm
      19             : template <typename X, typename Symm, typename IndexList>
      20             : class Tensor;
      21             : namespace gsl {
      22             : template <typename>
      23             : struct not_null;
      24             : }  // namespace gsl
      25             : /// \endcond
      26             : 
      27             : /// \ingroup SurfacesGroup
      28             : /// Contains functions that depend on a Strahlkorper but not on a metric.
      29             : namespace ylm {
      30             : /// @{
      31             : /*!
      32             :  * \f$(\theta,\phi)\f$ on the Strahlkorper surface.
      33             :  * Doesn't depend on the shape of the surface.
      34             :  *
      35             :  * We need to choose upper vs lower indices for theta_phi; it doesn't
      36             :  * matter because these are coordinates and not geometric objects, so
      37             :  * we choose lower indices arbitrarily.
      38             :  */
      39             : template <typename Fr>
      40           1 : tnsr::i<DataVector, 2, ::Frame::Spherical<Fr>> theta_phi(
      41             :     const Strahlkorper<Fr>& strahlkorper);
      42             : 
      43             : template <typename Fr>
      44           1 : void theta_phi(
      45             :     const gsl::not_null<tnsr::i<DataVector, 2, ::Frame::Spherical<Fr>>*>
      46             :         theta_phi,
      47             :     const Strahlkorper<Fr>& strahlkorper);
      48             : /// @}
      49             : 
      50             : /// @{
      51             : /*!
      52             :  * `r_hat(i)` is \f$\hat{r}_i = x_i/\sqrt{x^2+y^2+z^2}\f$ on the
      53             :  * Strahlkorper surface.  Doesn't depend on the shape of the surface.
      54             :  *
      55             :  * We need to choose upper vs lower indices for rhat; it doesn't
      56             :  * matter because rhat is a quantity defined with a Euclidean metric,
      57             :  * so we choose the lower index arbitrarily.
      58             :  */
      59             : template <typename Fr>
      60           1 : tnsr::i<DataVector, 3, Fr> rhat(
      61             :     const tnsr::i<DataVector, 2, ::Frame::Spherical<Fr>>& theta_phi);
      62             : 
      63             : template <typename Fr>
      64           1 : void rhat(const gsl::not_null<tnsr::i<DataVector, 3, Fr>*> r_hat,
      65             :           const tnsr::i<DataVector, 2, ::Frame::Spherical<Fr>>& theta_phi);
      66             : /// @}
      67             : 
      68             : /// @{
      69             : /*!
      70             :  * `Jacobian(i,0)` is \f$\frac{1}{r}\partial x^i/\partial\theta\f$,
      71             :  * and `Jacobian(i,1)`
      72             :  * is \f$\frac{1}{r\sin\theta}\partial x^i/\partial\phi\f$.
      73             :  * Here \f$r\f$ means \f$\sqrt{x^2+y^2+z^2}\f$.
      74             :  * `Jacobian` doesn't depend on the shape of the surface.
      75             :  */
      76             : template <typename Fr>
      77           1 : ylm::Tags::aliases::Jacobian<Fr> jacobian(
      78             :     const tnsr::i<DataVector, 2, ::Frame::Spherical<Fr>>& theta_phi);
      79             : 
      80             : template <typename Fr>
      81           1 : void jacobian(const gsl::not_null<ylm::Tags::aliases::Jacobian<Fr>*> jac,
      82             :               const tnsr::i<DataVector, 2, ::Frame::Spherical<Fr>>& theta_phi);
      83             : /// @}
      84             : 
      85             : /// @{
      86             : /*!
      87             :  * `InvJacobian(0,i)` is \f$r\partial\theta/\partial x^i\f$,
      88             :  * and `InvJacobian(1,i)` is \f$r\sin\theta\partial\phi/\partial x^i\f$.
      89             :  * Here \f$r\f$ means \f$\sqrt{x^2+y^2+z^2}\f$.
      90             :  * `InvJacobian` doesn't depend on the shape of the surface.
      91             :  */
      92             : template <typename Fr>
      93           1 : ylm::Tags::aliases::InvJacobian<Fr> inv_jacobian(
      94             :     const tnsr::i<DataVector, 2, ::Frame::Spherical<Fr>>& theta_phi);
      95             : 
      96             : template <typename Fr>
      97           1 : void inv_jacobian(
      98             :     const gsl::not_null<ylm::Tags::aliases::InvJacobian<Fr>*> inv_jac,
      99             :     const tnsr::i<DataVector, 2, ::Frame::Spherical<Fr>>& theta_phi);
     100             : /// @}
     101             : 
     102             : /// @{
     103             : /*!
     104             :  * `InvHessian(k,i,j)` is \f$r\partial (J^{-1}){}^k_j/\partial x^i\f$,
     105             :  * where \f$(J^{-1}){}^k_j\f$ is the inverse Jacobian.
     106             :  * Here \f$r\f$ means \f$\sqrt{x^2+y^2+z^2}\f$.
     107             :  * `InvHessian` is not symmetric because the Jacobians are Pfaffian.
     108             :  * `InvHessian` doesn't depend on the shape of the surface.
     109             :  */
     110             : template <typename Fr>
     111           1 : ylm::Tags::aliases::InvHessian<Fr> inv_hessian(
     112             :     const tnsr::i<DataVector, 2, ::Frame::Spherical<Fr>>& theta_phi);
     113             : 
     114             : template <typename Fr>
     115           1 : void inv_hessian(
     116             :     const gsl::not_null<ylm::Tags::aliases::InvHessian<Fr>*> inv_hess,
     117             :     const tnsr::i<DataVector, 2, ::Frame::Spherical<Fr>>& theta_phi);
     118             : /// @}
     119             : 
     120             : /// @{
     121             : /*!
     122             :  * (Euclidean) distance \f$r_{\rm surf}(\theta,\phi)\f$ from the
     123             :  * expansion center to each point of the Strahlkorper surface.
     124             :  */
     125             : template <typename Fr>
     126           1 : Scalar<DataVector> radius(const Strahlkorper<Fr>& strahlkorper);
     127             : 
     128             : template <typename Fr>
     129           1 : void radius(const gsl::not_null<Scalar<DataVector>*> result,
     130             :             const Strahlkorper<Fr>& strahlkorper);
     131             : /// @}
     132             : 
     133             : /// @{
     134             : /*!
     135             :  * `cartesian_coords(i)` is \f$x_{\rm surf}^i\f$, the vector of \f$(x,y,z)\f$
     136             :  * coordinates of each point on the Strahlkorper surface.
     137             :  *
     138             :  * \param strahlkorper The Strahlkorper surface.
     139             :  * \param radius The radius as a function of angle, as returned by
     140             :  * `ylm::radius`.
     141             :  * \param r_hat The Euclidean radial unit vector as returned by
     142             :  * `ylm::rhat`.
     143             :  */
     144             : template <typename Fr>
     145           1 : tnsr::I<DataVector, 3, Fr> cartesian_coords(
     146             :     const Strahlkorper<Fr>& strahlkorper, const Scalar<DataVector>& radius,
     147             :     const tnsr::i<DataVector, 3, Fr>& r_hat);
     148             : 
     149             : /*!
     150             :  * \param coords The returned Cartesian coordinates.
     151             :  * \param strahlkorper The Strahlkorper surface.
     152             :  * \param radius The radius as a function of angle, as returned by
     153             :  * `ylm::radius`.
     154             :  * \param r_hat The Euclidean radial unit vector as returned by
     155             :  * `ylm::rhat`.
     156             :  */
     157             : template <typename Fr>
     158           1 : void cartesian_coords(const gsl::not_null<tnsr::I<DataVector, 3, Fr>*> coords,
     159             :                       const Strahlkorper<Fr>& strahlkorper,
     160             :                       const Scalar<DataVector>& radius,
     161             :                       const tnsr::i<DataVector, 3, Fr>& r_hat);
     162             : /// @}
     163             : 
     164             : /// @{
     165             : /*!
     166             :  * `dx_scalar(i)` is \f$\partial f/\partial x^i\f$ evaluated on the
     167             :  * surface.  Here \f$f=f(r,\theta,\phi)=f(\theta,\phi)\f$ is some
     168             :  * scalar function independent of the radial coordinate. \f$f\f$ is
     169             :  * considered a function of Cartesian coordinates
     170             :  * \f$f=f(\theta(x,y,z),\phi(x,y,z))\f$ for this operation.
     171             :  *
     172             :  * \param scalar The scalar to be differentiated.
     173             :  * \param strahlkorper The Strahlkorper surface.
     174             :  * \param radius_of_strahlkorper The radius of the Strahlkorper at each
     175             :  * point, as returned by `ylm::radius`.
     176             :  * \param inv_jac The inverse Jacobian as returned by
     177             :  * `ylm::inv_jacobian`
     178             :  */
     179             : template <typename Fr>
     180           1 : tnsr::i<DataVector, 3, Fr> cartesian_derivs_of_scalar(
     181             :     const Scalar<DataVector>& scalar, const Strahlkorper<Fr>& strahlkorper,
     182             :     const Scalar<DataVector>& radius_of_strahlkorper,
     183             :     const ylm::Tags::aliases::InvJacobian<Fr>& inv_jac);
     184             : 
     185             : /*!
     186             :  * \param dx_scalar The returned derivatives of the scalar.
     187             :  * \param scalar The scalar to be differentiated.
     188             :  * \param strahlkorper The Strahlkorper surface.
     189             :  * \param radius_of_strahlkorper The radius of the Strahlkorper at each
     190             :  * point, as returned by `ylm::radius`.
     191             :  * \param inv_jac The inverse Jacobian as returned by
     192             :  * `ylm::inv_jacobian`
     193             :  */
     194             : template <typename Fr>
     195           1 : void cartesian_derivs_of_scalar(
     196             :     const gsl::not_null<tnsr::i<DataVector, 3, Fr>*> dx_scalar,
     197             :     const Scalar<DataVector>& scalar, const Strahlkorper<Fr>& strahlkorper,
     198             :     const Scalar<DataVector>& radius_of_strahlkorper,
     199             :     const ylm::Tags::aliases::InvJacobian<Fr>& inv_jac);
     200             : /// @}
     201             : 
     202             : /// @{
     203             : /*!
     204             :  * `d2x_scalar(i,j)` is \f$\partial^2 f/\partial x^i\partial x^j\f$
     205             :  * evaluated on the surface. Here
     206             :  * \f$f=f(r,\theta,\phi)=f(\theta,\phi)\f$ is some scalar function
     207             :  * independent of the radial coordinate. \f$f\f$ is considered a
     208             :  * function of Cartesian coordinates
     209             :  * \f$f=f(\theta(x,y,z),\phi(x,y,z))\f$ for this operation.
     210             :  *
     211             :  * \param scalar The scalar to be differentiated.
     212             :  * \param strahlkorper The Strahlkorper surface.
     213             :  * \param radius_of_strahlkorper The radius of the Strahlkorper at each
     214             :  * point, as returned by `ylm::radius`.
     215             :  * \param inv_jac The inverse Jacobian as returned by
     216             :  * `ylm::inv_jacobian`
     217             :  * \param inv_hess The inverse Hessian as returned by
     218             :  * `ylm::inv_hessian.
     219             :  */
     220             : template <typename Fr>
     221           1 : tnsr::ii<DataVector, 3, Fr> cartesian_second_derivs_of_scalar(
     222             :     const Scalar<DataVector>& scalar, const Strahlkorper<Fr>& strahlkorper,
     223             :     const Scalar<DataVector>& radius_of_strahlkorper,
     224             :     const ylm::Tags::aliases::InvJacobian<Fr>& inv_jac,
     225             :     const ylm::Tags::aliases::InvHessian<Fr>& inv_hess);
     226             : 
     227             : /*!
     228             :  * \param d2x_scalar The returned 2nd derivatives of the scalar.
     229             :  * \param scalar The scalar to be differentiated.
     230             :  * \param strahlkorper The Strahlkorper surface.
     231             :  * \param radius_of_strahlkorper The radius of the Strahlkorper at each
     232             :  * point, as returned by `ylm::radius`.
     233             :  * \param inv_jac The inverse Jacobian as returned by
     234             :  * `ylm::inv_jacobian`
     235             :  * \param inv_hess The inverse Hessian as returned by
     236             :  * `ylm::inv_hessian.
     237             :  */
     238             : template <typename Fr>
     239           1 : void cartesian_second_derivs_of_scalar(
     240             :     const gsl::not_null<tnsr::ii<DataVector, 3, Fr>*> d2x_scalar,
     241             :     const Scalar<DataVector>& scalar, const Strahlkorper<Fr>& strahlkorper,
     242             :     const Scalar<DataVector>& radius_of_strahlkorper,
     243             :     const ylm::Tags::aliases::InvJacobian<Fr>& inv_jac,
     244             :     const ylm::Tags::aliases::InvHessian<Fr>& inv_hess);
     245             : /// @}
     246             : 
     247             : /// @{
     248             : /*!
     249             :  * \f$\nabla^2 f\f$, the flat Laplacian of a scalar \f$f\f$ on the surface.
     250             :  * This is \f$\eta^{ij}\partial^2 f/\partial x^i\partial x^j\f$,
     251             :  * where \f$f=f(r,\theta,\phi)=f(\theta,\phi)\f$ is some scalar function
     252             :  * independent of the radial coordinate. \f$f\f$ is considered a
     253             :  * function of Cartesian coordinates
     254             :  * \f$f=f(\theta(x,y,z),\phi(x,y,z))\f$ for this operation.
     255             :  *
     256             :  */
     257             : template <typename Fr>
     258           1 : Scalar<DataVector> laplacian_of_scalar(
     259             :     const Scalar<DataVector>& scalar, const Strahlkorper<Fr>& strahlkorper,
     260             :     const tnsr::i<DataVector, 2, ::Frame::Spherical<Fr>>& theta_phi);
     261             : 
     262             : template <typename Fr>
     263           1 : void laplacian_of_scalar(
     264             :     const gsl::not_null<Scalar<DataVector>*> laplacian,
     265             :     const Scalar<DataVector>& scalar, const Strahlkorper<Fr>& strahlkorper,
     266             :     const tnsr::i<DataVector, 2, ::Frame::Spherical<Fr>>& theta_phi);
     267             : /// @}
     268             : 
     269             : /// @{
     270             : /*!
     271             :  * `tangents(i,j)` is \f$\partial x_{\rm surf}^i/\partial q^j\f$,
     272             :  * where \f$x_{\rm surf}^i\f$ are the Cartesian coordinates of the
     273             :  * surface (i.e. `cartesian_coords`) and are considered functions of
     274             :  * \f$(\theta,\phi)\f$.
     275             :  *
     276             :  * \f$\partial/\partial q^0\f$ means
     277             :  * \f$\partial/\partial\theta\f$; and \f$\partial/\partial q^1\f$
     278             :  * means \f$\csc\theta\,\,\partial/\partial\phi\f$.  Note that the
     279             :  * vectors `tangents(i,0)` and `tangents(i,1)` are orthogonal to the
     280             :  * `normal_one_form` \f$s_i\f$, i.e.
     281             :  * \f$s_i \partial x_{\rm surf}^i/\partial q^j = 0\f$; this statement
     282             :  * is independent of a metric.  Also, `tangents(i,0)` and
     283             :  * `tangents(i,1)` are not necessarily orthogonal to each other,
     284             :  * since orthogonality between 2 vectors (as opposed to a vector and
     285             :  * a one-form) is metric-dependent.
     286             :  *
     287             :  * \param strahlkorper The Strahlkorper surface.
     288             :  * \param radius The radius of the Strahlkorper at each
     289             :  * point, as returned by `ylm::radius`.
     290             :  * \param r_hat The radial unit vector as returned by
     291             :  * `ylm::rhat`.
     292             :  * \param jac The jacobian as returned by `ylm::jacobian`.
     293             :  */
     294             : template <typename Fr>
     295           1 : ylm::Tags::aliases::Jacobian<Fr> tangents(
     296             :     const Strahlkorper<Fr>& strahlkorper, const Scalar<DataVector>& radius,
     297             :     const tnsr::i<DataVector, 3, Fr>& r_hat,
     298             :     const ylm::Tags::aliases::Jacobian<Fr>& jac);
     299             : 
     300             : /*!
     301             :  * \param result The computed tangent vectors.
     302             :  * \param strahlkorper The Strahlkorper surface.
     303             :  * \param radius The radius of the Strahlkorper at each
     304             :  * point, as returned by `ylm::radius`.
     305             :  * \param r_hat The radial unit vector as returned by
     306             :  * `ylm::rhat`.
     307             :  * \param jac The jacobian as returned by `ylm::jacobian`.
     308             :  */
     309             : template <typename Fr>
     310           1 : void tangents(const gsl::not_null<ylm::Tags::aliases::Jacobian<Fr>*> result,
     311             :               const Strahlkorper<Fr>& strahlkorper,
     312             :               const Scalar<DataVector>& radius,
     313             :               const tnsr::i<DataVector, 3, Fr>& r_hat,
     314             :               const ylm::Tags::aliases::Jacobian<Fr>& jac);
     315             : /// @}
     316             : 
     317             : /// @{
     318             : /*!
     319             :  * `normal_one_form(i)` is \f$s_i\f$, the (unnormalized) normal one-form
     320             :  * to the surface, expressed in Cartesian components.
     321             :  * This is computed by \f$x_i/r-\partial r_{\rm surf}/\partial x^i\f$,
     322             :  * where \f$x_i/r\f$ is `Rhat` and
     323             :  * \f$\partial r_{\rm surf}/\partial x^i\f$ is `DxRadius`.
     324             :  * See Eq. (8) of \cite Baumgarte1996hh.
     325             :  * Note on the word "normal": \f$s_i\f$ points in the correct direction
     326             :  * (it is "normal" to the surface), but it does not have unit length
     327             :  * (it is not "normalized"; normalization requires a metric).
     328             :  *
     329             :  * \param dx_radius The Cartesian derivatives of the radius, as
     330             :  * returned by ylm::cartesian_derivs_of_scalar with
     331             :  * `ylm::radius` passed in as the scalar.
     332             :  * \param r_hat The radial unit vector as returned by
     333             :  * `ylm::rhat`.
     334             :  */
     335             : template <typename Fr>
     336           1 : tnsr::i<DataVector, 3, Fr> normal_one_form(
     337             :     const tnsr::i<DataVector, 3, Fr>& dx_radius,
     338             :     const tnsr::i<DataVector, 3, Fr>& r_hat);
     339             : 
     340             : /*!
     341             :  * \param one_form The returned normal one form.
     342             :  * \param dx_radius The Cartesian derivatives of the radius, as
     343             :  * returned by ylm::cartesian_derivs_of_scalar with
     344             :  * `ylm::radius` passed in as the scalar.
     345             :  * \param r_hat The radial unit vector as returned by
     346             :  * `ylm::rhat`.
     347             :  */
     348             : template <typename Fr>
     349           1 : void normal_one_form(const gsl::not_null<tnsr::i<DataVector, 3, Fr>*> one_form,
     350             :                      const tnsr::i<DataVector, 3, Fr>& dx_radius,
     351             :                      const tnsr::i<DataVector, 3, Fr>& r_hat);
     352             : 
     353             : /// @{
     354             : /*!
     355             :  * The linear least squares fit of the polynomial of order 3
     356             :  * given a `std::vector` of `Strahlkorper`s to their \f$Y_l^m\f$ coefficients.
     357             :  * Assumes the the \f$l_{\max}\f$ and \f$m_{\max}\f$ of each `Strahlkorper`
     358             :  * are the same, and the returned vector consists of \f$2l_{\max}m_{\max}\f$
     359             :  * (the number of \f$Y_l^m\f$ coefficients) `std::array<double, 4>`s, each of
     360             :  * which consists of the four coefficients that define the best fit cubic to
     361             :  * each \f$Y_l^m\f$ coefficient of the `Strahlkorper` as a function of time.
     362             :  *
     363             :  * \param times The time corresponding to each `Strahlkorper` to be fit to.
     364             :  * \param strahlkorpers The `Strahlkorper` surfaces which consists of a set
     365             :  * of \f$Y_l^m\f$ coefficients corresponding to the shape of the `Strahlkorper`
     366             :  * at a particular time.
     367             :  */
     368             : template <typename Fr>
     369           1 : std::vector<std::array<double, 4>> fit_ylm_coeffs(
     370             :     const DataVector& times,
     371             :     const std::vector<Strahlkorper<Fr>>& strahlkorpers);
     372             : 
     373             : /*!
     374             :  * \brief Compute the time derivative of a Strahlkorper from a number of
     375             :  * previous Strahlkorpers
     376             :  *
     377             :  * \details Does simple 1D FD with non-uniform spacing using
     378             :  * `fd::non_uniform_1d_weights`.
     379             :  * \param time_deriv Strahlkorper whose coefficients are the time derivative of
     380             :  * `previous_strahlkorpers`' coefficients.
     381             :  * \param previous_strahlkorpers All previous Strahlkorpers and the times they
     382             :  * are at. They are expected to have the most recent Strahlkorper in the front
     383             :  * and the Strahlkorper furthest in the past in the back of the deque.
     384             :  */
     385             : template <typename Frame>
     386           1 : void time_deriv_of_strahlkorper(
     387             :     gsl::not_null<Strahlkorper<Frame>*> time_deriv,
     388             :     const std::deque<std::pair<double, Strahlkorper<Frame>>>&
     389             :         previous_strahlkorpers);
     390             : }  // namespace ylm

Generated by: LCOV version 1.14