assyst package

Submodules

assyst.crystals module

Crystal structure generation step of ASSYST.

class assyst.crystals.Formulas(atoms: tuple[dict[str, int], ...])

Bases: Sequence

Simple helper to generate lists of structure compositions.

sample_space_groups() is the intended consumer and expects an iterable of dictionaries, where each dictionary maps an element name to the number of atoms of this type in one structure. Formulas behaves as if it were such a tuple, but extends the basic python arithmetic operations to make building the list a bit simpler.

The class can be initialized from any tuple of dictionaries.

>>> el_manual = Formulas(({'Cu': 1}, {'Cu': 2}))

range() is a helper class method that initializes Formulas for a single element and takes the same arguments as the builtin range, except that it skips the zero.

>>> el = Formulas.range('Cu', 3)
Formulas(atoms=({'Cu': 1}, {'Cu': 2}))
>>> el == el_manual
True

Addition is overloaded to the addition of the underlying tuples.

>>> Formulas.range('Cu', 1, 5) == Formulas.range('Cu', 1, 3) + Formulas.range('Cu', 3, 5)

The bitwise or operation is akin to the inner product

>>> Formulas.range('Cu', 3) | Formulas.range('Ag', 3)
Formulas(atoms=({'Cu': 1, 'Ag': 1}, {'Cu': 2, 'Ag': 2}))
>>> Formulas.range('Cu', 3) * Formulas.range('Ag', 3)
Formulas(atoms=({'Cu': 1, 'Ag': 1}, {'Cu': 2, 'Ag': 1}, {'Cu': 1, 'Ag': 2}, {'Cu': 2, 'Ag': 2}))
atoms: tuple[dict[str, int], ...]
property elements: set[str]

Set of elements present in elements.

classmethod range(elements: str | Iterable[str], *range_args) Self

Creates formulas with number of atoms as given by the builtin range.

Multiple elements are combined as the outer product.

trim(min_atoms: int = 1, max_atoms: int | None = None) Self

Returns a copy of itself with formulas with lesser or more atoms than given limits removed.

assyst.crystals.pyxtal(group: int | list[int], species: tuple[str], num_ions: tuple[int], dim=3, repeat=1, allow_exceptions=True, **kwargs) Atoms | list[dict]

Generate random crystal structures with PyXtal.

group must be between 1 and the largest possible value for the given dimensionality:

dim=3 => 1 - 230 (space groups) dim=2 => 1 - 80 (layer groups) dim=1 => 1 - 75 (rod groups) dim=0 => 1 - 58 (point groups)

When group is passed as a list of integers or repeat>1, generate multiple structures and return them in a list of dicts containing the keys atoms, symmetry and repeat for the ASE structure, the symmetry group number and which iteration it is, respectively.

Parameters:
  • group (list of int, or int) – the symmetry group to generate or a list of them

  • species (tuple of str) – which species to include, defines the stoichiometry together with num_ions

  • num_ions (tuple of int) – how many of each species to include, defines the stoichiometry together with species

  • dim (int) – dimensionality of the symmetry group, 0 is point groups, 1 is rod groups, 2 is layer groups and 3 is space groups

  • repeat (int) – how many random structures to generate

  • allow_exceptions (bool) – when generating multiple structures, silence errors when the requested stoichiometry and symmetry group are incompatible

  • **kwargs – passed to pyxtal.pyxtal function verbatim

Returns:

the generated structure, if repeat==1 and only one symmetry group is requested list of dict of all generated structures, if repeat>1 or multiple symmetry groups are requested

Return type:

Atoms

Raises:
  • ValueError – if species and num_ions are not of the same length

  • ValueError – if stoichiometry and symmetry group are incompatible and allow_exceptions==False or only one structure is requested

assyst.crystals.sample_space_groups(formulas: Formulas | Iterable[dict[str, int]], spacegroups: list[int] | tuple[int, ...] | Iterable[int] | None = None, min_atoms: int = 1, max_atoms: int = 10, max_structures: int | None = None, dim: Literal[0, 1, 2, 3] = 3, tolerance: Literal['metallic', 'atomic', 'molecular', 'vdW'] | DistanceFilter | dict = 'metallic') Iterator[Atoms]

