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 <iterator>
9 : #include <map>
10 : #include <memory>
11 : #include <vector>
12 :
13 : #include "DataStructures/Tensor/TypeAliases.hpp"
14 :
15 : /// \cond
16 : template <size_t VolumeDim>
17 : class ElementId;
18 : /// \endcond
19 :
20 : namespace domain {
21 : /// \cond
22 : template <size_t Dim>
23 : class ElementSearchTree;
24 : /// \endcond
25 :
26 : template <size_t Dim>
27 0 : class ElementSearchTreeIterator {
28 : public:
29 0 : using iterator_category = std::forward_iterator_tag;
30 0 : using value_type = ElementId<Dim>;
31 0 : using difference_type = std::ptrdiff_t;
32 0 : using pointer = const ElementId<Dim>*;
33 0 : using reference = const ElementId<Dim>&;
34 :
35 0 : ElementSearchTreeIterator();
36 0 : ElementSearchTreeIterator(ElementSearchTreeIterator&&);
37 0 : ElementSearchTreeIterator(const ElementSearchTreeIterator&);
38 0 : ElementSearchTreeIterator& operator=(ElementSearchTreeIterator&&);
39 0 : ElementSearchTreeIterator& operator=(const ElementSearchTreeIterator&);
40 0 : ~ElementSearchTreeIterator();
41 :
42 0 : reference operator*() const;
43 0 : pointer operator->() const;
44 :
45 0 : ElementSearchTreeIterator& operator++();
46 0 : ElementSearchTreeIterator operator++(int);
47 :
48 : private:
49 : friend class ElementSearchTree<Dim>;
50 :
51 : template <typename T>
52 0 : static ElementSearchTreeIterator from_impl(T impl);
53 :
54 : template <size_t Dim2>
55 0 : friend bool operator==(const ElementSearchTreeIterator<Dim2>& a,
56 : const ElementSearchTreeIterator<Dim2>& b);
57 :
58 : // Use an array and manual construction rather than a simpler pimpl
59 : // since iterators are constructed a lot.
60 0 : std::array<char, 8> data_;
61 : };
62 :
63 : /*!
64 : * \brief Search tree for efficiently looking up elements by their bounding
65 : * boxes in block-logical coordinates.
66 : *
67 : * The search tree is constructed from a list of `ElementId`s, which define
68 : * bounding boxes in block-logical coordinates. All `ElementId`s must be in the
69 : * same block. Then, the search tree can be used to efficiently search for the
70 : * element that contains a given block-logical coordinate (see e.g.
71 : * `element_logical_coordinates`).
72 : *
73 : * Example usage:
74 : * \snippet Test_ElementSearchTree.cpp element_search_tree_example
75 : *
76 : * Use `domain::index_element_ids()` to create one search tree for each block in
77 : * the domain given the full list of `ElementId`s.
78 : *
79 : * \details The search tree is a `boost::geometry::rtree` with a choice of
80 : * quadratic splitting algorithm and a maximum of 16 elements per node. These
81 : * choices work well, but haven't been extensively tuned.
82 : */
83 : template <size_t Dim>
84 1 : class ElementSearchTree {
85 : public:
86 0 : ElementSearchTree();
87 0 : ElementSearchTree(ElementSearchTree&&);
88 0 : ElementSearchTree& operator=(ElementSearchTree&&);
89 0 : ElementSearchTree(const ElementSearchTree&) = delete;
90 0 : ElementSearchTree& operator=(const ElementSearchTree&) = delete;
91 0 : ~ElementSearchTree();
92 :
93 : /// Construct a search tree containing the ids in `[begin, end)`.
94 : template <typename Iter>
95 1 : ElementSearchTree(Iter begin, const Iter end) : ElementSearchTree() {
96 : insert(begin, end);
97 : }
98 :
99 0 : size_t size() const;
100 0 : bool empty() const;
101 0 : void clear();
102 :
103 0 : void insert(const ElementId<Dim>& id);
104 :
105 : /// Insert the ids in `[begin, end)`.
106 : template <typename Iter>
107 1 : void insert(Iter begin, const Iter end) {
108 : while (begin != end) {
109 : insert(*begin);
110 : ++begin;
111 : }
112 : }
113 :
114 0 : ElementSearchTreeIterator<Dim> begin_covers(
115 : const tnsr::I<double, Dim, Frame::BlockLogical>& coords) const;
116 :
117 0 : ElementSearchTreeIterator<Dim> end_covers() const;
118 :
119 : private:
120 : // Use a pimpl to keep all the boost::geometry stuff in a cpp file,
121 : // because the boost headers are quite expensive to include.
122 : struct Impl;
123 0 : std::unique_ptr<Impl> impl_;
124 : };
125 :
126 : /*!
127 : * \brief Sorts element IDs into one `ElementSearchTree` per block for efficient
128 : * searching.
129 : *
130 : * Returns a map of search trees indexed by block ID. Each search tree contains
131 : * all the `ElementId`s for that block.
132 : *
133 : * \see ElementSearchTree
134 : */
135 : template <size_t Dim>
136 1 : std::map<size_t, ElementSearchTree<Dim>> index_element_ids(
137 : const std::vector<ElementId<Dim>>& element_ids);
138 : } // namespace domain
|