– A cylindrical particle packing

Voronoi tessellation in a cylinder

The direct cell-by-cell construction that Voro++ uses makes it particularly easy to handle non-standard boundary conditions, since the Voronoi cells can be individually tailored by applying additional plane cuts.

Voro++ contains a mechanism for adding walls to a container class, that create additional plane cuts during the cell computation. This is done through a pure virtual wall class, that represents any unspecified wall. This class contains two main functions. The first is point_inside() that returns whether a given point is within the wall or not. The second is cut_cell() that takes a voronoicell, and adds plane cuts due to the presence of the wall. In the header file wall.hh, the classes wall_plane, wall_cylinder, and wall_cone are defined to handle plane, cylinder, and conical walls; other wall types could be added by the user.

This example code demonstrates the use of the cylindrical wall object. The code makes use of the file “pack_cylinder” that was generated from a DEM simulation pouring 2300 particles into a cylindrical container of radius six. In line 22 of the code, a container class is initialized with non-periodic boundaries. In line 26, a wall_cylinder class is constructed. The first three arguments specify a point on the axis of the cylinder, the next three specify the direction of the axis, and the final one determines the cylinder radius. On line 27, the add_wall() function is called, that passes a pointer to the wall to the container class so that it can be referenced by the Voronoi cell computation routines. In the remainder of the code, particle positions are imported and the cells are computed in POV-Ray format.

The image above shows the computed Voronoi cells, rendered using the header file “cylinder.pov”. The cells mesh nicely against the wall, although some discrepancies can be seen, particularly near the top. This is because the cylindrical wall is approximated with a single plane cut. For dense packings this can produce good results, although it may become less accurate for sparsely-distributed particles. Better accuracy could be obtained by approximating the wall by more plane cuts.


Code listing

 1: // Cylindrical wall 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.5,x_max=6.5;
12: const double y_min=-6.5,y_max=6.5;
13: const double z_min=0,z_max=18.5;
15: // Set the computational grid size
16: const int n_x=7,n_y=7,n_z=14;
18: int main() {
19:         // Create a container with the geometry given above, and make it
20:         // non-periodic in each of the three coordinates. Allocate space for
21:         // eight particles within each computational block.
22:         container con(x_min,x_max,y_min,y_max,z_min,z_max,n_x,n_y,n_z,
23:                         false,false,false,8);
25:         // Add a cylindrical wall to the container
26:         wall_cylinder cyl(0,0,0,0,0,1,6);
27:         con.add_wall(cyl);
29:         // Import the particles from a file
30:         con.import("pack_cylinder");
32:         // Output the particle positions in POV-Ray format
33:         con.draw_particles_pov("cylinder_p.pov");
35:         // Output the Voronoi cells in POV-Ray format
36:         con.draw_cells_pov("cylinder_v.pov");
37: }