YouTube-simulations/sub_perco.c

3134 lines
107 KiB
C

/*********************/
/* Graphics routines */
/*********************/
#include "colors_waves.c"
#define CLUSTER_SHIFT 10 /* shift in numbering of open clusters */
double argument(double x, double y)
{
double alph;
if (x!=0.0)
{
alph = atan(y/x);
if (x<0.0)
alph += PI;
}
else
{
alph = PID;
if (y<0.0)
alph = PI*1.5;
}
return(alph);
}
int writetiff(char *filename, char *description, int x, int y, int width, int height, int compression)
{
TIFF *file;
GLubyte *image, *p;
int i;
file = TIFFOpen(filename, "w");
if (file == NULL)
{
return 1;
}
image = (GLubyte *) malloc(width * height * sizeof(GLubyte) * 3);
/* OpenGL's default 4 byte pack alignment would leave extra bytes at the
end of each image row so that each full row contained a number of bytes
divisible by 4. Ie, an RGB row with 3 pixels and 8-bit componets would
be laid out like "RGBRGBRGBxxx" where the last three "xxx" bytes exist
just to pad the row out to 12 bytes (12 is divisible by 4). To make sure
the rows are packed as tight as possible (no row padding), set the pack
alignment to 1. */
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, image);
TIFFSetField(file, TIFFTAG_IMAGEWIDTH, (uint32_t) width);
TIFFSetField(file, TIFFTAG_IMAGELENGTH, (uint32_t) height);
TIFFSetField(file, TIFFTAG_BITSPERSAMPLE, 8);
TIFFSetField(file, TIFFTAG_COMPRESSION, compression);
TIFFSetField(file, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
TIFFSetField(file, TIFFTAG_ORIENTATION, ORIENTATION_BOTLEFT);
TIFFSetField(file, TIFFTAG_SAMPLESPERPIXEL, 3);
TIFFSetField(file, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(file, TIFFTAG_ROWSPERSTRIP, 1);
TIFFSetField(file, TIFFTAG_IMAGEDESCRIPTION, description);
p = image;
for (i = height - 1; i >= 0; i--)
{
// if (TIFFWriteScanline(file, p, height - i - 1, 0) < 0)
if (TIFFWriteScanline(file, p, i, 0) < 0)
{
free(image);
TIFFClose(file);
return 1;
}
p += width * sizeof(GLubyte) * 3;
}
TIFFClose(file);
return 0;
}
void init() /* initialisation of window */
{
glLineWidth(3);
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
if (PLOT_3D) glOrtho(XMIN, XMAX, YMIN, YMAX , -1.0, 1.0);
else glOrtho(0.0, NX, 0.0, NY, -1.0, 1.0);
}
void blank()
{
if (BLACK) glClearColor(0.0, 0.0, 0.0, 1.0);
else glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
}
void write_text_fixedwidth( double x, double y, char *st)
{
int l, i;
l=strlen( st ); // see how many characters are in text string.
glRasterPos2d( x, y); // location to start printing text
for( i=0; i < l; i++) // loop until i is greater then l
{
// glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, st[i]); // Print a character on the screen
// glutBitmapCharacter(GLUT_BITMAP_8_BY_13, st[i]); // Print a character on the screen
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, st[i]); // Print a character on the screen
}
}
void write_text( double x, double y, char *st)
{
int l,i;
l=strlen( st ); // see how many characters are in text string.
glRasterPos2d( x, y); // location to start printing text
for( i=0; i < l; i++) // loop until i is greater then l
{
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, st[i]); // Print a character on the screen
// glutBitmapCharacter(GLUT_BITMAP_8_BY_13, st[i]); // Print a character on the screen
}
}
void save_frame_perc()
{
static int counter = 0;
char *name="perc.", n2[100];
char format[6]=".%05i";
counter++;
strcpy(n2, name);
sprintf(strstr(n2,"."), format, counter);
strcat(n2, ".tif");
printf(" saving frame %s \n",n2);
writetiff(n2, "Wave equation in a planar domain", 0, 0,
WINWIDTH, WINHEIGHT, COMPRESSION_LZW);
}
/*********************/
/* some basic math */
/*********************/
double ipow(double x, int n)
{
double y;
int i;
y = x;
for (i=1; i<n; i++) y *= x;
return(y);
}
int ipowi(int base, int n)
{
int p, i;
if (n == 0) return(1);
else
{
p = base;
for (i=1; i<n; i++) p *= base;
return(p);
}
}
double module2(double x, double y) /* Euclidean norm */
{
double m;
m = sqrt(x*x + y*y);
return(m);
}
/*********************/
/* drawing routines */
/*********************/
/* The billiard boundary is drawn in (x,y) coordinates */
/* However for the grid points, we use integer coordinates (i,j) */
/* GL would allow to always work in (x,y) coordinates but using both */
/* sets of coordinates decreases number of double computations when */
/* drawing the field */
void xy_to_ij(double x, double y, int ij[2])
/* convert (x,y) position to (i,j) in table representing wave */
{
double x1, y1;
x1 = (x - XMIN)/(XMAX - XMIN);
y1 = (y - YMIN)/(YMAX - YMIN);
ij[0] = (int)(x1 * (double)NX);
ij[1] = (int)(y1 * (double)NY);
}
void xy_to_pos(double x, double y, double pos[2])
/* convert (x,y) position to double-valued position in table representing wave */
{
double x1, y1;
if (PLOT_3D)
{
pos[0] = x;
pos[1] = y;
}
else
{
x1 = (x - XMIN)/(XMAX - XMIN);
y1 = (y - YMIN)/(YMAX - YMIN);
pos[0] = x1 * (double)NX;
pos[1] = y1 * (double)NY;
}
}
void erase_area_rgb(double x, double y, double dx, double dy, double rgb[3])
{
double pos[2];
glColor3f(rgb[0], rgb[1], rgb[2]);
glBegin(GL_QUADS);
xy_to_pos(x - dx, y - dy, pos);
glVertex2d(pos[0], pos[1]);
xy_to_pos(x + dx, y - dy, pos);
glVertex2d(pos[0], pos[1]);
xy_to_pos(x + dx, y + dy, pos);
glVertex2d(pos[0], pos[1]);
xy_to_pos(x - dx, y + dy, pos);
glVertex2d(pos[0], pos[1]);
glEnd();
}
void draw_line(double x1, double y1, double x2, double y2)
{
double pos[2];
glBegin(GL_LINE_STRIP);
xy_to_pos(x1, y1, pos);
glVertex2d(pos[0], pos[1]);
xy_to_pos(x2, y2, pos);
glVertex2d(pos[0], pos[1]);
glEnd();
}
void draw_rectangle(double x1, double y1, double x2, double y2)
{
double pos[2];
glBegin(GL_LINE_LOOP);
xy_to_pos(x1, y1, pos);
glVertex2d(pos[0], pos[1]);
xy_to_pos(x2, y1, pos);
glVertex2d(pos[0], pos[1]);
xy_to_pos(x2, y2, pos);
glVertex2d(pos[0], pos[1]);
xy_to_pos(x1, y2, pos);
glVertex2d(pos[0], pos[1]);
glEnd();
}
void draw_colored_rectangle(double x1, double y1, double x2, double y2, double hue)
{
double pos[2], rgb[3];
hsl_to_rgb_palette(hue, 0.9, 0.5, rgb, COLOR_PALETTE);
glColor3f(rgb[0], rgb[1], rgb[2]);
glBegin(GL_QUADS);
xy_to_pos(x1, y1, pos);
glVertex2d(pos[0], pos[1]);
xy_to_pos(x2, y1, pos);
glVertex2d(pos[0], pos[1]);
xy_to_pos(x2, y2, pos);
glVertex2d(pos[0], pos[1]);
xy_to_pos(x1, y2, pos);
glVertex2d(pos[0], pos[1]);
glEnd();
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_LINE_LOOP);
xy_to_pos(x1, y1, pos);
glVertex2d(pos[0], pos[1]);
xy_to_pos(x2, y1, pos);
glVertex2d(pos[0], pos[1]);
xy_to_pos(x2, y2, pos);
glVertex2d(pos[0], pos[1]);
xy_to_pos(x1, y2, pos);
glVertex2d(pos[0], pos[1]);
glEnd();
}
void draw_circle(double x, double y, double r, int nseg)
{
int i;
double pos[2], alpha, dalpha;
dalpha = DPI/(double)nseg;
glBegin(GL_LINE_LOOP);
for (i=0; i<=nseg; i++)
{
alpha = (double)i*dalpha;
xy_to_pos(x + r*cos(alpha), y + r*sin(alpha), pos);
glVertex2d(pos[0], pos[1]);
}
glEnd();
}
void draw_colored_circle(double x, double y, double r, int nseg)
{
int i;
double pos[2], alpha, dalpha;
dalpha = DPI/(double)nseg;
glBegin(GL_TRIANGLE_FAN);
xy_to_pos(x, y, pos);
glVertex2d(pos[0], pos[1]);
for (i=0; i<=nseg; i++)
{
alpha = (double)i*dalpha;
xy_to_pos(x + r*cos(alpha), y + r*sin(alpha), pos);
glVertex2d(pos[0], pos[1]);
}
glEnd();
}
int graphical_rep(int bcondition)
/* return type of drawing, depending on lattice/boundary conditions */
{
switch (bcondition) {
case (BC_SQUARE_DIRICHLET): return(PLOT_SQUARES);
case (BC_SQUARE_PERIODIC): return(PLOT_SQUARES);
case (BC_SQUARE_BOND_DIRICHLET): return(PLOT_SQUARE_BONDS);
case (BC_HEX_SITE_DIRICHLET): return(PLOT_HEX);
case (BC_HEX_BOND_DIRICHLET): return(PLOT_HEX_BONDS);
case (BC_TRIANGLE_SITE_DIRICHLET): return(PLOT_TRIANGLE);
case (BC_POISSON_DISC): return(PLOT_POISSON_DISC);
// case (BC_CUBIC_DIRICHLET): return(PLOT_SQUARES);
case (BC_CUBIC_DIRICHLET): return(PLOT_CUBES);
default: return(0);
}
}
double pcritical(int lattice)
/* critical probability in terms of lattice and boundary condition */
{
switch (lattice) {
case (BC_SQUARE_DIRICHLET): return(0.59274);
case (BC_SQUARE_PERIODIC): return(0.59274);
case (BC_SQUARE_BOND_DIRICHLET): return(0.5);
case (BC_HEX_BOND_DIRICHLET): return(1.0 - 2.0*sin(PI/18.0));
case (BC_TRIANGLE_SITE_DIRICHLET): return(0.6970402);
case (BC_CUBIC_DIRICHLET): return(0.311604);
default: return(0.5);
}
}
int cellnb(int i, int j, int group, int nx, int ny)
/* convert 2d coordinates to 1d */
{
switch (LATTICE) {
case (BC_SQUARE_DIRICHLET):
{
return(i*ny+j);
}
case (BC_SQUARE_PERIODIC):
{
return(i*ny+j);
}
case (BC_SQUARE_BOND_DIRICHLET):
{
if (group == 0) return(i+nx*j);
else return (nx*(ny+1) + i*ny+j);
}
case (BC_HEX_SITE_DIRICHLET):
{
return(i+nx*j);
}
case (BC_HEX_BOND_DIRICHLET):
{
return (group*nx*(ny+1) + i+nx*j);
}
case (BC_TRIANGLE_SITE_DIRICHLET):
{
return(i+2*nx*j);
}
case (BC_POISSON_DISC):
{
return(i);
}
}
}
int cellnb_3d(int i, int j, int k, int group, int nx, int ny, int nz)
/* convert 3d coordinates to 1d */
{
switch (LATTICE) {
case (BC_CUBIC_DIRICHLET):
{
return(k*nx*ny + j*nx + i);
}
}
}
int cell_to_ij(int c, int *i, int *j, int nx, int ny)
/* convert 1d coordinates to 2d, returns group */
{
int group;
switch (LATTICE) {
case (BC_SQUARE_DIRICHLET):
{
*i = c/ny;
*j = c - *i*ny;
return(0);
}
case (BC_SQUARE_PERIODIC):
{
*i = c/ny;
*j = c - *i*ny;
return(0);
}
case (BC_SQUARE_BOND_DIRICHLET):
{
if (c < nx*(ny+1))
{
*j = c/nx;
*i = c - *j*nx;
return(0);
}
else
{
c -= nx*(ny+1);
*i = c/ny;
*j = c - *i*ny;
return(1);
}
}
case (BC_HEX_SITE_DIRICHLET):
{
*j = c/nx;
*i = c - *j*nx;
return(0);
}
case (BC_HEX_BOND_DIRICHLET):
{
group = c/(nx*(ny+1));
c -= group*(nx*(ny+1));
*j = c/nx;
*i = c - *j*nx;
return(group);
}
case (BC_TRIANGLE_SITE_DIRICHLET):
{
*j= c/(2*nx);
*i = c - 2*(*j)*nx;
return(0);
}
}
}
double p_schedule(int i)
/* percolation probability p as a function of time */
{
double time, pstar;
int factor;
pstar = pcritical(LATTICE);
factor = ipow(2, P_SCHEDULE_POWER);
time = (double)i/(double)(NSTEPS-1);
if (time > 0.5) return(pstar + factor*(1.0 - pstar)*ipow(time - 0.5, P_SCHEDULE_POWER));
else return(pstar - factor*pstar*ipow(0.5 - time, P_SCHEDULE_POWER));
}
int in_plot_box(double x, double y)
{
int pos[2];
static double xmin, ymin;
static int first = 1;
if (first)
{
xy_to_ij(XMAX - 1.0, YMAX - 1.0, pos);
xmin = (double)pos[0];
ymin = (double)pos[1];
first = 0;
}
return((x > xmin)&&(y > ymin));
}
int in_plot_box_screencoord(double x, double y)
{
static double xmin, ymin;
static int first = 1;
if (first)
{
xmin = XMAX - 1.0;
ymin = YMAX - 1.0;
first = 0;
}
return((x > xmin)&&(y > ymin));
}
double size_ratio_color(int clustersize, int ncells)
/* color of cell as function of the size of its cluster */
{
double ratio, minratio = 1.0e-2, x, p = 0.1;
minratio = 1.0/(double)ncells;
ratio = (double)clustersize/(double)ncells;
if (ratio > 1.0) ratio = 1.0;
else if (ratio < minratio) ratio = minratio;
// x = log(ratio/minratio)/log(1.0/minratio);
// x = log(1.0 + log(ratio/minratio))/log(1.0 - log(minratio));
// x = pow(log(ratio/minratio)/(-log(minratio)), 0.1);
x = (pow(ratio, p) - pow(minratio, p))/(1.0 - pow(minratio, p));
return(CLUSTER_HUEMIN*x + CLUSTER_HUEMAX*(1.0 -x));
/* other attempts that seem to bug */
// ratio = log((double)(clustersize+1))/log((double)(ncells+1));
// // ratio = ((double)clustersize)/((double)ncells);
// // ratio = sqrt((double)clustersize)/sqrt((double)ncells);
// if (ratio > 1.0) ratio = 1.0;
// else if (ratio < 0.0) ratio = 0.0;
// return(CLUSTER_HUEMAX*ratio + CLUSTER_HUEMIN*(1.0 -ratio));
}
void compute_cell_color(t_perco cell, int *cluster_sizes, int fade, int max_cluster_size, int kx, int nx, int kz, int nz, double rgb[3])
/* compute color of cell */
{
int k, color, csize;
double fade_factor = 0.15, hue;
if (!cell.open) hsl_to_rgb_palette(HUE_CLOSED, 0.9, 0.5, rgb, COLOR_PALETTE);
else
{
if (!cell.flooded) hsl_to_rgb_palette(HUE_OPEN, 0.9, 0.5, rgb, COLOR_PALETTE);
else
{
if (COLOR_CELLS_BY_XCOORD)
{
hue = CLUSTER_HUEMIN + (CLUSTER_HUEMAX - CLUSTER_HUEMIN)*(double)kx/(double)nx;
hsl_to_rgb_palette(hue, 0.9, 0.5, rgb, COLOR_PALETTE);
}
else if (COLOR_CELLS_BY_ZCOORD)
{
hue = CLUSTER_HUEMIN + (CLUSTER_HUEMAX - CLUSTER_HUEMIN)*(double)kz/(double)nz;
hsl_to_rgb_palette(hue, 0.9, 0.5, rgb, COLOR_PALETTE);
}
else hsl_to_rgb_palette(HUE_FLOODED, 0.9, 0.5, rgb, COLOR_PALETTE);
}
if ((FIND_ALL_CLUSTERS)&&(COLOR_CLUSTERS_BY_SIZE))
{
csize = cluster_sizes[cell.cluster];
hue = size_ratio_color(csize, max_cluster_size);
hsl_to_rgb_palette(hue, 0.9, 0.5, rgb, COLOR_PALETTE);
}
else if ((FIND_ALL_CLUSTERS)&&(cell.cluster > 1))
{
color = cell.cluster%N_CLUSTER_COLORS;
hue = CLUSTER_HUEMIN + (CLUSTER_HUEMAX - CLUSTER_HUEMIN)*(double)color/(double)N_CLUSTER_COLORS;
hsl_to_rgb_palette(hue, 0.9, 0.5, rgb, COLOR_PALETTE);
}
// if ((FLOOD_LEFT_BOUNDARY)&&(cell.flooded == 1)) hsl_to_rgb_palette(HUE_FLOODED, 0.9, 0.5, rgb, COLOR_PALETTE);
}
if (fade) for (k=0; k<3; k++) rgb[k] = 1.0 - fade_factor + fade_factor*rgb[k];
}
void set_cell_color(t_perco cell, int *cluster_sizes, int fade, int max_cluster_size, int i, int nx, int k, int nz)
/* set color of cell */
{
double rgb[3];
compute_cell_color(cell, cluster_sizes, fade, max_cluster_size, i, nx, k, nz, rgb);
glColor3f(rgb[0], rgb[1], rgb[2]);
}
double plot_coord(double x, double xmin, double xmax)
{
return(xmin + x*(xmax - xmin));
}
void draw_size_plot(double plot_cluster_size[NSTEPS], int i, double pcrit)
/* draw plot of cluster sizes in terms of p */
{
int j;
char message[100];
static double xmin, xmax, ymin, ymax, xmid, ymid, dx, dy, plotxmin, plotxmax, plotymin, plotymax;
double pos[2], x1, y1, x2, y2, rgb[3], x;
static int first = 1;
if (first)
{
xmin = XMAX - 0.95;
xmax = XMAX - 0.05;
ymin = YMAX - 0.95;
ymax = YMAX - 0.05;
xmid = 0.5*(xmin + xmax);
ymid = 0.5*(ymin + ymax);
dx = 0.5*(xmax - xmin);
dy = 0.5*(ymax - ymin);
plotxmin = xmin + 0.05;
plotxmax = xmax - 0.1;
plotymin = ymin + 0.07;
plotymax = ymax - 0.15;
first = 0;
}
rgb[0] = 1.0; rgb[1] = 1.0; rgb[2] = 1.0;
// erase_area_rgb(xmid, ymid, dx, dy, rgb);
glColor3f(0.0, 0.0, 0.0);
glLineWidth(2);
/* axes and labels */
draw_line(plotxmin, plotymin, plotxmax + 0.05, plotymin);
draw_line(plotxmin, plotymin, plotxmin, plotymax + 0.1);
draw_line(plotxmin - 0.02, plotymax, plotxmin + 0.02, plotymax);
x = plot_coord(pcrit, plotxmin, plotxmax);
draw_line(x, plotymin, x, plotymax);
draw_line(plotxmax, plotymin - 0.02, plotxmax, plotymin + 0.02);
xy_to_pos(plotxmax + 0.06, plotymin - 0.03, pos);
sprintf(message, "p");
write_text_fixedwidth(pos[0], pos[1], message);
xy_to_pos(x - 0.02, plotymin - 0.04, pos);
sprintf(message, "pc");
write_text_fixedwidth(pos[0], pos[1], message);
hsl_to_rgb_palette(HUE_GRAPH_SIZE, 0.9, 0.5, rgb, COLOR_PALETTE);
glColor3f(rgb[0], rgb[1], rgb[2]);
xy_to_pos(plotxmax - 0.015, plotymin - 0.06, pos);
sprintf(message, "1");
write_text_fixedwidth(pos[0], pos[1], message);
xy_to_pos(plotxmin + 0.02, plotymax + 0.1, pos);
sprintf(message, "nflooded/nopen");
write_text_fixedwidth(pos[0], pos[1], message);
xy_to_pos(plotxmin - 0.05, plotymax - 0.01, pos);
sprintf(message, "1");
write_text_fixedwidth(pos[0], pos[1], message);
/* plot */
x1 = plotxmin;
y1 = plotymin;
for (j=0; j<i; j++)
{
// x2 = plot_coord((double)j/(double)NSTEPS, plotxmin, plotxmax);
x2 = plot_coord(p_schedule(j), plotxmin, plotxmax);
y2 = plot_coord(plot_cluster_size[j], plotymin, plotymax);
draw_line(x1, y1, x2, y2);
x1 = x2;
y1 = y2;
}
}
void draw_cluster_number_plot(int plot_cluster_number[NSTEPS], int max_number, int i, double pcrit)
/* draw plot of number of clusters in terms of p */
{
int j;
char message[100];
static double xmin, xmax, ymin, ymax, xmid, ymid, dx, dy, plotxmin, plotxmax, plotymin, plotymax;
double pos[2], x1, y1, x2, y2, rgb[3], x, y;
static int first = 1;
if (first)
{
xmin = XMAX - 0.95;
xmax = XMAX - 0.05;
ymin = YMAX - 0.95;
ymax = YMAX - 0.05;
xmid = 0.5*(xmin + xmax);
ymid = 0.5*(ymin + ymax);
dx = 0.5*(xmax - xmin);
dy = 0.5*(ymax - ymin);
plotxmin = xmin + 0.05;
plotxmax = xmax - 0.1;
plotymin = ymin + 0.07;
plotymax = ymax - 0.15;
first = 0;
}
rgb[0] = 1.0; rgb[1] = 1.0; rgb[2] = 1.0;
// erase_area_rgb(xmid, ymid, dx, dy, rgb);
glColor3f(0.0, 0.0, 0.0);
glLineWidth(2);
/* axes and labels */
draw_line(plotxmin, plotymin, plotxmax + 0.05, plotymin);
draw_line(plotxmin, plotymin, plotxmin, plotymax + 0.1);
draw_line(plotxmin - 0.02, plotymax, plotxmin + 0.02, plotymax);
x = plot_coord(pcrit, plotxmin, plotxmax);
draw_line(x, plotymin, x, plotymax);
draw_line(plotxmax, plotymin - 0.02, plotxmax, plotymin + 0.02);
xy_to_pos(plotxmax + 0.06, plotymin - 0.03, pos);
sprintf(message, "p");
write_text_fixedwidth(pos[0], pos[1], message);
xy_to_pos(x - 0.02, plotymin - 0.04, pos);
sprintf(message, "pc");
write_text_fixedwidth(pos[0], pos[1], message);
hsl_to_rgb_palette(HUE_GRAPH_CLUSTERS, 0.9, 0.5, rgb, COLOR_PALETTE);
glColor3f(rgb[0], rgb[1], rgb[2]);
xy_to_pos(plotxmax - 0.015, plotymin - 0.06, pos);
sprintf(message, "1");
write_text_fixedwidth(pos[0], pos[1], message);
xy_to_pos(plotxmin + 0.02, plotymax + 0.05, pos);
sprintf(message, "clusters/cells");
write_text_fixedwidth(pos[0], pos[1], message);
xy_to_pos(plotxmin + 0.05, plotymax - 0.01, pos);
sprintf(message, "%.2f", 1.0/(double)MAX_CLUSTER_NUMBER);
write_text_fixedwidth(pos[0], pos[1], message);
/* plot */
x1 = plotxmin;
y1 = plotymin;
for (j=0; j<i; j++)
{
// x2 = plot_coord((double)j/(double)NSTEPS, plotxmin, plotxmax);
x2 = plot_coord(p_schedule(j), plotxmin, plotxmax);
y2 = plot_coord((double)plot_cluster_number[j]/(double)max_number, plotymin, plotymax);
draw_line(x1, y1, x2, y2);
x1 = x2;
y1 = y2;
}
}
void draw_cluster_histogram(int ncells, int *cluster_sizes, int maxclustersize, int maxclusterlabel)
/* draw histogram of cluster size distribution */
{
int i, bin, nbins, binwidth, *histo, maxheight = 0, csize, dh, n, max_x_axis, di;
static int maxbins = HISTO_BINS;
char message[100];
static double xmin, xmax, ymin, ymax, xmid, ymid, dx, dy, plotxmin, plotxmax, plotymin, plotymax, x, y;
double pos[2], x1, y1, x2, y2, hue, delta, logfactor = 5.0, logbinwidth;
static int first = 1;
if (first)
{
xmin = XMAX - 0.95;
xmax = XMAX - 0.05;
ymin = YMAX - 0.95;
ymax = YMAX - 0.05;
xmid = 0.5*(xmin + xmax);
ymid = 0.5*(ymin + ymax);
dx = 0.5*(xmax - xmin);
dy = 0.5*(ymax - ymin);
plotxmin = xmin + 0.15;
plotxmax = xmax - 0.1;
plotymin = ymin + 0.07;
plotymax = ymax - 0.1;
first = 0;
}
if (maxclustersize > 0)
{
// if (maxclustersize < maxbins) nbins = maxclustersize;
// else
nbins = maxbins;
histo = (int *)malloc(nbins*sizeof(int));
for (bin = 0; bin < nbins; bin++) histo[bin] = 0;
// binwidth = maxclustersize/nbins;
// if (binwidth == 0) binwidth = 1;
if (HISTO_X_LOG_SCALE) logbinwidth = log(logfactor*(double)maxclustersize)/nbins;
else binwidth = maxclustersize/nbins + 1;
if (binwidth < 1) binwidth = 1;
if (logbinwidth < 0.2) logbinwidth = 0.2;
printf("max cluster size = %i, binwidth = %i\n", maxclustersize, binwidth);
/* compute histogram */
for (i=CLUSTER_SHIFT; i<maxclusterlabel; i++) if (cluster_sizes[i] > 0)
{
if (HISTO_X_LOG_SCALE)
{
bin = (int)(log(logfactor*(double)cluster_sizes[i])/logbinwidth) - 1;
if (bin >= nbins) bin = nbins - 1;
else if (bin < 0) bin = 0;
}
else bin = (cluster_sizes[i]-1)/binwidth;
// printf("cluster size = %i, bin = %i\n", cluster_sizes[i], bin);
histo[bin]++;
}
for (bin=0; bin<maxbins; bin++) if (histo[bin] > maxheight) maxheight = histo[bin];
/* draw histogram */
glColor3f(0.0, 0.0, 0.0);
glLineWidth(2);
x1 = plotxmin;
y1 = plotymin;
if (HISTO_X_LOG_SCALE) max_x_axis = log((double)maxclustersize);
else max_x_axis = maxclustersize;
if (max_x_axis < HISTO_BINS) max_x_axis = HISTO_BINS;
for (bin=0; bin < nbins; bin++)
{
// csize = bin*binwidth + binwidth/2;
if (HISTO_X_LOG_SCALE) csize = (int)(exp((double)bin*logbinwidth)/logfactor);
else csize = bin*binwidth;
if (csize >= ncells) csize = ncells-1;
hue = size_ratio_color(csize, ncells);
x2 = plot_coord((double)((bin+1)*binwidth)/(double)(max_x_axis), plotxmin, plotxmax);
// x2 = plot_coord((double)(bin+1)/(double)nbins, plotxmin, plotxmax);
y = log((double)(histo[bin]+1))/log((double)(maxheight+1));
y2 = plot_coord(y, plotymin, plotymax);
// printf("x1 = %.2f, x2 %.2f\n", x1, x2);
draw_colored_rectangle(x1, y1, x2, y2, hue);
x1 = x2;
}
draw_line(plotxmin, plotymin, plotxmax + 0.05, plotymin);
draw_line(plotxmin, plotymin, plotxmin, plotymax + 0.1);
/* graduation of y axis */
x = log((double)(maxheight+1))/log(10.0);
for (i=0; i<(int)x + 1; i++)
{
n = ipowi(10, i);
y = log((double)(n+1))/log((double)(maxheight+1));
y1 = plot_coord(y, plotymin, plotymax);
xy_to_pos(plotxmin - 0.1, y1, pos);
draw_line(plotxmin - 0.02, y1, plotxmin + 0.02, y1);
sprintf(message, "%i", n);
xy_to_pos(plotxmin - 0.07 - 0.025*(double)i, y1 - 0.01, pos);
write_text_fixedwidth(pos[0], pos[1], message);
}
/* graduation of x axis */
if (HISTO_X_LOG_SCALE)
{
y = log(logfactor*(double)(maxclustersize+1))/log(10.0);
printf("y = %.3lg\n", y);
for (i=1; i<(int)y + 1; i++)
{
n = ipowi(10, i);
x = log((double)(n+1))/(log(logfactor*(double)(maxclustersize+1)));
// printf("n = %i, x = %.3lg\n", n, x);
x1 = plot_coord(x, plotxmin, plotxmax);
xy_to_pos(x1, plotymin - 0.1, pos);
draw_line(x1, plotymin - 0.02, x1, plotymin + 0.02);
if (n <= 1000) sprintf(message, "%i", n);
else sprintf(message, "1e%i", i);
xy_to_pos(x1 - 0.015, plotymin - 0.05, pos);
write_text_fixedwidth(pos[0], pos[1], message);
}
}
else
{
x = log((double)(max_x_axis+1))/log(10.0);
n = ipowi(10, (int)x);
y = (double)n/10.0;
delta = plot_coord((double)n/((double)(max_x_axis+1)), plotxmin, plotxmax) - plotxmin;
if (delta > 0.13 + 0.01*x) di = 1;
else if (delta > 0.08 + 0.01*x) di = 2;
else di = 5;
for (i=di; i<10; i+=di)
{
x1 = plot_coord(y*(double)i*10.0/(double)(max_x_axis+1), plotxmin, plotxmax);
if (i*n < max_x_axis*11/10)
{
sprintf(message, "%i", i*n);
xy_to_pos(x1 + 0.005 - 0.012*x, plotymin - 0.07, pos);
write_text_fixedwidth(pos[0], pos[1], message);
}
}
delta = plot_coord((double)n/(10.0*(double)(max_x_axis+1)), plotxmin, plotxmax) - plotxmin;
for (i=0; i<100; i++) if (i*n < 11*max_x_axis)
{
y = (double)(i*n)/10.0;
x1 = plot_coord(y/(double)(max_x_axis+1), plotxmin, plotxmax);
xy_to_pos(x1, plotymin , pos);
if (i%10 == 0) draw_line(x1, plotymin - 0.02, x1, plotymin + 0.02);
else if (delta > 0.02) draw_line(x1, plotymin - 0.01, x1, plotymin + 0.01);
}
}
/* for debugging */
if (DEBUG) for (bin=0; bin < nbins; bin++) printf("Bin %i = %i\n", bin, histo[bin]);
free(histo);
}
}
void draw_cell(int c, int nx, int ny, int size)
/* draw a single cell, for debugging puposes */
{
int i, j, ishift, k, group;
double rgb[3], x, y, alpha, r, fade = 0, dsize;
static double h;
static int first = 1;
dsize = (double)size;
group = cell_to_ij(c, &i, &j, nx, ny);
switch (graphical_rep(LATTICE)) {
case (PLOT_SQUARES):
{
glBegin(GL_QUADS);
glVertex2i(i*size, j*size);
glVertex2i((i+1)*size, j*size);
glVertex2i((i+1)*size, (j+1)*size);
glVertex2i(i*size, (j+1)*size);
glEnd ();
break;
}
case (PLOT_SQUARE_BONDS):
{
glLineWidth(5);
glBegin(GL_LINES);
/* horizontal segments */
if (group == 0)
{
glVertex2i(i*size, j*size);
glVertex2i((i+1)*size, j*size);
}
/* vertical segments */
else
{
glVertex2i(i*size, j*size);
glVertex2i(i*size, (j+1)*size);
}
glEnd ();
break;
}
case (PLOT_HEX):
{
if (first)
{
h = 0.5*sqrt(3.0);
first = 0;
}
r = (double)size*0.5/h;
x = ((double)i + 0.75)*dsize;
if (j%2 == 1) x += 0.5*dsize;
y = h*dsize*((double)j + 1.0);
glBegin(GL_TRIANGLE_FAN);
glVertex2d(x, y);
for (k=0; k<7; k++)
{
alpha = (1.0 + 2.0*(double)k)*PI/6.0;
glVertex2d(x + r*cos(alpha), y + r*sin(alpha));
}
glEnd();
break;
}
case (PLOT_HEX_BONDS):
{
if (first)
{
h = 0.5*sqrt(3.0);
first = 0;
}
r = (double)size*0.5/h;
x = ((double)i + 0.75)*dsize;
if (j%2 == 1) x -= 0.5*dsize;
y = h*dsize*((double)j + 1.0);
glBegin(GL_LINES);
switch (group){
case (0): /* vertical bonds */
{
glVertex2d(x-0.5*dsize, y+0.5*r);
glVertex2d(x-0.5*dsize, y-0.5*r);
break;
}
case (1): /* NE-SW bonds */
{
glVertex2d(x, y-r);
glVertex2d(x+0.5*dsize, y-0.5*r);
break;
}
case (2): /* NW-SE bonds */
{
glVertex2d(x-0.5*dsize, y-0.5*r);
glVertex2d(x, y-r);
break;
}
}
glEnd();
break;
}
case (PLOT_TRIANGLE):
{
if (first)
{
h = 0.5*sqrt(3.0);
first = 0;
}
r = (double)size*0.5/h;
x = 0.5*((double)i + 1.25)*dsize;
y = h*dsize*((double)j);
printf("Drawing cell %i = (%i, %i) at (%.0f, %.0f)\n", c, i, j, x, y);
glBegin(GL_TRIANGLES);
if ((i+j)%2 == 1)
{
glVertex2d(x-0.5*dsize, y);
glVertex2d(x+0.5*dsize, y);
glVertex2d(x, y+h*dsize);
}
else
{
glVertex2d(x-0.5*dsize, y+h*dsize);
glVertex2d(x+0.5*dsize, y+h*dsize);
glVertex2d(x, y);
}
glEnd();
break;
}
case (PLOT_POISSON_DISC):
{
/* beta version, TO DO */
// draw_circle();
}
}
}
void test_neighbours(int start, t_perco *cell, int nx, int ny, int size, int ncells)
/* for debugging puposes */
{
int i, k;
for (i=start; i<ncells; i++)
{
printf("Testing cell %i of %i - %i neighbours\n", i, ncells, cell[i].nneighb);
blank();
glColor3f(1.0, 0.0, 0.0);
draw_cell(i, nx, ny, size);
glColor3f(0.0, 0.0, 1.0);
for (k=0; k<cell[i].nneighb; k++) draw_cell(cell[i].nghb[k], nx, ny, size);
glutSwapBuffers();
sleep(1);
}
}
void draw_cube_ijk(int i, int j, int k, t_perco *cell, int *cluster_sizes, int nx, int ny, int nz, int size, int max_cluster_size)
/* draw one cube of 3d configuration */
{
double dx, x, y, z, rgb[3];
dx = 1.0/(double)nx;
compute_cell_color(cell[k*nx*ny+j*nx+i], cluster_sizes, 0, max_cluster_size, i, nx, k, nz, rgb);
x = (double)i*dx - 0.5;
y = (double)j*dx - 0.5;
z = (double)k*dx - 0.5;
draw_cube(x, y, z, dx, rgb);
}
int plot_cube(t_perco cell)
/* returns 1 if cube is plotted */
{
if (PLOT_ONLY_FLOODED_CELLS) return(cell.flooded);
else return(cell.open);
}
void draw_configuration(t_perco *cell, int *cluster_sizes, int ncells, int nx, int ny, int nz, int size, int max_cluster_size)
/* draw the configuration */
{
int i, j, ishift, k, n, sector;
double rgb[3], x, y, z, alpha, r, fade = 0, dsize, radius, x2, y2, dx, dy, dz, observer_angle;
static double h, h1;
static int first = 1;
dsize = (double)size;
switch (graphical_rep(LATTICE)) {
case (PLOT_SQUARES):
{
blank();
glBegin(GL_QUADS);
for (i=0; i<nx; i++)
for (j=0; j<ny; j++)
{
if ((ADD_PLOT)&&(in_plot_box((double)(i+1)*dsize, (double)(j)*dsize))) fade = 1;
else fade = 0;
set_cell_color(cell[i*ny+j], cluster_sizes, fade, max_cluster_size, 0, 1, 0, 1);
glVertex2i(i*size, j*size);
glVertex2i((i+1)*size, j*size);
glVertex2i((i+1)*size, (j+1)*size);
glVertex2i(i*size, (j+1)*size);
}
glEnd ();
break;
}
case (PLOT_SQUARE_BONDS):
{
ishift = nx*(ny+1);
blank();
if (ADD_PLOT)
{
rgb[0] = 1.0; rgb[1] = 1.0; rgb[2] = 1.0;
erase_area_rgb(XMAX - 0.5, YMAX - 0.5, 0.5, 0.5, rgb);
}
if (size < 8) glLineWidth(1 + size/4);
else glLineWidth(3);
glBegin(GL_LINES);
/* horizontal segments */
for (i=0; i<nx; i++)
for (j=0; j<ny+1; j++)
{
if ((ADD_PLOT)&&(in_plot_box((double)(i+1)*dsize, (double)(j)*dsize))) fade = 1;
else fade = 0;
set_cell_color(cell[i+nx*j], cluster_sizes, fade, max_cluster_size, 0, 1, 0, 1);
glVertex2i(i*size, j*size);
glVertex2i((i+1)*size, j*size);
}
/* vertical segments */
for (i=0; i<nx+1; i++)
for (j=0; j<ny; j++)
{
if ((ADD_PLOT)&&(in_plot_box((double)(i+1)*dsize, (double)(j+1)*dsize))) fade = 1;
else fade = 0;
set_cell_color(cell[ishift+ny*i+j], cluster_sizes, fade, max_cluster_size, 0, 1, 0, 1);
glVertex2i(i*size, j*size);
glVertex2i(i*size, (j+1)*size);
}
glEnd ();
break;
}
case (PLOT_HEX):
{
blank();
if (first)
{
h = 0.5*sqrt(3.0);
first = 0;
}
r = (double)size*0.5/h;
for (j=0; j<ny; j++)
for (i=0; i<nx; i++)
{
x = ((double)i + 0.75)*dsize;
if (j%2 == 1) x += 0.5*dsize;
y = h*dsize*((double)j + 1.0);
if ((ADD_PLOT)&&(in_plot_box(x, y))) fade = 1;
else fade = 0;
set_cell_color(cell[j*nx+i], cluster_sizes, fade, max_cluster_size, 0, 1, 0, 1);
glBegin(GL_TRIANGLE_FAN);
glVertex2d(x, y);
for (k=0; k<7; k++)
{
alpha = (1.0 + 2.0*(double)k)*PI/6.0;
glVertex2d(x + r*cos(alpha), y + r*sin(alpha));
}
glEnd();
}
break;
}
case (PLOT_HEX_BONDS):
{
blank();
ishift = nx*(ny+1);
if (first)
{
h = 0.5*sqrt(3.0);
first = 0;
}
r = (double)size*0.5/h;
if (ADD_PLOT)
{
rgb[0] = 1.0; rgb[1] = 1.0; rgb[2] = 1.0;
erase_area_rgb(XMAX - 0.5, YMAX - 0.5, 0.5, 0.5, rgb);
}
if (size < 8) glLineWidth(1 + size/4);
else glLineWidth(3);
glBegin(GL_LINES);
for (i=0; i<nx; i++)
for (j=0; j<ny; j++)
{
x = ((double)i + 0.5)*dsize;
if (j%2 == 1) x -= 0.5*dsize;
y = h*dsize*((double)j + 0.75);
if ((ADD_PLOT)&&(in_plot_box(x, y))) fade = 1;
else fade = 0;
/* vertical bonds */
if (j<ny-1)
{
set_cell_color(cell[i+nx*j], cluster_sizes, fade, max_cluster_size, 0, 1, 0, 1);
glVertex2d(x-0.5*dsize, y+0.5*r);
glVertex2d(x-0.5*dsize, y-0.5*r);
}
if ((ADD_PLOT)&&(in_plot_box(x, y-0.5*h*dsize))) fade = 1;
else fade = 0;
/* NW-SE bonds */
set_cell_color(cell[2*ishift + i+nx*j], cluster_sizes, fade, max_cluster_size, 0, 1, 0, 1);
glVertex2d(x-0.5*dsize, y-0.5*r);
glVertex2d(x, y-r);
if ((ADD_PLOT)&&(in_plot_box(x+0.5*dsize, y-0.5*h*dsize))) fade = 1;
else fade = 0;
/* NE-SW bonds */
set_cell_color(cell[ishift + i+nx*j], cluster_sizes, fade, max_cluster_size, 0, 1, 0, 1);
glVertex2d(x, y-r);
glVertex2d(x+0.5*dsize, y-0.5*r);
}
glEnd();
break;
}
case (PLOT_TRIANGLE):
{
blank();
if (first)
{
h = 0.5*sqrt(3.0);
h1 = 0.5/sqrt(3.0);
first = 0;
}
r = (double)size*0.5/h;
for (j=0; j<ny; j++)
for (i=0; i<2*nx; i++)
{
x = 0.5*((double)i + 1.25)*dsize;
y = h*dsize*((double)j);
if ((ADD_PLOT)&&(in_plot_box(x, y+0.5*h*dsize))) fade = 1;
else fade = 0;
set_cell_color(cell[2*j*nx+i], cluster_sizes, fade, max_cluster_size, 0, 1, 0, 1);
glBegin(GL_TRIANGLES);
if ((i+j)%2 == 1)
{
glVertex2d(x-0.5*dsize, y);
glVertex2d(x+0.5*dsize, y);
glVertex2d(x, y+h*dsize);
}
else
{
glVertex2d(x-0.5*dsize, y+h*dsize);
glVertex2d(x+0.5*dsize, y+h*dsize);
glVertex2d(x, y);
}
glEnd();
}
break;
}
case (PLOT_POISSON_DISC):
{
radius = sqrt((XMAX - XMIN)*(YMAX - YMIN)/(PI*(double)nx));;
blank();
if (ADD_PLOT)
{
rgb[0] = 1.0; rgb[1] = 1.0; rgb[2] = 1.0;
erase_area_rgb(XMAX - 0.5, YMAX - 0.5, 0.5, 0.5, rgb);
}
for (i=0; i<ncells; i++)
{
x = cell[i].x;
y = cell[i].y;
if ((ADD_PLOT)&&(in_plot_box_screencoord(x, y))) fade = 1;
else fade = 0;
set_cell_color(cell[i], cluster_sizes, fade, max_cluster_size, 0, 1, 0, 1);
for (k=0; k<cell[i].nneighb; k++)
{
n = cell[i].nghb[k];
// printf("Cell %i, %ith neighbour cell %i\n", i, k, n);
x2 = cell[n].x;
y2 = cell[n].y;
draw_line(x, y, 0.5*(x + x2), 0.5*(y + y2));
}
draw_colored_circle(x, y, radius, NSEG);
}
break;
}
case (PLOT_CUBES): /* beta version */
{
blank();
// glBegin(GL_QUADS);
if (ADD_PLOT)
{
rgb[0] = 1.0; rgb[1] = 1.0; rgb[2] = 1.0;
erase_area_rgb(XMAX - 0.5, YMAX - 0.5, 0.5, 0.5, rgb);
}
for (k=0; k<nz; k++)
{
// if (ROTATE_VIEW)
{
observer_angle = argument(observer[0], observer[1]);
// observer_angle += 0.1*PID;
if (observer_angle < 0.0) observer_angle += DPI;
sector = (int)(observer_angle*2.0/PID);
// printf("Observer_angle = %.3lg\n", observer_angle*360.0/DPI);
switch (sector) {
case (0):
{
for (i=0; i<nx; i++)
for (j=0; j<ny; j++) if (plot_cube(cell[k*nx*ny+j*nx+i]))
draw_cube_ijk(i, j, k, cell, cluster_sizes, nx, ny, nz, size, max_cluster_size);
break;
}
case (1):
{
for (j=0; j<ny; j++)
for (i=0; i<nx; i++) if (plot_cube(cell[k*nx*ny+j*nx+i]))
draw_cube_ijk(i, j, k, cell, cluster_sizes, nx, ny, nz, size, max_cluster_size);
break;
}
case (2):
{
for (j=0; j<ny; j++)
for (i=nx-1; i>=0; i--) if (plot_cube(cell[k*nx*ny+j*nx+i]))
draw_cube_ijk(i, j, k, cell, cluster_sizes, nx, ny, nz, size, max_cluster_size);
break;
}
case (3):
{
for (i=nx-1; i>= 0; i--)
for (j=0; j<ny; j++) if (plot_cube(cell[k*nx*ny+j*nx+i]))
draw_cube_ijk(i, j, k, cell, cluster_sizes, nx, ny, nz, size, max_cluster_size);
break;
}
case (4):
{
for (i=nx-1; i>= 0; i--)
for (j=ny-1; j>=0; j--) if (plot_cube(cell[k*nx*ny+j*nx+i]))
draw_cube_ijk(i, j, k, cell, cluster_sizes, nx, ny, nz, size, max_cluster_size);
break;
}
case (5):
{
for (j=ny-1; j>=0; j--)
for (i=nx-1; i>=0; i--) if (plot_cube(cell[k*nx*ny+j*nx+i]))
draw_cube_ijk(i, j, k, cell, cluster_sizes, nx, ny, nz, size, max_cluster_size);
break;
}
case (6):
{
for (j=ny-1; j>=0; j--)
for (i=0; i<nx; i++) if (plot_cube(cell[k*nx*ny+j*nx+i]))
draw_cube_ijk(i, j, k, cell, cluster_sizes, nx, ny, nz, size, max_cluster_size);
break;
}
case (7):
{
for (i=0; i<nx; i++)
for (j=ny-1; j>=0; j--) if (plot_cube(cell[k*nx*ny+j*nx+i]))
draw_cube_ijk(i, j, k, cell, cluster_sizes, nx, ny, nz, size, max_cluster_size);
break;
}
}
}
// else
// {
// for (i=0; i < nx; i++)
// for (j=0; j<ny; j++) if (plot_cube(cell[k*nx*ny+j*nx+i]))
// draw_cube_ijk(i, j, k, cell, cluster_sizes, nx, ny, nz, size, max_cluster_size);
// }
}
break;
}
}
}
void print_p(double p)
{
char message[100];
double y = YMAX - 0.13, pos[2], rgb[3] = {1.0, 1.0, 1.0};
static double xleftbox, xlefttext, xrightbox, xrighttext;
static int first = 1;
if (first)
{
xleftbox = XMIN + 0.2;
xlefttext = xleftbox - 0.45;
if (PLOT_CLUSTER_HISTOGRAM) xrightbox = XMAX - 0.41;
else xrightbox = XMAX - 0.27;
xrighttext = xrightbox - 0.45;
first = 0;
}
if (!PLOT_CLUSTER_SIZE)
{
if (NX > 1280) erase_area_rgb(xrightbox, y + 0.025, 0.15, 0.05, rgb);
else erase_area_rgb(xrightbox, y + 0.025, 0.22, 0.05, rgb);
}
glColor3f(0.0, 0.0, 0.0);
if (NX > 1280) xy_to_pos(xrighttext + 0.35, y, pos);
else xy_to_pos(xrighttext + 0.3, y, pos);
sprintf(message, "p = %.4f", p);
write_text(pos[0], pos[1], message);
}
void print_nclusters(int nclusters)
{
char message[100];
double y = YMAX - 0.25, pos[2], rgb[3] = {1.0, 1.0, 1.0};
static double xleftbox, xlefttext, xrightbox, xrighttext;
static int first = 1;
if (first)
{
xleftbox = XMIN + 0.2;
xlefttext = xleftbox - 0.45;
xrightbox = XMAX - 0.31;
xrighttext = xrightbox - 0.48;
first = 0;
}
if (!PLOT_CLUSTER_SIZE)
{
if (NX > 1280) erase_area_rgb(xrightbox, y + 0.025, 0.18, 0.05, rgb);
else erase_area_rgb(xrightbox, y + 0.025, 0.25, 0.05, rgb);
}
glColor3f(0.0, 0.0, 0.0);
if (NX > 1280) xy_to_pos(xrighttext + 0.35, y, pos);
else xy_to_pos(xrighttext + 0.3, y, pos);
if (nclusters == 1) sprintf(message, "%i cluster", nclusters);
else sprintf(message, "%i clusters", nclusters);
write_text_fixedwidth(pos[0], pos[1], message);
}
void print_largest_cluster_size(int max_cluster_size)
{
char message[100];
double y = YMAX - 0.25, pos[2], rgb[3] = {1.0, 1.0, 1.0};
static double xleftbox, xlefttext, xrightbox, xrighttext;
static int first = 1;
if (first)
{
xleftbox = XMIN + 0.2;
xlefttext = xleftbox - 0.45;
xrightbox = XMAX - 0.41;
xrighttext = xrightbox - 0.48;
first = 0;
}
if (!PLOT_CLUSTER_SIZE)
{
if (NX > 1280) erase_area_rgb(xrightbox, y + 0.025, 0.18, 0.05, rgb);
else erase_area_rgb(xrightbox, y + 0.025, 0.25, 0.05, rgb);
}
glColor3f(0.0, 0.0, 0.0);
if (NX > 1280) xy_to_pos(xrighttext + 0.35, y, pos);
else xy_to_pos(xrighttext + 0.3, y, pos);
sprintf(message, "max size %i", max_cluster_size);
write_text_fixedwidth(pos[0], pos[1], message);
}
/*********************/
/* animation part */
/*********************/
int generate_poisson_discs(t_perco *cell, double dpoisson, int nmaxcells)
/* generate Poisson disc configuration */
{
double x, y, r, phi;
int i, j, k, n_p_active, ncircles, ncandidates=NPOISSON_CANDIDATES, naccepted;
short int *active_poisson, far;
active_poisson = (short int *)malloc(2*(nmaxcells)*sizeof(short int));
printf("Generating Poisson disc sample\n");
/* generate first circle */
cell[0].x = (XMAX - XMIN)*(double)rand()/RAND_MAX + XMIN;
cell[0].y = (YMAX - YMIN)*(double)rand()/RAND_MAX + YMIN;
active_poisson[0] = 1;
n_p_active = 1;
ncircles = 1;
while ((n_p_active > 0)&&(ncircles < nmaxcells))
{
/* randomly select an active circle */
i = rand()%(ncircles);
while (!active_poisson[i]) i = rand()%(ncircles);
/* generate new candidates */
naccepted = 0;
for (j=0; j<ncandidates; j++)
{
r = dpoisson*(2.0*(double)rand()/RAND_MAX + 1.0);
phi = DPI*(double)rand()/RAND_MAX;
x = cell[i].x + r*cos(phi);
y = cell[i].y + r*sin(phi);
// printf("Testing new circle at (%.3f,%.3f)\t", x, y);
far = 1;
for (k=0; k<ncircles; k++) if ((k!=i))
{
/* new circle is far away from circle k */
far = far*((x - cell[k].x)*(x - cell[k].x) + (y - cell[k].y)*(y - cell[k].y) >= dpoisson*dpoisson);
/* new circle is in domain */
far = far*(x < XMAX)*(x > XMIN)*(y < YMAX)*(y > YMIN);
}
if (far) /* accept new circle */
{
printf("New circle at (%.3f,%.3f) accepted\n", x, y);
cell[ncircles].x = x;
cell[ncircles].y = y;
cell[ncircles].active = 1;
active_poisson[ncircles] = 1;
ncircles++;
n_p_active++;
naccepted++;
}
// else printf("Rejected\n");
}
if (naccepted == 0) /* inactivate circle i */
{
active_poisson[i] = 0;
n_p_active--;
}
printf("%i active circles\n", n_p_active);
}
printf("Generated %i circles\n", ncircles);
free(active_poisson);
return(ncircles);
}
int cell_number(int nx, int ny, int nz)
/* total number of cells in graph */
{
switch (LATTICE) {
case (BC_SQUARE_DIRICHLET): return(nx*ny);
case (BC_SQUARE_PERIODIC): return(nx*ny);
case (BC_SQUARE_BOND_DIRICHLET): return(2*nx*ny + nx + ny);
case (BC_HEX_SITE_DIRICHLET): return((int)((double)(nx*ny)*2.0/sqrt(3.0))); /* hex lattice requires more vertical space! */
case (BC_HEX_BOND_DIRICHLET): return(3*(int)((double)((nx+2)*(ny+2))*2.0/sqrt(3.0)));
/* hex lattice requires more vertical space! */
case (BC_TRIANGLE_SITE_DIRICHLET): return((int)((double)(2*nx*ny)*2.0/sqrt(3.0))); /* triangle lattice requires more vertical space! */
case (BC_POISSON_DISC): return(nx*ny); /* TO IMPROVE */
case (BC_CUBIC_DIRICHLET): return(nx*ny*nz);
}
}
void compute_nxnynz(int size, int *nx, int *ny, int *nz)
/* compute the number of rows and columns depending on lattice */
{
switch (LATTICE) {
case (BC_HEX_SITE_DIRICHLET):
{
*nx = NX/size - 1;
*ny = (int)((double)NY*2.0/((double)size*sqrt(3.0)));
*nz = 1;
break;
}
case (BC_HEX_BOND_DIRICHLET):
{
*nx = NX/size + 1;
*ny = (int)((double)NY*2.0/((double)size*sqrt(3.0))) + 1;
*nz = 1;
break;
}
case (BC_TRIANGLE_SITE_DIRICHLET):
{
*nx = NX/size - 1;
*ny = (int)((double)NY*2.0/((double)size*sqrt(3.0))) + 1;
*nz = 1;
break;
}
case (BC_POISSON_DISC):
{
/* for Poisson disc configuration, use a 1d labelling */
*nx = NX*NY/(size*size);
*ny = 1;
*nz = 1;
break;
}
case (BC_CUBIC_DIRICHLET):
{
*nx = NX/size;
*ny = NY/size;
*nz = NZ/size;
break;
}
default:
{
*nx = NX/size;
*ny = NY/size;
*nz = 1;
}
}
}
int init_cell_lattice(t_perco *cell, int nx, int ny, int nz)
/* initialize the graph of connected cells - returns the number of cells */
{
int i, j, k, iplus, iminus, ishift, n;
int ncells;
double dpoisson, radius;
printf("Initializing cell lattice ...");
switch (LATTICE) {
case (BC_SQUARE_DIRICHLET):
{
/* neighbours in the bulk */
#pragma omp parallel for private(i,j)
for (i=1; i<nx-1; i++){
for (j=1; j<ny-1; j++){
n = cellnb(i, j, 0, nx, ny);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb(i+1, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(i-1, j, 0, nx, ny);
cell[n].nghb[2] = cellnb(i, j+1, 0, nx, ny);
cell[n].nghb[3] = cellnb(i, j-1, 0, nx, ny);
}
}
/* left boundary */
#pragma omp parallel for private(j)
for (j=1; j<ny-1; j++)
{
n = cellnb(0, j, 0, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(1, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(0, j+1, 0, nx, ny);
cell[n].nghb[2] = cellnb(0, j-1, 0, nx, ny);
}
/* right boundary */
#pragma omp parallel for private(j)
for (j=1; j<ny-1; j++)
{
n = cellnb(nx-1, j, 0, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(nx-2, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(nx-1, j+1, 0, nx, ny);
cell[n].nghb[2] = cellnb(nx-1, j-1, 0, nx, ny);
}
/* top boundary */
#pragma omp parallel for private(i)
for (i=1; i<nx-1; i++)
{
n = cellnb(i, ny-1, 0, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(i+1, ny-1, 0, nx, ny);
cell[n].nghb[1] = cellnb(i-1, ny-1, 0, nx, ny);
cell[n].nghb[2] = cellnb(i, ny-2, 0, nx, ny);
}
/* bottom boundary */
#pragma omp parallel for private(i)
for (i=1; i<nx-1; i++)
{
n = cellnb(i, 0, 0, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(i+1, 0, 0, nx, ny);
cell[n].nghb[1] = cellnb(i-1, 0, 0, nx, ny);
cell[n].nghb[2] = cellnb(i, 1, 0, nx, ny);
}
/* corners */
n = cellnb(0, 0, 0, nx, ny);
cell[n].nneighb = 2;
cell[n].nghb[0] = cellnb(1, 0, 0, nx, ny);
cell[n].nghb[1] = cellnb(0, 1, 0, nx, ny);
n = cellnb(0, ny-1, 0, nx, ny);
cell[n].nneighb = 2;
cell[n].nghb[0] = cellnb(0, ny-2, 0, nx, ny);
cell[n].nghb[1] = cellnb(1, ny-1, 0, nx, ny);
n = cellnb(nx-1, 0, 0, nx, ny);
cell[n].nneighb = 2;
cell[n].nghb[0] = cellnb(nx-1, 1, 0, nx, ny);
cell[n].nghb[1] = cellnb(nx-2, 0, 0, nx, ny);
n = cellnb(nx-1, ny-1, 0, nx, ny);
cell[n].nneighb = 2;
cell[n].nghb[0] = cellnb(nx-1, ny-2, 0, nx, ny);
cell[n].nghb[1] = cellnb(nx-2, ny-1, 0, nx, ny);
return(nx*ny);
break;
}
case (BC_SQUARE_PERIODIC):
{
/* neighbours in the bulk */
#pragma omp parallel for private(i,j)
for (i=1; i<nx-1; i++){
for (j=1; j<ny-1; j++){
n = cellnb(i, j, 0, nx, ny);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb(i+1, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(i-1, j, 0, nx, ny);
cell[n].nghb[2] = cellnb(i, j+1, 0, nx, ny);
cell[n].nghb[3] = cellnb(i, j-1, 0, nx, ny);
}
}
/* left boundary */
#pragma omp parallel for private(j)
for (j=1; j<ny-1; j++)
{
n = cellnb(0, j, 0, nx, ny);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb(1, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(nx-1, j, 0, nx, ny);
cell[n].nghb[2] = cellnb(0, j+1, 0, nx, ny);
cell[n].nghb[3] = cellnb(0, j+1, 0, nx, ny);
}
/* right boundary */
#pragma omp parallel for private(j)
for (j=1; j<ny-1; j++)
{
n = cellnb(nx-1, j, 0, nx, ny);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb(nx-2, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(0, j, 0, nx, ny);
cell[n].nghb[2] = cellnb(nx-1, j+1, 0, nx, ny);
cell[n].nghb[3] = cellnb(nx-1, j-1, 0, nx, ny);
}
/* top boundary */
#pragma omp parallel for private(i,iplus,iminus)
for (i=0; i<nx; i++)
{
n = cellnb(i, ny-1, 0, nx, ny);
iplus = (i+1) % nx;
iminus = (i-1) % nx;
if (iminus < 0) iminus += nx;
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb(iplus, ny-1, 0, nx, ny);
cell[n].nghb[1] = cellnb(iminus, ny-1, 0, nx, ny);
cell[n].nghb[2] = cellnb(i, ny-2, 0, nx, ny);
cell[n].nghb[3] = cellnb(i, 0, 0, nx, ny);
}
/* bottom boundary */
#pragma omp parallel for private(i,iplus,iminus)
for (i=0; i<nx; i++)
{
n = cellnb(i, 0, 0, nx, ny);
iplus = (i+1) % nx;
iminus = (i-1) % nx;
if (iminus < 0) iminus += nx;
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb(iplus, 0, 0, nx, ny);
cell[n].nghb[1] = cellnb(iminus, 0, 0, nx, ny);
cell[n].nghb[2] = cellnb(i, 1, 0, nx, ny);
cell[n].nghb[3] = cellnb(i, ny-1, 0, nx, ny);
}
return(nx*ny);
break;
}
case (BC_SQUARE_BOND_DIRICHLET):
{
ishift = nx*(ny+1);
/* horizontal bonds */
/* neighbours in the bulk */
#pragma omp parallel for private(i,j)
for (i=1; i<nx-1; i++){
for (j=1; j<ny; j++){
n = cellnb(i, j, 0, nx, ny);
cell[n].nneighb = 6;
cell[n].nghb[0] = cellnb(i+1, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(i-1, j, 0, nx, ny);
cell[n].nghb[2] = cellnb(i, j-1, 1, nx, ny);
cell[n].nghb[3] = cellnb(i, j, 1, nx, ny);
cell[n].nghb[4] = cellnb(i+1, j-1, 1, nx, ny);
cell[n].nghb[5] = cellnb(i+1, j, 1, nx, ny);
}
}
/* bottom boundary */
#pragma omp parallel for private(i)
for (i=1; i<nx-1; i++)
{
n = cellnb(i, 0, 0, nx, ny);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb(i+1, 0, 0, nx, ny);
cell[n].nghb[1] = cellnb(i-1, 0, 0, nx, ny);
cell[n].nghb[2] = cellnb(i, 0, 1, nx, ny);
cell[n].nghb[3] = cellnb(i+1, 0, 1, nx, ny);
}
/* top boundary */
#pragma omp parallel for private(i)
for (i=1; i<nx-1; i++)
{
n = cellnb(i, ny, 0, nx, ny);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb(i+1, ny, 0, nx, ny);
cell[n].nghb[1] = cellnb(i-1, ny, 0, nx, ny);
cell[n].nghb[2] = cellnb(i, ny-1, 1, nx, ny);
cell[n].nghb[3] = cellnb(i+1, ny-1, 1, nx, ny);
}
/* left boundary */
#pragma omp parallel for private(j)
for (j=1; j<ny; j++){
n = cellnb(0, j, 0, nx, ny);
cell[n].nneighb = 5;
cell[n].nghb[0] = cellnb(1, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(0, j-1, 1, nx, ny);
cell[n].nghb[2] = cellnb(0, j, 1, nx, ny);
cell[n].nghb[3] = cellnb(1, j-1, 1, nx, ny);
cell[n].nghb[4] = cellnb(1, j, 1, nx, ny);
}
/* right boundary */
#pragma omp parallel for private(j)
for (j=1; j<ny; j++){
n = cellnb(nx-1, j, 0, nx, ny);
cell[n].nneighb = 5;
cell[n].nghb[0] = cellnb(nx-2, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(nx-1, j-1, 1, nx, ny);
cell[n].nghb[2] = cellnb(nx-1, j, 1, nx, ny);
cell[n].nghb[3] = cellnb(nx, j-1, 1, nx, ny);
cell[n].nghb[4] = cellnb(nx, j, 1, nx, ny);
}
/* corners */
n = cellnb(0, 0, 0, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(1, 0, 0, nx, ny);
cell[n].nghb[1] = cellnb(0, 0, 1, nx, ny);
cell[n].nghb[2] = cellnb(1, 0, 1, nx, ny);
n = cellnb(nx-1, 0, 0, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(nx-2, 0, 0, nx, ny);
cell[n].nghb[1] = cellnb(nx-1, 0, 1, nx, ny);
cell[n].nghb[2] = cellnb(nx, 0, 1, nx, ny);
n = cellnb(0, ny, 0, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(1, ny, 0, nx, ny);
cell[n].nghb[1] = cellnb(0, ny-1, 1, nx, ny);
cell[n].nghb[2] = cellnb(1, ny-1, 1, nx, ny);
n = cellnb(nx-1, ny, 0, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(nx-2, ny, 0, nx, ny);
cell[n].nghb[1] = cellnb(nx-1, ny-1, 1, nx, ny);
cell[n].nghb[2] = cellnb(nx, ny-1, 1, nx, ny);
/* vertical bonds */
/* neighbours in the bulk */
#pragma omp parallel for private(i,j)
for (i=1; i<nx; i++){
for (j=1; j<ny-1; j++){
n = cellnb(i, j, 1, nx, ny);
cell[n].nneighb = 6;
cell[n].nghb[0] = cellnb(i, j-1, 1, nx, ny);
cell[n].nghb[1] = cellnb(i, j+1, 1, nx, ny);
cell[n].nghb[2] = cellnb(i, j, 0, nx, ny);
cell[n].nghb[3] = cellnb(i-1, j, 0, nx, ny);
cell[n].nghb[4] = cellnb(i, j+1, 0, nx, ny);
cell[n].nghb[5] = cellnb(i-1, j+1, 0, nx, ny);
}
}
/* left boundary */
#pragma omp parallel for private(j)
for (j=1; j<ny-1; j++){
n = cellnb(0, j, 1, nx, ny);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb(0, j-1, 1, nx, ny);
cell[n].nghb[1] = cellnb(0, j+1, 1, nx, ny);
cell[n].nghb[2] = cellnb(0, j, 0, nx, ny);
cell[n].nghb[3] = cellnb(0, j+1, 0, nx, ny);
}
/* right boundary */
#pragma omp parallel for private(j)
for (j=1; j<ny-1; j++){
n = cellnb(nx, j, 1, nx, ny);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb(nx, j-1, 1, nx, ny);
cell[n].nghb[1] = cellnb(nx, j+1, 1, nx, ny);
cell[n].nghb[2] = cellnb(nx-1, j, 0, nx, ny);
cell[n].nghb[3] = cellnb(nx-1, j+1, 0, nx, ny);
}
/* bottom boundary */
#pragma omp parallel for private(i)
for (i=1; i<nx; i++){
n = cellnb(i, 0, 1, nx, ny);
cell[n].nneighb = 5;
cell[n].nghb[0] = cellnb(i, 1, 1, nx, ny);
cell[n].nghb[1] = cellnb(i-1, 0, 0, nx, ny);
cell[n].nghb[2] = cellnb(i, 0, 0, nx, ny);
cell[n].nghb[3] = cellnb(i-1, 1, 0, nx, ny);
cell[n].nghb[4] = cellnb(i, 1, 0, nx, ny);
}
/* top boundary */
#pragma omp parallel for private(i)
for (i=1; i<nx; i++){
n = cellnb(i, ny-1, 1, nx, ny);
cell[n].nneighb = 5;
cell[n].nghb[0] = cellnb(i, ny-2, 1, nx, ny);
cell[n].nghb[1] = cellnb(i-1, ny-1, 0, nx, ny);
cell[n].nghb[2] = cellnb(i, ny-1, 0, nx, ny);
cell[n].nghb[3] = cellnb(i-1, ny, 0, nx, ny);
cell[n].nghb[4] = cellnb(i, ny, 0, nx, ny);
}
/* corners */
n = cellnb(0, 0, 1, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(0, 1, 1, nx, ny);
cell[n].nghb[1] = cellnb(0, 0, 0, nx, ny);
cell[n].nghb[2] = cellnb(0, 1, 0, nx, ny);
n = cellnb(0, ny-1, 1, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(0, ny-2, 1, nx, ny);
cell[n].nghb[1] = cellnb(0, ny-1, 0, nx, ny);
cell[n].nghb[2] = cellnb(0, ny, 0, nx, ny);
n = cellnb(nx, 0, 1, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(nx, 1, 1, nx, ny);
cell[n].nghb[1] = cellnb(nx-1, 0, 0, nx, ny);
cell[n].nghb[2] = cellnb(nx-1, 1, 0, nx, ny);
n = cellnb(nx, ny-1, 1, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(nx, ny-2, 1, nx, ny);
cell[n].nghb[1] = cellnb(nx-1, ny, 0, nx, ny);
cell[n].nghb[2] = cellnb(nx-1, ny-1, 0, nx, ny);
return(nx + ny + 2*nx*ny);
break;
}
case (BC_HEX_SITE_DIRICHLET):
{
/* neighbours in the bulk */
#pragma omp parallel for private(i,j)
for (i=1; i<nx-1; i++){
for (j=1; j<ny-1; j+=2){
n = cellnb(i, j, 0, nx, ny);
cell[n].nneighb = 6;
cell[n].nghb[0] = cellnb(i+1, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(i-1, j, 0, nx, ny);
cell[n].nghb[2] = cellnb(i+1, j+1, 0, nx, ny);
cell[n].nghb[3] = cellnb(i, j+1, 0, nx, ny);
cell[n].nghb[4] = cellnb(i+1, j-1,0, nx, ny);
cell[n].nghb[5] = cellnb(i, j-1, 0, nx, ny);
}
}
#pragma omp parallel for private(i,j)
for (i=1; i<nx-1; i++){
for (j=2; j<ny-1; j+=2){
n = cellnb(i, j, 0, nx, ny);
cell[n].nneighb = 6;
cell[n].nghb[0] = cellnb(i+1, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(i-1, j, 0, nx, ny);
cell[n].nghb[2] = cellnb(i-1, j+1, 0, nx, ny);
cell[n].nghb[3] = cellnb(i, j+1, 0, nx, ny);
cell[n].nghb[4] = cellnb(i-1, j-1,0, nx, ny);
cell[n].nghb[5] = cellnb(i, j-1, 0, nx, ny);
}
}
/* left boundary */
#pragma omp parallel for private(j)
for (j=1; j<ny-1; j+=2){
n = cellnb(0, j, 0, nx, ny);
cell[n].nneighb = 5;
cell[n].nghb[0] = cellnb(1, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(0, j+1, 0, nx, ny);
cell[n].nghb[2] = cellnb(1, j+1, 0, nx, ny);
cell[n].nghb[3] = cellnb(0, j-1, 0, nx, ny);
cell[n].nghb[4] = cellnb(1, j-1, 0, nx, ny);
}
#pragma omp parallel for private(j)
for (j=2; j<ny-1; j+=2){
n = cellnb(0, j, 0, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(1, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(0, j+1, 0, nx, ny);
cell[n].nghb[2] = cellnb(0, j-1, 0, nx, ny);
}
/* right boundary */
#pragma omp parallel for private(j)
for (j=1; j<ny-1; j+=2){
n = cellnb(nx-1, j, 0, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(nx-2, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(nx-1, j+1, 0, nx, ny);
cell[n].nghb[2] = cellnb(nx-1, j-1, 0, nx, ny);
}
#pragma omp parallel for private(j)
for (j=2; j<ny-1; j+=2){
n = cellnb(nx-1, j, 0, nx, ny);
cell[n].nneighb = 5;
cell[n].nghb[0] = cellnb(nx-2, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(nx-2, j+1, 0, nx, ny);
cell[n].nghb[2] = cellnb(nx-1, j+1, 0, nx, ny);
cell[n].nghb[3] = cellnb(nx-2, j-1, 0, nx, ny);
cell[n].nghb[4] = cellnb(nx-1, j-1, 0, nx, ny);
}
/* bottom boundary */
#pragma omp parallel for private(i)
for (i=1; i<nx-1; i++){
n = cellnb(i, 0, 0, nx, ny);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb(i+1, 0, 0, nx, ny);
cell[n].nghb[1] = cellnb(i-1, 0, 0, nx, ny);
cell[n].nghb[2] = cellnb(i-1, 1, 0, nx, ny);
cell[n].nghb[3] = cellnb(i, 1, 0, nx, ny);
}
/* top boundary */
#pragma omp parallel for private(i)
for (i=1; i<nx-1; i++){
n = cellnb(i, ny-1, 0, nx, ny);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb(i+1, ny-1, 0, nx, ny);
cell[n].nghb[1] = cellnb(i-1, ny-1, 0, nx, ny);
cell[n].nghb[2] = cellnb(i-1, ny-2, 0, nx, ny);
cell[n].nghb[3] = cellnb(i, ny-2, 0, nx, ny);
}
/* corners */
n = cellnb(0, 0, 0, nx, ny);
cell[n].nneighb = 2;
cell[n].nghb[0] = cellnb(1, 0, 0, nx, ny);
cell[n].nghb[1] = cellnb(0, 1, 0, nx, ny);
n = cellnb(nx-1, 0, 0, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(nx-2, 0, 0, nx, ny);
cell[n].nghb[1] = cellnb(nx-1, 1, 0, nx, ny);
cell[n].nghb[2] = cellnb(nx-2, 1, 0, nx, ny);
n = cellnb(0, ny-1, 0, nx, ny);
cell[n].nneighb = 2;
cell[n].nghb[0] = cellnb(1, ny-1, 0, nx, ny);
cell[n].nghb[1] = cellnb(0, ny-2, 0, nx, ny);
n = cellnb(nx-1, ny-1, 0, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(nx-2, ny-1, 0, nx, ny);
cell[n].nghb[1] = cellnb(nx-1, ny-2, 0, nx, ny);
cell[n].nghb[2] = cellnb(nx-2, ny-2, 0, nx, ny);
return(nx*ny);
break;
}
case (BC_HEX_BOND_DIRICHLET):
{
/* neighbours in the bulk */
/* vertical bonds */
#pragma omp parallel for private(i,j)
for (i=1; i<nx; i++){
for (j=1; j<ny; j+=2){
n = cellnb(i, j, 0, nx, ny);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb(i-1, j, 1, nx, ny);
cell[n].nghb[1] = cellnb(i, j, 2, nx, ny);
cell[n].nghb[2] = cellnb(i-1, j+1, 1, nx, ny);
cell[n].nghb[3] = cellnb(i-1, j+1, 2, nx, ny);
}
}
#pragma omp parallel for private(i,j)
for (i=1; i<nx; i++){
for (j=0; j<ny; j+=2){
n = cellnb(i, j, 0, nx, ny);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb(i-1, j, 1, nx, ny);
cell[n].nghb[1] = cellnb(i, j, 2, nx, ny);
cell[n].nghb[2] = cellnb(i, j+1, 1, nx, ny);
cell[n].nghb[3] = cellnb(i, j+1, 2, nx, ny);
}
}
/* NE-SW bonds */
#pragma omp parallel for private(i,j)
for (i=0; i<nx-1; i++){
for (j=1; j<ny-1; j+=2){
n = cellnb(i, j, 1, nx, ny);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb(i+1, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(i+1, j, 2, nx, ny);
cell[n].nghb[2] = cellnb(i, j-1, 0, nx, ny);
cell[n].nghb[3] = cellnb(i, j, 2, nx, ny);
}
}
#pragma omp parallel for private(i,j)
for (i=0; i<nx-1; i++){
for (j=2; j<ny-1; j+=2){
n = cellnb(i, j, 1, nx, ny);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb(i+1, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(i+1, j, 2, nx, ny);
cell[n].nghb[2] = cellnb(i+1, j-1, 0, nx, ny);
cell[n].nghb[3] = cellnb(i, j, 2, nx, ny);
}
}
/* NW-SE bonds */
#pragma omp parallel for private(i,j)
for (i=1; i<nx-1; i++){
for (j=1; j<ny-1; j+=2){
n = cellnb(i, j, 2, nx, ny);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb(i, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(i, j, 1, nx, ny);
cell[n].nghb[2] = cellnb(i, j-1, 0, nx, ny);
cell[n].nghb[3] = cellnb(i-1, j, 1, nx, ny);
}
}
#pragma omp parallel for private(i,j)
for (i=0; i<nx; i++){
for (j=2; j<ny-1; j+=2){
n = cellnb(i, j, 2, nx, ny);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb(i, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(i, j, 1, nx, ny);
cell[n].nghb[2] = cellnb(i+1, j-1, 0, nx, ny);
cell[n].nghb[3] = cellnb(i-1, j, 1, nx, ny);
}
}
/* left boundary */
/* vertical bonds */
#pragma omp parallel for private(j)
for (j=0; j<ny; j+=2)
{
n = cellnb(0, j, 0, nx, ny);
cell[n].nneighb = 2;
cell[n].nghb[0] = cellnb(0, j, 2, nx, ny);
cell[n].nghb[1] = cellnb(0, j+1, 1, nx, ny);
}
/* NE-SW bonds */
#pragma omp parallel for private(j)
for (j=1; j<ny-1; j+=2)
{
n = cellnb(0, j, 1, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(1, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(0, j-1, 0, nx, ny);
cell[n].nghb[2] = cellnb(1, j, 2, nx, ny);
}
/* NW-SE bonds */
#pragma omp parallel for private(j)
for (j=2; j<ny-1; j+=2)
{
n = cellnb(0, j, 2, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(0, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(1, j-1, 0, nx, ny);
cell[n].nghb[2] = cellnb(0, j, 1, nx, ny);
}
/* right boundary */
/* vertical bonds */
#pragma omp parallel for private(j)
for (j=0; j<ny; j+=2)
{
n = cellnb(nx-1, j, 0, nx, ny);
cell[n].nneighb = 2;
cell[n].nghb[0] = cellnb(nx-1, j+1, 2, nx, ny);
cell[n].nghb[1] = cellnb(nx-2, j, 1, nx, ny);
}
/* NE-SW bonds */
#pragma omp parallel for private(j)
for (j=1; j<ny-1; j+=2)
{
n = cellnb(nx-1, j, 1, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(nx, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(nx-1, j-1, 0, nx, ny);
cell[n].nghb[2] = cellnb(nx-1, j, 2, nx, ny);
}
#pragma omp parallel for private(j)
for (j=2; j<ny-1; j+=2)
{
n = cellnb(nx-1, j, 1, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(nx, j, 0, nx, ny);
cell[n].nghb[1] = cellnb(nx, j, 2, nx, ny);
cell[n].nghb[2] = cellnb(nx, j-1, 0, nx, ny);
}
/* NW-SE bonds */
#pragma omp parallel for private(j)
for (j=1; j<ny-1; j+=2)
{
n = cellnb(nx-1, j, 2, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(nx-1, j-1, 0, nx, ny);
cell[n].nghb[1] = cellnb(nx-1, j, 0, nx, ny);
cell[n].nghb[2] = cellnb(nx-2, j, 1, nx, ny);
}
#pragma omp parallel for private(j)
for (j=2; j<ny-1; j+=2)
{
n = cellnb(nx-1, j, 2, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(nx-1, j-1, 0, nx, ny);
cell[n].nghb[1] = cellnb(nx-1, j, 0, nx, ny);
cell[n].nghb[2] = cellnb(nx-2, j, 1, nx, ny);
}
/* bottom boundary */
/* NE-SW bonds */
#pragma omp parallel for private(i)
for (i=1; i<nx-1; i++)
{
n = cellnb(i, 0, 1, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(i+1, 0, 0, nx, ny);
cell[n].nghb[1] = cellnb(i, 0, 2, nx, ny);
cell[n].nghb[2] = cellnb(i+1, 0, 2, nx, ny);
}
/* NW-SE bonds */
#pragma omp parallel for private(i)
for (i=1; i<nx-1; i++)
{
n = cellnb(i, 0, 2, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(i, 0, 0, nx, ny);
cell[n].nghb[1] = cellnb(i-1, 0, 1, nx, ny);
cell[n].nghb[2] = cellnb(i, 0, 1, nx, ny);
}
/* top boundary */
/* vertical bonds */
#pragma omp parallel for private(i)
for (i=1; i<nx-1; i++)
{
n = cellnb(i, ny-1, 0, nx, ny);
cell[n].nneighb = 2;
cell[n].nghb[0] = cellnb(i-1, ny-1, 1, nx, ny);
cell[n].nghb[1] = cellnb(i, ny-1, 2, nx, ny);
}
/* NE-SW bonds */
#pragma omp parallel for private(i)
for (i=1; i<nx-1; i++)
{
n = cellnb(i, ny-1, 1, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(i+1, ny-1, 2, nx, ny);
cell[n].nghb[1] = cellnb(i, ny-1, 2, nx, ny);
cell[n].nghb[2] = cellnb(i+1, ny-2, 0, nx, ny);
}
/* NW-SE bonds */
#pragma omp parallel for private(i)
for (i=1; i<nx-1; i++)
{
n = cellnb(i, ny-1, 2, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(i-1, ny-1, 1, nx, ny);
cell[n].nghb[1] = cellnb(i, ny-1, 1, nx, ny);
cell[n].nghb[2] = cellnb(i+1, ny-2, 0, nx, ny);
}
/* corners */
n = cellnb(0, 0, 2, nx, ny);
cell[n].nneighb = 2;
cell[n].nghb[0] = cellnb(0, 0, 0, nx, ny);
cell[n].nghb[1] = cellnb(0, 0, 1, nx, ny);
return(3*(nx+1)*(ny+1)); /* TO BE CHECKED */
break;
}
case (BC_TRIANGLE_SITE_DIRICHLET):
{
/* neighbours in the bulk */
#pragma omp parallel for private(i,j)
for (i=1; i<2*nx-1; i++){
for (j=1; j<ny-1; j++){
n = cellnb(i, j, 0, nx, ny);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(i+1,j,0,nx,ny);
cell[n].nghb[1] = cellnb(i-1,j,0,nx,ny);
if ((i+j)%2 == 0) cell[n].nghb[2] = cellnb(i,j+1,0,nx,ny);
else cell[n].nghb[2] = cellnb(i,j-1,0,nx,ny);
}
}
/* left boundary */
#pragma omp parallel for private(j)
for (j=0; j<ny; j++){
n = cellnb(0, j, 0, nx, ny);
cell[n].nneighb = 2;
cell[n].nghb[0] = cellnb(1, j, 0, nx, ny);
if (j%2 == 0) cell[n].nghb[1] = cellnb(0, j+1, 0, nx, ny);
else cell[n].nghb[1] = cellnb(0, j-1, 0, nx, ny);
}
/* right boundary */
#pragma omp parallel for private(j)
for (j=1; j<ny-1; j++){
n = cellnb(2*nx-1, j, 0, nx, ny);
cell[n].nneighb = 2;
cell[n].nghb[0] = cellnb(2*nx-2, j, 0, nx, ny);
if (j%2 == 1) cell[n].nghb[1] = cellnb(2*nx-1, j+1, 0, nx, ny);
else cell[n].nghb[1] = cellnb(2*nx-1, j-1, 0, nx, ny);
}
/* bottom boundary */
#pragma omp parallel for private(i,j)
for (i=1; i<2*nx-1; i++){
n = cellnb(i, 0, 0, nx, ny);
if (i%2 == 0)
{
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(i-1, 0, 0, nx, ny);
cell[n].nghb[1] = cellnb(i+1, 0, 0, nx, ny);
cell[n].nghb[2] = cellnb(i, 1, 0, nx, ny);
}
else
{
cell[n].nneighb = 2;
cell[n].nghb[0] = cellnb(i+1, 0, 0, nx, ny);
cell[n].nghb[1] = cellnb(i-1, 0, 0, nx, ny);
}
}
/* top boundary */
#pragma omp parallel for private(i,j)
for (i=1; i<2*nx-1; i++){
n = cellnb(i, ny-1, 0, nx, ny);
if (i%2 == 1)
{
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb(i-1, ny-1, 0, nx, ny);
cell[n].nghb[1] = cellnb(i+1, ny-1, 0, nx, ny);
cell[n].nghb[2] = cellnb(i, ny-2, 0, nx, ny);
}
else
{
cell[n].nneighb = 2;
cell[n].nghb[0] = cellnb(i-1, ny-1, 0, nx, ny);
cell[n].nghb[1] = cellnb(i+1, ny-1, 0, nx, ny);
}
}
/* corners (at the right) */
n = cellnb(2*nx-1, 0, 0, nx, ny);
cell[n].nneighb = 1;
cell[n].nghb[0] = cellnb(2*nx-2, 0, 0, nx, ny);
n = cellnb(2*nx-1, ny-1, 0, nx, ny);
cell[n].nneighb = 1;
cell[n].nghb[0] = cellnb(2*nx-2, ny-1, 0, nx, ny);
return(2*nx*ny);
break;
}
case (BC_POISSON_DISC):
{
dpoisson = 3.0*sqrt((XMAX - XMIN)*(YMAX - YMIN)/(PI*(double)nx));
// printf("nx = %i, dpoisson = %.5lg\n", nx, dpoisson);
ncells = generate_poisson_discs(cell, dpoisson, nx);
radius = 1.8*dpoisson;
for (i=0; i<ncells; i++)
{
k = 0;
for (j=0; j<ncells; j++) if ((j != i)&&(k < MAX_NEIGHB))
{
if (module2(cell[j].x - cell[i].x, cell[j].y - cell[i].y) < radius)
{
cell[i].nghb[k] = j;
// printf("%i ", j);
k++;
}
}
cell[i].nneighb = k;
}
return(ncells);
break;
}
case (BC_CUBIC_DIRICHLET):
{
/* neighbours in the bulk */
#pragma omp parallel for private(i,j,k)
for (i=1; i<nx-1; i++){
for (j=1; j<ny-1; j++){
for (k=1; k<nz-1; k++){
n = cellnb_3d(i, j, k, 0, nx, ny, nz);
cell[n].nneighb = 6;
cell[n].nghb[0] = cellnb_3d(i+1, j, k, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(i-1, j, k, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(i, j+1, k, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(i, j-1, k, 0, nx, ny, nz);
cell[n].nghb[4] = cellnb_3d(i, j, k+1, 0, nx, ny, nz);
cell[n].nghb[5] = cellnb_3d(i, j, k-1, 0, nx, ny, nz);
}
}
}
/* back and front face */
#pragma omp parallel for private(j,k)
for (j=1; j<ny-1; j++){
for (k=1; k<nz-1; k++){
n = cellnb_3d(0, j, k, 0, nx, ny, nz);
cell[n].nneighb = 5;
cell[n].nghb[0] = cellnb_3d(0, j+1, k, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(0, j-1, k, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(0, j, k+1, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(0, j, k-1, 0, nx, ny, nz);
cell[n].nghb[4] = cellnb_3d(1, j, k, 0, nx, ny, nz);
n = cellnb_3d(nx-1, j, k, 0, nx, ny, nz);
cell[n].nneighb = 5;
cell[n].nghb[0] = cellnb_3d(nx-1, j+1, k, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(nx-1, j-1, k, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(nx-1, j, k+1, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(nx-1, j, k-1, 0, nx, ny, nz);
cell[n].nghb[4] = cellnb_3d(nx-2, j, k, 0, nx, ny, nz);
}
}
/* left and right face */
#pragma omp parallel for private(i,k)
for (i=1; i<nx-1; i++){
for (k=1; k<nz-1; k++){
n = cellnb_3d(i, 0, k, 0, nx, ny, nz);
cell[n].nneighb = 5;
cell[n].nghb[0] = cellnb_3d(i+1, 0, k, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(i-1, 0, k, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(i, 0, k+1, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(i, 0, k-1, 0, nx, ny, nz);
cell[n].nghb[4] = cellnb_3d(i, 1, k, 0, nx, ny, nz);
n = cellnb_3d(i, ny-1, k, 0, nx, ny, nz);
cell[n].nneighb = 5;
cell[n].nghb[0] = cellnb_3d(i+1, ny-1, k, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(i-1, ny-1, k, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(i, ny-1, k+1, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(i, ny-1, k-1, 0, nx, ny, nz);
cell[n].nghb[4] = cellnb_3d(i, ny-2, k, 0, nx, ny, nz);
}
}
/* lower and upper face */
#pragma omp parallel for private(i,j)
for (i=1; i<nx-1; i++){
for (j=1; j<ny-1; j++){
n = cellnb_3d(i, j, 0, 0, nx, ny, nz);
cell[n].nneighb = 5;
cell[n].nghb[0] = cellnb_3d(i+1, j, 0, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(i-1, j, 0, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(i, j+1, 0, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(i, j-1, 0, 0, nx, ny, nz);
cell[n].nghb[4] = cellnb_3d(i, j, 1, 0, nx, ny, nz);
n = cellnb_3d(i, j, nz-1, 0, nx, ny, nz);
cell[n].nneighb = 5;
cell[n].nghb[0] = cellnb_3d(i+1, j, nz-1, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(i-1, j, nz-1, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(i, j+1, nz-1, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(i, j-1, nz-1, 0, nx, ny, nz);
cell[n].nghb[4] = cellnb_3d(i, j, nz-2, 0, nx, ny, nz);
}
}
/* back to front edges */
#pragma omp parallel for private(i)
for (i=1; i<nx-1; i++){
n = cellnb_3d(i, 0, 0, 0, nx, ny, nz);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb_3d(i+1, 0, 0, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(i-1, 0, 0, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(i, 1, 0, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(i, 0, 1, 0, nx, ny, nz);
n = cellnb_3d(i, ny-1, 0, 0, nx, ny, nz);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb_3d(i+1, ny-1, 0, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(i-1, ny-1, 0, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(i, ny-2, 0, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(i, ny-1, 1, 0, nx, ny, nz);
n = cellnb_3d(i, 0, nz-1, 0, nx, ny, nz);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb_3d(i+1, 0, nz-1, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(i-1, 0, nz-1, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(i, 1, nz-1, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(i, 0, nz-2, 0, nx, ny, nz);
n = cellnb_3d(i, ny-1, nz-1, 0, nx, ny, nz);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb_3d(i+1, ny-1, nz-1, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(i-1, ny-1, nz-1, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(i, ny-2, nz-1, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(i, ny-1, nz-2, 0, nx, ny, nz);
}
/* left to right edges */
#pragma omp parallel for private(j)
for (j=1; j<ny-1; j++){
n = cellnb_3d(0, j, 0, 0, nx, ny, nz);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb_3d(0, j+1, 0, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(0, j-1, 0, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(1, j, 0, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(0, j, 1, 0, nx, ny, nz);
n = cellnb_3d(nx-1, j, 0, 0, nx, ny, nz);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb_3d(nx-1, j+1, 0, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(nx-1, j-1, 0, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(nx-2, j, 0, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(nx-1, j, 1, 0, nx, ny, nz);
n = cellnb_3d(0, j, nz-1, 0, nx, ny, nz);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb_3d(0, j+1, nz-1, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(0, j-1, nz-1, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(1, j, nz-1, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(0, j, nz-2, 0, nx, ny, nz);
n = cellnb_3d(nx-1, j, nz-1, 0, nx, ny, nz);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb_3d(nx-1, j+1, nz-1, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(nx-1, j-1, nz-1, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(nx-2, j, nz-1, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(nx-1, j, nz-2, 0, nx, ny, nz);
}
/* top to bottom edges */
#pragma omp parallel for private(k)
for (k=1; k<nz-1; k++){
n = cellnb_3d(0, 0, k, 0, nx, ny, nz);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb_3d(0, 0, k+1, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(0, 0, k-1, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(1, 0, k, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(0, 1, k, 0, nx, ny, nz);
n = cellnb_3d(nx-1, 0, k, 0, nx, ny, nz);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb_3d(nx-1, 0, k+1, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(nx-1, 0, k-1, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(nx-2, 0, k, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(nx-1, 1, k, 0, nx, ny, nz);
n = cellnb_3d(0, ny-1, k, 0, nx, ny, nz);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb_3d(0, ny-1, k+1, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(0, ny-1, k-1, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(1, ny-1, k, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(0, ny-2, k, 0, nx, ny, nz);
n = cellnb_3d(nx-1, ny-1, k, 0, nx, ny, nz);
cell[n].nneighb = 4;
cell[n].nghb[0] = cellnb_3d(nx-1, ny-1, k+1, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(nx-1, ny-1, k-1, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(nx-2, ny-1, k, 0, nx, ny, nz);
cell[n].nghb[3] = cellnb_3d(nx-1, ny-2, k, 0, nx, ny, nz);
}
/* corners */
n = cellnb_3d(0, 0, 0, 0, nx, ny, nz);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb_3d(1, 0, 0, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(0, 1, 0, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(0, 0, 1, 0, nx, ny, nz);
n = cellnb_3d(nx-1, 0, 0, 0, nx, ny, nz);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb_3d(nx-2, 0, 0, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(nx-1, 1, 0, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(nx-1, 0, 1, 0, nx, ny, nz);
n = cellnb_3d(0, ny-1, 0, 0, nx, ny, nz);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb_3d(1, ny-1, 0, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(0, ny-2, 0, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(0, ny-1, 1, 0, nx, ny, nz);
n = cellnb_3d(nx-1, ny-1, 0, 0, nx, ny, nz);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb_3d(nx-2, ny-1, 0, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(nx-1, ny-2, 0, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(nx-1, ny-1, 1, 0, nx, ny, nz);
n = cellnb_3d(0, 0, nz-1, 0, nx, ny, nz);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb_3d(1, 0, nz-1, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(0, 1, nz-1, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(0, 0, nz-2, 0, nx, ny, nz);
n = cellnb_3d(nx-1, 0, nz-1, 0, nx, ny, nz);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb_3d(nx-2, 0, nz-1, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(nx-1, 1, nz-1, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(nx-1, 0, nz-2, 0, nx, ny, nz);
n = cellnb_3d(0, ny-1, nz-1, 0, nx, ny, nz);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb_3d(1, ny-1, nz-1, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(0, ny-2, nz-1, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(0, ny-1, nz-2, 0, nx, ny, nz);
n = cellnb_3d(nx-1, ny-1, nz-1, 0, nx, ny, nz);
cell[n].nneighb = 3;
cell[n].nghb[0] = cellnb_3d(nx-2, ny-1, nz-1, 0, nx, ny, nz);
cell[n].nghb[1] = cellnb_3d(nx-1, ny-2, nz-1, 0, nx, ny, nz);
cell[n].nghb[2] = cellnb_3d(nx-1, ny-1, nz-2, 0, nx, ny, nz);
return(nx*ny*nz);
}
}
printf("Done\n");
}
void init_cell_probabilities(t_perco *cell, int ncells)
/* initialize the probabilities of cells being open */
{
int i;
printf("Initializing cell probabilities ...");
#pragma omp parallel for private(i)
for (i=0; i<ncells; i++)
{
cell[i].proba = (double)rand()/RAND_MAX;
}
printf("Done\n");
}
void init_cell_state(t_perco *cell, double p, int ncells, int first)
/* initialize the probabilities of cells being open */
{
int i, delta_i;
delta_i = ncells/100;
printf("Initializing cell state ...");
#pragma omp parallel for private(i)
for (i=0; i<ncells; i++)
{
if ((VERBOSE)&&(i%delta_i == 0)) printf("%i ", i/delta_i);
if (cell[i].proba < p)
{
cell[i].open = 1;
cell[i].active = 1;
}
else
{
cell[i].open = 0;
cell[i].active = 0;
}
cell[i].flooded = 0;
if (first) cell[i].previous_cluster = 0;
else cell[i].previous_cluster = cell[i].cluster;
cell[i].cluster = 0;
cell[i].tested = 0;
}
printf("Done\n");
}
int init_flooded_cells(t_perco *cell, int ncells, int nx, int ny, int nz, int bottom, t_perco* *pstack)
/* make the left row of cells flooded, returns number of flooded cells */
{
int i, j, k, n, ishift, c;
double pdisc_prop;
// printf("Initializing flooded cells ...");
switch (graphical_rep(LATTICE)) {
case (PLOT_SQUARES):
{
#pragma omp parallel for private(j)
for (j=0; j<ny; j++)
{
cell[j].open = 1;
cell[j].flooded = 1;
cell[j].cluster = 1;
cell[j].previous_cluster = 1;
cell[j].active = 1;
pstack[j] = &cell[j];
}
return(ny);
}
case (PLOT_SQUARE_BONDS):
{
ishift = nx*(ny+1);
#pragma omp parallel for private(j)
for (j=0; j<ny; j++)
{
cell[ishift + j].open = 1;
cell[ishift + j].flooded = 1;
cell[ishift + j].cluster = 1;
cell[ishift + j].previous_cluster = 1;
cell[ishift + j].active = 1;
pstack[j] = &cell[ishift + j];
}
return(ny);
}
case (PLOT_HEX):
{
#pragma omp parallel for private(j)
for (j=0; j<ny; j++)
{
cell[j*nx].open = 1;
cell[j*nx].flooded = 1;
cell[j*nx].cluster = 1;
cell[j*nx].previous_cluster = 1;
cell[j*nx].active = 1;
pstack[j] = &cell[j*nx];
}
return(ny);
}
case (PLOT_HEX_BONDS):
{
#pragma omp parallel for private(j)
for (j=0; j<ny; j+=2)
{
cell[j*nx].open = 1;
cell[j*nx].flooded = 1;
cell[j*nx].cluster = 1;
cell[j*nx].previous_cluster = 1;
cell[j*nx].active = 1;
pstack[j] = &cell[j*nx];
}
return(ny);
}
case (PLOT_TRIANGLE):
{
#pragma omp parallel for private(j)
for (j=0; j<ny; j++)
{
cell[2*j*nx].open = 1;
cell[2*j*nx].flooded = 1;
cell[2*j*nx].cluster = 1;
cell[2*j*nx].previous_cluster = 1;
cell[2*j*nx].active = 1;
pstack[j] = &cell[2*j*nx];
}
return(ny);
}
case (PLOT_POISSON_DISC):
{
n = 0;
pdisc_prop = 0.5/sqrt((double)ncells);
#pragma omp parallel for private(j)
for (j=0; j<ncells; j++) if (cell[j].x - XMIN < (XMAX - XMIN)*pdisc_prop)
{
// printf("Flooding cell %i\n", j);
cell[j].open = 1;
cell[j].flooded = 1;
cell[j].cluster = 1;
cell[j].previous_cluster = 1;
cell[j].active = 1;
pstack[n] = &cell[j];
n++;
}
printf("Flooded %i cells\n", n);
return(n);
}
case (PLOT_CUBES):
{
if (bottom)
{
#pragma omp parallel for private(i, j)
for (i=0; i<nx; i++)
for (j=0; j<ny; j++)
{
c = cellnb_3d(i, j, 0, 0, nx, ny, nz);
cell[c].open = 1;
cell[c].flooded = 1;
cell[c].cluster = 1;
cell[c].previous_cluster = 1;
cell[c].active = 1;
pstack[j*nx+i] = &cell[c];
}
return(nx*ny);
}
else
{
#pragma omp parallel for private(j,k)
for (j=0; j<ny; j++)
for (k=0; k<nz; k++)
{
c = cellnb_3d(0, j, k, 0, nx, ny, nz);
cell[c].open = 1;
cell[c].flooded = 1;
cell[c].cluster = 1;
cell[c].previous_cluster = 1;
cell[c].active = 1;
pstack[j*nz+k] = &cell[c];
}
return(ny*nz);
}
}
}
// printf("Done\n");
}
int count_open_cells(t_perco *cell, int ncells)
/* count the number of open cells */
{
int n = 0, i, delta_i;
delta_i = ncells/100;
for (i=0; i<ncells; i++)
{
if (cell[i].open) n++;
if ((VERBOSE)&&(i%delta_i == 0)) printf("%i ", i/delta_i);
}
return(n);
}
int count_flooded_cells(t_perco *cell, int ncells)
/* count the number of flooded cells */
{
int n = 0, i;
for (i=0; i<ncells; i++) if ((cell[i].open)&&(cell[i].flooded)) n++;
return(n);
}
int count_active_cells(t_perco *cell, int ncells)
/* count the number of active cells */
{
int n = 0, i;
for (i=0; i<ncells; i++)
if ((cell[i].active)&&(cell[i].flooded)) n++;
return(n);
}
int find_open_cells(t_perco *cell, int ncells, int position, t_perco* *pstack, int *stacksize, int cluster)
/* look for open neighbours of cell[position], returns difference in open cells */
{
int k, nopen = 0, n;
// printf("Position %i, open %i\n", position, pstack[position]->open);
if (!pstack[position]->open) return(-1);
pstack[position]->cluster = cluster;
for (k=0; k<pstack[position]->nneighb; k++)
{
n = pstack[position]->nghb[k];
if ((cell[n].open)&&(cell[n].cluster != cluster))
{
cell[n].flooded = 1;
cell[n].tested = 1;
cell[n].cluster = cluster;
cell[n].active = 1;
nopen++;
if (*stacksize < ncells)
{
(*stacksize)++;
pstack[*stacksize-1] = &cell[n];
}
}
}
if (nopen == 0)
{
pstack[position]->active = 0;
return(-1);
}
else return(nopen);
}
int find_percolation_cluster(t_perco *cell, int ncells, t_perco* *pstack, int nstack)
/* new version of cluster search algorithm, using stacks; returns number of flooded cells */
{
int position = 0, i, stacksize = nstack, nactive = nstack;
while (nactive > 0)
{
/* find an active cell in stack */
while (!pstack[position]->active) position++;
if (position == stacksize) position = 0;
nactive += find_open_cells(cell, ncells, position, pstack, &stacksize, 1);
}
printf("Stack size %i\n", stacksize);
return(stacksize);
}
int find_all_clusters(t_perco *cell, int ncells, int reset, int *max_cluster_label)
/* find all clusters of open cells; returns number of clusters */
{
int nclusters = 0, i, j, nactive, stacksize, position, newcluster = 1, maxlabel = 0, delta_i;
t_perco **cstack;
static int cluster;
cstack = (t_perco* *)malloc(ncells*sizeof(struct t_perco *));
if (reset) cluster = CLUSTER_SHIFT;
else cluster = (*max_cluster_label) + CLUSTER_SHIFT; /* give higher labels than before to new clusters */
delta_i = ncells/1000;
for (i=0; i<ncells; i++) if ((cell[i].open)&&(cell[i].cluster != 1)&&(!cell[i].tested))
{
position = 0;
stacksize = 1;
nactive = 1;
cstack[0] = &cell[i];
/* choice of new color */
if (cell[i].previous_cluster >= CLUSTER_SHIFT) newcluster = cell[i].previous_cluster;
else
{
newcluster = cluster;
cluster++;
}
cell[i].cluster = newcluster;
cell[i].active = 1;
cell[i].tested = 1;
while (nactive > 0)
{
/* find an active cell in stack */
while (!cstack[position]->active) position++;
if (position == stacksize) position = 0;
nactive += find_open_cells(cell, ncells, position, cstack, &stacksize, newcluster);
// if ((VERBOSE)&&(nactive%100 == 99)) printf ("%i active cells\n", nactive + 1);
}
if ((VERBOSE)&&(i%delta_i == 0)) printf("Found cluster %i with %i active cells\n", cluster, stacksize);
nclusters++;
}
free(cstack);
/* determine maximal cluster label */
// #pragma omp parallel for private(i)
for (i=0; i<ncells; i++) if ((cell[i].open)&&(cell[i].cluster > maxlabel)) maxlabel = cell[i].cluster;
printf("Cluster = %i, maxlabel = %i\n", cluster, maxlabel);
*max_cluster_label = maxlabel;
return(nclusters);
}
void print_cluster_sizes(t_perco *cell, int ncells, int *cluster_sizes)
/* for debugging purposes */
{
int j;
for (j=0; j<ncells; j++) if (cell[j].open == 1)
printf("(cell %i: cluster %i: size %i)\n", j, cell[j].cluster, cluster_sizes[cell[j].cluster]);
sleep(1);
printf("\n\n");
}
int find_cluster_sizes(t_perco *cell, int ncells, int *cluster_sizes, int *maxclusterlabel)
/* determine the sizes of all clusters; returns the size of largest cluster */
{
int i, max = 0, maxlabel = 0;
// if (maxclusterlabel > ncells) maxclusterlabel = ncells;
/* determine label of larges cluster */
for (i=0; i<ncells; i++) if (cell[i].cluster > maxlabel) maxlabel = cell[i].cluster;
*maxclusterlabel = maxlabel + 1;
#pragma omp parallel for private(i)
for (i=0; i<*maxclusterlabel; i++) cluster_sizes[i] = 0;
for (i=0; i<ncells; i++) if (cell[i].open) cluster_sizes[cell[i].cluster]++;
if (DEBUG)
{
printf("Computed %i cluster sizes\n", *maxclusterlabel);
print_cluster_sizes(cell, ncells, cluster_sizes);
}
for (i=0; i<*maxclusterlabel; i++) if (cluster_sizes[i] > max) max = cluster_sizes[i];
// for (i=0; i<ncells; i++) if (cell[i].open) printf("%i ", cluster_sizes[cell[i].cluster]);
printf("Max cluster label %i\n", *maxclusterlabel);
printf("Largest cluster has %i cells\n", max);
return(max);
}