Python/MATLAB/Mathematica 数值特征向量是否受到计算区域外的特征值退化的影响?

计算科学 Python 数字 计算物理学 本征系统 离散化
2021-12-07 05:33:25

我有一个离散的 2D 网格,我在其上计算一些 Hermitian 2 x 2 矩阵的特征值和特征向量,沿着由参数t参数化的闭环的每个点特征向量通常是复值。然后我使用特征向量计算数量z(t)复数值z (t)是通过将第一个特征向量与第二个特征向量的导数相乘来计算的。使用标准中心差分方案沿循环计算导数。z(t)绘制在复平面上时 - 即 (Re z(t) ,Im z(t) ) - 它是一条平滑曲线。

但是,有时,二维空间中可能存在具有特征值退化的点。问题是复杂的循环z(t)最终会导致不平滑的锯齿状混乱,即使特征值沿着网格上的循环是非退化的。从这个代码模型的物理问题来看,这是不期望的。只要循环中没有特征值退化,我们期望平滑z(t) 。最后的图说明了上下文。

因此,我很困惑。因为,从数值上看,就好像循环中的特征向量感觉到了其他地方出现的特征值退化的存在。它似乎是一个数字神器,但我不明白发生了什么。我在代码的 Python/MATLAB/Mathematica 实现中看到了这种行为。那么,有没有人对可能发生的事情有所了解?这是数值特征求解器的普遍特征吗?在这些求解器的基本层面上会发生什么导致这种情况?或者我将退化与非平滑复杂循环相关联是错误的?在不同的矩阵模型中观察到这种行为(即使对于来自大于 2 x 2 的矩阵的一对特征向量)。任何见解将不胜感激!

在此处输入图像描述


编辑:计算示意图

  • n_segs 是将循环离散化为的片段数(通常 = 250)

  • kloop 是一个二维坐标数组,用于指定 (x,y) 域中的路径。它由下面给出的函数 parameterize_loop() 生成

  • Hamiltonian() 返回给定 (x,y) 处的方阵

  • sort_eigens(),定义如下,根据特征值大小排序对特征向量进行排序

  • 有限差分在 dphim 中计算

  • wfc_dot(),定义如下,取两个向量的点积(一个向量的复共轭和另一个向量的有限差分,每个标准量子力学内积过程)

  • cloop 是我在右图中绘制的复数数组;z(t)

     for j in np.arange(1,n_segs):
    
         H = Hamiltonian(kloop[j-1][0],kloop[j-1][1])
         eval, psi0 = LA.eig(H)
         [eval,psi0]=sort_eigens(eval,psi0);
    
         H = Hamiltonian(kloop[j][0],kloop[j][1])
         eval2, psi1 = LA.eig(H)
         [eval2,psi1]=sort_eigens(eval2,psi1);
    
         H = Hamiltonian(kloop[j+1][0],kloop[j+1][1])
         eval, psi2 = LA.eig(H)
         [eval,psi2]=sort_eigens(eval,psi2);
    
         psi0 = psi0[:,band2]
         psi2 = psi2[:,band2]
         dphim = (psi2-psi0)*n_segs/(4*np.pi);
    
         phip = psi1[:,band1]
    
         cloop[j-1] = wfc_dot(phip,dphim)
    
     cloop[-1]=cloop[0] # this ensures the loop is closed; not really necessary
    

   def sort_eigens(eigenValues,eigenVectors):
    idx = eigenValues.argsort()
    vals=eigenValues[idx]
    vecs=eigenVectors[:,idx]
    for q in range(len(vecs)):
        v = vecs[:,q]
        non_zero_elems = v[np.nonzero(v)]
        v = v/(non_zero_elems[0,0])
    return [vals,vecs]

    def wfc_dot(wf1,wf2):
        wf1 = np.squeeze(np.asarray(wf1))
        wf2 = np.squeeze(np.asarray(wf2))
    return np.dot(wf1.flatten().conjugate(),wf2.flatten())  

    def parameterize_loop(kx0,ky0,r,n_segs): # parameterizes a counterclockwise loop of radius r centered at (kx0,ky0)
        a = np.linspace(0.0, 2*np.pi, num=n_segs+1) # time goes from 0 to 2pi
        a = np.append(a,a[1]) # to ensure continuity in subsequent winding loop calculations   
        k_loop=np.zeros((n_segs+2,2))
        for i in range(n_segs+2):
            k_loop[i,:]=np.array([kx0 + r*np.cos(a[i]), ky0 + r*np.sin(a[i])]) 
        return k_loop
1个回答

乍一看,我也希望这个问题表现得很好,因为 Hermitian 特征分解本身表现得很好(实特征值,正交特征向量)。事情可能出错的一个地方是调用一个不知道您输入的 Hermitian-ness 的例程/算法。在 LAPACK 中,您可能想要的例程是 ZHEEV,它确实提供了您期望的 Hermitian 特征分解的保证:正交特征向量、实特征值,甚至为您排序。您可以将此与 ZGEEV 进行对比,后者原则上也可以计算特征分解,但不利用结构并且不提供保证。

ZHEEV 文档。

ZGEEV 文档。

为了澄清,保证来自问题属性,而不是算法..所以如果你不小心使用 ZGEEV 而不是 ZHEEV,你的特征向量仍然是正交的,但可能不会达到相同的精度,你的特征值将是真实的,但可能有一些小的/roundoff-level 虚部等。它们肯定不会被排序,因为 ZGEEV 没有业务尝试对它假定为复杂的特征值应用排序。这两种算法也完全有可能对退化具有不同的敏感性,因为它们只是在底层使用了不同的转换。

排序位似乎特别值得注意,因为我希望您在改变 t 参数时需要某种“跟踪”/特征对的连续性,否则您可能会无意中计算 dot(x1,dx2) 而不是 dot(dx2, x1),或诸如此类。或者更糟糕的是,您可能会无意中将 x1(t+dt) 与 x2(t-dt) 进行有限差分,因为它们在本征求解过程中被打乱/交换。

所以我想这就是我首先要研究的内容,确保你正在使用任何更高级别的编程环境,关于这些对称/厄米特属性,以便它可以分派到正确的底层算法。这可能采用额外参数的形式(也许是“symm=true”),或者使用特殊的 Hermitian-only 矩阵容器/类型?很难确定。并确保在进行差分/打点时确实在跟踪/选择正确的特征向量。