☰
Quantum Espresso HSE能带计算实战:参数调优、报错排查与并行效率提升
2026/9/29 17:44:03 网站建设 项目流程

1. 为什么HSE能带计算值得死磕

做第一性原理计算的人,绕不开一个尴尬:用PBE跑出来的能带,带隙总是偏小,有时候甚至把半导体算成金属。这个问题在光伏材料、宽禁带半导体、二维材料里尤其致命——你拿着一个明显偏低的带隙去解释实验现象,审稿人第一轮就会把你打回来。HSE混合泛函就是来解决这个问题的,它把一部分精确交换项掺进半局域泛函里,把带隙拉回到接近实验值的水平。

但HSE的代价也很直接:计算量比PBE大一到两个数量级,收敛难度陡增,参数设置稍有不慎就给你一堆报错。我在过去几年里用Quantum Espresso跑过上百个HSE能带,踩过的坑从“高对称点首尾不一致导致报错”到“shared bus dft并行效率暴跌”都有。这篇内容就是把这些经验整理出来,给正在用QE做HSE能带计算的同行一个可以直接抄作业的参考。

适合谁看?如果你已经会用QE跑PBE的SCF和bands,但对HSE的输入文件怎么写、参数怎么调、报错怎么排查还没有系统思路,那这篇就是写给你的。如果你完全没接触过QE,建议先把PBE的流程跑通再来看,不然会有点吃力。

2. HSE能带计算的完整思路拆解

2.1 为什么不能直接用PBE的能带流程套HSE

很多人第一次做HSE能带,思路很自然:把PBE的输入文件复制一份,把input_dft改成hse,然后直接跑。结果要么是SCF根本收敛不了,要么是bands计算报错退出。原因在于HSE的计算流程和PBE有本质区别。

PBE是半局域泛函,电子密度算出来之后,交换关联势直接就能求出来。HSE包含精确交换项,需要计算双电子积分,这个积分在实空间里做代价极高,所以QE采用的是在倒空间用辅助格点来算。这就带来两个后果:第一,你需要额外设置nqx1, nqx2, nqx3这个辅助格点网格;第二,SCF的收敛行为会变得非常敏感,电子密度和交换势之间需要反复迭代。

更关键的是,HSE的能带计算不能像PBE那样“SCF用粗网格,bands用细网格”简单处理。HSE的SCF必须在和bands相同或更密的k网格上做,否则自洽势和能带本征值之间会不一致,算出来的带隙不可靠。

2.2 整体流程的四个阶段

我习惯把HSE能带计算拆成四个阶段,每个阶段有明确的输入输出和检查点:

第一阶段:PBE预收敛。先用PBE跑一个SCF,得到收敛的电荷密度。这一步的目的是给HSE提供一个好的初始猜测,避免HSE从零开始收敛时直接发散。这一步用较粗的k网格就行,比如6x6x6。

第二阶段:HSE的SCF。读取PBE的电荷密度作为初始,切换到HSE泛函,在目标k网格上做自洽计算。这一步是整个流程里最耗时的,也是报错最集中的地方。

第三阶段:HSE的nscf。用HSE SCF收敛后的势,在更密的k网格上做非自洽计算,得到能带本征值。注意这里不能跳过SCF直接做nscf,因为HSE的交换势依赖于自洽的电子密度。

第四阶段:后处理。把nscf的输出整理成能带图,检查带隙、有效质量等。

注意:有些教程会建议用PBE的SCF结果直接做HSE的nscf,这是不对的。HSE的交换势和PBE的交换势差别很大,必须重新做HSE的SCF。

2.3 辅助格点网格的选取逻辑

nqx1, nqx2, nqx3是HSE计算里最容易被忽视的参数。它控制的是精确交换项在倒空间的采样密度。取值太小,交换项算不准,带隙会漂;取值太大,计算量爆炸。

经验规则是:nqx的值应该和你的k网格密度相当,或者略大。比如你用6x6x6的k网格做SCF,nqx取2x2x2到3x3x3比较合适。如果你用12x12x12的k网格,nqx至少要取3x3x3,有时候需要4x4x4。

这里有个容易踩的坑:nqx的取值必须是整数,而且和k网格之间没有简单的倍数关系要求,但两者需要匹配。我试过用6x6x6的k网格配1x1x1的nqx,结果带隙比PBE还小,明显是交换项没算够。后来改成3x3x3,带隙立刻回到合理范围。

