mirror of
https://bitbucket.org/cosmicvoids/vide_public.git
synced 2025-07-04 23:31:12 +00:00
begin branch to replace qhull with voro++ for tessellation
This commit is contained in:
parent
be797c05dc
commit
53483fd0d8
11 changed files with 1449 additions and 1 deletions
481
c_source/vorozobov/voz1b1.cpp
Normal file
481
c_source/vorozobov/voz1b1.cpp
Normal file
|
@ -0,0 +1,481 @@
|
|||
#include "voz.h"
|
||||
#include <cstdio>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
|
||||
#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; i<np;i++) {
|
||||
if (r[i][0]<xmin) xmin = r[i][0]; if (r[i][0]>xmax) xmax = r[i][0];
|
||||
if (r[i][1]<ymin) ymin = r[i][1]; if (r[i][1]>ymax) ymax = r[i][1];
|
||||
if (r[i][2]<zmin) zmin = r[i][2]; 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<np; i++) {
|
||||
isitinbuf = 1;
|
||||
isitinmain = 1;
|
||||
DL {
|
||||
rtemp[d] = (double)r[i][d] - (double)c[d];
|
||||
if (rtemp[d] > 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<np; i++) {
|
||||
isitinmain = 1;
|
||||
DL {
|
||||
rtemp[d] = (float)r[i][d] - (float)c[d];
|
||||
if (rtemp[d] > 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<np; i++) {
|
||||
isitinbuf = 1;
|
||||
isitinmain = 1;
|
||||
|
||||
DL {
|
||||
rtemp[d] = (float)r[i][d] - (float)c[d];
|
||||
if (rtemp[d] > 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 && !isitinmain) {
|
||||
parts[3*nvpbuf] = rtemp[0];
|
||||
parts[3*nvpbuf+1] = rtemp[1];
|
||||
parts[3*nvpbuf+2] = rtemp[2];
|
||||
orig[nvpbuf] = i;
|
||||
|
||||
nvpbuf++;
|
||||
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];
|
||||
}
|
||||
}
|
||||
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<np;i++) free(r[i]);
|
||||
free(r);
|
||||
|
||||
|
||||
/* Add guard points */
|
||||
// first the internal boundaries between subdomains
|
||||
printf("Adding guard points to internal subdomain faces...\n");
|
||||
for (i=0; i<NGUARD+1; i++) {
|
||||
for (j=0; j<NGUARD+1; j++) {
|
||||
/* Bottom */
|
||||
if (b[2] != 0) { // we will do the outer edges next
|
||||
parts[3*nvpall] = -width2 + (float)i * s;
|
||||
parts[3*nvpall+1] = -width2 + (float)j * s;
|
||||
parts[3*nvpall+2] = -width2 - g;
|
||||
nvpall++;
|
||||
}
|
||||
/* Top */
|
||||
if (b[2] != numdiv-1) {
|
||||
parts[3*nvpall] = -width2 + (float)i * s;
|
||||
parts[3*nvpall+1] = -width2 + (float)j * s;
|
||||
parts[3*nvpall+2] = width2 + g;
|
||||
nvpall++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i=0; i<NGUARD+1; i++) { /* Don't want to overdo the corners*/
|
||||
for (j=0; j<NGUARD+1; j++) {
|
||||
if (b[1] != 0) { // we will do the outer edges next
|
||||
parts[3*nvpall] = -width2 + (float)i * s;
|
||||
parts[3*nvpall+1] = -width2 - g;
|
||||
parts[3*nvpall+2] = -width2 + (float)j * s;
|
||||
nvpall++;
|
||||
}
|
||||
|
||||
if (b[1] != numdiv-1) {
|
||||
parts[3*nvpall] = -width2 + (float)i * s;
|
||||
parts[3*nvpall+1] = width2 + g;
|
||||
parts[3*nvpall+2] = -width2 + (float)j * s;
|
||||
nvpall++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i=0; i<NGUARD+1; i++) {
|
||||
for (j=0; j<NGUARD+1; j++) {
|
||||
if (b[0] != 0) { // we will do the outer edges next
|
||||
parts[3*nvpall] = -width2 - g;
|
||||
parts[3*nvpall+1] = -width2 + (float)i * s;
|
||||
parts[3*nvpall+2] = -width2 + (float)j * s;
|
||||
nvpall++;
|
||||
}
|
||||
|
||||
if (b[0] != numdiv-1) {
|
||||
parts[3*nvpall] = width2 + g;
|
||||
parts[3*nvpall+1] = -width2 + (float)i * s;
|
||||
parts[3*nvpall+2] = -width2 + (float)j * s;
|
||||
nvpall++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now the external faces of the domain
|
||||
// (i'm tired and can't think of a better way to do this)
|
||||
isObs = 0;
|
||||
if (isObs != 1) {
|
||||
printf("Adding guard points to external domain faces...\n");
|
||||
for (i=0; i<NGUARD+1; i++) {
|
||||
for (j=0; j<NGUARD+1; j++) {
|
||||
/* Bottom */
|
||||
if (b[2] == 0) {
|
||||
parts[3*nvpall] = -width2 + (float)i * s;
|
||||
parts[3*nvpall+1] = -width2 + (float)j * s;
|
||||
parts[3*nvpall+2] = -width2 - g;
|
||||
nvpall++;
|
||||
}
|
||||
/* Top */
|
||||
if (b[2] == numdiv-1) {
|
||||
parts[3*nvpall] = -width2 + (float)i * s;
|
||||
parts[3*nvpall+1] = -width2 + (float)j * s;
|
||||
parts[3*nvpall+2] = width2 + g;
|
||||
nvpall++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i=0; i<NGUARD+1; i++) { /* Don't want to overdo the corners*/
|
||||
for (j=0; j<NGUARD+1; j++) {
|
||||
if (b[1] == 0) {
|
||||
parts[3*nvpall] = -width2 + (float)i * s;
|
||||
parts[3*nvpall+1] = -width2 - g;
|
||||
parts[3*nvpall+2] = -width2 + (float)j * s;
|
||||
nvpall++;
|
||||
}
|
||||
|
||||
if (b[1] == numdiv-1) {
|
||||
parts[3*nvpall] = -width2 + (float)i * s;
|
||||
parts[3*nvpall+1] = width2 + g;
|
||||
parts[3*nvpall+2] = -width2 + (float)j * s;
|
||||
nvpall++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i=0; i<NGUARD+1; i++) {
|
||||
for (j=0; j<NGUARD+1; j++) {
|
||||
if (b[0] == 0) {
|
||||
parts[3*nvpall] = -width2 - g;
|
||||
parts[3*nvpall+1] = -width2 + (float)i * s;
|
||||
parts[3*nvpall+2] = -width2 + (float)j * s;
|
||||
nvpall++;
|
||||
}
|
||||
|
||||
if (b[0] == numdiv-1) {
|
||||
parts[3*nvpall] = width2 + g;
|
||||
parts[3*nvpall+1] = -width2 + (float)i * s;
|
||||
parts[3*nvpall+2] = -width2 + (float)j * s;
|
||||
nvpall++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end if isObs != -1
|
||||
|
||||
|
||||
// TEST TEMP
|
||||
testFile = fopen("test.txt", "a");
|
||||
for (i=0; i<nvpall; i++){
|
||||
int itype = 0;
|
||||
if (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<nvpall;i++) {
|
||||
if (parts[3*i] < xmin) xmin = parts[3*i];
|
||||
if (parts[3*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<nvpall; i++) {
|
||||
if (i < nvp) con.put(po, i, parts[3*i], parts[3*i+1], parts[3*i+2]);
|
||||
else con.put(i, parts[3*i], parts[3*i+1], parts[3*i+2]);
|
||||
}
|
||||
|
||||
// loop over main particles and compute tesselation
|
||||
voronoicell_neighbor cell;
|
||||
c_loop_order vl(con,po);
|
||||
int p = 0;
|
||||
if(vl.start()) do if(con.compute_cell(cell,vl)) {
|
||||
// grab neighbor information and store in internal arrays
|
||||
std::vector<int> 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<nvp; i++) {
|
||||
int nActual = 0;
|
||||
for (j = 0; j < adjs[i].nadj; j++)
|
||||
if (adjs[i].adj[j] < nvp) nActual++;
|
||||
adjs[i].nadj = nActual;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Get the adjacencies back to their original values */
|
||||
|
||||
for (i=0; i<nvp; i++)
|
||||
for (j = 0; j < adjs[i].nadj; j++)
|
||||
adjs[i].adj[j] = orig[adjs[i].adj[j]];
|
||||
|
||||
totalvol = 0.;
|
||||
for (i=0;i<nvp; i++) {
|
||||
totalvol += (double)vols[i];
|
||||
}
|
||||
printf("Average volume = %g\n",totalvol/(float)nvp);
|
||||
|
||||
/* Now the output!
|
||||
First number of particles */
|
||||
sprintf(outfile,"%s/part.%s.%02d.%02d.%02d",outDir,suffix,b[0],b[1],b[2]);
|
||||
|
||||
printf("Output to %s\n\n",outfile);
|
||||
out = fopen(outfile,"w");
|
||||
if (out == NULL) {
|
||||
printf("Unable to open %s\n",outfile);
|
||||
exit(1);
|
||||
}
|
||||
fwrite(&np,1, sizeof(int),out);
|
||||
fwrite(&nvp,1, sizeof(int),out);
|
||||
printf("nvp = %d\n",nvp);
|
||||
|
||||
/* Tell us where the original particles were */
|
||||
fwrite(orig,sizeof(pid_t),nvp,out);
|
||||
/* Volumes*/
|
||||
fwrite(vols,sizeof(float),nvp,out);
|
||||
/* Adjacencies */
|
||||
for (i=0;i<nvp;i++) {
|
||||
fwrite(&(adjs[i].nadj),1,sizeof(pid_t),out);
|
||||
if (adjs[i].nadj > 0)
|
||||
fwrite(adjs[i].adj,adjs[i].nadj,sizeof(pid_t),out);
|
||||
else printf("0");
|
||||
}
|
||||
fclose(out);
|
||||
|
||||
return(0);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue