A Python package for calculating the local and bulk packing density of particles in 3D Cartesian and cylindrical coordinate systems, with capability to mesh a region and visualise packing density distribution.
Above image: Cross-sectional packing density distribution of 100,000 particles (~500-600 microns) in a cylindrical container of diameter 75 mm, with packing density calculated from z = [0.005 m, 0.020 m].
- Requirements
- Installation
- Key Functions
- How It Works
- Testing
- Examples
- Limitations
- Planned Features
- License
- Contact
- Python 3.8 or later*
- *WARNING: As of 28th Nov 2024, the VTK dependency of PyVista does not work with Python 3.13
- NumPy: For efficient numerical operations.
- PyVista: For reading and handling
.vtkfiles.
The package is available on PyPI and can be installed via:
pip install packing3dAlternatively, clone the repository at https://github.com/fjbarter/packing3d/ and install manually from the local files.
Computes the packing density of particles within a defined cuboidal region in Cartesian coordinates.
file(str, optional): Path to the.vtkfile containing particle data. Required if coordinate data is not provided.boundaries(dict, optional): Dictionary defining the cuboidal region boundaries with keysx_min,x_max,y_min,y_max,z_min, andz_max. Defaults to automatic boundaries based on the dataset.x_data,y_data,z_data(np.ndarray, optional): Preloaded x, y, z coordinates of particles.radii(np.ndarray, optional): Preloaded radii of particles.
- float: The packing density as the fraction of volume occupied by particles.
from packing3d import compute_packing_cartesian
packing_density = compute_packing_cartesian(file='particles.vtk')
print(f"Packing Density: {packing_density}")Generates a Cartesian mesh that can approximate a cuboidal or cylindrical region. If cylindrical_mesh_shape is specified True, the exact volume of the cartesian cells which overlap the cylinder walls is calculated and used for the packing density, so there is no need to worry about incorrectly low packing densities at the wall (although they will still be low!).
x_divisions,y_divisions,z_divisions(int): Number of divisions along the x, y, and z axes.boundaries(dict, optional): Dictionary defining the boundaries of the Cartesian region.cylindrical_mesh_shape(bool, optional): Boolean that creates a cylindrical mesh shape with cartesian cells.radius(float, optional): Radius of the cylindrical region to approximate, if applicable.base_level(float, optional): Base level of the cylinder in the z-direction.height(float, optional): Height of the cylindrical region for meshing
- list: A list of tuples, each containing
(indices, boundaries)for each cell.
from packing3d import generate_cartesian_mesh
mesh = generate_cartesian_mesh(x_divisions=10, y_divisions=10, z_divisions=5,
boundaries=boundaries, cylindrical_mesh_shape=False,
radius=None, base_level=None, height=None)
print(mesh)Computes the packing density of particles within a defined cylindrical region in cylindrical coordinates.
file(str, optional): Path to the.vtkfile containing particle data. Required if coordinate data is not provided.boundaries(dict, optional): Dictionary defining the cylindrical region boundaries with keysr_min,r_max,theta_min,theta_max,z_min, andz_max. Defaults to automatic boundaries based on the dataset.r_data,theta_data,z_data(np.ndarray, optional): Preloaded radial, angular, and z coordinates of particles.radii(np.ndarray, optional): Preloaded radii of particles.
- float: The packing density as the fraction of the cylindrical volume occupied by particles.
from packing3d import compute_packing_cylindrical
packing_density = compute_packing_cylindrical(file='particles.vtk')
print(f"Packing Density: {packing_density}")Generates a cylindrical mesh with division indices for radial, angular, and z-direction partitions. There is an inner cylindrical cell, created to avoid problems associated with converging radial lines.
The mesh cells created all have a constant volume, with theta_divisions determining the number of cells in the first ring, outside the inner cylindrical cell. If radius_inner is None, it will have a radius equal to the width of each radial division.
radius(float): Radius of the cylindrical region.height(float): Height of the cylindrical region.r_divisions,theta_divisions,z_divisions(int): Number of divisions in radial, angular, and z directions.- 'radius_inner' (float, optional): Radius of the inner cylindrical cell. Defaults to radius / r_divisions.
- list: A list of tuples, each containing
(indices, boundaries)for each cell.
from packing3d import generate_cylindrical_mesh
mesh = generate_cylindrical_mesh(radius=10, height=20, r_divisions=5, theta_divisions=8, z_divisions=10)
print(mesh)Converts Cartesian coordinates to cylindrical coordinates with theta in [0, 2π].
x_data(np.ndarray): Array of x-coordinates.y_data(np.ndarray): Array of y-coordinates.
r_data(np.ndarray): Radial distances from the origin.theta_data(np.ndarray): Angles in radians from the x-axis, in the range[0, 2π].
Reads a .vtk file using PyVista and returns the data object.
file(str): Path to the.vtkfile.
- pyvista.DataSet: The data object from the
.vtkfile.
Extracts x, y, z coordinates and radii from the dataset.
data: PyVista data object containing particle information.
x_data,y_data,z_data,radii(np.ndarray): Arrays of coordinates and radii.
-
Data Reading:
- Uses PyVista to read
.vtkfiles containing particle coordinates and radii. read_vtk_fileandretrieve_coordinatesfacilitate this process.
- Uses PyVista to read
-
Coordinate Conversion:
- For cylindrical computations, Cartesian coordinates are converted using
convert_to_cylindrical.
- For cylindrical computations, Cartesian coordinates are converted using
-
Boundary Determination:
- Boundaries can be user-defined or automatically computed based on the dataset using
compute_automatic_boundaries.
- Boundaries can be user-defined or automatically computed based on the dataset using
-
Volume Calculations:
- For particles completely inside the boundaries, their full volume is added.
- For particles partially overlapping boundaries, geometric functions compute the exact volume of intersection.
-
Packing Density Computation:
- Total particle volume within the boundaries is divided by the cell volume to obtain the packing density.
- Unit Tests: Planned for future releases to ensure accuracy and reliability.
- Sample Data:
.vtkfiles are provided for testing in the examples directory.
examples.pyin the examples directory provides three examples with corresponding vtk files.
- Optimised for spherical particles only.
- Requires
.vtkfiles with properly formatted particle data.
This project is licensed under the GNU General Public License v3.0. See the LICENSE file for details.
For questions, support, or contributions, reach out to:
- Name: Freddie Barter
- Email: fjbarter@outlook.com