SpECTRE Documentation Coverage Report
Current view: top level - NumericalAlgorithms/LinearOperators - PartialDerivatives.hpp Coverage Total Hit
Commit: a37d7b3c1803b88b537d2aef1c27ca5e6b499398 Lines: 55.6 % 36 20
Test Date: 2026-11-12 04:47:19
Legend: Lines:     hit not hit

            Line data    Source code
       1            1 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details.
       3              : 
       4              : /// \file
       5              : /// Defines functions computing partial derivatives.
       6              : 
       7              : #pragma once
       8              : 
       9              : #include <array>
      10              : #include <cstddef>
      11              : #include <string>
      12              : 
      13              : #include "DataStructures/DataBox/PrefixHelpers.hpp"
      14              : #include "DataStructures/DataBox/Prefixes.hpp"
      15              : #include "DataStructures/DataBox/Tag.hpp"
      16              : #include "DataStructures/DataBox/TagName.hpp"
      17              : #include "DataStructures/Variables.hpp"
      18              : #include "Utilities/Requires.hpp"
      19              : #include "Utilities/TMPL.hpp"
      20              : #include "Utilities/TypeTraits/IsA.hpp"
      21              : 
      22              : /// \cond
      23              : class DataVector;
      24              : class Matrix;
      25              : template <size_t Dim>
      26              : class Mesh;
      27              : 
      28              : namespace domain {
      29              : namespace Tags {
      30              : template <size_t Dim>
      31              : struct Mesh;
      32              : }  // namespace Tags
      33              : }  // namespace domain
      34              : namespace Tags {
      35              : template <class TagList>
      36              : struct Variables;
      37              : }  // namespace Tags
      38              : /// \endcond
      39              : 
      40              : namespace partial_derivatives_detail {
      41              : void apply_matrix_in_first_dim(double* result, const double* input,
      42              :                                const Matrix& matrix, size_t size,
      43              :                                bool add_to_result = false);
      44              : void apply_matrix_in_first_dim(std::complex<double>* result,
      45              :                                const std::complex<double>* input,
      46              :                                const Matrix& matrix, size_t size,
      47              :                                bool add_to_result = false);
      48              : 
      49              : // Transpose-free differentiation along all logical dimensions using
      50              : // fixed-size kernels (dispatched on the extent of the contracted dimension),
      51              : // writing the logical derivatives directly without the dgemm+transpose
      52              : // pipeline. Returns false when the mesh is not supported (basis other than
      53              : // Legendre/Chebyshev, or an extent outside the instantiated kernel range);
      54              : // the caller must then fall back to the generic implementation.
      55              : bool logical_derivatives_fast_path(const std::array<double*, 1>& logical_derivs,
      56              :                                    const double* u,
      57              :                                    size_t number_of_independent_components,
      58              :                                    const Mesh<1>& mesh);
      59              : bool logical_derivatives_fast_path(const std::array<double*, 2>& logical_derivs,
      60              :                                    const double* u,
      61              :                                    size_t number_of_independent_components,
      62              :                                    const Mesh<2>& mesh);
      63              : bool logical_derivatives_fast_path(const std::array<double*, 3>& logical_derivs,
      64              :                                    const double* u,
      65              :                                    size_t number_of_independent_components,
      66              :                                    const Mesh<3>& mesh);
      67              : 
      68              : // As above, but additionally contracts with the inverse Jacobian one
      69              : // component at a time, so the logical derivatives stay cache-resident and are
      70              : // never written to main memory. `du` must have room for
      71              : // `Dim * number_of_independent_components` components laid out as
      72              : // [component][derivative index][grid points], matching
      73              : // `partial_derivatives_impl`. `inverse_jacobian[d * Dim + i]` must point to
      74              : // the (logical d, inertial i) component. Returns false when the mesh is not
      75              : // supported.
      76              : bool fused_partial_derivatives_fast_path(
      77              :     double* du, const double* u, size_t number_of_independent_components,
      78              :     const Mesh<1>& mesh, const std::array<const double*, 1>& inverse_jacobian);
      79              : bool fused_partial_derivatives_fast_path(
      80              :     double* du, const double* u, size_t number_of_independent_components,
      81              :     const Mesh<2>& mesh, const std::array<const double*, 4>& inverse_jacobian);
      82              : bool fused_partial_derivatives_fast_path(
      83              :     double* du, const double* u, size_t number_of_independent_components,
      84              :     const Mesh<3>& mesh, const std::array<const double*, 9>& inverse_jacobian);
      85              : }  // namespace partial_derivatives_detail
      86              : 
      87              : /// @{
      88              : /// \ingroup NumericalAlgorithmsGroup
      89              : /// \brief Compute the partial derivatives of each variable with respect to
      90              : /// the element logical coordinate.
      91              : ///
      92              : /// \requires `DerivativeTags` to be the head of `VariableTags`
      93              : ///
      94              : /// Returns a `Variables` with a spatial tensor index appended to the front
      95              : /// of each tensor within `u` and each `Tag` wrapped with a `Tags::deriv`.
      96              : ///
      97              : /// \tparam DerivativeTags the subset of `VariableTags` for which derivatives
      98              : /// are computed.
      99              : template <typename DerivativeTags, typename VariableTags, size_t Dim>
     100            1 : void logical_partial_derivatives(
     101              :     gsl::not_null<std::array<Variables<DerivativeTags>, Dim>*>
     102              :         logical_partial_derivatives_of_u,
     103              :     const Variables<VariableTags>& u, const Mesh<Dim>& mesh);
     104              : 
     105              : template <typename DerivativeTags, typename VariableTags, size_t Dim>
     106            1 : auto logical_partial_derivatives(const Variables<VariableTags>& u,
     107              :                                  const Mesh<Dim>& mesh)
     108              :     -> std::array<Variables<DerivativeTags>, Dim>;
     109              : /// @}
     110              : 
     111              : /// @{
     112              : /*!
     113              :  * \ingroup NumericalAlgorithmsGroup
     114              :  * \brief Computes the logical partial derivative of a tensor, prepending the
     115              :  * spatial derivative index, e.g. for \f$\partial_i T_{a}{}^{b}\f$ the C++ call
     116              :  * is `get(i, a, b)`.
     117              :  *
     118              :  * There is an overload that accepts a `buffer` of size
     119              :  * `mesh.number_of_grid_points()` or larger. When passed this function performs
     120              :  * no memory allocations, which helps improve performance.
     121              :  *
     122              :  * If you have a `Variables` with several tensors you need to differentiate you
     123              :  * should use the `logical_partial_derivatives` function that operates on
     124              :  * `Variables` since that'll be more efficient.
     125              :  */
     126              : template <typename DataType, typename SymmList, typename IndexList, size_t Dim>
     127            1 : void logical_partial_derivative(
     128              :     gsl::not_null<TensorMetafunctions::prepend_spatial_index<
     129              :         Tensor<DataType, SymmList, IndexList>, Dim, UpLo::Lo,
     130              :         Frame::ElementLogical>*>
     131              :         logical_derivative_of_u,
     132              :     gsl::not_null<gsl::span<typename DataType::value_type>*> buffer,
     133              :     const Tensor<DataType, SymmList, IndexList>& u, const Mesh<Dim>& mesh);
     134              : 
     135              : template <typename DataType, typename SymmList, typename IndexList, size_t Dim>
     136            1 : void logical_partial_derivative(
     137              :     gsl::not_null<TensorMetafunctions::prepend_spatial_index<
     138              :         Tensor<DataType, SymmList, IndexList>, Dim, UpLo::Lo,
     139              :         Frame::ElementLogical>*>
     140              :         logical_derivative_of_u,
     141              :     const Tensor<DataType, SymmList, IndexList>& u, const Mesh<Dim>& mesh);
     142              : 
     143              : template <typename DataType, typename SymmList, typename IndexList, size_t Dim>
     144            1 : auto logical_partial_derivative(const Tensor<DataType, SymmList, IndexList>& u,
     145              :                                 const Mesh<Dim>& mesh)
     146              :     -> TensorMetafunctions::prepend_spatial_index<
     147              :         Tensor<DataType, SymmList, IndexList>, Dim, UpLo::Lo,
     148              :         Frame::ElementLogical>;
     149              : /// @}
     150              : 
     151              : /// @{
     152              : /*!
     153              :  * \ingroup NumericalAlgorithmsGroup
     154              :  * \brief Compute the partial derivatives of each variable, using the Cartoon
     155              :  * method for directions not in the computational domain.
     156              :  *
     157              :  * For a spacetime with some Killing vector \f$\xi^a\f$, not only does the
     158              :  * metric respect the isometry via \f$\mathcal{L}_\xi g_{ab} = 0\f$, but the
     159              :  * fields must as well.
     160              :  *
     161              :  * In the case of axial symmetry about the \f$y\f$-axis, the Killing vector is
     162              :  * \f$\xi^a = (0, -z, 0, x)\f$, so we have that for a vector \f$V^a\f$,
     163              :  *
     164              :  * \f{align*}{
     165              :  *     \mathcal{L}_\xi V^a &= \xi^b \partial_b V^a - V^b \partial_b \xi^a
     166              :  *       = -z \partial_x V^a + x \partial_z V^a - V^b \partial_b \xi^a = 0.
     167              :  * \f}
     168              :  *
     169              :  * Choosing the computational domain to be the \f$z=0\f$ plane, get the result:
     170              :  *
     171              :  * \f{align*}{
     172              :  *     \partial_z V^a &= \frac{V^b \partial_b \xi^a}{x}.
     173              :  * \f}
     174              :  *
     175              :  * In the case that $x=0$ is in the computational domain, L'H&ocirc;pital's
     176              :  * rule is used. For a general tensor,
     177              :  * \f$T^{a_0,\ldots,a_n}{}_{b_0,\ldots,b_m}\f$ we have
     178              :  *
     179              :  * \f{align*}{
     180              :  *   \partial_z T^{a_0,\ldots,a_n}{}_{b_0,\ldots,b_m} &=
     181              :  *   \left\{
     182              :  *   \begin{array}{ll}
     183              :  *     \partial_x(\sum_k
     184              :  *     T^{a_0,\ldots,c_k,\ldots,a_n}{}_{b_0,\ldots,b_m}\partial_{c_k}
     185              :  *     \xi^{a_k} & \\
     186              :  *     \;\;\;\;\;-\sum_k
     187              :  *     T^{a_0,\ldots,a_n}{}_{b_0,\ldots,c_k,\ldots,b_m}\partial_{b_k}
     188              :  *     \xi^{c_k}
     189              :  *     ) & \mathrm{if} \; x=0  \\
     190              :  *     (\sum_k
     191              :  *     T^{a_0,\ldots,c_k,\ldots,a_n}{}_{b_0,\ldots,b_m}\partial_{c_k}
     192              :  *     \xi^{a_k} & \\
     193              :  *     \;-\sum_k
     194              :  *     T^{a_0,\ldots,a_n}{}_{b_0,\ldots,c_k,\ldots,b_m}\partial_{b_k}
     195              :  *     \xi^{c_k})\frac{1}{x} & \mathrm{otherwise}
     196              :  *   \end{array}\right.
     197              :  * \f}
     198              :  *
     199              :  * In the case of spherical symmetry, another Killing vector
     200              :  * \f$\xi'^a = (0, -y, x, 0) \f$ is used as well, with the above equation
     201              :  * easily generalizing. In that case, the computational domain is only the
     202              :  * \f$x\f$-axis.
     203              :  *
     204              :  * This function computes the partial derivatives of _all_ variables in
     205              :  * `VariableTags`. The additional parameter `inertial_coords` is used for
     206              :  * division by the \f$x\f$ coordinates. If \f$x=0\f$ is included in the domain,
     207              :  * it is assumed to be present only at the first index and is handled by
     208              :  * L'H&ocirc;pital's rule.
     209              :  *
     210              :  * The mesh is required to have the Cartoon basis in the last and potentially
     211              :  * second-to-last coordinates and the inverse Jacobian is accordingly used only
     212              :  * in the first and potentially second dimensions.
     213              :  */
     214              : template <typename ResultTags, typename VariableTags, size_t Dim,
     215              :           typename DerivativeFrame, Requires<Dim == 3> = nullptr>
     216            1 : void cartoon_partial_derivatives(
     217              :     gsl::not_null<Variables<ResultTags>*> du, const Variables<VariableTags>& u,
     218              :     const Mesh<Dim>& mesh,
     219              :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     220              :                           DerivativeFrame>& inverse_jacobian_3d,
     221              :     const tnsr::I<DataVector, Dim, Frame::Inertial>& inertial_coords);
     222              : /// @}
     223              : 
     224              : /// @{
     225              : /// \ingroup NumericalAlgorithmsGroup
     226              : /// \brief Compute the partial derivatives of each variable with respect to
     227              : /// the coordinates of `DerivativeFrame`.
     228              : ///
     229              : /// Either compute partial derivatives of _all_ variables in `VariableTags`, or
     230              : /// of a subset of the `VariablesTags`. The subset of tags (`DerivativeTags`)
     231              : /// must be the head of `VariablesTags`.
     232              : ///
     233              : /// The return-by-reference overload infers all template parameters from the
     234              : /// arguments. The tensor types in the output buffer must have a spatial index
     235              : /// appended to the front.
     236              : ///
     237              : /// The return-by-value overload requires that the `DerivativeTags` are
     238              : /// specified explicitly as the first template parameter. It returns a
     239              : /// `Variables` with the `DerivativeTags` wrapped in `Tags::deriv`.
     240              : template <typename ResultTags, typename DerivativeTags, size_t Dim,
     241              :           typename DerivativeFrame>
     242            1 : void partial_derivatives(
     243              :     gsl::not_null<Variables<ResultTags>*> du,
     244              :     const std::array<Variables<DerivativeTags>, Dim>&
     245              :         logical_partial_derivatives_of_u,
     246              :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     247              :                           DerivativeFrame>& inverse_jacobian);
     248              : 
     249              : template <typename ResultTags, typename VariableTags, size_t Dim,
     250              :           typename DerivativeFrame>
     251            1 : void partial_derivatives(
     252              :     gsl::not_null<Variables<ResultTags>*> du, const Variables<VariableTags>& u,
     253              :     const Mesh<Dim>& mesh,
     254              :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     255              :                           DerivativeFrame>& inverse_jacobian);
     256              : 
     257              : template <typename DerivativeTags, typename VariableTags, size_t Dim,
     258              :           typename DerivativeFrame>
     259            1 : auto partial_derivatives(
     260              :     const Variables<VariableTags>& u, const Mesh<Dim>& mesh,
     261              :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     262              :                           DerivativeFrame>& inverse_jacobian)
     263              :     -> Variables<db::wrap_tags_in<Tags::deriv, DerivativeTags,
     264              :                                   tmpl::size_t<Dim>, DerivativeFrame>>;
     265              : /// @}
     266              : 
     267              : /// @{
     268              : /// \ingroup NumericalAlgorithmsGroup
     269              : /// \brief Compute the partial derivative of a `Tensor` with respect to
     270              : /// the coordinates of `DerivativeFrame`.
     271              : ///
     272              : /// Returns a `Tensor` with a spatial tensor index appended to the front
     273              : /// of the input `Tensor`.
     274              : ///
     275              : /// If you have a `Variables` with several tensors you need to differentiate,
     276              : /// you should use the `partial_derivatives` function that operates on
     277              : /// `Variables` since that'll be more efficient.
     278              : template <typename DataType, typename SymmList, typename IndexList, size_t Dim,
     279              :           typename DerivativeFrame>
     280            1 : void partial_derivative(
     281              :     const gsl::not_null<TensorMetafunctions::prepend_spatial_index<
     282              :         Tensor<DataType, SymmList, IndexList>, Dim, UpLo::Lo, DerivativeFrame>*>
     283              :         du,
     284              :     const TensorMetafunctions::prepend_spatial_index<
     285              :         Tensor<DataType, SymmList, IndexList>, Dim, UpLo::Lo,
     286              :         Frame::ElementLogical>& logical_partial_derivative_of_u,
     287              :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     288              :                           DerivativeFrame>& inverse_jacobian);
     289              : 
     290              : template <typename DataType, typename SymmList, typename IndexList, size_t Dim,
     291              :           typename DerivativeFrame>
     292            1 : void partial_derivative(
     293              :     const gsl::not_null<TensorMetafunctions::prepend_spatial_index<
     294              :         Tensor<DataType, SymmList, IndexList>, Dim, UpLo::Lo, DerivativeFrame>*>
     295              :         du,
     296              :     const Tensor<DataType, SymmList, IndexList>& u, const Mesh<Dim>& mesh,
     297              :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     298              :                           DerivativeFrame>& inverse_jacobian);
     299              : 
     300              : template <typename DataType, typename SymmList, typename IndexList, size_t Dim,
     301              :           typename DerivativeFrame>
     302            1 : auto partial_derivative(
     303              :     const Tensor<DataType, SymmList, IndexList>& u, const Mesh<Dim>& mesh,
     304              :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     305              :                           DerivativeFrame>& inverse_jacobian)
     306              :     -> TensorMetafunctions::prepend_spatial_index<
     307              :         Tensor<DataType, SymmList, IndexList>, Dim, UpLo::Lo, DerivativeFrame>;
     308              : /// @}
     309              : 
     310              : /// @{
     311              : /// \ingroup NumericalAlgorithmsGroup
     312              : /// \brief Compute the partial derivative of a `Tensor` with respect to
     313              : /// the coordinates of `DerivativeFrame` when a Cartoon basis is being used.
     314              : ///
     315              : /// Returns a `Tensor` with a spatial tensor index appended to the front
     316              : /// of the input `Tensor`.
     317              : ///
     318              : /// If you have a `Variables` with several tensors with Cartoon bases you need
     319              : /// to differentiate, you should use the `cartoon_partial_derivatives` function
     320              : /// that operates on `Variables` since that'll be more efficient.
     321              : template <typename SymmList, typename IndexList, size_t Dim,
     322              :           typename DerivativeFrame, Requires<Dim == 3> = nullptr>
     323            1 : void cartoon_partial_derivative(
     324              :     gsl::not_null<TensorMetafunctions::prepend_spatial_index<
     325              :         Tensor<DataVector, SymmList, IndexList>, Dim, UpLo::Lo,
     326              :         DerivativeFrame>*>
     327              :         du,
     328              :     const Tensor<DataVector, SymmList, IndexList>& u, const Mesh<Dim>& mesh,
     329              :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     330              :                           DerivativeFrame>& inverse_jacobian,
     331              :     const tnsr::I<DataVector, Dim, Frame::Inertial>& inertial_coords);
     332              : 
     333              : template <typename SymmList, typename IndexList, size_t Dim,
     334              :           typename DerivativeFrame, Requires<Dim == 3> = nullptr>
     335            1 : auto cartoon_partial_derivative(
     336              :     const Tensor<DataVector, SymmList, IndexList>& u, const Mesh<Dim>& mesh,
     337              :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     338              :                           DerivativeFrame>& inverse_jacobian,
     339              :     const tnsr::I<DataVector, Dim, Frame::Inertial>& inertial_coords)
     340              :     -> TensorMetafunctions::prepend_spatial_index<
     341              :         Tensor<DataVector, SymmList, IndexList>, Dim, UpLo::Lo,
     342              :         DerivativeFrame>;
     343              : /// @}
     344              : 
     345              : /// @{
     346              : /// \ingroup NumericalAlgorithmsGroup
     347              : /// \brief Calls the correct partial derivatives function, either normal
     348              : /// partials or cartoon partials, as determined by mesh basis.
     349              : ///
     350              : /// To be used in executables that allow a Cartoon basis, a choice that is
     351              : /// only known at runtime.
     352              : template <typename ResultTags, typename VariableTags, size_t Dim,
     353              :           typename DerivativeFrame>
     354            1 : void partial_derivatives(
     355              :     gsl::not_null<Variables<ResultTags>*> du,
     356              :     const Variables<VariableTags>& u, const Mesh<Dim>& mesh,
     357              :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     358              :                           DerivativeFrame>& inverse_jacobian,
     359              :     const tnsr::I<DataVector, Dim, Frame::Inertial>& inertial_coords);
     360              : /// @}
     361              : 
     362              : /// @{
     363              : /// \ingroup NumericalAlgorithmsGroup
     364              : /// \brief Calls the correct partial derivative function, either normal
     365              : /// partial or cartoon partial, as determined by mesh basis.
     366              : ///
     367              : /// To be used in executables that allow a Cartoon basis, a choice that is
     368              : /// only known at runtime.
     369              : template <typename SymmList, typename IndexList, size_t Dim,
     370              :           typename DerivativeFrame>
     371            1 : void partial_derivative(
     372              :     gsl::not_null<TensorMetafunctions::prepend_spatial_index<
     373              :         Tensor<DataVector, SymmList, IndexList>, Dim, UpLo::Lo,
     374              :         DerivativeFrame>*>
     375              :         du,
     376              :     const Tensor<DataVector, SymmList, IndexList>& u, const Mesh<Dim>& mesh,
     377              :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     378              :                           DerivativeFrame>& inverse_jacobian,
     379              :     const tnsr::I<DataVector, Dim, Frame::Inertial>& inertial_coords);
     380              : 
     381              : template <typename SymmList, typename IndexList, size_t Dim,
     382              :           typename DerivativeFrame>
     383            1 : auto partial_derivative(
     384              :     const Tensor<DataVector, SymmList, IndexList>& u, const Mesh<Dim>& mesh,
     385              :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     386              :                           DerivativeFrame>& inverse_jacobian,
     387              :     const tnsr::I<DataVector, Dim, Frame::Inertial>& inertial_coords)
     388              :     -> TensorMetafunctions::prepend_spatial_index<
     389              :         Tensor<DataVector, SymmList, IndexList>, Dim, UpLo::Lo,
     390              :         DerivativeFrame>;
     391              : /// @}
     392              : 
     393              : namespace Tags {
     394              : 
     395              : /*!
     396              :  * \ingroup DataBoxTagsGroup
     397              :  * \brief Compute the spatial derivatives of tags in a Variables
     398              :  *
     399              :  * Computes the spatial derivatives of the Tensors in the Variables represented
     400              :  * by `VariablesTag` in the frame mapped to by `InverseJacobianTag`. To only
     401              :  * take the derivatives of a subset of these Tensors you can set the
     402              :  * `DerivTags` template parameter. It takes a `tmpl::list` of the desired
     403              :  * tags and defaults to the full `tags_list` of the Variables.
     404              :  *
     405              :  * For an executable that does not allow a Cartoon basis, the last parameter,
     406              :  * `InertialCoordsTag`, should not be passed.
     407              :  *
     408              :  * This tag may be retrieved via `::Tags::Variables<db::wrap_tags_in<deriv,
     409              :  * DerivTags, Dim, deriv_frame>`.
     410              :  */
     411              : template <typename VariablesTag, typename MeshTag, typename InverseJacobianTag,
     412              :           typename DerivTags = typename VariablesTag::type::tags_list,
     413              :           typename InertialCoordsTag = void>
     414            1 : struct DerivCompute
     415              :     : db::add_tag_prefix<
     416              :           deriv, ::Tags::Variables<DerivTags>,
     417              :           tmpl::size_t<
     418              :               tmpl::back<typename InverseJacobianTag::type::index_list>::dim>,
     419              :           typename tmpl::back<
     420              :               typename InverseJacobianTag::type::index_list>::Frame>,
     421              :       db::ComputeTag {
     422              :  private:
     423            0 :   using inv_jac_indices = typename InverseJacobianTag::type::index_list;
     424            0 :   static constexpr auto Dim = tmpl::back<inv_jac_indices>::dim;
     425            0 :   using deriv_frame = typename tmpl::back<inv_jac_indices>::Frame;
     426              : 
     427              :  public:
     428            0 :   using base = db::add_tag_prefix<
     429              :       deriv, ::Tags::Variables<DerivTags>,
     430              :       tmpl::size_t<
     431              :           tmpl::back<typename InverseJacobianTag::type::index_list>::dim>,
     432              :       typename tmpl::back<
     433              :           typename InverseJacobianTag::type::index_list>::Frame>;
     434            0 :   using return_type = typename base::type;
     435            0 :   static constexpr void function(
     436              :       gsl::not_null<return_type*> du, const typename VariablesTag::type& u,
     437              :       const Mesh<Dim>& mesh,
     438              :       const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     439              :                             deriv_frame>& inverse_jacobian) {
     440              :     partial_derivatives(du, u, mesh, inverse_jacobian);
     441              :   }
     442            0 :   static constexpr void function(
     443              :       gsl::not_null<return_type*> du, const typename VariablesTag::type& u,
     444              :       const Mesh<Dim>& mesh,
     445              :       const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     446              :                             deriv_frame>& inverse_jacobian,
     447              :       const tnsr::I<DataVector, Dim, Frame::Inertial>& inertial_coords) {
     448              :     partial_derivatives(du, u, mesh, inverse_jacobian, inertial_coords);
     449              :   }
     450            0 :   using argument_tags = tmpl::conditional_t<
     451              :       std::is_same_v<void, InertialCoordsTag>,
     452              :       tmpl::list<VariablesTag, MeshTag, InverseJacobianTag>,
     453              :       tmpl::list<VariablesTag, MeshTag, InverseJacobianTag, InertialCoordsTag>>;
     454              : };
     455              : 
     456              : /*!
     457              :  * \ingroup DataBoxTagsGroup
     458              :  * \brief Computes the spatial derivative of a single tensor tag not in a
     459              :  * Variables.
     460              :  *
     461              :  * Computes the spatial derivative for a single tensor represented by
     462              :  * 'TensorTag' in the frame mapped to by 'InverseJacobianTag'. It takes a
     463              :  * single Tensor designated by 'TensorTag', the inverse Jacobian, and a mesh.
     464              :  *
     465              :  * For an executable that does not allow a Cartoon basis, the last parameter,
     466              :  * `InertialCoordsTag`, should not be passed.
     467              :  */
     468              : template <typename TensorTag, typename InverseJacobianTag, typename MeshTag,
     469              :           typename InertialCoordsTag = void>
     470            1 : struct DerivTensorCompute
     471              :     : ::Tags::deriv<TensorTag,
     472              :                     tmpl::size_t<tmpl::back<
     473              :                         typename InverseJacobianTag::type::index_list>::dim>,
     474              :                     typename tmpl::back<
     475              :                         typename InverseJacobianTag::type::index_list>::Frame>,
     476              :       db::ComputeTag {
     477              :  private:
     478            0 :   using inv_jac_indices = typename InverseJacobianTag::type::index_list;
     479            0 :   static constexpr auto Dim = tmpl::back<inv_jac_indices>::dim;
     480            0 :   using deriv_frame = typename tmpl::back<inv_jac_indices>::Frame;
     481              : 
     482              :  public:
     483            0 :   using base = ::Tags::deriv<TensorTag, tmpl::size_t<Dim>, deriv_frame>;
     484            0 :   using return_type = typename base::type;
     485            0 :   static constexpr void function(
     486              :       const gsl::not_null<return_type*> du, const typename TensorTag::type& u,
     487              :       const Mesh<Dim>& mesh,
     488              :       const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     489              :                             deriv_frame>& inverse_jacobian) {
     490              :     partial_derivative(du, u, mesh, inverse_jacobian);
     491              :   }
     492            0 :   static constexpr void function(
     493              :       const gsl::not_null<return_type*> du, const typename TensorTag::type& u,
     494              :       const Mesh<Dim>& mesh,
     495              :       const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     496              :                             deriv_frame>& inverse_jacobian,
     497              :       const tnsr::I<DataVector, Dim, Frame::Inertial>& inertial_coords) {
     498              :     partial_derivative(du, u, mesh, inverse_jacobian, inertial_coords);
     499              :   }
     500            0 :   using argument_tags = tmpl::conditional_t<
     501              :       std::is_same_v<void, InertialCoordsTag>,
     502              :       tmpl::list<TensorTag, MeshTag, InverseJacobianTag>,
     503              :       tmpl::list<TensorTag, MeshTag, InverseJacobianTag, InertialCoordsTag>>;
     504              : };
     505              : }  // namespace Tags
        

Generated by: LCOV version 2.0-1