#!/usr/bin/env python3
"""
概要: CIFファイルからVASPのバンド構造計算用KPOINTSファイルを生成します。
詳細説明:
pymatgenのHighSymmKpathユーティリティを利用して、CIFファイルから読み込んだ結晶構造に基づき、
高対称性kパスを自動的に決定し、VASP形式のKPOINTSファイルを生成します。
構造のプリミティブ化、k点の丸め処理、k点分割数の設定などが可能です。
関連リンク: :doc:`make_kpoints_usage`
"""
import argparse
import sys
from pymatgen.io.cif import CifParser
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
from pymatgen.symmetry.bandstructure import HighSymmKpath
from pymatgen.io.vasp.inputs import Kpoints
from fractions import Fraction
[ドキュメント]
def snap(coords, max_den=2):
"""
概要: 分数座標を、指定された最大分母数で丸めます。
詳細説明:
pymatgenのHighSymmKpathで生成された浮動小数点座標を、
KPOINTSファイルに記述する際に、より簡潔な分数表現に近づけるために使用します。
例えば、max_den=2の場合、座標は1/2までの分母で丸められます。
:param coords: list[float] 変換する座標のリスト。
:param max_den: int 丸めの最大分母数(デフォルト: 2)。
:returns: list[float] 丸められた座標のリスト。
"""
# max_den=2 なら 1/2 までの分母で丸め
return [float(Fraction(c).limit_denominator(max_den)) for c in coords]
[ドキュメント]
def initialize():
"""
概要: コマンドライン引数パーサーを初期化します。
詳細説明:
スクリプトが受け入れるコマンドライン引数とその説明を定義し、
`argparse.ArgumentParser` オブジェクトを返します。
これにより、ユーザーは様々なオプションを指定してスクリプトを実行できます。
:returns: argparse.ArgumentParser コマンドライン引数パーサーオブジェクト。
"""
parser = argparse.ArgumentParser(
description="Generate a VASP KPOINTS for band structure from a CIF."
)
parser.add_argument(
"ciffile",
help="Path to the input CIF file."
)
parser.add_argument(
"--primitive_on_read",
action="store_true",
help="Convert to primitive cell upon reading from CIF file"
)
parser.add_argument(
"-c", "--conventional",
action="store_true",
help="Keep cell red from CIF file"
)
# https://pymatgen.org/pymatgen.symmetry.html より、このフラグはFalseであるべき
parser.add_argument(
"--international-monoclinic",
action="store_true",
help="Use the international monoclinic convention when standardizing structure."
)
parser.add_argument(
"--keep-site-properties",
action="store_true",
help="Keep original site properties when reducing to primitive standard structure."
)
parser.add_argument(
"-f", "--frac_tolerance",
type=float,
default=1e-4,
help="Fractional tolerance in structure parameters (default: 1e-4)."
)
parser.add_argument(
"-d", "--max_den",
type=int,
default=4,
help="Number of digits to round fractional coordinates in reciprocal space (default: 4)."
)
parser.add_argument(
"-s", "--symprec",
type=float,
default=1e-4,
help="Positional tolerance for symmetry detection (default: 1e-4)."
)
parser.add_argument(
"-a", "--angle-tol",
type=float,
dest="angle_tolerance",
default=0.1,
help="Angular tolerance (degrees) for symmetry detection (default: 0.1)."
)
parser.add_argument(
"--atol",
type=float,
default=0.1,
help="Absolute tolerance used to determine symmetric equivalence of points and lines on the BZ."
)
parser.add_argument(
"-n", "--ndivisions",
type=int,
default=20,
help="Number of k-point divisions along each path segment (default: 20)."
)
parser.add_argument(
"-p", "--path-type",
choices=["setyawan_curtarolo", "latimer_munro", "hinuma", "all"],
default="setyawan_curtarolo",
help="Which high‐symmetry path convention to use (default: setyawan_curtarolo)."
)
parser.add_argument(
"-o", "--output",
default="KPOINTS",
help="Output filename for the KPOINTS file (default: KPOINTS)."
)
return parser
[ドキュメント]
def update_vars(parser):
"""
概要: コマンドライン引数をパースし、設定を更新します。
詳細説明:
`ArgumentParser` オブジェクトが定義した引数に従い、
ユーザーがコマンドラインで指定した引数を解析し、`argparse.Namespace` オブジェクトとして返します。
このオブジェクトには、各引数の値が属性として格納されます。
:param parser: argparse.ArgumentParser 初期化されたArgumentParserオブジェクト。
:returns: argparse.Namespace パースされたコマンドライン引数を格納するオブジェクト。
"""
return parser.parse_args()
[ドキュメント]
def read_cif(ciffile, frac_tolerance, primitive = True):
"""
概要: CIFファイルを読み込み、構造オブジェクトを返します。
詳細説明:
指定されたCIFファイルを`pymatgen`の`CifParser`で解析し、
ファイル内の最初の構造を`pymatgen.core.structure.Structure`オブジェクトとして取得します。
読み込み時にプリミティブセルへの変換を行うオプションも提供されます。
:param ciffile: str 読み込むCIFファイルのパス。
:param frac_tolerance: float 構造パラメータの分数許容誤差。
:param primitive: bool 読み込み時にプリミティブセルに変換するかどうか。
:returns: pymatgen.core.structure.Structure | None 読み込まれた構造オブジェクト、またはエラー発生時はNone。
"""
print()
print(f"Read cif from {ciffile}")
parser = CifParser(ciffile, frac_tolerance = frac_tolerance)
structures = parser.parse_structures(primitive = primitive)
if not structures:
print(f"Error: no structures found in '{args.ciffile}'") # pylint: disable=E0602
return False # ここはエラーハンドリングを考慮するとNoneが良いが、既存コードの変更は不可のためFalse
structure = structures[0]
print(structure)
analyzer = SpacegroupAnalyzer(structure)
# spacegroup = analyzer.get_space_group_symbol()
spg_name, spg_num = structure.get_space_group_info()
print(f"Space group: {spg_name} #{spg_num}")
return structure
[ドキュメント]
def convert_primitive(structure_original, symprec, angle_tolerance,
international_monoclinic, keep_site_properties):
"""
概要: 構造を標準化し、プリミティブセルに変換します。
詳細説明:
`pymatgen`の`SpacegroupAnalyzer`を使用して、与えられた構造の対称性を検出し、
その対称性に基づいて標準的なプリミティブセルに変換します。
単斜晶系の慣習やサイトプロパティの保持などのオプションを指定できます。
:param structure_original: pymatgen.core.structure.Structure 変換元の構造オブジェクト。
:param symprec: float 対称性検出のための位置許容誤差。
:param angle_tolerance: float 対称性検出のための角度許容誤差(度)。
:param international_monoclinic: bool 単斜晶系で国際的な慣習を使用するかどうか。
:param keep_site_properties: bool プリミティブ構造への変換時に元のサイトプロパティを保持するかどうか。
:returns: pymatgen.core.structure.Structure プリミティブ化された標準構造オブジェクト。
"""
print()
print("Standardize and reduce to primitive cell")
analyzer = SpacegroupAnalyzer(
structure_original,
symprec = symprec,
angle_tolerance = angle_tolerance
)
structure = analyzer.get_primitive_standard_structure(
international_monoclinic = international_monoclinic,
keep_site_properties = keep_site_properties
)
print(structure)
analyzer = SpacegroupAnalyzer(structure)
# spacegroup = analyzer.get_space_group_symbol()
spg_name, spg_num = structure.get_space_group_info()
print(f"Space group: {spg_name} #{spg_num}")
return structure
[ドキュメント]
def generate_kpoints(structure, args):
"""
概要: VASPのKPOINTSファイルを生成し、出力します。
詳細説明:
与えられた構造とコマンドライン引数に基づいて、
`pymatgen`の`HighSymmKpath`を使用して高対称性kパスを決定します。
その後、決定されたkパスに沿ってk点を生成し、
VASPのKPOINTSファイル(ラインモード)として指定されたファイル名で書き出します。
k点の座標は`snap`関数により丸め処理が施されます。
:param structure: pymatgen.core.structure.Structure Kポイントパス生成に使用する構造オブジェクト。
:param args: argparse.Namespace コマンドライン引数を含むオブジェクト。`path_type`, `symprec`, `angle_tolerance`, `atol`, `max_den`, `ndivisions`, `output` などの属性が必要です。
:returns: None
"""
print()
print("Generate k path")
# 3) Generate high‐symmetry k‐path
kpath = HighSymmKpath(structure, path_type=args.path_type,
symprec = args.symprec, angle_tolerance = args.angle_tolerance, atol = args.atol)
print("kpath:", kpath.kpath["path"])
print("K-point path segments:")
for segment in kpath.kpath["path"]:
print(" ", " -> ".join(segment))
print("\nHigh-symmetry k-points:")
for label, coord in kpath.kpath["kpoints"].items():
print(f" {label:10} {coord}")
print()
print("Correct k path")
for name, frac in kpath.kpath['kpoints'].items():
kpath.kpath['kpoints'][name] = snap(frac, max_den = args.max_den)
print("High-symmetry k-points:")
for label, coord in kpath.kpath["kpoints"].items():
print(f" {label:10} {coord}")
print()
print("Create KPOINTS")
# 4) Build and write the KPOINTS file in line-mode
kpoints = Kpoints.automatic_linemode(divisions = args.ndivisions, ibz=kpath)
print(kpoints)
kpoints.write_file(args.output)
print(f"\nWrote KPOINTS to '{args.output}'")
[ドキュメント]
def main():
"""
概要: スクリプトの主処理を実行します。
詳細説明:
この関数は、コマンドライン引数の解析から、CIFファイルの読み込み、
構造のプリミティブセルへの変換(オプション)、高対称性kパスの生成、
そしてVASP KPOINTSファイルの書き出しまでの一連の処理を制御します。
エラー発生時には適切なメッセージを出力し、処理を中断します。
:returns: None
"""
parser = initialize()
args = update_vars(parser)
#argsの内容を確認
print("Arguments:")
for key, value in vars(args).items():
print(f" {key}: {value}")
print()
print(f"Read CIF file and generate KPOINTS for VASP")
print(f"CIF file: {args.ciffile}")
print(f"Convert to primitive cell on read_cif(): {args.primitive_on_read}")
print(f"Use conventional cell: {args.conventional}")
structure = read_cif(args.ciffile, args.frac_tolerance, primitive = args.primitive_on_read)
if structure is None: return None
# 既存コードでは False を返すことがあるため、None の場合も考慮
if structure is False: # pylint: disable=W0125
print("Error: Structure could not be read or found.")
sys.exit(1)
if not args.conventional:
structure = convert_primitive(structure, args.symprec, args.angle_tolerance,
args.international_monoclinic, args.keep_site_properties)
if structure is None: return None # convert_primitive は常に構造を返すため、Noneにはならないはずだが念のため
generate_kpoints(structure, args)
if __name__ == "__main__":
main()