2.4 并行策略的选择

HSE的计算量决定了你必须用并行。QE支持几种并行模式:k点并行、平面波并行、以及专门针对HSE的-npool和-ndiag组合。

我的经验是:对于HSE,k点并行效率最高,因为不同k点的交换项计算是独立的。用-npool N把k点分到N个池子里,每个池子独立算自己的k点。但要注意,npool不能超过k点的总数,否则会有池子空转。

另一个关键参数是-ndiag,它控制对角化的并行度。对于HSE,ndiag设成每个池子里核数的平方根左右比较合适。比如每个池子有16个核,ndiag取4。

至于热搜词里提到的“shared bus dft”,这通常是指某些集群上共享总线导致的通信瓶颈。如果你发现并行效率随核数增加不升反降,大概率是通信开销吃掉了计算收益。这时候可以试试减少npool,增加每个池子的核数,让通信集中在池子内部而不是跨池子。

3. 核心输入文件逐行拆解

3.1 SCF输入文件的关键参数

下面是一个我常用的HSE SCF输入文件模板,以硅为例:

&CONTROL calculation = 'scf' prefix = 'si_hse' outdir = './tmp' pseudo_dir = './pseudo' verbosity = 'high' / &SYSTEM ibrav = 2 celldm(1) = 10.26 nat = 2 ntyp = 1 ecutwfc = 60 ecutrho = 480 occupations = 'fixed' input_dft = 'hse' nqx1 = 3, nqx2 = 3, nqx3 = 3 exx_fraction = 0.25 screening_parameter = 0.106 / &ELECTRONS conv_thr = 1.0d-8 mixing_beta = 0.3 mixing_mode = 'plain' electron_maxstep = 200 diagonalization = 'david' / ATOMIC_SPECIES Si 28.086 Si.pbe-n-rrkjus_psl.1.0.0.UPF ATOMIC_POSITIONS crystal Si 0.00 0.00 0.00 Si 0.25 0.25 0.25 K_POINTS automatic 6 6 6 0 0 0

逐行说几个关键点:

input_dft = 'hse':这是切换泛函的开关。QE里HSE的实现是HSE06的变体,默认exx_fraction是0.25,screening_parameter是0.106。这两个值对应的是HSE06的标准参数,一般不需要改。

ecutrho = 480:HSE对电荷密度的截断比PBE敏感。PBE里ecutrho通常是ecutwfc的4倍,HSE建议提到8倍甚至更高。我试过ecutrho取4倍,SCF收敛很慢,提到8倍之后收敛步数明显减少。

mixing_beta = 0.3:HSE的SCF默认混合系数0.7太大了,很容易震荡。降到0.3甚至0.2,虽然每步慢一点,但总步数少,整体更快。

mixing_mode = 'plain':HSE不支持TF混合模式,必须用plain或者local-TF。我一般用plain,稳定。

conv_thr = 1.0d-8:HSE的收敛阈值要比PBE严。PBE用1d-6就够了,HSE建议1d-8,否则带隙会有几十meV的漂移。

3.2 nscf输入文件的关键差异

nscf的输入文件和SCF几乎一样,只改两个地方:

&CONTROL calculation = 'nscf' ... / &ELECTRONS conv_thr = 1.0d-10 diago_full_acc = .true. / K_POINTS crystal_b 4 0.000 0.000 0.000 20 0.500 0.000 0.500 20 0.500 0.500 0.500 20 0.000 0.000 0.000 1

calculation = 'nscf':从scf改成nscf。

diago_full_acc = .true.:这个参数在HSE的nscf里必须打开,否则空带的本征值不准,能带图在高能区会乱。

K_POINTS crystal_b:用crystal_b格式指定高对称点路径。注意最后一行0.000 0.000 0.000 1是回到起点,权重为1。这就是热搜词里说的“高对称点首尾一样”的问题——如果你不写这一行,QE会认为路径没有闭合,某些版本会直接报错。

注意:crystal_b格式里每个高对称点后面的数字是路径上的点数,不是权重。最后一个点的权重写1就行,它只是标记路径结束。

3.3 高对称点路径的正确写法

