def neb_analysis(cl, show, up=None, push2archive=None, old_behaviour=None, results_dic=None, fitplot_args=None, style_dic=None, params=None): """ Analyse traectories and polarons params mep_shift_vector """ def determing_rms_for_surrounding_atoms(sts): # change of rms on each step compared to first structure #here first and last structures should correspond to first and last images st1 = sts[0] st_interp = interpolate(sts[0], sts[-1], 1)[0] rms_list = [] for st in sts: rms = rms_pos_diff(st_interp, st) rms_list.append(rms) print('rms is {:.3f}'.format(rms)) print('d rms is {:.3f}'.format(abs(rms_list[3] - rms_list[0]))) rms_change = abs(min(rms_list) - max(rms_list)) return rms_change def determing_born_barrier(sts): #here first and last structures should correspond to first and last images local_born_e = [] i = find_moving_atom(sts[0], sts[-1]) for st in sts: local_born_e.append(site_repulsive_e(st, i)) # import matplotlib.pyplot as plt # plt.plot(local_born_e) # plt.show() return abs(min(local_born_e) - max(local_born_e)) if params is None: params = {} if results_dic is None: results_dic = {} calc = header.calc path2mep_s = cl.project_path_cluster + '/' + cl.dir + '/mep.eps' itise = cl.id[0] + '.' + cl.id[1] # print(cl.ldauu) # sys.exit() name_without_ext = 'mep.' + itise + '.U' + str(max(cl.ldauu)) path2mep_l = cl.dir + name_without_ext + '.eps' # print(path2mep_l) if not os.path.exists(path2mep_l) or '2' in up: '' get_from_server( files=path2mep_s, to_file=path2mep_l, addr=cl.cluster_address, ) movie_to = cl.dir + '/movie.xyz' get_from_server( files=cl.project_path_cluster + '/' + cl.dir + '/movie.xyz', to_file=movie_to, addr=cl.cluster_address, ) if os.path.exists(movie_to): makedir('figs/' + name_without_ext + '.xyz') shutil.copyfile(movie_to, 'figs/' + name_without_ext + '.xyz') # trying to get one image closest to the saddle point if old_behaviour and cl.version == 2: #old behaviour, now created automatically in add callc im = cl.set.vasp_params['IMAGES'] # if im % 2 > 0: #odd # i = im//2 + 1 # else: # i = im/2 # if choose_image: # i = choose_image for i in range(im): i += 1 cl_i = copy.deepcopy(cl) cl_i.version += i cl_i.id = (cl.id[0], cl.id[1], cl_i.version) cl_i.name = str(cl_i.id[0]) + '.' + str(cl_i.id[1]) + '.' + str( cl_i.id[2]) # print cl_i.name cl_i.path["output"] = cl_i.dir + '0' + str(i) + "/OUTCAR" # for i in range(): cl_i.associated_outcars = [ aso[2:] for aso in cl_i.associated_outcars ] # print cl_i.path["output"] cl_i.state = '2. Ready to read outcar' # if not os.path.exists(cl_i.path["output"]): # load = 'o' outst2 = ("%s" % cl_i.name).ljust(name_field_length) if readfiles: print(outst2 + '|' + cl_i.read_results( loadflag, show=show, choose_outcar=choose_outcar)) else: print_and_log(outst2 + ' | File was not read') if cl_i.id in calc: #move creation of calcs with images to add_neb '' # print_and_log('Please test code below this message to save prev calcs') # if cl_i != calc[cl_i.id] # if hasattr(calc[cl_i.id], 'prev') and calc[cl_i.id].prev: # prevlist = calc[cl_i.id].prev # else: # prevlist = [calc[cl_i.id]] # cl_i.prev = prevlist # calc[cl_i.id] = cl_i else: calc[cl_i.id] = cl_i # print path2mep_l if 0: if os.path.exists(path2mep_l): # get_from_server(file = path2mep_s, to = path2mep_l, addr = cluster_address) runBash('evince ' + path2mep_l) else: a = glob.glob(cl.dir + '*mep*') if a: runBash('evince ' + a[0]) cl1 = calc[cl.id[0], cl.id[1], 1] cl2 = calc[cl.id[0], cl.id[1], 2] atom_num = find_moving_atom(cl1.end, cl2.end) # cl1.poscar() # cl2.poscar() # print('atom_num',atom_num) # sys.exit() #prepare lists ni = cl.set.vasp_params['IMAGES'] vlist = [1] + list(range(3, ni + 3)) + [2] # print( vlist) mep_energies = [] atom_pos = [] pols = [] sts = [] sts_loc = [] dAO2 = [] # A-(O,F) distance for each image dAO4 = [] # A-(O,F) distance for each image dAO6 = [] dAO6harm = [] dAO6dev = [] for v in vlist: cli = calc[cl.id[0], cl.id[1], v] # if v == 1: # cli = db['NaVP2O7_a.su.s101015v100.n5Na1v1ms.ifn.1mls.1'] # print(cl.id[0], cl.id[1], v, cli.state) if '4' not in cli.state and 'un' not in up: printlog('Attention! res_loop(): analys_type == neb, Calc', cli.id, 'is not finished; return') return {}, [] # print cli.id # cli.end = return_to_cell(cli.end) # mep_energies.append( min(cli.list_e_sigma0) ) #use minimum energy - not very good, sometimes unconverged energy could be lower! e0 = cli.energy_sigma0 if params and params.get( 'neb_penult_e' ): # allows to take e from the previous relaxation step in case the calculation was aborted e0 = cli.list_e_sigma0[-2] mep_energies.append(e0) #use last energy atom_pos.append(cli.end.xcart[atom_num]) # Find polaron positions if 'polaron' in show: # if 1 cause error for nomag calc pol, mag = find_polaron(cli.end, atom_num) if pol: for key in pol: if np.any(pol[key]): for n in pol[key]: if n not in pols: pols.append(n) else: '' # print('Mag_moments on trans,', mag.round(1)) if 0 or 'neb_geo' in show: #visualization of path # print(atom_num) st = copy.deepcopy(cli.end) # print('moving_atom', st.xcart[atom_num]) info = st.nn(atom_num, 15, from_one=False, silent=1) st.moving_atom_i = atom_num st_loc = info['st'] # print(st_loc.xcart) # st_loc = st_loc.shift if v == vlist[0]: st1 = copy.deepcopy(st) vec = st.center_on(atom_num) # vec = np.asarray([0.,0.,0.]) if params is not None and 'mep_shift_vector' in params: # vec += np.array([0.11,0.11,0]) # path4 # print(params['mep_shift_vector']) vec += np.array(params['mep_shift_vector']) # path4 # print(vec) st_loc = st_loc.shift_atoms(vec) if 0: st_loc.write_xyz() # st.write_cif('xyz/'+st.name) if 0: st.shift_atoms(vec).write_xyz() sts_loc.append(st_loc) st1 = st1.add_atom(st.xred[atom_num], 'Rb') sts.append(st.shift_atoms(vec)) if 0 or 'neb_geo2' in show: printlog('\n\nVersion {:}:'.format(v), imp='y') info1 = st.nn(atom_num, 2, from_one=False, silent=1, more_info=1) print('Av. dist A-2(O,F) {:.3f} A'.format( info1['av(A-O,F)'])) # print('Av. squared dist A-2(O,F) {:.3f} A'.format(info1['avsq(A-O,F)'])) dAO2.append(info1['av(A-O,F)']) info12 = st.nn(atom_num, 3, from_one=False, silent=1) print('Average distance A-3(O,F) {:.2f} A'.format( info12['av(A-O,F)'])) info2 = st.nn(atom_num, 4, from_one=False, silent=1) print('Average distance A-4(O,F) {:.2f} A'.format( info2['av(A-O,F)'])) dAO4.append(info2['av(A-O,F)']) info3 = st.nn(atom_num, 6, from_one=False, silent=1, more_info=1) print('Average_distance A-6(O,F) {:.2f} A '.format( info3['av(A-O,F)'])) print('Av. harm. dist A-6(O,F) {:.2f} A'.format( info3['avharm(A-O,F)'])) print('Average_deviation A-6(O,F) {:.1f} mA'.format( info3['avdev(A-O,F)'])) dAO6.append(info3['av(A-O,F)']) dAO6dev.append(info3['avdev(A-O,F)']) dAO6harm.append(info3['avharm(A-O,F)']) if 'neb_rms' in show: rms_change = determing_rms_for_surrounding_atoms(sts) results_dic['rms_change'] = rms_change if 'neb_born' in show: results_dic['born_barrier'] = determing_born_barrier(sts) print('Born barrier is {:.2f} eV '.format(results_dic['born_barrier'])) # print(results_dic['rms_change']) # print('show is', show) # sys.exit() # print('flag ', 'neb_noxyz' not in show, show) if 'neb_noxyz' not in show and sts: write_xyz(sts=sts) # write traectory write_xyz(sts=sts_loc) # write traectory if 'jmol' in params: write_xyz(sts=sts, jmol=1, jmol_args=params['jmol']) # write jmol st1 = st1.shift_atoms(vec) st1.name += '_all' # st1.write_cif('xyz/'+st1.name) st1.write_xyz() if dAO2: # find maximum change of distance during migration dAO2_change = abs(min(dAO2) - max(dAO2)) results_dic['dAO2_change'] = dAO2_change if dAO4: # find maximum change of distance during migration dAO4_change = abs(min(dAO4) - max(dAO4)) results_dic['dAO4_change'] = dAO4_change if dAO6: # dAO6_change = abs(min(dAO6) - max(dAO6)) results_dic['dAO6_change'] = dAO6_change if dAO6harm: # results_dic['dAO6harm_change'] = abs(min(dAO6harm) - max(dAO6harm)) if dAO6dev: # results_dic['dAO6dev_change'] = abs(min(dAO6dev) - max(dAO6dev)) results_dic[ 'sts_loc'] = sts_loc # list of local structures, each structure contains dlist - distances from central cation to anions, and ellist - types of elements results_dic[ 'sts'] = sts # list of mep structures, each structure contains moving_atom_i - number of moving atom if len(pols) > 0: print( 'During migration of alkali ions polarons are detected on atoms:', pols) elif len(pols) > 1: printlog( 'Attention! polaron is moving during migration! Obtained barrier is ambiguous' ) else: printlog( 'Compare magnetic moments above! In principle should be the same!') # print np.array(atom_pos) #test if the distances between points are not spoiled by PBC nbc = range(-1, 2) jj = 0 for x in atom_pos: x2 = atom_pos[jj + 1] # x = np.array(x) # x2 = np.array(x2) r = cl.end.rprimd d1, _ = image_distance(x, x2, r, order=1) #minimal distance x2_gen = (x2 + (r[0] * i + r[1] * j + r[2] * k) for i in nbc for j in nbc for k in nbc) #generator over PBC images x2c = copy.deepcopy(x2) ii = 0 while np.linalg.norm(x - x2c) > d1: #find the closest PBC image position if ii > 100: break ii += 1 x2c = next(x2_gen) atom_pos[jj + 1] = x2c jj += 1 if jj == len( atom_pos ) - 1: # the last point is not needed, we could not use slice since we need to use changed atom_pos in place break # print np.linalg.norm(x - x2c), d1 _, diff_barrier = plot_mep(atom_pos, mep_energies, plot=0, show=0, fitplot_args=fitplot_args, style_dic=style_dic) results_dic['barrier'] = diff_barrier middle_image = len(vlist) // 2 results_dic['dEm1'] = mep_energies[middle_image] - mep_energies[0] cl1.barrier = diff_barrier cl2.barrier = diff_barrier results_dic['atom_pos'] = [list(pos) for pos in atom_pos] results_dic['mep_energies'] = mep_energies if 'mep' in show: if 'mepp' in show: show_flag = True else: show_flag = False # sys.exit() plot_mep(atom_pos, mep_energies, image_name='figs/' + name_without_ext + '_my.eps', show=show_flag, fitplot_args=fitplot_args, style_dic=style_dic) if push2archive: path2saved, _ = plot_mep(atom_pos, mep_energies, image_name='figs/' + name_without_ext + '_my', fitplot_args=fitplot_args, style_dic=style_dic) push_figure_to_archive(local_figure_path=path2saved, caption=description_for_archive) if 0: #copy files according to chosen outcar to run nebresults locally wd = cl_i.dir out_i = cl_i.associated_outcars[choose_outcar - 1] out_1 = calc[cl.id[0], cl.id[1], 1].associated_outcars[choose_outcar - 1] out_2 = calc[cl.id[0], cl.id[1], 2].associated_outcars[choose_outcar - 1] # print out_1 # print out_2 shutil.copyfile(wd + out_1, wd + '00/OUTCAR') shutil.copyfile(wd + out_2, wd + '04/OUTCAR') for d in ['01/', '02/', '03/']: shutil.copyfile(wd + d + out_i, wd + d + 'OUTCAR') # print wd+d+out_i return results_dic
def fit_a(conv, n, description_for_archive, analysis_type, show, push2archive): """Fit equation of state for bulk systems. The following equation is used:: sjeos (default) A third order inverse polynomial fit 10.1103/PhysRevB.67.026103 2 3 -1/3 E(V) = c + c t + c t + c t , t = V 0 1 2 3 taylor A third order Taylor series expansion about the minimum volume murnaghan PRB 28, 5480 (1983) birch Intermetallic compounds: Principles and Practice, Vol I: Principles. pages 195-210 birchmurnaghan PRB 70, 224107 pouriertarantola PRB 70, 224107 vinet PRB 70, 224107 antonschmidt Intermetallics 11, 23-32 (2003) p3 A third order polynomial fit Use:: eos = EquationOfState(volumes, energies, eos='sjeos') v0, e0, B = eos.fit() eos.plot() """ # e, v, emin, vmin = plot_conv( conv[n], calc, "fit_gb_volume2") alist = [] vlist = [] etotlist = [] magn1 = [] magn2 = [] alphas = [] for id in conv[n]: cl = db[id] st = cl.end alist.append(cl.end.rprimd[0][0]) etotlist.append(cl.energy_sigma0) vlist.append(cl.end.vol) magn1.append(cl.magn1) magn2.append(cl.magn2) alpha, beta, gamma = st.get_angles() alphas.append(alpha) print('alpha, energy: {:4.2f}, {:6.3f}'.format(alpha, cl.energy_sigma0)) fit_and_plot(U1=(alphas, etotlist, 'o-r'), image_name='figs/angle', ylabel='Total energy, eV', xlabel='Angle, deg', xlim=(89, 92.6)) if ase_flag: if 'angle' in analysis_type: eos = EquationOfState(alphas, etotlist, eos='sjeos') else: eos = EquationOfState(vlist, etotlist, eos='sjeos') # import inspect # print (inspect.getfile(EquationOfState)) v0, e0, B = eos.fit() #print "c = ", clist[2] printlog(''' v0 = {0} A^3 a0 = {1} A E0 = {2} eV B = {3} eV/A^3'''.format(v0, v0**(1. / 3), e0, B), imp='Y') savedpath = 'figs/' + cl.name + '.png' makedir(savedpath) cl.B = B * 160.218 # plt.close() # plt.clf() # plt.close('all') if 'fit' in show: mpl.rcParams.update({'font.size': 14}) eos.plot(savedpath, show=True) printlog('fit results are saved in ', savedpath, imp='y') else: printlog('To use fitting install ase: pip install ase') # plt.clf() if push2archive: push_figure_to_archive(local_figure_path=savedpath, caption=description_for_archive) return