AutoPas  3.0.0
Loading...
Searching...
No Matches
OctreeNodeInterface.h
Go to the documentation of this file.
1
7#pragma once
8
9#include <array>
10#include <set>
11#include <vector>
12
15#include "autopas/utils/inBox.h"
16
17namespace autopas {
23template <typename Particle_T>
24class OctreeLeafNode;
25
31template <class Particle_T>
33 public:
43 OctreeNodeInterface(const std::array<double, 3> &boxMin, const std::array<double, 3> &boxMax,
44 OctreeNodeInterface<Particle_T> *parent, const int unsigned treeSplitThreshold,
45 const double interactionLength, const double cellSizeFactor)
46 : _boxMin(boxMin),
47 _boxMax(boxMax),
48 _parent(parent),
49 _treeSplitThreshold(treeSplitThreshold),
50 _interactionLength(interactionLength),
51 _cellSizeFactor(cellSizeFactor) {}
52
54 virtual ~OctreeNodeInterface() = default;
55
58
64 virtual std::unique_ptr<OctreeNodeInterface<Particle_T>> insert(const Particle_T &p) = 0;
65
69 virtual bool deleteParticle(Particle_T &particle) = 0;
70
75 virtual void collectAllParticles(std::vector<Particle_T *> &ps) const = 0;
76
81 virtual void appendAllLeafBoxes(
82 std::vector<std::pair<std::array<double, 3>, std::array<double, 3>>> &boxes) const = 0;
83
88 virtual void appendAllLeaves(std::vector<OctreeLeafNode<Particle_T> *> &leaves) const = 0;
89
94 virtual void clearChildren(std::unique_ptr<OctreeNodeInterface<Particle_T>> &ref) = 0;
95
99 virtual size_t size() const = 0;
100
104 virtual size_t getNumberOfParticles(IteratorBehavior behavior = IteratorBehavior::owned) const = 0;
105
113
120 virtual bool hasChildren() = 0;
121
128
135 virtual std::set<OctreeLeafNode<Particle_T> *> getLeavesInRange(const std::array<double, 3> &min,
136 const std::array<double, 3> &max) = 0;
137
143 bool isInside(const std::array<double, 3> &point) {
144 using namespace autopas::utils;
145 return inBox(point, _boxMin, _boxMax);
146 }
147
157 static bool volumeExistsOnAxis(const int axis, const std::array<double, 3> &aMin, const std::array<double, 3> &aMax,
158 const std::array<double, 3> &bMin, const std::array<double, 3> &bMax) {
159 const bool o1 = aMin[axis] < bMax[axis];
160 const bool o2 = bMin[axis] < aMax[axis];
161 return o1 and o2;
162 }
163
171 return volumeExistsOnAxis(axis, this->getBoxMin(), this->getBoxMax(), other->getBoxMin(), other->getBoxMax());
172 }
173
180 bool overlapsBox(const std::array<double, 3> &otherMin, const std::array<double, 3> &otherMax) {
181 bool result = true;
182 for (auto d = 0; d < 3; ++d) {
183 result &= (this->_boxMin[d] <= otherMax[d]) and (this->_boxMax[d] >= otherMin[d]);
184 }
185 return result;
186 }
187
196 static double getEnclosedVolumeWith(const std::array<double, 3> &aMin, const std::array<double, 3> &aMax,
197 const std::array<double, 3> &bMin, const std::array<double, 3> &bMax) {
198 auto product = 1.0;
199 int count = 0;
200 for (auto d = 0; d < 3; ++d) {
201 auto minOnAxis = std::max(aMin[d], bMin[d]);
202 auto maxOnAxis = std::min(aMax[d], bMax[d]);
203 auto dim = (maxOnAxis - minOnAxis);
204 if (dim > 0) {
205 ++count;
206 } else {
207 break;
208 }
209 product *= dim;
210 }
211 auto result = count == 3 ? product : 0;
212 return result;
213 }
214
221 double getEnclosedVolumeWith(const std::array<double, 3> &otherMin, const std::array<double, 3> &otherMax) {
222 return getEnclosedVolumeWith(this->getBoxMin(), this->getBoxMax(), otherMin, otherMax);
223 }
224
232 OctreeNodeInterface<Particle_T> *param, *P = this;
233 if (ADJ(I, SONTYPE(P))) {
234 param = FATHER(P)->EQ_FACE_NEIGHBOR(I);
235 } else {
236 param = FATHER(P);
237 }
238 return param->SON(REFLECT(I, SONTYPE(P)));
239 }
240
248 OctreeNodeInterface<Particle_T> *param, *P = this;
249 if (ADJ(I, SONTYPE(P))) {
250 param = FATHER(P)->EQ_EDGE_NEIGHBOR(I);
251 } else if (COMMON_FACE(I, SONTYPE(P)) != octree::O) {
252 param = FATHER(P)->EQ_FACE_NEIGHBOR(COMMON_FACE(I, SONTYPE(P)));
253 } else {
254 param = FATHER(P);
255 }
256 return param->SON(REFLECT(I, SONTYPE(P)));
257 }
258
266 OctreeNodeInterface<Particle_T> *param, *P = this;
267 if (ADJ(I, SONTYPE(P))) {
268 param = FATHER(P)->EQ_VERTEX_NEIGHBOR(I);
269 } else if (COMMON_EDGE(I, SONTYPE(P)) != octree::OO) {
270 param = FATHER(P)->EQ_EDGE_NEIGHBOR(COMMON_EDGE(I, SONTYPE(P)));
271 } else if (COMMON_FACE(I, SONTYPE(P)) != octree::O) {
272 param = FATHER(P)->EQ_FACE_NEIGHBOR(COMMON_FACE(I, SONTYPE(P)));
273 } else {
274 param = FATHER(P);
275 }
276 return param->SON(REFLECT(I, SONTYPE(P)));
277 }
278
286
294
302
308 virtual std::vector<OctreeLeafNode<Particle_T> *> getLeavesFromDirections(
309 const std::vector<octree::Vertex> &directions) = 0;
310
316 std::vector<OctreeLeafNode<Particle_T> *> getNeighborLeaves(const octree::Any direction) {
317 auto opposite = octree::getOppositeDirection(direction);
318 auto directions = octree::getAllowedDirections(opposite);
319 auto neighborLeaves = getLeavesFromDirections(directions);
320 return neighborLeaves;
321 }
322
327 std::set<OctreeLeafNode<Particle_T> *> getNeighborLeaves() {
328 std::set<OctreeLeafNode<Particle_T> *> result;
329
330 // Get all face neighbors
331 for (auto face : octree::Tables::faces) {
333 if (neighbor) {
334 auto leaves = neighbor->getNeighborLeaves(face);
335 result.insert(leaves.begin(), leaves.end());
336 }
337 }
338
339 // Get all edge neighbors
340 for (auto edge : octree::Tables::edges) {
342 if (neighbor) {
343 auto leaves = neighbor->getNeighborLeaves(edge);
344 result.insert(leaves.begin(), leaves.end());
345 }
346 }
347
348 // Get all face neighbors
349 for (auto vertex : octree::Tables::vertices) {
351 if (neighbor) {
352 auto leaves = neighbor->getNeighborLeaves(vertex);
353 result.insert(leaves.begin(), leaves.end());
354 }
355 }
356
357 return result;
358 }
359
364 [[nodiscard]] const std::array<double, 3> &getBoxMin() const { return _boxMin; }
365
370 [[nodiscard]] const std::array<double, 3> &getBoxMax() const { return _boxMax; }
371
377
378 protected:
383 bool hasParent() { return _parent != nullptr; }
384
389
393 std::array<double, 3> _boxMin;
394
398 std::array<double, 3> _boxMax;
399
404
409
414};
415
422template <class Particle_T>
424 // According to Samet: "All non-leaf nodes are said to be GRAY"
425 return node->hasChildren();
426}
427
435template <class Particle_T>
437 return node->getParent();
438}
439
448template <class Particle_T>
450 octree::Octant result = octree::OOO;
451 if (FATHER(node)) {
453 if (FATHER(node)->SON(test) == node) {
454 result = test;
455 break;
456 }
457 }
458 if (result == octree::OOO) {
459 throw std::runtime_error("[OctreeNodeInterface::SONTYPE()] Unable to determine SONTYPE");
460 }
461 }
462 return result;
463}
464
465template <class Particle_T>
467 // Check precondition
468 if (not isFace(I)) {
469 throw std::runtime_error("[OctreeNodeInterface::GTEQ_FACE_NEIGHBOR()] Received invalid face.");
470 }
471
472 auto null = [](OctreeNodeInterface<Particle_T> *T) { return T == nullptr; };
473
474 // Find a common ancestor
476 if ((not null(FATHER(P))) and ADJ(I, SONTYPE(P))) {
477 Q = FATHER(P)->GTEQ_FACE_NEIGHBOR(I);
478 } else {
479 Q = FATHER(P);
480 }
481
482 if ((not null(Q)) and GRAY(Q)) {
483 // Follow the reflected path to locate the neighbor
484 return Q->SON(REFLECT(I, SONTYPE(P)));
485 } else {
486 return Q;
487 }
488}
489
490template <class Particle_T>
492 // Check precondition
493 if (not isEdge(I)) {
494 throw std::runtime_error("[OctreeNodeInterface::GTEQ_EDGE_NEIGHBOR()] Received invalid edge.");
495 }
496
497 auto null = [](OctreeNodeInterface<Particle_T> *T) { return T == nullptr; };
498
499 // Find a common ancestor
501 if (null(FATHER(P))) {
502 Q = nullptr;
503 } else if (ADJ(I, SONTYPE(P))) {
504 Q = FATHER(P)->GTEQ_EDGE_NEIGHBOR(I);
505 } else if (octree::Face common = COMMON_FACE(I, SONTYPE(P)); common != octree::O) {
506 Q = FATHER(P)->GTEQ_FACE_NEIGHBOR(common);
507 } else {
508 Q = FATHER(P);
509 }
510
511 if ((not null(Q)) and GRAY(Q)) {
512 // Follow opposite path to locate the neighbor
513 return Q->SON(REFLECT(I, SONTYPE(P)));
514 } else {
515 return Q;
516 }
517}
518
519template <class Particle_T>
521 // Check precondition
522 if (not isVertex(I)) {
523 throw std::runtime_error("[OctreeNodeInterface::GTEQ_VERTEX_NEIGHBOR()] Received invalid vertex.");
524 }
525
526 // Find a common ancestor
528 if (not FATHER(P)) {
529 Q = nullptr;
530 } else if (ADJ(I, SONTYPE(P))) {
531 Q = FATHER(P)->GTEQ_VERTEX_NEIGHBOR(I);
532 } else if (octree::Edge commonEdge = COMMON_EDGE(I, SONTYPE(P)); commonEdge != octree::OO) {
533 Q = FATHER(P)->GTEQ_EDGE_NEIGHBOR(commonEdge);
534 } else if (octree::Face commonFace = COMMON_FACE(I, SONTYPE(P)); commonFace != octree::O) {
535 Q = FATHER(P)->GTEQ_FACE_NEIGHBOR(commonFace);
536 } else {
537 Q = FATHER(P);
538 }
539
540 if (Q and GRAY(Q)) {
541 // Follow opposite path to locate the neighbor
542 return Q->SON(REFLECT(I, SONTYPE(P)));
543 } else {
544 return Q;
545 }
546}
547} // namespace autopas
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
static double getEnclosedVolumeWith(const std::array< double, 3 > &aMin, const std::array< double, 3 > &aMax, const std::array< double, 3 > &bMin, const std::array< double, 3 > &bMax)
Get the enclosed volume between two boxes a and b.
Definition: OctreeNodeInterface.h:196
bool enclosesVolumeWithOtherOnAxis(const int axis, const OctreeNodeInterface< Particle_T > *other)
Check if an octree node's box encloses volume with another octree node's box on a specific axis.
Definition: OctreeNodeInterface.h:170
OctreeNodeInterface< Particle_T > * EQ_EDGE_NEIGHBOR(const octree::Edge I)
Find a node (via the pointer structure) that is of equal size of the current node's bounding box,...
Definition: OctreeNodeInterface.h:247
virtual std::vector< OctreeLeafNode< Particle_T > * > getLeavesFromDirections(const std::vector< octree::Vertex > &directions)=0
Find all leaf nodes along a list of given directions.
std::array< double, 3 > _boxMin
The min coordinate of the enclosed volume.
Definition: OctreeNodeInterface.h:393
virtual std::set< OctreeLeafNode< Particle_T > * > getLeavesInRange(const std::array< double, 3 > &min, const std::array< double, 3 > &max)=0
Find all leaves below this subtree that are in the given range.
const std::array< double, 3 > & getBoxMax() const
Get the maximum coordinate of the enclosing box.
Definition: OctreeNodeInterface.h:370
OctreeNodeInterface(const OctreeNodeInterface< Particle_T > &)=default
Default copy constructor.
virtual void appendAllLeaves(std::vector< OctreeLeafNode< Particle_T > * > &leaves) const =0
Put all leaves below this subtree into a given list.
virtual OctreeNodeInterface< Particle_T > * getChild(int index)=0
Get a child by its index from the node.
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
virtual OctreeNodeInterface< Particle_T > * SON(octree::Octant O)=0
Get a child node of this node (if there are children) given a specific octant using the spacial struc...
OctreeNodeInterface< Particle_T > * GTEQ_EDGE_NEIGHBOR(octree::Edge I)
Find a node (via the pointer structure) that is of greater than or equal to the size of the current n...
Definition: OctreeNodeInterface.h:491
std::set< OctreeLeafNode< Particle_T > * > getNeighborLeaves()
Get the neighbor leaves in all directions.
Definition: OctreeNodeInterface.h:327
double _interactionLength
The minimum distance at which a force is considered nonzero, cutoff+skin.
Definition: OctreeNodeInterface.h:408
OctreeNodeInterface< Particle_T > * EQ_VERTEX_NEIGHBOR(const octree::Vertex I)
Find a node (via the pointer structure) that is of equal size of the current node's bounding box,...
Definition: OctreeNodeInterface.h:265
virtual ~OctreeNodeInterface()=default
To make clang happy.
virtual void collectAllParticles(std::vector< Particle_T * > &ps) const =0
Put all particles that are below this node into the vector.
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 > * getParent() const
Get the parent node of this node.
Definition: OctreeNodeInterface.h:376
bool hasParent()
Check if this is not the root node.
Definition: OctreeNodeInterface.h:383
virtual size_t size() const =0
Get the total number of particles saved in the container (owned + halo + dummy).
OctreeNodeInterface< Particle_T > * _parent
A pointer to the parent node.
Definition: OctreeNodeInterface.h:388
virtual void appendAllLeafBoxes(std::vector< std::pair< std::array< double, 3 >, std::array< double, 3 > > > &boxes) const =0
Put the min/max corner coordinates of every leaf into the vector.
std::vector< OctreeLeafNode< Particle_T > * > getNeighborLeaves(const octree::Any direction)
This function combines all required functions when traversing down a subtree of the octree and findin...
Definition: OctreeNodeInterface.h:316
OctreeNodeInterface< Particle_T > * GTEQ_FACE_NEIGHBOR(octree::Face I)
Find a node (via the pointer structure) that is of greater than or equal to the size of the current n...
Definition: OctreeNodeInterface.h:466
virtual void clearChildren(std::unique_ptr< OctreeNodeInterface< Particle_T > > &ref)=0
Delete the entire tree below this node.
virtual std::unique_ptr< OctreeNodeInterface< Particle_T > > insert(const Particle_T &p)=0
Insert a particle into the octree.
virtual size_t getNumberOfParticles(IteratorBehavior behavior=IteratorBehavior::owned) const =0
Get the number of particles with respect to the specified IteratorBehavior.
bool overlapsBox(const std::array< double, 3 > &otherMin, const std::array< double, 3 > &otherMax)
Check if the node's axis aligned bounding box overlaps with the given axis aligned bounding box.
Definition: OctreeNodeInterface.h:180
double _cellSizeFactor
The cell size factor for this node.
Definition: OctreeNodeInterface.h:413
double getEnclosedVolumeWith(const std::array< double, 3 > &otherMin, const std::array< double, 3 > &otherMax)
Calculate the overlap volume between the node's axis aligned bounding box and the given box.
Definition: OctreeNodeInterface.h:221
static bool volumeExistsOnAxis(const int axis, const std::array< double, 3 > &aMin, const std::array< double, 3 > &aMax, const std::array< double, 3 > &bMin, const std::array< double, 3 > &bMax)
Check if the volume enclosed by two boxes a and b is nonzero on a specific axis.
Definition: OctreeNodeInterface.h:157
virtual bool deleteParticle(Particle_T &particle)=0
Delete the given particle from the data structure.
OctreeNodeInterface(const std::array< double, 3 > &boxMin, const std::array< double, 3 > &boxMax, OctreeNodeInterface< Particle_T > *parent, const int unsigned treeSplitThreshold, const double interactionLength, const double cellSizeFactor)
Create an octree node interface by initializing the given fields.
Definition: OctreeNodeInterface.h:43
virtual bool hasChildren()=0
Check if the node is a leaf or an inner node.
bool isInside(const std::array< double, 3 > &point)
Check if a 3d point is inside the node's axis aligned bounding box.
Definition: OctreeNodeInterface.h:143
OctreeNodeInterface< Particle_T > * EQ_FACE_NEIGHBOR(const octree::Face I)
Find a node (via the pointer structure) that is of equal size of the current node's bounding box,...
Definition: OctreeNodeInterface.h:231
OctreeNodeInterface< Particle_T > * GTEQ_VERTEX_NEIGHBOR(octree::Vertex I)
Find a node (via the pointer structure) that is of greater than or equal to the size of the current n...
Definition: OctreeNodeInterface.h:520
static constexpr std::array< Face, 6 > faces
All available faces for a cube.
Definition: OctreeDirection.h:98
static constexpr std::array< Edge, 12 > edges
All available edges for a cube.
Definition: OctreeDirection.h:103
static constexpr std::array< Vertex, 8 > vertices
All available vertices for a cube.
Definition: OctreeDirection.h:108
int unsigned Any
A datatype that is wide enough to hold faces, edges or vertices.
Definition: OctreeDirection.h:15
std::vector< Octant > getAllowedDirections(Any along)
Get a list of octants that are along the given direction.
Definition: OctreeDirection.h:526
Vertex
This enum can be used to index all vertices of a cube including an "invalid" vertex.
Definition: OctreeDirection.h:79
Edge
This enum can be used to index all edges of a cube including an "invalid" edge.
Definition: OctreeDirection.h:60
Any getOppositeDirection(Any direction)
Convert any direction to a direction that is directly opposing the given direction.
Definition: OctreeDirection.h:504
Face
This enum can be used to index the faces of a cube including an "invalid" face.
Definition: OctreeDirection.h:20
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
OctreeNodeInterface< Particle_T > * FATHER(const OctreeNodeInterface< Particle_T > *node)
Get the parent node of an arbitrary octree node.
Definition: OctreeNodeInterface.h:436
static octree::Octant SONTYPE(const OctreeNodeInterface< Particle_T > *node)
Get the octant in which a given node can be found in the parent.
Definition: OctreeNodeInterface.h:449
bool GRAY(OctreeNodeInterface< Particle_T > *node)
Check if a node is an inner node.
Definition: OctreeNodeInterface.h:423