Estoy desarrollando un código más grande para realizar cálculos de valores propios de enormes matrices dispersas, en el contexto de la física computacional. Pruebo mis rutinas contra el oscilador armónico simple en una dimensión, ya que los valores propios son bien conocidos analíticamente. Al hacerlo y al comparar mis propias rutinas con los solucionadores incorporados de SciPy, me he encontrado con la rareza que se muestra en la siguiente trama. Aquí puede ver los primeros 100 valores propios calculados numéricamente y valores propios analíticos λ a n a
Alrededor del valor propio número 40, los resultados numéricos comienzan a diferir de los analíticos. Esto no me sorprende (no voy a entrar en por qué aquí, a menos que aparezca en la discusión). Sin embargo, lo que me sorprende es que eigsh () produce valores propios degenerados (alrededor del número de valor propio 80). ¿Por qué eigsh () se comporta así incluso con un número tan pequeño de valores propios?
import numpy as np
from scipy.sparse.linalg import eigsh
import myFunctions as myFunc
import matplotlib.pyplot as plt
#discretize x-axis
N = 100
xmin = -10.
xmax = 10.
accuracy = 1e-5
#stepsize
h = (xmax - xmin) / (N + 1.)
#exclude first and last points since we force wave function to be zero there
x = np.linspace(-10. + h,10. - h,N)
#create potential
V = x**2
def fivePoint(N,h,V):
C0 = (np.ones(N))*30. / (12. * h * h) + V
C1 = (np.ones(N)) * (-16.) / (12. * h * h)
C2 = (np.ones(N)) / (12. * h * h)
H = sp.spdiags([C2, C1, C0, C1, C2],[-2, -1, 0, 1, 2],N,N)
return H
H = myFunc.fivePoint(N,h,V)
eigval,eigvec = eigsh(H, k=N-1, which='SM', tol=accuracy)
#comparison analytical and numerical eigenvalues
xAxes = np.linspace(0,len(eigval)-1,len(eigval))
analyticalEigval = 2. * (xAxes + 0.5)
plt.figure()
plt.plot(xAxes,eigval, '+', label=r"$\lambda_{num}$")
plt.plot(xAxes,analyticalEigval, label=r"$\lambda_{ana}$")
plt.xlabel("Number of Eigenvalue")
plt.ylabel("Eigenvalue")
plt.legend(loc=4)
plt.title("eigsh()-method: Comparison of $\lambda_{num}$ and $\lambda_{ana}$")
plt.show()
Respuestas:
La degeneración de algunos valores propios me parece el sello distintivo del colapso del algoritmo de Lanczos . El algoritmo de Lanczos es uno de los métodos más utilizados para aproximar los valores propios y los vectores propios de las matrices hermitianas; es lo que usa scipy.eigsh (), a través de una llamada a la biblioteca ARPACK .
En aritmética exacta, el algoritmo de Lanczos produce un conjunto de vectores ortogonales, pero en aritmética de coma flotante estos pueden dejar de ser ortogonales e incluso volverse linealmente dependientes. Lo realmente molesto es que esta pérdida de ortogonalidad ocurre precisamente cuando uno de los valores propios aproximados ha convergido a uno de los valores propios reales: el algoritmo se sabotea a sí mismo, por así decirlo. El resultado es que obtendrás algunos pares espurios de valores propios cercanos. Hay varias soluciones para esto, por ejemplo, usar Gram-Schmidt para forzar a cualquier vector propio convergente a ser ortogonal en cada paso.
Sin embargo, ningún método es perfecto, especialmente si está tratando de calcular todo el espectro de su matriz . Entonces, si está tratando de obtener los 50 valores propios más pequeños, es mejor que se aproxime a la función de onda mediante un vector con 100 elementos y solo solicite
eigsh()
los primeros 50 niveles de energía, en lugar de usar un vector con 50 puntos y pedir todos de los autovalores.Si desea leer más, mire los Métodos numéricos de Yousef Saad para problemas de gran valor propio .
fuente