晶胞转换


使用spglib将原胞的POSCAR重整为惯用晶胞的POSCAR的练习

默认POSCAR的原子坐标是分数坐标形式,后续慢慢学习如何转化坐标和将惯用晶胞转为原胞。

需要的三个python脚本

read_poscar.py
reposcar.py
run.py

read_poscar.py

import spglib
import numpy as np
import os
import linecache


class read_poscar(object):
    def __init__(
        self,
        struct=None,
        pos_name=None,
        lattice_index=None,
        lat=None,
        lat_recell=None,
        atomname=None,
        atomnum=None,
        postype=None,
        pos=None,
        spg_number=None,
    ):
        self.struct = linecache.getlines("POSCAR")
        # read POSCAR to get some paramatrics: sys_name; lattice; atom_name; atom_number; atom_position
        # and get spacegroup_number
        poscar = [line.strip() for line in self.struct]
        num = len(poscar)

        self.pos_name = poscar[0].split()
        self.lat_index = poscar[1].split()
        self.lattice_index = float(self.lat_index[0])

        # matrics of lattice vector

        lat_vector = np.zeros((3, 3))
        index = 0
        for latt in poscar[2:5]:
            latt = latt.split()
            lat_vector[index, :] = latt[0:3]
            index += 1
        self.lattice = lat_vector

        self.atomname = poscar[5].split()
        self.atomnum = poscar[6].split()
        self.postype = poscar[7].split()

        atom_len=len(self.atomname)

        # matrics of atom position

        i = num - 8
        position_vector = np.zeros((i, 3))
        index = 0
        for poss in poscar[8:num]:
            poss = poss.split()
            #position_vector[index, 0:3] = poss[0:3]
            position_vector[index,0] = poss[0]
            position_vector[index,1] = poss[1]
            position_vector[index,2] = poss[2]
            index += 1

        self.lat = lat_vector * self.lattice_index
        self.pos = position_vector
        atom_numbers = [1,] * (int(self.atomnum[0]))#+int(self.atomnum[1]))
        cell = (self.lat, self.pos, atom_numbers)
        database = spglib.get_symmetry_dataset(
            cell, symprec=1e-3
        )
        self.spg_number = database["number"]

    def system_name(self):
        return self.pos_name

    def latt_index(self):
        return self.lattice_index

    def latti(self):
        return self.lattice

    def atom_name(self):
        return self.atomname

    def atom_number(self):
        return self.atomnum

    def position_type(self):
        return self.postype

    def positions(self):
        return self.pos

    def spacegroup_num(self):
        return self.spg_number

reposcar.py

import os
import numpy as np
import read_poscar as readpos
import spglib


class recell(object):
    def __init__(
        self,
        spg_num=None,
        lattindex=None,
        latt=None,
        atomname=None,
        atomnum=None,
        postype=None,
        position=None,
        cell_lattice=None,
        cell_position=None,
        cell_atomnum=None,
        to_pricell = None
    ):
        # read the origmitive cell
        self.spg_num = readpos.read_poscar().spacegroup_num()
        self.lattindex = readpos.read_poscar().latt_index()
        self.latt = readpos.read_poscar().latti()
        self.atomname = readpos.read_poscar().atom_name()
        self.atomnum = readpos.read_poscar().atom_number()
        self.postype = readpos.read_poscar().position_type()
        self.position = readpos.read_poscar().positions()

        orignumbers = []
        for i in np.arange(0, len(self.atomname)):
            for j in np.arange(0, int(self.atomnum[i]), 1):
                orignumbers.append(i + 1)

        origlattice = self.latt * self.lattindex
        origpositon = self.position

        origcell = (origlattice, origpositon, orignumbers)

        if(to_pricell==False):

        # refine cell
            self.cell_lattice, re_position, re_numbers = spglib.standardize_cell(
                cell=origcell, symprec=1e-3, to_primitive=False
            )
        else:
            self.cell_lattice, re_position, re_numbers = spglib.standardize_cell(
                cell=origcell, symprec=1e-3, to_primitive=True
            )



        # 主要对坐标进行重新排序
        re_position_list = list(re_position)
        zipped = list(zip(re_numbers, re_position_list))
        zipsorted = sorted(zipped, key=lambda x: (x[0]))

        re_numbers_sort, re_positon_sort = zip(*zipsorted)

        self.cell_position = np.array(re_positon_sort)

        self.cell_atomnum = []
        for i in np.arange(0, len(self.atomnum), 1):
            num = int(self.atomnum[i]) * (len(re_numbers_sort) / len(orignumbers))
            self.cell_atomnum.append(num)

        # write the refine cell

        writepos = open("RECELL", mode="w")
        print("recell_poscar", file=writepos)
        print("1.0", file=writepos)

        for m in np.arange(0, 3, 1):
            print(
                format(self.cell_lattice[m, 0], ".10f"),
                "   ",
                format(self.cell_lattice[m, 1], ".10f"),
                "   ",
                format(self.cell_lattice[m, 2], ".10f"),
                file=writepos,
            )

        for j in np.arange(0, len(self.atomname), 1):
            print(self.atomname[j], file=writepos, end=" ")
        print(end="\n", file=writepos)
        for l in np.arange(0, len(self.atomname), 1):
            print(int(self.cell_atomnum[l]), end=" ", file=writepos)
        print(end="\n", file=writepos)
        print(self.postype[0], file=writepos)

        for n in np.arange(0, self.cell_position.shape[0], 1):
            print(
                format(self.cell_position[n, 0], ".10f"),
                "   ",
                format(self.cell_position[n, 1], ".10f"),
                "   ",
                format(self.cell_position[n, 2], ".10f"),
                file=writepos,
            )
        writepos.close()

    def latti(self):
        return self.cell_lattice

    def atom_number(self):
        return self.cell_atomnum

    def positions(self):
        return self.cell_position

