Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <array>
7 : #include <cstddef>
8 : #include <limits>
9 : #include <memory>
10 : #include <utility>
11 :
12 : #include "Utilities/Gsl.hpp"
13 :
14 : /// \cond
15 : template <size_t>
16 : class Index;
17 : /// \endcond
18 :
19 : /*!
20 : * \ingroup DataStructuresGroup
21 : * \brief Iterate over a (dim-1)-dimensional slice
22 : */
23 1 : class SliceIterator {
24 : public:
25 : /*!
26 : * @param extents the number of grid points in each dimension
27 : * @param fixed_dim the dimension to slice in
28 : * @param fixed_index the index of the `fixed_dim` to slice at
29 : */
30 : template <size_t Dim>
31 1 : SliceIterator(const Index<Dim>& extents, size_t fixed_dim,
32 : size_t fixed_index);
33 :
34 : /// Returns `true` if the iterator is valid
35 1 : explicit operator bool() const { return volume_offset_ < size_; }
36 :
37 : /// Step to the next grid point
38 1 : SliceIterator& operator++();
39 :
40 : /// Offset into a Dim-dimensional DataVector at the current gridpoint.
41 : /// Note that the size of the DataVector is assumed to be the product of the
42 : /// extents used to construct this SliceIterator
43 1 : size_t volume_offset() const { return volume_offset_; }
44 :
45 : /// Offset into a (Dim-1)-dimensional DataVector at the current gridpoint.
46 : /// Note that the size of the DataVector is assumed to be the product of the
47 : /// extents used to construct this SliceIterator divided by the extent in
48 : /// the fixed_dim used to construct this SliceIterator
49 1 : size_t slice_offset() const { return slice_offset_; }
50 :
51 : /// Reset the iterator
52 1 : void reset();
53 :
54 : private:
55 0 : size_t size_ = std::numeric_limits<size_t>::max();
56 0 : size_t stride_ = std::numeric_limits<size_t>::max();
57 0 : size_t stride_count_ = std::numeric_limits<size_t>::max();
58 0 : size_t jump_ = std::numeric_limits<size_t>::max();
59 0 : size_t initial_offset_ = std::numeric_limits<size_t>::max();
60 0 : size_t volume_offset_ = std::numeric_limits<size_t>::max();
61 0 : size_t slice_offset_ = std::numeric_limits<size_t>::max();
62 : };
63 :
64 : /*!
65 : * \ingroup DataStructuresGroup
66 : * \brief Get the mapping between volume and boundary slice indices
67 : *
68 : * SliceIterator is used to map between the index of a point on a slice in the
69 : * volume data and the index in the corresponding sliced data. Repeatedly
70 : * applying the SliceIterator on various components of a tensor becomes very
71 : * expensive and so precomputing the index map is sometimes advantageous. This
72 : * function computes the index map onto all boundary slices of volume mesh with
73 : * extents `extents`.
74 : *
75 : * The `unique_ptr` is where the volume and slice indices are stored in memory,
76 : * the array holds views into the memory buffer. The index of the array is the
77 : * fixed dimension, the outer `pair` holds the indices for the lower and upper
78 : * side, respectively, while the `pair`s in the `span`s hold the volume and
79 : * slice indices, respectively.
80 : */
81 : template <size_t VolumeDim>
82 1 : auto volume_and_slice_indices(const Index<VolumeDim>& extents)
83 : -> std::pair<std::unique_ptr<std::pair<size_t, size_t>[]>,
84 : std::array<std::pair<gsl::span<std::pair<size_t, size_t>>,
85 : gsl::span<std::pair<size_t, size_t>>>,
86 : VolumeDim>>;
|