Skip to content

Utils

Utility functions for structure generation, manipulation, and analysis.

random_packed_structure

random_packed_structure(composition: Composition, cell: ndarray, *, seed: int = 42, diameter: Optional[float] = None, auto_diameter: bool = False, max_iter: int = 100, fmax: float = 0.01, distance_tolerance: float = 0.0001, trajectory_file: Optional[str] = None, verbose: bool = True) -> tuple[Atoms, Optional[list[dict]]]

Generate a random packed atomic structure with minimal atomic overlaps.

Parameters:

Name Type Description Default
composition Composition

Pymatgen Composition object specifying atomic composition (e.g. Fe80B20). Numbers indicate actual atom counts.

required
cell ndarray

3x3 array defining triclinic simulation box in Angstroms.

required
seed int

Random seed for reproducible generation, by default 42. If None, uses random initialization.

42
diameter float

Minimum allowed interatomic distance for overlap detection. Used for soft-sphere potential, by default None.

None
auto_diameter bool

If True, automatically calculate diameter from atomic radii, by default False.

False
max_iter int

Maximum FIRE optimization steps to minimize overlaps, by default 100.

100
fmax float

Maximum force criterion for convergence in eV/Å, by default 0.01.

0.01
distance_tolerance float

Distance threshold for considering atoms at same position, by default 0.0001.

0.0001
trajectory_file str

Path to save optimization trajectory (.traj format), by default None.

None
verbose bool

Print progress information during optimization, by default True.

True

Returns:

Type Description
tuple[Atoms, Optional[list[dict]]]
  • ASE Atoms object with optimized positions
  • Optimization log if verbose=True, otherwise None

get_diameter

get_diameter(composition: Composition) -> float

Calculate characteristic atomic diameter for a chemical composition.

Parameters:

Name Type Description Default
composition Composition

Pymatgen Composition object specifying the chemical formula.

required

Returns:

Type Description
float

Estimated minimum atomic diameter in Angstroms.

Notes

For multi-element compositions, calculates minimum possible interatomic distance by: - Using ionic radii for each element - Finding minimum sum of radii across all element pairs

For single elements: - Uses metallic radius for metals - Uses atomic radius for non-metals, falling back to ionic radius if needed - Returns twice the radius as diameter

extract_crystallizable_subcells

extract_crystallizable_subcells(atoms: Atoms, *, d_frac: float = 0.2, n_min: int = 2, n_max: int = 8, cubic_only: bool = True, allowed_atom_counts: Optional[list[int]] = None, filter_function: Optional[Callable] = None, restrict_to_compositions: Optional[Sequence[str]] = None, max_coeff: Optional[int] = None, elements: Optional[Sequence[str]] = None) -> list[Atoms]

Extract and filter subcells from an amorphous structure for crystallization analysis.

Divides an amorphous structure into overlapping subcells and filters them based on shape criteria and atom count to identify potential crystalline structural motifs.

Parameters:

Name Type Description Default
atoms Atoms

ASE Atoms object representing the amorphous structure

required
d_frac float

Grid spacing in fractional coordinates for subcell division, by default 0.2

0.2
n_min int

Minimum number of atoms required in a subcell, by default 2

2
n_max int

Maximum number of atoms allowed in a subcell, by default 8

8
cubic_only bool

If True, only keep subcells where all dimensions are equal, by default True

True
allowed_atom_counts list[int]

If provided, only keep subcells with these atom counts, by default None

None
filter_function callable

Custom filter function that takes a subcell tuple (indices, lower_bound, upper_bound) and returns a boolean. If provided, used instead of default filter, by default None

None
restrict_to_compositions Sequence[str]

Chemical formulas to filter subcells by (e.g. ["AB", "AB2"]). Only matching compositions are returned.

None
max_coeff int

Maximum stoichiometric coefficient for auto-generating restrictions. E.g. max_coeff=2 allows AB2 but not AB3.

None
elements Sequence[str]

Elements for generating stoichiometries. Required if max_coeff provided.

None

Returns:

Type Description
list[Atoms]

List of ASE Atoms objects representing the filtered subcells

get_subcells_to_crystallize

get_subcells_to_crystallize(fractional_positions: ndarray, species: list[str], d_frac: float = 0.05, n_min: int = 1, n_max: int = 48, restrict_to_compositions: Optional[Sequence[str]] = None, max_coeff: Optional[int] = None, elements: Optional[Sequence[str]] = None) -> list[tuple[np.ndarray, np.ndarray, np.ndarray]]

Extract subcell structures from a larger structure for crystallization.

Parameters:

Name Type Description Default
fractional_positions ndarray

Fractional coordinates of atoms, shape [n_atoms, 3].

required
species list[str]

Chemical element symbols for each atom.

required
d_frac float

Grid spacing in fractional coordinates. Smaller values create more overlap.

0.05
n_min int

Minimum atoms per subcell.

1
n_max int

Maximum atoms per subcell.

48
restrict_to_compositions Sequence[str]

Chemical formulas to filter subcells by (e.g. ["AB", "AB2"]). Only matching compositions are returned.

None
max_coeff int

Maximum stoichiometric coefficient for auto-generating restrictions. E.g. max_coeff=2 allows AB2 but not AB3.