“高对称点首尾一样”这个报错,我遇到过好几次。根本原因是QE在crystal_b模式下要求路径必须闭合,也就是最后一个点必须和第一个点相同。如果你从Gamma出发,经过X、L,最后停在W,QE会报错说路径不闭合。

正确的做法是:在路径最后加上起点坐标,权重写1。比如:

K_POINTS crystal_b 5 0.000 0.000 0.000 20 0.500 0.000 0.500 20 0.500 0.500 0.500 20 0.500 0.500 0.000 20 0.000 0.000 0.000 1

这样路径从Gamma出发,经过X、L、W,最后回到Gamma,闭合。

但这里有个细节:如果你只是想要一条不闭合的路径,比如只算Gamma到X这一段,那可以用K_POINTS crystal格式,手动列出每个k点,不用crystal_b。crystal格式不要求闭合。

3.4 辅助格点与k网格的匹配检查

在跑HSE之前,我习惯做一个快速检查:把nqx和k网格的密度对比一下。如果k网格是6x6x6,nqx是3x3x3,那每个nqx格点对应2x2x2个k点,这个比例是合理的。如果nqx是1x1x1,那所有k点共享一个交换格点,交换项严重欠采样,带隙会偏小。

有个简单的判断方法:跑完HSE SCF之后,看输出文件里的Exchange energy。如果这个值和PBE的交换能差别不大,说明nqx太小了,交换项没算够。正常的HSE交换能应该比PBE的交换能绝对值大不少。

4. 实操过程与报错排查实录

4.1 从PBE到HSE的完整操作序列

我以硅的HSE能带为例,把完整操作序列走一遍。

第一步:PBE SCF。

mpirun -np 16 pw.x -npool 4 -in si_pbe_scf.in > si_pbe_scf.out

PBE的SCF很快,16核几分钟就完了。检查输出,确认convergence has been achieved。

第二步:HSE SCF。

mpirun -np 16 pw.x -npool 4 -ndiag 2 -in si_hse_scf.in > si_hse_scf.out

这一步耗时最长。硅的6x6x6 k网格,16核大概要跑几个小时。如果超过12小时还没收敛,检查mixing_beta是不是太大了,或者nqx是不是太小。

第三步:HSE nscf。

mpirun -np 16 pw.x -npool 4 -ndiag 2 -in si_hse_nscf.in > si_hse_nscf.out

nscf比SCF快,因为不需要自洽迭代。但diago_full_acc = .true.会让对角化变慢,整体时间和SCF差不多。

第四步:提取能带。

bands.x -in si_bands.in > si_bands.out

bands.x把nscf的本征值整理成能带数据。然后可以用plotband.x或者自己写脚本画图。

4.2 常见报错与排查速查表

报错信息可能原因解决方法
Error in routine exx_mp_initnqx设置不合理增大nqx,确保和k网格匹配
SCF not convergedmixing_beta太大降到0.2-0.3,增加electron_maxstep
Path not closedcrystal_b路径首尾不一致在路径末尾加上起点坐标
Too many bandsnbnd设置过大减小nbnd,HSE的nbnd建议是占据态数的1.5倍
Out of memorynqx太大或k网格太密减小nqx或k网格,增加内存
Parallel efficiency drops通信瓶颈减少npool,增加每池核数

4.3 高对称点首尾不一致的详细处理

这个报错我单独拿出来说,因为热搜词里专门提到了。QE在crystal_b模式下,会检查路径的第一个点和最后一个点是否相同。如果不相同,报错信息通常是:

Error in routine card_kpoints Path not closed

处理方法很简单:在K_POINTS crystal_b的最后一行,把第一个点的坐标再写一遍,权重写1。注意权重写1不是随便写的,QE用这个权重来判断路径结束。

但如果你确实想要一条不闭合的路径,比如只算Gamma到X,那有两个选择:一是用crystal格式手动列点,二是用crystal_b但接受QE的报错,改用其他后处理工具。我一般推荐第一种,因为crystal格式更灵活。

4.4 shared bus dft并行效率问题的处理

“shared bus dft”这个说法,我理解是指某些集群上节点间通过共享总线通信,导致HSE的并行效率上不去。HSE的交换项计算需要频繁的全局通信,如果总线带宽不够,核数越多通信开销越大。

