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;
public:
MpiWireworld(const MpiEnvironment& env, const Configuration& cfg)
: _env(env), _cfg(cfg), _tile(Tile::Read(cfg, env)),
_comm(env, cfg.Grid, _tile.tileSize()) {}
friend std::ostream& operator<<(std::ostream& out, const MpiWireworld& g) {
// for now, print the own tile
out << g._tile;
return out;
}
void simulateStep() {
auto& _model = _tile.model();
auto& _nextModel = _tile.nextModel();
const auto& _tileSize = _tile.tileSize();
_comm.Communicate(_model); // compute the border area first, then comm
// and compute the rest async
for (std::size_t y{1}; y <= _tileSize.Rows; ++y) {
for (std::size_t x{1}; x <= _tileSize.Cols; ++x) {
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;
}
}
std::swap(_model, _nextModel);
}
};