Create symmetric random structures.

Parameters:
  • formulas (Formulas or iterable of dicts from str to int) – list of chemical formulas

  • spacegroups (list of int) – which space groups to generate

  • max_atoms (int) – do not generate structures larger than this

  • max_structures (int) – generate at most this many structures

  • dim (one of 0, 1, 2, or 3) – the dimensionality of the structures to generate; if lower than 3 the code generates samples no longer from space groups, but from the subperiodic layer, rod, or point groups.

  • tolerance (str, dict of elements to radii) – specifies minimum allowed distances between atoms in generated structures; if str then it should be one values understood by pyxtal.tolerace.Tol_matrix; if dict each value gives the minimum radius allowed for an atom, whether a given distance is allowed then depends on the sum of the radii of the respective elements

Yields:

Atoms – random symmetric crystal structures

assyst.relax module

Relaxation step of ASSYST.

class assyst.relax.CellRelax(max_steps: int = 100, force_tolerance: float = 0.001, algorithm: Literal['LBFGS'] = 'LBFGS')

Bases: Relax

Minimize energy while keeping relative positions and volume constant.

apply_filter_and_constraints(structure: Atoms)

Hook to allow subclasses to add filters and constraints.

class assyst.relax.FullRelax(max_steps: int = 100, force_tolerance: float = 0.001, algorithm: Literal['LBFGS'] = 'LBFGS', pressure: float = 0.0)

Bases: Relax

Minimize energy with respect to internal positions and cell without constraints.

apply_filter_and_constraints(structure: Atoms)

Hook to allow subclasses to add filters and constraints.

pressure: float = 0.0
class assyst.relax.Relax(max_steps: int = 100, force_tolerance: float = 0.001, algorithm: Literal['LBFGS'] = 'LBFGS')

Bases: object

Minimize energy with respect to internal positions.

Also used as a base class for all other relaxation.

algorithm: Literal['LBFGS'] = 'LBFGS'
apply_filter_and_constraints(structure: Atoms)

Hook to allow subclasses to add filters and constraints.

force_tolerance: float = 0.001
max_steps: int = 100
relax(structure: Atoms) Atoms

Relax a structure and return result.

Structure must have a calculator attached. Returned structure will have a SinglePointCalculator with the final energy, forces and stresses attached.

Parameters:

structure (ase.Atoms) – structure to relax

Returns:

relaxed structure with attached single point calculator.

Return type:

ase.Atoms

class assyst.relax.SymmetryRelax(max_steps: int = 100, force_tolerance: float = 0.001, algorithm: Literal['LBFGS'] = 'LBFGS', pressure: float = 0.0)

Bases: Relax

Minimize energy with respect to internal positions and cell, while keeping space group fixed.

apply_filter_and_constraints(structure: Atoms)

Hook to allow subclasses to add filters and constraints.

pressure: float = 0.0
class assyst.relax.VolumeRelax(max_steps: int = 100, force_tolerance: float = 0.001, algorithm: Literal['LBFGS'] = 'LBFGS', pressure: float = 0.0)

Bases: Relax

Minimize energy while keeping relative positions and cell shape constant.

apply_filter_and_constraints(structure: Atoms)

Hook to allow subclasses to add filters and constraints.

pressure: float = 0.0
assyst.relax.relax(settings: Relax, calculator: AseCalculatorConfig | Calculator, structure: Iterable[Atoms]) Iterator[Atoms]

Relax structures according the given relaxation settings.

Output structures have the final energy and force attached as ase’s SinglePointCalculator.

Parameters:
Yields:

ase.Atoms – the corresponding relaxed configuration to each input structure

assyst.perturbations module

Classes to apply (random) perturbations to structures.

class assyst.perturbations.PerturbationABC

Bases: ABC

Apply some perturbation to a given structure.

