@@ -697,7 +697,7 @@ def real_eig(aop, x0, precond, tol_residual=1e-5, nroots=1, x0sym=None, pick=Non
697
697
Y_new = XY_new [:,A_size :].T
698
698
if x0sym is None :
699
699
V , W = VW_Gram_Schmidt_fill_holder (
700
- V_holder [:,:m1 ], W_holder [:,:m1 ], X_new , Y_new )
700
+ V_holder [:,:m1 ], W_holder [:,:m1 ], X_new , Y_new , lindep )
701
701
else :
702
702
xt_ir = xt_ir [r_index ]
703
703
xt_orth_ir = []
@@ -706,7 +706,7 @@ def real_eig(aop, x0, precond, tol_residual=1e-5, nroots=1, x0sym=None, pick=Non
706
706
for ir in set (xt_ir ):
707
707
idx = np .nonzero (xt_ir == ir )[0 ]
708
708
_V , _W = VW_Gram_Schmidt_fill_holder (
709
- V_holder [:,:m1 ], W_holder [:,:m1 ], X_new [:,idx ], Y_new [:,idx ])
709
+ V_holder [:,:m1 ], W_holder [:,:m1 ], X_new [:,idx ], Y_new [:,idx ], lindep )
710
710
V .append (_V )
711
711
W .append (_W )
712
712
xt_orth_ir .append ([ir ] * len (_V ))
@@ -932,7 +932,7 @@ def TDDFT_subspace_eigen_solver(a, b, sigma, pi, nroots):
932
932
y = x_p_y - x
933
933
return omega , x , y
934
934
935
- def VW_Gram_Schmidt_fill_holder (V_holder , W_holder , X_new , Y_new , lindep = 1e-6 ):
935
+ def VW_Gram_Schmidt_fill_holder (V_holder , W_holder , X_new , Y_new , lindep = 1e-12 ):
936
936
'''
937
937
QR orthogonalization for (X_new, Y_new) basis vectors, then apply symmetric
938
938
orthogonalization for {[X, Y]}, and its dual basis vectors {[Y, X]}
@@ -953,7 +953,7 @@ def VW_Gram_Schmidt_fill_holder(V_holder, W_holder, X_new, Y_new, lindep=1e-6):
953
953
s21 = X_new .T .dot (Y_new )
954
954
s21 += Y_new .T .dot (X_new )
955
955
e , c = np .linalg .eigh (s11 )
956
- mask = e > lindep ** 2
956
+ mask = e > lindep
957
957
e = e [mask ]
958
958
if e .size == 0 :
959
959
return (np .zeros ([0 , x0_size ], dtype = X_new .dtype ),
@@ -962,9 +962,10 @@ def VW_Gram_Schmidt_fill_holder(V_holder, W_holder, X_new, Y_new, lindep=1e-6):
962
962
963
963
csc = c .T .dot (s21 ).dot (c )
964
964
n = csc .shape [0 ]
965
+ lindep_sqrt = lindep ** .5
965
966
for i in range (n ):
966
967
w , u = np .linalg .eigh (csc [i :,i :])
967
- mask = 1 - abs (w ) > lindep
968
+ mask = 1 - abs (w ) > lindep_sqrt
968
969
if np .any (mask ):
969
970
c = c [:,i :]
970
971
break
@@ -975,13 +976,20 @@ def VW_Gram_Schmidt_fill_holder(V_holder, W_holder, X_new, Y_new, lindep=1e-6):
975
976
u = u [:,mask ]
976
977
c_orth = c .dot (u )
977
978
978
- if e [0 ] < 1e-6 or 1 - abs (w [0 ]) < 1e-3 :
979
- # Rerun the orthogonalization to reduce numerical errors
979
+ if e [0 ] < lindep_sqrt or any (abs (w )> 1 - 1e-3 ):
980
+ # Rerun the orthogonalization to reduce numerical errors.
981
+ # When w~=1-1e-3, errors in the orthogonalization (off-diagonal terms)
982
+ # is near 1e-6.
980
983
e , c = np .linalg .eigh (c_orth .T .dot (s11 ).dot (c_orth ))
981
984
c *= e ** - .5
982
985
c_orth = c_orth .dot (c )
983
986
csc = c_orth .T .dot (s21 ).dot (c_orth )
987
+ wlast = w
984
988
w , u = np .linalg .eigh (csc )
989
+
990
+ mask = 1 - abs (w ) > lindep_sqrt
991
+ w = w [mask ]
992
+ u = u [:,mask ]
985
993
c_orth = c_orth .dot (u )
986
994
987
995
# Symmetric diagonalize
0 commit comments