def __setitem__(self, index, atom): from collections import Sequence from method.atom import Atom from method import error if isinstance(atom, Sequence): for a in atom: if not isinstance(a, Atom): raise error.ValueError("Input should be of type Atom") else: if not isinstance(atom, Atom): raise error.ValueError("Input should be of type Atom") return self._atoms.__setitem__(index, atom)
def are_periodic_images(pos0, pos1, invcell=None, cell=None, tolerance=1e-8): """ True if two vector are periodic images of one another :param pos0: First position :param pos1: Second position :param invcell: The *inverse* of the cell defining the periodicity :param cell: The cell defining the periodicity :param tolerance: Fuzzy tolerance criteria Only one of cell and invcell need be given. """ from numpy import dot, floor from numpy.linalg import inv, norm from method import error if invcell is None: if cell is None: raise error.ValueError("One of cell or invcell should be given") invcell = inv(cell) result = dot(invcell, pos0 - pos1) result -= floor(result + tolerance) return all(abs(result) < tolerance)
def poscar(path="POSCAR", types=None): """ Tries to read a VASP POSCAR file. :param path: Path to the POSCAR file. Can also be an object with file-like behavior. :type path: str or file object :param types: Species in the POSCAR. :type types: None or sequence of str :return: `pylada.crystal.Structure` instance. """ import re from os.path import join, exists, isdir from copy import deepcopy from numpy import array, dot, transpose from numpy.linalg import det from quantities import angstrom from method.structure import Structure from method import error # if types is not none, converts to a list of strings. if types is not None: if isinstance(types, str): types = [types] # can't see another way of doing this... elif not hasattr(types, "__iter__"): types = [str(types)] # single lone vasp.specie.Specie else: types = [str(s) for s in types] if path is None: path = "POSCAR" if not hasattr(path, 'read'): assert exists(path), IOError("Could not find path %s." % (path)) if isdir(path): assert exists(join(path, "POSCAR")), IOError("Could not find POSCAR in %s." % (path)) path = join(path, "POSCAR") result = Structure() poscar = path if hasattr(path, "read") else open(path, 'r') try: # gets name of structure result.name = poscar.readline().strip() if len(result.name) > 0 and result.name[0] == "#": result.name = result.name[1:].strip() # reads scale scale = float(poscar.readline().split()[0]) # gets cell vectors. cell = [] for i in range(3): line = poscar.readline() assert len(line.split()) >= 3,\ RuntimeError("Could not read column vector from poscar: %s." % (line)) cell.append([float(f) for f in line.split()[:3]]) result.cell = transpose(array(cell)) vol = det(cell) if scale < 1.E-8: scale = abs(scale / vol) ** (1.0 / 3) result.scale = scale * angstrom # checks for vasp 5 input. is_vasp_5 = True line = poscar.readline().split() for i in line: if not re.match(r"[A-Z][a-z]?", i): is_vasp_5 = False break if is_vasp_5: text_types = deepcopy(line) if types is not None and not set(text_types).issubset(set(types)): raise error.ValueError("Unknown species in poscar: {0} not in {1}." .format(text_types, types)) types = text_types line = poscar.readline().split() if types is None: raise RuntimeError("No atomic species given in POSCAR or input.") # checks/reads for number of each specie if len(types) < len(line): raise RuntimeError("Too many atomic species in POSCAR.") nb_atoms = [int(u) for u in line] # Check whether selective dynamics, cartesian, or direct. first_char = poscar.readline().strip().lower()[0] selective_dynamics = False if first_char == 's': selective_dynamics = True first_char = poscar.readline().strip().lower()[0] # Checks whether cartesian or direct. is_direct = first_char not in ['c', 'k'] # reads atoms. for n, specie in zip(nb_atoms, types): for i in range(n): line = poscar.readline().split() pos = array([float(u) for u in line[:3]], dtype="float64") if is_direct: pos = dot(result.cell, pos) result.add_atom(pos=pos, type=specie) if selective_dynamics: for which, freeze in zip(line[3:], ['x', 'y', 'z']): if which.lower()[0] == 't': result[-1].freeze = getattr(result[-1], 'freeze', '') + freeze finally: poscar.close() return result