Skip to content
Snippets Groups Projects
MpiSimulation.cpp 5.77 KiB
Newer Older
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
#include <iostream>
#include <cmath>
#include "../datastructures/Body.hpp"
#include "../datastructures/Box.hpp"
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
#include "MpiSimulation.hpp"
#include "../datastructures/Tree.hpp"
#include "../datastructures/Node.hpp"
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed

namespace nbody {
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
	using namespace std;

Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
	MpiSimulation::MpiSimulation(int& argc, char**& argv) {
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
		Body b[2];
		int blocklengths[7] = {1, 3, 3, 3, 1, 1, 1};
		MPI::Datatype datatypes[7] = {MPI::LB, MPI::DOUBLE, MPI::DOUBLE, MPI::DOUBLE, MPI::DOUBLE, MPI::BOOL, MPI::UB};
		MPI::Aint displacements[7];
		this->bodyType = MPI::DATATYPE_NULL;

		//MPI::Init(argc, argv);
		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();
		this->mpiSize = MPI::COMM_WORLD.Get_size();
		this->mpiRank = MPI::COMM_WORLD.Get_rank();
		this->correctState = true;

		/*
		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];

Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
		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();
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
		*/
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
		if (argc == 2) {
			this->correctState = this->readInputData(string(argv[1]));
		} else {
			this->correctState = false;
		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);
		}
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
		if (this->mpiRank == 0) {
			MPI::COMM_WORLD.Send(b, 2, this->bodyType, 1, 0);
		} else if (this->mpiRank == 1) {
			MPI::COMM_WORLD.Recv(b, 2, this->bodyType, 0, 0);
		}
	}

	bool MpiSimulation::readInputData(string filename) {
		if (this->mpiRank == 0) {
			this->bodies = Tree::dubinskiParse(filename);
			if (this->bodies.empty()) {
				return false;
			}
		}
		return true;
	void MpiSimulation::cleanup() {
		while (!this->comms.empty()) {
			this->comms.back().cleanup();
			this->comms.pop_back();
		this->bodyType.Free();
	}

	bool MpiSimulation::stateCorrect() {
		return this->correctState;
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
	}

	MpiSimulation::~MpiSimulation() {
	}

	int MpiSimulation::getNumberOfProcesses() {
		return this->mpiSize;
	}

	int MpiSimulation::getProcessId() {
		return this->mpiRank;
	}
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
	MPI::Datatype* MpiSimulation::getDatatype() {
		return &this->bodyType;
	}

	void MpiSimulation::distributeBodies() {
		if (this->mpiRank == 0) {
			vector<Node> nodes;
			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();
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed

			for (unsigned int i = 0; i < nodes.size(); i++) {
				cout << i << ": " << nodes[i].getBodies().size() << endl;
			}
			for (unsigned int i = 1; i < nodes.size(); i++) {
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
				this->comms.push_back(MpiBodyComm(&this->bodyType));
				this->comms.back().sendUnblocking(i, nodes[i].getBodies());
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
				/*
				//vector<MpiBodyComm>::iterator it = this->comms.begin();

Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
				//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());
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
				it->sendBlocking(i, nodes[i].getBodies());
				*/
			}
		} else {
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
			this->comms.push_back(MpiBodyComm(&this->bodyType));
			this->comms[0].recvBlocking(0, this->bodies);
		cout << this->mpiRank << ": SIZE: " << this->bodies.size() << endl;
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
}