Source code for pylada.dftcrystal.external
__docformat__ = "restructuredtext en"
__all__ = ['External']
from .molecule import Molecule
[docs]class External(Molecule):
""" Functional CRYSTAL-wise structure, starting from Pylada structure.
Provides a mixture of CRYSTAL_ and Pylada-style structures. The starting
structure is a :py:class:`~pylada.crystal.cppwrappers.Structure` instance
which is inputed into CRYSTAL_ via the EXTERNAL keyword. This instance
also accepts functional modifications which will act upon the initial
structure, much as :py:class:`~pylada.dftcrystal.crystal.Crystal`
instances.
There are two ways of initializing an instance. The first allows the same
interface as :py:class:`~pylada.crystal.cppwrappers.Structure`.
>>> from quantities import angstrom
>>> from pylada.dftcrystal import External
>>> external = External([[0, 0.5, 0.5],
... [0.5, 0, 0.5],
... [0.5, 0.5, 0], scale=5.45*angstrom) \\
... .add_atom(0,0,0, 'Si') \\
... .add_atom(0.25, 0.25, 0.25, 'Si')
The second approach is to use a predefined
:py:class:`~pylada.crystal.cppwrappers.Structure` instance:
>>> from pylada.dftcrystal import External
>>> external = External(copy=diamond)
Where ``diamond`` in the snippet above is the instance in question. Note
that it is deepcopied upon initialization. In both cases, the initial
structure can be accessed as :py:attr:`initial`.
In both cases, CRYSTAL_ transformations can be added to modify the
initial structure.
>>> external.append('bohr')
>>> external.append(DiplaceAtoms().add_atom(0.1, 0, 0, 1))
In the snippet above, the displacement is in the current units of the
structure, as understood by CRYSTAL_. E.g. in "bohr"'s here. In other
words, the transformations should reference the structure the way
CRYSTAL_ understands it. It might be indicated to use :py:meth:`eval`.
.. note::
Pylada will attempt to discover the symmetries at run time. It is also
possible to enter them explicitely by setting :py:attr:`initial`'s
``spacegroup`` attribute to a list of 4x3 matrices.
"""
keyword = 'external'
""" CRYSTAL keyword. """
def __init__(self, *args, **kwargs):
""" Creates a crystal following the CRYSTAL philosophy. """
from ..crystal import Structure
self.__dict__['initial'] = None
super(External, self).__init__()
del self.symmgroup
del self.__dict__['atoms']
self.initial = kwargs.pop('copy', None)
""" Initial structure.
This is a :py:class:`~pylada.crystal.cppwrappers.Structure` instance.
"""
if self.initial is None: self.initial = Structure(*args, **kwargs)
else: self.initial = self.initial.copy()
[docs] def add_atoms(self, *args, **kwargs):
""" Adds atom to initial structure. """
self.initial.add_atom(*args, **kwargs)
return self
@property
def atoms(self):
""" Alias to the initial structure. """
return self.initial
@atoms.setter
[docs] def atoms(self, value):
""" Alias to the initial structure. """
from ..error import AttributeError
if self.initial is not None:
raise AttributeError('Cannot set atoms in External instance.')
self.__dict__['atoms'] = value
@property
def cell(self):
""" Cell-vectors of the initial instance. """
return self.initial.cell
@cell.setter
[docs] def cell(self, value):
self.initial.cell = value
def __repr_header__(self):
""" Dumps representation to string. """
# prints construction part.
args = ""
if self.initial is not None:
copy = self.initial.copy()
copy.clear()
args = repr(copy)
args = args[args.find('(')+1:args.rfind(')')]
return '{0.__class__.__name__}({1})'.format(self, args)
@property
def raw(self):
""" Raw input for structure. """
return ""
@raw.setter
def raw(self, value): pass
def output_map(self, **kwargs):
""" Writes external file and calls base class. """
from ..crystal import write
if kwargs.get('filework', False) == True: write.crystal(self.initial)
return super(External, self).output_map(**kwargs)