CoordinationShellTarget¶
First-shell coordination targets extracted from a reference crystal via
Gaussian-mixture decomposition of each
species-pair g(r) and of each rooted-angle distribution. The result
drives the bond-length, angle, and repulsion springs in
tricor.Supercell.generate() /
tricor.Supercell.shell_relax().
- class tricor.CoordinationShellTarget(atoms, label, species, species_labels, phi_num_bins, phi_edges, phi, phi_deg, angle_index, angle_lookup, pair_hard_min, pair_inner, pair_peak, pair_sigma, pair_outer, pair_mask, coordination_target, coordination_std, angle_target, angle_pair_mass_target, angle_mode_deg, angle_enabled_mask, motif_center_species, motif_neighbor_species, motif_neighbor_vectors, max_pair_outer, max_pair_outer_by_center, summary)[source]¶
Bases:
objectSpecies-aware first-shell coordination targets extracted from a crystal.
Construction
- Parameters:
atoms (Atoms) –
label (str) –
species (ndarray) –
phi_num_bins (int) –
phi_edges (ndarray) –
phi (ndarray) –
phi_deg (ndarray) –
angle_index (ndarray) –
angle_lookup (ndarray) –
pair_hard_min (ndarray) –
pair_inner (ndarray) –
pair_peak (ndarray) –
pair_sigma (ndarray) –
pair_outer (ndarray) –
pair_mask (ndarray) –
coordination_target (ndarray) –
coordination_std (ndarray) –
angle_target (ndarray) –
angle_pair_mass_target (ndarray) –
angle_mode_deg (ndarray) –
angle_enabled_mask (ndarray) –
motif_center_species (ndarray) –
max_pair_outer (float) –
max_pair_outer_by_center (ndarray) –
- classmethod from_atoms(atoms, *, phi_num_bins=72, shell_hist_step=0.05, shell_smooth_sigma_bins=1.2, extract_cutoff=None, auto_filter_lattice_artifacts=True, label=None)[source]¶
Extract first-shell coordination, distance, and angle targets from a reference crystal.
For every species pair in
atomsthe method fits the first peak of the radial pair distribution g(r) — its inner edge, peak position, Gaussian width, and outer edge — and counts the average number of neighbours each centre atom has within that window. For every triplet (centre, neighbour-A, neighbour-B) species combination it builds a histogram of bond angles ranged 0–180° usingphi_num_binsbins, identifying the dominant angle mode. All quantities are stored as 2-D / 3-D numpy arrays indexed by species index inspecies.- Parameters:
atoms (ase.Atoms) – Reference crystal whose g(r) and bond-angle distributions define the target geometry. Must be a periodic cell with at least one neighbour pair within
extract_cutoff(auto ifNone).phi_num_bins (int, optional) – Number of bins used to discretise the [0, 180°] bond-angle axis. Default
72(2.5° per bin). Higher values sharpen the angle target but slow down the angle measurement loop inSupercell.measure_g3().shell_hist_step (float, optional) – Bin width (Å) of the per-pair radial histogram used to locate the first peak. Default
0.05Å.shell_smooth_sigma_bins (float, optional) – Gaussian smoothing width (in bins) applied to the radial histogram before peak detection. Default
1.2bins.extract_cutoff (float, optional) – Maximum centre-neighbour distance (Å) considered when building the neighbour list. If
Nonethe routine picksmin(default, max(3.8 × NN, NN + 2))based on the inferred nearest-neighbour distance.auto_filter_lattice_artifacts (bool, optional) – If
True(default), zero outcoordination_targetfor species pairs that represent lattice artefacts rather than real chemical bonds. A pair(i, j)is kept only whenpair_peak[i, j]is the smallest enabled peak in either rowior columnj. This automatically silences the second-shellSi-Si/O-Osprings inSiO2, theSr-Sr/Ti-Ti/O-O/Sr-Tisprings inSrTiO3, etc. Set toFalseto keep every extracted pair (pre-2026 behaviour); callers can also override the filter by chainingwith_bonded_species_pairs()after extraction.label (str, optional) – Free-text identifier carried along on the returned target (used in plot legends and HTML viewer titles). Default uses the chemical formula of
atoms.
- Returns:
Frozen dataclass populated with every per-species and per-triplet field listed in the class header (
coordination_target,pair_peak,pair_inner,angle_target,angle_mode_deg, etc.). All ndarray fields are pre-symmetrised over species pairs and the angle-enabled mask is initialised toTrueeverywhere.- Return type:
Notes
Single-element references (Si, Cu, …) produce a 1×1 coordination matrix and one self-self angle channel. Multi-element references (SiO₂, SrTiO₃, …) populate every cross-pair entry — see
with_cross_species_bonds_only()andwith_bonded_species_pairs()for masking helpers when only a subset of pairs represents real chemical bonds.Examples
>>> from ase.build import bulk >>> import tricor as tc >>> atoms = bulk("Si", "diamond", a=5.431) >>> shell = tc.CoordinationShellTarget.from_atoms(atoms, ... phi_num_bins=90) >>> shell.coordination_target # 4 NN per Si array([[4.]]) >>> float(shell.pair_peak[0, 0]) 2.352
- classmethod from_targets(targets, *, cross_pair_peak=None, cross_pair_outer_scale=1.15, label=None)[source]¶
Stack multiple shell targets into one with a widened species axis.
Used for blended materials where atoms share an atomic number but want different local coordination (e.g. graphite sp² + diamond sp³ carbon). Each input target contributes a virtual species slot per element of its
speciesarray; the composite target’sspeciesis the concatenation of all inputs, withspecies_labelsrewritten asf"{key}_{element}".Cross-target pairs default to:
coordination_target = 0(no bonds form across virtual species boundaries; the repulsion term still keeps them apart),pair_peak = mean(peak_a, peak_b)unless overridden bycross_pair_peak,pair_outer = max(outer_a, outer_b) * cross_pair_outer_scale,pair_hard_min/pair_innerpro-rated from the two source values.
Cross-target triplets (any of the three species drawn from a different source than the other two) get
coordination_target = 0and zeroangle_mode_deg- the relaxer will never enumerate these triplets because no such bonds form.- Parameters:
targets (dict[str, CoordinationShellTarget]) – Mapping
{key: CoordinationShellTarget}. Insertion order defines the virtual-species order.cross_pair_peak (dict[tuple[str, str], float] | None) – Optional overrides for
pair_peakbetween elements drawn from different source targets. Keys are(key_a, key_b)with symbol lookup done viaatomic_numberswhen pair contains non-tuple element labels.cross_pair_outer_scale (float) – Multiplier applied to the larger of the two source
pair_outervalues when populating cross-target entries.label (str | None) – Optional label; defaults to
"composite(" + keys + ")".
- Return type:
Modifiers
- with_cross_species_bonds_only()[source]¶
Return a copy where same-species
coordination_targetentries are zeroed.Useful for network-former compounds such as SiO₂ where only cross-species pairs (Si-O) are real chemical bonds; the same-species “shell” peaks (Si-Si, O-O) come from the second coordination shell through the bridging atom and should not be treated as bonds by
Supercell.shell_relax()(which would otherwise install spurious angle springs on triplets like Si-Si-Si or O-O-O whoseangle_mode_degis just a geometric artefact of the reference sampling, not a physical target).- Returns:
New target whose
coordination_targetdiagonal is zeroed (off-diagonal cross-species entries preserved). The original target is unmodified.- Return type:
- with_bonded_species_pairs(pairs)[source]¶
Return a copy whose
coordination_targetis zero everywhere except for the listed species pairs.Useful for materials with spectator ions: perovskites like SrTiO₃ want only Ti-O bonds considered by
Supercell.shell_relax(), since Sr-O, Sr-Ti, O-O, Ti-Ti, etc. would either install spurious angle springs (angle_mode_degis a geometric artefact for non-bond triplets) or pin atoms via bond springs to distances that are really second-shell separations, not chemical bonds.- Parameters:
pairs (list of tuple of str) – Each
(symbol_a, symbol_b)pair is treated symmetrically — both directions in thecoordination_targetmatrix are preserved. Pairs whose symbols don’t appear inself.species_labelsare silently skipped.- Returns:
A new
CoordinationShellTarget(the original is left unmodified) whosecoordination_targetkeeps only the listed species-pair entries; every other slot is zeroed soSupercell.shell_relax()won’t try to enforce bonds there.- Return type:
Examples
# SrTiO3: preserve only TiO6 octahedra st.with_bonded_species_pairs([('Ti', 'O')]) # SiO2: equivalent to ``with_cross_species_bonds_only`` for a # binary, but explicit about what a bond is st.with_bonded_species_pairs([('Si', 'O')])
- with_angle_triplets(triplets)[source]¶
Return a copy whose angle-spring mask is enabled only for the listed triplet types; all other angle springs are disabled.
Each triplet is
(centre_symbol, neighbour_1_symbol, neighbour_2_symbol); both (n1, n2) and (n2, n1) are enabled automatically. Bond-distance springs are untouched - only the angle springs installed duringshell_relaxare filtered.Useful for multi-modal shells where the extracted
angle_mode_degpicks one peak of a bimodal / quadrimodal distribution; enforcing it would strain the other modes. SrTiO₃’s SrO₁₂ cuboctahedron (O-Sr-O angles at 60°/90°/120°/180°) is the canonical example.- Parameters:
triplets (list of tuple of str) – Each
(centre, n1, n2)triplet enables the angle-spring term for that combination of species. Ordering ofn1andn2is symmetrised internally.- Returns:
New target whose
angle_enabled_maskisTrueonly for the listed triplets; every other triplet’s angle spring is silenced.- Return type:
Examples
# Keep Ti-centered 90° and linear O-Ti-Ti 180° angle # springs; silence every Sr-centered or Sr-in-triplet # angle spring. st.with_angle_triplets([ ('Ti', 'O', 'O'), ('O', 'Ti', 'Ti'), ])
- without_angle_triplets(triplets)[source]¶
Return a copy with the angle mask disabled for the listed triplets.
Inverse of
with_angle_triplets(): starts from the currentangle_enabled_maskand turns OFF the listed triplets, leaving every other triplet’s angle spring intact.
Helpers
Restricting the bond graph¶
In multi-element compounds only a subset of species pairs represent
actual chemical bonds (e.g. Si-O in silica; Ti-O and Sr-O in
perovskites) — the other pairs’ first-shell peaks are lattice
separations through a bridging atom, and relaxing against them can
destroy the coordination geometry. from_atoms zeroes those
lattice-artefact pairs automatically
(auto_filter_lattice_artifacts=True): any pair whose pair_peak
is not the smallest in either its row or column is excluded. Two
helpers set the bond graph explicitly when the automatic rule is not
what you want:
# SiO2: only Si-O is a real bond (equivalent to the two-species helper)
st = tc.CoordinationShellTarget.from_atoms(atoms, phi_num_bins=90)
st = st.with_cross_species_bonds_only()
# SrTiO3: both Ti-O and Sr-O are real bonds. The SrO12 cuboctahedron
# is multi-modal (60°/90°/120°/180°) so Sr-centered angle springs
# would strain the other modes; mask them out but keep the Ti-O
# distance springs intact.
st = (
tc.CoordinationShellTarget.from_atoms(atoms, phi_num_bins=90)
.with_bonded_species_pairs([('Ti', 'O'), ('Sr', 'O')])
.with_angle_triplets([('Ti', 'O', 'O'), ('O', 'Ti', 'Ti')])
)
Masking angle springs (multi-modal shells)¶
Some coordination shells are multi-modal: the single
angle_mode_deg peak that from_atoms extracts is just the tallest
bar of a distribution with several physically valid modes. The
canonical example is the 12-coordinated cuboctahedron (Cu FCC, SrO₁₂
in SrTiO₃) whose angle distribution sits at 60° / 90° / 120° / 180°
simultaneously, so enforcing any one mode distorts the others.
Two helpers operate on the angle_enabled_mask field:
with_angle_triplets(triplets): whitelist; enable angle springs only for the listed triplet types.without_angle_triplets(triplets): blacklist; disable angle springs for the listed triplets, keep the rest.
Bond-distance springs are unaffected; masking only controls the
angle force term. For copper, the whole thing is replaced with
angle_weight=0.0 in the regime presets, but for mixed compounds
like SrTiO₃ you want 90° preserved on the TiO₆ octahedron while
silencing the Sr-centered cuboctahedron:
st.with_angle_triplets([
('Ti', 'O', 'O'), # O-Ti-O at 90° (octahedral)
('O', 'Ti', 'Ti'), # Ti-O-Ti at 180° (linear backbone)
])
Blending two reference crystals¶
For materials with a controllable phase mix (sp²/sp³ carbon; SiO₂ /
Si₃N₄ nitride-silica blends; etc.) extract one shell target per
chemistry and combine them with from_targets:
shell_sp2 = tc.CoordinationShellTarget.from_atoms(atoms_graphite, phi_num_bins=90)
shell_sp3 = tc.CoordinationShellTarget.from_atoms(atoms_diamond, phi_num_bins=90)
shell_target = tc.CoordinationShellTarget.from_targets(
{"sp2": shell_sp2, "sp3": shell_sp3},
)
The composite target holds virtual species (e.g. sp2_C at
index 0, sp3_C at index 1): both atomic number 6, but with
distinct coordination_target rows (3 vs 4), pair_peak (1.42
vs 1.54 Å), and angle_mode_deg (120° vs 109.5°). Each atom’s
virtual species is assigned at grain-build time via
Supercell.generate(..., grain_sources=[...]) (see
Carbon example); the relaxer then
pulls each atom toward the geometry of its source crystal.