SpECTRE Documentation Coverage Report
Current view: top level - Domain - InterfaceComputeTags.hpp Hit Total Coverage
Commit: aabde07399ba7837e5db64eedfd0a21f31f96922 Lines: 6 43 14.0 %
Date: 2024-04-26 02:38:13
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<parent_tag>;
     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<parent_tag>;
     298             : };
     299             : }  // namespace Tags

Generated by: LCOV version 1.14