Skip to content
Tile.hpp 2.53 KiB
Newer Older
#include <string>
#include "gsl/gsl"
#include "mpi.h"
#include "Configuration.hpp"
#include "FileIO.hpp"
#include "MpiEnvironment.hpp"
#include "Util.hpp"
#include "state.hpp"

class Tile {
	const MpiEnvironment& _env;
	const Configuration& _cfg;

	const HeaderInfo _header;
	const Size _tileSize;
	std::vector<State> _memoryA;
	std::vector<State> _memoryB;
	gsl::multi_span<State, -1, -1> _model;
	gsl::multi_span<State, -1, -1> _nextModel;

	Tile(const Configuration& cfg, const MpiEnvironment& env)
	    : _env(env), _cfg(cfg),
	      _header(FileIO::ReadHeader(cfg.InputFilePath)), //
	      _tileSize(FileIO::GetTileSize(_header.GlobalSize, cfg.Grid)) {
		if ((_header.GlobalSize.Cols % _tileSize.Cols) != 0 ||
		    (_header.GlobalSize.Rows % _tileSize.Rows) != 0) {
			std::cerr
			    << "Wireworld size is not even divisible by the grid size.\n";
			MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
		}
Thomas Steinreiter's avatar
Thomas Steinreiter committed
		const auto bufsize = (_tileSize.Cols + 2) * (_tileSize.Rows + 2);
		_memoryA.resize(bufsize);
		_memoryB.resize(bufsize);
		_model =
		    gsl::as_multi_span(_memoryA.data(), gsl::dim(_tileSize.Rows + 2),
		                       gsl::dim(_tileSize.Cols + 2));
		_nextModel =
		    gsl::as_multi_span(_memoryB.data(), gsl::dim(_tileSize.Rows + 2),
		                       gsl::dim(_tileSize.Cols + 2));

		FileIO::Tile(cfg.InputFilePath, _header, cfg.Grid, _env.worldRank(),
		             gsl::span<State>(_model))
		    .Read();

		if (env.worldRank() == 0)
			std::cout << "Tilesitze: cols:" << _tileSize.Cols
			          << ", rows: " << _tileSize.Rows << "\n";

  public:
	auto& model() { return _model; }
	auto& model() const { return _model; }
	auto& nextModel() { return _nextModel; }
	auto tileSize() const { return _tileSize; }

	static auto Read(const Configuration& cfg, const MpiEnvironment& env) {
		return Tile{cfg, env};
	}

	void write() const {
		const auto& path = _cfg.OutputFilePath;
		FileIO::WriteHeader(_header, path, _env);
		FileIO::Tile(path, _header, _cfg.Grid, _env.worldRank(),
		             gsl::span<State>(_model))
		    .Write();
	}
};

std::ostream& operator<<(std::ostream& out, const Tile& t) {
Thomas Steinreiter's avatar
Thomas Steinreiter committed
	const auto hline = [](auto& out, auto length) {
		out << '+';
		std::fill_n(std::ostream_iterator<char>(out), length, '-');
		out << "+\n";
	};
	hline(out, t.tileSize().Cols);
	for (std::size_t x{1}; x <= t.tileSize().Rows; ++x) {
		out << '|';
		for (std::size_t y{1}; y <= t.tileSize().Cols; ++y) {
			out << to_integral(t.model()[x][y]);
		}
		out << "|\n";
	}
	hline(out, t.tileSize().Cols);
	return out;
}