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>>;