def generate_latex_report(text, filename): # fn = filename + '.tex' makedir(fn) head = r""" \documentclass{article} % General document formatting \usepackage[margin=0.7in]{geometry} \usepackage[parfill]{parskip} \usepackage[utf8]{inputenc} % Related to math \usepackage{amsmath,amssymb,amsfonts,amsthm} \begin{document}""" with open(fn, 'w') as f: f.write(head + '\n') f.write(text + '\n') f.write(r'\end{document}') runBash('pdflatex ' + os.path.basename(fn), cwd=os.path.dirname(fn))
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_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 = 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 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 """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: """ Please rewrite using new functions """ 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 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): printlog("Error! write_xyz: check your structure") if name == '': name = 'noname' if xcart == [] or len(xcart) != len(xred): printlog( "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_jmol(xyzfile, pngfile, scriptfile=None, atomselection=None, topview=0, orientation=None, axis=False, bonds=True, rprimd=None, shift=None, rotate=None, label=None, high_contrast=None, specialcommand=None, boundbox=2, atom_labels=None): """ 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 label (tuple ()) - used for impurities, please decribe atom_labels (bool) - turn on atom labels """ 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 \n') #250 if 0: f.write('cpk 250 \nwireframe 0.3\n') f.write('background white \n') # f.write('select 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 atom_labels: f.write( 'select all\nset label "%e"\nset labeloffset 0 0\nset labelfront off\ncolor label black\nfont label 18 bold \n' ) if rotate: f.write('rotate z ' + str(rotate) + '\n') if specialcommand: f.write(specialcommand + '\n') if 1: f.write('set displayCellParameters False ;\n') # f.write('write image 2800 2800 png "'+pngfile+'"') f.write('write image 1800 1800 png "' + pngfile + '"') # print(header.PATH2JMOL) # sys.exit() printlog(runBash(header.PATH2JMOL + ' -ions ' + scriptfile)) # print runBash('convert '+pngfile+' -shave 0x5% -trim '+pngfile) #cut by 5% from up and down (shave) and that trim left background printlog(pngfile) printlog(runBash('convert ' + pngfile + ' -trim ' + pngfile)) # trim background printlog('png file by Jmol', pngfile, 'was written', imp='y') # print(header.PATH2JMOL) 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, 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, it_folder=None, inherit_magmom=False, x_start=None, xr_start=None, x_final=None, xr_final=None, upload_vts=False, center_on_moving=True, run=False, add_loop_dic=None, old_behaviour=None, params=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 or it_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 - old_behaviour (str) - choose naming behavior before some date in the past for compatibility with your projects '020917' '261018' - after this moment new namig convention applied if end_pos_types_z is used - add_loop_dic - standart parameters of add() - params (dic) - provide additional parameters to add() # should be removed ###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) """ naming_conventions209 = True # set False to reproduce old behavior before 2.09.2017 if old_behaviour == '020917': naming_conventions209 = False # # print('atom_to_insert', 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 = [] end_pos_types_z = sorted(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*') corenum = add_loop_dic.get('corenum') # print(corenum) # sys.exit() 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(corenum) # sys.exit() # 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] # print('atom_to_insert', atom_to_insert) # sys.exit() 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) final_pos_z = end_pos_types_z or [ invert(type_atom_to_move) ] # by default only moving atom is considered end_pos_types_el = [invert(z) for z in end_pos_types_z] sur = local_surrounding(x_m, st, n_neighbours=14, control='atoms', only_elements=final_pos_z, periodic=True) #exclude the atom itself # print(x_m) # print(sur) # st.nn() end_pos_n = sur[2][1:] print_and_log( 'I can suggest you ' + str(len(end_pos_n)) + ' end positions. The distances to them are : ', np.round(sur[3][1:], 2), ' A\n ', 'They are ', [invert(z) for z in final_pos_z], 'atoms, use *i_void_final* to choose required: 1, 2, 3 ..', imp='y') i_sym_final_l = [] for j in end_pos_n: for i, l in enumerate(numbers): if j in l: i_sym_final_l.append(i + 1) printlog('Their symmetry positions are ', i_sym_final_l, imp='y') # sys.exit() if not i_void_final: printlog('Changing i_void_final: None -> 1', imp='y') i_void_final = 1 #since zero is itself chosen_dist = sur[3][i_void_final] print_and_log('Choosing position ', i_void_final, 'with distance', round(chosen_dist, 2), 'A', imp='y') # print(end_pos_n) i_sym_final = 0 n_final = sur[2][i_void_final] for i, l in enumerate(numbers): if n_final in l: i_sym_final = i + 1 printlog('It is symmetrically non-equiv position #', i_sym_final, imp='y') # sys.exit() header.temp_chosen_dist = chosen_dist if old_behaviour == '261018': name_suffix += el_num_suffix + 'v' + str(i_void_final) else: name_suffix += el_num_suffix + 'v' + str( i_void_final) + list2string(end_pos_types_el, joiner='') # print(name_suffix) # sys.exit() 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 or 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 '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 if search_type != None: # for None not implemented; x_m should be determined first for this #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 and not it_folder: printlog( 'Error! please provide *it_new_folder* - folder for your new calculation', important='Y') if it_folder: it_new_folder = it_folder 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 if search_type is not None: 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() print('Trying to find x_m', x_m) i1 = st1.find_atom_num_by_xcart( x_m, prec=0.45, ) # sys.exit() print('Trying to find x_del', x_del) i2 = st2.find_atom_num_by_xcart( x_del, prec=0.45, ) 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.45) # the positions were changed # check if this is correct i2 = st2.find_atom_num_by_xcart(x_del, prec=0.45) 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 and search_type is not None: st1s = st1.replace_atoms([i1], 'Pu') st2s = st2.replace_atoms([i2], 'Pu') else: st1s = copy.deepcopy(st1) st2s = copy.deepcopy(st2) if center_on_moving and search_type is not None: 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') print(a) 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]) if run: add_loop_dic['run'] = run add_loop_dic['corenum'] = corenum # print(add_loop_dic) 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, # params=params, **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
cl2.read_results(show='fo') """2. Create intermediate steps""" interpolate(cl1.end, cl2.end, images, 3) printlog('Interpolation was successful!\n', imp='y') """3. Calculate energies of intermediate steps""" update_incar(parameter='NSW', value=0, run=1, write=0) for v in range(3, 3 + images): vasp_step(v, 'Intermediate position' + str(v), 1) elif mode == 'inherit': #from initial to last cl2 = vasp_step(2, 'Final position', 1) cl1 = vasp_step(1, 'Start position', 0) # copyfile(str(v)+'.POSCAR', 'POSCAR') update_incar(parameter='NSW', value=0, run=1, write=0) interpolate(cl1.end, cl2.end, images, 21, omit_edges=0) for v in range(21, 21 + images): vasp_step(v, 'Intermediate position' + str(v), rm=0) runBash('rm CHGCAR WAVECAR; gunzip 2.CHGCAR.gz; mv 2.CHGCAR CHGCAR') interpolate(cl2.end, cl1.end, images, 42, omit_edges=0) for v in range(42, 42 + images): vasp_step(v, 'Intermediate position' + str(v), rm=0) runBash('rm CHG WAVECAR') printlog('PH simulation finished!', imp='y')
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