rsspolymlp 0.3.4__tar.gz → 0.4.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.
- {rsspolymlp-0.3.4/src/rsspolymlp.egg-info → rsspolymlp-0.4.0}/PKG-INFO +16 -12
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/README.md +15 -11
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/pyproject.toml +1 -1
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/analysis/eos.py +1 -1
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/analysis/ghost_minima.py +9 -13
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/analysis/phase_analysis.py +7 -10
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/analysis/rss_summarize.py +48 -31
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/analysis/struct_matcher/struct_match.py +63 -32
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/analysis/unique_struct.py +5 -5
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/api/cli_rsspolymlp.py +16 -6
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/api/cli_rsspolymlp_devkit.py +23 -31
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/api/cli_rsspolymlp_utils.py +13 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/api/rsspolymlp.py +20 -16
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/api/rsspolymlp_devkit.py +24 -31
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/api/rsspolymlp_plot.py +7 -10
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/api/rsspolymlp_utils.py +47 -12
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/common/atomic_energy.py +1 -1
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/common/composition.py +2 -3
- rsspolymlp-0.4.0/src/rsspolymlp/common/interface_vasp.py +318 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/mlp_dev/dataset/gen_mlp_dataset.py +9 -8
- rsspolymlp-0.3.4/src/rsspolymlp/mlp_dev/dataset/divide_dataset.py → rsspolymlp-0.4.0/src/rsspolymlp/mlp_dev/dataset/split_dataset.py +63 -89
- rsspolymlp-0.4.0/src/rsspolymlp/mlp_dev/model_selection/binary/gen_single_model.py +74 -0
- {rsspolymlp-0.3.4/src/rsspolymlp/mlp_dev/model_selection → rsspolymlp-0.4.0/src/rsspolymlp/mlp_dev/model_selection/elemental}/gen_single_model.py +3 -3
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/mlp_dev/model_selection/n_feature.py +16 -4
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/mlp_dev/model_selection/pypolymlp_gridsearch.py +3 -3
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/mlp_dev/model_selection/reduce_grid.py +7 -1
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/mlp_dev/polymlp_dev.py +2 -1
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/rss/eliminate_duplicates.py +3 -3
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/rss/optimization_mlp.py +10 -6
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/matplot_util/examples/template.py +2 -2
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/opt_sscha/opt_geometry_sscha.py +4 -5
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/opt_sscha/sscha_property.py +10 -2
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/spglib_utils.py +1 -1
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/vasp_util/gen_script.py +3 -2
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/vasp_util/write_poscar.py +12 -1
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0/src/rsspolymlp.egg-info}/PKG-INFO +16 -12
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp.egg-info/SOURCES.txt +5 -9
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/tests/test_cli_help.py +0 -1
- rsspolymlp-0.3.4/src/rsspolymlp/analysis/struct_matcher/deprecated/invert_and_swap.py +0 -106
- rsspolymlp-0.3.4/src/rsspolymlp/analysis/struct_matcher/deprecated/irrep_position.py +0 -379
- rsspolymlp-0.3.4/src/rsspolymlp/analysis/struct_matcher/deprecated/niggli.py +0 -10
- rsspolymlp-0.3.4/src/rsspolymlp/analysis/struct_matcher/deprecated/struct_match.py +0 -264
- rsspolymlp-0.3.4/src/rsspolymlp/analysis/struct_matcher/deprecated/utils.py +0 -83
- rsspolymlp-0.3.4/src/rsspolymlp/utils/opt_sscha/harmonic_real.py +0 -379
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/LICENSE +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/setup.cfg +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/__init__.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/analysis/__init__.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/analysis/struct_matcher/__init__.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/analysis/struct_matcher/chiral_spg.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/analysis/struct_matcher/invert_and_swap.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/analysis/struct_matcher/reduced_position.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/api/__init__.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/api/cli_rsspolymlp_plot.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/common/__init__.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/common/convert_dict.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/common/property.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/mlp_dev/dataset/compress_vasprun.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/mlp_dev/estimate_cost.py +0 -0
- {rsspolymlp-0.3.4/src/rsspolymlp/mlp_dev/model_selection → rsspolymlp-0.4.0/src/rsspolymlp/mlp_dev/model_selection/elemental}/gen_hybrid_model.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/mlp_dev/pareto_opt_mlp.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/rss/__init__.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/rss/load_logfile.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/rss/random_struct.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/__init__.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/lammps_utils.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/matplot_util/__init__.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/matplot_util/custom_plt.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/matplot_util/examples/__init__.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/matplot_util/examples/example.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/matplot_util/make_plot.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/opt_sscha/opt_position_sscha.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/opt_sscha/run_opt_sscha.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/pymatgen_utils.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/vasp_util/__init__.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/vasp_util/api.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/utils/vasp_util/gen_incar.py +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp.egg-info/dependency_links.txt +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp.egg-info/entry_points.txt +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp.egg-info/requires.txt +0 -0
- {rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rsspolymlp
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: A framework for random structure search using polynomial MLPs
|
|
5
5
|
Author-email: Hayato Wakai <wakai@cms.mtl.kyoto-u.ac.jp>
|
|
6
6
|
Maintainer-email: Hayato Wakai <wakai@cms.mtl.kyoto-u.ac.jp>
|
|
@@ -35,17 +35,21 @@ Dynamic: license-file
|
|
|
35
35
|
|
|
36
36
|
If you use `rsspolymlp` in your study, please cite the following articles.
|
|
37
37
|
|
|
38
|
-
“
|
|
38
|
+
“Systematic global structure search of bismuth-based binary systems under pressure using machine learning potentials”, [Phys. Rev. Materials 10, 093801 (2026)](https://doi.org/10.1103/k9sg-v7hl)
|
|
39
39
|
```
|
|
40
|
-
@article{
|
|
41
|
-
title=
|
|
42
|
-
author={Hayato
|
|
43
|
-
journal={
|
|
44
|
-
volume={
|
|
45
|
-
|
|
46
|
-
pages={
|
|
47
|
-
|
|
48
|
-
|
|
40
|
+
@article{Phys.Rev.Mater.10.093801,
|
|
41
|
+
title = {Systematic global structure search of bismuth-based binary systems under pressure using machine learning potentials},
|
|
42
|
+
author = {Wakai, Hayato and Ishiwata, Shintaro and Seko, Atsuto},
|
|
43
|
+
journal = {Phys. Rev. Mater.},
|
|
44
|
+
volume = {10},
|
|
45
|
+
issue = {9},
|
|
46
|
+
pages = {093801},
|
|
47
|
+
numpages = {28},
|
|
48
|
+
year = {2026},
|
|
49
|
+
month = {Sep},
|
|
50
|
+
publisher = {American Physical Society},
|
|
51
|
+
doi = {10.1103/k9sg-v7hl},
|
|
52
|
+
url = {https://link.aps.org/doi/10.1103/k9sg-v7hl}
|
|
49
53
|
}
|
|
50
54
|
```
|
|
51
55
|
|
|
@@ -93,7 +97,7 @@ pip install rsspolymlp
|
|
|
93
97
|
- Unique structure identification and RSS result summarization
|
|
94
98
|
- Ghost minimum structure elimination
|
|
95
99
|
- Phase stability analysis
|
|
96
|
-
- [Development kit for polynomial MLPs](docs/
|
|
100
|
+
- [Development kit for polynomial MLPs](docs/rsspolymlp_dev.md)
|
|
97
101
|
- MLP dataset generation
|
|
98
102
|
- DFT dataset division
|
|
99
103
|
- Polynomial MLP development
|
|
@@ -4,17 +4,21 @@
|
|
|
4
4
|
|
|
5
5
|
If you use `rsspolymlp` in your study, please cite the following articles.
|
|
6
6
|
|
|
7
|
-
“
|
|
7
|
+
“Systematic global structure search of bismuth-based binary systems under pressure using machine learning potentials”, [Phys. Rev. Materials 10, 093801 (2026)](https://doi.org/10.1103/k9sg-v7hl)
|
|
8
8
|
```
|
|
9
|
-
@article{
|
|
10
|
-
title=
|
|
11
|
-
author={Hayato
|
|
12
|
-
journal={
|
|
13
|
-
volume={
|
|
14
|
-
|
|
15
|
-
pages={
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
@article{Phys.Rev.Mater.10.093801,
|
|
10
|
+
title = {Systematic global structure search of bismuth-based binary systems under pressure using machine learning potentials},
|
|
11
|
+
author = {Wakai, Hayato and Ishiwata, Shintaro and Seko, Atsuto},
|
|
12
|
+
journal = {Phys. Rev. Mater.},
|
|
13
|
+
volume = {10},
|
|
14
|
+
issue = {9},
|
|
15
|
+
pages = {093801},
|
|
16
|
+
numpages = {28},
|
|
17
|
+
year = {2026},
|
|
18
|
+
month = {Sep},
|
|
19
|
+
publisher = {American Physical Society},
|
|
20
|
+
doi = {10.1103/k9sg-v7hl},
|
|
21
|
+
url = {https://link.aps.org/doi/10.1103/k9sg-v7hl}
|
|
18
22
|
}
|
|
19
23
|
```
|
|
20
24
|
|
|
@@ -62,7 +66,7 @@ pip install rsspolymlp
|
|
|
62
66
|
- Unique structure identification and RSS result summarization
|
|
63
67
|
- Ghost minimum structure elimination
|
|
64
68
|
- Phase stability analysis
|
|
65
|
-
- [Development kit for polynomial MLPs](docs/
|
|
69
|
+
- [Development kit for polynomial MLPs](docs/rsspolymlp_dev.md)
|
|
66
70
|
- MLP dataset generation
|
|
67
71
|
- DFT dataset division
|
|
68
72
|
- Polynomial MLP development
|
|
@@ -8,9 +8,8 @@ import shutil
|
|
|
8
8
|
import numpy as np
|
|
9
9
|
from sklearn.cluster import KMeans
|
|
10
10
|
|
|
11
|
-
from pypolymlp.core.interface_vasp import Vasprun
|
|
12
11
|
from pypolymlp.core.units import EVtoGPa
|
|
13
|
-
from rsspolymlp.common.
|
|
12
|
+
from rsspolymlp.common.interface_vasp import parse_properties_from_vasprun
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
def detect_ghost_minima(energies: np.array, distances: np.array):
|
|
@@ -165,7 +164,9 @@ def detect_actual_ghost_minima(dft_path):
|
|
|
165
164
|
vasprun_get = False
|
|
166
165
|
for vasprun in vasprun_paths:
|
|
167
166
|
try:
|
|
168
|
-
|
|
167
|
+
structure, (energy_dft, _, stress_dft) = parse_properties_from_vasprun(
|
|
168
|
+
vasprun, units="GPa"
|
|
169
|
+
)
|
|
169
170
|
vasprun_get = True
|
|
170
171
|
except Exception:
|
|
171
172
|
continue
|
|
@@ -182,22 +183,17 @@ def detect_actual_ghost_minima(dft_path):
|
|
|
182
183
|
)
|
|
183
184
|
continue
|
|
184
185
|
|
|
185
|
-
energy_dft = vaspobj.energy
|
|
186
|
-
structure = vaspobj.structure
|
|
187
|
-
for element in structure.elements:
|
|
188
|
-
energy_dft -= atomic_energy(element)
|
|
189
|
-
energy_dft /= len(structure.elements)
|
|
190
186
|
vol_per_atom = structure.volume / len(structure.elements)
|
|
191
187
|
|
|
192
|
-
# Subtract pressure term from MLP enthalpy
|
|
193
188
|
mlp_energy = res["energy"]
|
|
194
189
|
mlp_energy -= pressure * vol_per_atom / EVtoGPa
|
|
190
|
+
energy_dft /= len(structure.elements)
|
|
191
|
+
e_diff = mlp_energy - energy_dft
|
|
195
192
|
|
|
196
|
-
stress_dft = [
|
|
193
|
+
stress_dft = [stress_dft[i][i] for i in range(3)]
|
|
197
194
|
press_diff = [pressure - stress_dft[i] for i in range(3)]
|
|
198
195
|
stress_diff = np.max(np.abs(press_diff)) * vol_per_atom / EVtoGPa
|
|
199
196
|
|
|
200
|
-
e_diff = mlp_energy - energy_dft
|
|
201
197
|
diff_all.append(
|
|
202
198
|
{
|
|
203
199
|
"energy_diff": e_diff,
|
|
@@ -221,8 +217,8 @@ def detect_actual_ghost_minima(dft_path):
|
|
|
221
217
|
|
|
222
218
|
print(f" - structure: {poscar}", file=f)
|
|
223
219
|
if not delta_e == "null":
|
|
224
|
-
print(f" energy_diff_meV_per_atom: {delta_e*1000:.3f}", file=f)
|
|
225
|
-
print(f" stress_diff_meV_per_atom: {delta_s*1000:.3f}", file=f)
|
|
220
|
+
print(f" energy_diff_meV_per_atom: {delta_e * 1000:.3f}", file=f)
|
|
221
|
+
print(f" stress_diff_meV_per_atom: {delta_s * 1000:.3f}", file=f)
|
|
226
222
|
e_threshold = -0.1 # unit: eV/atom
|
|
227
223
|
s_threshold = 0.5
|
|
228
224
|
if delta_e < e_threshold or delta_s > s_threshold:
|
|
@@ -7,9 +7,8 @@ import numpy as np
|
|
|
7
7
|
import yaml
|
|
8
8
|
from scipy.spatial import ConvexHull
|
|
9
9
|
|
|
10
|
-
from pypolymlp.core.interface_vasp import Vasprun
|
|
11
|
-
from rsspolymlp.common.atomic_energy import atomic_energy
|
|
12
10
|
from rsspolymlp.common.composition import compute_composition
|
|
11
|
+
from rsspolymlp.common.interface_vasp import parse_properties_from_vasprun
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
class ConvexHullAnalyzer:
|
|
@@ -247,9 +246,9 @@ class ConvexHullAnalyzer:
|
|
|
247
246
|
def parse_results(self, input_paths, ghost_minima_file=None, parse_vasp=False):
|
|
248
247
|
"""
|
|
249
248
|
Populate composition_data by parsing RSS JSON or VASP vasprun.xml outputs.
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
249
|
+
input_paths: List of RSS JSON files or VASP directories.
|
|
250
|
+
ghost_minima_file: YAML file listing ghost minima to exclude (RSS only).
|
|
251
|
+
parse_vasp: If True, parse VASP outputs; otherwise parse RSS JSON.
|
|
253
252
|
"""
|
|
254
253
|
if parse_vasp:
|
|
255
254
|
self._parse_vasp_results(input_paths)
|
|
@@ -319,15 +318,13 @@ class ConvexHullAnalyzer:
|
|
|
319
318
|
for dft_path in input_paths:
|
|
320
319
|
vasprun_path = f"{dft_path}/vasprun.xml"
|
|
321
320
|
try:
|
|
322
|
-
|
|
321
|
+
structure, (energy_dft, _, _) = parse_properties_from_vasprun(
|
|
322
|
+
vasprun_path
|
|
323
|
+
)
|
|
323
324
|
except Exception:
|
|
324
325
|
print(vasprun_path, "failed")
|
|
325
326
|
continue
|
|
326
327
|
|
|
327
|
-
energy_dft = vaspobj.energy
|
|
328
|
-
structure = vaspobj.structure
|
|
329
|
-
for element in structure.elements:
|
|
330
|
-
energy_dft -= atomic_energy(element)
|
|
331
328
|
energy_dft /= len(structure.elements)
|
|
332
329
|
if energy_dft < -15:
|
|
333
330
|
print(vasprun_path, "exhibits very low energy:", energy_dft, "eV/atom")
|
|
@@ -9,7 +9,6 @@ from time import time
|
|
|
9
9
|
|
|
10
10
|
import numpy as np
|
|
11
11
|
|
|
12
|
-
from pypolymlp.core.interface_vasp import Vasprun
|
|
13
12
|
from pypolymlp.utils.vasp_utils import write_poscar_file
|
|
14
13
|
from rsspolymlp.analysis.ghost_minima import detect_ghost_minima
|
|
15
14
|
from rsspolymlp.analysis.unique_struct import (
|
|
@@ -18,9 +17,9 @@ from rsspolymlp.analysis.unique_struct import (
|
|
|
18
17
|
log_all_unique_structures,
|
|
19
18
|
log_unique_structures,
|
|
20
19
|
)
|
|
21
|
-
from rsspolymlp.common.atomic_energy import atomic_energy
|
|
22
20
|
from rsspolymlp.common.composition import compute_composition
|
|
23
21
|
from rsspolymlp.common.convert_dict import polymlp_struct_from_dict
|
|
22
|
+
from rsspolymlp.common.interface_vasp import Vasprun, parse_properties_from_vasprun
|
|
24
23
|
from rsspolymlp.common.property import PropUtil
|
|
25
24
|
|
|
26
25
|
|
|
@@ -132,19 +131,22 @@ class RSSResultSummarizer:
|
|
|
132
131
|
for ustr in unique_structs:
|
|
133
132
|
num_opt_str += len(list(ustr.dupstr_paths))
|
|
134
133
|
|
|
135
|
-
with open(composition_tag + ".yaml", "w") as f:
|
|
136
|
-
print("general_information:", file=f)
|
|
137
|
-
print(f" sorting_time_sec: {round(time_finish, 2)}", file=f)
|
|
138
|
-
print(f" pressure_GPa: {self.pressure}", file=f)
|
|
139
|
-
print(f" num_optimized_structs: {num_opt_str}", file=f)
|
|
140
|
-
print(f" num_unique_structs: {len(unique_structs)}", file=f)
|
|
141
|
-
print("", file=f)
|
|
142
|
-
|
|
143
134
|
energies = np.array([s.energy for s in unique_structs])
|
|
144
135
|
distances = np.array([s.least_distance for s in unique_structs])
|
|
145
136
|
|
|
146
137
|
sort_idx = np.argsort(energies)
|
|
147
138
|
unique_str_sorted = [unique_structs[i] for i in sort_idx]
|
|
139
|
+
if self.thresholds is not None:
|
|
140
|
+
e_min = None
|
|
141
|
+
for idx, u in enumerate(unique_str_sorted):
|
|
142
|
+
if e_min is None:
|
|
143
|
+
e_min = u.energy
|
|
144
|
+
if u.energy - e_min > self.thresholds[0] * 0.001:
|
|
145
|
+
unique_str_sorted = unique_str_sorted[:idx]
|
|
146
|
+
break
|
|
147
|
+
output_file = f"{composition_tag}_{self.thresholds[0]}"
|
|
148
|
+
else:
|
|
149
|
+
output_file = composition_tag
|
|
148
150
|
|
|
149
151
|
if not self.parse_vasp:
|
|
150
152
|
os.makedirs("ghost_minima", exist_ok=True)
|
|
@@ -160,19 +162,27 @@ class RSSResultSummarizer:
|
|
|
160
162
|
else:
|
|
161
163
|
is_ghost_minima = None
|
|
162
164
|
|
|
165
|
+
with open(output_file + ".yaml", "w") as f:
|
|
166
|
+
print("general_information:", file=f)
|
|
167
|
+
print(f" sorting_time_sec: {round(time_finish, 2)}", file=f)
|
|
168
|
+
print(f" pressure_GPa: {self.pressure}", file=f)
|
|
169
|
+
print(f" num_optimized_structs: {num_opt_str}", file=f)
|
|
170
|
+
print(f" num_unique_structs: {len(unique_structs)}", file=f)
|
|
171
|
+
print("", file=f)
|
|
172
|
+
|
|
163
173
|
rss_result_all = log_unique_structures(
|
|
164
|
-
|
|
174
|
+
output_file + ".yaml",
|
|
165
175
|
unique_str_sorted,
|
|
166
176
|
is_ghost_minima,
|
|
167
177
|
pressure=self.pressure,
|
|
168
178
|
)
|
|
169
179
|
|
|
170
|
-
with open(f"json/{
|
|
180
|
+
with open(f"json/{output_file}.json", "w") as f:
|
|
171
181
|
json.dump(rss_result_all, f)
|
|
172
182
|
|
|
173
183
|
if self.thresholds is not None or self.output_poscar is not False:
|
|
174
184
|
self.generate_poscars(
|
|
175
|
-
f"json/{
|
|
185
|
+
f"json/{output_file}.json",
|
|
176
186
|
thresholds=self.thresholds,
|
|
177
187
|
output_poscar=self.output_poscar,
|
|
178
188
|
)
|
|
@@ -188,6 +198,13 @@ class RSSResultSummarizer:
|
|
|
188
198
|
print(f"Composition {composition_tag}: summarizing...")
|
|
189
199
|
self.analyzer = UniqueStructureAnalyzer()
|
|
190
200
|
|
|
201
|
+
if not self.parse_vasp:
|
|
202
|
+
axis_tol = 0.03
|
|
203
|
+
pos_tol = 0.03
|
|
204
|
+
else:
|
|
205
|
+
axis_tol = 0.1
|
|
206
|
+
pos_tol = 0.1
|
|
207
|
+
|
|
191
208
|
time_start = time()
|
|
192
209
|
for res_path in res_paths:
|
|
193
210
|
print(f" - Processing result file (parent): {res_path}")
|
|
@@ -195,8 +212,8 @@ class RSSResultSummarizer:
|
|
|
195
212
|
results_same_comp[composition_tag][res_path],
|
|
196
213
|
standardize_axis=True,
|
|
197
214
|
keep_unique=True,
|
|
198
|
-
axis_tol=
|
|
199
|
-
pos_tol=
|
|
215
|
+
axis_tol=axis_tol,
|
|
216
|
+
pos_tol=pos_tol,
|
|
200
217
|
)
|
|
201
218
|
time_finish = time() - time_start
|
|
202
219
|
|
|
@@ -333,7 +350,7 @@ class RSSResultSummarizer:
|
|
|
333
350
|
|
|
334
351
|
for res in rss_results:
|
|
335
352
|
if threshold is not None:
|
|
336
|
-
diff =
|
|
353
|
+
diff = res["energy"] - e_min
|
|
337
354
|
if diff * 1000 > threshold:
|
|
338
355
|
continue
|
|
339
356
|
|
|
@@ -348,11 +365,10 @@ class RSSResultSummarizer:
|
|
|
348
365
|
shutil.copy(poscar_path, dest)
|
|
349
366
|
else:
|
|
350
367
|
try:
|
|
351
|
-
|
|
368
|
+
polymlp_st = Vasprun(res["struct_path"]).structure
|
|
352
369
|
except Exception:
|
|
353
370
|
print(res["struct_path"], "failed")
|
|
354
371
|
continue
|
|
355
|
-
polymlp_st = vaspobj.structure
|
|
356
372
|
write_poscar_file(polymlp_st, filename=dest)
|
|
357
373
|
shutil.copy(res["struct_path"], dest_vasp)
|
|
358
374
|
else:
|
|
@@ -368,12 +384,16 @@ class RSSResultSummarizer:
|
|
|
368
384
|
|
|
369
385
|
def resolve_path(base: Path, p):
|
|
370
386
|
cwd = Path.cwd()
|
|
387
|
+
target = Path(p)
|
|
371
388
|
if p is None:
|
|
372
389
|
return None
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
390
|
+
if not self.parse_vasp:
|
|
391
|
+
p = Path(p)
|
|
392
|
+
target = (
|
|
393
|
+
base / p
|
|
394
|
+
if "opt_struct" in p.parts
|
|
395
|
+
else base / "opt_struct" / p.name
|
|
396
|
+
)
|
|
377
397
|
return os.path.relpath(target, start=cwd)
|
|
378
398
|
|
|
379
399
|
paths_same_comp = defaultdict(list)
|
|
@@ -418,24 +438,21 @@ class RSSResultSummarizer:
|
|
|
418
438
|
"dupstr_paths": None,
|
|
419
439
|
}
|
|
420
440
|
try:
|
|
421
|
-
|
|
441
|
+
polymlp_st, (energy_dft, _, _) = parse_properties_from_vasprun(
|
|
442
|
+
path_name + "/vasprun.xml",
|
|
443
|
+
)
|
|
422
444
|
except Exception:
|
|
423
445
|
print("ParseError:", path_name + "/vasprun.xml")
|
|
424
446
|
continue
|
|
425
447
|
|
|
426
|
-
polymlp_st = vaspobj.structure
|
|
427
|
-
objprop = PropUtil(polymlp_st.axis.T, polymlp_st.positions.T)
|
|
428
|
-
spg_list = objprop.analyze_space_group(polymlp_st.elements)
|
|
429
|
-
|
|
430
|
-
energy_dft = vaspobj.energy
|
|
431
|
-
for element in polymlp_st.elements:
|
|
432
|
-
energy_dft -= atomic_energy(element)
|
|
433
448
|
energy_dft /= len(polymlp_st.elements)
|
|
434
|
-
|
|
435
449
|
if energy_dft < -10:
|
|
436
450
|
print(path_name, "exhibits an unphysically low energy. Skipping.")
|
|
437
451
|
continue
|
|
438
452
|
|
|
453
|
+
objprop = PropUtil(polymlp_st.axis.T, polymlp_st.positions.T)
|
|
454
|
+
spg_list = objprop.analyze_space_group(polymlp_st.elements)
|
|
455
|
+
|
|
439
456
|
res_dict["struct_path"] = os.path.relpath(
|
|
440
457
|
path_name + "/vasprun.xml", os.getcwd()
|
|
441
458
|
)
|
{rsspolymlp-0.3.4 → rsspolymlp-0.4.0}/src/rsspolymlp/analysis/struct_matcher/struct_match.py
RENAMED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
import math
|
|
1
2
|
import re
|
|
2
3
|
from collections import Counter
|
|
4
|
+
from contextlib import redirect_stdout
|
|
3
5
|
from dataclasses import dataclass
|
|
4
6
|
from typing import Optional
|
|
5
7
|
|
|
6
8
|
import numpy as np
|
|
7
9
|
|
|
8
10
|
from pypolymlp.core.data_format import PolymlpStructure
|
|
9
|
-
from pypolymlp.core.interface_vasp import Poscar
|
|
10
11
|
from pypolymlp.utils.vasp_utils import write_poscar_file
|
|
11
12
|
from rsspolymlp.analysis.struct_matcher.reduced_position import StructRepReducer
|
|
12
13
|
from rsspolymlp.common.composition import compute_composition
|
|
14
|
+
from rsspolymlp.common.interface_vasp import Poscar
|
|
13
15
|
from rsspolymlp.utils.spglib_utils import SymCell
|
|
14
16
|
|
|
15
17
|
|
|
@@ -30,6 +32,7 @@ def struct_match(
|
|
|
30
32
|
pos_tol: float = 0.01,
|
|
31
33
|
spg_match: bool = True,
|
|
32
34
|
verbose: bool = False,
|
|
35
|
+
output_file: str = "struct_matcher.yaml",
|
|
33
36
|
) -> bool:
|
|
34
37
|
"""
|
|
35
38
|
Determine whether two sets of ReducedStructRep objects are structurally
|
|
@@ -111,40 +114,64 @@ def struct_match(
|
|
|
111
114
|
|
|
112
115
|
if verbose:
|
|
113
116
|
|
|
114
|
-
def log_axis_positions(symprec, axis, positions):
|
|
117
|
+
def log_axis_positions(symprec, axis, positions, round_axis=4, round_pos=3):
|
|
115
118
|
print(" - symprec:", np.round(symprec, 5).tolist())
|
|
116
|
-
print(" metric_tensor:", np.round(axis,
|
|
119
|
+
print(" metric_tensor:", np.round(axis, round_axis).tolist())
|
|
117
120
|
print(" positions:")
|
|
118
|
-
for
|
|
119
|
-
|
|
120
|
-
):
|
|
121
|
-
formatted = ",".join(f"{val:6.3f}" for val in p)
|
|
121
|
+
for p in positions.reshape(3, -1).tolist():
|
|
122
|
+
formatted = ",".join(f"{val:{round_pos + 3}.{round_pos}f}" for val in p)
|
|
122
123
|
print(f" - [{formatted}]")
|
|
123
124
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
125
|
+
with open(output_file, "w") as f, redirect_stdout(f):
|
|
126
|
+
print("tolerance:")
|
|
127
|
+
print(" axis_tol:", axis_tol)
|
|
128
|
+
print(" pos_tol:", pos_tol)
|
|
129
|
+
print("structures:")
|
|
130
|
+
for i, st_set in enumerate([st_1_set, st_2_set]):
|
|
131
|
+
print(f" - struct_No: {i + 1}")
|
|
132
|
+
for st in st_set:
|
|
133
|
+
print(" spg_number:", st.spg_number)
|
|
134
|
+
print(" representations:")
|
|
135
|
+
for h, pos in enumerate(st.positions):
|
|
136
|
+
log_axis_positions(st.symprec_set[h], st.axis[h], pos)
|
|
137
|
+
print("min_axis_l2_norm:", np.round(min_axis_l2_norm, 3))
|
|
138
|
+
if axis_d_min is not None:
|
|
139
|
+
x_axis = abs(float(axis_d_min[0]))
|
|
140
|
+
if x_axis <= 1e-12:
|
|
141
|
+
round_axis = 6
|
|
142
|
+
else:
|
|
143
|
+
round_axis = min(-math.floor(math.log10(x_axis)) + 1, 6)
|
|
144
|
+
x_pos = abs(float(pos_d_min[0]))
|
|
145
|
+
if x_pos <= 1e-12:
|
|
146
|
+
round_pos = 6
|
|
147
|
+
else:
|
|
148
|
+
round_pos = min(-math.floor(math.log10(x_pos)) + 1, 6)
|
|
149
|
+
|
|
150
|
+
print("difference_log:")
|
|
151
|
+
print(" - axis_l2_norm:", np.round(axis_d_min[0], round_axis))
|
|
152
|
+
print(" pos_max_abs:", np.round(pos_d_min[0], round_pos))
|
|
153
|
+
print(" structure_1:")
|
|
154
|
+
log_axis_positions(
|
|
155
|
+
pos_d_min[1][0],
|
|
156
|
+
axis_d_min[1][0],
|
|
157
|
+
pos_d_min[1][1],
|
|
158
|
+
round_axis,
|
|
159
|
+
round_pos,
|
|
160
|
+
)
|
|
161
|
+
print(" structure_2:")
|
|
162
|
+
log_axis_positions(
|
|
163
|
+
pos_d_min[1][2],
|
|
164
|
+
axis_d_min[1][1],
|
|
165
|
+
pos_d_min[1][3],
|
|
166
|
+
round_axis,
|
|
167
|
+
round_pos,
|
|
168
|
+
)
|
|
169
|
+
print(" diffs:")
|
|
170
|
+
log_axis_positions(
|
|
171
|
+
[], axis_d_min[1][2], pos_d_min[1][4], round_axis, round_pos
|
|
172
|
+
)
|
|
173
|
+
print("Match:", struct_match)
|
|
174
|
+
print(f"{output_file} is generated.")
|
|
148
175
|
|
|
149
176
|
return struct_match
|
|
150
177
|
|
|
@@ -153,6 +180,7 @@ def generate_primitive_cells(
|
|
|
153
180
|
poscar_name: Optional[str] = None,
|
|
154
181
|
polymlp_st: Optional[PolymlpStructure] = None,
|
|
155
182
|
symprec_set: list[float] = [1e-5, 1e-4, 1e-3, 1e-2],
|
|
183
|
+
refine_cell: bool = False,
|
|
156
184
|
) -> tuple[list[PolymlpStructure], list[int]]:
|
|
157
185
|
"""
|
|
158
186
|
Generate primitive cells of a given structure under different symmetry tolerances.
|
|
@@ -189,7 +217,10 @@ def generate_primitive_cells(
|
|
|
189
217
|
continue
|
|
190
218
|
else:
|
|
191
219
|
try:
|
|
192
|
-
|
|
220
|
+
if not refine_cell:
|
|
221
|
+
primitive_st = symutil.primitive_cell()
|
|
222
|
+
else:
|
|
223
|
+
primitive_st = symutil.refine_cell()
|
|
193
224
|
except TypeError:
|
|
194
225
|
continue
|
|
195
226
|
primitive_st_set.append(primitive_st)
|
|
@@ -6,7 +6,7 @@ import joblib
|
|
|
6
6
|
import numpy as np
|
|
7
7
|
|
|
8
8
|
from pypolymlp.core.data_format import PolymlpStructure
|
|
9
|
-
from
|
|
9
|
+
from rsspolymlp.common.interface_vasp import Poscar
|
|
10
10
|
from rsspolymlp.analysis.struct_matcher.struct_match import (
|
|
11
11
|
ReducedStructRep,
|
|
12
12
|
generate_primitive_cells,
|
|
@@ -430,11 +430,11 @@ def log_all_unique_structures(
|
|
|
430
430
|
with open(file_name, "a") as f:
|
|
431
431
|
print("unique_structures:", file=f)
|
|
432
432
|
for idx1, _str in enumerate(unique_structs):
|
|
433
|
-
print(f" - struct_No: {idx1+1}", file=f)
|
|
433
|
+
print(f" - struct_No: {idx1 + 1}", file=f)
|
|
434
434
|
print(" structures:", file=f)
|
|
435
435
|
for idx2, _str in enumerate(unique_structs[idx1]):
|
|
436
|
-
print(f" - sub_struct_No: '{idx1+1}_{idx2+1}'", file=f)
|
|
437
|
-
print(f"
|
|
436
|
+
print(f" - sub_struct_No: '{idx1 + 1}_{idx2 + 1}'", file=f)
|
|
437
|
+
print(f" struct_path: {_str.struct_path}", file=f)
|
|
438
438
|
print(f" pressure: {_str.pressure}", file=f)
|
|
439
439
|
print(f" enthalpy: {_str.energy}", file=f)
|
|
440
440
|
print(f" axis: {_str.axis_abc}", file=f)
|
|
@@ -460,7 +460,7 @@ def log_all_unique_structures(
|
|
|
460
460
|
_res["energy"] = _str.energy
|
|
461
461
|
_res["pressure"] = None
|
|
462
462
|
_res["spg_list"] = _str.spg_list
|
|
463
|
-
_res["struct_no"] = f"{idx1 + 1}_{idx2+1}"
|
|
463
|
+
_res["struct_no"] = f"{idx1 + 1}_{idx2 + 1}"
|
|
464
464
|
_res["is_ghost_minima"] = False
|
|
465
465
|
rss_results.append(_res)
|
|
466
466
|
if unique_structs_prop is not None:
|
|
@@ -4,9 +4,9 @@ from rsspolymlp.api.rsspolymlp import (
|
|
|
4
4
|
rss_ghost_minima_cands,
|
|
5
5
|
rss_ghost_minima_validate,
|
|
6
6
|
rss_init_struct,
|
|
7
|
+
rss_opt,
|
|
7
8
|
rss_phase_analysis,
|
|
8
9
|
rss_polymlp,
|
|
9
|
-
rss_run_parallel,
|
|
10
10
|
rss_summarize,
|
|
11
11
|
rss_uniq_struct,
|
|
12
12
|
)
|
|
@@ -21,9 +21,9 @@ def run():
|
|
|
21
21
|
help="Mode: Initial random structure generation",
|
|
22
22
|
)
|
|
23
23
|
parser.add_argument(
|
|
24
|
-
"--
|
|
24
|
+
"--rss_opt",
|
|
25
25
|
action="store_true",
|
|
26
|
-
help="Mode: RSS using the polynomial MLP
|
|
26
|
+
help="Mode: RSS using the polynomial MLP",
|
|
27
27
|
)
|
|
28
28
|
parser.add_argument(
|
|
29
29
|
"--rss_single",
|
|
@@ -100,7 +100,7 @@ def run():
|
|
|
100
100
|
help="Minimum interatomic distance in initial structure (angstrom)",
|
|
101
101
|
)
|
|
102
102
|
|
|
103
|
-
# --
|
|
103
|
+
# --rss_opt mode
|
|
104
104
|
parser.add_argument(
|
|
105
105
|
"--pot",
|
|
106
106
|
nargs="*",
|
|
@@ -108,6 +108,12 @@ def run():
|
|
|
108
108
|
default=["polymlp.yaml"],
|
|
109
109
|
help="Potential file for polynomial MLP",
|
|
110
110
|
)
|
|
111
|
+
parser.add_argument(
|
|
112
|
+
"--init_poscars_dir",
|
|
113
|
+
type=str,
|
|
114
|
+
default="initial_struct",
|
|
115
|
+
help="Directory containing POSCARs describing initial structures",
|
|
116
|
+
)
|
|
111
117
|
parser.add_argument(
|
|
112
118
|
"--n_opt_str",
|
|
113
119
|
type=int,
|
|
@@ -131,6 +137,7 @@ def run():
|
|
|
131
137
|
parser.add_argument(
|
|
132
138
|
"--solver_method", type=str, default="CG", help="Type of solver"
|
|
133
139
|
)
|
|
140
|
+
parser.add_argument("--gtol", type=float, default=1e-6, help="")
|
|
134
141
|
parser.add_argument(
|
|
135
142
|
"--c_maxiter",
|
|
136
143
|
type=int,
|
|
@@ -260,12 +267,14 @@ def run():
|
|
|
260
267
|
max_volume=args.max_volume,
|
|
261
268
|
)
|
|
262
269
|
|
|
263
|
-
if args.
|
|
264
|
-
|
|
270
|
+
if args.rss_opt:
|
|
271
|
+
rss_opt(
|
|
265
272
|
pot=args.pot,
|
|
273
|
+
init_poscars_dir=args.init_poscars_dir,
|
|
266
274
|
pressure=args.pressure,
|
|
267
275
|
with_symmetry=args.symmetry,
|
|
268
276
|
solver_method=args.solver_method,
|
|
277
|
+
gtol=args.gtol,
|
|
269
278
|
c_maxiter=args.c_maxiter,
|
|
270
279
|
n_opt_str=args.n_opt_str,
|
|
271
280
|
not_stop_rss=args.not_stop_rss,
|
|
@@ -292,6 +301,7 @@ def run():
|
|
|
292
301
|
max_volume=args.max_volume,
|
|
293
302
|
least_distance=args.least_distance,
|
|
294
303
|
solver_method=args.solver_method,
|
|
304
|
+
gtol=args.gtol,
|
|
295
305
|
not_stop_rss=args.not_stop_rss,
|
|
296
306
|
num_process=args.num_process,
|
|
297
307
|
backend=args.backend,
|