SpECTRE Documentation Coverage Report
Current view: top level - Domain - Tags.hpp Hit Total Coverage
Commit: 9f349d3c09e1c03107f00c2135ca40e209d3b84c Lines: 18 78 23.1 %
Date: 2023-06-09 21:05:06
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             :     *target_coords = element_map(source_coords);
     108             :   }
     109             : };
     110             : 
     111             : /// \ingroup DataBoxTagsGroup
     112             : /// \ingroup ComputationalDomainGroup
     113             : /// \brief The inverse Jacobian from the source frame to the target frame.
     114             : ///
     115             : /// Specifically, \f$\partial x^{\bar{i}} / \partial x^i\f$, where \f$\bar{i}\f$
     116             : /// denotes the source frame and \f$i\f$ denotes the target frame.
     117             : template <size_t Dim, typename SourceFrame, typename TargetFrame>
     118           1 : struct InverseJacobian : db::SimpleTag {
     119           0 :   static std::string name() {
     120             :     return "InverseJacobian(" + get_output(SourceFrame{}) + "," +
     121             :            get_output(TargetFrame{}) + ")";
     122             :   }
     123           0 :   using type = ::InverseJacobian<DataVector, Dim, SourceFrame, TargetFrame>;
     124             : };
     125             : 
     126             : /// \ingroup DataBoxTagsGroup
     127             : /// \ingroup ComputationalDomainGroup
     128             : /// Computes the inverse Jacobian of the map held by `MapTag` at the coordinates
     129             : /// held by `SourceCoordsTag`. The coordinates must be in the source frame of
     130             : /// the map.
     131             : template <typename MapTag, typename SourceCoordsTag>
     132           1 : struct InverseJacobianCompute
     133             :     : InverseJacobian<MapTag::dim, typename MapTag::source_frame,
     134             :                       typename MapTag::target_frame>,
     135             :       db::ComputeTag {
     136           0 :   using base = InverseJacobian<MapTag::dim, typename MapTag::source_frame,
     137             :                                typename MapTag::target_frame>;
     138           0 :   using return_type = typename base::type;
     139           0 :   using argument_tags = tmpl::list<MapTag, SourceCoordsTag>;
     140           0 :   static constexpr auto function(
     141             :       const gsl::not_null<return_type*> inv_jacobian,
     142             :       const typename MapTag::type& element_map,
     143             :       const tnsr::I<DataVector, MapTag::dim, typename MapTag::source_frame>&
     144             :           source_coords) {
     145             :     *inv_jacobian = element_map.inv_jacobian(source_coords);
     146             :   }
     147             : };
     148             : 
     149             : /// \ingroup DataBoxTagsGroup
     150             : /// \ingroup ComputationalDomainGroup
     151             : /// \brief The Jacobian from the source frame to the target frame.
     152             : ///
     153             : /// Specifically, \f$\partial x^{i} / \partial \xi^{\bar{i}}\f$, where
     154             : /// \f$\xi^\bar{i}\f$ denotes the source frame and \f$x^i\f$ denotes the target
     155             : /// frame.
     156             : template <size_t Dim, typename SourceFrame, typename TargetFrame>
     157           1 : struct Jacobian : db::SimpleTag {
     158           0 :   static std::string name() {
     159             :     return "Jacobian(" + get_output(SourceFrame{}) + "," +
     160             :            get_output(TargetFrame{}) + ")";
     161             :   }
     162           0 :   using type = ::Jacobian<DataVector, Dim, SourceFrame, TargetFrame>;
     163             : };
     164             : 
     165             : /// \ingroup DataBoxTagsGroup
     166             : /// \ingroup ComputationalDomainGroup
     167             : /// Computes the Jacobian of the map from the `InverseJacobian<Dim, SourceFrame,
     168             : /// TargetFrame>` tag.
     169             : template <size_t Dim, typename SourceFrame, typename TargetFrame>
     170           1 : struct JacobianCompute : Jacobian<Dim, SourceFrame, TargetFrame>,
     171             :                          db::ComputeTag {
     172           0 :   using base = Jacobian<Dim, SourceFrame, TargetFrame>;
     173           0 :   using return_type = typename base::type;
     174           0 :   using argument_tags =
     175             :       tmpl::list<InverseJacobian<Dim, SourceFrame, TargetFrame>>;
     176           0 :   static constexpr auto function(
     177             :       const gsl::not_null<return_type*> jacobian,
     178             :       const ::InverseJacobian<DataVector, Dim, SourceFrame, TargetFrame>&
     179             :           inv_jac) {
     180             :     *jacobian = determinant_and_inverse(inv_jac).second;
     181             :   }
     182             : };
     183             : 
     184             : /// \ingroup DataBoxTagsGroup
     185             : /// \ingroup ComputationalDomainGroup
     186             : /// \brief The determinant of the inverse Jacobian from the source frame to the
     187             : /// target frame.
     188             : template <typename SourceFrame, typename TargetFrame>
     189           1 : struct DetInvJacobian : db::SimpleTag {
     190           0 :   using type = Scalar<DataVector>;
     191           0 :   static std::string name() {
     192             :     return "DetInvJacobian(" + get_output(SourceFrame{}) + "," +
     193             :            get_output(TargetFrame{}) + ")";
     194             :   }
     195             : };
     196             : 
     197             : /// \ingroup DataBoxTagsGroup
     198             : /// \ingroup ComputationalDomainGroup
     199             : /// Computes the determinant of the inverse Jacobian.
     200             : template <size_t Dim, typename SourceFrame, typename TargetFrame>
     201           1 : struct DetInvJacobianCompute : db::ComputeTag,
     202             :                                DetInvJacobian<SourceFrame, TargetFrame> {
     203           0 :   using base = DetInvJacobian<SourceFrame, TargetFrame>;
     204           0 :   using return_type = typename base::type;
     205           0 :   using argument_tags =
     206             :       tmpl::list<InverseJacobian<Dim, SourceFrame, TargetFrame>>;
     207           0 :   static void function(const gsl::not_null<return_type*> det_inv_jac,
     208             :                        const ::InverseJacobian<DataVector, Dim, SourceFrame,
     209             :                                                TargetFrame>& inv_jac) {
     210             :     determinant(det_inv_jac, inv_jac);
     211             :   }
     212             : };
     213             : 
     214             : /// \ingroup DataBoxTagsGroup
     215             : /// \ingroup ComputationalDomainGroup
     216             : /// Base tag for boundary data needed for updating the variables.
     217           1 : struct VariablesBoundaryData : db::BaseTag {};
     218             : 
     219             : /// @{
     220             : /// \ingroup DataBoxTagsGroup
     221             : /// \ingroup ComputationalDomainGroup
     222             : /// The set of directions to neighboring Elements
     223             : template <size_t VolumeDim>
     224           1 : struct InternalDirections : db::SimpleTag {
     225           0 :   static constexpr size_t volume_dim = VolumeDim;
     226           0 :   using type = std::unordered_set<::Direction<VolumeDim>>;
     227             : };
     228             : 
     229             : template <size_t VolumeDim>
     230           0 : struct InternalDirectionsCompute : InternalDirections<VolumeDim>,
     231             :                                    db::ComputeTag {
     232           0 :   static constexpr size_t volume_dim = VolumeDim;
     233           0 :   using base = InternalDirections<VolumeDim>;
     234           0 :   using return_type = std::unordered_set<::Direction<VolumeDim>>;
     235           0 :   using argument_tags = tmpl::list<Element<VolumeDim>>;
     236           0 :   static void function(const gsl::not_null<return_type*> directions,
     237             :                        const ::Element<VolumeDim>& element) {
     238             :     for (const auto& direction_neighbors : element.neighbors()) {
     239             :       directions->insert(direction_neighbors.first);
     240             :     }
     241             :   }
     242             : };
     243             : /// @}
     244             : 
     245             : /// @{
     246             : /// \ingroup DataBoxTagsGroup
     247             : /// \ingroup ComputationalDomainGroup
     248             : /// The set of directions which correspond to external boundaries.
     249             : /// Used for representing data on the interior side of the external boundary
     250             : /// faces.
     251             : template <size_t VolumeDim>
     252           1 : struct BoundaryDirectionsInterior : db::SimpleTag {
     253           0 :   static constexpr size_t volume_dim = VolumeDim;
     254           0 :   using type = std::unordered_set<::Direction<VolumeDim>>;
     255             : };
     256             : 
     257             : template <size_t VolumeDim>
     258           0 : struct BoundaryDirectionsInteriorCompute
     259             :     : BoundaryDirectionsInterior<VolumeDim>,
     260             :       db::ComputeTag {
     261           0 :   static constexpr size_t volume_dim = VolumeDim;
     262           0 :   using base = BoundaryDirectionsInterior<VolumeDim>;
     263           0 :   using return_type = std::unordered_set<::Direction<VolumeDim>>;
     264           0 :   using argument_tags = tmpl::list<Element<VolumeDim>>;
     265           0 :   static void function(const gsl::not_null<return_type*> directions,
     266             :                        const ::Element<VolumeDim>& element) {
     267             :     *directions = element.external_boundaries();
     268             :   }
     269             : };
     270             : /// @}
     271             : 
     272             : /// @{
     273             : /// \ingroup DataBoxTagsGroup
     274             : /// \ingroup ComputationalDomainGroup
     275             : /// The set of directions which correspond to external boundaries. To be used
     276             : /// to represent data which exists on the exterior side of the external boundary
     277             : /// faces.
     278             : template <size_t VolumeDim>
     279           1 : struct BoundaryDirectionsExterior : db::SimpleTag {
     280           0 :   static constexpr size_t volume_dim = VolumeDim;
     281           0 :   using type = std::unordered_set<::Direction<VolumeDim>>;
     282             : };
     283             : 
     284             : template <size_t VolumeDim>
     285           0 : struct BoundaryDirectionsExteriorCompute
     286             :     : BoundaryDirectionsExterior<VolumeDim>,
     287             :       db::ComputeTag {
     288           0 :   static constexpr size_t volume_dim = VolumeDim;
     289           0 :   using base = BoundaryDirectionsExterior<VolumeDim>;
     290           0 :   using return_type = std::unordered_set<::Direction<VolumeDim>>;
     291           0 :   using argument_tags = tmpl::list<Element<VolumeDim>>;
     292           0 :   static constexpr auto function(const gsl::not_null<return_type*> directions,
     293             :                                  const ::Element<VolumeDim>& element) {
     294             :     *directions = element.external_boundaries();
     295             :   }
     296             : };
     297             : /// @}
     298             : 
     299             : /// \ingroup DataBoxTagsGroup
     300             : /// \ingroup ComputationalDomainGroup
     301             : /// \brief Tag which is either a SimpleTag for quantities on an
     302             : /// interface, base tag to a compute item which acts on tags on an interface, or
     303             : /// base tag to a compute item which slices a tag from the volume to an
     304             : /// interface.
     305             : ///
     306             : /// The contained object will be a map from ::Direction to the item type of
     307             : /// `Tag`, with the set of directions being those produced by `DirectionsTag`.
     308             : ///
     309             : /// If a SimpleTag is desired on the interface, then this tag can be added to
     310             : /// the DataBox directly. If a ComputeTag which acts on Tags on the interface is
     311             : /// desired, then the tag should be added using `InterfaceCompute`. If a
     312             : /// ComputeTag which slices a TensorTag or a VariablesTag in the volume to an
     313             : /// Interface is desired, then it should be added using `Slice`. In all cases,
     314             : /// the tag can then be retrieved using `Tags::Interface<DirectionsTag, Tag>`.
     315             : ///
     316             : /// \tparam DirectionsTag the item of directions
     317             : /// \tparam Tag the tag labeling the item
     318             : ///
     319             : /// \see InterfaceCompute, Slice
     320             : template <typename DirectionsTag, typename Tag>
     321           1 : struct Interface : db::SimpleTag {
     322             :   static_assert(db::is_simple_tag_v<DirectionsTag>);
     323             :   static_assert(db::is_simple_tag_v<Tag>);
     324           0 :   static std::string name() {
     325             :     return "Interface<" + db::tag_name<DirectionsTag>() + ", " +
     326             :            db::tag_name<Tag>() + ">";
     327             :   };
     328           0 :   using tag = Tag;
     329           0 :   using type = std::unordered_map<::Direction<DirectionsTag::volume_dim>,
     330             :                                   typename Tag::type>;
     331             : };
     332             : 
     333             : /// \ingroup DataBoxTagsGroup
     334             : /// \ingroup ComputationalDomainGroup
     335             : /// ::Direction to an interface
     336             : template <size_t VolumeDim>
     337           1 : struct Direction : db::SimpleTag {
     338           0 :   using type = ::Direction<VolumeDim>;
     339             : };
     340             : 
     341             : }  // namespace Tags
     342             : }  // namespace domain
     343             : 
     344             : namespace db {
     345             : namespace detail {
     346             : template <typename DirectionsTag, typename VariablesTag>
     347             : struct InterfaceSubitemsImpl {
     348             :   using type = tmpl::transform<
     349             :       typename VariablesTag::type::tags_list,
     350             :       tmpl::bind<domain::Tags::Interface, tmpl::pin<DirectionsTag>, tmpl::_1>>;
     351             : 
     352             :   using tag = domain::Tags::Interface<DirectionsTag, VariablesTag>;
     353             : 
     354             :   template <typename Subtag>
     355             :   static void create_item(
     356             :       const gsl::not_null<typename tag::type*> parent_value,
     357             :       const gsl::not_null<typename Subtag::type*> sub_value) {
     358             :     sub_value->clear();
     359             :     for (auto& direction_vars : *parent_value) {
     360             :       const auto& direction = direction_vars.first;
     361             :       auto& parent_vars = get<typename Subtag::tag>(direction_vars.second);
     362             :       auto& sub_var = (*sub_value)[direction];
     363             :       for (auto vars_it = parent_vars.begin(), sub_var_it = sub_var.begin();
     364             :            vars_it != parent_vars.end(); ++vars_it, ++sub_var_it) {
     365             :         sub_var_it->set_data_ref(&*vars_it);
     366             :       }
     367             :     }
     368             :   }
     369             : 
     370             :   // The `return_type` can be anything for Subitems because the DataBox figures
     371             :   // out the correct return type, we just use the `return_type` type alias to
     372             :   // signal to the DataBox we want mutating behavior.
     373             :   using return_type = NoSuchType;
     374             : 
     375             :   template <typename Subtag>
     376             :   static void create_compute_item(
     377             :       const gsl::not_null<typename Subtag::type*> sub_value,
     378             :       const typename tag::type& parent_value) {
     379             :     for (const auto& direction_vars : parent_value) {
     380             :       const auto& direction = direction_vars.first;
     381             :       const auto& parent_vars =
     382             :           get<typename Subtag::tag>(direction_vars.second);
     383             :       auto& sub_var = (*sub_value)[direction];
     384             :       auto sub_var_it = sub_var.begin();
     385             :       for (auto vars_it = parent_vars.begin();
     386             :            vars_it != parent_vars.end(); ++vars_it, ++sub_var_it) {
     387             :         // clang-tidy: do not use const_cast
     388             :         // The DataBox will only give out a const reference to the
     389             :         // result of a compute item.  Here, that is a reference to a
     390             :         // const map to Tensors of DataVectors.  There is no (publicly
     391             :         // visible) indirection there, so having the map const will
     392             :         // allow only allow const access to the contained DataVectors,
     393             :         // so no modification through the pointer cast here is
     394             :         // possible.
     395             :         sub_var_it->set_data_ref(const_cast<DataVector*>(&*vars_it));  // NOLINT
     396             :       }
     397             :     }
     398             :   }
     399             : };
     400             : }  // namespace detail
     401             : 
     402             : template <typename DirectionsTag, typename VariablesTag>
     403           0 : struct Subitems<domain::Tags::Interface<DirectionsTag, VariablesTag>,
     404             :                 Requires<tt::is_a_v<Variables, typename VariablesTag::type>>>
     405             :     : detail::InterfaceSubitemsImpl<DirectionsTag, VariablesTag> {};
     406             : 
     407             : }  // namespace db

Generated by: LCOV version 1.14