Reset platonic code.
[voro++.git] / branches / dynamic / src / voro++.hh
blob1a2e4066d91f1ceebd517ce4865e46d36fd23b6c
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 : July 1st 2008
7 /** \file voro++.hh
8 * \brief A file that loads all of the Voro++ header files. */
10 /** \mainpage Voro++ class reference manual
11 * \section intro Introduction
12 * Voro++ is a software library for carrying out 3D cell-based calculations of
13 * the Voronoi tessellation. It is primarily designed for applications in
14 * physics and materials science, where the Voronoi tessellation can be a
15 * useful tool in analyzing particle systems.
17 * Voro++ is comprised of several C++ classes, and is designed to be
18 * incorporated into other programs. This manual provides a reference for every
19 * function in the class structure. For a general overview of the program, see
20 * the Voro++ website at http://math.lbl.gov/voro++/ and in particular the
21 * example programs at http://math.lbl.gov/voro++/examples/ that demonstrate
22 * many of the library's features.
24 * \section class C++ class structure
25 * The code is structured around two main C++ classes. The voronoicell class
26 * contains all of the routines for constructing a single Voronoi cell. It
27 * represents the cell as a collection of vertices that are connected by edges,
28 * and there are routines for initializing, making, and outputting the cell.
29 * The container class represents a three-dimensional simulation region into
30 * which particles can be added. The class can then carry out a variety of
31 * Voronoi calculations by computing cells using the voronoicell class. It also
32 * has a general mechanism using virtual functions to implement walls,
33 * discussed in more detail below. To implement the radical Voronoi
34 * tessellation and the neighbor calculations, two class variants called
35 * voronoicell_neighbor and container_poly are provided by making use of
36 * templates, which is discussed below.
38 * \section voronoicell The voronoicell class
39 * The voronoicell class represents a single Voronoi cell as a convex
40 * polyhedron, with a set of vertices that are connected by edges. The class
41 * contains a variety of functions that can be used to compute and output the
42 * Voronoi cell corresponding to a particular particle. The command init()
43 * can be used to initialize a cell as a large rectangular box. The Voronoi cell
44 * can then be computed by repeatedly cutting it with planes that correspond to
45 * the perpendicular bisectors between that particle and its neighbors.
47 * This is achieved by using the plane() routine, which will recompute the
48 * cell's vertices and edges after cutting it with a single plane. This is the
49 * key routine in voronoicell class. It begins by exploiting the convexity
50 * of the underlying cell, tracing between edges to work out if the cell
51 * intersects the cutting plane. If it does not intersect, then the routine
52 * immediately exits. Otherwise, it finds an edge or vertex that intersects
53 * the plane, and from there, traces out a new face on the cell, recomputing
54 * the edge and vertex structure accordingly.
56 * Once the cell is computed, it can be drawn using commands such as
57 * draw_gnuplot() and draw_pov(), or its volume can be evaluated using the
58 * volume() function. Many more routines are available, and are described in
59 * the online reference manual.
61 * \subsection internal Internal data representation
62 * The voronoicell class has a public member p representing the
63 * number of vertices. The polyhedral structure of the cell is stored
64 * in the following arrays:
66 * - pts[]: an array of floating point numbers, that represent the position
67 * vectors x_0, x_1, ..., x_{p-1} of the polyhedron vertices.
68 * - nu[]: the order of each vertex n_0, n_1, ..., n_{p-1}, corresponding to
69 * the number of other vertices to which each is connected.
70 * - ed[][]: a table of edges and relations. For the ith vertex, ed[i] has
71 * 2n_i+1 elements. The first n_i elements are the edges e(j,i), where e(j,i)
72 * is the jth neighbor of vertex i. The edges are ordered according to a
73 * right-hand rule with respect to an outward-pointing normal. The next n_i
74 * elements are the relations l(j,i) which satisfy the property
75 * e(l(j,i),e(j,i)) = i. The final element of the ed[i] list is a back
76 * pointer used in memory allocation.
78 * In a very large number of cases, the values of n_i will be 3. This is because
79 * the only way that a higher-order vertex can be created in the plane()
80 * routine is if the cutting plane perfectly intersects an existing vertex. For
81 * random particle arrangements with position vectors specified to double
82 * precision this should happen very rarely. A preliminary version of this code
83 * was quite successful with only making use of vertices of order 3. However,
84 * when calculating millions of cells, it was found that this approach is not
85 * robust, since a single floating point error can invalidate the computation.
86 * This can also be a problem for cases featuring crystalline arrangements of
87 * particles where the corresponding Voronoi cells may have high-order vertices
88 * by construction.
90 * Because of this, Voro++ takes the approach that it if an existing vertex is
91 * within a small numerical tolerance of the cutting plane, it is treated as
92 * being exactly on the plane, and the polyhedral topology is recomputed
93 * accordingly. However, while this improves robustness, it also adds the
94 * complexity that n_i may no longer always be 3. This causes memory management
95 * to be significantly more complicated, as different vertices require a
96 * different number of elements in the ed[][] array. To accommodate this, the
97 * voronoicell class allocated edge memory in a different array called mep[][],
98 * in such a way that all vertices of order k are held in mep[k]. If vertex
99 * i has order k, then ed[i] points to memory within mep[k]. The array ed[][]
100 * is never directly initialized as a two-dimensional array itself, but points
101 * at allocations within mep[][]. To the user, it appears as though each row of
102 * ed[][] has a different number of elements. When vertices are added or
103 * deleted, care must be taken to reorder and reassign elements in these
104 * arrays.
106 * During the plane() routine, the code traces around the vertices of the cell,
107 * and adds new vertices along edges which intersect the cutting plane to
108 * create a new face. The values of l(j,i) are used in this computation, as
109 * when the code is traversing from one vertex on the cell to another, this
110 * information allows the code to immediately work out which edge of a vertex
111 * points back to the one it came from. As new vertices are created, the
112 * l(j,i) are also updated to ensure consistency. To ensure robustness, the
113 * plane cutting algorithm should work with any possible combination of
114 * vertices which are inside, outside, or exactly on the cutting plane.
116 * Vertices exactly on the cutting plane create some additional computational
117 * difficulties. If there are two marginal vertices connected by an existing
118 * edge, then it would be possible for duplicate edges to be created between
119 * those two vertices, if the plane routine traces along both sides of this
120 * edge while constructing the new face. The code recognizes these cases and
121 * prevents the double edge from being formed. Another possibility is the
122 * formation of vertices of order two or one. At the end of the plane cutting
123 * routine, the code checks to see if any of these are present, removing the
124 * order one vertices by just deleting them, and removing the order two
125 * vertices by connecting the two neighbors of each vertex together. It is
126 * possible that the removal of a single low-order vertex could result in the
127 * creation of additional low-order vertices, so the process is applied
128 * recursively until no more are left.
130 * \section container The container class
131 * The container class represents a three-dimensional rectangular box of
132 * particles. The constructor for this class sets up the coordinate ranges,
133 * sets whether each direction is periodic or not, and divides the box into a
134 * rectangular subgrid of regions. Particles can be added to the container
135 * using the put() command, that adds a particle's position and an integer
136 * numerical ID label to the corresponding region. Alternatively, the command
137 * import() can be used to read large numbers of particles from a text file.
139 * The key routine in this class is compute_cell(), which makes use of the
140 * voronoicell class to construct a Voronoi cell for a specific particle in the
141 * container. The basic approach that this function takes is to repeatedly cut
142 * the Voronoi cell by planes corresponding neighboring particles, and stop
143 * when it recognizes that all the remaining particles in the container are too
144 * far away to possibly influence cell's shape. The code makes use of two
145 * possible methods for working out when a cell computation is complete:
147 * - Radius test: if the maximum distance of a Voronoi cell
148 * vertex from the cell center is R, then no particles more than a distance
149 * 2R away can possibly influence the cell. This a very fast computation to
150 * do, but it has no directionality: if the cell extends a long way in one
151 * direction then particles a long distance in other directions will still
152 * need to be tested.
153 * - Region test: it is possible to test whether a specific region can
154 * possibly influence the cell by applying a series of plane tests at the
155 * point on the region which is closest to the Voronoi cell center. This is a
156 * slower computation to do, but it has directionality.
158 * Another useful observation is that the regions that need to be tested
159 * are simply connected, meaning that if a particular region does not need
160 * to be tested, then neighboring regions which are further away do not
161 * need to be tested.
163 * For maximum efficiency, it was found that a hybrid approach making use of both
164 * of the above tests worked well in practice. Radius tests work well for the
165 * first few blocks, but switching to region tests after then prevent the code
166 * from becoming extremely slow, due to testing over very large spherical shells of
167 * particles. The compute_cell() routine therefore takes the following
168 * approach:
170 * - Initialize the voronoicell class to fill the entire computational domain.
171 * - Cut the cell by any wall objects that have been added to the container.
172 * - Apply plane cuts to the cell corresponding to the other particles which
173 * are within the current particle's region.
174 * - Test over a pre-computed worklist of neighboring regions, that have been
175 * ordered according to the minimum distance away from the particle's
176 * position. Apply radius tests after every few regions to see if the
177 * calculation can terminate.
178 * - If the code reaches the end of the worklist, add all the neighboring
179 * regions to a new list.
180 * - Carry out a region test on the first item of the list. If the region needs
181 * to be tested, apply the plane() routine for all of its particles, and then
182 * add any neighboring regions to the end of the list that need to be tested.
183 * Continue until the list has no elements left.
185 * The compute_cell() routine forms the basis of many other routines, such as
186 * store_cell_volumes() and draw_cells_gnuplot() that can be used to calculate
187 * and draw the cells in the entire container or in a subdomain.
189 * \section walls Wall computation
190 * Wall computations are handled by making use of a pure virtual wall class.
191 * Specific wall types are derived from this class, and require the
192 * specification of two routines: point_inside() that tests to see if a point
193 * is inside a wall or not, and cut_cell() that cuts a cell according to the
194 * wall's position. The walls can be added to the container using the
195 * add_wall() command, and these are called each time a compute_cell() command
196 * is carried out. At present, wall types for planes, spheres, cylinders, and
197 * cones are provided, although custom walls can be added by creating new
198 * classes derived from the pure virtual class. Currently all wall types
199 * approximate the wall surface with a single plane, which produces some small
200 * errors, but generally gives good results for dense particle packings in
201 * direct contact with a wall surface. It would be possible to create more
202 * accurate walls by making cut_cell() routines that approximate the curved
203 * surface with multiple plane cuts.
205 * The wall objects can used for periodic calculations, although to obtain
206 * valid results, the walls should also be periodic as well. For example, in a
207 * domain that is periodic in the x direction, a cylinder aligned along the x
208 * axis could be added. At present, the interior of all wall objects are convex
209 * domains, and consequently any superposition of them will be a convex domain
210 * also. Carrying out computations in non-convex domains poses some problems,
211 * since this could theoretically lead to non-convex Voronoi cells, which the
212 * internal data representation of the voronoicell class does not support. For
213 * non-convex cases where the wall surfaces feature just a small amount of
214 * negative curvature (eg. a torus) approximating the curved surface with a
215 * single plane cut may give an acceptable level of accuracy. For non-convex
216 * cases that feature internal angles, the best strategy may be to decompose
217 * the domain into several convex subdomains, carry out a calculation in each,
218 * and then add the results together. The voronoicell class cannot be easily
219 * modified to handle non-convex cells as this would fundamentally alter the
220 * algorithms that it uses, and cases could arise where a single plane cut
221 * could create several new faces as opposed to just one.
223 * \section templates Extra functionality via the use of templates
224 * C++ templates are often presented as a mechanism for allowing functions to
225 * be coded to work with several different data types. However, they also
226 * provide an extremely powerful mechanism for achieving static polymorphism,
227 * allowing several variations of a program to be compiled from a single source
228 * code. Voro++ makes use of templates in order to handle the radical Voronoi
229 * tessellation and the neighbor calculations, both of which require only
230 * relatively minimal alterations to the main body of code.
232 * The main body of the voronoicell class is written as template named
233 * voronoicell_base. Two additional small classes are then written:
234 * neighbor_track, which contains small, inlined functions that encapsulate all
235 * of the neighbor calculations, and neighbor_none, which contains the same
236 * function names left blank. By making use of the typedef command, two classes
237 * are then created from the template:
239 * - voronoicell: an instance of voronoicell_base with the neighbor_none class.
240 * - voronoicell_neighbor: an instance of voronoicell_base with the
241 * neighbor_track class.
243 * The two classes will be the same, except that the second will get all of the
244 * additional neighbor-tracking functionality compiled into it through the
245 * neighbor_track class. Since the two instances of the template are created
246 * during the compilation, and since all of the functions in neighbor_none and
247 * neighbor_track are inlined, there should be no speed overhead with this
248 * construction; it should have the same efficiency as writing two completely
249 * separate classes. C++ has other methods for achieving similar results, such
250 * as virtual functions and class inheritance, but these are more focused on
251 * dynamic polymorphism, switching between functionality at run-time, resulting
252 * in a drop in performance. This would be particularly apparent in this case,
253 * as the neighbor computation code, while small, is heavily integrated into
254 * the low-level details of the plane() routine, and a virtual function
255 * approach would require a very large number of function address look-ups.
257 * In a similar manner, two small classes called radius_mono and radius_poly
258 * are provided. The first contains all routines suitable for calculate the
259 * standard Voronoi tessellation associated with a monodisperse particle
260 * packing, while the second incorporates variations to carry out the radical
261 * Voronoi tessellation associated with a polydisperse particle packing. Two
262 * classes are then created via typedef commands:
264 * - container: an instance of container_base with the radius_mono class.
265 * - container_poly: an instance of container_base with the radius_poly class.
267 * The container_poly class accepts an additional variable in the put() command
268 * for the particle's radius. These radii are then used to weight the plane
269 * positions in the compute_cell() routine.
271 * It should be noted that the underlying template structure is largely hidden
272 * from a typical user accessing the library's functionality, and as
273 * demonstrated in the examples, the classes listed above behave like regular
274 * C++ classes, and can be used in all the same ways. However, the template
275 * structure may provide an additional method of customizing the code; for
276 * example, an additional radius class could be written to implement a Voronoi
277 * tessellation variant. */
279 #ifndef VOROPP_HH
280 #define VOROPP_HH
282 #include "cell.hh"
283 #include "container.hh"
284 #include "wall.hh"
286 #endif