def _setup_images_global(): N_intermediate = 3 N_cell = 2 initial = bulk('Cu', cubic=True) initial *= N_cell # place vacancy near centre of cell D, D_len = get_distances(np.diag(initial.cell) / 2, initial.positions, initial.cell, initial.pbc) vac_index = D_len.argmin() vac_pos = initial.positions[vac_index] del initial[vac_index] # identify two opposing nearest neighbours of the vacancy D, D_len = get_distances(vac_pos, initial.positions, initial.cell, initial.pbc) D = D[0, :] D_len = D_len[0, :] nn_mask = np.abs(D_len - D_len.min()) < 1e-8 i1 = nn_mask.nonzero()[0][0] i2 = ((D + D[i1])**2).sum(axis=1).argmin() print(f'vac_index={vac_index} i1={i1} i2={i2} ' f'distance={initial.get_distance(i1, i2, mic=True)}') final = initial.copy() final.positions[i1] = vac_pos initial.calc = calc() final.calc = calc() qn = ODE12r(initial) qn.run(fmax=1e-3) qn = ODE12r(final) qn.run(fmax=1e-3) images = [initial] for image in range(N_intermediate): image = initial.copy() image.calc = calc() images.append(image) images.append(final) neb = NEB(images) neb.interpolate() return neb.images, i1, i2
def _ref_vacancy_global(_setup_images_global): # use distance from moving atom to one of its neighbours as reaction coord # relax intermediate image to the saddle point using a bondlength constraint images, i1, i2 = _setup_images_global initial, saddle, final = (images[0].copy(), images[2].copy(), images[4].copy()) initial.calc = calc() saddle.calc = calc() final.calc = calc() saddle.set_constraint(FixBondLength(i1, i2)) opt = ODE12r(saddle) opt.run(fmax=1e-2) nebtools = NEBTools([initial, saddle, final]) Ef_ref, dE_ref = nebtools.get_barrier(fit=False) print('REF:', Ef_ref, dE_ref) return Ef_ref, dE_ref, saddle