Pourquoi SciPy eigsh () produit-il des valeurs propres erronées en cas d'oscillateur harmonique?


15

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λnumλunenune

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?

entrez la description de l'image ici

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()

C'est un comportement très curieux. Je vais le tester plus tard dans la journée.
Rafael Reiter du

J'ai trouvé la réponse. En bref: ma pensée était fausse. Les solutions analytiques de l'oscillateur harmonique (HOSZ) sont valables sans aucune restriction spatiale. Cependant, dans le code ci-dessus, ma boîte va de -10 à 10, donc cela met une condition aux limites sur les solutions numériques. Par conséquent, eigsh () résout le système qui lui est donné correctement. Aux alentours de n = 50 (avec n étant le nombre quantique principal), les solutions analytiques ne rentrent plus dans la case -10, 10. Maintenant (après réflexion), cela semble évident. Cependant, je n'ai pas vu cela lors de la construction et du test du code.
seb

cela n'explique toujours pas la dégénérescence, n'est-ce pas?
seb

Réponses:


12

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 .

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.