– Dealing with irregular particle packings

Voronoi tessellation of an irregular particle packing

A common problem is to find an adequate method of prescribing boundary conditions when faced with an irregular cluster of particles. If the standard approach was used of placing a group of particles within a larger container, then the Voronoi cells for particles at the edges of the packing would be very large and extend off to the edges of the container.

This example presents a simple method of dealing with this problem, without creating very large Voronoi cells. Usually, when Voro++ creates Voronoi cells, it first initializes them to fill the entire container, and then cuts them down by making plane cuts that are the perpendicular bisectors with neighboring particles. To stop the Voronoi cells from becoming very large, one approach is to first initialize them to be a small polyhedron surrounding each particle. Voro++ will then cut them down based upon nearby particles, but the cells will never stretch beyond the initial polyhedron.

In this code, this is achieved by creating a new wall class called wall_initial_shape. When created, the class constructs a dodecahedron in a voronoicell class. Usually, wall classes function by applying plane cuts to Voronoi cells prior to the main computation. However, here, the wall class replaces the entire cell with a dodecahedron, which will then be used in the main computation. For the image above, for particles ont the outside, the silhouettes of the dodecahedron are visible, but within the packing, plane cuts are applied that will match the usual Voronoi tessellation.

The figure to the right represents a single Voronoi cell and particle from the packing above. The initial dodecahedron shape is shown in yellow. Once the cell is constructed, some of the original dodecahedron faces are still visible, but additional planes have been introduced to match the Voronoi tessellation

The use of a dodecahedron is arbitrary, and could be modified to any shape in the constructor on lines 28 to 34. One approach may be initialize every Voronoi cell to be an approximation to a sphere, in cases where it may be desirable for each particle to have influence up to a certain radius.

Code listing

 1: // Irregular packing example code
 2: //
 3: // Author   : Chris H. Rycroft (LBL / UC Berkeley)
 4: // Email    :
 5: // Date     : August 30th 2011
 7: #include "voro++.hh"
 8: using namespace voro;
10: // Set up constants for the container geometry
11: const double x_min=-6,x_max=6;
12: const double y_min=-6,y_max=6;
13: const double z_min=-3,z_max=9;
15: // Golden ratio constants
16: const double Phi=0.5*(1+sqrt(5.0));
17: const double phi=0.5*(1-sqrt(5.0));
19: // Set up the number of blocks that the container is divided
20: // into.
21: const int n_x=5,n_y=5,n_z=5;
23: // Create a wall class that, whenever called, will replace the Voronoi cell
24: // with a prescribed shape, in this case a dodecahedron
25: class wall_initial_shape : public wall {
26:         public:
27:                 wall_initial_shape() {
29:                         // Create a dodecahedron
30:                         v.init(-2,2,-2,2,-2,2);
31:                         v.plane(0,Phi,1);v.plane(0,-Phi,1);v.plane(0,Phi,-1);
32:                         v.plane(0,-Phi,-1);v.plane(1,0,Phi);v.plane(-1,0,Phi);
33:                         v.plane(1,0,-Phi);v.plane(-1,0,-Phi);v.plane(Phi,1,0);
34:                         v.plane(-Phi,1,0);v.plane(Phi,-1,0);v.plane(-Phi,-1,0);
35:                 };
36:                 bool point_inside(double x,double y,double z) {return true;}
37:                 bool cut_cell(voronoicell &c,double x,double y,double z) {
39:                         // Set the cell to be equal to the dodecahedron
40:                         c=v;
41:                         return true;
42:                 }
43:                 bool cut_cell(voronoicell_neighbor &c,double x,double y,double z) {
45:                         // Set the cell to be equal to the dodecahedron
46:                         c=v;
47:                         return true;
48:                 }
49:         private:
50:                 voronoicell v;
51: };
53: int main() {
55:         // Create a container with the geometry given above. This is bigger
56:         // than the particle packing itself.
57:         container con(x_min,x_max,y_min,y_max,z_min,z_max,n_x,n_y,n_z,
58:                         false,false,false,8);
60:         // Create the "initial shape" wall class and add it to the container
61:         wall_initial_shape(wis);
62:         con.add_wall(wis);
64:         // Import the irregular particle packing
65:         con.import("pack_irregular");
67:         // Save the particles and Voronoi cells in POV-Ray format
68:         con.draw_particles_pov("irregular_p.pov");
69:         con.draw_cells_pov("irregular_v.pov");
70: }