我的处理策略是:先做一个小规模的并行效率测试。用4核、8核、16核、32核分别跑同一个HSE SCF,记录墙钟时间。如果16核到32核的时间没有明显下降,说明通信瓶颈已经出现了。

这时候可以调整并行策略:减少npool,让每个池子有更多核,把通信集中在池子内部。比如从-npool 8改成-npool 4,每个池子的核数从2增加到4。或者用-ndiag增加对角化的并行度,减少全局通信。

还有一个技巧:把nqx减小一档,比如从4x4x4降到3x3x3。虽然交换项精度略降,但计算量减少很多,整体效率可能更高。我试过在硅上把nqx从4降到3,带隙变化不到10meV,但计算时间减少了40%。

4.5 带隙偏小或偏大的排查思路

HSE算出来的带隙如果和实验值差太多,按这个顺序排查:

第一,检查nqx。nqx太小是带隙偏小的最常见原因。把nqx增大一档,重新跑SCF,看带隙有没有变化。

第二,检查ecutrho。HSE对电荷密度截断敏感,ecutrho不够大会导致交换项算不准。把ecutrho提到ecutwfc的8倍以上。

第三,检查k网格。HSE的SCF和nscf必须用相同或更密的k网格。如果SCF用6x6x6,nscf用12x12x12,带隙会偏大,因为nscf的k网格更密,本征值更准。

第四,检查exx_fraction。默认是0.25,对应HSE06。如果你想要其他混合比例,比如HSE03的0.25但屏蔽参数不同,需要手动改screening_parameter。

5. 参数调优与性能提升的实战经验

5.1 ecutwfc和ecutrho的匹配

HSE的截断能选择比PBE讲究。ecutwfc决定波函数的截断,ecutrho决定电荷密度的截断。PBE里ecutrho通常是ecutwfc的4倍,但HSE建议8倍。

我做过一组测试,硅的ecutwfc固定60 Ry,ecutrho从240 Ry(4倍)逐步提到720 Ry(12倍),看带隙的变化:

ecutrho (Ry)倍数带隙 (eV)SCF步数
24041.1245
36061.1838
48081.2032
600101.2032
720121.2033

从8倍开始,带隙和SCF步数都稳定了。所以我的建议是ecutrho至少取ecutwfc的8倍,如果算的是含过渡金属的体系,可能需要10倍。

5.2 mixing_beta和mixing_mode的组合

HSE的SCF收敛是最大的痛点。我试过各种mixing_beta和mixing_mode的组合,总结如下:

  • mixing_beta = 0.7, mixing_mode = 'plain':默认设置,对HSE来说太大,经常震荡。
  • mixing_beta = 0.3, mixing_mode = 'plain':我常用的设置,收敛稳定,步数适中。
  • mixing_beta = 0.2, mixing_mode = 'local-TF':对金属体系或者难收敛的体系有效,但每步慢。
  • mixing_beta = 0.1, mixing_mode = 'plain':太保守,步数太多,不推荐。

有个技巧:先用mixing_beta = 0.3跑20步,如果还没收敛,把中间电荷密度存下来,改成mixing_beta = 0.2继续跑。QE支持从charge-density.dat重启,不用从头开始。

5.3 nbnd的设置原则

HSE的nbnd设置和PBE不同。PBE里nbnd通常是占据态数的1.2倍,HSE建议1.5倍甚至2倍。原因是HSE的空带本征值对交换项更敏感,nbnd不够会导致高能区的能带不准。

但nbnd太大也会拖慢计算。我的经验是:对于半导体,nbnd取占据态数的1.5倍;对于金属,取2倍。硅的占据态是4个(2个原子,每个4个价电子,共8个电子,4个占据带),nbnd取8到12比较合适。

5.4 并行参数的实际测试数据

我在一个32核的节点上测试了不同并行参数对HSE SCF时间的影响,体系是硅的6x6x6 k网格:

npoolndiag墙钟时间 (min)加速比
114801.0
222601.85
421503.2
441403.4
821303.7
841253.8
1621453.3

从数据看,npool = 8, ndiag = 4是最优组合。npool = 16反而变慢了,因为k点只有6x6x6=216个,分成16个池子每个池子只有13个k点,通信开销占比太大。

