Skip to content

Instantly share code, notes, and snippets.

@anon767
Last active February 18, 2018 21:21
Show Gist options
  • Save anon767/155f66a9a3d2a3adbf33713ce3198979 to your computer and use it in GitHub Desktop.
Save anon767/155f66a9a3d2a3adbf33713ce3198979 to your computer and use it in GitHub Desktop.
game of life in C and openmpi
#include <endian.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#include <math.h>
#include <sys/time.h>
#define calcIndex(width, x, y) ((y)*(width) + (x))
long TimeSteps = 500;
void writeVTK2(const size_t timestep, const double *data, const char prefix[1024], const unsigned w, const unsigned h) {
char filename[2048];
unsigned x, y;
unsigned offsetX = 0;
unsigned offsetY = 0;
float deltax = 1.0;
float deltay = 1.0;
unsigned nxy = w * h * sizeof(float);
snprintf(filename, sizeof(filename), "%s-%05ld%s", prefix, timestep, ".vti");
FILE *fp = fopen(filename, "w");
fprintf(fp, "<?xml version=\"1.0\"?>\n");
fprintf(fp, "<VTKFile type=\"ImageData\" version=\"0.1\" byte_order=\"LittleEndian\" header_type=\"UInt64\">\n");
fprintf(fp, "<ImageData WholeExtent=\"%d %d %d %d %d %d\" Origin=\"0 0 0\" Spacing=\"%le %le %le\">\n", offsetX,
offsetX + w - 1, offsetY, offsetY + h - 1, 0, 0, deltax, deltax, 0.0);
fprintf(fp, "<CellData Scalars=\"%s\">\n", prefix);
fprintf(fp, "<DataArray type=\"Float32\" Name=\"%s\" format=\"appended\" offset=\"0\"/>\n", prefix);
fprintf(fp, "</CellData>\n");
fprintf(fp, "</ImageData>\n");
fprintf(fp, "<AppendedData encoding=\"raw\">\n");
fprintf(fp, "_");
fwrite((unsigned char *) &nxy, sizeof(long), 1, fp);
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
float value = data[calcIndex(h, x, y)];
fwrite((unsigned char *) &value, sizeof(float), 1, fp);
}
}
fprintf(fp, "\n</AppendedData>\n");
fprintf(fp, "</VTKFile>\n");
fclose(fp);
}
void show(const double *currentfield, int w, int h) {
printf("\033[H");
for (unsigned y = 0; y < h; y++) {
for (unsigned x = 0; x < w; x++) printf(currentfield[calcIndex(w, x, y)] ? "\033[07m \033[m" : " ");
printf("\n");
}
fflush(stdout);
}
void
evolve(const double *currentfield, double *newfield, const unsigned startw, const unsigned starth, const unsigned w,
const unsigned h) {
for (unsigned y = starth; y < h; y++) {
for (unsigned x = startw; x < w; x++) {
if (!((x > 0) && (x < w - 1) && (y > 0) && (y < h - 1)))
continue; //skip edges
double sum = currentfield[calcIndex(w, x - 1, y - 1)]
+ currentfield[calcIndex(w, x, y - 1)]
+ currentfield[calcIndex(w, x - 1, y)]
+ currentfield[calcIndex(w, x + 1, y + 1)]
+ currentfield[calcIndex(w, x + 1, y)]
+ currentfield[calcIndex(w, x, y + 1)]
+ currentfield[calcIndex(w, x - 1, y + 1)]
+ currentfield[calcIndex(w, x + 1, y - 1)];
double currentcell = currentfield[calcIndex(w, x, y)];
if (currentcell == 0 && sum == 3)
newfield[calcIndex(w, x, y)] = 1;
else if (currentcell == 1 && sum < 2)
newfield[calcIndex(w, x, y)] = 0;
else if (currentcell == 1 && sum > 3)
newfield[calcIndex(w, x, y)] = 0;
else if (currentcell == 1 && (sum == 2 || sum == 3))
newfield[calcIndex(w, x, y)] = currentcell;
}
}
}
void filling(double *currentfield, const unsigned w, const unsigned h) {
for (size_t i = 0; i < h * w; i++) {
currentfield[i] = (rand() < RAND_MAX / 5) ? 1 : 0; ///< init domain randomly
}
for (size_t y = 0; y < h; y++) {
for (size_t x = 0; x < w; x++) {
if (!((x > 0) && (x < w - 1) && (y > 0) && (y < h - 1)))
currentfield[calcIndex(w, x, y)] = 0;
}
}
}
void game(const unsigned w, const unsigned h) {
double *currentfield = calloc(w * h, sizeof(double));
double *newfield = calloc(w * h, sizeof(double));
unsigned numthreads = 0;
printf("gimme thread num nomnomnomnom:");
fscanf(stdin, "%d", &numthreads);
filling(currentfield, w, h);
for (size_t t = 0; t < TimeSteps; t++) {
show(currentfield, w, h);
memcpy(newfield, currentfield, w * h * sizeof(double));
#pragma omp parallel for num_threads(numthreads)
for (size_t i = 0; i < numthreads; i++) {
evolve(currentfield, newfield, 0, (h / numthreads) * i, w, h / numthreads * (i + 1));
}
printf("%ld timestep\n", t);
// writeVTK2(t, currentfield, "gol", w, h);
#pragma omp barrier
usleep(100000);
//SWAP
double *temp = currentfield;
currentfield = newfield;
newfield = temp;
}
free(currentfield);
free(newfield);
}
int main(int c, char **v) {
unsigned w = 0, h = 0;
if (c > 1) w = atoi(v[1]); ///< read width
if (c > 2) h = atoi(v[2]); ///< read height
if (w <= 0) w = 40; ///< default width
if (h <= 0) h = 40; ///< default height
game(w, h);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment