Amorphous¶
Cu, 40 × 40 × 40 Å, regime preset "amorphous" with build-time
orientation refinement enabled.
Orientation-refinement movie¶
Each frame is one accepted grain rotation; the schedule walks 30° → 15° → 5° → 2° and accepts the best of 50 trials per (amplitude, grain). Discrete steps, no FIRE between accepts.
FIRE quench movie¶
Continuous atomic relaxation after rotation refinement. The starting state is whatever the rotation search settled on; FIRE then converges all atoms into the basin.
Cost trace: refinement + FIRE¶
Total / bond / angle / repulsion components. Left of the dashed line: rotation refinement (one point per accepted rotation). Right: FIRE convergence (downsampled).

g3 distribution: initial · after refine · after FIRE¶
Three rooted three-body distributions captured at three points along the pipeline so the algorithmic effect of each stage is visible.
Initial (post-build, post-retile): grain interiors are perfect crystal slabs at random orientations.
After refinement (pre-FIRE): SO(3) coordinate descent has walked each grain into a better-aligned basin against its neighbours. Differences from the initial g3 are concentrated at grain boundaries.
After FIRE (final): all atoms relaxed. A small post-FIRE thermal jitter (σ scaled by regime grain density) is applied before measurement so the peaks have realistic finite-T width rather than the perfectly sharp 0K-FIRE-quench result.
Code¶
from ase.build import bulk
import tricor as tc
atoms = bulk("Si", "diamond", a=5.431) # use the right reference for Cu
shell_target = tc.CoordinationShellTarget.from_atoms(atoms, phi_num_bins=90)
cell = tc.Supercell.from_atoms(
atoms,
cell_dim_angstroms=(40, 40, 40),
r_max=10, r_step=0.1, phi_num_bins=90,
rng_seed=42,
)
cell.generate(
shell_target,
**tc.Supercell.PRESETS["amorphous"],
refine_orientations=True,
refine_orientations_kwargs=dict(
amplitudes_deg=(30.0, 15.0, 5.0, 2.0),
trials_per_amplitude_per_grain=50,
max_rounds_per_amplitude=2,
cost_function="pair_distance",
score_cutoff_factor=1.5,
time_budget_sec=180.0,
capture_trajectory=True,
),
capture_trajectory=True,
)