#include "voz.h" #include #include #include #include #include "voro++.hh" using namespace voro; #define DL for (d=0;d<3;d++) #define BF 1e30 #define MAX(a,b) ( ((a) < (b)) ? (a) : (b) ) int posread(char *posfile, float ***p, float fact); int main(int argc, char *argv[]) { int exitcode; int i, j, np; float **r; double rtemp[3], *parts; double deladjs[3*MAXVERVER], points[3*MAXVERVER]; FILE *pos, *out, *testFile; char *posfile, outfile[200], *suffix, *outDir; PARTADJ *adjs; float *vols; float predict, xmin,xmax,ymin,ymax,zmin,zmax; int *orig; int isitinbuf; char isitinmain, d; int numdiv; int nvp, nvpall, nvpbuf; float width, width2, totwidth, totwidth2, bf, s, g; float border, boxsize; float c[3]; int b[3]; double totalvol; int isObs = 0; printf("Routine: voz1b1\n"); if (argc != 11) { printf("Wrong number of arguments.\n"); printf("arg1: position file\n"); printf("arg2: border size\n"); printf("arg3: boxsize\n"); printf("arg4: suffix\n"); printf("arg5: number of divisions\n"); printf("arg6-8: b[0-2]\n\n"); printf("arg9: output directory\n"); printf("arg10: observation flag\n"); exit(0); } posfile = argv[1]; if (sscanf(argv[2],"%f",&border) != 1) { printf("That's no border size; try again.\n"); exit(0); } if (sscanf(argv[3],"%f",&boxsize) != 1) { printf("That's no boxsize; try again.\n"); exit(0); } suffix = argv[4]; if (sscanf(argv[5],"%d",&numdiv) != 1) { printf("%s is no number of divisions; try again.\n",argv[5]); exit(0); } if (numdiv == 1) { printf("Only using one division; should only use for an isolated segment.\n"); } if (numdiv < 1) { printf("Cannot have a number of divisions less than 1. Resetting to 1.\n"); numdiv = 1; } if (sscanf(argv[6],"%d",&b[0]) != 1) { printf("That's no b index; try again.\n"); exit(0); } if (sscanf(argv[7],"%d",&b[1]) != 1) { printf("That's no b index; try again.\n"); exit(0); } if (sscanf(argv[8],"%d",&b[2]) != 1) { printf("That's no b index; try again.\n"); exit(0); } outDir = argv[9]; if (sscanf(argv[10],"%d",&isObs) != 1) { printf("That's no observation mode; try again.\n"); exit(0); } printf("Working with subdomain b=[%d,%d,%d]\n", b[0], b[1], b[2]); /* Boxsize should be the range in r, yielding a range 0-1 */ printf("Reading particle file...\n"); np = posread(posfile,&r,1./boxsize); printf("%d particles\n",np);fflush(stdout); xmin = BF; xmax = -BF; ymin = BF; ymax = -BF; zmin = BF; zmax = -BF; for (i=0; ixmax) xmax = r[i][0]; if (r[i][1]ymax) ymax = r[i][1]; if (r[i][2]zmax) zmax = r[i][2]; } printf("Full box particle stats: np: %d, x: %f,%f; y: %f,%f; z: %f,%f\n",np, xmin,xmax, ymin,ymax, zmin,zmax); fflush(stdout); width = 1./(float)numdiv; width2 = 0.5*width; if (border > 0.) bf = border; else bf = 0.1; /* In units of 0-1, the thickness of each subregion's buffer*/ totwidth = width+2.*bf; totwidth2 = width2 + bf; s = width/(float)NGUARD; if ((bf*bf - 2.*s*s) < 0.) { printf("bf = %f, s = %f.\n",bf,s); printf("Not enough guard points for given border.\nIncrease guards to >= %f\n.", sqrt(2.)*width/bf); exit(0); } g = (bf / 2.)*(1. + sqrt(1 - 2.*s*s/(bf*bf))); printf("Guard particle information: s = %f, bf = %f, g = %f.\n",s,bf,g); fflush(stdout); adjs = (PARTADJ *)malloc(np*sizeof(PARTADJ)); if (adjs == NULL) { printf("Unable to allocate adjs\n"); exit(1); } DL c[d] = ((float)b[d]+0.5)*width; printf("Counting particles in subdomain...\n"); /* Assign temporary array*/ nvpbuf = 0; /* Number of particles to tesselate, includng buffer and guards */ nvp = 0; /* Without the buffer */ for (i=0; i 0.5) rtemp[d] --; if (rtemp[d] < -0.5) rtemp[d] ++; isitinbuf = isitinbuf && (fabs(rtemp[d]) < totwidth2); isitinmain = isitinmain && (fabs(rtemp[d]) <= width2); } if (isitinbuf) nvpbuf++; if (isitinmain) nvp++; } nvpbuf += 6*(NGUARD+1)*(NGUARD+1); /* number of guard points */ parts = (double *)malloc(3*nvpbuf*sizeof(double)); orig = (pid_t *)malloc(nvpbuf*sizeof(pid_t)); if (parts == NULL) { printf("Unable to allocate parts\n"); fflush(stdout); exit(1); } if (orig == NULL) { printf("Unable to allocate orig\n"); fflush(stdout); exit(1); } printf("Placing particles in subdomain...\n"); nvp = 0; nvpall = 0; /* nvp = number of particles without buffer */ xmin = BF; xmax = -BF; ymin = BF; ymax = -BF; zmin = BF; zmax = -BF; for (i=0; i 0.5) rtemp[d] --; if (rtemp[d] < -0.5) rtemp[d] ++; isitinmain = isitinmain && (fabs(rtemp[d]) <= width2); } if (isitinmain) { parts[3*nvp] = rtemp[0]; parts[3*nvp+1] = rtemp[1]; parts[3*nvp+2] = rtemp[2]; orig[nvp] = i; nvp++; if (rtemp[0] < xmin) xmin = rtemp[0]; if (rtemp[0] > xmax) xmax = rtemp[0]; if (rtemp[1] < ymin) ymin = rtemp[1]; if (rtemp[1] > ymax) ymax = rtemp[1]; if (rtemp[2] < zmin) zmin = rtemp[2]; if (rtemp[2] > zmax) zmax = rtemp[2]; } } printf("Subdomain: b=(%d,%d,%d), c=(%f,%f,%f)\n", b[0],b[1],b[2],c[0],c[1],c[2]); printf(" nvp=%d, nvpbuf=%d\n", nvp,nvpbuf); printf(" Particle ranges: x: %f,%f; y: %f,%f; z:%f,%f\n", xmin,xmax,ymin,ymax,zmin,zmax); printf("Adding particles to buffer regions...\n"); nvpbuf = nvp; for (i=0; i 0.5) rtemp[d] --; if (rtemp[d] < -0.5) rtemp[d] ++; isitinbuf = isitinbuf && (fabs(rtemp[d]) xmax) xmax = rtemp[0]; if (rtemp[1] < ymin) ymin = rtemp[1]; if (rtemp[1] > ymax) ymax = rtemp[1]; if (rtemp[2] < zmin) zmin = rtemp[2]; if (rtemp[2] > zmax) zmax = rtemp[2]; } } nvpall = nvpbuf; predict = pow(width+2.*bf,3)*(float)np; printf("Total particles including buffer = %d (predicted ~%f)\n", nvpbuf, predict); printf(" Particle ranges including buffer: x: %f,%f; y: %f,%f; z:%f,%f\n", xmin,xmax,ymin,ymax,zmin,zmax); for (i=0;i nvp) itype = 1; // it's a buffer particle if (i > nvpbuf) itype = 2; // it's a guard particle fprintf(testFile, "%f %f %f %d %f %f %f\n", c[0], c[1], c[2], itype, parts[3*i], parts[3*i+1], parts[3*i+2]); } fclose(testFile); xmin = BF; xmax = -BF; ymin = BF; ymax = -BF; zmin = BF; zmax = -BF; for (i=nvpbuf;i xmax) xmax = parts[3*i]; if (parts[3*i+1] < ymin) ymin = parts[3*i+1]; if (parts[3*i+1] > ymax) ymax = parts[3*i+1]; if (parts[3*i+2] < zmin) zmin = parts[3*i+2]; if (parts[3*i+2] > zmax) zmax = parts[3*i+2]; } printf("Added guard points to total %d points (should be %d)\n",nvpall, nvpbuf + 6*(NGUARD+1)*(NGUARD+1)); printf("New particle ranges including guards: x: %f,%f; y: %f,%f; z:%f,%f\n", xmin,xmax,ymin,ymax,zmin,zmax); /* Do tesselation*/ printf("File read. Tessellating ...\n"); fflush(stdout); // initialize a voro++ container with non-periodic boundaries // per voro++ documentaiton, max efficiency is achieved with ~8 particles per subdomain block int nblocks = floor(pow(nvpall, 1/3.)/8); container con(xmin,xmax,ymin,ymax,zmin,zmax, nblocks,nblocks,nblocks, false,false,false, 8); particle_order po; // this will keep track of only original particles // initialize storage arrays vols = (float *)malloc(nvp*sizeof(float)); // place our particles in the container for (i=0; i adjsv; cell.neighbors(adjsv); // copy adjacencies to old-school data format adjs[p].nadj = adjsv.size(); adjs[p].adj = (int *)malloc(adjsv.size() * sizeof(int)); for (int iAdj; iAdj < adjsv.size(); ++iAdj) { adjs[p].adj[iAdj] = adjsv[iAdj]; } // grab volume and store vols[p] = cell.volume()*(float)np; p++; } while(vl.inc()); //if (i % 1000 == 0) // printf("%d: %d, %f\n",i,adjs[i].nadj,vols[i]); // PMS - reset number of adjancies to not include links to border guards /* for (i=0; i 0) fwrite(adjs[i].adj,adjs[i].nadj,sizeof(pid_t),out); else printf("0"); } fclose(out); return(0); }