#include <string> #include <sstream> #include <iostream> #include <fstream> #include "Tree.hpp" #include "Node.hpp" namespace nbody { using namespace std; Tree::Tree() { //insert dummy root node this->nodes = new Node(this); } Tree::~Tree() { this->clean(); delete this->nodes; } void Tree::clean() { //remove all nodes; refresh root node while (this->nodes->next != this->nodes) { Node* node = this->nodes->next; node->unlink(); delete node; } delete this->nodes; this->nodes = new Node(this); } bool Tree::isCorrect() { Node* current = this->nodes->next; while (current != this->nodes) { if (!current->isCorrect()) { return false; } current = current->next; } return true; } unsigned long Tree::numberOfNodes() { unsigned long nodes = 0; for (Node* node = this->nodes->next; node != this->nodes; node = node->next) { nodes++; } return nodes; } void Tree::accumulateForceOnto(Body& body) { Node* n = this->nodes->next; body.resetAcceleration(); while (n != this->nodes) { if (n->sufficientForBody(body)) { n->representative.accumulateForceOnto(body); } else if (n->leaf) { for (vector<Body>::iterator it = n->bodies.begin(); it != n->bodies.end(); it++) { it->accumulateForceOnto(body); } } n = n->afterSubtree; } } void Tree::computeForces() { for (Node* n = this->nodes->next; n != this->nodes; n = n->next) { if (n->leaf) { for (vector<Body>::iterator it = n->bodies.begin(); it != n->bodies.end(); it++) { this->accumulateForceOnto(*it); } } } } vector<Body> Tree::dubinskiParse(string filename) { vector<Body> result; string line; ifstream infile(filename.c_str(), ifstream::in); double mass, px, py, pz, vx, vy, vz; while (infile >> mass >> px >> py >> pz >> vx >> vy >> vz) { Body b(px, py, pz, vx, vy, vz, mass); result.push_back(b); } infile.close(); return result; } vector<Body> Tree::extractLocalBodies() { vector<Body> result; while (this->nodes->next != this->nodes) { if (this->nodes->next->leaf) { for (vector<Body>::iterator it = this->nodes->next->bodies.begin(); it != this->nodes->next->bodies.end(); it++) { if (!it->refinement) { result.push_back(*it); } } } Node* h = this->nodes->next; this->nodes->next->unlink(); delete(h); } this->clean(); return result; } vector<Body> Tree::copyRefinements(Box domain) { vector<Body> result; Node* current = this->nodes->next; while (current != this->nodes) { bool sufficient = current->sufficientForBox(domain); if (sufficient) { result.push_back(current->representative); current = current->afterSubtree; } else if (current->leaf) { result.insert(result.end(), current->bodies.begin(), current->bodies.end()); current = current->next; } else { current = current->next; } } return result; } Box Tree::getRootBB() { return this->nodes->next->bb; } void Tree::rebuild(Box domain) { this->build(this->extractLocalBodies(), domain); } void Tree::advance() { for (Node* n = this->nodes->next; n != this->nodes; n = n->next) { if (n->leaf) { for (vector<Body>::iterator it = n->bodies.begin(); it != n->bodies.end(); it++) { if (!it->refinement) { it->integrate(); } } } } } Box Tree::getLocalBB() { Box result; for (Node* n = this->nodes->next; n != this->nodes; n = n->next) { if (n->leaf) { for (vector<Body>::iterator it = n->bodies.begin(); it != n->bodies.end(); it++) { if (!it->refinement) { result.extend(*it); } } } } return result; } void Tree::print() { this->nodes->next->bb.print(); } }