kim-tools 0.3.5__py3-none-any.whl → 0.3.7__py3-none-any.whl
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.
- kim_tools/__init__.py +1 -1
- kim_tools/aflow_util/core.py +66 -4
- kim_tools/symmetry_util/core.py +314 -0
- kim_tools/symmetry_util/data/elast_cubic.svg +105 -0
- kim_tools/symmetry_util/data/elast_hexagonal.svg +105 -0
- kim_tools/symmetry_util/data/elast_monoclinic.svg +108 -0
- kim_tools/symmetry_util/data/elast_orthorhombic.svg +96 -0
- kim_tools/symmetry_util/data/elast_tetragonal_4_slash_m.svg +114 -0
- kim_tools/symmetry_util/data/elast_tetragonal_4_slash_mmm.svg +105 -0
- kim_tools/symmetry_util/data/elast_triclinic.svg +132 -0
- kim_tools/symmetry_util/data/elast_trigonal_3bar.svg +129 -0
- kim_tools/symmetry_util/data/elast_trigonal_3bar_m_2nd_pos.svg +117 -0
- kim_tools/symmetry_util/data/elast_trigonal_3bar_m_3rd_pos.svg +117 -0
- kim_tools/symmetry_util/elasticity.py +390 -0
- kim_tools/test_driver/core.py +95 -18
- {kim_tools-0.3.5.dist-info → kim_tools-0.3.7.dist-info}/METADATA +1 -1
- {kim_tools-0.3.5.dist-info → kim_tools-0.3.7.dist-info}/RECORD +20 -9
- {kim_tools-0.3.5.dist-info → kim_tools-0.3.7.dist-info}/WHEEL +0 -0
- {kim_tools-0.3.5.dist-info → kim_tools-0.3.7.dist-info}/licenses/LICENSE.CDDL +0 -0
- {kim_tools-0.3.5.dist-info → kim_tools-0.3.7.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,390 @@
|
|
1
|
+
import logging
|
2
|
+
import math
|
3
|
+
import os
|
4
|
+
import shutil
|
5
|
+
from typing import Dict, List, Tuple, Union
|
6
|
+
|
7
|
+
import numpy as np
|
8
|
+
import numpy.typing as npt
|
9
|
+
|
10
|
+
from .core import DATA_DIR, _check_space_group
|
11
|
+
|
12
|
+
logger = logging.getLogger(__name__)
|
13
|
+
logging.basicConfig(filename="kim-tools.log", level=logging.INFO, force=True)
|
14
|
+
|
15
|
+
|
16
|
+
def voigt_elast_class(sgnum: Union[int, str]) -> str:
|
17
|
+
"""
|
18
|
+
Get the name of the class of the structure of the elasticity tensor, out of
|
19
|
+
the following possibilities:
|
20
|
+
"cubic", "hexagonal", "trigonal_3bar_m_2nd_pos", "trigonal_3bar_m_3rd_pos",
|
21
|
+
"trigonal_3bar", "tetragonal_class_4_slash_mmm", "tetragonal_class_4_slash_m",
|
22
|
+
"orthorhombic", "monoclinic", "triclinic". The names that don't
|
23
|
+
correspond to a crystal system are taken from
|
24
|
+
https://dictionary.iucr.org/Laue_class
|
25
|
+
|
26
|
+
Note that this is a novel classification as far as the authors are aware.
|
27
|
+
Most crystallography texts on the subject will show 9 classes. This function
|
28
|
+
returns 10 possibilities, because the structure of the components of
|
29
|
+
the elasticity tensor for Laue class -3m depends on whether the twofold
|
30
|
+
axis is aligned along the Cartesian x or y axis. Assuming one adopts a
|
31
|
+
standard orientation of the hexagonal unit cell w.r.t. the Cartesian coordinate
|
32
|
+
system, as we do, different space groups in this Laue class have different
|
33
|
+
forms.
|
34
|
+
|
35
|
+
See https://doi.org/10.1017/CBO9781139017657.008 pg 232 for a review
|
36
|
+
of the subject.
|
37
|
+
"""
|
38
|
+
_check_space_group(sgnum)
|
39
|
+
sgnum = int(sgnum)
|
40
|
+
|
41
|
+
if sgnum < 3:
|
42
|
+
return "triclinic"
|
43
|
+
elif sgnum < 16:
|
44
|
+
return "monoclinic"
|
45
|
+
elif sgnum < 75:
|
46
|
+
return "orthorhombic"
|
47
|
+
elif sgnum < 89:
|
48
|
+
return "tetragonal_4_slash_m"
|
49
|
+
elif sgnum < 143:
|
50
|
+
return "tetragonal_4_slash_mmm"
|
51
|
+
elif sgnum < 149:
|
52
|
+
return "trigonal_3bar"
|
53
|
+
elif sgnum < 168:
|
54
|
+
# Determine if this is one of the groups with the 2-fold operation in the
|
55
|
+
# third position (e.g. 149:P312), which has different equations
|
56
|
+
if sgnum in (149, 151, 153, 157, 159, 162, 163):
|
57
|
+
return "trigonal_3bar_m_3rd_pos"
|
58
|
+
else:
|
59
|
+
return "trigonal_3bar_m_2nd_pos"
|
60
|
+
elif sgnum < 195:
|
61
|
+
return "hexagonal"
|
62
|
+
else:
|
63
|
+
return "cubic"
|
64
|
+
|
65
|
+
|
66
|
+
def voigt_elast_compon_eqn(sgnum: Union[int, str]) -> Dict:
|
67
|
+
"""
|
68
|
+
Get the algebraic equations describing the symmetry restrictions
|
69
|
+
on the elasticity matrix in Voigt form given a space group number.
|
70
|
+
The unit cell
|
71
|
+
must be in the orientation defined in doi.org/10.1016/j.commatsci.2017.01.017
|
72
|
+
for these equations to be correct.
|
73
|
+
|
74
|
+
Returns:
|
75
|
+
Encoding of symmetry restrictions on elasticity matrices.
|
76
|
+
The keys are the Voigt indices of non-independent components.
|
77
|
+
The values are a pair of lists representing the linear combination
|
78
|
+
of the unique compoonents that is used to determine the non-unique component
|
79
|
+
specified in the key. The first list is the coefficients, the second
|
80
|
+
is the indices. If a non-independent component is zero, this is indicated
|
81
|
+
by a value of None. Any components not listed as a key are assumed to
|
82
|
+
be independent. Only the upper triangle (i<j) is listed. Indices are
|
83
|
+
one-based.
|
84
|
+
"""
|
85
|
+
ELASTICITY_MATRIX_EQNS = {
|
86
|
+
"cubic": {
|
87
|
+
(1, 3): ([1], [(1, 2)]),
|
88
|
+
(1, 4): None,
|
89
|
+
(1, 5): None,
|
90
|
+
(1, 6): None,
|
91
|
+
(2, 2): ([1], [(1, 1)]),
|
92
|
+
(2, 3): ([1], [(1, 2)]),
|
93
|
+
(2, 4): None,
|
94
|
+
(2, 5): None,
|
95
|
+
(2, 6): None,
|
96
|
+
(3, 3): ([1], [(1, 1)]),
|
97
|
+
(3, 4): None,
|
98
|
+
(3, 5): None,
|
99
|
+
(3, 6): None,
|
100
|
+
(4, 5): None,
|
101
|
+
(4, 6): None,
|
102
|
+
(5, 5): ([1], [(4, 4)]),
|
103
|
+
(5, 6): None,
|
104
|
+
(6, 6): ([1], [(4, 4)]),
|
105
|
+
},
|
106
|
+
"hexagonal": {
|
107
|
+
(1, 4): None,
|
108
|
+
(1, 5): None,
|
109
|
+
(1, 6): None,
|
110
|
+
(2, 2): ([1], [(1, 1)]),
|
111
|
+
(2, 3): ([1], [(1, 3)]),
|
112
|
+
(2, 4): None,
|
113
|
+
(2, 5): None,
|
114
|
+
(2, 6): None,
|
115
|
+
(3, 4): None,
|
116
|
+
(3, 5): None,
|
117
|
+
(3, 6): None,
|
118
|
+
(4, 5): None,
|
119
|
+
(4, 6): None,
|
120
|
+
(5, 5): ([1], [(4, 4)]),
|
121
|
+
(5, 6): None,
|
122
|
+
(6, 6): ([0.5, -0.5], [(1, 1), (1, 2)]),
|
123
|
+
},
|
124
|
+
"trigonal_3bar_m_2nd_pos": {
|
125
|
+
(1, 5): None,
|
126
|
+
(1, 6): None,
|
127
|
+
(2, 2): ([1], [(1, 1)]),
|
128
|
+
(2, 3): ([1], [(1, 3)]),
|
129
|
+
(2, 4): ([-1], [(1, 4)]),
|
130
|
+
(2, 5): None,
|
131
|
+
(2, 6): None,
|
132
|
+
(3, 4): None,
|
133
|
+
(3, 5): None,
|
134
|
+
(3, 6): None,
|
135
|
+
(4, 5): None,
|
136
|
+
(4, 6): None,
|
137
|
+
(5, 5): ([1], [(4, 4)]),
|
138
|
+
(5, 6): ([1], [(1, 4)]),
|
139
|
+
(6, 6): ([0.5, -0.5], [(1, 1), (1, 2)]),
|
140
|
+
},
|
141
|
+
"trigonal_3bar_m_3rd_pos": {
|
142
|
+
(1, 4): None,
|
143
|
+
(1, 6): None,
|
144
|
+
(2, 2): ([1], [(1, 1)]),
|
145
|
+
(2, 3): ([1], [(1, 3)]),
|
146
|
+
(2, 4): None,
|
147
|
+
(2, 5): ([-1], [(1, 5)]),
|
148
|
+
(2, 6): None,
|
149
|
+
(3, 4): None,
|
150
|
+
(3, 5): None,
|
151
|
+
(3, 6): None,
|
152
|
+
(4, 5): None,
|
153
|
+
(4, 6): ([-1], [(1, 5)]),
|
154
|
+
(5, 5): ([1], [(4, 4)]),
|
155
|
+
(5, 6): None,
|
156
|
+
(6, 6): ([0.5, -0.5], [(1, 1), (1, 2)]),
|
157
|
+
},
|
158
|
+
"trigonal_3bar": {
|
159
|
+
(1, 6): None,
|
160
|
+
(2, 2): ([1], [(1, 1)]),
|
161
|
+
(2, 3): ([1], [(1, 3)]),
|
162
|
+
(2, 4): ([-1], [(1, 4)]),
|
163
|
+
(2, 5): ([-1], [(1, 5)]),
|
164
|
+
(2, 6): None,
|
165
|
+
(3, 4): None,
|
166
|
+
(3, 5): None,
|
167
|
+
(3, 6): None,
|
168
|
+
(4, 5): None,
|
169
|
+
(4, 6): ([-1], [(1, 5)]),
|
170
|
+
(5, 5): ([1], [(4, 4)]),
|
171
|
+
(5, 6): ([1], [(1, 4)]),
|
172
|
+
(6, 6): ([0.5, -0.5], [(1, 1), (1, 2)]),
|
173
|
+
},
|
174
|
+
"tetragonal_4_slash_mmm": {
|
175
|
+
(1, 4): None,
|
176
|
+
(1, 5): None,
|
177
|
+
(1, 6): None,
|
178
|
+
(2, 2): ([1], [(1, 1)]),
|
179
|
+
(2, 3): ([1], [(1, 3)]),
|
180
|
+
(2, 4): None,
|
181
|
+
(2, 5): None,
|
182
|
+
(2, 6): None,
|
183
|
+
(3, 4): None,
|
184
|
+
(3, 5): None,
|
185
|
+
(3, 6): None,
|
186
|
+
(4, 5): None,
|
187
|
+
(4, 6): None,
|
188
|
+
(5, 5): ([1], [(4, 4)]),
|
189
|
+
(5, 6): None,
|
190
|
+
},
|
191
|
+
"tetragonal_4_slash_m": {
|
192
|
+
(1, 4): None,
|
193
|
+
(1, 5): None,
|
194
|
+
(2, 2): ([1], [(1, 1)]),
|
195
|
+
(2, 3): ([1], [(1, 3)]),
|
196
|
+
(2, 4): None,
|
197
|
+
(2, 5): None,
|
198
|
+
(2, 6): ([-1], [(1, 6)]),
|
199
|
+
(3, 4): None,
|
200
|
+
(3, 5): None,
|
201
|
+
(3, 6): None,
|
202
|
+
(4, 5): None,
|
203
|
+
(4, 6): None,
|
204
|
+
(5, 5): ([1], [(4, 4)]),
|
205
|
+
(5, 6): None,
|
206
|
+
},
|
207
|
+
"orthorhombic": {
|
208
|
+
(1, 4): None,
|
209
|
+
(1, 5): None,
|
210
|
+
(1, 6): None,
|
211
|
+
(2, 4): None,
|
212
|
+
(2, 5): None,
|
213
|
+
(2, 6): None,
|
214
|
+
(3, 4): None,
|
215
|
+
(3, 5): None,
|
216
|
+
(3, 6): None,
|
217
|
+
(4, 5): None,
|
218
|
+
(4, 6): None,
|
219
|
+
(5, 6): None,
|
220
|
+
},
|
221
|
+
"monoclinic": {
|
222
|
+
(1, 4): None,
|
223
|
+
(1, 6): None,
|
224
|
+
(2, 4): None,
|
225
|
+
(2, 6): None,
|
226
|
+
(3, 4): None,
|
227
|
+
(3, 6): None,
|
228
|
+
(4, 5): None,
|
229
|
+
(5, 6): None,
|
230
|
+
},
|
231
|
+
"triclinic": {},
|
232
|
+
}
|
233
|
+
|
234
|
+
# error check typing in the above dicts
|
235
|
+
for eqn in ELASTICITY_MATRIX_EQNS.values():
|
236
|
+
# only unique keys
|
237
|
+
assert sorted(list(set(eqn.keys()))) == sorted(list(eqn.keys()))
|
238
|
+
# check that all components appearing in RHS of relations are independent, i.e.
|
239
|
+
# they don't appear as a key
|
240
|
+
for dependent_component in eqn:
|
241
|
+
if eqn[dependent_component] is not None:
|
242
|
+
for independent_component in eqn[dependent_component][1]:
|
243
|
+
assert not (independent_component in eqn)
|
244
|
+
|
245
|
+
return ELASTICITY_MATRIX_EQNS[voigt_elast_class(sgnum)]
|
246
|
+
|
247
|
+
|
248
|
+
def voigt_elast_struct_svg(sgnum: Union[int, str], dest_filename: str) -> None:
|
249
|
+
"""
|
250
|
+
Write a copy of the image showing the structure of the Voigt elasticity matrix for
|
251
|
+
the specified space group
|
252
|
+
"""
|
253
|
+
src_filename = os.path.join(DATA_DIR, "elast_" + voigt_elast_class(sgnum) + ".svg")
|
254
|
+
shutil.copyfile(src_filename, dest_filename)
|
255
|
+
|
256
|
+
|
257
|
+
def indep_elast_compon_names_and_values_from_voigt(
|
258
|
+
voigt: npt.ArrayLike, sgnum: Union[int, str]
|
259
|
+
) -> Tuple[List[str], List[float]]:
|
260
|
+
"""
|
261
|
+
From an elasticity matrix in Voigt order and a space group number,
|
262
|
+
extract the elastic constants that should be unique (cij where first i is as low as
|
263
|
+
possible, then j)
|
264
|
+
"""
|
265
|
+
eqn = voigt_elast_compon_eqn(sgnum)
|
266
|
+
|
267
|
+
elastic_constants_names = []
|
268
|
+
elastic_constants_values = []
|
269
|
+
|
270
|
+
# first, figure out which constants are unique and extract them
|
271
|
+
for i in range(1, 7):
|
272
|
+
for j in range(i, 7):
|
273
|
+
if (i, j) not in eqn:
|
274
|
+
elastic_constants_names.append("c" + str(i) + str(j))
|
275
|
+
elastic_constants_values.append(voigt[i - 1, j - 1])
|
276
|
+
|
277
|
+
return elastic_constants_names, elastic_constants_values
|
278
|
+
|
279
|
+
|
280
|
+
def calc_bulk(elastic_constants):
|
281
|
+
"""
|
282
|
+
Compute the bulk modulus given the elastic constants matrix in
|
283
|
+
Voigt ordering.
|
284
|
+
|
285
|
+
Parameters:
|
286
|
+
elastic_constants : float
|
287
|
+
A 6x6 numpy array containing the elastic constants in
|
288
|
+
Voigt ordering. The material can have arbitrary anisotropy.
|
289
|
+
|
290
|
+
Returns:
|
291
|
+
bulk : float
|
292
|
+
The bulk modulus, defined as the ratio between the hydrostatic
|
293
|
+
stress (negative of the pressure p) in hydrostatic loading and
|
294
|
+
the diltation e (trace of the strain tensor), i.e. B = -p/e
|
295
|
+
"""
|
296
|
+
# Compute bulk modulus, based on exercise 6.14 in Tadmor, Miller, Elliott,
|
297
|
+
# Continuum Mechanics and Thermodynamics, Cambridge University Press, 2012.
|
298
|
+
rank_elastic_constants = np.linalg.matrix_rank(elastic_constants)
|
299
|
+
elastic_constants_aug = np.concatenate(
|
300
|
+
(elastic_constants, np.transpose([[1, 1, 1, 0, 0, 0]])), 1
|
301
|
+
)
|
302
|
+
rank_elastic_constants_aug = np.linalg.matrix_rank(elastic_constants_aug)
|
303
|
+
if rank_elastic_constants_aug > rank_elastic_constants:
|
304
|
+
assert rank_elastic_constants_aug == rank_elastic_constants + 1
|
305
|
+
logger.info(
|
306
|
+
"Information: Hydrostatic pressure not in the image of the elasticity "
|
307
|
+
"matrix, zero bulk modulus!"
|
308
|
+
)
|
309
|
+
return 0.0
|
310
|
+
else:
|
311
|
+
# if a solution exists for a stress state of [1,1,1,0,0,0],
|
312
|
+
# you can always use the pseudoinverse
|
313
|
+
compliance = np.linalg.pinv(elastic_constants)
|
314
|
+
bulk = 1 / np.sum(compliance[0:3, 0:3])
|
315
|
+
return bulk
|
316
|
+
|
317
|
+
|
318
|
+
def map_to_Kelvin(C: npt.ArrayLike) -> npt.ArrayLike:
|
319
|
+
"""
|
320
|
+
Compute the Kelvin form of the input 6x6 Voigt matrix
|
321
|
+
"""
|
322
|
+
Ch = C.copy()
|
323
|
+
Ch[0:3, 3:6] *= math.sqrt(2.0)
|
324
|
+
Ch[3:6, 0:3] *= math.sqrt(2.0)
|
325
|
+
Ch[3:6, 3:6] *= 2.0
|
326
|
+
return Ch
|
327
|
+
|
328
|
+
|
329
|
+
def function_of_matrix(A, f):
|
330
|
+
"""Compute the function of a matrix"""
|
331
|
+
ev, R = np.linalg.eigh(A)
|
332
|
+
Dtilde = np.diag([f(e) for e in ev])
|
333
|
+
return np.matmul(np.matmul(R, Dtilde), np.transpose(R))
|
334
|
+
|
335
|
+
|
336
|
+
def find_nearest_isotropy(elastic_constants):
|
337
|
+
"""
|
338
|
+
Compute the distance between the provided matrix of elastic constants
|
339
|
+
in Voigt notation, to the nearest matrix of elastic constants for an
|
340
|
+
isotropic material. Return this distance, and the isotropic bulk and
|
341
|
+
shear modulus.
|
342
|
+
|
343
|
+
Ref: Morin, L; Gilormini, P and Derrien, K,
|
344
|
+
"Generalized Euclidean Distances for Elasticity Tensors",
|
345
|
+
Journal of Elasticity, Vol 138, pp. 221-232 (2020).
|
346
|
+
|
347
|
+
Parameters:
|
348
|
+
elastic_constants : float
|
349
|
+
A 6x6 numpy array containing the elastic constants in
|
350
|
+
Voigt ordering. The material can have arbitrary anisotropy.
|
351
|
+
|
352
|
+
Returns:
|
353
|
+
d : float
|
354
|
+
Distance to the nearest elastic constants.
|
355
|
+
log Euclidean metric.
|
356
|
+
kappa : float
|
357
|
+
Isotropic bulk modulus
|
358
|
+
mu : float
|
359
|
+
Isotropic shear modulus
|
360
|
+
"""
|
361
|
+
E0 = 1.0 # arbitrary scaling constant (result unaffected by it)
|
362
|
+
|
363
|
+
JJ = np.zeros(shape=(6, 6))
|
364
|
+
KK = np.zeros(shape=(6, 6))
|
365
|
+
v = {0: [0, 0], 1: [1, 1], 2: [2, 2], 3: [1, 2], 4: [0, 2], 5: [0, 1]}
|
366
|
+
for ii in range(6):
|
367
|
+
for jj in range(6):
|
368
|
+
# i j k l = v[ii][0] v[ii][1] v[jj][0] v[jj][1]
|
369
|
+
JJ[ii][jj] = (1.0 / 3.0) * (v[ii][0] == v[ii][1]) * (v[jj][0] == v[jj][1])
|
370
|
+
KK[ii][jj] = (1.0 / 2.0) * (
|
371
|
+
(v[ii][0] == v[jj][0]) * (v[ii][1] == v[jj][1])
|
372
|
+
+ (v[ii][0] == v[jj][1]) * (v[ii][1] == v[jj][0])
|
373
|
+
) - JJ[ii][jj]
|
374
|
+
Chat = map_to_Kelvin(elastic_constants)
|
375
|
+
JJhat = map_to_Kelvin(JJ)
|
376
|
+
KKhat = map_to_Kelvin(KK)
|
377
|
+
|
378
|
+
# Eqn (49) in Morin et al.
|
379
|
+
fCoverE0 = function_of_matrix(Chat / E0, math.log)
|
380
|
+
kappa = (E0 / 3.0) * math.exp(np.einsum("ij,ij", fCoverE0, JJhat))
|
381
|
+
mu = (E0 / 2.0) * math.exp(0.2 * np.einsum("ij,ij", fCoverE0, KKhat))
|
382
|
+
|
383
|
+
# Eqn (47) in Morin et al.
|
384
|
+
dmat = (
|
385
|
+
fCoverE0 - math.log(3.0 * kappa / E0) * JJhat - math.log(2.0 * mu / E0) * KKhat
|
386
|
+
)
|
387
|
+
d = math.sqrt(np.einsum("ij,ij", dmat, dmat))
|
388
|
+
|
389
|
+
# Return results
|
390
|
+
return d, kappa, mu
|
kim_tools/test_driver/core.py
CHANGED
@@ -30,6 +30,7 @@
|
|
30
30
|
Helper classes for KIM Test Drivers
|
31
31
|
|
32
32
|
"""
|
33
|
+
import json
|
33
34
|
import logging
|
34
35
|
import os
|
35
36
|
import shutil
|
@@ -65,7 +66,7 @@ from ..aflow_util import (
|
|
65
66
|
get_space_group_number_from_prototype,
|
66
67
|
prototype_labels_are_equivalent,
|
67
68
|
)
|
68
|
-
from ..aflow_util.core import AFLOW_EXECUTABLE
|
69
|
+
from ..aflow_util.core import AFLOW_EXECUTABLE, get_atom_indices_for_each_wyckoff_orb
|
69
70
|
from ..ase import get_isolated_energy_per_atom
|
70
71
|
from ..kimunits import convert_list, convert_units
|
71
72
|
from ..symmetry_util import (
|
@@ -91,6 +92,7 @@ __all__ = [
|
|
91
92
|
"detect_unique_crystal_structures",
|
92
93
|
"get_deduplicated_property_instances",
|
93
94
|
"minimize_wrapper",
|
95
|
+
"crystal_input_from_test_generator_line",
|
94
96
|
]
|
95
97
|
|
96
98
|
# Force tolerance for the optional initial relaxation of the provided cell
|
@@ -139,7 +141,7 @@ def minimize_wrapper(
|
|
139
141
|
logfile: Optional[Union[str, IO]] = "kim-tools.log",
|
140
142
|
algorithm: Optimizer = LBFGSLineSearch,
|
141
143
|
cell_filter: UnitCellFilter = FrechetCellFilter,
|
142
|
-
fix_symmetry: bool = False,
|
144
|
+
fix_symmetry: Union[bool, FixSymmetry] = False,
|
143
145
|
opt_kwargs: Dict = {},
|
144
146
|
flt_kwargs: Dict = {},
|
145
147
|
) -> bool:
|
@@ -179,7 +181,8 @@ def minimize_wrapper(
|
|
179
181
|
CellFilter:
|
180
182
|
Filter to use if variable_cell is requested
|
181
183
|
fix_symmetry:
|
182
|
-
Whether to fix the crystallographic symmetry
|
184
|
+
Whether to fix the crystallographic symmetry. Can provide
|
185
|
+
a FixSymmetry class here instead of detecting it on the fly
|
183
186
|
opt_kwargs:
|
184
187
|
Dictionary of kwargs to pass to optimizer
|
185
188
|
flt_kwargs:
|
@@ -188,8 +191,11 @@ def minimize_wrapper(
|
|
188
191
|
Returns:
|
189
192
|
Whether the minimization succeeded
|
190
193
|
"""
|
191
|
-
if fix_symmetry:
|
192
|
-
|
194
|
+
if fix_symmetry is not False:
|
195
|
+
if fix_symmetry is True:
|
196
|
+
symmetry = FixSymmetry(atoms)
|
197
|
+
else:
|
198
|
+
symmetry = fix_symmetry
|
193
199
|
atoms.set_constraint(symmetry)
|
194
200
|
if variable_cell:
|
195
201
|
supercell_wrapped = cell_filter(atoms, **flt_kwargs)
|
@@ -225,11 +231,18 @@ def minimize_wrapper(
|
|
225
231
|
del atoms.constraints
|
226
232
|
|
227
233
|
if minimization_stalled or iteration_limits_reached:
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
234
|
+
try:
|
235
|
+
logger.info("Final forces:")
|
236
|
+
logger.info(atoms.get_forces())
|
237
|
+
logger.info("Final stress:")
|
238
|
+
logger.info(atoms.get_stress())
|
239
|
+
except Exception as e:
|
240
|
+
logger.info(
|
241
|
+
"The following exception was caught "
|
242
|
+
"trying to evaluate final forces and stress:"
|
243
|
+
)
|
244
|
+
logger.info(repr(e))
|
245
|
+
return False
|
233
246
|
else:
|
234
247
|
return True
|
235
248
|
|
@@ -498,11 +511,15 @@ class KIMTestDriver(ABC):
|
|
498
511
|
requires a KIM model (e.g. a LAMMPS TD) with a non-KIM Calculator
|
499
512
|
"""
|
500
513
|
|
501
|
-
def __init__(
|
514
|
+
def __init__(
|
515
|
+
self, model: Union[str, Calculator], suppr_sm_lmp_log: bool = False
|
516
|
+
) -> None:
|
502
517
|
"""
|
503
518
|
Args:
|
504
519
|
model:
|
505
520
|
ASE calculator or KIM model name to use
|
521
|
+
suppr_sm_lmp_log:
|
522
|
+
Suppress writing a lammps.log
|
506
523
|
"""
|
507
524
|
if isinstance(model, Calculator):
|
508
525
|
self.__calc = model
|
@@ -512,6 +529,9 @@ class KIMTestDriver(ABC):
|
|
512
529
|
|
513
530
|
self.__kim_model_name = model
|
514
531
|
self.__calc = KIM(self.__kim_model_name)
|
532
|
+
if suppr_sm_lmp_log:
|
533
|
+
if hasattr(self.__calc.parameters, "log_file"):
|
534
|
+
self.__calc.parameters.log_file = None
|
515
535
|
|
516
536
|
self.__output_property_instances = "[]"
|
517
537
|
|
@@ -549,6 +569,8 @@ class KIMTestDriver(ABC):
|
|
549
569
|
# count how many instances we had before we started
|
550
570
|
previous_properties_end = len(kim_edn.loads(self.__output_property_instances))
|
551
571
|
|
572
|
+
os.makedirs("output", exist_ok=True)
|
573
|
+
|
552
574
|
# _setup is likely overridden by an derived class
|
553
575
|
self._setup(material, **kwargs)
|
554
576
|
|
@@ -1182,17 +1204,22 @@ class SingleCrystalTestDriver(KIMTestDriver):
|
|
1182
1204
|
"""
|
1183
1205
|
|
1184
1206
|
def __init__(
|
1185
|
-
self,
|
1207
|
+
self,
|
1208
|
+
model: Union[str, Calculator],
|
1209
|
+
suppr_sm_lmp_log: bool = False,
|
1210
|
+
aflow_executable: str = AFLOW_EXECUTABLE,
|
1186
1211
|
) -> None:
|
1187
1212
|
"""
|
1188
1213
|
Args:
|
1189
1214
|
model:
|
1190
1215
|
ASE calculator or KIM model name to use
|
1216
|
+
suppr_sm_lmp_log:
|
1217
|
+
Suppress writing a lammps.log
|
1191
1218
|
aflow_executable:
|
1192
1219
|
Path to AFLOW executable
|
1193
1220
|
"""
|
1194
1221
|
self.aflow_executable = aflow_executable
|
1195
|
-
super().__init__(model)
|
1222
|
+
super().__init__(model, suppr_sm_lmp_log=suppr_sm_lmp_log)
|
1196
1223
|
|
1197
1224
|
def _setup(
|
1198
1225
|
self,
|
@@ -1307,7 +1334,7 @@ class SingleCrystalTestDriver(KIMTestDriver):
|
|
1307
1334
|
)
|
1308
1335
|
print(f"\nNOTE: {msg}\n")
|
1309
1336
|
logger.info(msg)
|
1310
|
-
if cell_cauchy_stress_eV_angstrom3
|
1337
|
+
if cell_cauchy_stress_eV_angstrom3 == [0, 0, 0, 0, 0, 0]:
|
1311
1338
|
stress_max = np.max(atoms_tmp.get_stress())
|
1312
1339
|
if stress_max > FMAX_INITIAL:
|
1313
1340
|
msg = (
|
@@ -1856,6 +1883,22 @@ class SingleCrystalTestDriver(KIMTestDriver):
|
|
1856
1883
|
atoms_tmp.calc = self._calc
|
1857
1884
|
return atoms_tmp
|
1858
1885
|
|
1886
|
+
def get_nominal_prototype_label(self) -> str:
|
1887
|
+
return self._get_nominal_crystal_structure_npt()["prototype-label"][
|
1888
|
+
"source-value"
|
1889
|
+
]
|
1890
|
+
|
1891
|
+
def get_atom_indices_for_each_wyckoff_orb(self) -> List[Dict]:
|
1892
|
+
"""
|
1893
|
+
Get a list of dictionaries containing the atom indices of each Wyckoff
|
1894
|
+
orbit.
|
1895
|
+
|
1896
|
+
Returns:
|
1897
|
+
The information is in this format --
|
1898
|
+
``[{"letter":"a", "indices":[0,1]}, ... ]``
|
1899
|
+
"""
|
1900
|
+
return get_atom_indices_for_each_wyckoff_orb(self.get_nominal_prototype_label())
|
1901
|
+
|
1859
1902
|
|
1860
1903
|
def query_crystal_structures(
|
1861
1904
|
stoichiometric_species: List[str],
|
@@ -1955,7 +1998,7 @@ def query_crystal_structures(
|
|
1955
1998
|
logger.info(len_msg)
|
1956
1999
|
logger.debug(f"Query result (length={len(query_result)}):\n{query_result}")
|
1957
2000
|
|
1958
|
-
print(f"!!! {len_msg}
|
2001
|
+
print(f"\n!!! {len_msg} !!!\n")
|
1959
2002
|
|
1960
2003
|
return query_result
|
1961
2004
|
|
@@ -2210,6 +2253,40 @@ def get_deduplicated_property_instances(
|
|
2210
2253
|
return property_instances_deduplicated
|
2211
2254
|
|
2212
2255
|
|
2213
|
-
|
2214
|
-
|
2215
|
-
|
2256
|
+
def crystal_input_from_test_generator_line(
|
2257
|
+
test_generator_line: str, kim_model_name: str
|
2258
|
+
) -> List[Dict]:
|
2259
|
+
"""
|
2260
|
+
Produce a list of dictionaries of kwargs for a Crystal Genome Test Driver invocation
|
2261
|
+
from a line in its ``test_generator.json``
|
2262
|
+
"""
|
2263
|
+
test_generator_dict = json.loads(test_generator_line)
|
2264
|
+
stoichiometric_species = test_generator_dict["stoichiometric_species"]
|
2265
|
+
prototype_label = test_generator_dict["prototype_label"]
|
2266
|
+
cell_cauchy_stress_eV_angstrom3 = test_generator_dict.get(
|
2267
|
+
"cell_cauchy_stress_eV_angstrom3"
|
2268
|
+
)
|
2269
|
+
temperature_K = test_generator_dict.get("temperature_K")
|
2270
|
+
crystal_genome_test_args = test_generator_dict.get("crystal_genome_test_args")
|
2271
|
+
equilibria = query_crystal_structures(
|
2272
|
+
stoichiometric_species=stoichiometric_species,
|
2273
|
+
prototype_label=prototype_label,
|
2274
|
+
kim_model_name=kim_model_name,
|
2275
|
+
)
|
2276
|
+
inputs = []
|
2277
|
+
for equilibrium in equilibria:
|
2278
|
+
inputs.append(
|
2279
|
+
{
|
2280
|
+
"material": equilibrium,
|
2281
|
+
}
|
2282
|
+
)
|
2283
|
+
if cell_cauchy_stress_eV_angstrom3 is not None:
|
2284
|
+
inputs[-1][
|
2285
|
+
"cell_cauchy_stress_eV_angstrom3"
|
2286
|
+
] = cell_cauchy_stress_eV_angstrom3
|
2287
|
+
if temperature_K is not None:
|
2288
|
+
inputs[-1]["temperature_K"] = temperature_K
|
2289
|
+
if crystal_genome_test_args is not None:
|
2290
|
+
inputs[-1].update(crystal_genome_test_args)
|
2291
|
+
|
2292
|
+
return inputs
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: kim-tools
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.7
|
4
4
|
Summary: Base classes and helper routines for writing KIM Tests
|
5
5
|
Author-email: ilia Nikiforov <nikif002@umn.edu>, Ellad Tadmor <tadmor@umn.edu>, Claire Waters <bwaters@umn.edu>, "Daniel S. Karls" <karl0100umn@gmail.com>, Matt Bierbaum <matt.bierbaum@gmail.com>, Eric Fuemmeler <efuemmel@umn.edu>, Philipp Hoellmer <ph2484@nyu.edu>, Guanming Zhang <gz2241@nyu.edu>, Tom Egg <tje3676@nyu.edu>
|
6
6
|
Maintainer-email: ilia Nikiforov <nikif002@umn.edu>
|
@@ -1,7 +1,7 @@
|
|
1
|
-
kim_tools/__init__.py,sha256=
|
1
|
+
kim_tools/__init__.py,sha256=AZO0kIOJrYHA6ai-MX9cxxAzz4wsN21eGn9cAX7LRoc,433
|
2
2
|
kim_tools/kimunits.py,sha256=jOxBv9gRVhxPE6ygAIUxOzCAfPI6tT6sBaF_FNl9m-M,5387
|
3
3
|
kim_tools/aflow_util/__init__.py,sha256=lJnQ8fZCma80QVRQeKvY4MQ87oCWu-9KATV3dKJfpDc,80
|
4
|
-
kim_tools/aflow_util/core.py,sha256=
|
4
|
+
kim_tools/aflow_util/core.py,sha256=9qlQQwhcFKJ8HwcHdEPgoEKRK_viQAFlZUqCV9nlcE0,80301
|
5
5
|
kim_tools/aflow_util/aflow_prototype_encyclopedia/data/A108B24C11D24_cP334_222_h4i_i_bf_i-001/info.json,sha256=IsFiO9X2Ko7yoq2QkDurUVP7k1BE4WFgblu7oxl6iZs,2013
|
6
6
|
kim_tools/aflow_util/aflow_prototype_encyclopedia/data/A10B11_tI84_139_dehim_eh2n-001/info.json,sha256=f1EdtouuSL2y9NNw40Rvz2J9ZZcsqQBcyEmlHj6XoW8,1186
|
7
7
|
kim_tools/aflow_util/aflow_prototype_encyclopedia/data/A10B2C_hP39_171_5c_c_a-001/info.json,sha256=vD1xjZKWShL0E6XNsSlmIhilGcGNefl56oQDLQlHO1M,1596
|
@@ -2004,7 +2004,18 @@ kim_tools/aflow_util/aflow_prototype_encyclopedia/data/A_tP50_134_a2m2n-001/info
|
|
2004
2004
|
kim_tools/ase/__init__.py,sha256=1i6ko5tNr0VZC3T7hoEzq4fnSU0DdxNpxXcSaWMcJWc,76
|
2005
2005
|
kim_tools/ase/core.py,sha256=odRuHQGZl-pcRtkdYvG31_3kW6nt3qwHdKvAOJ-ifwM,31207
|
2006
2006
|
kim_tools/symmetry_util/__init__.py,sha256=uu-ZSUDUTe2P81rkAS3tXverx31s_uZ3wL4SD_dn5aI,86
|
2007
|
-
kim_tools/symmetry_util/core.py,sha256=
|
2007
|
+
kim_tools/symmetry_util/core.py,sha256=eMGgVt9MPcaLi_8jVMJ5UyQHvYbiiAFQ4HdJotnp8dk,43277
|
2008
|
+
kim_tools/symmetry_util/elasticity.py,sha256=VxJ8wUcsSOPyJ8id6OpKmVlRAbIUIWxtzYJtkvVJIVs,13328
|
2009
|
+
kim_tools/symmetry_util/data/elast_cubic.svg,sha256=UpN4XcoLoOwv8a7KE0WyINkSH5AU2DPVZ08eGQf-Cds,8953
|
2010
|
+
kim_tools/symmetry_util/data/elast_hexagonal.svg,sha256=wOkw5IO3fZy039tLHhvtwrkatVYs5XzigUormLKtRlw,8705
|
2011
|
+
kim_tools/symmetry_util/data/elast_monoclinic.svg,sha256=71zWo1ClStyVbM8KHLU-bEU1m7itJScFnsqIY7tHTuw,10555
|
2012
|
+
kim_tools/symmetry_util/data/elast_orthorhombic.svg,sha256=J-1rLi0JpBpHo0sD6gQcdO7CPZaYbuA6DUY6hMRqEcE,8197
|
2013
|
+
kim_tools/symmetry_util/data/elast_tetragonal_4_slash_m.svg,sha256=sBdXu0e0uqnglAyBJNoA-B7bllfp7_c9MiT7aCPNh0I,10321
|
2014
|
+
kim_tools/symmetry_util/data/elast_tetragonal_4_slash_mmm.svg,sha256=1oXCrWYqVhQetgcCNoGp-ypDgCyyugZ2023Evk417vI,8902
|
2015
|
+
kim_tools/symmetry_util/data/elast_triclinic.svg,sha256=9LGE6FLvYJ-4-M3c1BciasVkEu4eXo9jjeggJ8FJSIo,15269
|
2016
|
+
kim_tools/symmetry_util/data/elast_trigonal_3bar.svg,sha256=3gVsl_bRryw6hJRG7H_UTRDCWprcDhKfMXr7uQ5LDV4,12771
|
2017
|
+
kim_tools/symmetry_util/data/elast_trigonal_3bar_m_2nd_pos.svg,sha256=2kzOIKZPbQbGMwDzmlBs5pMg9EfrNZ7EV4ihnTiExz0,10738
|
2018
|
+
kim_tools/symmetry_util/data/elast_trigonal_3bar_m_3rd_pos.svg,sha256=pN8ov9-AQ2jYGoMZj5BrhLlYW2G-O6d5woz93H4K5Hc,10738
|
2008
2019
|
kim_tools/symmetry_util/data/possible_primitive_shifts.json,sha256=4OVNgn3NnykgGlYiAcecERmVWiIZFrmP2LZI3ml_Sh0,25010
|
2009
2020
|
kim_tools/symmetry_util/data/primitive_GENPOS_ops.json,sha256=FDu4H4PosOpK9yKwOPy3SxbH7xLMOmZfKZ4ItKPMjoQ,224498
|
2010
2021
|
kim_tools/symmetry_util/data/space_groups_for_each_bravais_lattice.json,sha256=wSNu6d5pH72lJ6Zj5MZ64qzwS_6Fn5WOs0ts7E9uPC4,2507
|
@@ -2012,11 +2023,11 @@ kim_tools/symmetry_util/data/wyck_pos_xform_under_normalizer.json,sha256=6g1YuYh
|
|
2012
2023
|
kim_tools/symmetry_util/data/wyckoff_multiplicities.json,sha256=qG2RPBd_-ejDIfz-E4ZhkHyRpIboxRy7oiXkdDf5Eg8,32270
|
2013
2024
|
kim_tools/symmetry_util/data/wyckoff_sets.json,sha256=f5ZpHKDHo6_JWki1b7KUGoYLlhU-44Qikw_-PtbLssw,9248
|
2014
2025
|
kim_tools/test_driver/__init__.py,sha256=KOiceeZNqkfrgZ66CiRiUdniceDrCmmDXQkOw0wXaCQ,92
|
2015
|
-
kim_tools/test_driver/core.py,sha256=
|
2026
|
+
kim_tools/test_driver/core.py,sha256=sSdDBr99Y4NvKV_BKvz-T8Sp1p_pzk2teZoHv0IjpSo,93309
|
2016
2027
|
kim_tools/vc/__init__.py,sha256=zXjhxXCKVMLBMXXWYG3if7VOpBnsFrn_RjVpnohDm5c,74
|
2017
2028
|
kim_tools/vc/core.py,sha256=BIjzEExnQAL2S90a_npptRm3ACqAo4fZBtvTDBMWMdw,13963
|
2018
|
-
kim_tools-0.3.
|
2019
|
-
kim_tools-0.3.
|
2020
|
-
kim_tools-0.3.
|
2021
|
-
kim_tools-0.3.
|
2022
|
-
kim_tools-0.3.
|
2029
|
+
kim_tools-0.3.7.dist-info/licenses/LICENSE.CDDL,sha256=I2luEED_SHjuZ01B4rYG-AF_135amL24JpHvZ1Jhqe8,16373
|
2030
|
+
kim_tools-0.3.7.dist-info/METADATA,sha256=xewZHVokzllXvhRCAbMMQ7JO5RNe8R2sB0VXEV7QyBM,2032
|
2031
|
+
kim_tools-0.3.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
2032
|
+
kim_tools-0.3.7.dist-info/top_level.txt,sha256=w_YCpJ5ERigj9te74ln7k64tqj1VumOzM_s9dsalIWY,10
|
2033
|
+
kim_tools-0.3.7.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|