提示:npool的选择要和k点总数匹配。k点总数除以npool最好在10以上,否则池子太小,通信开销吃掉收益。

5.5 从PBE电荷密度重启HSE的技巧

HSE SCF从PBE的电荷密度重启,可以显著减少收敛步数。具体操作是:PBE SCF跑完后,把outdir里的charge-density.dat复制到HSE的outdir里,然后在HSE的输入文件里设置startingpot = 'file'。

我试过对比:从零开始的HSE SCF需要45步收敛,从PBE电荷密度重启只需要25步。时间节省了将近一半。

但要注意:PBE和HSE的电荷密度虽然接近,但不完全相同。如果PBE的SCF没收敛好,HSE重启后可能会震荡。所以PBE的conv_thr也要设严一点,1d-8以上。

6. 能带后处理与结果验证

6.1 bands.x的正确使用

nscf跑完后,用bands.x提取能带数据。输入文件很简单:

&BANDS prefix = 'si_hse' outdir = './tmp' filband = 'si_hse_bands.dat' lsym = .false. /

lsym = .false.很重要。HSE的能带在对称性分析上有时会出问题,关掉对称性可以避免报错。代价是能带数据里没有对称性标记,但画图不受影响。

6.2 带隙的提取与验证

bands.x输出的si_hse_bands.dat里,能带本征值是按k点排列的。提取带隙需要找到价带顶和导带底。

我一般写个小脚本处理:

import numpy as np data = np.loadtxt('si_hse_bands.dat') # 假设第一列是k点索引,后面是各条能带的本征值 nbands = data.shape[1] - 1 vbm = np.max(data[:, 1:nbands//2+1]) cbm = np.min(data[:, nbands//2+1:]) gap = cbm - vbm print(f"VBM = {vbm:.4f} eV, CBM = {cbm:.4f} eV, Gap = {gap:.4f} eV")

硅的HSE带隙实验值是1.17 eV,HSE06算出来通常在1.15-1.20 eV之间。如果算出来是0.8 eV,说明nqx太小或者ecutrho不够。

6.3 能带图的绘制要点

画HSE能带图,有几个细节要注意:

第一,费米能级的位置。HSE的费米能级和PBE不同,不能直接用PBE的费米能级。要从HSE的输出里读highest occupied level。

第二,高对称点的标注。crystal_b格式里你写了哪些高对称点,画图时就要对应标注。比如Gamma、X、L、W。

第三,能带对齐。HSE的能带和PBE的能带不能直接叠在一起,因为参考能级不同。如果要对比,需要把价带顶对齐。

6.4 结果合理性检查清单

跑完HSE能带后,按这个清单检查一遍:

  • 带隙是否在实验值附近(±0.2 eV)?
  • 价带顶和导带底的位置是否和文献一致?
  • 有效质量是否合理?
  • 如果算的是二维材料,真空层是否足够大(>15 Å)?
  • nqx和k网格是否匹配?
  • ecutrho是否至少是ecutwfc的8倍?

如果带隙偏小,优先检查nqx和ecutrho。如果带隙偏大,检查k网格是否nscf比SCF密太多。

7. 我踩过的坑和最后的建议

HSE能带计算最坑的地方不是参数本身,而是参数之间的耦合。nqx、ecutrho、mixing_beta、k网格,这四个参数任何一个不对,都会导致带隙漂移或者SCF不收敛。我的建议是:每次只改一个参数,跑一个小体系测试,确认带隙稳定后再上大体系。

另一个坑是并行效率。很多人以为核数越多越快,HSE不是这样。npool和ndiag的组合需要实测,不同集群的最优值不一样。我一般会花半天时间做并行效率测试,找到最优组合后再跑正式计算。

最后分享一个小技巧:如果HSE SCF实在收敛不了,可以先用PBE跑一个SCF,然后把input_dft改成hse,但把exx_fraction设成0.1,跑一个“弱HSE”的SCF。收敛后,再把exx_fraction改回0.25,从弱HSE的电荷密度重启。这个方法我试过几次,对难收敛的体系很有效。

这个内容后续还可以扩展的方向:HSE的杂化泛函在二维材料里的应用、HSE+GdW的联合使用、以及HSE能带计算在光伏材料筛选中的自动化流程。如果你对这些方向感兴趣,可以自己先试试,有问题再交流。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询