SpECTRE Documentation Coverage Report
Current view: top level - NumericalAlgorithms/SphericalHarmonics - Tags.hpp Hit Total Coverage
Commit: 3c072f0ce967e2e56649d3fa12aa2a0e4fe2a42e Lines: 18 111 16.2 %
Date: 2024-04-23 20:50:18
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 <string>
       8             : #include <utility>
       9             : 
      10             : #include "DataStructures/DataBox/Tag.hpp"
      11             : #include "DataStructures/DataBox/TagName.hpp"
      12             : #include "DataStructures/DataVector.hpp"
      13             : #include "DataStructures/Tensor/Tensor.hpp"
      14             : #include "NumericalAlgorithms/SphericalHarmonics/Strahlkorper.hpp"
      15             : #include "NumericalAlgorithms/SphericalHarmonics/StrahlkorperFunctions.hpp"
      16             : #include "NumericalAlgorithms/SphericalHarmonics/TagsDeclarations.hpp"
      17             : #include "NumericalAlgorithms/SphericalHarmonics/TagsTypeAliases.hpp"
      18             : #include "PointwiseFunctions/GeneralRelativity/TagsDeclarations.hpp"
      19             : #include "Utilities/ForceInline.hpp"
      20             : #include "Utilities/Gsl.hpp"
      21             : #include "Utilities/TMPL.hpp"
      22             : 
      23             : /// \ingroup SurfacesGroup
      24             : /// Holds tags and ComputeItems associated with a `ylm::Strahlkorper`.
      25           1 : namespace ylm::Tags {
      26             : 
      27             : /// Tag referring to a `ylm::Strahlkorper`
      28             : template <typename Frame>
      29           1 : struct Strahlkorper : db::SimpleTag {
      30           0 :   using type = ylm::Strahlkorper<Frame>;
      31             : };
      32             : 
      33             : /// @{
      34             : /// \f$(\theta,\phi)\f$ on the grid.
      35             : /// Doesn't depend on the shape of the surface.
      36             : template <typename Frame>
      37           1 : struct ThetaPhi : db::SimpleTag {
      38           0 :   using type = tnsr::i<DataVector, 2, ::Frame::Spherical<Frame>>;
      39             : };
      40             : 
      41             : template <typename Frame>
      42           0 : struct ThetaPhiCompute : ThetaPhi<Frame>, db::ComputeTag {
      43           0 :   using base = ThetaPhi<Frame>;
      44           0 :   using return_type = tnsr::i<DataVector, 2, ::Frame::Spherical<Frame>>;
      45           0 :   static constexpr auto function = static_cast<void (*)(
      46             :       const gsl::not_null<tnsr::i<DataVector, 2, ::Frame::Spherical<Frame>>*>,
      47             :       const ylm::Strahlkorper<Frame>&)>(&::ylm::theta_phi<Frame>);
      48           0 :   using argument_tags = tmpl::list<Strahlkorper<Frame>>;
      49             : };
      50             : /// @}
      51             : 
      52             : /// @{
      53             : /// `Rhat(i)` is \f$\hat{r}^i = x_i/\sqrt{x^2+y^2+z^2}\f$ on the grid.
      54             : /// Doesn't depend on the shape of the surface.
      55             : template <typename Frame>
      56           1 : struct Rhat : db::SimpleTag {
      57           0 :   using type = tnsr::i<DataVector, 3, Frame>;
      58             : };
      59             : 
      60             : template <typename Frame>
      61           0 : struct RhatCompute : Rhat<Frame>, db::ComputeTag {
      62           0 :   using base = Rhat<Frame>;
      63           0 :   using return_type = tnsr::i<DataVector, 3, Frame>;
      64           0 :   static constexpr auto function = static_cast<void (*)(
      65             :       const gsl::not_null<tnsr::i<DataVector, 3, Frame>*>,
      66             :       const tnsr::i<DataVector, 2, ::Frame::Spherical<Frame>>&)>(
      67             :       &::ylm::rhat<Frame>);
      68           0 :   using argument_tags = tmpl::list<ThetaPhi<Frame>>;
      69             : };
      70             : /// @}
      71             : 
      72             : /// @{
      73             : /// `Jacobian(i,0)` is \f$\frac{1}{r}\partial x^i/\partial\theta\f$,
      74             : /// and `Jacobian(i,1)`
      75             : /// is \f$\frac{1}{r\sin\theta}\partial x^i/\partial\phi\f$.
      76             : /// Here \f$r\f$ means \f$\sqrt{x^2+y^2+z^2}\f$.
      77             : /// `Jacobian` doesn't depend on the shape of the surface.
      78             : template <typename Frame>
      79           1 : struct Jacobian : db::SimpleTag {
      80           0 :   using type = aliases::Jacobian<Frame>;
      81             : };
      82             : 
      83             : template <typename Frame>
      84           0 : struct JacobianCompute : Jacobian<Frame>, db::ComputeTag {
      85           0 :   using base = Jacobian<Frame>;
      86           0 :   using return_type = aliases::Jacobian<Frame>;
      87           0 :   static constexpr auto function = static_cast<void (*)(
      88             :       const gsl::not_null<ylm::Tags::aliases::Jacobian<Frame>*>,
      89             :       const tnsr::i<DataVector, 2, ::Frame::Spherical<Frame>>&)>(
      90             :       &::ylm::jacobian<Frame>);
      91           0 :   using argument_tags = tmpl::list<ThetaPhi<Frame>>;
      92             : };
      93             : /// @}
      94             : 
      95             : /// @{
      96             : /// `InvJacobian(0,i)` is \f$r\partial\theta/\partial x^i\f$,
      97             : /// and `InvJacobian(1,i)` is \f$r\sin\theta\partial\phi/\partial x^i\f$.
      98             : /// Here \f$r\f$ means \f$\sqrt{x^2+y^2+z^2}\f$.
      99             : /// `InvJacobian` doesn't depend on the shape of the surface.
     100             : template <typename Frame>
     101           1 : struct InvJacobian : db::SimpleTag {
     102           0 :   using type = aliases::InvJacobian<Frame>;
     103             : };
     104             : 
     105             : template <typename Frame>
     106           0 : struct InvJacobianCompute : InvJacobian<Frame>, db::ComputeTag {
     107           0 :   using base = InvJacobian<Frame>;
     108           0 :   using return_type = aliases::InvJacobian<Frame>;
     109           0 :   static constexpr auto function = static_cast<void (*)(
     110             :       const gsl::not_null<ylm::Tags::aliases::InvJacobian<Frame>*>,
     111             :       const tnsr::i<DataVector, 2, ::Frame::Spherical<Frame>>&)>(
     112             :       &::ylm::inv_jacobian<Frame>);
     113           0 :   using argument_tags = tmpl::list<ThetaPhi<Frame>>;
     114             : };
     115             : /// @}
     116             : 
     117             : /// @{
     118             : /// `InvHessian(k,i,j)` is \f$\partial (J^{-1}){}^k_j/\partial x^i\f$,
     119             : /// where \f$(J^{-1}){}^k_j\f$ is the inverse Jacobian.
     120             : /// `InvHessian` is not symmetric because the Jacobians are Pfaffian.
     121             : /// `InvHessian` doesn't depend on the shape of the surface.
     122             : template <typename Frame>
     123           1 : struct InvHessian : db::SimpleTag {
     124           0 :   using type = aliases::InvHessian<Frame>;
     125             : };
     126             : 
     127             : template <typename Frame>
     128           0 : struct InvHessianCompute : InvHessian<Frame>, db::ComputeTag {
     129           0 :   using base = InvHessian<Frame>;
     130           0 :   using return_type = aliases::InvHessian<Frame>;
     131           0 :   static constexpr auto function = static_cast<void (*)(
     132             :       const gsl::not_null<ylm::Tags::aliases::InvHessian<Frame>*>,
     133             :       const tnsr::i<DataVector, 2, ::Frame::Spherical<Frame>>&)>(
     134             :       &::ylm::inv_hessian<Frame>);
     135           0 :   using argument_tags = tmpl::list<ThetaPhi<Frame>>;
     136             : };
     137             : /// @}
     138             : 
     139             : /// @{
     140             : /// (Euclidean) distance \f$r_{\rm surf}(\theta,\phi)\f$ from the center to each
     141             : /// point of the surface.
     142             : template <typename Frame>
     143           1 : struct Radius : db::SimpleTag {
     144           0 :   using type = Scalar<DataVector>;
     145             : };
     146             : 
     147             : template <typename Frame>
     148           0 : struct RadiusCompute : Radius<Frame>, db::ComputeTag {
     149           0 :   using base = Radius<Frame>;
     150           0 :   using return_type = Scalar<DataVector>;
     151           0 :   static constexpr auto function =
     152             :       static_cast<void (*)(const gsl::not_null<Scalar<DataVector>*>,
     153             :                            const ylm::Strahlkorper<Frame>&)>(
     154             :           &(::ylm::radius<Frame>));
     155           0 :   using argument_tags = tmpl::list<Strahlkorper<Frame>>;
     156             : };
     157             : /// @}
     158             : 
     159             : /// @{
     160             : /// The geometrical center of the surface.  Uses
     161             : /// `ylm::Strahlkorper::physical_center`.
     162             : template <typename Frame>
     163           1 : struct PhysicalCenter : db::SimpleTag {
     164           0 :   using type = std::array<double, 3>;
     165             : };
     166             : 
     167             : template <typename Frame>
     168           0 : struct PhysicalCenterCompute : PhysicalCenter<Frame>, db::ComputeTag {
     169           0 :   using base = PhysicalCenter<Frame>;
     170           0 :   using return_type = std::array<double, 3>;
     171           0 :   static void function(gsl::not_null<std::array<double, 3>*> physical_center,
     172             :                        const ylm::Strahlkorper<Frame>& strahlkorper);
     173           0 :   using argument_tags = tmpl::list<Strahlkorper<Frame>>;
     174             : };
     175             : /// @}
     176             : 
     177             : /// @{
     178             : /// `CartesianCoords(i)` is \f$x_{\rm surf}^i\f$,
     179             : /// the vector of \f$(x,y,z)\f$ coordinates of each point
     180             : /// on the surface.
     181             : template <typename Frame>
     182           1 : struct CartesianCoords : db::SimpleTag {
     183           0 :   using type = tnsr::I<DataVector, 3, Frame>;
     184             : };
     185             : 
     186             : template <typename Frame>
     187           0 : struct CartesianCoordsCompute : CartesianCoords<Frame>, db::ComputeTag {
     188           0 :   using base = CartesianCoords<Frame>;
     189           0 :   using return_type = tnsr::I<DataVector, 3, Frame>;
     190           0 :   static constexpr auto function = static_cast<void (*)(
     191             :       const gsl::not_null<tnsr::I<DataVector, 3, Frame>*> coords,
     192             :       const ylm::Strahlkorper<Frame>& strahlkorper,
     193             :       const Scalar<DataVector>& radius,
     194             :       const tnsr::i<DataVector, 3, Frame>& r_hat)>(&ylm::cartesian_coords);
     195           0 :   using argument_tags =
     196             :       tmpl::list<Strahlkorper<Frame>, Radius<Frame>, Rhat<Frame>>;
     197             : };
     198             : /// @}
     199             : 
     200             : /// @{
     201             : /// `DxRadius(i)` is \f$\partial r_{\rm surf}/\partial x^i\f$.  Here
     202             : /// \f$r_{\rm surf}=r_{\rm surf}(\theta,\phi)\f$ is the function
     203             : /// describing the surface, which is considered a function of
     204             : /// Cartesian coordinates
     205             : /// \f$r_{\rm surf}=r_{\rm surf}(\theta(x,y,z),\phi(x,y,z))\f$
     206             : /// for this operation.
     207             : template <typename Frame>
     208           1 : struct DxRadius : db::SimpleTag {
     209           0 :   using type = tnsr::i<DataVector, 3, Frame>;
     210             : };
     211             : 
     212             : template <typename Frame>
     213           0 : struct DxRadiusCompute : DxRadius<Frame>, db::ComputeTag {
     214           0 :   using base = DxRadius<Frame>;
     215           0 :   using return_type = tnsr::i<DataVector, 3, Frame>;
     216           0 :   static constexpr auto function = static_cast<void (*)(
     217             :       const gsl::not_null<tnsr::i<DataVector, 3, Frame>*> dx_radius,
     218             :       const Scalar<DataVector>& scalar,
     219             :       const ylm::Strahlkorper<Frame>& strahlkorper,
     220             :       const Scalar<DataVector>& radius_of_strahlkorper,
     221             :       const aliases::InvJacobian<Frame>& inv_jac)>(
     222             :       &ylm::cartesian_derivs_of_scalar);
     223           0 :   using argument_tags = tmpl::list<Radius<Frame>, Strahlkorper<Frame>,
     224             :                                    Radius<Frame>, InvJacobian<Frame>>;
     225             : };
     226             : /// @}
     227             : 
     228             : /// @{
     229             : /// `D2xRadius(i,j)` is
     230             : /// \f$\partial^2 r_{\rm surf}/\partial x^i\partial x^j\f$. Here
     231             : /// \f$r_{\rm surf}=r_{\rm surf}(\theta,\phi)\f$ is the function
     232             : /// describing the surface, which is considered a function of
     233             : /// Cartesian coordinates
     234             : /// \f$r_{\rm surf}=r_{\rm surf}(\theta(x,y,z),\phi(x,y,z))\f$
     235             : /// for this operation.
     236             : template <typename Frame>
     237           1 : struct D2xRadius : db::SimpleTag {
     238           0 :   using type = tnsr::ii<DataVector, 3, Frame>;
     239             : };
     240             : 
     241             : template <typename Frame>
     242           0 : struct D2xRadiusCompute : D2xRadius<Frame>, db::ComputeTag {
     243           0 :   using base = D2xRadius<Frame>;
     244           0 :   using return_type = tnsr::ii<DataVector, 3, Frame>;
     245           0 :   static constexpr auto function = static_cast<void (*)(
     246             :       gsl::not_null<tnsr::ii<DataVector, 3, Frame>*> d2x_radius,
     247             :       const Scalar<DataVector>& scalar,
     248             :       const ylm::Strahlkorper<Frame>& strahlkorper,
     249             :       const Scalar<DataVector>& radius_of_strahlkorper,
     250             :       const aliases::InvJacobian<Frame>& inv_jac,
     251             :       const aliases::InvHessian<Frame>& inv_hess)>(
     252             :       &ylm::cartesian_second_derivs_of_scalar);
     253           0 :   using argument_tags =
     254             :       tmpl::list<Radius<Frame>, Strahlkorper<Frame>, Radius<Frame>,
     255             :                  InvJacobian<Frame>, InvHessian<Frame>>;
     256             : };
     257             : /// @}
     258             : 
     259             : /// @{
     260             : /// \f$\nabla^2 r_{\rm surf}\f$, the flat Laplacian of the surface.
     261             : /// This is \f$\eta^{ij}\partial^2 r_{\rm surf}/\partial x^i\partial x^j\f$,
     262             : /// where \f$r_{\rm surf}=r_{\rm surf}(\theta(x,y,z),\phi(x,y,z))\f$.
     263             : template <typename Frame>
     264           1 : struct LaplacianRadius : db::SimpleTag {
     265           0 :   using type = Scalar<DataVector>;
     266             : };
     267             : 
     268             : template <typename Frame>
     269           0 : struct LaplacianRadiusCompute : LaplacianRadius<Frame>, db::ComputeTag {
     270           0 :   using base = LaplacianRadius<Frame>;
     271           0 :   using return_type = Scalar<DataVector>;
     272           0 :   static constexpr auto function = static_cast<void (*)(
     273             :       gsl::not_null<Scalar<DataVector>*> lap_radius,
     274             :       const Scalar<DataVector>& radius,
     275             :       const ylm::Strahlkorper<Frame>& strahlkorper,
     276             :       const tnsr::i<DataVector, 2, ::Frame::Spherical<Frame>>& theta_phi)>(
     277             :       &ylm::laplacian_of_scalar);
     278           0 :   using argument_tags =
     279             :       tmpl::list<Radius<Frame>, Strahlkorper<Frame>, ThetaPhi<Frame>>;
     280             : };
     281             : /// @}
     282             : 
     283             : /// @{
     284             : /// `NormalOneForm(i)` is \f$s_i\f$, the (unnormalized) normal one-form
     285             : /// to the surface, expressed in Cartesian components.
     286             : /// This is computed by \f$x_i/r-\partial r_{\rm surf}/\partial x^i\f$,
     287             : /// where \f$x_i/r\f$ is `Rhat` and
     288             : /// \f$\partial r_{\rm surf}/\partial x^i\f$ is `DxRadius`.
     289             : /// See Eq. (8) of \cite Baumgarte1996hh.
     290             : /// Note on the word "normal": \f$s_i\f$ points in the correct direction
     291             : /// (it is "normal" to the surface), but it does not have unit length
     292             : /// (it is not "normalized"; normalization requires a metric).
     293             : template <typename Frame>
     294           1 : struct NormalOneForm : db::SimpleTag {
     295           0 :   using type = tnsr::i<DataVector, 3, Frame>;
     296             : };
     297             : 
     298             : template <typename Frame>
     299           0 : struct NormalOneFormCompute : NormalOneForm<Frame>, db::ComputeTag {
     300           0 :   using base = NormalOneForm<Frame>;
     301           0 :   using return_type = tnsr::i<DataVector, 3, Frame>;
     302           0 :   static constexpr auto function = static_cast<void (*)(
     303             :       gsl::not_null<tnsr::i<DataVector, 3, Frame>*> one_form,
     304             :       const tnsr::i<DataVector, 3, Frame>& dx_radius,
     305             :       const tnsr::i<DataVector, 3, Frame>& r_hat)>(&ylm::normal_one_form);
     306           0 :   using argument_tags = tmpl::list<DxRadius<Frame>, Rhat<Frame>>;
     307             : };
     308             : /// @}
     309             : 
     310             : /// @{
     311             : /// `Tangents(i,j)` is \f$\partial x_{\rm surf}^i/\partial q^j\f$,
     312             : /// where \f$x_{\rm surf}^i\f$ are the Cartesian coordinates of the
     313             : /// surface (i.e. `CartesianCoords`) and are considered functions of
     314             : /// \f$(\theta,\phi)\f$.
     315             : ///
     316             : /// \f$\partial/\partial q^0\f$ means
     317             : /// \f$\partial/\partial\theta\f$; and \f$\partial/\partial q^1\f$
     318             : /// means \f$\csc\theta\,\,\partial/\partial\phi\f$.  Note that the
     319             : /// vectors `Tangents(i,0)` and `Tangents(i,1)` are orthogonal to the
     320             : /// `NormalOneForm` \f$s_i\f$, i.e.
     321             : /// \f$s_i \partial x_{\rm surf}^i/\partial q^j = 0\f$; this statement
     322             : /// is independent of a metric.  Also, `Tangents(i,0)` and
     323             : /// `Tangents(i,1)` are not necessarily orthogonal to each other,
     324             : /// since orthogonality between 2 vectors (as opposed to a vector and
     325             : /// a one-form) is metric-dependent.
     326             : template <typename Frame>
     327           1 : struct Tangents : db::SimpleTag {
     328           0 :   using type = aliases::Jacobian<Frame>;
     329             : };
     330             : 
     331             : template <typename Frame>
     332           0 : struct TangentsCompute : Tangents<Frame>, db::ComputeTag {
     333           0 :   using base = Tangents<Frame>;
     334           0 :   using return_type = aliases::Jacobian<Frame>;
     335           0 :   static constexpr auto function =
     336             :       static_cast<void (*)(gsl::not_null<aliases::Jacobian<Frame>*> tangents,
     337             :                            const ylm::Strahlkorper<Frame>& strahlkorper,
     338             :                            const Scalar<DataVector>& radius,
     339             :                            const tnsr::i<DataVector, 3, Frame>& r_hat,
     340             :                            const aliases::Jacobian<Frame>& jac)>(
     341             :           &ylm::tangents);
     342           0 :   using argument_tags = tmpl::list<Strahlkorper<Frame>, Radius<Frame>,
     343             :                                    Rhat<Frame>, Jacobian<Frame>>;
     344             : };
     345             : /// @}
     346             : 
     347             : /// Tag for holding the previously-found values of a Strahlkorper,
     348             : /// which are saved for extrapolation for future initial guesses
     349             : /// and for computing the time deriv of a Strahlkorper.
     350             : template <typename Frame>
     351           1 : struct PreviousStrahlkorpers : db::SimpleTag {
     352           0 :   using type = std::deque<std::pair<double, ylm::Strahlkorper<Frame>>>;
     353             : };
     354             : 
     355             : /// @{
     356             : /// Tag to compute the time derivative of the coefficients of a Strahlkorper
     357             : /// from a number of previous Strahlkorpers.
     358             : template <typename Frame>
     359           1 : struct TimeDerivStrahlkorper : db::SimpleTag {
     360           0 :   using type = ylm::Strahlkorper<Frame>;
     361             : };
     362             : 
     363             : template <typename Frame>
     364           0 : struct TimeDerivStrahlkorperCompute : db::ComputeTag,
     365             :                                       TimeDerivStrahlkorper<Frame> {
     366           0 :   using base = TimeDerivStrahlkorper<Frame>;
     367           0 :   using return_type = typename base::type;
     368           0 :   static constexpr auto function = static_cast<void (*)(
     369             :       gsl::not_null<ylm::Strahlkorper<Frame>*>,
     370             :       const std::deque<std::pair<double, ylm::Strahlkorper<Frame>>>&)>(
     371             :       &ylm::time_deriv_of_strahlkorper<Frame>);
     372             : 
     373           0 :   using argument_tags = tmpl::list<PreviousStrahlkorpers<Frame>>;
     374             : };
     375             : /// @}
     376             : 
     377             : template <typename Frame>
     378           0 : using items_tags = tmpl::list<Strahlkorper<Frame>>;
     379             : 
     380             : template <typename Frame>
     381           0 : using compute_items_tags =
     382             :     tmpl::list<ThetaPhiCompute<Frame>, RhatCompute<Frame>,
     383             :                JacobianCompute<Frame>, InvJacobianCompute<Frame>,
     384             :                InvHessianCompute<Frame>, RadiusCompute<Frame>,
     385             :                CartesianCoordsCompute<Frame>, DxRadiusCompute<Frame>,
     386             :                D2xRadiusCompute<Frame>, LaplacianRadiusCompute<Frame>,
     387             :                NormalOneFormCompute<Frame>, TangentsCompute<Frame>>;
     388             : }  // namespace ylm::Tags
     389             : 
     390             : /// Tags related to symmetric trace-free tensors
     391           0 : namespace Stf::Tags {
     392             : 
     393             : /*!
     394             :  * \brief Tag used to hold a symmetric trace-free tensor of a certain rank.
     395             :  * \details The type is a symmetric tensor of the requested rank. A
     396             :  * ScalarBaseTag of type `Scalar<double>` is used to identify the tag of which
     397             :  * the symmetric trace-free expansion is done.
     398             :  */
     399             : template <typename ScalarBaseTag, size_t rank, size_t Dim, typename Frame>
     400           1 : struct StfTensor : db::SimpleTag {
     401             :   static_assert(std::is_same_v<typename ScalarBaseTag::type, Scalar<double>>,
     402             :                 "StfTensor base tags must be a Scalar.");
     403             :   static_assert(rank <= 3, "StfTensor tag is only implemented up to rank 3.");
     404           0 :   static std::string name() {
     405             :     return MakeString{} << "StfTensor(" << db::tag_name<ScalarBaseTag>()
     406             :                         << "," << rank << ")";
     407             :   }
     408           0 :   using type_list =
     409             :       tmpl::list<Scalar<double>, tnsr::i<double, Dim, Frame>,
     410             :                  tnsr::ii<double, Dim, Frame>, tnsr::iii<double, Dim, Frame>>;
     411           0 :   using type = tmpl::at<type_list, tmpl::size_t<rank>>;
     412             : };
     413             : }  // namespace Stf::Tags

Generated by: LCOV version 1.14