3D能带即将常见绘制在布里渊区高对称点路径上的电子能带绘制在倒空间内,通过倒空间轴的立体坐标,将能带立体化。
计算参考流程见:
https://vaspkit.com/tutorials.html#example-graphene-3d-band-structure
准备用于SCF计算的POSCAR和INCAR文件
运行VASPKIT并选择231
生成用于3D标注栏计算的KPOINTS文件。
231
+-------------------------- Warm Tips --------------------------+ * Accuracy Levels: (1) Low: 0.04~0.03; (2) Medium: 0.03~0.02; (3) Fine: 0.02~0.01. * 0.015 is Generally Precise Enough! +---------------------------------------------------------------+ Input KP-Resolved Value (unit: 2*PI/Ang): ------------>>0.015
-->> (01) Reading Structural Parameters from POSCAR File... -->> (02) Written KPOINTS File!
所生成的KP点包含1加权KP点和0加权KP点(注意,为了获得平滑的3D能带,用于生成KP点文件的分辨率值应该设置在0.01左右)
VASP计算完成后,再次运行VASPKIT并输入232或者233命令。
------------>>233 +-------------------------- Warm Tips --------------------------+ ONLY Reliable for Band-Structure Calculations! +---------------------------------------------------------------+ -->> (1) Reading Input Parameters From INCAR File... -->> (2) Reading Structural Parameters from POSCAR File... -->> (3) Reading Fermi-Level From DOSCAR File...ooooooooo The Fermi Energy will be set to zero eV oooooooooooooooo -->> (4) Reading Energy-Levels From EIGENVAL File... -->> (5) Reading Kmesh From KPOINTS File... -->> (6) Written BAND.HOMO.grd File. -->> (7) Written BAND.LUMO.grd File. -->> (8) Written KX.grd and KY.grd Files.
233命令可以输出VBM和CBM。保存在HOMO.grd和BAND.LUMO.grd。
232可以得到指定能带的计算数据。
如果VASPKIT已经设置了自动绘图,则会自动输出3D.PNG
这里使用具有空间群C2/m的 MoSeS结构的能带作示意图。

限于VASPKIT普通版本的绘图精度和设置自由度,使用vaspkit example中的绘图脚本,进行可设定的绘图。
文件路径:
vaspkit/examples/3D_band/

how_to_visual.m对应于MATLAB代码, how_to_visual.py 对应于python代码,均可进行对BAND_HOMO.grd BAND_LUMO.grd KX.grd KY.grd 数据文件的读取和绘图。
案例中石墨烯的3D能带绘制效果为

使用how_to_visual.m代码在MATLAB中进行绘制可实现角度拖动和放大缩放和自定义颜色等操作。


附how_to_visual.m代码内容
% An example for the visualization of 3D-bandstructure for graphene by using MATLABclcclear
kx_mesh=load('KX.grd'); ky_mesh=load('KY.grd'); CBM_mesh=load('BAND_LUMO.grd'); VBM_mesh=load('BAND_HOMO.grd');surf(kx_mesh,ky_mesh,VBM_mesh);hold onsurf(kx_mesh,ky_mesh,CBM_mesh);contourf(kx_mesh,ky_mesh,CBM_mesh,4)grid onhold offxlabel('$\it{k}_{x} (\textrm{1/\AA})$','Interpreter','latex','Fontname','TimesNewRoman')ylabel('$\it{k}_{y} (\textrm{1/\AA})$','Interpreter','latex','Fontname','TimesNewRoman')zlabel('Energy (eV)')axis imageaxis vis3dshading interp;colormap(hsv);set(gca,'FontSize',18);hold offzlim([-6,6]);
而通过运行how_to_visual.py代码,
#!/usr/bin/python# -*- coding:utf-8 -*-import numpy as npimport matplotlib as mplmpl.use('Agg') #silent modefrom matplotlib import pyplot as pltimport matplotlib.ticker as tickerfrom mpl_toolkits.mplot3d.axes3d import Axes3Dtry: kx_mesh=np.loadtxt('KX.grd') ky_mesh=np.loadtxt('KY.grd') CBM_mesh=np.loadtxt('BAND_LUMO.grd') VBM_mesh=np.loadtxt('BAND_HOMO.grd')except: print("Failed to open grds!")font = {'family' : 'arial', 'color' : 'black', 'weight' : 'normal', 'size' : 13, } fig = plt.figure()ax0 = fig.add_subplot(131, projection="3d") cmap = plt.cm.get_cmap("hsv") ax0.plot_surface(kx_mesh,ky_mesh,VBM_mesh,alpha=0.7,rstride=1,cstride=1,cmap=cmap,lw=0)ax0.plot_surface(kx_mesh,ky_mesh,CBM_mesh,alpha=0.7,rstride=1,cstride=1,cmap=cmap,lw=0)ax0.contourf(kx_mesh,ky_mesh,CBM_mesh,zdir='z',offset=0,cmap=cmap)#ax0.set_xlabel(r'$\mathbf{k}_{x}$',fontdict=font)ax0.set_ylabel(r'$\mathbf{k}_{y}$',fontdict=font)ax0.set_zlabel(r'$Energy (eV)$',fontdict=font)ax0.set_zlim((-5,5))ax0.set_xticks([])ax0.view_init(elev=0, azim=0) ax = fig.add_subplot(132, projection="3d") cmap = plt.cm.get_cmap("hsv") ax.plot_surface(kx_mesh,ky_mesh,VBM_mesh,alpha=0.7,rstride=1,cstride=1,cmap=cmap,lw=0)ax.plot_surface(kx_mesh,ky_mesh,CBM_mesh,alpha=0.7,rstride=1,cstride=1,cmap=cmap,lw=0)ax.contourf(kx_mesh,ky_mesh,CBM_mesh,zdir='z',offset=0,cmap=cmap)ax.set_xlabel(r'$\mathbf{k}_{x}$',fontdict=font)ax.set_ylabel(r'$\mathbf{k}_{y}$',fontdict=font)ax.set_zlabel(r'$Energy (eV)$',fontdict=font)ax.set_zlim((-5,5))ax.view_init(elev=0, azim=45)ax1 = fig.add_subplot(133, projection="3d") cmap = plt.cm.get_cmap("hsv") ax1.plot_surface(kx_mesh,ky_mesh,VBM_mesh,alpha=0.7,rstride=1,cstride=1,cmap=cmap,lw=0)ax1.plot_surface(kx_mesh,ky_mesh,CBM_mesh,alpha=0.7,rstride=1,cstride=1,cmap=cmap,lw=0)ax1.contourf(kx_mesh,ky_mesh,CBM_mesh,zdir='z',offset=0,cmap=cmap)ax1.set_xlabel(r'$\mathbf{k}_{x}$',fontdict=font)ax1.set_ylabel(r'$\mathbf{k}_{y}$',fontdict=font)ax1.set_zlabel(r'$Energy (eV)$',fontdict=font)ax1.set_zlim((-5,5))ax1.view_init(elev=5, azim=45)fig = plt.gcf()fig.set_size_inches(8,6)plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, hspace = 0, wspace = 0)#plt.show()plt.savefig('3D.png',dpi=300,pad_inches = 0)
运行效果为

