RI-RHF:极简演示
- 程序:
ri_rhf_slow.rs(gitee, github) - 实现内容:RI-RHF (restricted resolution-of-identity Hartree-Fock)
- 不关注程序效率
- 该程序总共约 50 行
在本节中,我们经常将密度矩阵 看作 长度的 1-D 向量,而非 的 2-D 矩阵。类似地,4c-2e 双电子积分经常看作是 的 2-D 矩阵,而非 的 4-D 张量。
目录
1. RI-RHF 回顾
相比于普通的 RHF,RI-RHF 方法不需要计算庞大的 4c-2e 双电子积分,而只需要计算较小的 3c-2e 双电子积分。同时,通过张量分解,其 Fock 矩阵的计算量明显比 RHF 方法小很多。
以 J 积分 为例,RI-V 近似下的 RI-RHF 的理解思路可以大致用下图表示:

1.1 4c-2e 双电子积分分解
RI-V 近似除了普通的分子轨道基组外,还需要设置辅助基组。辅助基数量越大、精度越高但计算消耗也越多。一般来说,辅助基组的数量 大约是 大小。从矩阵分解的角度来看,如果将 4c-2e 双电子积分看作 的矩阵,那么辅助基的大小 数量级上应该要接近 4c-2e 双电子积分的秩 (rank)。
3c-2e 双电子积分与 2c-2e 双电子积分定义如下:
随后对 2c-2e 双电子积分作 Cholesky 分解,分解得到的 是下三角矩阵:
考虑到 4c-2e 双电子积分在 RI-V 下的近似表达式为
定义 Cholesky 分解量 为 (在我们当前的项目中,需要注意其指标顺序与 3c-2e 双电子积分 不同)
那么 4c-2e 双电子积分的近似表达式也可以写为
1.2 J 积分
J 积分的计算近似为
如果用矩阵-向量乘法来表述,则是
1.3 K 积分
在 RI 近似下,K 积分的计算应代入分子轨道系数以提升计算效率。在闭壳层下,占据轨道总是双占据的。
当我们定义半转换 (half-transformed) 的 为
我们可以将 进一步写为
我们再定义记号 ,这两个张量完全等价。但当作矩阵看待时, 是 大小,而 是 大小。定义 的方便之处在于,K 积分可以用简单的矩阵乘法形式表达出来 (上标 half 是指该张量是经过半转换的):
2. 程序
2.1 4c-2e 双电子积分分解
在获得电子积分后,我们的主要目标是得到 。总共需要作两步计算:Cholesky 分解与矩阵求解:
在程序中的实现如下:
#![allow(unused)] fn main() { let int2c2e_l = rt::linalg::cholesky((int2c2e.view(), Lower)); let cderi = rt::linalg::solve_triangular((int2c2e_l.view(), int3c2e.reshape([nao * nao, naux]).t(), Lower)); let cderi = cderi.into_shape([naux, nao, nao]).into_contig(RowMajor); }
- 关于 Cholesky 分解,代码相信已经很直观了;
- 关于矩阵求解,需要注意到这里的 是下三角矩阵;通过三角矩阵求解函数
solve_triangular会比通常的矩阵求解函数solve_general或者求逆inv函数,性能上要快许多。 - 最后,我们对 作维度修改 (从 的 2-D 矩阵修改到 的 3-D 张量),并从效率角度出发要求该张量需要是 row-major 的 (需要让辅助基指标 是最不连续的维度,这在 K 积分计算中是比较关键的)。
2.2 J 积分
J 积分的过程非常简单,它就是两次矩阵-向量乘法。但需要注意乘法的顺序,否则效率会非常糟糕:
#![allow(unused)] fn main() { let cderi_flat = cderi.reshape([naux, nao * nao]); let dm_flat = dm.reshape([nao * nao]); (cderi_flat.t() % (&cderi_flat % dm_flat)).into_shape([nao, nao]) }
上面的代码花了一些功夫在维度更改上。
2.3 K 积分
K 积分的计算是两次矩阵乘法:
#![allow(unused)] fn main() { let occ_coeff = mo_coeff.i((.., ..nocc)); let scr = (occ_coeff.t() % cderi.reshape([naux * nao, nao]).t()).into_shape([nocc, naux, nao]); let scr_flat = scr.reshape([naux * nocc, nao]); 2.0_f64 * (scr_flat.t() % &scr_flat) }
上述程序的
- 第 1 行是从分子轨道系数中取出占据轨道的部分 ;
- 第 2 行是半转换得到 ;
- 第 3 行是重塑维度得到 ;
- 第 4 行是进行 的实际计算。
这里的程序实现与先前 RI-RHF 回顾中用到的公式还有些许差别。我们需要作一些额外的展开。
第 2 行中,我们实际执行的矩阵乘法是
该矩阵乘法对 重塑维度,并对参与乘法的两个矩阵都作转置,才能得到目标结果。这么做非常费劲,其目的是将半转换后指标 与 联系在一起,方便下面得到矩阵 时可以矩阵乘法一步到位。
由于 中,指标 与 是并在一起的;因此半转换得到的是 还是 并不重要,只要 与 联系在一起即可。