not crashing

This commit is contained in:
kai
2025-06-15 14:40:43 +02:00
parent e0e970543c
commit 7324ebf5f4
10 changed files with 112 additions and 73 deletions

View File

@@ -1,11 +1,10 @@
#include "game_of_life.h"
GameOfLife::GameOfLife(const Matrix& grid, MPIGridSize mpiProcs)
GameOfLife::GameOfLife(const SuperGrid &grid, MPIGridSize mpiProcs)
: grid_(grid), mpiProcs_(mpiProcs) {}
void GameOfLife::step() {
Matrix next = Matrix::zeros(grid_.rows(), grid_.cols());
SuperGrid next = SuperGrid::zeros(grid_.rows(), grid_.cols());
const int rows = grid_.rows();
const int cols = grid_.cols();
for (int i = 0; i < rows; ++i) {
@@ -25,9 +24,9 @@ int GameOfLife::countLiveNeighbors(int row, int col) const {
for (int i = -1; i <= 1; ++i) {
for (int j = -1; j <= 1; ++j) {
if (i == 0 && j == 0)
continue; // Skip the cell itself
int nextRow = (row + i + rows) % rows; // Wrap around
int nextCol = (col + j + cols) % cols; // Wrap around
continue; // Skip the cell itself
int nextRow = (row + i + rows) % rows; // Wrap around
int nextCol = (col + j + cols) % cols; // Wrap around
if (grid_(nextRow, nextCol) == 1) {
count++;
}
@@ -47,10 +46,6 @@ int GameOfLife::updateCell(int currentState, int numLiveNeighbors) const {
}
}
Matrix GameOfLife::getGrid() const {
return grid_;
}
Matrix GameOfLife::getGrid() const { return grid_.get_matrix(); }
MPIGridSize GameOfLife::mpiProcs() const {
return mpiProcs_;
}
MPIGridSize GameOfLife::mpiProcs() const { return mpiProcs_; }

View File

@@ -1,19 +1,20 @@
#ifndef GAME_OF_LIFE_H
#define GAME_OF_LIFE_H
#include <iostream>
#include <vector>
#include <fstream>
#include <memory>
#include <array>
#include <fstream>
#include <iostream>
#include <memory>
#include <mpi.h>
#include <vector>
#include "common.h"
#include "matrix.h"
#include "super_grid.h"
class GameOfLife {
public:
GameOfLife(const Matrix& grid, MPIGridSize mpiProcs);
public:
GameOfLife(const SuperGrid &grid, MPIGridSize mpiProcs);
void step();
@@ -21,12 +22,12 @@ class GameOfLife {
MPIGridSize mpiProcs() const;
private:
private:
int countLiveNeighbors(int row, int col) const;
int updateCell(int currentState, int numLiveNeighbors) const;
Matrix grid_;
SuperGrid grid_;
MPIGridSize mpiProcs_;
int myRank_ = 0;
@@ -35,4 +36,4 @@ class GameOfLife {
friend class GameOfLifeTest;
};
#endif // GAME_OF_LIFE_H
#endif // GAME_OF_LIFE_H

View File

@@ -1,15 +1,16 @@
#include <iostream>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <memory>
#include <mpi.h>
#include <string>
#include <filesystem>
#include "game_of_life.h"
#include "patterns.h"
#include "matrix_io.h"
#include "utils.h"
#include "common.h"
#include "game_of_life.h"
#include "matrix_io.h"
#include "patterns.h"
#include "super_grid.h"
#include "utils.h"
/**
* Main function to run the simulation of the game of life
@@ -19,12 +20,12 @@ void gameOfLife(MPIGridSize mpiProcs) {
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
// Create a grid that results in some interesting patterns
const Matrix grid = Pattern(20, 40, mpiProcs)
.glider(10, 17)
.beeHive(7, 10)
.octagon(6, 27)
.octagon(12, 0)
.getGrid();
const SuperGrid grid = Pattern(20, 40, mpiProcs)
.glider(10, 17)
.beeHive(7, 10)
.octagon(6, 27)
.octagon(12, 0)
.getGrid();
GameOfLife game(grid, mpiProcs);
@@ -40,7 +41,7 @@ void gameOfLife(MPIGridSize mpiProcs) {
std::cout << "Final state" << std::endl;
print(game);
storeAnimation("output", grid, 150, mpiProcs);
storeAnimation("output", grid.get_matrix(), 150, mpiProcs);
}
/**
@@ -48,7 +49,7 @@ void gameOfLife(MPIGridSize mpiProcs) {
* Initializes MPI, checks command line arguments, and starts the game of life
* simulation.
*/
int main(int argc, char* argv[]) {
int main(int argc, char *argv[]) {
MPI_Init(&argc, &argv);
if (argc != 3) {
std::cout << "Specify number of processes in x and y as arguments\n";
@@ -70,11 +71,11 @@ int main(int argc, char* argv[]) {
try {
gameOfLife({np0, np1});
} catch (const std::exception& e) {
} catch (const std::exception &e) {
std::cerr << "Error: " << e.what() << std::endl;
MPI_Abort(MPI_COMM_WORLD, 1);
return 1;
}
MPI_Finalize();
}
}

View File

@@ -23,6 +23,10 @@ test:
mpicxx $(SOURCE_FILES) test.cpp -g -o game_of_life_test ${COMPILER_FLAGS}
mpirun -np 16 --oversubscribe ./game_of_life_test
tests:
mpicxx $(SOURCE_FILES) test.cpp -g -o game_of_life_test ${COMPILER_FLAGS}
mpirun -np 1 --oversubscribe ./game_of_life_test
runserial:
mpirun -np 1 ./$(PROGRAM_NAME) 1 1
@@ -30,4 +34,4 @@ run: release
mpirun -np 16 --oversubscribe ./$(PROGRAM_NAME) 4 4
ani: animate.py
python3 animate.py
python3 animate.py

View File

@@ -1,7 +1,7 @@
#include "patterns.h"
Pattern::Pattern(int rows, int cols, MPIGridSize mpiProcs)
: mpiProcs_(mpiProcs), grid_(Matrix::zeros(rows / np0(), cols / np1())) {
: mpiProcs_(mpiProcs), grid_(SuperGrid::zeros(rows / np0(), cols / np1())) {
if (rows <= 0 || cols <= 0) {
throw std::invalid_argument("Rows and columns must be positive");
}
@@ -87,7 +87,7 @@ Pattern Pattern::octagon(int row, int col) {
return *this;
}
Matrix Pattern::getGrid() const { return grid_; }
SuperGrid Pattern::getGrid() const { return grid_; }
Pattern Pattern::setCell(int globalRow, int globalCol) {
if (globalRow < 0 || globalCol < 0 || globalRow >= numRowsTotal() ||

View File

@@ -1,11 +1,12 @@
#ifndef PATTERNS_H
#define PATTERNS_H
#include <memory>
#include <array>
#include <mpi.h>
#include "matrix.h"
#include "common.h"
#include "matrix.h"
#include "super_grid.h"
#include <array>
#include <memory>
#include <mpi.h>
/**
* Class to create some patterns for the Game of Life.
@@ -20,10 +21,10 @@
* Pattern pattern(20, 40, comm).glider(10, 17).getGrid();
*/
class Pattern {
public:
public:
Pattern(int rows, int cols, MPIGridSize mpiProcs);
Matrix getGrid() const;
SuperGrid getGrid() const;
Pattern setCell(int globalRow, int globalCol);
@@ -33,7 +34,7 @@ class Pattern {
Pattern octagon(int row, int col);
private:
private:
int numRowsLocal() const;
int numRowsTotal() const;
int numColsLocal() const;
@@ -43,9 +44,9 @@ class Pattern {
int np1() const;
MPIGridSize mpiProcs_;
Matrix grid_;
SuperGrid grid_;
MPI_Comm comm_;
MPI_Comm comm_;
};
#endif // PATTERNS_H
#endif // PATTERNS_H

View File

@@ -7,23 +7,48 @@ class SuperGrid {
public:
static SuperGrid zeros(int rows, int cols);
SuperGrid(const Matrix &other);
double &operator()(int i, int j);
const double &operator()(int i, int j) const;
const Matrix get_matrix() const;
int rows() const;
int cols() const;
double &operator()(int i, int j);
private:
Matrix grid_;
};
inline SuperGrid SuperGrid::zeros(int rows, int cols)
: grid_(Matrix::zeros(rows + 2, cols + 2)), {}
inline SuperGrid::SuperGrid(const Matrix &other) : grid_(other) {}
inline SuperGrid SuperGrid::zeros(int rows, int cols) {
return SuperGrid(Matrix::zeros(rows + 2, cols + 2));
}
inline double &SuperGrid::operator()(int i, int j) {
return this->grid_(i + 1, j + 1);
}
inline const double &SuperGrid::operator()(int i, int j) const {
return this->grid_(i + 1, j + 1);
}
inline int SuperGrid::rows() const { return this->grid_.rows() - 2; }
inline int SuperGrid::cols() const { return this->grid_.cols() - 2; }
inline const Matrix SuperGrid::get_matrix() const {
Matrix mat = Matrix::zeros(this->rows(), this->cols());
for (int i = 0; i < this->rows(); i++) {
for (int j = 0; j < this->rows(); j++) {
mat(i, j) = this->grid_(i + 1, j + 1);
}
}
return mat;
}
#endif // SUPER_GRID_H

View File

@@ -2,6 +2,7 @@
#include "common.h"
#include "game_of_life.h"
#include "matrix.h"
#include "utils.h"
Matrix init_step(Matrix start) {
GameOfLife gol = GameOfLife(start, MPIGridSize());
@@ -21,7 +22,10 @@ TEST(test_survive_2) {
start(0, 0) = 1;
start(0, 1) = 1;
start(1, 0) = 1;
print(start);
Matrix end = init_step(start);
print(end);
check(end(0, 0), 1);
}

View File

@@ -1,6 +1,7 @@
#include "utils.h"
#include "matrix.h"
void clearOrCreateFolder(const std::string& foldername) {
void clearOrCreateFolder(const std::string &foldername) {
namespace fs = std::filesystem;
fs::path folder(foldername);
if (fs::exists(folder)) {
@@ -21,7 +22,7 @@ void clearOrCreateFolder(const std::string& foldername) {
std::cout << "Clearing folder '" << foldername << "'...\n";
// Clear the folder
for (const auto& entry : fs::directory_iterator(folder)) {
for (const auto &entry : fs::directory_iterator(folder)) {
if (fs::is_directory(entry)) {
fs::remove_all(entry);
} else if (fs::is_regular_file(entry)) {
@@ -35,10 +36,8 @@ void clearOrCreateFolder(const std::string& foldername) {
}
}
void storeAnimation(const std::string& foldername,
const Matrix& initstate,
int numSteps,
MPIGridSize mpiProcs) {
void storeAnimation(const std::string &foldername, const Matrix &initstate,
int numSteps, MPIGridSize mpiProcs) {
GameOfLife game(initstate, mpiProcs);
MatrixIO io(mpiProcs);
@@ -67,7 +66,7 @@ void storeAnimation(const std::string& foldername,
}
}
void print(const GameOfLife& game) {
void print(const GameOfLife &game) {
MatrixIO io(game.mpiProcs());
Matrix grid = io.gatherMatrixOnRoot(game.getGrid());
@@ -81,4 +80,13 @@ void print(const GameOfLife& game) {
std::cout << std::endl;
}
}
}
}
void print(Matrix &grid) {
for (int i = 0; i < grid.rows(); ++i) {
for (int j = 0; j < grid.cols(); ++j) {
std::cout << ((grid(i, j) == 1) ? "X " : ". ");
}
std::cout << std::endl;
}
}

View File

@@ -1,15 +1,15 @@
#ifndef UTILS_H
#define UTILS_H
#include <filesystem>
#include <fstream>
#include <iostream>
#include <memory>
#include <fstream>
#include <filesystem>
#include "game_of_life.h"
#include "matrix_io.h"
#include "matrix.h"
#include "common.h"
#include "game_of_life.h"
#include "matrix.h"
#include "matrix_io.h"
/**
* Clears the contents of a folder or create it if it does not exist.
@@ -17,7 +17,7 @@
* all folder contents are removed.
* If the folder does not exist, it is created.
*/
void clearOrCreateFolder(const std::string& foldername);
void clearOrCreateFolder(const std::string &foldername);
/**
* Stores the animation of the Game of Life in a bunch of text files.
@@ -25,12 +25,12 @@ void clearOrCreateFolder(const std::string& foldername);
* where <n> is the step number.
* The files are stored in the specified folder.
*/
void storeAnimation(const std::string& foldername,
const Matrix& initstate,
int numSteps,
MPIGridSize mpiProcs);
void storeAnimation(const std::string &foldername, const Matrix &initstate,
int numSteps, MPIGridSize mpiProcs);
/** Print the current grid of the game on the console */
void print(const GameOfLife& game);
void print(const GameOfLife &game);
#endif // UTILS_H
void print(Matrix &matrix);
#endif // UTILS_H