Im am dealing with a sparse Matrix with very small elements. Consider a vector:
vec=[-1.e-76 -1.e-72 -1.e-68 -1.e-64 -1.e-60 -1.e-56 -1.e-52 -1.e-48 -1.e-44
-1.e-40 -1.e-36 -1.e-32 -1.e-28 -1.e-24 -1.e-20 -1.e-16 -1.e-12 -1.e-08
-1.e-04 -1.e-02 -1.e-04 -1.e-08 -1.e-12 -1.e-16 -1.e-20 -1.e-24 -1.e-28
-1.e-32 -1.e-36 -1.e-40 -1.e-44 -1.e-48 -1.e-52 -1.e-56 -1.e-60 -1.e-64
-1.e-68 -1.e-72 -1.e-76]
For those interested, those numbers represent the hopping amplitudes of a 1D system. They are not zero. The hamiltonian is given by a sparse matrix:
H=sps.diags([vec,vec],[-1,1],dtype='f8')
I am interested on the eigenvalues, but even more on the eigenvectors
. As far as I know, there are two ways of deal with the diagonalization:
scipy.linalg
and numpy.linalg
and the former is better.
denseHam=H.toarray()
The correct eigenvalue spectrum is given by all of these functions:
import numpy as np
import scipy.linalg as la
s1= la.eigvalsh(denseHam)
s2= np.linalg.eigvalsh(denseHam)
s3= np.linalg.eigvals(denseHam) #I did not expect that!
The correct spectrum is:
spectrum=[-3.16230928e-03 -3.16227766e-08 -3.16227766e-13 -3.16227766e-18
-3.16227766e-23 -3.16227766e-28 -3.16227766e-33 -3.16227766e-38
-3.16227766e-43 -3.16227766e-48 -3.16227766e-53 -3.16227766e-58
-3.16224604e-63 3.16224604e-63 3.16227766e-58 3.16227766e-53
3.16227766e-48 3.16227766e-43 3.16227766e-38 3.16227766e-33
3.16227766e-28 3.16227766e-23 3.16227766e-18 3.16227766e-13
3.16227766e-08 3.16230928e-03]
Nevertheless, the other functions (which involve the computation of the eigenvectors also) fail, and I can't go on because I need the eigenvectors.
I have to say that C++ is able to compute correctly also the eigenvectors.
So I have two questions:
- Why the function
np.linalg.eigh(denseHam)
gives different spectrum thannp.linalg.eigvalsh(denseHam)
? - Is there any way to compute correctly the eigenvectors with python?
Thank you very much in advance!
--- UPDATE------
I paste here a minimal complete example. Note the exporeous degeneracy of the numpy.linalg.eigh
:
import numpy as np
import scipy.sparse as sps
vec=np.array([-1.e-76, -1.e-72, -1.e-68, -1.e-64, -1.e-60, -1.e-56, -1.e-52,
-1.e-48, -1.e-44, -1.e-40, -1.e-36, -1.e-32, -1.e-28, -1.e-24,
-1.e-20, -1.e-16, -1.e-12, -1.e-08, -1.e-04, -1.e-02, -1.e-04,
-1.e-08, -1.e-12, -1.e-16, -1.e-20, -1.e-24, -1.e-28, -1.e-32,
-1.e-36, -1.e-40, -1.e-44, -1.e-48, -1.e-52, -1.e-56, -1.e-60,
-1.e-64, -1.e-68, -1.e-72, -1.e-76])
H=sps.diags([vec,vec],[-1,1],dtype='f8')
denseHam=H.toarray()
s1=np.linalg.eigvalsh(denseHam)
(s2,basis)=np.linalg.eigh(denseHam)
print("Note the difference between the eigenvalues computed with eigvalsh (1stcolumn) and eigh (2nd column)")
for elem in range(len(s1)):
print (s1[elem]," ",s2[elem])