Newer
Older
#include "MpiWireworld.hpp"
#include <algorithm>
#include <array>
#include <iostream>
#include <mpi.h>
#include <string>
#include <vector>
#include "gsl/multi_span"
#include "gsl/span"
#include "FileIO.hpp"
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#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();
auto nextState = _model[y][x];
switch (_model[y][x]) {
case State::ElectronHead:
nextState = State::ElectronTail;
break;
case State::ElectronTail:
nextState = 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);
nextState = (1 == headCount || headCount == 2) ? State::ElectronHead
: State::Conductor;
} break;
default:
break;
}
_nextModel[y][x] = nextState;
}
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()) {
58
59
60
61
62
63
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
_comm.Communicate(_tile.model());
}
std::ostream& operator<<(std::ostream& out, const MpiWireworld& g) {
// for now, print the own tile
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);
}