Newer
Older
#include "Tree.hpp"
Node::Node(Tree* tree_):tree(tree_) {}
Node::Node(const Box& bb_, std::vector<Body> bodies_, Tree* tree_): bodies(std::move(bodies_)), bb(bb_), tree(tree_) {}
Node::Node(std::vector<Body> bodies_, Tree* tree_) : bodies(std::move(bodies_)), bb(bodies), tree(tree_) {}
//check if node needs to be splitted during tree build
if (bodies.size() <= tree->maxLeafBodies) {
//this is to prevent errors with collocated particles
if (bb.volume() <= std::numeric_limits<float>::epsilon()) {
result = false;
}
return result;
}
void Node::extendBBforBodies() {
bb.extendForBodies(bodies);
}
void Node::extendBBtoCube() {
bb.extendToCube();
std::vector<Body> Node::getBodies() const {
}
void Node::insertBefore(Node* node) {
node->next = this;
node->prev = this->prev;
this->prev->next = node;
this->prev = node;
}
void Node::insertAfter(Node* node) {
this->next->insertBefore(node);
}
void Node::unlink() {
this->next->prev = this->prev;
this->prev->next = this->next;
this->next = this;
this->prev = this;
}
if (afterSubtree == nullptr) {
if (!bb.isCorrectBox()) {
if (bb.min > bb.max) {
std::cerr << "bb min " << bb.min << " max " << bb.max << '\n';
return false;
if (std::any_of(std::begin(bodies), std::end(bodies), [&](const Body& b) {return !isContained(b, bb); })) {
std::cerr << "bb out of bounds\n";
return false;
if (!leaf) {
Node* current = next;
std::size_t children = 0;
while (current != nullptr && current != afterSubtree) {
current = current->afterSubtree;
children++;
}
if (children != tree->numberOfChildren()) {
std::cerr << "wrong number of children " << children << '\n';
current = next;
for (std::size_t i = 0; i < tree->numberOfChildren(); i++) {
current = current->afterSubtree;
}
if (current != afterSubtree) {
std::cerr << "last sibling afterSubtree inconsistent\n";
return false;
}
}
if (!leaf && !bodies.empty()) {
if (leaf && nextSibling != nullptr && next != nextSibling) {
return false;
}
return true;
}
auto siblingNodesView = tree->getSiblingNodesView(this);
auto mass = [&] {
return leaf
? std::accumulate(std::begin(bodies), std::end(bodies), 0.0, [](double m, const Body& b) { return m + b.mass; })
: std::accumulate(std::begin(siblingNodesView), std::end(siblingNodesView), 0.0, [](double m, const Node& n) { return m + n.representative.mass; }); }();
auto position = [&] {
return leaf
? std::accumulate(std::begin(bodies), std::end(bodies), Vec3{}, [](Vec3 p, const Body& b) { return p + (b.position * b.mass); })
: Vec3{ 0.0 }; }();
representative.position = position / mass;
representative.mass = mass;
//get criterion to check if node is sufficient for force evaluation
return bb.maxSidelength();
void Node::print(std::size_t parallelId) const {
bb.printBB(parallelId);
for (const auto& body : bodies) {
//check if node is sufficient for force evaluation
bool Node::sufficientForBody(const Body& body) const {
const auto distance2 = SquaredDistance(representative.position, body.position);
return distance2 > std::pow(getL(), 2.0);
//check if node is sufficient for force evaluation for all bodies in box
bool Node::sufficientForBox(const Box& box) const {
return bb.distanceToBox(box) > getL();
void Node::extractLocalBodiesTo(std::vector<Body>& result) {
std::copy_if(std::begin(bodies), std::end(bodies), std::back_inserter(result), [](const Body& b) {return !b.refinement; });
bodies.clear();