def _velocity(mode, hw, dDk, degenerate): r""" For modes in an orthogonal basis """ # Along all directions v = np.empty([mode.shape[0], 3], dtype=dtype_complex_to_real(mode.dtype)) # Decouple the degenerate modes if not degenerate is None: for deg in degenerate: # Set the average frequency hw[deg] = np.average(hw[deg]) # Now diagonalize to find the contributions from individual modes # then re-construct the seperated degenerate modes # Since we do this for all directions we should decouple them all vv = conj(mode[deg, :]).dot(dDk[0].dot(mode[deg, :].T)) S = eigh_destroy(vv)[1].T.dot(mode[deg, :]) vv = conj(S).dot((dDk[1]).dot(S.T)) S = eigh_destroy(vv)[1].T.dot(S) vv = conj(S).dot((dDk[2]).dot(S.T)) mode[deg, :] = eigh_destroy(vv)[1].T.dot(S) v[:, 0] = (conj(mode.T) * dDk[0].dot(mode.T)).sum(0).real v[:, 1] = (conj(mode.T) * dDk[1].dot(mode.T)).sum(0).real v[:, 2] = (conj(mode.T) * dDk[2].dot(mode.T)).sum(0).real # Set everything to zero for the negative frequencies v[hw < 0, :] = 0 return v * _velocity_const / (2 * hw.reshape(-1, 1))
def eigh(self, k=(0, 0, 0), gauge='R', eigvals_only=True, **kwargs): """ Returns the eigenvalues of the physical quantity Setup the system and overlap matrix with respect to the given k-point and calculate the eigenvalues. All subsequent arguments gets passed directly to :code:`scipy.linalg.eigh` Parameters ---------- spin : int, optional the spin-component to calculate the eigenvalue spectrum of, note that this parameter is only valid for `Spin.POLARIZED` matrices. """ spin = kwargs.pop('spin', 0) dtype = kwargs.pop('dtype', None) if self.spin.kind == Spin.POLARIZED: P = self.Pk(k=k, dtype=dtype, gauge=gauge, spin=spin, format='array') else: P = self.Pk(k=k, dtype=dtype, gauge=gauge, format='array') if self.orthogonal: return lin.eigh_destroy(P, eigvals_only=eigvals_only, **kwargs) S = self.Sk(k=k, dtype=dtype, gauge=gauge, format='array') return lin.eigh_destroy(P, S, eigvals_only=eigvals_only, **kwargs)
def eigh(self, k=(0, 0, 0), gauge='R', eigvals_only=True, **kwargs): """ Returns the eigenvalues of the physical quantity Setup the system and overlap matrix with respect to the given k-point and calculate the eigenvalues. All subsequent arguments gets passed directly to :code:`scipy.linalg.eigh` """ dtype = kwargs.pop('dtype', None) P = self.Pk(k=k, dtype=dtype, gauge=gauge, format='array') if self.orthogonal: return lin.eigh_destroy(P, eigvals_only=eigvals_only, **kwargs) S = self.Sk(k=k, dtype=dtype, gauge=gauge, format='array') return lin.eigh_destroy(P, S, eigvals_only=eigvals_only, **kwargs)
def degenerate_decouple(state, M): r""" Return `vec` decoupled via matrix `M` The decoupling algorithm is this recursive algorithm starting from :math:`i=0`: .. math:: \mathbf p &= \mathbf V^\dagger \mathbf M_i \mathbf V \\ \mathbf p \mathbf u &= \boldsymbol \lambda \mathbf u \\ \mathbf V &= \mathbf u^T \mathbf V Parameters ---------- state : numpy.ndarray or State states to be decoupled on matrices `M` The states must have C-ordering, i.e. ``[0, ...]`` is the first state. M : numpy.ndarray matrix to project to before disentangling the states """ if isinstance(state, State): state.state = degenerate_decouple(state.state, M) else: # since M may be a sparse matrix, we cannot use __matmul__ p = _conj(state) @ M.dot(state.T) state = eigh_destroy(p)[1].T @ state return state
def test_eigh_d1(): np.random.seed(1204982) a = np.random.rand(10, 10) # Symmetrize a = a + a.T xs, vs = sl.eigh(a) x, v = eigh_destroy(a) assert np.allclose(xs, x) assert np.allclose(vs, v)