Skip to content
Tile.cpp 1.81 KiB
Newer Older
#include "Tile.hpp"

#include <iostream>
#include <string>

#include <mpi.h>

#include "FileIO.hpp"
#include "State.hpp"

Tile::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) {
		MpiReportErrorAbort(
		    "Wireworld size is not even divisible by the grid size.");
	}
	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();
}

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

void Tile::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) {
	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;
}