def set_vaspp(self, token, arg, des = "see manual"): """ Used for setting vasp parameters. """ if token in ("ISMEAR",): if type(arg) not in [int, None, ]: raise TypeError if token in ("KSPACING",): if type(arg) not in [float, None, ]: raise TypeError old = self.vasp_params[token] self.vasp_params[token] = arg if old == arg: print_and_log("Warning! You did not change "+token+" in "+self.ise+" set\n") else: self.history += " "+token+" was changed from "+str(old)+" to "+str(arg) + "\n" print_and_log(token+" was changed from "+str(old)+" to "+str(arg) +" - "+ des+" in set "+self.ise+" \n") self.update() return
def read_vectors(token, number_of_vectors, list_of_words): """Returns the list of numpy vectors for the last match""" number_of_matches = list_of_words.count(token) if number_of_matches == 0: #print_and_log("Warning token '"+token+"' was not found! return empty\n") return [None] if number_of_matches > 1: print_and_log("Warning token '" + token + "' was found more than one times\n") raise RuntimeError index = list_of_words.index(token, number_of_matches - 1) #Return the index of the last match #print list_of_words[index] list_of_vectors = [] vector = np.zeros((3)) for i in range(number_of_vectors): vector[0] = float(list_of_words[index + 1]) vector[1] = float(list_of_words[index + 2]) vector[2] = float(list_of_words[index + 3]) index += 3 list_of_vectors.append(vector.copy()) return list_of_vectors
def set_relaxation_type(self,type_of_relaxation): name = "Type of relaxation ISIF" if type(type_of_relaxation) not in [str, ]: raise TypeError old = self.vasp_params["ISIF"] if "ions" == type_of_relaxation: if int(self.ise[0]) != 9: print_and_log("Warning! The name of set is uncostintent with relaxation type\n") raise TypeError self.vasp_params["ISIF"] = 2 # self.set_nmdsteps(200) elif type_of_relaxation == "full": if int(self.ise[0]) != 2: print_and_log("Warning! The name of set is uncostintent with relaxation type\n") raise TypeError self.vasp_params["ISIF"] = 3 else: print_and_log("Error! Uncorrect type of relaxation\n") raise TypeError arg = self.vasp_params["ISIF"] if old == arg: print_and_log("Warning! You did not change "+name+" in "+self.ise+" set\n") return self.history += " "+name+" was changed from "+str(old)+" to "+str(arg) + "\n" print_and_log(name+" was changed from "+str(old)+" to "+str(arg) + " in set "+self.ise+" \n") self.update() #print self.history return
def printme(self): for key in self.vasp_params: if self.vasp_params[key] == None: continue print_and_log( "{:30s} = {:s} ".format("s.vasp_params['"+key+"']", str(self.vasp_params[key]) ), imp = 'Y', end = '\n' ) printlog('ngkpt:', self.ngkpt, imp = 'Y') printlog('POTDIR:', self.potdir, imp = 'Y', end = '\n' )
def add_conv_kpoint(self,arg): if type(arg) is not str: sys.exit("\nadd_conv_kpoint error\n") if arg in self.conv_kpoint: print_and_log( "Warning! You already have this name in list") return self.conv_kpoint.append(arg) self.history += "Name "+arg+" was added to self.conv_kpoint\n" self.update()
def load(self,param, inplace = False): """ Update parameters of set from dict param """ if inplace: s = self else: s = copy.deepcopy(self) for key in param: if key in vasp_keys: s.set_vaspp(key, param[key]) elif key == 'set_potential': for key2 in param[key]: # print key2, 'key2' s.set_potential(key2, param[key][key2]) elif key == 'add_nbands': # print param[key] s.set_add_nbands(param[key]) elif key == 'ngkpt': s.set_ngkpt(param[key]) elif key == 'bfolder': print_and_log( 'New blockfolder', param[key]) elif key in siman_keys: s.set_attrp(key, param[key] ) else: print_and_log('Error! Uknown key: '+key) raise RuntimeError if key == 'set_sequence': sets = [] for se in s.set_sequence: sets.append(copy.deepcopy(header.varset[se])) s.set_sequence = sets #put objects instead of names # if hasattr(s, 'set_sequence') and s.set_sequence: # sets = [] # for se in s.set_sequence: # if type(se) == str: # sets.append(copy.deepcopy(varset[se])) # else: # sets.append(copy.deepcopy(se)) # s.set_sequence = sets #put objects instead of names return s
def determine_unique_final(st_pores, sums, avds, x_m): final_table = [] insert_positions = [] """Please determine unique positions with similar distances taking into acc PBC!!! below is incorrect """ # crude_prec = 1 # sums_crude = np.unique(sums.round(crude_prec)) # print_and_log('The unique voids based on the sums:', # '\nwith 0.01 A prec:',np.unique(sums.round(2)), # '\nwith 0.1 A prec:',sums_crude, # imp ='y') # print_and_log('Based on crude criteria only', len(sums_crude),'types of void are relevant', imp = 'y') # xcart_unique = [] # avds_unique = [] # sums_unique = [] # for i, s in enumerate(sums_crude): # index_of_first = np.where(sums.round(crude_prec)==s)[0][0] # xcart_unique.append(st_pores.xcart[index_of_first]) # avds_unique.append(avds[index_of_first] ) # sums_unique.append(sums[index_of_first] ) # st_pores_unique = copy.deepcopy(st_pores) # st_pores_unique.xcart = xcart_unique # st_pores_unique.xcart2xred() sur = local_surrounding(x_m, st_pores, n_neighbours=len(st_pores.xcart), control='atoms', periodic=True) # print('neb.determine_unique_final(): sur', sur) print_and_log('I can suggest you ' + str(len(sur[0])) + ' end positions.', imp='y') for i, (x, d, ind) in enumerate(zip(sur[0], sur[3], sur[2])): # if i == 0: # continue final_table.append( [i, np.array(x).round(2), round(d, 2), avds[ind], sums[ind]]) print_and_log(tabulate(final_table, headers=['void #', 'Cart.', 'Dist', 'Dev.', 'Sum'], tablefmt='psql'), imp='Y') return sur
def makedir(path): """ *path* - path to some file Make dirname(path) directory if it does not exist """ dirname = os.path.dirname(path) if dirname and not os.path.exists(dirname): os.makedirs(dirname) print_and_log("Directory", dirname, " was created", imp = 'y') return
def set_ngkpt(self,arg): if not is_list_like(arg): printlog("Error! set_ngkpt type error") old = copy.copy(self.ngkpt) self.ngkpt = copy.copy(arg) self.kpoints_file = True self.vasp_params['KSPACING'] = None if old == arg: print_and_log( "Warning! You did not change one of your parameters in new set", imp = 'y') return self.history += "ngkpt was changed from "+str(old)+" to "+str(arg) + " and KPOINTS file was swithed on\n" return
def set_ngkpt(self,arg): if type(arg) is not tuple: sys.exit("\nset_ngkpt type error\n") old = copy.copy(self.ngkpt) self.ngkpt = copy.copy(arg) self.kpoints_file = True self.vasp_params['KSPACING'] = None if old == arg: print_and_log( "Warning! You did not change one of your parameters in new set", imp = 'y') return self.history += "ngkpt was changed from "+str(old)+" to "+str(arg) + " and KPOINTS file was swithed on\n" return
def set_add_nbands(self,arg): name = "add_nbands" if type(arg) not in [float, int ]: raise TypeError try: self.add_nbands except AttributeError: self.add_nbands = 1. old = self.add_nbands self.add_nbands = arg if old == arg: print_and_log("Warning! You did not change "+name+" in "+self.ise+" set\n") return self.history += " "+name+" was changed from "+str(old)+" to "+str(arg) + "\n" print_and_log(" "+name+" was changed from "+str(old)+" to "+str(arg) + " in set "+self.ise+" \n") return
def add_conv_tsmear(self,arg): if type(arg) is not str: sys.exit("\nadd_conv_tsmear type error\n") try: self.conv_tsmear[0] except AttributeError: print_and_log( "Error! Set "+self.ise+" does not have conv_tsmear, I create new\n") self.conv_tsmear = [] if arg in self.conv_tsmear: print_and_log( "Warning! You already have this name in list", imp = 'y') return self.conv_tsmear.append(arg) self.history += "Name "+arg+" was added to self.conv_tsmear\n" self.update()
def fit_and_plot(x1, y1, x2, y2, power, name = "", xlabel = "", ylabel = "", image_name = "test", lines = None): """Should be used in two below sections! Creates one plot with two dependecies and fit them; return minimum fitted value of x2 and corresponding valume of y2; if name == "" image will not be plotted power - the power of polynom lines - add lines at x = 0 and y = 0 """ coeffs1 = np.polyfit(x1, y1, power) coeffs2 = np.polyfit(x2, y2, power) fit_func1 = np.poly1d(coeffs1) fit_func2 = np.poly1d(coeffs2) #x_min = fit_func2.deriv().r[power-2] #derivative of function and the second cooffecient is minimum value of x. #y_min = fit_func2(x_min) if name: x_range = np.linspace(min(x2), max(x2)) fit_y1 = fit_func1(x_range); fit_y2 = fit_func2(x_range); plt.figure(figsize=(8,6.1)) # plt.title(name) plt.ylabel(ylabel) plt.xlabel(xlabel) plt.xlim(min(x2)-0.1*abs(min(x2) ), max(x2)+0.1*abs(min(x2))) plt.plot(x1, y1, 'ro', label = 'initial') plt.plot(x2, y2, 'bo', label = 'relaxed' ) plt.plot(x_range, fit_y1, 'r-',) #label = 'init_fit') plt.plot(x_range, fit_y2, 'b-',) #label = 'r_fit' ) plt.legend(loc =9) if lines == 'xy': plt.axvline(color='k') plt.axhline(color='k') plt.tight_layout() #plt.savefig('images/'+image_name) print_and_log( 'Saving file ...',path_to_images+str(image_name)+'.png', imp = 'y' ) plt.savefig(path_to_images+str(image_name)+'.png',format='png', dpi = 300) return fit_func2
def set_potential(self,znucl, arg): # print arg if type(arg) not in (str,): # sys.exit("\nset_potential error\n") raise RuntimeError if znucl in self.potdir: if arg == self.potdir[znucl]: print_and_log( "Warning! You already have the same potential for "+str(znucl)+" element\n" ) # print type(self.potdir) self.potdir[znucl] = arg self.history += "Potential for "+str(znucl)+" was changed to "+arg+"\n" print_and_log( "Potential for "+str(znucl)+" was changed to "+arg+"\n" ) # self.update() return
def gb_energy_volume(gb,bulk): if (gb.end.rprimd[1] != bulk.end.rprimd[1]).any() or (gb.end.rprimd[2] != bulk.end.rprimd[2]).any(): print_and_log("Warning! You are trying to calculate gb_energy from cells with different lateral sizes:"+str(gb.end.rprimd)+" "+str(bulk.end.rprimd)+"\n") #print bulk.vol V_1at = bulk.vol / bulk.natom #* to_ang**3 E_1at = bulk.energy_sigma0 / bulk.natom A = np.linalg.norm( np.cross(gb.end.rprimd[1], gb.end.rprimd[2]) ) #surface area of gb #print A gb.v_gb = ( gb.vol - V_1at * gb.natom) / A / 2. * 1000 gb.e_gb = ( gb.energy_sigma0 - E_1at * gb.natom) / A / 2. * eV_A_to_J_m * 1000 gb.e_gb_init = ( gb.list_e_sigma0[0] - E_1at * gb.natom) / A / 2. * eV_A_to_J_m * 1000 gb.bulk_extpress = bulk.extpress #print "Calc %s; e_gb_init = %.3f J/m^2; e_gb = %.3f J/m; v_gb = %.3f angstrom "%(gb.name, gb.e_gb_init, gb.e_gb, gb.v_gb ) outst = "%15s&%7.0f&%7.0f"%(gb.name, gb.e_gb, gb.v_gb) return outst
def calc_ac(a1, c1, a2, c2, a_b = 0.1, c_b = 0.1, type = "two_atoms"): """ Calculate values of hexagonal lattice parameters for cell with two different atoms. The used assumption is: 1. Provided lattice constants are for large enougth cells, in which excess volume (dV) of impurity does not depend on the size of cell. 2. Two atoms do not interact with each other, which allows to use dV(CO) = dV(C) + dV(O) Two regimes: two_atoms - calculate cell sizes if additional atom was added double_cell - if cell was doubled; only first cell and second_cell are needed Input: a1, c1 - lattice constants of cell with first impurity atom (first cell) a2, c2 - lattice constants of cell with second impurity atom (second cell) a_b, c_b - lattice constants of cell with pure hexagonal metall Output: a, c - lattice constants of cell with two atoms """ hstring = ("%s #on %s"% (traceback.extract_stack(None, 2)[0][3], datetime.date.today() ) ) if hstring != header.history[-1]: header.history.append( hstring ) A = (a1**2 * c1) + (a2**2 * c2) - (a_b**2 * c_b) B = 0.5 * (c1/a1 + c2/a2) C = ( (a1**2 * c1) + (a2**2 * c2) ) * 0.5 #sum of cell volumes divided by 2 since during the construction of new cell we will use multiplication by 2 # print "A,B=",A,B a = (A/B)**(1./3) c = a * B a = round(a,5) c = round(c,5) print_and_log( "a, c, c/a for cell with pure hcp ", a_b, c_b, round(c_b/a_b,4), imp ='y' ) print_and_log( "a, c, c/a for cell with first atom ", a1, c1, round(c1/a1,4), imp ='y' ) print_and_log( "a, c, c/a for cell with second atom ", a2, c2, round(c2/a2,4), imp ='y' ) #for double cell a3 = (C/B)**(1./3) c3 = a3 * B a3 = round(a3,5) c3 = round(c3,5) if type == "two_atoms": print_and_log( "a, c, c/a for cell with two atoms ", a, c, round(c/a,4), "# the same cell but with two atoms\n", imp ='y') elif type == "double_cell": print_and_log( "a, c, c/a for new cell ", a3, c3, round(c3/a3,4), "# for cell with V = V(first_cell) + V(second cell), but only for the case if V(second cell) == V(first_cell)", imp ='y') return a, c
def calculate_voronoi(self, state = 'end'): # By default two quantities per atom are calculated by this compute. # The first is the volume of the Voronoi cell around each atom. # Any point in an atom's Voronoi cell is closer to that atom than any other. # The second is the number of faces of the Voronoi cell, which # is also the number of nearest neighbors of the atom in the middle of the cell. # state - init or end; if init then saved in self.init.vorovol; if end than saved in self.vorovol write_lammps(self, state, filepath = 'voronoi_analysis/structure.lammps') #write structure for lammps runBash("rm voronoi_analysis/dump.voro; /home/aksenov/installed/lammps-1Feb14/src/lmp_serial < voronoi_analysis/voronoi.in > voronoi_analysis/log") if state == 'end': self.vorovol = [] self.vorofaces = [] vorovol = self.vorovol vorofaces = self.vorofaces elif state == 'init': self.init.vorovol = [] self.init.vorofaces = [] vorovol = self.init.vorovol vorofaces = self.init.vorofaces vsum=0 wlist = [] with open('voronoi_analysis/dump.voro','r') as volfile: #analyze dump.voro for line in volfile: if 'ITEM: ATOMS ' in line: break for line in volfile: ll = line.split() if int(ll[1]) > 1: wlist.append( [ll[0], ll[5], ll[6], ll[2]] ) # print 'Volume of atom ',ll[0],'is', ll[5] vsum= vsum+float(ll[5]) print_and_log( 'Check total volume ', vsum, self.end.vol) wlist.sort(key = itemgetter(0)) #sort according to the position of atoms print_and_log( "atom #, voronoi vol, voronoi faces, x coordinate: ", ) print_and_log( wlist) for w in wlist: vorovol.append(float(w[1])) vorofaces.append(int(w[2])) # print 'Voro vol ',self.end.vorovol # print 'Voro faces',self.end.vorofaces # print len(wlist) if hasattr(self, 'vorovol'): voro = '' if len(vorovol) == 2: #C and O voro = " {0:5.2f} & {1:2d} & {2:5.2f} & {3:2d} ".format(vorovol[0], vorofaces[0], vorovol[1], vorofaces[1] ).center(25) else: voro = " {0:5.2f} & {1:2d} ".format(vorovol[0], vorofaces[0] ).center(25) voro+='&' else: voro = "" print_and_log( "Voronoi volume = ", voro, imp = 'y') return voro
def determine_voids(st, r_impurity, fine=1, step_dec=0.05): if not r_impurity: printlog('add_neb(): Error!, Please provide *r_impurity* (1.6 A?)') sums = [] avds = [] printlog('Searching for voids', important='y') st_pores = find_pores(st, r_matrix=0.5, r_impurity=r_impurity, step_dec=step_dec, fine=fine, calctype='all_pores') printlog('List of found voids:\n', np.array(st_pores.xcart)) write_xyz(st.add_atoms(st_pores.xcart, 'H'), file_name=st.name + '_possible_positions') write_xyz(st.add_atoms(st_pores.xcart, 'H'), replications=(2, 2, 2), file_name=st.name + '_possible_positions_replicated') for x in st_pores.xcart: # summ = local_surrounding(x, st, n_neighbours = 6, control = 'sum', periodic = True) # avd = local_surrounding(x, st, n_neighbours = 6, control = 'av_dev', periodic = True) summ, avd = local_surrounding2(x, st, n_neighbours=6, control='sum_av_dev', periodic=True) # print (summ, avd) sums.append(summ) avds.append(avd[0]) # print sums = np.array(sums) avds = np.array(avds).round(0) print_and_log( 'Sum of distances to 6 neighboring atoms for each void (A):\n', sums, imp='y') print_and_log('Distortion of voids (0 - is symmetrical):\n', avds, imp='y') return st_pores, sums, avds
def element_name_inv(el): el_dict = header.el_dict nu_dict = header.nu_dict # print type(el), el, type(str('sdf') ) if is_string_like(el): try: elinv = el_dict[el] except: print_and_log("Error! Unknown element: " + str(el)) raise RuntimeError else: el = int(el) try: elinv = nu_dict[el] except: print_and_log("Error! Unknown element: " + str(el)) raise RuntimeError return elinv # inversed notion of element
def element_name_inv(el): el_dict = {'octa':200, 'n':0, 'H':1, 'He':2, 'Li':3, 'Be':4, 'B':5, 'C':6, 'N':7, 'O':8, 'F':9, 'Ne':10, 'Na':11, 'Mg':12, 'Al':13, 'Si':14, 'P':15, 'S':16, 'Cl':17, 'Ar':18, 'K':19, 'Ca':20, 'Sc':21, 'Ti':22, 'V':23, 'Cr':24, 'Mn':25, 'Fe':26, 'Co':27, 'Ni':28, 'Cu':29, 'Zn':30, 'Ga':31, 'Ge':32, 'As':33, 'Se':34, 'Br':35, 'Kr':36, 'Rb':37, 'Sr':38, 'Y':39, 'Zr':40, 'Nb':41, 'Mo':42, 'Tc':43, 'Ru':44, 'Rh':45, 'Pd':46, 'Ag':47, 'Cd':48, 'In':49, 'Sn':50, 'Sb':51, 'Te':52, 'I':53, 'Xe':54, 'Cs':55, 'Ba':56, 'La':57, 'Ce':58, 'Pr':59, 'Nd':60, 'Pm':61, 'Sm':62, 'Eu':63, 'Gd':64, 'Tb':65, 'Dy':66, 'Ho':67, 'Er':68, 'Tm':69, 'Yb':70, 'Lu':71, 'Hf':72, 'Ta':73, 'W':74, 'Re':75, 'Os':76, 'Ir':77, 'Pt':78, 'Au':79, 'Hg':80, 'Tl':81, 'Pb':82, 'Bi':83, 'Po':84, 'At':85, 'Rn':86, 'Fr':87, 'Ra':88, 'Ac':89, 'Th':90, 'Pa':91, 'U':92, 'Np':93, 'Pu':94, 'Am':95, 'Cm':96, 'Bk':97, 'Cf':98, 'Es':99, 'Fm':100, 'Md':101, 'No':102, 'Lr':103, 'Rf':104, 'Db':105, 'Sg':106, 'Bh':107, 'Hs':108, 'Mt':109, 'Ds':110, 'Rg':111, 'Cn':112, 'Uuq':114, 'Uuh':116, } nu_dict = { 200:'octa', 0:'n', 1:'H', 2:'He', 3:'Li', 4:'Be', 5:'B', 6:'C', 7:'N', 8:'O', 9:'F', 10:'Ne', 11:'Na', 12:'Mg', 13:'Al', 14:'Si', 15:'P', 16:'S', 17:'Cl', 18:'Ar', 19:'K', 20:'Ca', 21:'Sc', 22:'Ti', 23:'V', 24:'Cr', 25:'Mn', 26:'Fe', 27:'Co', 28:'Ni', 29:'Cu', 30:'Zn', 31:'Ga', 32:'Ge', 33:'As', 34:'Se', 35:'Br', 36:'Kr', 37:'Rb', 38:'Sr', 39:'Y', 40:'Zr', 41:'Nb', 42:'Mo', 43:'Tc', 44:'Ru', 45:'Rh', 46:'Pd', 47:'Ag', 48:'Cd', 49:'In', 50:'Sn', 51:'Sb', 52:'Te', 53:'I', 54:'Xe', 55:'Cs', 56:'Ba', 57:'La', 58:'Ce', 59:'Pr', 60:'Nd', 61:'Pm', 62:'Sm', 63:'Eu', 64:'Gd', 65:'Tb', 66:'Dy', 67:'Ho', 68:'Er', 69:'Tm', 70:'Yb', 71:'Lu', 72:'Hf', 73:'Ta', 74:'W', 75:'Re', 76:'Os', 77:'Ir', 78:'Pt', 79:'Au', 80:'Hg', 81:'Tl', 82:'Pb', 83:'Bi', 84:'Po', 85:'At', 86:'Rn', 87:'Fr', 88:'Ra', 89:'Ac', 90:'Th', 91:'Pa', 92:'U', 93:'Np', 94:'Pu', 95:'Am', 96:'Cm', 97:'Bk', 98:'Cf', 99:'Es', 100:'Fm', 101:'Md', 102:'No', 103:'Lr', 104:'Rf', 105:'Db', 106:'Sg', 107:'Bh', 108:'Hs', 109:'Mt', 110:'Ds', 111:'Rg', 112:'Cn', 114:'Uuq', 116:'Uuh', } # print type(el), el, type(str('sdf') ) if is_string_like(el): try: elinv = el_dict[el] except: print_and_log("Error! Unknown element: " +str(el)) raise RuntimeError else: el = int(el) try: elinv = nu_dict[el] except: print_and_log("Error! Unknown element: "+str(el)) raise RuntimeError return elinv # inversed notion of element
def determine_unique_voids(st_pores, sums, avds): crude_prec = 1 sums_crude = np.unique(sums.round(crude_prec)) print_and_log('The unique voids based on the sums:', '\nwith 0.01 A prec:', np.unique(sums.round(2)), '\nwith 0.1 A prec:', sums_crude, imp='y') print_and_log('Based on crude criteria only', len(sums_crude), 'types of void are relevant', imp='y') insert_positions = [] start_table = [] for i, s in enumerate(sums_crude): index_of_first = np.where(sums.round(crude_prec) == s)[0][0] start_table.append([ i, st_pores.xcart[index_of_first].round(2), index_of_first, avds[index_of_first], sums[index_of_first] ]) insert_positions.append(st_pores.xcart[index_of_first]) print_and_log(tabulate(start_table, headers=['void #', 'Cart.', 'Index', 'Dev.', 'Sum'], tablefmt='psql'), imp='Y') return insert_positions
def gb_energy_volume(gb, bulk): if (gb.end.rprimd[1] != bulk.end.rprimd[1]).any() or ( gb.end.rprimd[2] != bulk.end.rprimd[2]).any(): print_and_log( "Warning! You are trying to calculate gb_energy from cells with different lateral sizes:" + str(gb.end.rprimd) + " " + str(bulk.end.rprimd) + "\n") #print bulk.vol V_1at = bulk.vol / bulk.natom #* to_ang**3 E_1at = bulk.energy_sigma0 / bulk.natom A = np.linalg.norm(np.cross(gb.end.rprimd[1], gb.end.rprimd[2])) #surface area of gb #print A gb.v_gb = (gb.vol - V_1at * gb.natom) / A / 2. * 1000 gb.e_gb = (gb.energy_sigma0 - E_1at * gb.natom) / A / 2. * eV_A_to_J_m * 1000 gb.e_gb_init = (gb.list_e_sigma0[0] - E_1at * gb.natom) / A / 2. * eV_A_to_J_m * 1000 gb.bulk_extpress = bulk.extpress #print "Calc %s; e_gb_init = %.3f J/m^2; e_gb = %.3f J/m; v_gb = %.3f angstrom "%(gb.name, gb.e_gb_init, gb.e_gb, gb.v_gb ) outst = "%15s&%7.0f&%7.0f" % (gb.name, gb.e_gb, gb.v_gb) return outst
def set_potential(self,znucl, arg = ''): # print arg if not arg: arg = header.PATH2POTENTIALS+'/'+invert(znucl) printlog('Attention!, Default potentials is chosen from ',header.PATH2POTENTIALS, 'for',invert(znucl) , imp ='Y') if type(arg) not in (str,): # sys.exit("\nset_potential error\n") raise RuntimeError if znucl in self.potdir: if arg == self.potdir[znucl]: print_and_log( "Warning! You already have the same potential for "+str(znucl)+" element\n" ) # print type(self.potdir) self.potdir[znucl] = arg self.history += "Potential for "+str(znucl)+" was changed to "+arg+"\n" print_and_log( "Potential for "+str(znucl)+" was changed to "+arg+"\n" ) # self.update() return
def read_vectors(token, number_of_vectors, list_of_words): """Returns the list of numpy vectors for the last match""" number_of_matches = list_of_words.count( token ) if number_of_matches == 0: #print_and_log("Warning token '"+token+"' was not found! return empty\n") return [None] if number_of_matches > 1: print_and_log("Warning token '"+token+"' was found more than one times\n") raise RuntimeError index = list_of_words.index(token, number_of_matches - 1 ) #Return the index of the last match #print list_of_words[index] list_of_vectors = [] vector = np.zeros((3)) for i in range(number_of_vectors): vector[0] = float(list_of_words[index + 1]) vector[1] = float(list_of_words[index + 2]) vector[2] = float(list_of_words[index + 3]) index+=3 list_of_vectors.append(vector.copy()) return list_of_vectors
def push_figure_to_archive(local_figure_path, caption, figlabel=None, autocompl=True): shutil.copy(local_figure_path, header.path_to_images) print_and_log('push_figure_to_archive():', local_figure_path, 'copied to', header.path_to_images, imp='y') name_without_ext = '.'.join( os.path.basename(local_figure_path).split('.')[:-1]) figfile = '{{' + name_without_ext + '}}' if not figlabel: figlabel = '.'.join(name_without_ext.split('.')[:-1]) if autocompl: caption += ' for ' + figlabel tex_text = \ ("\\begin{{figure}} \n\includegraphics[width=\columnwidth]{{{:s}}}\n" "\caption{{\label{{fig:{:s}}} {:s} }}\n" "\end{{figure}}\n").format(figfile, figlabel, caption ) # print (tex_text) with open(header.project_conf.path_to_paper + '/auto_fig.tex', 'a+', newline='') as f: f.seek(0) a = f.read() # print (a) if tex_text not in a: f.write(tex_text) return
def inherit_iset(ise_new, ise_from, varset, override = False, newblockfolder = None): """ Create new set copying from existing and update some fields. If ise_from does not exist create new""" ise_new = ise_new.strip() ise_from = ise_from.strip() if ise_from not in varset: print_and_log( "\nError! Set "+ise_from+" does not exist. I return new empty set\n") return InputSet(ise_new) old = varset[ise_from] for key in vasp_electronic_keys+vasp_ionic_keys+vasp_other_keys: #check if new keys was added if key not in old.vasp_params: old.vasp_params[key] = None if override: print_and_log( "\nAttention! You have chosen to override set "+ise_new+"\n") elif ise_new in varset: print_and_log( "\nSet "+ise_new+" already exists. I return it without changes. Be carefull not to spoil it\n") return varset[ise_new] new = copy.deepcopy( old ) new.ise = ise_new new.compare_with = ise_from+" " new.des = "no description for these set, see history" new.conv = {} print_and_log( "New set "+ise_new+" was inherited from set "+ise_from+"\n") new.history = old.history + "\nSet "+ise_new+" was inherited from: "+ ise_from +"\n" if newblockfolder: new.history += 'blockfolder changed from '+new.blockfolder+' to '+newblockfolder+'\n' new.blockfolder = newblockfolder varset[ise_new] = new return new
def add_conv(self,arg,type_of_conv): if type(arg) is not str: raise TypeError if type_of_conv not in ["kpoint_conv","tsmear_conv","ecut_conv","nband_conv","npar_conv"]: raise TypeError try: self.conv[type_of_conv][0] except AttributeError: print_and_log( "Warning! Set "+self.ise+" does not have conv, I create new\n") self.conv = {} except KeyError: print_and_log( "Warning! Set "+self.ise+" does not have list for this key in conv, I add new\n") self.conv[type_of_conv] = [] except IndexError: pass if arg in self.conv[type_of_conv]: print_and_log( "Warning! You already have name %s in list of conv %s. Nothing done.\n" % \ (str(arg), str(self.conv[type_of_conv]) ) ) return self.conv[type_of_conv].append(arg) self.history += "Name "+arg+" was added to self.conv["+type_of_conv+"]\n" print_and_log( "Name "+arg+" was added to self.conv["+type_of_conv+"] of set "+self.ise+" \n") self.update()
def test_adding_of_impurities(added, init, v): """ Can be used only inside add_impurity() Replicates the structure and find again pores """ global natoms_v1 if added == None: return if v == 1: #TEST natoms_v1 = len(added.init.xcart) # for test st_rep_after = added.init.replic((1, 2, 1)) rep = copy.deepcopy(init) rep.init = rep.init.replic((1, 2, 1)) #print rep rep = add(znucl, "", rep, write_geo=False) #print rep #print "xcart of replic after adding ", st_rep_after.xcart #print "xcart of adding to replic ", rep.init.xcart if len(st_rep_after.xcart) != len(rep.init.xcart): raise RuntimeError p = 0 #for x2 in st_rep_after.xcart: # print x2 for x in rep.init.xcart: a = any((np.around(x2, p) == np.around(x, p)).all() for x2 in st_rep_after.xcart) #b = any( ( np.ceil(x2, p) == np.ceil(x, p) ).all() for x2 in st_rep_after.xcart ) #c = any( ( np.floor(x2, p) == np.floor(x, p) ).all() for x2 in st_rep_after.xcart ) #print a, b, c #np.concatenate(a, b, c): if not a: print_and_log("Error! Can't find ", np.around(x, 3), "in replic ") raise RuntimeError #assert all([ all( np.around(v1, 8) == np.around(v2, 8) ) for (v1, v2) in zip(st_rep_after.xcart, rep.init.xcart) ]) print_and_log("add_impurity: test succesfully done") if natoms_v1 != len(added.init.xcart): print_and_log( "You have different number of pores in different versions\n") raise RuntimeError return
def set_attrp(self, token, arg, des = "see manual"): """ set any attribute. """ # print token if hasattr(self, token): old = getattr(self, token) if old == arg: print_and_log("Warning! You did not change "+token+" in "+self.ise+" set\n") else: setattr(self, token, arg) self.history += " "+token+" was changed from "+str(old)+" to "+str(arg) + "\n" print_and_log(token+" was changed from "+str(old)+" to "+str(arg) +" - "+ des+" in set "+self.ise+" \n") else: setattr(self, token, arg) print_and_log("New attribute "+token+" added to "+self.ise+" set\n") self.history += " "+token+" was added as a new attr with "+str(arg) + " value \n" return
def test_adding_of_impurities(added, init, v): """ Can be used only inside add_impurity() Replicates the structure and find again pores """ global natoms_v1 if added == None: return if v == 1: #TEST natoms_v1 = len(added.init.xcart) # for test st_rep_after = replic( added.init, (1,2,1) ) rep = copy.deepcopy(init) rep.init = replic( rep.init, (1,2,1) ); #print rep rep = add(znucl, "", rep, write_geo = False) #print rep #print "xcart of replic after adding ", st_rep_after.xcart #print "xcart of adding to replic ", rep.init.xcart if len(st_rep_after.xcart) != len(rep.init.xcart): raise RuntimeError p = 0 #for x2 in st_rep_after.xcart: # print x2 for x in rep.init.xcart: a = any( ( np.around(x2, p) == np.around(x, p) ).all() for x2 in st_rep_after.xcart ) #b = any( ( np.ceil(x2, p) == np.ceil(x, p) ).all() for x2 in st_rep_after.xcart ) #c = any( ( np.floor(x2, p) == np.floor(x, p) ).all() for x2 in st_rep_after.xcart ) #print a, b, c #np.concatenate(a, b, c): if not a: print_and_log( "Error! Can't find ", np.around(x,3), "in replic ") raise RuntimeError #assert all([ all( np.around(v1, 8) == np.around(v2, 8) ) for (v1, v2) in zip(st_rep_after.xcart, rep.init.xcart) ]) print_and_log( "add_impurity: test succesfully done") if natoms_v1 != len(added.init.xcart): print_and_log("You have different number of pores in different versions\n"); raise RuntimeError return
def write_jmol(xyzfile, pngfile, scriptfile = None, atomselection = None, topview = False, orientation = None, axis = False, bonds = True, rprimd = None, shift = None, rotate = None, label = None, high_contrast = None, specialcommand = None, boundbox = 2): """ atomselection - string in gmol format with number of atoms to be nrotateSelected topview - additional top view, requires two models in xyz orientation - additional rotation axis - add axes rotate - rotation of all atoms around view axis in degrees """ if not scriptfile: scriptfile = os.getcwd()+'/'+'temporary_jmol_script' with open(scriptfile,'w') as f: f.write('set frank off\n') #no jmol label if bonds: f.write('set autobond on\n') else: f.write('set autobond off\n set bonds off\n') f.write('load "'+xyzfile+'"\n') f.write('select all \ncpk 250 \nwireframe 0.3\n') #250 f.write('background white \nselect Ti* \ncolor [20,120,250] \nselect C* \ncolor [80,80,80]\n cpk 100\n') f.write('set perspectivedepth off\n') if boundbox: f.write('set boundbox ' +str(boundbox)+ ' \n') # f.write('set specular 85\n set specpower 85\n set diffuse 85\n') if high_contrast: #allows to make better view for black and white printing f.write('set ambient 10 \nset specular 95\n set specpower 95\n set diffuse 95\n') if axis: f.write('set axes 10 \naxes scale 2.5 \n') f.write('axes labels "X" "Y" "Z" "" \n') f.write('color axes red \n') f.write('font axes 26 \n') if orientation: f.write(orientation+'\n') if atomselection: f.write('select '+atomselection+'\n') f.write('color purple \n') if topview: f.write('select * /2 \ntranslateSelected 0 '+str(-rprimd[1][1]*shift)+' 0\nrotateSelected X 90\n') f.write('wireframe 0.1\ncpk 150\nmodel 0\n#zoom 60\n') if label: j = 1 name_old = '' for i, el in enumerate(label): name = el[0]+el[1] if name != name_old: j = 1 label = str(j)+el[1] # print "label",label f.write('select '+el[0]+str(i+1)+'\ncpk 200\nset labeloffset 0 0\nset labelfront\ncolor label black\nlabel '+label+'\n font label 24 bold \n') j+=1 name_old = name if rotate: f.write('rotate z '+str(rotate)+'\n') if specialcommand: f.write(specialcommand) # f.write('write image 2800 2800 png "'+pngfile+'"') f.write('write image 1800 1800 png "'+pngfile+'"') print_and_log( runBash(header.path_to_jmol+' -ions '+scriptfile) ) # print runBash('convert '+pngfile+' -shave 0x5% -trim '+pngfile) #cut by 5% from up and down (shave) and that trim left background print_and_log( pngfile ) print_and_log( runBash('convert '+pngfile+' -trim '+pngfile) ) # trim background return
def write_lammps(st, filename = '', charges = None): """Writes structure in lammps format charges (list of float) - list of charges for each atom type """ rprimd = st.rprimd xcart = st.xcart xred = st.xred typat = st.typat ntypat = st.ntypat znucl = st.znucl name = st.name natom = st.natom if natom != len(xred) != len(xcart) != len(typat) or len(znucl) != max(typat): print_and_log( "Error! write_xyz: check your structure" ) if name == '': name = 'noname' if xcart == [] or len(xcart) != len(xred): print_and_log( "Warining! write_xyz: len(xcart) != len(xred) making xcart from xred.\n", imp = 'y') xcart = xred2xcart(xred, rprimd) #print xcart[1] if not filename: filename = 'lammps/'+name filename+='.inp' makedir(filename) """Write lammps structure file; """ if 1: """ My version; valid only for octahedral cells""" printlog( "Warining! write_lammps(): this func supports only orthogonal cells", imp = 'Y') with open(filename+'','w') as f: f.write("Lammps format "+name+'\n') f.write(str(natom)+" atoms\n") f.write(str(ntypat)+" atom types\n") f.write("{:10.8f} {:10.8f} xlo xhi\n".format(0, rprimd[0][0])) f.write("{:10.8f} {:10.8f} ylo yhi\n".format(0, rprimd[1][1])) f.write("{:10.8f} {:10.8f} zlo zhi\n".format(0, rprimd[2][2])) f.write("0.00000000 0.00000000 0.00000000 xy xz yz\n") f.write("\nAtoms\n\n") for i, x in enumerate(xcart): f.write("{0:8d} {1:2d}".format(i+1, typat[i])) if charges: f.write(" {:6.3f}".format(charges[typat[i]-1] ) ) f.write(" {:12.6f} {:12.6f} {:12.6f}\n".format(x[0], x[1], x[2] )) f.write("\n") printlog('File', filename, 'was written', imp = 'y') else: """Write poscar and convert from poscar to lammps using external script; Valid for arbitary cells""" cl.write_structure('POSCAR', 'dir', path = 'voronoi_analysis/', state = state) runBash("voronoi_analysis/VASP-poscar2lammps.awk voronoi_analysis/POSCAR > "+filepath) if 0: """Write lammps.in file """ with open('voronoi_analysis/voronoi.in','w') as f: f.write("""units metal atom_style atomic boundary p p p\n""") f.write("read_data /home/aksenov/programs/Simulation_wrapper/siman1/voronoi_analysis/structure.lammps\n") # f.write('lattice custom 1 ') # for i, a in enumerate(rprimd): # f.write(' a'+str(i+1)) # for x in a: # f.write(' '+str(x)) # f.write(' &\n') # for x in xred: # f.write(' basis {0:f} {1:f} {2:f}&\n '.format(x[0], x[1], x[2]) ) # f.write("""\n # region 1 prism 0 1 0 1 0 1 1 0 0 # create_box 1 prism # create_atoms 1 prism""") for i in range(ntypat): f.write('\nmass '+str(i+1)+' '+str(int(znucl[i]))+'\n') f.write('pair_style lj/cut 2.0\n') for i in range(ntypat): for j in range(i, ntypat): f.write('pair_coeff '+str(i+1)+' '+str(j+1)+' 0.0 1.0\n') f.write("""compute v1 all voronoi/atom dump d1 all custom 1 /home/aksenov/programs/Simulation_wrapper/siman1/voronoi_analysis/dump.voro id type x y z c_v1[1] c_v1[2] run 0 uncompute v1\n""") return
def write_xyz(st, path = None, repeat = 1, shift = 1.0, gbpos2 = None, gbwidth = 1 , imp_positions = [], specialcommand = None, analysis = None, show_around = None, replications = None, nnumber = 6, topview = True, filename = None, file_name = None, full_cell = False, orientation = None, boundbox = 2, withgb = False, include_boundary = 2, rotate = None, imp_sub_positions = None, jmol = None, show_around_x = None, ): """Writes st structure in xyz format in the folder xyz/path if repeat == 2: produces jmol script shift - in rprimd[1][1] - shift of the second view gbpos2 - position of grain boundary in A gbwidth - atoms aroung gbpos2 will be colored differently imp_positions - type and xcart coordinates additionally to be added to structure; to visulaze all impurity positions: for jmol imp_sub_positions - list of atom numbers; the typat of these atoms is changed: not used now specialcommand - any command at the end of script analysis - additional processing, allows to show only specifice atoms, 'imp_surrounding' - shows Ti atoms only around impurity nnumber - number of neighbours to show show_around - choose atom number around which to show show_around_x - show atoms around point, has higher priority replications - list of replications, (2,2,2) full_cell - returns atoms to cell and replicate boundary atoms jmol - 1,0 - allow to use jmol """ if replications: st = replic(st, mul = replications, inv = 1 ) def update_var(): return st.rprimd, st.xcart, st.xred, st.typat, st.znucl, len(st.xred) rprimd, xcart, xred, typat, znucl, natom = update_var() if file_name: name = file_name elif filename: name = filename else: name = st.name if natom != len(xred) != len(xcart) != len(typat) or len(znucl) != max(typat): print_and_log( "Error! write_xyz: check your arrays.\n\n" ) # print st.natom, len(st.xred), len(st.xcart), len(st.typat), len(st.znucl), max(st.typat) print_and_log("write_xyz(): Name is", name, important = 'n') if name == '': name = 'noname' if xcart == [] or len(xcart) != len(xred): print_and_log( "Warining! write_xyz: len(xcart) != len(xred) making xcart from xred.\n") xcart = xred2xcart(xred, rprimd) #print xcart[1] if path: basepath = path else: basepath = 'xyz/' xyzfile = os.path.join(basepath, name+".xyz") makedir(xyzfile) """Processing section""" if analysis == 'imp_surrounding': lxcart = [] ltypat = [] i=0 for t, x in zip(typat, xcart): condition = False # print show_around, 'show' if show_around: # print i, condition condition = (i + 1 == show_around) # print i, condition else: condition = (t > 1) # compat with prev behav # print 'se', condition if condition: # lxcart.append(x) # ltypat.append(t) # print x, ' x' x_t = local_surrounding(x, st, nnumber, control = 'atoms', periodic = True) # print x_t[1] lxcart+=x_t[0] ltypat+=x_t[1] i+=1 if show_around_x: x = show_around_x x_t = local_surrounding(x, st, nnumber, control = 'atoms', periodic = True) # print x_t[1] lxcart+=x_t[0] ltypat+=x_t[1] xcart = lxcart typat = ltypat natom = len(typat) # print natom, 'nat' """Include atoms on the edge of cell""" if full_cell: # print xred # print natom # st = return_atoms_to_cell(st) # print xred st = replic(st, mul = (1,1,2), inv = 0, cut_one_cell = 1, include_boundary = include_boundary) # print natom, st.natom # print st.xred rprimd, xcart, xred, typat, znucl, natom = update_var() # asdegf """Writing section""" # print_and_log("Writing xyz: "+xyzfile, imp = 'y') #analyze imp_positions if imp_sub_positions == None: imp_sub_positions = [] nsub = 0 for pos in imp_positions: if 's' not in pos[4]: continue # skip interstitial positions xs = np.asarray([pos[0],pos[1],pos[2]]) nsub+=1 # print xs for i, x in enumerate(xcart): # print np.linalg.norm( x-xs) if np.linalg.norm( x-xs) < 1: imp_sub_positions.append(i) if imp_sub_positions : print_and_log( imp_sub_positions, ': numbers of found atoms to be changed ' ) # for i in sorted(indices, reverse=True): # del somelist[i] with open(xyzfile,'w') as f: for i in range(repeat): f.write(str(natom + len(imp_positions)-nsub + 3)+"\n") #+3 vectors f.write(name+"\n") if imp_positions: for i, el in enumerate(imp_positions): # if len(el) != 4: continue f.write( "%s %.5f %.5f %.5f \n"%( el[3], el[0], el[1], el[2] ) ) # print 'composite -pointsize 60 label:{0:d} -geometry +{1:d}+{2:d} 1.png 2.png'.format(i, el[0], el[1]) for i in range(natom): typ = typat[i] - 1 z = int ( znucl[ typ ] ) if i in imp_sub_positions: # f.write( "Be " ) continue else: el = element_name_inv(z) f.write( el+" " ) f.write( "%.5f %.5f %.5f \n"%( xcart[i][0], xcart[i][1], xcart[i][2] ) ) for r in st.rprimd: f.write('Tv {:.10f} {:.10f} {:.10f}\n'.format(*r) ) # os._exit(1) printlog('File', xyzfile, 'was written', imp = 'y') if jmol: """ script mode for jmol. Create script file as well for elobarate visualization """ """Choose gb atoms to change their color""" print_and_log( 'position of boundary 2', gbpos2) atomselection = '' #create consistent xcart_new list like it will be in Jmol xcart_new = [] for i, x in enumerate(xcart): if i in imp_sub_positions: continue xcart_new.append(x) if gbpos2: gbpos1 = gbpos2 - rprimd[0][0]/2. gbatoms = [] for i, x in enumerate(xcart_new): # print i # if x[0] > gbpos1 - gbwidth/2. and x[0] < gbpos1 + gbwidth/2.: if abs(x[0] - gbpos1) < gbwidth/2.: gbatoms.append(i) # print i, x[0], abs(x[0] - gbpos1) if abs(x[0] - gbpos2) < gbwidth/2.: # if x[0] > gbpos2 - gbwidth/2. and x[0] < gbpos2 + gbwidth/2.: # print i, x[0], abs(x[0] - gbpos2) gbatoms.append(i) print_and_log( 'Atoms at GB:', gbatoms) atomselection = '' for i in gbatoms: atomselection +='Ti'+str(i+1+len(imp_positions))+',' atomselection = atomselection[:-1] # elif withgb: # color half of cell # else: # color half of cell # # pass # atomselection = 'atomno>'+str(0+len(imp_positions) )+' and atomno<'+str(( natom + len(imp_positions) )/2-1) xyzfile = os.getcwd()+'/'+xyzfile scriptfile = basepath+name+".jmol" pngfile = os.getcwd()+'/'+basepath+name+".png" print_and_log( 'imp_positions = ',imp_positions) write_jmol(xyzfile, pngfile, scriptfile, atomselection, topview = topview, rprimd =rprimd, shift = shift, label = [(pos[3], pos[4]) for pos in imp_positions], specialcommand = specialcommand, orientation = orientation, boundbox =boundbox, rotate = rotate) return
def plot_conv(list_of_calculations=None, calc=None, type_of_plot=None, conv_ext=[], labelnames=None, cl=None, plot=1, filename=None): """ Allows to fit and plot different properties; Input: 'type_of_plot' - ("fit_gb_volume"-fits gb energies and volume and plot dependencies without relaxation and after it, 'dimer' cl - calculation to use - new interface, please rewrite the old one """ def fit_and_plot(x1, y1, x2, y2, power, name="", xlabel="", ylabel="", image_name="test", lines=None): """Should be used in two below sections! Creates one plot with two dependecies and fit them; return minimum fitted value of x2 and corresponding valume of y2; if name == "" image will not be plotted power - the power of polynom lines - add lines at x = 0 and y = 0 """ coeffs1 = np.polyfit(x1, y1, power) coeffs2 = np.polyfit(x2, y2, power) fit_func1 = np.poly1d(coeffs1) fit_func2 = np.poly1d(coeffs2) #x_min = fit_func2.deriv().r[power-2] #derivative of function and the second cooffecient is minimum value of x. #y_min = fit_func2(x_min) if name: x_range = np.linspace(min(x2), max(x2)) fit_y1 = fit_func1(x_range) fit_y2 = fit_func2(x_range) plt.figure(figsize=(8, 6.1)) # plt.title(name) plt.ylabel(ylabel) plt.xlabel(xlabel) plt.xlim( min(x2) - 0.1 * abs(min(x2)), max(x2) + 0.1 * abs(min(x2))) plt.plot(x1, y1, 'ro', label='initial') plt.plot(x2, y2, 'bo', label='relaxed') plt.plot( x_range, fit_y1, 'r-', ) #label = 'init_fit') plt.plot( x_range, fit_y2, 'b-', ) #label = 'r_fit' ) plt.legend(loc=9) if lines == 'xy': plt.axvline(color='k') plt.axhline(color='k') plt.tight_layout() #plt.savefig('images/'+image_name) file = header.path_to_images + '/' + str(image_name) + '.png' makedir(file) print_and_log('Saving file ...', file, imp='y') plt.savefig(file, format='png', dpi=300) return fit_func2 if list_of_calculations: conv = list_of_calculations n = conv[0] name = [] name.append(n[0]) image_name = n[0] + '_' + n[1] + '_' + str(n[2]) energies = [] init_energies = [] volumes = [] gb_volumes = [] pressures = [] pressures_init = [] sigma_xx = [] sigma_yy = [] sigma_zz = [] e_gbs = [] e_gbs_init = [] if type_of_plot == "e_imp": e_imps = [] v_imps = [] lengths = [] for id in conv: e_imps.append(calc[id].e_imp * 1000) v_imps.append(calc[id].v_imp) l = calc[id].vlength lengths.append("%s\n%.1f\n%.1f\n%.1f" % (id[0], l[0], l[1], l[2])) #l = lengths[0] #print str(l[0])+'\n'+str(l[1])+'\n'+str(l[2]) xlabel = "Sizes, $\AA$" ylabel = "Impurity energy, meV" ylabel2 = "Impurity volume, $\AA^3$" plt.figure() plt.title(str(name) + ' other cells') plt.ylabel(ylabel) plt.xlabel(xlabel) x = range(len(e_imps)) plt.xticks(x, lengths) plt.plot(x, e_imps, 'ro-', label='energy') plt.legend() plt.twinx() plt.ylabel(ylabel2) plt.plot(x, v_imps, 'bo-', label='volume') plt.subplots_adjust(left=None, bottom=0.2, right=None, top=None, wspace=None, hspace=None) #plt.ticker.formatter.set_scientific(True) plt.legend(loc=9) plt.savefig('images/e_imp_' + str(image_name) + '.png', format='png') #+str(image_name))#+'e_imp') if type_of_plot == "e_2imp": def dist_between_imp(cl): """Only for two impurities""" return np.linalg.norm( cl.end.xcart[-1] - cl.end.xcart[-2] ) #assuming that impurities are at the end of xcart list. e_imps = [] # binding energy dist = [] #dist between impurities e_imps_ex = [] dist_ex = [] name_ex = [] for id in conv: cl = calc[id] e_imps.append(cl.e_imp * 1000) #dist.append( "%s\n%.1f"%(id[0],dist_between_imp(cl) ) ) dist.append(dist_between_imp(cl)) xlabel = "Distance between atoms, $\AA$" ylabel = "Interaction energy, meV" plt.figure() # plt.title(str(name)+' v1-15') plt.ylabel(ylabel) plt.xlabel(xlabel) #x = range( len(e_imps) ) #plt.xticks(x, dist) # plt.yscale('log') # plt.yscale('semilog') if labelnames: label = labelnames else: label = [] label[0] = str(name) label[1] = name_ex[0] label[2] = name_ex[1] plt.plot(dist, e_imps, 'ro-', label=label[0], linewidth=2) if conv_ext: #manually add for conv in conv_ext: e_imps_ex.append([]) dist_ex.append([]) for id in conv: cl = calc[id] e_imps_ex[-1].append(cl.e_imp * 1000) #dist.append( "%s\n%.1f"%(id[0],dist_between_imp(cl) ) ) dist_ex[-1].append(dist_between_imp(cl)) name_ex.append(id[0]) plt.plot(dist_ex[0], e_imps_ex[0], 'go-', label=label[1], linewidth=2) plt.plot(dist_ex[1], e_imps_ex[1], 'bo-', label=label[2], linewidth=2) plt.axhline(color='k') #horizontal line plt.tight_layout() # plt.subplots_adjust(left=None, bottom=0.2, right=None, top=None, # wspace=None, hspace=None) # #plt.ticker.formatter.set_scientific(True) plt.legend(loc=9) plt.savefig(path_to_images + 'e_2imp_' + str(image_name) + '.png', format='png', dpi=300) #+str(image_name))#+'e_imp') if type_of_plot == "fit_gb_volume_pressure": for id in conv: #energies.append(calc[id].energy_sigma0) #init_energies.append( calc[id].list_e_sigma0[0] ) gb_volumes.append(calc[id].v_gb) #volumes.append(calc[id].end.vol) pressures.append(calc[id].extpress / 1000.) pressures_init.append(calc[id].extpress_init / 1000.) sigma_xx.append(calc[id].stress[0]) sigma_yy.append(calc[id].stress[1]) sigma_zz.append(calc[id].stress[2]) #pressures_init = pressures e_gbs.append(calc[id].e_gb) e_gbs_init.append(calc[id].e_gb_init) # print calc[id].bulk_extpress power = 3 fit_ve = fit_and_plot(gb_volumes, e_gbs_init, gb_volumes, e_gbs, power, name, "Grain boundary expansion (m$\AA$)", "Grain boundary energy (mJ/m$^2$)", image_name + "_fit_ve") fit = fit_and_plot(pressures_init, e_gbs_init, pressures, e_gbs, power, name, "External pressure (GPa)", "Grain boundary energy (mJ/m$^2$)", image_name + "_pe") #print fit ext_p_min = fit.deriv().r[ power - 2] #external pressure in the minimum; derivative of function and the value of x in minimum fit_sxe = fit_and_plot(sigma_xx, e_gbs_init, sigma_xx, e_gbs, power, name, "Sigma xx (MPa)", "Grain boundary energy (mJ/m$^2$)", image_name + "_sxe") sxe_min = fit_sxe.deriv().r[power - 2] #sigma xx at the minimum of energy print_and_log("sigma xx at the minimum of energy is", sxe_min, " MPa") fit1 = fit_and_plot(pressures_init, gb_volumes, pressures, gb_volumes, 1, name, "External pressure (GPa)", "Grain boundary expansion (m$\AA$)", image_name + "_pv", lines='xy') #print fit1 pulay = -calc[id].bulk_extpress #print " At external pressure of %.0f MPa; Pulay correction is %.0f MPa." % (ext_p_min+pulay, pulay) #print " Egb = %.1f mJ m-2; Vgb = %.0f mA;"%(fit(ext_p_min), fit1(ext_p_min) ) print_and_log("%s.fit.pe_pv & %.0f & %.0f & %0.f & %0.f \\\\" % (n[0] + '.' + n[1], fit(ext_p_min), fit1(ext_p_min), ext_p_min, ext_p_min + pulay)) #print "\n At zero pressure with Pullay correction:" #print " Egb = %.1f mJ m-2; Vgb = %.0f mA; " % (fit(-pulay), fit1(-pulay)) outstring = ("%s.fit.pe_pv & %.0f & %.0f & %0.f & %0.f\\\\" % (n[0] + '.' + n[1], fit(-pulay), fit1(-pulay), -pulay, 0)) # print outstring calc[conv[0]].egb = fit(-pulay) calc[conv[0]].vgb = fit1(-pulay) return outstring #fit(ext_p_min), fit1(ext_p_min) if type_of_plot == "fit_gb_volume": """ should be rewritten using fit_and_plot() function """ for id in conv: #energies.append(calc[id].energy_sigma0) #init_energies.append( calc[id].list_e_sigma0[0] ) gb_volumes.append(calc[id].v_gb) e_gbs.append(calc[id].e_gb) e_gbs_init.append(calc[id].e_gb_init) power = 3 fit_ve = fit_and_plot(gb_volumes, e_gbs_init, gb_volumes, e_gbs, power, name, "Excess volume ($m\AA$)", "Twin energy ($mJ/m^2$)", image_name + "_fit_ve") vgb_min = fit_ve.deriv().r[power - 2] #print "Fit of excess volume against energy. Pressure is uknown:" #print "Test Egb_min = %.1f mJ m-2; v_min = %.0f mA;"%(fit_ve(vgb_min), vgb_min) print("%s.fit.ve & %.0f & %.0f & - & - \\\\" % ( n[0] + '.' + n[1], fit_ve(vgb_min), vgb_min, )) if type_of_plot == "fit_gb_volume2": for id in conv: energies.append(calc[id].energy_sigma0) init_energies.append(calc[id].list_e_sigma0[0]) volumes.append(calc[id].end.vol) pressures.append(calc[id].extpress) pressures_init.append(calc[id].extpress_init) power = 3 pulay = 500 fit_ve = fit_and_plot(volumes, init_energies, volumes, energies, power, name, "Volume ($\AA^3$)", "Energy sigma->0 ($eV$)", image_name + "_fit_ve") Vmin = fit_ve.deriv().r[power - 2] # minimum volume at the minimum energy Emin = fit_ve(Vmin) fit_pe = fit_and_plot(pressures_init, init_energies, pressures, energies, power, name, "External pressure ($MPa$)", "Energy sigma->0 ($eV$)", image_name + "_fit_pe") ext_p_min = fit_pe.deriv().r[ power - 2] #external pressure in the minimum; derivative of function and the value of x in minimum fit_pv = fit_and_plot(pressures_init, volumes, pressures, volumes, 1, name, "External pressure ($MPa$)", "Volume of cell ($\AA^3$)", image_name + "_fit_pv") atP = (" Emin = %.3f meV; Vmin = %.0f A^3; "%( fit_pe(ext_p_min), fit_pv(ext_p_min) ) ) + \ (" for the minimum of energy relative to external pressure. The value of pressure is %.0f MPa; Pulay correction is %.0f MPa." % (ext_p_min+pulay, pulay) ) at_zeroP = (" Emin = %.3f meV; Vmin = %.0f A^3; " % (fit_pe(-pulay), fit_pv(-pulay) ) ) + \ (" the value of energy and volume at zero pressure with Pullay correction" ) #print " Emin = %.3f meV; Vmin = %.0f A^3; for the minimum of energy relative to volume at some external pressure"%(fit_ve(Vmin), Vmin ) #print atP #print at_zeroP print_and_log("Compare V at -pulay and V for energy minimum", fit_pv(-pulay), Vmin) return fit_pe(-pulay), fit_pv(-pulay), Emin, Vmin if type_of_plot == "kpoint_conv": energies = [] kpoints = [] times = [] for id in list_of_calculations: if "4" not in calc[id].state: continue energies.append(calc[id].potenergy) kpoints.append(calc[id].kspacing[2]) times.append(calc[id].time) name.append(id[1]) plt.figure() plt.title(name) plt.plot(kpoints, energies, 'bo-') plt.ylabel("Total energy (eV)") plt.xlabel("KSPACING along 3rd recip. vector ($\AA ^{-1}$)") plt.twinx() plt.plot(kpoints, times, 'ro-') plt.ylabel("Elapsed time (min)") plt.savefig('images/' + str(conv[0]) + 'kconv') if type_of_plot == "contour": alist = [] clist = [] nn = str(calc[conv[0]].id[0]) + "." + str(calc[conv[0]].id[1]) f = open("a_c_convergence/" + nn + "/" + nn + ".out", "w") f.write("END DATASET(S)\n") k = 1 for id in conv: #Find lattice parameters and corresponding energies a = calc[id].a c = calc[id].c if a not in alist: alist.append(a) if c not in clist: clist.append(c) f.write("acell%i %f %f %f Bohr\n" % (k, calc[id].a / to_ang, calc[id].a / to_ang, calc[id].c / to_ang)) #print "etotal%i %f\n"%(k, calc[id].energy_sigma0/to_eV ), k += 1 X, Y = np.meshgrid(alist, clist) Z = np.zeros(X.shape) Zinv = np.zeros(X.shape) k = 1 for i in range(len(alist)): for j in range(len(clist)): for id in conv: if calc[id].a == alist[i] and calc[id].c == clist[j]: Z[i][j] = calc[id].energy_sigma0 Zinv[j][i] = calc[id].energy_sigma0 f.write("etotal%i %f\n" % (k, calc[id].energy_sigma0 / to_eV)) k += 1 f.write( "+Overall time at end (sec) : cpu= 976300.2 wall= 976512.8" ) f.close #Make two plots for different a and c plt.figure() plt.title(name) for i in range(len(alist)): plt.plot(clist, Z[i], 'o-', label='a=' + str(alist[i])) plt.legend() plt.ylabel("Total energy (eV)") plt.xlabel("c parameter ($\AA$)") plt.savefig('images/' + str(conv[0]) + 'c') plt.figure() plt.title(name) for j in range(len(clist)): plt.plot(alist, Zinv[j], 'o-', label='c=' + str(clist[j])) plt.legend() plt.ylabel("Total energy (eV)") plt.xlabel("a parameter ($\AA$)") plt.savefig('images/' + str(conv[0]) + 'a') #Make contour plt.figure() cf = plt.contourf(X, Y, Z, 20, cmap=plt.cm.jet) cbar = plt.colorbar(cf) cbar.ax.set_ylabel('Energy (eV)') plt.xlabel('$a$ ($\AA$)') plt.ylabel('$c/a$') plt.legend() plt.savefig('images/ru-contourf.png') #plt.show() #Make equation of state eos = EquationOfState(clist, Z[2]) v0, e0, B = eos.fit() #print "a = ", alist[2] print_and_log(''' v0 = {0} A^3 E0 = {1} eV B = {2} eV/A^3'''.format(v0, e0, B)) eos.plot('images/a[2]-eos.png') eos = EquationOfState(alist, Zinv[2]) v0, e0, B = eos.fit() #print "c = ", clist[2] print_and_log(''' v0 = {0} A^3 E0 = {1} eV B = {2} eV/A^3'''.format(v0, e0, B)) eos.plot('images/c[2]-eos.png') if type_of_plot == "dimer": if not cl: cl = calc[list_of_calculations[0]] x1 = [] #list of distances if cl.end.natom > 2: raise RuntimeError # print (cl.end.list_xcart) for xcart in cl.end.list_xcart: # x = xcart[1] # d = (x[0]**2 + x[1]**2 + x[2]**2)**0.5 d = np.linalg.norm(xcart[1] - xcart[0]) #assuming there are only two atoms print(xcart[0], xcart[1], d) x1.append(d) y1 = cl.list_e_without_entr power = 4 name = 'dimer' xlabel = 'Bond length' ylabel = 'Full energy' # print(x1, y1) coeffs1 = np.polyfit(x1, y1, power) fit_func1 = np.poly1d(coeffs1) x_range = np.linspace(min(x1), max(x1)) fit_y1 = fit_func1(x_range) f = fit_func1.deriv() min_e = fit_func1(f.r[2]).real printlog( "The minimum energy per atom and optimal length of dimer are {:.3f} eV and {:.3f} A" .format(min_e / 2., f.r[2].real), imp='Y') try: printlog( "The atomization energy for dimer is {:.3f} eV ; The energy of atom in box is taken from the provided b_id" .format(min_e - 2 * cl.e_ref), imp='Y') except: print('Reference energy was not found') plt.figure() plt.title(name) plt.ylabel(ylabel) plt.xlabel(xlabel) plt.plot(x1, y1, 'ro', label='init') plt.plot(x_range, fit_y1, 'r-', label='init_fit') if filename: path2saved, path2saved_png = process_fig_filename( filename, fig_format) if plot: plt.show() return
def insert_cluster(insertion, i_center, matrix, m_center): """ Take care of orientation; typat should be consistent Input: insertion - object of class Structure(), which is supposed to be inserted in matrix in such a way that i_center will be combined with m_center. matrix - object of class Structure(). i_center, m_center - numpy arrays (3). """ ins = copy.deepcopy(insertion) mat = copy.deepcopy(matrix) r = mat.rprimd for i, z in enumerate(ins.znucl): if z not in mat.znucl: mat.znucl.append(z) mat.ntypat += 1 mat.nznucl.append(ins.nznucl[i]) hproj = [(r[0][i] + r[1][i] + r[2][i]) * 0.5 for i in (0, 1, 2)] #projection of vectors on three axis for i, x in enumerate(ins.xcart): ins.xcart[i] = x - i_center for i, x in enumerate(mat.xcart): mat.xcart[i] = x - m_center max_dis = 1 for i_x, ix in enumerate(ins.xcart): dv_min = max_dis print_and_log( "Insertion atom ", ix, ) for j, mx in enumerate(mat.xcart): dv = mx - ix for i in 0, 1, 2: if dv[i] > hproj[i]: dv = dv - mat.rprimd[ i] #periodic boundary conditions - can be not correct (in the sense that closest image can lie not 100 % in the neighbourhood image cell ) for oblique cells and large absolute values of dv if dv[i] < -hproj[i]: dv = dv + mat.rprimd[i] len1 = np.linalg.norm(dv) len2, second_len2 = mat.image_distance(mx, ix, r, 2) #check len1 #print "Lengths calculated with two methods ", len1, len2 len1 = len2 #just use second method #assert np.around(len1,1) == np.around(len2,1) if len1 < dv_min: dv_min = len1 j_r = j # number of matrix atom to replace if dv_min == max_dis: print_and_log(" is more far away from any matrix atom than ", dv_min, " A; I insert it") mat.xcart.append(ix) print_and_log('type of added atom is ', ins.typat[i_x]) mat.typat.append(ins.typat[i_x]) else: print_and_log("will replace martix atom", mat.xcart[j_r]) mat.xcart[j_r] = ix.copy() mat.rprimd = r mat.xcart2xred() mat.natom = len(mat.xcart) mat.name = 'test_of_insert' write_xyz(mat) return mat
def add_impurity(it_new, impurity_type = None, addtype = 'central', calc = [], r_pore = 0.5, it_to = '', ise_to = '', verlist_to = [], copy_geo_from = "", find_close_to = (),add_to_version = 0, write_geo = True, only_version = None, fine = 4, put_exactly_to = None, check_pore_vol = 0, replace_atom = None, override = False): """ Add impurities in pores. Input: it_new - name of new structure with impurity impurity_type - name of impurity from Mendeley table, for example 'C' addtype - type of adding: ['central',]; 'central' means that impurity will be placed as close to the geometrical center of cell as possible. it_to , ise_to , verlist_to - completed calculations in which impurity will be added if 'verlist_to' is empty, function will try to find geometry files in 'geo_folder + struct_des[it_to].sfolder' folder; even if 'it_to' is empty it will try to find files in 'geo_folder + struct_des[it_new].sfolder+'/from' ' folder. 'ise_to' also can be empty if 'copy_geo_from' is not empty, then programm copy all files from folder 'copy_geo_from' to folder 'geo_folder + struct_des[it_to].sfolder+"/"+it_to' or 'geo_folder + struct_des[it_new].sfolder+"/from" ' 'find_close_to' is tuple of three reduced coordinates of point close to which you want to find impurity. If empty - ignored; 'add_to_version' is integer number added to each 'verlist_to' number to produce ver_new. 'only_version' - if == [v,], then instertion will be provided only for v. If None insertion will be made in all found versions If you want to add impurity to relaxed structure ... 'fine' - integer number; allows to reduce number of small steps for defining center Possible addtype's: 'central' - add one atom to the pore which is most close to the center of the cell but with reduced coordinates less than 0.5 0.5 0.5 'all_pore' - add atoms in every found pore 'all_local' - add atoms to every local point which allows to visualise topology of pores. 'gb' - uses self.gbpos and places atom close to this value assuming that it will be at gb 'grain_vol' - uses self.gbpos and assuming that cell contains two gb and two equal grains, places atom close to the centre of grain; y and z can be arbiratry put_exactly_to - will add impurity to this point find_close_to - will try to find closest void and insert pore here. check_pore_vol - allows to estimate volume of pores; has problems for big cells replace_atom - if not None, than the specified atom is substituted Side effects: creates new geometry folder with input structures; """ struct_des = header.struct_des def test_adding_of_impurities(added, init, v): """ Can be used only inside add_impurity() Replicates the structure and find again pores """ global natoms_v1 if added == None: return if v == 1: #TEST natoms_v1 = len(added.init.xcart) # for test st_rep_after = replic( added.init, (1,2,1) ) rep = copy.deepcopy(init) rep.init = replic( rep.init, (1,2,1) ); #print rep rep = add(znucl, "", rep, write_geo = False) #print rep #print "xcart of replic after adding ", st_rep_after.xcart #print "xcart of adding to replic ", rep.init.xcart if len(st_rep_after.xcart) != len(rep.init.xcart): raise RuntimeError p = 0 #for x2 in st_rep_after.xcart: # print x2 for x in rep.init.xcart: a = any( ( np.around(x2, p) == np.around(x, p) ).all() for x2 in st_rep_after.xcart ) #b = any( ( np.ceil(x2, p) == np.ceil(x, p) ).all() for x2 in st_rep_after.xcart ) #c = any( ( np.floor(x2, p) == np.floor(x, p) ).all() for x2 in st_rep_after.xcart ) #print a, b, c #np.concatenate(a, b, c): if not a: print_and_log( "Error! Can't find ", np.around(x,3), "in replic ") raise RuntimeError #assert all([ all( np.around(v1, 8) == np.around(v2, 8) ) for (v1, v2) in zip(st_rep_after.xcart, rep.init.xcart) ]) print_and_log( "add_impurity: test succesfully done") if natoms_v1 != len(added.init.xcart): print_and_log("You have different number of pores in different versions\n"); raise RuntimeError return def add(znucl, xyzpath = "", new = None, write_geo = True, put_exactly_to = None): "if put_exactly_to is True, then atom just added and nothing are searched" if write_geo and os.path.exists(new.path["input_geo"]) and not override: print_and_log("add: File '"+new.path["input_geo"]+"' already exists; continue\n", imp = 'Y'); return new #new.init = return_atoms_to_cell(new.init) if replace_atom: #atom substitution if znucl not in new.init.znucl: new.init.znucl.append(znucl) new.init.ntypat+=1 new.init.typat[replace_atom] = new.init.ntypat else: ind = new.init.znucl.index(znucl) new.init.typat[replace_atom] = ind + 1 new.init.nznucl = [] for typ in range(1, new.init.ntypat+1): new.init.nznucl.append(new.init.typat.count(typ) ) else: new_before = copy.deepcopy(new) # new.init.xcart[-2][0]-=0.9 #was made once manually for c1gCOi10.1 # new.init.xcart[-2][2]+=0.2 # new.init.xred = xcart2xred(new.init.xcart, new.init.rprimd) write_xyz(new.init) #step = 0.042 step = 0.06 #r_pore = 0.56 #fine = 0.3 # for visualisation of pores #fine = 4 #controls small steps; the steps are smaller for larger numbers #r_pore = 0.54 prec = 0.004 # precision of center Angs if new.hex_a == None: r_mat = 1.48 -step else: r_mat = new.hex_a / 2 - step if put_exactly_to: pores_xred = [np.array(put_exactly_to),] print_and_log( 'Inmpurity just put in ', pores_xred, imp = 'Y') else: pores = find_pores(new.init, r_mat, r_pore, step, fine, prec, addtype, new.gbpos, find_close_to, check_pore_vol) #octahedral pores_xred = pores.xred npores = len(pores_xred) st = new.init #delete last oxygen; was made once manually for c1gCOi10.1 # st.natom-=1 # del st.xred[-1] # del st.typat[-1] st.natom += npores st.xred.extend( pores_xred ) if znucl in st.znucl: print_and_log( "znucl of added impurity is already in cell") ind = st.znucl.index(znucl) typat = ind+1 st.nznucl[ind]+=npores else: st.ntypat +=1 typat = st.ntypat st.znucl.append( znucl ) st.nznucl.append( npores ) for i in range( npores ): st.typat.append( typat ) st.xcart = xred2xcart(st.xred, st.rprimd) new.init = st #print "Add impurity: len(xred ", len(new.init.xred) #print "natom", new.init.natom #For automatisation of fit try: #new.build if new.build.nadded == None: new.build.nadded=npores else: new.build.nadded+=npores if new.build.listadded == [None]: new.build.listadded = range(new.natom - npores, new.natom) #list of atoms which were added else: new.build.listadded.extend( range(new.natom - npores, new.natom) ) #print "Warning!!! Information about added impurities rewritten" except AttributeError: pass #new.init.znucl = new.znucl #new.init.typat = new.typat #write_xyz(replic(new.init, (2,1,2)) , xyzpath) #test_adding_of_impurities(new, new_before, v) print_and_log("Impurity with Z="+str(znucl)+" has been added to the found pore in "+new.name+"\n\n") if write_geo: write_xyz(new.init , xyzpath) new.write_geometry("init",new.des, override = override) print_and_log( "\n") return new """0.Begin----------------------------------------------------------------------------""" znucl = element_name_inv(impurity_type) if impurity_type != 'octa' and impurity_type not in it_new: print_and_log("add_impurity: Your name 'it_new' is incorrect!\n\n") raise RuntimeError #del header.history[-2] # #hstring = ("add_impurity('%s', '%s', '%s', calc, %.3f, '%s', '%s', %s, '%s') #at %s" % # (it_new, impurity_type, addtype, r_pore, # it_to, ise_to, verlist_to, copy_geo_from, # datetime.date.today() ) ) hstring = ("%s #on %s"% (traceback.extract_stack(None, 2)[0][3], datetime.date.today() ) ) if hstring != header.history[-1]: header.history.append( hstring ) #geo_exists = """1. The case of insertion to existing calculations--------------------------------------------------""" if verlist_to: for v in verlist_to: if only_version and v not in only_version: continue # only_version = None works for all versions id = (it_to, ise_to, v) new = copy.deepcopy(calc[id]) new.init = new.end #replace init structure by the end structure new.version = v+add_to_version new.name = it_new#+'.'+id[1]+'.'+str(id[2]) new.des = 'Obtained from '+str(id)+' by adding '+impurity_type+' impurity ' path_new_geo = struct_des[it_new].sfolder+"/"+it_new+"/"+it_new+'.imp.'+addtype+'.'+str(new.version)+'.'+'geo' new.init.name = it_new+".init."+str(new.version) xyzpath = struct_des[it_new].sfolder+"/"+it_new new.path["input_geo"] = geo_folder+path_new_geo print_and_log("File '"+new.path["input_geo"] +"' with impurity will be created\n"); #new.init.name = 'test_before_add_impurity' new = add(znucl, xyzpath, new, write_geo, put_exactly_to = put_exactly_to) """2. The case of insertion to geo files------------------------------------------------------------""" else: print_and_log("You does not set 'id' of relaxed calculation. I try to find geometry files in "+it_new+" folder\n") if it_to: geo_path = geo_folder + struct_des[it_to].sfolder + "/" + it_to else: geo_path = geo_folder + struct_des[it_new].sfolder + "/" + it_new+'/from' if copy_geo_from: print_and_log("You asked to copy geo files from "+copy_geo_from+" to " +geo_path+ " folder\n") #if not os.path.exists(os.path.dirname(geo_path)): runBash( "mkdir -p "+geo_path ) runBash( "cp "+copy_geo_from+"/* "+geo_path ) if os.path.exists(geo_path): print_and_log("Folder '"+geo_path +"' was found. Trying to add impurity\n"); else: print_and_log("Error! Folder "+geo_path+" does not exist\n"); raise RuntimeError #geofilelist = glob.glob(geo_path+'/*.geo*') #Find input_geofile #geofilelist = runBash('find '+geo_path+' -name "*grainA*.geo*" ').splitlines() #geofilelist = runBash('find '+geo_path+' -name "*.geo*" ').splitlines() geofilelist = glob.glob(geo_path+'/*.geo*') print_and_log( "There are several files here already: ", geofilelist, imp = 'y' ) #print 'find '+geo_path+' -name "*.geo*" ',geofilelist #return for input_geofile in geofilelist: v = int( runBash("grep version "+str(input_geofile) ).split()[1] ) if only_version and v not in only_version: continue # only_version = None works for all versions new = CalculationVasp() new.version = v new.name = input_geofile new.read_geometry(input_geofile) init = copy.deepcopy(new) igl = input_geofile.split("/") #new.name = igl[-3]+'/'+igl[-3] #+input_geofile new.name = struct_des[it_new].sfolder+"/"+it_new+"/"+it_new print_and_log( "New path and part of name of file is ", new.name, imp = 'Y') #return new.des = 'Obtained from '+input_geofile+' by adding '+impurity_type+' impurity ' #new.init.xred = new.xred #new.init.rprimd = new.rprimd #print new.rprimd new.init.name = new.name+'.imp.'+addtype+'.'+str(new.version) #new.path["input_geo"] = geo_folder+it_new+"/"+new.end.name+'.'+'geo' new.path["input_geo"] = geo_folder+"/"+new.init.name+'.'+'geo' #new.init.name = 'test_before_add_impurity' new = add(znucl, "", new, write_geo, put_exactly_to = put_exactly_to) return new.path["input_geo"] #return for last version
def plot_mep(atom_pos, mep_energies, image_name=None, filename=None, show=None, plot=1, fitplot_args=None, style_dic=None): """ Used for NEB method atom_pos (list) - xcart positions of diffusing atom along the path, mep_energies (list) - full energies of the system corresponding to atom_pos image_name - deprecated, use filename style_dic - dictionary with styles 'p' - style of points 'l' - style of labels 'label' - label of points plot - if plot or not """ from analysis import determine_barrier if filename is None: filename = image_name #Create if not style_dic: style_dic = {'p': 'ro', 'l': 'b-', 'label': None} if not fitplot_args: fitplot_args = {} atom_pos = np.array(atom_pos) data = atom_pos.T # tck, u = interpolate.splprep( data) #now we get all the knots and info about the interpolated spline path = interpolate.splev( np.linspace(0, 1, 500), tck ) #increase the resolution by increasing the spacing, 500 in this example path = np.array(path) diffs = np.diff(path.T, axis=0) path_length = np.linalg.norm(diffs, axis=1).sum() mep_pos = np.array([p * path_length for p in u]) if 0: #plot the path in 3d fig = plt.figure() ax = Axes3D(fig) ax.plot(data[0], data[1], data[2], label='originalpoints', lw=2, c='Dodgerblue') ax.plot(path[0], path[1], path[2], label='fit', lw=2, c='red') ax.legend() plt.show() # if '_mep' not in calc: calc['_mep'] = [ atom_pos, mep_energies ] # just save in temp list to use the results in neb_wrapper if hasattr(header, 'plot_mep_invert') and header.plot_mep_invert: # for vacancy mep_energies = list(reversed(mep_energies)) mine = min(mep_energies) eners = np.array(mep_energies) - mine xnew = np.linspace(0, path_length, 1000) # ynew = spline(mep_pos, eners, xnew ) # spl = CubicSpline(mep_pos, eners, bc_type = 'natural' ) # second-derivative zero # spl = CubicSpline(mep_pos, eners,) # # spl = CubicSpline(mep_pos, eners, bc_type = 'periodic') # spl = CubicSpline(mep_pos, eners, bc_type = 'clamped' ) #first derivative zero spl = scipy.interpolate.PchipInterpolator(mep_pos, eners) ynew = spl(xnew) diff_barrier = determine_barrier(mep_pos, eners) print_and_log('plot_mep(): Diffusion barrier =', round(diff_barrier, 2), ' eV', imp='y') # sys.exit() # print() path2saved = None if plot: # print(image_name) path2saved = fit_and_plot(orig=(mep_pos, eners, style_dic['p'], style_dic['label']), spline=(xnew, ynew, style_dic['l'], None), xlim=(-0.05, None), xlabel='Reaction coordinate ($\AA$)', ylabel='Energy (eV)', image_name=image_name, filename=filename, show=show, fig_format='eps', **fitplot_args) # print(image_name, filename) if 0: with open(filename + '.txt', 'w') as f: f.write('DFT points:\n') for m, e in zip(mep_pos, eners): f.write('{:10.5f}, {:10.5f} \n'.format(m, e)) f.write('Spline:\n') for m, e in zip(xnew, ynew): f.write('{:10.5f}, {:10.5f} \n'.format(m, e)) return path2saved, diff_barrier
def insert_cluster(insertion, i_center, matrix, m_center): """ Take care of orientation; typat should be consistent Input: insertion - object of class Structure(), which is supposed to be inserted in matrix in such a way that i_center will be combined with m_center. matrix - object of class Structure(). i_center, m_center - numpy arrays (3). """ ins = copy.deepcopy(insertion) mat = copy.deepcopy(matrix) r = mat.rprimd for i, z in enumerate(ins.znucl): if z not in mat.znucl: mat.znucl.append(z) mat.ntypat+=1 mat.nznucl.append( ins.nznucl[i] ) hproj = [ (r[0][i]+r[1][i]+r[2][i]) * 0.5 for i in (0,1,2) ] #projection of vectors on three axis for i, x in enumerate(ins.xcart): ins.xcart[i] = x - i_center for i, x in enumerate(mat.xcart): mat.xcart[i] = x - m_center max_dis = 1 for i_x, ix in enumerate(ins.xcart): dv_min = max_dis print_and_log( "Insertion atom ",ix,) for j, mx in enumerate(mat.xcart): dv = mx - ix for i in 0,1,2: if dv[i] > hproj[i]: dv = dv - mat.rprimd[i] #periodic boundary conditions - can be not correct (in the sense that closest image can lie not 100 % in the neighbourhood image cell ) for oblique cells and large absolute values of dv if dv[i] < -hproj[i]: dv = dv + mat.rprimd[i] len1 = np.linalg.norm(dv) len2, second_len2 = image_distance(mx, ix, r, 2) #check len1 #print "Lengths calculated with two methods ", len1, len2 len1 = len2 #just use second method #assert np.around(len1,1) == np.around(len2,1) if len1 < dv_min: dv_min = len1; j_r = j # number of matrix atom to replace if dv_min == max_dis: print_and_log( " is more far away from any matrix atom than ",dv_min," A; I insert it") mat.xcart.append( ix ) print_and_log( 'type of added atom is ', ins.typat[i_x]) mat.typat.append( ins.typat[i_x] ) else: print_and_log( "will replace martix atom", mat.xcart[j_r] ) mat.xcart[j_r] = ix.copy() mat.xred = xcart2xred(mat.xcart, r) mat.natom = len(mat.xcart) mat.name = 'test_of_insert' write_xyz(mat) return mat
def find_pores(st_in, r_matrix=1.4, r_impurity = 0.6, step_dec = 0.05, fine = 0.3, prec = 0.1, calctype = 'central', gbpos = 0, find_close_to = (), check_pore_vol = 0): """ st_in - input Structure() object r_impurity (A)- all pores smaller than this radius will be found r_matrix (A) - radius of matrix atoms disregarding to their type step_dec - scanning step of the cell in Angstroms fine - allows to change density of local points; local_step = step_dec/fine prec - precicion of pore center determination check_pore_vol - allows to estimate volume of pores; has problems for big cells 'find_close_to' - works in the cases of gb and grain_vol; allows to ignore all and find pore close to provided three reduced coordinates return - instance of Structure() class with coordinates of pores. Number and type of included pores depend on the argument of 'calctype'. """ xred = st_in.xred natom = len(xred) rprimd = st_in.rprimd name = st_in.name #print xred """Additional values""" # check_pore_vol = 1 #if calctype in ("pore_vol","gb","grain_vol","all_local" ): check_pore_vol = 1 #something wrong with this function, especially for big cells """----Conversions of types for C++""" r1 = create_c_array(rprimd[0], float) r2 = create_c_array(rprimd[1], float) r3 = create_c_array(rprimd[2], float) xred1 = (c_float * len(xred))(*[x[0] for x in xred]) xred2 = (c_float * len(xred))(*[x[1] for x in xred]) xred3 = (c_float * len(xred))(*[x[2] for x in xred]) max_npores = 10000; ntot = ctypes.c_int32(); npores = ctypes.c_int32() l_pxred1 = (c_float * max_npores)(0) #make static arrays fol local points l_pxred2 = (c_float * max_npores)(0) l_pxred3 = (c_float * max_npores)(0) l_npores = (ctypes.c_int32 * max_npores)(0) pxred1 = (c_float * max_npores)(0) #make static arrays natoms + npore pxred2 = (c_float * max_npores)(0) pxred3 = (c_float * max_npores)(0) """----Run C++ function""" print_and_log("Starting C++ function lib.findpores()...\n") lib.findpores ( check_pore_vol, \ max_npores, \ byref(ntot), l_pxred1, l_pxred2, l_pxred3, l_npores, \ byref(npores), pxred1, pxred2, pxred3, \ natom, xred1, xred2, xred3, \ c_float(r_matrix), c_float(r_impurity), c_float(step_dec), c_float(fine), c_float(prec), \ r1, r2, r3 ) print_and_log( "ntot is ", ntot.value) print_and_log( "l_npores[0] is ",l_npores[0]) v = np.zeros((3)) l_pxred = [] shift1 = 0; shift2 = 0 for i_por in range(npores.value): l_pxred.append( [] ) shift2+=l_npores[i_por] for i in range(shift1, shift2): v[0] = l_pxred1[i]; v[1] = l_pxred2[i]; v[2] = l_pxred3[i] l_pxred[i_por].append( v.copy() ) shift1 = shift2 if shift2 != ntot.value: print_and_log( "Error! final shift2 not equal to ntot") #print l_pxred[0] pxred = [] # only coordinates of pores #print pxred1[natom] for i in range(npores.value): v[0] = pxred1[i+natom]; v[1]= pxred2[i+natom]; v[2] = pxred3[i+natom] #with shift, because first natom elements are coordinates of atoms pxred.append( v.copy() ) #print pxred """----End of C++; result is two lists: lpxred - local geometry of all pores, pxred - coordinates of all pores""" """ Analyse of pores """ st_result = Structure() st_result.rprimd = rprimd targetp = np.array((0.,0.,0.)) if find_close_to: targetp = np.asarray(find_close_to) #targer point print_and_log( "Target point is ",targetp) a = step_dec/fine #the side of little cube formed by the mesh which is used to find spheres inside the pore. aaa = a*a*a #find most central pore if calctype == 'central': #return coordinates of the most central pore st_result.name = "central_pore_from "+name center = np.array((0.5,0.5,0.5))#center of cell d_min = 100 for x in pxred: d = np.linalg.norm(x - center) #print x, x-center, d if d < d_min and x[0] <= 0.5 and x[1] <= 0.5 and x[2] <= 0.5: d_min = d x_min = x print_and_log( "The closest pore to the center has coordinates",x_min) st_result.xred.append( x_min ) elif calctype == 'gb': #add impurity at gb st_result.name = "gb_pore_from "+name d_min = 100; #d2_min = 100 dt_min =100 i_min = 0; x_min = np.zeros((3)) for i, x in enumerate(pxred): #print "l_npores ",l_npores[i] d = abs(x[0] - gbpos/rprimd[0][0]) # #print x[0], d if find_close_to: closer = (np.linalg.norm(targetp - x) < dt_min) else: closer = ( d < d_min ) # and x[1]>0.3 and x[2]>0.3: if closer: x_pre = x_min i_pre = i_min d_min = d dt_min = np.linalg.norm(targetp - x) x_min = x i_min = i #find and add impurity in bulk #d2 = abs( x[0] - (gbpos/rprimd[0][0] - 0.25) ) #if d2 < d2_min: # d2_min = d2 # x2_min = x # i2_min = i #print "rprimd[0][0]", rprimd[0][0] print_and_log( "Position of boundary is ",gbpos/rprimd[0][0]) #x_min[0] = gbpos/rprimd[0][0] if find_close_to: print_and_log( "The closest pore to the target point is [ %.2f %.2f %.2f ]"%(x_min[0], x_min[1], x_min[2])) else: print_and_log( "The closest pore to the gb has coordinates",x_min) st_result.xred.append( x_min ) #st_result.xred.append( x_pre ) #Calculate volume of the pore using local balls: print_and_log( "The number of pore is ",i_min," ; It has ",l_npores[i_min], "local balls") print_and_log( "Volume of pore is ", l_npores[i_min] * a*a*a, " A^3") #st_result.xred.extend( l_pxred[i_min] ) #st_result.xred.extend( l_pxred[i_pre] ) #print "The closest pore to the center of bulk has coordinates",x2_min #st_result.xred.append( x2_min ) #Calculate volume of the pore using local balls: #print "The number of bulk pore is ",i2_min," ; It has ",l_npores[i2_min], "local balls" #print "Volume of pore is ", l_npores[i2_min] * a*a*a, " A^3"; #st_result.xred.extend( l_pxred[i2_min] ) elif calctype == 'grain_vol': #add impurity to volume of grain st_result.name = "grain_volume_pore_from "+name d2_min = 100 dt_min = 100 i_min = 0; x_min = np.zeros((3)) for i, x in enumerate(pxred): #find and add impurity to the bulk d2 = abs( x[0] - (gbpos/rprimd[0][0] - 0.25) ) if find_close_to: closer = (np.linalg.norm(targetp - x) < dt_min) else: closer = ( d2 < d2_min ) # and x[1]>0.3 and x[2]>0.3: if closer: dt_min = np.linalg.norm(targetp - x) d2_min = d2 x2_min = x i2_min = i if find_close_to: print_and_log( "The closest pore to the target point is [ %.2f %.2f %.2f ]"%(x2_min[0], x2_min[1], x2_min[2])) else: print_and_log( "The closest pore to the center of bulk has coordinates",x2_min) st_result.xred.append( x2_min ) #Calculate volume of the pore using local balls: print_and_log( "The number of bulk pore is ",i2_min," ; It has ",l_npores[i2_min], "local balls") print_and_log( "Volume of pore is ", l_npores[i2_min] * a*a*a, " A^3") st_result.xred.extend( l_pxred[i2_min] ) elif calctype == 'all_local': st_result.name = "all_local_points_from "+name v_max = 0 i_max = 0 for i in range(npores.value): v_pore = l_npores[i] * aaa print_and_log( "Volume of pore is ", l_npores[i] * aaa, " A^3") if v_pore > v_max: v_max = v_pore; i_max = i print_and_log( "Pore number ", i_max,"has the largest volume ", v_max," A^3") # st_result.xred = l_pxred[i_max] # here coordinates of all local points to show geometry of pore with largerst volume st_result.xred = [x for group in l_pxred for x in group ] # all pores elif calctype == 'all_pores': st_result.name = "all_local_pores_from "+name st_result.xred = pxred st_result.xcart = xred2xcart(st_result.xred, rprimd) st_result.typat = [1 for x in st_result.xred] st_result.natom = len(st_result.typat) st_result.znucl = [200] st_ntypat = 1 return st_result
def insert(it_ins, ise_ins, mat_path, it_new, calc, type_of_insertion = "xcart" ): """For insertion of atoms to cells with changed lateral sizes Input: 'type_of_insertion = xred' used to add xred coordinates mat_path - path to geo files which are supposed to be changed it_ins - already existed calculation; xred will be used from this calculation. it_new - new folder in geo folder for obtained structure This function finds version of calculation in folder mat_path and tries to use the same version of it_ins """ if not os.path.exists(mat_path): print_and_log("Error! Path "+mat_path+" does not exist\n\n") raise RuntimeError if it_ins not in mat_path and it_ins not in it_new: print_and_log('Cells are', it_ins, mat_path, it_new) print_and_log("Error! you are trying to insert coordinates from cell with different name\n\n") #raise RuntimeError hstring = ("%s #on %s"% (traceback.extract_stack(None, 2)[0][3], datetime.date.today() ) ) if hstring != header.history[-1]: header.history.append( hstring ) geofilelist = runBash('find '+mat_path+'/target -name "*.geo*" ').splitlines() if geofilelist == []: print_and_log("Warning! Target folder is empty. Trying to find in root folder ...") geofilelist = runBash('find '+mat_path+'/ -name "*.geo*" ').splitlines() ins = None for mat_geofile in geofilelist: mat = CalculationVasp() mat.name = mat_geofile mat.read_geometry(mat_geofile) #step = 0.27 #r_pore = 0.56 #r_mat = mat.hex_a / 2 - step #pores = find_pores(mat.init, r_mat, r_pore, step, 0.3, 'central') #octahedral #mat.xcart.append ( pores.xcart[0] ) #mat.typat.append(1) try: ins_working = ins ins = calc[(it_ins, ise_ins, mat.version)] except KeyError: print_and_log( "No key", (it_ins, ise_ins, mat.version), "I use previous working version !!!", imp = 'y' ) ins = ins_working #return #ins.end.znucl = ins.znucl #ins.end.nznucl = ins.nznucl #ins.end.ntypat = ins.ntypat #ins.end.typat = ins.typat #print ins.xcart[-1] mat_geopath = geo_folder+struct_des[it_new].sfolder + '/' if type_of_insertion == "xcart": #Please update here! mat_filename = '/'+it_new+"."+"inserted."+str(mat.version)+'.'+'geo' v = np.zeros(3) result = insert_cluster(ins.end, v, mat.init, v ) mat.end = result mat.init = result # mat.znucl = mat.end.znucl # mat.nznucl = mat.end.nznucl # mat.ntypat = mat.end.ntypat # mat.typat = mat.end.typat # mat.natom = len(mat.end.xred) #mat.version = ins.version des = ins.name+" was inserted to "+mat_geofile elif type_of_insertion == "xred": mat_filename = '/from/'+it_new+".xred."+str(mat.version)+'.'+'geo' #mat.end.rprimd = mat.rprimd #mat.init.xred = copy.deepcopy(ins.end.xred) #mat.init.typat = copy.deepcopy(ins.end.) #print ins.end.xcart rprimd = copy.deepcopy(mat.init.rprimd) #build = mat.build mat.init = copy.deepcopy(ins.end) #mat.build = build mat.init.rprimd = rprimd #return initial rprimd mat.init.xcart = xred2xcart(mat.init.xred, mat.init.rprimd) #calculate xcart with new rprimd des = "atoms with reduced coord. from "+ins.name+" was fully copied to "+mat_geofile mat.init.name = 'test_insert_xred'+str(mat.version) write_xyz(mat.init) mat.path["input_geo"] = mat_geopath + it_new + mat_filename if not mat.write_geometry("init",des): continue print_and_log("Xred from "+it_ins+" was inserted in "+mat_geofile+" and saved as "+mat_filename+" \n\n") return
def add(znucl, xyzpath="", new=None, write_geo=True, put_exactly_to=None): "if put_exactly_to is True, then atom just added and nothing are searched" if write_geo and os.path.exists( new.path["input_geo"]) and not override: print_and_log("add: File '" + new.path["input_geo"] + "' already exists; continue\n", imp='Y') return new #new.init = return_atoms_to_cell(new.init) if replace_atom: #atom substitution if znucl not in new.init.znucl: new.init.znucl.append(znucl) new.init.ntypat += 1 new.init.typat[replace_atom] = new.init.ntypat else: ind = new.init.znucl.index(znucl) new.init.typat[replace_atom] = ind + 1 new.init.nznucl = [] for typ in range(1, new.init.ntypat + 1): new.init.nznucl.append(new.init.typat.count(typ)) else: new_before = copy.deepcopy(new) # new.init.xcart[-2][0]-=0.9 #was made once manually for c1gCOi10.1 # new.init.xcart[-2][2]+=0.2 # new.init.xred = xcart2xred(new.init.xcart, new.init.rprimd) write_xyz(new.init) #step = 0.042 step = 0.06 #r_pore = 0.56 #fine = 0.3 # for visualisation of pores #fine = 4 #controls small steps; the steps are smaller for larger numbers #r_pore = 0.54 prec = 0.004 # precision of center Angs if new.hex_a == None: r_mat = 1.48 - step else: r_mat = new.hex_a / 2 - step if put_exactly_to: pores_xred = [ np.array(put_exactly_to), ] print_and_log('Inmpurity just put in ', pores_xred, imp='Y') else: pores = find_pores(new.init, r_mat, r_pore, step, fine, prec, addtype, new.gbpos, find_close_to, check_pore_vol) #octahedral pores_xred = pores.xred npores = len(pores_xred) st = new.init #delete last oxygen; was made once manually for c1gCOi10.1 # st.natom-=1 # del st.xred[-1] # del st.typat[-1] st.natom += npores st.xred.extend(pores_xred) if znucl in st.znucl: print_and_log("znucl of added impurity is already in cell") ind = st.znucl.index(znucl) typat = ind + 1 st.nznucl[ind] += npores else: st.ntypat += 1 typat = st.ntypat st.znucl.append(znucl) st.nznucl.append(npores) for i in range(npores): st.typat.append(typat) st.xred2xcart() new.init = st #print "Add impurity: len(xred ", len(new.init.xred) #print "natom", new.init.natom #For automatisation of fit try: #new.build if new.build.nadded == None: new.build.nadded = npores else: new.build.nadded += npores if new.build.listadded == [None]: new.build.listadded = range( new.natom - npores, new.natom) #list of atoms which were added else: new.build.listadded.extend( range(new.natom - npores, new.natom)) #print "Warning!!! Information about added impurities rewritten" except AttributeError: pass #new.init.znucl = new.znucl #new.init.typat = new.typat #write_xyz(replic(new.init, (2,1,2)) , xyzpath) #test_adding_of_impurities(new, new_before, v) print_and_log("Impurity with Z=" + str(znucl) + " has been added to the found pore in " + new.name + "\n\n") if write_geo: write_xyz(new.init, xyzpath) new.write_geometry("init", new.des, override=override) print_and_log("\n") return new
def add_neb(starting_calc = None, st = None, it_new = None, ise_new = None, i_atom_to_move = None, up = 'up1', search_type = 'vacancy_creation', images = 3, r_impurity = None, corenum = 15, calc_method = ['neb'], inherit_option = None, mag_config = None, i_void_start = None, i_void_final = None, atom_to_insert = None, replicate = None, it_new_folder = None, inherit_magmom = False, x_start = None, xr_start = None, x_final = None, xr_final = None, upload_vts = False, run = False ): """ Prepare needed files for NEB Provides several regimes controlled by *search_type* flag: - existing_voids - search for voids around atom and use them as a final position - vacancy_creation - search for neighbors of the same type and make a vacancy as a start position - interstitial_insertion - search for two neighboring voids; use them as start and final positions by inserting atom *atom_to_insert* ###INPUT: - starting_calc (Calculation) - Calculation object with structure - st (Structure) - structure, can be used instead of Calculation - it_new (str) - name for calculation - i_atom_to_move (int) - number of atom for moving; - *mag_config* (int ) - choose magnetic configuration - allows to obtain different localizations of electron - *replicate* (tuple 3*int) - replicate cell along rprimd - i_void_start, i_void_final (int) - number of voids from the suggested lists - atom_to_insert (str) - element name of atom to insert - it_new_folder (str) - section folder - inherit_option (str) - passed only to add_loop - inherit_magmom (bool) - if True than magmom from starting_calc is used, else from set - calc_method (list) - 'neb' - 'only_neb' - run only footer - x_start, x_final (array) - explicit coordinates of moving atom for starting and final positions, combined with atom_to_insert - upload_vts (bool) - if True upload Vasp.pm and nebmake.pl to server - run (bool) - run on server ###RETURN: None ###DEPENDS: ###TODO please take care of manually provided i_atom_to_move in case of replicate flag using init_numbers """ calc = header.calc struct_des = header.struct_des varset = header.varset if not hasattr(calc_method, '__iter__'): calc_method = [calc_method] if starting_calc and st: printlog('Warning! both *starting_calc* and *st* are provided. I use *starting_calc*') st = copy.deepcopy(starting_calc.end) elif starting_calc: st = copy.deepcopy(starting_calc.end) printlog('I use *starting_calc*') elif st: '' printlog('I use *st*') else: printlog('Error! no input structure. Use either *starting_calc* or *st*') if corenum: # header.corenum = corenum '' else: corenum = header.CORENUM if corenum % images > 0: print_and_log('Error! Number of cores should be dividable by number of IMAGES') name_suffix = '' st_pores = [] name_suffix+='n'+str(images) """Replicate cell """ if replicate: print_and_log('You have chosen to replicate the structure by', replicate) st = replic(st, mul = replicate) name_suffix += str(replicate[0])+str(replicate[1])+str(replicate[2]) """1. Choose atom (or insert) for moving """ atoms_to_move = [] for i, typ, x in zip(range(st.natom), st.typat, st.xcart): #try to find automatically if st.znucl[typ-1] == 3: #Li atoms_to_move.append([i, 'Li', x]) if st.znucl[typ-1] == 11: # atoms_to_move.append([i, 'Na', x]) if st.znucl[typ-1] == 19: # atoms_to_move.append([i, 'K', x]) if is_list_like(xr_start): x_start = xred2xcart([xr_start], st.rprimd)[0] st1 = st.add_atoms([x_start], atom_to_insert) x_m = x_start name_suffix+='s' write_xyz(st1, file_name = st.name+'_manually_start') printlog('Start position is created manually by adding xr_start', xr_start, x_start) elif not atoms_to_move: print_and_log('No atoms to move found, you probably gave me intercalated structure', important = 'y') print_and_log('Searching for voids', important = 'y') st_pores = find_pores(st, r_matrix = 0.5, r_impurity = r_impurity, fine = 1, calctype = 'all_pores') print_and_log('List of found voids:\n', np.array(st_pores.xcart) ) write_xyz(st.add_atoms(st_pores.xcart, 'H'), file_name = st.name+'_possible_positions') write_xyz(st.add_atoms(st_pores.xcart, 'H'), replications = (2,2,2), file_name = st.name+'_possible_positions_replicated') sums = [] avds = [] for x in st_pores.xcart: summ = local_surrounding(x, st, n_neighbours = 6, control = 'sum', periodic = True) avd = local_surrounding(x, st, n_neighbours = 6, control = 'av_dev', periodic = True) # print sur, sums.append(summ) avds.append(avd[0]) # print sums = np.array(sums) avds = np.array(avds).round(0) print_and_log('Sum of distances to 6 neighboring atoms for each void (A):\n', sums, imp ='y') print_and_log('Distortion of voids (0 - is symmetrical):\n', avds, imp ='y') crude_prec = 1 sums_crude = np.unique(sums.round(crude_prec)) print_and_log('The unique voids based on the sums:', '\nwith 0.01 A prec:',np.unique(sums.round(2)), '\nwith 0.1 A prec:',sums_crude, imp ='y') print_and_log('Based on crude criteria only', len(sums_crude),'types of void are relevant') print_and_log('Please use *i_void_start* to choose the void for atom insertion from this Table:', end = '\n', imp = 'Y') insert_positions = [] start_table = [] for i, s in enumerate(sums_crude): index_of_first = np.where(sums.round(crude_prec)==s)[0][0] start_table.append([i, st_pores.xcart[index_of_first].round(2), index_of_first, avds[index_of_first], sums[index_of_first] ]) insert_positions.append( st_pores.xcart[index_of_first] ) print_and_log( tabulate(start_table, headers = ['Start void #', 'Cart.', 'Index', 'Dev.', 'Sum'], tablefmt='psql'), imp = 'Y' ) if i_void_start == None: sys.exit() st = st.add_atoms([insert_positions[i_void_start],], atom_to_insert) name_suffix+='i'+str(i_void_start) i_m = st.natom-1 x_m = st.xcart[i_m] search_type = 'existing_voids' type_atom_to_move = atom_to_insert el_num_suffix = '' else: print_and_log('I have found', len(atoms_to_move), ' anion atoms', important = 'n') print_and_log( 'Sums of bond lengths around these atoms:',) sums = [] for a in atoms_to_move: summ = local_surrounding(a[2], st, n_neighbours = 6, control = 'sum', periodic = True) sums.append(summ) # print( summ, end = '') print_and_log('\nAmong them only',len(set(sums)), 'unique' , important = 'n') # if print_and_log('Choosing the first' , important = 'n') type_atom_to_move = atoms_to_move[0][1] i_atom_to_move = atoms_to_move[0][0]+1 el_num_suffix = type_atom_to_move +str(i_atom_to_move) i_m = i_atom_to_move-1 x_m = st.xcart[i_m] #highlight the moving atom for user for double-check # st_new = st.change_atom_z(i_m, new_z = 100) # search_type = 'vacancy_creation' """2. Choose final position""" if is_list_like(xr_final): x_final = xred2xcart([xr_final], st.rprimd)[0] st2 = st.add_atoms([x_final], atom_to_insert) x_del = x_final search_type = 'manual_insertion' name_suffix+='f'+atom_to_insert write_xyz(st2, file_name = st.name+'_manually_final') printlog('Final position is created manually by adding xr_final', xr_final, x_del) elif search_type == 'existing_voids': #Search for voids around choosen atoms if not st_pores: st_pores = find_pores(st, r_matrix = 0.5, r_impurity = r_impurity, fine = 2, calctype = 'all_pores') sur = local_surrounding(x_m, st_pores, n_neighbours = len(st_pores.xcart), control = 'atoms', periodic = True) # print sur print_and_log( 'I can suggest you '+str (len(sur[0])-1 )+' end positions.' ) # The distances to them are : '+str(np.round(sur[3], 2) )+' A\n ', # 'Openning Jmol end positions are highlighted by inserting H ', important = 'y') # print x_m # print sur[0] print_and_log('Please choose *i_void_final* from the following Table:', end = '\n', imp = 'Y') final_table = [] for i, (x, d, ind) in enumerate( zip(sur[0], sur[3], sur[2])[1:] ): final_table.append([i, np.array(x).round(2), round(d, 2), avds[ind], sums[ind] ] ) print_and_log( tabulate(final_table, headers = ['Final void #', 'Cart.', 'Dist', 'Dev.', 'Sum'], tablefmt='psql'), imp = 'Y' ) if i_void_final == None: sys.exit() x_final = sur[0][i_void_final+1] # +1 because first element is x_m atom itself write_xyz(st.add_atoms([ x_final], 'H'), replications = (2,2,2), file_name = st.name+'_possible_positions2_replicated') # sys.exit() # write_xyz(st.add_atoms(sur[0][2:3], 'H'), analysis = 'imp_surrounding', show_around = 230,nnumber = 10, replications = (2,2,2), file_name = 'local230') # # write_xyz(st.add_atoms(sur[0][0:1], 'H'), analysis = 'imp_surrounding', show_around = 226,nnumber = 10, replications = (2,2,2), file_name = 'local') # run_jmol print_and_log('Choosing the closest position as end', important = 'n') # i_void_final = 0 st1 = st # print st1.natom # sys.exit() st2 = st.mov_atoms(i_m, x_final) name_suffix += el_num_suffix+'e'+str(i_void_final)+atom_to_insert st1 = return_atoms_to_cell(st1) st2 = return_atoms_to_cell(st2) write_xyz(st1, file_name = st1.name+name_suffix +'_start') write_xyz(st2, file_name = st2.name+name_suffix +'_final') elif search_type == 'vacancy_creation': #Create vacancy by removing some neibouring atom of the same type print_and_log('You have chosen vacancy_creation mode of add_neb tool', important = 'Y') print_and_log( 'Type of atom to move = ', type_atom_to_move, imp = 'y') # print 'List of left atoms = ', np.array(st.leave_only(type_atom_to_move).xcart) sur = local_surrounding(x_m, st.leave_only(type_atom_to_move) , n_neighbours = 4, control = 'atoms', periodic = False) # print 'xcart of moving atom', x_m # print 'Local surround = ', sur # print 'len', len(sur[0]) if len(sur[0]) < 3: # print 'rprimd = \n',np.array(st.rprimd) # print 'r lengths = \n',( [np.linalg.norm(r) for r in st.rprimd] ) # print 'xred = \n', np.array(st.xred) # print 'xcart = \n', np.array(st.xcart) print_and_log('The supercell is too small, I increase it 8 times!') st = replic(st, mul = (2,2,2) ) sur = local_surrounding(x_m, st.leave_only(type_atom_to_move) , n_neighbours = 4, control = 'atoms', periodic = False) # print 'xcart of moving atom', x_m write_xyz(st, file_name = st.name+'_replicated')#replications = (2,2,2)) # print 'Local surround = ', sur # sys.exit() print_and_log( 'I can suggest you '+str (len(sur[0]) )+' end positions. The distances to them are : '+str(np.round(sur[3], 2) )+' A\n ', 'They are all', type_atom_to_move, 'atoms', important = 'y') print_and_log('Choosing the closest position as end', important = 'n') neb_config = 1 #cause the first item in sur is moving atom itself x_del = sur[0][neb_config] i_del = st.find_atom_num_by_xcart(x_del) print_and_log('Making vacancy at end position for starting configuration', important = 'n') print_and_log( 'number of atom to delete = ', i_del) # print st.magmom st1 = st.del_atom(i_del) # print st1.magmom print_and_log('Making vacancy at start position for final configuration', important = 'n') st2 = st.mov_atoms(i_m, x_del) # i_m and sur[0][neb_config] should coincide st2 = st2.del_atom(i_del) # these two steps provide the same order name_suffix += el_num_suffix+'v'+str(neb_config) write_xyz(st1, file_name = st1.name+'_start')# replications = (2,2,2)) write_xyz(st2, file_name = st2.name+'_end')# replications = (2,2,2)) # sys.exit() # sys.exit() """ Determining magnetic moments """ if varset[ise_new].vasp_params['ISPIN'] == 2: print_and_log('Magnetic calculation detected. Preparing spin modifications ...', imp = 'y') cl_test = CalculationVasp(varset[ise_new]) cl_test.init = st1 # print 'asdfsdfasdfsadfsadf', st1.magmom if inherit_magmom and hasattr(st, 'magmom') and st.magmom and any(st.magmom): print_and_log('inherit_magmom=True: You have chosen MAGMOM from provided structure', imp = 'y') name_suffix+='mp' #Magmom from Previous else: cl_test.init.magmom = None print_and_log('inherit_magmom=False or no magmom in input structure : MAGMOM will be determined from set', imp = 'y') name_suffix+='ms' #Magmom from Set cl_test.actualize_set() #find magmom for current structure st1.magmom = copy.deepcopy(cl_test.init.magmom) st2.magmom = copy.deepcopy(cl_test.init.magmom) # sys.exit() # print_and_log('The magnetic moments from set:') # print cl_test.init.magmom #checking for closest atoms now only for Fe, Mn, Ni, Co sur = local_surrounding(x_m, st1, n_neighbours = 3, control = 'atoms', periodic = True, only_elements = header.TRANSITION_ELEMENTS) dist = np.array(sur[3]).round(2) numb = np.array(sur[2]) a = zip(numb, dist ) # a= np.array(a) # print a[1] # a = np.apply_along_axis(np.unique, 1, a) # print a def unique_by_key(elements, key=None): if key is None: # no key: the whole element must be unique key = lambda e: e return list ( {key(el): el for el in elements}.values() ) # print a mag_atoms_dists = unique_by_key(a, key=itemgetter(1)) # print (mag_atoms_dists) # a = unique_by_key(a, key=itemgetter(1)) print_and_log( 'I change spin for the following atoms:\ni atom dist\n', np.round(mag_atoms_dists, 2) , imp = 'y' ) # print 'I have found closest Fe atoms' muls = [(1.2, 0.6), (0.6, 1.2)] mag_moments_variants = [] for mm in muls: mags = copy.deepcopy(cl_test.init.magmom) # print mags for a, m in zip(mag_atoms_dists, mm): # print t[1] mags[a[0]] = mags[a[0]]*m mag_moments_variants.append(mags) print_and_log( 'The list of possible mag_moments:', imp = 'y' ) for i, mag in enumerate(mag_moments_variants): print_and_log( i, mag) print_and_log( 'Please use *mag_config* arg to choose desired config' , imp = 'y' ) if mag_config != None: st1.magmom = copy.deepcopy(mag_moments_variants[mag_config]) st2.magmom = copy.deepcopy(mag_moments_variants[mag_config]) name_suffix+='m'+str(mag_config) print_and_log('You have chosen mag configuration #',mag_config,imp = 'y') else: print_and_log('Non-magnetic calculation continue ...') """3. Add to struct_des, create geo files, check set, add_loop """ if starting_calc: it = starting_calc.id[0] it_new = it+'v'+str(starting_calc.id[2])+'.'+name_suffix if not it_new_folder: it_new_folder = struct_des[it].sfolder+'/neb/' obtained_from = str(starting_calc.id) if not ise_new: print_and_log('I will run add_loop() using the same set', important = 'Y') ise_new = cl.id[1] elif st: if not it_new: printlog('Error! please provide *it_new* - name for your calculation', important = 'Y') it = None it_new+='.'+name_suffix obtained_from = st.name if not ise_new: printlog('Error! please provide *ise_new*', important = 'Y') if not it_new_folder: printlog('Error! please provide *it_new_folder* - folder for your new calculation', important = 'Y') if it_new not in struct_des: add_des(struct_des, it_new, it_new_folder, 'Automatically created and added from '+obtained_from ) print_and_log('Creating geo files for starting and final configurations (versions 1 and 2) ', important = 'y') # if starting_calc: # cl = copy.deepcopy(starting_calc) # else: cl = CalculationVasp() #write start position struct_des[it_new].x_m_ion_start = x_m struct_des[it_new].xr_m_ion_start = xcart2xred([x_m], st1.rprimd)[0] cl.end = st1 ver_new = 1 cl.version = ver_new cl.path["input_geo"] = header.geo_folder + struct_des[it_new].sfolder + '/' + \ it_new+"/"+it_new+'.auto_created_starting_position_for_neb_'+search_type+'.'+str(ver_new)+'.'+'geo' cl.write_siman_geo(geotype = 'end', description = 'Starting conf. for neb from '+obtained_from, override = True) #write final position struct_des[it_new].x_m_ion_final = x_del struct_des[it_new].xr_m_ion_final = xcart2xred([x_del], st2.rprimd)[0] cl.end = st2 ver_new = 2 cl.version = ver_new cl.path["input_geo"] = header.geo_folder + struct_des[it_new].sfolder + '/' + \ it_new+"/"+it_new+'.auto_created_final_position_for_neb_'+search_type+'.'+str(ver_new)+'.'+'geo' cl.write_siman_geo(geotype = 'end', description = 'Final conf. for neb from '+obtained_from, override = True) #prepare calculations #Check if nebmake is avail # if int(runBash('ssh '+cluster_address+' test -e '+project_path_cluster+'/tools/vts/nebmake.pl; echo $?') ): # '' # print_and_log('Please upload vtsttools to ',cluster_address, project_path_cluster+'/tools/vts/') # raise RuntimeError # copy_to_server(path_to_wrapper+'/vtstscripts/nebmake.pl', to = project_path_cluster+'/tools/', addr = cluster_address) # if int(runBash('ssh '+cluster_address+' test -e '+project_path_cluster+'/tools/Vasp.pm; echo $?') ): # copy_to_server(path_to_wrapper+'/vtstscripts/Vasp.pm', to = project_path_cluster+'/tools/', addr = cluster_address) inherit_ngkpt(it_new, it, varset[ise_new]) add_loop(it_new, ise_new, verlist = [1,2], up = up, calc_method = calc_method, savefile = 'ov', inherit_option = inherit_option, n_neb_images = images, corenum = corenum, run =run ) if upload_vts: siman_dir = os.path.dirname(__file__) # print(upload_vts) push_to_server([siman_dir+'/cluster_tools/nebmake.pl', siman_dir+'/cluster_tools/Vasp.pm'], to = header.cluster_home+'/tools/vts', addr = header.cluster_address) else: print_and_log('Please be sure that vtsttools are at',header.cluster_address, header.cluster_home+'/tools/vts/', imp = 'Y') return it_new
def make_sets_for_conv(isefrom,conv,list_of_parameters,varset): varset[isefrom].add_conv( isefrom, conv ); i = len(varset[isefrom].conv[conv]) #print varset[isefrom].conv[conv] for param in list_of_parameters: newise = isefrom+conv[0:2]+str(i) ; i+=1 if newise in varset: print_and_log("Set %s already in varset; continue\n" %( str(newise) ) ) continue if conv == "kpoint_conv": for key in varset[isefrom].conv[conv]: if varset[key].ngkpt == param: print_and_log( "Set %s already contains param %s; please check; return; \n" %( str(key), str(param) ) ) return #print newise s = inherit_iset(newise, isefrom, varset,newblockfolder = conv) s.set_ngkpt(param) #print s elif conv == "tsmear_conv": for key in varset[isefrom].conv[conv]: if varset[key].tsmear == param: print_and_log( "Set %s already contains param %s; please check; return; \n" %( str(key), str(param) ) ) return s = inherit_iset(newise, isefrom, varset,newblockfolder = conv) s.set_tsmear(param) elif conv == "ecut_conv": #automatically set dilatmx == 1 for key in varset[isefrom].conv[conv]: if varset[key].vasp_params["ENCUT"] == param: print_and_log( "Set %s already contains param %s; please check; return; \n" %( str(key), str(param) ) ) return s = inherit_iset(newise, isefrom, varset,newblockfolder = conv) s.set_dilatmx(1.) s.set_ecut(param) else: print_and_log( "Warning! Unknown type of conv; return\n") return varset[isefrom].add_conv( newise, conv ) print_and_log( "The following sets are in varset[%s].conv %s \n"%(str(isefrom),str(varset[isefrom].conv) ) ) return
def fit_and_plot(ax=None, power=None, xlabel=None, ylabel=None, image_name=None, filename=None, show=None, pad=None, xlim=None, ylim=None, title=None, figsize=None, xlog=False, ylog=False, scatter=False, legend=False, ncol=1, fontsize=None, legend_fontsize=None, markersize=None, linewidth=None, hor=False, fig_format='eps', dpi=300, ver_lines=None, xy_line=None, x_nbins=None, alpha=0.8, fill=False, first=True, last=True, convex=None, dashes=None, corner_letter=None, hide_ylabels=None, hide_xlabels=None, annotate=None, **data): """ Plot multiple plots on one axes using *data* return filename of saved plot ax (axes) - matplotlib axes object - to create multiple axes plots data - each entry should be (X, Y, fmt) or (X, Y, fmt, label) or {'x':,'y':, 'fmt':, 'label', 'xticks' } not implemented for powers and scatter yet or (X, Y, R, fmt) - for scatter = 1, R - size of spots first, last - allows to call this function multiple times to put several plots on one axes. Use first = 1, last = 0 for the first plot, 0, 0 for intermidiate, and 0, 1 for last power (int) - the power of polynom, turn on fitting scatter (bool) - plot scatter points - the data format is slightly different - see *data* convex (bool) - plot convex hull around points like in ATAT fill (bool) - fill under the curves filename (str) - name of file with figure, image_name - deprecated fig_format (str) - format of saved file. dpi - resolution of saved file ver_lines - list of dic args for vertical lines {'x':, 'c', 'lw':, 'ls':} hide_ylabels - just hide numbers ncol - number of legend columns corner_letter - letter in the corner of the plot pad - additional padding, experimental annotate - annotate each point, 'annotates' list should be in data dic! linewidth - was 3 ! markersize - was 10 x_nbins - number of ticks TODO: remove some arguments that can be provided in data dict """ if image_name == None: image_name = filename if fontsize: header.mpl.rcParams.update({'font.size': fontsize + 4}) if legend_fontsize is None: legend_fontsize = fontsize header.mpl.rc('legend', fontsize=legend_fontsize) if hasattr(header, 'first'): first = header.first if hasattr(header, 'last'): last = header.last # print('fit_and_plot, first and last', first, last) if ax is None: if first: # fig, ax = plt.subplots(1,1,figsize=figsize) plt.figure(figsize=figsize) ax = plt.gca() # get current axes ))) # ax = fig.axes if title: ax.title(title) # print(dir(plt)) # print(ax) # plt.ylabel(ylabel, axes = ax) # print(ylabel) if ylabel != None: ax.set_ylabel(ylabel) if xlabel != None: '' # plt.xlabel(xlabel, axes = ax) ax.set_xlabel(xlabel) if corner_letter: # print(corner_letter) sz = header.mpl.rcParams['font.size'] ax.text(0.05, 0.85, corner_letter, size=sz * 1.5, transform=ax.transAxes ) # transform = None - by default in data coordinates! # text(x, y, s, bbox=dict(facecolor='red', alpha=0.5)) if convex: from scipy.spatial import ConvexHull for key in sorted(data): if scatter: ax.scatter(data[key][0], data[key][1], s=data[key][2], c=data[key][-1], alpha=alpha, label=key) else: con = data[key] # print(con) # sys.exit() if type(con) == list or type(con) == tuple: try: label = con[3] except: label = key try: fmt = con[2] except: fmt = '' xyf = [con[0], con[1], fmt] con = {'label': label} #fmt -color style elif type(con) == dict: if 'fmt' not in con: con['fmt'] = '' # print(con) if 'x' not in con: l = len(con['y']) con['x'] = list(range(l)) if 'xticks' in con: # print(con['xticks']) ax.set_xticklabels(con['xticks']) ax.set_xticks(con['x']) del con['xticks'] xyf = [con['x'], con['y'], con['fmt']] # if 'lw' in if linewidth: con['lw'] = linewidth # print(con) # sys.exit() if markersize: con['ms'] = markersize # print('key is ', key) # print('x ', xyf[0]) con_other_args = copy.deepcopy(con) for k in ['x', 'y', 'fmt', 'annotates']: if k in con_other_args: del con_other_args[k] ax.plot(*xyf, alpha=alpha, **con_other_args) if power: coeffs1 = np.polyfit(xyf[0], xyf[1], power) fit_func1 = np.poly1d(coeffs1) x_range = np.linspace(min(xyf[0]), max(xyf[0])) fit_y1 = fit_func1(x_range) ax.plot( x_range, fit_y1, xyf[2][0], ) # x_min = fit_func2.deriv().r[power-2] #derivative of function and the second cooffecient is minimum value of x. # y_min = fit_func2(x_min) slope, intercept, r_value, p_value, std_err = scipy.stats.linregress( xyf[0], xyf[1]) print('R^2 = {:5.2f} for {:s}'.format(r_value**2, key)) if annotate: if adjustText_installed: ts = [] for t, x, y in zip(con['annotates'], con['x'], con['y']): ts.append( ax.text(x, y, t, size=10, alpha=0.5, color=con['fmt'][0])) adjust_text( ts, ax=ax, # force_points=10, force_text=10, force_objects = 0.5, expand_text=(2, 2), expand_points=(2, 2), # lim = 150, expand_align=(2, 2), # expand_objects=(0, 0), text_from_text=1, text_from_points=1, # arrowprops=dict(arrowstyle='->', color='black') ) else: for name, x, y in zip(con['annotates'], con['x'], con['y']): ax.annotate( name, xy=(x, y), xytext=(-20, 20), fontsize=9, textcoords='offset points', ha='center', va='bottom', # bbox=dict(boxstyle='round,pad=0.2', fc='yellow', alpha=0.3), arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=0.5', color='black')) # print(key) # print(con) if fill: '' ax.fill(xyf[0], xyf[1], facecolor=con['c'], alpha=0.6) if convex: points = np.asarray(list(zip(xyf[0], xyf[1]))) hull = ConvexHull(points) for simplex in hull.simplices: if max(points[simplex, 1]) > 0: continue ax.plot(points[simplex, 0], points[simplex, 1], 'k-') if hor: ax.axhline(color='k') #horizontal line ax.axvline(color='k') # vertical line at 0 always if ver_lines: for line in ver_lines: ax.axvline(**line) if xy_line: ylim = ax.get_ylim() # print(ylim) x = np.linspace(*ylim) # print(x) ax.plot(x, x) if x_nbins: ax.locator_params(nbins=x_nbins, axis='x') if xlim: ax.set_xlim(xlim) if ylim: ax.set_ylim(ymin=ylim[0]) if ylim[1]: ax.set_ylim(ymax=ylim[1]) if xlog: ax.set_xscale('log') if ylog: if "sym" in str(ylog): ax.set_yscale('symlog', linthreshx=0.1) else: ax.set_yscale('log') if hide_ylabels: ax.yaxis.set_major_formatter(plt.NullFormatter()) # ax.yaxis.set_ticklabels([]) if hide_xlabels: ax.xaxis.set_major_formatter(plt.NullFormatter()) if legend: scatterpoints = 1 # for legend ax.legend(loc=legend, scatterpoints=scatterpoints, ncol=ncol) # plt.legend() # plt.tight_layout(pad = 2, h_pad = 0.5) plt.tight_layout() if pad: plt.subplots_adjust(left=0.13, bottom=None, right=None, top=None, wspace=0.07, hspace=None) path2saved = '' if last: if image_name: # plt.subplots_adjust(hspace=0.1) path2saved, path2saved_png = process_fig_filename( image_name, fig_format) plt.savefig(path2saved, dpi=dpi, format=fig_format) plt.savefig(path2saved_png, dpi=300) print_and_log("Image saved to ", path2saved, imp='y') elif show is None: show = True # print_and_log(show) if show: plt.show() plt.clf() plt.close('all') else: printlog('Attention! last = False, no figure is saved') return path2saved
def printme(self): for key in self.vasp_params: if self.vasp_params[key] == None: continue print_and_log( "{:30s} = {:s} ".format("s.vasp_params['"+key+"']", str(self.vasp_params[key]) ), imp = 'Y', end = '\n' ) print_and_log('POTDIR:', self.potdir, imp = 'Y', end = '\n' )
def plot_bar(xlabel="xlabel", ylabel="ylabel", xlim=None, ylim=None, image_name=None, title=None, bottom=0.18, hspace=0.15, barwidth=0.2, data1=[], data2=[], data3=[], data4=[], **data): width = barwidth # the width of the bars if data: N = len(data.values()[0][0]) key = data.keys()[0] xlabels = data[key][0] # print N ind = np.arange(N) # the x locations for the groups shift = 0 fig, ax = plt.subplots() for key in sorted(data): # print 'color', data[key][2] ax.bar(ind + shift, data[key][1], width, color=data[key][2], label=data[key][-1]) # yerr=menStd) # print ind shift += width elif data1 and data4: fig = plt.figure(figsize=(10, 5)) #5:7 ratio for A4, gs = gridspec.GridSpec(2, 2, width_ratios=[5, 1], height_ratios=[1, 1]) gs.update(top=0.98, bottom=bottom, left=0.1, right=0.98, wspace=0.15, hspace=hspace) ax1 = plt.subplot(gs[0]) ax2 = plt.subplot(gs[1]) ax3 = plt.subplot(gs[2]) ax4 = plt.subplot(gs[3]) # fig, ax = plt.subplots() # fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, sharex='col')#, sharey='row') equal for ax, data in (ax1, data1), (ax2, data2), (ax3, data3), (ax4, data4): N = len(data[0][0]) xlabels = data[0][0] ind = np.arange(N) # the x locations for the groups shift = 0 for d in data: ax.bar(ind + shift, d[1], width, color=d[2], label=d[-1]) # yerr=menStd) # print ind shift += width ax.axhline(y=0, color='black') # ax.set_xticklabels(xlabels , rotation=70 ) ax.set_xticks(ind + width) ax3.set_xticklabels(data3[0][0], rotation=80) ax4.set_xticklabels(data4[0][0], rotation=80) plt.setp(ax1.get_xticklabels(), visible=False) plt.setp(ax2.get_xticklabels(), visible=False) ax3.set_ylabel(ylabel) ax3.yaxis.set_label_coords(-0.1, 1.1) # plt.ylabel(ylabel) ax1.legend(loc=2, ) ax3.legend(loc=2, ) # ax1.axis('tight') # ax2.axis('tight') # ax3.axis('tight') # ax4.axis('tight') ax1.margins(0.0, 0.2) ax2.margins(0.0, 0.2) ax3.margins(0.0, 0.2) ax4.margins(0.0, 0.2) elif data1 and data2 and not data4: fig = plt.figure(figsize=(10, 5)) #5:7 ratio for A4, gs = gridspec.GridSpec(1, 2, width_ratios=[5, 1], height_ratios=[1, 0]) gs.update(top=0.95, bottom=bottom, left=0.1, right=0.98, wspace=0.15, hspace=hspace) ax1 = plt.subplot(gs[0]) ax2 = plt.subplot(gs[1]) for ax, data in (ax1, data1), (ax2, data2): N = len(data[0][0]) xlabels = data[0][0] ind = np.arange(N) # the x locations for the groups # print ind+width # print data[0][0] shift = 0.2 for d in data: ax.bar(ind + shift, d[1], width, color=d[2], label=d[-1]) # yerr=menStd) # print ind shift += width ax.axhline(y=0, color='black') # ax.set_xticklabels(xlabels , rotation=70 ) ax.set_xticks(ind + width + len(data) * width / 2) names1 = [n1 for n1, n2 in zip(data1[0][0], data1[1][0])] # names2 = [n1 for n1, n2 in zip(data2[0][0], data2[1][0])] ax1.set_xticklabels(names1, rotation=80) # Names of configurations on x axis ax2.set_xticklabels(names2, rotation=80) ax1.set_ylabel(ylabel) ax1.legend(loc=2, ) ax1.axis('tight') ax2.axis('tight') elif data1 and not data2: # fig = plt.figure(figsize=(10,5)) #5:7 ratio for A4, gs = gridspec.GridSpec(1, 2, width_ratios=[9, 1], height_ratios=[1, 0]) gs.update(top=0.95, bottom=bottom, left=0.1, right=0.98, wspace=0.15, hspace=hspace) ax1 = plt.subplot(gs[0]) # ax2 = plt.subplot(gs[1]) for ax, data in (ax1, data1), : N = len(data[0][0]) xlabels = data[0][0] ind = np.arange(N) # the x locations for the groups # print ind+width # print data[0][0] shift = 0.2 for d in data: ax.bar(ind + shift, d[1], width, color=d[2], label=d[-1]) # yerr=menStd) # print ind shift += width ax.axhline(y=0, color='black') # ax.set_xticklabels(xlabels , rotation=70 ) ax.set_xticks(ind + width + len(data) * width / 2) names1 = [n1 + '; ' + n2 for n1, n2 in zip(data1[0][0], data1[1][0])] # ax1.set_xticklabels(names1, rotation=80) # Names of configurations on x axis ax1.set_ylabel(ylabel) ax1.legend(loc=2, ) ax1.axis('tight') # ax2.axis('tight') # ax.set_yscale('log') # plt.yscale('symlog', linthreshx=0.1) # ax.set_title('Scores by group and gender') def autolabel(rects): # attach some text labels for rect in rects: height = rect.get_height() ax.text(rect.get_x() + rect.get_width() / 2., 1.05 * height, '%d' % int(height), ha='center', va='bottom') # autolabel(rects1) # autolabel(rects2) # plt.axis('tight') # plt.margins(0.05, 0) # plt.tight_layout() # elif data1: gs.tight_layout(fig) if image_name: print_and_log("Saving image ...", str(image_name), imp='y') plt.savefig(str(image_name) + '.png', dpi=200, format='png') else: plt.show() return
def read_vasp_sets(user_vasp_sets, override_global = False): """ Read user sets and add them to project database Now for VASP ###INPUT: - varset (dict) - database dict with all sets of a project - user_vasp_sets (list) - list of user sets that describes creation of new sets based on inheritance - override - allows to recreate all sets; can be usefull than you want to add some new property to all your sets - very dangerous to do! ###RETURN: - user_vasp_sets (list) """ # print varset.keys() # varset['9'].printme() # print varset['9ml'].history # print varset['9'].history varset = header.varset vasp_keys = vasp_electronic_keys+vasp_ionic_keys+vasp_other_keys bfolder = '' #by default no blockfolder for l in user_vasp_sets: if override_global or 'over' in l[-1]: override = True else: override = False if override or l[0] not in varset: # print override, 'override' param = l[2] if 'bfolder' in param: bfolder = param['bfolder'] else: bfolder = None s = inherit_iset(l[0], l[1], varset, override = override, newblockfolder = bfolder) # print param for key in param: if key in vasp_keys: s.set_vaspp(key, param[key]) elif key == 'set_potential': for key2 in param[key]: # print key2, 'key2' s.set_potential(key2, param[key][key2]) elif key == 'add_nbands': # print param[key] s.set_add_nbands(param[key]) elif key == 'bfolder': print_and_log( 'New blockfolder', param[key]) elif key in siman_keys: s.set_attrp(key, param[key] ) else: print_and_log('Error! Uknown key: '+key) raise RuntimeError if key == 'set_sequence': sets = [] for se in s.set_sequence: sets.append(copy.deepcopy(varset[se])) s.set_sequence = sets #put objects instead of names # if hasattr(s, 'set_sequence') and s.set_sequence: # sets = [] # for se in s.set_sequence: # if type(se) == str: # sets.append(copy.deepcopy(varset[se])) # else: # sets.append(copy.deepcopy(se)) # s.set_sequence = sets #put objects instead of names header.varset = varset return varset
def fit_and_plot(x1, y1, x2, y2, power, name="", xlabel="", ylabel="", image_name="test", lines=None): """Should be used in two below sections! Creates one plot with two dependecies and fit them; return minimum fitted value of x2 and corresponding valume of y2; if name == "" image will not be plotted power - the power of polynom lines - add lines at x = 0 and y = 0 """ coeffs1 = np.polyfit(x1, y1, power) coeffs2 = np.polyfit(x2, y2, power) fit_func1 = np.poly1d(coeffs1) fit_func2 = np.poly1d(coeffs2) #x_min = fit_func2.deriv().r[power-2] #derivative of function and the second cooffecient is minimum value of x. #y_min = fit_func2(x_min) if name: x_range = np.linspace(min(x2), max(x2)) fit_y1 = fit_func1(x_range) fit_y2 = fit_func2(x_range) plt.figure(figsize=(8, 6.1)) # plt.title(name) plt.ylabel(ylabel) plt.xlabel(xlabel) plt.xlim( min(x2) - 0.1 * abs(min(x2)), max(x2) + 0.1 * abs(min(x2))) plt.plot(x1, y1, 'ro', label='initial') plt.plot(x2, y2, 'bo', label='relaxed') plt.plot( x_range, fit_y1, 'r-', ) #label = 'init_fit') plt.plot( x_range, fit_y2, 'b-', ) #label = 'r_fit' ) plt.legend(loc=9) if lines == 'xy': plt.axvline(color='k') plt.axhline(color='k') plt.tight_layout() #plt.savefig('images/'+image_name) file = header.path_to_images + '/' + str(image_name) + '.png' makedir(file) print_and_log('Saving file ...', file, imp='y') plt.savefig(file, format='png', dpi=300) return fit_func2
def insert(it_ins, ise_ins, mat_path, it_new, calc, type_of_insertion="xcart"): """For insertion of atoms to cells with changed lateral sizes Input: 'type_of_insertion = xred' used to add xred coordinates mat_path - path to geo files which are supposed to be changed it_ins - already existed calculation; xred will be used from this calculation. it_new - new folder in geo folder for obtained structure This function finds version of calculation in folder mat_path and tries to use the same version of it_ins """ if not os.path.exists(mat_path): print_and_log("Error! Path " + mat_path + " does not exist\n\n") raise RuntimeError if it_ins not in mat_path and it_ins not in it_new: print_and_log('Cells are', it_ins, mat_path, it_new) print_and_log( "Error! you are trying to insert coordinates from cell with different name\n\n" ) #raise RuntimeError hstring = ("%s #on %s" % (traceback.extract_stack(None, 2)[0][3], datetime.date.today())) if hstring != header.history[-1]: header.history.append(hstring) geofilelist = runBash('find ' + mat_path + '/target -name "*.geo*" ').splitlines() if geofilelist == []: print_and_log( "Warning! Target folder is empty. Trying to find in root folder ..." ) geofilelist = runBash('find ' + mat_path + '/ -name "*.geo*" ').splitlines() ins = None for mat_geofile in geofilelist: mat = CalculationVasp() mat.name = mat_geofile mat.read_geometry(mat_geofile) #step = 0.27 #r_pore = 0.56 #r_mat = mat.hex_a / 2 - step #pores = find_pores(mat.init, r_mat, r_pore, step, 0.3, 'central') #octahedral #mat.xcart.append ( pores.xcart[0] ) #mat.typat.append(1) try: ins_working = ins ins = calc[(it_ins, ise_ins, mat.version)] except KeyError: print_and_log("No key", (it_ins, ise_ins, mat.version), "I use previous working version !!!", imp='y') ins = ins_working #return #ins.end.znucl = ins.znucl #ins.end.nznucl = ins.nznucl #ins.end.ntypat = ins.ntypat #ins.end.typat = ins.typat #print ins.xcart[-1] mat_geopath = geo_folder + struct_des[it_new].sfolder + '/' if type_of_insertion == "xcart": #Please update here! mat_filename = '/' + it_new + "." + "inserted." + str( mat.version) + '.' + 'geo' v = np.zeros(3) result = insert_cluster(ins.end, v, mat.init, v) mat.end = result mat.init = result # mat.znucl = mat.end.znucl # mat.nznucl = mat.end.nznucl # mat.ntypat = mat.end.ntypat # mat.typat = mat.end.typat # mat.natom = len(mat.end.xred) #mat.version = ins.version des = ins.name + " was inserted to " + mat_geofile elif type_of_insertion == "xred": mat_filename = '/from/' + it_new + ".xred." + str( mat.version) + '.' + 'geo' #mat.end.rprimd = mat.rprimd #mat.init.xred = copy.deepcopy(ins.end.xred) #mat.init.typat = copy.deepcopy(ins.end.) #print ins.end.xcart rprimd = copy.deepcopy(mat.init.rprimd) #build = mat.build mat.init = copy.deepcopy(ins.end) #mat.build = build mat.init.rprimd = rprimd #return initial rprimd mat.init.xred2xcart() #calculate xcart with new rprimd des = "atoms with reduced coord. from " + ins.name + " was fully copied to " + mat_geofile mat.init.name = 'test_insert_xred' + str(mat.version) write_xyz(mat.init) mat.path["input_geo"] = mat_geopath + it_new + mat_filename if not mat.write_geometry("init", des): continue print_and_log("Xred from " + it_ins + " was inserted in " + mat_geofile + " and saved as " + mat_filename + " \n\n") return
def add_neb( starting_calc=None, st=None, st_end=None, it_new=None, ise_new=None, i_atom_to_move=None, up='up2', search_type='vacancy_creation', images=None, r_impurity=None, corenum=None, calc_method=['neb'], inherit_option=None, mag_config=None, i_void_start=None, i_void_final=None, atom_to_insert=None, atom_to_move=None, rep_moving_atom=None, end_pos_types_z=None, replicate=None, it_new_folder=None, inherit_magmom=False, x_start=None, xr_start=None, x_final=None, xr_final=None, upload_vts=False, run=False, add_loop_dic=None, old_behaviour=None, ): """ Prepare needed files for NEB Provides several regimes controlled by *search_type* flag: - existing_voids - search for voids around atom and use them as a final position - vacancy_creation - search for neighbors of the same type and make a vacancy as a start position - interstitial_insertion - search for two neighboring voids; use them as start and final positions by inserting atom *atom_to_insert* - None - just use st and st2 as initial and final ###INPUT: - starting_calc (Calculation) - Calculation object with structure - st (Structure) - structure, can be used instead of Calculation - it_new (str) - name for calculation - st_end (Structure) - final structure - i_atom_to_move (int) - number of atom for moving starting from 0; - *mag_config* (int ) - choose magnetic configuration - allows to obtain different localizations of electron - *replicate* (tuple 3*int) - replicate cell along rprimd - i_void_start, i_void_final (int) - position numbers of voids (or atoms) from the suggested lists - atom_to_insert (str) - element name of atom to insert - atom_to_move (str) - element name of atom to move - it_new_folder (str) - section folder - inherit_option (str) - passed only to add_loop - inherit_magmom (bool) - if True than magmom from starting_calc is used, else from set - end_pos_types_z (list of int) - list of Z - type of atoms, which could be considered as final positions in vacancy creation mode - calc_method (list) - 'neb' - 'only_neb' - run only footer - x_start, x_final (array) - explicit xcart coordinates of moving atom for starting and final positions, combined with atom_to_insert - xr_start, xr_final (array) - explicit xred - rep_moving_atom (str)- replace moving atom by needed atom - can be useful than completly different atom is needed. - upload_vts (bool) - if True upload Vasp.pm and nebmake.pl to server - run (bool) - run on server ###RETURN: None ###DEPENDS: ###TODO 1. Take care of manually provided i_atom_to_move in case of replicate flag using init_numbers 2. For search_type == None x_m and x_del should be determined for magnetic searching and for saving their coordinates to struct_des; now their just (0,0,0) """ if old_behaviour: naming_conventions209 = False # else: naming_conventions209 = True # set False to reproduce old behavior before 2.09.2017 # print(atom_to_insert) # sys.exit() calc = header.calc struct_des = header.struct_des varset = header.varset if not add_loop_dic: add_loop_dic = {} if not end_pos_types_z: end_pos_types_z = [] if not hasattr(calc_method, '__iter__'): calc_method = [calc_method] if starting_calc and st: printlog( 'Warning! both *starting_calc* and *st* are provided. I use *starting_calc*' ) st = copy.deepcopy(starting_calc.end) elif starting_calc: st = copy.deepcopy(starting_calc.end) printlog('I use *starting_calc*') elif st: '' printlog('I use *st*') else: printlog( 'Error! no input structure. Use either *starting_calc* or *st*') if corenum == None: if images == 3: corenum = 15 elif images == 5: corenum = 15 elif images == 7: corenum = 14 else: printlog('add_neb(): Error! number of images', images, 'is unknown to me; please provide corenum!') # print(atom_to_insert) # sys.exit() if corenum: # header.corenum = corenum '' else: corenum = header.CORENUM if corenum % images > 0: print_and_log( 'Error! Number of cores should be dividable by number of IMAGES', images, corenum) if not ise_new: ise_new = starting_calc.id[1] printlog('I use', ise_new, 'as ise_new', imp='y') name_suffix = '' st_pores = [] name_suffix += 'n' + str(images) """Replicate cell """ if replicate: print_and_log('You have chosen to replicate the structure by', replicate) st = replic(st, mul=replicate) name_suffix += str(replicate[0]) + str(replicate[1]) + str( replicate[2]) printlog('Search type is ', search_type) if search_type == None: if st_end == None: printlog( 'Error! You have provided search_type == None, st_end should be provided!' ) st1 = st st2 = st_end x_m = (0, 0, 0) x_del = (0, 0, 0) else: """1. Choose atom (or insert) for moving """ if is_list_like(xr_start): x_start = xred2xcart([xr_start], st.rprimd)[0] st1, i_m = st.add_atoms([x_start], atom_to_insert, return_ins=1) x_m = x_start # i_m = st1.find_atom_num_by_xcart(x_start) # print(st1.get_elements()[i_m]) # sys.exit() if i_atom_to_move: nn = str(i_atom_to_move + 1) else: nn = str(i_void_start) name_suffix += atom_to_insert + nn write_xyz(st1, file_name=st.name + '_manually_start') printlog('Start position is created manually by adding xr_start', xr_start, x_start) type_atom_to_move = atom_to_insert el_num_suffix = '' else: atoms_to_move = [] atoms_to_move_types = [] # print('d', i_atom_to_move) # sys.exit() if i_atom_to_move: typ = st.get_elements()[i_atom_to_move] printlog('add_neb(): atom', typ, 'will be moved', imp='y') atoms_to_move.append( [i_atom_to_move, typ, st.xcart[i_atom_to_move]]) atoms_to_move_types.append(typ) if naming_conventions209: name_suffix += typ + str(i_atom_to_move + 1) else: #try to find automatically among alkali - special case for batteries for i, typ, x in zip(range(st.natom), st.get_elements(), st.xcart): if typ in ['Li', 'Na', 'K', 'Rb', 'Mg']: atoms_to_move.append([i, typ, x]) if typ not in atoms_to_move_types: atoms_to_move_types.append(typ) if atoms_to_move: # print(atom_to_move) # sys.exit() if not atom_to_move: atom_to_move = atoms_to_move_types[ 0] # taking first found element if len(atoms_to_move_types) > 1: printlog( 'Error! More than one type of atoms available for moving detected', atoms_to_move_types, 'please specify needed atom with *atom_to_move*') type_atom_to_move = atom_to_move #atoms_to_move[0][1] # printlog('atom ', type_atom_to_move, 'will be moved', imp ='y') if i_atom_to_move: printlog('add_neb(): *i_atom_to_move* = ', i_atom_to_move, 'is used', imp='y') numbers = [[i_atom_to_move]] i_void_start = 1 else: printlog('add_neb(): determine_symmetry_positions ...', imp='y') numbers = determine_symmetry_positions(st, atom_to_move) # print(numbers) # sys.exit() if len(numbers) > 0: printlog('Please choose position using *i_void_start* :', [i + 1 for i in range(len(numbers))], imp='y') printlog('*i_void_start* = ', i_void_start) i_m = numbers[i_void_start - 1][0] printlog('Position', i_void_start, 'chosen, atom:', i_m + 1, type_atom_to_move, imp='y') else: i_m = numbers[0][0] x_m = st.xcart[i_m] el_num_suffix = type_atom_to_move + str(i_m + 1) atom_to_insert = atom_to_move st1 = st # elif atom_to_replace: # num = st.get_specific_elements(atom_to_replace) # if len(n)>0: # printlog('Please choose position using *i_void_start* :', [i+1 for i in range(len(num))],imp = 'y' ) # printlog('*i_void_start* = ', i_void_start) # i_m = num[i_void_start-1] # printlog('Position',i_void_start,'chosen, atom to replace:', i_m+1, atom_to_replace, imp = 'y' ) # sys.exit() else: print_and_log( 'No atoms to move found, you probably gave me deintercalated structure', important='y') st_pores, sums, avds = determine_voids(st, r_impurity, step_dec=0.1, fine=2) insert_positions = determine_unique_voids(st_pores, sums, avds) print_and_log( 'Please use *i_void_start* to choose the void for atom insertion from the Table above:', end='\n', imp='Y') if i_void_start == None: sys.exit() if atom_to_insert == None: printlog('Error! atom_to_insert = None') st = st.add_atoms([ insert_positions[i_void_start], ], atom_to_insert) name_suffix += 'i' + str(i_void_start) i_m = st.natom - 1 x_m = st.xcart[i_m] search_type = 'existing_voids' type_atom_to_move = atom_to_insert el_num_suffix = '' st1 = st """2. Choose final position""" if is_list_like(xr_final): x_final = xred2xcart([xr_final], st.rprimd)[0] #old #check if i_atom_to_move should be removed # st2 = st1.del_atom(i_m) # st2 = st2.add_atoms([x_final], atom_to_insert) #new st2 = st1.mov_atoms(i_m, x_final) # st1.printme() # st2.printme() # sys.exit() x_del = x_final search_type = 'manual_insertion' name_suffix += 'v' + str(i_void_final) write_xyz(st2, file_name=st.name + '_manually_final') printlog('Final position is created manually by adding xr_final', xr_final, x_del) elif search_type == 'existing_voids': #Search for voids around choosen atoms if not st_pores: st_pores, sums, avds = determine_voids(st, r_impurity) sur = determine_unique_final(st_pores, sums, avds, x_m) print_and_log('Please choose *i_void_final* from the Table above:', end='\n', imp='Y') if i_void_final == None: sys.exit() x_final = sur[0][i_void_final] # printlog('You chose:', np.array(x_final).round(2), end='\n', imp='Y') x_del = x_final #please compare with vacancy creation mode write_xyz(st.add_atoms([x_final], 'H'), replications=(2, 2, 2), file_name=st.name + '_possible_positions2_replicated') print_and_log('Choosing the closest position as end', important='n') st1 = st st2 = st.mov_atoms(i_m, x_final) name_suffix += el_num_suffix + 'e' + str( i_void_final) + atom_to_insert st1 = return_atoms_to_cell(st1) st2 = return_atoms_to_cell(st2) write_xyz(st1, file_name=st1.name + name_suffix + '_start') write_xyz(st2, file_name=st2.name + name_suffix + '_final') elif search_type == 'vacancy_creation': #Create vacancy by removing some neibouring atom of the same type print_and_log( 'You have chosen vacancy_creation mode of add_neb tool', imp='Y') print_and_log('Type of atom to move = ', type_atom_to_move, imp='y') # print 'List of left atoms = ', np.array(st.leave_only(type_atom_to_move).xcart) sur = local_surrounding(x_m, st, n_neighbours=12, control='atoms', only_elements=[invert(type_atom_to_move)] + end_pos_types_z, periodic=True) #exclude the atom itself # print(x_m) # print(sur) # st.nn() print_and_log( 'I can suggest you ' + str(len(sur[0][1:])) + ' end positions. The distances to them are : ', np.round(sur[3][1:], 2), ' A\n ', 'They are ', type_atom_to_move, [invert(z) for z in end_pos_types_z], 'atoms, use *i_void_final* to choose required: 1, 2, 3 ..', imp='y') if not i_void_final: i_void_final = 1 #since zero is itself print_and_log('Choosing position ', i_void_final, 'with distance', round(sur[3][i_void_final], 2), 'A', imp='y') name_suffix += el_num_suffix + 'v' + str(i_void_final) x_del = sur[0][i_void_final] printlog('xcart of atom to delete', x_del) i_del = st.find_atom_num_by_xcart(x_del) # print(x_del) # print(st.xcart) # for x in st.xcart: # if x[0] > 10: # print(x) print_and_log('number of atom to delete = ', i_del, imp='y') if i_del == None: printlog('add_neb(): Error! I could find atom to delete!') # print st.magmom # print st1.magmom # try: if is_list_like(xr_start): st2 = st1.mov_atoms( i_m, x_del) # i_m and sur[0][neb_config] should coincide # i_del = st1.find_atom_num_by_xcart(x_del) st1 = st1.del_atom(i_del) else: print_and_log( 'Making vacancy at end position for starting configuration', imp='y') st1 = st.del_atom(i_del) print_and_log( 'Making vacancy at start position for final configuration', important='n') st2 = st.mov_atoms( i_m, x_del) # i_m and sur[0][neb_config] should coincide # except: # st2 = st st2 = st2.del_atom(i_del) # these two steps provide the same order """Checking correctness of path""" #if start and final positions are used, collisions with existing atoms are possible if is_list_like(xr_start) and is_list_like(xr_final): printlog('Checking correctness') st1, _, _ = st1.remove_close_lying() stt = st1.add_atoms([ x_final, ], 'Pu') stt, x, _ = stt.remove_close_lying( rm_both=True ) # now the final position is empty for sure; however the order can be spoiled # print(st._removed) if stt._removed: st1 = stt # only if overlapping was found we assign new structure st2, _, _ = st2.remove_close_lying(rm_first=stt._removed) stt = st2.add_atoms([ x_start, ], 'Pu') stt, x, _ = stt.remove_close_lying( rm_both=True) # now the start position is empty for sure if stt._removed: st2 = stt print(st2.get_elements()) # sys.exit() elif is_list_like(xr_final) and not is_list_like(xr_start) or is_list_like( xr_start) and not is_list_like(xr_final): printlog( 'Attention! only start of final position is provided, please check that everything is ok with start and final states!!!' ) """ Determining magnetic moments """ vp = varset[ise_new].vasp_params if search_type != None: #for None not implemented; x_m should be determined first for this if 'ISPIN' in vp and vp['ISPIN'] == 2: print_and_log( 'Magnetic calculation detected. Preparing spin modifications ...', imp='y') cl_test = CalculationVasp(varset[ise_new]) cl_test.init = st1 # print 'asdfsdfasdfsadfsadf', st1.magmom if inherit_magmom and hasattr(st, 'magmom') and st.magmom and any( st.magmom): print_and_log( 'inherit_magmom=True: You have chosen MAGMOM from provided structure', imp='y') name_suffix += 'mp' #Magmom from Previous else: cl_test.init.magmom = None print_and_log( 'inherit_magmom=False or no magmom in input structure : MAGMOM will be determined from set', imp='y') name_suffix += 'ms' #Magmom from Set cl_test.actualize_set() #find magmom for current structure st1.magmom = copy.deepcopy(cl_test.init.magmom) st2.magmom = copy.deepcopy(cl_test.init.magmom) # sys.exit() # print_and_log('The magnetic moments from set:') # print cl_test.init.magmom #checking for closest atoms now only for Fe, Mn, Ni, Co sur = local_surrounding(x_m, st1, n_neighbours=3, control='atoms', periodic=True, only_elements=header.TRANSITION_ELEMENTS) dist = np.array(sur[3]).round(2) numb = np.array(sur[2]) a = zip(numb, dist) # a= np.array(a) # print a[1] # a = np.apply_along_axis(np.unique, 1, a) # print a def unique_by_key(elements, key=None): if key is None: # no key: the whole element must be unique key = lambda e: e return list({key(el): el for el in elements}.values()) # print a mag_atoms_dists = unique_by_key(a, key=itemgetter(1)) # print (mag_atoms_dists) # a = unique_by_key(a, key=itemgetter(1)) print_and_log( 'I change spin for the following atoms:\ni atom dist\n', np.round(mag_atoms_dists, 2), imp='y') # print 'I have found closest Fe atoms' muls = [(1.2, 0.6), (0.6, 1.2)] mag_moments_variants = [] for mm in muls: mags = copy.deepcopy(cl_test.init.magmom) # print mags for a, m in zip(mag_atoms_dists, mm): # print t[1] mags[a[0]] = mags[a[0]] * m mag_moments_variants.append(mags) print_and_log('The list of possible mag_moments:', imp='y') for i, mag in enumerate(mag_moments_variants): print_and_log(i, mag) print_and_log( 'Please use *mag_config* arg to choose desired config', imp='y') if mag_config != None: st1.magmom = copy.deepcopy(mag_moments_variants[mag_config]) st2.magmom = copy.deepcopy(mag_moments_variants[mag_config]) name_suffix += 'm' + str(mag_config) print_and_log('You have chosen mag configuration #', mag_config, imp='y') else: print_and_log('Non-magnetic calculation continue ...') """3. Add to struct_des, create geo files, check set, add_loop """ if starting_calc: it = starting_calc.id[0] it_new = it + 'v' + str(starting_calc.id[2]) + '.' + name_suffix if not it_new_folder: it_new_folder = struct_des[it].sfolder + '/neb/' obtained_from = str(starting_calc.id) if not ise_new: print_and_log('I will run add_loop() using the same set', important='Y') ise_new = cl.id[1] elif st: if not it_new: printlog( 'Error! please provide *it_new* - name for your calculation', important='Y') it = None it_new += '.' + name_suffix obtained_from = st.name if not ise_new: printlog('Error! please provide *ise_new*', important='Y') if not it_new_folder: printlog( 'Error! please provide *it_new_folder* - folder for your new calculation', important='Y') if rep_moving_atom: it_new += 'r' + rep_moving_atom if it_new not in struct_des: add_des(struct_des, it_new, it_new_folder, 'Automatically created and added from ' + obtained_from) print_and_log( 'Creating geo files for starting and final configurations (versions 1 and 2) ', important='y') # if starting_calc: # cl = copy.deepcopy(starting_calc) # else: cl = CalculationVasp() #write start position struct_des[it_new].x_m_ion_start = x_m struct_des[it_new].xr_m_ion_start = xcart2xred([x_m], st1.rprimd)[0] # st1, _, _ = st1.remove_close_lying() # st2, _, _ = st2.remove_close_lying() i1 = st1.find_atom_num_by_xcart(x_m, prec=0.3) i2 = st2.find_atom_num_by_xcart(x_del, prec=0.3) if rep_moving_atom: #replace the moving atom by required st1 = st1.replace_atoms([i1], rep_moving_atom) st2 = st2.replace_atoms([i2], rep_moving_atom) else: #allows to make correct order for nebmake.pl st1 = st1.replace_atoms([i1], type_atom_to_move) st2 = st2.replace_atoms([i2], type_atom_to_move) i1 = st1.find_atom_num_by_xcart(x_m, prec=0.3) # the positions were changed i2 = st2.find_atom_num_by_xcart(x_del, prec=0.3) cl.end = st1 ver_new = 1 cl.version = ver_new cl.path["input_geo"] = header.geo_folder + struct_des[it_new].sfolder + '/' + \ it_new+"/"+it_new+'.auto_created_starting_position_for_neb_'+str(search_type)+'.'+str(ver_new)+'.'+'geo' cl.write_siman_geo(geotype='end', description='Starting conf. for neb from ' + obtained_from, override=True) #write final position struct_des[it_new].x_m_ion_final = x_del struct_des[it_new].xr_m_ion_final = xcart2xred([x_del], st2.rprimd)[0] cl.end = st2 ver_new = 2 cl.version = ver_new cl.path["input_geo"] = header.geo_folder + struct_des[it_new].sfolder + '/' + \ it_new+"/"+it_new+'.auto_created_final_position_for_neb_'+str(search_type)+'.'+str(ver_new)+'.'+'geo' cl.write_siman_geo(geotype='end', description='Final conf. for neb from ' + obtained_from, override=True) if not rep_moving_atom: st1s = st1.replace_atoms([i1], 'Pu') st2s = st2.replace_atoms([i2], 'Pu') else: st1s = copy.deepcopy(st1) st2s = copy.deepcopy(st2) vec = st1.center_on(i1) st1s = st1s.shift_atoms(vec) st2s = st2s.shift_atoms(vec) write_xyz(st1s, file_name=it_new + '_start') write_xyz(st2s, file_name=it_new + '_end') st1s.write_poscar('xyz/POSCAR1') st2s.write_poscar('xyz/POSCAR2') # print(a) # runBash('cd xyz; mkdir '+it_new+'_all;'+"""for i in {00..04}; do cp $i/POSCAR """+ it_new+'_all/POSCAR$i; done; rm -r 00 01 02 03 04') with cd('xyz'): a = runBash(header.PATH2NEBMAKE + ' POSCAR1 POSCAR2 3') dst = it_new + '_all' makedir(dst + '/any') for f in ['00', '01', '02', '03', '04']: shutil.move(f + '/POSCAR', dst + '/POSCAR' + f) shutil.rmtree(f) #prepare calculations # sys.exit() #Check if nebmake is avail # if int(runBash('ssh '+cluster_address+' test -e '+project_path_cluster+'/tools/vts/nebmake.pl; echo $?') ): # '' # print_and_log('Please upload vtsttools to ',cluster_address, project_path_cluster+'/tools/vts/') # raise RuntimeError # copy_to_server(path_to_wrapper+'/vtstscripts/nebmake.pl', to = project_path_cluster+'/tools/', addr = cluster_address) # if int(runBash('ssh '+cluster_address+' test -e '+project_path_cluster+'/tools/Vasp.pm; echo $?') ): # copy_to_server(path_to_wrapper+'/vtstscripts/Vasp.pm', to = project_path_cluster+'/tools/', addr = cluster_address) inherit_ngkpt(it_new, it, varset[ise_new]) add_loop(it_new, ise_new, verlist=[1, 2], up=up, calc_method=calc_method, savefile='oc', inherit_option=inherit_option, n_neb_images=images, corenum=corenum, run=run, **add_loop_dic) if upload_vts: siman_dir = os.path.dirname(__file__) # print(upload_vts) push_to_server([ siman_dir + '/cluster_tools/nebmake.pl', siman_dir + '/cluster_tools/Vasp.pm' ], to=header.cluster_home + '/tools/vts', addr=header.cluster_address) else: print_and_log('Please be sure that vtsttools are at', header.cluster_address, header.cluster_home + '/tools/vts/', imp='Y') printlog('add_neb finished') return it_new
def add(znucl, xyzpath = "", new = None, write_geo = True, put_exactly_to = None): "if put_exactly_to is True, then atom just added and nothing are searched" if write_geo and os.path.exists(new.path["input_geo"]) and not override: print_and_log("add: File '"+new.path["input_geo"]+"' already exists; continue\n", imp = 'Y'); return new #new.init = return_atoms_to_cell(new.init) if replace_atom: #atom substitution if znucl not in new.init.znucl: new.init.znucl.append(znucl) new.init.ntypat+=1 new.init.typat[replace_atom] = new.init.ntypat else: ind = new.init.znucl.index(znucl) new.init.typat[replace_atom] = ind + 1 new.init.nznucl = [] for typ in range(1, new.init.ntypat+1): new.init.nznucl.append(new.init.typat.count(typ) ) else: new_before = copy.deepcopy(new) # new.init.xcart[-2][0]-=0.9 #was made once manually for c1gCOi10.1 # new.init.xcart[-2][2]+=0.2 # new.init.xred = xcart2xred(new.init.xcart, new.init.rprimd) write_xyz(new.init) #step = 0.042 step = 0.06 #r_pore = 0.56 #fine = 0.3 # for visualisation of pores #fine = 4 #controls small steps; the steps are smaller for larger numbers #r_pore = 0.54 prec = 0.004 # precision of center Angs if new.hex_a == None: r_mat = 1.48 -step else: r_mat = new.hex_a / 2 - step if put_exactly_to: pores_xred = [np.array(put_exactly_to),] print_and_log( 'Inmpurity just put in ', pores_xred, imp = 'Y') else: pores = find_pores(new.init, r_mat, r_pore, step, fine, prec, addtype, new.gbpos, find_close_to, check_pore_vol) #octahedral pores_xred = pores.xred npores = len(pores_xred) st = new.init #delete last oxygen; was made once manually for c1gCOi10.1 # st.natom-=1 # del st.xred[-1] # del st.typat[-1] st.natom += npores st.xred.extend( pores_xred ) if znucl in st.znucl: print_and_log( "znucl of added impurity is already in cell") ind = st.znucl.index(znucl) typat = ind+1 st.nznucl[ind]+=npores else: st.ntypat +=1 typat = st.ntypat st.znucl.append( znucl ) st.nznucl.append( npores ) for i in range( npores ): st.typat.append( typat ) st.xcart = xred2xcart(st.xred, st.rprimd) new.init = st #print "Add impurity: len(xred ", len(new.init.xred) #print "natom", new.init.natom #For automatisation of fit try: #new.build if new.build.nadded == None: new.build.nadded=npores else: new.build.nadded+=npores if new.build.listadded == [None]: new.build.listadded = range(new.natom - npores, new.natom) #list of atoms which were added else: new.build.listadded.extend( range(new.natom - npores, new.natom) ) #print "Warning!!! Information about added impurities rewritten" except AttributeError: pass #new.init.znucl = new.znucl #new.init.typat = new.typat #write_xyz(replic(new.init, (2,1,2)) , xyzpath) #test_adding_of_impurities(new, new_before, v) print_and_log("Impurity with Z="+str(znucl)+" has been added to the found pore in "+new.name+"\n\n") if write_geo: write_xyz(new.init , xyzpath) new.write_geometry("init",new.des, override = override) print_and_log( "\n") return new