kim-tools 0.3.5__py3-none-any.whl → 0.3.6__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 +26 -3
- kim_tools/symmetry_util/core.py +90 -0
- kim_tools/test_driver/core.py +40 -17
- {kim_tools-0.3.5.dist-info → kim_tools-0.3.6.dist-info}/METADATA +1 -1
- {kim_tools-0.3.5.dist-info → kim_tools-0.3.6.dist-info}/RECORD +9 -9
- {kim_tools-0.3.5.dist-info → kim_tools-0.3.6.dist-info}/WHEEL +0 -0
- {kim_tools-0.3.5.dist-info → kim_tools-0.3.6.dist-info}/licenses/LICENSE.CDDL +0 -0
- {kim_tools-0.3.5.dist-info → kim_tools-0.3.6.dist-info}/top_level.txt +0 -0
kim_tools/__init__.py
CHANGED
kim_tools/aflow_util/core.py
CHANGED
@@ -392,6 +392,30 @@ def get_wyckoff_lists_from_prototype(prototype_label: str) -> List[str]:
|
|
392
392
|
return expanded_wyckoff_letters
|
393
393
|
|
394
394
|
|
395
|
+
def get_atom_indices_for_each_wyckoff_orb(prototype_label: str) -> List[Dict]:
|
396
|
+
"""
|
397
|
+
Get a list of dictionaries containing the atom indices of each Wyckoff
|
398
|
+
orbit.
|
399
|
+
|
400
|
+
Returns:
|
401
|
+
The information is in this format:
|
402
|
+
|
403
|
+
[{"letter":"a", "indices":[0,1]}, ... ]
|
404
|
+
"""
|
405
|
+
return_list = []
|
406
|
+
wyck_lists = get_wyckoff_lists_from_prototype(prototype_label)
|
407
|
+
sgnum = get_space_group_number_from_prototype(prototype_label)
|
408
|
+
range_start = 0
|
409
|
+
for letter in "".join(wyck_lists):
|
410
|
+
multiplicity = get_primitive_wyckoff_multiplicity(sgnum, letter)
|
411
|
+
range_end = range_start + multiplicity
|
412
|
+
return_list.append(
|
413
|
+
{"letter": letter, "indices": list(range(range_start, range_end))}
|
414
|
+
)
|
415
|
+
range_start = range_end
|
416
|
+
return return_list
|
417
|
+
|
418
|
+
|
395
419
|
def prototype_labels_are_equivalent(
|
396
420
|
prototype_label_1: str,
|
397
421
|
prototype_label_2: str,
|
@@ -841,9 +865,8 @@ class AFLOW:
|
|
841
865
|
"that the AFLOW executable was not found."
|
842
866
|
)
|
843
867
|
# I am fine with allowing prereleases
|
844
|
-
|
845
|
-
|
846
|
-
if aflow_ver_no_prerelease < Version.parse(REQUIRED_AFLOW):
|
868
|
+
aflow_ver = Version.parse(ver_str)
|
869
|
+
if aflow_ver.replace(prerelease=None) < Version.parse(REQUIRED_AFLOW):
|
847
870
|
raise self.AFLOWNotFoundException(
|
848
871
|
f"Your AFLOW version {ver_str} is less "
|
849
872
|
f"than the required {REQUIRED_AFLOW}"
|
kim_tools/symmetry_util/core.py
CHANGED
@@ -14,6 +14,7 @@ import numpy as np
|
|
14
14
|
import numpy.typing as npt
|
15
15
|
from ase import Atoms
|
16
16
|
from ase.cell import Cell
|
17
|
+
from ase.constraints import FixSymmetry
|
17
18
|
from ase.geometry import get_distances, get_duplicate_atoms
|
18
19
|
from matplotlib.backends.backend_pdf import PdfPages
|
19
20
|
from pymatgen.core.operations import SymmOp
|
@@ -617,6 +618,20 @@ def get_primitive_genpos_ops(sgnum: Union[int, str]) -> List[Dict]:
|
|
617
618
|
return np.asarray(json.load(f)[str(sgnum)])
|
618
619
|
|
619
620
|
|
621
|
+
def transform_atoms(atoms: Atoms, op: Dict) -> Atoms:
|
622
|
+
"""
|
623
|
+
Transform atoms by an operation defined by a dictionary containing a matrix 'W' and
|
624
|
+
translation 'w' defined as fractional operations in the unit cell. 'W' should be
|
625
|
+
oriented to operate on column vectors
|
626
|
+
"""
|
627
|
+
frac_pos_columns = atoms.get_scaled_positions().T
|
628
|
+
frac_pos_cols_xform = op["W"] @ frac_pos_columns + np.reshape(op["w"], (3, 1))
|
629
|
+
atoms_transformed = atoms.copy()
|
630
|
+
atoms_transformed.set_scaled_positions(frac_pos_cols_xform.T)
|
631
|
+
atoms_transformed.wrap()
|
632
|
+
return atoms_transformed
|
633
|
+
|
634
|
+
|
620
635
|
def reduce_and_avg(
|
621
636
|
atoms: Atoms, repeat: Tuple[int, int, int]
|
622
637
|
) -> Tuple[Atoms, npt.ArrayLike]:
|
@@ -832,3 +847,78 @@ def fit_voigt_tensor_to_cell_and_space_group(
|
|
832
847
|
t_symmetrized = sum(t_rotated_list) / len(t_rotated_list)
|
833
848
|
|
834
849
|
return t_symmetrized.voigt
|
850
|
+
|
851
|
+
|
852
|
+
class FixProvidedSymmetry(FixSymmetry):
|
853
|
+
"""
|
854
|
+
A modification of :obj:`~ase.constraints.FixSymmetry` that takes
|
855
|
+
a prescribed symmetry instead of analyzing the atoms object on the fly
|
856
|
+
"""
|
857
|
+
|
858
|
+
def __init__(
|
859
|
+
self,
|
860
|
+
atoms: Atoms,
|
861
|
+
symmetry: Union[str, int, List[Dict]],
|
862
|
+
adjust_positions=True,
|
863
|
+
adjust_cell=True,
|
864
|
+
):
|
865
|
+
"""
|
866
|
+
Args:
|
867
|
+
symmetry:
|
868
|
+
Either the space group number, or a list of operations
|
869
|
+
as dictionaries with keys "W": (fractional rotation matrix),
|
870
|
+
"w": (fractional translation). The space group number input
|
871
|
+
will not work correctly unless this contraint is applied to
|
872
|
+
a primitive unit cell as defined in
|
873
|
+
http://doi.org/10.1016/j.commatsci.2017.01.017
|
874
|
+
"""
|
875
|
+
self.atoms = atoms.copy()
|
876
|
+
self.symmetry = symmetry
|
877
|
+
|
878
|
+
if isinstance(symmetry, str) or isinstance(symmetry, int):
|
879
|
+
primitive_genpos_ops = get_primitive_genpos_ops(symmetry)
|
880
|
+
else:
|
881
|
+
try:
|
882
|
+
for op in symmetry:
|
883
|
+
assert np.asarray(op["W"]).shape == (3, 3)
|
884
|
+
assert np.asarray(op["w"]).shape == (3,)
|
885
|
+
primitive_genpos_ops = symmetry
|
886
|
+
except Exception:
|
887
|
+
raise RuntimeError("Incorrect input provided to FixProvidedSymmetry")
|
888
|
+
|
889
|
+
self.rotations = []
|
890
|
+
self.translations = []
|
891
|
+
for op in primitive_genpos_ops:
|
892
|
+
self.rotations.append(np.asarray(op["W"]))
|
893
|
+
self.translations.append(np.asarray(op["w"]))
|
894
|
+
self.prep_symm_map()
|
895
|
+
|
896
|
+
self.do_adjust_positions = adjust_positions
|
897
|
+
self.do_adjust_cell = adjust_cell
|
898
|
+
|
899
|
+
def prep_symm_map(self) -> None:
|
900
|
+
"""
|
901
|
+
Prepare self.symm_map using provided symmetries
|
902
|
+
"""
|
903
|
+
self.symm_map = []
|
904
|
+
scaled_pos = self.atoms.get_scaled_positions()
|
905
|
+
for rot, trans in zip(self.rotations, self.translations):
|
906
|
+
this_op_map = [-1] * len(self.atoms)
|
907
|
+
for i_at in range(len(self.atoms)):
|
908
|
+
new_p = rot @ scaled_pos[i_at, :] + trans
|
909
|
+
dp = scaled_pos - new_p
|
910
|
+
dp -= np.round(dp)
|
911
|
+
i_at_map = np.argmin(np.linalg.norm(dp, axis=1))
|
912
|
+
this_op_map[i_at] = i_at_map
|
913
|
+
self.symm_map.append(this_op_map)
|
914
|
+
|
915
|
+
def todict(self):
|
916
|
+
return {
|
917
|
+
"name": "FixProvidedSymmetry",
|
918
|
+
"kwargs": {
|
919
|
+
"atoms": self.atoms,
|
920
|
+
"symmetry": self.symmetry,
|
921
|
+
"adjust_positions": self.do_adjust_positions,
|
922
|
+
"adjust_cell": self.do_adjust_cell,
|
923
|
+
},
|
924
|
+
}
|
kim_tools/test_driver/core.py
CHANGED
@@ -65,7 +65,7 @@ from ..aflow_util import (
|
|
65
65
|
get_space_group_number_from_prototype,
|
66
66
|
prototype_labels_are_equivalent,
|
67
67
|
)
|
68
|
-
from ..aflow_util.core import AFLOW_EXECUTABLE
|
68
|
+
from ..aflow_util.core import AFLOW_EXECUTABLE, get_atom_indices_for_each_wyckoff_orb
|
69
69
|
from ..ase import get_isolated_energy_per_atom
|
70
70
|
from ..kimunits import convert_list, convert_units
|
71
71
|
from ..symmetry_util import (
|
@@ -139,7 +139,7 @@ def minimize_wrapper(
|
|
139
139
|
logfile: Optional[Union[str, IO]] = "kim-tools.log",
|
140
140
|
algorithm: Optimizer = LBFGSLineSearch,
|
141
141
|
cell_filter: UnitCellFilter = FrechetCellFilter,
|
142
|
-
fix_symmetry: bool = False,
|
142
|
+
fix_symmetry: Union[bool, FixSymmetry] = False,
|
143
143
|
opt_kwargs: Dict = {},
|
144
144
|
flt_kwargs: Dict = {},
|
145
145
|
) -> bool:
|
@@ -179,7 +179,8 @@ def minimize_wrapper(
|
|
179
179
|
CellFilter:
|
180
180
|
Filter to use if variable_cell is requested
|
181
181
|
fix_symmetry:
|
182
|
-
Whether to fix the crystallographic symmetry
|
182
|
+
Whether to fix the crystallographic symmetry. Can provide
|
183
|
+
a FixSymmetry class here instead of detecting it on the fly
|
183
184
|
opt_kwargs:
|
184
185
|
Dictionary of kwargs to pass to optimizer
|
185
186
|
flt_kwargs:
|
@@ -188,8 +189,11 @@ def minimize_wrapper(
|
|
188
189
|
Returns:
|
189
190
|
Whether the minimization succeeded
|
190
191
|
"""
|
191
|
-
if fix_symmetry:
|
192
|
-
|
192
|
+
if fix_symmetry is not False:
|
193
|
+
if fix_symmetry is True:
|
194
|
+
symmetry = FixSymmetry(atoms)
|
195
|
+
else:
|
196
|
+
symmetry = fix_symmetry
|
193
197
|
atoms.set_constraint(symmetry)
|
194
198
|
if variable_cell:
|
195
199
|
supercell_wrapped = cell_filter(atoms, **flt_kwargs)
|
@@ -225,11 +229,18 @@ def minimize_wrapper(
|
|
225
229
|
del atoms.constraints
|
226
230
|
|
227
231
|
if minimization_stalled or iteration_limits_reached:
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
232
|
+
try:
|
233
|
+
logger.info("Final forces:")
|
234
|
+
logger.info(atoms.get_forces())
|
235
|
+
logger.info("Final stress:")
|
236
|
+
logger.info(atoms.get_stress())
|
237
|
+
except Exception as e:
|
238
|
+
logger.info(
|
239
|
+
"The following exception was caught "
|
240
|
+
"trying to evaluate final forces and stress:"
|
241
|
+
)
|
242
|
+
logger.info(repr(e))
|
243
|
+
return False
|
233
244
|
else:
|
234
245
|
return True
|
235
246
|
|
@@ -1307,7 +1318,7 @@ class SingleCrystalTestDriver(KIMTestDriver):
|
|
1307
1318
|
)
|
1308
1319
|
print(f"\nNOTE: {msg}\n")
|
1309
1320
|
logger.info(msg)
|
1310
|
-
if cell_cauchy_stress_eV_angstrom3
|
1321
|
+
if cell_cauchy_stress_eV_angstrom3 == [0, 0, 0, 0, 0, 0]:
|
1311
1322
|
stress_max = np.max(atoms_tmp.get_stress())
|
1312
1323
|
if stress_max > FMAX_INITIAL:
|
1313
1324
|
msg = (
|
@@ -1856,6 +1867,23 @@ class SingleCrystalTestDriver(KIMTestDriver):
|
|
1856
1867
|
atoms_tmp.calc = self._calc
|
1857
1868
|
return atoms_tmp
|
1858
1869
|
|
1870
|
+
def get_nominal_prototype_label(self) -> str:
|
1871
|
+
return self._get_nominal_crystal_structure_npt()["prototype-label"][
|
1872
|
+
"source-value"
|
1873
|
+
]
|
1874
|
+
|
1875
|
+
def get_atom_indices_for_each_wyckoff_orb(self) -> List[Dict]:
|
1876
|
+
"""
|
1877
|
+
Get a list of dictionaries containing the atom indices of each Wyckoff
|
1878
|
+
orbit.
|
1879
|
+
|
1880
|
+
Returns:
|
1881
|
+
The information is in this format:
|
1882
|
+
|
1883
|
+
[{"letter":"a", "indices":[0,1]}, ... ]
|
1884
|
+
"""
|
1885
|
+
return get_atom_indices_for_each_wyckoff_orb(self.get_nominal_prototype_label())
|
1886
|
+
|
1859
1887
|
|
1860
1888
|
def query_crystal_structures(
|
1861
1889
|
stoichiometric_species: List[str],
|
@@ -1955,7 +1983,7 @@ def query_crystal_structures(
|
|
1955
1983
|
logger.info(len_msg)
|
1956
1984
|
logger.debug(f"Query result (length={len(query_result)}):\n{query_result}")
|
1957
1985
|
|
1958
|
-
print(f"!!! {len_msg}
|
1986
|
+
print(f"\n!!! {len_msg} !!!\n")
|
1959
1987
|
|
1960
1988
|
return query_result
|
1961
1989
|
|
@@ -2208,8 +2236,3 @@ def get_deduplicated_property_instances(
|
|
2208
2236
|
property_instances_deduplicated.sort(key=lambda a: a["instance-id"])
|
2209
2237
|
|
2210
2238
|
return property_instances_deduplicated
|
2211
|
-
|
2212
|
-
|
2213
|
-
# If called directly, do nothing
|
2214
|
-
if __name__ == "__main__":
|
2215
|
-
pass
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: kim-tools
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.6
|
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=kYbIfF9bmWajsk_oLkaGok3kpnHeo1rlLBUAranse8o,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=YH1KCMQjXiKMqhT1TAuoafpsGqPlybsykRRMaa8wWqc,78219
|
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,7 @@ 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=aDaeYmtwfkNlNDcYQ3mAkez7e9_Lk84xQxwQ24cir38,34231
|
2008
2008
|
kim_tools/symmetry_util/data/possible_primitive_shifts.json,sha256=4OVNgn3NnykgGlYiAcecERmVWiIZFrmP2LZI3ml_Sh0,25010
|
2009
2009
|
kim_tools/symmetry_util/data/primitive_GENPOS_ops.json,sha256=FDu4H4PosOpK9yKwOPy3SxbH7xLMOmZfKZ4ItKPMjoQ,224498
|
2010
2010
|
kim_tools/symmetry_util/data/space_groups_for_each_bravais_lattice.json,sha256=wSNu6d5pH72lJ6Zj5MZ64qzwS_6Fn5WOs0ts7E9uPC4,2507
|
@@ -2012,11 +2012,11 @@ kim_tools/symmetry_util/data/wyck_pos_xform_under_normalizer.json,sha256=6g1YuYh
|
|
2012
2012
|
kim_tools/symmetry_util/data/wyckoff_multiplicities.json,sha256=qG2RPBd_-ejDIfz-E4ZhkHyRpIboxRy7oiXkdDf5Eg8,32270
|
2013
2013
|
kim_tools/symmetry_util/data/wyckoff_sets.json,sha256=f5ZpHKDHo6_JWki1b7KUGoYLlhU-44Qikw_-PtbLssw,9248
|
2014
2014
|
kim_tools/test_driver/__init__.py,sha256=KOiceeZNqkfrgZ66CiRiUdniceDrCmmDXQkOw0wXaCQ,92
|
2015
|
-
kim_tools/test_driver/core.py,sha256=
|
2015
|
+
kim_tools/test_driver/core.py,sha256=DseMkfdb-b116rRQQR0N7HKhsMsZGq8ZxtKoCBlw8X8,91307
|
2016
2016
|
kim_tools/vc/__init__.py,sha256=zXjhxXCKVMLBMXXWYG3if7VOpBnsFrn_RjVpnohDm5c,74
|
2017
2017
|
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.
|
2018
|
+
kim_tools-0.3.6.dist-info/licenses/LICENSE.CDDL,sha256=I2luEED_SHjuZ01B4rYG-AF_135amL24JpHvZ1Jhqe8,16373
|
2019
|
+
kim_tools-0.3.6.dist-info/METADATA,sha256=Q_aemQPU34z7rSPK04WnMP6WzUnS845Frlr3YWofcjw,2032
|
2020
|
+
kim_tools-0.3.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
2021
|
+
kim_tools-0.3.6.dist-info/top_level.txt,sha256=w_YCpJ5ERigj9te74ln7k64tqj1VumOzM_s9dsalIWY,10
|
2022
|
+
kim_tools-0.3.6.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|