这一章继续讲c_bands的重要部分,计算 |\psi_j\rangle = H|\phi_j\rangle 的h_psi -> h_psi_函数。
由于DFT考虑的效应越来越多,h_psi函数也就成了个逐渐叠buff的函数,最基本的是两项
! 动能 T * phi,直接在G空间计算
DO
ibnd
=
1
,
m
hpsi
(
1
:
n
,
ibnd
)
=
g2kin
(
1
:
n
)
*
psi
(
1
:
n
,
ibnd
)
ENDDO
! 势能(离子,Vxc等) V * phi,实空间计算
CALL
vloc_psi_k
(
lda
,
n
,
m
,
psi
,
vrs
(
1
,
current_spin
),
hpsi
)
其他效应包括
! Meta-GGA, 比如SCAN
IF
(
xclib_dft_is
(
'meta'
))
CALL
h_psi_meta
(
lda
,
n
,
m
,
psi
,
hpsi
)
! Exact Exchange, 杂化泛函
CALL
vexx
(
lda
,
n
,
m
,
psi
,
hpsi
,
becp
)
! 体相电场,https://www.quantum-espresso.org/Doc/INPUT_PW.html#lelfield
CALL
h_epsi_her_apply
(
lda
,
n
,
m
,
psi
,
hpsi
,
ipol
,
efield_cry
(
ipol
)
)
! DFT + U
CALL
vhpsi
(
lda
,
n
,
m
,
psi
,
hpsi
)
囊括这些效应,只需要在上述这些函数中,对hpsi进行累加即可
COMPLEX
(
DP
),
INTENT
(
INOUT
)
::
hpsi
(
lda
,
m
)
hpsi
=
hpsi
+
....
笼统地说,除了动能计算是非常简单粗暴的G空间向量 乘法,所有的势能波函数乘法都是在实空间进行的。基本思路如下:
- 构建实空间的势能函数V(r)。大部分的势场函数 ,这一步在进入c_bands之前就计算完成了,应该会在后面详细讲(再次挖坑)。
- 对G空间波函数\phi(G) 进行傅里叶变换FFT,得到实空间波函数 \phi(r) ;
- 在实空间进行对应的乘法 \psi(r) = V(r)\phi(r) ;
- 将 \psi(r) 进行傅里叶变换回到G空间 \psi(G) .
相应的程序如下 (vloc_psi_k) [1] :
DO
ibnd
=
1
,
m
! 第ibnd个波函数 psi(G) 赋值一个临时变量psic
DO
j
=
1
,
n
psic
(
dffts
%
nl
(
igk_k
(
j
,
current_k
)))
=
psi
(
j
,
ibnd
)
ENDDO
! psic做FFT,注意psic的值既是输入也是输出,也就是说结束后psic中存了实空间的波函数
! 这也是为什么要把psi的值拷贝给psic
CALL
invfft
(
'Wave'
,
psic
,
dffts
)
! 在实空间计算 psi * V,
! 注意这里是对所有实空间格点dffts%nnr遍历
! 结束后 psic再次变成 V(r)\phi(r)
! 这一切都是为了省内存空间.....
DO
j
=
1
,
dffts
%
nnr
psic
(
j
)
=
psic
(
j
)
*
v
(
j
)
ENDDO
! 将V\phi经过FFT变回到G空间,同样的,psic被改变了,成了V\phi(G)
CALL
fwfft
(
'Wave'
,
psic
,
dffts
)
! 将 psic 累加到 hpsi 上,hpsi是输出,psic将被释放
DO
j
=
1
,
n
hpsi
(
j
,
ibnd
)
=
hpsi
(
j
,
ibnd
)
+
psic
(
dffts
%
nl
(
igk_k
(
j
,
current_k
)))
ENDDO
ENDDO
如我上一章提到的,这一章很线性,逻辑上没啥难点。重点就是了解势场是实空间计算,以及如何计算的即可。
这两章就解决了如何计算哈密顿量 和解本征值/矢的问题,下一章.....下一章该讲什么来着?
(早知道不挖这么大的坑了,含泪填吧.....)
哦想起来了,下一章讲怎么有了本征值/矢,怎么算占据数和电荷密度 (sum_band)。
参考
- ^ 这一段是实际的函数,注释是我加的。包括注释也就这么长,可谓十分简洁易懂。前提是不引入openmp,能带并行等效率优化部分