Skip to content
Snippets Groups Projects
Commit c04b3b64 authored by Paul Heinzlreiter's avatar Paul Heinzlreiter
Browse files

* particle distribution

parent 8d83982f
Branches
No related merge requests found
......@@ -12,23 +12,7 @@ namespace nbody {
}
vector<Box> BarnesHutTree::splitBB(Node* node) {
vector<Box> result;
for (unsigned int i = 0; i < 8; i++) {
Box current = node->getBB();
for (unsigned int j = 0; j < 3; j++) {
double middle = current.getMin(j) + (current.getMax(j) - current.getMin(j)) / 2.0;
if (i & (1 << j)) {
current.setMin(j, middle);
} else {
current.setMax(j, middle);
}
}
result.push_back(current);
}
return result;
return node->getBB().octreeSplit();
}
int BarnesHutTree::numberOfChildren() {
......
......@@ -28,6 +28,24 @@ namespace nbody {
this->max[index] = value;
}
void Box::extendForBodies(vector<Body> bodies) {
if (bodies.empty()) return;
for (int i = 0; i < 3; i++) {
this->min[i] = bodies.front().position[i];
this->max[i] = bodies.front().position[i];
}
for (vector<Body>::iterator it = bodies.begin(); it != bodies.end(); it++) {
for (int i = 0; i < 3; i++) {
if (it->position[i] < this->min[i]) {
this->min[i] = it->position[i];
}
if (it->position[i] > this->max[i]) {
this->max[i] = it->position[i];
}
}
}
}
void Box::extendToCube() {
int longestSide = -1;
double sidelength = 0.0;
......@@ -163,6 +181,26 @@ namespace nbody {
}
vector<Box> Box::octreeSplit() {
vector<Box> result;
for (unsigned int i = 0; i < 8; i++) {
Box current = *this;
for (unsigned int j = 0; j < 3; j++) {
double middle = current.getMin(j) + (current.getMax(j) - current.getMin(j)) / 2.0;
if (i & (1 << j)) {
current.setMin(j, middle);
} else {
current.setMax(j, middle);
}
}
result.push_back(current);
}
return result;
}
bool Box::isCorrect() {
for (int i = 0; i < 3; i++) {
if (this->max[i] < this->min[i]) {
......
......@@ -16,6 +16,7 @@ namespace nbody {
Box();
virtual ~Box();
virtual void extendToCube();
virtual void extendForBodies(vector<Body> bodies);
virtual double getMin(int index);
virtual double getMax(int index);
virtual void setMin(int index, double value);
......@@ -30,6 +31,7 @@ namespace nbody {
virtual void print();
virtual bool overlapsSphere(double* sphereCenter, double sphereRadius);
virtual double distanceToPosition(double* position);
virtual vector<Box> octreeSplit();
};
}
......
......@@ -41,21 +41,7 @@ namespace nbody {
}
void Node::extendBBforBodies() {
if (this->bodies.empty()) return;
for (int i = 0; i < 3; i++) {
this->bb.min[i] = this->bodies.front().position[i];
this->bb.max[i] = this->bodies.front().position[i];
}
for (vector<Body>::iterator it = this->bodies.begin(); it != this->bodies.end(); it++) {
for (int i = 0; i < 3; i++) {
if (it->position[i] < this->bb.getMin(i)) {
this->bb.min[i] = it->position[i];
}
if (it->position[i] > this->bb.max[i]) {
this->bb.max[i] = it->position[i];
}
}
}
this->bb.extendForBodies(this->bodies);
}
void Node::extendBBtoCube() {
......
#include "datastructures/BarnesHutTree.hpp"
#include "parallelization/MpiSimulation.hpp"
#include <iostream>
#include <mpi.h>
using namespace nbody;
using namespace std;
int main(int argc, char* argv[]) {
MPI::Init(argc, argv);
MpiSimulation simulation(argc, argv);
simulation.distributeBodies();
simulation.cleanup();
MPI::Finalize();
return 0;
}
......@@ -11,14 +11,22 @@ namespace nbody {
}
MpiBodyComm::~MpiBodyComm() {
/*
if (this->request != MPI::REQUEST_NULL) {
//wait for termination of possibly open request
this->request.Wait();
//TODO: check why request cannot be freed
//this->request.Free();
}
*/
}
void MpiBodyComm::cleanup() {
if (this->request != MPI::REQUEST_NULL) {
this->request.Wait();
//this->request.Free();
}
}
void MpiBodyComm::sendBlocking(int target, vector<Body> bodies) {
MPI::COMM_WORLD.Send(&bodies[0], bodies.size(), *this->datatype, target, 0);
......@@ -44,10 +52,12 @@ namespace nbody {
//unblocking send still not finished
return false;
}
/*
if (this->request != MPI::REQUEST_NULL) {
//TODO: check if works for reuse of a MPIBodyComm
this->request.Free();
}
*/
this->buffer.resize(bodies.size());
std::copy(bodies.begin(), bodies.end(), this->buffer.begin());
this->request = MPI::COMM_WORLD.Isend(&this->buffer[0], this->buffer.size(), *this->datatype, target, 0);
......
......@@ -16,6 +16,7 @@ namespace nbody {
public:
MpiBodyComm(MPI::Datatype* bodyDatatype);
virtual ~MpiBodyComm();
virtual void cleanup();
virtual void sendBlocking(int target, vector<Body> bodies);
virtual void recvBlocking(int source, vector<Body>& bodies);
virtual bool sendUnblocking(int target, vector<Body> bodies);
......
#include <iostream>
#include <cmath>
#include "../datastructures/Body.hpp"
#include "../datastructures/Box.hpp"
#include "MpiSimulation.hpp"
#include "../datastructures/Tree.hpp"
......@@ -8,15 +10,23 @@ namespace nbody {
MpiSimulation::MpiSimulation(int& argc, char**& argv) {
Body b[2];
//number of (array) elements in struct elements
int blocklengths[7] = {1, 3, 3, 3, 1, 1, 1};
//dataytypes with lower bound and upper bound adresses of the structure
MPI::Datatype datatypes[7] = {MPI::LB, MPI::DOUBLE, MPI::DOUBLE, MPI::DOUBLE, MPI::DOUBLE, MPI::BOOL, MPI::UB};
MPI::Aint displacements[7];
MPI::Init(argc, argv);
this->mpiSize = MPI::COMM_WORLD.Get_size();
this->mpiRank = MPI::COMM_WORLD.Get_rank();
float log2 = logf(this->mpiSize) / logf(2.0f);
if (ceilf(log2) != log2 || floorf(log2) != log2) {
cerr << "number of processes needs to be a power of two" << endl;
MPI::Finalize();
exit(-1);
}
this->correctState = true;
this->bodyType = MPI::DATATYPE_NULL;
//displacements are calculated from the start of the structure
displacements[0] = MPI::Get_address(&(b[0])) - MPI::Get_address(&(b[0]));
displacements[1] = MPI::Get_address(&(b[0].position[0])) - MPI::Get_address(&(b[0]));
displacements[2] = MPI::Get_address(&(b[0].velocity[0])) - MPI::Get_address(&(b[0]));
......@@ -34,22 +44,25 @@ namespace nbody {
this->bodies = Tree::dubinskiParse(string(argv[1]));
if (this->bodies.empty()) {
this->correctState = false;
cerr << "Body file parsing failed" << endl;
}
}
}
MPI::COMM_WORLD.Bcast(&this->correctState, 1, MPI::BOOL, 0);
MpiBodyComm comm(&this->bodyType);
if (!this->correctState) {
cerr << "Error occurred: terminating ..." << endl;
this->bodyType.Free();
MPI::Finalize();
exit(-1);
}
}
if (this->mpiRank == 0) {
comm.sendUnblocking(1, this->bodies);
} else if (this->mpiRank == 1) {
while (!comm.recvUnblocking(0, this->bodies));
//comm.recvBlocking(0, this->bodies);
cout << "SIZE: " << this->bodies.size() << endl;
for (unsigned int i = 0; i < this->bodies.size(); i++) {
this->bodies[i].print();
}
void MpiSimulation::cleanup() {
while (!this->comms.empty()) {
this->comms.back().cleanup();
this->comms.pop_back();
}
this->bodyType.Free();
}
bool MpiSimulation::stateCorrect() {
......@@ -57,8 +70,6 @@ namespace nbody {
}
MpiSimulation::~MpiSimulation() {
this->bodyType.Free();
MPI::Finalize();
}
int MpiSimulation::getNumberOfProcesses() {
......@@ -68,4 +79,29 @@ namespace nbody {
int MpiSimulation::getProcessId() {
return this->mpiRank;
}
void MpiSimulation::distributeBodies() {
this->comms.push_back(MpiBodyComm(&this->bodyType));
if (this->mpiRank == 0) {
Box bb;
vector<Box> domains;
vector<MpiBodyComm>::iterator it;
bb.extendForBodies(this->bodies);
bb.extendToCube();
domains = bb.octreeSplit();
for (int i = 1; i < this->mpiSize; i++) {
vector<Body> toSend = domains[i].extractBodies(this->bodies);
it = this->comms.begin();
while (!it->sendUnblocking(i, toSend) && it != this->comms.end()) it++;
if (it == this->comms.end()) {
this->comms.push_back(MpiBodyComm(&this->bodyType));
this->comms.back().sendUnblocking(i, toSend);
}
}
} else {
this->comms[0].recvBlocking(0, this->bodies);
}
}
}
......@@ -21,9 +21,11 @@ namespace nbody {
public:
MpiSimulation(int& argc, char**& argv);
virtual ~MpiSimulation();
virtual void cleanup();
virtual int getNumberOfProcesses();
virtual int getProcessId();
virtual bool stateCorrect();
virtual void distributeBodies();
};
}
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment