Ejemplo n.º 1
0
    def atoms(self, constrained=True, parameters=DEFAULT):
        if parameters is DEFAULT:
            parameters = self.parameters()
        parameters = self.defaultParameters(parameters)
        vectors = np.array(parameters['vectors'])

        lengths = vectorLength(vectors, 1)
        assert lengths.all()

        atoms = self.__atoms.copy()
        pos = atoms.get_positions()
        size = np.array([pos[:, i].max() - pos[:,i].min() for i in range(3)])
        size = size + parameters['length_scales']['correlation_length']

        repeats = (1, 1, vectors[0][0])
        vectors = atoms.cell[2] * vectors[0][0]

        atoms = atoms.repeat(repeats)
        atoms.set_cell(size)
        atoms.cell[2] = vectors
        atoms = removeCopies(atoms)
        atoms = orderAtoms(atoms)

        atoms = self.makeAtomsRelaxed(atoms, self.relaxation())

        return atoms
Ejemplo n.º 2
0
    def atoms(self,
            constrained=True,
            parameters=DEFAULT,
            ):
        system = self.fullyUnrelaxed()
        if parameters is DEFAULT:
            parameters = self.parameters()

        parameters = system.defaultParameters(parameters)
        slab = system.slab()

        slab_parameters = parameters['slab_parameters']
        atoms = slab.atoms(
                constrained=constrained,
                initialized=True,
                parameters=slab_parameters,
                )
        atoms = system.change(atoms, to='orth_system', fro='orth_defect')
        atoms.wrap(center=0)
        atoms = orderAtoms(atoms)


        molecule_atoms = self.moleculeAtoms(parameters=parameters['molecule_parameters'])
        atoms += molecule_atoms

        if len(molecule_atoms) > 0:
            name = self.name().replace(os.sep, '_')
            atoms.setRegion(name=name, picker=slice(-len(molecule_atoms), None),
                              cell=atoms.get_cell(), pbc=[False, False, False])

        atoms = self.makeAtomsRelaxed(atoms, self.relaxation())

        return atoms
Ejemplo n.º 3
0
    def crystalAtoms(self,
                     start_layer=0,
                     end_layer=1,
                     coordinates='orth_surface',
                     sub_layers=False,
                     minimal=True,
                     ):
        atoms = self.crystal().atoms()

        if sub_layers:
            in_equal_layers = self.inequivalentLayers()
            repeats = int(np.ceil(end_layer/float(in_equal_layers)))
            atoms = atoms.repeat((1, 1, repeats + 1))
            atoms.positions -= self.crystal().unitCell()*(repeats)
            start_layer += in_equal_layers -1
            end_layer += in_equal_layers -1
            atoms = orderAtoms(atoms, (2, 1, 0))
            sl = slice(start_layer, end_layer)

            groups = groupAtoms(atoms)[::-1][sl]
            if len(groups) == 0:
                atoms = Atoms([], cell=atoms.get_cell(), pbc=atoms.get_pbc())
            else:
                atoms, indices = groups[0]
                for group, indices in groups[1:]:
                    atoms += group
        else:
            cell = atoms.unitCell()
            atoms = atoms.repeat((1, 1, end_layer-start_layer))
            atoms.positions += cell*start_layer

        return atoms
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
    def crystalAtoms(self,
                     start_layer=0,
                     end_layer=1,
                     coordinates='orth_surface',
                     vectors=((1,0),(0,1)),
                     sub_layers=False,
                     minimal=True,
                     ):
        sl = slice(start_layer, end_layer)
        if minimal:
            unit_cell = self.minimalCell('crystal')
        else:
            unit_cell = self.cell('crystal')
        catoms = self.crystal().atoms()
        catoms.purgeTags()
        atoms = makeSlabWithVectors(catoms, unit_cell, sl.stop)
        atoms = self.change(atoms, to=coordinates, fro='orth_crystal')
        unit_cell = self.crystal().change(unit_cell, to='orth_crystal', fro='crystal',
                                    difference=True,)[:2]
        unit_cell = self.change(unit_cell, to='orth_surface', fro='orth_crystal')

        if len(atoms)==0:
            return atoms

        if minimal:
            vectors = unit_cell
        else:
            vectors = np.array(vectors)
            vectors = np.dot(unit_cell.transpose(), vectors.transpose()).transpose()
            repeats = fitBoxIntoBox(unit_cell, vectors)
            atoms = atoms.repeat(list(repeats) + [1])

        out_vector = atoms.cell[2]
        out_vector[:2] = 0
        vectors = np.array([vectors[0], vectors[1], out_vector])

        atoms.set_cell(vectors)
        atoms.set_pbc([True, True, False])
        atoms = removeCopies(atoms)
        atoms.wrap()
        atoms = orderAtoms(atoms, (2, 1, 0))


        if sub_layers:
            groups = groupAtoms(atoms)[sl]
            if len(groups) == 0:
                return Atoms([], cell=atoms.get_cell(), pbc=atoms.get_pbc())

            atoms, indices = groups[0]
            for atoms_group, indices in groups[1:]:
                atoms += atoms_group

        return atoms
