rsspolymlp 0.4.1__tar.gz → 0.4.3__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.4.1/src/rsspolymlp.egg-info → rsspolymlp-0.4.3}/PKG-INFO +28 -22
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/README.md +28 -22
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/pyproject.toml +1 -1
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/analysis/rss_summarize.py +27 -28
- rsspolymlp-0.4.3/src/rsspolymlp/analysis/struct_matcher/assignment_algo.py +181 -0
- rsspolymlp-0.4.3/src/rsspolymlp/analysis/struct_matcher/gen_struct_rep.py +371 -0
- rsspolymlp-0.4.3/src/rsspolymlp/analysis/struct_matcher/identify_uniqstr.py +232 -0
- rsspolymlp-0.4.3/src/rsspolymlp/analysis/struct_matcher/redrep_lattice.py +144 -0
- rsspolymlp-0.4.3/src/rsspolymlp/analysis/struct_matcher/redrep_position.py +371 -0
- rsspolymlp-0.4.3/src/rsspolymlp/analysis/struct_matcher/struct_match.py +290 -0
- rsspolymlp-0.4.3/src/rsspolymlp/analysis/struct_matcher/test/gen_lattice.py +53 -0
- rsspolymlp-0.4.3/src/rsspolymlp/analysis/struct_matcher/test/time_measure.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/api/cli_rsspolymlp_utils.py +52 -40
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/api/rsspolymlp.py +2 -1
- rsspolymlp-0.4.3/src/rsspolymlp/api/rsspolymlp_utils.py +238 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/rss/eliminate_duplicates.py +9 -6
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/rss/random_struct.py +32 -7
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3/src/rsspolymlp.egg-info}/PKG-INFO +28 -22
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp.egg-info/SOURCES.txt +7 -3
- rsspolymlp-0.4.1/src/rsspolymlp/analysis/struct_matcher/gen_redrep.py +0 -338
- rsspolymlp-0.4.1/src/rsspolymlp/analysis/struct_matcher/invert_and_swap.py +0 -457
- rsspolymlp-0.4.1/src/rsspolymlp/analysis/struct_matcher/reduced_position.py +0 -366
- rsspolymlp-0.4.1/src/rsspolymlp/analysis/struct_matcher/struct_match.py +0 -331
- rsspolymlp-0.4.1/src/rsspolymlp/api/rsspolymlp_utils.py +0 -175
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/LICENSE +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/setup.cfg +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/__init__.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/analysis/__init__.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/analysis/eos.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/analysis/ghost_minima.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/analysis/phase_analysis.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/analysis/struct_matcher/__init__.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/analysis/struct_matcher/chiral_spg.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/api/__init__.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/api/cli_rsspolymlp.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/api/cli_rsspolymlp_devkit.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/api/cli_rsspolymlp_plot.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/api/rsspolymlp_devkit.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/api/rsspolymlp_plot.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/common/__init__.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/common/atomic_energy.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/common/composition.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/common/convert_dict.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/common/interface_vasp.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/common/property.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/mlp_dev/dataset/compress_vasprun.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/mlp_dev/dataset/gen_mlp_dataset.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/mlp_dev/dataset/split_dataset.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/mlp_dev/estimate_cost.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/mlp_dev/model_selection/binary/gen_single_model.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/mlp_dev/model_selection/elemental/gen_hybrid_model.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/mlp_dev/model_selection/elemental/gen_single_model.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/mlp_dev/model_selection/n_feature.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/mlp_dev/model_selection/pypolymlp_gridsearch.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/mlp_dev/model_selection/reduce_grid.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/mlp_dev/pareto_opt_mlp.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/mlp_dev/polymlp_dev.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/rss/__init__.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/rss/load_logfile.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/rss/optimization_mlp.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/__init__.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/lammps_utils.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/matplot_util/__init__.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/matplot_util/custom_plt.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/matplot_util/examples/__init__.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/matplot_util/examples/example.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/matplot_util/examples/template.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/matplot_util/make_plot.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/opt_sscha/opt_geometry_sscha.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/opt_sscha/opt_position_sscha.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/opt_sscha/run_opt_sscha.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/opt_sscha/sscha_property.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/pymatgen_utils.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/spglib_utils.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/vasp_util/__init__.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/vasp_util/api.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/vasp_util/gen_incar.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/vasp_util/gen_script.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp/utils/vasp_util/write_poscar.py +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp.egg-info/dependency_links.txt +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp.egg-info/entry_points.txt +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp.egg-info/requires.txt +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/src/rsspolymlp.egg-info/top_level.txt +0 -0
- {rsspolymlp-0.4.1 → rsspolymlp-0.4.3}/tests/test_cli_help.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rsspolymlp
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.3
|
|
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>
|
|
@@ -31,27 +31,9 @@ Dynamic: license-file
|
|
|
31
31
|
|
|
32
32
|
# Framework for random structure search using polynomial machine learning potentials
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
```
|
|
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}
|
|
53
|
-
}
|
|
54
|
-
```
|
|
34
|
+
`rsspolymlp` is a Python code designed to conduct random structure searches (RSS) using polynomial machine learning potentials (MLPs).
|
|
35
|
+
The code provides functionalities for generating initial random structures, performing geometry optimization using polynomial MLPs, and eliminating duplicate structures.
|
|
36
|
+
The formulation and development of polynomial MLPs are detailed in [`pypolymlp`](https://github.com/sekocha/pypolymlp).
|
|
55
37
|
|
|
56
38
|
## Installation
|
|
57
39
|
|
|
@@ -89,6 +71,7 @@ conda install -c conda-forge scikit-learn joblib pypolymlp spglib symfc
|
|
|
89
71
|
pip install rsspolymlp
|
|
90
72
|
```
|
|
91
73
|
|
|
74
|
+
|
|
92
75
|
## How to use rsspolymlp
|
|
93
76
|
|
|
94
77
|
- [Workflow of RSS with polynomial MLPs](docs/rsspolymlp.md)
|
|
@@ -107,3 +90,26 @@ pip install rsspolymlp
|
|
|
107
90
|
- Single-point calculation
|
|
108
91
|
- Local geometry optimization
|
|
109
92
|
- [Matplotlib utilities](src/rsspolymlp/utils/matplot_util/readme.md)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
## Citation of rsspolymlp
|
|
96
|
+
|
|
97
|
+
If you use `rsspolymlp` in your study, please cite the following articles.
|
|
98
|
+
|
|
99
|
+
“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)
|
|
100
|
+
```
|
|
101
|
+
@article{Phys.Rev.Mater.10.093801,
|
|
102
|
+
title = {Systematic global structure search of bismuth-based binary systems under pressure using machine learning potentials},
|
|
103
|
+
author = {Wakai, Hayato and Ishiwata, Shintaro and Seko, Atsuto},
|
|
104
|
+
journal = {Phys. Rev. Mater.},
|
|
105
|
+
volume = {10},
|
|
106
|
+
issue = {9},
|
|
107
|
+
pages = {093801},
|
|
108
|
+
numpages = {28},
|
|
109
|
+
year = {2026},
|
|
110
|
+
month = {Sep},
|
|
111
|
+
publisher = {American Physical Society},
|
|
112
|
+
doi = {10.1103/k9sg-v7hl},
|
|
113
|
+
url = {https://link.aps.org/doi/10.1103/k9sg-v7hl}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
@@ -1,26 +1,8 @@
|
|
|
1
1
|
# Framework for random structure search using polynomial machine learning potentials
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
```
|
|
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}
|
|
22
|
-
}
|
|
23
|
-
```
|
|
3
|
+
`rsspolymlp` is a Python code designed to conduct random structure searches (RSS) using polynomial machine learning potentials (MLPs).
|
|
4
|
+
The code provides functionalities for generating initial random structures, performing geometry optimization using polynomial MLPs, and eliminating duplicate structures.
|
|
5
|
+
The formulation and development of polynomial MLPs are detailed in [`pypolymlp`](https://github.com/sekocha/pypolymlp).
|
|
24
6
|
|
|
25
7
|
## Installation
|
|
26
8
|
|
|
@@ -58,6 +40,7 @@ conda install -c conda-forge scikit-learn joblib pypolymlp spglib symfc
|
|
|
58
40
|
pip install rsspolymlp
|
|
59
41
|
```
|
|
60
42
|
|
|
43
|
+
|
|
61
44
|
## How to use rsspolymlp
|
|
62
45
|
|
|
63
46
|
- [Workflow of RSS with polynomial MLPs](docs/rsspolymlp.md)
|
|
@@ -75,4 +58,27 @@ pip install rsspolymlp
|
|
|
75
58
|
- [VASP calculation utilities](src/rsspolymlp/utils/vasp_util/readme.md)
|
|
76
59
|
- Single-point calculation
|
|
77
60
|
- Local geometry optimization
|
|
78
|
-
- [Matplotlib utilities](src/rsspolymlp/utils/matplot_util/readme.md)
|
|
61
|
+
- [Matplotlib utilities](src/rsspolymlp/utils/matplot_util/readme.md)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
## Citation of rsspolymlp
|
|
65
|
+
|
|
66
|
+
If you use `rsspolymlp` in your study, please cite the following articles.
|
|
67
|
+
|
|
68
|
+
“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)
|
|
69
|
+
```
|
|
70
|
+
@article{Phys.Rev.Mater.10.093801,
|
|
71
|
+
title = {Systematic global structure search of bismuth-based binary systems under pressure using machine learning potentials},
|
|
72
|
+
author = {Wakai, Hayato and Ishiwata, Shintaro and Seko, Atsuto},
|
|
73
|
+
journal = {Phys. Rev. Mater.},
|
|
74
|
+
volume = {10},
|
|
75
|
+
issue = {9},
|
|
76
|
+
pages = {093801},
|
|
77
|
+
numpages = {28},
|
|
78
|
+
year = {2026},
|
|
79
|
+
month = {Sep},
|
|
80
|
+
publisher = {American Physical Society},
|
|
81
|
+
doi = {10.1103/k9sg-v7hl},
|
|
82
|
+
url = {https://link.aps.org/doi/10.1103/k9sg-v7hl}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
@@ -9,15 +9,14 @@ from time import time
|
|
|
9
9
|
from typing import Optional
|
|
10
10
|
|
|
11
11
|
import numpy as np
|
|
12
|
-
|
|
13
12
|
from pypolymlp.utils.vasp_utils import write_poscar_file
|
|
13
|
+
|
|
14
14
|
from rsspolymlp.analysis.ghost_minima import detect_ghost_minima
|
|
15
|
-
from rsspolymlp.analysis.struct_matcher.
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
from rsspolymlp.analysis.struct_matcher.gen_struct_rep import (
|
|
16
|
+
StructRepGenerator,
|
|
17
|
+
StructReps,
|
|
18
18
|
)
|
|
19
|
-
from rsspolymlp.analysis.struct_matcher.
|
|
20
|
-
UniqueStructIdentifier,
|
|
19
|
+
from rsspolymlp.analysis.struct_matcher.identify_uniqstr import (
|
|
21
20
|
identify_unique_structure,
|
|
22
21
|
)
|
|
23
22
|
from rsspolymlp.common.composition import compute_composition
|
|
@@ -58,7 +57,7 @@ class RSSResultSummarizer:
|
|
|
58
57
|
self.update_parent = update_parent
|
|
59
58
|
|
|
60
59
|
self.pressure = None
|
|
61
|
-
self.analyzer =
|
|
60
|
+
self.analyzer = None
|
|
62
61
|
|
|
63
62
|
def run_summarize(self):
|
|
64
63
|
os.makedirs("json", exist_ok=True)
|
|
@@ -92,8 +91,6 @@ class RSSResultSummarizer:
|
|
|
92
91
|
|
|
93
92
|
for comp_tag, res_paths in json_paths_c.items():
|
|
94
93
|
print(f"Composition {comp_tag}: summarizing...")
|
|
95
|
-
self.analyzer = UniqueStructIdentifier()
|
|
96
|
-
|
|
97
94
|
time_start = time()
|
|
98
95
|
|
|
99
96
|
processed_paths = set()
|
|
@@ -196,8 +193,6 @@ class RSSResultSummarizer:
|
|
|
196
193
|
|
|
197
194
|
for comp_tag, res_paths in json_paths_c.items():
|
|
198
195
|
print(f"Composition {comp_tag}: summarizing...")
|
|
199
|
-
self.analyzer = UniqueStructIdentifier()
|
|
200
|
-
|
|
201
196
|
if not self.parse_vasp:
|
|
202
197
|
axis_tol = 0.03
|
|
203
198
|
pos_tol = 0.03
|
|
@@ -210,7 +205,7 @@ class RSSResultSummarizer:
|
|
|
210
205
|
print(f" - Processing result file (parent): {res_path}")
|
|
211
206
|
self.analyzer = identify_unique_structure(
|
|
212
207
|
rss_results_c[comp_tag][res_path],
|
|
213
|
-
|
|
208
|
+
normalize_axis=True,
|
|
214
209
|
keep_unique=True,
|
|
215
210
|
axis_tol=axis_tol,
|
|
216
211
|
pos_tol=pos_tol,
|
|
@@ -264,15 +259,17 @@ class RSSResultSummarizer:
|
|
|
264
259
|
r["dupstr_paths"] = set(r["dupstr_paths"])
|
|
265
260
|
|
|
266
261
|
print(" - Converting reduced crystal structure representation...")
|
|
267
|
-
|
|
268
|
-
rss_results,
|
|
262
|
+
generator = StructRepGenerator(
|
|
269
263
|
num_process=self.num_process,
|
|
270
264
|
backend=self.backend,
|
|
271
|
-
|
|
265
|
+
primitive_symprecs=self.primitive_symprecs,
|
|
266
|
+
)
|
|
267
|
+
struct_reps_list = generator.generate_struct_reps_parallel(
|
|
268
|
+
rss_results,
|
|
272
269
|
)
|
|
273
270
|
if self.update_parent:
|
|
274
271
|
print(" - Eliminating duplicate structures...")
|
|
275
|
-
for idx, redreps in enumerate(
|
|
272
|
+
for idx, redreps in enumerate(struct_reps_list):
|
|
276
273
|
self.analyzer.identify_duplicate_struct(
|
|
277
274
|
unique_struct=redreps,
|
|
278
275
|
other_properties=rss_results[idx],
|
|
@@ -280,7 +277,7 @@ class RSSResultSummarizer:
|
|
|
280
277
|
pos_tol=0.03,
|
|
281
278
|
)
|
|
282
279
|
else:
|
|
283
|
-
self.analyzer._initialize_unique_structs(
|
|
280
|
+
self.analyzer._initialize_unique_structs(struct_reps_list, rss_results)
|
|
284
281
|
|
|
285
282
|
return set(processed_paths)
|
|
286
283
|
|
|
@@ -461,21 +458,22 @@ class RSSResultSummarizer:
|
|
|
461
458
|
|
|
462
459
|
def dump_json_rss_results(
|
|
463
460
|
file_name: str,
|
|
464
|
-
|
|
461
|
+
struct_reps_list: list[StructReps],
|
|
465
462
|
enthalpy_lists: list[float],
|
|
466
463
|
is_ghost_minima=None,
|
|
467
464
|
pressure=None,
|
|
468
465
|
):
|
|
469
466
|
if is_ghost_minima is None:
|
|
470
|
-
is_ghost_minima = np.full_like(
|
|
467
|
+
is_ghost_minima = np.full_like(struct_reps_list, False, dtype=bool)
|
|
471
468
|
|
|
472
469
|
rss_results = []
|
|
473
|
-
for idx, _str in enumerate(
|
|
470
|
+
for idx, _str in enumerate(struct_reps_list):
|
|
474
471
|
polymlp_st = _str.original_polymlp_st
|
|
475
472
|
objprop = PropUtil(polymlp_st.axis.T, polymlp_st.positions.T)
|
|
476
473
|
rss_results.append(
|
|
477
474
|
{
|
|
478
475
|
"struct_path": _str.struct_path,
|
|
476
|
+
"poscar_path": _str.struct_path,
|
|
479
477
|
"structure": polymlp_struct_to_dict(polymlp_st),
|
|
480
478
|
"energy": enthalpy_lists[idx],
|
|
481
479
|
"axis_abc": objprop.abc,
|
|
@@ -487,8 +485,8 @@ def dump_json_rss_results(
|
|
|
487
485
|
"is_ghost_minima": bool(is_ghost_minima[idx]),
|
|
488
486
|
}
|
|
489
487
|
)
|
|
490
|
-
if len(
|
|
491
|
-
comp_res = compute_composition(
|
|
488
|
+
if len(struct_reps_list) > 0:
|
|
489
|
+
comp_res = compute_composition(struct_reps_list[0].original_polymlp_st.elements)
|
|
492
490
|
rss_result_all = {
|
|
493
491
|
"elements": comp_res.unique_elements.tolist(),
|
|
494
492
|
"comp_ratio": comp_res.comp_ratio,
|
|
@@ -507,13 +505,13 @@ def dump_json_rss_results(
|
|
|
507
505
|
|
|
508
506
|
def log_unique_structures(
|
|
509
507
|
file_name: str,
|
|
510
|
-
|
|
508
|
+
struct_reps_list: list[StructReps],
|
|
511
509
|
enthalpy_lists: Optional[list[float]] = None,
|
|
512
510
|
is_ghost_minima=None,
|
|
513
511
|
unique_struct_iters=None,
|
|
514
512
|
):
|
|
515
513
|
if is_ghost_minima is None:
|
|
516
|
-
is_ghost_minima = np.full_like(
|
|
514
|
+
is_ghost_minima = np.full_like(struct_reps_list, False, dtype=bool)
|
|
517
515
|
energy_min = None
|
|
518
516
|
if enthalpy_lists is not None:
|
|
519
517
|
for i in range(len(enthalpy_lists)):
|
|
@@ -522,9 +520,10 @@ def log_unique_structures(
|
|
|
522
520
|
break
|
|
523
521
|
|
|
524
522
|
struct_num_max = max(
|
|
525
|
-
(_s.struct_tag for _s in
|
|
523
|
+
(_s.struct_tag for _s in struct_reps_list if _s.struct_tag is not None),
|
|
524
|
+
default=0,
|
|
526
525
|
)
|
|
527
|
-
for _s in
|
|
526
|
+
for _s in struct_reps_list:
|
|
528
527
|
if _s.struct_tag is None:
|
|
529
528
|
struct_num_max += 1
|
|
530
529
|
_s.struct_tag = struct_num_max
|
|
@@ -532,7 +531,7 @@ def log_unique_structures(
|
|
|
532
531
|
with open(file_name, "a") as f:
|
|
533
532
|
print("unique_structures:", file=f)
|
|
534
533
|
for is_ghost in [False, True]:
|
|
535
|
-
for idx, _str in enumerate(
|
|
534
|
+
for idx, _str in enumerate(struct_reps_list):
|
|
536
535
|
if energy_min is not None:
|
|
537
536
|
e_diff = round((enthalpy_lists[idx] - energy_min) * 1000, 2)
|
|
538
537
|
if (not is_ghost and e_diff < -300) or (
|
|
@@ -579,7 +578,7 @@ def log_unique_structures(
|
|
|
579
578
|
|
|
580
579
|
def log_all_unique_structures(
|
|
581
580
|
file_name,
|
|
582
|
-
unique_structs: list[list[
|
|
581
|
+
unique_structs: list[list[StructReps]],
|
|
583
582
|
unique_str_prop: Optional[list[list[dict]]] = None,
|
|
584
583
|
unique_other_prop=None,
|
|
585
584
|
):
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import time
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from scipy.sparse import csr_array
|
|
5
|
+
from scipy.sparse.csgraph import maximum_bipartite_matching
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def sort_match_screen(
|
|
9
|
+
pos_reps1: np.ndarray,
|
|
10
|
+
pos_reps2: np.ndarray,
|
|
11
|
+
elements1: np.ndarray,
|
|
12
|
+
elements2: np.ndarray,
|
|
13
|
+
axis_abc: np.ndarray,
|
|
14
|
+
pos_tol: float,
|
|
15
|
+
verbose: bool = False,
|
|
16
|
+
):
|
|
17
|
+
# pos1: (N1, n_atoms, 3)
|
|
18
|
+
# pos2: (N2, n_atoms, 3)
|
|
19
|
+
if len(elements1) != len(elements2):
|
|
20
|
+
return np.zeros((len(pos_reps1), len(pos_reps2)), dtype=bool)
|
|
21
|
+
unique_elements = np.unique(elements1)
|
|
22
|
+
|
|
23
|
+
def sort_positions_axis(pos_reps, elements, axis):
|
|
24
|
+
pos_reps = np.asarray(pos_reps)
|
|
25
|
+
sorted_reps = np.empty_like(pos_reps[:, :, axis])
|
|
26
|
+
start = 0
|
|
27
|
+
for el in unique_elements:
|
|
28
|
+
idx = np.flatnonzero(elements == el)
|
|
29
|
+
n = len(idx)
|
|
30
|
+
sorted_reps[:, start : start + n] = np.sort(
|
|
31
|
+
pos_reps[:, idx, axis],
|
|
32
|
+
axis=1,
|
|
33
|
+
)
|
|
34
|
+
start += n
|
|
35
|
+
return sorted_reps
|
|
36
|
+
|
|
37
|
+
matched = np.ones(
|
|
38
|
+
(len(pos_reps1), len(pos_reps2)),
|
|
39
|
+
dtype=bool,
|
|
40
|
+
)
|
|
41
|
+
for axis in range(3):
|
|
42
|
+
rows, cols = np.where(matched)
|
|
43
|
+
if len(rows) == 0:
|
|
44
|
+
break
|
|
45
|
+
|
|
46
|
+
t_start_s = time.time()
|
|
47
|
+
pos1_axis = sort_positions_axis(pos_reps1, elements1, axis)
|
|
48
|
+
pos2_axis = sort_positions_axis(pos_reps2, elements2, axis)
|
|
49
|
+
if verbose:
|
|
50
|
+
print(f"code: sort_match_screen (axis {axis})")
|
|
51
|
+
print(f" Sorting: {round((time.time() - t_start_s) * 1000, 2)} ms")
|
|
52
|
+
|
|
53
|
+
t_start_m = time.time()
|
|
54
|
+
diff = pos1_axis[rows] - pos2_axis[cols]
|
|
55
|
+
diff -= axis_abc[axis] * np.round(diff / axis_abc[axis])
|
|
56
|
+
matched[rows, cols] = np.all(np.abs(diff) <= pos_tol, axis=1)
|
|
57
|
+
if verbose:
|
|
58
|
+
print(f" Matching: {round((time.time() - t_start_m) * 1000, 2)} ms")
|
|
59
|
+
print(f" Candidate matches: {np.count_nonzero(matched)}")
|
|
60
|
+
return matched
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def greedy_match(
|
|
64
|
+
pos1: np.ndarray,
|
|
65
|
+
pos2: np.ndarray,
|
|
66
|
+
elements1: np.ndarray,
|
|
67
|
+
elements2: np.ndarray,
|
|
68
|
+
axis_abc: np.ndarray,
|
|
69
|
+
pos_tol: float,
|
|
70
|
+
verbose: bool = False,
|
|
71
|
+
):
|
|
72
|
+
judge = True
|
|
73
|
+
inv_axis_abc = 1 / axis_abc
|
|
74
|
+
|
|
75
|
+
t_start_g = time.time()
|
|
76
|
+
for el in np.unique(elements1):
|
|
77
|
+
if not judge:
|
|
78
|
+
break
|
|
79
|
+
targets1 = np.where(elements1 == el)[0]
|
|
80
|
+
targets2 = np.where(elements2 == el)[0]
|
|
81
|
+
used = np.zeros(len(targets1), dtype=bool)
|
|
82
|
+
for i in targets1:
|
|
83
|
+
diff = np.abs(pos2[targets2] - pos1[i])
|
|
84
|
+
diff -= axis_abc * np.round(inv_axis_abc * diff)
|
|
85
|
+
diff_max = np.max(np.abs(diff), axis=1)
|
|
86
|
+
diff[used] = np.inf
|
|
87
|
+
j = np.argmin(diff_max)
|
|
88
|
+
if diff_max[j] >= pos_tol:
|
|
89
|
+
judge = False
|
|
90
|
+
break
|
|
91
|
+
used[j] = True
|
|
92
|
+
if verbose:
|
|
93
|
+
print("code: greedy_match")
|
|
94
|
+
print(f" Matching: {round((time.time() - t_start_g) * 1000, 2)} ms")
|
|
95
|
+
|
|
96
|
+
if judge:
|
|
97
|
+
return True
|
|
98
|
+
else:
|
|
99
|
+
return False
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def bottleneck_assignment(
|
|
103
|
+
pos1: np.ndarray,
|
|
104
|
+
pos2: np.ndarray,
|
|
105
|
+
elements1: np.ndarray,
|
|
106
|
+
elements2: np.ndarray,
|
|
107
|
+
axis_abc: np.ndarray,
|
|
108
|
+
pos_tol: float,
|
|
109
|
+
best_matching: bool = False,
|
|
110
|
+
verbose: bool = False,
|
|
111
|
+
):
|
|
112
|
+
inv_axis_abc = 1 / axis_abc
|
|
113
|
+
for el in np.unique(elements1):
|
|
114
|
+
targets1 = np.where(elements1 == el)[0]
|
|
115
|
+
targets2 = np.where(elements2 == el)[0]
|
|
116
|
+
pos1_sub = pos1[targets1]
|
|
117
|
+
pos2_sub = pos2[targets2]
|
|
118
|
+
|
|
119
|
+
t_start_d = time.time()
|
|
120
|
+
diff = pos1_sub[:, None, :] - pos2_sub[None, :, :]
|
|
121
|
+
diff -= axis_abc * np.round(diff * inv_axis_abc)
|
|
122
|
+
pos_d = np.max(np.abs(diff), axis=2)
|
|
123
|
+
n = pos_d.shape[0]
|
|
124
|
+
if verbose:
|
|
125
|
+
print("code: bottleneck_assignment")
|
|
126
|
+
print(
|
|
127
|
+
f" Difference Calc.: {round((time.time() - t_start_d) * 1000, 2)} ms"
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
t_start_m = time.time()
|
|
131
|
+
if best_matching:
|
|
132
|
+
# Sort distinct candidate distances
|
|
133
|
+
values = np.unique(pos_d)
|
|
134
|
+
left, right = 0, len(values) - 1
|
|
135
|
+
while left < right:
|
|
136
|
+
mid = (left + right) // 2
|
|
137
|
+
rows, cols = np.where(pos_d <= values[mid])
|
|
138
|
+
graph = csr_array(
|
|
139
|
+
(
|
|
140
|
+
np.ones(len(rows), dtype=np.int8),
|
|
141
|
+
(rows, cols),
|
|
142
|
+
),
|
|
143
|
+
shape=pos_d.shape,
|
|
144
|
+
)
|
|
145
|
+
matching = maximum_bipartite_matching(graph, perm_type="column")
|
|
146
|
+
if np.all(matching >= 0):
|
|
147
|
+
right = mid
|
|
148
|
+
else:
|
|
149
|
+
left = mid + 1
|
|
150
|
+
|
|
151
|
+
threshold = values[left]
|
|
152
|
+
rows, cols = np.where(pos_d <= threshold)
|
|
153
|
+
graph = csr_array(
|
|
154
|
+
(
|
|
155
|
+
np.ones(len(rows), dtype=np.int8),
|
|
156
|
+
(rows, cols),
|
|
157
|
+
),
|
|
158
|
+
shape=pos_d.shape,
|
|
159
|
+
)
|
|
160
|
+
matching = maximum_bipartite_matching(graph, perm_type="column")
|
|
161
|
+
pos_max_diffs = pos_d[np.arange(n), matching].tolist()
|
|
162
|
+
if verbose:
|
|
163
|
+
print(f" Matching: {round((time.time() - t_start_m) * 1000, 2)} ms")
|
|
164
|
+
if max(pos_max_diffs) > pos_tol:
|
|
165
|
+
return False
|
|
166
|
+
else:
|
|
167
|
+
t_start_m = time.time()
|
|
168
|
+
rows, cols = np.where(pos_d <= pos_tol)
|
|
169
|
+
graph = csr_array(
|
|
170
|
+
(
|
|
171
|
+
np.ones(len(rows), dtype=np.int8),
|
|
172
|
+
(rows, cols),
|
|
173
|
+
),
|
|
174
|
+
shape=pos_d.shape,
|
|
175
|
+
)
|
|
176
|
+
matching = maximum_bipartite_matching(graph, perm_type="column")
|
|
177
|
+
if verbose:
|
|
178
|
+
print(f" Matching: {round((time.time() - t_start_m) * 1000, 2)} ms")
|
|
179
|
+
if not np.all(matching >= 0):
|
|
180
|
+
return False
|
|
181
|
+
return True
|