Voro++
voro++.hh
Go to the documentation of this file.
00001 // Voro++, a 3D cell-based Voronoi library
00002 //
00003 // Author   : Chris H. Rycroft (LBL / UC Berkeley)
00004 // Email    : chr@alum.mit.edu
00005 // Date     : August 30th 2011
00006 
00007 /** \file voro++.hh
00008  * \brief A file that loads all of the Voro++ header files. */
00009 
00010 /** \mainpage Voro++ class reference manual
00011  * \section intro Introduction
00012  * Voro++ is a software library for carrying out three-dimensional computations
00013  * of the Voronoi tessellation. A distinguishing feature of the Voro++ library
00014  * is that it carries out cell-based calculations, computing the Voronoi cell
00015  * for each particle individually, rather than computing the Voronoi
00016  * tessellation as a global network of vertices and edges. It is particularly
00017  * well-suited for applications that rely on cell-based statistics, where
00018  * features of Voronoi cells (eg. volume, centroid, number of faces) can be
00019  * used to analyze a system of particles.
00020  *
00021  * Voro++ is written in C++ and can be built as a static library that can be
00022  * linked to. This manual provides a reference for every function in the class
00023  * structure. For a general overview of the program, see the Voro++ website at
00024  * http://math.lbl.gov/voro++/ and in particular the example programs at
00025  * http://math.lbl.gov/voro++/examples/ that demonstrate many of the library's
00026  * features.
00027  *
00028  * \section class C++ class structure
00029  * The code is structured around several C++ classes. The voronoicell_base
00030  * class contains all of the routines for constructing a single Voronoi cell.
00031  * It represents the cell as a collection of vertices that are connected by
00032  * edges, and there are routines for initializing, making, and outputting the
00033  * cell. The voronoicell_base class form the base of the voronoicell and
00034  * voronoicell_neighbor classes, which add specialized routines depending on
00035  * whether neighboring particle ID information for each face must be tracked or
00036  * not. Collectively, these classes are referred to as "voronoicell classes"
00037  * within the documentation.
00038  *
00039  * There is a hierarchy of classes that represent three-dimensional particle
00040  * systems. All of these are derived from the voro_base class, which contains
00041  * constants that divide a three-dimensional system into a rectangular grid of
00042  * equally-sized rectangular blocks; this grid is used for computational
00043  * efficiency during the Voronoi calculations.
00044  *
00045  * The container_base, container, and container_poly are then derived from the
00046  * voro_base class to represent a particle system in a specific
00047  * three-dimensional rectangular box using both periodic and non-periodic
00048  * boundary conditions. In addition, the container_periodic_base,
00049  * container_periodic, and container_periodic_poly classes represent
00050  * a particle system in a three-dimensional non-orthogonal periodic domain,
00051  * defined by three periodicity vectors that represent a parallelepiped.
00052  * Collectively, these classes are referred to as "container classes" within
00053  * the documentation.
00054  *
00055  * The voro_compute template encapsulates all of the routines for computing
00056  * Voronoi cells. Each container class has a voro_compute template within
00057  * it, that accesses the container's particle system, and computes the Voronoi
00058  * cells.
00059  *
00060  * There are several wall classes that can be used to apply certain boundary
00061  * conditions using additional plane cuts during the Voronoi cell compution.
00062  * The code also contains a number of small loop classes, c_loop_all,
00063  * c_loop_subset, c_loop_all_periodic, and c_loop_order that can be used to
00064  * iterate over a certain subset of particles in a container. The latter class
00065  * makes use of a special particle_order class that stores a specific order of
00066  * particles within the container. The library also contains the classes
00067  * pre_container_base, pre_container, and pre_container_poly, that can be used
00068  * as temporary storage when importing data of unknown size.
00069  *
00070  * \section voronoicell The voronoicell classes
00071  * The voronoicell class represents a single Voronoi cell as a convex
00072  * polyhedron, with a set of vertices that are connected by edges. The class
00073  * contains a variety of functions that can be used to compute and output the
00074  * Voronoi cell corresponding to a particular particle. The command init()
00075  * can be used to initialize a cell as a large rectangular box. The Voronoi cell
00076  * can then be computed by repeatedly cutting it with planes that correspond to
00077  * the perpendicular bisectors between that particle and its neighbors.
00078  *
00079  * This is achieved by using the plane() routine, which will recompute the
00080  * cell's vertices and edges after cutting it with a single plane. This is the
00081  * key routine in voronoicell class. It begins by exploiting the convexity
00082  * of the underlying cell, tracing between edges to work out if the cell
00083  * intersects the cutting plane. If it does not intersect, then the routine
00084  * immediately exits. Otherwise, it finds an edge or vertex that intersects
00085  * the plane, and from there, traces out a new face on the cell, recomputing
00086  * the edge and vertex structure accordingly.
00087  *
00088  * Once the cell is computed, there are many routines for computing features of
00089  * the the Voronoi cell, such as its volume, surface area, or centroid. There
00090  * are also many routines for outputting features of the Voronoi cell, or
00091  * writing its shape in formats that can be read by Gnuplot or POV-Ray.
00092  *
00093  * \subsection internal Internal data representation
00094  * The voronoicell class has a public member p representing the
00095  * number of vertices. The polyhedral structure of the cell is stored
00096  * in the following arrays:
00097  *
00098  * - pts: a one-dimensional array of floating point numbers, that represent the
00099  *   position vectors x_0, x_1, ..., x_{p-1} of the polyhedron vertices.
00100  * - nu: the order of each vertex n_0, n_1, ..., n_{p-1}, corresponding to
00101  *   the number of other vertices to which each is connected.
00102  * - ed: a two-dimensional table of edges and relations. For the ith vertex,
00103  *   ed[i] has 2n_i+1 elements. The first n_i elements are the edges e(j,i),
00104  *   where e(j,i) is the jth neighbor of vertex i. The edges are ordered
00105  *   according to a right-hand rule with respect to an outward-pointing normal.
00106  *   The next n_i elements are the relations l(j,i) which satisfy the property
00107  *   e(l(j,i),e(j,i)) = i. The final element of the ed[i] list is a back
00108  *   pointer used in memory allocation.
00109  *
00110  * In a very large number of cases, the values of n_i will be 3. This is because
00111  * the only way that a higher-order vertex can be created in the plane()
00112  * routine is if the cutting plane perfectly intersects an existing vertex. For
00113  * random particle arrangements with position vectors specified to double
00114  * precision this should happen very rarely. A preliminary version of this code
00115  * was quite successful with only making use of vertices of order 3. However,
00116  * when calculating millions of cells, it was found that this approach is not
00117  * robust, since a single floating point error can invalidate the computation.
00118  * This can also be a problem for cases featuring crystalline arrangements of
00119  * particles where the corresponding Voronoi cells may have high-order vertices
00120  * by construction.
00121  *
00122  * Because of this, Voro++ takes the approach that it if an existing vertex is
00123  * within a small numerical tolerance of the cutting plane, it is treated as
00124  * being exactly on the plane, and the polyhedral topology is recomputed
00125  * accordingly. However, while this improves robustness, it also adds the
00126  * complexity that n_i may no longer always be 3. This causes memory management
00127  * to be significantly more complicated, as different vertices require a
00128  * different number of elements in the ed[][] array. To accommodate this, the
00129  * voronoicell class allocated edge memory in a different array called mep[][],
00130  * in such a way that all vertices of order k are held in mep[k]. If vertex
00131  * i has order k, then ed[i] points to memory within mep[k]. The array ed[][]
00132  * is never directly initialized as a two-dimensional array itself, but points
00133  * at allocations within mep[][]. To the user, it appears as though each row of
00134  * ed[][] has a different number of elements. When vertices are added or
00135  * deleted, care must be taken to reorder and reassign elements in these
00136  * arrays.
00137  *
00138  * During the plane() routine, the code traces around the vertices of the cell,
00139  * and adds new vertices along edges which intersect the cutting plane to
00140  * create a new face. The values of l(j,i) are used in this computation, as
00141  * when the code is traversing from one vertex on the cell to another, this
00142  * information allows the code to immediately work out which edge of a vertex
00143  * points back to the one it came from. As new vertices are created, the l(j,i)
00144  * are also updated to ensure consistency. To ensure robustness, the plane
00145  * cutting algorithm should work with any possible combination of vertices
00146  * which are inside, outside, or exactly on the cutting plane.
00147  *
00148  * Vertices exactly on the cutting plane create some additional computational
00149  * difficulties. If there are two marginal vertices connected by an existing
00150  * edge, then it would be possible for duplicate edges to be created between
00151  * those two vertices, if the plane routine traces along both sides of this
00152  * edge while constructing the new face. The code recognizes these cases and
00153  * prevents the double edge from being formed. Another possibility is the
00154  * formation of vertices of order two or one. At the end of the plane cutting
00155  * routine, the code checks to see if any of these are present, removing the
00156  * order one vertices by just deleting them, and removing the order two
00157  * vertices by connecting the two neighbors of each vertex together. It is
00158  * possible that the removal of a single low-order vertex could result in the
00159  * creation of additional low-order vertices, so the process is applied
00160  * recursively until no more are left.
00161  *
00162  * \section container The container classes
00163  * There are four container classes available for general usage: container,
00164  * container_poly, container_periodic, and container_periodic_poly. Each of
00165  * these represent a system of particles in a specific three-dimensional
00166  * geometry. They contain routines for importing particles from a text file,
00167  * and adding particles individually. They also contain a large number of
00168  * analyzing and outputting the particle system. Internally, the routines that
00169  * compute Voronoi cells do so by making use of the voro_compute template.
00170  * Each container class contains routines that tell the voro_compute template
00171  * about the specific geometry of this container.
00172  *
00173  * \section voro_compute The voro_compute template
00174  * The voro_compute template encapsulates the routines for carrying out the
00175  * Voronoi cell computations. It contains data structures suchs as a mask and a
00176  * queue that are used in the computations. The voro_compute template is
00177  * associated with a specific container class, and during the computation, it
00178  * calls routines in the container class to access the particle positions that
00179  * are stored there.
00180  *
00181  * The key routine in this class is compute_cell(), which makes use of a
00182  * voronoicell class to construct a Voronoi cell for a specific particle in the
00183  * container. The basic approach that this function takes is to repeatedly cut
00184  * the Voronoi cell by planes corresponding neighboring particles, and stop
00185  * when it recognizes that all the remaining particles in the container are too
00186  * far away to possibly influence cell's shape. The code makes use of two
00187  * possible methods for working out when a cell computation is complete:
00188  *
00189  * - Radius test: if the maximum distance of a Voronoi cell
00190  *   vertex from the cell center is R, then no particles more than a distance
00191  *   2R away can possibly influence the cell. This a very fast computation to
00192  *   do, but it has no directionality: if the cell extends a long way in one
00193  *   direction then particles a long distance in other directions will still
00194  *   need to be tested.
00195  * - Region test: it is possible to test whether a specific region can
00196  *   possibly influence the cell by applying a series of plane tests at the
00197  *   point on the region which is closest to the Voronoi cell center. This is a
00198  *   slower computation to do, but it has directionality.
00199  *
00200  * Another useful observation is that the regions that need to be tested are
00201  * simply connected, meaning that if a particular region does not need to be
00202  * tested, then neighboring regions which are further away do not need to be
00203  * tested.
00204  *
00205  * For maximum efficiency, it was found that a hybrid approach making use of
00206  * both of the above tests worked well in practice. Radius tests work well for
00207  * the first few blocks, but switching to region tests after then prevent the
00208  * code from becoming extremely slow, due to testing over very large spherical
00209  * shells of particles. The compute_cell() routine therefore takes the
00210  * following approach:
00211  *
00212  * - Initialize the voronoicell class to fill the entire computational domain.
00213  * - Cut the cell by any wall objects that have been added to the container.
00214  * - Apply plane cuts to the cell corresponding to the other particles which
00215  *   are within the current particle's region.
00216  * - Test over a pre-computed worklist of neighboring regions, that have been
00217  *   ordered according to the minimum distance away from the particle's
00218  *   position. Apply radius tests after every few regions to see if the
00219  *   calculation can terminate.
00220  * - If the code reaches the end of the worklist, add all the neighboring
00221  *   regions to a new list.
00222  * - Carry out a region test on the first item of the list. If the region needs
00223  *   to be tested, apply the plane() routine for all of its particles, and then
00224  *   add any neighboring regions to the end of the list that need to be tested.
00225  *   Continue until the list has no elements left.
00226  *
00227  * The compute_cell() routine forms the basis of many other routines, such as
00228  * store_cell_volumes() and draw_cells_gnuplot() that can be used to calculate
00229  * and draw the cells in a container.
00230  *
00231  * \section walls Wall computation
00232  * Wall computations are handled by making use of a pure virtual wall class.
00233  * Specific wall types are derived from this class, and require the
00234  * specification of two routines: point_inside() that tests to see if a point
00235  * is inside a wall or not, and cut_cell() that cuts a cell according to the
00236  * wall's position. The walls can be added to the container using the
00237  * add_wall() command, and these are called each time a compute_cell() command
00238  * is carried out. At present, wall types for planes, spheres, cylinders, and
00239  * cones are provided, although custom walls can be added by creating new
00240  * classes derived from the pure virtual class. Currently all wall types
00241  * approximate the wall surface with a single plane, which produces some small
00242  * errors, but generally gives good results for dense particle packings in
00243  * direct contact with a wall surface. It would be possible to create more
00244  * accurate walls by making cut_cell() routines that approximate the curved
00245  * surface with multiple plane cuts.
00246  *
00247  * The wall objects can used for periodic calculations, although to obtain
00248  * valid results, the walls should also be periodic as well. For example, in a
00249  * domain that is periodic in the x direction, a cylinder aligned along the x
00250  * axis could be added. At present, the interior of all wall objects are convex
00251  * domains, and consequently any superposition of them will be a convex domain
00252  * also. Carrying out computations in non-convex domains poses some problems,
00253  * since this could theoretically lead to non-convex Voronoi cells, which the
00254  * internal data representation of the voronoicell class does not support. For
00255  * non-convex cases where the wall surfaces feature just a small amount of
00256  * negative curvature (eg. a torus) approximating the curved surface with a
00257  * single plane cut may give an acceptable level of accuracy. For non-convex
00258  * cases that feature internal angles, the best strategy may be to decompose
00259  * the domain into several convex subdomains, carry out a calculation in each,
00260  * and then add the results together. The voronoicell class cannot be easily
00261  * modified to handle non-convex cells as this would fundamentally alter the
00262  * algorithms that it uses, and cases could arise where a single plane cut
00263  * could create several new faces as opposed to just one.
00264  *
00265  * \section loops Loop classes
00266  * The container classes have a number of simple routines for calculating
00267  * Voronoi cells for all particles within them. However, in some situations it
00268  * is desirable to iterate over a specific subset of particles. This can be
00269  * achieved with the c_loop classes that are all derived from the c_loop_base
00270  * class. Each class can iterate over a specific subset of particles in a
00271  * container. There are three loop classes for use with the container and
00272  * container_poly classes:
00273  *
00274  * - c_loop_all will loop over all of the particles in a container.
00275  * - c_loop_subset will loop over a subset of particles in a container that lie
00276  *   within some geometrical region. It can loop over particles in a
00277  *   rectangular box, particles in a sphere, or particles that lie within
00278  *   specific internal computational blocks.
00279  * - c_loop_order will loop over a specific list of particles that were
00280  *   previously stored in a particle_order class.
00281  *
00282  * Several of the key routines within the container classes (such as
00283  * draw_cells_gnuplot and print_custom) have versions where they can be passed
00284  * a loop class to use. Loop classes can also be used directly and there are
00285  * some examples on the library website that demonstrate this. It is also
00286  * possible to write custom loop classes.
00287  *
00288  * In addition to the loop classes mentioned above, there is also a
00289  * c_loop_all_periodic class, that is specifically for use with the
00290  * container_periodic and container_periodic_poly classes. Since the data
00291  * structures of these containers differ considerably, it requires a different
00292  * loop class that is not interoperable with the others.
00293  *
00294  * \section pre_container The pre_container classes
00295  * Voro++ makes use of internal computational grid of blocks that are used to
00296  * configure the code for maximum efficiency. As discussed on the library
00297  * website, the best performance is achieved for around 5 particles per block,
00298  * with anything in the range from 3 to 12 giving good performance. Usually
00299  * the size of the grid can be chosen by ensuring that the number of blocks is
00300  * equal to the number of particles divided by 5.
00301  *
00302  * However, this can be difficult to choose in cases when the number of
00303  * particles is not known a priori, and in thes cases the pre_container classes
00304  * can be used. They can import an arbitrary number of particle positions from
00305  * a file, dynamically allocating memory in chunks as necessary. Once particles
00306  * are imported, they can guess an optimal block arrangement to use for the
00307  * container class, and then transfer the particles to the container. By
00308  * default, this procedure is used by the command-line utility to enable it to
00309  * work well with arbitrary sizes of input data.
00310  *
00311  * The pre_container class can be used when no particle radius information is
00312  * available, and the pre_container_poly class can be used when radius
00313  * information is available. At present, the pre_container classes can only be
00314  * used with the container and container_poly classes. They do not support
00315  * the container_periodic and container_periodic_poly classes. */
00316 
00317 #ifndef VOROPP_HH
00318 #define VOROPP_HH
00319 
00320 #include "config.hh"
00321 #include "common.hh"
00322 #include "cell.hh"
00323 #include "v_base.hh"
00324 #include "rad_option.hh"
00325 #include "container.hh"
00326 #include "unitcell.hh"
00327 #include "container_prd.hh"
00328 #include "pre_container.hh"
00329 #include "v_compute.hh"
00330 #include "c_loops.hh"
00331 #include "wall.hh"
00332 
00333 #endif