Esempio n. 1
0
def surface_energy(bulk, z_offset):
    Nat = bulk.get_number_of_atoms()

    # shift so cut is through shuffle plane
    bulk.positions[:, 2] += z_offset
    bulk.wrap()

    # relax atom positions, holding cell fixed
    # vac = relax_atoms(vac, fmax=fmax)

    # compute surface formation energy as difference of bulk and expanded cell
    ebulk = bulk.get_potential_energy()
    print 'bulk cell energy', ebulk

    bulk.cell[2, :] += [0.0, 0.0, 10.0]

    np.random.seed(75)

    bulk.positions += (np.random.rand((Nat * 3)) * 0.1).reshape([Nat, 3])
    bulk = relax_atoms(bulk,
                       tol=fmax,
                       traj_file="model-" + model.name +
                       "-surface-energy-111-relaxed.opt.xyz")

    eexp = bulk.get_potential_energy()

    ase.io.write(sys.stdout, bulk, format='extxyz')

    print 'expanded cell energy', eexp
    e_form = 0.5 * (eexp - ebulk) / np.linalg.norm(
        np.cross(bulk.cell[0, :], bulk.cell[1, :]))
    print 'relaxed 111 surface formation energy', e_form
    return e_form
Esempio n. 2
0
def fourfold_defect_energy(bulk):
    Nat = bulk.get_number_of_atoms()
    defect = bulk.copy()
    defect.set_calculator(bulk.get_calculator())

    # modify atom positions so that relaxation creates a fourfold defect
    p = defect.get_positions()
    # p[0,0] += 1.2
    # p[0,1] += 1.2
    # p[1,0] -= 1.2
    # p[1,1] -= 1.2
    # from CASTEP relaxed structure
    p[0, :] += (0.81, 0.81, -0.43)
    p[1, :] -= (0.81, 0.81, -0.43)

    defect.set_positions(p)

    ase.io.write(sys.stdout, defect, format='extxyz')
    # relax atom positions, holding cell fixed
    print "JOE test relaxing defect"
    defect = relax_atoms(defect,
                         tol=tol,
                         traj_file="model-" + model.name +
                         "-test-fourfold-defect.opt.xyz",
                         method="lbfgs")
    print "JOE test done relaxing defect"
    ase.io.write(sys.stdout, defect, format='extxyz')

    # compute formation energy as difference of bulk and int energies
    print 'bulk energy', bulk_energy
    print 'defect energy', defect.get_potential_energy()
    e_form = defect.get_potential_energy() - bulk_energy
    print 'defect formation energy', e_form
    return e_form
Esempio n. 3
0
def surface_energy(bulk):
    Nat = bulk.get_number_of_atoms()

    # relax atom positions, holding cell fixed
    # vac = relax_atoms(vac, fmax=fmax)

    # compute surface formation energy as half the difference of bulk and expanded cell
    print "len(bulk)", len(bulk)
    ebulk = bulk.get_potential_energy()
    print 'bulk cell energy', ebulk

    bulk.cell[2, :] += [0.0, 0.0, 10.0]

    ase.io.write(sys.stdout, bulk, format='extxyz')

    # relax expanded cell
    bulk = relax_atoms(bulk,
                       tol=fmax,
                       method='lbfgs',
                       traj_file="model-" + model.name +
                       "-surface-energy-100-relaxed.opt.xyz",
                       use_armijo=False)
    eexp = bulk.get_potential_energy()

    ase.io.write(sys.stdout, bulk, format='extxyz')

    print 'expanded cell energy', eexp
    e_form = 0.5 * (eexp - ebulk) / np.linalg.norm(
        np.cross(bulk.cell[0, :], bulk.cell[1, :]))

    print 'relaxed 100 surface formation energy', e_form
    return e_form
