python numpy.libalg.eigh()返回错误的特征向量。为什么?

时间:2017-08-31 20:07:41

标签: python python-2.7 numpy physics numerical-methods

对于一个简短的信息,我的任务是模拟一个被抛物线电位监禁的量子粒子的波函数(这个问题与量子谐振子有关)。 我使用矩阵方法得到一维薛定谔方程。在我正确地构造它之后(矩阵是三对角的,这是重要的)我使用np.eigh来找到该矩阵的特征向量,这些波函数对应于该粒子的能量状态(来自矩阵的特征值)。 numpy方法返回适当的特征值,但不幸的是返回了错误的特征向量。 这里是numpy对粒子基态的数值解(用matplotlib绘制),黄色曲线是比较的精确解: numpy numerical solution

如您所见,解决方案甚至不是很接近,因此我使用自己的函数生成三对角矩阵的特征向量。该数值解决方案给出: own numerical solution

这就是我想要的。问题是为什么numpy方法返回错误的特征向量?是因为它对大型矩阵来说是非常差的,还是因为它处理三对角矩阵很差?我为这个模块运行内置测试,它说它一切都好......

>>> np.linalg.test()
Running unit tests for numpy.linalg
NumPy version 1.11.2
NumPy relaxed strides checking option: False
NumPy is installed in /usr/local/lib/python2.7/dist-packages/numpy
Python version 2.7.12 (default, Jul  1 2016, 15:12:24) [GCC 5.4.0 20160609]
nose version 1.3.7
----------------------------------------------------------------------
Ran 134 tests in 6.935s
OK
nose.result.TextTestResult run=134 errors=0 failures=0

我编写的代码是在python 2.7.12中:

import numpy as np
import matplotlib.pyplot as plt
###global variables###

N=100 #always -1 from real number of points
L=2 ##Calculation box length,too large spoils the solution!
dx=2.*L/(N+-0.) #calculation step
N=N+1
ax_x=[] #stores x values
ax_v=[] #stores potential values corresponding to x
omega=10. #parabole parameter
######################

def fill_matrix(ax_pot):
    matrix=[]
    for i in range(N):
        matrix.append([])
        for j in range(N):
            matrix[i].append(0.)
    for i in range(N):
        matrix[i][i]=1./(dx*dx)+ax_pot[i]
        if i != N-1:
            matrix[i][i+1]=matrix[i+1][i]=1./ ( 2.*(dx*dx) )
    return matrix


def fill_pot_par(ax_x,omega):
    for i in range(N):
        ax_v.append(ax_x[i]*ax_x[i]/2.*omega*omega)

def get_eig_val_id(e_vals,number_counted_from_smallest=0):
    evals=sorted(e_val)
    wsk=None
    for i in range(len(evals)):
        if e_vals[number_counted_from_smallest] == evals[i]:
            wsk=i
            break
    return wsk

def hermit_f_0(x):
    return 1

def get_analytical_solution(x_vec,e_val,omega_):
    new_x_vec=[]
    for i in range(len(x_vec)):
        new_x_vec.append(-x_vec[i]*x_vec[i]*omega_/2.)

    omega_sqrt=np.sqrt(omega_)
    new_x_vec=np.exp(new_x_vec)
    h_vec=[]
    print(e_val)
    if e_val == 0:
        for i in x_vec:
            h_vec.append(hermit_f_0(i*omega_sqrt))
    for i in range(len(new_x_vec)):
        new_x_vec[i]=new_x_vec[i]*h_vec[i]
    norm=0
    for i in new_x_vec:
        norm=norm+i*i
    norm=np.sqrt(norm)
    for i in range(len(new_x_vec)):
        new_x_vec[i]=new_x_vec[i]/norm
    return new_x_vec

def get_eig_vector(matrix,selfval):
    e_vec=[]
    sv=selfval
    sigma=0
    ga=matrix[0][1]
    for i in range(len(matrix)):
        if i == 0:
            e_vec.append(1.)
            continue
        if i == 1:
            sigma=matrix[0][0]
            e_vec.append((sv-sigma)/ga)
            continue
        sigma=matrix[i-1][i-1]
        tmp_val=(sv-sigma)*e_vec[i-1]/ga-e_vec[i-2]
        e_vec.append(tmp_val)
    #print(e_vec)
    norm=0
    for i in e_vec:
        norm=norm+i*i
    norm=np.sqrt(norm)
    for i in range(len(e_vec)):
        e_vec[i]=e_vec[i]/norm
    return e_vec

if __name__ == "__main__":


    #filling axis
    for i in range(N):
        ax_x.append(-L+i*dx)

    fill_pot_par(ax_x,omega)

    #matrix to solve
    h_mat=fill_matrix(ax_v)

    #numpy method
    e_val,e_vec=np.linalg.eigh(h_mat)

    #becouse numpy returns the values in random order
   #you need to get the lowest by yourself
    wsk=get_eig_val_id(e_val,0)

    #my solution
    my_vector=get_eig_vector(h_mat,e_val[wsk])

    #analytical solution
    an_sol=get_analytical_solution(ax_x,0,omega)    

    #plotting
    fig, ax1 = plt.subplots()
    ax2=ax1.twinx()

    ax1.plot(ax_x,an_sol,'y',ax_x,e_vec[wsk],'b',ax_x,my_vector,'g')
    ax2.plot(ax_x,ax_v,'r')

    for t in ax1.get_yticklabels():
        t.set_color('b')
    for t in ax2.get_yticklabels():
        t.set_color('r')    
    plt.show()  
编辑:@Warren Weckesser解决了我的问题。问题在于绘制e_vec [wsk]而不是e_vec [:,wsk]谢谢!

0 个答案:

没有答案