Minkowski test code.
[voro++.git] / trunk / src / container_prd.hh
blob36f4da5ae1af2a6d2b46b2421d47bf6b2d4cd430
1 // Voro++, a 3D cell-based Voronoi library
2 //
3 // Author : Chris H. Rycroft (LBL / UC Berkeley)
4 // Email : chr@alum.mit.edu
5 // Date : August 30th 2011
7 /** \file container_prd.hh
8 * \brief Header file for the container_periodic_base and related classes. */
10 #ifndef VOROPP_CONTAINER_PRD_HH
11 #define VOROPP_CONTAINER_PRD_HH
13 #include <cstdio>
14 #include <vector>
16 #include "config.hh"
17 #include "common.hh"
18 #include "v_base.hh"
19 #include "cell.hh"
20 #include "c_loops.hh"
21 #include "v_compute.hh"
22 #include "unitcell.hh"
23 #include "rad_option.hh"
25 namespace voro {
27 /** \brief Class for representing a particle system in a 3D periodic
28 * non-orthogonal periodic domain.
30 * This class represents a particle system in a three-dimensional
31 * non-orthogonal periodic domain. The domain is defined by three periodicity
32 * vectors (bx,0,0), (bxy,by,0), and (bxz,byz,bz) that represent a
33 * parallelepiped. Internally, the class stores particles in the box 0<x<bx,
34 * 0<y<by, 0<z<bz, and constructs periodic images of particles that displaced
35 * by the three periodicity vectors when they are necessary for the
36 * computation. The internal memory structure for this class is significantly
37 * different from the container_base class in order to handle the dynamic
38 * construction of these periodic images.
40 * The class is derived from the unitcell class, which encapsulates information
41 * about the domain geometry, and the voro_base class, which encapsulates
42 * information about the underlying computational grid. */
43 class container_periodic_base : public unitcell, public voro_base {
44 public:
45 const double max_len_sq;
46 /** The lower y index (inclusive) of the primary domain within
47 * the block structure. */
48 int ey;
49 /** The lower z index (inclusive) of the primary domain within
50 * the block structure. */
51 int ez;
52 /** The upper y index (exclusive) of the primary domain within
53 * the block structure. */
54 int wy;
55 /** The upper z index (exclusive) of the primary domain within
56 * the block structure. */
57 int wz;
58 /** The total size of the block structure (including images) in
59 * the y direction. */
60 int oy;
61 /** The total size of the block structure (including images) in
62 * the z direction. */
63 int oz;
64 /** The total number of blocks. */
65 int oxyz;
66 /** This array holds the numerical IDs of each particle in each
67 * computational box. */
68 int **id;
69 /** A two dimensional array holding particle positions. For the
70 * derived container_poly class, this also holds particle
71 * radii. */
72 double **p;
73 /** This array holds the number of particles within each
74 * computational box of the container. */
75 int *co;
76 /** This array holds the maximum amount of particle memory for
77 * each computational box of the container. If the number of
78 * particles in a particular box ever approaches this limit,
79 * more is allocated using the add_particle_memory() function.
81 int *mem;
82 /** An array holding information about periodic image
83 * construction at a given location. */
84 char *img;
85 /** The initial amount of memory to allocate for particles
86 * for each block. */
87 const int init_mem;
88 /** The amount of memory in the array structure for each
89 * particle. This is set to 3 when the basic class is
90 * initialized, so that the array holds (x,y,z) positions. If
91 * the container class is initialized as part of the derived
92 * class container_poly, then this is set to 4, to also hold
93 * the particle radii. */
94 const int ps;
95 container_periodic_base(double bx_,double bxy_,double by_,double bxz_,double byz_,double bz_,
96 int nx_,int ny_,int nz_,int init_mem_,int ps);
97 ~container_periodic_base();
98 /** Prints all particles in the container, including those that
99 * have been constructed in image blocks. */
100 inline void print_all_particles() {
101 int ijk,q;
102 for(ijk=0;ijk<oxyz;ijk++) for(q=0;q<co[ijk];q++)
103 printf("%d %g %g %g\n",id[ijk][q],p[ijk][ps*q],p[ijk][ps*q+1],p[ijk][ps*q+2]);
105 void region_count();
106 /** Initializes the Voronoi cell prior to a compute_cell
107 * operation for a specific particle being carried out by a
108 * voro_compute class. The cell is initialized to be the
109 * pre-computed unit Voronoi cell based on planes formed by
110 * periodic images of the particle.
111 * \param[in,out] c a reference to a voronoicell object.
112 * \param[in] ijk the block that the particle is within.
113 * \param[in] q the index of the particle within its block.
114 * \param[in] (ci,cj,ck) the coordinates of the block in the
115 * container coordinate system.
116 * \param[out] (i,j,k) the coordinates of the test block
117 * relative to the voro_compute
118 * coordinate system.
119 * \param[out] (x,y,z) the position of the particle.
120 * \param[out] disp a block displacement used internally by the
121 * compute_cell routine.
122 * \return False if the plane cuts applied by walls completely
123 * removed the cell, true otherwise. */
124 template<class v_cell>
125 inline bool initialize_voronoicell(v_cell &c,int ijk,int q,int ci,int cj,int ck,int &i,int &j,int &k,double &x,double &y,double &z,int &disp) {
126 c=unit_voro;
127 double *pp=p[ijk]+ps*q;
128 x=*(pp++);y=*(pp++);z=*pp;
129 i=nx;j=ey;k=ez;
130 return true;
132 /** Initializes parameters for a find_voronoi_cell call within
133 * the voro_compute template.
134 * \param[in] (ci,cj,ck) the coordinates of the test block in
135 * the container coordinate system.
136 * \param[in] ijk the index of the test block
137 * \param[out] (i,j,k) the coordinates of the test block
138 * relative to the voro_compute
139 * coordinate system.
140 * \param[out] disp a block displacement used internally by the
141 * find_voronoi_cell routine (but not needed
142 * in this instance.) */
143 inline void initialize_search(int ci,int cj,int ck,int ijk,int &i,int &j,int &k,int &disp) {
144 i=nx;j=ey;k=ez;
146 /** Returns the position of a particle currently being computed
147 * relative to the computational block that it is within. It is
148 * used to select the optimal worklist entry to use.
149 * \param[in] (x,y,z) the position of the particle.
150 * \param[in] (ci,cj,ck) the block that the particle is within.
151 * \param[out] (fx,fy,fz) the position relative to the block.
153 inline void frac_pos(double x,double y,double z,double ci,double cj,double ck,double &fx,double &fy,double &fz) {
154 fx=x-boxx*ci;
155 fy=y-boxy*(cj-ey);
156 fz=z-boxz*(ck-ez);
158 /** Calculates the index of block in the container structure
159 * corresponding to given coordinates.
160 * \param[in] (ci,cj,ck) the coordinates of the original block
161 * in the current computation, relative
162 * to the container coordinate system.
163 * \param[in] (ei,ej,ek) the displacement of the current block
164 * from the original block.
165 * \param[in,out] (qx,qy,qz) the periodic displacement that
166 * must be added to the particles
167 * within the computed block.
168 * \param[in] disp a block displacement used internally by the
169 * find_voronoi_cell and compute_cell routines
170 * (but not needed in this instance.)
171 * \return The block index. */
172 inline int region_index(int ci,int cj,int ck,int ei,int ej,int ek,double &qx,double &qy,double &qz,int &disp) {
173 int qi=ci+(ei-nx),qj=cj+(ej-ey),qk=ck+(ek-ez);
174 int iv(step_div(qi,nx));if(iv!=0) {qx=iv*bx;qi-=nx*iv;} else qx=0;
175 create_periodic_image(qi,qj,qk);
176 return qi+nx*(qj+oy*qk);
178 void create_all_images();
179 void check_compartmentalized();
180 protected:
181 void add_particle_memory(int i);
182 void put_locate_block(int &ijk,double &x,double &y,double &z);
183 void put_locate_block(int &ijk,double &x,double &y,double &z,int &ai,int &aj,int &ak);
184 /** Creates particles within an image block by copying them
185 * from the primary domain and shifting them. If the given
186 * block is aligned with the primary domain in the z-direction,
187 * the routine calls the simpler create_side_image routine
188 * where the image block may comprise of particles from up to
189 * two primary blocks. Otherwise is calls the more complex
190 * create_vertical_image where the image block may comprise of
191 * particles from up to four primary blocks.
192 * \param[in] (di,dj,dk) the coordinates of the image block to
193 * create. */
194 inline void create_periodic_image(int di,int dj,int dk) {
195 if(di<0||di>=nx||dj<0||dj>=oy||dk<0||dk>=oz)
196 voro_fatal_error("Constructing periodic image for nonexistent point",VOROPP_INTERNAL_ERROR);
197 if(dk>=ez&&dk<wz) {
198 if(dj<ey||dj>=wy) create_side_image(di,dj,dk);
199 } else create_vertical_image(di,dj,dk);
201 void create_side_image(int di,int dj,int dk);
202 void create_vertical_image(int di,int dj,int dk);
203 void put_image(int reg,int fijk,int l,double dx,double dy,double dz);
204 inline void remap(int &ai,int &aj,int &ak,int &ci,int &cj,int &ck,double &x,double &y,double &z,int &ijk);
207 /** \brief Extension of the container_periodic_base class for computing regular
208 * Voronoi tessellations.
210 * This class is an extension of the container_periodic_base that has routines
211 * specifically for computing the regular Voronoi tessellation with no
212 * dependence on particle radii. */
213 class container_periodic : public container_periodic_base, public radius_mono {
214 public:
215 container_periodic(double bx_,double bxy_,double by_,double bxz_,double byz_,double bz_,
216 int nx_,int ny_,int nz_,int init_mem_);
217 void clear();
218 void put(int n,double x,double y,double z);
219 void put(int n,double x,double y,double z,int &ai,int &aj,int &ak);
220 void put(particle_order &vo,int n,double x,double y,double z);
221 void import(FILE *fp=stdin);
222 void import(particle_order &vo,FILE *fp=stdin);
223 /** Imports a list of particles from an open file stream into
224 * the container. Entries of four numbers (Particle ID, x
225 * position, y position, z position) are searched for. If the
226 * file cannot be successfully read, then the routine causes a
227 * fatal error.
228 * \param[in] filename the name of the file to open and read
229 * from. */
230 inline void import(const char* filename) {
231 FILE *fp=safe_fopen(filename,"r");
232 import(fp);
233 fclose(fp);
235 /** Imports a list of particles from an open file stream into
236 * the container. Entries of four numbers (Particle ID, x
237 * position, y position, z position) are searched for. In
238 * addition, the order in which particles are read is saved
239 * into an ordering class. If the file cannot be successfully
240 * read, then the routine causes a fatal error.
241 * \param[in,out] vo the ordering class to use.
242 * \param[in] filename the name of the file to open and read
243 * from. */
244 inline void import(particle_order &vo,const char* filename) {
245 FILE *fp=safe_fopen(filename,"r");
246 import(vo,fp);
247 fclose(fp);
249 void compute_all_cells();
250 double sum_cell_volumes();
251 /** Dumps particle IDs and positions to a file.
252 * \param[in] vl the loop class to use.
253 * \param[in] fp a file handle to write to. */
254 template<class c_loop>
255 void draw_particles(c_loop &vl,FILE *fp) {
256 double *pp;
257 if(vl.start()) do {
258 pp=p[vl.ijk]+3*vl.q;
259 fprintf(fp,"%d %g %g %g\n",id[vl.ijk][vl.q],*pp,pp[1],pp[2]);
260 } while(vl.inc());
262 /** Dumps all of the particle IDs and positions to a file.
263 * \param[in] fp a file handle to write to. */
264 inline void draw_particles(FILE *fp=stdout) {
265 c_loop_all_periodic vl(*this);
266 draw_particles(vl,fp);
268 /** Dumps all of the particle IDs and positions to a file.
269 * \param[in] filename the name of the file to write to. */
270 inline void draw_particles(const char *filename) {
271 FILE *fp=safe_fopen(filename,"w");
272 draw_particles(fp);
273 fclose(fp);
275 /** Dumps particle positions in POV-Ray format.
276 * \param[in] vl the loop class to use.
277 * \param[in] fp a file handle to write to. */
278 template<class c_loop>
279 void draw_particles_pov(c_loop &vl,FILE *fp) {
280 double *pp;
281 if(vl.start()) do {
282 pp=p[vl.ijk]+3*vl.q;
283 fprintf(fp,"// id %d\nsphere{<%g,%g,%g>,s}\n",
284 id[vl.ijk][vl.q],*pp,pp[1],pp[2]);
285 } while(vl.inc());
287 /** Dumps all particle positions in POV-Ray format.
288 * \param[in] fp a file handle to write to. */
289 inline void draw_particles_pov(FILE *fp=stdout) {
290 c_loop_all_periodic vl(*this);
291 draw_particles_pov(vl,fp);
293 /** Dumps all particle positions in POV-Ray format.
294 * \param[in] filename the name of the file to write to. */
295 inline void draw_particles_pov(const char *filename) {
296 FILE *fp=safe_fopen(filename,"w");
297 draw_particles_pov(fp);
298 fclose(fp);
300 /** Computes Voronoi cells and saves the output in gnuplot
301 * format.
302 * \param[in] vl the loop class to use.
303 * \param[in] fp a file handle to write to. */
304 template<class c_loop>
305 void draw_cells_gnuplot(c_loop &vl,FILE *fp) {
306 voronoicell c(*this);double *pp;
307 if(vl.start()) do if(compute_cell(c,vl)) {
308 pp=p[vl.ijk]+ps*vl.q;
309 c.draw_gnuplot(*pp,pp[1],pp[2],fp);
310 } while(vl.inc());
312 /** Computes all Voronoi cells and saves the output in gnuplot
313 * format.
314 * \param[in] fp a file handle to write to. */
315 inline void draw_cells_gnuplot(FILE *fp=stdout) {
316 c_loop_all_periodic vl(*this);
317 draw_cells_gnuplot(vl,fp);
319 /** Compute all Voronoi cells and saves the output in gnuplot
320 * format.
321 * \param[in] filename the name of the file to write to. */
322 inline void draw_cells_gnuplot(const char *filename) {
323 FILE *fp=safe_fopen(filename,"w");
324 draw_cells_gnuplot(fp);
325 fclose(fp);
327 /** Computes Voronoi cells and saves the output in POV-Ray
328 * format.
329 * \param[in] vl the loop class to use.
330 * \param[in] fp a file handle to write to. */
331 template<class c_loop>
332 void draw_cells_pov(c_loop &vl,FILE *fp) {
333 voronoicell c(*this);double *pp;
334 if(vl.start()) do if(compute_cell(c,vl)) {
335 fprintf(fp,"// cell %d\n",id[vl.ijk][vl.q]);
336 pp=p[vl.ijk]+ps*vl.q;
337 c.draw_pov(*pp,pp[1],pp[2],fp);
338 } while(vl.inc());
340 /** Computes all Voronoi cells and saves the output in POV-Ray
341 * format.
342 * \param[in] fp a file handle to write to. */
343 inline void draw_cells_pov(FILE *fp=stdout) {
344 c_loop_all_periodic vl(*this);
345 draw_cells_pov(vl,fp);
347 /** Computes all Voronoi cells and saves the output in POV-Ray
348 * format.
349 * \param[in] filename the name of the file to write to. */
350 inline void draw_cells_pov(const char *filename) {
351 FILE *fp=safe_fopen(filename,"w");
352 draw_cells_pov(fp);
353 fclose(fp);
355 /** Computes the Voronoi cells and saves customized information
356 * about them.
357 * \param[in] vl the loop class to use.
358 * \param[in] format the custom output string to use.
359 * \param[in] fp a file handle to write to. */
360 template<class c_loop>
361 void print_custom(c_loop &vl,const char *format,FILE *fp) {
362 int ijk,q;double *pp;
363 if(contains_neighbor(format)) {
364 voronoicell_neighbor c(*this);
365 if(vl.start()) do if(compute_cell(c,vl)) {
366 ijk=vl.ijk;q=vl.q;pp=p[ijk]+ps*q;
367 c.output_custom(format,id[ijk][q],*pp,pp[1],pp[2],default_radius,fp);
368 } while(vl.inc());
369 } else {
370 voronoicell c(*this);
371 if(vl.start()) do if(compute_cell(c,vl)) {
372 ijk=vl.ijk;q=vl.q;pp=p[ijk]+ps*q;
373 c.output_custom(format,id[ijk][q],*pp,pp[1],pp[2],default_radius,fp);
374 } while(vl.inc());
377 void print_custom(const char *format,FILE *fp=stdout);
378 void print_custom(const char *format,const char *filename);
379 bool find_voronoi_cell(double x,double y,double z,double &rx,double &ry,double &rz,int &pid);
380 /** Computes the Voronoi cell for a particle currently being
381 * referenced by a loop class.
382 * \param[out] c a Voronoi cell class in which to store the
383 * computed cell.
384 * \param[in] vl the loop class to use.
385 * \return True if the cell was computed. If the cell cannot be
386 * computed because it was removed entirely for some reason,
387 * then the routine returns false. */
388 template<class v_cell,class c_loop>
389 inline bool compute_cell(v_cell &c,c_loop &vl) {
390 return vc.compute_cell(c,vl.ijk,vl.q,vl.i,vl.j,vl.k);
392 /** Computes the Voronoi cell for given particle.
393 * \param[out] c a Voronoi cell class in which to store the
394 * computed cell.
395 * \param[in] ijk the block that the particle is within.
396 * \param[in] q the index of the particle within the block.
397 * \return True if the cell was computed. If the cell cannot be
398 * computed because it was removed entirely for some reason,
399 * then the routine returns false. */
400 template<class v_cell>
401 inline bool compute_cell(v_cell &c,int ijk,int q) {
402 int k(ijk/(nx*oy)),ijkt(ijk-(nx*oy)*k),j(ijkt/nx),i(ijkt-j*nx);
403 return vc.compute_cell(c,ijk,q,i,j,k);
405 /** Computes the Voronoi cell for a ghost particle at a given
406 * location.
407 * \param[out] c a Voronoi cell class in which to store the
408 * computed cell.
409 * \param[in] (x,y,z) the location of the ghost particle.
410 * \return True if the cell was computed. If the cell cannot be
411 * computed, if it is removed entirely by a wall or boundary
412 * condition, then the routine returns false. */
413 template<class v_cell>
414 inline bool compute_ghost_cell(v_cell &c,double x,double y,double z) {
415 int ijk;
416 put_locate_block(ijk,x,y,z);
417 double *pp=p[ijk]+3*co[ijk]++;
418 *(pp++)=x;*(pp++)=y;*(pp++)=z;
419 bool q=compute_cell(c,ijk,co[ijk]-1);
420 co[ijk]--;
421 return q;
423 private:
424 voro_compute<container_periodic> vc;
425 friend class voro_compute<container_periodic>;
428 /** \brief Extension of the container_periodic_base class for computing radical
429 * Voronoi tessellations.
431 * This class is an extension of container_periodic_base that has routines
432 * specifically for computing the radical Voronoi tessellation that depends
433 * on the particle radii. */
434 class container_periodic_poly : public container_periodic_base, public radius_poly {
435 public:
436 container_periodic_poly(double bx_,double bxy_,double by_,double bxz_,double byz_,double bz_,
437 int nx_,int ny_,int nz_,int init_mem_);
438 void clear();
439 void put(int n,double x,double y,double z,double r);
440 void put(int n,double x,double y,double z,double r,int &ai,int &aj,int &ak);
441 void put(particle_order &vo,int n,double x,double y,double z,double r);
442 void import(FILE *fp=stdin);
443 void import(particle_order &vo,FILE *fp=stdin);
444 /** Imports a list of particles from an open file stream into
445 * the container_poly class. Entries of five numbers (Particle
446 * ID, x position, y position, z position, radius) are searched
447 * for. If the file cannot be successfully read, then the
448 * routine causes a fatal error.
449 * \param[in] filename the name of the file to open and read
450 * from. */
451 inline void import(const char* filename) {
452 FILE *fp=safe_fopen(filename,"r");
453 import(fp);
454 fclose(fp);
456 /** Imports a list of particles from an open file stream into
457 * the container_poly class. Entries of five numbers (Particle
458 * ID, x position, y position, z position, radius) are searched
459 * for. In addition, the order in which particles are read is
460 * saved into an ordering class. If the file cannot be
461 * successfully read, then the routine causes a fatal error.
462 * \param[in,out] vo the ordering class to use.
463 * \param[in] filename the name of the file to open and read
464 * from. */
465 inline void import(particle_order &vo,const char* filename) {
466 FILE *fp=safe_fopen(filename,"r");
467 import(vo,fp);
468 fclose(fp);
470 void compute_all_cells();
471 double sum_cell_volumes();
472 /** Dumps particle IDs, positions and radii to a file.
473 * \param[in] vl the loop class to use.
474 * \param[in] fp a file handle to write to. */
475 template<class c_loop>
476 void draw_particles(c_loop &vl,FILE *fp) {
477 double *pp;
478 if(vl.start()) do {
479 pp=p[vl.ijk]+4*vl.q;
480 fprintf(fp,"%d %g %g %g %g\n",id[vl.ijk][vl.q],*pp,pp[1],pp[2],pp[3]);
481 } while(vl.inc());
483 /** Dumps all of the particle IDs, positions and radii to a
484 * file.
485 * \param[in] fp a file handle to write to. */
486 inline void draw_particles(FILE *fp=stdout) {
487 c_loop_all_periodic vl(*this);
488 draw_particles(vl,fp);
490 /** Dumps all of the particle IDs, positions and radii to a
491 * file.
492 * \param[in] filename the name of the file to write to. */
493 inline void draw_particles(const char *filename) {
494 FILE *fp=safe_fopen(filename,"w");
495 draw_particles(fp);
496 fclose(fp);
498 /** Dumps particle positions in POV-Ray format.
499 * \param[in] vl the loop class to use.
500 * \param[in] fp a file handle to write to. */
501 template<class c_loop>
502 void draw_particles_pov(c_loop &vl,FILE *fp) {
503 double *pp;
504 if(vl.start()) do {
505 pp=p[vl.ijk]+4*vl.q;
506 fprintf(fp,"// id %d\nsphere{<%g,%g,%g>,%g}\n",
507 id[vl.ijk][vl.q],*pp,pp[1],pp[2],pp[3]);
508 } while(vl.inc());
510 /** Dumps all the particle positions in POV-Ray format.
511 * \param[in] fp a file handle to write to. */
512 inline void draw_particles_pov(FILE *fp=stdout) {
513 c_loop_all_periodic vl(*this);
514 draw_particles_pov(vl,fp);
516 /** Dumps all the particle positions in POV-Ray format.
517 * \param[in] filename the name of the file to write to. */
518 inline void draw_particles_pov(const char *filename) {
519 FILE *fp(safe_fopen(filename,"w"));
520 draw_particles_pov(fp);
521 fclose(fp);
523 /** Computes Voronoi cells and saves the output in gnuplot
524 * format.
525 * \param[in] vl the loop class to use.
526 * \param[in] fp a file handle to write to. */
527 template<class c_loop>
528 void draw_cells_gnuplot(c_loop &vl,FILE *fp) {
529 voronoicell c(*this);double *pp;
530 if(vl.start()) do if(compute_cell(c,vl)) {
531 pp=p[vl.ijk]+ps*vl.q;
532 c.draw_gnuplot(*pp,pp[1],pp[2],fp);
533 } while(vl.inc());
535 /** Compute all Voronoi cells and saves the output in gnuplot
536 * format.
537 * \param[in] fp a file handle to write to. */
538 inline void draw_cells_gnuplot(FILE *fp=stdout) {
539 c_loop_all_periodic vl(*this);
540 draw_cells_gnuplot(vl,fp);
542 /** Compute all Voronoi cells and saves the output in gnuplot
543 * format.
544 * \param[in] filename the name of the file to write to. */
545 inline void draw_cells_gnuplot(const char *filename) {
546 FILE *fp(safe_fopen(filename,"w"));
547 draw_cells_gnuplot(fp);
548 fclose(fp);
550 /** Computes Voronoi cells and saves the output in POV-Ray
551 * format.
552 * \param[in] vl the loop class to use.
553 * \param[in] fp a file handle to write to. */
554 template<class c_loop>
555 void draw_cells_pov(c_loop &vl,FILE *fp) {
556 voronoicell c(*this);double *pp;
557 if(vl.start()) do if(compute_cell(c,vl)) {
558 fprintf(fp,"// cell %d\n",id[vl.ijk][vl.q]);
559 pp=p[vl.ijk]+ps*vl.q;
560 c.draw_pov(*pp,pp[1],pp[2],fp);
561 } while(vl.inc());
563 /** Computes all Voronoi cells and saves the output in POV-Ray
564 * format.
565 * \param[in] fp a file handle to write to. */
566 inline void draw_cells_pov(FILE *fp=stdout) {
567 c_loop_all_periodic vl(*this);
568 draw_cells_pov(vl,fp);
570 /** Computes all Voronoi cells and saves the output in POV-Ray
571 * format.
572 * \param[in] filename the name of the file to write to. */
573 inline void draw_cells_pov(const char *filename) {
574 FILE *fp(safe_fopen(filename,"w"));
575 draw_cells_pov(fp);
576 fclose(fp);
578 /** Computes the Voronoi cells and saves customized information
579 * about them.
580 * \param[in] vl the loop class to use.
581 * \param[in] format the custom output string to use.
582 * \param[in] fp a file handle to write to. */
583 template<class c_loop>
584 void print_custom(c_loop &vl,const char *format,FILE *fp) {
585 int ijk,q;double *pp;
586 if(contains_neighbor(format)) {
587 voronoicell_neighbor c(*this);
588 if(vl.start()) do if(compute_cell(c,vl)) {
589 ijk=vl.ijk;q=vl.q;pp=p[ijk]+ps*q;
590 c.output_custom(format,id[ijk][q],*pp,pp[1],pp[2],pp[3],fp);
591 } while(vl.inc());
592 } else {
593 voronoicell c(*this);
594 if(vl.start()) do if(compute_cell(c,vl)) {
595 ijk=vl.ijk;q=vl.q;pp=p[ijk]+ps*q;
596 c.output_custom(format,id[ijk][q],*pp,pp[1],pp[2],pp[3],fp);
597 } while(vl.inc());
600 /** Computes the Voronoi cell for a particle currently being
601 * referenced by a loop class.
602 * \param[out] c a Voronoi cell class in which to store the
603 * computed cell.
604 * \param[in] vl the loop class to use.
605 * \return True if the cell was computed. If the cell cannot be
606 * computed because it was removed entirely for some reason,
607 * then the routine returns false. */
608 template<class v_cell,class c_loop>
609 inline bool compute_cell(v_cell &c,c_loop &vl) {
610 return vc.compute_cell(c,vl.ijk,vl.q,vl.i,vl.j,vl.k);
612 /** Computes the Voronoi cell for given particle.
613 * \param[out] c a Voronoi cell class in which to store the
614 * computed cell.
615 * \param[in] ijk the block that the particle is within.
616 * \param[in] q the index of the particle within the block.
617 * \return True if the cell was computed. If the cell cannot be
618 * computed because it was removed entirely for some reason,
619 * then the routine returns false. */
620 template<class v_cell>
621 inline bool compute_cell(v_cell &c,int ijk,int q) {
622 int k(ijk/(nx*oy)),ijkt(ijk-(nx*oy)*k),j(ijkt/nx),i(ijkt-j*nx);
623 return vc.compute_cell(c,ijk,q,i,j,k);
625 /** Computes the Voronoi cell for a ghost particle at a given
626 * location.
627 * \param[out] c a Voronoi cell class in which to store the
628 * computed cell.
629 * \param[in] (x,y,z) the location of the ghost particle.
630 * \param[in] r the radius of the ghost particle.
631 * \return True if the cell was computed. If the cell cannot be
632 * computed, if it is removed entirely by a wall or boundary
633 * condition, then the routine returns false. */
634 template<class v_cell>
635 inline bool compute_ghost_cell(v_cell &c,double x,double y,double z,double r) {
636 int ijk;
637 put_locate_block(ijk,x,y,z);
638 double *pp=p[ijk]+4*co[ijk]++,tm=max_radius;
639 *(pp++)=x;*(pp++)=y;*(pp++)=z;*pp=r;
640 if(r>max_radius) max_radius=r;
641 bool q=compute_cell(c,ijk,co[ijk]-1);
642 co[ijk]--;max_radius=tm;
643 return q;
645 void print_custom(const char *format,FILE *fp=stdout);
646 void print_custom(const char *format,const char *filename);
647 bool find_voronoi_cell(double x,double y,double z,double &rx,double &ry,double &rz,int &pid);
648 private:
649 voro_compute<container_periodic_poly> vc;
650 friend class voro_compute<container_periodic_poly>;
655 #endif