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

Generated by: LCOV version 1.14