Esempio n. 4
0
def vacancy_energy(bulk, remove_index=0):
    Nat = bulk.get_number_of_atoms()
    vac = bulk.copy()
    vac.set_calculator(bulk.get_calculator())

    nl = NeighborList([a0*sqrt(3.0)/4*0.6]*len(bulk), self_interaction=False, bothways=True)
    nl.update(bulk)
    indices, offsets = nl.get_neighbors(remove_index)
    offset_factor=0.13
    for i, offset in zip(indices, offsets):
       ri = vac.positions[remove_index] - (vac.positions[i] + dot(offset, vac.get_cell()))
       vac.positions[i] += offset_factor*ri
       offset_factor += 0.01

    del vac[remove_index] # remove an atom to introduce a vacancy

    # perturb positions
    vac.rattle(0.1)

    ##
    try:
        model.calculator.set(local_gap_error='local_gap_error')
        vac.get_potential_energy()
        unrelaxed_local_gap_error_max = amax(model.calculator.results['local_gap_error'])
        unrelaxed_local_gap_error_sum = sum(model.calculator.results['local_gap_error'])
    except:
        unrelaxed_local_gap_error_max = None
        unrelaxed_local_gap_error_sum = None
    if isinstance(model, Potential):
        model.calculator.set(local_gap_error='')

    # relax atom positions, holding cell fixed
    vac = relax_atoms(vac, tol=fmax, traj_file="model-"+model.name+"-test-vacancy-energy.opt.xyz")

    vac.write("model-"+model.name+"test-vacancy-energy-relaxed.xyz")

    ##
    try:
        model.calculator.set(local_gap_error='local_gap_error')
        vac.get_potential_energy()
        relaxed_local_gap_error_max = amax(model.calculator.results['local_gap_error'])
        relaxed_local_gap_error_sum = sum(model.calculator.results['local_gap_error'])
    except:
        relaxed_local_gap_error_max = None
        relaxed_local_gap_error_sum = None
    if isinstance(model, Potential):
        model.calculator.set(local_gap_error='')
    ##

    # compute vacancy formation energy as difference of bulk and vac energies
    print 'bulk cell energy', bulk_energy
    print 'vacancy cell energy', vac.get_potential_energy()
    e_form = vac.get_potential_energy() - bulk_energy*vac.get_number_of_atoms()/bulk.get_number_of_atoms()
    print 'vacancy formation energy', e_form
    return (e_form, unrelaxed_local_gap_error_max, unrelaxed_local_gap_error_sum, relaxed_local_gap_error_max, relaxed_local_gap_error_sum)
Esempio n. 5
0
def surface_energy(n, bulk, ebulk_per_atom, e111):

    tmp = ase.io.read(os.path.dirname(__file__) + '/si111_' + str(n) + 'x' +
                      str(n) + '_8layer.xyz',
                      index=':',
                      format='extxyz')
    surf = tmp[0]

    # adjust lattice constant
    L = surf.get_cell()
    bulkL = bulk.get_cell()
    scaling_factor = bulkL[0, 0] * n / L[0, 0]
    surf.set_cell(L * scaling_factor, scale_atoms=True)

    fixed_list = np.where(surf.arrays['move_mask'] == 0)[0]
    c = FixAtoms(fixed_list)
    surf.set_constraint(c)

    # relax atom positions of the reconstructed surface, holding cell fixed
    surfNat = surf.get_number_of_atoms()
    #surf.positions += (np.random.rand((surfNat*3))*0.1).reshape([surfNat,3])
    surf = relax_atoms(surf,
                       tol=fmax,
                       traj_file="model-" + model.name +
                       "-surface-energy-111-" + str(n) + "x" + str(n) +
                       "-reconstruction-relaxed.opt.xyz")
    ase.io.write(sys.stdout, surf, format='extxyz')

    esurf = surf.get_potential_energy()
    print '111 ' + str(n) + 'x' + str(
        n) + ' reconstructed surface cell energy', esurf
    surf_area = np.linalg.norm(np.cross(surf.cell[0, :], surf.cell[1, :]))
    e_form = (esurf - surfNat * ebulk_per_atom) / surf_area - e111
    print '111 ' + str(n) + 'x' + str(
        n) + ' reconstructed surface formation energy', e_form
    return e_form
Esempio n. 6
0
remove_index_f = None
initial.arrays['ind'] = array([i for i in range(len(initial))])
offset_factor = 0.13
for i, offset in zip(indices, offsets):
    ri = initial.positions[remove_index] - (initial.positions[i] +
                                            dot(offset, initial.get_cell()))
    if remove_index_f is None:
        remove_index_f = i
    print "initial offset ", i, offset_factor, ri
    initial.positions[i] += offset_factor * ri
    offset_factor += 0.01

del initial[remove_index]
initial.set_calculator(model.calculator)

initial = relax_atoms(initial, tol=tol, traj_file=None)
#initial = ase.io.read(os.path.join("initial-relax", "castep.castep"))
initial.set_calculator(model.calculator)

print 'initial energy', initial.get_potential_energy()
e_form = initial.get_potential_energy(
) - e_bulk_per_atom * initial.get_number_of_atoms()
print 'vacancy formation energy', e_form

# make final
final = bulk.copy()

nl = NeighborList([a0 * sqrt(3.0) / 4 * 0.6] * len(final),
                  self_interaction=False,
                  bothways=True)
nl.update(final)