None
elements Sequence[str]

Elements for generating stoichiometries. Required if max_coeff provided.

None

Returns:

Type Description
list[tuple[ndarray, ndarray, ndarray]]

List of (indices, lower_bounds, upper_bounds) where: - indices: Atom indices in subcell - lower_bounds: Lower bounds in fractional coords [3] - upper_bounds: Upper bounds in fractional coords [3]

Notes

Divides a structure into overlapping subcells that can be relaxed to find stable crystal structures. Uses a grid in fractional coordinates to identify atom groups meeting size and composition criteria.

default_subcell_filter

default_subcell_filter(subcell: tuple[ndarray, ndarray, ndarray], cubic_only: bool = True, allowed_atom_counts: Optional[list[int]] = None) -> bool

Filter subcells based on shape and size criteria.

Parameters:

Name Type Description Default
subcell tuple[ndarray, ndarray, ndarray]

Tuple containing (atom_indices, lower_bound, upper_bound) arrays that define the subcell

required
cubic_only bool

If True, only accept subcells with equal dimensions in x, y, and z

True
allowed_atom_counts list[int]

List of allowed atom counts. If provided, only accept subcells with specified atom counts

None

Returns:

Type Description
bool

True if subcell meets all criteria, False otherwise

subcells_to_structures

subcells_to_structures(candidates: list[tuple[ndarray, ndarray, ndarray]], fractional_positions: ndarray, cell: ndarray, species: list[str]) -> list[tuple[np.ndarray, np.ndarray, list[str]]]

Convert subcell candidates to structure tuples.

Parameters:

Name Type Description Default
candidates list[tuple[ndarray, ndarray, ndarray]]

List of (atom_indices, lower_bound, upper_bound) tuples defining subcell regions

required
fractional_positions ndarray

Fractional coordinates of all atoms in parent structure, shape [n_atoms, 3]

required
cell ndarray

3x3 array representing parent unit cell

required
species list[str]

Chemical symbols for all atoms in parent structure

required

Returns:

Type Description
list[tuple[ndarray, ndarray, list[str]]]

List of (frac_coords, cell, species) tuples for each subcell: - frac_coords: Normalized [0,1] fractional coordinates - cell: Scaled 3x3 subcell - species: Chemical symbols for subcell atoms

valid_subcell

valid_subcell(atoms: Atoms, initial_energy: float, final_energy: float, *, e_tol: float = 0.001, fe_lower_limit: float = -5.0, fe_upper_limit: float = 0.0, fusion_distance: float = 1.5, distance_tolerance: float = 0.0001) -> bool

Validate a relaxed subcell structure.

Parameters:

Name Type Description Default
atoms Atoms

ASE Atoms object with atomic positions, species, and cell information.

required
initial_energy float

Total energy before relaxation in eV.

required
final_energy float

Total energy after relaxation in eV.

required
e_tol float

Energy tolerance (eV) for comparing initial and final energies.

0.001
fe_lower_limit float

Lower limit for formation energy (eV/atom). More negative values are unphysical.

-5.0
fe_upper_limit float

Upper limit for formation energy (eV/atom). Higher values indicate poor convergence.

0.0
fusion_distance float

Minimum allowed interatomic distance (Å). Shorter distances indicate atomic fusion.

1.5
distance_tolerance float

Distance tolerance (Å) for considering atoms at same position.

0.0001

Returns:

Type Description
bool

True if structure passes all validation checks: - Formation energy is physically reasonable - Energy decreased during relaxation - Final energy indicates good convergence - No atomic fusion detected

min_distance

min_distance(structure: Structure, distance_tolerance: float = 0.0001) -> float

Calculate minimum interatomic distance in a periodic structure.

Computes the smallest non-zero distance between any pair of atoms, accounting for periodic boundary conditions. Self-interactions are excluded via a distance tolerance.

Parameters:

Name Type Description Default
structure Structure

Pymatgen Structure object containing atomic positions and cell information

required
distance_tolerance float

Distances below this value (in Å) are considered self-interactions and ignored

0.0001

Returns:

Type Description
float

Minimum distance between any two different atoms in Å

get_target_temperature

get_target_temperature(step: int, equi_steps: int, cool_steps: int, T_high: float, T_low: float) -> float

Calculate target temperature for a melt-quench-equilibrate simulation step.

Parameters:

Name Type Description Default
step int

Current simulation step number (0-indexed)

required
equi_steps int

Number of steps for initial high-temperature equilibration

required
cool_steps int

Number of steps for linear cooling

required
T_high float

Initial high temperature in Kelvin

required
T_low float

Final low temperature in Kelvin

required

Returns:

Type Description
float

Target temperature in Kelvin for the current step

Notes

The temperature profile consists of three phases: 1. Initial equilibration at T_high for equi_steps 2. Linear cooling from T_high to T_low over cool_steps 3. Final equilibration at T_low for remaining steps

Examples:

>>> get_target_temperature(10, 100, 200, 2000.0, 300.0)  # During equilibration
2000.0
>>> get_target_temperature(200, 100, 200, 2000.0, 300.0)  # During cooling
1150.0
>>> get_target_temperature(350, 100, 200, 2000.0, 300.0)  # After cooling
300.0