使用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