ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/REPOS_ERICCA/poly_occ/voro++-0.4.6/src/container.cc
Revision: 979
Committed: Thu Oct 18 23:40:32 2018 UTC (6 years, 7 months ago) by francois
File size: 22815 byte(s)
Log Message:
creation de polycristaux avec OCC

File Contents

# User Rev Content
1 francois 979 // 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
6    
7     /** \file container.cc
8     * \brief Function implementations for the container and related classes. */
9    
10     #include "container.hh"
11    
12     namespace voro {
13    
14     /** The class constructor sets up the geometry of container, initializing the
15     * minimum and maximum coordinates in each direction, and setting whether each
16     * direction is periodic or not. It divides the container into a rectangular
17     * grid of blocks, and allocates memory for each of these for storing particle
18     * positions and IDs.
19     * \param[in] (ax_,bx_) the minimum and maximum x coordinates.
20     * \param[in] (ay_,by_) the minimum and maximum y coordinates.
21     * \param[in] (az_,bz_) the minimum and maximum z coordinates.
22     * \param[in] (nx_,ny_,nz_) the number of grid blocks in each of the three
23     * coordinate directions.
24     * \param[in] (xperiodic_,yperiodic_,zperiodic_) flags setting whether the
25     * container is periodic in each
26     * coordinate direction.
27     * \param[in] init_mem the initial memory allocation for each block.
28     * \param[in] ps_ the number of floating point entries to store for each
29     * particle. */
30     container_base::container_base(double ax_,double bx_,double ay_,double by_,double az_,double bz_,
31     int nx_,int ny_,int nz_,bool xperiodic_,bool yperiodic_,bool zperiodic_,int init_mem,int ps_)
32     : voro_base(nx_,ny_,nz_,(bx_-ax_)/nx_,(by_-ay_)/ny_,(bz_-az_)/nz_),
33     ax(ax_), bx(bx_), ay(ay_), by(by_), az(az_), bz(bz_),
34     xperiodic(xperiodic_), yperiodic(yperiodic_), zperiodic(zperiodic_),
35     id(new int*[nxyz]), p(new double*[nxyz]), co(new int[nxyz]), mem(new int[nxyz]), ps(ps_) {
36     int l;
37     for(l=0;l<nxyz;l++) co[l]=0;
38     for(l=0;l<nxyz;l++) mem[l]=init_mem;
39     for(l=0;l<nxyz;l++) id[l]=new int[init_mem];
40     for(l=0;l<nxyz;l++) p[l]=new double[ps*init_mem];
41     }
42    
43     /** The container destructor frees the dynamically allocated memory. */
44     container_base::~container_base() {
45     int l;
46     for(l=0;l<nxyz;l++) delete [] p[l];
47     for(l=0;l<nxyz;l++) delete [] id[l];
48     delete [] id;
49     delete [] p;
50     delete [] co;
51     delete [] mem;
52     }
53    
54     /** The class constructor sets up the geometry of container.
55     * \param[in] (ax_,bx_) the minimum and maximum x coordinates.
56     * \param[in] (ay_,by_) the minimum and maximum y coordinates.
57     * \param[in] (az_,bz_) the minimum and maximum z coordinates.
58     * \param[in] (nx_,ny_,nz_) the number of grid blocks in each of the three
59     * coordinate directions.
60     * \param[in] (xperiodic_,yperiodic_,zperiodic_) flags setting whether the
61     * container is periodic in each
62     * coordinate direction.
63     * \param[in] init_mem the initial memory allocation for each block. */
64     container::container(double ax_,double bx_,double ay_,double by_,double az_,double bz_,
65     int nx_,int ny_,int nz_,bool xperiodic_,bool yperiodic_,bool zperiodic_,int init_mem)
66     : container_base(ax_,bx_,ay_,by_,az_,bz_,nx_,ny_,nz_,xperiodic_,yperiodic_,zperiodic_,init_mem,3),
67     vc(*this,xperiodic_?2*nx_+1:nx_,yperiodic_?2*ny_+1:ny_,zperiodic_?2*nz_+1:nz_) {}
68    
69     /** The class constructor sets up the geometry of container.
70     * \param[in] (ax_,bx_) the minimum and maximum x coordinates.
71     * \param[in] (ay_,by_) the minimum and maximum y coordinates.
72     * \param[in] (az_,bz_) the minimum and maximum z coordinates.
73     * \param[in] (nx_,ny_,nz_) the number of grid blocks in each of the three
74     * coordinate directions.
75     * \param[in] (xperiodic_,yperiodic_,zperiodic_) flags setting whether the
76     * container is periodic in each
77     * coordinate direction.
78     * \param[in] init_mem the initial memory allocation for each block. */
79     container_poly::container_poly(double ax_,double bx_,double ay_,double by_,double az_,double bz_,
80     int nx_,int ny_,int nz_,bool xperiodic_,bool yperiodic_,bool zperiodic_,int init_mem)
81     : container_base(ax_,bx_,ay_,by_,az_,bz_,nx_,ny_,nz_,xperiodic_,yperiodic_,zperiodic_,init_mem,4),
82     vc(*this,xperiodic_?2*nx_+1:nx_,yperiodic_?2*ny_+1:ny_,zperiodic_?2*nz_+1:nz_) {ppr=p;}
83    
84     /** Put a particle into the correct region of the container.
85     * \param[in] n the numerical ID of the inserted particle.
86     * \param[in] (x,y,z) the position vector of the inserted particle. */
87     void container::put(int n,double x,double y,double z) {
88     int ijk;
89     if(put_locate_block(ijk,x,y,z)) {
90     id[ijk][co[ijk]]=n;
91     double *pp=p[ijk]+3*co[ijk]++;
92     *(pp++)=x;*(pp++)=y;*pp=z;
93     }
94     }
95    
96     /** Put a particle into the correct region of the container.
97     * \param[in] n the numerical ID of the inserted particle.
98     * \param[in] (x,y,z) the position vector of the inserted particle.
99     * \param[in] r the radius of the particle. */
100     void container_poly::put(int n,double x,double y,double z,double r) {
101     int ijk;
102     if(put_locate_block(ijk,x,y,z)) {
103     id[ijk][co[ijk]]=n;
104     double *pp=p[ijk]+4*co[ijk]++;
105     *(pp++)=x;*(pp++)=y;*(pp++)=z;*pp=r;
106     if(max_radius<r) max_radius=r;
107     }
108     }
109    
110     /** Put a particle into the correct region of the container, also recording
111     * into which region it was stored.
112     * \param[in] vo the ordering class in which to record the region.
113     * \param[in] n the numerical ID of the inserted particle.
114     * \param[in] (x,y,z) the position vector of the inserted particle. */
115     void container::put(particle_order &vo,int n,double x,double y,double z) {
116     int ijk;
117     if(put_locate_block(ijk,x,y,z)) {
118     id[ijk][co[ijk]]=n;
119     vo.add(ijk,co[ijk]);
120     double *pp=p[ijk]+3*co[ijk]++;
121     *(pp++)=x;*(pp++)=y;*pp=z;
122     }
123     }
124    
125     /** Put a particle into the correct region of the container, also recording
126     * into which region it was stored.
127     * \param[in] vo the ordering class in which to record the region.
128     * \param[in] n the numerical ID of the inserted particle.
129     * \param[in] (x,y,z) the position vector of the inserted particle.
130     * \param[in] r the radius of the particle. */
131     void container_poly::put(particle_order &vo,int n,double x,double y,double z,double r) {
132     int ijk;
133     if(put_locate_block(ijk,x,y,z)) {
134     id[ijk][co[ijk]]=n;
135     vo.add(ijk,co[ijk]);
136     double *pp=p[ijk]+4*co[ijk]++;
137     *(pp++)=x;*(pp++)=y;*(pp++)=z;*pp=r;
138     if(max_radius<r) max_radius=r;
139     }
140     }
141    
142     /** This routine takes a particle position vector, tries to remap it into the
143     * primary domain. If successful, it computes the region into which it can be
144     * stored and checks that there is enough memory within this region to store
145     * it.
146     * \param[out] ijk the region index.
147     * \param[in,out] (x,y,z) the particle position, remapped into the primary
148     * domain if necessary.
149     * \return True if the particle can be successfully placed into the container,
150     * false otherwise. */
151     bool container_base::put_locate_block(int &ijk,double &x,double &y,double &z) {
152     if(put_remap(ijk,x,y,z)) {
153     if(co[ijk]==mem[ijk]) add_particle_memory(ijk);
154     return true;
155     }
156     #if VOROPP_REPORT_OUT_OF_BOUNDS ==1
157     fprintf(stderr,"Out of bounds: (x,y,z)=(%g,%g,%g)\n",x,y,z);
158     #endif
159     return false;
160     }
161    
162     /** Takes a particle position vector and computes the region index into which
163     * it should be stored. If the container is periodic, then the routine also
164     * maps the particle position to ensure it is in the primary domain. If the
165     * container is not periodic, the routine bails out.
166     * \param[out] ijk the region index.
167     * \param[in,out] (x,y,z) the particle position, remapped into the primary
168     * domain if necessary.
169     * \return True if the particle can be successfully placed into the container,
170     * false otherwise. */
171     inline bool container_base::put_remap(int &ijk,double &x,double &y,double &z) {
172     int l;
173    
174     ijk=step_int((x-ax)*xsp);
175     if(xperiodic) {l=step_mod(ijk,nx);x+=boxx*(l-ijk);ijk=l;}
176     else if(ijk<0||ijk>=nx) return false;
177    
178     int j=step_int((y-ay)*ysp);
179     if(yperiodic) {l=step_mod(j,ny);y+=boxy*(l-j);j=l;}
180     else if(j<0||j>=ny) return false;
181    
182     int k=step_int((z-az)*zsp);
183     if(zperiodic) {l=step_mod(k,nz);z+=boxz*(l-k);k=l;}
184     else if(k<0||k>=nz) return false;
185    
186     ijk+=nx*j+nxy*k;
187     return true;
188     }
189    
190     /** Takes a position vector and attempts to remap it into the primary domain.
191     * \param[out] (ai,aj,ak) the periodic image displacement that the vector is in,
192     * with (0,0,0) corresponding to the primary domain.
193     * \param[out] (ci,cj,ck) the index of the block that the position vector is
194     * within, once it has been remapped.
195     * \param[in,out] (x,y,z) the position vector to consider, which is remapped
196     * into the primary domain during the routine.
197     * \param[out] ijk the block index that the vector is within.
198     * \return True if the particle is within the container or can be remapped into
199     * it, false if it lies outside of the container bounds. */
200     inline bool container_base::remap(int &ai,int &aj,int &ak,int &ci,int &cj,int &ck,double &x,double &y,double &z,int &ijk) {
201     ci=step_int((x-ax)*xsp);
202     if(ci<0||ci>=nx) {
203     if(xperiodic) {ai=step_div(ci,nx);x-=ai*(bx-ax);ci-=ai*nx;}
204     else return false;
205     } else ai=0;
206    
207     cj=step_int((y-ay)*ysp);
208     if(cj<0||cj>=ny) {
209     if(yperiodic) {aj=step_div(cj,ny);y-=aj*(by-ay);cj-=aj*ny;}
210     else return false;
211     } else aj=0;
212    
213     ck=step_int((z-az)*zsp);
214     if(ck<0||ck>=nz) {
215     if(zperiodic) {ak=step_div(ck,nz);z-=ak*(bz-az);ck-=ak*nz;}
216     else return false;
217     } else ak=0;
218    
219     ijk=ci+nx*cj+nxy*ck;
220     return true;
221     }
222    
223     /** Takes a vector and finds the particle whose Voronoi cell contains that
224     * vector. This is equivalent to finding the particle which is nearest to the
225     * vector. Additional wall classes are not considered by this routine.
226     * \param[in] (x,y,z) the vector to test.
227     * \param[out] (rx,ry,rz) the position of the particle whose Voronoi cell
228     * contains the vector. If the container is periodic,
229     * this may point to a particle in a periodic image of
230     * the primary domain.
231     * \param[out] pid the ID of the particle.
232     * \return True if a particle was found. If the container has no particles,
233     * then the search will not find a Voronoi cell and false is returned. */
234     bool container::find_voronoi_cell(double x,double y,double z,double &rx,double &ry,double &rz,int &pid) {
235     int ai,aj,ak,ci,cj,ck,ijk;
236     particle_record w;
237     double mrs;
238    
239     // If the given vector lies outside the domain, but the container
240     // is periodic, then remap it back into the domain
241     if(!remap(ai,aj,ak,ci,cj,ck,x,y,z,ijk)) return false;
242     vc.find_voronoi_cell(x,y,z,ci,cj,ck,ijk,w,mrs);
243    
244     if(w.ijk!=-1) {
245    
246     // Assemble the position vector of the particle to be returned,
247     // applying a periodic remapping if necessary
248     if(xperiodic) {ci+=w.di;if(ci<0||ci>=nx) ai+=step_div(ci,nx);}
249     if(yperiodic) {cj+=w.dj;if(cj<0||cj>=ny) aj+=step_div(cj,ny);}
250     if(zperiodic) {ck+=w.dk;if(ck<0||ck>=nz) ak+=step_div(ck,nz);}
251     rx=p[w.ijk][3*w.l]+ai*(bx-ax);
252     ry=p[w.ijk][3*w.l+1]+aj*(by-ay);
253     rz=p[w.ijk][3*w.l+2]+ak*(bz-az);
254     pid=id[w.ijk][w.l];
255     return true;
256     }
257    
258     // If no particle if found then just return false
259     return false;
260     }
261    
262     /** Takes a vector and finds the particle whose Voronoi cell contains that
263     * vector. Additional wall classes are not considered by this routine.
264     * \param[in] (x,y,z) the vector to test.
265     * \param[out] (rx,ry,rz) the position of the particle whose Voronoi cell
266     * contains the vector. If the container is periodic,
267     * this may point to a particle in a periodic image of
268     * the primary domain.
269     * \param[out] pid the ID of the particle.
270     * \return True if a particle was found. If the container has no particles,
271     * then the search will not find a Voronoi cell and false is returned. */
272     bool container_poly::find_voronoi_cell(double x,double y,double z,double &rx,double &ry,double &rz,int &pid) {
273     int ai,aj,ak,ci,cj,ck,ijk;
274     particle_record w;
275     double mrs;
276    
277     // If the given vector lies outside the domain, but the container
278     // is periodic, then remap it back into the domain
279     if(!remap(ai,aj,ak,ci,cj,ck,x,y,z,ijk)) return false;
280     vc.find_voronoi_cell(x,y,z,ci,cj,ck,ijk,w,mrs);
281    
282     if(w.ijk!=-1) {
283    
284     // Assemble the position vector of the particle to be returned,
285     // applying a periodic remapping if necessary
286     if(xperiodic) {ci+=w.di;if(ci<0||ci>=nx) ai+=step_div(ci,nx);}
287     if(yperiodic) {cj+=w.dj;if(cj<0||cj>=ny) aj+=step_div(cj,ny);}
288     if(zperiodic) {ck+=w.dk;if(ck<0||ck>=nz) ak+=step_div(ck,nz);}
289     rx=p[w.ijk][4*w.l]+ai*(bx-ax);
290     ry=p[w.ijk][4*w.l+1]+aj*(by-ay);
291     rz=p[w.ijk][4*w.l+2]+ak*(bz-az);
292     pid=id[w.ijk][w.l];
293     return true;
294     }
295    
296     // If no particle if found then just return false
297     return false;
298     }
299    
300     /** Increase memory for a particular region.
301     * \param[in] i the index of the region to reallocate. */
302     void container_base::add_particle_memory(int i) {
303     int l,nmem=mem[i]<<1;
304    
305     // Carry out a check on the memory allocation size, and
306     // print a status message if requested
307     if(nmem>max_particle_memory)
308     voro_fatal_error("Absolute maximum memory allocation exceeded",VOROPP_MEMORY_ERROR);
309     #if VOROPP_VERBOSE >=3
310     fprintf(stderr,"Particle memory in region %d scaled up to %d\n",i,nmem);
311     #endif
312    
313     // Allocate new memory and copy in the contents of the old arrays
314     int *idp=new int[nmem];
315     for(l=0;l<co[i];l++) idp[l]=id[i][l];
316     double *pp=new double[ps*nmem];
317     for(l=0;l<ps*co[i];l++) pp[l]=p[i][l];
318    
319     // Update pointers and delete old arrays
320     mem[i]=nmem;
321     delete [] id[i];id[i]=idp;
322     delete [] p[i];p[i]=pp;
323     }
324    
325     /** Import a list of particles from an open file stream into the container.
326     * Entries of four numbers (Particle ID, x position, y position, z position)
327     * are searched for. If the file cannot be successfully read, then the routine
328     * causes a fatal error.
329     * \param[in] fp the file handle to read from. */
330     void container::import(FILE *fp) {
331     int i,j;
332     double x,y,z;
333     while((j=fscanf(fp,"%d %lg %lg %lg",&i,&x,&y,&z))==4) put(i,x,y,z);
334     if(j!=EOF) voro_fatal_error("File import error",VOROPP_FILE_ERROR);
335     }
336    
337     /** Import a list of particles from an open file stream, also storing the order
338     * of that the particles are read. Entries of four numbers (Particle ID, x
339     * position, y position, z position) are searched for. If the file cannot be
340     * successfully read, then the routine causes a fatal error.
341     * \param[in,out] vo a reference to an ordering class to use.
342     * \param[in] fp the file handle to read from. */
343     void container::import(particle_order &vo,FILE *fp) {
344     int i,j;
345     double x,y,z;
346     while((j=fscanf(fp,"%d %lg %lg %lg",&i,&x,&y,&z))==4) put(vo,i,x,y,z);
347     if(j!=EOF) voro_fatal_error("File import error",VOROPP_FILE_ERROR);
348     }
349    
350     /** Import a list of particles from an open file stream into the container.
351     * Entries of five numbers (Particle ID, x position, y position, z position,
352     * radius) are searched for. If the file cannot be successfully read, then the
353     * routine causes a fatal error.
354     * \param[in] fp the file handle to read from. */
355     void container_poly::import(FILE *fp) {
356     int i,j;
357     double x,y,z,r;
358     while((j=fscanf(fp,"%d %lg %lg %lg %lg",&i,&x,&y,&z,&r))==5) put(i,x,y,z,r);
359     if(j!=EOF) voro_fatal_error("File import error",VOROPP_FILE_ERROR);
360     }
361    
362     /** Import a list of particles from an open file stream, also storing the order
363     * of that the particles are read. Entries of four numbers (Particle ID, x
364     * position, y position, z position, radius) are searched for. If the file
365     * cannot be successfully read, then the routine causes a fatal error.
366     * \param[in,out] vo a reference to an ordering class to use.
367     * \param[in] fp the file handle to read from. */
368     void container_poly::import(particle_order &vo,FILE *fp) {
369     int i,j;
370     double x,y,z,r;
371     while((j=fscanf(fp,"%d %lg %lg %lg %lg",&i,&x,&y,&z,&r))==5) put(vo,i,x,y,z,r);
372     if(j!=EOF) voro_fatal_error("File import error",VOROPP_FILE_ERROR);
373     }
374    
375     /** Outputs the a list of all the container regions along with the number of
376     * particles stored within each. */
377     void container_base::region_count() {
378     int i,j,k,*cop=co;
379     for(k=0;k<nz;k++) for(j=0;j<ny;j++) for(i=0;i<nx;i++)
380     printf("Region (%d,%d,%d): %d particles\n",i,j,k,*(cop++));
381     }
382    
383     /** Clears a container of particles. */
384     void container::clear() {
385     for(int *cop=co;cop<co+nxyz;cop++) *cop=0;
386     }
387    
388     /** Clears a container of particles, also clearing resetting the maximum radius
389     * to zero. */
390     void container_poly::clear() {
391     for(int *cop=co;cop<co+nxyz;cop++) *cop=0;
392     max_radius=0;
393     }
394    
395     /** Computes all the Voronoi cells and saves customized information about them.
396     * \param[in] format the custom output string to use.
397     * \param[in] fp a file handle to write to. */
398     void container::print_custom(const char *format,FILE *fp) {
399     c_loop_all vl(*this);
400     print_custom(vl,format,fp);
401     }
402    
403     /** Computes all the Voronoi cells and saves customized
404     * information about them.
405     * \param[in] format the custom output string to use.
406     * \param[in] fp a file handle to write to. */
407     void container_poly::print_custom(const char *format,FILE *fp) {
408     c_loop_all vl(*this);
409     print_custom(vl,format,fp);
410     }
411    
412     /** Computes all the Voronoi cells and saves customized information about them.
413     * \param[in] format the custom output string to use.
414     * \param[in] filename the name of the file to write to. */
415     void container::print_custom(const char *format,const char *filename) {
416     FILE *fp=safe_fopen(filename,"w");
417     print_custom(format,fp);
418     fclose(fp);
419     }
420    
421     /** Computes all the Voronoi cells and saves customized
422     * information about them
423     * \param[in] format the custom output string to use.
424     * \param[in] filename the name of the file to write to. */
425     void container_poly::print_custom(const char *format,const char *filename) {
426     FILE *fp=safe_fopen(filename,"w");
427     print_custom(format,fp);
428     fclose(fp);
429     }
430    
431     /** Computes all of the Voronoi cells in the container, but does nothing
432     * with the output. It is useful for measuring the pure computation time
433     * of the Voronoi algorithm, without any additional calculations such as
434     * volume evaluation or cell output. */
435     void container::compute_all_cells() {
436     voronoicell c;
437     c_loop_all vl(*this);
438     if(vl.start()) do compute_cell(c,vl);
439     while(vl.inc());
440     }
441    
442     /** Computes all of the Voronoi cells in the container, but does nothing
443     * with the output. It is useful for measuring the pure computation time
444     * of the Voronoi algorithm, without any additional calculations such as
445     * volume evaluation or cell output. */
446     void container_poly::compute_all_cells() {
447     voronoicell c;
448     c_loop_all vl(*this);
449     if(vl.start()) do compute_cell(c,vl);while(vl.inc());
450     }
451    
452     /** Calculates all of the Voronoi cells and sums their volumes. In most cases
453     * without walls, the sum of the Voronoi cell volumes should equal the volume
454     * of the container to numerical precision.
455     * \return The sum of all of the computed Voronoi volumes. */
456     double container::sum_cell_volumes() {
457     voronoicell c;
458     double vol=0;
459     c_loop_all vl(*this);
460     if(vl.start()) do if(compute_cell(c,vl)) vol+=c.volume();while(vl.inc());
461     return vol;
462     }
463    
464     /** Calculates all of the Voronoi cells and sums their volumes. In most cases
465     * without walls, the sum of the Voronoi cell volumes should equal the volume
466     * of the container to numerical precision.
467     * \return The sum of all of the computed Voronoi volumes. */
468     double container_poly::sum_cell_volumes() {
469     voronoicell c;
470     double vol=0;
471     c_loop_all vl(*this);
472     if(vl.start()) do if(compute_cell(c,vl)) vol+=c.volume();while(vl.inc());
473     return vol;
474     }
475    
476     /** This function tests to see if a given vector lies within the container
477     * bounds and any walls.
478     * \param[in] (x,y,z) the position vector to be tested.
479     * \return True if the point is inside the container, false if the point is
480     * outside. */
481     bool container_base::point_inside(double x,double y,double z) {
482     if(x<ax||x>bx||y<ay||y>by||z<az||z>bz) return false;
483     return point_inside_walls(x,y,z);
484     }
485    
486     /** Draws an outline of the domain in gnuplot format.
487     * \param[in] fp the file handle to write to. */
488     void container_base::draw_domain_gnuplot(FILE *fp) {
489     fprintf(fp,"%g %g %g\n%g %g %g\n%g %g %g\n%g %g %g\n",ax,ay,az,bx,ay,az,bx,by,az,ax,by,az);
490     fprintf(fp,"%g %g %g\n%g %g %g\n%g %g %g\n%g %g %g\n",ax,by,bz,bx,by,bz,bx,ay,bz,ax,ay,bz);
491     fprintf(fp,"%g %g %g\n\n%g %g %g\n%g %g %g\n\n",ax,by,bz,ax,ay,az,ax,ay,bz);
492     fprintf(fp,"%g %g %g\n%g %g %g\n\n%g %g %g\n%g %g %g\n\n",bx,ay,az,bx,ay,bz,bx,by,az,bx,by,bz);
493     }
494    
495     /** Draws an outline of the domain in POV-Ray format.
496     * \param[in] fp the file handle to write to. */
497     void container_base::draw_domain_pov(FILE *fp) {
498     fprintf(fp,"cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n"
499     "cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n",ax,ay,az,bx,ay,az,ax,by,az,bx,by,az);
500     fprintf(fp,"cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n"
501     "cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n",ax,by,bz,bx,by,bz,ax,ay,bz,bx,ay,bz);
502     fprintf(fp,"cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n"
503     "cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n",ax,ay,az,ax,by,az,bx,ay,az,bx,by,az);
504     fprintf(fp,"cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n"
505     "cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n",bx,ay,bz,bx,by,bz,ax,ay,bz,ax,by,bz);
506     fprintf(fp,"cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n"
507     "cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n",ax,ay,az,ax,ay,bz,bx,ay,az,bx,ay,bz);
508     fprintf(fp,"cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n"
509     "cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n",bx,by,az,bx,by,bz,ax,by,az,ax,by,bz);
510     fprintf(fp,"sphere{<%g,%g,%g>,rr}\nsphere{<%g,%g,%g>,rr}\n"
511     "sphere{<%g,%g,%g>,rr}\nsphere{<%g,%g,%g>,rr}\n",ax,ay,az,bx,ay,az,ax,by,az,bx,by,az);
512     fprintf(fp,"sphere{<%g,%g,%g>,rr}\nsphere{<%g,%g,%g>,rr}\n"
513     "sphere{<%g,%g,%g>,rr}\nsphere{<%g,%g,%g>,rr}\n",ax,ay,bz,bx,ay,bz,ax,by,bz,bx,by,bz);
514     }
515    
516    
517     /** The wall_list constructor sets up an array of pointers to wall classes. */
518     wall_list::wall_list() : walls(new wall*[init_wall_size]), wep(walls), wel(walls+init_wall_size),
519     current_wall_size(init_wall_size) {}
520    
521     /** The wall_list destructor frees the array of pointers to the wall classes.
522     */
523     wall_list::~wall_list() {
524     delete [] walls;
525     }
526    
527     /** Adds all of the walls on another wall_list to this class.
528     * \param[in] wl a reference to the wall class. */
529     void wall_list::add_wall(wall_list &wl) {
530     for(wall **wp=wl.walls;wp<wl.wep;wp++) add_wall(*wp);
531     }
532    
533     /** Deallocates all of the wall classes pointed to by the wall_list. */
534     void wall_list::deallocate() {
535     for(wall **wp=walls;wp<wep;wp++) delete *wp;
536     }
537    
538     /** Increases the memory allocation for the walls array. */
539     void wall_list::increase_wall_memory() {
540     current_wall_size<<=1;
541     if(current_wall_size>max_wall_size)
542     voro_fatal_error("Wall memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR);
543     wall **nwalls=new wall*[current_wall_size],**nwp=nwalls,**wp=walls;
544     while(wp<wep) *(nwp++)=*(wp++);
545     delete [] walls;
546     walls=nwalls;wel=walls+current_wall_size;wep=nwp;
547     }
548    
549     }