VASP之POSCAR进行原子固定


问题描述

VASP计算表面时,需要将下面几层进行固定,用于模拟体相,如下面例子中我们把z方向坐标在0-0.5之间的原子全部固定

处理脚本

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()
        #tmp_str=in_str.split()[1:]
        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_label= [Element(elem) for elem in in_str.split()[1:]]
        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("|")
        #tmp_str=in_str.split()[1:];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)
    #if in_str.strip().startswith('a'):
    #   atom_index_list=parse_index(in_str)
    #elif in_str.strip().startswith('b'):
    #   atom_index_list=parse_label(in_str)
    #elif in_str.strip().startswith('c'):
    #   atom_index_list=parse_range(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')

运行脚本 python run.py,确保当前文件夹里面有L1-Te2.vasp文件
L1-Te2.vasp文件内容为:

Li6 V9 Te4 O24
1.0
6.042800 0.000000 0.000000
-3.021400 5.233218 0.000000
0.000000 0.000000 30.535545
Li V Te O
6 9 4 24
direct
0.333333 0.666667 0.265354 Li
0.333333 0.666667 0.395473 Li
0.000000 0.000000 0.434944 Li
0.000000 0.000000 0.565063 Li
0.666667 0.333333 0.604534 Li
0.666667 0.333333 0.734653 Li
0.833330 0.666667 0.330406 V
0.333333 0.166670 0.330406 V
0.833330 0.166670 0.330406 V
0.166670 0.333333 0.669585 V
-0.000000 0.500000 0.500001 V
0.500000 0.500000 0.500001 V
0.666667 0.833330 0.669585 V
0.166670 0.833330 0.669585 V
0.500000 0.000000 0.500001 V
0.000000 0.000000 0.245619 Te
0.666667 0.333333 0.415209 Te
0.333333 0.666667 0.584798 Te
0.000000 0.000000 0.754388 Te
0.666667 0.333333 0.296140 O
0.153020 0.306040 0.290630 O
0.693960 0.846980 0.290630 O
0.153020 0.846980 0.290630 O
0.333333 0.666667 0.465730 O
0.513650 0.486350 0.370182 O
0.972710 0.486350 0.370182 O
0.513650 0.027290 0.370182 O
0.819690 0.639370 0.460220 O
0.360630 0.180310 0.460220 O
0.819690 0.180310 0.460220 O
0.000000 0.000000 0.364687 O
0.000000 0.000000 0.635320 O
0.180310 0.819690 0.539772 O
0.639370 0.819690 0.539772 O
0.180310 0.360630 0.539772 O
0.486350 0.972710 0.629825 O
0.027290 0.513650 0.629825 O
0.486350 0.513650 0.629825 O
0.666667 0.333333 0.534277 O
0.846980 0.153020 0.709361 O
0.306040 0.153020 0.709361 O
0.846980 0.693960 0.709361 O
0.333333 0.666667 0.703867 O

即可得到如下内容:


    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
       
Full Formula (Li6 V9 Te4 O24)
Reduced Formula: Li6V9(TeO6)4
abc   :   6.042800   6.042800  30.535545
angles:  90.000000  90.000000 120.000001
Sites (43)
  #  SP            a         b         c
