Skip to content
MpiWireworld.hpp 2.17 KiB
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 "FileIO.hpp"
#include "MpiEnvironment.hpp"
#include "Util.hpp"
#include "state.hpp"

class MpiWireworld {
	const MpiEnvironment& _env;
	const Configuration& _cfg;
	Communicator _comm;
  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;
	void write() const {
		_tile.write();
	}

		auto& _model = _tile.model();
		auto& _nextModel = _tile.nextModel();
Thomas Steinreiter's avatar
Thomas Steinreiter committed
		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]  //
Thomas Steinreiter's avatar
Thomas Steinreiter committed
					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;