1 // Voronoi calculation example code
3 // Author : Chris H. Rycroft (LBL / UC Berkeley)
4 // Email : chr@alum.mit.edu
5 // Date : August 30th 2011
13 // Set up constants for the container geometry
14 const double boxl
=1.2;
16 // Set up the number of blocks that the container is divided into
19 // Set the number of particles that are going to be randomly introduced
20 const int particles
=2000;
24 // This function returns a random double between 0 and 1
25 double rnd() {return double(rand())/RAND_MAX
;}
27 struct wall_shell
: public wall
{
29 wall_shell(double xc_
,double yc_
,double zc_
,double rc
,double sc
,int w_id_
=-99)
30 : w_id(w_id_
), xc(xc_
), yc(yc_
), zc(zc_
), lc(rc
-sc
), uc(rc
+sc
) {}
31 bool point_inside(double x
,double y
,double z
) {
32 double rsq
=(x
-xc
)*(x
-xc
)+(y
-yc
)*(y
-yc
)+(z
-zc
)*(z
-zc
);
33 return rsq
>lc
*lc
&&rsq
<uc
*uc
;
35 template<class v_cell
>
36 bool cut_cell_base(v_cell
&c
,double x
,double y
,double z
) {
37 double xd
=x
-xc
,yd
=y
-yc
,zd
=z
-zc
,dq
=xd
*xd
+yd
*yd
+zd
*zd
,dq2
;
39 dq2
=2*(sqrt(dq
)*lc
-dq
);
40 dq
=2*(sqrt(dq
)*uc
-dq
);
41 return c
.nplane(xd
,yd
,zd
,dq
,w_id
)&&c
.nplane(-xd
,-yd
,-zd
,-dq2
,w_id
);
45 bool cut_cell(voronoicell
&c
,double x
,double y
,double z
) {return cut_cell_base(c
,x
,y
,z
);}
46 bool cut_cell(voronoicell_neighbor
&c
,double x
,double y
,double z
) {return cut_cell_base(c
,x
,y
,z
);}
49 const double xc
,yc
,zc
,lc
,uc
;
55 double x
,y
,z
,r
,dx
,dy
,dz
;
57 double p
[3*particles
];
59 // Create a container with the geometry given above, and make it
60 // non-periodic in each of the three coordinates. Allocate space for
61 // eight particles within each computational block
62 container
con(-boxl
,boxl
,-boxl
,boxl
,-boxl
,boxl
,bl
,bl
,bl
,false,false,false,8);
64 wall_shell
ws(0,0,0,1,0.00001);
67 // Randomly add particles into the container
74 r
=1/sqrt(r
);x
*=r
;y
*=r
;z
*=r
;
83 for(fp
=faces
;fp
<faces
+nface
;fp
++) *fp
=0;
84 if(vl
.start()) do if(con
.compute_cell(c
,vl
)) {
91 i
=c
.number_of_faces()-4;
92 if(i
<0) i
=0;if(i
>=nface
) i
=nface
-1;
96 double fac
=0;//l<9000?0.1/sqrt(double(l)):0;
97 for(i
=0;i
<particles
;i
++) con
.put(i
,p
[3*i
]+fac
*(2*rnd()-1),p
[3*i
+1]+fac
*(2*rnd()-1),p
[3*i
+2]+fac
*(2*rnd()-1));
99 for(fp
=faces
;fp
<faces
+nface
;fp
++) printf(" %d",*fp
);
103 // Output the particle positions in gnuplot format
104 con
.draw_particles("sphere_mesh_p.gnu");
106 // Output the Voronoi cells in gnuplot format
107 con
.draw_cells_gnuplot("sphere_mesh_v.gnu");
109 // Allocate memory for neighbor relations
110 int *q
=new int[particles
*nface
],*qn
=new int[particles
],*qp
;
111 for(l
=0;l
<particles
;l
++) qn
[l
]=0;
113 // Create a table of all neighbor relations
115 voronoicell_neighbor c
;
117 if(vl
.start()) do if(con
.compute_cell(c
,vl
)) {
118 i
=vl
.pid();qp
=q
+i
*nface
;
120 if(vi
.size()>nface
+2) voro_fatal_error("Too many faces; boost nface",5);
122 for(l
=0;l
<(signed int) vi
.size();l
++) if(vi
[l
]>=0) qp
[qn
[i
]++]=vi
[l
];
125 // Sort the connections in anti-clockwise order
128 for(l
=0;l
<particles
;l
++) {
130 for(i
=0;i
<qn
[l
]-2;i
++) {
132 //printf("---> %d,%d\n",i,o);
136 // printf("-> %d %d\n",j,ll);
138 for(k
=0;k
<qn
[ll
];k
++) {
139 // printf("%d %d %d\n",ll,k,q[ll*nface+k]);
140 if(q
[ll
*nface
+k
]==o
) {connect
=true;break;}
146 // Swap the connected vertex into this location
147 //printf("%d %d\n",i+1,j);
149 q
[l
*nface
+i
+1]=q
[l
*nface
+j
];
153 // Reverse all connections if the have the wrong handedness
154 j
=3*l
;k
=3*q
[l
*nface
];o
=3*q
[l
*nface
+1];
155 x
=p
[j
]-p
[k
];dx
=p
[j
]-p
[o
];
156 y
=p
[j
+1]-p
[k
+1];dy
=p
[j
+1]-p
[o
+1];
157 z
=p
[j
+2]-p
[k
+2];dz
=p
[j
+2]-p
[o
+2];
158 if(p
[j
]*(y
*dz
-z
*dy
)+p
[j
+1]*(z
*dx
-x
*dz
)+p
[j
+2]*(x
*dy
-y
*dx
)<0) {
159 for(i
=0;i
<qn
[l
]/2;i
++) {
161 q
[l
*nface
+i
]=q
[l
*nface
+qn
[l
]-1-i
];
162 q
[l
*nface
+qn
[l
]-1-i
]=o
;
167 FILE *ff
=safe_fopen("sphere_mesh.net","w");
168 int *mp
=new int[particles
],*mpi
=new int[particles
];
169 for(i
=0;i
<particles
;i
++) mp
[i
]=-1;
170 *mpi
=0;*mp
=0;l
=1;o
=0;
173 for(j
=0;j
<qn
[i
];j
++) {
180 fprintf(ff
,"%g %g %g\n%g %g %g\n\n\n",p
[3*i
],p
[3*i
+1],p
[3*i
+2],p
[3*k
],p
[3*k
+1],p
[3*k
+2]);
186 // Save binary representation of the mesh
187 FILE *fb
=safe_fopen("sphere_mesh.bin","wb");
190 int kk
[3],sz
=tote
+particles
+2,*red(new int[sz
]),*rp
=red
;
191 *kk
=1;kk
[1]=sz
;kk
[2]=3*particles
;
192 fwrite(kk
,sizeof(int),3,fb
);
194 // Assemble the connections and write them
195 *(rp
++)=particles
;*(rp
++)=tote
;
196 for(l
=0;l
<particles
;l
++) *(rp
++)=qn
[mpi
[l
]];
197 for(l
=0;l
<particles
;l
++) {
198 i
=mpi
[l
];printf("%d",l
);
199 for(j
=0;j
<qn
[i
];j
++) {*(rp
++)=mp
[q
[i
*nface
+j
]];printf(" %d",*(rp
-1));}
202 fwrite(red
,sizeof(int),sz
,fb
);
205 double *pm
=new double[3*particles
],*a
=pm
,*b
;
206 for(i
=0;i
<particles
;i
++) {
208 *(a
++)=*(b
++);*(a
++)=*(b
++);*(a
++)=*b
;
210 fwrite(pm
,sizeof(double),3*particles
,fb
);
213 // Free dynamically allocated arrays