mod soap

module soap

SOAP power spectrum and Cartesian pullback through ∂p/∂R. SOAP power spectrum and the Cartesian pullback through its Jacobian.

Local fingerprints are per-atom power spectra p_{nn'l}(i) = Σ_m c_{nlm}(i) c_{n'lm}(i) with c_{nlm}(i) = Σ_{j≠i} w_n(r_{ij}) Y_{lm}(hat r_{ij}). The map is R^{3N} R^{N n_feat}. Its Jacobian is analytic: each pair contributes ∂w/∂r and ∂Y/∂r̂ through the projector (I r̂ᵀ)/r. Finite differences are not that map — they cost O(N) SOAP evals, they jump at the cutoff, and a 24-D global average has rank at most 24 in R^{3N}, so it cannot see which atoms carry icosahedral versus fivefold-join environments.

A residual step is a direction on the cloud of local spectra. The recommended hop is the observed-cloud residual 2p μ, partitioned by observed atomic numbers and by the mobile mask. That is the same map on a Lennard-Jones cluster, a water cluster, and an adsorbate on a frozen slab: no CNA class, no fcc prototype. Frozen atoms stay in the neighbour list and do not move. When the cloud of a species is a Dirac the residual vanishes and SOAP yields rather than inventing a packing. The Cartesian step is the Tikhonov pullback of the stacked leftover [Δp; Δχ] through the stacked analytic Jacobian. The hop fingerprint is SOAP at l_max = 6 plus the ACE ν=3 / λ-SOAP CG contraction of the same spherical expansion. Ih is silent in the power spectrum until l = 6. Surface coordination is SOFI/IRA (a length), not this map. The 555→421 / fcc-prototype residual is an oracle. Opt-in, cluster only.

Functions

fn class_masses(x: ArrayView1<f64>, spec: SoapSpec) -> [f64; 3]

Soft class masses (m_555, m_421, m_422).

fn class_residual_rms(x: ArrayView1<f64>, spec: SoapSpec) -> f64

RMS of 555-class SOAP toward the 421 target. O(1) on a Mackay ico.

fn class_target(x: ArrayView1<f64>, spec: SoapSpec) -> Array1<f64>

Oracle target: 555 atoms toward 421 (occupied mean, else fcc prototype).

Invents a close-packed class when the observed cloud has none. Same class as a template reseed. Not the recommended hop.

fn fivefold_axis_count(x: ArrayView1<f64>) -> usize

Number of candidate axes whose fivefold length is below FIVEFOLD_AXIS.

fn fivefold_axis_table(x: ArrayView1<f64>) -> Vec<([f64; 3], f64)>

Candidate axis and its fivefold length, best first.

fn fivefold_length(x: ArrayView1<f64>) -> f64

Fivefold SOFI/greedy length of x about the best candidate axis.

fn fivefold_probe(x: ArrayView1<f64>, rmsd: f64) -> FivefoldProbe

Probe the fivefold hop: length, residual concentration, gated yield.

fn ih_dominated(x: ArrayView1<f64>, spec: SoapSpec) -> bool

True when the contact graph carries a substantial 555 (icosahedral) fraction.

Observation, not a hop target. Used to withhold Ih-preserving symmetrise. Does not name a destination packing.

fn jacobian(x: ArrayView1<f64>, spec: SoapSpec) -> Array2<f64>

Analytic Jacobian of the stacked local spectra, shape (N dim, 3N).

fn jacobian_ace(x: ArrayView1<f64>, spec: SoapSpec, species: Option<&[u32]>) -> Array2<f64>

Analytic Jacobian of the ACE ν=3 block, shape (N · nu3_feat, 3N).

fn jacobian_fd(x: ArrayView1<f64>, spec: SoapSpec, eps: f64) -> Array2<f64>

Finite-difference Jacobian of the global average, test-only.

fn jacobian_four(x: ArrayView1<f64>, spec: SoapSpec, species: Option<&[u32]>) -> Array2<f64>

Analytic Jacobian of the two 4-body triple invariants, shape (N · nu3_dim, 3N).

fn jacobian_nu3(x: ArrayView1<f64>, spec: SoapSpec, species: Option<&[u32]>) -> Array2<f64>

Stacked Jacobian of SOAP power spectrum and ACE ν=3 scalars.

fn jacobian_z(x: ArrayView1<f64>, spec: SoapSpec, species: Option<&[u32]>) -> Array2<f64>

Analytic Jacobian of stacked local spectra, species channels included.

fn local_nu3(x: ArrayView1<f64>, spec: SoapSpec) -> Array2<f64>

SOAP power spectrum concatenated with the two 4-body triple invariants.

Three unit directions have three rotational invariants. Pairwise dots collapse into the SOAP l=1 power. The other two are [û_j·(û_k×û_p)]² and (û_j·û_k)(û_k·û_p)(û_p·û_j). featomic’s λ-SOAP / ACE ν=3 is the CG contraction that produces the same scalars from the spherical expansion.

fn local_nu3_z(x: ArrayView1<f64>, spec: SoapSpec, species: Option<&[u32]>) -> Array2<f64>

Species-aware SOAP plus the same 4-body scalars (all neighbors).

fn local_spectra(x: ArrayView1<f64>, spec: SoapSpec) -> Array2<f64>

Per-atom power spectra, shape (N, dim). One neighbour-species channel.

