SpECTRE Documentation Coverage Report
Current view: top level - Domain - InterfaceComputeTags.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 14.0 % 43 6
Test Date: 2026-10-22 17:29:42
Legend: Lines:     hit not hit

            Line data    Source code
       1            0 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details.
       3              : 
       4              : #pragma once
       5              : 
       6              : #include <cstddef>
       7              : 
       8              : #include "DataStructures/DataBox/SubitemTag.hpp"
       9              : #include "DataStructures/DataBox/Subitems.hpp"
      10              : #include "DataStructures/DataBox/Tag.hpp"
      11              : #include "DataStructures/DataBox/TagName.hpp"
      12              : #include "DataStructures/DataBox/TagTraits.hpp"
      13              : #include "DataStructures/SliceVariables.hpp"
      14              : #include "DataStructures/Tensor/Slice.hpp"
      15              : #include "Domain/CoordinateMaps/Tags.hpp"
      16              : #include "Domain/ElementMap.hpp"
      17              : #include "Domain/InterfaceHelpers.hpp"
      18              : #include "Domain/Structure/Direction.hpp"
      19              : #include "Domain/Structure/IndexToSliceAt.hpp"
      20              : #include "Domain/Tags.hpp"
      21              : #include "NumericalAlgorithms/Spectral/LogicalCoordinates.hpp"
      22              : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
      23              : #include "Utilities/Gsl.hpp"
      24              : #include "Utilities/TMPL.hpp"
      25              : #include "Utilities/TypeTraits/IsA.hpp"
      26              : 
      27              : /// \cond
      28              : namespace Tags {
      29              : struct Time;
      30              : }  // namespace Tags
      31              : /// \endcond
      32              : 
      33              : namespace domain {
      34              : namespace Tags {
      35              : struct FunctionsOfTime;
      36              : }  // namespace Tags
      37              : 
      38              : namespace Tags {
      39              : 
      40              : namespace Interface_detail {
      41              : 
      42              : template <typename ComputeTag, typename VolumeTags, typename... ArgumentTags,
      43              :           size_t Dim, typename... ArgTypes>
      44              : constexpr void evaluate_compute_item(
      45              :     const gsl::not_null<typename ComputeTag::type*> result,
      46              :     const ::Direction<Dim>& direction, tmpl::list<ArgumentTags...> /*meta*/,
      47              :     const ArgTypes&... args) {
      48              :   ComputeTag::function(
      49              :       result,
      50              :       InterfaceHelpers_detail::unmap_interface_args<
      51              :           tmpl::list_contains_v<VolumeTags, ArgumentTags>>::apply(direction,
      52              :                                                                   args)...);
      53              : }
      54              : }  // namespace Interface_detail
      55              : 
      56              : /// \ingroup DataBoxTagsGroup
      57              : /// \ingroup ComputationalDomainGroup
      58              : /// \brief Compute tag for representing items computed on a set of interfaces.
      59              : /// Can be retrieved using `Tags::Interface<DirectionsTag, Tag>`
      60              : ///
      61              : /// The computed object will be a map from a ::Direction to the item type of
      62              : /// `Tag` (i.e. `Tag::type`), with the set of directions being those produced by
      63              : /// `DirectionsTag`. `Tag::function` will be applied separately to the data on
      64              : /// each interface. If some of the compute item's inputs (i.e.
      65              : /// `Tag::argument_tags`) should be taken from the volume rather than the
      66              : /// interface, they should be specified in the typelist `Tag::volume_tags`.
      67              : ///
      68              : /// \tparam DirectionsTag the simple tag labeling the set of Directions
      69              : /// \tparam Tag the compute tag to apply on each interface
      70              : template <typename DirectionsTag, typename Tag>
      71            1 : struct InterfaceCompute : Interface<DirectionsTag, typename Tag::base>,
      72              :                           db::ComputeTag {
      73              :   static_assert(db::is_simple_tag_v<DirectionsTag>);
      74              :   static_assert(db::is_compute_tag_v<Tag>,
      75              :                 "Cannot use a non compute item as an interface compute item.");
      76            0 :   using base = Interface<DirectionsTag, typename Tag::base>;
      77            0 :   static constexpr size_t volume_dim = DirectionsTag::volume_dim;
      78            0 :   using return_type =
      79              :       std::unordered_map<::Direction<volume_dim>, typename Tag::type>;
      80              : 
      81            0 :   using forwarded_argument_tags =
      82              :       InterfaceHelpers_detail::get_interface_argument_tags<Tag, DirectionsTag>;
      83            0 :   using argument_tags =
      84              :       tmpl::push_front<forwarded_argument_tags, DirectionsTag>;
      85              : 
      86            0 :   using volume_tags = get_volume_tags<Tag>;
      87              :   static_assert(
      88              :       tmpl::size<tmpl::list_difference<volume_tags, argument_tags>>::value == 0,
      89              :       "volume_tags contains tags not in argument_tags");
      90              : 
      91              :   template <typename... ArgTypes>
      92            0 :   static constexpr void function(
      93              :       const gsl::not_null<return_type*> result,
      94              :       const std::unordered_set<::Direction<volume_dim>>& directions,
      95              :       const ArgTypes&... args) {
      96              :     for (const auto& direction : directions) {
      97              :       Interface_detail::evaluate_compute_item<Tag, volume_tags>(
      98              :           make_not_null(&(*result)[direction]), direction,
      99              :           forwarded_argument_tags{}, args...);
     100              :     }
     101              :   }
     102              : };
     103              : 
     104              : /// \ingroup DataBoxTagsGroup
     105              : /// \ingroup ComputationalDomainGroup
     106              : /// \brief Compute tag for representing a compute item that slices data from
     107              : /// the volume to a set of interfaces.
     108              : ///
     109              : /// The computed object will be a map from a ::Direction to the item type of
     110              : /// `Tag` (i.e. `Tag::type`), with the set of directions being those produced by
     111              : /// `DirectionsTag`. `Tag::type` must be a `Tensor` or a `Variables`.
     112              : /// Retrievable from the DataBox using `Tags::Interface<DirectionsTag, Tag>`
     113              : ///
     114              : /// \requires `Tag` correspond to a `Tensor` or a `Variables`
     115              : ///
     116              : /// \tparam DirectionsTag the simple tag labeling the set of Directions
     117              : /// \tparam Tag the simple tag for the volume data to be sliced
     118              : template <typename DirectionsTag, typename Tag>
     119            1 : struct Slice : Interface<DirectionsTag, Tag>, db::ComputeTag {
     120              :   static_assert(db::is_simple_tag_v<DirectionsTag>);
     121              :   static_assert(db::is_simple_tag_v<Tag>);
     122            0 :   using base = Interface<DirectionsTag, Tag>;
     123            0 :   static constexpr size_t volume_dim = DirectionsTag::volume_dim;
     124              : 
     125            0 :   using return_type =
     126              :       std::unordered_map<::Direction<volume_dim>, typename Tag::type>;
     127              : 
     128            0 :   static constexpr void function(
     129              :       const gsl::not_null<return_type*> sliced_vars,
     130              :       const ::Mesh<volume_dim>& mesh,
     131              :       const std::unordered_set<::Direction<volume_dim>>& directions,
     132              :       const typename Tag::type& variables) {
     133              :     for (const auto& direction : directions) {
     134              :       data_on_slice(make_not_null(&((*sliced_vars)[direction])), variables,
     135              :                     mesh.extents(), direction.dimension(),
     136              :                     index_to_slice_at(mesh.extents(), direction));
     137              :     }
     138              :   }
     139              : 
     140            0 :   using argument_tags = tmpl::list<Mesh<volume_dim>, DirectionsTag, Tag>;
     141            0 :   using volume_tags = tmpl::list<Mesh<volume_dim>, Tag>;
     142              : };
     143              : 
     144              : /// \cond
     145              : template <typename DirectionsTag, size_t VolumeDim>
     146              : struct InterfaceCompute<DirectionsTag, Direction<VolumeDim>>
     147              :     : db::ComputeTag, Interface<DirectionsTag, Direction<VolumeDim>> {
     148              :   static_assert(db::is_simple_tag_v<DirectionsTag>);
     149              :   using base = Interface<DirectionsTag, Direction<VolumeDim>>;
     150              :   using return_type =
     151              :       std::unordered_map<::Direction<VolumeDim>, ::Direction<VolumeDim>>;
     152              :   using argument_tags = tmpl::list<DirectionsTag>;
     153              :   static constexpr auto function(
     154              :       const gsl::not_null<
     155              :           std::unordered_map<::Direction<VolumeDim>, ::Direction<VolumeDim>>*>
     156              :           result,
     157              :       const std::unordered_set<::Direction<VolumeDim>>& directions) {
     158              :     for (const auto& d : directions) {
     159              :       result->insert_or_assign(d, d);
     160              :     }
     161              :   }
     162              : };
     163              : /// \endcond
     164              : 
     165              : /// \ingroup DataBoxTagsGroup
     166              : /// \ingroup ComputationalDomainGroup
     167              : /// Computes the `VolumeDim-1` dimensional mesh on an interface from the volume
     168              : /// mesh. `Tags::InterfaceCompute<Dirs, InterfaceMesh<VolumeDim>>` is
     169              : /// retrievable as `Tags::Interface<Dirs, Mesh<VolumeDim>>` from the DataBox.
     170              : template <size_t VolumeDim>
     171            1 : struct InterfaceMesh : db::ComputeTag, Tags::Mesh<VolumeDim - 1> {
     172            0 :   using base = Tags::Mesh<VolumeDim - 1>;
     173            0 :   using return_type = typename base::type;
     174            0 :   using argument_tags = tmpl::list<Direction<VolumeDim>, Mesh<VolumeDim>>;
     175            0 :   static constexpr auto function(const gsl::not_null<return_type*> mesh,
     176              :                                  const ::Direction<VolumeDim>& direction,
     177              :                                  const ::Mesh<VolumeDim>& volume_mesh) {
     178              :     *mesh = volume_mesh.slice_away(direction.dimension());
     179              :   }
     180            0 :   using volume_tags = tmpl::list<Mesh<VolumeDim>>;
     181              : };
     182              : 
     183              : /// \ingroup DataBoxTagsGroup
     184              : /// \ingroup ComputationalDomainGroup
     185              : /// Computes the coordinates in the frame `Frame` on the faces defined by
     186              : /// `Direction`. Intended to be prefixed by a `Tags::InterfaceCompute` to
     187              : /// define the directions on which to compute the coordinates.
     188              : template <size_t VolumeDim, bool MovingMesh = false>
     189            1 : struct BoundaryCoordinates : db::ComputeTag,
     190              :                              Tags::Coordinates<VolumeDim, Frame::Inertial> {
     191            0 :   using base = Tags::Coordinates<VolumeDim, Frame::Inertial>;
     192            0 :   using return_type = typename base::type;
     193            0 :   static void function(const gsl::not_null<return_type*> boundary_coords,
     194              :                        const ::Direction<VolumeDim>& direction,
     195              :                        const ::Mesh<VolumeDim - 1>& interface_mesh,
     196              :                        const ::ElementMap<VolumeDim, Frame::Inertial>& map) {
     197              :     *boundary_coords =
     198              :         map(interface_logical_coordinates(interface_mesh, direction));
     199              :   }
     200              : 
     201            0 :   static void function(
     202              :       const gsl::not_null<return_type*> boundary_coords,
     203              :       const ::Direction<VolumeDim>& direction,
     204              :       const ::Mesh<VolumeDim - 1>& interface_mesh,
     205              :       const ::ElementMap<VolumeDim, ::Frame::Grid>& logical_to_grid_map,
     206              :       const domain::CoordinateMapBase<Frame::Grid, Frame::Inertial, VolumeDim>&
     207              :           grid_to_inertial_map,
     208              :       const double time,
     209              :       const std::unordered_map<
     210              :           std::string,
     211              :           std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
     212              :           functions_of_time) {
     213              :     *boundary_coords =
     214              :         grid_to_inertial_map(logical_to_grid_map(interface_logical_coordinates(
     215              :                                  interface_mesh, direction)),
     216              :                              time, functions_of_time);
     217              :   }
     218              : 
     219            0 :   using argument_tags = tmpl::conditional_t<
     220              :       MovingMesh,
     221              :       tmpl::list<Direction<VolumeDim>, Mesh<VolumeDim - 1>,
     222              :                  Tags::ElementMap<VolumeDim, Frame::Grid>,
     223              :                  CoordinateMaps::Tags::CoordinateMap<VolumeDim, Frame::Grid,
     224              :                                                      Frame::Inertial>,
     225              :                  ::Tags::Time, domain::Tags::FunctionsOfTime>,
     226              :       tmpl::list<Direction<VolumeDim>, Mesh<VolumeDim - 1>,
     227              :                  ElementMap<VolumeDim, Frame::Inertial>>>;
     228            0 :   using volume_tags = tmpl::conditional_t<
     229              :       MovingMesh,
     230              :       tmpl::list<Tags::ElementMap<VolumeDim, Frame::Grid>,
     231              :                  CoordinateMaps::Tags::CoordinateMap<VolumeDim, Frame::Grid,
     232              :                                                      Frame::Inertial>,
     233              :                  ::Tags::Time, domain::Tags::FunctionsOfTime>,
     234              :       tmpl::list<ElementMap<VolumeDim, Frame::Inertial>>>;
     235              : };
     236              : 
     237              : }  // namespace Tags
     238              : }  // namespace domain
     239              : 
     240              : namespace db {
     241              : template <typename DirectionsTag, typename VariablesTag>
     242            0 : struct Subitems<domain::Tags::InterfaceCompute<DirectionsTag, VariablesTag>,
     243              :                 Requires<tt::is_a_v<Variables, typename VariablesTag::type>>>
     244              :     : detail::InterfaceSubitemsImpl<DirectionsTag,
     245              :                                     typename VariablesTag::base> {};
     246              : 
     247              : template <typename DirectionsTag, typename VariablesTag>
     248            0 : struct Subitems<domain::Tags::Slice<DirectionsTag, VariablesTag>,
     249              :                 Requires<tt::is_a_v<Variables, typename VariablesTag::type>>>
     250              :     : detail::InterfaceSubitemsImpl<DirectionsTag, VariablesTag> {};
     251              : }  // namespace db
     252              : 
     253              : namespace Tags {
     254              : /// \brief specialization of a subitem tag for an interface compute tag of a
     255              : /// Variables
     256              : ///
     257              : /// This is a compute tag for an unordered map from ::Direction (with the set of
     258              : /// directions being those produced by `DirectionsTag`) to a Tensor (whose
     259              : /// type comes from `TensorTag`) that is contained in a Variables (labeled by
     260              : /// `VariablesTag`) for a ::domain::Tags::InterfaceCompute<DirectionsTag,
     261              : /// VariablesTag>>.
     262              : template <typename DirectionsTag, typename TensorTag, typename VariablesTag>
     263            1 : struct Subitem<::domain::Tags::Interface<DirectionsTag, TensorTag>,
     264              :                ::domain::Tags::InterfaceCompute<DirectionsTag, VariablesTag>>
     265              :     : db::ComputeTag, ::domain::Tags::Interface<DirectionsTag, TensorTag> {
     266            0 :   using base = ::domain::Tags::Interface<DirectionsTag, TensorTag>;
     267            0 :   using return_type = typename base::type;
     268            0 :   using parent_tag =
     269              :       ::domain::Tags::InterfaceCompute<DirectionsTag, VariablesTag>;
     270            0 :   static void function(const gsl::not_null<return_type*> subitems,
     271              :                        const typename parent_tag::type& parent_value) {
     272              :     ::db::Subitems<parent_tag>::template create_compute_item<base>(
     273              :         subitems, parent_value);
     274              :   }
     275            0 :   using argument_tags = tmpl::list<typename parent_tag::base>;
     276              : };
     277              : 
     278              : /// \brief specialization of a subitem tag for an interface compute tag of a
     279              : /// sliced Variables
     280              : ///
     281              : /// This is a compute tag for an unordered map from ::Direction (with the set of
     282              : /// directions being those produced by `DirectionsTag`) to a Tensor (whose
     283              : /// type comes from `TensorTag`) that is contained in a Variables (labeled by
     284              : /// `VariablesTag`) for a domain::Tags::Slice<DirectionsTag, VariablesTag>>.
     285              : template <typename DirectionsTag, typename TensorTag, typename VariablesTag>
     286            1 : struct Subitem<::domain::Tags::Interface<DirectionsTag, TensorTag>,
     287              :                ::domain::Tags::Slice<DirectionsTag, VariablesTag>>
     288              :     : db::ComputeTag, ::domain::Tags::Interface<DirectionsTag, TensorTag> {
     289            0 :   using base = ::domain::Tags::Interface<DirectionsTag, TensorTag>;
     290            0 :   using return_type = typename base::type;
     291            0 :   using parent_tag = ::domain::Tags::Slice<DirectionsTag, VariablesTag>;
     292            0 :   static void function(const gsl::not_null<return_type*> subitems,
     293              :                        const typename parent_tag::type& parent_value) {
     294              :     ::db::Subitems<parent_tag>::template create_compute_item<base>(
     295              :         subitems, parent_value);
     296              :   }
     297            0 :   using argument_tags = tmpl::list<typename parent_tag::base>;
     298              : };
     299              : }  // namespace Tags
        

Generated by: LCOV version 2.0-1