SPH
KdTree.h
Go to the documentation of this file.
1 #pragma once
2 
7 
8 #include "io/Logger.h"
10 #include "objects/geometry/Box.h"
15 #include "thread/ThreadLocal.h"
16 #include <set>
17 #include <shared_mutex>
18 
20 
24 struct KdNode : public Noncopyable {
26  enum class Type : Size { X, Y, Z, LEAF };
28 
31 
32  KdNode(const Type& type)
33  : type(type) {}
34 
35  INLINE bool isLeaf() const {
36  return type == Type::LEAF;
37  }
38 };
39 
41 template <typename TBase>
42 struct InnerNode : public TBase {
45 
48 
51 
53  : TBase(KdNode::Type(-1)) {}
54 
55  InnerNode(const KdNode::Type& type)
56  : TBase(type) {}
57 };
58 
60 template <typename TBase>
61 struct LeafNode : public TBase {
64 
67 
70 
71  LeafNode(const KdNode::Type& type)
72  : TBase(type) {}
73 
75  INLINE Size size() const {
76  return to - from;
77  }
78 };
79 
80 static_assert(sizeof(Size) == sizeof(float), "Sizes must match to keep this layout");
81 
86 private:
87  ArrayView<const Size> mapping;
88 
89 public:
92  , mapping(mapping) {}
93 
94  INLINE Size operator*() const {
95  return mapping[idx];
96  }
97 };
98 
101 private:
102  ArrayView<const Size> mapping;
103 
104 public:
106  : IndexSequence(from, to)
107  , mapping(mapping) {
108  SPH_ASSERT(to <= mapping.size());
109  }
110 
112  return LeafIndexIterator(from, mapping);
113  }
114 
116  return LeafIndexIterator(to, mapping);
117  }
118 };
119 
121  INLINE Float operator()(const Vector& v) const {
122  return getSqrLength(v);
123  }
124 };
125 
126 enum class KdChild;
127 
135 template <typename TNode, typename TMetric = EuclideanMetric>
136 class KdTree : public FinderTemplate<KdTree<TNode, TMetric>> {
137 private:
138  struct {
141 
144  } config;
145 
146  Box entireBox;
147 
148  Array<Size> idxs;
149 
151 
152  Array<InnerNode<TNode>> nodes;
153  std::atomic_int nodeCounter;
154  std::shared_timed_mutex nodesMutex;
155 
156  static constexpr Size ROOT_PARENT_NODE = -1;
157 
158 public:
159  explicit KdTree(const Size leafSize = 25, const Size maxParallelDepth = 50) {
160  SPH_ASSERT(leafSize >= 1);
161  config.leafSize = leafSize;
162  config.maxParallelDepth = maxParallelDepth;
163  }
164 
165  template <bool FindAll>
166  Size find(const Vector& pos, const Size index, const Float radius, Array<NeighbourRecord>& neighs) const;
167 
169  INLINE TNode& getNode(const Size nodeIdx) {
170  return nodes[nodeIdx];
171  }
172 
174  INLINE const TNode& getNode(const Size nodeIdx) const {
175  return nodes[nodeIdx];
176  }
177 
180  return nodes.size();
181  }
182 
185  return LeafIndexSequence(leaf.from, leaf.to, idxs);
186  }
187 
189  Outcome sanityCheck() const;
190 
191 protected:
192  virtual void buildImpl(IScheduler& scheduler, ArrayView<const Vector> points) override;
193 
194 private:
195  void init();
196 
197  void buildTree(IScheduler& scheduler,
198  const Size parent,
199  const KdChild child,
200  const Size from,
201  const Size to,
202  const Box& box,
203  const Size slidingCnt,
204  const Size depth);
205 
206  void addLeaf(const Size parent, const KdChild child, const Size from, const Size to);
207 
208  Size addInner(const Size parent, const KdChild child, const Float splitPosition, const Size splitIdx);
209 
210  bool isSingular(const Size from, const Size to, const Size splitIdx) const;
211 
212  bool checkBoxes(const Size from, const Size to, const Size mid, const Box& box1, const Box& box2) const;
213 };
214 
215 
216 enum class IterateDirection {
217  TOP_DOWN,
218  BOTTOM_UP,
219 };
220 
231 template <IterateDirection Dir, typename TNode, typename TMetric, typename TFunctor>
233  IScheduler& scheduler,
234  const TFunctor& functor,
235  const Size nodeIdx = 0,
236  const Size depthLimit = Size(-1));
237 
239 template <IterateDirection Dir, typename TNode, typename TMetric, typename TFunctor>
240 void iterateTree(const KdTree<TNode, TMetric>& tree,
241  IScheduler& scheduler,
242  const TFunctor& functor,
243  const Size nodeIdx = 0,
244  const Size depthLimit = Size(-1));
245 
247 
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
Object representing a three-dimensional axis-aligned box.
const float radius
Definition: CurveDialog.cpp:18
Wraps a functor and executes it once the wrapper goes out of scope.
Generic wrappers of lambdas, functors and other callables.
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
Definition: Globals.h:13
Helper objects allowing to iterate in reverse, iterate over multiple containeres, etc.
IterateDirection
Definition: KdTree.h:216
@ BOTTOM_UP
From leaves to root.
@ TOP_DOWN
From root to leaves.
void iterateTree(KdTree< TNode, TMetric > &tree, IScheduler &scheduler, const TFunctor &functor, const Size nodeIdx=0, const Size depthLimit=Size(-1))
Calls a functor for every node of a K-d tree tree in specified direction.
Definition: KdTree.inl.h:465
KdChild
Definition: KdTree.inl.h:5
Logging routines of the run.
#define INLINE
Macros for conditional compilation based on selected compiler.
Definition: Object.h:31
#define NAMESPACE_SPH_END
Definition: Object.h:12
Return value of function that may fail, containing either SUCCEES (true) or error message.
Template for thread-local storage.
INLINE Float getSqrLength(const Vector &v)
Definition: Vector.h:574
INLINE TCounter size() const
Definition: ArrayView.h:101
INLINE TCounter size() const noexcept
Definition: Array.h:193
Helper object defining three-dimensional interval (box).
Definition: Box.h:17
Helper template, allowing to define all three functions with a single function.
Interface that allows unified implementation of sequential and parallelized versions of algorithms.
Definition: Scheduler.h:27
K-d tree, used for hierarchical clustering of particles and accelerated Kn queries.
Definition: KdTree.h:136
INLINE TNode & getNode(const Size nodeIdx)
Returns the node with given index.
Definition: KdTree.h:169
virtual void buildImpl(IScheduler &scheduler, ArrayView< const Vector > points) override
Builds finder from set of vectors.
Definition: KdTree.inl.h:11
INLINE const TNode & getNode(const Size nodeIdx) const
Returns the node with given index.
Definition: KdTree.h:174
INLINE LeafIndexSequence getLeafIndices(const LeafNode< TNode > &leaf) const
Returns the sequence of particles indices belonging to given leaf.
Definition: KdTree.h:184
KdTree(const Size leafSize=25, const Size maxParallelDepth=50)
Definition: KdTree.h:159
Size find(const Vector &pos, const Size index, const Float radius, Array< NeighbourRecord > &neighs) const
Definition: KdTree.inl.h:316
Size leafSize
Maximal number of particles in the leaf node.
Definition: KdTree.h:140
Outcome sanityCheck() const
Performs some checks of KdTree consistency, returns SUCCESS if everything is OK.
Definition: KdTree.inl.h:394
INLINE Size getNodeCnt() const
Returns the number of nodes in the tree.
Definition: KdTree.h:179
Size maxParallelDepth
Maximal depth for which the build is parallelized.
Definition: KdTree.h:143
Index iterator with given mapping (index permutation).
Definition: KdTree.h:85
INLINE Size operator*() const
Definition: KdTree.h:94
INLINE LeafIndexIterator(const Size idx, ArrayView< const Size > mapping)
Definition: KdTree.h:90
Helper index sequence to iterate over particle indices of a leaf node.
Definition: KdTree.h:100
INLINE LeafIndexIterator end() const
Definition: KdTree.h:115
INLINE LeafIndexIterator begin() const
Definition: KdTree.h:111
INLINE LeafIndexSequence(const Size from, const Size to, ArrayView< const Size > mapping)
Definition: KdTree.h:105
INLINE Float operator()(const Vector &v) const
Definition: KdTree.h:121
Inner node of K-d tree.
Definition: KdTree.h:42
InnerNode(const KdNode::Type &type)
Definition: KdTree.h:55
InnerNode()
Definition: KdTree.h:52
Size right
Index of right child node.
Definition: KdTree.h:50
Size left
Index of left child node.
Definition: KdTree.h:47
float splitPosition
Position where the selected dimension is split.
Definition: KdTree.h:44
Base class for nodes of K-d tree.
Definition: KdTree.h:24
Type
Here X, Y, Z must be 0, 1, 2.
Definition: KdTree.h:26
INLINE bool isLeaf() const
Definition: KdTree.h:35
KdNode(const Type &type)
Definition: KdTree.h:32
Type type
Definition: KdTree.h:27
Box box
Bounding box of particles in the node.
Definition: KdTree.h:30
Leaf (bucket) node of K-d tree.
Definition: KdTree.h:61
Size to
One-past-last index of particles belonging to the leaf.
Definition: KdTree.h:66
LeafNode(const KdNode::Type &type)
Definition: KdTree.h:71
INLINE Size size() const
Returns the number of points in the leaf. Can be zero.
Definition: KdTree.h:75
Size from
First index of particlse belonging to the leaf.
Definition: KdTree.h:63
Size padding
Unused, used so that LeafNode and InnerNode have the same size.
Definition: KdTree.h:69
Object with deleted copy constructor and copy operator.
Definition: Object.h:54