import numpy.random as random import numpy as np from ase_ext import Atoms from ase_ext.calculators.neighborlist import NeighborList atoms = Atoms(numbers=list(range(10)), cell=[(0.2, 1.2, 1.4), (1.4, 0.1, 1.6), (1.3, 2.0, -0.1)]) atoms.set_scaled_positions(3 * random.random((10, 3)) - 1) def count(nl, atoms): c = np.zeros(len(atoms), int) R = atoms.get_positions() cell = atoms.get_cell() d = 0.0 for a in range(len(atoms)): i, offsets = nl.get_neighbors(a) for j in i: c[j] += 1 c[a] += len(i) d += (((R[i] + np.dot(offsets, cell) - R[a])**2).sum(1)**0.5).sum() return d, c for sorted in [False, True]: for p1 in range(2): for p2 in range(2): for p3 in range(2): print(p1, p2, p3) atoms.set_pbc((p1, p2, p3)) nl = NeighborList(atoms.numbers * 0.2 + 0.5,
def read_vasp(filename='CONTCAR'): """Import POSCAR/CONTCAR type file. Reads unitcell, atom positions and constraints from the POSCAR/CONTCAR file and tries to read atom types from POSCAR/CONTCAR header, if this fails the atom types are read from OUTCAR or POTCAR file. """ from ase_ext import Atoms, Atom from ase_ext.constraints import FixAtoms, FixScaled from ase_ext.data import chemical_symbols import numpy as np if isinstance(filename, str): f = open(filename) else: # Assume it's a file-like object f = filename # First line should contain the atom symbols , eg. "Ag Ge" in # the same order # as later in the file (and POTCAR for the full vasp run) atomtypes = f.readline().split() lattice_constant = float(f.readline()) # Now the lattice vectors a = [] for ii in range(3): s = f.readline().split() floatvect = float(s[0]), float(s[1]), float(s[2]) a.append(floatvect) basis_vectors = np.array(a) * lattice_constant # Number of atoms. Again this must be in the same order as # in the first line # or in the POTCAR or OUTCAR file atom_symbols = [] numofatoms = f.readline().split() #vasp5.1 has an additional line which gives the atom types #the following try statement skips this line try: int(numofatoms[0]) except ValueError: numofatoms = f.readline().split() numsyms = len(numofatoms) if len(atomtypes) < numsyms: # First line in POSCAR/CONTCAR didn't contain enough symbols. atomtypes = atomtypes_outpot(f.name, numsyms) else: try: for atype in atomtypes[:numsyms]: if not atype in chemical_symbols: raise KeyError except KeyError: atomtypes = atomtypes_outpot(f.name, numsyms) for i, num in enumerate(numofatoms): numofatoms[i] = int(num) [atom_symbols.append(atomtypes[i]) for na in range(numofatoms[i])] # Check if Selective dynamics is switched on sdyn = f.readline() selective_dynamics = sdyn[0].lower() == "s" # Check if atom coordinates are cartesian or direct if selective_dynamics: ac_type = f.readline() else: ac_type = sdyn cartesian = ac_type[0].lower() == "c" or ac_type[0].lower() == "k" tot_natoms = sum(numofatoms) atoms_pos = np.empty((tot_natoms, 3)) if selective_dynamics: selective_flags = np.empty((tot_natoms, 3), dtype=bool) for atom in range(tot_natoms): ac = f.readline().split() atoms_pos[atom] = (float(ac[0]), float(ac[1]), float(ac[2])) if selective_dynamics: curflag = [] for flag in ac[3:6]: curflag.append(flag == 'F') selective_flags[atom] = curflag # Done with all reading if type(filename) == str: f.close() if cartesian: atoms_pos *= lattice_constant atoms = Atoms(symbols=atom_symbols, cell=basis_vectors, pbc=True) if cartesian: atoms.set_positions(atoms_pos) else: atoms.set_scaled_positions(atoms_pos) if selective_dynamics: constraints = [] indices = [] for ind, sflags in enumerate(selective_flags): if sflags.any() and not sflags.all(): constraints.append(FixScaled(atoms.get_cell(), ind, sflags)) elif sflags.all(): indices.append(ind) if indices: constraints.append(FixAtoms(indices)) if constraints: atoms.set_constraint(constraints) return atoms