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/Requires.hpp"
17 : #include "Utilities/TMPL.hpp"
18 : #include "Utilities/TypeTraits.hpp" // IWYU pragma: keep
19 : #include "Utilities/TypeTraits/IsA.hpp"
20 :
21 : /// \cond
22 : class DataVector;
23 : template <size_t Dim>
24 : class Mesh;
25 : template <typename TagsList>
26 : class Variables;
27 :
28 : namespace domain {
29 : namespace Tags {
30 : template <size_t Dim>
31 : struct Mesh;
32 : } // namespace Tags
33 : } // namespace domain
34 : /// \endcond
35 :
36 : namespace Tags {
37 : /// \ingroup DataBoxTagsGroup
38 : /// \brief Prefix indicating the divergence
39 : ///
40 : /// Prefix indicating the divergence of a Tensor.
41 : ///
42 : /// \see Tags::DivVectorCompute Tags::DivVariablesCompute
43 : template <typename Tag, typename = std::nullptr_t>
44 1 : struct div;
45 :
46 : /// \cond
47 : template <typename Tag>
48 : struct div<Tag, Requires<tt::is_a_v<Tensor, typename Tag::type>>>
49 : : db::PrefixTag, db::SimpleTag {
50 : using tag = Tag;
51 : using type = TensorMetafunctions::remove_first_index<typename Tag::type>;
52 : };
53 : /// \endcond
54 : } // namespace Tags
55 :
56 : /// @{
57 : /// \ingroup NumericalAlgorithmsGroup
58 : /// \brief Compute the (Euclidean) divergence of fluxes
59 : template <typename FluxTags, size_t Dim, typename DerivativeFrame>
60 1 : auto divergence(
61 : const Variables<FluxTags>& F, const Mesh<Dim>& mesh,
62 : const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
63 : DerivativeFrame>& inverse_jacobian)
64 : -> Variables<db::wrap_tags_in<Tags::div, FluxTags>>;
65 :
66 : template <typename... DivTags, typename... FluxTags, size_t Dim,
67 : typename DerivativeFrame>
68 1 : void divergence(
69 : gsl::not_null<Variables<tmpl::list<DivTags...>>*> divergence_of_F,
70 : const Variables<tmpl::list<FluxTags...>>& F, const Mesh<Dim>& mesh,
71 : const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
72 : DerivativeFrame>& inverse_jacobian);
73 : /// @}
74 :
75 : /// @{
76 : /// \ingroup NumericalAlgorithmsGroup
77 : /// \brief Compute the divergence of the vector `input`
78 : template <size_t Dim, typename DerivativeFrame>
79 1 : Scalar<DataVector> divergence(
80 : const tnsr::I<DataVector, Dim, DerivativeFrame>& input,
81 : const Mesh<Dim>& mesh,
82 : const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
83 : DerivativeFrame>& inverse_jacobian);
84 :
85 : template <size_t Dim, typename DerivativeFrame>
86 1 : void divergence(
87 : gsl::not_null<Scalar<DataVector>*> div_input,
88 : const tnsr::I<DataVector, Dim, DerivativeFrame>& input,
89 : const Mesh<Dim>& mesh,
90 : const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
91 : DerivativeFrame>& inverse_jacobian);
92 : /// @}
93 :
94 : namespace Tags {
95 : /*!
96 : * \ingroup DataBoxTagsGroup
97 : * \brief Compute the divergence of a Variables
98 : *
99 : * Computes the divergence of the every Tensor in the Variables represented by
100 : * `Tag`. The first index of each Tensor must be an upper spatial index, i.e.,
101 : * the first index must have type
102 : * `TensorIndexType<Dim, UpLo::Up, Frame::TargetFrame, IndexType::Spatial>`.
103 : * The divergence is computed in the frame `TargetFrame`, and
104 : * `InverseJacobianTag` must be associated with a map from
105 : * `Frame::ElementLogical` to `Frame::TargetFrame`.
106 : *
107 : * Note that each tensor may have additional tensor indices - in this case the
108 : * divergence is computed for each additional index. For instance, a tensor
109 : * \f$F^i_{ab}\f$ has divergence
110 : * \f$Div_{ab} = \partial_i F^i_{ab}\f$. This is to accommodate evolution
111 : * equations where the evolved variables \f$u_\alpha\f$ are higher-rank tensors
112 : * and thus their fluxes can be written as \f$F^i_\alpha\f$. A simple example
113 : * would be the fluid velocity in hydro systems, where we would write the flux
114 : * as \f$F^{ij}\f$.
115 : *
116 : * This tag inherits from `db::add_tag_prefix<Tags::div, Tag>`.
117 : */
118 : template <typename Tag, typename MeshTag, typename InverseJacobianTag>
119 1 : struct DivVariablesCompute : db::add_tag_prefix<div, Tag>, db::ComputeTag {
120 : private:
121 0 : using inv_jac_indices = typename InverseJacobianTag::type::index_list;
122 0 : static constexpr auto dim = tmpl::back<inv_jac_indices>::dim;
123 : static_assert(std::is_same_v<typename tmpl::front<inv_jac_indices>::Frame,
124 : Frame::ElementLogical>,
125 : "Must map from the logical frame.");
126 :
127 : public:
128 0 : using base = db::add_tag_prefix<div, Tag>;
129 0 : using return_type = typename base::type;
130 0 : static constexpr void (*function)(
131 : const gsl::not_null<return_type*>, const typename Tag::type&,
132 : const Mesh<dim>&, const typename InverseJacobianTag::type&) = divergence;
133 0 : using argument_tags =
134 : tmpl::list<Tag, domain::Tags::Mesh<dim>, InverseJacobianTag>;
135 : };
136 :
137 : /// \ingroup DataBoxTagsGroup
138 : /// \brief Compute the divergence of a `tnsr::I` (vector)
139 : ///
140 : /// This tag inherits from `db::add_tag_prefix<Tags::div, Tag>`.
141 : template <typename Tag, typename MeshTag, typename InverseJacobianTag>
142 1 : struct DivVectorCompute : div<Tag>, db::ComputeTag {
143 : private:
144 0 : using inv_jac_indices = typename InverseJacobianTag::type::index_list;
145 0 : static constexpr auto dim = tmpl::back<inv_jac_indices>::dim;
146 : static_assert(std::is_same_v<typename tmpl::front<inv_jac_indices>::Frame,
147 : Frame::ElementLogical>,
148 : "Must map from the logical frame.");
149 :
150 : public:
151 0 : using base = div<Tag>;
152 0 : using return_type = typename base::type;
153 0 : static constexpr void (*function)(const gsl::not_null<return_type*>,
154 : const typename Tag::type&, const Mesh<dim>&,
155 : const typename InverseJacobianTag::type&) =
156 : divergence<dim, typename tmpl::back<inv_jac_indices>::Frame>;
157 0 : using argument_tags = tmpl::list<Tag, MeshTag, InverseJacobianTag>;
158 : };
159 : } // namespace Tags
|