pymdkit 1.6.1__tar.gz → 1.6.2__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.
- {pymdkit-1.6.1 → pymdkit-1.6.2}/PKG-INFO +12 -3
- {pymdkit-1.6.1 → pymdkit-1.6.2}/README.md +13 -4
- {pymdkit-1.6.1 → pymdkit-1.6.2}/pyproject.toml +1 -1
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/__init__.py +1 -1
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/_symmetry.py +4 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/compute_rmsd.py +3 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/convert.py +30 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/gpumd_group.py +2 -2
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/realloc_occ.py +6 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/substitute.py +5 -1
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/supercell.py +1 -3
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit.egg-info/PKG-INFO +12 -3
- {pymdkit-1.6.1 → pymdkit-1.6.2}/tests/test_convert.py +53 -1
- {pymdkit-1.6.1 → pymdkit-1.6.2}/tests/test_realloc_occ.py +4 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/LICENSE +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/setup.cfg +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/__init__.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/_cifio.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/_extxyz.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/_fileio.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/_geometry.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/_gpumd.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/_lattice.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/_oxidation.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/_precision.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/_reduction.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/_supercell.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/_vasp_output.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/_vaspset.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/add_config_type.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/chemsys_entry.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/compute_ehull.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/ewald.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/gather_fs.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/gpumd_msd.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/gpumd_relax.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/gpumd_thermo.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/gpumd_trjcat.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/nep_rmse.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/pca.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/perturb.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/submit_vasp.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/trj_extract.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/trj_sparse.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/umap.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/vasp2xyz.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/vasp_fe.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/vasp_relax.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/commands/vasp_static.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit/pymdkit_main.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit.egg-info/SOURCES.txt +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit.egg-info/dependency_links.txt +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit.egg-info/entry_points.txt +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit.egg-info/requires.txt +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/src/pymdkit.egg-info/top_level.txt +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/tests/test_lattice_symmetry.py +0 -0
- {pymdkit-1.6.1 → pymdkit-1.6.2}/tests/test_vaspset.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pymdkit
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.2
|
|
4
4
|
Summary: A unified command-line toolkit for atomistic / MD structure workflows.
|
|
5
5
|
Author-email: Yueda Wang <ydwang0608@ustc.edu.cn>
|
|
6
6
|
License-Expression: GPL-3.0-or-later
|
|
@@ -263,8 +263,9 @@ and `0.875`. Generated CIF occupancy fields use two decimal places.
|
|
|
263
263
|
`-max-supercell AxBxC` searches bounded diagonal supercells, smallest volume
|
|
264
264
|
first, until every multiplicity times occupancy times supercell determinant is
|
|
265
265
|
an integer. Equal-volume choices favor the most isotropic resulting cell.
|
|
266
|
-
All selections, site atom counts, oxidation states, charges,
|
|
267
|
-
recorded in
|
|
266
|
+
All selections, site atom counts, oxidation states, charges, failures, the
|
|
267
|
+
allowed occupancy grid, and the final summary are recorded in
|
|
268
|
+
`OUTPUT/realloc-occ.txt` for both single-file and folder modes.
|
|
268
269
|
|
|
269
270
|
`gather-fs` recursively scans all job folders below the current directory. For
|
|
270
271
|
VASP it follows the global `vaspout.h5 > vasprun.xml > OUTCAR` priority and
|
|
@@ -330,6 +331,14 @@ International Tables setting from pymatgen/spglib and correspond to the
|
|
|
330
331
|
[Bilbao Crystallographic Server WYCKPOS tables](https://cryst.ehu.es/cryst/get_wp.html);
|
|
331
332
|
the provenance URL is also recorded inside each generated CIF.
|
|
332
333
|
|
|
334
|
+
For structural conversion, supercell creation, and GPUMD grouping, PMK reads
|
|
335
|
+
CIF input with pymatgen rather than ASE. ASE interprets
|
|
336
|
+
`_space_group_crystal_system` as a setting hint only for rhombohedral groups
|
|
337
|
+
and emits a potentially misleading warning for other crystal systems. Using
|
|
338
|
+
pymatgen avoids that ambiguity while PMK continues to use ASE for non-CIF
|
|
339
|
+
formats. A partially occupied CIF must first be ordered with `convert -d2o`
|
|
340
|
+
before it can be represented as an explicit atom list.
|
|
341
|
+
|
|
333
342
|
CIF `_atom_type_symbol` and `_atom_site_label` values use per-element
|
|
334
343
|
inequivalent-site identifiers such as `Li1`, `Y1`, `Cl1`, and `Cl2`.
|
|
335
344
|
The final atom-site loop starts with `_atom_site_label`, followed by
|
|
@@ -236,9 +236,10 @@ and `0.875`. Generated CIF occupancy fields use two decimal places.
|
|
|
236
236
|
`-max-supercell AxBxC` searches bounded diagonal supercells, smallest volume
|
|
237
237
|
first, until every multiplicity times occupancy times supercell determinant is
|
|
238
238
|
an integer. Equal-volume choices favor the most isotropic resulting cell.
|
|
239
|
-
All selections, site atom counts, oxidation states, charges,
|
|
240
|
-
recorded in
|
|
241
|
-
|
|
239
|
+
All selections, site atom counts, oxidation states, charges, failures, the
|
|
240
|
+
allowed occupancy grid, and the final summary are recorded in
|
|
241
|
+
`OUTPUT/realloc-occ.txt` for both single-file and folder modes.
|
|
242
|
+
|
|
242
243
|
`gather-fs` recursively scans all job folders below the current directory. For
|
|
243
244
|
VASP it follows the global `vaspout.h5 > vasprun.xml > OUTCAR` priority and
|
|
244
245
|
requires full convergence before copying the selected `-fs-name` as `.vasp`. The gathered VASP file's first line is replaced with `energy=<final_energy> eV` for later screening.
|
|
@@ -301,7 +302,15 @@ atom-site loop. Multiplicity-letter
|
|
|
301
302
|
assignments use the conventional
|
|
302
303
|
International Tables setting from pymatgen/spglib and correspond to the
|
|
303
304
|
[Bilbao Crystallographic Server WYCKPOS tables](https://cryst.ehu.es/cryst/get_wp.html);
|
|
304
|
-
the provenance URL is also recorded inside each generated CIF.
|
|
305
|
+
the provenance URL is also recorded inside each generated CIF.
|
|
306
|
+
|
|
307
|
+
For structural conversion, supercell creation, and GPUMD grouping, PMK reads
|
|
308
|
+
CIF input with pymatgen rather than ASE. ASE interprets
|
|
309
|
+
`_space_group_crystal_system` as a setting hint only for rhombohedral groups
|
|
310
|
+
and emits a potentially misleading warning for other crystal systems. Using
|
|
311
|
+
pymatgen avoids that ambiguity while PMK continues to use ASE for non-CIF
|
|
312
|
+
formats. A partially occupied CIF must first be ordered with `convert -d2o`
|
|
313
|
+
before it can be represented as an explicit atom list.
|
|
305
314
|
|
|
306
315
|
CIF `_atom_type_symbol` and `_atom_site_label` values use per-element
|
|
307
316
|
inequivalent-site identifiers such as `Li1`, `Y1`, `Cl1`, and `Cl2`.
|
|
@@ -42,6 +42,10 @@ def load_structure(path):
|
|
|
42
42
|
try:
|
|
43
43
|
return Structure.from_file(str(path))
|
|
44
44
|
except Exception as pymatgen_error:
|
|
45
|
+
if _cifio.is_cif(path):
|
|
46
|
+
raise ValueError(
|
|
47
|
+
f"pymatgen could not read CIF {path}: {pymatgen_error}"
|
|
48
|
+
) from pymatgen_error
|
|
45
49
|
try:
|
|
46
50
|
from ase.io import read
|
|
47
51
|
from pymatgen.io.ase import AseAtomsAdaptor
|
|
@@ -55,6 +55,9 @@ def load_structure(path):
|
|
|
55
55
|
try:
|
|
56
56
|
return Structure.from_file(str(path))
|
|
57
57
|
except Exception as pymatgen_error:
|
|
58
|
+
if path.suffix.lower() == ".cif":
|
|
59
|
+
print(f" [warn] pymatgen could not read CIF {path}: {pymatgen_error}")
|
|
60
|
+
return None
|
|
58
61
|
try:
|
|
59
62
|
from ase.io import read
|
|
60
63
|
from pymatgen.io.ase import AseAtomsAdaptor
|
|
@@ -21,7 +21,32 @@ COMMAND = "convert"
|
|
|
21
21
|
HELP = "Convert structures, refine CIF symmetry, or order disorder."
|
|
22
22
|
|
|
23
23
|
|
|
24
|
+
def _read_cif(path):
|
|
25
|
+
"""Read CIF with pymatgen, avoiding ASE's setting-name ambiguity."""
|
|
26
|
+
from pymatgen.core import Structure
|
|
27
|
+
from pymatgen.io.ase import AseAtomsAdaptor
|
|
28
|
+
|
|
29
|
+
structure = Structure.from_file(str(path))
|
|
30
|
+
if not structure.is_ordered:
|
|
31
|
+
raise ValueError(
|
|
32
|
+
"partially occupied CIF cannot be converted to an explicit atom "
|
|
33
|
+
"format; use convert -d2o first"
|
|
34
|
+
)
|
|
35
|
+
return AseAtomsAdaptor.get_atoms(structure)
|
|
36
|
+
|
|
37
|
+
|
|
24
38
|
def _read(path, all_frames=False):
|
|
39
|
+
path = Path(path)
|
|
40
|
+
if _cifio.is_cif(path):
|
|
41
|
+
if all_frames:
|
|
42
|
+
raise ValueError("CIF input is a structure, not a trajectory")
|
|
43
|
+
try:
|
|
44
|
+
return _read_cif(path)
|
|
45
|
+
except Exception as error:
|
|
46
|
+
raise ValueError(
|
|
47
|
+
f"pymatgen could not read CIF {path}: {error}"
|
|
48
|
+
) from error
|
|
49
|
+
|
|
25
50
|
from ase.io import read
|
|
26
51
|
|
|
27
52
|
try:
|
|
@@ -234,6 +259,11 @@ def convert_one(
|
|
|
234
259
|
angle_tolerance,
|
|
235
260
|
add_oxidation,
|
|
236
261
|
)
|
|
262
|
+
elif _cifio.is_cif(input_path) and _cifio.is_cif(output_path):
|
|
263
|
+
structure = _read_structure(input_path)
|
|
264
|
+
_write_structure(
|
|
265
|
+
output_path, structure, refine=False, symmetrize=False
|
|
266
|
+
)
|
|
237
267
|
else:
|
|
238
268
|
atoms = _read(input_path, all_frames=trajectory)
|
|
239
269
|
_write(output_path, atoms, symmetrize=False)
|
|
@@ -14,7 +14,7 @@ import argparse
|
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
|
|
16
16
|
import numpy as np
|
|
17
|
-
from ase.io import
|
|
17
|
+
from ase.io import write
|
|
18
18
|
|
|
19
19
|
try:
|
|
20
20
|
from . import _cifio, _fileio, convert
|
|
@@ -38,7 +38,7 @@ def add_arguments(parser):
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
def _tag_one(in_path, out_path, elements):
|
|
41
|
-
atoms =
|
|
41
|
+
atoms = convert._read(in_path)
|
|
42
42
|
groups = []
|
|
43
43
|
for element in atoms.get_chemical_symbols():
|
|
44
44
|
if element in elements:
|
|
@@ -699,9 +699,15 @@ def run(args):
|
|
|
699
699
|
|
|
700
700
|
output_root = Path(args.output_folder)
|
|
701
701
|
output_root.mkdir(parents=True, exist_ok=True)
|
|
702
|
+
occupancy_text = (
|
|
703
|
+
"automatic"
|
|
704
|
+
if allowed_occupancies is None
|
|
705
|
+
else ", ".join(f"{value:.3f}" for value in allowed_occupancies)
|
|
706
|
+
)
|
|
702
707
|
report = [
|
|
703
708
|
"PMK realloc-occ summary",
|
|
704
709
|
f"Target formula: {args.formula}",
|
|
710
|
+
f"Allowed occupancies: {occupancy_text}",
|
|
705
711
|
f"Maximum supercell: {'x'.join(map(str, max_supercell))}",
|
|
706
712
|
"",
|
|
707
713
|
]
|
|
@@ -212,7 +212,11 @@ def read_structure(path):
|
|
|
212
212
|
path = Path(path)
|
|
213
213
|
try:
|
|
214
214
|
return Structure.from_file(str(path))
|
|
215
|
-
except Exception:
|
|
215
|
+
except Exception as pymatgen_error:
|
|
216
|
+
if _cifio.is_cif(path):
|
|
217
|
+
raise ValueError(
|
|
218
|
+
f"pymatgen could not read CIF {path}: {pymatgen_error}"
|
|
219
|
+
) from pymatgen_error
|
|
216
220
|
from ase.io import read as ase_read
|
|
217
221
|
from pymatgen.io.ase import AseAtomsAdaptor
|
|
218
222
|
|
|
@@ -78,9 +78,7 @@ def make_supercell(
|
|
|
78
78
|
max_abc=None,
|
|
79
79
|
close_abc=None,
|
|
80
80
|
):
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
atoms = read(str(in_path))
|
|
81
|
+
atoms = convert._read(in_path)
|
|
84
82
|
lengths, _, _ = _lattice.geometry_from_matrix(atoms.cell.array)
|
|
85
83
|
supercell_matrix = _supercell.resolve_matrix(
|
|
86
84
|
lengths,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pymdkit
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.2
|
|
4
4
|
Summary: A unified command-line toolkit for atomistic / MD structure workflows.
|
|
5
5
|
Author-email: Yueda Wang <ydwang0608@ustc.edu.cn>
|
|
6
6
|
License-Expression: GPL-3.0-or-later
|
|
@@ -263,8 +263,9 @@ and `0.875`. Generated CIF occupancy fields use two decimal places.
|
|
|
263
263
|
`-max-supercell AxBxC` searches bounded diagonal supercells, smallest volume
|
|
264
264
|
first, until every multiplicity times occupancy times supercell determinant is
|
|
265
265
|
an integer. Equal-volume choices favor the most isotropic resulting cell.
|
|
266
|
-
All selections, site atom counts, oxidation states, charges,
|
|
267
|
-
recorded in
|
|
266
|
+
All selections, site atom counts, oxidation states, charges, failures, the
|
|
267
|
+
allowed occupancy grid, and the final summary are recorded in
|
|
268
|
+
`OUTPUT/realloc-occ.txt` for both single-file and folder modes.
|
|
268
269
|
|
|
269
270
|
`gather-fs` recursively scans all job folders below the current directory. For
|
|
270
271
|
VASP it follows the global `vaspout.h5 > vasprun.xml > OUTCAR` priority and
|
|
@@ -330,6 +331,14 @@ International Tables setting from pymatgen/spglib and correspond to the
|
|
|
330
331
|
[Bilbao Crystallographic Server WYCKPOS tables](https://cryst.ehu.es/cryst/get_wp.html);
|
|
331
332
|
the provenance URL is also recorded inside each generated CIF.
|
|
332
333
|
|
|
334
|
+
For structural conversion, supercell creation, and GPUMD grouping, PMK reads
|
|
335
|
+
CIF input with pymatgen rather than ASE. ASE interprets
|
|
336
|
+
`_space_group_crystal_system` as a setting hint only for rhombohedral groups
|
|
337
|
+
and emits a potentially misleading warning for other crystal systems. Using
|
|
338
|
+
pymatgen avoids that ambiguity while PMK continues to use ASE for non-CIF
|
|
339
|
+
formats. A partially occupied CIF must first be ordered with `convert -d2o`
|
|
340
|
+
before it can be represented as an explicit atom list.
|
|
341
|
+
|
|
333
342
|
CIF `_atom_type_symbol` and `_atom_site_label` values use per-element
|
|
334
343
|
inequivalent-site identifiers such as `Li1`, `Y1`, `Cl1`, and `Cl2`.
|
|
335
344
|
The final atom-site loop starts with `_atom_site_label`, followed by
|
|
@@ -9,10 +9,62 @@ from unittest.mock import patch
|
|
|
9
9
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
|
|
10
10
|
|
|
11
11
|
from pymdkit import pymdkit_main
|
|
12
|
-
from pymdkit.commands import
|
|
12
|
+
from pymdkit.commands import (
|
|
13
|
+
_cifio,
|
|
14
|
+
_supercell,
|
|
15
|
+
_symmetry,
|
|
16
|
+
compute_rmsd,
|
|
17
|
+
convert,
|
|
18
|
+
substitute,
|
|
19
|
+
)
|
|
13
20
|
|
|
14
21
|
|
|
15
22
|
class ConvertTests(unittest.TestCase):
|
|
23
|
+
def test_cif_input_uses_pymatgen_reader(self):
|
|
24
|
+
atoms = object()
|
|
25
|
+
with patch.object(convert, "_read_cif", return_value=atoms) as reader:
|
|
26
|
+
self.assertIs(convert._read("input.cif"), atoms)
|
|
27
|
+
reader.assert_called_once_with(Path("input.cif"))
|
|
28
|
+
with self.assertRaisesRegex(ValueError, "not a trajectory"):
|
|
29
|
+
convert._read("input.cif", all_frames=True)
|
|
30
|
+
|
|
31
|
+
def test_failed_cif_parse_never_falls_back_to_ase(self):
|
|
32
|
+
class Structure:
|
|
33
|
+
@classmethod
|
|
34
|
+
def from_file(cls, path):
|
|
35
|
+
raise RuntimeError("invalid CIF")
|
|
36
|
+
|
|
37
|
+
pymatgen = types.ModuleType("pymatgen")
|
|
38
|
+
core = types.ModuleType("pymatgen.core")
|
|
39
|
+
core.Structure = Structure
|
|
40
|
+
pymatgen.core = core
|
|
41
|
+
modules = {"pymatgen": pymatgen, "pymatgen.core": core}
|
|
42
|
+
with patch.dict(sys.modules, modules):
|
|
43
|
+
with self.assertRaisesRegex(ValueError, "pymatgen could not read CIF"):
|
|
44
|
+
_symmetry.load_structure("broken.cif")
|
|
45
|
+
with self.assertRaisesRegex(ValueError, "pymatgen could not read CIF"):
|
|
46
|
+
substitute.read_structure("broken.cif")
|
|
47
|
+
self.assertIsNone(compute_rmsd.load_structure("broken.cif"))
|
|
48
|
+
|
|
49
|
+
def test_cif_to_cif_preserves_disorder_through_pymatgen(self):
|
|
50
|
+
structure = object()
|
|
51
|
+
with patch.object(
|
|
52
|
+
convert, "_read_structure", return_value=structure
|
|
53
|
+
) as reader, patch.object(
|
|
54
|
+
convert, "_write_structure"
|
|
55
|
+
) as writer, patch.object(
|
|
56
|
+
convert, "_read"
|
|
57
|
+
) as ase_reader:
|
|
58
|
+
convert.convert_one("input.cif", "output.cif")
|
|
59
|
+
reader.assert_called_once_with(Path("input.cif"))
|
|
60
|
+
writer.assert_called_once_with(
|
|
61
|
+
Path("output.cif"),
|
|
62
|
+
structure,
|
|
63
|
+
refine=False,
|
|
64
|
+
symmetrize=False,
|
|
65
|
+
)
|
|
66
|
+
ase_reader.assert_not_called()
|
|
67
|
+
|
|
16
68
|
def test_cli_defaults_to_p1_and_optional_supercell(self):
|
|
17
69
|
parser = argparse.ArgumentParser()
|
|
18
70
|
convert.add_arguments(parser)
|
|
@@ -176,6 +176,10 @@ class ReallocOccTests(unittest.TestCase):
|
|
|
176
176
|
):
|
|
177
177
|
self.assertEqual(realloc_occ.run(args), 0)
|
|
178
178
|
report = (output / "realloc-occ.txt").read_text(encoding="utf-8")
|
|
179
|
+
self.assertIn(
|
|
180
|
+
"Allowed occupancies: 0.250, 0.500, 0.750, 1.000",
|
|
181
|
+
report,
|
|
182
|
+
)
|
|
179
183
|
self.assertIn("supercell=1x1x1", report)
|
|
180
184
|
self.assertIn("Li1=6", report)
|
|
181
185
|
self.assertIn("charge=0.00000000", report)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|