def test_k(self): """ lattice: Test the method Lattice1d.k(). """ L = 7 lattice_L123 = Lattice1d(num_cell=L, boundary="periodic", cell_num_site=1, cell_site_dof=[2, 3]) kq = lattice_L123.k() kop = np.zeros((L, L), dtype=complex) for row in range(L): for col in range(L): if row == col: kop[row, col] = (L - 1) / 2 else: kop[row, col] = 1 / (np.exp(2j * np.pi * (row - col) / L) - 1) kt = np.kron(kop * 2 * np.pi / L, np.eye(6)) dim_H = [[2, 2, 3], [2, 2, 3]] kt = Qobj(kt, dims=dim_H) [k_q, Vq] = kq.eigenstates() [k_t, Vt] = kt.eigenstates() k_tC = k_t - 2 * np.pi / L * ((L - 1) // 2) # k_ts = [(i-(L-1)//2)*2*np.pi/L for i in range(L)] # k_w = np.kron((np.array(k_ts)).T, np.ones((1,6))) assert_((np.abs(k_tC - k_q) < 1E-13).all())
def test_Transformation4(): "Transform 10-level imag to eigenbasis and back" N = 10 H1 = Qobj(1j * (0.5 - scipy.rand(N, N))) H1 = H1 + H1.dag() evals, ekets = H1.eigenstates() Heb = H1.transform(ekets) # eigenbasis (should be diagonal) H2 = Heb.transform(ekets, True) # back to original basis assert_equal((H1 - H2).norm() < 1e-6, True)
def get_dispersion(self, knpoints=0): """ Returns dispersion relationship for the lattice with the specified number of unit cells with a k array and a band energy array. Returns ------- knxa : np.array knxA[j][0] is the jth good Quantum number k. val_kns : np.array val_kns[j][:] is the array of band energies of the jth band good at all the good Quantum numbers of k. """ # The _k_space_calculations() function is not used for get_dispersion # because we calculate the infinite crystal dispersion in # plot_dispersion using this coode and we do not want to calculate # all the eigen-values, eigenvectors of the bulk Hamiltonian for too # many points, as is done in the _k_space_calculations() function. if self.period_bnd_cond_x == 0: raise Exception("The lattice is not periodic.") if knpoints == 0: knpoints = self.num_cell a = 1 # The unit cell length is always considered 1 kn_start = 0 kn_end = 2*np.pi/a val_kns = np.zeros((self._length_of_unit_cell, knpoints), dtype=float) knxA = np.zeros((knpoints, 1), dtype=float) G0_H = self._H_intra # knxA = np.roll(knxA, np.floor_divide(knpoints, 2)) for ks in range(knpoints): knx = kn_start + (ks*(kn_end-kn_start)/knpoints) if knx >= np.pi: knxA[ks, 0] = knx - 2 * np.pi else: knxA[ks, 0] = knx knxA = np.roll(knxA, np.floor_divide(knpoints, 2)) for ks in range(knpoints): kx = knxA[ks, 0] H_ka = G0_H k_cos = [[kx]] for m in range(len(self._H_inter_list)): r_cos = self._inter_vec_list[m] kr_dotted = np.dot(k_cos, r_cos) H_int = self._H_inter_list[m]*np.exp(kr_dotted*1j)[0] H_ka = H_ka + H_int + H_int.dag() H_k = csr_matrix(H_ka) qH_k = Qobj(H_k) (vals, veks) = qH_k.eigenstates() val_kns[:, ks] = vals[:] return (knxA, val_kns)
def k(self): """ Returns the crystal momentum operator. All degrees of freedom has the cell number at their correspondig entry in the position operator. Returns ------- Qobj(ks) : qutip.Qobj The crystal momentum operator in units of 1/a. L is the number of unit cells, a is the length of a unit cell which is always taken to be 1. """ L = self.num_cell kop = np.zeros((L, L), dtype=complex) for row in range(L): for col in range(L): if row == col: kop[row, col] = (L-1)/2 # kop[row, col] = ((L+1) % 2)/ 2 # shifting the eigenvalues else: kop[row, col] = 1/(np.exp(2j * np.pi * (row - col)/L) - 1) qkop = Qobj(kop) [kD, kV] = qkop.eigenstates() kop_P = np.zeros((L, L), dtype=complex) for eno in range(L): if kD[eno] > (L // 2 + 0.5): vl = kD[eno] - L else: vl = kD[eno] vk = kV[eno] kop_P = kop_P + vl * vk * vk.dag() kop = 2 * np.pi / L * kop_P nx = self.cell_num_site ne = self._length_for_site k = np.kron(kop, np.eye(nx*ne)) dim_H = [self.lattice_tensor_config, self.lattice_tensor_config] return Qobj(k, dims=dim_H)
def _k_space_calculations(self, knpoints=0): """ Returns bulk Hamiltonian, its eigenvectors and eigenvectors of the space Hamiltonian at all the good quantum numbers of a periodic translationally invariant lattice. Returns ------- knxa : np.array knxA[j][0] is the jth good Quantum number k. qH_ks : np.ndarray of Qobj's qH_ks[j] is the Oobj of type oper that holds a bulk Hamiltonian for a good quantum number k. vec_xs : np.ndarray of Qobj's vec_xs[j] is the Oobj of type ket that holds an eigenvector of the Hamiltonian of the lattice. vec_kns : np.ndarray of Qobj's vec_kns[j] is the Oobj of type ket that holds an eigenvector of the bulk Hamiltonian of the lattice. """ if knpoints == 0: knpoints = self.num_cell a = 1 # The unit cell length is always considered 1 kn_start = 0 kn_end = 2*np.pi/a val_kns = np.zeros((self._length_of_unit_cell, knpoints), dtype=float) knxA = np.zeros((knpoints, 1), dtype=float) G0_H = self._H_intra vec_kns = np.zeros((knpoints, self._length_of_unit_cell, self._length_of_unit_cell), dtype=complex) vec_xs = np.array([None for i in range( knpoints * self._length_of_unit_cell)]) qH_ks = np.array([None for i in range(knpoints)]) for ks in range(knpoints): knx = kn_start + (ks*(kn_end-kn_start)/knpoints) if knx >= np.pi: knxA[ks, 0] = knx - 2 * np.pi else: knxA[ks, 0] = knx knxA = np.roll(knxA, np.floor_divide(knpoints, 2)) dim_hk = [self.cell_tensor_config, self.cell_tensor_config] for ks in range(knpoints): kx = knxA[ks, 0] H_ka = G0_H k_cos = [[kx]] for m in range(len(self._H_inter_list)): r_cos = self._inter_vec_list[m] kr_dotted = np.dot(k_cos, r_cos) H_int = self._H_inter_list[m]*np.exp(kr_dotted*1j)[0] H_ka = H_ka + H_int + H_int.dag() H_k = csr_matrix(H_ka) qH_k = Qobj(H_k, dims=dim_hk) qH_ks[ks] = qH_k (vals, veks) = qH_k.eigenstates() plane_waves = np.kron(np.exp(-1j * (kx * range(self.num_cell))), np.ones(self._length_of_unit_cell)) for eig_no in range(self._length_of_unit_cell): unit_cell_periodic = np.kron( np.ones(self.num_cell), veks[eig_no].dag()) vec_x = np.multiply(plane_waves, unit_cell_periodic) dim_H = [list(np.ones(len(self.lattice_tensor_config), dtype=int)), self.lattice_tensor_config] if self.is_real: if np.count_nonzero(vec_x) > 0: vec_x = np.real(vec_x) length_vec_x = np.sqrt((Qobj(vec_x) * Qobj(vec_x).dag())[0][0]) vec_x = vec_x / length_vec_x vec_x = Qobj(vec_x, dims=dim_H) vec_xs[ks*self._length_of_unit_cell+eig_no] = vec_x.dag() for i in range(self._length_of_unit_cell): v0 = np.squeeze(veks[i].full(), axis=1) vec_kns[ks, i, :] = v0 val_kns[:, ks] = vals[:] return (knxA, qH_ks, val_kns, vec_kns, vec_xs)