YouTube-simulations/percolation.c

338 lines
14 KiB
C
Raw Normal View History

2022-08-01 22:30:40 +02:00
/*********************************************************************************/
/* */
/* Simulation of percolation in 2D */
/* */
/* N. Berglund, July 2022 */
/* */
/* Feel free to reuse, but if doing so it would be nice to drop a */
/* line to nils.berglund@univ-orleans.fr - Thanks! */
/* */
/* compile with */
/* gcc -o percolation percolation.c */
/* -L/usr/X11R6/lib -ltiff -lm -lGL -lGLU -lX11 -lXmu -lglut -O3 -fopenmp */
/* */
/* OMP acceleration may be more effective after executing */
/* export OMP_NUM_THREADS=2 in the shell before running the program */
/* */
/* To make a video, set MOVIE to 1 and create subfolder tif_perc */
/* It may be possible to increase parameter PAUSE */
/* */
/* create movie using */
/* ffmpeg -i perc.%05d.tif -vcodec libx264 perc.mp4 */
/* */
/*********************************************************************************/
/*********************************************************************************/
/* */
/* NB: The algorithm used to simulate the wave equation is highly paralellizable */
/* One could make it much faster by using a GPU */
/* */
/*********************************************************************************/
#include <math.h>
#include <string.h>
#include <GL/glut.h>
#include <GL/glu.h>
#include <unistd.h>
#include <sys/types.h>
#include <tiffio.h> /* Sam Leffler's libtiff library. */
#include <omp.h>
#include <time.h>
2022-10-18 23:28:20 +02:00
#define MOVIE 0 /* set to 1 to generate movie */
2022-08-01 22:30:40 +02:00
/* General geometrical parameters */
2022-10-18 23:28:20 +02:00
#define WINWIDTH 1920 /* window width */
#define WINHEIGHT 1000 /* window height */
2022-08-01 22:30:40 +02:00
// #define NX 1920 /* number of grid points on x axis */
// #define NY 992 /* number of grid points on y axis */
2022-10-18 23:28:20 +02:00
#define XMIN -2.0
#define XMAX 2.0 /* x interval */
#define YMIN -1.041666667
#define YMAX 1.041666667 /* y interval for 9/16 aspect ratio */
2022-08-01 22:30:40 +02:00
#define HIGHRES 0 /* set to 1 if resolution of grid is double that of displayed image */
2022-10-18 23:28:20 +02:00
// #define WINWIDTH 1280 /* window width */
// #define WINHEIGHT 720 /* window height */
2022-08-01 22:30:40 +02:00
2022-10-18 23:28:20 +02:00
#define NX 256 /* number of grid points on x axis */
#define NY 256 /* number of grid points on y axis */
#define NZ 256 /* number of grid points on z axis, for 3D percolation */
2022-08-01 22:30:40 +02:00
2022-10-18 23:28:20 +02:00
// #define XMIN -2.0
// #define XMAX 2.0 /* x interval */
// #define YMIN -1.125
// #define YMAX 1.125 /* y interval for 9/16 aspect ratio */
2022-08-01 22:30:40 +02:00
/* Boundary conditions, see list in global_pdes.c */
2022-10-18 23:28:20 +02:00
#define LATTICE 100
2022-08-01 22:30:40 +02:00
2022-10-18 23:28:20 +02:00
#define FLOOD_LEFT_BOUNDARY 0 /* set to 1 to flood cells on left boundary */
#define FLOOD_BOTTOM_BOUNDARY 0 /* set to 1 to flood cells on bottom boundary */
#define FIND_ALL_CLUSTERS 1 /* set to 1 to find all open clusters */
#define PLOT_ONLY_FLOODED_CELLS 0 /* set to 1 to plot only flooded cells */
2022-08-01 22:30:40 +02:00
2022-08-20 16:02:07 +02:00
#define PLOT_CLUSTER_SIZE 0 /* set to 1 to add a plot for the size of the percolation cluster */
2022-08-01 22:30:40 +02:00
#define PLOT_CLUSTER_NUMBER 0 /* set to 1 to add a graph of the number of clusters */
2022-08-20 16:02:07 +02:00
#define PLOT_CLUSTER_HISTOGRAM 1 /* set to 1 to add a histogram of the number of clusters */
2022-10-18 23:28:20 +02:00
#define PRINT_LARGEST_CLUSTER_SIZE 0 /* set to 1 to print size of largest cluster */
#define HISTO_X_LOG_SCALE 1 /* set to 1 to use a log scale on cluster sizes */
#define P_SCHEDULE_POWER 4 /* power controlling slowing down near pc - 2 is standard, higher values mean slower passage */
2022-08-01 22:30:40 +02:00
#define MAX_CLUSTER_NUMBER 6 /* vertical scale of the cluster number plot */
2022-08-20 16:02:07 +02:00
#define HISTO_BINS 30 /* number of bins in histogram */
2022-08-01 22:30:40 +02:00
2022-08-20 16:02:07 +02:00
#define NSTEPS 100 /* number of frames of movie */
2022-10-18 23:28:20 +02:00
// #define NSTEPS 760 /* number of frames of movie */
2022-08-01 22:30:40 +02:00
#define PAUSE 200 /* number of frames after which to pause */
#define PSLEEP 2 /* sleep time during pause */
#define SLEEP1 1 /* initial sleeping time */
#define SLEEP2 1 /* final sleeping time */
#define MID_FRAMES 20 /* number of still frames between parts of two-part movie */
#define END_FRAMES 100 /* number of still frames at end of movie */
#define FADE 1 /* set to 1 to fade at end of movie */
/* Color schemes */
2022-10-18 23:28:20 +02:00
#define COLOR_PALETTE 10 /* Color palette, see list in global_pdes.c */
2022-08-01 22:30:40 +02:00
#define BLACK 1 /* background */
2022-08-20 16:02:07 +02:00
#define COLOR_CLUSTERS_BY_SIZE 1 /* set to 1 to link cluster color to their size */
2022-10-18 23:28:20 +02:00
#define COLOR_CELLS_BY_XCOORD 0 /* set to 1 to color cells according to their x-coordinate */
#define COLOR_CELLS_BY_ZCOORD 0 /* set to 1 to color cells according to their z-coordinate */
2022-08-01 22:30:40 +02:00
#define SCALE 0 /* set to 1 to adjust color scheme to variance of field */
#define SLOPE 1.0 /* sensitivity of color on wave amplitude */
#define ATTENUATION 0.0 /* exponential attenuation coefficient of contrast with time */
2022-08-20 16:02:07 +02:00
#define HUE_CLOSED 350.0 /* color hue of closed cells */
2022-08-01 22:30:40 +02:00
#define HUE_OPEN 200.0 /* color hue of open (dry) cells */
2022-10-18 23:28:20 +02:00
#define HUE_FLOODED 300.0 /* color hue of open flooded cells */
#define HUE_GRAPH_SIZE 250.0 /* color hue in graph of cluster size */
#define HUE_GRAPH_CLUSTERS 150.0 /* color hue in graph of cluster size */
2022-08-01 22:30:40 +02:00
2022-10-18 23:28:20 +02:00
#define CLUSTER_HUEMIN 10.0 /* minimal color hue of clusters */
2022-08-20 16:02:07 +02:00
#define CLUSTER_HUEMAX 300.0 /* maximal color hue of clusters */
2022-08-01 22:30:40 +02:00
#define N_CLUSTER_COLORS 20 /* number of different colors of clusters */
#define COLORHUE 260 /* initial hue of water color for scheme C_LUM */
#define COLORDRIFT 0.0 /* how much the color hue drifts during the whole simulation */
#define LUMMEAN 0.5 /* amplitude of luminosity variation for scheme C_LUM */
#define LUMAMP 0.3 /* amplitude of luminosity variation for scheme C_LUM */
#define HUEMEAN 180.0 /* mean value of hue for color scheme C_HUE */
#define HUEAMP -180.0 /* amplitude of variation of hue for color scheme C_HUE */
2022-10-18 23:28:20 +02:00
/* parameters of 3D representation */
double u_3d[2] = {0.75, -0.45}; /* projections of basis vectors for REP_AXO_3D representation */
double v_3d[2] = {-0.75, -0.45};
double w_3d[2] = {0.0, 0.015};
double light[3] = {0.816496581, 0.33333333, 0.4714045}; /* vector of "light" direction for P_3D_ANGLE color scheme */
double observer[3] = {8.0, 11.0, 10.0}; /* location of observer for REP_PROJ_3D representation */
int reset_view = 0; /* switch to reset 3D view parameters (for option ROTATE_VIEW) */
#define REPRESENTATION_3D 1 /* choice of 3D representation */
#define Z_SCALING_FACTOR 1.0 /* overall scaling factor of z axis for REP_PROJ_3D representation */
#define XY_SCALING_FACTOR 2.4 /* overall scaling factor for on-screen (x,y) coordinates after projection */
#define ZMAX_FACTOR 1.0 /* max value of z coordinate for REP_PROJ_3D representation */
#define XSHIFT_3D -0.4 /* overall x shift for REP_PROJ_3D representation */
#define YSHIFT_3D 0.0 /* overall y shift for REP_PROJ_3D representation */
#define ROTATE_VIEW 0 /* set to 1 to rotate viewpoint */
#define ROTATE_ANGLE 360.0 /* total angle of viewpoint rotation */
2022-08-20 16:02:07 +02:00
/* debugging options */
#define VERBOSE 0 /* set to 1 to print more messages in shell */
#define DEBUG 0 /* set to 1 for some debugging features */
#define DEBUG_SLEEP_TIME 1 /* sleep time between frames when debugging */
#define TEST_GRAPH 0 /* set to 1 to test graph connectivity matrix */
#define TEST_START 2210 /* start position of connectivity test */
2022-08-01 22:30:40 +02:00
#define ADD_PLOT ((PLOT_CLUSTER_SIZE)||(PLOT_CLUSTER_NUMBER)||(PLOT_CLUSTER_HISTOGRAM))
#define FIND_CLUSTER_SIZES ((COLOR_CLUSTERS_BY_SIZE)||(PLOT_CLUSTER_HISTOGRAM))
2022-10-18 23:28:20 +02:00
#define PLOT_3D (LATTICE == BC_CUBIC_DIRICHLET)
2022-08-01 22:30:40 +02:00
#include "global_perc.c" /* constants and global variables */
2022-10-18 23:28:20 +02:00
#include "sub_perco_3d.c" /* support for 3D graphics */
2022-08-01 22:30:40 +02:00
#include "sub_perco.c"
void animation(int size)
{
2022-10-18 23:28:20 +02:00
int i, j, k, s, nx, ny, nz, nmaxcells, maxsize, nopen, nflooded, nstack, nclusters, maxclustersize = 0, maxclusterlabel;
2022-08-01 22:30:40 +02:00
int *plot_cluster_number, *cluster_sizes;
2022-08-20 16:02:07 +02:00
int ncells;
2022-08-01 22:30:40 +02:00
double p, *plot_cluster_size;
t_perco *cell;
t_perco **pstack;
2022-10-18 23:28:20 +02:00
compute_nxnynz(size, &nx, &ny, &nz);
2022-08-01 22:30:40 +02:00
2022-10-18 23:28:20 +02:00
nmaxcells = cell_number(NX, NY, NZ);
2022-08-01 22:30:40 +02:00
cell = (t_perco *)malloc(nmaxcells*sizeof(t_perco));
if (PLOT_CLUSTER_SIZE) plot_cluster_size = (double *)malloc(NSTEPS*sizeof(double));
if (PLOT_CLUSTER_NUMBER) plot_cluster_number = (int *)malloc(NSTEPS*sizeof(double));
2022-08-20 16:02:07 +02:00
// if (FIND_CLUSTER_SIZES)
cluster_sizes = (int *)malloc(2*nmaxcells*sizeof(int));
2022-08-01 22:30:40 +02:00
2022-10-18 23:28:20 +02:00
ncells = init_cell_lattice(cell, nx, ny, nz);
printf("nx = %i, ny = %i, nz = %i, ncells = %i, maxcells = %i\n", nx, ny, nz, ncells, nmaxcells);
2022-08-20 16:02:07 +02:00
2022-08-01 22:30:40 +02:00
pstack = (t_perco* *)malloc(ncells*sizeof(struct t_perco *));
if (TEST_GRAPH) test_neighbours(TEST_START, cell, nx, ny, size, ncells);
init_cell_probabilities(cell, ncells);
for (i=0; i<NSTEPS; i++)
{
p = p_schedule(i);
printf("\ni = %i, p = %.4lg\n", i, p);
2022-10-18 23:28:20 +02:00
if (ROTATE_VIEW)
{
viewpoint_schedule(i);
reset_view = 1;
}
2022-08-01 22:30:40 +02:00
init_cell_state(cell, p, ncells, (i == 0));
2022-10-18 23:28:20 +02:00
if (FLOOD_LEFT_BOUNDARY) nstack = init_flooded_cells(cell, ncells, nx, ny, nz, 0, pstack);
if (FLOOD_BOTTOM_BOUNDARY) nstack = init_flooded_cells(cell, ncells, nx, ny, nz, 1, pstack);
2022-08-01 22:30:40 +02:00
nopen = count_open_cells(cell, ncells);
2022-08-20 16:02:07 +02:00
printf("Flooded cells, %i open cells, nstack = %i\n", nopen, nstack);
2022-10-18 23:28:20 +02:00
if ((FLOOD_LEFT_BOUNDARY)||(FLOOD_BOTTOM_BOUNDARY))
2022-08-20 16:02:07 +02:00
{
nflooded = find_percolation_cluster(cell, ncells, pstack, nstack);
printf("Found percolation cluster with %i flooded cells\n", nflooded);
}
2022-08-01 22:30:40 +02:00
if (FIND_ALL_CLUSTERS)
{
nclusters = find_all_clusters(cell, ncells, (i == 0), &maxclusterlabel);
printf("Found %i clusters\n", nclusters);
}
if (FIND_CLUSTER_SIZES)
{
maxclustersize = find_cluster_sizes(cell, ncells, cluster_sizes, &maxclusterlabel);
printf("Max cluster size %i, max cluster label %i, ncells %i\n", maxclustersize, maxclusterlabel, ncells);
}
// print_cluster_sizes(cell, ncells, cluster_sizes);
2022-10-18 23:28:20 +02:00
draw_configuration(cell, cluster_sizes, ncells, nx, ny, nz, size, ncells);
2022-08-01 22:30:40 +02:00
print_p(p);
if (PRINT_LARGEST_CLUSTER_SIZE) print_largest_cluster_size(maxclustersize);
printf("%i open cells, %i flooded cells out of %i cells\n", nopen, nflooded, ncells);
if (PLOT_CLUSTER_SIZE)
{
plot_cluster_size[i] = (double)(nflooded)/(double)(nopen);
draw_size_plot(plot_cluster_size, i, pcritical(LATTICE));
}
if (PLOT_CLUSTER_NUMBER)
{
plot_cluster_number[i] = nclusters;
draw_cluster_number_plot(plot_cluster_number, ncells/MAX_CLUSTER_NUMBER, i, pcritical(LATTICE));
print_nclusters(nclusters);
}
if (PLOT_CLUSTER_HISTOGRAM) draw_cluster_histogram(ncells, cluster_sizes, maxclustersize, maxclusterlabel);
glutSwapBuffers();
if (DEBUG)
{
printf("\n\n");
sleep(DEBUG_SLEEP_TIME);
}
if (MOVIE) save_frame_perc();
}
if (MOVIE)
{
for (i=0; i<MID_FRAMES; i++) save_frame_perc();
s = system("mv perc*.tif tif_perc/");
}
free(cell);
free(pstack);
if (PLOT_CLUSTER_SIZE) free(plot_cluster_size);
if (PLOT_CLUSTER_NUMBER) free(plot_cluster_number);
2022-08-20 16:02:07 +02:00
// if (FIND_CLUSTER_SIZES)
free(cluster_sizes);
2022-08-01 22:30:40 +02:00
}
void display(void)
{
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
glPushMatrix();
blank();
glutSwapBuffers();
blank();
glutSwapBuffers();
// animation(128);
// animation(64);
2022-08-20 16:02:07 +02:00
// animation(32);
// animation(16);
2022-10-18 23:28:20 +02:00
animation(8);
// animation(4);
2022-08-20 16:02:07 +02:00
// animation(2);
// animation(1);
2022-08-01 22:30:40 +02:00
sleep(SLEEP2);
glPopMatrix();
glutDestroyWindow(glutGetWindow());
printf("Start local time and date: %s", asctime(timeinfo));
time(&rawtime);
timeinfo = localtime(&rawtime);
printf("Current local time and date: %s", asctime(timeinfo));
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(WINWIDTH,WINHEIGHT);
glutCreateWindow("Percolation in a planar domain");
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}