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