def makeSlab(surface, pertubation_length, correlation_length): vectors = surface.cell(coordinates='orth_crystal') atoms = makeSample(surface.crystal(), vectors) surface.change(atoms, to='orth_surface', fro='orth_crystal') vectors = surface.cell(coordinates='orth_surface') vectors, repeats = makeLargeEnoughQuiteOrthogonalBox(vectors, pertubation_length) atoms = atoms.repeat(repeats) # Make repetitions to satisfy correlation length. n2 = int(numpy.ceil(correlation_length/vectors[2,2])) atoms = atoms.repeat((1,1,n2)) # Wrap into box with atoms below zero in third direction. wrap_vectors = numpy.array([vectors[0], vectors[1], -n2*vectors[2]]) atoms.set_cell(wrap_vectors) atoms = wrap(atoms) atoms.set_cell(vectors) atoms.set_pbc([True, True, False]) # Crop number of layers. take = atoms.get_positions()[:, 2] > - correlation_length + 1e-5 atoms = atoms[take] extra_atoms = surface.extraAtoms('orth_surface') repeats = fitBoxIntoBox(extra_atoms.get_cell()[:2], vectors[:2]) repeats = list(repeats) repeats.append(1) extra_atoms = extra_atoms.repeat(tuple(repeats)) extra_atoms.set_cell(vectors) extra_atoms = wrap(extra_atoms) extra_atoms = removeCopies(extra_atoms) atoms += extra_atoms # Passivate lower surface. positions = atoms.get_positions() z_min = min(positions[:,2]) lower_positions = positions[(positions[:,2] < z_min + 1e-5)] h_positions = [position + [0,0,-0.8] for position in lower_positions] passivation = Atoms('H%d'%len(h_positions), h_positions) atoms += passivation # Make vaccum in the out-of-surface direction. z_pos = atoms.get_positions()[:, 2] z_min, z_max = min(z_pos), max(z_pos) z_diff = z_max - z_min tot_diff = correlation_length + z_diff atoms.cell[2] = numpy.array([0,0,tot_diff]) atoms = wrap(atoms) # Put atoms in order. atoms = orderAtoms(atoms) # Fix lowest coordinates. constraint = FixAtoms(mask=(atoms.get_positions()[:, 2] < -pertubation_length + 1e-5)) atoms.set_constraint(constraint) return atoms
def makeSample(crystal, vectors): radius = numpy.max(vectorLength(vectors)) repeats = findNeededRepetitions(crystal.unitCell(), radius) atoms = crystal.toAseAtoms() atoms = atoms.repeat(repeats) atoms.set_cell(vectors) atoms = wrap(atoms) atoms = removeCopies(atoms) return atoms
def makeSlabWithVector(surface, vector, radius): v1 = numpy.zeros(3, dtype=numpy.int) v1[:2] = vector v1 = surface.change(v1, to='orth_surface', fro='surface') unit_cell = surface.unitCell('orth_surface') pro = [abs(numpy.dot(v, v1))/vectorLength(v) for v in unit_cell] v2 = unit_cell[numpy.argmin(pro)] l1 = vectorLength(v1) pro = vectorLength(numpy.cross(v1/l1, v2)) n2 = int(numpy.ceil(radius/pro)) v2 *= n2 v3 = surface.outOfPlaneVector('orth_surface') vectors = numpy.array([v1, v2, v3]) vectors = surface.change(vectors, to='crystal', fro='orth_surface') layer_distance = surface.outOfPlaneVector('orth_surface')[2] n_layers = int(numpy.ceil(radius/layer_distance)) atoms = makeSlabWithVectors(surface.crystal(), vectors, n_layers) surface.change(atoms, to='orth_surface', fro='orth_crystal') atoms.cell[2, :2] = 0 atoms.set_pbc([True, True, False]) atoms = wrap(atoms) # Make vaccum in the out-of-surface direction. z_pos = atoms.get_positions()[:, 2] z_min, z_max = min(z_pos), max(z_pos) z_diff = z_max - z_min tot_diff = radius + z_diff atoms.cell[2] = numpy.array([0,0,tot_diff]) atoms = wrap(atoms) # Put atoms in order. atoms = orderAtoms(atoms) return atoms
def makeSlabWithVectors(atoms, vectors, n_layers): unit_cell = atoms.get_cell() vectors[2] *= -1 vectors = numpy.dot(unit_cell.transpose(), vectors.transpose()).transpose() repeats = fitBoxIntoBox(unit_cell, vectors) atoms = atoms.repeat(repeats) atoms.set_cell(vectors) atoms = wrap(atoms) atoms = removeCopies(atoms) atoms = atoms.repeat((1,1,n_layers)) return atoms
def makePeriodicSample(crystal, radius=5): unit_cell=crystal.unitCell() l_b=len(unit_cell) atoms = crystal.toAseAtoms() repeats = findNeededRepetitions(unit_cell, numpy.array([radius]*3)) sample = atoms.repeat(repeats) vectors = makeQuiteOrthogonalVectors(unit_cell, repeats) sample.set_cell(vectors) sample = removeCopies(sample) sample = wrap(sample) return sample