---  ----  ---------  --------  --------
  0  Li     0.333333  0.666667  0.265354
  1  Li     0.333333  0.666667  0.395473
  2  Li     0         0         0.434944
  3  Li     0         0         0.565063
  4  Li     0.666667  0.333333  0.604534
  5  Li     0.666667  0.333333  0.734653
  6  V      0.83333   0.666667  0.330406
  7  V      0.333333  0.16667   0.330406
  8  V      0.83333   0.16667   0.330406
  9  V      0.16667   0.333333  0.669585
 10  V     -0         0.5       0.500001
 11  V      0.5       0.5       0.500001
 12  V      0.666667  0.83333   0.669585
 13  V      0.16667   0.83333   0.669585
 14  V      0.5       0         0.500001
 15  Te     0         0         0.245619
 16  Te     0.666667  0.333333  0.415209
 17  Te     0.333333  0.666667  0.584798
 18  Te     0         0         0.754388
 19  O      0.666667  0.333333  0.29614
 20  O      0.15302   0.30604   0.29063
 21  O      0.69396   0.84698   0.29063
 22  O      0.15302   0.84698   0.29063
 23  O      0.333333  0.666667  0.46573
 24  O      0.51365   0.48635   0.370182
 25  O      0.97271   0.48635   0.370182
 26  O      0.51365   0.02729   0.370182
 27  O      0.81969   0.63937   0.46022
 28  O      0.36063   0.18031   0.46022
 29  O      0.81969   0.18031   0.46022
 30  O      0         0         0.364687
 31  O      0         0         0.63532
 32  O      0.18031   0.81969   0.539772
 33  O      0.63937   0.81969   0.539772
 34  O      0.18031   0.36063   0.539772
 35  O      0.48635   0.97271   0.629825
 36  O      0.02729   0.51365   0.629825
 37  O      0.48635   0.51365   0.629825
 38  O      0.666667  0.333333  0.534277
 39  O      0.84698   0.15302   0.709361
 40  O      0.30604   0.15302   0.709361
 41  O      0.84698   0.69396   0.709361
 42  O      0.333333  0.666667  0.703867

 ------------------------------------------
Li6 V9 Te4 O24
1.0
6.042800 0.000000 0.000000
-3.021400 5.233218 0.000000
0.000000 0.000000 30.535545
Li V Te O
6 9 4 24
Selective dynamics
direct
0.333333 0.666667 0.265354 F F F Li
0.333333 0.666667 0.395473 F F F Li
0.000000 0.000000 0.434944 F F F Li
0.000000 0.000000 0.565063 T T T Li
0.666667 0.333333 0.604534 T T T Li
0.666667 0.333333 0.734653 T T T Li
0.833330 0.666667 0.330406 F F F V
0.333333 0.166670 0.330406 F F F V
0.833330 0.166670 0.330406 F F F V
0.166670 0.333333 0.669585 T T T V
-0.000000 0.500000 0.500001 T T T V
0.500000 0.500000 0.500001 T T T V
0.666667 0.833330 0.669585 T T T V
0.166670 0.833330 0.669585 T T T V
0.500000 0.000000 0.500001 T T T V
0.000000 0.000000 0.245619 F F F Te
0.666667 0.333333 0.415209 F F F Te
0.333333 0.666667 0.584798 T T T Te
0.000000 0.000000 0.754388 T T T Te
0.666667 0.333333 0.296140 F F F O
0.153020 0.306040 0.290630 F F F O
0.693960 0.846980 0.290630 F F F O
0.153020 0.846980 0.290630 F F F O
0.333333 0.666667 0.465730 F F F O
0.513650 0.486350 0.370182 F F F O
0.972710 0.486350 0.370182 F F F O
0.513650 0.027290 0.370182 F F F O
0.819690 0.639370 0.460220 F F F O
0.360630 0.180310 0.460220 F F F O
0.819690 0.180310 0.460220 F F F O
0.000000 0.000000 0.364687 F F F O
0.000000 0.000000 0.635320 T T T O
0.180310 0.819690 0.539772 T T T O
0.639370 0.819690 0.539772 T T T O
0.180310 0.360630 0.539772 T T T O
0.486350 0.972710 0.629825 T T T O
0.027290 0.513650 0.629825 T T T O
0.486350 0.513650 0.629825 T T T O
0.666667 0.333333 0.534277 T T T O
0.846980 0.153020 0.709361 T T T O
0.306040 0.153020 0.709361 T T T O
0.846980 0.693960 0.709361 T T T O
0.333333 0.666667 0.703867 T T T O

当然该脚本还支持其他模式的原子固定,具体可以参考tip


文章作者: ustc-haidi
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 ustc-haidi !
  目录