AutoPas  3.0.0
Loading...
Searching...
No Matches
OctreeInnerNode.h
Go to the documentation of this file.
1
8#pragma once
9
13#include "autopas/utils/inBox.h"
14
15namespace autopas {
22template <class Particle_T>
23class OctreeInnerNode : public OctreeNodeInterface<Particle_T> {
24 public:
34 OctreeInnerNode(const std::array<double, 3> &boxMin, const std::array<double, 3> &boxMax,
35 OctreeNodeInterface<Particle_T> *parent, int unsigned treeSplitThreshold, double interactionLength,
36 double cellSizeFactor)
37 : OctreeNodeInterface<Particle_T>(boxMin, boxMax, parent, treeSplitThreshold, interactionLength, cellSizeFactor) {
38 using namespace autopas::utils;
39 using namespace autopas::utils::ArrayMath::literals;
40
41 // The inner node is initialized with 8 leaves.
42 const auto center = (boxMin + boxMax) * 0.5;
43 for (auto i = 0; i < _children.size(); ++i) {
44 // Subdivide the bounding box of the parent.
45 std::array<double, 3> newBoxMin = {};
46 std::array<double, 3> newBoxMax = {};
47 for (auto d = 0; d < 3; ++d) {
48 // `i`, `d` and `mask` are used to generate minimum and maximum coordinates for every octree leaf's bounding
49 // box. `i` represents a 3-bit wide number, where each bit corresponds to an axis. The following table
50 // visualizes this layout:
51 //
52 // <-- msb lsb -->
53 // +------++-----+---+---+---+
54 // | bit || ... | 2 | 1 | 0 |
55 // +------+------+---+---+---+
56 // | axis || x | y | z |
57 // +------++---------+---+---+
58 //
59 // When an axis bit is not set, a leaf is expected to range from the minimum coordinate to the center of the
60 // enclosing box on the respective axis `d`. If the axis bit is set, the leaf's region should start at the
61 // center coordinate and end at the maximum coordinate of the enclosing box.
62 //
63 // `mask` is used to extract the individual axis components from `i`: Using the shift operation, `mask` can
64 // either become 0b100, 0b010 or 0b001 since `d` ranges from 0 to 2 inclusively. This covers all available axis
65 // in 3 dimensions.
66 const auto mask = 4 >> d;
67 newBoxMin[d] = (not(i & mask)) ? boxMin[d] : center[d];
68 newBoxMax[d] = (not(i & mask)) ? center[d] : boxMax[d];
69 }
70
71 // Assign new leaves as the children.
72 _children[i] = std::make_unique<OctreeLeafNode<Particle_T>>(newBoxMin, newBoxMax, this, treeSplitThreshold,
73 interactionLength, cellSizeFactor);
74 }
75 }
76
82 : OctreeNodeInterface<Particle_T>(other._boxMin, other._boxMax, other._parent, other._treeSplitThreshold,
84 for (auto i = 0; i < other._children.size(); ++i) {
85 auto *otherChild = other._children[i].get();
86 if (otherChild->hasChildren()) {
87 _children[i] =
88 std::make_unique<OctreeInnerNode<Particle_T>>((OctreeInnerNode<Particle_T> &)*other._children[i]);
89 } else {
90 _children[i] = std::make_unique<OctreeLeafNode<Particle_T>>((OctreeLeafNode<Particle_T> &)*other._children[i]);
91 }
92 }
93 }
94
98 std::unique_ptr<OctreeNodeInterface<Particle_T>> insert(const Particle_T &p) override {
99 // Find a child to insert the particle into.
100 for (auto &child : _children) {
101 if (child->isInside(p.getR())) {
102 auto ret = child->insert(p);
103 if (ret) child = std::move(ret);
104 break;
105 }
106 }
107
108 return nullptr;
109 }
110
111 bool deleteParticle(Particle_T &particle) override {
112 for (auto &child : _children) {
113 if (child->isInside(particle.getR())) {
114 return child->deleteParticle(particle);
115 }
116 }
117 // clang-format off
119 "Particle not found in this node!"
120 "\nBoxMin: " + utils::ArrayUtils::to_string(this->_boxMin) +
121 "\nBoxMax: " + utils::ArrayUtils::to_string(this->_boxMax) +
122 "\n" + particle.toString());
123 // clang-format on
124 return false;
125 }
126
130 void collectAllParticles(std::vector<Particle_T *> &ps) const override {
131 // An inner node does not contain particles, traverse down to the children.
132 for (auto &child : _children) {
133 child->collectAllParticles(ps);
134 }
135 }
136
140 void appendAllLeafBoxes(std::vector<std::pair<std::array<double, 3>, std::array<double, 3>>> &boxes) const override {
141 for (auto &child : _children) {
142 child->appendAllLeafBoxes(boxes);
143 }
144 }
145
149 void clearChildren(std::unique_ptr<OctreeNodeInterface<Particle_T>> &ref) override {
150 for (auto &child : _children) {
151 child->clearChildren(child);
152 }
153
154 std::unique_ptr<OctreeLeafNode<Particle_T>> newLeaf = std::make_unique<OctreeLeafNode<Particle_T>>(
155 this->getBoxMin(), this->getBoxMax(), this->_parent, this->_treeSplitThreshold, this->_interactionLength,
156 this->_cellSizeFactor);
157 ref = std::move(newLeaf);
158 }
159
163 size_t size() const override {
164 unsigned int result = 0;
165 for (const auto &child : _children) {
166 result += child->size();
167 }
168 return result;
169 }
170
174 size_t getNumberOfParticles(IteratorBehavior behavior) const override {
175 unsigned int result = 0;
176 for (const auto &child : _children) {
177 result += child->getNumberOfParticles(behavior);
178 }
179 return result;
180 }
181
185 bool hasChildren() override { return true; }
186
190 OctreeNodeInterface<Particle_T> *getChild(int index) override { return _children[index].get(); }
191
192 std::vector<OctreeLeafNode<Particle_T> *> getLeavesFromDirections(
193 const std::vector<octree::Vertex> &directions) override {
194 std::vector<OctreeLeafNode<Particle_T> *> result;
195 // Only take the children that are allowed (i.e. those which are in the given directions list)
196 for (auto d : directions) {
197 int childIndex = vertexToIndex(d);
198 if (childIndex < 0) {
199 throw std::runtime_error("[OctreeInnerNode::getLeavesFromDirections()] Calculated invalid child index");
200 }
201
202 auto child = getChild(childIndex);
203 auto childLeaves = child->getLeavesFromDirections(directions);
204 result.insert(result.end(), childLeaves.begin(), childLeaves.end());
205 }
206 return result;
207 }
208
210 // convert the Octant to a flat child index
211 auto flat = vertexToIndex(octant);
212 return _children[flat].get();
213 }
214
215 void appendAllLeaves(std::vector<OctreeLeafNode<Particle_T> *> &leaves) const override {
216 for (auto &child : _children) {
217 child->appendAllLeaves(leaves);
218 }
219 }
220
221 std::set<OctreeLeafNode<Particle_T> *> getLeavesInRange(const std::array<double, 3> &min,
222 const std::array<double, 3> &max) override {
223 std::set<OctreeLeafNode<Particle_T> *> result;
224 for (auto &child : _children) {
225 double vol = child->getEnclosedVolumeWith(min, max);
226 // Prevent iteration of the subtree if it is unnecessary
227 if (vol > 0.0) {
228 auto leaves = child->getLeavesInRange(min, max);
229 result.insert(leaves.begin(), leaves.end());
230 }
231 }
232 return result;
233 }
234
238 template <typename Lambda>
239 void forEach(Lambda forEachLambda) {
240 for (auto &child : _children) {
241 withStaticNodeType(child, [&](auto nodePtr) { nodePtr->forEach(forEachLambda); });
242 }
243 }
244
248 template <typename Lambda, typename A>
249 void reduce(Lambda reduceLambda, A &result) {
250 for (auto &child : _children) {
251 withStaticNodeType(child, [&](auto nodePtr) { nodePtr->reduce(reduceLambda, result); });
252 }
253 }
254
265 template <typename Lambda>
266 void forEach(Lambda forEachLambda, const std::array<double, 3> &lowerCorner,
267 const std::array<double, 3> &higherCorner, IteratorBehavior behavior) {
268 for (auto &child : _children) {
269 double vol = child->getEnclosedVolumeWith(lowerCorner, higherCorner);
270 if (vol > 0.0)
271 withStaticNodeType(child,
272 [&](auto nodePtr) { nodePtr->forEach(forEachLambda, lowerCorner, higherCorner, behavior); });
273 }
274 }
275
288 template <typename Lambda, typename A>
289 void reduce(Lambda reduceLambda, A &result, const std::array<double, 3> &lowerCorner,
290 const std::array<double, 3> &higherCorner, IteratorBehavior behavior) {
291 for (auto &child : _children) {
292 double vol = child->getEnclosedVolumeWith(lowerCorner, higherCorner);
293 if (vol > 0.0)
295 child, [&](auto nodePtr) { nodePtr->reduce(reduceLambda, result, lowerCorner, higherCorner, behavior); });
296 }
297 }
298
299 private:
303 std::array<std::unique_ptr<OctreeNodeInterface<Particle_T>>, 8> _children;
304};
305} // namespace autopas
Inner nodes of the octree data structure.
Definition: OctreeInnerNode.h:23
void clearChildren(std::unique_ptr< OctreeNodeInterface< Particle_T > > &ref) override
Delete the entire tree below this node.
Definition: OctreeInnerNode.h:149
size_t getNumberOfParticles(IteratorBehavior behavior) const override
Get the number of particles with respect to the specified IteratorBehavior.
Definition: OctreeInnerNode.h:174
bool deleteParticle(Particle_T &particle) override
Delete the given particle from the data structure.
Definition: OctreeInnerNode.h:111
void forEach(Lambda forEachLambda)
Apply the forEach lambda to each particle.
Definition: OctreeInnerNode.h:239
void appendAllLeaves(std::vector< OctreeLeafNode< Particle_T > * > &leaves) const override
Put all leaves below this subtree into a given list.
Definition: OctreeInnerNode.h:215
OctreeNodeInterface< Particle_T > * SON(octree::Octant octant) override
Get a child node of this node (if there are children) given a specific octant using the spacial struc...
Definition: OctreeInnerNode.h:209
void reduce(Lambda reduceLambda, A &result)
Apply the reduce lambda to each particle.
Definition: OctreeInnerNode.h:249
bool hasChildren() override
Check if the node is a leaf or an inner node.
Definition: OctreeInnerNode.h:185
void reduce(Lambda reduceLambda, A &result, const std::array< double, 3 > &lowerCorner, const std::array< double, 3 > &higherCorner, IteratorBehavior behavior)
Apply the reduce lambda to each particle in the region.
Definition: OctreeInnerNode.h:289
std::set< OctreeLeafNode< Particle_T > * > getLeavesInRange(const std::array< double, 3 > &min, const std::array< double, 3 > &max) override
Find all leaves below this subtree that are in the given range.
Definition: OctreeInnerNode.h:221
std::vector< OctreeLeafNode< Particle_T > * > getLeavesFromDirections(const std::vector< octree::Vertex > &directions) override
Find all leaf nodes along a list of given directions.
Definition: OctreeInnerNode.h:192
void collectAllParticles(std::vector< Particle_T * > &ps) const override
Put all particles that are below this node into the vector.
Definition: OctreeInnerNode.h:130
size_t size() const override
Get the total number of particles saved in the container (owned + halo + dummy).
Definition: OctreeInnerNode.h:163
OctreeInnerNode(const std::array< double, 3 > &boxMin, const std::array< double, 3 > &boxMax, OctreeNodeInterface< Particle_T > *parent, int unsigned treeSplitThreshold, double interactionLength, double cellSizeFactor)
Create an octree inner node that points to eight leaves.
Definition: OctreeInnerNode.h:34
void forEach(Lambda forEachLambda, const std::array< double, 3 > &lowerCorner, const std::array< double, 3 > &higherCorner, IteratorBehavior behavior)
Apply the forEach lambda to each particle in the region.
Definition: OctreeInnerNode.h:266
OctreeNodeInterface< Particle_T > * getChild(int index) override
Get a child by its index from the node.
Definition: OctreeInnerNode.h:190
void appendAllLeafBoxes(std::vector< std::pair< std::array< double, 3 >, std::array< double, 3 > > > &boxes) const override
Put the min/max corner coordinates of every leaf into the vector.
Definition: OctreeInnerNode.h:140
std::unique_ptr< OctreeNodeInterface< Particle_T > > insert(const Particle_T &p) override
Insert a particle into the octree.
Definition: OctreeInnerNode.h:98
OctreeInnerNode(const OctreeInnerNode< Particle_T > &other)
Copy all children from the other octree into this octree.
Definition: OctreeInnerNode.h:81
An octree leaf node.
Definition: OctreeLeafNode.h:27
The base class that provides the necessary function definitions that can be applied to an octree.
Definition: OctreeNodeInterface.h:32
std::array< double, 3 > _boxMin
The min coordinate of the enclosed volume.
Definition: OctreeNodeInterface.h:393
const std::array< double, 3 > & getBoxMax() const
Get the maximum coordinate of the enclosing box.
Definition: OctreeNodeInterface.h:370
std::array< double, 3 > _boxMax
The max coordinate of the enclosed volume.
Definition: OctreeNodeInterface.h:398
const std::array< double, 3 > & getBoxMin() const
Get the minimum coordinate of the enclosing box.
Definition: OctreeNodeInterface.h:364
double _interactionLength
The minimum distance at which a force is considered nonzero, cutoff+skin.
Definition: OctreeNodeInterface.h:408
int unsigned _treeSplitThreshold
Maximum number of particles inside a leaf node before the leaf tries to split itself.
Definition: OctreeNodeInterface.h:403
OctreeNodeInterface< Particle_T > * _parent
A pointer to the parent node.
Definition: OctreeNodeInterface.h:388
double _cellSizeFactor
The cell size factor for this node.
Definition: OctreeNodeInterface.h:413
static void exception(const Exception e)
Handle an exception derived by std::exception.
Definition: ExceptionHandler.h:63
Vertex
This enum can be used to index all vertices of a cube including an "invalid" vertex.
Definition: OctreeDirection.h:79
void to_string(std::ostream &os, const Container &container, const std::string &delimiter, const std::array< std::string, 2 > &surround, Fun elemToString)
Generates a string representation of a container which fulfills the Container requirement (provide cb...
Definition: ArrayUtils.h:102
In this namespace some helper classes and functions can be found used inside of AutoPas.
Definition: namespaces.h:44
This is the main namespace of AutoPas.
Definition: AutoPasDecl.h:32
decltype(auto) withStaticNodeType(const std::unique_ptr< OctreeNodeInterface< Particle_T > > &root, FunctionType &&function)
Will execute the passed function on the given root node.
Definition: OctreeStaticNodeSelector.h:29