Source code for sisl.physics.spin

from __future__ import print_function, division

import numpy as np

__all__ = ['Spin']


[docs]class Spin(object): r""" Spin class to determine configurations and spin components. The basic class ``Spin`` implements a generic method to determine a spin configuration. Its usage can be summarized in these few examples: >>> Spin(Spin.UNPOLARIZED) == Spin('unpolarized') == Spin() True >>> Spin(Spin.POLARIZED) == Spin('polarized') == Spin('p') True >>> Spin(Spin.NONCOLINEAR, dtype=np.complex128) == Spin('non-colinear') == Spin('nc') True >>> Spin(Spin.SPINORBIT, dtype=np.complex128) == Spin('spin-orbit') == Spin('so') True Note that a data-type may be associated with a spin-object. This is not to say that the data-type is used in the configuration, but merely that it helps any sub-classed or classes who use the spin-object to determine the usage of the different spin-components. """ UNPOLARIZED = 0 POLARIZED = 1 NONCOLINEAR = 2 SPINORBIT = 3 __slots__ = ['_spins', '_kind', '_dtype'] def __init__(self, kind='', dtype=np.float64): if isinstance(kind, Spin): self._kind = kind._kind self._dtype = kind._dtype self._spins = kind._spins return # Copy data-type self._dtype = dtype kind = {'unpolarized': Spin.UNPOLARIZED, '': Spin.UNPOLARIZED, Spin.UNPOLARIZED: Spin.UNPOLARIZED, 'polarized': Spin.POLARIZED, 'p': Spin.POLARIZED, Spin.POLARIZED: Spin.POLARIZED, 'non-colinear': Spin.NONCOLINEAR, 'nc': Spin.NONCOLINEAR, Spin.NONCOLINEAR: Spin.NONCOLINEAR, 'spin-orbit': Spin.SPINORBIT, 'so': Spin.SPINORBIT, Spin.SPINORBIT: Spin.SPINORBIT}.get(kind) # Now assert the checks self._kind = kind if np.dtype(dtype).kind == 'c': spins = {self.UNPOLARIZED: 1, self.POLARIZED: 2, self.NONCOLINEAR: 4, self.SPINORBIT: 4}.get(kind) else: spins = {self.UNPOLARIZED: 1, self.POLARIZED: 2, self.NONCOLINEAR: 4, self.SPINORBIT: 8}.get(kind) self._spins = spins def __repr__(self): s = self.__class__.__name__ if self.is_unpolarized: return s + '{{unpolarized, kind={}}}'.format(self.dkind) if self.is_polarized: return s + '{{polarized, kind={}}}'.format(self.dkind) if self.is_noncolinear: return s + '{{non-colinear, kind={}}}'.format(self.dkind) return s + '{{spin-orbit, kind={}}}'.format(self.dkind)
[docs] def copy(self): return Spin(self.kind, self.dtype)
@property def dtype(self): """ Data-type of the spin configuration """ return self._dtype @property def dkind(self): """ Data-type kind """ return np.dtype(self._dtype).kind @property def spins(self): """ Number of spin-components """ return self._spins @property def kind(self): """ A unique ID for the kind of spin configuration """ return self._kind @property def is_unpolarized(self): """ True if the configuration is not polarized """ # Regardless of data-type return self.kind == Spin.UNPOLARIZED @property def is_polarized(self): """ True if the configuration is polarized """ return self.kind == Spin.POLARIZED is_colinear = is_polarized @property def is_noncolinear(self): """ True if the configuration non-colinear """ return self.kind == Spin.NONCOLINEAR @property def is_spinorbit(self): """ True if the configuration is spin-orbit """ return self.kind == Spin.SPINORBIT def __len__(self): return self._spins # Comparisons def __lt__(a, b): return a.kind < b.kind def __le__(a, b): return a.kind <= b.kind def __eq__(a, b): return a.kind == b.kind def __ne__(a, b): return not a == b def __gt__(a, b): return a.kind > b.kind def __ge__(a, b): return a.kind >= b.kind