Source code for pyiron.atomistics.structure.pyscal

# coding: utf-8
# Copyright (c) Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department
# Distributed under the terms of "New BSD License", see the LICENSE file.

import numpy as np
from pyiron_base import Settings
import pyiron.atomistics.structure.atoms
import pyscal.core as pc
from sklearn import cluster

__author__ = "Sarath Menon, Jan Janssen"
__copyright__ = (
    "Copyright 2020, Max-Planck-Institut für Eisenforschung GmbH - "
    "Computational Materials Design (CM) Department"
)
__version__ = "1.0"
__maintainer__ = "Sarath Menon"
__email__ = "sarath.menon@rub.de"
__status__ = "development"
__date__ = "Nov 6, 2019"

s = Settings()


[docs]def get_steinhardt_parameter_structure(atoms, neighbor_method="cutoff", cutoff=0, n_clusters=2, q=(4, 6), averaged=False, clustering=True): """ Calculate Steinhardts parameters Args: atoms: Atoms object neighbor_method (str) : can be ['cutoff', 'voronoi'] cutoff (float) : can be 0 for adaptive cutoff or any other value n_clusters (int) : number of clusters for K means clustering q (list) : can be from 2-12, the required q values to be calculated averaged (bool) : If True, calculates the averaged versions of the parameter clustering (bool) : If True, cluster based on the q values Returns: q (list) : calculated q parameters """ s.publication_add(publication()) sys = pc.System() sys.read_inputfile( pyiron.atomistics.structure.atoms.pyiron_to_ase(atoms), format='ase' ) sys.find_neighbors( method=neighbor_method, cutoff=cutoff ) sys.calculate_q( q, averaged=averaged ) sysq = sys.get_qvals( q, averaged=averaged ) if clustering: cl = cluster.KMeans( n_clusters=n_clusters ) ind = cl.fit(list(zip(*sysq))).labels_ == 0 return sysq, ind else: return sysq
[docs]def analyse_centro_symmetry(atoms, num_neighbors=12): """ Analyse centrosymmetry parameter Args: atoms: Atoms object num_neighbors (int) : number of neighbors Returns: csm (list) : list of centrosymmetry parameter """ s.publication_add(publication()) sys = pc.System() sys.read_inputfile(atoms, format="ase") return np.array(sys.calculate_centrosymmetry(nmax=num_neighbors))
[docs]def analyse_diamond_structure(atoms, mode="total", ovito_compatibility=False): """ Analyse diamond structure Args: atoms: Atoms object mode ("total"/"numeric"/"str"): Controls the style and level of detail of the output. - total : return number of atoms belonging to each structure - numeric : return a per atom list of numbers- 0 for unknown, 1 fcc, 2 hcp, 3 bcc and 4 icosa - str : return a per atom string of sructures ovito_compatibility(bool): use ovito compatiblity mode Returns: (depends on `mode`) """ s.publication_add(publication()) sys = pc.System() sys.read_inputfile(atoms, format="ase") diamond_dict = sys.identify_diamond() ovito_identifiers = [ 'Cubic diamond', 'Cubic diamond (1st neighbor)', 'Cubic diamond (2nd neighbor)', 'Hexagonal diamond', 'Hexagonal diamond (1st neighbor)', 'Hexagonal diamond (2nd neighbor)', 'Other' ] pyscal_identifiers = [ 'others', 'fcc', 'hcp', 'bcc', 'ico', 'cubic diamond', 'cubic diamond 1NN', 'cubic diamond 2NN', 'hex diamond', 'hex diamond 1NN', 'hex diamond 2NN' ] convert_to_ovito = { 0: 6, 1: 6, 2: 6, 3: 6, 4: 6, 5: 0, 6: 1, 7: 2, 8: 3, 9: 4, 10: 5 } if mode == "total": if not ovito_compatibility: return diamond_dict else: return { 'IdentifyDiamond.counts.CUBIC_DIAMOND': diamond_dict['cubic diamond'], 'IdentifyDiamond.counts.CUBIC_DIAMOND_FIRST_NEIGHBOR': diamond_dict['cubic diamond 1NN'], 'IdentifyDiamond.counts.CUBIC_DIAMOND_SECOND_NEIGHBOR': diamond_dict['cubic diamond 2NN'], 'IdentifyDiamond.counts.HEX_DIAMOND': diamond_dict['hex diamond'], 'IdentifyDiamond.counts.HEX_DIAMOND_FIRST_NEIGHBOR': diamond_dict['hex diamond 1NN'], 'IdentifyDiamond.counts.HEX_DIAMOND_SECOND_NEIGHBOR': diamond_dict['hex diamond 2NN'], 'IdentifyDiamond.counts.OTHER': diamond_dict['others'] + diamond_dict['fcc'] + diamond_dict['hcp'] + diamond_dict['bcc'] + diamond_dict['ico'] } elif mode == "numeric": if not ovito_compatibility: return np.array([atom.structure for atom in sys.atoms]) else: return np.array([convert_to_ovito[atom.structure] for atom in sys.atoms]) elif mode == "str": if not ovito_compatibility: return np.array([pyscal_identifiers[atom.structure] for atom in sys.atoms]) else: return np.array([ovito_identifiers[convert_to_ovito[atom.structure]] for atom in sys.atoms]) else: raise ValueError("Only total, str and numeric mode is imported for analyse_diamond_structure()")
[docs]def analyse_cna_adaptive(atoms, mode="total", ovito_compatibility=False): """ Use common neighbor analysis Args: atoms (pyiron.structure.atoms.Atoms): The structure to analyze. mode ("total"/"numeric"/"str"): Controls the style and level of detail of the output. - total : return number of atoms belonging to each structure - numeric : return a per atom list of numbers- 0 for unknown, 1 fcc, 2 hcp, 3 bcc and 4 icosa - str : return a per atom string of sructures ovito_compatibility(bool): use ovito compatiblity mode Returns: (depends on `mode`) """ s.publication_add(publication()) if mode not in ["total", "numeric", "str"]: raise ValueError("Unsupported mode") pyscal_parameter = ['others', 'fcc', 'hcp', 'bcc', 'ico'] ovito_parameter = [ 'CommonNeighborAnalysis.counts.OTHER', 'CommonNeighborAnalysis.counts.FCC', 'CommonNeighborAnalysis.counts.HCP', 'CommonNeighborAnalysis.counts.BCC', 'CommonNeighborAnalysis.counts.ICO' ] sys = pc.System() sys.read_inputfile(atoms, format="ase") cna = sys.calculate_cna() if mode == "total": if not ovito_compatibility: return cna else: return {o: cna[p] for o, p in zip( ovito_parameter, pyscal_parameter )} else: atoms = sys.atoms cnalist = np.array([atom.structure for atom in atoms]) if mode == "numeric": return cnalist elif mode == "str": if not ovito_compatibility: dd = ['others', 'fcc', 'hcp', 'bcc', 'ico'] return np.array([dd[int(x)] for x in cnalist]) else: dd = ['Other', "FCC", "HCP", "BCC", "ICO"] return np.array([dd[int(x)] for x in cnalist]) else: raise ValueError("Only total, str and numeric mode is imported for analyse_cna_adaptive()")
[docs]def analyse_voronoi_volume(atoms): """ Calculate the Voronoi volume of atoms Args: atoms : (pyiron.structure.atoms.Atoms): The structure to analyze. """ s.publication_add(publication()) sys = pc.System() sys.read_inputfile(atoms, format="ase") sys.find_neighbors(method="voronoi") atoms = sys.atoms return np.array([atom.volume for atom in atoms])
[docs]def publication(): return { "pyscal": { "Menon2019": { "doi": "10.21105/joss.01824", "url": "https://doi.org/10.21105/joss.01824", "year": "2019", "volume": "4", "number": "43", "pages": "1824", "author": ["Sarath Menon", "Grisell Diaz Leines", "Jutta Rogal"], "title": "pyscal: A python module for structural analysis of atomic environments", "journal": "Journal of Open Source Software", } } }