kim-tools 0.2.0b0__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.
@@ -0,0 +1,4 @@
1
+ from .core import *
2
+ from .core import __all__ as vc_all
3
+
4
+ __all__ = vc_all
kim_tools/vc/core.py ADDED
@@ -0,0 +1,397 @@
1
+ ################################################################################
2
+ #
3
+ # CDDL HEADER START
4
+ #
5
+ # The contents of this file are subject to the terms of the Common Development
6
+ # and Distribution License Version 1.0 (the "License").
7
+ #
8
+ # You can obtain a copy of the license at
9
+ # http:# www.opensource.org/licenses/CDDL-1.0. See the License for the
10
+ # specific language governing permissions and limitations under the License.
11
+ #
12
+ # When distributing Covered Code, include this CDDL HEADER in each file and
13
+ # include the License file in a prominent location with the name LICENSE.CDDL.
14
+ # If applicable, add the following below this CDDL HEADER, with the fields
15
+ # enclosed by brackets "[]" replaced with your own identifying information:
16
+ #
17
+ # Portions Copyright (c) [yyyy] [name of copyright owner]. All rights reserved.
18
+ #
19
+ # CDDL HEADER END
20
+ #
21
+ # Copyright (c) 2017-2019, Regents of the University of Minnesota.
22
+ # All rights reserved.
23
+ #
24
+ # Contributor(s):
25
+ # Ellad B. Tadmor
26
+ #
27
+ ################################################################################
28
+ """
29
+ Helper routines for KIM Verification Checks
30
+
31
+ """
32
+
33
+ import math
34
+ import os
35
+ import sys
36
+ import textwrap
37
+ import time
38
+
39
+ import jinja2
40
+ import numpy as np
41
+ from ase import Atoms
42
+
43
+ __all__ = [
44
+ "KIMVCError",
45
+ "VerificationCheck",
46
+ "setup_and_run_vc",
47
+ "vc_stripall",
48
+ "vc_letter_grade_machine_precision",
49
+ ]
50
+
51
+
52
+ ################################################################################
53
+ class KIMVCError(Exception):
54
+ def __init__(self, msg):
55
+ # Call the base class constructor with the parameters it needs
56
+ super(KIMVCError, self).__init__(msg)
57
+ self.msg = msg
58
+
59
+ def __str__(self):
60
+ return self.msg
61
+
62
+
63
+ ################################################################################
64
+ def vc_stripall(string):
65
+ """
66
+ In "string", remove leading and trailing newlines, replace internal newlines
67
+ with spaces, and remove carriage returns.
68
+
69
+ Primary purpose is to process docstring at top of VC code and convert to
70
+ vc_description.
71
+ """
72
+ return string.strip().replace("\n", " ").replace("\r", "")
73
+
74
+
75
+ ################################################################################
76
+ def vc_letter_grade_machine_precision(error, Amax=7.5, Bmax=10.0, Cmax=12.5, Dmax=15.0):
77
+ """
78
+ This function assigns a letter grade in the range A-D and F for fail
79
+ based on the obtained 'error' as compared with the machine precision
80
+ of the computation.
81
+ """
82
+ if not Amax < Bmax < Cmax < Dmax:
83
+ raise KIMVCError("ERROR: This condition not satisfied: Amax<Bmax<Cmax<Dmax")
84
+ eps = np.finfo(float).eps
85
+ if abs(error) < eps:
86
+ letter_grade = "A"
87
+ else:
88
+ score = math.log10(abs(error) / eps)
89
+ if score <= Amax:
90
+ letter_grade = "A"
91
+ elif score <= Bmax:
92
+ letter_grade = "B"
93
+ elif score <= Cmax:
94
+ letter_grade = "C"
95
+ elif score <= Dmax:
96
+ letter_grade = "D"
97
+ else:
98
+ letter_grade = "F"
99
+ # Return with assigned letter grade
100
+ comment = (
101
+ "The letter grade {0:} was assigned because the normalized error in the "
102
+ "computation was {1:.5e} compared with a machine precision of {2:.5e}. The "
103
+ "letter grade was based on 'score=log10(error/eps)', with ranges "
104
+ "A=[0, {3:.1f}], B=({3:.1f}, {4:.1f}], C=({4:.1f}, {5:.1f}], D=({5:.1f}, "
105
+ "{6:.1f}), F>{6:.1f}. 'A' is the best grade, and 'F' indicates failure."
106
+ ).format(letter_grade, error, eps, Amax, Bmax, Cmax, Dmax)
107
+ return letter_grade, comment
108
+
109
+
110
+ ################################################################################
111
+ def setup_and_run_vc(
112
+ do_vc,
113
+ model,
114
+ vc_name,
115
+ vc_author,
116
+ vc_description,
117
+ vc_category,
118
+ vc_grade_basis,
119
+ vc_files,
120
+ vc_debug,
121
+ ):
122
+ """
123
+ Construct VerificationCheck object containing all info related to VC,
124
+ and perform the VC by calling the user supplied `do_vc` function. The VC
125
+ report and property instance re generated. If `vc_debug` is True, errors
126
+ generate exceptions will full traceback, otherwise exceptions are trapped
127
+ and an error message is reported.
128
+ """
129
+
130
+ # Define VC object and do verification check
131
+ vc = VerificationCheck(
132
+ vc_name,
133
+ vc_author,
134
+ vc_description,
135
+ vc_category,
136
+ vc_grade_basis,
137
+ vc_files,
138
+ vc_debug,
139
+ )
140
+ try:
141
+ with vc:
142
+ # Perform verification check and get grade
143
+ try:
144
+ vc_grade, vc_comment = do_vc(model, vc)
145
+ vc.rwrite("Grade: {}".format(vc_grade))
146
+ vc.rwrite("")
147
+ vc.rwrite("Comment: " + vc_comment)
148
+ vc.rwrite("")
149
+ except BaseException as e:
150
+ vc_grade = "N/A"
151
+ vc_comment = "Unable to perform verification check due to an error."
152
+ if vc_debug:
153
+ raise
154
+ else:
155
+ vc.rwrite(
156
+ "\nERROR: Unable to perform verification check.\n\n Message = "
157
+ + str(e)
158
+ )
159
+ finally:
160
+ # Pack results in a dictionary and write VC property instance
161
+ results = {
162
+ "vc_name": vc_name,
163
+ "vc_description": vc_description,
164
+ "vc_category": vc_category,
165
+ "vc_grade_basis": vc_grade_basis,
166
+ "vc_grade": vc_grade,
167
+ "vc_comment": vc_comment,
168
+ "vc_files": vc_files,
169
+ }
170
+ vc.write_results(results)
171
+ except Exception as e:
172
+ if vc_debug:
173
+ raise
174
+ else:
175
+ sys.stderr.write(
176
+ "\nERROR: Unable to initalize verification check.\n\n Message = "
177
+ + str(e)
178
+ )
179
+
180
+
181
+ ################################################################################
182
+ class VerificationCheck(object):
183
+ """
184
+ Features routines related to outputting VC information and results.
185
+ """
186
+
187
+ ############################################################################
188
+ def rwrite(self, string):
189
+ """
190
+ Write 'string' with appended newline to report and echo to stdout
191
+ """
192
+ if not self.report_ready:
193
+ raise KIMVCError(
194
+ "ERROR: Trying to write out string to "
195
+ "report file that is not ready.\n\n"
196
+ ' string = "{}"\n'.format(string)
197
+ )
198
+
199
+ self.report.write(string + "\n")
200
+ sys.stdout.write(string + "\n")
201
+
202
+ ############################################################################
203
+ def __init__(
204
+ self,
205
+ vc_name,
206
+ vc_author,
207
+ vc_description,
208
+ vc_category,
209
+ vc_grade_basis,
210
+ vc_files,
211
+ vc_debug,
212
+ ):
213
+ """
214
+ Initialize a VC object.
215
+ """
216
+ # Initialize object variables
217
+ self.output_ready = False # Output directory not setup
218
+ self.report_ready = False # Report file not open for writing
219
+ self.vc_name = vc_name
220
+ self.vc_description = vc_description
221
+ self.vc_author = vc_author
222
+ self.vc_category = vc_category
223
+ self.vc_grade_basis = vc_grade_basis
224
+ self.vc_files = vc_files
225
+ self.vc_debug = vc_debug
226
+
227
+ ############################################################################
228
+ def __enter__(self):
229
+ """
230
+ Beginning with block:
231
+ Send message to stdout, open report file, print header,
232
+ and return report file object.
233
+ """
234
+ # Send message to stdout that VC calculation is starting
235
+ print()
236
+ print(
237
+ "=== Verification check {} start ({}) ==="
238
+ "".format(self.vc_name, time.strftime("%Y-%m-%d %H:%M:%S"))
239
+ )
240
+ # Create directory 'output' if it does not already exist:
241
+ try:
242
+ if not os.path.exists("output"):
243
+ os.makedirs("output")
244
+ self.output_ready = True
245
+ except (OSError, IOError):
246
+ raise KIMVCError("ERROR: Unable to create directory 'output'.\n")
247
+ # Open report file and write header
248
+ try:
249
+ self.report = open(
250
+ os.path.abspath(os.path.join("output", "report.txt")),
251
+ "w",
252
+ encoding="utf-8",
253
+ )
254
+ self.report_ready = True
255
+ except (OSError, IOError):
256
+ raise KIMVCError(
257
+ "ERROR: Unable to open verification check report file for writing.\n"
258
+ )
259
+ # Output header to report file
260
+ padside = 5
261
+ c = "!"
262
+ content_line = "VERIFICATION CHECK: " + self.vc_name
263
+ content_width = len(content_line)
264
+ content_line += " " * (content_width - len(content_line))
265
+ width = 2 * padside + 4 + content_width
266
+ self.rwrite(c * width)
267
+ self.rwrite(c * width)
268
+ self.rwrite(c * padside + " " * (content_width + 4) + c * padside)
269
+ self.rwrite(c * padside + " " + content_line + " " + c * padside)
270
+ self.rwrite(c * padside + " " * (content_width + 4) + c * padside)
271
+ self.rwrite(c * width)
272
+ self.rwrite(c * width)
273
+ self.rwrite("")
274
+ prefix = "Description: "
275
+ preferredWidth = 80
276
+ wrapper = textwrap.TextWrapper(
277
+ initial_indent=prefix,
278
+ width=preferredWidth,
279
+ subsequent_indent=" " * len(prefix),
280
+ )
281
+ self.rwrite(wrapper.fill(self.vc_description))
282
+ self.rwrite("")
283
+ self.rwrite("Author: {}".format(self.vc_author))
284
+
285
+ ############################################################################
286
+ def __exit__(self, exc_type, exc_val, exc_tb):
287
+ """
288
+ Leaving with block:
289
+ Finishing VC calculation. Send message to stdout, and close report file.
290
+ """
291
+ # Send message to stdout that VC calculation is starting
292
+ print()
293
+ print(
294
+ "=== Verification check {} end ({}) ==="
295
+ "".format(self.vc_name, time.strftime("%Y-%m-%d %H:%M:%S"))
296
+ )
297
+ # Close report file
298
+ self.report.close()
299
+
300
+ ############################################################################
301
+ def write_results(self, results):
302
+ """
303
+ Use jinja2 to Process the template file 'results.edn.tpl' (expected
304
+ in the current working directory) to replace the keys in 'results'.
305
+ Place the new 'results.edn' file in a directory called 'output',
306
+ creating it if it does not already exist.
307
+ """
308
+ if not self.report_ready:
309
+ raise KIMVCError(
310
+ "ERROR: Trying to write out results.edn "
311
+ "but directory 'output' is not ready.\n"
312
+ )
313
+
314
+ # Turn lists into strings with double quotes to to be compatible with
315
+ # EDN format
316
+ for key in results:
317
+ if isinstance(results[key], list):
318
+ results[key] = str(results[key]).replace("'", '"')
319
+
320
+ template_environment = jinja2.Environment(
321
+ loader=jinja2.FileSystemLoader("/"),
322
+ block_start_string="@[",
323
+ block_end_string="]@",
324
+ variable_start_string="@<",
325
+ variable_end_string=">@",
326
+ comment_start_string="@#",
327
+ comment_end_string="#@",
328
+ undefined=jinja2.StrictUndefined,
329
+ )
330
+ # Template the EDN output
331
+ with open(
332
+ os.path.abspath(os.path.join("output", "results.edn")),
333
+ "w",
334
+ encoding="utf-8",
335
+ ) as f:
336
+ template = template_environment.get_template(
337
+ os.path.abspath("results.edn.tpl")
338
+ )
339
+ f.write(template.render(**results))
340
+
341
+ ############################################################################
342
+ def write_aux_ase_atoms(self, aux_file, atoms, format):
343
+ """
344
+ Write the configuration in the ASE 'atoms' object to an auxiliary
345
+ file 'aux_file' in the output directory in the specified 'format'.
346
+ For supported formats, see https://wiki.fysik.dtu.dk/ase/ase/io/io.html
347
+ """
348
+ if not self.report_ready:
349
+ raise KIMVCError(
350
+ "ERROR: Trying to write out ASE Atoms "
351
+ "aux file but directory 'output' is not ready.\n"
352
+ )
353
+
354
+ Atoms.write(atoms, os.path.join("output", aux_file), format=format)
355
+
356
+ ############################################################################
357
+ def write_aux_x_y(self, aux_file, x, y):
358
+ """
359
+ Write a file containing the lists x and y:
360
+ x[0] y[0]
361
+ x[1] y[1]
362
+ ...
363
+ If the lists are not the same length, the shorter sets the size.
364
+ """
365
+ if not self.report_ready:
366
+ raise KIMVCError(
367
+ "ERROR: Trying to write out x-y data "
368
+ "aux file but directory 'output' is not ready.\n"
369
+ )
370
+
371
+ with open(
372
+ os.path.abspath(os.path.join("output", aux_file)), "w", encoding="utf-8"
373
+ ) as f:
374
+ for i in range(0, min(len(x), len(y))):
375
+ f.write("{0: 11.8e} {1: 11.8e}\n".format(x[i], y[i]))
376
+
377
+ ############################################################################
378
+ def write_aux_string(self, aux_file, string):
379
+ """
380
+ Write a file containing the contents in 'string'
381
+ """
382
+ if not self.report_ready:
383
+ raise KIMVCError(
384
+ "ERROR: Trying to write out string to "
385
+ "aux file but directory 'output' is not ready.\n"
386
+ )
387
+
388
+ with open(
389
+ os.path.abspath(os.path.join("output", aux_file)), "w", encoding="utf-8"
390
+ ) as f:
391
+ f.write("{}\n".format(string))
392
+
393
+
394
+ ################################################################################
395
+ # If called directly, do nothing
396
+ if __name__ == "__main__":
397
+ pass
@@ -0,0 +1,32 @@
1
+ Metadata-Version: 2.4
2
+ Name: kim-tools
3
+ Version: 0.2.0b0
4
+ Summary: Base classes and helper routines for writing KIM Tests
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>
6
+ Maintainer-email: ilia Nikiforov <nikif002@umn.edu>
7
+ Project-URL: Homepage, https://kim-tools.readthedocs.io
8
+ Project-URL: Issues, https://github.com/openkim/kim-tools/issues
9
+ Keywords: kim-tools,kim_tools,openkim,crystal genome
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: License :: OSI Approved :: Common Development and Distribution License 1.0 (CDDL-1.0)
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Topic :: Scientific/Engineering :: Physics
15
+ Requires-Python: >=3.8
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE.CDDL
18
+ Requires-Dist: ase>=3.23
19
+ Requires-Dist: kim-property>=2.6.8
20
+ Requires-Dist: kim-edn>=1.4.1
21
+ Requires-Dist: spglib>=2.1.0
22
+ Requires-Dist: kim-query>=3.0.0
23
+ Requires-Dist: sympy>=1.13.2
24
+ Requires-Dist: numpy>=1.13.1
25
+ Requires-Dist: scipy>=1.3.0
26
+ Requires-Dist: jinja2>=2.7.2
27
+ Dynamic: license-file
28
+
29
+ # kim-tools
30
+
31
+ KIMTestDriver and SingleCrystalTestDriver classes for creating OpenKIM Test Drivers, and helper routines for writing
32
+ KIM Tests and Verification Checks. Documentation at https://kim-tools.readthedocs.io.
@@ -0,0 +1,24 @@
1
+ kim_tools/__init__.py,sha256=_IDKtgO7O3TeqoIhOaAUUqV2IEv5Suk3PPsYokbtI7Q,435
2
+ kim_tools/kimunits.py,sha256=kR5VMTurQnbPOHcWF1XN-mjY9FXRAdWI8hA-RZHhrek,5036
3
+ kim_tools/aflow_util/__init__.py,sha256=lJnQ8fZCma80QVRQeKvY4MQ87oCWu-9KATV3dKJfpDc,80
4
+ kim_tools/aflow_util/core.py,sha256=Xqjh2Xwf4-e-98FMJ8RfRXsTdx2NeWeZXwrPP0xkvwM,71847
5
+ kim_tools/aflow_util/data/README_PROTO.TXT,sha256=bTpcd8GHOkpcQn6YUZzqKhiTytwSDpkgu4boeoogT38,447851
6
+ kim_tools/ase/__init__.py,sha256=1i6ko5tNr0VZC3T7hoEzq4fnSU0DdxNpxXcSaWMcJWc,76
7
+ kim_tools/ase/core.py,sha256=d6eOu_HSxVr-ae0TSEbY4HKdePxhNu3yv8NN9VDl-BA,30256
8
+ kim_tools/symmetry_util/__init__.py,sha256=uu-ZSUDUTe2P81rkAS3tXverx31s_uZ3wL4SD_dn5aI,86
9
+ kim_tools/symmetry_util/core.py,sha256=eQV6gBVlLzGz3LvbRhD1H64uOooyRWTFxU346jSUbE4,20083
10
+ kim_tools/symmetry_util/data/possible_primitive_shifts.json,sha256=4OVNgn3NnykgGlYiAcecERmVWiIZFrmP2LZI3ml_Sh0,25010
11
+ kim_tools/symmetry_util/data/primitive_GENPOS_ops.json,sha256=FDu4H4PosOpK9yKwOPy3SxbH7xLMOmZfKZ4ItKPMjoQ,224498
12
+ kim_tools/symmetry_util/data/space_groups_for_each_bravais_lattice.json,sha256=wSNu6d5pH72lJ6Zj5MZ64qzwS_6Fn5WOs0ts7E9uPC4,2507
13
+ kim_tools/symmetry_util/data/wyck_pos_xform_under_normalizer.json,sha256=6g1YuYhnZwCq4n9Y0r4D7FfmI9cb5m_n5REk7FUlukQ,61980
14
+ kim_tools/symmetry_util/data/wyckoff_multiplicities.json,sha256=qG2RPBd_-ejDIfz-E4ZhkHyRpIboxRy7oiXkdDf5Eg8,32270
15
+ kim_tools/symmetry_util/data/wyckoff_sets.json,sha256=f5ZpHKDHo6_JWki1b7KUGoYLlhU-44Qikw_-PtbLssw,9248
16
+ kim_tools/test_driver/__init__.py,sha256=KOiceeZNqkfrgZ66CiRiUdniceDrCmmDXQkOw0wXaCQ,92
17
+ kim_tools/test_driver/core.py,sha256=YFLwqV6bBAxRzoinAB3cH86z90fQqENwhMcjyzrJxPM,78225
18
+ kim_tools/vc/__init__.py,sha256=zXjhxXCKVMLBMXXWYG3if7VOpBnsFrn_RjVpnohDm5c,74
19
+ kim_tools/vc/core.py,sha256=BIjzEExnQAL2S90a_npptRm3ACqAo4fZBtvTDBMWMdw,13963
20
+ kim_tools-0.2.0b0.dist-info/licenses/LICENSE.CDDL,sha256=I2luEED_SHjuZ01B4rYG-AF_135amL24JpHvZ1Jhqe8,16373
21
+ kim_tools-0.2.0b0.dist-info/METADATA,sha256=feOdrstYpWjnu0VzAeNU0_zTWgsSM7yBZfs0RkD7fbA,1462
22
+ kim_tools-0.2.0b0.dist-info/WHEEL,sha256=ck4Vq1_RXyvS4Jt6SI0Vz6fyVs4GWg7AINwpsaGEgPE,91
23
+ kim_tools-0.2.0b0.dist-info/top_level.txt,sha256=w_YCpJ5ERigj9te74ln7k64tqj1VumOzM_s9dsalIWY,10
24
+ kim_tools-0.2.0b0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+