文献中会有晶体结构中一个位点部分占据的情况,实际上是在一个超胞中,用其它原子进行取代,在materials studio里面虽然可以在一个位点上面设置部分占据的数值(occupancy),导出的.cif文件里也有,但从vesta导出POSCAR后,会自动将部分占据补齐变成满占据,即vasp的输入文件中不能有部分占据。而我们可以用pymatgen建模,构建一个晶胞结构,若有部分占据的情况,pymatgen可以将其转换为vsap输入文件进行计算。
具体教程参考:
https://matgenb.materialsvirtuallab.org/2013/01/01/Ordering-Disordered-Structures.html
https://pymatgen.org/introduction.html?tdsourcetag=s_pctim_aiomsg#usage
https://matgenb.materialsvirtuallab.org/2013/01/01/Basic-functionality.html
下面举例
from pymatgen import Structure,Lattice
from pymatgen.transformations.standard_transformations import OrderDisorderedStructureTransformation
from pymatgen.io.vasp.sets import batch_write_input, MPRelaxSet
import pymatgen as mg
lattice = mg.Lattice.cubic(3.722)
specie1 = {"K1+":0.5} #要写出每个元素的化合价,即使化合价为0也要标出,如{"Cu0+":0.5},后面是占据数
specie2 = {"Na1+":1/3,"Fe2+":2/3} #占据数可取分数
specie3 = {"O2-":1}
structure = Structure.from_spacegroup("Fm-3m",lattice, [specie3,specie1,specie2], [[0,0,0],[0.5,0,0],[0.25,0.25,0.25]])
structure.make_supercell([a,b,c]) #这里需要计算一下,即所建的超胞的sites数,乘以占据数(occupancy)要为整数,文献里SI一般会给出
#ordering有两种方法,这里是第一种方法
trans = OrderDisorderedStructureTransformation()
ss = trans.apply_transformation(structure, return_ranked_list=200)
#ordering还有一种更严谨的方法是用EnumerateStructureTransformation,不过用这个方法需要安装enumlib,因为是windows系统,我找不到enumlib.x文件,因此在虚拟机里面安装了,安装enumlib过程和注意事项在另一篇博文中
#ss的数据类型是list,需要先运行下面这行代码才能生成vasp输入文件。而上面会生成很多结构,我们一般选取十个能量最低的结构进行运算,上面生成的结构是按能量由低到高排列的,因此选取前十个结构
structures = [d["structure"] for d in ss[:10]]
#print("%d structures returned." % len(structures))
#一定要注意生成的list数据类型要执行上面的代码,要不然就会报这个错 AttributeError: 'list' object has no attribute 'get_sorted_structure'
#下面生成十个结构各自的vasp四个输入文件,生成的文件在解释器里的文件路径中可以找到;生成vasp输入文件需要指定POTCAR的位置,因为我的POTCAR安装在虚拟机里,所有生成的文件在虚拟机里拖出来放到超算就行
for i,d in enumerate(structures):
ll = structures[i]
relax = MPRelaxSet(ll,user_incar_settings={"NPAR":4})
relax.write_input("%d_relax" %i)
#一般我们计算100个结构文件进行计算,可以像下面这样写
trans = OrderDisorderedStructureTransformation()
ss = trans.apply_transformation(structure, return_ranked_list=100)
structures = [d["structure"] for d in ss]
for i,d in enumerate(structures):
ll = structures[i]
relax = MPRelaxSet(ll,user_incar_settings={"NPAR":4})
relax.write_input("/home/min/Linux共享/one-hundred b-Li8GeP4/%d_relax" %i)