SpECTRE Documentation Coverage Report
Current view: top level - Domain - ElementLogicalCoordinates.hpp Hit Total Coverage
Commit: 47056168667e3fcaf5c2563461756c37676bb94c Lines: 3 6 50.0 %
Date: 2024-04-19 14:00:09
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             : #include <optional>
       8             : #include <unordered_map>
       9             : #include <vector>
      10             : 
      11             : #include "DataStructures/Tensor/TypeAliases.hpp"
      12             : 
      13             : /// \cond
      14             : namespace domain {
      15             : class BlockId;
      16             : }  // namespace domain
      17             : class DataVector;
      18             : template <size_t VolumeDim>
      19             : class ElementId;
      20             : template <typename IdType, typename DataType>
      21             : class IdPair;
      22             : /// \endcond
      23             : 
      24             : /*!
      25             :  * \brief Map block logical coordinates to element logical coordinates
      26             :  *
      27             :  * If the point is outside the element, returns std::nullopt. Otherwise, returns
      28             :  * the element logical coordinates of the point.
      29             :  *
      30             :  * Points on the element boundary are considered to be in the element and will
      31             :  * have element logical coordinates of -1 or 1. See the other function overload
      32             :  * for handling multiple points and disambiguating points on shared element
      33             :  * boundaries.
      34             :  */
      35             : template <size_t Dim>
      36             : std::optional<tnsr::I<double, Dim, Frame::ElementLogical>>
      37           1 : element_logical_coordinates(
      38             :     const tnsr::I<double, Dim, Frame::BlockLogical>& x_block_logical,
      39             :     const ElementId<Dim>& element_id);
      40             : 
      41             : /// \ingroup ComputationalDomainGroup
      42             : ///
      43             : /// Holds element logical coordinates of an arbitrary set of points on
      44             : /// a single `Element`.  The arbitrary set of points is assumed to be
      45             : /// a subset of a larger set of points spanning multiple `Element`s,
      46             : /// and this class holds `offsets` that index into that larger set of
      47             : /// points.
      48             : ///
      49             : /// \details `offsets.size()` is the same as the size of the `DataVector`
      50             : /// inside `element_logical_coords`.
      51             : ///
      52             : /// This is used during the process of interpolating volume quantities
      53             : /// on the `Elements` (e.g. the spatial metric) onto an arbitrary set
      54             : /// of points (e.g. the points on an apparent horizon or a
      55             : /// wave-extraction surface) expressed in some frame.  Here is an
      56             : /// outline of how this interpolation proceeds, and where
      57             : /// `element_logical_coordinates` and `block_logical_coordinates` fit
      58             : /// into the picture:
      59             : ///
      60             : /// Assume some component (e.g. HorizonA) has a `Tensor<DataVector>`
      61             : /// of target coordinate points in some coordinate frame.  The goal is
      62             : /// to determine the `Element` and logical coordinates of each point,
      63             : /// have each `Element` interpolate volume data onto the points
      64             : /// contained inside that `Element`, and send the interpolated data
      65             : /// back to the component.  The first step of this process is to
      66             : /// determine the block_id and block_logical_coordinates of each
      67             : /// point; this is done by the component (e.g. HorizonA), which calls
      68             : /// the function `block_logical_coordinates` on its full set of target
      69             : /// points.  The result of `block_logical_coordinates` is then
      70             : /// communicated to the members of a NodeGroup component
      71             : /// (e.g. HorizonManager).  Each node of the NodeGroup then calls
      72             : /// `element_logical_coordinates`, which returns a map of `ElementId`
      73             : /// to `ElementLogicalCoordHolder` for all the `Element`s on that node
      74             : /// that contain one or more of the target points. The NodeGroup
      75             : /// (which already has received the volume data from the `Elements` on
      76             : /// that node), interpolates the volume data to the element logical
      77             : /// coordinates for all of these `ElementId`s.  The `offsets` in the
      78             : /// `ElementLogicalCoordHolder` are the indices into the `DataVectors`
      79             : /// of the original target coordinates and will be used to assemble
      80             : /// the interpolated data into `Tensor<DataVector>`s that have the
      81             : /// same ordering as the original target coordinates. The NodeGroups
      82             : /// perform a reduction to get the data back to the original
      83             : /// component.
      84             : template <size_t Dim>
      85           1 : struct ElementLogicalCoordHolder {
      86           0 :   tnsr::I<DataVector, Dim, Frame::ElementLogical> element_logical_coords;
      87           0 :   std::vector<size_t> offsets;
      88             : };
      89             : 
      90             : /// \ingroup ComputationalDomainGroup
      91             : ///
      92             : /// Given a set of points in block logical coordinates and their
      93             : /// `BlockIds`, as returned from the function
      94             : /// `block_logical_coordinates`, determines which `Element`s in a list
      95             : /// of `ElementId`s contains each point, and determines the element
      96             : /// logical coordinates of each point.
      97             : ///
      98             : /// \details Returns a std::unordered_map from `ElementId`s to
      99             : /// `ElementLogicalCoordHolder`s.
     100             : /// It is expected that only a subset of the points will be found
     101             : /// in the given `Element`s.
     102             : /// Boundary points: If a point is on the boundary of an Element, it is
     103             : /// considered contained in that Element only if it is on the lower bound
     104             : /// of the Element, or if it is on the upper bound of the element and that
     105             : /// upper bound coincides with the upper bound of the containing Block.
     106             : /// This means that each boundary point is contained in one and only one
     107             : /// Element.  We assume that the input block_coord_holders associates
     108             : /// a point on a Block boundary with only a single Block, the one with
     109             : /// the smaller BlockId, which is always the lower-bounding Block.
     110             : ///
     111             : /// \code
     112             : ///  <---    Block 0   ---> <---   Block 1   --->
     113             : ///  |          |          |          |          |
     114             : /// P_0   E0   P_1   E1   P_2   E2   P_3   E3   P_4
     115             : ///  |          |          |          |          |
     116             : ///
     117             : /// For example, the above 1D diagram shows four Elements labeled E0
     118             : /// through E3, and five boundary points labeled P_0 through P_4 (where
     119             : /// P_0 and P_4 are external boundaries).  There are two Blocks.  This
     120             : /// algorithm assigns each boundary point to one and only one Element as
     121             : /// follows:
     122             : /// P_0 -> E0
     123             : /// P_1 -> E1
     124             : /// P_2 -> E1 (Note: block_coord_holders includes P_2 only in Block 0)
     125             : /// P_3 -> E3
     126             : /// P_4 -> E3
     127             : /// \endcode
     128             : template <size_t Dim>
     129           1 : auto element_logical_coordinates(
     130             :     const std::vector<ElementId<Dim>>& element_ids,
     131             :     const std::vector<std::optional<IdPair<
     132             :         domain::BlockId, tnsr::I<double, Dim, typename Frame::BlockLogical>>>>&
     133             :         block_coord_holders)
     134             :     -> std::unordered_map<ElementId<Dim>, ElementLogicalCoordHolder<Dim>>;

Generated by: LCOV version 1.14