Source code for pyiron.atomistics.structure.factory

# 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.

from ase.build import bulk
from ase.build import (
        add_adsorbate,
        add_vacuum,
        bcc100,
        bcc110,
        bcc111,
        diamond100,
        diamond111,
        fcc100,
        fcc110,
        fcc111,
        fcc211,
        hcp0001,
        hcp10m10,
        mx2,
        hcp0001_root,
        fcc111_root,
        bcc111_root,
        root_surface,
        root_surface_analysis,
        surface as ase_surf,
    )
from ase.io import read
import numpy as np
from pyiron.atomistics.structure.pyironase import publication as publication_ase
from pyiron.atomistics.structure.atoms import CrystalStructure, ase_to_pyiron, Atoms
from pyiron.atomistics.structure.periodic_table import PeriodicTable
from pyiron_base import Settings, PyironFactory
import types

__author__ = "Sudarsan Surendralal"
__copyright__ = (
    "Copyright 2020, Max-Planck-Institut für Eisenforschung GmbH - "
    "Computational Materials Design (CM) Department"
)
__version__ = "1.0"
__maintainer__ = "Sudarsan Surendralal"
__email__ = "surendralal@mpie.de"
__status__ = "production"
__date__ = "May 1, 2020"

s = Settings()


[docs]class StructureFactory(PyironFactory):
[docs] def ase_read(self, *args, **kwargs): """ Returns a ASE's read result, wrapped as a `pyiron.atomstic.structure.atoms.Atoms` object. ase.io.read docstring: """ return ase_to_pyiron(read(*args, **kwargs))
ase_read.__doc__ += read.__doc__
[docs] @staticmethod def surface( element, surface_type, size=(1, 1, 1), vacuum=1.0, center=False, pbc=True, **kwargs ): """ Generate a surface based on the ase.build.surface module. Args: element (str): Element name surface_type (str): The string specifying the surface type generators available through ase (fcc111, hcp0001 etc.) size (tuple): Size of the surface vacuum (float): Length of vacuum layer added to the surface along the z direction center (bool): Tells if the surface layers have to be at the center or at one end along the z-direction pbc (list/numpy.ndarray): List of booleans specifying the periodic boundary conditions along all three directions. **kwargs: Additional, arguments you would normally pass to the structure generator like 'a', 'b', 'orthogonal' etc. Returns: pyiron.atomistics.structure.atoms.Atoms instance: Required surface """ # https://gitlab.com/ase/ase/blob/master/ase/lattice/surface.py if pbc is None: pbc = True s.publication_add(publication_ase()) for surface_class in [ add_adsorbate, add_vacuum, bcc100, bcc110, bcc111, diamond100, diamond111, fcc100, fcc110, fcc111, fcc211, hcp0001, hcp10m10, mx2, hcp0001_root, fcc111_root, bcc111_root, root_surface, root_surface_analysis, ase_surf, ]: if surface_type == surface_class.__name__: surface_type = surface_class break if isinstance(surface_type, types.FunctionType): if center: surface = surface_type( symbol=element, size=size, vacuum=vacuum, **kwargs ) else: surface = surface_type(symbol=element, size=size, **kwargs) z_max = np.max(surface.positions[:, 2]) surface.cell[2, 2] = z_max + vacuum surface.pbc = pbc return ase_to_pyiron(surface) else: return None
[docs] @staticmethod def surface_hkl(lattice, hkl, layers, vacuum=1.0, center=False, pbc=True): """ Use ase.build.surface to build a surface with surface normal (hkl). Args: lattice (pyiron.atomistics.structure.atoms.Atoms/str): bulk Atoms instance or str, e.g. "Fe", from which to build the surface hkl (list): miller indices of surface to be created layers (int): # of atomic layers in the surface vacuum (float): vacuum spacing center (bool): shift all positions to center the surface in the cell Returns: pyiron.atomistics.structure.atoms.Atoms instance: Required surface """ # https://gitlab.com/ase/ase/blob/master/ase/lattice/surface.py s.publication_add(publication_ase()) surface = ase_surf(lattice, hkl, layers) z_max = np.max(surface.positions[:, 2]) surface.cell[2, 2] = z_max + vacuum if center: surface.positions += 0.5 * surface.cell[2] - [0, 0, z_max/2] surface.pbc = pbc return ase_to_pyiron(surface)
[docs] @staticmethod def crystal(element, bravais_basis, lattice_constant): """ Create a crystal structure using pyiron's native crystal structure generator Args: element (str): Element name bravais_basis (str): Basis type lattice_constant (float/list): Lattice constants Returns: pyiron.atomistics.structure.atoms.Atoms: The required crystal structure """ return CrystalStructure( element=element, bravais_basis=bravais_basis, lattice_constants=[lattice_constant], )
[docs] @staticmethod def ase_bulk( name, crystalstructure=None, a=None, c=None, covera=None, u=None, orthorhombic=False, cubic=False, ): """ Creating bulk systems using ASE bulk module. Crystal structure and lattice constant(s) will be guessed if not provided. name (str): Chemical symbol or symbols as in 'MgO' or 'NaCl'. crystalstructure (str): Must be one of sc, fcc, bcc, hcp, diamond, zincblende, rocksalt, cesiumchloride, fluorite or wurtzite. a (float): Lattice constant. c (float): Lattice constant. c_over_a (float): c/a ratio used for hcp. Default is ideal ratio: sqrt(8/3). u (float): Internal coordinate for Wurtzite structure. orthorhombic (bool): Construct orthorhombic unit cell instead of primitive cell which is the default. cubic (bool): Construct cubic unit cell if possible. Returns: pyiron.atomistics.structure.atoms.Atoms: Required bulk structure """ s.publication_add(publication_ase()) return ase_to_pyiron(bulk( name=name, crystalstructure=crystalstructure, a=a, c=c, covera=covera, u=u, orthorhombic=orthorhombic, cubic=cubic, ))
[docs] @staticmethod def atoms( symbols=None, positions=None, numbers=None, tags=None, momenta=None, masses=None, magmoms=None, charges=None, scaled_positions=None, cell=None, pbc=None, celldisp=None, constraint=None, calculator=None, info=None, indices=None, elements=None, dimension=None, species=None, **qwargs ): """ Creates a atomistics.structure.atoms.Atoms instance. Args: elements (list/numpy.ndarray): List of strings containing the elements or a list of atomistics.structure.periodic_table.ChemicalElement instances numbers (list/numpy.ndarray): List of atomic numbers of elements symbols (list/numpy.ndarray): List of chemical symbols positions (list/numpy.ndarray): List of positions scaled_positions (list/numpy.ndarray): List of scaled positions (relative coordinates) pbc (boolean): Tells if periodic boundary conditions should be applied cell (list/numpy.ndarray): A 3x3 array representing the lattice vectors of the structure momenta (list/numpy.ndarray): List of momentum values tags (list/numpy.ndarray): A list of tags masses (list/numpy.ndarray): A list of masses magmoms (list/numpy.ndarray): A list of magnetic moments charges (list/numpy.ndarray): A list of point charges celldisp: constraint (list/numpy.ndarray): A list of constraints calculator: ASE calculator info (list/str): ASE compatibility indices (list/numpy.ndarray): The list of species indices dimension (int): Dimension of the structure species (list): List of species Returns: pyiron.atomistics.structure.atoms.Atoms: The required structure instance """ if pbc is None: pbc = True return Atoms( symbols=symbols, positions=positions, numbers=numbers, tags=tags, momenta=momenta, masses=masses, magmoms=magmoms, charges=charges, scaled_positions=scaled_positions, cell=cell, pbc=pbc, celldisp=celldisp, constraint=constraint, calculator=calculator, info=info, indices=indices, elements=elements, dimension=dimension, species=species, **qwargs )
[docs] @staticmethod def element(parent_element, new_element_name=None, spin=None, potential_file=None): """ Args: parent_element (str, int): The parent element eq. "N", "O", "Mg" etc. new_element_name (str): The name of the new parent element (can be arbitrary) spin (float): Value of the magnetic moment (with sign) potential_file (str): Location of the new potential file if necessary Returns: atomistics.structure.periodic_table.ChemicalElement instance """ periodic_table = PeriodicTable() if new_element_name is None: if spin is not None: new_element_name = ( parent_element + "_spin_" + str(spin).replace(".", "_") ) else: new_element_name = parent_element + "_1" if potential_file is not None: if spin is not None: periodic_table.add_element( parent_element=parent_element, new_element=new_element_name, spin=str(spin), pseudo_potcar_file=potential_file, ) else: periodic_table.add_element( parent_element=parent_element, new_element=new_element_name, pseudo_potcar_file=potential_file, ) elif spin is not None: periodic_table.add_element( parent_element=parent_element, new_element=new_element_name, spin=str(spin), ) else: periodic_table.add_element( parent_element=parent_element, new_element=new_element_name ) return periodic_table.element(new_element_name)