Supercells and volume ranges

Public API for HNF, Supercell, and the SupercellSelection family.

Enumlib.HNFType
HNF{D}

A Hermite Normal Form matrix in D dimensions: a lower-triangular integer matrix with positive diagonal entries and sub-diagonal entries reduced into [0, m[i,i]). The determinant n = ∏ m[i,i] is the supercell index — the number of parent cells fitting inside the supercell B = parent.A * h.matrix.

Construction validates the HNF form (lower-triangular, positive diagonal, sub-diagonal range). Once built, an HNF{D} is guaranteed to satisfy the form; downstream code can rely on that without re-checking.

HNF{D} is parametric on the spatial dimension D. Almost all uses are D=3; the constructor infers D from size(matrix, 1).

source
Enumlib.SupercellType
Supercell{D}

A symmetry-inequivalent supercell representative: an HNF{D} plus the cached SNF diagonal and the permutation group induced by the parent space-group operations that fix the superlattice. Carries the per-supercell data the labeling enumeration reuses across all colorings on this supercell.

Cached fields

  • hnf — the supercell-defining HNF.
  • snf — diagonal of the Smith Normal Form decomposition of hnf.matrix. Length D, with s_1 | s_2 | ... | s_D. Used by the labeling enumeration to index supercell sites.
  • n_stabilizer_ops — number of parent.space_group operations whose action fixes the superlattice (the order of the stabilizer subgroup).
  • permutation_group — permutations of the n × n_D supercell sites induced by the stabilizer's rotations composed with the supercell's translation group. This is what the labeling enumeration consults when crossing out symmetry-equivalent labelings.
  • hnf_degeneracy — the size of this supercell's parent-point-group orbit on the set of volume-n HNFs. Mirrors the Fortran enumlib's hnf_degen. Diagnostic-grade.

Construction

Supercell(hnf::HNF{D}, parent::ParentLattice{D}) builds the SNF, finds the stabilizer subgroup of parent.space_group, and constructs the permutation group via getPermG. The permutation-group construction is cached at construction time — small memory cost (~kB per supercell) for substantial savings during the labeling enumeration loop, which consults permutation_group once per labeling check.

hnf_degeneracy is computed on demand by counting the HNF's parent-point-group orbit at the given volume. For batch construction inside enumerate(...), the degeneracy is precomputed via getSymInequivHNFs_with_degeneracies and passed in to skip the recomputation: Supercell(hnf, parent; hnf_degeneracy = precomputed).

Examples

Building one of FCC's two symmetry-inequivalent volume-2 supercells:

julia> p = ParentLattice([0.0 0.5 0.5; 0.5 0.0 0.5; 0.5 0.5 0.0]);

julia> sc = Supercell(enumerate_hnfs(VolumeRange(2:2), p)[1], p)
Supercell{3} (n = 2, |stabilizer| = 12, |perm group| = 2, hnf_degeneracy = 4)
  HNF: 1 0 0 / 0 1 0 / 0 0 2
  SNF diag: [1, 1, 2]

julia> volume(sc.hnf)
2

julia> sc.snf
3-element Vector{Int64}:
 1
 1
 2
source
Enumlib.volumeFunction
volume(h::HNF) -> Int

The supercell volume / index — the number of parent cells fitting inside the supercell defined by h. Equals the product of the diagonal entries (since h.matrix is lower-triangular, this is also its determinant).

Examples

julia> h = HNF([1 0 0; 0 2 0; 0 0 3]);

julia> volume(h)
6
source
Enumlib.SupercellSelectionType
abstract type SupercellSelection end

User-facing description of "which supercells should we enumerate over?". Three concrete subtypes:

  • VolumeRange(range) — enumerate all symmetry-inequivalent HNFs of supercell volume in range.
  • RadiusBound(; max_radius_ratio, max_volume) — enumerate HNFs whose avg_cell_radius is at most max_radius_ratio times the parent cell's, with a max_volume safety stop.
  • ExplicitHNFs(hnfs) — pass a hand-curated list of HNFs through; no symmetry reduction happens (the user has already done it).

The dispatcher enumerate_hnfs(::SupercellSelection, parent) turns any selection into a concrete Vector{HNF{D}} that downstream code can iterate over uniformly.

source
Enumlib.VolumeRangeType
VolumeRange(range::AbstractRange{Int})

Enumerate all symmetry-inequivalent HNFs whose volume det(h) lies in range. The most common selection — covers the "I want all supercells of size 2 through 8" use case.

source
Enumlib.RadiusBoundType
RadiusBound(; max_radius_ratio::Real, max_volume::Integer = typemax(Int))

Enumerate symmetry-inequivalent HNFs whose Minkowski-reduced cell radius (per avg_cell_radius) is at most max_radius_ratio times the parent cell's own radius. The max_volume is a safety stop — without it, very large max_radius_ratio values would scan unbounded volumes.

The radius measure is the average distance from cell center to the 8 corners of the Minkowski-reduced basis. Average gives finer tie-breaking than max-distance and is more descriptive for elongated cells.

source
Enumlib.ExplicitHNFsType
ExplicitHNFs(hnfs::AbstractVector{HNF{D}})

Enumerate over a user-supplied list of HNFs. No symmetry reduction or filtering — the dispatcher passes the list through unchanged, since the user has already curated it.

Useful for: domain-specific HNF filters, regression tests against literature reference cases, hand-picked supercells the user wants to study individually.

source
Enumlib.enumerate_hnfsFunction
enumerate_hnfs(s::SupercellSelection, parent::ParentLattice{D}) -> Vector{HNF{D}}

Turn a SupercellSelection into a concrete Vector{HNF{D}} for the parent lattice. Three methods, one per subtype:

  • VolumeRange: loop through volumes in the range; concatenate per-volume getSymInequivHNFs results.
  • RadiusBound: scan volumes 1..max_volume, compute each candidate's avg_cell_radius, keep those within the bound, then symmetry-reduce.
  • ExplicitHNFs: pass through unchanged.

Downstream code (enumerate(...)) treats the returned vector uniformly regardless of which selection produced it.

Examples

FCC has 2 symmetry-inequivalent HNFs at volume 2:

julia> p = ParentLattice([0.0 0.5 0.5; 0.5 0.0 0.5; 0.5 0.5 0.0]);

julia> hnfs = enumerate_hnfs(VolumeRange(2:2), p);

julia> length(hnfs)
2

julia> volume.(hnfs)
2-element Vector{Int64}:
 2
 2
source
Enumlib.avg_cell_radiusFunction
avg_cell_radius(B) -> Float64

Get the average distance from the center of the unit cell B to its 8 corners. Used as a unit-cell size measure for the radius-based supercell selection (RadiusBound). Minkowski-reduces the basis first so the measure is independent of the user's cell representation (e.g., a skewed basis and its Minkowski-reduced equivalent get the same value).

Average distance (rather than max) gives finer tie-breaking — 8 corner distances rarely all match pairwise — and is more descriptive for elongated cells (max gets dominated by the longest direction; avg weights all axes smoothly). For a cube avg ≈ max ≈ side·√3/2 so the difference only shows up for non-cubic cells.

Examples

A unit cube spans [0, 1]^3; its center is at (0.5, 0.5, 0.5), equidistant from all 8 corners at √3/2 ≈ 0.866.

julia> using LinearAlgebra: I

julia> avg_cell_radius(Matrix{Float64}(I, 3, 3))
0.8660254037844385
source