Ejemplo n.º 6
0
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
Ejemplo n.º 7
0
    def atoms(
            self,
            parameters=DEFAULT,
            passivated=True,
            passivation_constrained=False,
            constrained=True,
            ):
        unrelaxed = self.fullyUnrelaxed()

        if parameters is DEFAULT:
            parameters = self.parameters()
        else:
            parameters = unrelaxed.defaultParameters(parameters)

        # Add outer surface layer.
        extra_atoms = unrelaxed.surfaceLayer(parameters)
        atoms = unrelaxed.crystalAtoms(
                start_layer=0,
                end_layer=parameters.nLayers(),
                sub_layers=True,
                )
        atoms += extra_atoms

        pos = atoms.positions
        size = np.array([pos[:, i].max() - pos[:,i].min() for i in range(3)])
        atoms.cell[:2,:2] = extra_atoms.cell[:2, :2]
        atoms = orderAtoms(atoms)

        if passivated:
            before = len(atoms)
            atoms = unrelaxed.passivateLowerSurface(atoms)
            after = len(atoms)
            n_passivated = after - before

        if constrained:
            fro, to = parameters['free_layers'], parameters.nLayers()
            constrain_mask = unrelaxed.findLayers(atoms, start_layer=fro, end_layer=to)
        else:
            constrain_mask = np.zeros(len(atoms), bool)

        if parameters['electrode_layers'] > 0:
            fro, to = parameters.nLayers() - parameters['electrode_layers'], parameters.nLayers()
            electrode_mask = unrelaxed.findLayers(atoms, start_layer=fro, end_layer=to)
            electrode_cell = unrelaxed.electrodeCell(parameters['electrode_layers'], atoms.get_cell()[:2])
            central_mask = np.logical_not(electrode_mask)
        else:
            electrode_mask = np.zeros(len(atoms), int)
            electrode_cell = np.identity(3)
            central_mask = np.ones(len(atoms), int)

        if passivated and passivation_constrained:
            constrain_mask[:n_passivated] = True

        # Make vaccum in the out-of-surface direction.
        atoms.set_cell(np.array(parameters['cell_size']) + size)

        if electrode_mask.sum() > 0:
            electrode_cell[:2] = atoms.cell[:2]
            atoms.setRegion(
                name=self.crystal().name(),
                picker=electrode_mask,
                cell=electrode_cell,
                pbc=(False, False, (False, True)),
                )

        atoms.setRegion(name=self.name(),
                          picker=central_mask,
                          cell=atoms.get_cell(),
                          pbc=(False, False, False),
                          )

        if constrained:
            constraint = FixAtoms(mask=constrain_mask)
            atoms.set_constraint(constraint)

        cell_center = atoms.cell.sum(axis=0)/2
        atoms_center = (atoms.positions.max(axis=0) + atoms.positions.min(axis=0))/2
        move = cell_center - atoms_center
        atoms.set_celldisp(-move)

        atoms = self.makeAtomsRelaxed(atoms, self.relaxation())

        return atoms
Ejemplo n.º 8
0
    def atoms(
            self,
            constrained=True,
            initialized=True,
            parameters=DEFAULT,
            passivation_constrained=False,
            ):
        if parameters is DEFAULT:
            parameters = self.parameters()

        system = self.fullyUnrelaxed()
        basis_changer = system.basisChanger()

        parameters = system.defaultParameters(parameters)
        scales = parameters['length_scales']

        electrode_sep = parameters.nLayers() - parameters['electrode_layers']
        c_atoms = system.crystalAtoms(
                          start_layer=electrode_sep,
                          end_layer=parameters.nLayers(),
                          vectors=parameters['vectors'],
                          minimal=True,
                          sub_layers=True,
                          )
        c_atoms += system.crystalAtoms(
                          start_layer=0,
                          end_layer=electrode_sep,
                          vectors=parameters['vectors'],
                          minimal=False,
                          sub_layers=True,
                          )
        atoms = c_atoms.copy()
        vectors = system.fullCell(parameters)
        v3 = np.zeros(3)
        v3[2] = -abs(atoms.cell[2][2])
        tmp_vectors = np.array([vectors[0], vectors[1], v3])
        atoms.set_cell(tmp_vectors)
        atoms.set_pbc([True, True, False])
        atoms.wrap()

        # Add outer surface layer.
        extra_atoms = system.surfaceLayer(parameters)
        atoms += extra_atoms
        atoms.cell[:2,:2] = extra_atoms.cell[:2, :2]

        if parameters['passivated']:
            before = len(atoms)
            atoms = self.passivateLowerSurface(atoms)
            after = len(atoms)
            n_passivated = after - before

        # Make vaccum in the out-of-surface direction.
        atoms.cell[2] = np.array([0,0, parameters['cell_size']])

        if constrained:
            fro, to = parameters['free_layers'], parameters.nLayers()
            constrain_mask = system.findLayers(atoms, start_layer=fro, end_layer=to)
        else:
            constrain_mask = np.zeros(len(atoms), bool)

        if parameters['passivated'] and passivation_constrained:
            constrain_mask[:n_passivated] = True

        if initialized:
            atoms = system.initializedState(atoms)


        if parameters['electrode_layers'] > 0:
            fro, to = parameters.nLayers() - parameters['electrode_layers'], parameters.nLayers()
            mask = system.findLayers(atoms, start_layer=fro, end_layer=to)
            cell = system.electrodeCell(parameters['electrode_layers'], parameters['vectors'])
            atoms.setToRegion(
                    name=self.crystal().name(),
                    picker=mask,
                    cell=cell,
                    pbc=(True, True, (True, False)),
                    )
            mask = np.logical_not(mask)
            if mask.sum() >0:
                atoms.setToRegion(name=self.name(),
                                  picker=mask,
                                  cell=atoms.get_cell(),
                                  pbc=(True, True, False),
                                  )

        constraint = FixAtoms(mask=constrain_mask)
        atoms.set_constraint(constraint)
        atoms.wrap(center=0, eps=0.01)
        atoms = orderAtoms(atoms)
        mask = system.findLayers(atoms, start_layer=0, end_layer=parameters.nLayers())
        atoms.setTag('ReferenceBulk', picker=mask)
        atoms.setTag('Reference', picker=slice(-n_passivated, None))
        atoms = self.makeAtomsRelaxed(atoms, self.relaxation())

        return atoms