run.py

import reposcar

reposcar.recell(to_pricell=False) #转化为惯用晶胞
reposcar.recell(to_pricell=True)  #转化为原胞

例子:

原胞

Primitive Cell
  1.000000
    1.40175686596237   -2.92091081962523    0.00000000000000
    1.40175686596237    2.92091081962523    0.00000000000000
    0.00000000000000    0.00000000000000    4.90466659076150
  U 
   2
DIRECT
    0.9016657719149295    0.0983342280850705    0.7500000000000000
    0.0983342280850705    0.9016657719149295    0.2500000000000000 

输出晶胞

recell_poscar
1.0
2.8035137319     0.0000000000     0.0000000000
0.0000000000     5.8418216393     0.0000000000
0.0000000000     0.0000000000     4.9046665908
U 
4 
DIRECT
0.0000000000     0.0983342281     0.2500000000
0.5000000000     0.4016657719     0.7500000000
0.5000000000     0.5983342281     0.2500000000
0.0000000000     0.9016657719     0.7500000000

ThO2

原胞

ThO2                                    
   1.00000000000000     
     0.0000000000000000    2.8080796680000000    2.8080796680000000
     2.8080796680000000    0.0000000000000000    2.8080796680000000
     2.8080796680000000    2.8080796680000000    0.0000000000000000
   Th   O 
     1     2
Direct
  0.0000000000000000  0.0000000000000000  0.0000000000000000
  0.2500000000000000  0.2500000000000000  0.2500000000000000
  0.7500000000000000  0.7500000000000000  0.7500000000000000

输出晶胞

recell_poscar
1.0
5.6161593360     0.0000000000     0.0000000000
0.0000000000     5.6161593360     0.0000000000
0.0000000000     0.0000000000     5.6161593360
Th O 
4 8 
Direct
0.0000000000     0.0000000000     0.0000000000
0.0000000000     0.5000000000     0.5000000000
0.5000000000     0.0000000000     0.5000000000
0.5000000000     0.5000000000     0.0000000000
0.2500000000     0.7500000000     0.7500000000
0.2500000000     0.2500000000     0.7500000000
0.2500000000     0.2500000000     0.2500000000
0.2500000000     0.7500000000     0.2500000000
0.7500000000     0.7500000000     0.2500000000
0.7500000000     0.2500000000     0.2500000000
0.7500000000     0.2500000000     0.7500000000
0.7500000000     0.7500000000     0.7500000000

铀转化为原胞

输入晶胞

recell_poscar
1.0
2.8035137319     0.0000000000     0.0000000000
0.0000000000     5.8418216393     0.0000000000
0.0000000000     0.0000000000     4.9046665908
U 
4 
DIRECT
0.0000000000     0.0983342281     0.2500000000
0.5000000000     0.4016657719     0.7500000000
0.5000000000     0.5983342281     0.2500000000
0.0000000000     0.9016657719     0.7500000000

输出原胞

recell_poscar
1.0
1.4017568659     -2.9209108196     0.0000000000
1.4017568659     2.9209108196     0.0000000000
0.0000000000     0.0000000000     4.9046665908
U 
2 
DIRECT
0.9016657719     0.0983342281     0.2500000000
0.0983342281     0.9016657719     0.7500000000

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