packmol-util 0.2.4__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.
- packmol_util-0.2.4/PKG-INFO +66 -0
- packmol_util-0.2.4/README.md +43 -0
- packmol_util-0.2.4/pyproject.toml +46 -0
- packmol_util-0.2.4/setup.cfg +4 -0
- packmol_util-0.2.4/src/__init__.py +0 -0
- packmol_util-0.2.4/src/packmol_util/__init__.py +3 -0
- packmol_util-0.2.4/src/packmol_util/builder.py +312 -0
- packmol_util-0.2.4/src/packmol_util/config.py +79 -0
- packmol_util-0.2.4/src/packmol_util/model.py +621 -0
- packmol_util-0.2.4/src/packmol_util/packmol.py +491 -0
- packmol_util-0.2.4/src/packmol_util/packmol_inp.py +252 -0
- packmol_util-0.2.4/src/packmol_util/param.py +100 -0
- packmol_util-0.2.4/src/packmol_util.egg-info/PKG-INFO +66 -0
- packmol_util-0.2.4/src/packmol_util.egg-info/SOURCES.txt +15 -0
- packmol_util-0.2.4/src/packmol_util.egg-info/dependency_links.txt +1 -0
- packmol_util-0.2.4/src/packmol_util.egg-info/requires.txt +15 -0
- packmol_util-0.2.4/src/packmol_util.egg-info/top_level.txt +2 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: packmol_util
|
|
3
|
+
Version: 0.2.4
|
|
4
|
+
Summary: using packmol
|
|
5
|
+
Author-email: Kengo NAKADA <kengo.nakada@email.com>
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: xlogger-py
|
|
9
|
+
Requires-Dist: dataclasses
|
|
10
|
+
Requires-Dist: coloredlogs
|
|
11
|
+
Requires-Dist: colorlog
|
|
12
|
+
Requires-Dist: pytest
|
|
13
|
+
Requires-Dist: pytest-asyncio
|
|
14
|
+
Requires-Dist: pyyaml
|
|
15
|
+
Requires-Dist: toml
|
|
16
|
+
Requires-Dist: nest_asyncio
|
|
17
|
+
Requires-Dist: sphinx
|
|
18
|
+
Requires-Dist: myst-parser
|
|
19
|
+
Requires-Dist: sphinx-autobuild
|
|
20
|
+
Requires-Dist: sphinx-rtd-theme
|
|
21
|
+
Requires-Dist: sphinxcontrib-napoleon
|
|
22
|
+
Requires-Dist: linkify-it-py
|
|
23
|
+
|
|
24
|
+
# packmol_util
|
|
25
|
+
[](https://github.com/shimane-dev/rmc_dft/blob/main/README.md)
|
|
26
|
+
[](https://github.com/shimane-dev/rmc_dft/blob/main/README.ja.md)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
A **Python utility kit for automatically generating amorphous initial structures (POSCAR)** for first-principles calculations (VASP) and molecular dynamics (MD) simulations using Packmol.
|
|
30
|
+
|
|
31
|
+
By specifying only the stoichiometric ratio, density (mass density or number density), and total number of atoms, this tool automatically completes the full workflow: generating the Packmol input file, running Packmol, and outputting a POSCAR in VASP format with Direct coordinates.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## ๐ก Features
|
|
36
|
+
|
|
37
|
+
1. **Intuitive density specification**
|
|
38
|
+
- Packmol itself does not interpret density or atomic weights, but this tool performs the required internal calculations and determines the cubic cell length $L$ that satisfies the specified density.
|
|
39
|
+
2. **Exclusion radius specification by element symbol**
|
|
40
|
+
- This hides Packmol's inconvenient atom-index-based specification inside XYZ files. Interatomic avoidance distances can be controlled using an intuitive element-name-based dictionary, such as `{"P": 0.25, "O": 1.05}`.
|
|
41
|
+
3. **Preservation of molecular units (geometries)**
|
|
42
|
+
- For systems such as $\text{Li}_3\text{PO}_4$, amorphization through mixing and packing can be performed while preserving intramolecular bond lengths, such as those in $\text{PO}_4$ tetrahedra.
|
|
43
|
+
4. **Extremely simple high-level API**
|
|
44
|
+
- By using `AmorphousBuilder`, the cumbersome file relay workflow (`.inp` construction $\rightarrow$ external execution $\rightarrow$ coordinate conversion) can be condensed into only a few lines of script.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## ๐ Directory structure
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
src/
|
|
52
|
+
โโโ packmol_util/
|
|
53
|
+
โ
|
|
54
|
+
โ โโโ __init__.py # Package initialization file
|
|
55
|
+
โ โโโ builder.py # High-level integrated builder (AmorphousBuilder) โ
NEW
|
|
56
|
+
โ โโโ model.py # Template XYZ generation and structure-definition module
|
|
57
|
+
โ โโโ packmol.py # Core density calculation, Packmol execution, and POSCAR conversion
|
|
58
|
+
โ โโโ packmol_inp.py # Parsing engine for constructing packmol.inp
|
|
59
|
+
โ โโโ param.py # Atomic weights and physical constants for the periodic table
|
|
60
|
+
|
|
61
|
+
โโโ example/ # Location for material-specific generation scripts
|
|
62
|
+
โโโ Li3PO4/
|
|
63
|
+
โ โโโ make_Li3PO4.py
|
|
64
|
+
โโโ FeSiB/
|
|
65
|
+
โโโ make_FeSiB.py
|
|
66
|
+
```
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# packmol_util
|
|
2
|
+
[](https://github.com/shimane-dev/rmc_dft/blob/main/README.md)
|
|
3
|
+
[](https://github.com/shimane-dev/rmc_dft/blob/main/README.ja.md)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
A **Python utility kit for automatically generating amorphous initial structures (POSCAR)** for first-principles calculations (VASP) and molecular dynamics (MD) simulations using Packmol.
|
|
7
|
+
|
|
8
|
+
By specifying only the stoichiometric ratio, density (mass density or number density), and total number of atoms, this tool automatically completes the full workflow: generating the Packmol input file, running Packmol, and outputting a POSCAR in VASP format with Direct coordinates.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## ๐ก Features
|
|
13
|
+
|
|
14
|
+
1. **Intuitive density specification**
|
|
15
|
+
- Packmol itself does not interpret density or atomic weights, but this tool performs the required internal calculations and determines the cubic cell length $L$ that satisfies the specified density.
|
|
16
|
+
2. **Exclusion radius specification by element symbol**
|
|
17
|
+
- This hides Packmol's inconvenient atom-index-based specification inside XYZ files. Interatomic avoidance distances can be controlled using an intuitive element-name-based dictionary, such as `{"P": 0.25, "O": 1.05}`.
|
|
18
|
+
3. **Preservation of molecular units (geometries)**
|
|
19
|
+
- For systems such as $\text{Li}_3\text{PO}_4$, amorphization through mixing and packing can be performed while preserving intramolecular bond lengths, such as those in $\text{PO}_4$ tetrahedra.
|
|
20
|
+
4. **Extremely simple high-level API**
|
|
21
|
+
- By using `AmorphousBuilder`, the cumbersome file relay workflow (`.inp` construction $\rightarrow$ external execution $\rightarrow$ coordinate conversion) can be condensed into only a few lines of script.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## ๐ Directory structure
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
src/
|
|
29
|
+
โโโ packmol_util/
|
|
30
|
+
โ
|
|
31
|
+
โ โโโ __init__.py # Package initialization file
|
|
32
|
+
โ โโโ builder.py # High-level integrated builder (AmorphousBuilder) โ
NEW
|
|
33
|
+
โ โโโ model.py # Template XYZ generation and structure-definition module
|
|
34
|
+
โ โโโ packmol.py # Core density calculation, Packmol execution, and POSCAR conversion
|
|
35
|
+
โ โโโ packmol_inp.py # Parsing engine for constructing packmol.inp
|
|
36
|
+
โ โโโ param.py # Atomic weights and physical constants for the periodic table
|
|
37
|
+
|
|
38
|
+
โโโ example/ # Location for material-specific generation scripts
|
|
39
|
+
โโโ Li3PO4/
|
|
40
|
+
โ โโโ make_Li3PO4.py
|
|
41
|
+
โโโ FeSiB/
|
|
42
|
+
โโโ make_FeSiB.py
|
|
43
|
+
```
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=71.0","coloredlogs"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "packmol_util"
|
|
7
|
+
version = "0.2.4"
|
|
8
|
+
|
|
9
|
+
description = "using packmol"
|
|
10
|
+
authors = [
|
|
11
|
+
{ name="Kengo NAKADA", email="kengo.nakada@email.com" },
|
|
12
|
+
]
|
|
13
|
+
readme = "README.md"
|
|
14
|
+
# requires-python = ">=3.8"
|
|
15
|
+
requires-python = ">=3.10"
|
|
16
|
+
dependencies = [
|
|
17
|
+
#"x_logger",
|
|
18
|
+
"xlogger-py",
|
|
19
|
+
"dataclasses",
|
|
20
|
+
"coloredlogs",
|
|
21
|
+
"colorlog",
|
|
22
|
+
"pytest",
|
|
23
|
+
"pytest-asyncio",
|
|
24
|
+
"pyyaml",
|
|
25
|
+
"toml",
|
|
26
|
+
# "grpcio",
|
|
27
|
+
"nest_asyncio",
|
|
28
|
+
"sphinx",
|
|
29
|
+
"myst-parser",
|
|
30
|
+
"sphinx-autobuild",
|
|
31
|
+
"sphinx-rtd-theme",
|
|
32
|
+
"sphinxcontrib-napoleon",
|
|
33
|
+
"linkify-it-py"
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[tool.pytest.ini_options]
|
|
37
|
+
pythonpath = ["src"]
|
|
38
|
+
|
|
39
|
+
# ใใใงpytestใฎiniใจๅใใใใซใชใใทใงใณใๆธใใ
|
|
40
|
+
# ไพใใฐใในใใใผใฏใใใฃใซใฟใใซใใฌใใธใชใฉใ่ฟฝ่จๅฏ่ฝ
|
|
41
|
+
|
|
42
|
+
[tool.black]
|
|
43
|
+
line-length = 88
|
|
44
|
+
|
|
45
|
+
[tool.isort]
|
|
46
|
+
profile = "black"
|
|
File without changes
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
packmol_util/builder.py
|
|
4
|
+
|
|
5
|
+
่ฉณ็ดฐใชใใกใคใซใฎใใฑใใชใฌใผใ้ ่ฝใใ
|
|
6
|
+
ๆฐ่กใงใขใขใซใใกในๆง้ ใไฝๆใใใใใฎ้ซใฌใใซ็ตฑๅใขใธใฅใผใซใ
|
|
7
|
+
|
|
8
|
+
ไปฅไธใฎ 3 ็นใๅค้จๅ
ฅๅใฎๅบๆบใจใใ๏ผ
|
|
9
|
+
1. ๅๅญฆ้่ซๆฏ๏ผๆดๆฐๆฏ๏ผ
|
|
10
|
+
2. ๅฏๅบฆ [g/cm^3] ใพใใฏ ๆฐๅฏๅบฆ [1/ร
^3] ใฎใใใใไธๆน
|
|
11
|
+
3. ใปใซๅ
ใฎ็ทๅๅญๆฐ total_atom_count
|
|
12
|
+
|
|
13
|
+
ใ้่ฆใๆๅฎใใ total_atom_count ใ ratios ใฎๅ่จใงๅฒใๅใใชใ๏ผ็ตๆๆฏใ็ถญๆใงใใชใ๏ผๅ ดๅใ
|
|
14
|
+
ใใญใฐใฉใ ใ็ ด็ถปใใใฎใ้ฒใใใใๆๅฎใใใๅๅญๆฐใซๆใ่ฟใใๅฒใๅใใ็ทๅๅญๆฐใใธ่ชๅ่ฃๆญฃใ่กใใ
|
|
15
|
+
ๅ
้จใง่จ็ฎใใใๅ
จไฝใฎในใฑใผใซๅ็๏ผmultiplier๏ผใๅค้จใซๅ
ฌ้๏ผใใญใใใฃๅ๏ผใใใใจใงใ
|
|
16
|
+
ๅฉ็จๅดใฎในใฏใชใใใใฆใใใๆงๆๅไฝใงใฎใใใญใณใฐๅๆฐใไธๅ
็ฎก็ใงใใใใใซ่จญ่จใใใฆใใใ
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from typing import Dict, List, Optional, Tuple
|
|
20
|
+
from packmol_util.packmol import Packmol
|
|
21
|
+
from packmol_util.packmol_inp import PackmolInp
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class AmorphousBuilder:
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
symbols: List[str],
|
|
29
|
+
ratios: List[int],
|
|
30
|
+
total_atom_count: int, # ๅธๆใใใใผในใฎ็ทๅๅญๆฐ
|
|
31
|
+
minimum_separation: float,
|
|
32
|
+
mass_density: Optional[float] = None,
|
|
33
|
+
number_density: Optional[float] = None,
|
|
34
|
+
packmol_bin: str = "packmol",
|
|
35
|
+
):
|
|
36
|
+
if len(symbols) != len(ratios):
|
|
37
|
+
raise ValueError("symbols ใจ ratios ใฎ้ทใใไธ่ดใใฆใใพใใใ")
|
|
38
|
+
|
|
39
|
+
if total_atom_count <= 0:
|
|
40
|
+
raise ValueError("total_atom_count ใฏๆญฃใฎๆดๆฐใงใใๅฟ
่ฆใใใใพใใ")
|
|
41
|
+
|
|
42
|
+
self.symbols = symbols
|
|
43
|
+
self.ratios = ratios
|
|
44
|
+
self.minimum_separation = minimum_separation
|
|
45
|
+
self.packmol_bin = packmol_bin
|
|
46
|
+
|
|
47
|
+
# --- ใ่ชๅ่ฃๆญฃใญใธใใฏใๆๅฎใงใใชใๆฏ็๏ผๅฒใๅใใชใๆฐ๏ผใฎใจใใฎ่ชๅ่ฃๆญฃ ---
|
|
48
|
+
ratio_sum = sum(ratios)
|
|
49
|
+
if total_atom_count % ratio_sum != 0:
|
|
50
|
+
# ๆใ่ฟใๆดๆฐๅ๏ผๅ็๏ผใ่จ็ฎ
|
|
51
|
+
multiplier = round(total_atom_count / ratio_sum)
|
|
52
|
+
if multiplier < 1:
|
|
53
|
+
multiplier = 1
|
|
54
|
+
adjusted_atom_count = ratio_sum * multiplier
|
|
55
|
+
print(
|
|
56
|
+
f"[Warning] ๆๅฎใใใ็ทๅๅญๆฐ {total_atom_count} ใฏ็ตๆๆฏใฎๅ่จ {ratio_sum} ใงๅฒใๅใใพใใใ"
|
|
57
|
+
)
|
|
58
|
+
print(
|
|
59
|
+
f" ็ตๆๆฏใ็ถญๆใใใใใ็ทๅๅญๆฐใ {adjusted_atom_count} (ๅ็: {multiplier}) ใซ่ชๅ่ชฟๆดใใพใใใ"
|
|
60
|
+
)
|
|
61
|
+
self.total_atom_count = adjusted_atom_count
|
|
62
|
+
self._multiplier = multiplier
|
|
63
|
+
else:
|
|
64
|
+
self.total_atom_count = total_atom_count
|
|
65
|
+
self._multiplier = total_atom_count // ratio_sum
|
|
66
|
+
|
|
67
|
+
# ๅฏๅบฆใฎ่จ็ฎใจใปใซไธ่พบใฎ้ทใๆฑบๅฎ
|
|
68
|
+
self.packmol_runner = Packmol()
|
|
69
|
+
if number_density is not None:
|
|
70
|
+
self.box_length = self.packmol_runner.cell_length_from_number_density(
|
|
71
|
+
self.total_atom_count, number_density
|
|
72
|
+
)
|
|
73
|
+
elif mass_density is not None:
|
|
74
|
+
n_density = self.packmol_runner.number_density_from_mass_density(
|
|
75
|
+
symbols, ratios, mass_density
|
|
76
|
+
)
|
|
77
|
+
self.box_length = self.packmol_runner.cell_length_from_number_density(
|
|
78
|
+
self.total_atom_count, n_density
|
|
79
|
+
)
|
|
80
|
+
else:
|
|
81
|
+
raise ValueError(
|
|
82
|
+
"mass_density ใพใใฏ number_density ใฎใฉใกใใใๆๅฎใใฆใใ ใใใ"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
self.templates: List[dict] = []
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def multiplier(self) -> int:
|
|
89
|
+
"""
|
|
90
|
+
ๅ
จไฝใฎๅๅญฆ้่ซๆฏใซๅฏพใใใปใซใฎในใฑใผใซๅ็ใ่ฟใใ
|
|
91
|
+
ๅฉ็จๅดใฎในใฏใชใใใฏใใใฎๅ็ใใฆใใใใฎ1ๅผใใใๆงๆๆฏใซไน็ฎใใใใจใงใ
|
|
92
|
+
Packmol ใซๅผใๆธกใในใๅฎ้ใฎ่ค่ฃฝๅๆฐ๏ผnumber๏ผใ็ฎๅบใใใ
|
|
93
|
+
"""
|
|
94
|
+
return self._multiplier
|
|
95
|
+
|
|
96
|
+
def add_template(
|
|
97
|
+
self,
|
|
98
|
+
xyz_file: str,
|
|
99
|
+
number: int, # ใใฎใใณใใฌใผใใ Packmol ใใปใซๅ
ใซไฝๅ้
็ฝฎใใใใ่กจใๅฎ้ใฎ่ค่ฃฝๅๆฐ
|
|
100
|
+
packing_radii: Optional[Dict[str, float]] = None,
|
|
101
|
+
fnc_pairs_in_template: Optional[List[Tuple[int, int, int]]] = None,
|
|
102
|
+
fnc_distance_ranges: Optional[Dict[int, Tuple[float, float]]] = None,
|
|
103
|
+
# packmolๅพใซใFNCไฝๆใงใฎๅฝข็ถๅบๅฎใฎ้ธๆ
|
|
104
|
+
fnc_output_constraint_types: Optional[List[int]] = None,
|
|
105
|
+
):
|
|
106
|
+
"""
|
|
107
|
+
Packmol ใฎ 1 ใคใฎ structure ใใญใใฏใซๅฏพๅฟใใใใณใใฌใผใๆ
ๅ ฑใ็ป้ฒใใใ
|
|
108
|
+
|
|
109
|
+
ๅผๆฐใฎ่ชฌๆ๏ผ
|
|
110
|
+
xyz_file: Packmol ใซๆธกใๅๅๅญใพใใฏๅๅญใฆใใใใใณใใฌใผใใฎๅบงๆจใใกใคใซๅ (.xyz)
|
|
111
|
+
number: ใใฎใใณใใฌใผใใไฝๅ่ค่ฃฝใใฆ้
็ฝฎใใใใๆๅฎใใ [int]
|
|
112
|
+
packing_radii: Packmol ้
็ฝฎๆใซไฝฟใๅ
็ด ่จๅทๅฅใฎๆ้คๅๅพใฎ่พๆธ๏ผไปปๆ๏ผใ
|
|
113
|
+
ๅๅญใฆใใใๅ
้จใฎ็ตๅ่ท้ขใๅฝข็ถใไฝใๅคใงใฏใชใใ
|
|
114
|
+
fnc_pairs_in_template: ใใณใใฌใผใๅ
ใฎๅฑๆๅๅญ็ชๅทใงๆๅฎใใ FNC ใใขใ
|
|
115
|
+
(local_i, local_j, constraint_type) ใฎใชในใใงๆๅฎใใใ
|
|
116
|
+
fnc_distance_ranges: FNC constraint type ใใจใฎ่ท้ข็ฏๅฒใ
|
|
117
|
+
{type: (rmin, rmax)} ใงๆๅฎใใใ
|
|
118
|
+
fnc_output_constraint_types: .fnc ใซๅฎ้ใซๅบๅใใ constraint type ใฎใชในใใ
|
|
119
|
+
None ใฎๅ ดๅใฏๅ
จ type ใๅบๅใใใ
|
|
120
|
+
ไพ: [1] ใๆๅฎใใใจ type 1 ใฎใใขใ ใใๅบๅใใใ
|
|
121
|
+
Packmol ็จ XYZ ใใณใใฌใผใใฎๅฝข็ถใ้
็ฝฎใซใฏๅฝฑ้ฟใใชใใ
|
|
122
|
+
"""
|
|
123
|
+
# builder ใงใฏใใใณใใฌใผใใใพใ Packmol ๅ
ฅๅใธๅคๆใใชใใ
|
|
124
|
+
# ใใใงใฏใใฉใฎ XYZ ใใณใใฌใผใใไฝๅ็ฝฎใใใใจใๅฟ
่ฆใชใ้
็ฝฎ็จ packing ๅๅพใ ใใไฟๅญใใใ
|
|
125
|
+
# ๅ
ทไฝ็ใช structure ... end structure ใธใฎๅคๆใฏ build() ๅ
ใฎ PackmolInp ใๆ
ๅฝใใใ
|
|
126
|
+
self.templates.append(
|
|
127
|
+
{
|
|
128
|
+
"xyz": xyz_file,
|
|
129
|
+
"number": number,
|
|
130
|
+
"radii": packing_radii,
|
|
131
|
+
"fnc_pairs_in_template": fnc_pairs_in_template,
|
|
132
|
+
"fnc_distance_ranges": fnc_distance_ranges,
|
|
133
|
+
# Packmol ใฏ xyz_file ใฎใใณใใฌใผใๅฝข็ถใใใฎใพใพ้
็ฝฎใใใ
|
|
134
|
+
# ใใฎๆๅฎใฏ Packmol ใซใฏๆธกใใใPackmol ๅพใซ .fnc ใไฝใๆฎต้ใ ใใงไฝฟใใ
|
|
135
|
+
# None: ๅ
จ FNC type ใๅบๅใใใ
|
|
136
|
+
# [1]: type 1 ใฎๆๆใ ใใ .fnc ใซๅบๅใใใ
|
|
137
|
+
"fnc_output_constraint_types": fnc_output_constraint_types,
|
|
138
|
+
}
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
def build(self, output_prefix: str, fnc_file: Optional[str] = None):
|
|
142
|
+
# output_prefix ใฏใไธ้ฃใฎ็ๆใใกใคใซๅใฎๆฅ้ ญ่พใจใใฆไฝฟใใ
|
|
143
|
+
# ไพ: output_prefix="Li3PO4" ใฎๅ ดๅใLi3PO4_packmol.inp / Li3PO4_packmol.xyz / Li3PO4_packmol.log ใไฝใใ
|
|
144
|
+
input_file = f"{output_prefix}_packmol.inp"
|
|
145
|
+
output_xyz = f"{output_prefix}_packmol.xyz"
|
|
146
|
+
output_log = f"{output_prefix}_packmol.log"
|
|
147
|
+
poscar_file = "POSCAR"
|
|
148
|
+
vasp_file = "POSCAR.vasp"
|
|
149
|
+
if fnc_file is None:
|
|
150
|
+
fnc_file = f"{output_prefix}.fnc"
|
|
151
|
+
|
|
152
|
+
# 1. PackmolInp ใๆง็ฏใใใ
|
|
153
|
+
# AmorphousBuilder ใๆใคๆ
ๅ ฑใฏ Python ๅดใฎๆฝ่ฑก่กจ็พใงใใใ
|
|
154
|
+
# PackmolInp ใฏใใใใ Packmol ใฎ .inp ๆๆณใธ่ฝใจใๅฝนๅฒใๆใคใ
|
|
155
|
+
inp_builder = PackmolInp(
|
|
156
|
+
minimum_separation_distance=self.minimum_separation,
|
|
157
|
+
output_xyz=output_xyz,
|
|
158
|
+
box_length=self.box_length,
|
|
159
|
+
use_pbc=True,
|
|
160
|
+
)
|
|
161
|
+
for t in self.templates:
|
|
162
|
+
# 1 ไปถใฎ template ใฏ Packmol ๅ
ฅๅใฎ 1 ใคใฎ structure ใใญใใฏใซๅฏพๅฟใใใ
|
|
163
|
+
# ๅๅๅญใใณใใฌใผใใงใ PO4 ใฎใใใชๅๅญใฆใใใใงใใใใใงใฏๅใ็ป้ฒๅฆ็ใ้ใใ
|
|
164
|
+
inp_builder.add_structure(
|
|
165
|
+
xyz_file=t["xyz"],
|
|
166
|
+
number=t["number"],
|
|
167
|
+
packing_radii_by_atom_symbol=t["radii"],
|
|
168
|
+
)
|
|
169
|
+
# ็ป้ฒใใ template ็พคใ Packmol ๅ
ฅๅใใกใคใซใจใใฆๆธใๅบใใ
|
|
170
|
+
inp_builder.write(input_file)
|
|
171
|
+
|
|
172
|
+
# 2. Packmol ใๅฎ่กใใ็ๆใใใ XYZ ใ POSCAR ใซๅคๆใใใ
|
|
173
|
+
self.packmol_runner.run_packmol(
|
|
174
|
+
input_file=input_file,
|
|
175
|
+
output_log=output_log,
|
|
176
|
+
packmol_bin=self.packmol_bin,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
# Packmol ๅบๅใฏ Cartesian ๅบงๆจใชใฎใงใVASP POSCAR ็จใซ Direct ๅบงๆจใธๅคๆใใใ
|
|
180
|
+
xyz_to_poscar_index = self.packmol_runner.xyz_to_poscar(
|
|
181
|
+
xyz_file=output_xyz,
|
|
182
|
+
poscar_file=poscar_file,
|
|
183
|
+
packmol_inp=input_file,
|
|
184
|
+
comment=f"{output_prefix} amorphous initial model generated by Packmol (Total Atoms: {self.total_atom_count})",
|
|
185
|
+
elements=self.symbols,
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
self._write_fnc_from_templates(
|
|
189
|
+
output_xyz=output_xyz,
|
|
190
|
+
xyz_to_poscar_index=xyz_to_poscar_index,
|
|
191
|
+
fnc_file=fnc_file,
|
|
192
|
+
output_prefix=output_prefix,
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
# ๅค้จใใผใซ้ฃๆบ็จใซ vasp.xyz๏ผใใใใฏ POSCAR.vasp๏ผใๅๆงใซๅบๅใใใ
|
|
196
|
+
self.packmol_runner.xyz_to_poscar(
|
|
197
|
+
xyz_file=output_xyz,
|
|
198
|
+
poscar_file=vasp_file,
|
|
199
|
+
packmol_inp=input_file,
|
|
200
|
+
comment=f"{output_prefix} amorphous initial model vasp format",
|
|
201
|
+
elements=self.symbols,
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
def _write_fnc_from_templates(
|
|
205
|
+
self,
|
|
206
|
+
output_xyz: str,
|
|
207
|
+
xyz_to_poscar_index: Dict[int, int],
|
|
208
|
+
fnc_file: str,
|
|
209
|
+
output_prefix: str,
|
|
210
|
+
) -> None:
|
|
211
|
+
"""
|
|
212
|
+
็ป้ฒๆธใฟใใณใใฌใผใใฎ FNC ๅฑๆใใขใใๆ็ต POSCAR/cfg ็ชๅทใธๅคๆใใฆ *.fnc ใๆธใใ
|
|
213
|
+
|
|
214
|
+
Packmol ๅบๅ XYZ ใงใฏใใณใใฌใผใๅไฝใฎๅๅญ้ ใๆฎใใไธๆนใPOSCAR ๅคๆใงใฏ
|
|
215
|
+
ๅ
็ด ใใจใซๅบงๆจใไธฆในๆฟใใใใใPO4 ใฎ P ใจ O ใฎ็ชๅทใฏ้ขใใใ
|
|
216
|
+
ใใฎใกใฝใใใฏใPackmol XYZ ็ชๅทใไธญ้็ชๅทใจใใฆไฝฟใใ
|
|
217
|
+
ใใณใใฌใผใๅ
ๅฑๆ็ชๅทใใๆ็ต POSCAR/cfg ็ชๅทใฎ FNC ใใขใไฝใใ
|
|
218
|
+
"""
|
|
219
|
+
all_fnc_pairs: List[Tuple[int, int, int]] = []
|
|
220
|
+
merged_distance_ranges: Dict[int, Tuple[float, float]] = {}
|
|
221
|
+
|
|
222
|
+
xyz_start_index = 1
|
|
223
|
+
for template in self.templates:
|
|
224
|
+
xyz_file = str(template["xyz"])
|
|
225
|
+
number = int(template["number"])
|
|
226
|
+
fnc_pairs_in_template = template.get("fnc_pairs_in_template")
|
|
227
|
+
fnc_distance_ranges = template.get("fnc_distance_ranges")
|
|
228
|
+
# packmolๅพใซๅฝข็ถๅบๅฎใงใฎFNCใฎ้ธๆๆ็ก
|
|
229
|
+
fnc_output_constraint_types = template.get("fnc_output_constraint_types")
|
|
230
|
+
|
|
231
|
+
atom_count_in_template = self.packmol_runner.count_atoms_in_xyz(
|
|
232
|
+
xyz_file=xyz_file,
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
if fnc_pairs_in_template is not None:
|
|
236
|
+
if fnc_distance_ranges is None:
|
|
237
|
+
raise ValueError(
|
|
238
|
+
f"{xyz_file} ใซ fnc_pairs_in_template ใๆๅฎใใใฆใใใใ"
|
|
239
|
+
"fnc_distance_ranges ใๆๅฎใใใฆใใชใใ"
|
|
240
|
+
)
|
|
241
|
+
########################################
|
|
242
|
+
# Packmol ็จใใณใใฌใผใๆง้ ใฏๅคๆดใใชใใ
|
|
243
|
+
# ใใใงใฏ Packmol ๅพใฎๆ็ตๆง้ ใใ .fnc ใไฝใๆฎต้ใ ใใงใ
|
|
244
|
+
# RMC ใซๆธกใ constraint type ใ้ธๅฅใใใ
|
|
245
|
+
if fnc_output_constraint_types is None:
|
|
246
|
+
active_constraint_types = list(fnc_distance_ranges.keys())
|
|
247
|
+
else:
|
|
248
|
+
active_constraint_types = list(fnc_output_constraint_types)
|
|
249
|
+
|
|
250
|
+
active_constraint_type_set = set(active_constraint_types)
|
|
251
|
+
|
|
252
|
+
for type_index in active_constraint_types:
|
|
253
|
+
if type_index not in fnc_distance_ranges:
|
|
254
|
+
raise ValueError(
|
|
255
|
+
f"{xyz_file} ใฎ fnc_output_constraint_types ใซ type={type_index} "
|
|
256
|
+
"ใๆๅฎใใใฆใใใใfnc_distance_ranges ใซๅญๅจใใชใใ"
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
active_fnc_pairs_in_template = [
|
|
260
|
+
pair
|
|
261
|
+
for pair in fnc_pairs_in_template
|
|
262
|
+
if pair[2] in active_constraint_type_set
|
|
263
|
+
]
|
|
264
|
+
|
|
265
|
+
active_fnc_distance_ranges = {
|
|
266
|
+
type_index: fnc_distance_ranges[type_index]
|
|
267
|
+
for type_index in active_constraint_types
|
|
268
|
+
}
|
|
269
|
+
############################
|
|
270
|
+
|
|
271
|
+
for type_index, distance_range in active_fnc_distance_ranges.items():
|
|
272
|
+
if type_index in merged_distance_ranges:
|
|
273
|
+
if merged_distance_ranges[type_index] != distance_range:
|
|
274
|
+
raise ValueError(
|
|
275
|
+
"ๅใ FNC constraint type ใซ็ฐใชใ่ท้ข็ฏๅฒใๆๅฎใใใฆใใใ"
|
|
276
|
+
f" type={type_index}"
|
|
277
|
+
)
|
|
278
|
+
else:
|
|
279
|
+
merged_distance_ranges[type_index] = distance_range
|
|
280
|
+
|
|
281
|
+
copy_index = 0
|
|
282
|
+
while copy_index < number:
|
|
283
|
+
molecule_xyz_start = (
|
|
284
|
+
xyz_start_index + copy_index * atom_count_in_template
|
|
285
|
+
)
|
|
286
|
+
for (
|
|
287
|
+
local_i,
|
|
288
|
+
local_j,
|
|
289
|
+
constraint_type,
|
|
290
|
+
) in active_fnc_pairs_in_template:
|
|
291
|
+
xyz_i = molecule_xyz_start + local_i - 1
|
|
292
|
+
xyz_j = molecule_xyz_start + local_j - 1
|
|
293
|
+
poscar_i = xyz_to_poscar_index[xyz_i]
|
|
294
|
+
poscar_j = xyz_to_poscar_index[xyz_j]
|
|
295
|
+
all_fnc_pairs.append((poscar_i, poscar_j, constraint_type))
|
|
296
|
+
copy_index = copy_index + 1
|
|
297
|
+
|
|
298
|
+
xyz_start_index = xyz_start_index + number * atom_count_in_template
|
|
299
|
+
|
|
300
|
+
if len(all_fnc_pairs) == 0:
|
|
301
|
+
return
|
|
302
|
+
|
|
303
|
+
self.packmol_runner.write_fnc_file(
|
|
304
|
+
fnc_file=fnc_file,
|
|
305
|
+
total_atom_count=self.total_atom_count,
|
|
306
|
+
fnc_pairs=all_fnc_pairs,
|
|
307
|
+
distance_ranges_by_type=merged_distance_ranges,
|
|
308
|
+
title=f"{output_prefix} FNC generated from Packmol template mapping",
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
#
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""packmol_util ใฎ่จญๅฎไฟๆใฏใฉในใ"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional, Sequence, Union
|
|
6
|
+
import os
|
|
7
|
+
|
|
8
|
+
import yaml
|
|
9
|
+
from x_logger import XLogger
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Config:
|
|
13
|
+
"""packmol_util ็จใฎ่จญๅฎๅคใไฟๆใใใ"""
|
|
14
|
+
|
|
15
|
+
N_tot: int = 2000
|
|
16
|
+
mass_density_g_cm3: float = 7.3336
|
|
17
|
+
number_density_A3: float = 0.09119
|
|
18
|
+
element_info: Union[str, Sequence[str]] = ["Fe", "Si", "B"]
|
|
19
|
+
ratios: Sequence[int] = [82, 4, 14]
|
|
20
|
+
|
|
21
|
+
packmol_bin: str = "packmol"
|
|
22
|
+
minimum_separation: float = 2.0
|
|
23
|
+
output_prefix: str = "amorphous"
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
yaml_path: Optional[str] = None,
|
|
28
|
+
logger: Optional[XLogger] = None,
|
|
29
|
+
) -> None:
|
|
30
|
+
if logger is None:
|
|
31
|
+
logger = XLogger(logger_name=__name__)
|
|
32
|
+
self._logger = logger
|
|
33
|
+
|
|
34
|
+
if yaml_path:
|
|
35
|
+
self._load_yaml(yaml_path)
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def load_yaml(cls, yaml_path: Optional[str] = None) -> None:
|
|
39
|
+
"""YAML ใฎๅ
ๅฎนใงใฏใฉในๅคๆฐใไธๆธใใใใ"""
|
|
40
|
+
if yaml_path is None:
|
|
41
|
+
yaml_path = os.environ.get("PACKMOL_UTIL_CONFIG_YAML")
|
|
42
|
+
if yaml_path is None:
|
|
43
|
+
return
|
|
44
|
+
|
|
45
|
+
with open(yaml_path, "r") as f:
|
|
46
|
+
data = yaml.safe_load(f)
|
|
47
|
+
|
|
48
|
+
if data is None:
|
|
49
|
+
return
|
|
50
|
+
|
|
51
|
+
for key, value in data.items():
|
|
52
|
+
if hasattr(cls, key):
|
|
53
|
+
setattr(cls, key, value)
|
|
54
|
+
else:
|
|
55
|
+
print("NO SUCH VAR:", key)
|
|
56
|
+
|
|
57
|
+
def _load_yaml(self, yaml_path: Optional[str] = None) -> None:
|
|
58
|
+
"""YAML ใฎๅ
ๅฎนใงใคใณในใฟใณในๅฑๆงใไธๆธใใใใ"""
|
|
59
|
+
self._logger.info(f"load_yaml: {yaml_path}")
|
|
60
|
+
|
|
61
|
+
if yaml_path is None:
|
|
62
|
+
yaml_path = os.environ.get("PACKMOL_UTIL_CONFIG_YAML")
|
|
63
|
+
if yaml_path is None:
|
|
64
|
+
return
|
|
65
|
+
|
|
66
|
+
yaml_path = os.path.abspath(yaml_path)
|
|
67
|
+
self._logger.info(f"abspath: {yaml_path}")
|
|
68
|
+
|
|
69
|
+
with open(yaml_path, "r") as f:
|
|
70
|
+
data = yaml.safe_load(f)
|
|
71
|
+
|
|
72
|
+
if data is None:
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
for key, value in data.items():
|
|
76
|
+
if hasattr(self, key):
|
|
77
|
+
setattr(self, key, value)
|
|
78
|
+
else:
|
|
79
|
+
print("NO SUCH VAR:", key)
|