Je développe un code plus grand pour effectuer des calculs de valeurs propres d'énormes matrices clairsemées, dans le contexte de la physique computationnelle. Je teste mes routines contre le simple oscillateur harmonique dans une dimension, car les valeurs propres sont bien connues analytiquement. Ce faisant et en comparant mes propres routines aux solveurs intégrés de SciPy, je suis tombé sur l'étrangeté affichée dans l'intrigue ci-dessous. Ici vous pouvez voir les 100 premières valeurs propres calculées numériquement et les valeurs propres analytiques λ a n a
Autour de la valeur propre 40, les résultats numériques commencent à diverger des résultats analytiques. Cela ne me surprend pas (je ne vais pas expliquer pourquoi ici, sauf si cela revient dans la discussion). Cependant, ce qui est surprenant pour moi que eigsh () produit des valeurs propres dégénérées (autour de 80) nombre de valeurs propres. Pourquoi eigsh () se comporte-t-il ainsi même pour un si petit nombre de valeurs propres?
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()
Réponses:
La dégénérescence de certaines valeurs propres me semble être la marque de la panne de l'algorithme de Lanczos . L'algorithme de Lanczos est l'une des méthodes les plus couramment utilisées pour approximer les valeurs propres et les vecteurs propres des matrices hermitiennes; c'est ce que scipy.eigsh () utilise, via un appel à la bibliothèque ARPACK .
En arithmétique exacte, l'algorithme de Lanczos produit un ensemble de vecteurs orthogonaux, mais en arithmétique à virgule flottante, ceux-ci peuvent ne pas être orthogonaux et même devenir linéairement dépendants. Ce qui est vraiment ennuyeux, c'est que cette perte d'orthogonalité se produit précisément lorsque l'une des valeurs propres approximatives a convergé vers l'une des valeurs propres réelles - l'algorithme se sabote pour ainsi dire. Le résultat est que vous obtiendrez de fausses paires de valeurs propres proches. Il existe plusieurs correctifs pour cela, par exemple en utilisant Gram-Schmidt pour forcer tous les vecteurs propres convergents à être orthogonaux à chaque étape.
Néanmoins, aucune méthode n'est parfaite, surtout si vous essayez de calculer le spectre entier de votre matrice . Donc, si vous essayez d'obtenir les 50 plus petites valeurs propres, il vaut peut-être mieux approximer la fonction d'onde par un vecteur avec 100 éléments et ne demander
eigsh()
que les 50 premiers niveaux d'énergie, plutôt que d'utiliser un vecteur avec 50 points et demander tout des valeurs propres.Si vous voulez en savoir plus, consultez les méthodes numériques de Yousef Saad pour les problèmes de grandes valeurs propres .
la source