Newer
Older
#pragma once
#include <algorithm>
#include <array>
#include <cstddef>
#include <fstream>
#include <iostream>
#include <mpi.h>
#include <string>
#include <tuple>
#include <vector>
#include "gsl/multi_span"
#include "gsl/span"
#include "Communicator.hpp"
#include "MpiEnvironment.hpp"
#include "state.hpp"
class MpiWireworld {
const MpiEnvironment& _env;
const Configuration& _cfg;
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
57
58
59
60
61
62
63
64
65
void 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;
}
public:
MpiWireworld(const MpiEnvironment& env, const Configuration& cfg)
: _env(env), _cfg(cfg), _tile(Tile::Read(cfg, env)),
_comm(env, cfg.Grid, _tile.tileSize()) {
// for (std::size_t y{1}; y <= _tile.tileSize().Rows; ++y) {
// for (std::size_t x{1}; x <= _tile.tileSize().Cols; ++x) {
// _idxs.push_back({x, y});
// }
//}
_comm.Communicate(_tile.model());
}
friend std::ostream& operator<<(std::ostream& out, const MpiWireworld& g) {
// for now, print the own tile
out << g._tile;
return out;
}
void write() const { _tile.write(); }
void simulateStep() {
auto& _model = _tile.model();
auto& _nextModel = _tile.nextModel();
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//// 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();
//_comm.Communicate(_model);
// for (std::size_t y{1}; y <= _tileSize.Rows; ++y) {
// for (std::size_t x{1}; x <= _tileSize.Cols; ++x) {
// processCell(x, y);
// }
//}
std::swap(_model, _nextModel);
}
};