Quick Start

Installation

pip install tricor

Or to install the development checkout:

git clone https://github.com/ophusgroup/tricor.git
cd tricor
uv sync                # or: pip install -e '.[test]'

tricor requires Python ≥ 3.10. numba is a hard dependency (installed automatically) and powers both the parallel measure_g3 kernel and the thermal_relax / grain-orientation-refinement features.

Minimal example

Generate a silicon MRO supercell, inspect its three-body distribution, and open the interactive 3D viewer:

from ase.build import bulk
import tricor as tc

# 1. Reference crystal and first-shell target
atoms = bulk("Si", "diamond", a=5.431)
shell_target = tc.CoordinationShellTarget.from_atoms(atoms, phi_num_bins=90)

# 2. Create the empty supercell
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,
)

# 3. Generate a medium-range-order structure
cell.generate(shell_target, **tc.Supercell.PRESETS["MRO"])

# 4. Measure and view the three-body distribution
cell.measure_g3()
cell.plot_g3()

# 5. Interactive 3D viewer (Jupyter); blue Si tetrahedra by default
cell.view_structure()

Presets

Supercell.PRESETS provides tuned keyword dictionaries for silicon in six disorder regimes. Expand any entry directly into generate:

cell.generate(shell_target, **tc.Supercell.PRESETS["MRO"])

Available keys, in order of increasing structural order:

Preset

Grain size (Å)

Notes

liquid

-

No grains; fully random starting positions.

amorphous

6

Short-range tetrahedral network with 6 Å grains.

SRO

10

Short-range order.

MRO

13

Medium-range order.

LRO

18

Long-range order.

nanocrystalline

20

Few large grains per cell (≈ 8 grains in a 40 Å cube).

See the preset summary table on the silicon examples page for the full parameter values.

Multi-species materials

For binary / ternary materials the default CoordinationShellTarget allows bonds between every species pair, which lets shell_relax develop spurious second-shell bonds (e.g. Si-Si in SiO₂, Ti-Ti in SrTiO₃). Restrict bonds to the real chemical connections before calling generate:

# SiO2: every bond is cross-species (Si-O)
shell_target = (
    tc.CoordinationShellTarget.from_atoms(atoms_sio2, phi_num_bins=90)
    .with_cross_species_bonds_only()
)

# SrTiO3: both Ti-O and Sr-O are real bonds; silence the
# multi-modal Sr-centered cuboctahedral angle springs so only the
# single-mode Ti-centered 90° and Ti-O-Ti 180° remain.
shell_target = (
    tc.CoordinationShellTarget.from_atoms(atoms_sto, phi_num_bins=90)
    .with_bonded_species_pairs([("Ti", "O"), ("Sr", "O")])
    .with_angle_triplets([("Ti", "O", "O"), ("O", "Ti", "Ti")])
)

Phase blends (sp²/sp³ carbon, etc.)

For materials with a controllable phase mix (sp² ↔ sp³ carbon, a polymer/ceramic boundary, etc.), extract one shell target per chemistry and combine them with from_targets:

from ase.io import read
atoms_g = read("docs/structures/C_graphite.cif")
atoms_d = read("docs/structures/C_diamond.cif")

shell_sp2 = tc.CoordinationShellTarget.from_atoms(atoms_g, phi_num_bins=90)
shell_sp3 = tc.CoordinationShellTarget.from_atoms(atoms_d, phi_num_bins=90)
shell_target = tc.CoordinationShellTarget.from_targets(
    {"sp2": shell_sp2, "sp3": shell_sp3},
)

# 50/50 graphite/diamond grains, assigned at Voronoi-grain time
cell.generate(
    shell_target,
    grain_size=10.0,
    grain_sources=[
        {"atoms": atoms_g, "species_offset": 0, "weight": 0.5},  # sp²
        {"atoms": atoms_d, "species_offset": 1, "weight": 0.5},  # sp³
    ],
    num_steps=120, bond_weight=2.0, angle_weight=1.0,
    repulsion_weight=2.0, hard_core_scale=0.9,
    nonbond_push_scale=0.8, displacement_sigma=0.03,
)

Each atom inherits a virtual-species index (0 = sp², 1 = sp³) from its grain, and the relaxer pulls each atom toward the coordination + angle target of its source chemistry. See the Carbon example for the full regime ladder.

Regime-ladder comparison

Building the same material across every preset and comparing the results side-by-side is a standard tricor workflow:

cells = {}
for name in ["liquid", "amorphous", "SRO", "MRO", "LRO", "nanocrystalline"]:
    c = 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)
    c.generate(shell_target, **tc.Supercell.PRESETS[name])
    cells[name] = c

# Overlaid g(r) stack (most disordered bottom, most ordered top)
tc.plot_g2_compare(cells, r_max=8.0, title="Silicon regime ladder")

# Synchronised rotating 3D grid
tc.export_overview_html("overview.html", list(cells.items()))

Accessing the structure

After generate(), the ASE Atoms object is at cell.atoms:

cell.atoms.write("supercell.cif")

positions   = cell.atoms.positions      # (N, 3)
numbers     = cell.atoms.numbers        # (N,)
cell_matrix = cell.atoms.cell.array     # (3, 3)

Exporting interactive HTML

Every visualiser has a standalone-HTML counterpart that bakes the scene into one file; no server is required to view it.

# Trajectory playback needs capture_trajectory=True during generate()
cell.generate(shell_target, capture_trajectory=True, **tc.Supercell.PRESETS["MRO"])

cell.export_trajectory_html("mro_trajectory.html")
cell.export_g3_html("mro_g3.html")
cell.export_g2_html("mro_g2.html")

See the Visualization section for the full set of viewers (3D structure, rotating movies, trajectory playback, multi-panel overview, g(r), g3).

Next steps

  • Static Examples: case studies across materials, with interactive viewers embedded.

  • Generating order variety: batch generation of every disorder regime for a single material.

  • Generating very large cells: the bond_relax shortcut + MC-subsampled g(r) / g3 measurement for production cells at 100³ Å and beyond.

  • Algorithms: mathematical details of grain construction, shell relaxation, and target-g3 construction.

  • API reference: every public class and function.