Newer
Older
#include "MpiWireworld.hpp"
#include <algorithm>
#include <array>
#include <iostream>
#include <mpi.h>
#include <string>
#include <vector>
#include "Tile.hpp"
#include "Util.hpp"
void MpiWireworld::processCell(std::size_t x, std::size_t y) {
const auto& _model = _tile.model();
auto& _nextModel = _tile.nextModel();
_nextModel[y][x] = [&]() {
switch (currentState) {
case State::ElectronHead:
return State::ElectronTail;
break;
case State::ElectronTail:
return State::Conductor;
break;
case State::Conductor: {
const std::array<State, 9> mooreNeighborhood = {
_model[y - 1][x - 1], //
_model[y + 0][x - 1], //
_model[y + 1][x - 1], //
_model[y - 1][x + 0], //
_model[y + 1][x + 0], //
_model[y - 1][x + 1], //
_model[y + 0][x + 1], //
_model[y + 1][x + 1] //
};
const auto headCount =
std::count(std::begin(mooreNeighborhood),
std::end(mooreNeighborhood), State::ElectronHead);
return (1 == headCount || headCount == 2) ? State::ElectronHead
: State::Conductor;
} break;
default:
return currentState;
break;
}
}();
}
MpiWireworld::MpiWireworld(const MpiEnvironment& env, const Configuration& cfg)
: _env(env), _cfg(cfg), _tile(Tile::Read(cfg, env)),
_comm(env, cfg.CommMode, cfg.Grid, _tile.tileSize()) {
_comm.Communicate(_tile.model());
}
std::ostream& operator<<(std::ostream& out, const MpiWireworld& g) {
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
out << g._tile;
return out;
}
void MpiWireworld::write() const { _tile.write(); }
void MpiWireworld::simulateStep() {
auto& _model = _tile.model();
auto& _nextModel = _tile.nextModel();
const auto _tileSize = _tile.tileSize();
//// compute the border area first, then comm
//// and compute the core async
/// border area
// top
for (std::size_t x{1}; x <= _tileSize.Cols; ++x) {
const auto y = 1;
processCell(x, y);
}
// left and right
for (std::size_t y{2}; y < _tileSize.Rows; ++y) {
const auto x1 = 1;
const auto x2 = _tileSize.Cols;
processCell(x1, y);
processCell(x2, y);
}
// bottom
for (std::size_t x{1}; x <= _tileSize.Cols; ++x) {
const auto y = _tileSize.Rows;
processCell(x, y);
}
// start communication of border while processing the core
auto req = _comm.AsyncCommunicate(_nextModel);
/// core
for (std::size_t y{2}; y < _tileSize.Rows; ++y) {
for (std::size_t x{2}; x < _tileSize.Cols; ++x) { processCell(x, y); }
}
req.Wait();
std::swap(_model, _nextModel);
}