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 <memory>
8 : #include <optional>
9 : #include <string>
10 : #include <unordered_map>
11 : #include <vector>
12 :
13 : #include "DataStructures/IdPair.hpp"
14 : #include "DataStructures/Tensor/TypeAliases.hpp"
15 : #include "Domain/FunctionsOfTime/FunctionOfTime.hpp"
16 : #include "Domain/Structure/BlockId.hpp"
17 :
18 : /// \cond
19 : class DataVector;
20 : template <size_t VolumeDim>
21 : class Domain;
22 : template <size_t VolumeDim>
23 : class Block;
24 : /// \endcond
25 :
26 : template <size_t Dim>
27 0 : using BlockLogicalCoords = std::optional<
28 : IdPair<domain::BlockId, tnsr::I<double, Dim, Frame::BlockLogical>>>;
29 :
30 : /// @{
31 : /// \ingroup ComputationalDomainGroup
32 : ///
33 : /// Computes the block logical coordinates and the containing `BlockId` of
34 : /// a set of points, given coordinates in a particular frame.
35 : ///
36 : /// \details Returns a std::vector<std::optional<IdPair<BlockId,coords>>>,
37 : /// where the vector runs over the points and is indexed in the same order as
38 : /// the input coordinates `x`. For each point, the `IdPair` holds the
39 : /// block logical coords of that point and the `BlockId` of the `Block` that
40 : /// contains that point.
41 : /// The std::optional is invalid if the point is not in any Block.
42 : /// If a point is on a shared boundary of two or more `Block`s, it is
43 : /// returned only once, and is considered to belong to the `Block`
44 : /// with the smaller `BlockId`.
45 : ///
46 : /// The `block_logical_coordinates_single_point` function will search the passed
47 : /// in block for the passed in coordinate and return the logical coordinates of
48 : /// that point. It will return a `std::nullopt` if it can't find the point in
49 : /// that block.
50 : ///
51 : /// \warning Since map inverses can involve numerical roundoff error, care must
52 : /// be taken with points on shared block boundaries. They will be assigned to
53 : /// the first block (by block ID) that contains the point _within roundoff
54 : /// error_. Therefore, be advised to use the logical coordinates returned by
55 : /// this function, which are guaranteed to be in [-1, 1] and can be safely
56 : /// passed along to `element_logical_coordinates`.
57 : ///
58 : /// \warning `block_logical_coordinates` with x in
59 : /// `::Frame::Distorted` ignores all `Block`s that lack a distorted
60 : /// frame, and it will return std::nullopt for points that lie outside
61 : /// all distorted-frame-endowed `Block`s. This is what is expected for
62 : /// typical use cases. This means that `block_logical_coordinates`
63 : /// does not assume that grid and distorted frames are equal in
64 : /// `Block`s that lack a distorted frame.
65 : template <size_t Dim, typename Fr>
66 1 : auto block_logical_coordinates(
67 : const Domain<Dim>& domain, const tnsr::I<DataVector, Dim, Fr>& x,
68 : double time = std::numeric_limits<double>::signaling_NaN(),
69 : const domain::FunctionsOfTimeMap& functions_of_time = {},
70 : std::optional<gsl::not_null<std::vector<size_t>*>> block_order =
71 : std::nullopt) -> std::vector<BlockLogicalCoords<Dim>>;
72 :
73 : template <size_t Dim, typename Fr>
74 : std::optional<tnsr::I<double, Dim, ::Frame::BlockLogical>>
75 1 : block_logical_coordinates_single_point(
76 : const tnsr::I<double, Dim, Fr>& input_point, const Block<Dim>& block,
77 : double time = std::numeric_limits<double>::signaling_NaN(),
78 : const domain::FunctionsOfTimeMap& functions_of_time = {});
79 :
80 : /// A `block_order` can be provided to this overload to speed up the search for
81 : /// the block containing the point. When the point is found, the containing
82 : /// block will be pushed to the front of the list. If an empty block order is
83 : /// provided, it will be initially filled with the list of blocks in the domain
84 : /// and then updated. The block order does not affect the result: points on
85 : /// shared block boundaries are still assigned to the block with the smallest
86 : /// `BlockId`, so the result doesn't depend on the order in which points are
87 : /// processed.
88 : template <size_t Dim, typename Fr>
89 1 : BlockLogicalCoords<Dim> block_logical_coordinates_single_point(
90 : const tnsr::I<double, Dim, Fr>& input_point, const Domain<Dim>& domain,
91 : double time = std::numeric_limits<double>::signaling_NaN(),
92 : const domain::FunctionsOfTimeMap& functions_of_time = {},
93 : std::optional<gsl::not_null<std::vector<size_t>*>> block_order =
94 : std::nullopt);
95 : /// @}
|