Phonopy画图示例

1047 字
5 分钟
Phonopy画图示例

声子谱绘图#

导入必要的库并设置绘图参数#

import matplotlib.pyplot as plt
from matplotlib.ticker import AutoMinorLocator
from matplotlib.axes._axes import Axes
from PltSci import whole_plot_set, half_plot_set, set_ticks, cm
import numpy as np
import pandas as pd
from pathlib import Path

设置phonopy输出的文件所在的文件夹#

phonopy_dir= Path("Your phonopy output directory")

计算声子谱#

# 查看声子谱
import yaml
def read_band_yaml(filename):
"""读取 band.yaml 文件"""
with open(filename, "r") as file:
data = yaml.safe_load(file)
# 提取数据
q_points = []
frequencies = []
for phonon in data["phonon"]:
q_points.append(phonon["q-position"])
freqs = [band["frequency"] for band in phonon["band"]]
frequencies.append(freqs)
return np.array(q_points), np.array(frequencies)
def calculate_path_distances(q_points):
"""计算路径距离"""
distances = [0]
for i in range(1, len(q_points)):
delta = np.linalg.norm(q_points[i] - q_points[i-1])
distances.append(distances[-1] + delta)
return np.array(distances)/10
def calculate_label_positions(config_file):
with open(config_file, 'r') as f:
lines = f.readlines()
# 提取 BAND 行
band_line = None
band_labels = None
for line in lines:
if 'BAND_LABELS' in line.split():
band_labels = line.split('=')[1].strip().split()
elif 'BAND' in line.split():
band_line = line.split('=')[1].strip()
if not band_line or not band_labels:
return None, None
# 解析坐标
coords = np.array([float(x) for x in band_line.split()]).reshape(-1, 3)
# 计算累积距离
distances = [0]
for i in range(1, len(coords)):
delta = np.linalg.norm(coords[i] - coords[i-1])
distances.append(distances[-1] + delta)
return distances, band_labels

得到所有声子支及其对应的频率,以及高对称点路径及其距离#

q_points, frequencies = read_band_yaml(phonopy_dir/"band.yaml")
x = calculate_path_distances(q_points)
distabces,band_labels = calculate_label_positions(phonopy_dir/"band.conf")
# 将x和frequencies转换为DataFrame
df = pd.DataFrame(frequencies, index=x)
df.columns=[f"Mode {i+1}" for i in range(df.shape[1])]
df.to_csv(phonopy_dir/"band.csv")
print(band_labels)
print(distabces)
df

输出如下:

['Γ', 'X', 'M', 'Γ', 'Z', 'Z$_0$', 'M', 'X', 'P', 'N', 'Γ']
[0, np.float64(0.5), np.float64(1.2071067811865475), np.float64(2.0731321849709863), np.float64(2.6530321572528663), np.float64(3.6559849432852403), np.float64(3.9421103747877986), np.float64(4.6492171559743465), np.float64(5.082229857866566), np.float64(5.515242559758786), np.float64(6.015242559758786)]
x Mode 1 Mode 2 Mode 3 Mode 4 Mode 5 Mode 6 Mode 7 Mode 8 Mode 9 Mode 10 ... Mode 30 Mode 31 Mode 32 Mode 33 Mode 34 Mode 35 Mode 36 Mode 37 Mode 38 Mode 39
0.000000 -0.016602 -0.016578 -0.004214 2.261070 3.087513 4.017914 4.039012 4.039012 4.081514 4.283571 ... 8.734425 8.995253 8.995253 9.103420 9.212984 9.213265 9.740371 10.843518 10.843519 11.937467
0.002632 0.144104 0.145348 0.285528 2.262128 3.087593 4.014263 4.037053 4.040149 4.081030 4.282455 ... 8.743481 8.993692 8.993947 9.104067 9.214416 9.214815 9.739465 10.842642 10.843391 11.935715
0.005263 0.287903 0.291999 0.570570 2.265253 3.087838 4.003063 4.031526 4.043538 4.079532 4.279206 ... 8.767466 8.989158 8.990148 9.105905 9.218562 9.219394 9.736746 10.840038 10.843012 11.930510
0.007895 0.430888 0.438105 0.853010 2.270298 3.088269 3.983696 4.023369 4.049117 4.076885 4.274125 ... 8.800488 8.982057 8.984175 9.108669 9.225029 9.226795 9.732215 10.835784 10.842385 11.921997
0.010526 0.572668 0.583785 1.131684 2.277025 3.088925 3.955521 4.013769 4.056782 4.072881 4.267678 ... 8.838111 8.972920 8.976431 9.112035 9.233294 9.236693 9.725876 10.830004 10.841518 11.910418
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
0.590998 0.784618 0.899562 1.514743 2.348375 3.129820 3.897475 3.943181 3.978098 4.110157 4.245356 ... 8.733970 8.974490 8.987286 8.988509 9.145138 9.255682 9.801084 10.827591 10.835713 11.920785
0.593630 0.590667 0.677458 1.146342 2.311092 3.110628 3.943047 3.982800 4.002031 4.101885 4.261316 ... 8.736877 8.979828 8.991620 9.030845 9.173239 9.238195 9.778077 10.834311 10.839040 11.927932
0.596261 0.394689 0.452855 0.768873 2.283598 3.097620 3.980764 4.013259 4.021565 4.093443 4.273361 ... 8.738840 8.987067 8.993696 9.068773 9.193910 9.225594 9.758531 10.839345 10.841500 11.933180
0.598893 0.197156 0.226451 0.385737 2.266747 3.090019 4.007491 4.032456 4.034496 4.085458 4.280960 ... 8.736032 8.993033 8.994874 9.094361 9.206825 9.217712 9.745159 10.842463 10.843009 11.936388
0.601524 -0.016602 -0.016578 -0.004214 2.261070 3.087513 4.017914 4.039012 4.039012 4.081514 4.283571 ... 8.734425 8.995253 8.995253 9.103420 9.212984 9.213265 9.740371 10.843518 10.843519 11.937467

