Supercell¶
The central class. Constructs a periodic simulation cell from a reference crystal and provides the full disorder-generation pipeline (Voronoi grain build → optional orientation refinement → FIRE-style relaxation), measurement, visualisation, and HTML-export helpers.
- class tricor.Supercell(distribution, cell_dim_angstroms, *, relative_density=0.96, measure_g3=False, plot_g3_compare=False, label=None, rng_seed=None, g3_weight_r_scale=None, g3_weight_exponent=2.0, g3_weight_floor=0.1, spatial_bin_size=None, **kwargs)[source]
Bases:
_GrainMixin,_ShellRelaxMixin,_PlottingMixin,_MonteCarloMixin,_ResampleMixinRandom supercell scaffold driven by a target
G3Distribution.Construction
- Parameters:
- classmethod from_atoms(atoms, cell_dim_angstroms, *, r_max=10.0, r_step=0.2, phi_num_bins=90, relative_density=0.96, rng_seed=None, label=None, **kwargs)[source]¶
Create a random supercell directly from a reference crystal.
This is a convenience constructor that measures the reference g3 distribution internally, avoiding the need to create a
G3Distributionmanually. Usegenerate()to build the desired structure (amorphous, nanocrystalline, etc.).- Parameters:
atoms (Atoms) – Reference crystal structure (ASE Atoms object).
cell_dim_angstroms (float | Sequence[float]) – Physical supercell lengths in Angstrom. A single scalar produces a cubic box.
r_max (float) – Maximum radius for the g3 measurement grid.
r_step (float) – Radial bin width for the g3 measurement grid.
phi_num_bins (int) – Number of angular bins for the g3 measurement grid.
relative_density (float) – Density relative to the crystalline reference.
rng_seed (int | None) – Random seed for reproducible initialization.
label (str | None) – Human-readable label.
**kwargs (Any) – Forwarded to
Supercell.__init__().
- Returns:
A new random supercell ready for
generate()orshell_relax().- Return type:
Supercell
Generation
- generate(shell_target, num_steps=200, *, grain_size=None, crystalline_fraction=1.0, bond_weight=1.0, angle_weight=0.5, repulsion_weight=3.0, hard_core_scale=1.0, nonbond_push_scale=1.0, displacement_sigma=0.0, atom_species_index=None, grain_sources=None, refine_orientations=False, refine_orientations_kwargs=None, show_progress=True, **shell_relax_kwargs)[source]¶
Generate a disordered supercell from liquid to nanocrystalline.
Covers the full spectrum of disorder by combining Voronoi grain construction with spring-network relaxation. See
PRESETSfor recommended parameter sets for Si.- Parameters:
shell_target (CoordinationShellTarget) – First-shell coordination targets from the reference crystal.
num_steps (int) – Number of relaxation sweeps.
grain_size (float | None) – Diameter of crystalline grains in Angstrom.
Nonemeans no grains - start from random positions (liquid/amorphous).crystalline_fraction (float) – Volume fraction filled by crystalline grains (0–1). Only used when grain_size is set. The remaining volume is filled with random (amorphous) positions.
bond_weight (float) – Harmonic spring strength pulling bonded neighbours toward the target bond distance. Larger = tighter distances.
angle_weight (float) – Spring strength pushing bond angles toward the target angle. Larger = tighter angles. Near-zero = liquid-like freedom.
displacement_sigma (float) – Gaussian displacement (Angstrom) applied to atoms within crystalline grains as thermal broadening. 0 = no jitter.
show_progress (bool) – Display a text progress bar.
**shell_relax_kwargs (Any) – Additional keyword arguments forwarded to
shell_relax()(e.g.repulsion_weight,hard_core_scale,step_size).repulsion_weight (float) –
hard_core_scale (float) –
nonbond_push_scale (float) –
atom_species_index (ndarray | None) –
refine_orientations (bool) –
refine_orientations_kwargs (dict | None) –
- Returns:
Summary dict with regime, construction parameters, and relaxation loss values.
- Return type:
Orientation refinement
- refine_initial_orientations(shell_target, *, amplitudes_deg=(30.0, 15.0, 5.0, 2.0), trials_per_amplitude_per_grain=50, max_rounds_per_amplitude=2, bond_weight=1.0, angle_weight=0.5, repulsion_weight=3.0, hard_core_scale=1.0, nonbond_push_scale=1.0, time_budget_sec=120.0, final_fire_steps=0, capture_trajectory=False, cost_function='pair_distance', score_cutoff_factor=1.5, topology_rebuild='per_grain', rng_seed=None, show_progress=True)¶
Optimise per-grain rotations via SO(3) coordinate descent BEFORE the global FIRE quench.
Walks each Voronoi grain through a sequence of progressively finer rotation perturbations, accepting any rotation that lowers a fast topology-free pair-distance score against the grain’s local environment. Designed to be called between the Voronoi tile (which assigns random initial rotations) and the global FIRE quench. The intended workflow is:
cell.generate(shell, num_steps=0, ...) # build only cell.refine_initial_orientations(shell) # this method cell.shell_relax(shell, num_steps=150, ...) # FIRE quench
Or equivalently use
cell.generate(refine_orientations=True, refine_orientations_kwargs=...)which chains the three steps in one call.- Parameters:
shell_target (CoordinationShellTarget) – Target whose
pair_peakdefines the per-pair bond length the score targets.amplitudes_deg (tuple of float, optional) – Schedule of rotation amplitudes (degrees) the SO(3) coordinate search walks through. Default
(30, 15, 5, 2): the largest step lets a misaligned grain escape its starting basin, the smallest step locks in the chosen orientation.trials_per_amplitude_per_grain (int, optional) – Number of random rotations sampled per (amplitude, grain). Default
50. The best-scoring trial is accepted if it beats the current orientation by more thanscore_cutoff_factor.max_rounds_per_amplitude (int, optional) – Number of full passes over all grains within one amplitude phase. Default
2.bond_weight (float, optional) – Spring weights forwarded to the per-trial score. Only used when
cost_function="cached_topology"; the default"pair_distance"mode ignores them.angle_weight (float, optional) – Spring weights forwarded to the per-trial score. Only used when
cost_function="cached_topology"; the default"pair_distance"mode ignores them.repulsion_weight (float, optional) – Spring weights forwarded to the per-trial score. Only used when
cost_function="cached_topology"; the default"pair_distance"mode ignores them.hard_core_scale (float, optional) – Repulsion thresholds passed through to the per-trial score’s clash-penalty term.
nonbond_push_scale (float, optional) – Repulsion thresholds passed through to the per-trial score’s clash-penalty term.
time_budget_sec (float, optional) – Wall-time guard rail (seconds). The search bails after this even if amplitudes remain. Default
120.final_fire_steps (int, optional) – If > 0, run a whole-cell
shell_relaxfor this many steps after the SO(3) search completes — bakes a final quench into a single call. Default0(caller is expected to run their ownshell_relax).capture_trajectory (bool, optional) – Record the cell’s atom positions at every accepted rotation. Default
False(faster). Set toTruefor trajectory-replay HTML export.cost_function ({"pair_distance", "cached_topology"}, optional) – Score to minimise.
"pair_distance"(default, recommended) is a topology-freeΣ (d - pair_peak)²over neighbour pairs in the grain’s local frame — fast and consistent across grains and trials."cached_topology"uses_total_energy_fastwith a rebuilt bond list (more physically faithful but the rebuilt topology drifts as positions change and can walk into a worse basin on big cells).score_cutoff_factor (float, optional) – Acceptance threshold relative to the current baseline score. Higher values accept more aggressively. Default
1.5.topology_rebuild ({"per_grain", "per_amp", "once"}, optional) – Cadence for rebuilding the bond list (only used when
cost_function="cached_topology"). Default"per_grain".rng_seed (int, optional) – Seed for the random rotation sampler.
None(default) uses the cell’s own RNG.show_progress (bool, optional) – Display a tqdm progress bar over the (amplitudes × rounds × grains) workload. Default
True.self (Supercell) –
- Returns:
History captured under
self.refine_initial_orientations_history:iteration(ndarray of int) — accept indices, starting at 0 for the initial state.global_cost(ndarray of float) — total cost at each accepted state.cost_bond/cost_angle/cost_rep— cost decomposition (only populated forcost_function="cached_topology").accepted_grain(ndarray of int) — grain index that moved at each acceptance (-1 for the initial state).rotation_amplitude_deg(ndarray of float) — the current amplitude phase at each acceptance.amplitude_phase(ndarray of int) — phase index intoamplitudes_deg.trajectory(ndarray of float32, optional) — only present whencapture_trajectory=True: positions(num_accepts, num_atoms, 3)at each accepted rotation.
- Return type:
- refine_grains(shell_target, *, time_budget_sec=300.0, max_passes=20, n_rot=8, n_trans=4, rotation_min_deg=10.0, rotation_max_deg=180.0, local_fire_steps=50, neighbor_shell_radius_factor=2.5, bond_weight=1.0, angle_weight=0.5, repulsion_weight=3.0, hard_core_scale=1.0, nonbond_push_scale=1.0, final_quench_steps=200, capture_trajectory=True, show_progress=True, rng_seed=None)¶
Iterative per-grain rotation refinement with local FIRE.
Walks the grain list round-robin; for each grain, tries
n_rot * n_transcandidate (rotation, translation) pairs, keeping the lowest-cost outcome. A trial is judged by total bond + angle + repulsion cost after a shortlocal_fire_steps-step FIRE pass on the grain plus its neighbour shell.Returns the history dict that gets stashed on
self.refine_grains_historyand used bySupercell.export_trajectory_html(history='refine_grains')().- Parameters:
time_budget_sec (float) – Stop after this many seconds of wall-clock have elapsed. For demo-quality results 60 - 300 s is plenty; for production runs raise to 1800 - 3600 s.
max_passes (int) – Stop after this many full round-robin passes regardless of time. A pass with zero accepts triggers early convergence.
n_rot (int, optional) – Per-grain rotation trials. Wall time scales linearly with
n_rot * n_trans * num_grains.n_trans (int, optional) – Per-grain translation trials. Combined with
n_rotsets the basin coverage per grain.rotation_min_deg (float, optional) – Lower bound on trial rotation angle (degrees). Lower values encourage fine local refinements late in the search.
rotation_max_deg (float, optional) – Upper bound on trial rotation angle (degrees). Trial rotations sample uniformly in
[rotation_min_deg, rotation_max_deg]about a uniformly-random axis.neighbor_shell_radius_factor (float) – The local FIRE region around each grain extends
radius_factor * pair_peak_maxÅ beyond the grain atoms. ~2.5 covers the grain’s own atoms plus the atoms in adjacent grains that share a Voronoi face, which is what bonds across grain boundaries actually depend on.local_fire_steps (int) – Number of FIRE descent steps per trial. 50 is enough to absorb the boundary strain from a fresh rotation; raising past 100 wastes budget.
bond_weight (float, optional) – Spring weight for bond-distance terms. Mirror the value used when the cell was originally generated.
angle_weight (float, optional) – Spring weight for bond-angle terms.
repulsion_weight (float, optional) – Spring weight for hard-core + nonbond-clearance terms.
hard_core_scale (float, optional) – Multiplier on
shell_target.pair_innersetting the minimum allowed pair distance.nonbond_push_scale (float, optional) – Multiplier on
shell_target.pair_peaksetting the non-bonded shell-clearance radius.final_quench_steps (int) – After the round-robin loop finishes, run this many full-cell FIRE steps (no freezing, no restraint) to lock in the global minimum. Set 0 to skip.
capture_trajectory (bool) – When True, append a frame to the history each time a grain rotation is accepted. Adds the initial state and the post-final-quench state too.
self (Supercell) –
shell_target (CoordinationShellTarget) –
show_progress (bool) –
rng_seed (int | None) –
- Return type:
Notes
Wall-clock for the demo runs in this repo (
cell_dim_angstroms = (40, 40, 40)):regime
grains
~accepts/run
wall time
amorphous
~600
~50
5–7 min
MRO
~50
~10
2–3 min
nano (NC)
~5
~3
30–60 s
For production-quality output (e.g. ML training datasets), raise
time_budget_secto 1800 - 3600, raisen_rotto 16 - 32, and run multiple seeds in parallel.
- refine_grains_coarse_to_fine(shell_target, *, initial_uniform_trials=32, angle_schedule_deg=(45.0, 22.0, 11.0, 5.0, 2.0, 1.0), trials_per_amplitude=12, max_rounds_per_amplitude=3, local_fire_steps=50, neighbor_shell_radius_factor=2.5, bond_weight=1.0, angle_weight=0.5, repulsion_weight=3.0, hard_core_scale=1.0, nonbond_push_scale=1.0, final_quench_steps=200, time_budget_sec=180.0, capture_trajectory=True, show_progress=True, rng_seed=None)¶
Coarse-to-fine basin hopping for per-grain rotations.
Walks an angle-amplitude schedule from coarse to fine. For each
(amplitude, grain)pair, samplestrials_per_amplitudecandidate rotations bounded in angle byamplitudeand composed onto the grain’s current orientation, applies a short local FIRE on each, and accepts the lowest-cost outcome. The same amplitude is repeated up tomax_rounds_per_amplituderounds while it keeps producing accepts; then the schedule steps down.This finds dozens of accepts where uniform-SO(3) sampling finds only 1-2 because every trial is anchored to the current orientation, so fine refinements within the chosen basin keep yielding small improvements; translations are also bounded by the amplitude (
trans_scale = amplitude / 180°); and multi-round at each amplitude exhausts the local search before stepping to a smaller amplitude.- Parameters:
shell_target (CoordinationShellTarget) – Target whose
pair_peakdefines the per-pair bond length the cost function targets.initial_uniform_trials (int, optional) – Stage-1 uniform-SO(3) basin search per grain (rotations sampled independently of the current orientation, used only to escape the seed orientation). Default
32. Set0to skip the basin search.angle_schedule_deg (tuple of float, optional) – Stage-2 amplitude schedule (degrees), coarse → fine. Default
(45, 22, 11, 5, 2, 1).trials_per_amplitude (int, optional) – Candidate rotations per (amplitude, grain). Default
12.max_rounds_per_amplitude (int, optional) – Maximum round-robin passes over all grains within one amplitude phase. Default
3.local_fire_steps (int, optional) – FIRE steps applied to each trial’s neighbour shell to evaluate its cost. Default
50.neighbor_shell_radius_factor (float, optional) – Local-FIRE neighbour shell extends to this multiple of
shell_target.pair_peakaround the perturbed grain. Default2.5.bond_weight (float, optional) – Spring weights forwarded to the per-trial FIRE + cost evaluation.
angle_weight (float, optional) – Spring weights forwarded to the per-trial FIRE + cost evaluation.
repulsion_weight (float, optional) – Spring weights forwarded to the per-trial FIRE + cost evaluation.
hard_core_scale (float, optional) – Repulsion thresholds for the per-trial FIRE.
nonbond_push_scale (float, optional) – Repulsion thresholds for the per-trial FIRE.
final_quench_steps (int, optional) – Whole-cell FIRE quench steps applied after the SO(3) search completes. Default
200; set0to skip.time_budget_sec (float, optional) – Wall-time guard rail (seconds). The search bails after this even if amplitudes remain. Default
180.capture_trajectory (bool, optional) – Record per-frame atom positions after each acceptance. Default
True(needed for trajectory-replay HTML).show_progress (bool, optional) – Display a tqdm progress bar. Default
True.rng_seed (int, optional) – Seed for the rotation sampler.
None(default) uses the cell’s own RNG.self (Supercell) –
- Returns:
History captured under
self.refine_grains_coarse_to_fine_history— same shape asrefine_grains()’s history (so the trajectory + cost plotters work unchanged), plus arotation_amplitude_degarray marking which amplitude phase produced each accept.- Return type:
Relaxation
- shell_relax(shell_target, num_steps=200, *, bond_weight=1.0, angle_weight=0.5, repulsion_weight=3.0, k_restraint=0.0, r_initial_override=None, freeze_mask=None, freeze_grain_interiors=False, hard_core_scale=1.0, nonbond_push_scale=1.0, step_size=0.1, step_decay=0.995, neighbor_update_interval=10, neighbor_cutoff_scale=1.5, max_force_clip=2.0, capture_trajectory=False, show_progress=True)¶
Relax random positions to match first-shell targets using spring forces.
Moves all atoms simultaneously each step via three vectorized force terms: bond springs toward the target nearest-neighbor distance, angle springs toward the target bond angle, and soft repulsion to eliminate overlaps and close-packed background. Bond topology (K-nearest assignment) is rebuilt periodically using ASE’s
neighbor_list.- Parameters:
shell_target (CoordinationShellTarget) – First-shell coordination targets extracted from the reference crystal via
CoordinationShellTarget.from_atoms().num_steps (int) – Number of relaxation sweeps.
bond_weight (float) – Strength of the harmonic spring pulling bonded neighbors toward
pair_peakdistance.angle_weight (float) – Strength of the angular spring pushing bond angles toward
angle_mode_deg.repulsion_weight (float) – Strength of the short-range repulsive force below
pair_hard_min.k_restraint (float) – Spring constant (eV / Ų) for a global position-restraint energy
½ k_restraint Σ ‖r_i - r_initial_i‖²that tethers every atom to its starting position.0.0(default) disables the term and reproduces unrestrained relaxation. Small values (~0.1 - 1.0) preserve regime character (grain layout, amorphous topology) while still permitting local relaxation; large values (≫ 10) hold the structure rigid.hard_core_scale (float) – Multiplier for the hard-core repulsion radius. 1.0 uses
max(pair_hard_min, pair_inner)as the wall. Values below 1.0 allow shorter bonds (softer wall for liquid). Values above 1.0 enforce a larger exclusion zone.nonbond_push_scale (float) – Multiplier for the non-bonded shell clearance distance. 1.0 pushes non-bonded atoms to
1.5 * pair_peak. Values below 1.0 allow non-bonded atoms closer (broader 2nd shell for liquid). 0.0 disables non-bonded push.step_size (float) – Initial maximum displacement per step (Angstrom).
step_decay (float) – Multiplicative decay applied to step_size each iteration.
neighbor_update_interval (int) – Rebuild the bond topology every this many steps.
neighbor_cutoff_scale (float) – Neighbor search cutoff as a multiple of
max_pair_outer.max_force_clip (float) – Per-atom force magnitude is clipped to this value before integration to keep the dynamics stable.
freeze_grain_interiors (bool) – If
True, atoms identified as deep grain interior (more than0.5 × max(pair_peak)away from the nearest grain-boundary plane) are held fixed during relaxation.False(default since 2026-05) lets every atom relax, which is required for multi-species systems where the interior atoms must accommodate cross-species spring strain (SiO2, SrTiO3, sp²/sp³ carbon). SettingTruereproduces the pre-2026 behaviour and is occasionally useful for single-species nanocrystalline cells where the interiors are already at their target geometry. Has no effect on cells built without agrain_size.show_progress (bool) – Display a text progress bar.
self (Supercell) –
r_initial_override (np.ndarray | None) –
freeze_mask (np.ndarray | None) –
capture_trajectory (bool) –
- Returns:
Summary with parameters and final/initial loss values.
- Return type:
- bond_relax(shell_target, n_iter=40, attract_frac=0.2, repel_frac=1.0, max_step=0.2)[source]¶
Combined attract-to-bond-peak + repel-from-hard-core sweep.
A fast O(N log N) alternative to a full FIRE relaxation for cleaning up Voronoi-tiled or ML-predicted positions. Each iteration:
Pulls bonded species pairs (those with non-zero
shell_target.coordination_target) towardshell_target.pair_peak.Pushes any pair below
shell_target.pair_hard_minapart.
Mutates
self.atoms.positionsin place. Usesscipy.spatial.cKDTreeso cost scales linearly with N at constant density — at 200³ Å × 600 k atoms, ~1 s/iter on CPU. Drives Si-O to its 1.61 Å peak and non-bonded pairs (Si-Si, O-O) onto their hard-core walls in 40-80 iterations.- Parameters:
shell_target – The
CoordinationShellTargetwhosepair_peak/pair_hard_min/pair_outer/coordination_targetmatrices drive the forces.n_iter (int) – Number of sweeps. 40 typically reaches the bond peak to within 0.01 Å.
attract_frac (float) – Per-sweep gap-closing fraction toward the bond peak.
repel_frac (float) – Per-sweep gap-closing fraction away from the hard-core wall.
1.0(default) closes the gap in one shot, withmax_stepproviding the safety against overshoot in dense regions.max_step (float) – Per-atom displacement cap (Å) per sweep.
- Return type:
None
- enforce_hard_core(shell_target, n_iter=40, push_fraction=0.5)[source]¶
Geometric projection step that clears hard-core overlaps.
Iteratively finds pairs below
shell_target.pair_hard_min(viascipy.spatial.cKDTree) and pushes each violating pair apart along their bond vector bypush_fraction × deficit. Pure geometry - no force springs - so it cannot pull a pair through its wall the way the FIRE finisher’s bond springs can. Use this as a final cleanup whenever you suspect FIRE’s bond-spring forces have compressed pairs below their hard-core distance in dense regions (a real failure mode at 100+ Å cells).Mutates
self.atoms.positionsin place. Cost: ~1 s per sweep at 200³ Å × 600 k atoms; converges in roughlyO(log(initial_deficit / push_fraction))sweeps for moderate overlaps, more for severe ones from a fresh Voronoi tile. Defaults are tuned to clear NB 01 / NB 02-scale overlaps in a single call.- Parameters:
shell_target – The
CoordinationShellTargetwhosepair_hard_minmatrix sets the wall distances.n_iter (int) – Number of projection sweeps. Early-terminates if no violations remain.
push_fraction (float) – Per-iter fraction of the deficit to close.
0.5(default) is the natural choice - both atoms move symmetrically and meet in the middle. Larger values risk overshoot; smaller values just need more sweeps.
- Return type:
None
- thermal_relax(shell_target, *, num_sweeps=1000, T_schedule='anneal', T_start=0.05, T_end=0.001, hold_sweeps=200, step_sigma=0.05, smart_dt=0.02, adapt_step=True, target_accept=0.4, move_probs=None, bond_weight=1.0, angle_weight=0.5, repulsion_weight=3.0, k_restraint=0.0, hard_core_scale=1.0, nonbond_push_scale=1.0, neighbor_update_interval=100, rep_neighbor_update_interval=20, capture_stride=10, capture_trajectory=True, restore_best=True, freeze_interior=None, freeze_mask=None, grain_moves=None, grain_move_interval=1, grain_sigma_rot=0.01, grain_sigma_trans=0.01, show_progress=True)¶
Temperature-dependent Metropolis Monte-Carlo relaxation.
Sits alongside
shell_relax()- same spring-network energy (bond + angle + repulsion fromshell_target), but moves atoms by Metropolis accept/reject with a temperature schedule. Good for escaping the local minima that gradient descent settles into and for producing annealed amorphous configurations.A typical workflow is: run
shell_relax()orgenerate()once to bring the initial random / tile configuration into a low-energy basin, then callthermal_relax()with a moderate-to-cold anneal schedule to explore the basin and settle into the global minimum of that basin.- Parameters:
shell_target (CoordinationShellTarget) – First-shell coordination targets, same object used by
shell_relax().num_sweeps (int) – Number of sweeps. Each sweep performs
len(atoms)trial moves.T_schedule –
"hold"(constantT_start),"anneal"(hold atT_startforhold_sweepsthen linearly drop toT_end), or acallable(sweep_index) -> T.T_start (float) – Parameters for the
"anneal"schedule.T_end (float) – Parameters for the
"anneal"schedule.hold_sweeps (int) – Parameters for the
"anneal"schedule.step_sigma (float) – Initial Gaussian trial-move amplitude in Å.
adapt_step (bool) – If
True, adaptstep_sigmaevery 20 sweeps to targettarget_acceptacceptance rate.move_probs (dict | None) – Dictionary with optional keys
"displace","swap","smart". Weights are normalised; default{"displace": 1.0}."swap"exchanges virtual species between two atoms of different species; useful for multi-element + composite-shell-target systems."smart"is a force-biased Langevin proposal with Metropolis correction (reserved for v2; currently treated as no-op).bond_weight (float, optional) – Same as
shell_relax(). Default1.0.angle_weight (float, optional) – Same as
shell_relax(). Default0.5.repulsion_weight (float, optional) – Same as
shell_relax(). Default3.0.k_restraint (float, optional) – Spring constant (eV / Ų) for a global position-restraint energy
½ k_restraint Σ ‖r_i - r_initial_i‖²that tethers every atom to its starting position.0.0(default) disables the term and reproduces unrestrained MC. Small values (~0.1 - 1.0) preserve the input regime character (grain layout, amorphous topology) while still permitting local relaxation; large values (≫ 10) hold the structure essentially rigid. Differentiable + globally defined, so unlike a hardfreeze_interiorthe cost surface stays smooth and the relaxation can find consistent low-strain configurations across grain boundaries.hard_core_scale (float, optional) – Same as
shell_relax(). Default1.0.nonbond_push_scale (float, optional) – Same as
shell_relax(). Default1.0.neighbor_update_interval (int) – Rebuild the bond topology every this many sweeps.
capture_stride (int) – Store a history frame every this many sweeps. Smaller = finer trajectory movie, larger = less memory.
capture_trajectory (bool) – Whether to store per-sweep positions. Disable for very long runs where only cost / T / accept_rate matter.
freeze_interior (bool | None) – Legacy hard-freeze of crystalline grain interiors. Only takes effect when explicitly set to
Trueand the cell has populated_grain_ids/_grain_seeds(i.e. came fromgenerate()withgrain_size). DefaultNoneleaves all atoms free; preferk_restraint > 0for a smooth, differentiable, regime-preserving alternative.freeze_mask (np.ndarray | None) – Explicit per-atom freeze mask of shape
(num_atoms,).Trueentries are pinned for the entire run. Overridesfreeze_interior. Useful when the cell isn’t grain-tiled but you still want to hold specific atoms (e.g. an interface) fixed.grain_moves (bool, optional) – If
True(orNoneand the cell has ≥2 grains), propose rigid rotation + translation of each grain everygrain_move_intervalsweeps.grain_move_interval (int, optional) – Sweep cadence of the rigid-grain proposals. Default
1(one set of grain moves per sweep when enabled).grain_sigma_rot (float, optional) – Std-dev of the per-grain rotation angle (radians). Default
0.01.grain_sigma_trans (float, optional) – Std-dev of the per-grain translation (Å). Default
0.01.self (Supercell) –
smart_dt (float) –
target_accept (float) –
rep_neighbor_update_interval (int) –
restore_best (bool) –
show_progress (bool) –
- Returns:
History dictionary assigned to
self.thermal_relax_history. Layout matchesshell_relax_history()where possible, soexport_trajectory_html()can visualise the trajectory unchanged.- Return type:
Measurement
- measure_g3(*, force=False, show_progress=True, backend='auto', sample_fraction=1.0, sample_rng_seed=None)¶
Measure the current random supercell on the target distribution grid.
- Parameters:
force (bool) – If True, discard any cached measurement and recompute.
show_progress (bool) – If True, display a text progress bar while the supercell histogram is accumulated.
backend (str) – Kernel selector forwarded to
G3Distribution.measure_g3()."auto"(default) picks the numba-parallel path when numba is installed.sample_fraction (float) – Monte-Carlo origin subsampling.
sample_fraction < 1.0iterates only a uniform random subset of origin atoms (preserves PBC tile, full neighbour set). At 200³ Å set this to ~``(40/200)**3`` so the histogram cost matches a 40³ Å reference cell.sample_rng_seed (int | None) – Monte-Carlo origin subsampling.
sample_fraction < 1.0iterates only a uniform random subset of origin atoms (preserves PBC tile, full neighbour set). At 200³ Å set this to ~``(40/200)**3`` so the histogram cost matches a 40³ Å reference cell.self (Supercell) –
- Return type:
G3Distribution
- sync_g3(*, show_progress=True)¶
Recompute the supercell’s g2 + g3 from scratch and rebuild Monte-Carlo caches.
Forces a fresh
measure_g3()(bypassing any cached result) and then re-initialises the per-atom contribution tables thatmonte_carlo()uses to compute incremental ΔG3 / Δcost on each trial move. Call after externally modifyingself.atoms.positions(e.g. injecting anumpy.random.normal()thermal jitter) or after chaining ashell_relax()between MC rounds — otherwise the MC caches refer to stale neighbour pairings and the proposed-move statistics drift.- Parameters:
show_progress (bool, optional) – Display a tqdm-style progress bar while the underlying
measure_g3()iterates. DefaultTrue.self (Supercell) –
- Returns:
The freshly measured distribution, also stored as
self.current_distribution.- Return type:
G3Distribution
Inline visualisation (Jupyter)
- view_structure(shell_target=None, *, polyhedra=True, **kwargs)¶
Return an interactive 3D structure viewer widget.
Renders atoms as spheres (coloured by element). Two overlay modes, independently toggle-able in the widget:
Bonds - cylinders between atoms within a radial cutoff.
Polyhedra - translucent tetrahedra / octahedra / cuboctahedra around atoms that pass a distance + angle tolerance check (see
export_trajectory_html()/_detect_tetrahedra()for the underlying algorithm). Enabled by default for materials whose coordination polyhedron we can auto-detect (Si / C tetrahedra at half-scale, Cu cuboctahedra, SiO2 tetrahedra, SrTiO3 octahedra).
Sliders in the side panel let you tune the radial tolerance, angular tolerance, centre-vertex bond length, and polyhedra scale (0.5 places vertices at bond midpoints, 1.0 at atoms).
- Parameters:
shell_target (CoordinationShellTarget | None) – Sets the default bond cutoff and bond_length from
shell_target.max_pair_outer/pair_peak. IfNone, uses the shell_target stored from the lastgenerate()call.polyhedra (dict | bool | None) – Polyhedra config.
True/None(default) auto-pick kind + settings from species;Falsedisables polyhedra; adictoverrides individual settings - e.g.{'kind': 'octahedra', 'center_symbol': 'Ti', 'vertex_symbol': 'O', 'bond_length': 1.96}.**kwargs – Forwarded to
StructureWidget(e.g.atom_scale,bond_cutoff,show_bonds,slab_x, etc.).self (Supercell) –
- Returns:
An anywidget instance for display in Jupyter.
- Return type:
StructureWidget
- plot_structure(shell_target=None, *, output=None, width=1024, height=1024, fps=60, duration=6.0, elevation=15.0, atom_size=10.0, bond_cutoff=None, show_cell=True, show_atoms=True, background='white', colormap='Reds', tetrahedral_thresh=0.4, show_progress=True)¶
Render a bond-centric rotating 3D view of the atomic structure.
Bonds are the primary visual: crystalline (tetrahedral) bonds are drawn thick and coloured by depth; boundary / amorphous bonds are drawn faint. Atoms are optional small dots. The animation performs a full periodic 360-degree rotation.
Classification follows the MATLAB
plotAtoms02convention: an atom is crystalline if it has exactly K nearest neighbours within bond_cutoff and the mean displacement of those neighbours is less than tetrahedral_thresh (i.e. the local coordination is symmetric / tetrahedral).- Parameters:
shell_target (CoordinationShellTarget | None) – First-shell targets. Used to set bond_cutoff and the coordination number K automatically.
output (str | None) – File path for a
.mp4(recommended) or.gif.Noneshows a static figure.width (int) – Frame size in pixels.
height (int) – Frame size in pixels.
fps (int) – Frames per second (GIF only).
duration (float) – Total GIF length in seconds. Rotation is always exactly 360 degrees so the loop is seamless.
elevation (float) – Camera elevation in degrees.
atom_size (float) – Matplotlib scatter marker size. Set to 0 to hide atoms.
bond_cutoff (float | None) – NN bond length cutoff in Angstrom.
show_cell (bool) – Draw the periodic cell outline.
show_atoms (bool) – Draw atom dots.
background (str) – Figure background colour.
colormap (str) – Matplotlib colormap for crystalline bonds (coloured by depth / y-coordinate after rotation, like MATLAB
bone).tetrahedral_thresh (float) – Maximum norm of mean NN displacement vector for an atom to be classified as crystalline. Smaller = stricter.
show_progress (bool) – Print frame counter during GIF rendering.
self (Supercell) –
- plot_g2(*, r_max=10.0, r_step=0.05, title='', height=420, show_progress=False)¶
Return an inline Jupyter display of the g(r) pair-correlation viewer.
Convenience wrapper around
export_g2_html()that packages the HTML as anIPython.display.HTMLobject so you can just docells['MRO'].plot_g2()in a notebook cell. The viewer is embedded via asrcdociframe so it renders isolated from the surrounding notebook CSS / JS.- Parameters:
r_max (float) – Forwarded to
export_g2_html().r_step (float) – Forwarded to
export_g2_html().title (str) – Forwarded to
export_g2_html().show_progress (bool) – Forwarded to
export_g2_html().height (int) – Iframe height in pixels.
self (Supercell) –
- plot_g3(pair=0, *, normalize=True)¶
Return an interactive explorer for the supercell’s measured g3.
Requires
measure_g3()to have been called first.
- plot_g3_compare(pair=0, *, normalize=True)¶
Interactive side-by-side comparison of the current supercell’s g3 against its target g3.
Renders an anywidget-based two-panel viewer in Jupyter: left panel is the supercell’s measured g3 for the chosen species-pair triplet channel, right panel is the corresponding target g3 (set via
Supercell.target_distribution). Drag the radial-shell slider below either panel to inspect a g3 slice at fixed root-bond radius.- Parameters:
pair (int or str, optional) – Which triplet channel to display. Either an integer index into
target_distribution.angle_indexor a string label like"Si-Si-Si"resolved byG3Distribution._resolve_pair_index(). Default0(first channel).normalize (bool, optional) – If
True(default), normalise both g3 values by the uniform-random reference so bins read as enhancements (>1) or depletions (<1). IfFalse, raw counts.self (Supercell) –
- Returns:
Interactive anywidget instance. Display it inline in Jupyter (returning the widget from a cell auto-renders).
- Return type:
G3CompareWidget
- plot_shell_relax(*, log_y=False)¶
Plot the FIRE relaxation loss history captured by the most recent
shell_relax()call.Renders the per-step total loss alongside its best-so-far envelope and the three component contributions (bond, angle, repulsion). When the run was launched with
k_restraint > 0, the position-restraint contribution is added as a fifth curve in purple.- Parameters:
log_y (bool, optional) – Display the loss axis on a log scale. Useful for runs that span several orders of magnitude (e.g.
num_steps> 200 with stiff springs). DefaultFalse.self (Supercell) –
- Returns:
The created figure.
- Return type:
matplotlib.figure.Figure
- Raises:
ValueError – If
shell_relax()has not been run yet (self.shell_relax_history is None).
- plot_thermal_relax(*, log_y=False, log_x=False)¶
Plot thermal-MC history: cost + T on shared x-axis.
Two stacked panels with
sharex=Trueso the hold-plateau / anneal-ramp shape in temperature lines up visually with the cost trajectory.- Parameters:
log_y (bool) – Log-scale the cost axis. Recommended for convergence checking - a converged run shows a clear plateau when the cost curve flattens on a log scale.
log_x (bool) – Log-scale the sweep axis. Off by default because a typical hold+anneal schedule is linear in sweep index, so log-x distorts the temperature ramp visually. Useful if your schedule spans many orders of magnitude in sweep number or you want to emphasize early-sweep dynamics.
self (Supercell) –
- plot_thermal_before_after(*, r_max=8.0, title=None)¶
Compare g(r) before and after the most recent
thermal_relax()call.Builds a g(r) overlay viewer with two curves: the cell state cached at the start of
thermal_relax()(“before”) and the current state after the Monte-Carlo run completes (“after”). Useful for visualising how an anneal schedule sharpened or broadened the radial distribution.- Parameters:
- Returns:
The rendered comparison viewer (auto-displays inline in Jupyter when returned from a cell).
- Return type:
IPython.display.HTML
- Raises:
ValueError – If
thermal_relax()has not been run yet (no cached pre-thermal snapshot or history).
- plot_monte_carlo(*, log_y=False, show_run_boundaries=True)¶
Plot the Monte-Carlo cost history captured by the most recent
monte_carlo()call.Two curves are drawn on a single matplotlib axis: instantaneous cost (current MC state) and best-so-far cost (envelope). Vertical dashed markers separate consecutive
monte_carloruns whenshow_run_boundaries=True.- Parameters:
log_y (bool, optional) – Display the cost on a logarithmic y-axis. Useful for anneal schedules that span several orders of magnitude. Default
False.show_run_boundaries (bool, optional) – If
True, draw vertical dashed lines at the start of each new MC run whenmc_history["run_index"]increments (e.g. when chained calls extend the history). DefaultTrue.self (Supercell) –
- Returns:
The created figure.
- Return type:
matplotlib.figure.Figure
- Raises:
ValueError – If
monte_carlo()has not been run yet (self.mc_history is None).
HTML export
- export_trajectory_html(output_path, *, bond_cutoff=None, atom_scale=0.17, bond_radius=0.06, background_color='#f7f8f5', title='', tetrahedra=None, tetrahedra_color=(0.35, 0.45, 0.95), tetrahedra_opacity=0.45, octahedra=None, octahedra_color=(0.95, 0.55, 0.25), octahedra_opacity=0.4, cuboctahedra=None, cuboctahedra_color=(0.55, 0.35, 0.85), cuboctahedra_opacity=0.4, polyhedra_groups=None, show_bonds=None, history=None)¶
Export an interactive 3D trajectory viewer as a self-contained HTML file.
Requires
shell_relax()orgenerate()to have been run withcapture_trajectory=True. The resulting HTML embeds the full position trajectory, uses Three.js (from CDN) for rendering, and provides play/pause/slider controls.- Parameters:
output_path (str) – Path to write the HTML file.
bond_cutoff (float | None) – Maximum bond length in Angstrom. If
Noneand the supercell was generated with a shell_target, usesshell_target.max_pair_outer * 1.2. Otherwise 3.0.atom_scale (float) – Radius scale for atom spheres (multiplied by covalent radii).
bond_radius (float) – Radius of bond cylinders in Angstrom.
background_color (str) – CSS colour for the viewer background.
title (str) – Optional title displayed above the viewer.
show_bonds (bool | None) – Whether to emit bond cylinders.
None(default) auto-picks:Truewhen notetrahedraare requested,Falsewhen they are (tetrahedra supersede bonds). PassTrue/Falseexplicitly to override.history (dict | str | None) – Which trajectory history to render.
None(default) usesself.shell_relax_history. Pass"thermal_relax"to renderself.thermal_relax_history, or pass an explicit history dict. Both shell-relax and thermal-relax dicts have a"trajectory"key when their parent call was run withcapture_trajectory=True.self (Supercell) –
tetrahedra (dict | None) –
tetrahedra_opacity (float) –
octahedra (dict | None) –
octahedra_opacity (float) –
cuboctahedra (dict | None) –
cuboctahedra_opacity (float) –
- Returns:
The output path.
- Return type:
- export_g3_html(output_path, *, r_max=10.0, r_step=0.1, phi_num_bins=45, background_color='#f7f8f5', title='', show_progress=False, show_all_triplets=False)¶
Export a static 2D g3 viewer as a self-contained HTML file.
Renders one heatmap per species-triplet of the reduced three-body distribution (density / uniform, where
1.0= white). The viewer uses a diverging RdBu_r colormap centred at1.0and lets the user pick the triplet and adjust the upper colour limit.A fresh
G3Distributionis measured from the current atoms on the coarse export grid (by default 50 x 45 bins per triplet) so the embedded JSON stays small (~500 KB) without affecting anything the supercell itself has cached.- Parameters:
output_path (str) – Path to write the HTML file.
r_max (float) – Measurement grid for the exported distribution.
r_step (float) – Measurement grid for the exported distribution.
phi_num_bins (int) – Measurement grid for the exported distribution.
background_color (str) – Cosmetic.
title (str) – Cosmetic.
show_progress (bool) – Forwarded to the g3 measurement call.
show_all_triplets (bool) – If True, the viewer renders a grid of all triplet heatmaps simultaneously (sharing one legend and colour scale) instead of the interactive single-panel view. Useful for multi- species cases like SiO₂ where it’s otherwise unclear which triplet channel is being displayed.
self (Supercell) –
- Return type:
- export_g2_html(output_path=None, *, r_max=10.0, r_step=0.05, background_color='#f7f8f5', title='', show_progress=False)¶
Export a standalone interactive 2D g(r) viewer.
Shows the per-species-pair pair-correlation function g_{AB}(r) as a single g(r) plot with a dropdown to switch species pair, and an “overlay all” checkbox to compare all pairs on one axis. Essentially the bottom panel of
export_g3_html()lifted out on its own with a species-pair selector - useful as a quick 2-body PDF viewer without any angular content.- Parameters:
output_path (str | None) – Path to write the HTML file. When
Nonethe HTML is not written to disk; the raw HTML string is still returned so the caller can embed it directly (for example viaIPython.display.HTML()) - see alsoplot_g2()for a ready-made Jupyter wrapper.r_max (float) – Radial grid for the measurement. A finer
r_step(default 0.05 Å) gives smoother curves than the coarse 0.1 Å grid used by the g3 viewer.r_step (float) – Radial grid for the measurement. A finer
r_step(default 0.05 Å) gives smoother curves than the coarse 0.1 Å grid used by the g3 viewer.background_color (str) – Cosmetic.
title (str) – Cosmetic.
show_progress (bool) – Forwarded to the underlying
measure_g3()call (this exporter reuses the g3 machinery because the g2 array is a by-product;phi_num_binsis set low for speed).self (Supercell) –
- Returns:
The resolved output path when
output_pathwas provided, otherwise the HTML source string.- Return type:
Class attributes
- PRESETS: dict[str, dict[str, Any]] = {'LRO': {'angle_weight': 1.0, 'bond_weight': 2.0, 'displacement_sigma': 0.04, 'grain_size': 18.0, 'hard_core_scale': 0.95, 'nonbond_push_scale': 0.9, 'num_steps': 150}, 'MRO': {'angle_weight': 0.9, 'bond_weight': 1.9, 'displacement_sigma': 0.04, 'grain_size': 13.0, 'hard_core_scale': 0.95, 'nonbond_push_scale': 0.7, 'num_steps': 150, 'repulsion_weight': 2.5}, 'SRO': {'angle_weight': 1.0, 'bond_weight': 2.2, 'displacement_sigma': 0.04, 'grain_size': 10.0, 'hard_core_scale': 0.95, 'nonbond_push_scale': 0.6, 'num_steps': 200, 'repulsion_weight': 2.0}, 'amorphous': {'angle_weight': 0.6, 'bond_weight': 1.2, 'displacement_sigma': 0.08, 'grain_size': 6.0, 'hard_core_scale': 0.9, 'nonbond_push_scale': 0.5, 'num_steps': 150, 'repulsion_weight': 1.5}, 'liquid': {'angle_weight': 0.5, 'bond_weight': 0.4, 'grain_size': None, 'hard_core_scale': 0.75, 'nonbond_push_scale': 0.7, 'num_steps': 100, 'repulsion_weight': 0.5}, 'nanocrystalline': {'angle_weight': 1.5, 'bond_weight': 3.0, 'displacement_sigma': 0.02, 'grain_size': 20.0, 'num_steps': 150}}¶
Presets¶
Ready-to-use parameter dictionaries available as Supercell.PRESETS.
See the
silicon preset summary
for the per-regime values used in the static examples.