#include <iostream> #include <cmath> #include "../datastructures/Body.hpp" #include "../datastructures/Box.hpp" #include "MpiSimulation.hpp" #include "../datastructures/Tree.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(); 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])); 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) { 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); } } }