Source code for ase2sprkkr.sprkkr.atoms_region

""" This module defines :class:`AtomsRegion`: a class,
that describe a symmetry of a region of Atoms object. """

from ase.cell import Cell
from ase import Atoms
import numpy as np
from typing import List, Union, Optional
from ..common.decorators import cached_property
from . import sprkkr_atoms


[docs] class AtomsRegion: """ AtomsRegion define a region of Atoms object, that can have its own cell and pbc. E.g. this system:: |^^T^^^^^^^^^^^^^^^^^^^T^^| | | | | |__|___________________|__| has two semiinfinite 3D periodic regions and a central 2D-symmetric region. """
[docs] def __init__(self, name:str, slice:slice, cell:Union[Cell, np.ndarray], pbc:List[Optional[bool]]=[True, True, True], inherit_cell:Union[bool,List[bool]]=False, atoms:Atoms=None, add=True): """ Atoms region defines a spatial part of an Atoms object. The cell can has zero vectors - such vectors are taken from the parent atoms object. Parameters ---------- slice Which sites (atoms) belong to the region cell The primitive cell pbc The peridodicity vector (see :class:`ase.Atoms`) inherit_cell Inherit the cell and the pcb from the parent atoms for given axes. Use of this argument is the same, as setting ``pbc`` to None and ``cell`` to ``[0,0,0]`` for the given axes. atoms The master object, of which the region is defined """ self.name = name self.atoms = atoms self._slice = slice if inherit_cell is not False: cell = cell.copy() if inherit_cell is True: cell[:] = 0 pbc = [ None, None, None ] else: pbc = np.array( pbc, dtype=object ) cell[inherit_cell] = 0 pbc[inherit_cell] = None self.incomplete_cell = Cell(cell) self.incomplete_pbc = pbc if atoms: self.set_atoms(atoms, add)
[docs] @staticmethod def from_atoms(from_atoms: Atoms, name:str, slice:slice, inherit_cell=False, atoms:Atoms=None): """ Creates a region from the property of the given atoms object. The pbc and cell are taken from it. """ return AtomsRegion(name, slice, from_atoms.cell, from_atoms.pbc, inherit_cell, atoms)
@property def cell(self): """ Return the cell. If the cell has some zero vectors, these are replaced with parent atoms cell vectors """ cell = self.incomplete_cell.copy() if self.atoms is not None: for i,v in enumerate(cell): if not v.any(): # no nonzero v[:] = self.atoms.cell[i] return cell
[docs] def get_cell(self): return self.cell
@cell.setter def cell(self, cell): if not isinstance(cell, Cell): cell = np.asarray(cell) assert cell.shape == (3, 3) self.incomplete_cell = cell @property def pbc(self): """ Return the pbc If the pbc has None items, these are replace with parent atoms pbc values """ pbc = np.array(self.incomplete_pbc) if self.atoms is not None: for i,v in enumerate(pbc): if v is None: pbc[i] = self.atoms.pbc[i] return pbc @pbc.setter def pbc(self, pbc): assert len(pbc) == 3 self.incomplete_pbc = pbc @property def slice(self): return self._slice @slice.setter def slice(self, slice): self._slice = slice self._clear_cache
[docs] def _clear_cache(self): for i in ('ids', 'set_of_ids'): if i in self.__dict__: delattr(self, i)
[docs] def set_atoms(self, atoms, add=True): """ Set the master atoms - of which the region is described """ if add: # atoms will call set_atoms again sprkkr_atoms.SPRKKRAtoms.promote_ase_atoms(atoms) atoms.add_region(self) else: self.atoms = atoms self._clear_cache()
[docs] def create_atoms(self): """ Create an atoms object, that contains only the region """ atoms = self.atoms[self.slice] atoms.cell = self.cell atoms.pbc = self.pbc
@property def symbols(self): """ Return the symbols in the region """ return self.atoms.symbols[self.slice] def __len__(self): return len(self.ids)
[docs] def shared_ids_with(self, region): """ Return ids of the sites, that belongs to the both regions """ if self.atoms != region.atoms: return False return self.set_of_ids.intersection(region.set_of_ids)
@cached_property def ids(self): """ Returns ids of sites that belongs to the region """ return np.arange(len(self.atoms))[self.slice] @cached_property def set_of_ids(self): """ Returns set of ids of sites that belongs to the region """ return set(self.ids) @property def positions(self): return self.atoms.positions[self.slice]
[docs] def only_vacuum_atoms(self): for site in self.atoms.sites[self.slice]: for at in site.occupation: if not at.is_vacuum(): return False return True
[docs] def sites(self): return self.atoms.sites[self.slice]
[docs] def get_array(self, name, copy): return self.atoms.get_array(name, copy)[self.slice]
[docs] def are_sites_inited(self): return isinstance(self.atoms, sprkkr_atoms.SPRKKRAtoms) and self.atoms.are_sites_inited()
[docs] def get_atomic_numbers(self): return self.atoms.get_atomic_numbers()[self.slice]
@cached_property def arrays(self): class Wrap: def __getitem__(slf, name): return self.atoms.arrays[name][self.slice] def __contains__(slf, name): return name in self.atoms.arrays return Wrap()
[docs] def get_scaled_positions(self): return self.atoms.get_scaled_positions()[self.slice]