#include <iostream> #include <cmath> #include "../datastructures/Body.hpp" #include "../datastructures/Box.hpp" #include "MpiSimulation.hpp" #include "../datastructures/Tree.hpp" #include "../datastructures/Node.hpp" namespace nbody { using namespace std; 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]; this->mpiSize = MPI::COMM_WORLD.Get_size(); this->mpiRank = MPI::COMM_WORLD.Get_rank(); 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])); displacements[3] = MPI::Get_address(&(b[0].acceleration[0])) - MPI::Get_address(&(b[0])); displacements[4] = MPI::Get_address(&(b[0].mass)) - MPI::Get_address(&(b[0])); displacements[5] = MPI::Get_address(&(b[0].refinement)) - MPI::Get_address(&(b[0])); displacements[6] = MPI::Get_address(&(b[1])) - MPI::Get_address(&(b[0])); this->bodyType = this->bodyType.Create_struct(7, blocklengths, displacements, datatypes); this->bodyType.Commit(); if (this->mpiRank == 0) { if (argc != 2) { this->correctState = false; } else { 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); if (!this->correctState) { cerr << "Error occurred: terminating ..." << endl; this->bodyType.Free(); MPI::Finalize(); exit(-1); } } void MpiSimulation::cleanup() { while (!this->comms.empty()) { this->comms.back().cleanup(); this->comms.pop_back(); } this->bodyType.Free(); } bool MpiSimulation::stateCorrect() { return this->correctState; } MpiSimulation::~MpiSimulation() { } int MpiSimulation::getNumberOfProcesses() { return this->mpiSize; } int MpiSimulation::getProcessId() { return this->mpiRank; } void MpiSimulation::distributeBodies() { this->comms.push_back(MpiBodyComm(&this->bodyType)); if (this->mpiRank == 0) { vector<Node> nodes; Box bb; nodes.push_back(Node(NULL)); nodes.front().setBodies(this->bodies); bb = nodes.front().getBB(); bb.extendForBodies(this->bodies); nodes.front().setBB(bb); while (nodes.size() < this->mpiSize) { int mostBodiesIndex = 0; for (unsigned int i = 0; i < nodes.size(); i++) { if (nodes[i].getBodies().size() > nodes[mostBodiesIndex].getBodies().size()) { mostBodiesIndex = i; } } vector<Box> subdomains = nodes[mostBodiesIndex].getBB().splitLongestSide(); vector<Body> buf = nodes[mostBodiesIndex].getBodies(); Node n(NULL); Box bb; n.setBodies(subdomains[0].extractBodies(buf)); bb.extendForBodies(n.getBodies()); n.setBB(bb); nodes.insert(nodes.begin() + mostBodiesIndex, n); n = Node(NULL); n.setBodies(subdomains[1].extractBodies(buf)); bb.extendForBodies(n.getBodies()); n.setBB(bb); nodes.insert(nodes.begin() + mostBodiesIndex, n); nodes.erase(nodes.begin() + mostBodiesIndex + 2); } this->bodies = nodes[0].getBodies(); /* for (unsigned int i = 1; i < nodes.size(); i++) { vector<MpiBodyComm>::iterator it = this->comms.begin(); while (!it->sendUnblocking(i, nodes[i].getBodies()) && it != this->comms.end()) it++; if (it == this->comms.end()) { this->comms.push_back(MpiBodyComm(&this->bodyType)); this->comms.back().sendUnblocking(i, nodes[i].getBodies()); } } */ } else { //this->comms[0].recvBlocking(0, this->bodies); } cout << this->mpiRank << ": SIZE: " << this->bodies.size() << endl; } }