InterOptimus 0.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- interoptimus-0.0.0/InterOptimus/CNID.py +84 -0
- interoptimus-0.0.0/InterOptimus/MPsoap.py +368 -0
- interoptimus-0.0.0/InterOptimus/VaspWorkFlow.py +341 -0
- interoptimus-0.0.0/InterOptimus/__init__.py +0 -0
- interoptimus-0.0.0/InterOptimus/core.py +340 -0
- interoptimus-0.0.0/InterOptimus/equi_term.py +230 -0
- interoptimus-0.0.0/InterOptimus/itworker.py +562 -0
- interoptimus-0.0.0/InterOptimus/matching.py +797 -0
- interoptimus-0.0.0/InterOptimus/optimize.py +850 -0
- interoptimus-0.0.0/InterOptimus/tool.py +258 -0
- interoptimus-0.0.0/InterOptimus.egg-info/PKG-INFO +32 -0
- interoptimus-0.0.0/InterOptimus.egg-info/SOURCES.txt +18 -0
- interoptimus-0.0.0/InterOptimus.egg-info/dependency_links.txt +1 -0
- interoptimus-0.0.0/InterOptimus.egg-info/requires.txt +11 -0
- interoptimus-0.0.0/InterOptimus.egg-info/top_level.txt +1 -0
- interoptimus-0.0.0/LICENSE +22 -0
- interoptimus-0.0.0/PKG-INFO +32 -0
- interoptimus-0.0.0/README.md +7 -0
- interoptimus-0.0.0/setup.cfg +4 -0
- interoptimus-0.0.0/setup.py +32 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module calculate CNID vectors for a interface
|
|
3
|
+
"""
|
|
4
|
+
from numpy import *
|
|
5
|
+
from numpy.linalg import *
|
|
6
|
+
from interfacemaster.cellcalc import DSCcalc
|
|
7
|
+
from interfacemaster.hetero_searching import apply_function_to_array, float_to_rational
|
|
8
|
+
|
|
9
|
+
def get_au_vector(B):
|
|
10
|
+
"""
|
|
11
|
+
calculate the auxiliary vector of two vectors
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
B (array): two column vectors
|
|
15
|
+
|
|
16
|
+
Return:
|
|
17
|
+
(array): auxiliary normalized vector perpendicular to the input
|
|
18
|
+
"""
|
|
19
|
+
auv = cross(B[:,0], B[:,1])
|
|
20
|
+
return auv / norm(auv)
|
|
21
|
+
|
|
22
|
+
def from_2D_to_3D_transformation(B1, B2):
|
|
23
|
+
"""
|
|
24
|
+
calculate the 3D transformation matrix of two 2D bases
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
B1, B2 (arrays): two bases
|
|
28
|
+
|
|
29
|
+
Return:
|
|
30
|
+
rotation matrix converting B2 to B1
|
|
31
|
+
"""
|
|
32
|
+
auv_B1 = get_au_vector(B1)
|
|
33
|
+
auv_B2 = get_au_vector(B2)
|
|
34
|
+
C1 = column_stack((B1, auv_B1))
|
|
35
|
+
C2 = column_stack((B2, auv_B2))
|
|
36
|
+
return dot(C1, inv(C2))
|
|
37
|
+
|
|
38
|
+
def get_au_lattice(B):
|
|
39
|
+
"""
|
|
40
|
+
get the auxiliary 3D lattice for a 2D basis
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
B (array): 2D basis
|
|
44
|
+
|
|
45
|
+
Return:
|
|
46
|
+
(array): 3D auxiliary lattice vectors
|
|
47
|
+
"""
|
|
48
|
+
auv = get_au_vector(B)
|
|
49
|
+
return column_stack((B,auv))
|
|
50
|
+
|
|
51
|
+
def triple_dot(a, b, c):
|
|
52
|
+
"""
|
|
53
|
+
combined product
|
|
54
|
+
"""
|
|
55
|
+
return dot(a, dot(b, c))
|
|
56
|
+
|
|
57
|
+
def calculate_cnid_in_supercell(interface):
|
|
58
|
+
"""
|
|
59
|
+
calculate CNID for a interface
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
interface (Interface)
|
|
63
|
+
|
|
64
|
+
Return:
|
|
65
|
+
(array, dtype = float): CNID vectors by float
|
|
66
|
+
(array, dtype = string): CNID vectors by rational numbers
|
|
67
|
+
"""
|
|
68
|
+
props = interface.interface_properties
|
|
69
|
+
transformation = from_2D_to_3D_transformation(props['substrate_sl_vectors'].T, props['film_sl_vectors'].T)
|
|
70
|
+
B_substrate = array(props['substrate_vectors']).T
|
|
71
|
+
B_film = array(props['film_vectors']).T
|
|
72
|
+
B_substrate = get_au_lattice(B_substrate)
|
|
73
|
+
B_film = get_au_lattice(B_film)
|
|
74
|
+
B_film = dot(transformation, B_film)
|
|
75
|
+
calc = DSCcalc()
|
|
76
|
+
calc.parse_int_U(B_substrate, B_film, 200)
|
|
77
|
+
calc.compute_CSL()
|
|
78
|
+
calc.compute_CNID([0,0,1])
|
|
79
|
+
CSL = calc.CSL
|
|
80
|
+
CNID = calc.CNID
|
|
81
|
+
slB = get_au_lattice(array(props['substrate_sl_vectors']).T)
|
|
82
|
+
B = get_au_lattice(array(props['substrate_vectors']).T)
|
|
83
|
+
CNID_sl = triple_dot(inv(slB), B, CNID)
|
|
84
|
+
return CNID_sl, apply_function_to_array(CNID_sl, float_to_rational)
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
"""This module provides class to extract SOAP descriptors of the non-identical sites in the crystalline materials in Materials Project."""
|
|
2
|
+
from pymatgen.analysis.local_env import CrystalNN
|
|
3
|
+
from pymatgen.analysis.interfaces.substrate_analyzer import SubstrateAnalyzer
|
|
4
|
+
from pymatgen.core.structure import Structure
|
|
5
|
+
from pymatgen.analysis.structure_analyzer import SpacegroupAnalyzer
|
|
6
|
+
from dscribe.descriptors import SOAP
|
|
7
|
+
from ase.io import read as aR
|
|
8
|
+
from numpy import *
|
|
9
|
+
from pymatgen.core.periodic_table import Element
|
|
10
|
+
from mp_api.client import MPRester
|
|
11
|
+
import os
|
|
12
|
+
import itertools
|
|
13
|
+
import shutil
|
|
14
|
+
import pandas as pd
|
|
15
|
+
from scipy.spatial.distance import pdist
|
|
16
|
+
from tqdm import tqdm
|
|
17
|
+
import pickle
|
|
18
|
+
import time
|
|
19
|
+
from InterOptimus.tool import read_key_item, existfilehere
|
|
20
|
+
|
|
21
|
+
def get_Z(struct):
|
|
22
|
+
"""given structure, get element names.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
struct (Structure).
|
|
26
|
+
|
|
27
|
+
Return:
|
|
28
|
+
list of atomic numbers.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
return [i.Z for i in struct.elements]
|
|
32
|
+
|
|
33
|
+
def generate_combinations(elements):
|
|
34
|
+
"""given elements, get all possible combinations.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
elements (list): list of elements.
|
|
38
|
+
|
|
39
|
+
Return:
|
|
40
|
+
combinations (list): list of combinations.
|
|
41
|
+
"""
|
|
42
|
+
combinations = []
|
|
43
|
+
|
|
44
|
+
for i in range(1, len(elements) + 1):
|
|
45
|
+
for combo in itertools.combinations(elements, i):
|
|
46
|
+
combinations.append('-'.join(combo))
|
|
47
|
+
return combinations
|
|
48
|
+
|
|
49
|
+
def get_elements(struct):
|
|
50
|
+
"""given structure, get atomic number list.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
struct (Structure).
|
|
54
|
+
|
|
55
|
+
Return:
|
|
56
|
+
list of elements.
|
|
57
|
+
"""
|
|
58
|
+
return [i.symbol for i in struct.elements]
|
|
59
|
+
|
|
60
|
+
def to_ase(pymatgen_struct):
|
|
61
|
+
"""given pymatgen structure, get ase Atoms.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
struct (Structure).
|
|
65
|
+
|
|
66
|
+
return:
|
|
67
|
+
ase Atoms.
|
|
68
|
+
"""
|
|
69
|
+
pymatgen_struct.to_file('POSCAR_tt')
|
|
70
|
+
ase_struct = aR('POSCAR_tt')
|
|
71
|
+
os.remove('POSCAR_tt')
|
|
72
|
+
return ase_struct
|
|
73
|
+
|
|
74
|
+
def MPsearch(elements, API_KEY, theoretical = False, is_stable = True, filter_elemental_materials = True):
|
|
75
|
+
"""searching for synthesized structures including at least a set of elements from Materials Project.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
elements (list): list of elments included at least.
|
|
79
|
+
API_KEY (str): API key.
|
|
80
|
+
|
|
81
|
+
return:
|
|
82
|
+
docs (list): list of searching results.
|
|
83
|
+
"""
|
|
84
|
+
#print(generate_combinations(elements))
|
|
85
|
+
with MPRester(API_KEY) as mpr:
|
|
86
|
+
docs = mpr.materials.summary.search(
|
|
87
|
+
chemsys=generate_combinations(elements), \
|
|
88
|
+
fields=["material_id", "structure", "nelements"], \
|
|
89
|
+
theoretical=False,
|
|
90
|
+
is_stable=is_stable,
|
|
91
|
+
)
|
|
92
|
+
if theoretical:
|
|
93
|
+
with MPRester(API_KEY) as mpr:
|
|
94
|
+
docs.extend(mpr.materials.summary.search(
|
|
95
|
+
chemsys=generate_combinations(elements), \
|
|
96
|
+
fields=["material_id", "structure", "nelements"], \
|
|
97
|
+
theoretical=True,
|
|
98
|
+
is_stable=is_stable,
|
|
99
|
+
))
|
|
100
|
+
if filter_elemental_materials:
|
|
101
|
+
docs = [i for i in docs if i.nelements > 1]
|
|
102
|
+
return docs
|
|
103
|
+
|
|
104
|
+
class stct_help_class:
|
|
105
|
+
def __init__(self, structure):
|
|
106
|
+
self.structure = structure
|
|
107
|
+
|
|
108
|
+
class soap_data_generator:
|
|
109
|
+
"""generate soap data from MP database.
|
|
110
|
+
"""
|
|
111
|
+
def __init__(self, \
|
|
112
|
+
elements, \
|
|
113
|
+
API_KEY, \
|
|
114
|
+
theoretical, is_stable, filter_elemental_materials, structure_from_MP, film, substrate, from_dir = False):
|
|
115
|
+
self.elements = elements
|
|
116
|
+
self.theoretical = theoretical
|
|
117
|
+
self.structure_from_MP = structure_from_MP
|
|
118
|
+
if not from_dir:
|
|
119
|
+
if self.structure_from_MP:
|
|
120
|
+
self.docs = MPsearch(elements, API_KEY, theoretical, is_stable, filter_elemental_materials)
|
|
121
|
+
else:
|
|
122
|
+
self.docs = [stct_help_class(film), stct_help_class(substrate)]
|
|
123
|
+
else:
|
|
124
|
+
with open('MPdocs.pkl', 'rb') as file:
|
|
125
|
+
docs = pickle.load(file)
|
|
126
|
+
self.docs = []
|
|
127
|
+
for i in docs.keys():
|
|
128
|
+
self.docs.append(stct_help_class(Structure.from_dict(docs[i])))
|
|
129
|
+
"""
|
|
130
|
+
Args:
|
|
131
|
+
elements (list): list of elements to consider.
|
|
132
|
+
API_KEY (string): API key for using Materials Project.
|
|
133
|
+
theoretical (bool): whether to consider theoretical materials (not synthesized yet).
|
|
134
|
+
"""
|
|
135
|
+
@classmethod
|
|
136
|
+
def from_dir(cls):
|
|
137
|
+
set_data = read_key_item('INTAR')
|
|
138
|
+
substrate_conv = Structure.from_file('SBS.cif')
|
|
139
|
+
film_conv = Structure.from_file('FLM.cif')
|
|
140
|
+
elements = list(set([i.symbol for i in film_conv.elements]).union([i.symbol for i in substrate_conv.elements]))
|
|
141
|
+
return cls(elements, set_data['APIKEY'], set_data['THEORETICAL'], set_data['STABLE'], set_data['NOELEM'],\
|
|
142
|
+
set_data['STCTMP'], film_conv, substrate_conv, True)
|
|
143
|
+
|
|
144
|
+
def calculate_soaps(self, soap_params = None, output_sym_stct = False):
|
|
145
|
+
"""
|
|
146
|
+
get soap descriptors for all the searched materials.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
soap_params (dict): SOAP parameters.
|
|
150
|
+
"""
|
|
151
|
+
soap_params_default = {'r_cut':6, 'n_max':7, 'l_max':7, \
|
|
152
|
+
'weighting':{"function":"pow", "r0":4, "c":1, "d":1,
|
|
153
|
+
"m":20}}
|
|
154
|
+
if soap_params == None or len(soap_params) == 0:
|
|
155
|
+
self.soap_params = soap_params_default
|
|
156
|
+
else:
|
|
157
|
+
for j in soap_params.keys():
|
|
158
|
+
soap_params_default[j] = soap_params[j]
|
|
159
|
+
self.soap_params = soap_params_default
|
|
160
|
+
self.soap_elements = []
|
|
161
|
+
self.soap_struct_indices = []
|
|
162
|
+
self.sym_structures = []
|
|
163
|
+
self.soap_site_indices = []
|
|
164
|
+
self.soap_descs = []
|
|
165
|
+
self.min_nb_distances = []
|
|
166
|
+
self.EN_diffs = []
|
|
167
|
+
#soap analyzer initialization
|
|
168
|
+
with tqdm(total=len(self.docs), desc="calculating SOAPs", leave=False) as struct_bar:
|
|
169
|
+
for i in range(len(self.docs)):
|
|
170
|
+
my_soap_analyzer = soap_analyzer(self.elements, self.docs[i].structure, i, self.soap_params)
|
|
171
|
+
|
|
172
|
+
#extract soap for each element
|
|
173
|
+
my_soap_analyzer.extract_soap_for_searching_elements(self.elements)
|
|
174
|
+
#update symmetrized structure info
|
|
175
|
+
self.sym_structures.append(my_soap_analyzer.struct)
|
|
176
|
+
#update soap structured data
|
|
177
|
+
for j in my_soap_analyzer.soap_infos:
|
|
178
|
+
if len(self.soap_descs) == 0:
|
|
179
|
+
self.soap_descs = j.vector
|
|
180
|
+
else:
|
|
181
|
+
self.soap_descs = vstack((self.soap_descs, j.vector))
|
|
182
|
+
self.soap_elements.append(j.center_element)
|
|
183
|
+
self.soap_struct_indices.append(j.belonging_structure_index)
|
|
184
|
+
self.soap_site_indices.append(j.site_index)
|
|
185
|
+
self.min_nb_distances.append(j.min_nb_distance)
|
|
186
|
+
self.EN_diffs.append(j.EN_diff)
|
|
187
|
+
struct_bar.update(1)
|
|
188
|
+
self.soap_elements, self.soap_struct_indices, \
|
|
189
|
+
self.soap_site_indices, self.min_nb_distances, self.EN_diffs = \
|
|
190
|
+
array(self.soap_elements), array(self.soap_struct_indices), \
|
|
191
|
+
array(self.soap_site_indices), array(self.min_nb_distances),\
|
|
192
|
+
array(self.EN_diffs)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
self.cluster_by_element()
|
|
196
|
+
|
|
197
|
+
if output_sym_stct:
|
|
198
|
+
try:
|
|
199
|
+
shutil.rmtree('docs_sym_structures')
|
|
200
|
+
except:
|
|
201
|
+
print('generate searched structures')
|
|
202
|
+
os.mkdir('docs_sym_structures')
|
|
203
|
+
for i in range(len(self.sym_structures)):
|
|
204
|
+
self.sym_structures[i].to_file(f'docs_sym_structures/{i}_POSCAR')
|
|
205
|
+
|
|
206
|
+
def cluster_by_element(self):
|
|
207
|
+
"""
|
|
208
|
+
cluster the soap descriptors by element names.
|
|
209
|
+
"""
|
|
210
|
+
self.by_element_dict = {}
|
|
211
|
+
min_dists_saved = existfilehere('min_dists.dat')
|
|
212
|
+
for i in self.elements:
|
|
213
|
+
self.by_element_dict[i] = {}
|
|
214
|
+
self.by_element_dict[i]['soap_descs'] = \
|
|
215
|
+
self.soap_descs[self.soap_elements == i]
|
|
216
|
+
|
|
217
|
+
self.by_element_dict[i]['soap_struct_indices'] = \
|
|
218
|
+
self.soap_struct_indices[self.soap_elements == i]
|
|
219
|
+
|
|
220
|
+
self.by_element_dict[i]['soap_site_indices'] = \
|
|
221
|
+
self.soap_site_indices[self.soap_elements == i]
|
|
222
|
+
|
|
223
|
+
self.by_element_dict[i]['min_nb_distances'] = \
|
|
224
|
+
self.min_nb_distances[self.soap_elements == i]
|
|
225
|
+
if not min_dists_saved:
|
|
226
|
+
with open('min_dists.dat','a') as f:
|
|
227
|
+
for distance in self.min_nb_distances[self.soap_elements == i]:
|
|
228
|
+
f.write(f'{distance} ')
|
|
229
|
+
f.write(f'\n')
|
|
230
|
+
|
|
231
|
+
self.by_element_dict[i]['EN_diffs'] = \
|
|
232
|
+
self.EN_diffs[self.soap_elements == i]
|
|
233
|
+
|
|
234
|
+
self.by_element_dict[i]['min_nb_distance'] = \
|
|
235
|
+
min(self.by_element_dict[i]['min_nb_distances'])
|
|
236
|
+
|
|
237
|
+
self.by_element_dict[i]['pd'] =\
|
|
238
|
+
pd.DataFrame(columns=['elements','struct_id','site_id'])
|
|
239
|
+
|
|
240
|
+
for j in range(len(self.by_element_dict[i]['soap_descs'])):
|
|
241
|
+
self.by_element_dict[i]['pd'].loc[j] =\
|
|
242
|
+
[self.docs[self.by_element_dict[i]['soap_struct_indices'][j]].structure.elements,\
|
|
243
|
+
self.by_element_dict[i]['soap_struct_indices'][j],\
|
|
244
|
+
self.by_element_dict[i]['soap_site_indices'][j]]
|
|
245
|
+
|
|
246
|
+
def get_distances(self):
|
|
247
|
+
"""
|
|
248
|
+
get the distances(dissimilarities) of all the descriptors
|
|
249
|
+
|
|
250
|
+
Return:
|
|
251
|
+
distance_pdist (array): distance list.
|
|
252
|
+
"""
|
|
253
|
+
distance_pdist = {}
|
|
254
|
+
for i in self.elements:
|
|
255
|
+
dis_list = pdist(self.by_element_dict[i]['soap_descs'], \
|
|
256
|
+
metric = 'cosine')
|
|
257
|
+
distance_pdist[i] = dis_list
|
|
258
|
+
return distance_pdist
|
|
259
|
+
|
|
260
|
+
class soap_info:
|
|
261
|
+
"""
|
|
262
|
+
soap descriptor information
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
vector (array): soap descripor.
|
|
266
|
+
center_element (string): center element name.
|
|
267
|
+
belonging_structure_index (int): which structure it belongs to.
|
|
268
|
+
site_index (int): which site it is.
|
|
269
|
+
min_nb_distance: nearest neighboring distance.
|
|
270
|
+
"""
|
|
271
|
+
def __init__(self, vector, center_element, belonging_structure_index, \
|
|
272
|
+
site_index, min_nb_distance, EN_diff):
|
|
273
|
+
self.vector = vector #soap vector
|
|
274
|
+
self.center_element = center_element #center element
|
|
275
|
+
self.belonging_structure_index = belonging_structure_index #which structure it belongs to
|
|
276
|
+
self.site_index = site_index #at which site
|
|
277
|
+
self.min_nb_distance = min_nb_distance #minimum neighboring distance
|
|
278
|
+
self.EN_diff = EN_diff
|
|
279
|
+
|
|
280
|
+
class soap_analyzer:
|
|
281
|
+
"""
|
|
282
|
+
for a given structure, get the soap descriptors for all the non-identical sites
|
|
283
|
+
"""
|
|
284
|
+
def __init__(self, elements, struct, struct_index, soap_params):
|
|
285
|
+
"""
|
|
286
|
+
Args:
|
|
287
|
+
|
|
288
|
+
elements: (list): list of elements considered
|
|
289
|
+
structure (Structure): structure to calculate soap
|
|
290
|
+
struct_index (int): index of the structure
|
|
291
|
+
soap_params (dict): soap parameters
|
|
292
|
+
"""
|
|
293
|
+
self.struct = struct
|
|
294
|
+
self.get_non_equi_sites_indices()
|
|
295
|
+
|
|
296
|
+
periodic_soap = SOAP(
|
|
297
|
+
species={i: Element(i).Z for i in elements},
|
|
298
|
+
r_cut=soap_params['r_cut'],
|
|
299
|
+
n_max=soap_params['n_max'],
|
|
300
|
+
l_max=soap_params['l_max'],
|
|
301
|
+
periodic=True,
|
|
302
|
+
sparse=False,
|
|
303
|
+
weighting = soap_params['weighting'],
|
|
304
|
+
#compression = {"mode": "mu2", "species_weighting":{el.symbol:el.Z * soap_params['Z_scale'] for el in Element}}
|
|
305
|
+
)
|
|
306
|
+
self.soap_discriptors_nesites = periodic_soap.create(self.ase_struct, \
|
|
307
|
+
centers = self.non_equi_sites_indices)
|
|
308
|
+
self.struct_index = struct_index
|
|
309
|
+
|
|
310
|
+
def get_non_equi_sites_indices(self):
|
|
311
|
+
"""given structure, get the indices of the non-equivalent sites
|
|
312
|
+
"""
|
|
313
|
+
analyzer = SpacegroupAnalyzer(self.struct.get_primitive_structure())
|
|
314
|
+
symmetrized_structure = analyzer.get_symmetrized_structure()
|
|
315
|
+
self.non_equi_sites_indices = [i[0] for i in symmetrized_structure.equivalent_indices]
|
|
316
|
+
self.non_equi_sites_elements = [i[0].label for i in symmetrized_structure.equivalent_sites]
|
|
317
|
+
self.struct = symmetrized_structure
|
|
318
|
+
self.ase_struct = to_ase(symmetrized_structure)
|
|
319
|
+
|
|
320
|
+
def extract_soap_for_searching_elements(self, cons_elements):
|
|
321
|
+
"""extract soap for determined elements
|
|
322
|
+
|
|
323
|
+
Args:
|
|
324
|
+
cons_elements (list): elements to extract their soaps
|
|
325
|
+
"""
|
|
326
|
+
self.soap_infos = []
|
|
327
|
+
for i in range(len(self.non_equi_sites_elements)):
|
|
328
|
+
if self.non_equi_sites_elements[i] in cons_elements:
|
|
329
|
+
this_soap = soap_info(self.soap_discriptors_nesites[i],
|
|
330
|
+
self.non_equi_sites_elements[i],
|
|
331
|
+
self.struct_index,
|
|
332
|
+
self.non_equi_sites_indices[i],
|
|
333
|
+
get_min_nb_distance(self.non_equi_sites_indices[i], self.struct),
|
|
334
|
+
get_EN_diff_crystall(self.struct, self.non_equi_sites_indices[i]))
|
|
335
|
+
self.soap_infos.append(this_soap)
|
|
336
|
+
|
|
337
|
+
def get_delta_distances(atom_index, structure, cutoff):
|
|
338
|
+
neighbors = structure.get_neighbors(structure[atom_index], r=cutoff)
|
|
339
|
+
if len(neighbors) > 0:
|
|
340
|
+
return array([neighbor[1] for neighbor in neighbors])
|
|
341
|
+
else:
|
|
342
|
+
return array([cutoff])
|
|
343
|
+
|
|
344
|
+
def get_min_nb_distance(atom_index, structure):
|
|
345
|
+
"""
|
|
346
|
+
get the minimum neighboring distance for certain atom in a structure
|
|
347
|
+
|
|
348
|
+
Args:
|
|
349
|
+
atom_index (int): atom index in the structure
|
|
350
|
+
structure (Structure)
|
|
351
|
+
|
|
352
|
+
Return:
|
|
353
|
+
(float): nearest neighboring distance
|
|
354
|
+
"""
|
|
355
|
+
neighbors = structure.get_neighbors(structure[atom_index], r=10)
|
|
356
|
+
return min([neighbor[1] for neighbor in neighbors])
|
|
357
|
+
|
|
358
|
+
def get_EN_diff_crystall(structure, site_idx):
|
|
359
|
+
cn = CrystalNN()
|
|
360
|
+
center_EN = structure[site_idx].specie.X
|
|
361
|
+
nb_ENs = array([i['site'].specie.X for i in cn.get_nn_shell_info(structure, site_idx, 1)])
|
|
362
|
+
return sum(nb_ENs - center_EN)
|
|
363
|
+
|
|
364
|
+
def get_EN_diff_interface(interface, site_idx, r_cut):
|
|
365
|
+
cn = CrystalNN()
|
|
366
|
+
center_EN = interface[site_idx].specie.X
|
|
367
|
+
nb_ENs = array([i['site'].specie.X for i in cn.get_nn_info(interface, site_idx) if i['site'].distance(interface[site_idx]) < r_cut])
|
|
368
|
+
return sum(nb_ENs - center_EN)
|