jsap_crystal.benzene のソースコード

"""
ベンゼン分子のHückel近似による電子構造計算と状態密度(DOS)の可視化を行うスクリプト。

詳細説明:
このスクリプトは、Hückel近似法を用いてベンゼン分子(6炭素環)の電子構造を解析します。
Hückel行列を定義し、その固有値問題を解くことで、分子軌道のエネルギー準位と波動関数を計算します。
計算されたエネルギー準位はソートされ、その縮重度が特定されます。
その後、ガウス型ブロードニングを適用して状態密度(DOS)を計算します。
最後に、matplotlibライブラリを使用して、計算された電子準位と状態密度の両方を一つの図にプロットし、
ベンゼン分子の電子状態を視覚的に表現します。

関連リンク:
:doc:`benzene_usage`
"""

import numpy as np
from pprint import pprint
import matplotlib.pyplot as plt
from scipy.ndimage import gaussian_filter1d
from collections import Counter
from matplotlib.gridspec import GridSpec

#===================
# Global parameters
#===================

# Hückel行列の定義(ベンゼンは6炭素環)
# α=0, β=1 とした隣接行列形式
H_BENZENE = np.array([[0, 1, 0, 0, 0, 1],
                      [1, 0, 1, 0, 0, 0],
                      [0, 1, 0, 1, 0, 0],
                      [0, 0, 1, 0, 1, 0],
                      [0, 0, 0, 1, 0, 1],
                      [1, 0, 0, 0, 1, 0]])

# 状態密度(DOS)パラメータ
NUM_POINTS = 1000
SIGMA = 0.1  # ブロードニング幅

[ドキュメント] def main(): """ Hückel行列の対角化を行い、エネルギー準位と状態密度をプロットします。 """ print("\nHückel行列(ベンゼン):") pprint(H_BENZENE) # 固有値・固有ベクトルの計算 eigenvalues, eigenvectors = np.linalg.eig(H_BENZENE) # 実数部のみ取得しソート eigenvalues = np.sort(eigenvalues.real) # エネルギー準位のソートと出力 print("\nエネルギー準位(ソート後):") print(eigenvalues) print() # 縮重度の計算 # 浮動小数点の微小な差を丸めてカウント rounded_eigenvalues = np.round(eigenvalues, 8) degeneracies = Counter(rounded_eigenvalues) # 状態密度(DOS)の計算 energy_range = np.linspace(min(eigenvalues) - 1, max(eigenvalues) + 1, NUM_POINTS) dos = np.zeros(NUM_POINTS) for energy, deg in degeneracies.items(): # ガウス関数によるブロードニング dos += deg * np.exp(-((energy_range - energy) ** 2) / (2 * SIGMA ** 2)) # 状態密度のさらなる平滑化(オプション) dos = gaussian_filter1d(dos, SIGMA * (NUM_POINTS / (max(energy_range) - min(energy_range)))) # 図を描画 fig = plt.figure(figsize=(8, 6)) gs = GridSpec(1, 2, width_ratios=[1, 3], wspace=0.4) # 電子準位図の描画 ax0 = fig.add_subplot(gs[0]) ax0.set_title('Hückel Levels') for energy, deg in degeneracies.items(): # 縮重している場合は少しずらすか、線の太さを変える等の表現も可能ですが # オリジナルのプロット形式を維持します ax0.hlines(energy, 0, 1, colors='k', linestyles='solid') ax0.set_ylabel('Energy (units of β)') ax0.set_xticks([]) ax0.set_xlabel('') # DOSの描画 ax1 = fig.add_subplot(gs[1], sharey=ax0) ax1.plot(dos, energy_range, 'k-') ax1.fill_betweenx(energy_range, 0, dos, color='gray', alpha=0.3) ax1.set_title('Density of States (DOS)') ax1.set_xlabel('DOS (Arbitrary Units)') plt.tight_layout() plt.show()
if __name__ == "__main__": main()