def optimize_wrapper(cl, ise, add=0, show_fit=1, params=None): #wrapper for optimization function up_res = 'up1' readfiles = 1 check_job = 1 id_res = (cl.id[0] + '.su', ise, 100) if add: add_loop(*cl.id, ise_new=ise, up='up2', calc_method='uniform_scale', scale_region=(-4, 4), input_st=cl.end, show='', run=0, inherit_option='inherit_xred', it_folder=cl.sfolder + '/scaled/', params=params) else: if show_fit: res_loop(*id_res[0:2], list(range(0 + 1, 0 + 8)) + [100], up=up_res, readfiles=readfiles, analys_type='fit_a', show='fitfo') else: res_loop(*id_res, up=up_res, show='fo', check_job=check_job)
def run_wrapper(sts, ise = None, add = 0, cl = None, suf = 'w', it_folder = None, ngkpt = None, acc = None, ise1= None, acc2 = None, ise2 = None): """ Add Several structures """ folder = suf.replace('.', '') # print(folder) # sys.exit() if ise1 is None: ise1 = ise for i, st in enumerate(sts): itn = cl.id[0]+suf+ str(i) # del header.struct_des[itn] # continue if add: add_loop(itn, ise, 1, show = 'fo', up = 'up2', input_st = st, ngkpt = ngkpt, it_folder = cl.sfolder+'/'+folder+'/', ) # else: '' if acc: if acc2: db[itn+'.ifc', ise1, 1].run(ise2, show = 'fo', iopt = 'full_chg', add = 0, up = 'up2', ngkpt = ngkpt) else: db[itn, ise, 1].run(ise1, show = 'fo', iopt = 'full_chg', add = 0, up = 'up2', ngkpt = ngkpt) else: res_loop(itn, ise, 1, up = 'up2') return
def calc_bulk_list(data_list, spacegroup='', ise_nomag='8', ise_mag='8m', status=None, up=None, corenum=1): """ function can add or res for set of bulk calculations data_list = read_pmg_info() of some csv file ise - set of calculation. Usually use '8' for nonmag calc and '8m' for mag calc status = add or res """ spacegroup = '.' + spacegroup for i in data_list: st = get_matproj_st(i) if float(i['total_magnetization']): mag_flag = 1 ise = ise_mag else: mag_flag = 0 ise = ise_nomag if status == 'add': add_loop(i['pretty_formula'] + spacegroup, ise, 1, it_folder='bulk', input_st=st, corenum=corenum) if status == 'res': try: res_loop(i['pretty_formula'] + spacegroup, ise, 1, it_folder='bulk', up=up) except KeyError: print(i['total_magnetization'])
def run_wrapper(sts, ise=None, add=0, cl=None, suf='w', it_folder=None, cls=None, ngkpt=None, acc=None, ise1=None, acc2=None, ise2=None, params=None): """ Add Several structures params - pass to add_loop if add == 0: read results RETURN cl with lowest energy """ if params is None: params = {} folder = suf.replace('.', '') # print(folder) # sys.exit() if ise1 is None: ise1 = ise if cls is None: cls = [cl] * len(sts) energies = [] for i, st, cl_i in zip(range(len(sts)), sts, cls): itn = cl_i.id[0] + suf + str(i) # del header.struct_des[itn] # continue if add: # add_loop(itn, ise, 1, show = 'fo', up = 'up2', input_st = st, ngkpt = ngkpt, it_folder = cl.sfolder+'/'+folder+'/', **params ) # add_loop(itn, ise, 1, show='fo', up='up2', input_st=st, ngkpt=ngkpt, it_folder=cl.sfolder, **params) # else: '' if acc: if acc2: db[itn + '.ifc', ise1, 1].run(ise2, show='fo', iopt='full_chg', add=0, up='up1', ngkpt=ngkpt) cln = db[itn + '.ifc.ifc', ise2, 1] else: # db[itn, ise, 1].run(ise1, show = 'fo', iopt = 'full_chg', add = 0, up = 'up1', ngkpt = ngkpt) cln = db[itn + '.ifc', ise1, 1] cln.res(choose_outcar=0, show='fo') suf_acc = '.ifc' else: suf_acc = '' res_loop(itn, ise, 1, up='up1') cln = db[itn, ise, 1] if hasattr(cln, 'e0'): energies.append(cln.e0) for i, e in enumerate(energies): print(i, e) if not add and len(energies) > 0: i_min = energies.index(min(energies)) print('Minimum energy is for ', i_min, energies[i_min]) itn = cl.id[0] + suf + str(i_min) + suf_acc db[itn, ise, 1].res() return db[itn, ise, 1] else: return None
def make_defect(cl, el, st_type='end', option='vac', pos=None, ise=None, opt_vol=0, suf='', it_folder=None, el_rep='', pos_rep=1, pos_rep2=None, polaron_pos=None, occ_matrix=None, up=0, fit=0, outcar=None, only_read=0, Eref=0, compat1=False, add_loop_arg={}): """ Function allow to create point defects and run them previous name: make_vacancy() cl - starting Calculation st_type - starting structure of cl: 'init' or 'end' el - element to be removed or replaced option - 'vac' - make vacancy 'rep' - replace one atom with 'el_rep', 'pair' - make vacancy -Ti complex for V-Ti project pos - unique position of el if non-eqivalent atoms exist - for vac pos_rep - number of position to replace from 0 ise - new set opt_vol (bool) - optimize volume suf (str) - mannually added suffix it_folder - mannually provided it_folder up (bool) - [ 0, 1 ] update current calculation fit = 0, outcar = None, only_read = 0 - flow control as usual polaron_pos - choose polaron position occ_matrix - list of lists see format in classes compat1 - compatability with previous calculations, which were used for Na2FePO4F project Eref - reference energy for solution energy TODO: rename to ?_point_defects() """ from siman.project_funcs import e_bind if pos == None: pos = '' if polaron_pos == None: pol_suf = '' else: pol_suf = '.p' + str(polaron_pos) # polaron suffix ssuf = el + str(pos) + el_rep + pol_suf + suf if 'su' in cl.id[0] and not 'su.' in cl.id[0]: it_new = cl.id[0].replace('su', option) + ssuf else: it_new = cl.id[0] + option + ssuf if compat1: # no element in name it_new = cl.id[0].replace('su', 'vac') + str(pos) id_new, st, it_folder = prepare(it_new, opt_vol, it_folder, ise, cl, st_type, option) occfile = None if not only_read and (up or id_new not in calc): # it_new if 'vac' in option: st_del1, i_del = remove_one_atom(st, el, pos) st_vis = st.replace_atoms([i_del], 'U') st_vis.name = it_new + '_visual' st_vis.write_xyz() #possible polaron positions tr = st.get_transition_elements(fmt='z') i_tr = st.get_transition_elements(fmt='n') # dist = [] max_d = 0 i_max_d = None for i in i_tr: d1, d2 = image_distance(st.xcart[i], st.xcart[i_del], st.rprimd) # print(i+1, d1, d2) if d1 < d2: if d1 > max_d: max_d = d1 i_max_d = i if i_max_d is not None: print( 'The longest distance to transition metal in current supercell is ', max_d, 'A for atom', i_max_d + 1, st.get_elements()[i_max_d]) numb = st.nn(i_del, from_one=0, n=len(tr) + 5, only=list(set(tr)))['numbers'][1:] printlog( 'Choose polaron position starting from 1 using *polaron_pos*', imp='y') if polaron_pos: i_pol = numb[polaron_pos - 1] printlog('atom', i_pol + 1, st.get_elements()[i_pol], 'is chosen', imp='y') # print(numb) # sys.exit() #take_occupation matrices from cl print('substitution occupation matrix of atom', i_pol + 1) occ_matrices = copy.deepcopy(cl.occ_matrices) occ_matrices[i_pol] = occ_matrix # print(pd.DataFrame(cl.occ_matrices[i_pol])) occfile = write_occmatrix(occ_matrices, cl.dir + '/occ/') # print(occfile) # sys.exit() else: occfile = None elif 'rep' in option: st_del1 = st.replace_atoms([pos_rep], el_rep) print( 'Atom', str(pos_rep), st.get_elements()[pos_rep], ' replaced with', el_rep, ) print(st_del1.get_elements()[pos_rep]) st_del1.name = it_new elif 'pair' in option: st_del1 = st.replace_atoms([1], el_rep) if 'pair2' in option: st_del1 = st_del1.replace_atoms([pos_rep2], el_rep) st_del1 = remove_one_atom(st_del1, el, pos) print('Atom 1 replaced with', el, 'and atom removed') st_del1.name = it_new st_del1.write_xyz() if opt_vol: it = add_loop(it_new, ise, 1, calc_method='uniform_scale', scale_region=(-4, 4), inherit_option='inherit_xred', input_st=st_del1, it_folder=it_folder, params={'occmatrix': occfile}, **add_loop_arg) else: it = add_loop(it_new, ise, 1, input_st=st_del1, it_folder=it_folder, params={'occmatrix': occfile}, **add_loop_arg) else: if opt_vol and fit: res_loop(it_new + '.su', ise, list(range(1, 8)) + [100], analys_type='fit_a', show='fitfo', up='2', choose_outcar=outcar) else: res_loop(*id_new, up='2', choose_outcar=outcar, show='fo') # calc[it_new+'.su', ise, 100].end.jmol() cl_v = calc[id_new] if '4' not in cl.state: cl.res() if not hasattr(cl_v, 'e0'): printlog('Warning', cl_v.id, 'is bad') return calc_redox(cl_v, cl) # print(cl_v.end.vol, cl.end.vol) dE = None if option == 'vac': cl_v.res() cl.res() print('Evac = {:3.2f} eV'.format(cl_v.e0 - cl.e0 / cl.end.natom * cl_v.end.natom)) elif option == 'rep': diffE, diffV = matrix_diff(cl_v, cl) print('Esol = {:3.2f} eV'.format(diffE - Eref)) elif 'pair' in option: '' cl_bulk = cl cl_pair = cl_v it = cl.id[0] if 'V54' in it: it = it.replace('.su', '.') id_vac = (it + 'vacV', cl.id[1], 1) id_sol = (it + 'repTi', cl.id[1], 1) cl_vac = calc[id_vac] cl_sol = calc[id_sol] # print(id_vac, id_sol) # if option == 'pair': dE = e_bind(cl_bulk, cl_vac, cl_sol, cl_pair) print('Ecomplex = {:3.2f} eV'.format(dE)) # elif '2' in option: return {'dE': dE, 'N': cl_v.end.natom, 'Name': cl.id}
def process_modified(cl, mod_dic=None, scale_region=(-4, 4), opt_vol=1, fit=0, st_type='end', name=None, el_new=None, run=0, ise=None, it_folder=None, mode=None, add_loop_arg=None): """ inherited from create_charges - functionality is extended The utility allows to (contrlolled by mode parameter): 1) create charged cells by removing specific atoms provided in del_dic 2) replace specific atoms add_loop res_loop mode - delete remove None mod_dic - dic of configurations with atom numbers starting from 1 """ # if not del_dic: if add_loop_arg == None: add_loop_arg = {} if mod_dic == None: mod_dic = {1: 1} for key in mod_dic: mod_pos = mod_dic[key] if mode: mod_pos = [p - 1 for p in mod_pos] if mode: suf = '.' + mode[0] + str(key) else: suf = '' it_new = cl.id[0] + suf id_new, stA, it_folder = prepare(it_new, opt_vol, it_folder, ise, cl, st_type, mode) if run: if mode == 'delete': st = stA.remove_atoms(mod_pos) elif mode == 'replace': st = stA.replace_atoms(atoms_to_replace=mod_pos, el_new=el_new) else: st = stA st.name += suf st.write_xyz() # sys.exit() if opt_vol: add_loop(it_new, id_new[1], 1, calc_method='uniform_scale', scale_region=scale_region, inherit_option='inherit_xred', input_st=st, it_folder=it_folder, **add_loop_arg) else: add_loop(it_new, id_new[1], 1, input_st=st, it_folder=it_folder, **add_loop_arg) else: if 'check_job' in add_loop_arg: cj = add_loop_arg['check_job'] else: cj = None if opt_vol and fit: # res_loop(id_new[0], id_new[1], list(range(1,8))+[100], analys_type = 'fit_a', show = 'fitfo', up = '2', choose_outcar = None) res_loop(id_new[0], id_new[1], list(range(1, 8)) + [100], analys_type='fit_a', show='fitfo', up='2', choose_outcar=None, check_job=cj) else: res_loop(*id_new, up='1', choose_outcar=None, show='fo') 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
def run_wrapper(sts, ise=None, add=0, cl=None, suf='w', it_folder=None, cls=None, ngkpt=None, acc=None, ise1=None, acc2=None, ise2=None, params=None): """ Add Several structures params - pass to add_loop """ if params is None: params = {} folder = suf.replace('.', '') # print(folder) # sys.exit() if ise1 is None: ise1 = ise if cls is None: cls = [cl] * len(sts) for i, st, cl in zip(range(len(sts)), sts, cls): itn = cl.id[0] + suf + str(i) # del header.struct_des[itn] # continue if add: add_loop(itn, ise, 1, show='fo', up='up2', input_st=st, ngkpt=ngkpt, it_folder=cl.sfolder + '/' + folder + '/', **params) # else: '' if acc: if acc2: db[itn + '.ifc', ise1, 1].run(ise2, show='fo', iopt='full_chg', add=0, up='up2', ngkpt=ngkpt) else: db[itn, ise, 1].run(ise1, show='fo', iopt='full_chg', add=0, up='up2', ngkpt=ngkpt) else: res_loop(itn, ise, 1, up='up2') return
def calc_suf_stoich_mat(self, ise='9sm', bulk_cl_name=None, it_folder='bulk/', status='create', suf_list=None, min_slab_size=12, only_stoich=1, corenum=4, cluster='cee', conv=1, create=1, reset_old_polar=0, reset_old_nonpolar=0, suffix=None, polar=1, nonpolar=1): from siman.header import db from siman.geo import create_surface2, stoichiometry_criteria, stoichiometry_criteria2, symmetry_criteria, calc_k_point_mesh from siman.calc_manage import add_loop, res_loop if not bulk_cl_name: bulk_cl_name = ['it', 'ise', '1'] if not suf_list: suf_list = [[1, 1, 0], [1, 1, 1]] st_bulk = db[self.bulk_cl_scale].end.get_conventional_cell() # if conv: # st_bulk = st_bulk.get_conventional_cell() st_name = '.'.join( [self.pretty_formula, self.sg_crystal_str, self.sg_symbol]) st_name = st_name.replace('/', '_') # st_bulk.printme() try: # print(self.suf) self.suf_pol.keys() except AttributeError: self.suf_pol = {} self.suf_pol_status = {} try: # print(self.suf) self.suf_nonpol.keys() except AttributeError: self.suf_nonpol = {} self.suf_nonpol_status = {} try: self.suf_pol_cl.keys() except AttributeError: self.suf_pol_cl = {} try: self.suf_nonpol_cl.keys() except AttributeError: self.suf_nonpol_cl = {} try: self.suf_en_pol.keys() except AttributeError: self.suf_en_pol = {} try: self.suf_en_nonpol.keys() except AttributeError: self.suf_en_nonpol = {} if reset_old_polar: self.suf_pol = {} self.suf_pol_status = {} self.suf_pol_cl = {} self.suf_en_pol = {} if reset_old_nonpolar: self.suf_nonpol = {} self.suf_nonpol_status = {} self.suf_nonpol_cl = {} self.suf_en_nonpol = {} ##################### create slab if status == 'create': try: for surface in suf_list: print(surface) if self.suf_pol == {} or ''.join( [str(surface[0]), str(surface[1]), str(surface[2])]) not in self.suf_pol.keys(): ###############polar if polar: print('Polar_suf') slabs_polar = create_surface2( st_bulk, miller_index=surface, min_slab_size=min_slab_size, min_vacuum_size=15, surface_i=0, symmetrize=0, lll_reduce=1, primitive=1) for sl_i in slabs_polar: st = st_bulk sl = st.update_from_pymatgen(sl_i) print(' Stoichoimetry:', stoichiometry_criteria2(st, sl), ' Eqvuivalent:', sl_i.have_equivalent_surfaces()) ############nonpolar if nonpolar: print('Nonpolar_suf') slabs_nonpolar = create_surface2( st_bulk, miller_index=surface, min_slab_size=min_slab_size, min_vacuum_size=15, surface_i=0, symmetrize=1, lll_reduce=1, primitive=1) for sl_i in slabs_nonpolar: st = st_bulk sl = st.update_from_pymatgen(sl_i) print(' Stoichoimetry:', stoichiometry_criteria2(st, sl), ' Eqvuivalent:', sl_i.have_equivalent_surfaces()) if create: ###############polar if polar: if len(slabs_polar): s_i = 0 n = 0 for sl_i in slabs_polar: st = st_bulk sl = st.update_from_pymatgen(sl_i) if stoichiometry_criteria2( st, sl ) and sl_i.have_equivalent_surfaces( ) == False: # if sl.natom < 31: suf_name = str(surface[0]) + str( surface[1]) + str( surface[2]) + '.' + str(s_i) # if self.suf_pol_status == 'Zero slabs constructed': # self.suf_pol_status = {} self.suf_pol[suf_name] = sl self.suf_pol_status[ suf_name] = 'created' n += 1 s_i += 1 print(st_name + ' Polar\n', surface, n, ' from ', len(slabs_polar), ' slabs\n', sl.natom, ' atoms\n') else: suf_name = str(surface[0]) + str( surface[1]) + str( surface[2]) + '.' + str(0) self.suf_pol_status[ suf_name] = 'Zero slabs constructed' print('\nWarning! Zero slabs constructed!\n') ###############nonpolar if nonpolar: if len(slabs_nonpolar): s_i = 0 n = 0 for sl_i in slabs_nonpolar: st = st_bulk sl = st.update_from_pymatgen(sl_i) if stoichiometry_criteria2( st, sl ) and sl_i.have_equivalent_surfaces( ) == True: # if sl.natom < 31: suf_name = str(surface[0]) + str( surface[1]) + str( surface[2]) + '.' + str(s_i) # if self.suf_nonpol_status == 'Zero slabs constructed': # self.suf_nonpol_status = {} self.suf_nonpol[suf_name] = sl self.suf_nonpol_status[ suf_name] = 'created' n += 1 s_i += 1 print(st_name + ' Nonolar\n', surface, n, ' from ', len(slabs_nonpolar), ' slabs\n', sl.natom, ' atoms\n') else: suf_name = str(surface[0]) + str( surface[1]) + str( surface[2]) + '.' + str(0) self.suf_nonpol_status[ suf_name] = 'Zero slabs constructed' print('\nWarning! Zero slabs constructed!\n') except AttributeError: self.suf_pol_status = 'Bulk calculation has some problems' self.suf_nonpol_status = 'Bulk calculation has some problems' print('\nWarning! Bulk calculation of {} has some problems!!\n'. format(st_name)) ##################### add slab calc if status == 'add': for suf_name in self.suf_pol_status.keys(): if self.suf_pol_status[suf_name] != 'Zero slabs constructed': suffix = '.polar' if self.suf_pol_status[suf_name] in ['created']: sl = self.suf_pol[suf_name] if only_stoich: if stoichiometry_criteria2(sl, st_bulk): print(sl.rprimd) ngkpt = calc_k_point_mesh(sl.rprimd, kspacing=0.2) ngkpt = ngkpt[:2] + (1, ) add_loop(st_name + '.sl.' + suf_name + suffix, ise, 1, ngkpt=ngkpt, input_st=sl, it_folder='slabs_new/' + st_name, up='up2', cluster=cluster, corenum=corenum) self.suf_pol_status[suf_name] = 'added' self.suf_pol_cl[suf_name] = '.'.join([ st_name + '.sl.' + suf_name + suffix, ise, '1' ]) else: print('Non-stoichiometric slab') else: None else: print('\nThis slab hasn\'t been created yet!\n') print(self.suf_pol_status[suf_name]) print(self.suf_nonpol_status) for suf_name in self.suf_nonpol_status.keys(): if self.suf_nonpol_status[suf_name] != 'Zero slabs constructed': suffix = '.nonpolar' if self.suf_nonpol_status[suf_name] in ['created']: sl = self.suf_nonpol[suf_name] if only_stoich: if stoichiometry_criteria2(sl, st_bulk): # print(st_name+'.sl.'+ suf_name, ise, 1, suf_name) ngkpt = calc_k_point_mesh(sl.rprimd, kspacing=0.2) ngkpt = ngkpt[:2] + (1, ) add_loop(st_name + '.sl.' + suf_name + suffix, ise, 1, ngkpt=ngkpt, input_st=sl, it_folder='slabs_new/' + st_name, up='up2', cluster=cluster, corenum=corenum) self.suf_nonpol_status[suf_name] = 'added' self.suf_nonpol_cl[suf_name] = '.'.join([ st_name + '.sl.' + suf_name + suffix, ise, '1' ]) else: print('Non-stoichiometric slab') else: None else: print('\nThis slab hasn\'t been created yet!\n') print(self.suf_nonpol_status[suf_name]) ##################### res slab calc if status == 'res': # # print('1111') print(self.suf_pol.keys(), self.suf_pol_status) suffix = '.polar' for suf_name in self.suf_pol.keys(): s_hkl = suf_name.split('.')[0] # # print(s_hkl) key = [] delta = 0 for i in range(0, 3): i += delta if s_hkl[i] != '-': key.append(int(s_hkl[i])) else: key.append(-int(s_hkl[i + 1])) delta = 1 # hkl = [int(s_hkl[0]), int(s_hkl[1]), int(s_hkl[2])] hkl = key if self.suf_pol_status[suf_name] in ['added', 'calculated' ] and hkl in suf_list: try: try: res_loop(st_name + '.sl.' + suf_name + suffix, ise, 1, up='up2') except ValueError: self.suf_pol_status[suf_name] = 'Error' self.suf_en_pol[suf_name] = 'Error' break except KeyError: break self.suf_pol_status[suf_name] = 'calculated' from siman.analysis import suf_en try: print(self.suf_pol_cl[suf_name]) except KeyError: self.suf_pol_cl[suf_name] = '.'.join( [st_name + '.sl.' + suf_name, ise, '1']) try: e = '-' if db[self.suf_pol_cl[suf_name]]: # in db.keys(): e = suf_en(db[self.suf_pol_cl[suf_name]], db[self.bulk_cl_scale]) # self.suf_en = {} try: self.suf_en_pol[suf_name] = round(float(e), 3) except ValueError: self.suf_en_pol[suf_name] = e except AttributeError: self.suf_en_pol[suf_name] = 'Error' if self.suf_pol_status == 'Zero slabs constructed': self.suf_en_pol = 'Zero slabs constructed' print(self.suf_nonpol.keys(), self.suf_nonpol_status) suffix = '.nonpolar' for suf_name in self.suf_nonpol.keys(): s_hkl = suf_name.split('.')[0] # # print(s_hkl) key = [] delta = 0 for i in range(0, 3): i += delta if s_hkl[i] != '-': key.append(int(s_hkl[i])) else: key.append(-int(s_hkl[i + 1])) delta = 1 # hkl = [int(s_hkl[0]), int(s_hkl[1]), int(s_hkl[2])] hkl = key if self.suf_nonpol_status[suf_name] in ['added', 'calculated' ] and hkl in suf_list: try: try: res_loop(st_name + '.sl.' + suf_name + suffix, ise, 1, up='up2') except ValueError: self.suf_nonpol_status[suf_name] = 'Error' self.suf_en_nonpol[suf_name] = 'Error' break except KeyError: break self.suf_nonpol_status[suf_name] = 'calculated' from siman.analysis import suf_en try: print(self.suf_nonpol_cl[suf_name]) except KeyError: self.suf_nonpol_cl[suf_name] = '.'.join( [st_name + '.sl.' + suf_name, ise, '1']) try: e = '-' if db[self.suf_nonpol_cl[suf_name]]: # in db.keys(): e = suf_en(db[self.suf_nonpol_cl[suf_name]], db[self.bulk_cl_scale]) # self.suf_en = {} try: self.suf_en_nonpol[suf_name] = round(float(e), 3) except ValueError: self.suf_en_nonpol[suf_name] = e except AttributeError: self.suf_en_nonpol[suf_name] = 'Error' if self.suf_nonpol_status == 'Zero slabs constructed': self.suf_en_nonpol = 'Zero slabs constructed'
def calc_suf_mat(self, ise='9sm', bulk_cl_name=None, it_folder='bulk/', status='create', suf_list=None, min_slab_size=12, only_stoich=1, symmetrize=True, corenum=4, cluster='cee', conv=1, create=1, reset_old=0, suffix=None): ''' ''' from siman.header import db from siman.geo import create_surface2, stoichiometry_criteria, stoichiometry_criteria2 from siman.calc_manage import add_loop, res_loop if not bulk_cl_name: bulk_cl_name = ['it', 'ise', '1'] if not suf_list: suf_list = [[1, 1, 0], [1, 1, 1]] st_bulk = db[self.bulk_cl_scale].end if conv: st_bulk = st_bulk.get_conventional_cell() st_name = '.'.join( [self.pretty_formula, self.sg_crystal_str, self.sg_symbol]) st_name = st_name.replace('/', '_') # st_bulk.printme() try: # print(self.suf) self.suf.keys() except AttributeError: self.suf = {} self.suf_status = {} try: self.suf_cl.keys() except AttributeError: self.suf_cl = {} try: self.suf_en.keys() except AttributeError: self.suf_en = {} if reset_old: self.suf = {} self.suf_status = {} self.suf_cl = {} self.suf_en = {} ##################### create slab if status == 'create': try: for surface in suf_list: print(surface) if self.suf == {} or ''.join( [str(surface[0]), str(surface[1]), str(surface[2])]) not in self.suf.keys(): slabs = create_surface2(st_bulk, miller_index=surface, min_slab_size=min_slab_size, min_vacuum_size=15, surface_i=0, symmetrize=symmetrize, lll_reduce=1, primitive=1) for sl_i in slabs: st = st_bulk sl = st.update_from_pymatgen(sl_i) stoichiometry_criteria2(st, sl) s_i = 0 if create: if len(slabs): for sl_i in slabs: st = st_bulk sl = st.update_from_pymatgen(sl_i) stoichiometry_criteria2(st, sl) suf_name = str(surface[0]) + str( surface[1]) + str( surface[2]) + '.' + str(s_i) if self.suf_status == 'Zero slabs constructed': self.suf_status = {} self.suf[suf_name] = sl self.suf_status[suf_name] = 'created' print(st_name + '\n', surface, s_i + 1, ' from ', len(slabs), ' slabs\n', sl.natom, ' atoms') s_i += 1 else: self.suf_status = 'Zero slabs constructed' print('\nWarning! Zero slabs constructed!\n') except AttributeError: self.suf_status = 'Bulk calculation has some problems' print('\nWarning! Bulk calculation of {} has some problems!!\n'. format(st_name)) ##################### add slab calc if status == 'add': # for surface in suf_list: for suf_name in self.suf_status.keys(): if self.suf_status[suf_name] in ['created']: sl = self.suf[suf_name] if only_stoich: if stoichiometry_criteria2(sl, st_bulk): # print(st_name+'.sl.'+ suf_name, ise, 1, suf_name) add_loop(st_name + '.sl.' + suf_name + suffix, ise, 1, input_st=sl, it_folder='slabs_new/' + st_name, up='up2', cluster=cluster, corenum=corenum) self.suf_status[suf_name] = 'added' self.suf_cl[suf_name] = '.'.join( [st_name + '.sl.' + suf_name, ise, '1']) else: print('Non-stoichiometric slab') else: None else: print('\nThis slab hasn\'t been created yet!\n') print(self.suf_status[suf_name]) ##################### res slab calc if status == 'res': # print('1111') print(self.suf.keys(), self.suf_status) for suf_name in self.suf.keys(): s_hkl = suf_name.split('.')[0] # print(s_hkl) key = [] delta = 0 for i in range(0, 3): i += delta if s_hkl[i] != '-': key.append(int(s_hkl[i])) else: key.append(-int(s_hkl[i + 1])) delta = 1 # hkl = [int(s_hkl[0]), int(s_hkl[1]), int(s_hkl[2])] hkl = key if self.suf_status[suf_name] in ['added', 'calculated' ] and hkl in suf_list: try: try: res_loop(st_name + '.sl.' + suf_name + suffix, ise, 1, up='up2') except ValueError: self.suf_status[suf_name] = 'Error' self.suf_en[suf_name] = 'Error' break except KeyError: break self.suf_status[suf_name] = 'calculated' from siman.analysis import suf_en try: print(self.suf_cl[suf_name]) except KeyError: self.suf_cl[suf_name] = '.'.join( [st_name + '.sl.' + suf_name, ise, '1']) try: e = '-' if self.suf_cl[suf_name] in db.keys(): e = suf_en(db[self.suf_cl[suf_name]], db[self.bulk_cl_scale]) # self.suf_en = {} self.suf_en[suf_name] = e except AttributeError: self.suf_en[suf_name] = 'Error' if self.suf_status == 'Zero slabs constructed': self.suf_en = 'Zero slabs constructed' return
def calc_suf_list_sg(data_list, sg, suf_list, flag=0): """ to run a set of slabs for every str from matproj data_list sg - 'spacegroup.symbol' """ # print('start') for i in data_list: if i['spacegroup.symbol'] == sg: print(i['spacegroup.symbol']) st_name = i['pretty_formula'] + '.' + i['spacegroup.crystal_system'] print(st_name) if float(i['total_magnetization']): mag_flag = 1 ise = '9sm' st_bulk = db[st_name, '8m', 1].end else: mag_flag = 0 ise = '9s' st_bulk = db[st_name, '8', 1].end try: for surface in suf_list: slabs = create_surface2(st_bulk, miller_index=surface, min_slab_size=10, min_vacuum_size=10, surface_i=0, symmetrize=True) s_i = 0 if len(slabs): for sl_i in slabs: st = st_bulk sl = st.update_from_pymatgen(sl_i) if stoichiometry_criteria(sl, st_bulk): if flag == 'add': add_loop( st_name + '.cubic.' + i['spacegroup.symbol'] + '.' + str(surface[0]) + str(surface[1]) + str(surface[2]) + '.' + str(s_i), ise, 1, input_st=sl, it_folder='slab/' + st_name + '.cubic.' + i['spacegroup.symbol'], up='up2') elif flag == 'res': res_loop(st_name + '.cubic.' + i['spacegroup.symbol'] + '.' + str(surface[0]) + str(surface[1]) + str(surface[2]) + '.' + str(s_i), ise, 1, up='up2') else: print(st_name + '\n', surface, s_i + 1, ' from ', len(slabs), ' slabs\n', sl.natom, ' atoms') s_i += 1 if s_i == 3: break else: print('Non-stoichiometric slab') else: print('\nWarning! Zero slabs constructed!\n') except AttributeError: print( '\nWarning! Bulk calculation of {} has some problems!!\n'. format(st_name))