Source code for matchest.cli.structure

from pathlib import Path
from typing import Optional

import ase
import ase.io
import spglib


[docs] def get_primitive_atoms( atoms: ase.Atoms, threshold: float = 1e-5, angle_tolerance: float = -1.0, print_spacegroup: bool = False, ) -> ase.Atoms: """Convert ASE Atoms to primitive cell using spglib""" atoms_spglib = ( atoms.cell.array, atoms.get_scaled_positions(), atoms.numbers, ) spacegroup = spglib.get_spacegroup(atoms_spglib, symprec=threshold, angle_tolerance=angle_tolerance) if print_spacegroup: print(f"Space group: {spacegroup}") cell, positions, atomic_numbers = spglib.find_primitive( atoms_spglib, symprec=threshold, angle_tolerance=angle_tolerance ) primitive_atoms = ase.Atoms(scaled_positions=positions, cell=cell, numbers=atomic_numbers, pbc=True) return primitive_atoms
[docs] def get_primitive( input_file: Path = Path("POSCAR"), input_format: Optional[str] = None, output_file: Optional[Path] = None, output_format: Optional[str] = None, threshold: float = 1e-5, angle_tolerance: float = -1.0, verbose: bool = False, precision: int = 6, ) -> None: if output_file is None: verbose = True float_format_str = f"{{:{precision + 4}.{precision}f}}" def format_float(x: float) -> str: return float_format_str.format(x) atoms = ase.io.read(input_file, format=input_format) atoms = get_primitive_atoms( atoms, threshold=threshold, angle_tolerance=angle_tolerance, print_spacegroup=verbose, ) if verbose: print("Primitive cell vectors:") for row in atoms.cell: print(" ".join(map(format_float, row))) print("Atomic positions and proton numbers:") for position, number in zip(atoms.get_scaled_positions(), atoms.numbers): print(" ".join(map(format_float, position)) + f"\t{number}") if output_file is None: pass else: atoms.write(output_file, format=output_format)
[docs] def get_spacegroup(filename: Optional[Path] = None, filetype: Optional[str] = None): if filename is None: for candidate in ("geometry.in", "POSCAR", "castep.cell"): if (structure_file := Path.cwd() / candidate).is_file(): filename = structure_file break else: raise ValueError("Input file not specified, no default found.") atoms = ase.io.read(str(filename), format=filetype) cell = (atoms.cell.array, atoms.get_scaled_positions(), atoms.numbers) print("| Threshold / Å | Space group |") print("|---------------|-------------------|") for threshold in (1e-5, 1e-4, 5e-4, 1e-3, 5e-3, 1e-2, 5e-2, 1e-1): print(f"| {threshold:0.5f} | {spglib.get_spacegroup(cell, symprec=threshold): <16} |")