class assyst.perturbations.RandomChoice(choice_a: Callable[[Atoms], Atoms] | PerturbationABC, choice_b: Callable[[Atoms], Atoms] | PerturbationABC, chance: float)

Bases: PerturbationABC

Apply either of two alternatives randomly.

chance: float

Probability to pick choice b

choice_a: Callable[[Atoms], Atoms] | PerturbationABC
choice_b: Callable[[Atoms], Atoms] | PerturbationABC
class assyst.perturbations.Rattle(sigma: float, create_supercells: bool = False)

Bases: PerturbationABC

Displace atoms by some absolute amount from a normal distribution.

create_supercells: bool = False

Create minimal 2x2x2 super cells when applied to structures of only one atom.

sigma: float
class assyst.perturbations.Series(perturbations: tuple[Callable[[Atoms], Atoms] | PerturbationABC, ...])

Bases: PerturbationABC

Apply some perturbations in sequence.

perturbations: tuple[Callable[[Atoms], Atoms] | PerturbationABC, ...]
class assyst.perturbations.Stretch(hydro: float, shear: float, minimum_strain: float = 0.001)

Bases: PerturbationABC

Apply random cell perturbation.

hydro: float
minimum_strain: float = 0.001
shear: float
assyst.perturbations.apply_perturbations(structures: Iterable[Atoms], perturbations: Iterable[Callable[[Atoms], Atoms] | PerturbationABC], filters: Iterable[Callable[[Atoms], bool] | FilterBase] | Callable[[Atoms], bool] | FilterBase | None = None) Iterator[Atoms]

Apply a list of perturbations to each structure and yield the result of each perturbation separately.

If a perturbation raises ValueError it is ignored.

assyst.perturbations.rattle(structure: Atoms, sigma: float) Atoms

Randomly displace positions with gaussian noise.

Operates INPLACE.

assyst.perturbations.stretch(structure: Atoms, hydro: float, shear: float, minimum_strain=0.001) Atoms

Randomly stretch cell with uniform noise.

Ensures at least minimum_strain strain to avoid structures very close to their original structures. These don’t offer a lot of new information and can also confuse VASP’s symmetry analyzer.

Operates INPLACE.

assyst.filters module

Classes that filter structures according to some criteria.

The code in the other modules that uses them is set up such that simple functions can always be passed as well and that the classes here are just for convenience.

class assyst.filters.AndFilter(l: Callable[[Atoms], bool] | FilterBase, r: Callable[[Atoms], bool] | FilterBase)

Bases: FilterBase

Conjunction of two filters.

l: Callable[[Atoms], bool] | FilterBase
r: Callable[[Atoms], bool] | FilterBase
class assyst.filters.AspectFilter(maximum_aspect_ratio: float = 6)

Bases: FilterBase

Filters structures with high aspect ratios.

maximum_aspect_ratio: float = 6
class assyst.filters.CalculatorFilter(*, missing: Literal['error', 'ignore'] = 'error')

Bases: FilterBase

Filters that require a single point calculator set on the structure.

missing: Literal['error', 'ignore'] = 'error'

What to do when a structure has no (correct) calculator attached.

class assyst.filters.DistanceFilter(radii: dict[str, float])

Bases: FilterBase

Filter structures that contain too close atoms.

Setting a radius to NaN allows all bonds involving this atom.

radii: dict[str, float]
to_tol_matrix(prototype: Literal['metallic', 'atomic', 'molecular', 'vdW'] = 'metallic') Tol_matrix

Returns equivalent tolerance matrix for pyxtal.

Parameters:

prototype (metallic, atomic, molecular or vdW) – passed to Tol_matrix as is and used there to initialize radii of elements not explicitly set in this filter

class assyst.filters.EnergyFilter(min_energy: float = -inf, max_energy: float = inf, *, missing: Literal['error', 'ignore'] = 'error')

Bases: CalculatorFilter

Filters structures by energy per atom.

max_energy: float = inf
min_energy: float = -inf
class assyst.filters.FilterBase

