我有一个离散的 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