/
misc.py
176 lines (145 loc) · 5.33 KB
/
misc.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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import pyscal.core as pc
import numpy as np
import warnings
def compare_atomic_env(infile, atomtype=2, precision=2, format="poscar", print_results=True, return_system=False):
"""
Compare the atomic environment of given types of atoms
in the inputfile. The comparison is made in terms of Voronoi
volume and Voronoi fingerprint.
Parameters
----------
infile : string
name of the inputfile
atomtype: int, optional
type of the atom
default 2
precision: float, optional
precision for comparing Voronoi volumes
default 3
format: string, optional
format of the input file
default poscar
print_results: bool, optional
if True, print the results. If False, return the data
instead. default True
return_system: bool, optional
if True, return the system object.
default False
Returns
-------
vvx : list of floats
unique Voronoi volumes. Returned only if print results is False
vrx : list of strings
unique Voronoi polyhedra. Returned only if print results is False
vvc : list of ints
number of unique quantities specified above. Returned only if print results is False
"""
sys = pc.System()
sys.read_inputfile(infile, format=format)
sys.find_neighbors(method="voronoi")
sys.calculate_vorovector()
atoms = sys.atoms
vols = []
vors = []
for atom in atoms:
if atom.type == atomtype:
vols.append(atom.volume)
vors.append(" ".join(np.array(atom.vorovector).astype(str)))
vols = np.array(vols)
vols = np.round(vols, decimals=precision)
vvx, vvc = np.unique(vols, return_counts=True)
vrx, vrc = np.unique(vors, return_counts=True)
length_mismatch = False
if (len(vvx) != len(vrx)):
warnings.warn("Different voronoi polyhedra with same volume! Fingerprint wont be printed. Maybe change precision?")
length_mismatch = True
if precision > 3:
warnings.warn("More than 3 digits of precision selected!")
if print_results:
print("%d clusters found"%len(vvx))
if not length_mismatch:
for i in range(len(vvx)):
print("voro fingerprint = <%s>, vol = %.3f, counts = %d"%(vrx[i], vvx[i], vvc[i]))
else:
for i in range(len(vvx)):
print("voro fingerprint = <x x x x>, vol = %.3f, counts = %d"%(vvx[i], vvc[i]))
if return_system:
return sys
else:
if return_system:
return np.array([vvx, vrx, vvc]), sys
else:
return np.array([vvx, vrx, vvc])
def find_tetrahedral_voids(infile, format="poscar", print_results=True, return_system=False,
direct_coordinates=True, precision=0.1):
"""
Check for tetrahedral voids in the system
Parameters
----------
infile : string
name of the input file
format : string
format of the input file, optional
default poscar
print_results: bool, optional
if True, print the results. If False, return the data
instead. default True
return_system: bool, optional
if True, return the system object.
default False
direct_coordinates: bool, optional
if True, results are provided in direct coordinates
default False
precision: int, optional
the number of digits to check for distances.
default 1
Returns
-------
types : list of atom types
volumes : list of atom volumes
pos : list of atom positions
sys : system object, returns only if return_sys is True
"""
sys = pc.System()
sys.read_inputfile(infile, format=format)
sys.find_neighbors(method="voronoi")
sys.calculate_vorovector()
atoms = sys.atoms
volumes = []
pos = []
types = []
box = sys.box
boxx = box[0][1] - box[0][0]
boxy = box[1][1] - box[1][0]
boxz = box[2][1] - box[2][0]
if len(atoms) < 21:
warnings.warn("Very less number of atoms, results maybe wrong. See https://github.com/srmnitc/pyscal/issues/63 ")
for atom in atoms:
if atom.vorovector[1] == 4:
#first to prevent small cells we need to filter
neighs = np.unique(atom.neighbors)
dists = np.array([sys.get_distance(atom, atoms[x]) for x in neighs])
mindist = dists[np.argsort(dists)][0]
mindistcount = 0
for i in range(len(dists)):
if mindist*(1.0-precision) <= dists[i] <= mindist*(1.0+precision):
mindistcount += 1
if mindistcount == 4:
volumes.append(atom.volume)
if direct_coordinates:
p = atom.pos
pos.append([p[0]/boxx, p[1]/boxy, p[2]/boxz])
else:
pos.append(atom.pos)
types.append(atom.type)
if print_results:
if len(volumes) > 0:
print("%d atoms found in tetrahedral position"%len(volumes))
for i in range(len(volumes)):
print("%d volume %f type %d at %f, %f, %f"%(i+1, volumes[i], types[i], pos[i][0], pos[i][1], pos[i][2]))
else:
print("no atoms found in tetrahedral position")
if return_system:
return types, volumes, pos, sys
else:
return types, volumes, pos