SpECTRE Documentation Coverage Report
Current view: top level - Domain - Tags.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 22.9 % 83 19
Test Date: 2026-10-22 17:29:42
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 tags related to domain quantities
       6              : 
       7              : #pragma once
       8              : 
       9              : #include <array>
      10              : #include <cstddef>
      11              : #include <memory>
      12              : #include <string>
      13              : #include <unordered_map>
      14              : #include <unordered_set>
      15              : #include <vector>
      16              : 
      17              : #include "DataStructures/DataBox/Subitems.hpp"
      18              : #include "DataStructures/DataBox/Tag.hpp"
      19              : #include "DataStructures/DataBox/TagName.hpp"
      20              : #include "DataStructures/Tensor/EagerMath/Determinant.hpp"
      21              : #include "DataStructures/Tensor/EagerMath/DeterminantAndInverse.hpp"
      22              : #include "DataStructures/Tensor/TypeAliases.hpp"
      23              : #include "DataStructures/Variables.hpp"
      24              : #include "Domain/Structure/Direction.hpp"
      25              : #include "Domain/Structure/Element.hpp"
      26              : #include "Utilities/GetOutput.hpp"
      27              : #include "Utilities/Gsl.hpp"
      28              : #include "Utilities/NoSuchType.hpp"
      29              : #include "Utilities/Requires.hpp"
      30              : #include "Utilities/TMPL.hpp"
      31              : #include "Utilities/TypeTraits.hpp"
      32              : #include "Utilities/TypeTraits/IsA.hpp"
      33              : 
      34              : /// \cond
      35              : class DataVector;
      36              : template <size_t VolumeDim>
      37              : class Domain;
      38              : template <size_t VolumeDim, typename Frame>
      39              : class ElementMap;
      40              : template <size_t VolumeDim>
      41              : class Mesh;
      42              : /// \endcond
      43              : 
      44              : namespace domain {
      45              : /// \ingroup ComputationalDomainGroup
      46              : /// \brief %Tags for the domain.
      47              : namespace Tags {
      48              : /// \ingroup DataBoxTagsGroup
      49              : /// \ingroup ComputationalDomainGroup
      50              : /// The ::Element associated with the DataBox
      51              : template <size_t VolumeDim>
      52            1 : struct Element : db::SimpleTag {
      53            0 :   using type = ::Element<VolumeDim>;
      54              : };
      55              : 
      56              : /// \ingroup DataBoxTagsGroup
      57              : /// \ingroup ComputationalDomainGroup
      58              : /// \brief The computational grid of the Element in the DataBox
      59              : /// \details The corresponding interface tag uses Mesh::slice_through to compute
      60              : /// the mesh on the face of the element.
      61              : template <size_t VolumeDim>
      62            1 : struct Mesh : db::SimpleTag {
      63            0 :   using type = ::Mesh<VolumeDim>;
      64              : };
      65              : 
      66              : /// \ingroup DataBoxTagsGroup
      67              : /// \ingroup ComputationalDomainGroup
      68              : /// The coordinate map from the ElementLogical frame to the TargetFrame
      69              : template <size_t VolumeDim, typename TargetFrame = Frame::Inertial>
      70            1 : struct ElementMap : db::SimpleTag {
      71            0 :   static constexpr size_t dim = VolumeDim;
      72            0 :   using target_frame = TargetFrame;
      73            0 :   using source_frame = Frame::ElementLogical;
      74              : 
      75            0 :   static std::string name() {
      76              :     return "ElementMap(" + get_output(TargetFrame{}) + ")";
      77              :   }
      78            0 :   using type = ::ElementMap<VolumeDim, TargetFrame>;
      79              : };
      80              : 
      81              : /// \ingroup DataBoxTagsGroup
      82              : /// \ingroup ComputationalDomainGroup
      83              : /// The coordinates in a given frame.
      84              : template <size_t Dim, typename Frame>
      85            1 : struct Coordinates : db::SimpleTag {
      86            0 :   static std::string name() { return get_output(Frame{}) + "Coordinates"; }
      87            0 :   using type = tnsr::I<DataVector, Dim, Frame>;
      88              : };
      89              : 
      90              : /// \ingroup DataBoxTagsGroup
      91              : /// \ingroup ComputationalDomainGroup
      92              : /// The coordinates in the target frame of `MapTag`. The `SourceCoordsTag`'s
      93              : /// frame must be the source frame of `MapTag`
      94              : template <class MapTag, class SourceCoordsTag,
      95              :           template <size_t, class> class CoordinatesTag = Coordinates>
      96            1 : struct MappedCoordinates
      97              :     : CoordinatesTag<MapTag::dim, typename MapTag::target_frame>,
      98              :       db::ComputeTag {
      99            0 :   using base = CoordinatesTag<MapTag::dim, typename MapTag::target_frame>;
     100            0 :   using return_type = typename base::type;
     101            0 :   using argument_tags = tmpl::list<MapTag, SourceCoordsTag>;
     102            0 :   static constexpr auto function(
     103              :       const gsl::not_null<return_type*> target_coords,
     104              :       const typename MapTag::type& element_map,
     105              :       const tnsr::I<DataVector, MapTag::dim, typename MapTag::source_frame>&
     106              :           source_coords) {
     107              :     if (source_coords.get(0).size() == 0) {
     108              :       // When subcell is not supported on an element due to topology, the
     109              :       // subcell mesh is
     110              :       // {0, Basis::Uninitialized, Quadrature::Uninitialized}. It is never
     111              :       // used, but the compute items still need to run
     112              :       return;
     113              :     }
     114              :     *target_coords = element_map(source_coords);
     115              :   }
     116              : };
     117              : 
     118              : /// \ingroup DataBoxTagsGroup
     119              : /// \ingroup ComputationalDomainGroup
     120              : /// \brief The inverse Jacobian from the source frame to the target frame.
     121              : ///
     122              : /// Specifically, \f$\partial x^{\bar{i}} / \partial x^i\f$, where \f$\bar{i}\f$
     123              : /// denotes the source frame and \f$i\f$ denotes the target frame.
     124              : template <size_t Dim, typename SourceFrame, typename TargetFrame>
     125            1 : struct InverseJacobian : db::SimpleTag {
     126            0 :   static std::string name() {
     127              :     return "InverseJacobian(" + get_output(SourceFrame{}) + "," +
     128              :            get_output(TargetFrame{}) + ")";
     129              :   }
     130            0 :   using type = ::InverseJacobian<DataVector, Dim, SourceFrame, TargetFrame>;
     131              : };
     132              : 
     133              : /// \ingroup DataBoxTagsGroup
     134              : /// \ingroup ComputationalDomainGroup
     135              : /// Computes the inverse Jacobian of the map held by `MapTag` at the coordinates
     136              : /// held by `SourceCoordsTag`. The coordinates must be in the source frame of
     137              : /// the map.
     138              : template <typename MapTag, typename SourceCoordsTag>
     139            1 : struct InverseJacobianCompute
     140              :     : InverseJacobian<MapTag::dim, typename MapTag::source_frame,
     141              :                       typename MapTag::target_frame>,
     142              :       db::ComputeTag {
     143            0 :   using base = InverseJacobian<MapTag::dim, typename MapTag::source_frame,
     144              :                                typename MapTag::target_frame>;
     145            0 :   using return_type = typename base::type;
     146            0 :   using argument_tags = tmpl::list<MapTag, SourceCoordsTag>;
     147            0 :   static constexpr auto function(
     148              :       const gsl::not_null<return_type*> inv_jacobian,
     149              :       const typename MapTag::type& element_map,
     150              :       const tnsr::I<DataVector, MapTag::dim, typename MapTag::source_frame>&
     151              :           source_coords) {
     152              :     *inv_jacobian = element_map.inv_jacobian(source_coords);
     153              :   }
     154              : };
     155              : 
     156              : /// \ingroup DataBoxTagsGroup
     157              : /// \ingroup ComputationalDomainGroup
     158              : /// \brief The Jacobian from the source frame to the target frame.
     159              : ///
     160              : /// Specifically, \f$\partial x^{i} / \partial \xi^{\bar{i}}\f$, where
     161              : /// \f$\xi^\bar{i}\f$ denotes the source frame and \f$x^i\f$ denotes the target
     162              : /// frame.
     163              : template <size_t Dim, typename SourceFrame, typename TargetFrame>
     164            1 : struct Jacobian : db::SimpleTag {
     165            0 :   static std::string name() {
     166              :     return "Jacobian(" + get_output(SourceFrame{}) + "," +
     167              :            get_output(TargetFrame{}) + ")";
     168              :   }
     169            0 :   using type = ::Jacobian<DataVector, Dim, SourceFrame, TargetFrame>;
     170              : };
     171              : 
     172              : /// \ingroup DataBoxTagsGroup
     173              : /// \ingroup ComputationalDomainGroup
     174              : /// Computes the Jacobian of the map from the `InverseJacobian<Dim, SourceFrame,
     175              : /// TargetFrame>` tag.
     176              : template <size_t Dim, typename SourceFrame, typename TargetFrame>
     177            1 : struct JacobianCompute : Jacobian<Dim, SourceFrame, TargetFrame>,
     178              :                          db::ComputeTag {
     179            0 :   using base = Jacobian<Dim, SourceFrame, TargetFrame>;
     180            0 :   using return_type = typename base::type;
     181            0 :   using argument_tags =
     182              :       tmpl::list<InverseJacobian<Dim, SourceFrame, TargetFrame>>;
     183            0 :   static constexpr auto function(
     184              :       const gsl::not_null<return_type*> jacobian,
     185              :       const ::InverseJacobian<DataVector, Dim, SourceFrame, TargetFrame>&
     186              :           inv_jac) {
     187              :     *jacobian = determinant_and_inverse(inv_jac).second;
     188              :   }
     189              : };
     190              : 
     191              : /// \ingroup DataBoxTagsGroup
     192              : /// \ingroup ComputationalDomainGroup
     193              : /// \brief The determinant of the inverse Jacobian from the source frame to the
     194              : /// target frame.
     195              : template <typename SourceFrame, typename TargetFrame>
     196            1 : struct DetInvJacobian : db::SimpleTag {
     197            0 :   using type = Scalar<DataVector>;
     198            0 :   static std::string name() {
     199              :     return "DetInvJacobian(" + get_output(SourceFrame{}) + "," +
     200              :            get_output(TargetFrame{}) + ")";
     201              :   }
     202              : };
     203              : 
     204              : /// \ingroup DataBoxTagsGroup
     205              : /// \ingroup ComputationalDomainGroup
     206              : /// Computes the determinant of the inverse Jacobian.
     207              : template <size_t Dim, typename SourceFrame, typename TargetFrame>
     208            1 : struct DetInvJacobianCompute : db::ComputeTag,
     209              :                                DetInvJacobian<SourceFrame, TargetFrame> {
     210            0 :   using base = DetInvJacobian<SourceFrame, TargetFrame>;
     211            0 :   using return_type = typename base::type;
     212            0 :   using argument_tags =
     213              :       tmpl::list<InverseJacobian<Dim, SourceFrame, TargetFrame>>;
     214            0 :   static void function(const gsl::not_null<return_type*> det_inv_jac,
     215              :                        const ::InverseJacobian<DataVector, Dim, SourceFrame,
     216              :                                                TargetFrame>& inv_jac) {
     217              :     determinant(det_inv_jac, inv_jac);
     218              :   }
     219              : };
     220              : 
     221              : /// \ingroup DataBoxTagsGroup
     222              : /// \ingroup ComputationalDomainGroup
     223              : /// \brief The determinant of the Jacobian from the source frame to the target
     224              : /// frame.
     225              : template <typename SourceFrame, typename TargetFrame>
     226            1 : struct DetJacobian : db::SimpleTag {
     227            0 :   using type = Scalar<DataVector>;
     228            0 :   static std::string name() {
     229              :     return "DetJacobian(" + get_output(SourceFrame{}) + "," +
     230              :            get_output(TargetFrame{}) + ")";
     231              :   }
     232              : };
     233              : 
     234              : /// \ingroup DataBoxTagsGroup
     235              : /// \ingroup ComputationalDomainGroup
     236              : /// \brief The inverse Jacobian times the determinant of the Jacobian.
     237              : ///
     238              : /// This quantity is divergence-free analytically. See
     239              : /// `::dg::metric_identity_det_jac_times_inv_jac` for more information.
     240              : template <size_t Dim, typename SourceFrame, typename TargetFrame>
     241            1 : struct DetTimesInvJacobian : db::SimpleTag {
     242            0 :   using type = ::InverseJacobian<DataVector, Dim, SourceFrame, TargetFrame>;
     243            0 :   static std::string name() {
     244              :     return "DetTimesInvJacobian(" + get_output(SourceFrame{}) + "," +
     245              :            get_output(TargetFrame{}) + ")";
     246              :   }
     247              : };
     248              : 
     249              : /// @{
     250              : /// \ingroup DataBoxTagsGroup
     251              : /// \ingroup ComputationalDomainGroup
     252              : /// The set of directions to neighboring Elements
     253              : template <size_t VolumeDim>
     254            1 : struct InternalDirections : db::SimpleTag {
     255            0 :   static constexpr size_t volume_dim = VolumeDim;
     256            0 :   using type = std::unordered_set<::Direction<VolumeDim>>;
     257              : };
     258              : 
     259              : template <size_t VolumeDim>
     260            0 : struct InternalDirectionsCompute : InternalDirections<VolumeDim>,
     261              :                                    db::ComputeTag {
     262            0 :   static constexpr size_t volume_dim = VolumeDim;
     263            0 :   using base = InternalDirections<VolumeDim>;
     264            0 :   using return_type = std::unordered_set<::Direction<VolumeDim>>;
     265            0 :   using argument_tags = tmpl::list<Element<VolumeDim>>;
     266            0 :   static void function(const gsl::not_null<return_type*> directions,
     267              :                        const ::Element<VolumeDim>& element) {
     268              :     for (const auto& direction_neighbors : element.neighbors()) {
     269              :       directions->insert(direction_neighbors.first);
     270              :     }
     271              :   }
     272              : };
     273              : /// @}
     274              : 
     275              : /// @{
     276              : /// \ingroup DataBoxTagsGroup
     277              : /// \ingroup ComputationalDomainGroup
     278              : /// The set of directions which correspond to external boundaries.
     279              : /// Used for representing data on the interior side of the external boundary
     280              : /// faces.
     281              : template <size_t VolumeDim>
     282            1 : struct BoundaryDirectionsInterior : db::SimpleTag {
     283            0 :   static constexpr size_t volume_dim = VolumeDim;
     284            0 :   using type = std::unordered_set<::Direction<VolumeDim>>;
     285              : };
     286              : 
     287              : template <size_t VolumeDim>
     288            0 : struct BoundaryDirectionsInteriorCompute
     289              :     : BoundaryDirectionsInterior<VolumeDim>,
     290              :       db::ComputeTag {
     291            0 :   static constexpr size_t volume_dim = VolumeDim;
     292            0 :   using base = BoundaryDirectionsInterior<VolumeDim>;
     293            0 :   using return_type = std::unordered_set<::Direction<VolumeDim>>;
     294            0 :   using argument_tags = tmpl::list<Element<VolumeDim>>;
     295            0 :   static void function(const gsl::not_null<return_type*> directions,
     296              :                        const ::Element<VolumeDim>& element) {
     297              :     *directions = element.external_boundaries();
     298              :   }
     299              : };
     300              : /// @}
     301              : 
     302              : /// @{
     303              : /// \ingroup DataBoxTagsGroup
     304              : /// \ingroup ComputationalDomainGroup
     305              : /// The set of directions which correspond to external boundaries. To be used
     306              : /// to represent data which exists on the exterior side of the external boundary
     307              : /// faces.
     308              : template <size_t VolumeDim>
     309            1 : struct BoundaryDirectionsExterior : db::SimpleTag {
     310            0 :   static constexpr size_t volume_dim = VolumeDim;
     311            0 :   using type = std::unordered_set<::Direction<VolumeDim>>;
     312              : };
     313              : 
     314              : template <size_t VolumeDim>
     315            0 : struct BoundaryDirectionsExteriorCompute
     316              :     : BoundaryDirectionsExterior<VolumeDim>,
     317              :       db::ComputeTag {
     318            0 :   static constexpr size_t volume_dim = VolumeDim;
     319            0 :   using base = BoundaryDirectionsExterior<VolumeDim>;
     320            0 :   using return_type = std::unordered_set<::Direction<VolumeDim>>;
     321            0 :   using argument_tags = tmpl::list<Element<VolumeDim>>;
     322            0 :   static constexpr auto function(const gsl::not_null<return_type*> directions,
     323              :                                  const ::Element<VolumeDim>& element) {
     324              :     *directions = element.external_boundaries();
     325              :   }
     326              : };
     327              : /// @}
     328              : 
     329              : /// \ingroup DataBoxTagsGroup
     330              : /// \ingroup ComputationalDomainGroup
     331              : /// \brief Tag which is either a SimpleTag for quantities on an
     332              : /// interface, base tag to a compute item which acts on tags on an interface, or
     333              : /// base tag to a compute item which slices a tag from the volume to an
     334              : /// interface.
     335              : ///
     336              : /// The contained object will be a map from ::Direction to the item type of
     337              : /// `Tag`, with the set of directions being those produced by `DirectionsTag`.
     338              : ///
     339              : /// If a SimpleTag is desired on the interface, then this tag can be added to
     340              : /// the DataBox directly. If a ComputeTag which acts on Tags on the interface is
     341              : /// desired, then the tag should be added using `InterfaceCompute`. If a
     342              : /// ComputeTag which slices a TensorTag or a VariablesTag in the volume to an
     343              : /// Interface is desired, then it should be added using `Slice`. In all cases,
     344              : /// the tag can then be retrieved using `Tags::Interface<DirectionsTag, Tag>`.
     345              : ///
     346              : /// \tparam DirectionsTag the item of directions
     347              : /// \tparam Tag the tag labeling the item
     348              : ///
     349              : /// \see InterfaceCompute, Slice
     350              : template <typename DirectionsTag, typename Tag>
     351            1 : struct Interface : db::SimpleTag {
     352              :   static_assert(db::is_simple_tag_v<DirectionsTag>);
     353              :   static_assert(db::is_simple_tag_v<Tag>);
     354            0 :   static std::string name() {
     355              :     return "Interface<" + db::tag_name<DirectionsTag>() + ", " +
     356              :            db::tag_name<Tag>() + ">";
     357              :   };
     358            0 :   using tag = Tag;
     359            0 :   using type = std::unordered_map<::Direction<DirectionsTag::volume_dim>,
     360              :                                   typename Tag::type>;
     361              : };
     362              : 
     363              : /// \ingroup DataBoxTagsGroup
     364              : /// \ingroup ComputationalDomainGroup
     365              : /// ::Direction to an interface
     366              : template <size_t VolumeDim>
     367            1 : struct Direction : db::SimpleTag {
     368            0 :   using type = ::Direction<VolumeDim>;
     369              : };
     370              : 
     371              : }  // namespace Tags
     372              : }  // namespace domain
     373              : 
     374              : namespace db {
     375              : namespace detail {
     376              : template <typename DirectionsTag, typename VariablesTag>
     377              : struct InterfaceSubitemsImpl {
     378              :   using type = tmpl::transform<
     379              :       typename VariablesTag::type::tags_list,
     380              :       tmpl::bind<domain::Tags::Interface, tmpl::pin<DirectionsTag>, tmpl::_1>>;
     381              : 
     382              :   using tag = domain::Tags::Interface<DirectionsTag, VariablesTag>;
     383              : 
     384              :   template <typename Subtag>
     385              :   static void create_item(
     386              :       const gsl::not_null<typename tag::type*> parent_value,
     387              :       const gsl::not_null<typename Subtag::type*> sub_value) {
     388              :     sub_value->clear();
     389              :     for (auto& direction_vars : *parent_value) {
     390              :       const auto& direction = direction_vars.first;
     391              :       auto& parent_vars = get<typename Subtag::tag>(direction_vars.second);
     392              :       auto& sub_var = (*sub_value)[direction];
     393              :       for (auto vars_it = parent_vars.begin(), sub_var_it = sub_var.begin();
     394              :            vars_it != parent_vars.end(); ++vars_it, ++sub_var_it) {
     395              :         sub_var_it->set_data_ref(&*vars_it);
     396              :       }
     397              :     }
     398              :   }
     399              : 
     400              :   // The `return_type` can be anything for Subitems because the DataBox figures
     401              :   // out the correct return type, we just use the `return_type` type alias to
     402              :   // signal to the DataBox we want mutating behavior.
     403              :   using return_type = NoSuchType;
     404              : 
     405              :   template <typename Subtag>
     406              :   static void create_compute_item(
     407              :       const gsl::not_null<typename Subtag::type*> sub_value,
     408              :       const typename tag::type& parent_value) {
     409              :     for (const auto& direction_vars : parent_value) {
     410              :       const auto& direction = direction_vars.first;
     411              :       const auto& parent_vars =
     412              :           get<typename Subtag::tag>(direction_vars.second);
     413              :       auto& sub_var = (*sub_value)[direction];
     414              :       auto sub_var_it = sub_var.begin();
     415              :       for (auto vars_it = parent_vars.begin();
     416              :            vars_it != parent_vars.end(); ++vars_it, ++sub_var_it) {
     417              :         // clang-tidy: do not use const_cast
     418              :         // The DataBox will only give out a const reference to the
     419              :         // result of a compute item.  Here, that is a reference to a
     420              :         // const map to Tensors of DataVectors.  There is no (publicly
     421              :         // visible) indirection there, so having the map const will
     422              :         // allow only allow const access to the contained DataVectors,
     423              :         // so no modification through the pointer cast here is
     424              :         // possible.
     425              :         sub_var_it->set_data_ref(const_cast<DataVector*>(&*vars_it));  // NOLINT
     426              :       }
     427              :     }
     428              :   }
     429              : };
     430              : }  // namespace detail
     431              : 
     432              : template <typename DirectionsTag, typename VariablesTag>
     433            0 : struct Subitems<domain::Tags::Interface<DirectionsTag, VariablesTag>,
     434              :                 Requires<tt::is_a_v<Variables, typename VariablesTag::type>>>
     435              :     : detail::InterfaceSubitemsImpl<DirectionsTag, VariablesTag> {};
     436              : 
     437              : }  // namespace db
        

Generated by: LCOV version 2.0-1