Kepler’s conjecture: packing efficiency of SC, BCC, FCC, and HCP#

Kepler (1611) guessed that no stacking of equal spheres fills space more densely than the layered (face-centered cubic / hexagonal close) packing, with fraction \(\pi/\sqrt{18}\approx0.7405\). Comparing the four textbook lattices shows the close-packed pair at exactly that bound.

The four lattices implemented here (chemistrykit.crystal.systems.packing) share the LatticePacking interface: each derives its atomic packing factor from pure geometry (touching spheres, atoms-per-cell, and a lattice-constant-to-radius relation). FCC and ideal HCP – both close-packed, differing only in stacking sequence – turn out to share the same maximum packing fraction.

import matplotlib.pyplot as plt
import numpy as np

from chemistrykit.crystal.systems.packing import (
    BodyCenteredCubicPacking,
    FaceCenteredCubicPacking,
    HexagonalClosePacking,
    SimpleCubicPacking,
)
from chemistrykit.crystal.visualizers.crystal_plots import plot_packing_fractions

lattices = {
    "SC": SimpleCubicPacking(),
    "BCC": BodyCenteredCubicPacking(),
    "FCC": FaceCenteredCubicPacking(),
    "HCP (ideal)": HexagonalClosePacking(),
}

for name, lattice in lattices.items():
    pf = lattice.packing_fraction()
    print(f"{name:12s} packing fraction = {pf:.4f}   coordination = {lattice.coordination_number:2d}   atoms/cell = {lattice.atoms_per_cell}")
SC           packing fraction = 0.5236   coordination =  6   atoms/cell = 1.0
BCC          packing fraction = 0.6802   coordination =  8   atoms/cell = 2.0
FCC          packing fraction = 0.7405   coordination = 12   atoms/cell = 4.0
HCP (ideal)  packing fraction = 0.7405   coordination = 12   atoms/cell = 2.0

FCC and ideal HCP are both close-packed and share the same packing fraction, even though the underlying models (cubic vs. hexagonal cell, 4 vs. 2 atoms per cell) look nothing alike:

fcc_pf = lattices["FCC"].packing_fraction()
hcp_pf = lattices["HCP (ideal)"].packing_fraction()
print(f"\nFCC packing fraction:  {fcc_pf:.9f}")
print(f"HCP packing fraction:  {hcp_pf:.9f}")
print(f"Match: {abs(fcc_pf - hcp_pf) < 1e-9}")
print(f"Kepler's bound pi/sqrt(18) = {np.pi / np.sqrt(18.0):.9f}")
assert abs(fcc_pf - np.pi / np.sqrt(18.0)) < 1e-12
FCC packing fraction:  0.740480490
HCP packing fraction:  0.740480490
Match: True
Kepler's bound pi/sqrt(18) = 0.740480490

A real HCP metal’s actual c/a ratio deviates from the ideal value, which lowers its packing fraction below the FCC/ideal-HCP maximum:

zinc_hcp = HexagonalClosePacking(c_over_a=1.856)  # zinc's anomalous c/a
print(f"\nZinc-like HCP (c/a=1.856) packing fraction: {zinc_hcp.packing_fraction():.4f} (below the ideal {hcp_pf:.4f})")
Zinc-like HCP (c/a=1.856) packing fraction: 0.6515 (below the ideal 0.7405)
names = list(lattices.keys())
fractions = [lattices[name].packing_fraction() for name in names]
ax = plot_packing_fractions(names, fractions)
ax.axhline(np.pi / np.sqrt(18.0), color="k", ls="--", lw=1, label=r"Kepler bound $\pi/\sqrt{18}$")
ax.legend()
plt.tight_layout()
plt.show()
Atomic packing factor by lattice type

Total running time of the script: (0 minutes 0.031 seconds)

Gallery generated by Sphinx-Gallery