-
Notifications
You must be signed in to change notification settings - Fork 0
/
get_voronoi_volume.py
102 lines (91 loc) · 3.37 KB
/
get_voronoi_volume.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# -*- coding: utf-8 -*-
"""
Created on Fri May 14 10:15:55 2021
@author: ZHANG Jun
Emain: j.zhang@my.cityu.edu.hk
This script is used to calculate the voronoi volume of each sites in a crystal.
"""
from pymatgen.core.structure import Structure
import numpy as np
from scipy.spatial import ConvexHull
from scipy.spatial import Voronoi
class VoronoiAnalyse(object):
"""
Description
----------
This script is used to calculate the voronoi volume of a BCC crystal.
For another crystal types, you need to modify the value of
"volume_fraction_for_cubic" in "__call__()" function.
Parameters
----------
file_name : str
User defined file name.
start_index : int
In many cases, we don't need all the Voronoi volumes of every atom.
Therefore, this is the start. For python, the index starts from zero.
end_index : int
This is the end of index. If you want include the 100th atom, the end
index should be 100.
"""
def __init__(self,
file_name,
start_index,
end_index):
self.file_name = file_name
self.start_index = start_index
self.end_index = end_index
def voronoi_volumes(self, points): # Refer to: https://stackoverflow.com/questions/19634993/volume-of-voronoi-cell-python
"""
Parameters
----------
points : np.array
Cartesian coordinates of the crystal.
Return
----------
vol: list
Voronoi volumes of each site.
"""
v = Voronoi(points)
vol = np.zeros(v.npoints)
for i, reg_num in enumerate(v.point_region):
indices = v.regions[reg_num]
if -1 in indices: # some regions can be opened
vol[i] = np.inf
else:
vol[i] = ConvexHull(v.vertices[indices]).volume
return vol
def __call__(self):
"""
Return
----------
vor_vol: list
Voronoi volumes of specified sites.
error: float
Compare the total Voronoi volume and the cell volume.
Positive value indicates overestimating.
"""
crystal = Structure.from_file(self.file_name)
self.cell_volume = crystal.volume
self.number_of_atoms = crystal.num_sites
volume_fraction_for_cubic = 0.5235987755982988
self.atomic_diameter = (self.cell_volume * volume_fraction_for_cubic / self.number_of_atoms * 3 / 4 / np.pi) ** (1 / 3) * 2
all_NN = crystal.get_all_neighbors(r=self.atomic_diameter*1.2071067811865475,
include_index=True)
vor_vol = []
for i in range(self.number_of_atoms):
number_of_neighbors = len(all_NN[i])
coords = []
coords.append(crystal[i].coords)
for j in range(number_of_neighbors):
coords.append(all_NN[i][j].coords)
coords = np.array(coords)
vor_vol.append(self.voronoi_volumes(coords)[0])
error = np.sum(vor_vol) / self.cell_volume - 1.0
vor_vol = vor_vol[self.start_index: self.end_index]
return vor_vol, error
if __name__ == '__main__':
vor_crystal = VoronoiAnalyse('POSCAR.txt', 0, 32)
vor_vol, error = vor_crystal()
for i in range(len(vor_vol)):
print(i, flush=True)
print('Error:', error)