SpECTRE Documentation Coverage Report
Current view: top level - NumericalAlgorithms/LinearOperators - Divergence.hpp Hit Total Coverage
Commit: 1f2210958b4f38fdc0400907ee7c6d5af5111418 Lines: 15 30 50.0 %
Date: 2025-12-05 05:03:31
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 and tags for taking a divergence.
       6             : 
       7             : #pragma once
       8             : 
       9             : #include <cstddef>
      10             : #include <string>
      11             : 
      12             : #include "DataStructures/DataBox/PrefixHelpers.hpp"
      13             : #include "DataStructures/DataBox/Tag.hpp"
      14             : #include "DataStructures/DataBox/TagName.hpp"
      15             : #include "DataStructures/Tensor/Tensor.hpp"
      16             : #include "Utilities/TMPL.hpp"
      17             : #include "Utilities/TypeTraits.hpp"
      18             : #include "Utilities/TypeTraits/IsA.hpp"
      19             : 
      20             : /// \cond
      21             : class DataVector;
      22             : template <size_t Dim>
      23             : class Mesh;
      24             : template <typename TagsList>
      25             : class Variables;
      26             : 
      27             : namespace domain {
      28             : namespace Tags {
      29             : template <size_t Dim>
      30             : struct Mesh;
      31             : }  // namespace Tags
      32             : }  // namespace domain
      33             : /// \endcond
      34             : 
      35             : namespace Tags {
      36             : /// \ingroup DataBoxTagsGroup
      37             : /// \brief Prefix indicating the divergence
      38             : ///
      39             : /// Prefix indicating the divergence of a Tensor.
      40             : ///
      41             : /// \see Tags::DivVectorCompute Tags::DivVariablesCompute
      42             : template <typename Tag>
      43             :   requires(tt::is_a_v<Tensor, typename Tag::type>)
      44           1 : struct div : db::PrefixTag, db::SimpleTag {
      45           0 :   using tag = Tag;
      46           0 :   using type = TensorMetafunctions::remove_first_index<typename Tag::type>;
      47             : };
      48             : }  // namespace Tags
      49             : 
      50             : /// @{
      51             : /// \ingroup NumericalAlgorithmsGroup
      52             : /// \brief Compute the (Euclidean) divergence of fluxes
      53             : template <typename FluxTags, size_t Dim, typename DerivativeFrame>
      54           1 : auto divergence(const Variables<FluxTags>& F, const Mesh<Dim>& mesh,
      55             :                 const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
      56             :                                       DerivativeFrame>& inverse_jacobian)
      57             :     -> Variables<db::wrap_tags_in<Tags::div, FluxTags>>;
      58             : 
      59             : template <typename... DivTags, typename... FluxTags, size_t Dim,
      60             :           typename DerivativeFrame>
      61           1 : void divergence(
      62             :     gsl::not_null<Variables<tmpl::list<DivTags...>>*> divergence_of_F,
      63             :     const Variables<tmpl::list<FluxTags...>>& F, const Mesh<Dim>& mesh,
      64             :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
      65             :                           DerivativeFrame>& inverse_jacobian);
      66             : /// @}
      67             : 
      68             : /// @{
      69             : /// \ingroup NumericalAlgorithmsGroup
      70             : /// \brief Compute the divergence of the vector `input`
      71             : template <typename DataType, size_t Dim, typename DerivativeFrame>
      72           1 : Scalar<DataType> divergence(
      73             :     const tnsr::I<DataType, Dim, DerivativeFrame>& input, const Mesh<Dim>& mesh,
      74             :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
      75             :                           DerivativeFrame>& inverse_jacobian);
      76             : 
      77             : template <typename DataType, size_t Dim, typename DerivativeFrame>
      78           1 : void divergence(gsl::not_null<Scalar<DataType>*> div_input,
      79             :                 const tnsr::I<DataType, Dim, DerivativeFrame>& input,
      80             :                 const Mesh<Dim>& mesh,
      81             :                 const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
      82             :                                       DerivativeFrame>& inverse_jacobian);
      83             : /// @}
      84             : 
      85             : /// @{
      86             : /*!
      87             :  * \ingroup NumericalAlgorithmsGroup
      88             :  * \brief Compute the divergence of fluxes where a Cartoon basis is being
      89             :  * utilized.
      90             :  *
      91             :  * The additional parameter `inertial_coords` is used for division by the
      92             :  * \f$x\f$ coordinates. If \f$x=0\f$ is included in the domain, it is assumed to
      93             :  * be present only at the first index and is handled by L'H&ocirc;pital's rule.
      94             :  *
      95             :  * The mesh is required to have the Cartoon basis in the last and potentially
      96             :  * second-to-last coordinates and the inverse jacobian is accordingly used only
      97             :  * in the first and potentially second dimensions.
      98             :  *
      99             :  * \see cartoon_partial_derivatives for details on Cartoon derivatives.
     100             :  */
     101             : template <typename... DivTags, typename... FluxTags, size_t Dim,
     102             :           typename DerivativeFrame, Requires<Dim == 3> = nullptr>
     103           1 : void cartoon_divergence(
     104             :     gsl::not_null<Variables<tmpl::list<DivTags...>>*> divergence_of_F,
     105             :     const Variables<tmpl::list<FluxTags...>>& F, const Mesh<Dim>& mesh,
     106             :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     107             :                           DerivativeFrame>& inverse_jacobian_3d,
     108             :     const tnsr::I<DataVector, Dim, Frame::Inertial>& inertial_coords);
     109             : /// @}
     110             : 
     111             : /// @{
     112             : /*!
     113             :  * \ingroup NumericalAlgorithmsGroup
     114             :  * \brief Calls the correct divergence function, either normal divergence or
     115             :  * cartoon divergence, as determined by mesh basis.
     116             :  *
     117             :  * If you have a `Variables` with several tensors with Cartoon bases you need
     118             :  * to find the divergence of, you should use the `divergence` function
     119             :  * that operates on `Variables` since that'll be more efficient.
     120             :  */
     121             : template <typename... DivTags, typename... FluxTags, size_t Dim,
     122             :           typename DerivativeFrame>
     123           1 : void divergence(
     124             :     gsl::not_null<Variables<tmpl::list<DivTags...>>*> div_fluxes,
     125             :     const Variables<tmpl::list<FluxTags...>>& fluxes, const Mesh<Dim>& mesh,
     126             :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     127             :                           DerivativeFrame>& inverse_jacobian_3d,
     128             :     const tnsr::I<DataVector, Dim, Frame::Inertial>& inertial_coords);
     129             : template <typename DataType, size_t Dim, typename DerivativeFrame>
     130           1 : void divergence(
     131             :     gsl::not_null<Scalar<DataType>*> div_input,
     132             :     const tnsr::I<DataType, Dim, DerivativeFrame>& input, const Mesh<Dim>& mesh,
     133             :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     134             :                           DerivativeFrame>& inverse_jacobian,
     135             :     const tnsr::I<DataVector, Dim, Frame::Inertial>& inertial_coords);
     136             : template <typename DataType, size_t Dim, typename DerivativeFrame>
     137           1 : Scalar<DataType> divergence(
     138             :     const tnsr::I<DataType, Dim, DerivativeFrame>& input, const Mesh<Dim>& mesh,
     139             :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
     140             :                           DerivativeFrame>& inverse_jacobian,
     141             :     const tnsr::I<DataVector, Dim, Frame::Inertial>& inertial_coords);
     142             : /// @}
     143             : 
     144             : /// @{
     145             : /*!
     146             :  * \brief Compute the divergence of fluxes in logical coordinates
     147             :  *
     148             :  * Applies the logical differentiation matrix to the fluxes in each dimension
     149             :  * and sums over dimensions.
     150             :  *
     151             :  * \see divergence
     152             :  */
     153             : template <typename ResultTensor, typename FluxTensor, size_t Dim>
     154           1 : void logical_divergence(gsl::not_null<ResultTensor*> div_flux,
     155             :                         const FluxTensor& flux, const Mesh<Dim>& mesh);
     156             : 
     157             : template <typename FluxTags, size_t Dim>
     158           1 : auto logical_divergence(const Variables<FluxTags>& flux, const Mesh<Dim>& mesh)
     159             :     -> Variables<db::wrap_tags_in<Tags::div, FluxTags>>;
     160             : 
     161             : template <typename... DivTags, typename... FluxTags, size_t Dim>
     162           1 : void logical_divergence(
     163             :     gsl::not_null<Variables<tmpl::list<DivTags...>>*> div_flux,
     164             :     const Variables<tmpl::list<FluxTags...>>& flux, const Mesh<Dim>& mesh);
     165             : /// @}
     166             : 
     167             : namespace Tags {
     168             : /*!
     169             :  * \ingroup DataBoxTagsGroup
     170             :  * \brief Compute the divergence of a Variables
     171             :  *
     172             :  * Computes the divergence of the every Tensor in the Variables represented by
     173             :  * `Tag`. The first index of each Tensor must be an upper spatial index, i.e.,
     174             :  * the first index must have type
     175             :  * `TensorIndexType<Dim, UpLo::Up, Frame::TargetFrame, IndexType::Spatial>`.
     176             :  * The divergence is computed in the frame `TargetFrame`, and
     177             :  * `InverseJacobianTag` must be associated with a map from
     178             :  * `Frame::ElementLogical` to `Frame::TargetFrame`.
     179             :  *
     180             :  * Note that each tensor may have additional tensor indices - in this case the
     181             :  * divergence is computed for each additional index. For instance, a tensor
     182             :  * \f$F^i_{ab}\f$ has divergence
     183             :  * \f$Div_{ab} = \partial_i F^i_{ab}\f$. This is to accommodate evolution
     184             :  * equations where the evolved variables \f$u_\alpha\f$ are higher-rank tensors
     185             :  * and thus their fluxes can be written as \f$F^i_\alpha\f$. A simple example
     186             :  * would be the fluid velocity in hydro systems, where we would write the flux
     187             :  * as \f$F^{ij}\f$.
     188             :  *
     189             :  * This tag inherits from `db::add_tag_prefix<Tags::div, Tag>`.
     190             :  */
     191             : template <typename Tag, typename MeshTag, typename InverseJacobianTag>
     192           1 : struct DivVariablesCompute : db::add_tag_prefix<div, Tag>, db::ComputeTag {
     193             :  private:
     194           0 :   using inv_jac_indices = typename InverseJacobianTag::type::index_list;
     195           0 :   static constexpr auto dim = tmpl::back<inv_jac_indices>::dim;
     196             :   static_assert(std::is_same_v<typename tmpl::front<inv_jac_indices>::Frame,
     197             :                                Frame::ElementLogical>,
     198             :                 "Must map from the logical frame.");
     199             : 
     200             :  public:
     201           0 :   using base = db::add_tag_prefix<div, Tag>;
     202           0 :   using return_type = typename base::type;
     203           0 :   static constexpr void (*function)(
     204             :       const gsl::not_null<return_type*>, const typename Tag::type&,
     205             :       const Mesh<dim>&, const typename InverseJacobianTag::type&) = &divergence;
     206           0 :   using argument_tags =
     207             :       tmpl::list<Tag, domain::Tags::Mesh<dim>, InverseJacobianTag>;
     208             : };
     209             : 
     210             : /// \ingroup DataBoxTagsGroup
     211             : /// \brief Compute the divergence of a `tnsr::I` (vector)
     212             : ///
     213             : /// This tag inherits from `db::add_tag_prefix<Tags::div, Tag>`.
     214             : ///
     215             : /// For an executable that does not allow a Cartoon basis, the last parameter,
     216             : /// `InertialCoordsTag`, should not be passed.
     217             : template <typename Tag, typename MeshTag, typename InverseJacobianTag,
     218             :           typename InertialCoordsTag = void>
     219           1 : struct DivVectorCompute : div<Tag>, db::ComputeTag {
     220             :  private:
     221           0 :   using inv_jac_indices = typename InverseJacobianTag::type::index_list;
     222           0 :   static constexpr auto dim = tmpl::back<inv_jac_indices>::dim;
     223             :   static_assert(std::is_same_v<typename tmpl::front<inv_jac_indices>::Frame,
     224             :                                Frame::ElementLogical>,
     225             :                 "Must map from the logical frame.");
     226             : 
     227             :  public:
     228           0 :   using base = div<Tag>;
     229           0 :   using return_type = typename base::type;
     230           0 :   static constexpr void function(
     231             :       const gsl::not_null<return_type*> div_input,
     232             :       const typename Tag::type& input, const Mesh<dim>& mesh,
     233             :       const typename InverseJacobianTag::type& inverse_jacobian) {
     234             :     divergence(div_input, input, mesh, inverse_jacobian);
     235             :   }
     236           0 :   static constexpr void function(
     237             :       const gsl::not_null<return_type*> div_input,
     238             :       const typename Tag::type& input, const Mesh<dim>& mesh,
     239             :       const typename InverseJacobianTag::type& inverse_jacobian,
     240             :       const tnsr::I<DataVector, dim, Frame::Inertial>& inertial_coords) {
     241             :     divergence(div_input, input, mesh, inverse_jacobian, inertial_coords);
     242             :   }
     243           0 :   using argument_tags = tmpl::conditional_t<
     244             :       std::is_same_v<void, InertialCoordsTag>,
     245             :       tmpl::list<Tag, MeshTag, InverseJacobianTag>,
     246             :       tmpl::list<Tag, MeshTag, InverseJacobianTag, InertialCoordsTag>>;
     247             : };
     248             : }  // namespace Tags

Generated by: LCOV version 1.14