200 rows × 39 columns

fig,ax= plt.subplots(figsize=(cm(7), cm(5)),dpi=500)
for i in range(frequencies.shape[1]):
plt.plot(x, frequencies[:, i], color='#1763bb', linewidth=0.5)
x_max= np.max(x)
distabces=distabces/distabces[-1]*x_max
set_ticks(ax,xrange=(distabces[0], distabces[-1], 0.05), yrange=(-1, 13, 2))
ax.set_yticks(np.arange(0,12.1, 2))
for label, point in zip(band_labels, distabces):
ax.axvline(point, color='dimgray', linewidth=0.5, linestyle='--')
ax.text(point, -1.2, label, ha='center', va='top', fontsize=8)
ax.axhline(0, color='dimgray', linewidth=0.5, linestyle='--')
# 不显示x轴坐标和刻度
ax.set_xticks([])
ax.set_xticklabels([])
ax.set_ylabel("Frequency (THz)", fontsize=8)
half_plot_set(ax)

png
png

fig.savefig(phonopy_dir/"phonon_band.png", bbox_inches='tight', dpi=1200)

提取声子态密度数据#

# 计算声子态密度
# 读取mesh.yaml文件来计算DOS
mesh_data = yaml.safe_load(open(phonopy_dir / "mesh.yaml"))
# 提取频率数据
frequencies_mesh = []
weights = []
for phonon in mesh_data["phonon"]:
freqs = [band["frequency"] for band in phonon["band"]]
frequencies_mesh.append(freqs)
weights.append(phonon["weight"])
frequencies_mesh = np.array(frequencies_mesh)
weights = np.array(weights)
# 计算DOS
freq_range = np.linspace(-1, 13, 1000)
dos = np.zeros_like(freq_range)
# 使用高斯展宽计算DOS
sigma = 0.1 # 展宽参数
for i, freq_point in enumerate(freq_range):
dos_set=weights * np.exp(-((freq_point - frequencies_mesh) ** 2) / (2 * sigma**2)).T
dos[i] = np.sum(dos_set)
# 归一化
dos = dos / (sigma * np.sqrt(2 * np.pi) * np.sum(weights))
# 绘制DOS
fig_dos, ax_dos = plt.subplots(figsize=(cm(7), cm(5)), dpi=500)
ax_dos.plot(freq_range, dos, color=color_map[0], linewidth=1)
ax_dos.fill_between(freq_range, dos, alpha=0.3, color=color_map[0])
set_ticks(ax_dos, xrange=(-1, 13, 2), yrange=(0, 9, 2))
ax_dos.set_xlabel("Frequency (THz)", fontsize=8)
ax_dos.set_ylabel("DOS", fontsize=8)
ax_dos.axvline(0, color='dimgray', linewidth=0.5, linestyle='--')
half_plot_set(ax_dos)

png
png

fig.savefig(phonopy_dir/"phonon_DOS.png", bbox_inches='tight', dpi=1200)

画一个组合图#

fig, axs = plt.subplots(
1, 2, figsize=(cm(7), cm(5)), dpi=500, gridspec_kw={"width_ratios": [3.5, 1]}
)
ax = axs[0]
# 绘制所有声子支
for i in range(frequencies.shape[1]):
ax.plot(x, frequencies[:, i], color="#1763bb", linewidth=0.5)
x_max = np.max(x)
distabces = distabces / distabces[-1] * x_max
set_ticks(ax, xrange=(distabces[0], distabces[-1], 0.05), yrange=(-1, 13, 2))
ax.set_yticks(np.arange(0, 12.1, 2))
i = 0
for label, point in zip(band_labels, distabces):
ax.axvline(point, color="dimgray", linewidth=0.5, linestyle="--")
if i == 5:
ax.text(point - 0.005, -1.2, label, ha="center", va="top", fontsize=8)
elif i == 6:
ax.text(point + 0.005, -1.2, label, ha="center", va="top", fontsize=8)
else:
ax.text(point, -1.2, label, ha="center", va="top", fontsize=8)
i += 1
ax.axhline(0, color="dimgray", linewidth=0.5, linestyle="--")
# 不显示x轴坐标和刻度
ax.set_xticks([])
ax.set_xticklabels([])
ax.set_ylabel("Frequency (THz)", fontsize=10)
half_plot_set(ax)
ax = axs[1]
# 绘制DOS
ax.plot(dos, freq_range, color=color_map[0], linewidth=0.5)
ax.fill_betweenx(freq_range, dos, alpha=0.3, color=color_map[0])
set_ticks(ax, xrange=(0, 9, 2), yrange=(-1, 13, 2))
ax.axhline(0, color="dimgray", linewidth=0.5, linestyle="--")
ax.set_yticklabels([])
ax.set_xticks([])
ax.set_xticklabels([])
half_plot_set(ax)
ax.text(4.5, -1.2, "DOS", ha="center", va="top", fontsize=8)
fig.subplots_adjust(wspace=0) # 调整子图间距

Phonopy声子谱
Phonopy声子谱

fig.savefig(phonopy_dir/"phonon_band_dos.png", bbox_inches='tight', dpi=1200)
Phonopy画图示例
https://www.kaimoe.cn/posts/phonopy画图示例/
作者
开萌
发布于
2026-04-05
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
开萌
记录材料计算、科研绘图与开发配置。
分类
标签

目录