def write_occmatrix(occs, folder): #create OCCMATRIX makedir(folder) printlog('I create OCCMATRIX in ', folder, imp='y') filename = folder + '/OCCMATRIX' with open(filename, 'w', newline='') as f: numat = len(occs) f.write(str(numat) + ' #num of atoms to be specified\n') at_nums = occs.keys() at_spin = [] # # 2 or 1 at_ltyp = [] # l - orbital type, 1 - s, 2 - d, 3 - f for key in occs: occ = occs[key] if len(occ) == 10: # spin polarized, d orbital at_spin.append(2) at_ltyp.append(2) else: raise RuntimeError # please write by yourself for other cases for i, l, s in zip(at_nums, at_spin, at_ltyp): f.write(list2string([i + 1, l, s]) + ' #i, l, s\n') # for sp in range(s): f.write('spin 1\n') for row in occs[i][0:len(occs[i]) // s]: f.write(list2string(row) + '\n') if s == 2: f.write('spin 2\n') for row in occs[i][len(occs[i]) // s:]: f.write(list2string(row) + '\n') f.write('\n') return filename
def process_fig_filename(image_name, fig_format): makedir(image_name) if fig_format in image_name: path2saved = str(image_name) elif str(image_name).split('.')[-1] in ['eps', 'png', 'pdf']: path2saved = str(image_name) fig_format = str(image_name).split('.')[-1] else: path2saved = str(image_name) + '.' + fig_format dirname = os.path.dirname(image_name) if not dirname: dirname += '.' path2saved_png = dirname + '/png/' + os.path.basename(image_name) + '.png' makedir(path2saved_png) return path2saved, path2saved_png
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 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 get_from_server(files=None, to=None, to_file=None, addr=None, trygz=True): """ Download files using either paramiko (higher priority) or rsync; For paramiko header.ssh_object should be defined files (list of str) - files on cluster to download to (str) - path to local folder ! to_file (str) - path to local file (if name should be changed); in this case len(files) should be 1 The gz file is also checked RETURN result of download TODO: now for each file new connection is opened, copy them in one connection """ # print(addr) def download(file, to_file): if header.ssh_object: exist = file_exists_on_server(file, addr) # try: if exist: printlog('Using paramiko: ssh_object.get(): from to ', file, to_file) header.ssh_object.get(file, to_file) out = '' # except FileNotFoundError: else: out = 'file not found' else: # print(addr,file,to_file) out = runBash('rsync -uaz ' + addr + ':' + file + ' ' + to_file) if 'error' in out: res = out else: res = 'OK' out = '' printlog('Download result is ', res) return out if '*' in files: printlog('get_from_server(): get by template') files = run_on_server('ls ' + files, addr).splitlines() # print(files) # sys.exit() printlog('get_from_server(): I download', files) elif not is_list_like(files): files = [files] files = [file.replace('\\', '/') for file in files] #make sure the path is POSIX files_str = ', '.join(np.array(files)) printlog('Trying to download', files_str, 'from server', imp='n') for file in files: if not to and not to_file: #use temporary file with tempfile.NamedTemporaryFile() as f: to_file_l = f.name #system independent filename elif not to_file: #obtain filename to_file_l = os.path.join(to, os.path.basename(file)) else: to_file_l = to_file makedir(to_file_l) out = download(file, to_file_l) if out and trygz: printlog('File', file, 'does not exist, trying gz', imp='n') file += '.gz' to_file_l += '.gz' out = download(file, to_file_l) if out: printlog(' No gz either!', imp='n') else: gunzip_file(to_file_l) return out
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_xyz(st=None, path=None, filename=None, file_name=None, include_vectors=True, repeat=1, shift_2view=1.0, replications=None, full_cell=False, analysis=None, show_around=None, show_around_x=None, nnumber=6, only_elements=None, gbpos2=None, gbwidth=1, withgb=False, include_boundary=2, imp_positions=[], imp_sub_positions=None, jmol=None, specialcommand=None, jmol_args=None, sts=None): """Writes st structure in xyz format in the folder xyz/path if repeat == 2: produces jmol script shift_2view - 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 - (x1,x2,x3, element, label)- xcart and element name coordinates additionally to be added to structure; to visulaze all impurity positions: for jmol, additional key 's', 'i' can be added after element imp_sub_positions - list of atom numbers; the typat of these atoms is changed: not used now 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, from 1 show_around_x - show atoms around point, has higher priority only_elements - see local_surrounding replications - list of replications, (2,2,2) full_cell - returns atoms to cell and replicate boundary atoms include_vectors (bool) - write primitive vectors to xyz jmol - 1,0 - use jmol to produce png picture jmol_args - see write_jmol() specialcommand - any command at the end of jmol script sts - list of Structure - write several structures to xyz file - other options are not working in this regime """ if jmol_args == None: jmol_args = {} if st == None: st = sts[0] if replications: st = replic(st, mul=replications, inv=1) def update_var(st): if st.natom != len(st.xred) != len(st.xcart) != len(st.typat) or len( st.znucl) != max(st.typat): printlog("Error! write_xyz: check your arrays.\n\n") if st.xcart == [] or len(st.xcart) != len(st.xred): printlog( "Warining! write_xyz: len(xcart) != len(xred) making xcart from xred.\n" ) st.xcart = xred2xcart(st.xred, st.rprimd) #print xcart[1] return st.rprimd, st.xcart, st.xred, st.typat, st.znucl, len(st.xred) rprimd, xcart, xred, typat, znucl, natom = update_var(st) if file_name: name = file_name elif filename: name = filename else: name = st.name if sts: name += '_traj' printlog("write_xyz(): Name is", name, important='n') if name == '': name = 'noname' if path: basepath = path else: basepath = 'xyz/' suf = '' """Processing section""" if analysis == 'imp_surrounding': if show_around == 0: printlog('Error! number of atom *show_around* should start from 1') suf = '_loc' + str(show_around) lxcart = [] ltypat = [] i = 0 if is_list_like(show_around_x): x = show_around_x x_t = local_surrounding(x, st, nnumber, control='atoms', periodic=True, only_elements=only_elements) # print('write_xyz: local_surround:', x_t) lxcart += x_t[0] ltypat += x_t[1] else: 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, to show around any impurities (all atoms with typat more than one) # 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, only_elements=only_elements) # print x_t[1] lxcart += x_t[0] ltypat += x_t[1] i += 1 xcart = lxcart typat = ltypat natom = len(typat) # print natom, 'nat' name += suf xyzfile = os.path.join(basepath, name + ".xyz") makedir(xyzfile) """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(st) # asdegf """Writing section""" # printlog("Writing xyz: "+xyzfile, imp = 'y') #analyze imp_positions if imp_sub_positions == None: imp_sub_positions = [] nsub = 0 for pos in imp_positions: # if len(pos) > 4: # 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: printlog(imp_sub_positions, ': numbers of found atoms to be changed ') # for i in sorted(indices, reverse=True): # del somelist[i] if include_vectors: nvect = 3 else: nvect = 0 def write(st): rprimd, xcart, xred, typat, znucl, natom = update_var(st) f.write(str(natom + len(imp_positions) - nsub + nvect) + "\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])) if include_vectors: for r in st.rprimd: f.write('Tv {:.10f} {:.10f} {:.10f}\n'.format(*r)) with open(xyzfile, 'w') as f: if sts: for st in sts: write(st) else: for i in range(repeat): write(st) # os._exit(1) printlog('File', xyzfile, 'was written', imp='y') pngfile = None if jmol: """ script mode for jmol. Create script file as well for elobarate visualization """ """Choose gb atoms to change their color""" printlog('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) printlog('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" bn = (basepath + name).replace('.', '_') pngfile = os.getcwd() + '/' + bn + ".png" printlog('imp_positions = ', imp_positions) write_jmol(xyzfile, pngfile, scriptfile, atomselection, rprimd=rprimd, shift=shift_2view, label=[(pos[3], pos[4]) for pos in imp_positions], specialcommand=specialcommand, **jmol_args) return xyzfile, pngfile
def neb_analysis(cl, show, up = None, push2archive = None, old_behaviour = None, results_dic = None, fitplot_args = None, style_dic = None, params = None): """ Analyse traectories and polarons params mep_shift_vector """ if results_dic is None: results_dic = {} calc = header.calc path2mep_s = cl.project_path_cluster+'/'+cl.dir+'/mep.eps' itise = cl.id[0]+'.'+cl.id[1] # print(cl.ldauu) # sys.exit() name_without_ext = 'mep.'+itise+'.U'+str(max(cl.ldauu)) path2mep_l = cl.dir+name_without_ext+'.eps' # print(path2mep_l) if not os.path.exists(path2mep_l) or '2' in up: '' get_from_server(files = path2mep_s, to_file = path2mep_l, addr = cl.cluster_address, ) movie_to = cl.dir+'/movie.xyz' get_from_server(files = cl.project_path_cluster+'/'+cl.dir+'/movie.xyz', to_file = movie_to, addr = cl.cluster_address, ) if os.path.exists(movie_to): makedir('figs/'+name_without_ext+'.xyz') shutil.copyfile(movie_to, 'figs/'+name_without_ext+'.xyz') # trying to get one image closest to the saddle point if old_behaviour and cl.version == 2: #old behaviour, now created automatically in add callc im = cl.set.vasp_params['IMAGES'] # if im % 2 > 0: #odd # i = im//2 + 1 # else: # i = im/2 # if choose_image: # i = choose_image for i in range(im): i+=1 cl_i = copy.deepcopy(cl) cl_i.version+=i cl_i.id = (cl.id[0], cl.id[1], cl_i.version) cl_i.name = str(cl_i.id[0])+'.'+str(cl_i.id[1])+'.'+str(cl_i.id[2]) # print cl_i.name cl_i.path["output"] = cl_i.dir+'0'+str(i)+"/OUTCAR" # for i in range(): cl_i.associated_outcars = [ aso[2:] for aso in cl_i.associated_outcars ] # print cl_i.path["output"] cl_i.state = '2. Ready to read outcar' # if not os.path.exists(cl_i.path["output"]): # load = 'o' outst2 = ("%s"%cl_i.name).ljust(name_field_length) if readfiles: print(outst2+'|'+cl_i.read_results(loadflag, show = show, choose_outcar = choose_outcar) ) else: print_and_log(outst2+' | File was not read') if cl_i.id in calc: #move creation of calcs with images to add_neb '' # print_and_log('Please test code below this message to save prev calcs') # if cl_i != calc[cl_i.id] # if hasattr(calc[cl_i.id], 'prev') and calc[cl_i.id].prev: # prevlist = calc[cl_i.id].prev # else: # prevlist = [calc[cl_i.id]] # cl_i.prev = prevlist # calc[cl_i.id] = cl_i else: calc[cl_i.id] = cl_i # print path2mep_l if 0: if os.path.exists(path2mep_l): # get_from_server(file = path2mep_s, to = path2mep_l, addr = cluster_address) runBash('evince '+path2mep_l) else: a = glob.glob(cl.dir+'*mep*') if a: runBash('evince '+a[0]) cl1 = calc[cl.id[0], cl.id[1], 1] cl2 = calc[cl.id[0], cl.id[1], 2] atom_num = find_moving_atom(cl1.end, cl2.end) #prepare lists ni = cl.set.vasp_params['IMAGES'] vlist = [1]+list(range(3, ni+3) )+[2] # print( vlist) mep_energies = [] atom_pos = [] pols = [] sts = [] sts_loc = [] dAO = [] # A-(O,F) distance for each image for v in vlist: cli = calc[cl.id[0], cl.id[1], v] # print(cl.id[0], cl.id[1], v, cli.state) if '4' not in cli.state and 'un' not in up: printlog('Attention! res_loop(): analys_type == neb, Calc',cli.id,'is not finished; return') return {}, [] # print cli.id # cli.end = return_to_cell(cli.end) # mep_energies.append( min(cli.list_e_sigma0) ) #use minimum energy - not very good, sometimes unconverged energy could be lower! mep_energies.append( cli.energy_sigma0 ) #use last energy atom_pos.append( cli.end.xcart[atom_num] ) # Find polaron positions if 1 or 'polaron' in show: pol, mag = find_polaron(cli.end, atom_num) if pol: for key in pol: if np.any(pol[key]): for n in pol[key]: if n not in pols: pols.append(n) else: '' # print('Mag_moments on trans,', mag.round(1)) if 1 or 'neb_geo' in show: #visualization of path # print(atom_num) st = copy.deepcopy(cli.end) # print('moving_atom', st.xcart[atom_num]) info = st.nn(atom_num, 15, from_one = False, silent = 1) st.moving_atom_i = atom_num st_loc = info['st'] # print(st_loc.xcart) # st_loc = st_loc.shift if v == vlist[0]: st1 = copy.deepcopy(st) vec = st.center_on(atom_num) # vec = np.asarray([0.,0.,0.]) if params is not None and 'mep_shift_vector' in params: # vec += np.array([0.11,0.11,0]) # path4 # print(params['mep_shift_vector']) vec += np.array(params['mep_shift_vector']) # path4 # print(vec) st_loc = st_loc.shift_atoms(vec) if 0: st_loc.write_xyz() # st.write_cif('xyz/'+st.name) st.shift_atoms(vec).write_xyz() sts_loc.append(st_loc) st1 = st1.add_atom(st.xred[atom_num], 'Rb') sts.append(st.shift_atoms(vec)) if 0: info1 = st.nn(atom_num, 2, from_one = False, silent = 1) print('Average_distance A-2(O,F)', info1['av(A-O,F)'], 'A') dAO.append (info1['av(A-O,F)']) if 0 or 'neb_geo' in show: av = st.nn(atom_num, 2, from_one = False, silent = 1, more_info = 1)['avsq(A-O,F)'] print('Average squared distance A-2(O,F)', av, 'A') info2 = st.nn(atom_num, 4, from_one = False, silent = 1) print('Average_distance A-4(O,F)', info2['av(A-O,F)'], 'A') print('Elements are ', info2['el']) info3 = st.nn(atom_num, 6, from_one = False, silent = 1, more_info = 1) print('Average_distance A-6(O,F)', info3['av(A-O,F)'], 'A') print('Average_deviation A-6(O,F)', info3['avdev(A-O,F)'], 'mA') print('Elements are ', info3['el']) write_xyz(sts = sts) # write traectory write_xyz(sts = sts_loc) # write traectory st1 = st1.shift_atoms(vec) st1.name +='_all' # st1.write_cif('xyz/'+st1.name) st1.write_xyz() if dAO: # find maximum change of distance during migration dAO_change = abs(min(dAO) - max(dAO)) results_dic['dAO_change'] = dAO_change results_dic['sts_loc'] = sts_loc # list of local structures, each structure contains dlist - distances from central cation to anions, and ellist - types of elements results_dic['sts'] = sts # list of mep structures, each structure contains moving_atom_i - number of moving atom if len(pols) > 0: print('During migration of alkali ions polarons are detected on atoms:', pols) elif len(pols) > 1: printlog('Attention! polaron is moving during migration! Obtained barrier is ambiguous') else: printlog('Compare magnetic moments above! In principle should be the same!') # print np.array(atom_pos) #test if the distances between points are not spoiled by PBC nbc = range(-1, 2) jj=0 for x in atom_pos: x2 = atom_pos[jj+1] r = cl.end.rprimd d1, _ = image_distance(x, x2, r, order = 1) #minimal distance x2_gen = (x2 + (r[0] * i + r[1] * j + r[2] * k) for i in nbc for j in nbc for k in nbc) #generator over PBC images x2c = copy.deepcopy(x2) ii = 0 while np.linalg.norm(x - x2c) > d1: #find the closest PBC image position if ii > 100: break ii+=1 x2c = next(x2_gen) atom_pos[jj+1] = x2c jj+=1 if jj == len(atom_pos)-1: # the last point is not needed, we could not use slice since we need to use changed atom_pos in place break # print np.linalg.norm(x - x2c), d1 _, diff_barrier = plot_mep(atom_pos, mep_energies, plot = 0, show = 0, fitplot_args = fitplot_args, style_dic = style_dic) results_dic['barrier'] = diff_barrier middle_image = len(vlist) // 2 results_dic['dEm1'] = mep_energies[middle_image] - mep_energies[0] cl1.barrier = diff_barrier cl2.barrier = diff_barrier if 'mep' in show: if 'mepp' in show: show_flag = True else: show_flag = False # sys.exit() plot_mep(atom_pos, mep_energies, image_name = 'figs/'+name_without_ext+'_my.eps', show = show_flag, fitplot_args = fitplot_args, style_dic = style_dic) if push2archive: path2saved, _ = plot_mep(atom_pos, mep_energies, image_name = 'figs/'+name_without_ext+'_my', fitplot_args = fitplot_args, style_dic = style_dic) push_figure_to_archive(local_figure_path = path2saved, caption = description_for_archive) if 0: #copy files according to chosen outcar to run nebresults locally wd = cl_i.dir out_i = cl_i.associated_outcars[choose_outcar-1] out_1 = calc[cl.id[0],cl.id[1], 1].associated_outcars[choose_outcar-1] out_2 = calc[cl.id[0],cl.id[1], 2].associated_outcars[choose_outcar-1] # print out_1 # print out_2 shutil.copyfile(wd+out_1, wd+'00/OUTCAR') shutil.copyfile(wd+out_2, wd+'04/OUTCAR') for d in ['01/','02/','03/' ]: shutil.copyfile(wd+d+out_i, wd+d+'OUTCAR') # print wd+d+out_i return results_dic
def fit_a(conv, n, description_for_archive, analysis_type, show, push2archive): """Fit equation of state for bulk systems. The following equation is used:: sjeos (default) A third order inverse polynomial fit 10.1103/PhysRevB.67.026103 2 3 -1/3 E(V) = c + c t + c t + c t , t = V 0 1 2 3 taylor A third order Taylor series expansion about the minimum volume murnaghan PRB 28, 5480 (1983) birch Intermetallic compounds: Principles and Practice, Vol I: Principles. pages 195-210 birchmurnaghan PRB 70, 224107 pouriertarantola PRB 70, 224107 vinet PRB 70, 224107 antonschmidt Intermetallics 11, 23-32 (2003) p3 A third order polynomial fit Use:: eos = EquationOfState(volumes, energies, eos='sjeos') v0, e0, B = eos.fit() eos.plot() """ # e, v, emin, vmin = plot_conv( conv[n], calc, "fit_gb_volume2") from picture_functions import fit_and_plot alist = [] vlist = [] etotlist = [] magn1 = [] magn2 = [] alphas= [] for id in conv[n]: cl = db[id] st = cl.end alist.append(cl.end.rprimd[0][0]) etotlist.append(cl.energy_sigma0) vlist.append(cl.end.vol) magn1.append(cl.magn1) magn2.append(cl.magn2) alpha, beta, gamma = st.get_angles() alphas.append(alpha) print('alpha, energy: {:4.2f}, {:6.3f}'.format(alpha, cl.energy_sigma0)) fit_and_plot(U1 = (alphas, etotlist, 'o-r'), image_name = 'figs/angle', ylabel = 'Total energy, eV', xlabel = 'Angle, deg', xlim = (89, 92.6)) if ase_flag: if 'angle' in analysis_type: eos = EquationOfState(alphas, etotlist, eos = 'sjeos') else: eos = EquationOfState(vlist, etotlist, eos = 'sjeos') # import inspect # print (inspect.getfile(EquationOfState)) v0, e0, B = eos.fit() #print "c = ", clist[2] printlog( ''' v0 = {0} A^3 a0 = {1} A E0 = {2} eV B = {3} eV/A^3'''.format(v0, v0**(1./3), e0, B), imp = 'Y' ) savedpath = 'figs/'+cl.name+'.png' makedir(savedpath) cl.B = B*160.218 # plt.close() # plt.clf() # plt.close('all') if 'fit' in show: mpl.rcParams.update({'font.size': 14}) eos.plot(savedpath, show = True) printlog('fit results are saved in ',savedpath, imp = 'y') else: printlog('To use fitting install ase: pip install ase') # plt.clf() if push2archive: push_figure_to_archive(local_figure_path = savedpath, caption = description_for_archive) return
def add_to_archive_database(cl, subgroup): """ cl is Calculation which should be added to database subgroup (str) - subgroup folder """ from pymatgen.core.composition import Composition from pymatgen.io.cif import CifWriter from pymatgen.symmetry.analyzer import SpacegroupAnalyzer join = os.path.join basename = os.path.basename dirname = os.path.dirname save_format = 'azh' dbpath = header.PATH2DATABASE it = cl.id[0] # print(cl.path) sub_folder = cl.path['output'].split('/')[ 0] # usually basic chemical formula # sub_folder = header.struct_des[it].sfolder.split('/')[0] # usually basic chemical formula print('Processing ', cl.id) cl.read_results() if '4' not in cl.state: return st = cl.end # print(cl.end.typat) # sys.exit() if 1: #determine x #universal method, supports several alkali elements #requires cl.base_formula in 'Na2FePO4F' format #requires pymatgen, would be nice to remove dependency cmb = Composition(cl.base_formula) cm = st.get_pm_composition() rc = cl.end.get_reduced_composition().as_dict( ) #reduced composition dict rcb = cmb.reduced_composition.as_dict() # print(rc, rcb) alk = list(set(st.get_specific_elements( header.ALKALI_ION_ELEMENTS))) # list of unique alkali elements tra = list(set(st.get_specific_elements(header.TRANSITION_ELEMENTS))) # print(alk, tra) el_for_norm = tra[0] #first element used for normalization nnb = rcb[el_for_norm] #number of norm elements in base nn = rc[el_for_norm] #number of norm elements in interesting structure # print(nb, n) mul = nn / nnb # multiplier that garanties normalization # print(rcb) nab = sum([ rcb[invert(z)] for z in header.ALKALI_ION_ELEMENTS if invert(z) in rcb ]) na = sum([rc[el] for el in alk]) x = na / mul / nab # determine formula # cm = st.get_pm_composition() #get pymatgen composition class # print( (cm/4).formula) # print('Material detected:', formula, 'sub_folder:', sub_folder) #obtain base without alk formula = (cm.reduced_composition / mul).formula # formula = formula.replace('1 ', '').replace(' ', '') # print(formula) cl.formula = formula # print(Composition('Na0.75')) print('Material detected:', formula, 'sub_folder:', sub_folder) # sys.exit() if 0: #Old method, not robust at all! #determine x for alkali ion from structure name parsed = re.findall(r'([A-Z][a-z]*)(\d*)', formula) parsed = [(el, x if x else '1') for (el, x) in parsed] print(parsed) print('detected element is ', parsed[0][0]) if parsed[0][0] in [invert(z) for z in header.ALKALI_ION_ELEMENTS]: x = parsed[0][0] if hasattr(cl, 'max_alk_ion_content'): x = float(x) / cl.max_alk_ion_content else: x = '1' else: x = '0' sfolder = os.path.join(dbpath, sub_folder) name = [] if 'azh' in save_format: #1. Single point calculation of total energy # print(sfolder) makedir(join(sfolder, 'dummy')) if x < 1: x = int(round(100 * x, 0)) else: x = int(round(x, 0)) print('Concentration x:', x) name.append('x' + str(x)) # sys.exit() # if formula in ['LiCoO2', 'LiTiO2', 'LiFePO4', 'NaFePO4', 'LiMnPO4', # 'LiNiO2', 'LiTiS2', 'LiMn2O4', 'LiVP2O7', 'LiVPO4F', # 'NaMnAsO4', 'Na2FePO4F', 'Na2FeVF7', 'KFeSO4F', 'NaLiCoPO4F', 'KVPO4F' ]: sfolder = join(sfolder, subgroup) makedir(join(sfolder, 'dummy')) cl.set.update() # print(cl.potcar_lines) potcar1_m = cl.potcar_lines[0][0] if '_' in potcar1_m: (pot, _) = potcar1_m.split('_') else: pot = potcar1_m xc = cl.xc_inc if '-' in xc: xc = cl.xc_pot if xc == 'PE': func = 'PBE' elif xc == 'CA': func = 'LDA' elif xc == 'PS': func = 'PBEsol' else: print('uknown xc type:', xc) sys.exit() if cl.set.spin_polarized: func = 'U' + func #unrestricted u_ramping_flag = False if hasattr(cl.set, 'u_ramping_nstep') and cl.set.u_ramping_nstep: func += '-UR' u_ramping_flag = True elif cl.set.dftu: func += '-U' else: func += '-' func += pot.lower() ecut = str(round(cl.set.ecut)) func += ecut # print(func) name.append(func) name.extend([it.replace('.', '_')] + [cl.id[1]] + [str(cl.id[2])]) name_str = '_'.join(name) # print('_'.join(name) ) # sys.exit() outcar_name = name_str + '.out' shutil.copyfile(cl.path["output"], join(sfolder, outcar_name)) if u_ramping_flag: print(cl.associated_outcars) for i, u_outcar in enumerate( cl.associated_outcars[:-1] ): # except the last one, which was copied above u = u_outcar.split('.')[1] # print(u) path_to_outcar = join(dirname(cl.path["output"]), u_outcar) cl.read_results(load='o', choose_outcar=i + 1, only_load=1) shutil.copyfile(path_to_outcar, join(sfolder, name_str + '_' + u + '.out')) # sys.exit() cl.end.write_xyz(path=sfolder, filename=name_str) pickle_file = cl.serialize(os.path.join(sfolder, 'bin', name_str)) # cl #write input, problem with fitted version 100, which does not have input geometry, since they are created on cluster # makedir(sfolder+'input/dummy') # shutil.copyfile(cl.path["input_geo"], sfolder+'input/'+name_str+'.geo') st_mp = cl.end.convert2pymatgen() sg_before = st_mp.get_space_group_info() # from pymatgen.symmetry.finder import SymmetryFinder # sf = SymmetryFinder(st_mp_prim) symprec = 0.1 sf = SpacegroupAnalyzer(st_mp, symprec=symprec) st_mp_prim = sf.find_primitive() # st_mp_prim = sf.get_primitive_standard_structure() # st_mp_prim = sf.get_conventional_standard_structure() # st_mp_conv = sf.get_conventional_standard_structure() # print(st_mp_conv) # print(st_mp_conv.lattice.matrix) # print(st_mp_prim) # print(st_mp_prim.lattice) sg_after = st_mp_prim.get_space_group_info() if sg_before[0] != sg_after[0]: printlog( 'Attention! the space group was changed after primitive cell searching', sg_before, sg_after) printlog('I will save supercell in cif and reduce symprec to 0.01') st_mp_prim = st_mp symprec = 0.01 if st_mp_prim: cif = CifWriter(st_mp_prim, symprec=symprec) cif_name = name_str + '.cif' cif.write_file(join(sfolder, cif_name)) printlog('Writing cif', cif_name) if 0: #get multiplication matrix which allows to obtain the supercell from primitive cell. #however this matrix is not integer which is not convinient. print(st_mp.lattice.matrix.round(2)) print(st_mp_prim.lattice.matrix.round(2)) mul_matrix = np.dot(st_mp.lattice.matrix, np.linalg.inv(st_mp_prim.lattice.matrix)) print(mul_matrix.round(1)) rprimd = np.dot(mul_matrix, st_mp_prim.lattice.matrix) print(rprimd.round(2)) #write chg if 1: path_to_chg = cl.get_chg_file('CHGCAR') if path_to_chg: makedir(join(sfolder, 'bin', 'dummy')) printlog('path to chgcar', path_to_chg) gz = '.gz' if gz not in path_to_chg: gz = '' shutil.copyfile(path_to_chg, join(sfolder, 'bin', name_str + '.chg' + gz)) #write dos if subgroup in ['dos', 'DOS']: DOSCAR = cl.get_file('DOSCAR', nametype='asoutcar') if DOSCAR: printlog('path to DOSCAR', DOSCAR) gz = '.gz' if gz not in path_to_chg: gz = '' shutil.copyfile(DOSCAR, join(sfolder, 'bin', name_str + '.dos' + gz)) if subgroup in ['BAD']: #bader cl.get_bader_ACF() acf = cl.get_file(basename(cl.path['acf'])) # print(acf) # sys.exit() if acf: shutil.copyfile(acf, join(sfolder, 'bin', name_str + '.acf')) if subgroup in ['ph', 'PH']: #bader # cl.get_bader_ACF() xml = cl.get_file('vasprun.xml', nametype='asoutcar') # print(acf) # sys.exit() if xml: shutil.copyfile(xml, join(sfolder, 'bin', name_str + '.xml')) #make dat #incars makedir(join(sfolder, 'dat', 'dummy')) incars = glob.glob(join(cl.dir, '*INCAR*')) # print(incars) for inc in incars: dest = join(sfolder, 'dat') # inc_name = if not os.path.exists(join(dest, basename(inc))): shutil.copy(inc, dest) #kpoints if it in header.struct_des: with open(join(sfolder, 'dat', 'kpoints_for_kspacings.json'), 'w', newline='') as fp: json.dump( header.struct_des[it].ngkpt_dict_for_kspacings, fp, ) else: printlog('Warning!, it not in struct_des:', it) # print(cl.set.toJSON()) #prepare for neb # makedir(sfolder+'neb_'+name_str+'/dummy') return
def get_from_database(x1, x2, mat, inquiry_keys=None, silent=None, ssh_object=None): """ inquiry_keys (list) - list of keys that should exist in filenames both for x1 and x2 ssh_object (SSHTools) - ssh object based on paramiko with access details """ from classes import CalculationVasp def check(key, inquiry_keys): return all([k in key for k in inquiry_keys]) path2database = '/home/Data/CEStorage/' hash_dict_file = 'hash_dict.json' cluster_path2hash = os.path.join(path2database, hash_dict_file) if inquiry_keys is None: inquiry_keys = [] if ssh_object: # ssh_object.get() tempdir = tempfile.gettempdir() local_path2hash = os.path.join(tempdir, hash_dict_file) ssh_object.get(cluster_path2hash, local_path2hash) # sys.exit() with open(local_path2hash, 'r') as fp: hash_dict = json.load(fp) # print(hash_dict) x1s = [] x2s = [] # print(hash_dict) for key, val in hash_dict.items(): if check(key, inquiry_keys + [x1, mat]): x1s.append(key) if check(key, inquiry_keys + [x2, mat]): x2s.append(key) x1s = sorted(x1s, key=lambda el: len(el)) x2s = sorted(x2s, key=lambda el: len(el)) for xi, xis in (x1, x1s), (x2, x2s): if not silent: print('\nFiles for', xi, ':') for i, f in enumerate(xis): if not silent: print(i + 1, f) if len(x1s) == 0 or len(x2s) == 0: print('No information in database for this inquire:', x1, x2, mat, str(inquiry_keys)) return None, None key1 = x1s[0] key2 = x2s[0] if not silent: print('\nI choose first entries for both concentrations:', key1, 'and', key2, '\n') # print('Use *inquiry_keys* arg to clarify the output results.\n') #get files loc1 = os.path.join(tempdir, hash_dict[key1]) loc2 = os.path.join(tempdir, hash_dict[key2]) makedir(loc1) makedir(loc2) # print()/ ssh_object.get(os.path.join(path2database, hash_dict[key1]), loc1) ssh_object.get(os.path.join(path2database, hash_dict[key2]), loc2) cl1 = CalculationVasp().deserialize(loc1) cl2 = CalculationVasp().deserialize(loc2) return cl1, cl2