@@ -21,6 +21,20 @@ def save(ar, fileName):
2121 # Used only when verbosity level > 10.
2222 np .savetxt (fileName , ar , precision = 8 )
2323
24+ def _report_nonhermitian (M , a , b , name ):
25+ """
26+ Report if `M` is not a hermitian matrix given the tolerances `a`, `b`.
27+ """
28+ from scipy .linalg import norm
29+
30+ md = M - M .T .conj ()
31+
32+ nmd = norm (md , 1 )
33+ tol = max (np .spacing (10 ** a ), (10 ** b )* norm (M , 1 ))
34+ if nmd > tol :
35+ print ('matrix %s is not enough Hermitian for a=%d, b=%d:'
36+ % (name , a , b ))
37+ print ('condition: %.e < %e' % (nmd , tol ))
2438
2539def as2d (ar ):
2640 """
@@ -85,6 +99,15 @@ def _b_orthonormalize(B, blockVectorV, blockVectorBV=None, retInvR=False):
8599 else :
86100 return blockVectorV , blockVectorBV
87101
102+ def _get_indx (_lambda , num , largest ):
103+ """Get `num` indices into `_lambda` depending on `largest` option."""
104+ ii = np .argsort (_lambda )
105+ if largest :
106+ ii = ii [:- num - 1 :- 1 ]
107+ else :
108+ ii = ii [:num ]
109+
110+ return ii
88111
89112def lobpcg (A , X ,
90113 B = None , M = None , Y = None ,
@@ -299,7 +322,14 @@ def lobpcg(A, X,
299322
300323 A_dense = A (np .eye (n ))
301324 B_dense = None if B is None else B (np .eye (n ))
302- return eigh (A_dense , B_dense , eigvals = eigvals , check_finite = False )
325+
326+ vals , vecs = eigh (A_dense , B_dense , eigvals = eigvals , check_finite = False )
327+ if largest :
328+ # Reverse order to be compatible with eigs() in 'LM' mode.
329+ vals = vals [::- 1 ]
330+ vecs = vecs [:, ::- 1 ]
331+
332+ return vals , vecs
303333
304334 if residualTolerance is None :
305335 residualTolerance = np .sqrt (1e-15 ) * n
@@ -332,11 +362,7 @@ def lobpcg(A, X,
332362 gramXAX = np .dot (blockVectorX .T .conj (), blockVectorAX )
333363
334364 _lambda , eigBlockVector = eigh (gramXAX , check_finite = False )
335-
336- if largest :
337- ii = np .argsort (- _lambda )[:sizeX ]
338- else :
339- ii = np .argsort (_lambda )[:sizeX ]
365+ ii = _get_indx (_lambda , sizeX , largest )
340366 _lambda = _lambda [ii ]
341367
342368 eigBlockVector = np .asarray (eigBlockVector [:, ii ])
@@ -456,17 +482,17 @@ def lobpcg(A, X,
456482 gramB = np .bmat ([[ident0 , xbw ],
457483 [xbw .T .conj (), ident ]])
458484
485+ if verbosityLevel > 0 :
486+ _report_nonhermitian (gramA , 3 , - 1 , 'gramA' )
487+ _report_nonhermitian (gramB , 3 , - 1 , 'gramB' )
488+
459489 if verbosityLevel > 10 :
460490 save (gramA , 'gramA' )
461491 save (gramB , 'gramB' )
462492
463493 # Solve the generalized eigenvalue problem.
464494 _lambda , eigBlockVector = eigh (gramA , gramB , check_finite = False )
465-
466- if largest :
467- ii = np .argsort (- _lambda )[: sizeX ]
468- else :
469- ii = np .argsort (_lambda )[: sizeX ]
495+ ii = _get_indx (_lambda , sizeX , largest )
470496
471497 if verbosityLevel > 10 :
472498 print (ii )
0 commit comments