Voronoi Tessellation#

Voronoi tessellation partitions space into cells around each atom. pyscal uses it for:

  1. Neighbor finding via find_neighbors(method="voronoi")

  2. Voronoi vectors \((n_3, n_4, n_5, n_6)\) — the number of Voronoi faces with 3, 4, 5, or 6 edges

The Voronoi vector is a structural fingerprint: for example, FCC has \((0, 12, 0, 0)\) and BCC has \((0, 6, 0, 8)\).

Important: You must call find_neighbors(method='voronoi') before computing Voronoi vectors.

import pyscal
from pyscal.structures import make_crystal
import numpy as np

Computing Voronoi Vectors#

fcc = make_crystal("fcc", lattice_constant=3.6, repetitions=(4, 4, 4))

# Step 1: Find neighbors using Voronoi
pyscal.find_neighbors(fcc, method="voronoi")

# Step 2: Compute Voronoi vectors
voro = pyscal.voronoi_vector(fcc)

print(f"Shape: {voro.shape}  (n_atoms x 4)")
print(f"First atom: n3={voro[0,0]}, n4={voro[0,1]}, n5={voro[0,2]}, n6={voro[0,3]}")
print(f"Expected for FCC: (0, 12, 0, 0)")
Shape: (256, 4)  (n_atoms x 4)
First atom: n3=0, n4=12, n5=0, n6=0
Expected for FCC: (0, 12, 0, 0)

Comparing Structures#

structures = {
    "FCC": make_crystal("fcc", lattice_constant=3.6, repetitions=(4, 4, 4)),
    "BCC": make_crystal("bcc", lattice_constant=2.87, repetitions=(4, 4, 4)),
    "HCP": make_crystal("hcp", lattice_constant=3.2, repetitions=(4, 4, 4), ca_ratio=1.633),
}

print(f"{'Structure':<10} {'n3':>4} {'n4':>4} {'n5':>4} {'n6':>4}")
print("-" * 30)
for name, s in structures.items():
    pyscal.find_neighbors(s, method="voronoi")
    v = pyscal.voronoi_vector(s)
    # Show the most common Voronoi vector
    print(f"{name:<10} {v[0,0]:>4} {v[0,1]:>4} {v[0,2]:>4} {v[0,3]:>4}")
Structure    n3   n4   n5   n6
------------------------------
FCC           0   12    0    0
BCC           0    6    0    8
HCP           0   12    0    0

Voronoi Volumes#

When you call find_neighbors(method='voronoi'), pyscal also computes Voronoi volumes.

atoms = make_crystal("fcc", lattice_constant=3.6, repetitions=(4, 4, 4))
pyscal.find_neighbors(atoms, method="voronoi")

# Voronoi volumes
volumes = atoms.arrays["pyscal_voronoi_volume"]
print(f"Voronoi volume (atom 0): {volumes[0]:.4f}")
print(f"Mean volume: {volumes.mean():.4f}")
Voronoi volume (atom 0): 11.6640
Mean volume: 11.6640