/*********************/ /* 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) width); TIFFSetField(file, TIFFTAG_IMAGELENGTH, (uint32) 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 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 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 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 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=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= 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=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 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= 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; iopen); if (!pstack[position]->open) return(-1); pstack[position]->cluster = cluster; for (k=0; knneighb; 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= 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 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) maxclusterlabel = ncells; /* determine label of larges cluster */ for (i=0; i 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 max) max = cluster_sizes[i]; // for (i=0; i