mod structure

module structure

Naming the local structure a point sits in.

Two analyses that OVITO made standard, ported because this crate needs them for its own reasons rather than for pictures.

The Lennard-Jones sizes this crate is measured on fail by morphology: at 75 points the search settles into an icosahedral funnel and the answer is a Marks decahedron. Every continuous collective variable tried on that distinction was too blunt, the fourth-order bond-order parameter separating the two funnels by 0.023 against a deposition width four times larger. A per-point structural classification is a sharper instrument: an icosahedron and a decahedron differ in what their points are, not by a small number.

Common neighbour analysis

Honeycutt and Andersen. Each bonded pair is labelled by three integers: how many neighbours the two share, how many bonds are among those shared neighbours, and the longest chain those bonds form. A pair inside an icosahedral shell gives 555; a face-centred cubic environment gives 421 and hexagonal close packed gives 422. A decahedron carries a fivefold axis and close-packed facets together, so it shows 555 alongside a substantial 421 population, which an icosahedron does not.

Polyhedral template matching

Larsen, Schmidt and Schiøtz, Robust structural identification via polyhedral template matching, Modelling Simul. Mater. Sci. Eng. 24, 055007 (2016). Common neighbour analysis decides through a bond cutoff, so it degrades when the structure is warm or strained: a bond that falls just outside the cutoff changes the triplet. Template matching instead compares the neighbourhood to ideal templates after scaling and optimal rotation, and reports the residual, so the answer degrades smoothly instead of flipping.

What is implemented here is that comparison. The published method finds the correspondence between a neighbourhood and a template through the topology of the convex hull; this enumerates starting correspondences and refines each by iterated closest point, which is a different way of solving the same subproblem and is stated as such rather than claimed to be theirs. The classification and the residual are the parts anything downstream uses.

Functions

fn atom_triplet_fracs(x: ArrayView1<f64>, n: usize, cutoff: f64) -> Vec<[f64; 3]>

Per-atom fractions of 555 / 421 / 422 among that atom’s bonds.

fn cna(x: ArrayView1<f64>, n: usize, cutoff: f64) -> CnaCounts

Common-neighbour triplets over every bonded pair.

The default cutoff for a Lennard-Jones cluster sits between the first and second neighbour shells, where the radial distribution is near zero, so the bond set is insensitive to its exact value.

fn cna_descriptor(x: ArrayView1<f64>, n: usize, cutoff: f64) -> Array1<f64>

Common-neighbour fractions as a morphology descriptor.

[f555, f421, f422, f544, f433, bonds per point]. These are the triplets that separate the packings the cluster sizes here compete between: 555 is the icosahedral signature, 421 close-packed cubic, 422 hexagonal, and a decahedron carries 555 together with a substantial 421 population, which an icosahedron does not.

Preferred over ptm_fractions for this purpose, and the reason is a measurement rather than a preference. Template matching classifies only points with a complete neighbour shell, which at 38 points is 6 of 38, so its fraction vector is dominated by the surface and resolved 13 distinct morphologies across 218 searches. Common-neighbour analysis reads every bonded pair, including the surface, and costs less because no rotational alignment is involved.

fn ptm(x: ArrayView1<f64>, n: usize, cutoff: f64) -> Vec<Match>

Classifies every point by its local environment.

cutoff is the residual past which nothing is claimed. Larsen and coworkers use a value near 0.1 for warm structures; smaller is stricter.

fn ptm_fractions(x: ArrayView1<f64>, n: usize, cutoff: f64) -> Array1<f64>

Share of points carrying each template, as a descriptor.

Ordered as face-centred cubic, hexagonal close packed, icosahedral, simple cubic, other, so it can be compared by distance like any other fingerprint.

fn ring_profile(x: ArrayView1<f64>, n: usize, cutoff: f64) -> (usize, usize, usize)

Primitive-ring profile of the contact graph: counts of 3-, 4- and 5-rings.

The shortest-path ring criterion of Franzblau (doi:10.1103/PhysRevB.44.4925), the primitive of seams-core’s network analysis: a cycle counts only when no chord shortcuts it, so two fused triangles do not masquerade as a square. Ring statistics separate packing families by topology rather than by any order parameter, and cost nothing but graph walks.

Enums

enum Template

A local structure a neighbourhood can be matched to.

FaceCentredCubic

Twelve neighbours, cuboctahedral.

HexagonalClosePacked

Twelve neighbours, anticuboctahedral.

Icosahedral

Twelve neighbours, icosahedral.

SimpleCubic

Six neighbours, octahedral.

Other

Nothing matched within the residual cutoff.

Implementations

impl Template

Functions

fn all() -> [Template; 4]

The templates a neighbourhood is tried against.

fn points(&self) -> Vec<[f64; 3]>

The ideal neighbour positions, scaled so the mean distance is one.

fn size(&self) -> usize

Neighbours the template is built from.

Structs and Unions

struct CnaCounts

Counts of common-neighbour triplets over the bonded pairs of a structure.

counts: Vec<((usize, usize, usize), usize)>

(r, s, t) keys and how often each occurred.

bonds: usize

Bonded pairs found.

Implementations

impl CnaCounts

Functions

fn fraction(&self, key: (usize, usize, usize)) -> f64

Share of bonded pairs carrying a triplet.

fn get(&self, key: (usize, usize, usize)) -> usize

Occurrences of one triplet.

struct Match

The template a point’s neighbourhood matches, and how well.

template: Template

Best-matching template, or Template::Other past the cutoff.

rmsd: f64

Scale-invariant root-mean-square residual to it.