Voro++
|
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