美文网首页
使用pymatgen进行有序无序转变(上)

使用pymatgen进行有序无序转变(上)

作者: Martentite | 来源:发表于2020-04-10 01:28 被阅读0次

    pymatgen的transformations模块提供了许多用于结构转换的方法(类),使用这些类可以轻易的实现掺杂、建超胞、添加氧化态等功能,这里介绍一下用于有序无序转换的两个类:EnumerateStructureTransformationOrderDisorderedStructureTransformation。这两个类可以实现类似supercell软件的功能,将无序结构转变为有序结构。

    下面我们以立方体结构钙钛矿(CaTiO_3)为例,学习一下如何使用该模块建模。(CaTiO_3)的结构文件可以去 materials project 网站下载(mp-5827)。

    关于有序无序转变

    首先来了解一下什么是有序(order)与无序(disorder)结构,打开我们在mp上下载的cif文件:

    # generated using pymatgen
    data_CaTiO3
    _symmetry_space_group_name_H-M   Pm-3m
    _cell_length_a   3.88947141
    _cell_length_b   3.88947141
    _cell_length_c   3.88947141
    _cell_angle_alpha   90.00000000
    _cell_angle_beta   90.00000000
    _cell_angle_gamma   90.00000000
    _symmetry_Int_Tables_number   221
    _chemical_formula_structural   CaTiO3
    _chemical_formula_sum   'Ca1 Ti1 O3'
    _cell_volume   58.83987623
    _cell_formula_units_Z   1
    loop_
     _symmetry_equiv_pos_site_id
     _symmetry_equiv_pos_as_xyz
      1  'x, y, z'
      2  '-x, -y, -z'
      3  '-y, x, z'
      4  'y, -x, -z'
      5  '-x, -y, z'
      6  'x, y, -z'
      7  'y, -x, z'
      8  '-y, x, -z'
      9  'x, -y, -z'
      10  '-x, y, z'
      11  '-y, -x, -z'
      12  'y, x, z'
      13  '-x, y, -z'
      14  'x, -y, z'
      15  'y, x, -z'
      16  '-y, -x, z'
      17  'z, x, y'
      18  '-z, -x, -y'
      19  'z, -y, x'
      20  '-z, y, -x'
      21  'z, -x, -y'
      22  '-z, x, y'
      23  'z, y, -x'
      24  '-z, -y, x'
      25  '-z, x, -y'
      26  'z, -x, y'
      27  '-z, -y, -x'
      28  'z, y, x'
      29  '-z, -x, y'
      30  'z, x, -y'
      31  '-z, y, x'
      32  'z, -y, -x'
      33  'y, z, x'
      34  '-y, -z, -x'
      35  'x, z, -y'
      36  '-x, -z, y'
      37  '-y, z, -x'
      38  'y, -z, x'
      39  '-x, z, y'
      40  'x, -z, -y'
      41  '-y, -z, x'
      42  'y, z, -x'
      43  '-x, -z, -y'
      44  'x, z, y'
      45  'y, -z, -x'
      46  '-y, z, x'
      47  'x, -z, y'
      48  '-x, z, -y'
    loop_
     _atom_site_type_symbol
     _atom_site_label
     _atom_site_symmetry_multiplicity
     _atom_site_fract_x
     _atom_site_fract_y
     _atom_site_fract_z
     _atom_site_occupancy
      Ca  Ca0  1  0.500000  0.500000  0.500000  1
      Ti  Ti1  1  0.000000  0.000000  0.000000  1
      O  O2  3  0.000000  0.000000  0.500000  1
    

    内容很多,前面的内容我们只需要关注这么几个内容:

    • 空间群 Pm-3m
    • 化学式 CaTiO3
    • 各原子数目 Ca1 Ti1 O3

    下面我们来看一下最后几行

     _atom_site_type_symbol
     _atom_site_label
     _atom_site_symmetry_multiplicity
     _atom_site_fract_x
     _atom_site_fract_y
     _atom_site_fract_z
     _atom_site_occupancy
      Ca  Ca0  1  0.500000  0.500000  0.500000  1
      Ti  Ti1  1  0.000000  0.000000  0.000000  1
      O  O2  3  0.000000  0.000000  0.500000  1
    

    上面七行对应的是下面七列的信息,分别是:

    元素符号 原子序号 原子数 x轴坐标 y轴坐标 z轴坐标 占据比
    Ca Ca0 1 0.5 0.5 0.5 1
    Ti Ti1 1 0 0 0 1
    O O2 3 0 0 0.5 1

    可以看到CaTiO3中每个原子的占据比都是1,且其结构符合 Pm\overline3m 空间群的对称性,因此它是一个有序结构,也可以说是一个完美晶体。而无序结构顾名思义就是不是完美晶体的结构,在这里一般指的是占据比 occupancy != 1的结构。

    在研究掺杂的过程中,我们会经常遇到这种情况,某个位置发生取代掺杂,部分原子被取代后占据比就会小于1。还有一种情况就是某种材料具有钙钛矿、尖晶石等结构,但是没有这种材料的结构文件,比如Li_{3x}La_{2/3-x}TiO_3(LLTO),锂镧钛氧是一种离子电导率很高的固态电解质材料,通过解析XRD数据发现它具有钙钛矿结构,其中Li和La占据A site,也就是Ca的位置,那么我们就可以以CaTiO3的结构为基础,通过取代Ca来得到 LLTO 的结构文件。

    但是问题就来了,我们取代后的文件元素占据比小于1,变成了无序结构(disordered structure),而我们使用VASP的软件进行计算的时候,原子的占据比必须是1,那我们怎么办呢?

    一种通用的做法是建一个超胞(supercell),也就是把现有的晶胞在三个方向上扩展若干倍,将分数占据比的元素按比例分配到每个位置上,得到一系列的结构后计算它们的能量,取能量最低者即为我们需要的结构。
    比如我们在三个方向上都扩展三倍,得到一个 3x3x3 的超胞,此时结构化学式就变成了 Ca_{27}Ti_{27}O_{81},对于电导率最高的 Li_{0.33}La_{0.56}TiO_3

    • Li : 0.33 x 27 = 8.91 \approx 9
    • La : 0.56 x 27 = 15.12 \approx 15
    • Ti : 1 x 27 = 27
    • O : 3x27 = 81

    此时LLTO的化学式可以写作 Li_9La_{15}Ti_{27}O_{81},也就是说,我们用9个Li、15个La和3个空位取代了A site上的27个Ca,此时我们得到了一个有132个原子的超胞,我们可以把它作为 LLTO 的晶胞,这个过程称之为 ordering,通过这个过程我们把一个分数占据的disordered的结构变成了一个ordered的结构。

    但是问题就来了,我们取代后可以得到多少种结构呢?做个排列组合:C_{27}^{15}C_{12}^9 = 17383860 x 220 = 3824449200,对于简单地取代,我们可以通过枚举将所有结构列出来,但对这种有天文数字的组合,显然我们不可能全部列出来。

    对这种情况,一种可行的方法是随机取代得到若干种结构,然后通过静电能(electrostatic energy) 排序取能量最低的几个结构,再对这几个结构进行DFT计算以得到能量最低者。

    两种方法

    下面我们分别来介绍一下两种方法,我们以LSTF为例,即 Li_{0.38}Sr_{0.44}Ta_{0.7}Hf_{0.3}O_{2.95}F_{0.05},这是一种固态电解质,具有立方体型钙钛矿结构。为了方便,我们忽略F,只考虑Li、Sr、Ta、Hf、O五种元素,化合价分别为+1、+2、+5、+4、-2。细心的同学可能会发现电荷不平衡,不过没有关系。

    首先我们要设计一下结构,为了对称这里我选择建一个 3x3x3 的超胞,则该结构化学式为:Li_{10}Sr_{12}Ta_{19}Hf_8O_{81}

    pymatgen提供了多种建超胞的方法,可以通过structure的make_supercell()方法直接建,也可以通过SupercellTransformation类返回新的结构而不改变原结构。

    OrderDisorderedStructureTransformation类

    我们首先来看一下如何使用OrderDisorderedStructureTransformation类进行ordering,该类位于pymatgen.transformations.standard_transformations模块中:

    class OrderDisorderedStructureTransformation(algo=0, symmetrized_structures=False, no_oxi_states=False)
    

    可以看到,该类有三个可选参数:

    • algo,即algorithm,排序所用算法,默认为0,可以不用管
      • 0:ALGO_FAST
      • 1:ALGO_COMPLETE
      • 2:ALGO_BEST_FIRST
    • symmetrized_structures:是否为对称性结构,默认False
    • no_oxi_states:是否在ordering前去除氧化态,默认False,即不去除

    氧化态即是否带电荷,我们的结构文件中是原子,因此不带电荷,而计算静电能需要知道每种元素的电荷,因为静电能是整体的电荷相互作用,没有电荷也就无法计算静电能了。我们可以通过Structure类的add_oxidation_state_by_element方法给元素添加氧化态,也可以通过该模块下的OxidationStateDecorationTransformation类进行添加。

    属性与方法
    属性:

    • lowest_energy_structure:具有最低能量的结构
    • _all_structures:存有ordering后结构的列表,结构以字典的形式储存。
    • inverse: 没什么意义,不用管
    • is_one_to_many: 是否返回多个结果,不用管

    方法:apply_transformation(structure, return_ranked_list=False)
    ordering的方法,structure为我们要排序的结构,return_ranked_list控制返回值:

    • False:默认值,返回Ewald能最低的结构
    • 整数:返回该数量的结构,以字典列表的形式,每个结构储存在一个字典中,字典还包括其他信息,可以通过structure 键来访问。

    代码:

    import os
    from pymatgen.io.cif import CifParser, CifWriter
    from pymatgen.transformations.standard_transformations import SubstitutionTransformation, OrderDisorderedStructureTransformation, SupercellTransformation
    
    # read in the CaTiO3 structure from cif file 
    filename = 'CaTiO3_mp-5827_symmetrized.cif'
    parser = CifParser(filename)
    init_structure = parser.get_structures()[0]
    
    # add oxidation states to the structure
    data = {"Ca":2, "Ti":4, "O":-2}
    init_structure.add_oxidation_state_by_element(data)
    
    # substitute to get the partial occupancied structure
    species_map = {"Ca2+":{"Li1+":0.38, "Sr2+":0.44},"Ti4+":{"Ta5+":0.7,"Hf4+":0.3}}
    substitutuin = SubstitutionTransformation(species_map)
    structure = substitutuin.apply_transformation(init_structure)
    ``
    # make a 3x3x3 supercell
    structure.make_supercell(3)
    '''
    # you can also use the SupercellTransformation class to achieve it
    sc = SupercellTransformation().from_scaling_factors(3,3,3)
    supercell = sc.apply_transformation(structure)
    '''
    
    # ordering,here we set return_ranked_list as 100 to get 100 structures
    order = OrderDisorderedStructureTransformation()
    standard_structures = order.apply_transformation(structure,return_ranked_list=100)
    
    # save ordered structures to files
    if !os.path.exists('ordering'):
        os.mkdir('ordering')
    i = 1
    for s in ordered_structures:
        cif = CifWriter(s['structure'])
        cif.write_file('ordering/structure_{:0>3d}.cif'.format(i))
        i+=1
    

    当你运行这段代码的时候,你会发现程序会报错:

    ValueError: Occupancy fractions not consistent with size of unit cell
    

    这是为什么呢?我们查看一下该类的源码,找到出错的位置:

    for k, v in total_occupancy.items():
        if abs(v - round(v)) > 0.25:
            raise ValueError("Occupancy fractions not consistent "
                             "with size of unit cell")
    

    再来看看文档中对该类的说明:

    simple rounding of the occupancies are performed, with no attempt made to achieve a target composition. This is usually not a problem for most ordering problems, but there can be times where rounding errors may result in structures that do not have the desired composition.

    龟龟,文档中说会简单地取整,应该可以理解为四舍五入,然鹅,代码中设置了限制,超过0.25就不给算了,而对Li:0.38 x 27 = 10.26 比我们取的10大了0.26,已经超过了0.25,我们对代码做一下修改,把0.38改为0.37,此时:0.37 x 27 = 9.99 就没得问题了:

    # substitute to get the partial occupancied structure
    species_map = {"Ca2+":{"Li1+":0.37, "Sr2+":0.44},"Ti4+":{"Ta5+":0.7,"Hf4+":0.3}}
    substitutuin = SubstitutionTransformation(species_map)
    structure = substitutuin.apply_transformation(init_structure)
    

    再次运行程序,我的电脑陷入了沉思...
    看一下说明:

    The algorithm can currently compute approximately 5,000,000 permutations per minute.

    这个算法每分钟能处理大约5百万个结果,但是我们有上亿种结构,因此需要程序跑几分钟。当然如果你用超算或者服务器的话应该会快一点。

    程序运行完后,你会发现脚本目录下多了一个 ordering 文件夹,里面有我们order后的结构,文件名形如 structure_***.cif 的形式,结构是根据ewald energy / atom由低到高排列的。

    相关文章

      网友评论

          本文标题:使用pymatgen进行有序无序转变(上)

          本文链接:https://www.haomeiwen.com/subject/hfakmhtx.html