1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
| from pymatgen import Structure,Element import numpy as np
def atom_selection(struct,in_str=None): r''' select atoms by three different schemes: 1. by atomic index 2. by element symbol 3. by fractional coordinates range ''' tip=""" select atoms by following ways: 1. atomic index in POSCAR i.e. : 1 2 4-8 10 12-30 i.e. : 1 2 4 8 10 2. atomic label i.e. : Si O 3. atomic position i.e. : 0 0.5 | 0.2 0.4 | 0.3 0.7 this means atoms with 0<x<0.5, 0.2<y<0.4 and 0.3<z<0.7 will be seleted or just specific the z coordinates, i.e. : ||0.3 0.7 """ print(tip)
def parse_index(in_str): atom_index=[] tmp_str=in_str.split() for i in tmp_str: if '-' not in i: atom_index.append(int(i)) else: atom_index.extend(range(int(i.split('-')[0]),int(i.split('-')[1])+1)) return [i-1 for i in atom_index]
def parse_label(in_str): atom_label= [Element(elem) for elem in in_str.split()] atom_index=[] for i, site in enumerate(struct.sites): if site.specie in atom_label: atom_index.append(i) return atom_index
def parse_range(in_str):
def check_frac(coord,lim): con=[False]*3 for i in range(3): con[i]=coord[i]>=lim[i][0] and coord[i]<=lim[i][1] if np.all(con): return True else: return False
coord_range={} tmp_str=in_str.split();tmp1_str=' '.join(tmp_str);tmp2_str=tmp1_str.split("|") icount=0 for i in tmp2_str:
if i=='': coord_range[icount]='' else: coord_range[icount]=[float(x) for x in i.split()] icount+=1 for key in coord_range.keys(): if coord_range[key]=='': coord_range[key]=[0,1] atom_index=[] for i, site in enumerate(struct.sites): if check_frac(site.frac_coords,coord_range): atom_index.append(i) return atom_index
if "|" in in_str.strip(): atom_index_list=parse_range(in_str) else: for str in in_str.strip(): if str.isalpha(): atom_index_list=parse_label(in_str) return atom_index_list,in_str atom_index_list=parse_index(in_str) return atom_index_list,in_str
def constrain(struct,in_str=None): natom=struct.num_sites atom_index,in_str=atom_selection(struct,in_str) selective_dynamics=[[True for col in range(3)] for row in range(natom)] for i in range(natom): if i in atom_index: selective_dynamics[i]=[False,False,False] tmp_struct=Structure(struct.lattice,struct.species,struct.frac_coords,site_properties={'selective_dynamics':selective_dynamics}) return tmp_struct if __name__=='__main__': from pymatgen.io.vasp import Poscar st=Structure.from_file('L1-Te2.vasp') in_str='||0.0 0.5' cst=constrain(st,in_str=in_str) poscar=Poscar(cst) print(st) print(poscar) poscar.comment=poscar.comment+' |--> '+in_str poscar.write_file('Fixed.vasp')
|