Source code for sknano.core.atoms._periodic_atoms

# -*- coding: utf-8 -*-
"""
===============================================================================
Atom classes for PBCs (:mod:`sknano.core.atoms._periodic_atoms`)
===============================================================================

.. currentmodule:: sknano.core.atoms._periodic_atoms

"""
from __future__ import absolute_import, division, print_function
from __future__ import unicode_literals
__docformat__ = 'restructuredtext en'

from functools import total_ordering
from operator import attrgetter

import numpy as np

from ._atoms import Atom, Atoms

__all__ = ['PBCAtom', 'PBCAtoms']


@total_ordering
[docs]class PBCAtom(Atom): """Atom class with PBC attributes. Parameters ---------- element : {str, int}, optional A string representation of the element symbol or an integer specifying an element atomic number. xperiodic, yperiodic, zperiodic : :class:`~python:bool`, optional PBC along each :math:`x, y, z` axis """ def __init__(self, *args, xperiodic=False, yperiodic=False, zperiodic=False, **kwargs): super().__init__(*args, **kwargs) self.xperiodic = xperiodic self.yperiodic = yperiodic self.zperiodic = zperiodic self.fmtstr = super().fmtstr + \ ", xperiodic={xperiodic!r}, yperiodic={yperiodic!r}" + \ ", zperiodic={zperiodic!r}" def __eq__(self, other): return np.allclose(self.pbc, other.pbc) and super().__eq__(other) def __lt__(self, other): return (self.pbc < other.pbc and super().__le__(other)) or \ (self.pbc <= other.pbc and super().__lt__(other)) def __dir__(self): attrs = super().__dir__() attrs.extend(['xperiodic', 'yperiodic', 'zperiodic']) return attrs @property def xperiodic(self): return self._xperiodic @xperiodic.setter def xperiodic(self, value): self._xperiodic = bool(value) @property def yperiodic(self): return self._yperiodic @yperiodic.setter def yperiodic(self, value): self._yperiodic = bool(value) @property def zperiodic(self): return self._zperiodic @zperiodic.setter def zperiodic(self, value): self._zperiodic = bool(value) @property def pbc(self): return np.asarray([self.xperiodic, self.yperiodic, self.zperiodic], dtype=bool) @pbc.setter def pbc(self, value): if not isinstance(value, (list, np.ndarray)): raise TypeError('Expected an array_like object') self.xperiodic, self.yperiodic, self.zperiodic = value
[docs] def todict(self): pdict = super().todict() pdict.update(dict(xperiodic=self.xperiodic, yperiodic=self.yperiodic, zperiodic=self.zperiodic)) return pdict
[docs]class PBCAtoms(Atoms): """:class:`~sknano.core.atoms.Atoms` class for PBC.""" @property def __atom_class__(self): return PBCAtom
[docs] def sort(self, key=attrgetter('pbc'), reverse=False): super().sort(key=key, reverse=reverse)
@property def pbc(self): return np.asarray([atom.pbc for atom in self])
[docs] def set_pbc(self, xperiodic=True, yperiodic=True, zperiodic=True): [setattr(atom, 'xperiodic', xperiodic) for atom in self] [setattr(atom, 'yperiodic', yperiodic) for atom in self] [setattr(atom, 'zperiodic', zperiodic) for atom in self]
[docs] def unset_pbc(self): [setattr(atom, 'xperiodic', False) for atom in self] [setattr(atom, 'yperiodic', False) for atom in self] [setattr(atom, 'zperiodic', False) for atom in self]
[docs] def wrap_coords(self, pbc=None): try: [setattr(atom, 'r', self.lattice.wrap_cartesian_coordinate( atom.r, pbc=pbc if pbc is not None else atom.pbc)) for atom in self] except AttributeError: pass