smooth_disorder.structural

structural.py — Structure I/O, Distance Calculations, and Periodic Boundaries

This module handles everything related to reading atomic structures and computing the distances between atoms, taking periodic boundary conditions (PBC) into account.

Background

Crystal and glass structures are described by:
  • Atomic positions: the (x, y, z) coordinates of each atom in Å.

  • Lattice vectors: three vectors (a, b, c) that define the repeating unit cell. The real material is infinite — it is the unit cell tiled in all directions.

Because the disordered materials are treated as large periodic unit cells, the shortest distance between two atoms is not simply the straight-line distance between their coordinates in the primary cell. We must also consider copies of each atom in neighbouring cells. Selecting the shortest such distance is called the Minimum Image Convention (MIC).

Two MIC implementations are provided:
  • obtain_distances_ase: uses the ASE library (recommended, more accurate for non-orthorhombic cells).

  • obtain_distances_big_structures: manual implementation, faster for very large structures but approximate for large off-diagonal cells.

Reference

Appendix C of https://pure.rug.nl/ws/portalfiles/portal/2839530/03_c3.pdf explains the limitations of the single-image MIC approximation.

smooth_disorder.structural.obtain_density(atoms: Atoms) float[source]

Compute the mass density of a material from its unit cell.

The density is calculated as:

ρ = total_mass / volume

where total_mass is the sum of all atomic masses in the cell (in atomic mass units, converted to grams) and volume is the cell volume in cm³.

Parameters:

atoms (ase.atoms.Atoms) – ASE Atoms object with positions, cell, and chemical species.

Returns:

float – Density in g/cm³.

smooth_disorder.structural.obtain_distances_ase(atoms: Atoms, n_smallest: int) Tuple[ndarray, ndarray][source]

Compute the n_smallest nearest-neighbour distances for every atom using the ASE Minimum Image Convention (preferred method).

ASE’s get_distances method handles the MIC correctly for all cell shapes (orthorhombic, monoclinic, triclinic), making it more accurate than the manual implementation for non-cubic cells.

Parameters:
  • atoms (ase.atoms.Atoms) – ASE Atoms object containing positions and cell (lattice vectors). Load from file with ase.io.read(filename).

  • n_smallest (int) – Number of nearest neighbours (including central atom) to keep per atom.

Returns:

  • distances (np.ndarray, shape (N, n_smallest)) – Sorted nearest-neighbour distances (in Ångström).

  • idx_distances (np.ndarray, shape (N, n_smallest)) – Global atom indices corresponding to those distances.

smooth_disorder.structural.obtain_distances_big_structures(atomic_positions: ndarray, lattice_vectors: ndarray, n_smallest: int) Tuple[ndarray, ndarray][source]

Compute the n_smallest nearest-neighbour distances for every atom using a manual Minimum Image Convention (MIC).

This function is a manual implementation of the MIC. It is provided as an alternative to obtain_distances_ase for very large structures where the ASE call may be slow. Note: it is only an approximation for large distances in non-orthorhombic cells.

How it works

For each atom i:
  1. Compute the vector from i to every other atom j: Δr = r_j - r_i.

  2. Express Δr in fractional coordinates (units of the lattice vectors) by multiplying by the inverse lattice matrix.

  3. Apply the MIC: if any fractional coordinate is outside [-0.5, 0.5], shift it by ±1 so it moves inside that range. This picks the nearest periodic image of atom j.

  4. Convert back to Cartesian coordinates and compute the distance.

  5. Keep only the n_smallest distances using argpartition (O(n)).

Parameters:
  • atomic_positions (np.ndarray, shape (N, 3)) – Cartesian positions in Ångström.

  • lattice_vectors (np.ndarray, shape (3, 3)) – Lattice vectors as rows.

  • n_smallest (int) – Number of nearest neighbours (including central atom) to keep per atom.

Returns:

  • distances (np.ndarray, shape (N, n_smallest)) – Sorted nearest-neighbour distances for each atom (in Ångström).

  • idx_distances (np.ndarray, shape (N, n_smallest)) – Global atom indices corresponding to those distances.

smooth_disorder.structural.obtain_positions_and_lattice_vectors(primitive_filename: str) Tuple[ndarray, ndarray][source]

Read an atomic structure file and return atomic positions and lattice vectors.

Uses ASE (Atomic Simulation Environment), which supports many common formats: VASP POSCAR, CIF, XYZ, extended XYZ, and more. ASE autodetects the format from the filename extension or content.

Parameters:

primitive_filename (str) – Path to the structure file (e.g. "POSCAR", "structure.cif").

Returns:

  • positions (np.ndarray, shape (num_atoms, 3)) – Cartesian coordinates of each atom in Ångström.

  • lattice_vectors (np.ndarray, shape (3, 3)) – Rows are the three lattice vectors a, b, c (in Ångström). lattice_vectors[0] = a, lattice_vectors[1] = b, etc.