fn local_spectra_z(x: ArrayView1<f64>, spec: SoapSpec, species: Option<&[u32]>) -> Array2<f64>

Per-atom power spectra. With species, one channel per observed neighbour atomic number, concatenated. Shape (N, feat_dim).

fn mean_residual_rms(x: ArrayView1<f64>, spec: SoapSpec) -> f64

RMS of 555-class SOAP from that class’s own mean. Near zero on Mackay ico.

fn power_spectrum(x: ArrayView1<f64>, spec: SoapSpec) -> Array1<f64>

Packed average SOAP of x (flattened 3N).

fn prototype_spectrum(kind: usize, spec: SoapSpec) -> Array1<f64>

SOAP of the centre atom of an ideal neighbourhood template.

0 = icosahedral (555), 1 = fcc cuboctahedron (421), 2 = hcp (422). Classifier / diagnostic only. Feeding this into a hop target is an oracle: the search then presupposes a packing it has not observed.

fn pullback(x: ArrayView1<f64>, target: ArrayView1<f64>, spec: SoapSpec) -> Array1<f64>

Cartesian displacement that realises a SOAP residual through analytic J.

fn pullback_nu3(x: ArrayView1<f64>, target: ArrayView1<f64>, spec: SoapSpec, species: Option<&[u32]>, mobile: Option<&[usize]>) -> Array1<f64>

Pullback of a stacked SOAP+ν=3 residual through the stacked analytic J.

fn pullback_z(x: ArrayView1<f64>, target: ArrayView1<f64>, spec: SoapSpec, species: Option<&[u32]>, mobile: Option<&[usize]>) -> Array1<f64>

Pullback with observed species channels and a mobile mask.

Frozen atoms stay in the neighbour list. Their Cartesian columns are dropped from J and their displacement is zero. Rigid-body stripping runs only when every atom is mobile.

fn step_away<R: Rng + ?Sized>(x: ArrayView1<f64>, _observed: &[Array1<f64>], spec: SoapSpec, rmsd: f64, _rng: &mut R) -> Array1<f64>

Oracle residual: 555 toward 421 / fcc prototype, pulled back by analytic J.

Opt-in measurement (soap_class_residual). The recommended hop is step_away_mean.

fn step_away_cloud<R: Rng + ?Sized>(x: ArrayView1<f64>, spec: SoapSpec, rmsd: f64, species: Option<&[u32]>, mobile: Option<&[usize]>, groups: Option<&[Vec<usize>]>, rng: &mut R) -> Array1<f64>

Observed-cloud residual, partitioned by observed atomic number and restricted to the mobile set. Frozen atoms are neighbours, not movers.

On a packing cluster the hop is the SOFI fivefold residual: it fires only while the fivefold length is small and the step increases that length. Molecules and slabs keep the ACE leftover. groups is accepted for call-site compatibility.

fn step_away_fivefold<R: Rng + ?Sized>(x: ArrayView1<f64>, rmsd: f64, rng: &mut R) -> Array1<f64>

Leave the fivefold funnel: amplify the SOFI C5 residual on the high-mismatch shell, or break a perfect pentagon. Yields unless at least two candidate axes are still fivefold. On an open shell the axis is drawn from the good set so the hop is not a single deterministic pentagon.

fn step_away_fivefold_about(x: ArrayView1<f64>, rmsd: f64, axis: [f64; 3]) -> Array1<f64>

Fivefold residual hop about one named axis. Used to probe which pentagon opening leaves the icosahedral shelf.

fn step_away_mean<R: Rng + ?Sized>(x: ArrayView1<f64>, spec: SoapSpec, rmsd: f64, _rng: &mut R) -> Array1<f64>

Observed-cloud residual on the stacked SOAP+4-body cloud.

The hop is μ on every block. A Dirac 4-body cloud yields.

Structs and Unions

struct FivefoldProbe

Snapshot of the fivefold hop before the cap is applied.

d5: f64

SOFI/greedy C5 length of x on the best axis.

n_axes: usize

How many candidate axes sit below FIVEFOLD_AXIS.

residual_rms: f64

RMS of x R_5 x under the best axis.

gated: bool

True when fewer than FIVEFOLD_MIN_AXES axes are fivefold.

used_pentagon: bool

True when the residual vanished and the step is a pentagon break.

top5_share: f64

Share of residual power on the five atoms with the largest |dr_i|.

top12_share: f64

Share of residual power on the twelve atoms with the largest |dr_i|.

y: Array1<f64>

Proposed coordinates after the cap.

struct SoapSpec

Radial and angular resolution, and the cutoff in nearest-neighbour units.

n_max: usize

Radial functions n = 0..n_max.

l_max: usize

Angular momentum l = 0..l_max.

rcut_nn: f64

Cutoff in coordinate units. Fixed: a moving median-NN cutoff is not a map R^{3N} p and has no Jacobian.

Implementations

impl SoapSpec

Functions

fn dim(self) -> usize

Length of the packed power spectrum n n', l l_max.

fn feat_dim(self, species: Option<&[u32]>) -> usize

dim times the number of observed neighbour-species channels.

fn nu3_dim(self) -> usize

ACE ν=3 / λ-SOAP scalars per atom per species channel.

fn nu3_feat_dim(self, species: Option<&[u32]>) -> usize

nu3_dim times the number of observed neighbour-species channels.

Traits implemented

impl Default for SoapSpec