8 辅助工具使用教程
备注
cli 是 dspawpy (一个基于 Python ≥ 3.6 的库)的命令行交互程序,提供了十几个选项,用于快速完成常见任务。对于更复杂的任务,可参考本章第二节开始的脚本示例。
安装 dspawpy后,命令行输入 cli
即可使用:
$ cli
********这是dspawpy命令行交互小工具,预祝您使用愉快********
( )
_| | ___ _ _ _ _ _ _ _ _ _ _ _
/'_` |/',__)( '_`\ /'_` )( ) ( ) ( )( '_`\ ( ) ( )
( (_| |\__, \| (_) )( (_| || \_/ \_/ || (_) )| (_) |
`\__,_)(____/| ,__/'`\__,_)`\___x___/'| ,__/'`\__, |
| | | | ( )_| |
(_) (_) `\___/'
正在联网检查dspawpy版本... 使用 -q 参数启动此程序可跳过检查
成功导入 x.x.x(最新版)dspawpy
********这是dspawpy命令行交互小工具,预祝您使用愉快********
1: dspawpy更新
2: structure结构转化
3: volumetricData数据处理
4: band能带数据处理
5: dos态密度数据处理
6: bandDos能带和态密度共同显示
7: optical光学性质数据处理
8: neb过渡态计算数据处理
9: phonon声子计算数据处理
10: aimd分子动力学模拟数据处理
11: Polarization铁电极化数据处理
12: ZPE零点振动能数据处理
13: TS的热校正能
--> 输入数字后回车选择功能:
8.1 安装与更新
在HZW机器上,已提前安装 dspawpy,使用以下命令激活虚拟环境即可使用:
source /data/hzwtech/profile/dspawpy.env
在其他机器上,请自行安装 dspawpy(下列两种方式二选一):
使用 conda
推荐使用 conda, 它在管理 python 包时会全局考虑依赖关系,出现底层依赖库错误的概率较低
conda install dspawpy -c conda-forge
或使用 pip
pip install dspawpy
更新 dspawpy
如果 dspawpy 是通过 conda 安装的,使用以下命令更新:
conda update dspawpy
如果 dspawpy 是通过 pip 安装的,那么:
pip install dspawpy -U # -U 表示安装最新版
备注
如果 pip 使用了国内的镜像网站,可能由于镜像网站尚未同步最新版 dspawpy 1.2.0 而导致无法顺利升级,需指定从pypi官网下载安装:
pip install dspawpy -i https://pypi.org/simple --user -U # -i 指定下载地址,--user 表示仅为当前用户安装,-U 表示安装最新版
如果运行时出现 dspawpy 相关 错误信息,请先检查是否已正确导入最新版本的 dspawpy 并检查安装路径:
$ python3 # 或 python
>>> import dspawpy
>>> dspawpy.__version__ # 将输出版本号
>>> dspawpy.__file__ # 将输出安装路径
如果当前用户目录下存在 .local/lib
文件夹,Python 将优先从中寻找并导入包,这可能导致包的版本错误(即使已进入conda虚拟环境)!
请尝试在运行时增加 -s 选项避免导入 .local/lib 中的包: python -s your-script.py
8.2 structure结构转化
读取结构信息使用 read
函数;将结构信息写入文件,使用 write
函数;快速结构转化,使用 convert
函数:
可参考 2conversion.py
脚本完成转化:
1# -*- coding: utf-8 -*-
2from dspawpy.io.structure import convert
3
4convert(
5 infile="dspawpy_proj/dspawpy_tests/inputs/2.1/relax.h5", # 待转化结构,如果在当前路径,可以只写文件名
6 si=None, # 筛选构型编号,如果不指定,默认读取全部
7 ele=None, # 筛选元素符号,默认读取所有元素的原子信息
8 ai=None, # 筛选原子编号,从 1 开始,默认读取所有原子信息
9 infmt=None, # 输入结构文件类型,例如 'h5',如果为None,将根据文件名规则模糊匹配
10 task="relax", # 任务类型,此参数仅当 infile 为文件夹而非文件名时有效
11 outfile="dspawpy_proj/dspawpy_tests/outputs/us/relaxed.xyz", # 结构文件名
12 outfmt=None, # 输出结构文件类型,例如 'xyz',如果为None,将根据文件名规则模糊匹配
13 coords_are_cartesian=True, # 默认以笛卡尔坐标写入
14)
convert 函数的几个关键参数设置规则见下表:
infile/outfile(输入/输出文件名模糊匹配) |
infmt(输入文件格式) |
outfmt(输出文件格式) |
兼容性 |
说明 |
---|---|---|---|---|
*.h5 |
h5 |
h5 |
读+ |
DS-PAW计算完成后保存的hdf5类型文件 |
*.json |
json |
json |
读+ 写 |
DS-PAW计算完成后保存的json类型文件 |
*.pdb |
pdb |
pdb |
读+ 写+ |
Protein Data Bank |
*.as |
as |
as |
读 写 |
DS-PAW记载原子坐标等信息的结构文件 |
*.hzw |
hzw |
hzw |
读 写 |
DeviceStudio默认的结构文件 |
*.xyz |
无 |
xyz |
写+ |
extended-xyz类型轨迹文件 |
*.dump |
无 |
dump |
写+ |
lammps-dump类型轨迹文件 |
*.cif*/*.mcif* |
无 |
cif/mcif |
读 写 |
Crystallographic Information File |
*.vasp/*POSCAR*/*CONTCAR* |
无 |
poscar |
读 写 |
VASP结构文件 |
*.cssr* |
无 |
cssr |
读 写 |
Crystal Structure Standard Representation |
*.xsf* |
无 |
xsf |
读 写 |
eXtended Structural Format |
*rndstr.in*/*lat.in*/*bestsqs* |
无 |
mcsqs |
读 写 |
Monte Carlo Special Quasirandom Structure |
*.yaml/*.yml |
无 |
yaml |
读 写 |
YAML Ain’t Markup Language |
inp*.xml/*.in*/inp_* |
无 |
fleur-inpgen |
读 写 |
FLEUR 结构文件,须安装 pymatgen-io-fleur |
*prismatic* |
无 |
prismatic |
写 |
用于STEM模拟的一种文件格式 |
*.res |
无 |
res |
写 |
ShelX res 结构文件 |
备注
读取时,infmt参数优先级高于文件名模糊匹配规则;例如,指定infmt=’h5’后,文件名可以是任意值,甚至可以是 a.json
写入时,outfmt参数优先级高于文件名模糊匹配规则;例如,指定outfmt=’h5’后,文件名可以是任意值,甚至可以是 a.json
“infile/outfile”列
*
号表示任意字符,“兼容性”列+
号表示支持处理多个结构,否则只能处理单个结构:
警告
将结构信息写入文件时,所有列出的格式(outfmt)都支持,而文件名模糊匹配规则不一定完全适用
*.cif*/*.mcif* 及以下的匹配规则已简化,更多参数细节,请查阅 pymatgen 的 from_file() 和 to() 两个函数的源代码。
将结构信息写为 json 格式时,仅支持可视化 NEB 链任务,详见 观察NEB链 节相关说明
DS-PAW 输出的 neb.h5、phonon.h5、phonon.json、neb.json以及wannier.json 暂时无法读取结构信息。
8.3 volumetricData数据处理
volumetricData可视化
参考
3vis_vol.py
:1# -*- coding: utf-8 -*- 2from dspawpy.io.write import write_VESTA 3 4# 读取数据文件(h5或json格式),处理后输出到cube文件 5write_VESTA( 6 in_filename="dspawpy_proj/dspawpy_tests/inputs/2.2/rho.h5", # 包含电子体系信息的json或h5文件路径 7 data_type="rho", # 数据类型,支持 "rho", "potential", "elf", "pcharge", "rhoBound" 8 out_filename="dspawpy_proj/dspawpy_tests/outputs/us/DS-PAW_rho.cube", # 输出文件路径 9 gridsize=(10, 10, 10), # 指定插值网格大小 10 format="cube", # 支持cube, vesta和txt格式(xyz格点坐标+数值) 11)
将转换后的文件 DS-PAW_rho.cube 拖入 VESTA 软件中显示:
晶体硅单胞的电荷密度分布示意图
差分volumetricData可视化
参考
3dvol.py
:1# -*- coding: utf-8 -*- 2from dspawpy.io.write import write_delta_rho_vesta 3 4# 读取数据文件(h5或json格式),处理后输出到cube文件,可直接使用vesta打开且体积小 5write_delta_rho_vesta( 6 total="dspawpy_proj/dspawpy_tests/inputs/supplement/AB.h5", # 包含所有组元的体系的数据文件 7 individuals=[ 8 "dspawpy_proj/dspawpy_tests/inputs/supplement/A.h5", 9 "dspawpy_proj/dspawpy_tests/inputs/supplement/B.h5", 10 ], # 包含各组元的体系的数据文件 11 output="dspawpy_proj/dspawpy_tests/outputs/us/3delta_rho.cube", # 输出文件路径 12)
上述脚本支持处理多元体系的电荷密度差,示例以二元体系为例,得到了 AB.h5 与 A.h5 和 B.h5 之间的电荷密度差文件 delta_rho.cube ,该文件可直接使用 VESTA 打开。
volumetricData面平均
参考
3planar_ave.py
:
1# -*- coding: utf-8 -*-
2from dspawpy.plot import average_along_axis
3
4axes = ["2"] # “0”, "1", "2" 分别对应xyz轴向,选择要沿着哪些轴平均
5axes_indices = [int(i) for i in axes]
6for ai in axes_indices:
7 plt = average_along_axis(
8 datafile="dspawpy_proj/dspawpy_tests/inputs/3.3/scf.h5", # 数据文件路径
9 task="potential", # 任务名称,可以是 'rho', 'potential', 'elf', 'pcharge', 'rhoBound'
10 axis=ai, # 沿着哪个轴向绘制势能曲线
11 smooth=False, # 是否平滑
12 smooth_frac=0.8, # 平滑系数
13 subtype=None, # 用于指定task数据子类,目前仅用于 Potential
14 label=f"axis{ai}", # 图例标签
15 )
16if len(axes_indices) > 1:
17 plt.legend()
18
19plt.xlabel("Grid Index")
20plt.ylabel("TotalElectrostaticPotential (eV)")
21plt.savefig("dspawpy_proj/dspawpy_tests/outputs/us/3pot_ave.png", dpi=300) # 图片名称
处理 应用案例 3.3 小节所得静电势文件,可得真空方向势函数曲线如下所示:
AuAl势函数示意图
8.4 band能带数据处理
知识点:
脚本中调用get_band_data()读取数据,在读取数据时设置efermi=XX可将能量零点修改为指定值;设置zero_to_efermi=True, 可将能量零点修改问所读取的文件中的费米能级处
脚本调用pymatgen的BSPlotter.get_plot()画图,在画图时可设置zero_to_efermi=True,将坐标轴能量零点修改到费米能级处。由于pymatgen在2023.8.17的一处关键更新将绘图函数返回对象从plt改成了axes,导致后续脚本可能出现不兼容。因此用户脚本相关部分已添加一个判断语句加以处理。
能带两步算需从第一步自洽计算获取准确费米能级(从自洽获得的system.json),若获取失败,用户可在调用get_band_data读取数据时,利用参数efermi修改能量零点。例如:band_data=get_band_data(‘band.h5’,efermi=-1.5)
脚本中画图调用pymatgen中的BSPlotter.get_plot, 当判断体系为非金属时,设置zero_to_efermi会认为VBM为费米能级能量而非文件读取时的费米能级。故当体系为非金属时,在数据读取时设置zero_to_efermi=True和在画图时设置zero_to_efermi=True得到的图会有区别
执行本节所列的python脚本,程序会判断是否为金属体系。若为非金属体系,将要求选择是否平移费米能级到能量零点,请按提示操作。
普通能带处理
参考 4bandplot.py
:
1# -*- coding: utf-8 -*-
2import os
3import matplotlib.pyplot as plt
4from dspawpy.io.read import get_band_data
5from pymatgen.electronic_structure.plotter import BSPlotter
6
7datafile = "dspawpy_proj/dspawpy_tests/inputs/supplement/pband.h5" # 指定数据文件路径
8band_data = get_band_data(
9 band_dir=datafile,
10 syst_dir=None, # system.json文件路径,仅当band_dir为json文件时需要
11 efermi=None, # 用于手动修正费米能级
12 zero_to_efermi=True, # 非金属体系应将零点能移动到费米能级
13)
14
15bsp = BSPlotter(band_data)
16axes_or_plt = bsp.get_plot(
17 zero_to_efermi=False, # 上面读取数据时已经平移,此处应关闭
18 ylim=[-10, 10], # 能带图的纵坐标范围
19 smooth=False, # 是否对能带图进行平滑处理
20 vbm_cbm_marker=False, # 是否在能带图中标记导带和价带
21 smooth_tol=0, # 平滑处理的阈值
22 smooth_k=3, # 平滑处理的阶数
23 smooth_np=100, # 平滑处理的点数
24)
25
26if isinstance(axes_or_plt, plt.Axes):
27 fig = axes_or_plt.get_figure() # version newer than v2023.8.10
28else:
29 fig = axes_or_plt.gcf() # older version pymatgen
30
31# 添加能量零点参考线
32for ax in fig.axes:
33 ax.axhline(0, lw=2, ls="-.", color="gray")
34
35figname = "dspawpy_proj/dspawpy_tests/outputs/us/4bandplot.png" # 输出的能带图文件名
36os.makedirs(os.path.dirname(os.path.abspath(figname)), exist_ok=True)
37fig.savefig(figname, dpi=300)
知识点:
能带两步算需从自洽计算获取准确的费米能级(从system.json获取),若获取失败,用户可在 get_band_data 函数中指定 efermi 参数修改
执行代码可以得到类似以下能带图:
二硫化钼能带示意图
将能带投影到每一种元素分别作图,数据点大小表示该元素对该轨道的贡献
参考 4bandplot_elt.py
:
1# -*- coding: utf-8 -*-
2import os
3import numpy as np
4import matplotlib.pyplot as plt
5from dspawpy.io.read import get_band_data
6from pymatgen.electronic_structure.plotter import BSPlotterProjected
7
8datafile = "dspawpy_proj/dspawpy_tests/inputs/supplement/pband.h5" # 指定数据文件路径
9band_data = get_band_data(
10 band_dir=datafile,
11 syst_dir=None, # system.json文件路径,仅当band_dir为json文件时需要
12 efermi=None, # 用于手动修正费米能级
13 zero_to_efermi=True, # 非金属体系应将零点能移动到费米能级
14)
15
16bsp = BSPlotterProjected(bs=band_data) # 初始化BSPlotterProjected类
17axes_or_plt = bsp.get_elt_projected_plots(
18 zero_to_efermi=False, # 上面读取数据时已经平移,此处应关闭
19 ylim=[-8, 5], # 设置能量范围
20 vbm_cbm_marker=False, # 是否标记导带底和价带顶
21)
22
23if isinstance(axes_or_plt, plt.Axes):
24 fig = axes_or_plt.get_figure() # version newer than v2023.8.10
25elif np.iterable(axes_or_plt):
26 fig = np.asarray(axes_or_plt).flatten()[0].get_figure()
27else:
28 fig = axes_or_plt.gcf() # older version pymatgen
29
30# 添加能量零点参考线
31for ax in fig.axes:
32 ax.axhline(0, lw=2, ls="-.", color="gray")
33
34figname = (
35 "dspawpy_proj/dspawpy_tests/outputs/us/4bandplot_elt.png" # 输出的能带图文件名
36)
37os.makedirs(os.path.dirname(os.path.abspath(figname)), exist_ok=True)
38fig.savefig(figname, dpi=300)
知识点:
用户如果需要绘制能带投影的数据,此时需要使用 BSPlotterProjected模块
使用 BSPlotterProjected模块中 get_elt_projected_plots 函数能够绘制每种元素对轨道贡献的能带图
执行代码可以得到类似以下能带图:
二硫化钼元素投影能带示意图
能带投影到不同元素的不同轨道
1# -*- coding: utf-8 -*-
2import os
3import numpy as np
4import matplotlib.pyplot as plt
5from dspawpy.io.read import get_band_data
6from pymatgen.electronic_structure.plotter import BSPlotterProjected
7
8datafile = "dspawpy_proj/dspawpy_tests/inputs/supplement/pband.h5" # 指定数据文件路径
9band_data = get_band_data(
10 band_dir=datafile,
11 syst_dir=None, # system.json文件路径,仅当band_dir为json文件时需要
12 efermi=None, # 用于手动修正费米能级
13 zero_to_efermi=True, # 非金属体系应将零点能移动到费米能级
14)
15
16bsp = BSPlotterProjected(bs=band_data) # 初始化BSPlotterProjected类
17# ! 选定元素与轨道,创建字典
18dict_elem_orbit = {"Mo": ["d"], "S": ["s"]}
19
20axes_or_plt = bsp.get_projected_plots_dots(
21 dictio=dict_elem_orbit,
22 zero_to_efermi=False, # 上面读取数据时已经平移,此处应关闭
23 ylim=[-8, 5], # 设置能量范围
24 vbm_cbm_marker=False, # 是否标记导带底和价带顶
25)
26
27if isinstance(axes_or_plt, plt.Axes):
28 fig = axes_or_plt.get_figure() # version newer than v2023.8.10
29elif np.iterable(axes_or_plt):
30 fig = np.asarray(axes_or_plt).flatten()[0].get_figure()
31else:
32 fig = axes_or_plt.gcf() # older version pymatgen
33
34# 添加能量零点参考线
35for ax in fig.axes:
36 ax.axhline(0, lw=2, ls="-.", color="gray")
37
38figname = "dspawpy_proj/dspawpy_tests/outputs/us/4bandplot_elt_orbit.png" # 输出的能带图文件名
39os.makedirs(os.path.dirname(os.path.abspath(figname)), exist_ok=True)
40fig.savefig(figname, dpi=300)
知识点:
使用 BSPlotterProjected模块中 get_projected_plots_dots可以让用户来自定义需要绘制的某种元素某种轨道(L)的能带图
例如 get_projected_plots_dots ({‘Mo’:[‘d’],’S’:[‘s’]})就是绘制Mo的d轨道和S的s轨道
执行代码可以得到类似以下能带图:
二硫化钼元素轨道投影能带示意图
将能带投影到不同原子的不同轨道
参考 4bandplot_patom_porbit.py
:
1# -*- coding: utf-8 -*- 2import os 3import numpy as np 4import matplotlib.pyplot as plt 5from dspawpy.io.read import get_band_data 6from pymatgen.electronic_structure.plotter import BSPlotterProjected 7 8datafile = "dspawpy_proj/dspawpy_tests/inputs/supplement/pband.h5" # 指定数据文件路径 9band_data = get_band_data( 10 band_dir=datafile, 11 syst_dir=None, # system.json文件路径,仅当band_dir为json文件时需要 12 efermi=None, # 用于手动修正费米能级 13 zero_to_efermi=True, # 非金属体系应将零点能移动到费米能级 14) 15 16bsp = BSPlotterProjected(bs=band_data) 17# ! 指定元素和轨道和原子序号 18dict_elem_orbit = {"Mo": ["px", "py", "pz"]} 19dict_elem_index = {"Mo": [1]} 20 21axes_or_plt = bsp.get_projected_plots_dots_patom_pmorb( 22 dictio=dict_elem_orbit, # 指定元素-轨道字典 23 dictpa=dict_elem_index, # 指定元素-原子序号字典 24 sum_atoms=None, # 是否对原子求和 25 sum_morbs=None, # 是否对轨道求和 26 zero_to_efermi=False, # 上面读取数据时已经平移,此处应关闭 27 ylim=None, # 设置能量范围 28 vbm_cbm_marker=False, # 是否标记导带底和价带顶 29 selected_branches=None, # 指定绘制的能带分支 30 w_h_size=(12, 8), # 设置图片宽高 31 num_column=None, # 设置每行显示的图片数量 32) 33 34if isinstance(axes_or_plt, plt.Axes): 35 fig = axes_or_plt.get_figure() # version newer than v2023.8.10 36elif np.iterable(axes_or_plt): 37 fig = np.asarray(axes_or_plt).flatten()[0].get_figure() 38else: 39 fig = axes_or_plt.gcf() # older version pymatgen 40 41# 添加能量零点参考线 42for ax in fig.axes: 43 ax.axhline(0, lw=2, ls="-.", color="gray") 44 45figname = ( 46 "dspawpy_proj/dspawpy_tests/outputs/us/4band_patom_porbit.png" # 输出的能带图文件名 47) 48os.makedirs(os.path.dirname(os.path.abspath(figname)), exist_ok=True) 49fig.savefig(figname, dpi=300)
知识点:
使用 BSPlotterProjected模块中 get_projected_plots_dots_patom_pmorb 的自由度更高,可以让用户来自定义需要绘制的某些原子某些轨道的能带图
dictpa指定原子,dictio 指定该原子的轨道
如果要将一些原子或一些轨道的投影分量叠加起来,请根据 get_projected_plots_dots_patom_pmorb 函数文档指定 sum_atoms 或 sum_morbs 参数
警告
如果只选择单个轨道,且轨道名称不止一个字母(例如px、dxy、dxz),get_projected_plots_dots_patom_pmorb 函数将报错,详情见 此处
执行代码可以得到类似以下能带图:
二硫化钼原子投影能带示意图
能带反折叠处理
参考 4bandunfolding.py
:
1# -*- coding: utf-8 -*-
2import os
3
4from dspawpy.plot import plot_bandunfolding
5
6plt = plot_bandunfolding(
7 datafile="dspawpy_proj/dspawpy_tests/inputs/2.22.1/band.h5", # 读取数据
8 ef=None, # 费米能级,从文件中读取
9 de=0.05, # 能带宽度,默认0.05
10 dele=0.06, # 能带间隔,默认0.06
11)
12
13plt.ylim(-15, 10)
14figname = (
15 "dspawpy_proj/dspawpy_tests/outputs/us/4bandunfolding.png" # 输出的能带图文件名
16)
17os.makedirs(os.path.dirname(os.path.abspath(figname)), exist_ok=True)
18plt.savefig(figname, dpi=300)
19# plt.show()
执行代码可以得到类似以下能带图:
Cu3Au能带反折叠示意图
警告
此功能暂不支持将非金属材料的费米能级设为能量零点(默认价带顶为能量零点)。
band-compare能带对比图处理
将普通能带和wannier能带绘制在同一张图上
参考 4bandcompare.py
:
1# -*- coding: utf-8 -*-
2import os
3from dspawpy.io.read import get_band_data
4from pymatgen.electronic_structure.plotter import BSPlotter
5
6band_data = get_band_data(
7 band_dir="dspawpy_proj/dspawpy_tests/inputs/2.30/wannier.h5", # 瓦尼尔能带文件路径
8 syst_dir=None, # system.json文件路径,仅当band_dir为json文件时需要
9 efermi=None, # 用于手动修正费米能级
10 zero_to_efermi=False, # 是否将零点能移动到费米能级
11)
12bsp = BSPlotter(bs=band_data)
13band_data = get_band_data(
14 band_dir="dspawpy_proj/dspawpy_tests/inputs/2.3/band.h5", # 读取DFT能带
15 syst_dir=None, # system.json文件路径,仅当band_dir为json文件时需要
16 efermi=None, # 用于手动修正费米能级
17 zero_to_efermi=False, # 是否将零点能移动到费米能级
18)
19
20bsp2 = BSPlotter(bs=band_data)
21bsp.add_bs(bsp2._bs)
22axes_or_plt = bsp.get_plot(
23 zero_to_efermi=True, # 将零点能移动到费米能级
24 ylim=[-10, 10], # 能带图的纵坐标范围
25 smooth=False, # 是否对能带图进行平滑处理
26 vbm_cbm_marker=False, # 是否在能带图中标记导带和价带
27 smooth_tol=0, # 平滑处理的阈值
28 smooth_k=3, # 平滑处理的阶数
29 smooth_np=100, # 平滑处理的点数
30 bs_labels=["wannier interpolated", "DFT"], # 能带图中的标签
31)
32
33import matplotlib.pyplot as plt # noqa: E402
34
35if isinstance(axes_or_plt, plt.Axes):
36 fig = axes_or_plt.get_figure() # version newer than v2023.8.10
37else:
38 fig = axes_or_plt.gcf() # older version pymatgen
39
40# 添加能量零点参考线
41for ax in fig.axes:
42 ax.axhline(0, lw=2, ls="-.", color="gray")
43
44figname = "dspawpy_proj/dspawpy_tests/outputs/us/4wanierBand.png" # 输出的能带图文件名
45os.makedirs(os.path.dirname(os.path.abspath(figname)), exist_ok=True)
46fig.savefig(figname, dpi=300)
执行代码可得到类似如下能带对比曲线:
晶体硅瓦尼尔能带与DFT能带示意图
8.5 dos态密度数据处理
总的态密度
参考 5dosplot_total.py
:
1# -*- coding: utf-8 -*-
2import os
3from dspawpy.io.read import get_dos_data
4from pymatgen.electronic_structure.plotter import DosPlotter
5from dspawpy.plot import plot_dos
6
7dos_data = get_dos_data(
8 dos_dir="dspawpy_proj/dspawpy_tests/inputs/3.2.4/dos.h5", # 读取投影态密度数据
9 return_dos=False, # 如果为False,则统一返回CompleteDos对象(无论计算时是否开了投影)
10)
11dos_plotter = DosPlotter(
12 zero_at_efermi=True, # 是否将费米能级作为零点
13 stack=False, # True表示绘制面积图
14 sigma=None, # 高斯展宽,None表示不进行平滑处理
15)
16dos_plotter.add_dos(label="total dos", dos=dos_data) # 设置态密度图例 # 传入态密度数据
17
18ax = plot_dos(
19 dosplotter=dos_plotter,
20 xlim=[-10, 5], # 设置能量范围
21 ylim=[-15, 15], # 设置态密度范围
22)
23ax.axhline(0, lw=2, ls="-.", color="gray")
24
25filename = (
26 "dspawpy_proj/dspawpy_tests/outputs/us/5dos_total.png" # 输出的态密度图文件名
27)
28os.makedirs(os.path.dirname(os.path.abspath(filename)), exist_ok=True)
29
30fig = ax.get_figure()
31fig.savefig(filename, dpi=300)
知识点:
使用 get_dos_data 函数可以将DS-PAW计算得到的 dos.h5 文件转化为 pymatgen 支持的格式
使用 DosPlotter模块获取到DS-PAW计算的 dos.h5 的数据
DosPlotter函数可以传递参数:stack参数表示画态密度是否加阴影, zero_at_efermi 表示是否在态密度图中进行将费米能量置零,这里设置 stack=False , zero_at_efermi=False
使用 DosPlotter 模块中 add_dos 获取态密度的数据
DosPlotter模块中 get_plot函数 绘制态密度图
执行代码可以得到类似以下态密度图:
NiO态密度示意图
将态密度投影到不同的轨道上
参考 5dosplot_spd.py
:
1# -*- coding: utf-8 -*-
2import os
3from dspawpy.plot import plot_dos
4from dspawpy.io.read import get_dos_data
5from pymatgen.electronic_structure.plotter import DosPlotter
6
7dos_data = get_dos_data(
8 dos_dir="dspawpy_proj/dspawpy_tests/inputs/3.2.4/dos.h5", # 读取投影态密度数据
9 return_dos=False, # 如果为False,则统一返回CompleteDos对象(无论计算时是否开了投影)
10)
11dos_plotter = DosPlotter(
12 zero_at_efermi=True, # 是否将费米能级作为零点
13 stack=False, # True表示绘制面积图
14 sigma=None, # 高斯展宽,None表示不进行平滑处理
15)
16dos_plotter.add_dos_dict(
17 dos_dict=dos_data.get_spd_dos(),
18 key_sort_func=None, # 轨道投影 # 指定排序函数
19)
20ax = plot_dos(
21 dosplotter=dos_plotter,
22 xlim=[-10, 5], # 设置能量范围
23 ylim=None, # 设置态密度范围
24)
25
26ax.axhline(0, lw=2, ls="-.", color="gray")
27
28filename = "dspawpy_proj/dspawpy_tests/outputs/us/5dos_spd.png" # 输出的态密度图文件名
29os.makedirs(os.path.dirname(os.path.abspath(filename)), exist_ok=True)
30
31fig = ax.get_figure()
32fig.savefig(filename, dpi=300)
知识点:
使用 DosPlotter模块中 add_dos_dict 函数 获取投影态密度的数据,之后使用 get_spd_dos 将投影信息按照 spd 轨道投影输出
执行代码可以得到类似以下态密度图:
NiO轨道投影态密度示意图
将态密度投影到不同的元素上
参考 5dosplot_elt.py
:
1# -*- coding: utf-8 -*-
2import os
3from dspawpy.plot import plot_dos
4from dspawpy.io.read import get_dos_data
5from pymatgen.electronic_structure.plotter import DosPlotter
6
7dos_data = get_dos_data(
8 dos_dir="dspawpy_proj/dspawpy_tests/inputs/3.2.4/dos.h5", # 读取投影态密度数据
9 return_dos=False, # 如果为False,则统一返回CompleteDos对象(无论计算时是否开了投影)
10)
11dos_plotter = DosPlotter(
12 zero_at_efermi=True, # 是否将费米能级作为零点
13 stack=False, # True表示绘制面积图
14 sigma=None, # 高斯展宽,None表示不进行平滑处理
15)
16dos_plotter.add_dos_dict(
17 dos_dict=dos_data.get_element_dos(),
18 key_sort_func=None, # 元素投影态密度 # 指定排序函数
19)
20
21ax = plot_dos(
22 dosplotter=dos_plotter,
23 xlim=[-10, 5], # 设置能量范围
24 ylim=None, # 设置态密度范围
25)
26ax.axhline(0, lw=2, ls="-.", color="gray")
27
28filename = "dspawpy_proj/dspawpy_tests/outputs/us/5dos_elt.png" # 输出的态密度图文件名
29os.makedirs(os.path.dirname(os.path.abspath(filename)), exist_ok=True)
30
31fig = ax.get_figure()
32fig.savefig(filename, dpi=300)
知识点:
使用 DosPlotter模块中 add_dos_dict 函数 获取投影态密度的数据,之后使用 get_element_dos 将投影信息按照不同元素投影输出
执行代码可以得到类似以下态密度图:
NiO元素投影态密度示意图
将态密度投影到不同原子的不同轨道上
1# -*- coding: utf-8 -*-
2import os
3from dspawpy.io.read import get_dos_data
4from dspawpy.plot import plot_dos
5from pymatgen.electronic_structure.core import Orbital
6from pymatgen.electronic_structure.plotter import DosPlotter
7
8dos_data = get_dos_data(
9 dos_dir="dspawpy_proj/dspawpy_tests/inputs/3.2.4/dos.h5", # 读取投影态密度数据
10 return_dos=False, # 如果为False,则统一返回CompleteDos对象(无论计算时是否开了投影)
11)
12dos_plotter = DosPlotter(
13 zero_at_efermi=True, # 是否将费米能级作为零点
14 stack=False, # True表示绘制面积图
15 sigma=None, # 高斯展宽,None表示不进行平滑处理
16)
17
18# ! 指定原子序号和轨道
19dict_index_orbit = {0: ["dxy"], 2: ["s"]}
20
21print("正在绘图...")
22for index in dict_index_orbit:
23 _os = dict_index_orbit[index]
24 _e = str(dos_data.structure.sites[index].species)
25 for _orb in _os:
26 dos_plotter.add_dos(
27 f"{_e}(atom-{index}) {_orb}", # label
28 dos_data.get_site_orbital_dos(
29 dos_data.structure[index], getattr(Orbital, _orb)
30 ),
31 )
32
33ax = plot_dos(
34 dosplotter=dos_plotter,
35 xlim=[-10, 5], # 设置能量范围
36 ylim=None, # 设置态密度范围
37)
38ax.axhline(0, lw=2, ls="-.", color="gray")
39
40figname = (
41 "dspawpy_proj/dspawpy_tests/outputs/us/5dos_atom_orbit.png" # 输出的态密度图文件名
42)
43os.makedirs(os.path.dirname(os.path.abspath(figname)), exist_ok=True)
44
45fig = ax.get_figure()
46fig.savefig(figname, dpi=300)
知识点:
使用 get_site_orbital_dos函数提取dos数据中特定原子特定轨道的贡献,dos_data.structure[0],Orbital(4) 表示获取第1个原子的dxy轨道的态密度,get_site_orbital_dos函数中序号从0开始
运行此脚本,根据提示选择元素和轨道,可以得到相应的态密度图
执行代码可以得到类似以下态密度图:
NiO原子轨道态密度示意图
将态密度投影到不同原子的分裂d轨道(t2g, eg)上
参考 5dosplot_t2g_eg.py
:
1# -*- coding: utf-8 -*-
2import os
3from dspawpy.plot import plot_dos
4from dspawpy.io.read import get_dos_data
5from pymatgen.electronic_structure.plotter import DosPlotter
6
7dos_data = get_dos_data(
8 dos_dir="dspawpy_proj/dspawpy_tests/inputs/3.2.4/dos.h5", # 读取投影态密度数据
9 return_dos=False, # 如果为False,则统一返回CompleteDos对象(无论计算时是否开了投影)
10)
11dos_plotter = DosPlotter(
12 zero_at_efermi=True, # 是否将费米能级作为零点
13 stack=False, # True表示绘制面积图
14 sigma=None, # 高斯展宽,None表示不进行平滑处理
15)
16# print(dos_data.structure)
17
18# ! 指定原子序号,从0开始
19ais = [1]
20
21print("正在绘图...")
22atom_indices = [int(ai) for ai in ais]
23for atom_index in atom_indices:
24 dos_plotter.add_dos_dict(
25 dos_data.get_site_t2g_eg_resolved_dos(dos_data.structure[atom_index])
26 )
27
28ax = plot_dos(
29 dosplotter=dos_plotter,
30 xlim=[-10, 5], # 设置能量范围
31 ylim=None, # 设置态密度范围
32)
33ax.axhline(0, lw=2, ls="-.", color="gray")
34
35filename = (
36 "dspawpy_proj/dspawpy_tests/outputs/us/5dos_t2g_eg.png" # 输出的态密度图文件名
37)
38os.makedirs(os.path.dirname(os.path.abspath(filename)), exist_ok=True)
39
40fig = ax.get_figure()
41fig.savefig(filename, dpi=300)
知识点:
使用 get_site_t2g_eg_resolved_dos函数 提取dos数据中特定原子的 t2g和 eg轨道的贡献,这是获取第2个原子的t2g和eg轨道的贡献
运行此脚本,根据提示选择原子序号,可以得到相应的态密度图
执行代码可以得到类似以下态密度图:
NiO分裂d轨道原子投影态密度示意图
知识点:
如果元素不含d轨道,会画成空白图片
d-带中心分析
以 Pb-slab 体系为例,对 Pt 原子进行 d-band 中心分析:
参考 5center_dband.py
:
1# -*- coding: utf-8 -*-
2from dspawpy.io.read import get_dos_data
3from dspawpy.io.utils import d_band
4
5dos_data = get_dos_data(
6 dos_dir="dspawpy_proj/dspawpy_tests/inputs/supplement/dos.h5", # 读取投影态密度数据
7 return_dos=False, # 如果为False,则统一返回CompleteDos对象(无论计算时是否开了投影)
8)
9for spin in dos_data.densities:
10 print("spin=", spin)
11 c = d_band(spin, dos_data)
12 print(c)
执行代码可以得到类似以下结果:
spin=1
-1.785319344084034
备注
目前仅支持全部原子平均的 d 轨道中心,不支持元素、原子投影或其他轨道,也不支持选择自旋方向或能量范围。
get_dos_data
函数负责处理态密度数据:
8.6 bandDos能带和态密度共同显示
以应用教程中Si体系为例:
将能带和态密度显示在一张图上
参考 6bandDosplot.py
:
1# -*- coding: utf-8 -*-
2import os
3import numpy as np
4from matplotlib.axes import Axes
5from dspawpy.io.read import get_band_data, get_dos_data
6from pymatgen.electronic_structure.plotter import BSDOSPlotter
7
8bandfile = "dspawpy_proj/dspawpy_tests/inputs/2.3/band.h5" # 普通能带数据
9band_data = get_band_data(
10 band_dir=bandfile,
11 syst_dir=None, # system.json文件路径,仅当band_dir为json文件时需要
12 efermi=None, # 用于手动修正费米能级
13 zero_to_efermi=True, # 非金属体系应将零点能移动到费米能级
14)
15dosfile = "dspawpy_proj/dspawpy_tests/inputs/2.5/dos.h5" # 态密度数据
16dos_data = get_dos_data(
17 dos_dir=dosfile,
18 return_dos=False, # 如果为False,则统一返回CompleteDos对象(无论计算时是否开了投影)
19)
20bdp = BSDOSPlotter(
21 bs_projection="elements", # 能带的投影方式,None表示不投影
22 dos_projection=None, # 态密度的投影方式,None表示不投影
23 vb_energy_range=4, # 价带能量范围
24 cb_energy_range=4, # 导带能量范围
25 fixed_cb_energy=False, # 是否固定导带能量范围
26 egrid_interval=1, # 能量格点间隔
27 font="DejaVu Sans", # 默认Times New Roman,修改成 DejaVu Sans,可避免在linux上因字体未安装而出现的警告
28 axis_fontsize=20, # 坐标轴字体大小
29 tick_fontsize=15, # 刻度字体大小
30 legend_fontsize=14, # 图例字体大小
31 bs_legend="best", # 能带图图例位置
32 dos_legend="best", # 态密度图图例位置
33 rgb_legend=True, # 是否使用彩色图例
34 fig_size=(11, 8.5), # 图片大小
35)
36axes_or_plt = bdp.get_plot(bs=band_data, dos=dos_data) # 传入能带数据 # 传入态密度数据
37
38if isinstance(axes_or_plt, Axes):
39 fig = axes_or_plt.get_figure() # version newer than v2023.8.10
40elif np.iterable(axes_or_plt):
41 fig = np.asarray(axes_or_plt).flatten()[0].get_figure()
42else:
43 fig = axes_or_plt.gcf() # older version pymatgen
44
45filename = (
46 "dspawpy_proj/dspawpy_tests/outputs/us/6bandDos.png" # 输出的能带-态密度图文件名
47)
48os.makedirs(os.path.dirname(os.path.abspath(filename)), exist_ok=True)
49fig.savefig(filename, dpi=300)
执行代码可以得到类似以下能带态密度图:
单晶硅能带-态密度示意图
将能带和投影态密度显示在一张图上
参考 6bandPdosplot.py
:
1# -*- coding: utf-8 -*-
2import os
3import numpy as np
4from matplotlib.axes import Axes
5from dspawpy.io.read import get_band_data, get_dos_data
6from pymatgen.electronic_structure.plotter import BSDOSPlotter
7
8bandfile = "dspawpy_proj/dspawpy_tests/inputs/2.3/band.h5" # 普通能带数据
9band_data = get_band_data(
10 band_dir=bandfile,
11 syst_dir=None, # system.json文件路径,仅当band_dir为json文件时需要
12 efermi=None, # 用于手动修正费米能级
13 zero_to_efermi=True, # 非金属体系应将零点能移动到费米能级
14)
15dosfile = "dspawpy_proj/dspawpy_tests/inputs/2.6/dos.h5" # 投影态密度数据
16dos_data = get_dos_data(
17 dos_dir=dosfile,
18 return_dos=False, # 如果为False,则统一返回CompleteDos对象(无论计算时是否开了投影)
19)
20bdp = BSDOSPlotter(
21 bs_projection="elements", # 能带的投影方式,None表示不投影
22 dos_projection="elements", # 投影态密度到元素上
23 vb_energy_range=4, # 价带能量范围
24 cb_energy_range=4, # 导带能量范围
25 fixed_cb_energy=False, # 是否固定导带能量范围
26 egrid_interval=1, # 能量格点间隔
27 font="DejaVu Sans", # 默认Times New Roman,修改成 DejaVu Sans,可避免在linux上因字体未安装而出现的警告
28 axis_fontsize=20, # 坐标轴字体大小
29 tick_fontsize=15, # 刻度字体大小
30 legend_fontsize=14, # 图例字体大小
31 bs_legend="best", # 能带图图例位置
32 dos_legend="best", # 投影态密度图图例位置
33 rgb_legend=True, # 是否使用彩色图例
34 fig_size=(11, 8.5), # 图片大小
35)
36axes_or_plt = bdp.get_plot(
37 bs=band_data, dos=dos_data
38) # 传入能带数据 # 传入投影态密度数据
39
40if isinstance(axes_or_plt, Axes):
41 fig = axes_or_plt.get_figure() # version newer than v2023.8.10
42elif np.iterable(axes_or_plt):
43 fig = np.asarray(axes_or_plt).flatten()[0].get_figure()
44else:
45 fig = axes_or_plt.gcf() # older version pymatgen
46
47filename = "dspawpy_proj/dspawpy_tests/outputs/us/6bandPdos.png" # 输出的能带-投影态密度图文件名
48os.makedirs(os.path.dirname(os.path.abspath(filename)), exist_ok=True)
49fig.savefig(filename, dpi=300)
执行代码可以得到类似以下能带态密度图:
单晶硅能带-投影态密度示意图
警告
给定投影能带数据,默认将沿着元素投影;给定普通能带数据(或体系所含元素种类超过4种),则不投影,并输出警告
给定投影态密度数据,默认也将沿着元素投影,可以换成沿着轨道投影,或者不投影;给定普通态密度数据且未关闭态密度投影选项 BSDOSPlotter(dos_projection=None),pymatgen绘图程序将报错,这就是上面特意准备了一个 6bandDosplot.py 文件的原因。
8.7 optical光学性质数据处理
以快速入门Si体系光学性质计算得到的 scf.h5 为例(注:输出文件名与task一致,task = scf,io.optical = true可计算光学性质):
反射率数据处理,参考 7optical.py
:
1# -*- coding: utf-8 -*-
2import os
3
4import matplotlib.pyplot as plt # noqa: E402
5from dspawpy.plot import plot_optical
6
7# 读取数据,处理反射率数据
8plot_optical(
9 datafile="dspawpy_proj/dspawpy_tests/inputs/2.12/scf.h5",
10 keys=["ExtinctionCoefficient", "Reflectance"],
11 raw=True,
12)
13# 绘图细节
14plt.tick_params(labelsize=16)
15plt.tight_layout()
16
17filename = (
18 "dspawpy_proj/dspawpy_tests/outputs/us/7optical.png" # 输出的光学性质图文件名
19)
20os.makedirs(os.path.dirname(os.path.abspath(filename)), exist_ok=True)
21plt.savefig(filename, dpi=300)
22# plt.show()
知识点:
Reflectance为光学性质中的一种,用户可以根据自己的需求将该关键词修改为“AbsorptionCoefficient”或”ExtinctionCoefficient”或”RefractiveIndex”,分别对应吸收系数、消光系数和折射率
执行代码可以得到类似以下反射率随能量变化的曲线:
单晶硅Reflectance随光子能量变化趋势示意图
8.8 neb过渡态计算数据处理
以快速入门 H 在 Pt(100) 表面扩散为例进行介绍:
输入文件之生成中间构型
参考
8neb_interpolate_structures.py
:1# -*- coding: utf-8 -*- 2from dspawpy.diffusion.neb import NEB, write_neb_structures 3from dspawpy.diffusion.nebtools import write_json_chain 4from dspawpy.io.structure import read 5 6# 读取初态构型 7init_struct = read("dspawpy_proj/dspawpy_tests/inputs/2.15/00/structure00.as")[0] 8# 读取末态构型 9final_struct = read("dspawpy_proj/dspawpy_tests/inputs/2.15/04/structure04.as")[0] 10 11neb = NEB( 12 initial_structure=init_struct, # 初态构型 13 final_structure=final_struct, # 末态构型 14 nimages=8, # 共8个构型,包括初末态 15) 16structures = neb.linear_interpolate() # 线性插值 17# structures = neb.idpp_interpolate() #idpp插值 18 19# 保存 as 结构文件到 dest 路径下 20write_neb_structures( 21 structures=structures, # 插入插值后的构型链 22 coords_are_cartesian=True, # 是否以笛卡尔坐标保存 23 fmt="as", # 保存格式,支持'json', 'as', 'hzw', 'pdb', 'xyz', 'dump' 六种 24 path="dspawpy_proj/dspawpy_tests/outputs/us/8neb_interpolate_structures", # 保存路径 25 prefix="structure", # 文件名前缀 26) 27 28# 预览初插构型链 29write_json_chain( 30 preview=True, # 是否为预览模式 31 directory="dspawpy_proj/dspawpy_tests/outputs/us/8neb_interpolate_structures", # NEB计算目录 32 step=-1, # 默认保存最后一个离子步(最新)的构型链 33 dst="dspawpy_proj/dspawpy_tests/outputs/us/8neb", # 保存路径 34) 35# write_xyz_chain(preview=True, # 是否为预览模式 36# directory="dspawpy_proj/dspawpy_tests/outputs/us/8neb_interpolate_structures", # NEB计算目录 37# step=-1, # 默认保存最后一个离子步(最新)的构型链 38# dst='dspawpy_proj/dspawpy_tests/outputs/us/8neb' # 保存路径 39# )
知识点:
用户可以根据需要自行修改插点个数,设置为8得到包含8个结构文件的文件夹,其中中间构型为6个
neb.linear_interpolate为线性插值方法,若使用idpp插值请注释该行放开下一行
绘制能垒图
neb.iniFin = true/false
当设置 neb.iniFin = true/false 时,都可使用读取neb计算的路径进行势垒分析(确保初末态计算文件在neb计算路径下):
参考
8neb_barrier_CubicSpline.py
:1# -*- coding: utf-8 -*- 2from dspawpy.diffusion.nebtools import plot_barrier 3 4directory_of_neb_task = ( 5 "dspawpy_proj/dspawpy_tests/inputs/2.15" # <-- 请修改成实际NEB路径 6) 7 8# 三次样条插值 (CubicSpline) 绘制能垒图 9plot_barrier( 10 directory=directory_of_neb_task, # neb任务的路径 11 method="CubicSpline", # 三次样条插值 12 figname="dspawpy_proj/dspawpy_tests/outputs/us/8neb_barrier_CubicSpline.png", # 输出的能垒图文件名 13 show=False, # 是否显示能垒图 14)
备注
运行上述脚本后,可得到类似以下三次样条插值的势垒曲线:
对于这个算例,三次样条插值后,曲线会出现不合理的“下坠”区域,这是三次样条插值算法的特性所决定的。
dspawpy 内部调用 scipy 的插值算法 ,上面这个脚本我们以三次样条插值算法为例,它在 scipy 文档中的定义为:
class scipy.interpolate.CubicSpline(x, y, axis=0, bc_type='not-a-knot', extrapolate=None)
关键词参数包括 axis, bc_type, extrapolate,具体含义见 scipy.interpolate.CubicSpline 。我们可以往 plot_barrier 函数中指定相应的关键词参数(axis, bc_type, extrapolate),将其传递给 scipy.interpolate.CubicSpline 这个类处理。
下面我们采用 8neb_barrier.py
脚本,对比三种算法插值绘制出的曲线:
1# -*- coding: utf-8 -*-
2import os
3
4import matplotlib.pyplot as plt # noqa: E402
5from dspawpy.diffusion.nebtools import plot_barrier
6
7# 对比不同插值方法绘制出的能垒曲线的区别,此时show应当设置为False
8# 1. interp1d
9plot_barrier(
10 directory="dspawpy_proj/dspawpy_tests/inputs/2.15", # neb计算的路径
11 ri=None, # 初始构型与第二个构型之间的反应坐标,当NEB任务只计算了中间构型时需要
12 rf=None, # 最后一个构型与倒数第二个构型之间的反应坐标,当NEB任务只计算了中间构型时需要
13 ei=None, # 初始构型的能量,当NEB任务只计算了中间构型时需要
14 ef=None, # 最后一个构型的能量,当NEB任务只计算了中间构型时需要
15 method="interp1d", # 插值方法
16 figname=None, # 输出的能垒图文件名
17 show=False, # 是否显示能垒图
18 kind="quadratic", # 插值方法的参数
19)
20# 2. CubicSpline
21plot_barrier(
22 directory="dspawpy_proj/dspawpy_tests/inputs/2.15",
23 method="CubicSpline",
24 figname=None,
25 show=False,
26)
27# 3. pchip
28plot_barrier(
29 directory="dspawpy_proj/dspawpy_tests/inputs/2.15",
30 method="pchip",
31 figname=None,
32 show=False,
33)
34
35filename = "dspawpy_proj/dspawpy_tests/outputs/us/8neb_barrier_comparison.png" # 输出的能垒图文件名
36os.makedirs(os.path.dirname(os.path.abspath(filename)), exist_ok=True)
37plt.savefig(filename, dpi=300)
38# plt.show()
知识点:
选择合适的插值算法对于优化最终曲线的呈现效果至关重要
多数情况下,选择 pchip 这种单调三次样条插值算法即可达到较好效果,这也是默认调用的插值算法
neb.iniFin = true
当设置 neb.iniFin = true 时,读取neb计算所得的 neb.h5/neb.json 文件可快速进行势垒分析:
参考
8neb_barrier_CubicSpline.py
:1# -*- coding: utf-8 -*- 2from dspawpy.diffusion.nebtools import plot_barrier 3 4# 三次样条插值 (CubicSpline) 绘制能垒图 5plot_barrier( 6 datafile="dspawpy_proj/dspawpy_tests/inputs/2.15/neb.h5", # neb.h5的路径 7 method="CubicSpline", # 三次样条插值 8 figname="dspawpy_proj/dspawpy_tests/outputs/us/8neb_barrier_.png", # 输出的能垒图文件名 9 show=False, # 是否显示能垒图 10)
处理得到的势垒图与之前读取路径效果一致。
备注
neb.h5 和 neb.json文件所存能量为TotalEnergy,如需得精确的势垒值,建议采用读取neb计算路径的方法进行处理(取TotalEnergy0)
过渡态计算数据处理
NEB计算完成后,一般要画出能垒图观察,并检查各插值构型最终的受力大小,从而确保受力小于指定的阈值。如果结果异常,还需要检查各插值构型在结构优化过程中的受力与能量变化趋势,判断是否真正“收敛”。上述这些操作至少需要三次循环,为简化操作,我们提供了一个一步到位的总结函数 summary
:
-
1# -*- coding: utf-8 -*- 2from dspawpy.diffusion.nebtools import summary 3 4# 导入neb计算目录,需提供neb计算完成后的完整文件夹 5summary( 6 directory="dspawpy_proj/dspawpy_tests/inputs/2.15", 7 show_converge=False, # 是否显示能量和受力收敛过程图 8 outdir="dspawpy_proj/dspawpy_tests/outputs/us/8neb", # 能量和受力收敛过程图保存路径 9 figname="dspawpy_proj/dspawpy_tests/outputs/us/8neb/neb_barrier_summary.png", # 能垒图保存路径 10) 11# 可以进一步设置其他关键字参数,用于绘制能垒图,例如: 12# summary(directory = 'dspawpy_proj/dspawpy_tests/inputs/2.15', method='CubicSpline') # 改为三次样条插值CubicSpline
知识点:
此脚本将以表格形式打印各构型的能量和受力、绘制能垒图,并绘制中间构型的能量与受力收敛过程图
若
neb.iniFin = false
,用户必须将自洽计算的结果文件 scf.h5 或 system.json 文件复制到对应的初末态子文件夹中,否则程序无法读取初末态能量和受力信息,将报错退出默认情况下,能垒图存储在neb计算目录外层,各中间构型的能量与受力收敛图存储在各子文件夹
执行代码可以得到类似如下NEB计算各构型的能量和受力表格:
Image
Force (eV/Å)
Reaction coordinate (Å)
Energy (eV)
Delta energy (eV)
00
0.1803
0.0000
-39637.0984
0.0000
01
0.0263
0.5428
-39637.0186
0.0798
02
0.0248
1.0868
-39636.8801
0.2183
03
0.2344
1.5884
-39636.9984
0.1000
04
0.0141
2.0892
-39637.0900
0.0084
除了可以获得能垒图外,还可以得到各中间构型的能量和受力收敛曲线(以02构型为例)
观察NEB链
此处所说NEB链指的是各插值构型(structure00.as, structure01.as, …)之间的几何关系,而不是单个构型在优化过程中的变化。
NEB任务计算量较大,观察NEB链有助于判断NEB计算的收敛速度。另外,通过插值算法生成中间结构后,经常需要预览NEB链。这些需求可以通过
8neb_visualize.py
脚本实现:
1# -*- coding: utf-8 -*-
2from dspawpy.diffusion.nebtools import write_json_chain, write_xyz_chain
3
4# 将NEB计算路径下的构型链转成json格式文件
5write_json_chain(
6 preview=False, # NEB计算如果已经完成,则可以不是预览模式
7 directory="dspawpy_proj/dspawpy_tests/inputs/2.15", # NEB计算目录
8 step=-1, # 默认保存最后一个离子步(最新)的构型链
9 dst="dspawpy_proj/dspawpy_tests/outputs/us/8neb", # 保存路径
10 ignorels=False, # 设为True则忽略 latestStructureXX.as 文件
11)
12
13# 将NEB计算路径下的构型链转成xyz格式文件
14write_xyz_chain(
15 preview=False, # NEB计算如果已经完成,则可以不是预览模式
16 directory="dspawpy_proj/dspawpy_tests/inputs/2.15", # NEB计算目录
17 step=-1, # 默认保存最后一个离子步(最新)的构型链
18 dst="dspawpy_proj/dspawpy_tests/outputs/us/8neb", # 保存路径
19 ignorels=False, # 设为True则忽略 latestStructureXX.as 文件
20)
知识点:
此脚本生成neb_movie*.json文件后,通过
Device Studio
–>Simulator
–>DS-PAW
–>Analysis Plot
打开 json 文件即可观察directory指定为NEB计算主路径,需提供neb计算完成后的完整文件夹
该脚本支持处理正在进行中的(即未完成的)neb计算文件,方便用户监测实时轨迹
xyz文件可通过 OVITO 软件打开查看:通过
Device Studio
–>Simulator
–>OVITO
打开可视化界面,将xyz文件拖入即可结构信息读取优先级:latestStructureXX.as > h5 > json;设置ignorels为True后,先尝试读取 h5 中的数据,失败则读取 json 中的数据
计算构型间距
参考这个脚本
8calc_dist.py
:1# -*- coding: utf-8 -*- 2from dspawpy.diffusion.nebtools import get_distance 3from dspawpy.io.structure import read 4 5# 请根据实际情况修改 structure01.as 和 structure02.as 结构文件的路径 6# 先读取两个构型的分数坐标、元素列表和晶胞信息 7s1 = read("dspawpy_proj/dspawpy_tests/inputs/2.15/01/structure01.as")[0] 8s2 = read("dspawpy_proj/dspawpy_tests/inputs/2.15/02/structure02.as")[0] 9# 计算两个构型的距离,注意这个函数只接受分数坐标 10dist = get_distance( 11 spo1=s1.frac_coords, 12 spo2=s2.frac_coords, 13 lat1=s1.lattice.matrix, 14 lat2=s2.lattice.matrix, 15) 16print("两个构型的距离为:", dist, "Angstrom")
neb续算
如果需对neb进行续算,可参考
8neb_restart.py
:1# -*- coding: utf-8 -*- 2from dspawpy.diffusion.nebtools import restart 3from shutil import copytree 4import os 5 6if not os.path.exists("dspawpy_proj/dspawpy_tests/inputs/supplement/neb4bk"): 7 copytree( 8 "dspawpy_proj/dspawpy_tests/inputs/2.15", 9 "dspawpy_proj/dspawpy_tests/inputs/supplement/neb4bk", 10 ) 11restart( 12 directory="dspawpy_proj/dspawpy_tests/inputs/supplement/neb4bk", 13 output="dspawpy_proj/dspawpy_tests/outputs/us/8neb_restart", # NEB任务路径 # 备份到哪 14)
具体效果见 neb过渡态计算续算说明。
8.9 phonon声子计算数据处理
以MgO体系的声子能带态密度计算得到的 phonon.h5 为例:
如果未安装 phonopy,运行下列脚本时会弹出 no module named 'phonopy'
信息,不影响程序正常运行
声子能带数据处理
参考
9phonon_bandplot.py
:
1# -*- coding: utf-8 -*-
2import os
3
4from dspawpy.io.read import get_phonon_band_data
5from pymatgen.phonon.plotter import PhononBSPlotter
6
7band_data = get_phonon_band_data(
8 "dspawpy_proj/dspawpy_tests/inputs/2.16.1/phonon.h5"
9) # 读取声子能带
10bsp = PhononBSPlotter(band_data)
11axes_or_plt = bsp.get_plot(ylim=None, units="thz") # y轴范围 # 单位
12import matplotlib.pyplot as plt # noqa: E402
13
14if isinstance(axes_or_plt, plt.Axes):
15 fig = axes_or_plt.get_figure() # version newer than v2023.8.10
16elif isinstance(axes_or_plt, tuple):
17 fig = axes_or_plt[0].get_figure()
18else:
19 fig = axes_or_plt.gcf() # older version pymatgen
20
21filename = "dspawpy_proj/dspawpy_tests/outputs/us/9phonon_bandplot.png" # 输出的声子能带图文件名
22os.makedirs(os.path.dirname(os.path.abspath(filename)), exist_ok=True)
23fig.savefig(filename, dpi=300)
执行代码可以得到类似以下声子能带曲线:
声子态密度数据处理
参考
9phonon_dosplot.py
:1# -*- coding: utf-8 -*- 2import os 3 4from dspawpy.io.read import get_phonon_dos_data 5from pymatgen.phonon.plotter import PhononDosPlotter 6 7dos = get_phonon_dos_data("dspawpy_proj/dspawpy_tests/inputs/2.16.1/phonon.h5") 8dp = PhononDosPlotter( 9 stack=False, # True表示绘制面积图 10 sigma=None, # 高斯模糊参数 11) 12dp.add_dos(label="Phonon", dos=dos) # 图例 # 要绘制的声子态密度 13axes_or_plt = dp.get_plot( 14 xlim=[0, 20], # x轴范围 15 ylim=None, # y轴范围 16 units="thz", # 单位 17) 18import matplotlib.pyplot as plt # noqa: E402 19 20if isinstance(axes_or_plt, plt.Axes): 21 fig = axes_or_plt.get_figure() # version newer than v2023.8.10 22elif isinstance(axes_or_plt, tuple): 23 fig = axes_or_plt[0].get_figure() 24else: 25 fig = axes_or_plt.gcf() # older version pymatgen 26 27filename = ( 28 "dspawpy_proj/dspawpy_tests/outputs/us/9phonon_dosplot.png" # 输出的能垒图文件名 29) 30os.makedirs(os.path.dirname(os.path.abspath(filename)), exist_ok=True) 31fig.savefig(filename, dpi=300)
执行代码可以得到类似以下声子态密度曲线:
单晶硅声子态密度示意图
声子热力学数据处理
可以参考 9phonon_thermal.py
:
1# -*- coding: utf-8 -*-
2from dspawpy.plot import plot_phonon_thermal
3
4plot_phonon_thermal(
5 datafile="dspawpy_proj/dspawpy_tests/inputs/2.26/phonon.h5", # phonon.h5数据文件路径
6 figname="dspawpy_proj/dspawpy_tests/outputs/us/9phonon.png", # 输出的声子热力学图文件名
7 show=False, # 是否显示图片
8)
执行代码可以得到类似以下声子热力学曲线:
单晶硅声子热力学性质示意图
8.10 aimd分子动力学模拟数据处理
以快速入门 \(H_{2}O\) 分子体系分子动力学模拟得到的 aimd.h5 为例:
轨迹文件转换格式为.xyz或.dump
从aimd输出的hdf5文件中读取数据,并生成轨迹文件
生成的.xyz或.dump格式文件,可拖入OVITO观察,通过 Device Studio –> Simulator –> OVITO 打开 OVITO 可视化界面,将xyz文件或dump文件拖入OVITO即可。
参考 10write_aimd_traj.py
:
1# -*- coding: utf-8 -*-
2from dspawpy.io.structure import convert
3
4convert(
5 infile="dspawpy_proj/dspawpy_tests/inputs/2.18/aimd.h5", # 待转化结构,如果在当前路径,可以只写文件名
6 si=None, # 筛选构型编号,如果不指定,默认读取全部
7 ele=None, # 筛选元素符号,默认读取所有元素的原子信息
8 ai=None, # 筛选原子编号,从 1 开始,默认读取所有原子信息
9 outfile="dspawpy_proj/dspawpy_tests/outputs/us/10aimdTraj.xyz", # 也可以生成 .dump 文件(精度较低),暂时只支持正交晶胞
10)
执行代码将生成.xyz和.dump格式的轨迹文件,该文件可通过OVITO打开。关于结构文件转化的更多细节,请参考 structure结构转化
知识点:
OVITO 与 dspawpy 都不支持将非正交晶胞的体系保存为dump文件
动力学过程中能量、温度等变化曲线
参考
10check_aimd_conv.py
:1# -*- coding: utf-8 -*- 2from dspawpy.plot import plot_aimd 3 4plot_aimd( 5 datafile="dspawpy_proj/dspawpy_tests/inputs/2.18/aimd.h5", # 数据文件路径 6 show=False, # 是否弹出图像窗口 7 figname="dspawpy_proj/dspawpy_tests/outputs/us/10aimd.png", # 输出的图像文件名 8 flags_str="1 2 3 4 5", # 选择数据类型 9) 10# 其中flags_str的含义如下 11# 1. 动能 12# 2. 总能 13# 3. 压力 14# 4. 温度 15# 5. 体积
执行代码将生成如下组合图:
均方位移(MSD) 分析
参考
10aimd_msd.py
:1# -*- coding: utf-8 -*- 2from dspawpy.analysis.aimdtools import get_lagtime_msd, plot_msd 3 4# 如果AIMD非一次性完成,可以将多个h5文件路径以列表形式赋值给datafile参数 5lagtime, msd = get_lagtime_msd( 6 datafile="dspawpy_proj/dspawpy_tests/inputs/2.18/aimd.h5", # 数据文件路径 7 select="all", # 默认选择所有原子 8 msd_type="xyz", # 默认计算xyz方向的msd 9 timestep=None, # 默认从datafile文件中读取时间步长 10) 11# 用获取的数据画图并保存 12plot_msd( 13 lagtime, # 横坐标 14 msd, # 纵坐标 15 xlim=None, # 设置x轴的显示范围 16 ylim=None, # 设置y轴的显示范围 17 figname="dspawpy_proj/dspawpy_tests/outputs/us/10MSD.png", # 输出的图像文件名 18 show=False, # 是否弹出图像窗口 19 # ax = None, # 可指定子图 20)
执行代码将生成类似如下图片:
均方位移(MSD)示意图
均方根偏差(RMSD) 分析
参考
10aimd_rmsd.py
:1# -*- coding: utf-8 -*- 2from dspawpy.analysis.aimdtools import get_lagtime_rmsd, plot_rmsd 3 4# 如果AIMD非一次性完成,可以将多个h5文件路径以列表形式赋值给datafile参数 5lagtime, rmsd = get_lagtime_rmsd( 6 datafile="dspawpy_proj/dspawpy_tests/inputs/2.18/aimd.h5", 7 timestep=None, # 数据文件路径 # 默认从datafile文件中读取时间步长 8) 9plot_rmsd( 10 lagtime, # 横坐标 11 rmsd, # 纵坐标 12 xlim=None, # 设置x轴的显示范围 13 ylim=None, # 设置y轴的显示范围 14 figname="dspawpy_proj/dspawpy_tests/outputs/us/10RMSD.png", # 输出的图像文件名 15 show=False, # 是否弹出图像窗口 16 ax=None, # 可指定子图 17)
执行代码将生成类似如下图片:
均方根偏差(RMSD)示意图
原子对分布函数或径向分布函数(RDFs) 分析
参考
10aimd_rdf.py
:1# -*- coding: utf-8 -*- 2from dspawpy.analysis.aimdtools import get_rs_rdfs, plot_rdf 3 4# 如果AIMD非一次性完成,可以将多个h5文件路径以列表形式赋值给datafile参数 5rs, rdfs = get_rs_rdfs( 6 datafile="dspawpy_proj/dspawpy_tests/inputs/2.18/aimd.h5", # 数据文件路径 7 ele1="H", # 中心元素 8 ele2="O", # 对象元素 9 rmin=0.0, # 最小半径 10 rmax=10.0, # 最大半径 11 ngrid=1000, # 网格数 12 sigma=0.1, # sigma值 13) 14plot_rdf( 15 rs, # 横坐标 16 rdfs, # 纵坐标 17 "H", # 中心元素 18 "O", # 对象元素 19 figname="dspawpy_proj/dspawpy_tests/outputs/us/10RDF.png", # 图像保存路径 20 show=False, # 是否弹出图像窗口 21 ax=None, # 可指定子图 22)
执行代码将生成类似如下图片:
径向分布函数(RDFs)示意图
这部分涉及的统计学计算较复杂,更多细节请参考函数API
8.11 Polarization铁电极化数据处理
以快速入门 \(HfO_{2}\) 体系铁电计算得到的系列 scf.h5 为例:
参考
11Ferri.py
:1# -*- coding: utf-8 -*- 2from dspawpy.plot import plot_polarization_figure 3 4plot_polarization_figure( 5 directory="dspawpy_proj/dspawpy_tests/inputs/2.20", # 铁电极化计算路径 6 repetition=2, # 数据点绘图时重复次数 7 figname="dspawpy_proj/dspawpy_tests/outputs/us/11pol.png", # 输出的极化图文件名 8 show=False, # 是否显示极化图 9) # --> pol.png
执行代码将生成如下组合图:
12组结构对应极化数值
查看首尾构型的铁电极化数值,可以参考如下:
1from dspawpy.plot import plot_polarization_figure 2 3plot_polarization_figure(directory='.', annotation=True, annotation_style=1) # 显示首尾构型的铁电极化数值
执行代码将生成如下组合图:
12组结构对应极化数值(带首尾构型数值)
也可以使用第二种批注样式:
1from dspawpy.plot import plot_polarization_figure 2 3plot_polarization_figure(directory='.', annotation=True, annotation_style=2) # 显示首尾构型的铁电极化数值
执行代码将生成如下组合图:
12组结构对应极化数值(带首尾构型数值)
8.12 ZPE零点振动能数据处理
以快速入门 \(CO\) 体系频率计算得到的 frequency.txt 文件为例,计算零点振动能,基于以下公式:
其中, \(\nu_i\) 是简正频率, \(h\) 是普朗克常数( \(6.626\times10^{-34} J\cdot s\)), \(N\) 是原子数。
参考
12getZPE.py
:1# -*- coding: utf-8 -*- 2from dspawpy.io.utils import getZPE 3 4# 导入频率计算得到的frequency.txt文件 5getZPE( 6 fretxt="dspawpy_proj/dspawpy_tests/inputs/2.13/frequency.txt", 7 outfile="dspawpy_proj/dspawpy_tests/outputs/us/12ZPE.txt", 8)
执行代码结果文件将保存到 ZPE.dat 文件中,文件内容如下:
Data read from D:\quickstart\2.13\frequency.txt Frequency (meV) 284.840038 --> Zero-point energy, ZPE (eV): 0.142420019
8.13 TS的热校正能
吸附质的熵变对能量的贡献
计算基于以下公式:
其中, \(\Delta S_{a d s}\) 表示吸附质的熵变,根据简谐近似计算。\(S_{v i b}\) 表示振动熵。 \(\nu_i\) 是简正频率,\(N_A\) 是阿伏伽德罗常数( \(6.022\times10^{23} mol^{-1}\) ), \(h\) 是普朗克常数( \(6.626\times10^{-34} J\cdot s\)), \(k_B\) 是玻尔兹曼常数( \(1.38\times10^{-23} J\cdot K^{-1}\)), \(R\) 是理想气体常数( \(8.314 J\cdot mol^{-1}\cdot K^{-1}\)), \(T\) 是体系温度,单位 \(K\)。
参考
13getTSads.py
:1# -*- coding: utf-8 -*- 2from dspawpy.io.utils import getTSads 3 4# 导入频率计算得到的frequency.txt文件,温度可自行修改 5getTSads( 6 fretxt="dspawpy_proj/dspawpy_tests/inputs/2.13/frequency.txt", 7 T=298.15, 8 outfile="dspawpy_proj/dspawpy_tests/outputs/us/13TSads.txt", 9)
执行代码结果文件将保存到 TS.dat 文件中,文件内容如下:
Data read from D:\quickstart\2.13\frequency.txt Frequency (THz) 68.873994 --> Entropy contribution, T*S (eV): 4.7566990201851275e-06
理想气体的熵变对能量的贡献
计算基于如下公式:
其中:
其中:\(I_A\) 到 \(I_C\) 是非线性分子的三个主惯性矩, \(I\) 是线性分子的简并惯性矩, \(\sigma\) 是分子的对称数。另外,momatomic 表示单原子分子,linear 表示线性分子,nonlinear 表示非线性分子。total spin 是总自旋数。 vib DOF 表示振动自由度。
参考
13getTSgas.py
脚本处理:1# -*- coding: utf-8 -*- 2from dspawpy.io.utils import getTSgas 3 4# 从计算结果文件json或h5中读取元素和坐标 5TSgas = getTSgas( 6 fretxt="dspawpy_proj/dspawpy_tests/inputs/2.13/frequency.txt", 7 datafile="dspawpy_proj/dspawpy_tests/inputs/2.13/frequency.h5", 8 potentialenergy=-0.0, 9 geometry="linear", 10 symmetrynumber=1, 11 spin=1, 12 temperature=298.15, 13 pressure=101325.0, 14 outfile="dspawpy_proj/dspawpy_tests/outputs/us/13TSgas.txt", 15) 16print("Entropy contribution, T*S (eV):", TSgas) 17 18# 如果只有频率txt文件,可通过手动指定元素和坐标完成计算 19# TSgas = getTSgas(fretxt='dspawpy_proj/dspawpy_tests/inputs/2.13/frequency.txt', datafile=None, potentialenergy=-0.0, elements=['H', 'H'], geometry='linear', positions=[[0.0, 0.0, 0.0], [0.0, 0.0, 1.0]], symmetrynumber=1, spin=1, temperature=298.15, pressure=101325.0)
8.14 附录
快速下载所有脚本,点击
用户脚本.zip