def get_mlwf_initial_guess(self): """calculate initial guess for maximally localized wannier functions. Does not work for the infinite band limit. cu_nl: rotation coefficents of unoccupied states U_ii: rotation matrix of eigenstates and edf. """ Vu_ni = self.Vu_ni[self.M:self.N] cu_nl = np.dot(Vu_ni, self.b_il) U_ii = np.vstack((self.Uo_ni, self.Uu_li)) lowdin(U_ii) return U_ii, cu_nl
def __init__(self, V_nM, No, ortho=False): Nw = V_nM.shape[1] assert No <= Nw V_oM, V_uM = V_nM[:No], V_nM[No:] F_MM = np.dot(V_uM.T.conj(), V_uM) U_ow, U_lw, U_Ml = get_rot(F_MM, V_oM, Nw - No) self.U_nw = np.vstack((U_ow, dots(V_uM, U_Ml, U_lw))) # stop here ?? XXX self.S_ww = self.rotate_matrix(np.ones(1)) if ortho: lowdin(self.U_nw, self.S_ww) self.S_ww = np.identity(Nw) self.norms_n = np.dot(self.U_nw, np.linalg.solve( self.S_ww, self.U_nw.T.conj())).diagonal()
def get_locfun_rotation(projections_nj, M=None, T=0, ortho=False): """Mikkel Strange's localized functions. projections_nj = <psi_n|p_j> psi_n: eigenstates p_j: localized function Nw = number of localized functions M = Number of fixed states T = Number of virtual states to exclude (from above) """ Nbands, Nw = projections_nj.shape if M is None: M = Nw L = Nw - M # Extra degrees of freedom V = Nbands - M - T # Virtual states a0_nj = projections_nj[:M, :] a0_vj = projections_nj[M:M + V, :] if V == 0: D_jj = np.dot(dagger(projections_nj), projections_nj) U_nj = 1.0 / np.sqrt(D_jj.diagonal()) * projections_nj S_jj = np.dot(dagger(U_nj), U_nj) assert np.diagonal(np.linalg.cholesky(S_jj)).min() > .01, \ 'Close to linear dependence.' if ortho: lowdin(U_nj, S_jj) S_jj = np.identity(len(S_jj)) return U_nj, S_jj #b_v, b_vv = np.linalg.eigh(np.dot(a0_vj, dagger(a0_vj))) #T_vp = b_vv[:, np.argsort(-b_v)[:L]] b_j, b_jj = np.linalg.eigh(np.dot(dagger(a0_vj), a0_vj)) T_vp = np.dot(a0_vj, b_jj[:, np.argsort(-b_j.real)[:L]]) R_vv = np.dot(T_vp, dagger(T_vp)) D_jj = np.dot(dagger(a0_nj), a0_nj) + np.dot(dagger(a0_vj), np.dot(R_vv, a0_vj)) D2_j = 1.0 / np.sqrt(D_jj.diagonal()) ap_nj = D2_j * a0_nj ap_vj = D2_j * np.dot(R_vv, a0_vj) S_jj = np.dot(dagger(ap_nj), ap_nj) + np.dot(dagger(ap_vj), ap_vj) # Check for linear dependencies Scd = np.diagonal(np.linalg.cholesky(S_jj)).min() if Scd < 0.01: print(('Warning: possibly near linear dependence.\n' 'Minimum eigenvalue of cholesky decomposition is %s' % Scd)) if ortho: lowdin(ap_nj, S_jj) lowdin(ap_vj, S_jj) S_jj = np.identity(len(S_jj)) U_nj = np.concatenate([ap_nj.flat, ap_vj.flat]).reshape(M + V, Nw) return U_nj, S_jj