def read_cohp(self, ): """read COHP anlysis results """ from ase.calculators.vasp import VaspDos dos = VaspDos(os.path.join(self.directory, 'DOSCAR.lobster')) self.dos = dos._total_dos[1] self.dos_energies = dos._total_dos[0] # read COHP results datas = np.genfromtxt(os.path.join(self.directory, 'COHPCAR.lobster'), skip_header=3 + len(self.indexs)) self.cohp = datas[:, 1] self.cohp_energies = datas[:, 0] # read COOP results datas = np.genfromtxt(os.path.join(self.directory, 'COOPCAR.lobster'), skip_header=3 + len(self.indexs)) self.coop = datas[:, 1] self.coop_energies = datas[:, 0] # read COBI results datas = np.genfromtxt(os.path.join(self.directory, 'COBICAR.lobster'), skip_header=3 + len(self.indexs)) self.cobi = datas[:, 1] self.cobi_energies = datas[:, 0]
def plot_dos( cl1, cl2=None, dostype=None, iatom=None, iatom2=None, orbitals=('s'), up=None, neighbors=6, show=1, labels=None, path='dos', xlim=(None, None), ylim=(None, None), savefile=True, plot_param={}, suf2='', fontsize=8, nsmooth=12, lts2='--', split_type='octa', plot_spin_pol=1, show_gravity=None, ): """ cl1 (CalculationVasp) - object created by add_loop() dostype (str) - control which dos to plot: 'total' - plot total dos 'diff_total' - difference of total dos, use cl2 for second calculation 'partial' - partial dos orbitals (list of str) - any from 's, p, d, py, pz, px, dxy, dyz, dz2, dxz, dx2' where 'p' and 'd' are sums of projections also to sum around neigbours use p6 and d6 and neighbors parameter up - 'up2' allows to download the file once again labels - two manual labels for cl1 and cl2 instead of auto iatom (int) - number of atom starting from 1 to plot DOS; iatom ([float]*3) - cartesian coordinates of point around which atoms will be found show (bool) - whether to show the dos path (str) - path to folder with images neighbors - number of neighbours around iatom to plot dos on them using p6 or d6; only p6 is implemented to the moment in plot section xlim, ylim (tuple)- limits for plot plot_param - dict of parameters to fit_and_plot dashes - control of dahsed lines suf2 - additional suffix # nsmooth = 15 # smooth of dos lts2 - style of lines for cl2 split_type - octa - the names are t2g and eg tetra - the names are t2 and e plot_spin_pol - 0 - spin-polarized components are summed up show_gravity (list) - print gravity centers (i, type, range, ); i - 1 or 2 cl type (str) 'p6' - for p orbitals of neighbors 'p' #0 s 1 py 2 pz 3 px 4 dxy 5 dyz 6 dz2 7 dxz 8 dx2 #In all cases, the units of the l- and site projected DOS are states/atom/energy. """ if fontsize: header.mpl.rcParams.update({'font.size': fontsize + 4}) header.mpl.rc('legend', fontsize=fontsize) if dostype == 'partial': eld1, eld2 = {}, {} for i, el in enumerate(cl1.end.get_elements()): eld1[i + 1] = el if cl2: for i, el in enumerate(cl2.end.get_elements()): eld2[i + 1] = el if not iatom: printlog( 'Warning! Please choose atom number *iatom* from the following list:\n' ) printlog(eld) sys.exit() else: printlog('cl1: Atom', iatom, 'of type', eld1[iatom], 'is choosen', imp='y') printlog('cl1: Atom numbers:', eld1, imp='y') printlog('cl1:', determine_symmetry_positions(cl1.end, eld1[iatom]), imp='y') # print(cl2) if cl2: if not iatom2: printlog('Error! provide iatom2!') printlog('cl2: Atom', iatom2, 'of type', eld2[iatom2], 'is choosen', imp='y') printlog('cl2:', determine_symmetry_positions(cl2.end, eld2[iatom2]), imp='y') iatom -= 1 if cl2: if not iatom2: printlog('Error!, provide *iatom2*!') iatom2 -= 1 if 'figsize' not in plot_param: plot_param['figsize'] = (4, 6) if 'legend' not in plot_param: plot_param['legend'] = 'best' """1. Read dos""" printlog("------Start plot_dos()-----", imp='Y') dos = [] # main list for cl1 and cl2 for cl in cl1, cl2: if cl == None: continue if not hasattr(cl, "efermi"): cl.read_results('o') printlog(cl.name, 'e_fermi', cl.efermi, imp='Y') DOSCAR = cl.get_file('DOSCAR', nametype='asoutcar') printlog('DOSCAR file is ', DOSCAR) dos.append(VaspDos(DOSCAR, cl.efermi)) #determine number of zero energy i_efermi = int( len(dos[0].energy) * -dos[0].energy[0] / (dos[0].energy[-1] - dos[0].energy[0])) # number of point with zero fermi energy if cl2: i_efermi_e = int( len(dos[1].energy) * -dos[1].energy[0] / (dos[1].energy[-1] - dos[1].energy[0])) # number of point with zero fermi energy if len(dos[0].dos) == 2: spin_pol = True else: spin_pol = False """2. Plot dos for different cases""" if dostype == 'total': # print(dos[0].dos) ylabel = "DOS (states/eV)" if spin_pol: dosplot = { 'Tot up': { 'x': dos[0].energy, 'y': smoother(dos[0].dos[0], 10), 'c': 'b', 'ls': '-' }, 'Tot down': { 'x': dos[0].energy, 'y': -smoother(dos[0].dos[1], 10), 'c': 'r', 'ls': '-' } } else: dosplot = { 'Total': { 'x': dos[0].energy, 'y': smoother(dos[0].dos, 10), 'c': 'b', 'ls': '-' } } # args[nam_down] = {'x':d.energy, 'y':-smoother(d.site_dos(iat, i_orb_down[orb]), nsmooth), 'c':color[orb], 'ls':l, 'label':None} # xlabel = "Energy (eV)", ylabel = "DOS (states/eV)" # print(plot_param) image_name = os.path.join(path, cl1.name + '.dosTotal') fit_and_plot(show=show, image_name=image_name, hor=True, **plot_param, **dosplot) elif dostype == 'diff_total': #no spin-polarized!!!! ylabel = "DOS (states/eV)" if len(dos) > 1: #calculate dos diff dosd = [(d0 - d1) * e for d0, d1, e in zip(dos[0].dos, dos[1].dos, dos[0].energy) ] #calculate difference area = trapz(dosd[:i_efermi], dx=1) printlog("area under dos difference = ", -area, imp='Y') fit_and_plot(show=show, image_name=cl1.name + '--' + cl2.name + '.dosTotal_Diff', xlabel="Energy (eV)", ylabel="DOS (states/eV)", hor=True, **plot_param, Diff_Total=(dos[0].energy, smoother(dosd, 15), 'b-')) else: printlog( 'You provided only one calculation; could not use diff_total') elif 'partial' in dostype: #Partial dos #1 p carbon, d Ti #0 s 1 py 2 pz 3 px 4 dxy 5 dyz 6 dz2 7 dxz 8 dx2 ylabel = "PDOS (states/atom/eV)" try: dos[0].site_dos(0, 4) except: printlog( 'Error! No information about partial dxy dos in DOSCAR; use LORBIT 12 to calculate it' ) """Determine neighbouring atoms """ # printlog("Number of considered neighbors is ", neighbors, imp = 'y') if type( iatom ) == int: #for the cases when we need to build surrounding around specific atom in this calculation - just use number of atom t = cl1.end.typat[iatom] z = cl1.end.znucl[t - 1] el = element_name_inv(z) printlog('Typat of chosen imp atom in cl1 is ', el, imp='y') surround_center = cl1.end.xcart[iatom] else: #for the case when coordinates of arbitary point are provided. surround_center = iatom el = 'undef' local_atoms = local_surrounding(surround_center, cl1.end, neighbors, control='atoms', periodic=True) numbers = local_atoms[2] els = cl1.end.get_elements() el_sur = els[numbers[1]] # element of surrounding type printlog("Numbers of local atoms:", [n + 1 for n in numbers], imp='Y') printlog("Elements of local atoms:", [els[i] for i in numbers], imp='Y') printlog("List of distances", [round(d, 2) for d in local_atoms[3]], imp='Y') iX = numbers[0] # first atom is impurity if exist # printlog numbers_list = [numbers] # numbers_list is list of lists calcs = [cl1] if cl2: numbers_list.append([iatom2]) # for cl2 only one atom is supported calcs.append(cl2) for cl, d, numbers in zip(calcs, dos, numbers_list): d.p = [] #central and surrounding d.d = [] d.p_up = [] d.p_down = [] d.p_down = [] #central and and surrounding d.d_up = [] #central atom and surrounding atoms d.d_down = [] #central atom and surrounding atoms d.t2g_up = [] d.t2g_down = [] d.eg_up = [] d.eg_down = [] d.p_all = [] #sum over all atoms d.d_all = [] #sum over all atoms d.p_all_up = [] #sum over all atoms d.d_all_up = [] #sum over all atoms d.p_all_down = [] #sum over all atoms d.d_all_down = [] #sum over all atoms if 'p_all' in orbitals or 'd_all' in orbitals: #sum over all atoms p = [] p_up = [] p_down = [] dd = [] d_up = [] d_down = [] els = cl.end.get_elements() for i in range(cl.end.natom): # if 'O' not in els[i]: # continue if spin_pol: plist_up = [d.site_dos(i, l) for l in (2, 4, 6)] plist_down = [d.site_dos(i, l) for l in (3, 5, 7)] plist = plist_up + plist_down p_up.append([sum(x) for x in zip(*plist_up)]) p_down.append([sum(x) for x in zip(*plist_down)]) p.append([sum(x) for x in zip(*plist)]) else: plist = [d.site_dos(i, l) for l in (1, 2, 3)] p.append([sum(x) for x in zip(*plist)]) if spin_pol: dlist_up = [ d.site_dos(i, l) for l in (8, 10, 12, 14, 16) ] # dlist_down = [ d.site_dos(i, l) for l in (9, 11, 13, 15, 17) ] # dlist = dlist_up + dlist_down d_up.append([sum(x) for x in zip(*dlist_up)]) d_down.append([sum(x) for x in zip(*dlist_down)]) dd.append([sum(x) for x in zip(*dlist)]) else: dlist = [d.site_dos(i, l) for l in (4, 5, 6, 7, 8)] # dd.append([sum(x) for x in zip(*dlist)]) d.p_all = [sum(pi) for pi in zip(*p)] #sum over all atoms d.d_all = [sum(di) for di in zip(*dd)] if spin_pol: d.p_all_up = [sum(pi) for pi in zip(*p_up)] d.p_all_down = [sum(pi) for pi in zip(*p_down)] d.d_all_up = [sum(pi) for pi in zip(*d_up)] d.d_all_down = [sum(pi) for pi in zip(*d_down)] #sum by surrounding atoms atoms n_sur = len(numbers) for i in numbers: #Now for surrounding atoms in numbers list: if spin_pol: plist_up = [d.site_dos(i, l) for l in (2, 4, 6)] plist_down = [d.site_dos(i, l) for l in (3, 5, 7)] d.p_up.append([sum(x) for x in zip(*plist_up)]) d.p_down.append([sum(x) for x in zip(*plist_down)]) plist = plist_up + plist_down d.p.append([sum(x) for x in zip(*plist)]) else: plist = [d.site_dos(i, l) for l in (1, 2, 3)] d.p.append([sum(x) for x in zip(*plist)]) if spin_pol: dlist_up = [d.site_dos(i, l) for l in (8, 10, 12, 14, 16)] # dlist_down = [ d.site_dos(i, l) for l in (9, 11, 13, 15, 17) ] # dlist = dlist_up + dlist_down d.d.append([sum(x) for x in zip(*dlist)]) d.d_up.append([sum(x) for x in zip(*dlist_up)]) d.d_down.append([sum(x) for x in zip(*dlist_down)]) t2g_down = [d.site_dos(i, l) for l in (9, 11, 15)] eg_down = [d.site_dos(i, l) for l in (13, 17)] t2g_up = [d.site_dos(i, l) for l in (8, 10, 14)] eg_up = [d.site_dos(i, l) for l in (12, 16)] d.t2g_down.append([sum(x) for x in zip(*t2g_down)]) d.eg_down.append([sum(x) for x in zip(*eg_down)]) d.t2g_up.append([sum(x) for x in zip(*t2g_up)]) d.eg_up.append([sum(x) for x in zip(*eg_up)]) else: dlist = [d.site_dos(i, l) for l in (4, 5, 6, 7, 8)] # d.d.append([sum(x) for x in zip(*dlist)]) d.p6 = [sum(pi) / n_sur for pi in zip(*d.p) ] #sum over neighbouring atoms now only for spin up if spin_pol: d.p6_up = [sum(pi) / n_sur for pi in zip(*d.p_up) ] #sum over neighbouring atoms now only for spin up d.p6_down = [ sum(pi) / n_sur for pi in zip(*d.p_down) ] #sum over neighbouring atoms now only for spin up d.d6 = [sum(di) for di in zip(*d.d)] #sum over neighbouring atoms """Plotting""" # nsmooth = 15 # smooth of dos d1 = dos[0] ds = [d1] names = [] names = [cl1.id[0] + '_at_' + eld1[iatom + 1] + str(iatom + 1)] atoms = [iatom] els = [eld1[iatom + 1]] lts = [ '-', ] #linetypes if cl2: ds.append(dos[1]) d2 = dos[1] # if labels: # names.append(labels[1]) # else: names.append(cl2.id[0] + '_at_' + eld2[iatom2 + 1] + str(iatom2 + 1)) lts.append(lts2) atoms.append(iatom2) els.append(eld2[iatom2 + 1]) if not spin_pol: plot_spin_pol = 0 # could not plot spin polarization for non-spin polarization plot if 'dashes' in plot_param: dashes = plot_param['dashes'] del plot_param['dashes'] else: dashes = (5, 1) energy1 = dos[0].energy args = {} if spin_pol: i_orb = { 's': 0, 'py': 2, 'pz': 4, 'px': 6, 'dxy': 8, 'dyz': 10, 'dz2': 12, 'dxz': 14, 'dx2': 16 } i_orb_down = { 's': 1, 'py': 3, 'pz': 5, 'px': 7, 'dxy': 9, 'dyz': 11, 'dz2': 13, 'dxz': 15, 'dx2': 17 } else: i_orb = { 's': 0, 'py': 1, 'pz': 2, 'px': 3, 'dxy': 4, 'dyz': 5, 'dz2': 6, 'dxz': 7, 'dx2': 8 } # color = {'s':'k', 'p':'#F14343', 'd':'#289191', 'py':'g', 'pz':'b', 'px':'c', 'dxy':'m', 'dyz':'c', 'dz2':'k', 'dxz':'r', 'dx2':'g', 't2g':'b', 'eg':'g', 'p6':'k'} color = { 's': 'k', 'p': '#FF0018', 'd': '#138BFF', 'py': 'g', 'pz': 'b', 'px': 'c', 'dxy': 'm', 'dyz': 'c', 'dz2': 'k', 'dxz': 'r', 'dx2': 'g', 't2g': '#138BFF', 'eg': '#8E12FF', 'p6': '#FF0018', 'p_all': 'r', 'd_all': 'b' } #http://paletton.com/#uid=54-100kwi++bu++hX++++rd++kX # color = {'s':'k', 'p':'r', 'd':'g', 'py':'g', 'pz':'b', 'px':'c', 'dxy':'m', 'dyz':'c', 'dz2':'m', 'dxz':'r', 'dx2':'g'} for orb in orbitals: i = 0 for n, l, iat, el, d in zip(names, lts, atoms, els, ds): if el in ['Fe', 'Co', 'V', 'Mn'] and orb in ['p', 's']: continue if el == 'O' and orb in ('d', 't2g', 'eg', 'dxy', 'dyz', 'dxz', 'dz2', 'dx2'): continue nam = orb nam_down = nam + '_down' # print('name', n) # print('lts', l) if labels: formula = labels[i] else: formula = latex_chem(n.split('.')[0]) i += 1 if spin_pol: nam += '' suf = '; ' + n nam += suf nam_down += suf if orb == 'p': if plot_spin_pol: args[nam] = { 'x': d.energy, 'y': smoother(d.p_up[0], nsmooth), 'c': color[orb], 'ls': l, 'label': formula + ' ' + el + suf2 + ' ' + orb, 'dashes': dashes } args[nam_down] = { 'x': d.energy, 'y': -smoother(d.p_down[0], nsmooth), 'c': color[orb], 'ls': l, 'label': None, 'dashes': dashes } color[orb] = 'c' else: args[nam] = { 'x': d.energy, 'y': smoother(d.p[0], nsmooth), 'c': color[orb], 'ls': l, 'label': formula + ' ' + el + suf2 + ' ' + orb, 'dashes': dashes } elif orb == 'p6': # now spin-polarized components could not be shown if plot_spin_pol: args[nam] = { 'x': d.energy, 'y': smoother(d.p6_up, nsmooth), 'c': color[orb], 'ls': l, 'label': formula + ' ' + el_sur + suf2 + ' p', 'dashes': dashes } args[nam_down] = { 'x': d.energy, 'y': -smoother(d.p6_down, nsmooth), 'c': color[orb], 'ls': l, 'label': None, 'dashes': dashes } else: args[nam] = { 'x': d.energy, 'y': smoother(d.p6, nsmooth), 'c': color[orb], 'ls': l, 'label': formula + ' ' + el_sur + suf2 + ' p', 'dashes': dashes } elif orb == 'd': if plot_spin_pol: args[nam] = { 'x': d.energy, 'y': smoother(d.d_up[0], nsmooth), 'c': color[orb], 'ls': l, 'label': formula + ' ' + el + suf2 + ' ' + orb } args[nam_down] = { 'x': d.energy, 'y': -smoother(d.d_down[0], nsmooth), 'c': color[orb], 'ls': l, 'label': None } color[orb] = 'm' else: args[nam] = { 'x': d.energy, 'y': smoother(d.d[0], nsmooth), 'c': color[orb], 'ls': l, 'label': formula + ' ' + el + suf2 + ' ' + orb } elif orb == 't2g': if split_type == 'octa': orb_name = orb elif split_type == 'tetra': orb_name = 't2' args[nam] = { 'x': d.energy, 'y': smoother(d.t2g_up[0], nsmooth), 'c': color[orb], 'ls': l, 'label': formula + ' ' + el + suf2 + ' ' + orb_name } if spin_pol: args[nam_down] = { 'x': d.energy, 'y': -smoother(d.t2g_down[0], nsmooth), 'c': color[orb], 'ls': l, 'label': None } elif orb == 'eg': if split_type == 'octa': orb_name = orb elif split_type == 'tetra': orb_name = 'e' args[nam] = { 'x': d.energy, 'y': smoother(d.eg_up[0], nsmooth), 'c': color[orb], 'ls': l, 'label': formula + ' ' + el + suf2 + ' ' + orb_name } if spin_pol: args[nam_down] = { 'x': d.energy, 'y': -smoother(d.eg_down[0], nsmooth), 'c': color[orb], 'ls': l, 'label': None } elif orb == 'p_all': if plot_spin_pol: args[nam] = { 'x': d.energy, 'y': smoother(d.p_all_up, nsmooth), 'c': color[orb], 'ls': l, 'label': formula + ' ' + el + suf2 + ' ' + orb } args[nam_down] = { 'x': d.energy, 'y': -smoother(d.p_all_down, nsmooth), 'c': color[orb], 'ls': l, 'label': None } # color[orb] = 'm' else: args[nam] = { 'x': d.energy, 'y': smoother(d.p_all, nsmooth), 'c': color[orb], 'ls': l, 'label': formula + ' ' + el + suf2 + ' ' + orb } elif orb == 'd_all': if plot_spin_pol: args[nam] = { 'x': d.energy, 'y': smoother(d.d_all_up, nsmooth), 'c': color[orb], 'ls': l, 'label': formula + ' ' + el + suf2 + ' ' + orb } args[nam_down] = { 'x': d.energy, 'y': -smoother(d.d_all_down, nsmooth), 'c': color[orb], 'ls': l, 'label': None } # color[orb] = 'm' else: args[nam] = { 'x': d.energy, 'y': smoother(d.d_all, nsmooth), 'c': color[orb], 'ls': l, 'label': formula + ' ' + el + suf2 + ' ' + orb } else: # args[nam] = (d.energy, smoother(d.site_dos(iat, i_orb[orb]), nsmooth), color[orb]+l) args[nam] = { 'x': d.energy, 'y': smoother(d.site_dos(iat, i_orb[orb]), nsmooth), 'c': color[orb], 'ls': l, 'label': formula + ' ' + el + suf2 + ' ' + orb } if spin_pol: args[nam_down] = { 'x': d.energy, 'y': -smoother(d.site_dos(iat, i_orb_down[orb]), nsmooth), 'c': color[orb], 'ls': l, 'label': None } # args[nam_down] = (d.energy, -smoother(d.site_dos(iat, i_orb_down[orb]), nsmooth), color[orb]+l) """Additional dos analysis; to be refined""" if show_gravity: if show_gravity[0] == 1: d = d1 elif show_gravity[0] == 2: d = d2 if show_gravity[2]: erange = show_gravity[2] else: erange = (-100, 0) if show_gravity[1] == 'p6': gc = det_gravity2(d.energy, d.p6, erange) printlog( 'Gravity center for cl1 for p6 for {:} is {:5.2f}'.format( erange, gc), imp='Y') # gc = det_gravity2(d.energy, d.d[0], erange) # printlog('Gravity center for cl1 for d for {:} is {:5.2f}'.format(erange, gc), imp = 'Y') elif show_gravity[1] == 'p': gc = det_gravity2(d.energy, d.p[0], erange) # for first atom for cl2 elif show_gravity[1] == 'p_all': gc = det_gravity2(d.energy, d.p_all, erange) # for first atom for cl2 printlog('Gravity center for cl1 for p_all for {:} is {:5.2f}'. format(erange, gc), imp='Y') plot_param['ver_lines'] = [{'x': gc, 'c': 'k', 'ls': '--'}] """Plot everything""" image_name = os.path.join( path, '_'.join(names) + '.' + ''.join(orbitals) + '.' + el + str(iat + 1)) if 'xlabel' not in plot_param: plot_param['xlabel'] = "Energy (eV)" if 'ylabel' not in plot_param: plot_param['ylabel'] = ylabel fit_and_plot( show=show, image_name=image_name, hor=True, # title = cl1.name.split('.')[0]+'; V='+str(round(cl1.vol) )+' $\AA^3$; Impurity: '+el, **plot_param, **args) # printlog("Writing file", image_name, imp = 'Y') if 0: """Calculate d DOS at Fermi level""" nn = 50 #number to integrate in both directions x1 = dos[0].energy[i_efermi - nn:i_efermi + nn] y1 = smoother(dos[0].d6, nsmooth)[i_efermi - nn:i_efermi + nn] x2 = dos[1].energy[i_efermi_e - nn:i_efermi_e + nn] y2 = smoother(dos[1].d6, nsmooth)[i_efermi_e - nn:i_efermi_e + nn] f1 = interp1d(x1, y1, kind='cubic') f2 = interp1d(x2, y2, kind='cubic') # if debug: print '\n' # if debug: print dos[0].d6[i_efermi] - dos[1].d6[i_efermi_e], " - by points; change of d Ti DOS at the Fermi level due to the carbon" # if debug: print f2(0), f1(0) e_at_Ef_shift = f1(0) - f2(0) printlog( "{:5.2f} reduction of d dos at Fermi level; smoothed and interpolated" .format(e_at_Ef_shift), imp='Y') if 0: """Calculate second derivative of d at the Fermi level""" # tck1 = interpolate.splrep(x1, y1, s=0) # tck2 = interpolate.splrep(x2, y2, s=0) # e_at_Ef_shift_spline = interpolate.splev(0, tck1, der=0) - interpolate.splev(0, tck2, der=0) # if debug: print "{:5.2f} smoothed and interpolated from spline".format( e_at_Ef_shift_spline ) # # if debug: print type(interpolate.splev(0, tck1, der=2)) # if debug: print "{:5.2f} {:5.2f} gb and bulk second derivative at Fermi from spline".format( float(interpolate.splev(0, tck1, der=2)), float(interpolate.splev(0, tck2, der=2)) ) if 0: """Calculate shift of d orbitals after adding impurity""" d_shift = det_gravity(dos[0], Erange=(-2.8, 0)) - det_gravity( dos[1], Erange=(-2.8, 0) ) #negative means impurity shifts states to negative energies, which is favourable printlog("{:5.2f} Shift of Ti d center of gravity".format(d_shift), imp='Y') # if debug: print det_gravity(dos[0], Erange = (-2.8, 0)), det_gravity(dos[1], Erange = (-2.8, 0)) """Calculate correlation between imp p and matrix d""" def rmsdiff(a, b): # rms difference of vectors a and b: #Root-mean-square deviation rmsdiff = 0 for (x, y) in zip(a, b): rmsdiff += ( x - y)**2 # NOTE: overflow danger if the vectors are long! return math.sqrt(rmsdiff / min(len(a), len(b))) pd_drms = 1 / rmsdiff( dos[0].p, dos[0].d6) # the higher the number the higher hybridization printlog("{:5.2f} p-d hybridization estimate".format(pd_drms), imp='Y') # if debug: print "sqeuclidean", sqeuclidean(dos[0].p, dos[0].d6)/len(dos[0].d6) # if debug: print "pearsonr", pearsonr(dos[0].p, dos[0].d6) #Pearson correlation coefficient; only shape; the larger number means more similarity in shape # def autocorr(x): # result = np.correlate(x, x, mode='full') # return result[result.size/2:] printlog("------End plot_dos()-----\n\n") return {'name': cl1.name, 'filename': image_name}
from step0 import * from numpy import * from ase.dft import DOS from ase.dft import get_distribution_moment from ase.calculators.vasp import VaspDos os.chdir('work-dos') emax, emin, ngrid, efermi = dos_info('DOSCAR') vdos = VaspDos() vdos.read_doscar('DOSCAR') vdos._set_efermi(efermi) e = vdos.energy dos_up = vdos.dos[0] dos_down = vdos.dos[1] dos_total = dos_up + dos_down dos_s_up = np.zeros(len(e)) dos_p_up = np.zeros(len(e)) dos_d_up = np.zeros(len(e)) dos_s_down = np.zeros(len(e)) dos_p_down = np.zeros(len(e)) dos_d_down = np.zeros(len(e)) for i in range(len(atoms)): dos_s_up += vdos.site_dos(i, 's-up') dos_p_up += vdos.site_dos(i, 'px-up') + vdos.site_dos(
b = a / 2. bulk = Atoms([Atom('Pd', (0.0, 0.0, 0.0))], cell=[(0, b, b), (b, 0, b), (b, b, 0)]) with jasp('bulk/pd-ados', encut=300, xc='PBE', lreal=False, rwigs=[1.5], # wigner-seitz radii for ados kpts=(8, 8, 8), atoms=bulk) as calc: # this runs the calculation bulk.get_potential_energy() # now get results ados = VaspDos(efermi=calc.get_fermi_level()) energies = ados.energy # energy is an attribute, not a function dos = ados.site_dos(0, 'd') # this is a function, get d-orbitals on atom 0 # we will select energies in the range of -10, 5 ind = (energies < 5) & (energies > -10) energies = energies[ind] dos = dos[ind] Nstates = np.trapz(dos, energies) occupied = energies <= 0.0 N_occupied_states = np.trapz(dos[occupied], energies[occupied]) # first moment ed = np.trapz(energies * dos, energies) / Nstates # second moment wd2 = np.trapz(energies**2 * dos, energies) / Nstates print 'Total # states = {0:1.2f}'.format(Nstates) print 'number of occupied states = {0:1.2f}'.format(N_occupied_states)
a = 3.9 # approximate lattice constant b = a / 2. bulk = Atoms([Atom('Pd', (0.0, 0.0, 0.0))], cell=[(0, b, b), (b, 0, b), (b, b, 0)]) with jasp( 'bulk/pd-ados', encut=300, xc='PBE', lreal=False, rwigs=[1.5], # wigner-seitz radii for ados kpts=(8, 8, 8), atoms=bulk) as calc: # this runs the calculation bulk.get_potential_energy() # now get results ados = VaspDos(efermi=calc.get_fermi_level()) energies = ados.energy # energy is an attribute, not a function dos = ados.site_dos(0, 'd') # this is a function, get d-orbitals on atom 0 # we will select energies in the range of -10, 5 ind = (energies < 5) & (energies > -10) energies = energies[ind] dos = dos[ind] Nstates = np.trapz(dos, energies) occupied = energies <= 0.0 N_occupied_states = np.trapz(dos[occupied], energies[occupied]) # first moment ed = np.trapz(energies * dos, energies) / Nstates # second moment wd2 = np.trapz(energies**2 * dos, energies) / Nstates print 'Total # states = {0:1.2f}'.format(Nstates) print 'number of occupied states = {0:1.2f}'.format(N_occupied_states)
def calc_to_dict(calc, **kwargs): d = {'doc': '''JSON representation of a VASP calculation. energy is in eV forces are in eV/\AA stress is in GPa (sxx, syy, szz, syz, sxz, sxy) magnetic moments are in Bohr-magneton The density of states is reported with E_f at 0 eV. Volume is reported in \AA^3 Coordinates and cell parameters are reported in \AA If atom-projected dos are included they are in the form: {ados:{energy:data, {atom index: {orbital : dos}}} '''} d['incar'] = {'doc': 'INCAR parameters'} d['incar'].update(dict(filter(lambda item: item[1] is not None, calc.float_params.items()))) d['incar'].update(dict(filter(lambda item: item[1] is not None, calc.exp_params.items()))) d['incar'].update(dict(filter(lambda item: item[1] is not None, calc.string_params.items()))) d['incar'].update(dict(filter(lambda item: item[1] is not None, calc.int_params.items()))) d['incar'].update(dict(filter(lambda item: item[1] is not None, calc.bool_params.items()))) d['incar'].update(dict(filter(lambda item: item[1] is not None, calc.list_params.items()))) d['incar'].update(dict(filter(lambda item: item[1] is not None, calc.dict_params.items()))) d['input'] = calc.input_params d['potcar'] = calc.get_pseudopotentials() d['atoms'] = atoms_to_dict(calc.get_atoms()) d['data'] = {'doc': 'Data from the output of the calculation'} atoms = calc.get_atoms() d['data']['total_energy'] = atoms.get_potential_energy() d['data']['forces'] = atoms.get_forces().tolist() # There are times when no stress is calculated try: stress = atoms.get_stress() except NotImplementedError: stress = None except AssertionError: stress = None if stress is not None: d['data']['stress'] = atoms.get_stress().tolist() else: d['data']['stress'] = None d['data']['fermi_level'] = calc.get_fermi_level() d['data']['volume'] = atoms.get_volume() if calc.spinpol: d['data']['magmom'] = atoms.get_magnetic_moment() if (calc.int_params.get('lorbit', 0) >= 10 or calc.list_params.get('rwigs', None)): try: d['data']['magmoms'] = atoms.get_magnetic_moments().tolist() except AttributeError: d['data']['magmoms'] = None # store the metadata if hasattr(calc, 'metadata'): d['metadata'] = calc.metadata if kwargs.get('dos', None): from ase.dft.dos import DOS dos = DOS(calc, width=kwargs.get('width', 0.2)) e = dos.get_energies() d['data']['dos'] = {'doc': 'Total density of states'} d['data']['dos']['e'] = e.tolist() if calc.spinpol: d['data']['dos']['dos-up'] = dos.get_dos(spin=0).tolist() d['data']['dos']['dos-down'] = dos.get_dos(spin=1).tolist() else: d['data']['dos']['dos'] = dos.get_dos().tolist() if kwargs.get('ados', None): from ase.calculators.vasp import VaspDos ados = VaspDos(efermi=calc.get_fermi_level()) d['data']['ados'] = {'doc': 'Atom projected DOS'} nonspin_orbitals_no_phase = ['s', 'p', 'd'] nonspin_orbitals_phase = ['s', 'py', 'pz', 'px', 'dxy', 'dyz', 'dz2', 'dxz', 'dx2'] spin_orbitals_no_phase = [] for x in nonspin_orbitals_no_phase: spin_orbitals_no_phase += ['{0}-up'.format(x)] spin_orbitals_no_phase += ['{0}-down'.format(x)] spin_orbitals_phase = [] for x in nonspin_orbitals_phase: spin_orbitals_phase += ['{0}-up'.format(x)] spin_orbitals_phase += ['{0}-down'.format(x)] if calc.spinpol and calc.int_params['lorbit'] != 11: orbitals = spin_orbitals_no_phase elif calc.spinpol and calc.int_params['lorbit'] == 11: orbitals = spin_orbitals_phase elif calc.int_params['lorbit'] != 11: orbitals = nonspin_orbitals_no_phase else: orbitals = nonspin_orbitals_phase for i, atom in enumerate(atoms): d['data']['ados']['energy'] = ados.energy.tolist() d['data']['ados'][i] = {} for orbital in orbitals: d['data']['ados'][i][orbital] = ados.site_dos(0, orbital).tolist() # convert all numpy arrays to lists for key in d: try: d[key] = d[key].tolist() except: pass for key in d['input']: try: d['input'][key] = d['input'][key].tolist() except: pass return d
from step0 import * from numpy import * from ase.dft import DOS from ase.dft import get_distribution_moment from ase.calculators.vasp import VaspDos os.chdir('work-dos') emax, emin, ngrid, efermi = dos_info('DOSCAR') vdos = VaspDos() vdos.read_doscar('DOSCAR') vdos._set_efermi(efermi) e = vdos.energy dos_up = vdos.dos[0] dos_down = vdos.dos[1] dos_total = dos_up + dos_down dos_s_up = np.zeros(len(e)) dos_p_up = np.zeros(len(e)) dos_d_up = np.zeros(len(e)) dos_s_down = np.zeros(len(e)) dos_p_down = np.zeros(len(e)) dos_d_down = np.zeros(len(e)) for i in range(len(atoms)): dos_s_up += vdos.site_dos(i,'s-up')
def calc_to_dict(calc, **kwargs): """Convert calc to a dictionary.""" d = { 'doc': '''JSON representation of a VASP calculation. energy is in eV forces are in eV/\AA stress is in GPa (sxx, syy, szz, syz, sxz, sxy) magnetic moments are in Bohr-magneton The density of states is reported with E_f at 0 eV. Volume is reported in \AA^3 Coordinates and cell parameters are reported in \AA If atom-projected dos are included they are in the form: {ados:{energy:data, {atom index: {orbital : dos}}} ''' } d['incar'] = {'doc': 'INCAR parameters'} d['incar'].update( dict( filter(lambda item: item[1] is not None, calc.float_params.items()))) d['incar'].update( dict(filter(lambda item: item[1] is not None, calc.exp_params.items()))) d['incar'].update( dict( filter(lambda item: item[1] is not None, calc.string_params.items()))) d['incar'].update( dict(filter(lambda item: item[1] is not None, calc.int_params.items()))) d['incar'].update( dict(filter(lambda item: item[1] is not None, calc.bool_params.items()))) d['incar'].update( dict(filter(lambda item: item[1] is not None, calc.list_params.items()))) d['incar'].update( dict(filter(lambda item: item[1] is not None, calc.dict_params.items()))) d['input'] = calc.input_params d['potcar'] = calc.get_pseudopotentials() d['atoms'] = atoms_to_dict(calc.get_atoms()) d['data'] = {'doc': 'Data from the output of the calculation'} atoms = calc.get_atoms() d['data']['total_energy'] = atoms.get_potential_energy() d['data']['forces'] = atoms.get_forces().tolist() # There are times when no stress is calculated try: stress = atoms.get_stress() except NotImplementedError: stress = None except AssertionError: stress = None if stress is not None: d['data']['stress'] = atoms.get_stress().tolist() else: d['data']['stress'] = None d['data']['fermi_level'] = calc.get_fermi_level() d['data']['volume'] = atoms.get_volume() if calc.spinpol: d['data']['magmom'] = atoms.get_magnetic_moment() if (calc.int_params.get('lorbit', 0) >= 10 or calc.list_params.get('rwigs', None)): try: d['data']['magmoms'] = atoms.get_magnetic_moments().tolist() except AttributeError: d['data']['magmoms'] = None # store the metadata if hasattr(calc, 'metadata'): d['metadata'] = calc.metadata if kwargs.get('dos', None): from ase.dft.dos import DOS dos = DOS(calc, width=kwargs.get('width', 0.2)) e = dos.get_energies() d['data']['dos'] = {'doc': 'Total density of states'} d['data']['dos']['e'] = e.tolist() if calc.spinpol: d['data']['dos']['dos-up'] = dos.get_dos(spin=0).tolist() d['data']['dos']['dos-down'] = dos.get_dos(spin=1).tolist() else: d['data']['dos']['dos'] = dos.get_dos().tolist() if kwargs.get('ados', None): from ase.calculators.vasp import VaspDos ados = VaspDos(efermi=calc.get_fermi_level()) d['data']['ados'] = {'doc': 'Atom projected DOS'} nonspin_orbitals_no_phase = ['s', 'p', 'd'] nonspin_orbitals_phase = [ 's', 'py', 'pz', 'px', 'dxy', 'dyz', 'dz2', 'dxz', 'dx2' ] spin_orbitals_no_phase = [] for x in nonspin_orbitals_no_phase: spin_orbitals_no_phase += ['{0}-up'.format(x)] spin_orbitals_no_phase += ['{0}-down'.format(x)] spin_orbitals_phase = [] for x in nonspin_orbitals_phase: spin_orbitals_phase += ['{0}-up'.format(x)] spin_orbitals_phase += ['{0}-down'.format(x)] if calc.spinpol and calc.int_params['lorbit'] != 11: orbitals = spin_orbitals_no_phase elif calc.spinpol and calc.int_params['lorbit'] == 11: orbitals = spin_orbitals_phase elif calc.int_params['lorbit'] != 11: orbitals = nonspin_orbitals_no_phase else: orbitals = nonspin_orbitals_phase for i, atom in enumerate(atoms): d['data']['ados']['energy'] = ados.energy.tolist() d['data']['ados'][i] = {} for orbital in orbitals: d['data']['ados'][i][orbital] = ados.site_dos( 0, orbital).tolist() # convert all numpy arrays to lists for key in d: try: d[key] = d[key].tolist() except: pass for key in d['input']: try: d['input'][key] = d['input'][key].tolist() except: pass return d
cell=[(0, b, b), (b, 0, b), (b, b, 0)]) RWIGS = [1.0, 1.1, 1.25, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0 ] ED, WD, N = [], [], [] for rwigs in RWIGS: with jasp('bulk/pd-ados') as calc: calc.clone('bulk/pd-ados-rwigs-{0}'.format(rwigs)) with jasp('bulk/pd-ados-rwigs-{0}'.format(rwigs)) as calc: calc.set(rwigs=[rwigs]) try: calc.calculate() except (VaspSubmitted, VaspQueued): continue # now get results ados = VaspDos(efermi=calc.get_fermi_level()) energies = ados.energy dos = ados.site_dos(0, 'd') #we will select energies in the range of -10, 5 ind = (energies < 5) & (energies > -10) energies = energies[ind] dos = dos[ind] Nstates = np.trapz(dos, energies) occupied = energies <= 0.0 N_occupied_states = np.trapz(dos[occupied], energies[occupied]) ed = np.trapz(energies * dos, energies) / np.trapz(dos, energies) wd2 = np.trapz(energies**2 * dos, energies) / np.trapz(dos, energies) N.append(N_occupied_states) ED.append(ed) WD.append(wd2**0.5) plt.plot(RWIGS, N, 'bo', label='N. occupied states')
def drawPropagation(xmin, xmax, z, doslist): sy = z.size # # temporary read DOSCAR for getting size # dos = VaspDos(doscar=doslist[0]) T = dos.energy idx = np.where((xmin < T) & (T < xmax)) # limit xmin-xmax T = T[idx] sx = T.size T = np.tile(T, (sy, 1)) # extend T z = np.tile(z, (sx, 1)).T for i, idoscar in enumerate(doslist): dos = VaspDos(doscar=idoscar) efermi = get_efermi_from_doscar(idoscar) T[i] += efermi U = dos.dos[idx] U = np.tile(U, (sy, 1)) for i, idoscar in enumerate(doslist): dos = VaspDos(doscar=idoscar) U[i] = dos.dos[idx] U[i, 0] = 0.0 U[i, -1] = 0.0 # to make bottom line flat fig = plt.figure(figsize=(12, 12)) ax = fig.add_subplot(1, 1, 1, projection="3d", proj_type="ortho") verts = [] for i, idoscar in enumerate(doslist): efermi = get_efermi_from_doscar(idoscar) verts.append(list(zip(T[i, :] - efermi, U[i, :] / np.max(U[i, :])))) poly = PolyCollection(verts, facecolors=(1, 1, 1, 1.0), edgecolors=(0, 0, 0, 1), linewidth=1.4) # RGBA ax.add_collection3d(poly, zs=z[:, 0], zdir="y") ax.set_xlim3d(xmin, xmax) ax.set_ylim3d(np.min(z) - 2.0, np.max(z) - 2.0) ax.set_zlim3d(0, 1.1) labels = [] for idoscar in range(len(doslist)): labels.append(doslist[idoscar].split("_")[1]) ax.set_yticks(np.linspace(np.min(z), np.max(z), len(doslist))) ax.set_yticks(z[:, 0]) ax.set_yticklabels(labels, va='center', ha='left', fontsize=14, fontname="Arial") ax.grid(False) ax.set_xticks(np.arange(xmin, xmax + 1, 2)) ax.set_xticklabels(np.arange(xmin, xmax + 1, 2), fontsize=14, fontname="Arial") ax.set_zticks([]) ax.w_xaxis.set_pane_color((1.0, 1.0, 1.0, 1.0)) ax.w_zaxis.set_pane_color((0.0, 0.0, 0.0, 1.0)) ax.xaxis.pane.set_edgecolor('black') ax.yaxis.pane.set_edgecolor('black') ax.xaxis.pane.fill = False ax.yaxis.pane.fill = False ax.zaxis.pane.fill = False ax.get_proj = lambda: np.dot(Axes3D.get_proj(ax), np.diag([1.0, 5.0, 0.1, 1])) ax.view_init(elev=15, azim=270)
save(result_file, '3rd calculation \n total energy : {0} eV, {1} eV/atom'.format(p, p/len(atoms))) save(result_file, 'magnetic moment : {0} mB, {1} mB/atom'.format(m, m/len(atoms))) save(result_file, 'forces \n {0}'.format(atoms.get_forces())) calc.set(ismear=-5, lorbit=11, nedos=3001) p = atoms.get_potential_energy() save(result_file, '4th calculation \n total energy : {0} eV, {1} eV/atom'.format(p, p/len(atoms))) tm = atoms.get_magnetic_moment() m = atoms.get_magnetic_moments() save(result_file, 'total magnetic moment : {0} mB {1} mB/atom '.format(tm, tm/len(atoms))) save(result_file, 'magnetic moment: {0}'.format(m)) vdos = VaspDos() vdos.read_doscar('DOSCAR') print vdos.efermi print vdos.site_dos(0,0) dos = DOS(calc, width=0.05) d = dos.get_dos() up = dos.get_dos(0) down = dos.get_dos(1) e = dos.get_energies() plt.plot(e,d, label='total') plt.plot(e,up, label='spin-up')
from step0 import * from numpy import * from ase.dft import DOS from ase.dft import get_distribution_moment from ase.calculators.vasp import VaspDos os.chdir('work-dos') emax, emin, ngrid, efermi = dos_info('DOSCAR') vdos = VaspDos() vdos.read_doscar('DOSCAR') vdos._set_efermi(efermi) e = vdos.energy dos_total = vdos.dos dos_s = np.zeros(len(e)) dos_p = np.zeros(len(e)) dos_d = np.zeros(len(e)) for i in range(len(atoms)): # atomic type number dos_s += vdos.site_dos(i,'s') dos_p += vdos.site_dos(i,'px') + vdos.site_dos(i,'py') + vdos.site_dos(i,'pz') dos_d += vdos.site_dos(i,'dxy') + vdos.site_dos(i,'dyz') + vdos.site_dos(i,'dz2') + vdos.site_dos(i,'dxz') + vdos.site_dos(i,'dx2') # dos_s_up = vdos.site_dos(4,'s-up') # dos_p_up = vdos.site_dos(4,'px-up') + vdos.site_dos(4,'py-up') + vdos.site_dos(4, 'pz-up')
draw_pdos = True else: draw_pdos = False doscar = "DOSCAR_" + system sigma = 20.0 # # finding natom # f = open(doscar, "r") line1 = f.readline() natom = int(line1.split()[0]) f.close() dos = VaspDos(doscar=doscar) ene = dos.energy tdos = dos.dos tdos = smear_dos(ene, tdos, sigma=sigma) if draw_pdos: pdos = np.zeros(len(tdos)) for i in range(0, natom): pdos = pdos + dos.site_dos(i, orbital) pdos = smear_dos(ene, pdos, sigma=sigma) sb.set(context='notebook', style='darkgrid', palette='deep', font='sans-serif',
if len(argvs) == 3: orbital = argvs[2] draw_pdos = True else: draw_pdos = False doscar = "DOSCAR_" + system sigma = 10.0 # # finding natom # f = open(doscar, "r") line1 = f.readline() natom = int(line1.split()[0]) f.close() dos = VaspDos(doscar=doscar) ene = dos.energy tdos = dos.dos tdos = smear_dos(ene, tdos, sigma=sigma) outname = system + ".txt" fout = open(outname, "w") for i, x in enumerate(ene): fout.write("{0:<12.4f}{1:12.4e}\n".format(ene[i], tdos[i])) fout.close()
norbs = len(argvs) - 3 # number of orbitals efermi = get_efermi_from_doscar(doscar) # # get orbital list # for i in range(0, norbs): orbitals.append(str(argvs[i + 3])) # # finding natom # f = open(doscar, "r") line1 = f.readline() natom = int(line1.split()[0]) f.close() dos = VaspDos(doscar=doscar) ene = dos.energy tdos = dos.dos system = obj.system # already know! lattice = obj.lattice data = obj.data # # limit analysis only for occupied part # margin = 0.0 ene = list(filter(lambda x: x <= efermi + margin, ene)) for orbital in orbitals: #
nargs=2) parser.add_option("-o", "--orbital", action="store", type="string", default="all", help="specify orbitals for which atoms will be printed", nargs=1) (options, args) = parser.parse_args() num = len(sys.argv) if (num < 2): parser.print_help() else: doscar = VaspDos(sys.argv[num - 1]) # get number of atoms dos_size = len(doscar._site_dos[0][0]) number_of_atoms = len(doscar._site_dos) energy = doscar._get_energy() if (dos_size != len(energy)): print "Error: The DOS array size (", dos_size, ") is difrent than the energy array size (", len( energy), ")" # atoms seting a = [] if (options.atoms[0] == -1 and options.atoms[1] == -1): a = [1, number_of_atoms] else: