1 // Voro++, a 3D cell-based Voronoi library
3 // Author : Chris H. Rycroft (LBL / UC Berkeley)
4 // Email : chr@alum.mit.edu
5 // Date : August 30th 2011
8 * \brief Header file for the container_base and related classes. */
10 #ifndef VOROPP_CONTAINER_HH
11 #define VOROPP_CONTAINER_HH
21 #include "v_compute.hh"
22 #include "rad_option.hh"
26 /** \brief Pure virtual class from which wall objects are derived.
28 * This is a pure virtual class for a generic wall object. A wall object
29 * can be specified by deriving a new class from this and specifying the
34 /** A pure virtual function for testing whether a point is
35 * inside the wall object. */
36 virtual bool point_inside(double x
,double y
,double z
) = 0;
37 /** A pure virtual function for cutting a cell without
38 * neighbor-tracking with a wall. */
39 virtual bool cut_cell(voronoicell
&c
,double x
,double y
,double z
) = 0;
40 /** A pure virtual function for cutting a cell with
41 * neighbor-tracking enabled with a wall. */
42 virtual bool cut_cell(voronoicell_neighbor
&c
,double x
,double y
,double z
) = 0;
45 /** \brief A class for storing a list of pointers to walls.
47 * This class stores a list of pointers to wall classes. It contains several
48 * simple routines that make use of the wall classes (such as telling whether a
49 * given position is inside all of the walls or not). It can be used by itself,
50 * but also forms part of container_base, for associating walls with this
54 /** An array holding pointers to wall objects. */
56 /** A pointer to the next free position to add a wall pointer.
61 /** Adds a wall to the list.
62 * \param[in] w the wall to add. */
63 inline void add_wall(wall
*w
) {
64 if(wep
==wel
) increase_wall_memory();
67 /** Adds a wall to the list.
68 * \param[in] w a reference to the wall to add. */
69 inline void add_wall(wall
&w
) {add_wall(&w
);}
70 void add_wall(wall_list
&wl
);
71 /** Determines whether a given position is inside all of the
73 * \param[in] (x,y,z) the position to test.
74 * \return True if it is inside, false if it is outside. */
75 inline bool point_inside_walls(double x
,double y
,double z
) {
76 for(wall
**wp
=walls
;wp
<wep
;wp
++) if(!((*wp
)->point_inside(x
,y
,z
))) return false;
79 /** Cuts a Voronoi cell by all of the walls currently on
81 * \param[in] c a reference to the Voronoi cell class.
82 * \param[in] (x,y,z) the position of the cell.
83 * \return True if the cell still exists, false if the cell is
85 template<class c_class
>
86 bool apply_walls(c_class
&c
,double x
,double y
,double z
) {
87 for(wall
**wp
=walls
;wp
<wep
;wp
++) if(!((*wp
)->cut_cell(c
,x
,y
,z
))) return false;
92 void increase_wall_memory();
93 /** A pointer to the limit of the walls array, used to
94 * determine when array is full. */
96 /** The current amount of memory allocated for walls. */
97 int current_wall_size
;
100 /** \brief Class for representing a particle system in a three-dimensional
103 * This class represents a system of particles in a three-dimensional
104 * rectangular box. Any combination of non-periodic and periodic coordinates
105 * can be used in the three coordinate directions. The class is not intended
106 * for direct use, but instead forms the base of the container and
107 * container_poly classes that add specialized routines for computing the
108 * regular and radical Voronoi tessellations respectively. It contains routines
109 * that are commonly between these two classes, such as those for drawing the
110 * domain, and placing particles within the internal data structure.
112 * The class is derived from the wall_list class, which encapsulates routines
113 * for associating walls with the container, and the voro_base class, which
114 * encapsulates routines about the underlying computational grid. */
115 class container_base
: public voro_base
, public wall_list
{
117 /** The minimum x coordinate of the container. */
119 /** The maximum x coordinate of the container. */
121 /** The minimum y coordinate of the container. */
123 /** The maximum y coordinate of the container. */
125 /** The minimum z coordinate of the container. */
127 /** The maximum z coordinate of the container. */
129 /** The maximum length squared that could be encountered in the
130 * Voronoi cell calculation. */
131 const double max_len_sq
;
132 /** A boolean value that determines if the x coordinate in
133 * periodic or not. */
134 const bool xperiodic
;
135 /** A boolean value that determines if the y coordinate in
136 * periodic or not. */
137 const bool yperiodic
;
138 /** A boolean value that determines if the z coordinate in
139 * periodic or not. */
140 const bool zperiodic
;
141 /** This array holds the numerical IDs of each particle in each
142 * computational box. */
144 /** A two dimensional array holding particle positions. For the
145 * derived container_poly class, this also holds particle
148 /** This array holds the number of particles within each
149 * computational box of the container. */
151 /** This array holds the maximum amount of particle memory for
152 * each computational box of the container. If the number of
153 * particles in a particular box ever approaches this limit,
154 * more is allocated using the add_particle_memory() function.
157 /** The amount of memory in the array structure for each
158 * particle. This is set to 3 when the basic class is
159 * initialized, so that the array holds (x,y,z) positions. If
160 * the container class is initialized as part of the derived
161 * class container_poly, then this is set to 4, to also hold
162 * the particle radii. */
164 container_base(double ax_
,double bx_
,double ay_
,double by_
,double az_
,double bz_
,
165 int nx_
,int ny_
,int nz_
,bool xperiodic_
,bool yperiodic_
,bool zperiodic_
,
166 int init_mem
,int ps_
);
168 bool point_inside(double x
,double y
,double z
);
170 /** Initializes the Voronoi cell prior to a compute_cell
171 * operation for a specific particle being carried out by a
172 * voro_compute class. The cell is initialized to fill the
173 * entire container. For non-periodic coordinates, this is set
174 * by the position of the walls. For periodic coordinates, the
175 * space is equally divided in either direction from the
176 * particle's initial position. Plane cuts made by any walls
177 * that have been added are then applied to the cell.
178 * \param[in,out] c a reference to a voronoicell object.
179 * \param[in] ijk the block that the particle is within.
180 * \param[in] q the index of the particle within its block.
181 * \param[in] (ci,cj,ck) the coordinates of the block in the
182 * container coordinate system.
183 * \param[out] (i,j,k) the coordinates of the test block
184 * relative to the voro_compute
186 * \param[out] (x,y,z) the position of the particle.
187 * \param[out] disp a block displacement used internally by the
188 * compute_cell routine.
189 * \return False if the plane cuts applied by walls completely
190 * removed the cell, true otherwise. */
191 template<class v_cell
>
192 inline bool initialize_voronoicell(v_cell
&c
,int ijk
,int q
,int ci
,int cj
,int ck
,
193 int &i
,int &j
,int &k
,double &x
,double &y
,double &z
,int &disp
) {
194 double x1
,x2
,y1
,y2
,z1
,z2
,*pp
=p
[ijk
]+ps
*q
;
195 x
=*(pp
++);y
=*(pp
++);z
=*pp
;
196 if(xperiodic
) {x1
=-(x2
=0.5*(bx
-ax
));i
=nx
;} else {x1
=ax
-x
;x2
=bx
-x
;i
=ci
;}
197 if(yperiodic
) {y1
=-(y2
=0.5*(by
-ay
));j
=ny
;} else {y1
=ay
-y
;y2
=by
-y
;j
=cj
;}
198 if(zperiodic
) {z1
=-(z2
=0.5*(bz
-az
));k
=nz
;} else {z1
=az
-z
;z2
=bz
-z
;k
=ck
;}
199 c
.init(x1
,x2
,y1
,y2
,z1
,z2
);
200 if(!apply_walls(c
,x
,y
,z
)) return false;
201 disp
=ijk
-i
-nx
*(j
+ny
*k
);
204 /** Initializes parameters for a find_voronoi_cell call within
205 * the voro_compute template.
206 * \param[in] (ci,cj,ck) the coordinates of the test block in
207 * the container coordinate system.
208 * \param[in] ijk the index of the test block
209 * \param[out] (i,j,k) the coordinates of the test block
210 * relative to the voro_compute
212 * \param[out] disp a block displacement used internally by the
213 * find_voronoi_cell routine. */
214 inline void initialize_search(int ci
,int cj
,int ck
,int ijk
,int &i
,int &j
,int &k
,int &disp
) {
218 disp
=ijk
-i
-nx
*(j
+ny
*k
);
220 /** Returns the position of a particle currently being computed
221 * relative to the computational block that it is within. It is
222 * used to select the optimal worklist entry to use.
223 * \param[in] (x,y,z) the position of the particle.
224 * \param[in] (ci,cj,ck) the block that the particle is within.
225 * \param[out] (fx,fy,fz) the position relative to the block.
227 inline void frac_pos(double x
,double y
,double z
,double ci
,double cj
,double ck
,
228 double &fx
,double &fy
,double &fz
) {
233 /** Calculates the index of block in the container structure
234 * corresponding to given coordinates.
235 * \param[in] (ci,cj,ck) the coordinates of the original block
236 * in the current computation, relative
237 * to the container coordinate system.
238 * \param[in] (ei,ej,ek) the displacement of the current block
239 * from the original block.
240 * \param[in,out] (qx,qy,qz) the periodic displacement that
241 * must be added to the particles
242 * within the computed block.
243 * \param[in] disp a block displacement used internally by the
244 * find_voronoi_cell and compute_cell routines.
245 * \return The block index. */
246 inline int region_index(int ci
,int cj
,int ck
,int ei
,int ej
,int ek
,double &qx
,double &qy
,double &qz
,int &disp
) {
247 if(xperiodic
) {if(ci
+ei
<nx
) {ei
+=nx
;qx
=-(bx
-ax
);} else if(ci
+ei
>=(nx
<<1)) {ei
-=nx
;qx
=bx
-ax
;} else qx
=0;}
248 if(yperiodic
) {if(cj
+ej
<ny
) {ej
+=ny
;qy
=-(by
-ay
);} else if(cj
+ej
>=(ny
<<1)) {ej
-=ny
;qy
=by
-ay
;} else qy
=0;}
249 if(zperiodic
) {if(ck
+ek
<nz
) {ek
+=nz
;qz
=-(bz
-az
);} else if(ck
+ek
>=(nz
<<1)) {ek
-=nz
;qz
=bz
-az
;} else qz
=0;}
250 return disp
+ei
+nx
*(ej
+ny
*ek
);
252 void draw_domain_gnuplot(FILE *fp
=stdout
);
253 /** Draws an outline of the domain in Gnuplot format.
254 * \param[in] filename the filename to write to. */
255 inline void draw_domain_gnuplot(const char* filename
) {
256 FILE *fp
=safe_fopen(filename
,"w");
257 draw_domain_gnuplot(fp
);
260 void draw_domain_pov(FILE *fp
=stdout
);
261 /** Draws an outline of the domain in Gnuplot format.
262 * \param[in] filename the filename to write to. */
263 inline void draw_domain_pov(const char* filename
) {
264 FILE *fp
=safe_fopen(filename
,"w");
268 /** Sums up the total number of stored particles.
269 * \return The number of particles. */
270 inline int total_particles() {
272 for(int *cop
=co
+1;cop
<co
+nxyz
;cop
++) tp
+=*cop
;
276 void add_particle_memory(int i
);
277 bool put_locate_block(int &ijk
,double &x
,double &y
,double &z
);
278 inline bool put_remap(int &ijk
,double &x
,double &y
,double &z
);
279 inline bool remap(int &ai
,int &aj
,int &ak
,int &ci
,int &cj
,int &ck
,double &x
,double &y
,double &z
,int &ijk
);
282 /** \brief Extension of the container_base class for computing regular Voronoi
285 * This class is an extension of the container_base class that has routines
286 * specifically for computing the regular Voronoi tessellation with no
287 * dependence on particle radii. */
288 class container
: public container_base
, public radius_mono
{
290 container(double ax_
,double bx_
,double ay_
,double by_
,double az_
,double bz_
,
291 int nx_
,int ny_
,int nz_
,bool xperiodic_
,bool yperiodic_
,bool zperiodic_
,int init_mem
);
293 void put(int n
,double x
,double y
,double z
);
294 void put(particle_order
&vo
,int n
,double x
,double y
,double z
);
295 void import(FILE *fp
=stdin
);
296 void import(particle_order
&vo
,FILE *fp
=stdin
);
297 /** Imports a list of particles from an open file stream into
298 * the container. Entries of four numbers (Particle ID, x
299 * position, y position, z position) are searched for. If the
300 * file cannot be successfully read, then the routine causes a
302 * \param[in] filename the name of the file to open and read
304 inline void import(const char* filename
) {
305 FILE *fp
=safe_fopen(filename
,"r");
309 /** Imports a list of particles from an open file stream into
310 * the container. Entries of four numbers (Particle ID, x
311 * position, y position, z position) are searched for. In
312 * addition, the order in which particles are read is saved
313 * into an ordering class. If the file cannot be successfully
314 * read, then the routine causes a fatal error.
315 * \param[in,out] vo the ordering class to use.
316 * \param[in] filename the name of the file to open and read
318 inline void import(particle_order
&vo
,const char* filename
) {
319 FILE *fp
=safe_fopen(filename
,"r");
323 void compute_all_cells();
324 double sum_cell_volumes();
325 /** Dumps particle IDs and positions to a file.
326 * \param[in] vl the loop class to use.
327 * \param[in] fp a file handle to write to. */
328 template<class c_loop
>
329 void draw_particles(c_loop
&vl
,FILE *fp
) {
333 fprintf(fp
,"%d %g %g %g\n",id
[vl
.ijk
][vl
.q
],*pp
,pp
[1],pp
[2]);
336 /** Dumps all of the particle IDs and positions to a file.
337 * \param[in] fp a file handle to write to. */
338 inline void draw_particles(FILE *fp
=stdout
) {
339 c_loop_all
vl(*this);
340 draw_particles(vl
,fp
);
342 /** Dumps all of the particle IDs and positions to a file.
343 * \param[in] filename the name of the file to write to. */
344 inline void draw_particles(const char *filename
) {
345 FILE *fp
=safe_fopen(filename
,"w");
349 /** Dumps particle positions in POV-Ray format.
350 * \param[in] vl the loop class to use.
351 * \param[in] fp a file handle to write to. */
352 template<class c_loop
>
353 void draw_particles_pov(c_loop
&vl
,FILE *fp
) {
357 fprintf(fp
,"// id %d\nsphere{<%g,%g,%g>,s}\n",
358 id
[vl
.ijk
][vl
.q
],*pp
,pp
[1],pp
[2]);
361 /** Dumps all particle positions in POV-Ray format.
362 * \param[in] fp a file handle to write to. */
363 inline void draw_particles_pov(FILE *fp
=stdout
) {
364 c_loop_all
vl(*this);
365 draw_particles_pov(vl
,fp
);
367 /** Dumps all particle positions in POV-Ray format.
368 * \param[in] filename the name of the file to write to. */
369 inline void draw_particles_pov(const char *filename
) {
370 FILE *fp
=safe_fopen(filename
,"w");
371 draw_particles_pov(fp
);
374 /** Computes Voronoi cells and saves the output in gnuplot
376 * \param[in] vl the loop class to use.
377 * \param[in] fp a file handle to write to. */
378 template<class c_loop
>
379 void draw_cells_gnuplot(c_loop
&vl
,FILE *fp
) {
380 voronoicell
c(*this);double *pp
;
381 if(vl
.start()) do if(compute_cell(c
,vl
)) {
382 pp
=p
[vl
.ijk
]+ps
*vl
.q
;
383 c
.draw_gnuplot(*pp
,pp
[1],pp
[2],fp
);
386 /** Computes all Voronoi cells and saves the output in gnuplot
388 * \param[in] fp a file handle to write to. */
389 inline void draw_cells_gnuplot(FILE *fp
=stdout
) {
390 c_loop_all
vl(*this);
391 draw_cells_gnuplot(vl
,fp
);
393 /** Computes all Voronoi cells and saves the output in gnuplot
395 * \param[in] filename the name of the file to write to. */
396 inline void draw_cells_gnuplot(const char *filename
) {
397 FILE *fp
=safe_fopen(filename
,"w");
398 draw_cells_gnuplot(fp
);
401 /** Computes Voronoi cells and saves the output in POV-Ray
403 * \param[in] vl the loop class to use.
404 * \param[in] fp a file handle to write to. */
405 template<class c_loop
>
406 void draw_cells_pov(c_loop
&vl
,FILE *fp
) {
407 voronoicell
c(*this);double *pp
;
408 if(vl
.start()) do if(compute_cell(c
,vl
)) {
409 fprintf(fp
,"// cell %d\n",id
[vl
.ijk
][vl
.q
]);
410 pp
=p
[vl
.ijk
]+ps
*vl
.q
;
411 c
.draw_pov(*pp
,pp
[1],pp
[2],fp
);
414 /** Computes all Voronoi cells and saves the output in POV-Ray
416 * \param[in] fp a file handle to write to. */
417 inline void draw_cells_pov(FILE *fp
=stdout
) {
418 c_loop_all
vl(*this);
419 draw_cells_pov(vl
,fp
);
421 /** Computes all Voronoi cells and saves the output in POV-Ray
423 * \param[in] filename the name of the file to write to. */
424 inline void draw_cells_pov(const char *filename
) {
425 FILE *fp
=safe_fopen(filename
,"w");
429 /** Computes the Voronoi cells and saves customized information
431 * \param[in] vl the loop class to use.
432 * \param[in] format the custom output string to use.
433 * \param[in] fp a file handle to write to. */
434 template<class c_loop
>
435 void print_custom(c_loop
&vl
,const char *format
,FILE *fp
) {
436 int ijk
,q
;double *pp
;
437 if(contains_neighbor(format
)) {
438 voronoicell_neighbor
c(*this);
439 if(vl
.start()) do if(compute_cell(c
,vl
)) {
440 ijk
=vl
.ijk
;q
=vl
.q
;pp
=p
[ijk
]+ps
*q
;
441 c
.output_custom(format
,id
[ijk
][q
],*pp
,pp
[1],pp
[2],default_radius
,fp
);
444 voronoicell
c(*this);
445 if(vl
.start()) do if(compute_cell(c
,vl
)) {
446 ijk
=vl
.ijk
;q
=vl
.q
;pp
=p
[ijk
]+ps
*q
;
447 c
.output_custom(format
,id
[ijk
][q
],*pp
,pp
[1],pp
[2],default_radius
,fp
);
451 void print_custom(const char *format
,FILE *fp
=stdout
);
452 void print_custom(const char *format
,const char *filename
);
453 bool find_voronoi_cell(double x
,double y
,double z
,double &rx
,double &ry
,double &rz
,int &pid
);
454 /** Computes the Voronoi cell for a particle currently being
455 * referenced by a loop class.
456 * \param[out] c a Voronoi cell class in which to store the
458 * \param[in] vl the loop class to use.
459 * \return True if the cell was computed. If the cell cannot be
460 * computed, if it is removed entirely by a wall or boundary
461 * condition, then the routine returns false. */
462 template<class v_cell
,class c_loop
>
463 inline bool compute_cell(v_cell
&c
,c_loop
&vl
) {
464 return vc
.compute_cell(c
,vl
.ijk
,vl
.q
,vl
.i
,vl
.j
,vl
.k
);
466 /** Computes the Voronoi cell for given particle.
467 * \param[out] c a Voronoi cell class in which to store the
469 * \param[in] ijk the block that the particle is within.
470 * \param[in] q the index of the particle within the block.
471 * \return True if the cell was computed. If the cell cannot be
472 * computed, if it is removed entirely by a wall or boundary
473 * condition, then the routine returns false. */
474 template<class v_cell
>
475 inline bool compute_cell(v_cell
&c
,int ijk
,int q
) {
476 int k
=ijk
/nxy
,ijkt
=ijk
-nxy
*k
,j
=ijkt
/nx
,i
=ijkt
-j
*nx
;
477 return vc
.compute_cell(c
,ijk
,q
,i
,j
,k
);
479 /** Computes the Voronoi cell for a ghost particle at a given
481 * \param[out] c a Voronoi cell class in which to store the
483 * \param[in] (x,y,z) the location of the ghost particle.
484 * \return True if the cell was computed. If the cell cannot be
485 * computed, if it is removed entirely by a wall or boundary
486 * condition, then the routine returns false. */
487 template<class v_cell
>
488 inline bool compute_ghost_cell(v_cell
&c
,double x
,double y
,double z
) {
490 if(put_locate_block(ijk
,x
,y
,z
)) {
491 double *pp
=p
[ijk
]+3*co
[ijk
]++;
492 *(pp
++)=x
;*(pp
++)=y
;*pp
=z
;
493 bool q
=compute_cell(c
,ijk
,co
[ijk
]-1);
500 voro_compute
<container
> vc
;
501 friend class voro_compute
<container
>;
504 /** \brief Extension of the container_base class for computing radical Voronoi
507 * This class is an extension of container_base class that has routines
508 * specifically for computing the radical Voronoi tessellation that depends on
509 * the particle radii. */
510 class container_poly
: public container_base
, public radius_poly
{
512 container_poly(double ax_
,double bx_
,double ay_
,double by_
,double az_
,double bz_
,
513 int nx_
,int ny_
,int nz_
,bool xperiodic_
,bool yperiodic_
,bool zperiodic_
,int init_mem
);
515 void put(int n
,double x
,double y
,double z
,double r
);
516 void put(particle_order
&vo
,int n
,double x
,double y
,double z
,double r
);
517 void import(FILE *fp
=stdin
);
518 void import(particle_order
&vo
,FILE *fp
=stdin
);
519 /** Imports a list of particles from an open file stream into
520 * the container_poly class. Entries of five numbers (Particle
521 * ID, x position, y position, z position, radius) are searched
522 * for. If the file cannot be successfully read, then the
523 * routine causes a fatal error.
524 * \param[in] filename the name of the file to open and read
526 inline void import(const char* filename
) {
527 FILE *fp
=safe_fopen(filename
,"r");
531 /** Imports a list of particles from an open file stream into
532 * the container_poly class. Entries of five numbers (Particle
533 * ID, x position, y position, z position, radius) are searched
534 * for. In addition, the order in which particles are read is
535 * saved into an ordering class. If the file cannot be
536 * successfully read, then the routine causes a fatal error.
537 * \param[in,out] vo the ordering class to use.
538 * \param[in] filename the name of the file to open and read
540 inline void import(particle_order
&vo
,const char* filename
) {
541 FILE *fp
=safe_fopen(filename
,"r");
545 void compute_all_cells();
546 double sum_cell_volumes();
547 /** Dumps particle IDs, positions and radii to a file.
548 * \param[in] vl the loop class to use.
549 * \param[in] fp a file handle to write to. */
550 template<class c_loop
>
551 void draw_particles(c_loop
&vl
,FILE *fp
) {
555 fprintf(fp
,"%d %g %g %g %g\n",id
[vl
.ijk
][vl
.q
],*pp
,pp
[1],pp
[2],pp
[3]);
558 /** Dumps all of the particle IDs, positions and radii to a
560 * \param[in] fp a file handle to write to. */
561 inline void draw_particles(FILE *fp
=stdout
) {
562 c_loop_all
vl(*this);
563 draw_particles(vl
,fp
);
565 /** Dumps all of the particle IDs, positions and radii to a
567 * \param[in] filename the name of the file to write to. */
568 inline void draw_particles(const char *filename
) {
569 FILE *fp
=safe_fopen(filename
,"w");
573 /** Dumps particle positions in POV-Ray format.
574 * \param[in] vl the loop class to use.
575 * \param[in] fp a file handle to write to. */
576 template<class c_loop
>
577 void draw_particles_pov(c_loop
&vl
,FILE *fp
) {
581 fprintf(fp
,"// id %d\nsphere{<%g,%g,%g>,%g}\n",
582 id
[vl
.ijk
][vl
.q
],*pp
,pp
[1],pp
[2],pp
[3]);
585 /** Dumps all the particle positions in POV-Ray format.
586 * \param[in] fp a file handle to write to. */
587 inline void draw_particles_pov(FILE *fp
=stdout
) {
588 c_loop_all
vl(*this);
589 draw_particles_pov(vl
,fp
);
591 /** Dumps all the particle positions in POV-Ray format.
592 * \param[in] filename the name of the file to write to. */
593 inline void draw_particles_pov(const char *filename
) {
594 FILE *fp
=safe_fopen(filename
,"w");
595 draw_particles_pov(fp
);
598 /** Computes Voronoi cells and saves the output in gnuplot
600 * \param[in] vl the loop class to use.
601 * \param[in] fp a file handle to write to. */
602 template<class c_loop
>
603 void draw_cells_gnuplot(c_loop
&vl
,FILE *fp
) {
604 voronoicell c
;double *pp
;
605 if(vl
.start()) do if(compute_cell(c
,vl
)) {
606 pp
=p
[vl
.ijk
]+ps
*vl
.q
;
607 c
.draw_gnuplot(*pp
,pp
[1],pp
[2],fp
);
610 /** Compute all Voronoi cells and saves the output in gnuplot
612 * \param[in] fp a file handle to write to. */
613 inline void draw_cells_gnuplot(FILE *fp
=stdout
) {
614 c_loop_all
vl(*this);
615 draw_cells_gnuplot(vl
,fp
);
617 /** Compute all Voronoi cells and saves the output in gnuplot
619 * \param[in] filename the name of the file to write to. */
620 inline void draw_cells_gnuplot(const char *filename
) {
621 FILE *fp
=safe_fopen(filename
,"w");
622 draw_cells_gnuplot(fp
);
625 /** Computes Voronoi cells and saves the output in POV-Ray
627 * \param[in] vl the loop class to use.
628 * \param[in] fp a file handle to write to. */
629 template<class c_loop
>
630 void draw_cells_pov(c_loop
&vl
,FILE *fp
) {
631 voronoicell
c(*this);double *pp
;
632 if(vl
.start()) do if(compute_cell(c
,vl
)) {
633 fprintf(fp
,"// cell %d\n",id
[vl
.ijk
][vl
.q
]);
634 pp
=p
[vl
.ijk
]+ps
*vl
.q
;
635 c
.draw_pov(*pp
,pp
[1],pp
[2],fp
);
638 /** Computes all Voronoi cells and saves the output in POV-Ray
640 * \param[in] fp a file handle to write to. */
641 inline void draw_cells_pov(FILE *fp
=stdout
) {
642 c_loop_all
vl(*this);
643 draw_cells_pov(vl
,fp
);
645 /** Computes all Voronoi cells and saves the output in POV-Ray
647 * \param[in] filename the name of the file to write to. */
648 inline void draw_cells_pov(const char *filename
) {
649 FILE *fp
=safe_fopen(filename
,"w");
653 /** Computes the Voronoi cells and saves customized information
655 * \param[in] vl the loop class to use.
656 * \param[in] format the custom output string to use.
657 * \param[in] fp a file handle to write to. */
658 template<class c_loop
>
659 void print_custom(c_loop
&vl
,const char *format
,FILE *fp
) {
660 int ijk
,q
;double *pp
;
661 if(contains_neighbor(format
)) {
662 voronoicell_neighbor
c(*this);
663 if(vl
.start()) do if(compute_cell(c
,vl
)) {
664 ijk
=vl
.ijk
;q
=vl
.q
;pp
=p
[ijk
]+ps
*q
;
665 c
.output_custom(format
,id
[ijk
][q
],*pp
,pp
[1],pp
[2],pp
[3],fp
);
668 voronoicell
c(*this);
669 if(vl
.start()) do if(compute_cell(c
,vl
)) {
670 ijk
=vl
.ijk
;q
=vl
.q
;pp
=p
[ijk
]+ps
*q
;
671 c
.output_custom(format
,id
[ijk
][q
],*pp
,pp
[1],pp
[2],pp
[3],fp
);
675 /** Computes the Voronoi cell for a particle currently being
676 * referenced by a loop class.
677 * \param[out] c a Voronoi cell class in which to store the
679 * \param[in] vl the loop class to use.
680 * \return True if the cell was computed. If the cell cannot be
681 * computed, if it is removed entirely by a wall or boundary
682 * condition, then the routine returns false. */
683 template<class v_cell
,class c_loop
>
684 inline bool compute_cell(v_cell
&c
,c_loop
&vl
) {
685 return vc
.compute_cell(c
,vl
.ijk
,vl
.q
,vl
.i
,vl
.j
,vl
.k
);
687 /** Computes the Voronoi cell for given particle.
688 * \param[out] c a Voronoi cell class in which to store the
690 * \param[in] ijk the block that the particle is within.
691 * \param[in] q the index of the particle within the block.
692 * \return True if the cell was computed. If the cell cannot be
693 * computed, if it is removed entirely by a wall or boundary
694 * condition, then the routine returns false. */
695 template<class v_cell
>
696 inline bool compute_cell(v_cell
&c
,int ijk
,int q
) {
697 int k
=ijk
/nxy
,ijkt
=ijk
-nxy
*k
,j
=ijkt
/nx
,i
=ijkt
-j
*nx
;
698 return vc
.compute_cell(c
,ijk
,q
,i
,j
,k
);
700 /** Computes the Voronoi cell for a ghost particle at a given
702 * \param[out] c a Voronoi cell class in which to store the
704 * \param[in] (x,y,z) the location of the ghost particle.
705 * \param[in] r the radius of the ghost particle.
706 * \return True if the cell was computed. If the cell cannot be
707 * computed, if it is removed entirely by a wall or boundary
708 * condition, then the routine returns false. */
709 template<class v_cell
>
710 inline bool compute_ghost_cell(v_cell
&c
,double x
,double y
,double z
,double r
) {
712 if(put_locate_block(ijk
,x
,y
,z
)) {
713 double *pp
=p
[ijk
]+4*co
[ijk
]++,tm
=max_radius
;
714 *(pp
++)=x
;*(pp
++)=y
;*(pp
++)=z
;*pp
=r
;
715 if(r
>max_radius
) max_radius
=r
;
716 bool q
=compute_cell(c
,ijk
,co
[ijk
]-1);
717 co
[ijk
]--;max_radius
=tm
;
722 void print_custom(const char *format
,FILE *fp
=stdout
);
723 void print_custom(const char *format
,const char *filename
);
724 bool find_voronoi_cell(double x
,double y
,double z
,double &rx
,double &ry
,double &rz
,int &pid
);
726 voro_compute
<container_poly
> vc
;
727 friend class voro_compute
<container_poly
>;