Bases: ABC

Base class for filter objects that implements conjunction and disjunction operators.

class assyst.filters.ForceFilter(max_force: float = inf, *, missing: Literal['error', 'ignore'] = 'error')

Bases: CalculatorFilter

Filters structures by maximum force magnitude.

max_force: float = inf
class assyst.filters.OrFilter(l: Callable[[Atoms], bool] | FilterBase, r: Callable[[Atoms], bool] | FilterBase)

Bases: FilterBase

Disjunction of two filters.

l: Callable[[Atoms], bool] | FilterBase
r: Callable[[Atoms], bool] | FilterBase
class assyst.filters.VolumeFilter(maximum_volume_per_atom: float)

Bases: FilterBase

Filters structures by volume.

maximum_volume_per_atom: float

assyst.calculators module

Convenience shorts to create ASE calculators to be used inside ASSYST.

Exists mostly to avoid passing around potentially large and unpickle-able calculator objects.

class assyst.calculators.AseCalculatorConfig

Bases: ABC

Base class to keep calculator configurations.

abstractmethod get_calculator() Calculator

Return the actual calculator object.

Returns:

the actually usable calculator

Return type:

ase.calculators.calculator.Calculator

class assyst.calculators.Grace(model: str = 'GRACE-FS-OAM')

Bases: AseCalculatorConfig

Universal Graph Atomic Cluster Expansion models.

Attention

This class needs additional dependencies! Install tensorpotential from PyPI.

get_calculator() Calculator

Return the actual calculator object.

Returns:

the actually usable calculator

Return type:

ase.calculators.calculator.Calculator

model: str = 'GRACE-FS-OAM'
class assyst.calculators.Morse(epsilon: float = 1.0, r0: float = 1.0, rho0: float = 1.0)

Bases: AseCalculatorConfig

Morse potential for testing. Parameters as in ASE.

epsilon: float = 1.0
get_calculator() Calculator

Return the actual calculator object.

Returns:

the actually usable calculator

Return type:

ase.calculators.calculator.Calculator

r0: float = 1.0
rho0: float = 1.0

assyst.plot module

Helper plotting functions.

assyst.plot.concentration_histogram(structures: list[Atoms], elements: Iterable[str] | None = None, **kwargs)

Plot histogram of concentrations.

Parameters:
  • structures (list of ase.Atoms) – structures to plot

  • elements (iterable of str) – which element concentrations to plot, by default all present

  • **kwargs – passed through to matplotlib.pyplot.bar

assyst.plot.distance_histogram(structures: list[Atoms], rmax: float = 6.0, reduce: Literal['min', 'mean'] | Callable[[Iterable[float]], float] = 'min', **kwargs)

Plot histogram of per-atom volumes.

Parameters:
  • structures (list of ase.Atoms) – structures to plot

  • rmax (float) – maximum cutoff to consider neighborhood

  • reduce (callable from array of floats to float) – applied to the neighbor distances per structure, and should reduce a single scalar that is binned

  • **kwargs – passed through to matplotlib.pyplot.hist

Returns:

Return value of matplotlib.pyplot.hist

assyst.plot.energy_volume(structures: list[Atoms], **kwargs)

Plot energy per atom versus volume per atom.

Requires that ase.calculators.SinglePointCalculator are attached to the atoms, either from a relaxation for final training set calculation.

Parameters:

structure – list[Atoms], structures to plot

assyst.plot.size_histogram(structures: list[Atoms], **kwargs)

Plot histogram of number of atoms.

Parameters:
  • structures (list of ase.Atoms) – structures to plot

  • **kwargs – passed through to matplotlib.pyplot.hist

Returns:

Return value of matplotlib.pyplot.hist

assyst.plot.volume_histogram(structures: list[Atoms], **kwargs)

Plot histogram of per-atom volumes.

Parameters:
  • structures (list of ase.Atoms) – structures to plot

  • **kwargs – passed through to matplotlib.pyplot.hist

Returns:

Return value of matplotlib.pyplot.hist

Module contents