矩阵形成中的奇怪行为C++,Armadillo

问题描述

我有一个 while 循环,只要能量变量(double 类型)没有收敛到某个阈值以下,它就会继续。计算此能量所需的变量之一是名为 f_mo 的双打犰狳矩阵。在 while 循环中,这个 f_mo 迭代更新,所以我在每个循环开始时计算 f_mo 为:

    arma::mat f_mo = h_core_mo;//h_core_mo is an Armadillo matrix of doubles
    for(size_t p = 0; p < n_mo; p++) {//n_mo is of type size_t
    for(size_t q = 0; q < n_mo; q++) {
        double sum = 0.0;
            for(size_t i = 0; i < n_occ; i++) {//n_occ is of type size_t
                //f_mo(p,q) += 2.0*g_mat_full_qp1_qp1_mo(p*n_mo + q,i*n_mo + i)-g_mat_full_qp1_qp1_mo(p*n_mo+i,i*n_mo+q); //all g_mat_ are Armadillo matrices of doubles
                sum += 2.0*g_mat_full_qp1_qp1_mo(p*n_mo + q,i*n_mo+q);
            }
            for(size_t i2 = 0; i2 < n_occ2; i2++) {//n_occ2 is of type size_t
                //f_mo(p,q) -= 1.0*g_mat_full_qp1_qp2_mo(p*n_mo + q,i2*n_mo2 + i2);
                sum -= 1.0*g_mat_full_qp1_qp2_mo(p*n_mo + q,i2*n_mo2 + i2);
            }
        
        f_mo(p,q) +=sum;
    }}

但是说我用 f_mo(p,q) 直接(注释掉的代码)替换了总和(我在最后添加到 f_mo(p,q))。输出 f_mo 矩阵与机器精度相同。关于代码的任何内容都不应更改。循环中唯一受影响的变量是 sum 和 f_mo。然而,代码收敛到不同的能量和大量不同的 while 循环迭代。我不知道差异的原因。当我运行相同的代码 2、3、4、5 次时,每次都会得到相同的结果。当我在没有优化的情况下重新编译时,我遇到了同样的问题。当我在不同的计算机上运行(控制环境)时,尽管 f_mo 相同,但我再次在 while 循环数上出现差异,但每种方法的总迭代次数(sum += 和 f_mo(p,q) += ) 不同。

值得注意的是,代码输出不同的点总是g_mat_full_qp1_qp2_mo,后面会在while循环中重新计算。然而,进入 g_mat_full_qp1_qp2_mo 计算的每个变量在两个代码之间是相同的。这让我觉得 C++ 有一些我不理解的更深刻的东西。我欢迎任何关于如何继续调试此行为的想法(我几乎可以肯定这不是一个典型的错误,我已经控制了环境和优化)

解决方法

我将假设这是一个 Hartree-Fock,或某种其他类型的电子结构计算,其中您将双电子积分添加到核心哈密顿量中,并应用一些领域知识。

部分假设是两电子积分的各个元素非常小,特别是与核心哈密顿量相比。因此,正如 1201ProgramAlarm 在他们的评论中提到的,添加的顺序很重要。 You will get a more accurate result if you add smaller numbers together first to avoid loosing precision when adding two numbers many orders of magintude apart.。因为您迭代这个过程直到 Fock 矩阵 f_mo 紧密收敛,所以您最终会收敛到相同的值。

为了以更准确的顺序将数字相加,并希望更快收敛,大多数电子结构程序都有一个单独的程序来计算两电子积分,然后将它们添加到核心哈密顿量,这就是您在示例代码中逐个元素执行的操作。

Presentation on numerical computing.

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...