vasp-util 0.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
vasp_util/__init__.py ADDED
@@ -0,0 +1,17 @@
1
+ """
2
+ K.NAKADA, kengo.nakada@gmail.com
3
+ """
4
+
5
+ from vasp_util.vasp import Vasp
6
+ from vasp_util.vasp_incar import VaspIncar
7
+ from vasp_util.vasp_kpoints import VaspKpoints
8
+ from vasp_util.vasp_potcar import VaspPotcarBuilder
9
+ from vasp_util.vasp_log import VaspLog
10
+ from vasp_util.vasp_outcar import VaspOutcar
11
+
12
+ from vasp_util.vasp_poscar import VaspPoscar
13
+ from vasp_util.vasp_poscar_analyzer import VaspPoscarAnalyzer
14
+
15
+ # from .vasp import Vasp
16
+ # from .collect_result import VaspLog
17
+ # from . import util
vasp_util/config.py ADDED
@@ -0,0 +1,102 @@
1
+ """
2
+ K.NAKADA, kengo.nakada@gmail.com (1st, 3rd varsion)
3
+ K.KOBAYASHI (2nd version)
4
+ """
5
+
6
+ from typing import Any, Dict, List, Optional, Union, Tuple, Callable, Sequence
7
+ import yaml
8
+ import os
9
+
10
+ from x_logger import XLogger
11
+
12
+
13
+ class Config:
14
+
15
+ # VASP parameter mirror
16
+ vasp_incar_tags: Dict[str, Any] = {}
17
+ vasp_kpoints_mode: Optional[str] = None
18
+ vasp_kpoints_grid: Optional[Tuple[int, int, int]] = None
19
+ vasp_kpoints_shift: Optional[Tuple[int, int, int]] = None
20
+ vasp_kpoints_comment: Optional[str] = None
21
+
22
+ # ------- DFT (VASP) --------
23
+ dft_code: str = "Vasp"
24
+ dft_log_dir: str = "vasp_log"
25
+ vasp_name: str = "aaa" # aaa.vasp
26
+ run_mode: str = "local"
27
+
28
+ #
29
+ # VASP path
30
+ #
31
+ # dft_bin = f"/home/hpc/vasp/bin/vasp-gamma"
32
+ # dft_bin = f"/home/k/Downloads/vasp.6.4.2/bin/vasp_gam"
33
+ # dft_bin = "/home/hpc/vasp/bin/vasp"
34
+ dft_bin: Optional[str] = f"vasp_gam"
35
+
36
+ num_procs: Optional[int] = 1
37
+
38
+ mpi_cmd: Optional[str] = "mpirun"
39
+ # mpi = f"mpirun -np {num_procs} {os.path.expanduser('/home/hpc/vasp/bin/vasp')}"
40
+
41
+ mpi_flag: Optional[str] = "-np"
42
+
43
+ dft_omp_num_threads: Optional[int] = None
44
+
45
+ # default job_name
46
+ job_cmd: Optional[str] = "qsub job_hpcs2024_node2.sh"
47
+
48
+ # 自動セーブ
49
+ auto_write: bool = True
50
+
51
+ def __init__(
52
+ self,
53
+ yaml_path: Optional[str] = None,
54
+ *,
55
+ logger: Optional[XLogger] = XLogger(),
56
+ ):
57
+ """
58
+
59
+ Args:
60
+ yaml_path (str):
61
+ logger (XLogger):
62
+ """
63
+ self._logger = logger
64
+
65
+ # インスタンスで使いたいときだけ、ここで個別設定
66
+ if yaml_path:
67
+ self._load_yaml(yaml_path)
68
+
69
+ @classmethod
70
+ def load_yaml(cls, yaml_path=None):
71
+ if yaml_path is None:
72
+ yaml_path = os.environ.get("RMC_DFT_CONFIG_YAML")
73
+ if yaml_path is None:
74
+ return
75
+ # with open(yaml_path, "r") as f:
76
+ with open(yaml_path, "r", encoding="utf-8") as f:
77
+ data = yaml.safe_load(f)
78
+ for k, v in data.items():
79
+ if hasattr(cls, k):
80
+ setattr(cls, k, v)
81
+ else:
82
+ print("NO SUCH VAR:", k)
83
+
84
+ def _load_yaml(self, yaml_path=None):
85
+ # インスタンス用:インスタンスdictにのみ上書き
86
+ self._logger.info(f"load_yaml: {yaml_path}")
87
+ if yaml_path is None:
88
+ yaml_path = os.environ.get("RMC_DFT_CONFIG_YAML")
89
+ if yaml_path is None:
90
+ return
91
+ yaml_path = os.path.abspath(yaml_path)
92
+ self._logger.info(f"abspath: {yaml_path}")
93
+ with open(yaml_path, "r") as f:
94
+ data = yaml.safe_load(f)
95
+ for k, v in data.items():
96
+ setattr(self, k, v)
97
+
98
+
99
+ if __name__ == "__main__":
100
+ config = Config("config.yml")
101
+ print(config.num_procs)
102
+ print(type(config.num_procs))
@@ -0,0 +1,22 @@
1
+ from rmc_dft.vasp.util.poscar2cfg import (
2
+ vasp2cfg,
3
+ poscar2cfg,
4
+ contcar2cfg,
5
+ convert_to_cfg,
6
+ )
7
+
8
+ from rmc_dft.vasp.util.cell_geometry import (
9
+ _lattice,
10
+ cell_volume,
11
+ cartesian_to_direct,
12
+ wrap_direct,
13
+ wrap_cartesian,
14
+ minimum_image_vector,
15
+ periodic_distance,
16
+ )
17
+
18
+ from rmc_dft.vasp.util.copy_contcar_to_vasp import copy_contcar_to_vasp
19
+ from rmc_dft.vasp.util.copy_vasp_to_poscar import copy_vasp_to_poscar
20
+ from rmc_dft.vasp.util.ensure_vasp5_format import ensure_vasp5_format
21
+ from rmc_dft.vasp.util.xdatcar2poscar import xdatcar2poscar
22
+ from rmc_dft.vasp.util.make_potcar import VaspPotcarBuilder
@@ -0,0 +1,130 @@
1
+ """周期結晶セルの汎用幾何操作。格子ベクトルは3x3行列の行に格納する。
2
+
3
+ POSCARの読み込みは既存の rmc_dft.vasp.vasp_poscar.VaspPoscar を使用する。
4
+ 本モジュールはファイル入出力やRMC/ænet固有の構造生成を行わない。
5
+ 最短画像は整数格子シフトを列挙して直交座標ノルムで判定する。
6
+ """
7
+
8
+ from itertools import product
9
+ from typing import List, Dict, Optional, Tuple
10
+ import numpy as np
11
+
12
+
13
+ def _lattice(
14
+ cell: np.ndarray,
15
+ ) -> np.ndarray:
16
+ """格子行列を検査し、float64の3x3行列として返す。"""
17
+ lattice = np.asarray(cell, dtype=float)
18
+ if lattice.shape != (3, 3):
19
+ raise ValueError("cell must be a 3x3 matrix")
20
+ if abs(float(np.linalg.det(lattice))) < 1.0e-12:
21
+ raise ValueError("cell is singular")
22
+ return lattice
23
+
24
+
25
+ def cell_volume(
26
+ cell: np.ndarray,
27
+ ) -> float:
28
+ """周期セルの体積を返す(格子がÅならų)。"""
29
+ return abs(float(np.linalg.det(_lattice(cell))))
30
+
31
+
32
+ def direct_to_cartesian(
33
+ coords: np.ndarray,
34
+ cell: np.ndarray,
35
+ ) -> np.ndarray:
36
+ """分率座標 (...,3) を直交座標へ変換する。"""
37
+ return np.asarray(coords, dtype=float) @ _lattice(cell)
38
+
39
+
40
+ def cartesian_to_direct(
41
+ coords: np.ndarray,
42
+ cell: np.ndarray,
43
+ ) -> np.ndarray:
44
+ """直交座標 (...,3) を分率座標へ変換する。"""
45
+ return np.asarray(coords, dtype=float) @ np.linalg.inv(_lattice(cell))
46
+
47
+
48
+ def wrap_direct(
49
+ coords: np.ndarray,
50
+ ) -> np.ndarray:
51
+ """分率座標を [0,1) に折り返す。入力は変更しない。"""
52
+ return np.mod(np.asarray(coords, dtype=float), 1.0)
53
+
54
+
55
+ def wrap_cartesian(
56
+ coords: np.ndarray,
57
+ cell: np.ndarray,
58
+ ) -> np.ndarray:
59
+ """直交座標を周期セル内に折り返す。"""
60
+ return direct_to_cartesian(wrap_direct(cartesian_to_direct(coords, cell)), cell)
61
+
62
+
63
+ def minimum_image_vector(
64
+ a: np.ndarray,
65
+ b: np.ndarray,
66
+ cell: np.ndarray,
67
+ search_radius: int = 1,
68
+ ) -> np.ndarray:
69
+ """aからbへの最短周期変位(直交座標、Å)を返す。
70
+
71
+ 分率差を最近整数で中心化した後、[-search_radius,+search_radius]^3
72
+ の画像を探索する。強く歪んだセルでは探索範囲の拡大が必要。
73
+ """
74
+ if search_radius < 0:
75
+ raise ValueError("search_radius must be nonnegative")
76
+ lattice = _lattice(cell)
77
+ delta = cartesian_to_direct(
78
+ np.asarray(b, dtype=float) - np.asarray(a, dtype=float), lattice
79
+ )
80
+ if delta.shape != (3,):
81
+ raise ValueError("a and b must be 3-vectors")
82
+ delta = delta - np.round(delta)
83
+ best = None
84
+ best_squared = float("inf")
85
+ for shift in product(range(-search_radius, search_radius + 1), repeat=3):
86
+ vec = (delta + np.asarray(shift, dtype=float)) @ lattice
87
+ squared = float(vec @ vec)
88
+ if squared < best_squared:
89
+ best = vec
90
+ best_squared = squared
91
+ if best is None:
92
+ raise RuntimeError("周期画像の探索に失敗しました")
93
+ return best
94
+
95
+
96
+ def periodic_distance(
97
+ a: np.ndarray,
98
+ b: np.ndarray,
99
+ cell: np.ndarray,
100
+ search_radius: int = 1,
101
+ ) -> float:
102
+ """2点の周期最短距離(Å)。"""
103
+ return float(np.linalg.norm(minimum_image_vector(a, b, cell, search_radius)))
104
+
105
+
106
+ def check_pair_distances(
107
+ symbols: List[str],
108
+ positions: np.ndarray,
109
+ cell: np.ndarray,
110
+ minimums: Dict[str, float],
111
+ fallback: Optional[float] = None,
112
+ ) -> Tuple[bool, float]:
113
+ """周期距離に基づき、全原子対の下限距離を検証する。"""
114
+ shortest = float("inf")
115
+ for i in range(len(symbols)):
116
+ for j in range(i + 1, len(symbols)):
117
+ key = "-".join(sorted((symbols[i], symbols[j])))
118
+ if key in minimums:
119
+ threshold = minimums[key]
120
+ elif fallback is not None:
121
+ threshold = fallback
122
+ else:
123
+ raise ValueError(f"距離閾値が未設定です: {key}")
124
+ distance = periodic_distance(positions[i], positions[j], cell)
125
+ shortest = min(shortest, distance)
126
+ if not np.isfinite(distance):
127
+ return False, shortest
128
+ if distance < threshold:
129
+ return False, shortest
130
+ return True, shortest
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ K.NAKADA, kengo.nakada@gmail.com
4
+ """
5
+
6
+ from typing import Any, Dict, List, Optional, Union, Tuple, Callable, Sequence
7
+
8
+ import shutil
9
+ from pathlib import Path
10
+ from x_logger import XLogger
11
+
12
+
13
+ def copy_contcar_to_vasp(
14
+ vasp_name: str,
15
+ logger: Optional[XLogger] = XLogger(),
16
+ ) -> bool:
17
+ """
18
+ CONTCAR ファイルを {name}.vasp にコピーする
19
+
20
+ Args:
21
+ vasp_name (str): 出力ファイル名(拡張子なし)
22
+ logger (XLogger):
23
+
24
+ Returns:
25
+ bool:
26
+
27
+ """
28
+ src = Path("CONTCAR")
29
+ dst = Path(f"{vasp_name}.vasp")
30
+
31
+ if not src.exists():
32
+ logger.error("Error: CONTCAR ファイルが見つかりません。")
33
+ return False
34
+
35
+ shutil.copyfile(src, dst)
36
+ logger.info(f"{src} --> {dst} にコピーしました")
37
+ return True
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ K.NAKADA, kengo.nakada@gmail.com
4
+ """
5
+
6
+ from typing import Any, Dict, List, Optional, Union, Tuple, Callable, Sequence
7
+ from pathlib import Path
8
+ import shutil
9
+
10
+ from x_logger import XLogger
11
+
12
+
13
+ def copy_vasp_to_poscar(
14
+ vasp_name: str,
15
+ logger: Optional[XLogger] = XLogger(),
16
+ ) -> bool:
17
+ """
18
+ {vasp_name}.vasp ファイルを POSCAR にコピーする
19
+
20
+ Args:
21
+ vasp_name (str): 入力ファイル名(拡張子なし)
22
+ logger (XLogger): ロガー(未指定の場合は新規生成)
23
+
24
+ Returns:
25
+ bool: 成功時 True、失敗時 False
26
+ """
27
+ src = Path(f"{vasp_name}.vasp")
28
+ dst = Path("POSCAR")
29
+
30
+ if not src.exists():
31
+ logger.error(f"Error: {src} が見つかりません。")
32
+ return False
33
+
34
+ try:
35
+ shutil.copyfile(src, dst)
36
+ logger.info(f"{src} --> {dst} にコピーしました")
37
+ return True
38
+ except Exception as e:
39
+ logger.error(f"Error: コピーに失敗しました ({e})")
40
+ return False
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ K.NAKADA, kengo.nakada@gmail.com
4
+ """
5
+ from typing import Any, Dict, List, Optional, Union, Tuple, Callable, Sequence
6
+
7
+ from x_logger import XLogger
8
+
9
+
10
+ def ensure_vasp5_format(
11
+ poscar_name: str,
12
+ element_info: Optional[Union[str, Sequence[str]]] = None,
13
+ logger: Optional[XLogger] = XLogger(),
14
+ ) -> bool:
15
+ """
16
+ VASPファイルの6行目にラベルを設定する
17
+ VASP4 type POSCAR to VASP5 type POSCAR
18
+ 繰り返し実行しても副作用はない
19
+
20
+ RMC pot の cfg 形式は元素名がないために、POSCAR 形式に変換したときに困る場合があるので
21
+ VASP5 形式にする (cfg2poscar は element 情報がない VASP4 形式)
22
+
23
+ Args:
24
+ poscar_name (str): POSCAR
25
+ element_info (str): element 情報があるファイル名 or element のリスト
26
+ logger (XLogger):
27
+
28
+ Returns:
29
+ bool: True/False
30
+ """
31
+ if element_info is None:
32
+ element_info = "label.txt"
33
+
34
+ logger.info(f"element_info: {element_info}")
35
+
36
+ # ラベル行の内容の決定
37
+ if isinstance(element_info, str):
38
+ # ファイル名として扱う
39
+ try:
40
+ with open(element_info, "r", encoding="utf-8") as file:
41
+ label_line: str = file.readline().strip()
42
+ except FileNotFoundError:
43
+ logger.error("element info file not found.")
44
+ return False
45
+ else:
46
+ # Sequence[str] として扱う
47
+ # すべて str であることを軽く確認
48
+ if not all(isinstance(e, str) for e in element_info):
49
+ logger.error("element_info must be a sequence of str.")
50
+ return False
51
+ label_line = " ".join(element_info)
52
+
53
+ # VASP の POSCAR 読み込み
54
+ with open(poscar_name, "r") as file:
55
+ lines = file.readlines()
56
+ label_place = 6
57
+
58
+ # VASP の POSCAR 更新(VASP4 -> VASP5)
59
+ if 1 <= label_place <= len(lines):
60
+ lines[label_place - 1] = label_line + "\n" # 改行を付けて置換
61
+
62
+ # ファイルに上書き保存
63
+ with open(poscar_name, "w") as file:
64
+ file.writelines(lines)
65
+ logger.info(f"{poscar_name} label back.")
66
+ else:
67
+ logger.error("error: line number out of range.")
68
+ return False
69
+
70
+ return True
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ K.NAKADA, kengo.nakada@gmail.com
4
+ """
5
+
6
+ import sys
7
+ from vasp_util.vasp_potcar import VaspPotcarBuilder
8
+
9
+ if __name__ == "__main__":
10
+ if len(sys.argv) < 2:
11
+ print("Usage: python make_potcar.py Li Mn O [output_file(optional)]")
12
+ sys.exit(1)
13
+
14
+ # 最後の引数が出力ファイル名なら分離
15
+ # . を含んでいる時は元素名ではなくてフォルダ名となる
16
+ # make_poscar.py Li Mn O ./bb/POTCAR
17
+ args = sys.argv[1:]
18
+ if len(args) >= 2 and "." in args[-1]:
19
+ _poscar_name = args[-1]
20
+ _elements = args[:-1]
21
+ else:
22
+ _poscar_name = "POTCAR"
23
+ _elements = args
24
+
25
+ builder = VaspPotcarBuilder("~/potpaw_PBE.64")
26
+ builder.build(_elements, poscar_name=_poscar_name)