def mycut(atoms, a_atom, b_atom, c_atom, origo_atom, nlayers=None, extend=1.0, tolerance=0.01, maxatoms=None): """ atoms: atoms a_atoms,b_atoms,c_atoms: the symol_number of the atoms (a_atom-origo_atom)-> a; ... origo_atom: the atom at the origin. other parameters are as ase.io.geometry.cut """ symdict = symbol_number(atoms) origo = symdict[origo_atom] a = symdict[a_atom] b = symdict[b_atom] c = symdict[c_atom] atoms = cut(atoms, a=a, b=b, c=c, clength=None, origo=origo, nlayers=None, extend=1.0, tolerance=0.01, maxatoms=None) return atoms
def rh2hex(lattice): """ return Atomic objects with 3 times volume hexgonal cell of the input rhombohedral cell exist slightly different cut vectors, see ITC vol. A """ from ase.utils.geometry import cut re=cut(lattice, (1.0, -1.0, 0.0), (0.0, 1.0, -1.0), (1.0, 1.0,1.0), origo=(0,0,0)) return re
def primitive_from_conventional_cell(atoms, spacegroup=1, setting=1): """Returns primitive cell given an Atoms object for a conventional cell and it's spacegroup.""" from ase.lattice.spacegroup import Spacegroup from ase.utils.geometry import cut sg = Spacegroup(spacegroup, setting) prim_cell = sg.scaled_primitive_cell # Check if we need to transpose return cut(atoms, a=prim_cell[0], b=prim_cell[1], c=prim_cell[2])
def cut_z(atoms, symnum1, symnum2, shift): """ cut along the z direction. """ symdict = symbol_number(atoms) z1 = atoms.get_positions()[symdict[symnum1]][2] - shift z2 = atoms.get_positions()[symdict[symnum2]][2] - shift c = atoms.get_cell()[2][2] dz = z2 - z1 newatoms = cut(atoms, clength=dz, origo=(0, 0, z1 / c)) newatoms.translate([0, 0, -shift]) return newatoms
"Test the ase.utils.geometry module" import numpy as np from ase.lattice.spacegroup import crystal from ase.utils.geometry import get_layers, cut, stack np.set_printoptions(suppress=True) al = crystal('Al', [(0, 0, 0)], spacegroup=225, cellpar=4.05) # Cut out slab of 5 Al(001) layers al001 = cut(al, nlayers=5) correct_pos = np.array([[0., 0., 0.], [0., 0.5, 0.2], [0.5, 0., 0.2], [0.5, 0.5, 0.], [0., 0., 0.4], [0., 0.5, 0.6], [0.5, 0., 0.6], [0.5, 0.5, 0.4], [0., 0., 0.8], [0.5, 0.5, 0.8]]) assert np.allclose(correct_pos, al001.get_scaled_positions()) # Check layers along 001 tags, levels = get_layers(al001, (0, 0, 1)) assert np.allclose(tags, [0, 1, 1, 0, 2, 3, 3, 2, 4, 4]) assert np.allclose(levels, [0., 2.025, 4.05, 6.075, 8.1]) # Check layers along 101 tags, levels = get_layers(al001, (1, 0, 1)) assert np.allclose(tags, [0, 1, 5, 3, 2, 4, 8, 7, 6, 9]) assert np.allclose( levels, [0.000, 0.752, 1.504, 1.880, 2.256, 2.632, 3.008, 3.384, 4.136, 4.888], atol=0.001)
import numpy as np import ase.utils.geometry as geometry import ase.io as io # Create a new atoms instance with Co at origo including all atoms on the # surface of the unit cell cosb3 = geometry.cut(skutterudite, origo=(0.25, 0.25, 0.25), extend=1.01) # Define the atomic bonds to show bondatoms = [] symbols = cosb3.get_chemical_symbols() for i in xrange(len(cosb3)): for j in xrange(i): if (symbols[i] == symbols[j] == 'Co' and cosb3.get_distance(i, j) < 4.53): bondatoms.append((i, j)) elif (symbols[i] == symbols[j] == 'Sb' and cosb3.get_distance(i, j) < 2.99): bondatoms.append((i, j)) # Create nice-looking image using povray io.write( 'spacegroup-cosb3.pov', cosb3, transparent=False, display=False, run_povray=True, camera_type='perspective', canvas_width=320, radii=0.4, rotation='90y',
"""Test the ase.utils.geometry module""" import numpy as np from ase.lattice.spacegroup import crystal from ase.utils.geometry import get_layers, cut, stack from ase.atoms import Atoms np.set_printoptions(suppress=True) al = crystal("Al", [(0, 0, 0)], spacegroup=225, cellpar=4.05) # Cut out slab of 5 Al(001) layers al001 = cut(al, nlayers=5) correct_pos = np.array( [ [0.0, 0.0, 0.0], [0.0, 0.5, 0.2], [0.5, 0.0, 0.2], [0.5, 0.5, 0.0], [0.0, 0.0, 0.4], [0.0, 0.5, 0.6], [0.5, 0.0, 0.6], [0.5, 0.5, 0.4], [0.0, 0.0, 0.8], [0.5, 0.5, 0.8], ] ) assert np.allclose(correct_pos, al001.get_scaled_positions())
def crystal(symbols=None, basis=None, spacegroup=1, setting=1, cell=None, cellpar=None, ab_normal=(0,0,1), a_direction=None, size=(1,1,1), ondublicates='warn', symprec=0.001, pbc=True, primitive_cell=False, **kwargs): """Create an Atoms instance for a conventional unit cell of a space group. Parameters: symbols : str | sequence of str | sequence of Atom | Atoms Element symbols of the unique sites. Can either be a string formula or a sequence of element symbols. E.g. ('Na', 'Cl') and 'NaCl' are equivalent. Can also be given as a sequence of Atom objects or an Atoms object. basis : list of scaled coordinates Positions of the unique sites corresponding to symbols given either as scaled positions or through an atoms instance. Not needed if *symbols* is a sequence of Atom objects or an Atoms object. spacegroup : int | string | Spacegroup instance Space group given either as its number in International Tables or as its Hermann-Mauguin symbol. setting : 1 | 2 Space group setting. cell : 3x3 matrix Unit cell vectors. cellpar : [a, b, c, alpha, beta, gamma] Cell parameters with angles in degree. Is not used when `cell` is given. ab_normal : vector Is used to define the orientation of the unit cell relative to the Cartesian system when `cell` is not given. It is the normal vector of the plane spanned by a and b. a_direction : vector Defines the orientation of the unit cell a vector. a will be parallel to the projection of `a_direction` onto the a-b plane. size : 3 positive integers How many times the conventional unit cell should be repeated in each direction. ondublicates : 'keep' | 'replace' | 'warn' | 'error' Action if `basis` contain symmetry-equivalent positions: 'keep' - ignore additional symmetry-equivalent positions 'replace' - replace 'warn' - like 'keep', but issue an UserWarning 'error' - raises a SpacegroupValueError symprec : float Minimum "distance" betweed two sites in scaled coordinates before they are counted as the same site. pbc : one or three bools Periodic boundary conditions flags. Examples: True, False, 0, 1, (1, 1, 0), (True, False, False). Default is True. primitive_cell : bool Wheter to return the primitive instead of the conventional unit cell. Keyword arguments: All additional keyword arguments are passed on to the Atoms constructor. Currently, probably the most useful additional keyword arguments are `info`, `constraint` and `calculator`. Examples: Two diamond unit cells (space group number 227) >>> diamond = crystal('C', [(0,0,0)], spacegroup=227, ... cellpar=[3.57, 3.57, 3.57, 90, 90, 90], size=(2,1,1)) >>> ase.view(diamond) # doctest: +SKIP A CoSb3 skutterudite unit cell containing 32 atoms >>> skutterudite = crystal(('Co', 'Sb'), ... basis=[(0.25,0.25,0.25), (0.0, 0.335, 0.158)], ... spacegroup=204, cellpar=[9.04, 9.04, 9.04, 90, 90, 90]) >>> len(skutterudite) 32 """ sg = Spacegroup(spacegroup, setting) if (not isinstance(symbols, str) and hasattr(symbols, '__getitem__') and len(symbols) > 0 and isinstance(symbols[0], ase.Atom)): symbols = ase.Atoms(symbols) if isinstance(symbols, ase.Atoms): basis = symbols symbols = basis.get_chemical_symbols() if isinstance(basis, ase.Atoms): basis_coords = basis.get_scaled_positions() if cell is None and cellpar is None: cell = basis.cell if symbols is None: symbols = basis.get_chemical_symbols() else: basis_coords = np.array(basis, dtype=float, copy=False, ndmin=2) sites, kinds = sg.equivalent_sites(basis_coords, ondublicates=ondublicates, symprec=symprec) symbols = parse_symbols(symbols) symbols = [symbols[i] for i in kinds] if cell is None: cell = cellpar_to_cell(cellpar, ab_normal, a_direction) info = dict(spacegroup=sg) if primitive_cell: info['unit_cell'] = 'primitive' else: info['unit_cell'] = 'conventional' if 'info' in kwargs: info.update(kwargs['info']) kwargs['info'] = info atoms = ase.Atoms(symbols, scaled_positions=sites, cell=cell, pbc=pbc, **kwargs) if isinstance(basis, ase.Atoms): for name in basis.arrays: if not atoms.has(name): array = basis.get_array(name) atoms.new_array(name, [array[i] for i in kinds], dtype=array.dtype, shape=array.shape[1:]) if primitive_cell: from ase.utils.geometry import cut prim_cell = sg.scaled_primitive_cell atoms = cut(atoms, a=prim_cell[0], b=prim_cell[1], c=prim_cell[2]) if size != (1, 1, 1): atoms = atoms.repeat(size) return atoms
def cut111(crystal,nlayers=6): """Cleave the 111 surface""" crystal111 = cut(crystal,[1,0,1],[1,1,0],nlayers=nlayers) return crystal111
def cut001(crystal,nlayers=6): """Cleave the 001 surface""" crystal001 = cut(crystal,[0,1,0],[0,0,1],nlayers=nlayers) return crystal001
def cut010(crystal,nlayers=6): """Cleave the 010 surface""" crystal010 = cut(crystal,[1,0,0],[0,0,1],nlayers=nlayers) return crystal010
def cut100(crystal,nlayers=6): """Cleave the 100 surface""" crystal100 = cut(crystal,[0,0,1],[0,1,0],nlayers=nlayers) return crystal100
def crystal(symbols=None, basis=None, spacegroup=1, setting=1, cell=None, cellpar=None, ab_normal=(0, 0, 1), a_direction=None, size=(1, 1, 1), ondublicates='warn', symprec=0.001, pbc=True, primitive_cell=False, **kwargs): """Create an Atoms instance for a conventional unit cell of a space group. Parameters: symbols : str | sequence of str | sequence of Atom | Atoms Element symbols of the unique sites. Can either be a string formula or a sequence of element symbols. E.g. ('Na', 'Cl') and 'NaCl' are equivalent. Can also be given as a sequence of Atom objects or an Atoms object. basis : list of scaled coordinates Positions of the unique sites corresponding to symbols given either as scaled positions or through an atoms instance. Not needed if *symbols* is a sequence of Atom objects or an Atoms object. spacegroup : int | string | Spacegroup instance Space group given either as its number in International Tables or as its Hermann-Mauguin symbol. setting : 1 | 2 Space group setting. cell : 3x3 matrix Unit cell vectors. cellpar : [a, b, c, alpha, beta, gamma] Cell parameters with angles in degree. Is not used when `cell` is given. ab_normal : vector Is used to define the orientation of the unit cell relative to the Cartesian system when `cell` is not given. It is the normal vector of the plane spanned by a and b. a_direction : vector Defines the orientation of the unit cell a vector. a will be parallel to the projection of `a_direction` onto the a-b plane. size : 3 positive integers How many times the conventional unit cell should be repeated in each direction. ondublicates : 'keep' | 'replace' | 'warn' | 'error' Action if `basis` contain symmetry-equivalent positions: 'keep' - ignore additional symmetry-equivalent positions 'replace' - replace 'warn' - like 'keep', but issue an UserWarning 'error' - raises a SpacegroupValueError symprec : float Minimum "distance" betweed two sites in scaled coordinates before they are counted as the same site. pbc : one or three bools Periodic boundary conditions flags. Examples: True, False, 0, 1, (1, 1, 0), (True, False, False). Default is True. primitive_cell : bool Wheter to return the primitive instead of the conventional unit cell. Keyword arguments: All additional keyword arguments are passed on to the Atoms constructor. Currently, probably the most useful additional keyword arguments are `info`, `constraint` and `calculator`. Examples: Two diamond unit cells (space group number 227) >>> diamond = crystal('C', [(0,0,0)], spacegroup=227, ... cellpar=[3.57, 3.57, 3.57, 90, 90, 90], size=(2,1,1)) >>> ase.view(diamond) # doctest: +SKIP A CoSb3 skutterudite unit cell containing 32 atoms >>> skutterudite = crystal(('Co', 'Sb'), ... basis=[(0.25,0.25,0.25), (0.0, 0.335, 0.158)], ... spacegroup=204, cellpar=[9.04, 9.04, 9.04, 90, 90, 90]) >>> len(skutterudite) 32 """ sg = Spacegroup(spacegroup, setting) if (not isinstance(symbols, str) and hasattr(symbols, '__getitem__') and len(symbols) > 0 and isinstance(symbols[0], ase.Atom)): symbols = ase.Atoms(symbols) if isinstance(symbols, ase.Atoms): basis = symbols symbols = basis.get_chemical_symbols() if isinstance(basis, ase.Atoms): basis_coords = basis.get_scaled_positions() if cell is None and cellpar is None: cell = basis.cell if symbols is None: symbols = basis.get_chemical_symbols() else: basis_coords = np.array(basis, dtype=float, copy=False, ndmin=2) sites, kinds = sg.equivalent_sites(basis_coords, ondublicates=ondublicates, symprec=symprec) symbols = parse_symbols(symbols) symbols = [symbols[i] for i in kinds] if cell is None: cell = cellpar_to_cell(cellpar, ab_normal, a_direction) info = dict(spacegroup=sg) if primitive_cell: info['unit_cell'] = 'primitive' else: info['unit_cell'] = 'conventional' if 'info' in kwargs: info.update(kwargs['info']) kwargs['info'] = info atoms = ase.Atoms(symbols, scaled_positions=sites, cell=cell, pbc=pbc, **kwargs) if isinstance(basis, ase.Atoms): for name in basis.arrays: if not atoms.has(name): array = basis.get_array(name) atoms.new_array(name, [array[i] for i in kinds], dtype=array.dtype, shape=array.shape[1:]) if primitive_cell: from ase.utils.geometry import cut prim_cell = sg.scaled_primitive_cell atoms = cut(atoms, a=prim_cell[0], b=prim_cell[1], c=prim_cell[2]) if size != (1, 1, 1): atoms = atoms.repeat(size) return atoms
import numpy as np import ase.utils.geometry as geometry import ase.io as io # Create a new atoms instance with Co at origo including all atoms on the # surface of the unit cell cosb3 = geometry.cut(skutterudite, origo=(0.25, 0.25, 0.25), extend=1.01) # Define the atomic bonds to show bondatoms = [] symbols = cosb3.get_chemical_symbols() for i in xrange(len(cosb3)): for j in xrange(i): if (symbols[i] == symbols[j] == 'Co' and cosb3.get_distance(i, j) < 4.53): bondatoms.append((i, j)) elif (symbols[i] == symbols[j] == 'Sb' and cosb3.get_distance(i, j) < 2.99): bondatoms.append((i, j)) # Create nice-looking image using povray io.write('spacegroup-cosb3.pov', cosb3, transparent=False, display=False, run_povray=True, camera_type='perspective', canvas_width=320, radii=0.4, rotation='90y', bondlinewidth=0.07, bondatoms=bondatoms,