可更改脚本末尾处设置,增强分辨率
#plt.show()plt.savefig('3D.png',dpi=800,pad_inches = 0)
使用下部可实现制作3D能带旋转动图
from matplotlib.animation import FuncAnimationdef rotate(angle, elev=0): ax.view_init(elev=elev, azim=angle) return ax
rot_animation = FuncAnimation(fig, rotate, frames=np.arange(0, 360, 5), interval=100, fargs=(0,))rot_animation.save('3D.gif', dpi=80, writer='pillow')plt.close()
这里使用具有空间群C2/m的 MoSeS结构的能带作示意图。
同时可通过更改代码实现自定义颜色渐变和连续。

绘制处于平面内旋转角度0-350°内不同角度的图像,并保存在文件夹degree中
if not os.path.exists('degree'): os.makedirs('degree')for angle in np.arange(0, 360, 10): ax.view_init(elev=0, azim=angle) plt.savefig(f'degree/degree_{angle:03d}.png', dpi=600, pad_inches=0, bbox_inches='tight')
plt.close()

部分角度输出图像如图如下(使用结构: MoSeS,C2/m),实际使用时请根据倒格矢确定位置。

3D-BAND.GIF完整脚本
#!/usr/bin/python# -*- coding:utf-8 -*-import numpy as npimport matplotlib as mplmpl.use('Agg') # silent modefrom matplotlib import pyplot as pltimport matplotlib.ticker as tickerfrom mpl_toolkits.mplot3d.axes3d import Axes3D
try: kx_mesh = np.loadtxt('KX.grd') ky_mesh = np.loadtxt('KY.grd') CBM_mesh = np.loadtxt('BAND_LUMO.grd') VBM_mesh = np.loadtxt('BAND_HOMO.grd')
except: print("Failed to open .grd files!")
font = {'family': 'arial', 'color': 'black', 'weight': 'normal', 'size': 13, }
fig = plt.figure(figsize=(8, 6))ax = fig.add_subplot(111, projection="3d")
cmap = plt.cm.get_cmap("viridis")ax.plot_surface(kx_mesh, ky_mesh, VBM_mesh, alpha=0.7, rstride=1, cstride=1, cmap=cmap, lw=0)ax.plot_surface(kx_mesh, ky_mesh, CBM_mesh, alpha=0.7, rstride=1, cstride=1, cmap=cmap, lw=0)
ax.contourf(kx_mesh, ky_mesh, CBM_mesh, zdir='z', offset=0, cmap=cmap, alpha=0.5)
ax.set_zlim((-1, 1))ax.set_xticks([])ax.set_zticks(np.linspace(-1, 1, 5))ax.set_ylabel(r'$\mathbf{k}_{y}$', fontdict=font)ax.set_zlabel(r'$Energy (eV)$', fontdict=font)
plt.subplots_adjust(top=1, bottom=0, right=1, left=0, hspace=0, wspace=0)
from matplotlib.animation import FuncAnimation
def rotate(angle, elev=0): ax.view_init(elev=elev, azim=angle) return ax
rot_animation = FuncAnimation(fig, rotate, frames=np.arange(0, 360, 5), interval=100, fargs=(0,))rot_animation.save('3D.gif', dpi=80, writer='pillow')plt.close()