def ground(N, basis="dicke"): """ Generate the density matrix of the ground state. This state is given by (N/2, -N/2) in the Dicke basis. If the argument `basis` is "uncoupled" then it generates the state in a :math:`2^N` dim Hilbert space. Parameters ---------- N: int The number of two-level systems. basis: str The basis to use. Either "dicke" or "uncoupled" Returns ------- state: :class: qutip.Qobj The ground state density matrix in the requested basis. """ if basis == "uncoupled": state = _uncoupled_ground(N) return state nds = _num_dicke_states(N) rho = dok_matrix((nds, nds)) rho[N, N] = 1 return Qobj(rho)
def dicke(N, j, m): """ Generate a Dicke state as a pure density matrix in the Dicke basis. For instance, the superradiant state given by :math:`|j, m\\rangle = |1, 0\\rangle` for N = 2, and the state is represented as a density matrix of size (nds, nds) or (4, 4), with the (1, 1) element set to 1. Parameters ---------- N: int The number of two-level systems. j: float The eigenvalue j of the Dicke state (j, m). m: float The eigenvalue m of the Dicke state (j, m). Returns ------- rho: :class: qutip.Qobj The density matrix. """ nds = num_dicke_states(N) rho = np.zeros((nds, nds)) jmm1_dict = jmm1_dictionary(N)[1] i, k = jmm1_dict[(j, m, m)] rho[i, k] = 1. return Qobj(rho)
def Ham_RC_gen(H_sub, sigma, Omega, kappa, N, rotating=False, shift=0., shift_op=None, w_laser=0.): """ will only work for spin-boson like models Input: System Hamiltonian, RC freq., system-RC coupling and Hilbert space dimension Output: Hamiltonian, sigma_- and sigma_z in the vibronic Hilbert space """ a = destroy(N) I_sys = Qobj(qeye(H_sub.shape[0]), dims=sigma.dims) #print(( "shift is ", shift)) H_sub += shift_op * shift # shift is zero if no shift is required if rotating: # Hopefully removes energy scale. Shift operator should be the same as # the site energy-scale operator. H_sub -= shift_op * H_sub * (shift_op.dag()) H_S = tensor(H_sub, qeye(N)) + kappa * tensor(shift_op, (a + a.dag())) H_S += tensor(I_sys, Omega * a.dag() * a) A_em = tensor(sigma, qeye(N)) A_nrwa = tensor(sigma + sigma.dag(), qeye(N)) A_ph = tensor(I_sys, a) return H_S, A_em, A_nrwa, A_ph
def ghz(N, basis="dicke"): """ Generate the density matrix of the GHZ state. If the argument `basis` is "uncoupled" then it generates the state in a :math:`2^N` dim Hilbert space. Parameters ---------- N: int The number of two-level systems. basis: str The basis to use. Either "dicke" or "uncoupled". Returns ------- state: :class: qutip.Qobj The GHZ state density matrix in the requested basis. """ if basis == "uncoupled": return _uncoupled_ghz(N) nds = _num_dicke_states(N) rho = dok_matrix((nds, nds)) rho[0, 0] = 1 / 2 rho[N, N] = 1 / 2 rho[N, 0] = 1 / 2 rho[0, N] = 1 / 2 return Qobj(rho)
def _get_onto_evo_target(self): """ Get the inverse of the target. Used for calculating the 'onto target' evolution This is actually only relevant for unitary dynamics where the target.dag() is what is required However, for completeness, in general the inverse of the target operator is is required For state-to-state, the bra corresponding to the is required ket """ if self.target.shape[0] == self.target.shape[1]: #Target is operator targ = la.inv(self.target.full()) if self.oper_dtype == Qobj: self._onto_evo_target = Qobj(targ) elif self.oper_dtype == np.ndarray: self._onto_evo_target = targ elif self.oper_dtype == sp.csr_matrix: self._onto_evo_target = sp.csr_matrix(targ) else: targ_cls = self._target.__class__ self._onto_evo_target = targ_cls(targ) else: if self.oper_dtype == Qobj: self._onto_evo_target = self.target.dag() elif self.oper_dtype == np.ndarray: self._onto_evo_target = self.target.dag().full() elif self.oper_dtype == sp.csr_matrix: self._onto_evo_target = self.target.dag().data else: targ_cls = self._target.__class__ self._onto_evo_target = targ_cls(self.target.dag().full()) return self._onto_evo_target
def test_dicke_basis(self): """ PIQS: Test if the Dicke basis (j, m, m') is constructed correctly. We test the state with for N = 2, 0 0 0.3 0 0 0.5 0 0 0.3 0 0 0 0 0 0 0.5 """ N = 2 true_dicke_basis = np.zeros((4, 4)) true_dicke_basis[1, 1] = 0.5 true_dicke_basis[-1, -1] = 0.5 true_dicke_basis[0, 2] = 0.3 true_dicke_basis[2, 0] = 0.3 true_dicke_basis = Qobj(true_dicke_basis) jmm1_1 = {(N / 2, 0, 0): 0.5} jmm1_2 = {(0, 0, 0): 0.5} jmm1_3 = {(N / 2, N / 2, N / 2 - 2): 0.3} jmm1_4 = {(N / 2, N / 2 - 2, N / 2): 0.3} db1 = dicke_basis(2, jmm1_1) db2 = dicke_basis(2, jmm1_2) db3 = dicke_basis(2, jmm1_3) db4 = dicke_basis(2, jmm1_4) test_dicke_basis = db1 + db2 + db3 + db4 assert_equal(test_dicke_basis, true_dicke_basis) # error assert_raises(AttributeError, dicke_basis, N)
def _uncoupled_ghz(N): """ Generate the density matrix of the GHZ state in the full 2^N dimensional Hilbert space. Parameters ---------- N: int The number of two-level systems. Returns ------- ghz: :class: qutip.Qobj The density matrix for the GHZ state in the full Hilbert space. """ N = int(N) rho = np.zeros((2**N, 2**N)) rho[0, 0] = 1 / 2 rho[2**N - 1, 0] = 1 / 2 rho[0, 2**N - 1] = 1 / 2 rho[2**N - 1, 2**N - 1] = 1 / 2 spin_dim = [2 for i in range(0, N)] spins_dims = list((spin_dim, spin_dim)) rho = Qobj(rho, dims=spins_dims) return rho
def _compute_prop_grad(self, k, j, compute_prop=True): """ Calculate the gradient of propagator wrt the control amplitude in the timeslot using the expm_frechet method The propagtor is calculated (almost) for 'free' in this method and hence it is returned if compute_prop==True Returns: [prop], prop_grad """ dyn = self.parent if dyn.oper_dtype == Qobj: A = dyn._get_phased_dyn_gen(k).full() * dyn.tau[k] E = dyn._get_phased_ctrl_dyn_gen(j).full() * dyn.tau[k] if compute_prop: prop_dense, prop_grad_dense = la.expm_frechet(A, E) dyn._prop[k] = Qobj(prop_dense, dims=dyn.dyn_dims) dyn._prop_grad[k, j] = Qobj(prop_grad_dense, dims=dyn.dyn_dims) else: prop_grad_dense = la.expm_frechet(A, E, compute_expm=False) dyn._prop_grad[k, j] = Qobj(prop_grad_dense, dims=dyn.dyn_dims) elif dyn.oper_dtype == np.ndarray: A = dyn._get_phased_dyn_gen(k) * dyn.tau[k] E = dyn._get_phased_ctrl_dyn_gen(j) * dyn.tau[k] if compute_prop: dyn._prop[k], dyn._prop_grad[k, j] = la.expm_frechet(A, E) else: dyn._prop_grad[k, j] = la.expm_frechet(A, E, compute_expm=False) else: # Assuming some sparse matrix spcls = dyn._dyn_gen[k].__class__ A = (dyn._get_phased_dyn_gen(k) * dyn.tau[k]).toarray() E = (dyn._get_phased_ctrl_dyn_gen(j) * dyn.tau[k]).toarray() if compute_prop: prop_dense, prop_grad_dense = la.expm_frechet(A, E) dyn._prop[k] = spcls(prop_dense) dyn._prop_grad[k, j] = spcls(prop_grad_dense) else: prop_grad_dense = la.expm_frechet(A, E, compute_expm=False) dyn._prop_grad[k, j] = spcls(prop_grad_dense) if compute_prop: return dyn._prop[k], dyn._prop_grad[k, j] else: return dyn._prop_grad[k, j]
def rand_dm(N, density=0.75, pure=False, dims=None): """Creates a random NxN density matrix. Parameters ---------- N : int Shape of output density matrix. density : float Density etween [0,1] of output density matrix. dims : list Dimensions of quantum object. Used for specifying tensor structure. Default is dims=[[N],[N]]. Returns ------- oper : qobj NxN density matrix quantum operator. Notes ----- For small density matricies, choosing a low density will result in an error as no diagonal elements will be generated such that :math:`Tr(\\rho)=1`. """ if dims: _check_dims(dims, N, N) if pure: dm_density = sqrt(density) psi = rand_ket(N, dm_density) H = psi * psi.dag() else: density = density**2 non_zero = 0 tries = 0 while non_zero == 0 and tries < 10: H = rand_herm(N, density) H = H.dag() * H non_zero = sum([H.tr()]) tries += 1 if tries >= 10: raise ValueError( "Requested density is too low to generate density matrix.") if dims: return Qobj(H / H.tr(), dims=dims, shape=[N, N]) else: return Qobj(H / H.tr())
def operator_at_cells(self, op, cells): """ A function that returns an operator matrix that applies op to specific cells specified in the cells list Parameters ---------- op : qutip.Qobj Qobj representing the operator to be applied at certain cells. cells: list of int The cells at which the operator op is to be applied. Returns ------- Qobj(op_H) : Qobj Quantum object representing the operator with op applied at the specified cells. """ if isinstance(cells, int): cells = [cells] if isinstance(cells, list): for i, cells_i in enumerate(cells): if not isinstance(cells_i, int): raise Exception("cells[", i, "] is not an int!elements of \ cells is required to be ints.") else: raise Exception("cells in operator_at_cells() need to be an int or\ a list of ints.") nSb = self._H_intra.shape if (not isinstance(op, Qobj)): raise Exception("op in operator_at_cells need to be Qobj's. \n") nSi = op.shape if (nSb != nSi): raise Exception("op in operstor_at_cells() is required to \ be dimensionaly the same as Hamiltonian_of_cell.") (xx, yy) = op.shape row_ind = np.array([]) col_ind = np.array([]) data = np.array([]) nS = self._length_of_unit_cell nx_units = self.num_cell ny_units = 1 for i in range(nx_units): lin_RI = i if (i in cells): for k in range(xx): for l in range(yy): row_ind = np.append(row_ind, [lin_RI*nS+k]) col_ind = np.append(col_ind, [lin_RI*nS+l]) data = np.append(data, [op[k, l]]) m = nx_units*ny_units*nS op_H = csr_matrix((data, (row_ind, col_ind)), [m, m], dtype=np.complex128) dim_op = [self.lattice_tensor_config, self.lattice_tensor_config] return Qobj(op_H, dims=dim_op)
def get_random_QUBO_Hf(num_of_qubits, output_problem_path='output/qubo_problem.csv'): QUBO_mat = randomize_QUBO_small_gap(num_of_qubits) H_f_sparse = QUBO_to_Hamiltonian(QUBO_mat) H_final = Qobj(H_f_sparse.toarray()) output_problem = pd.DataFrame(H_f_sparse.toarray()) output_problem.to_csv(output_problem_path, header=False, index=False) return general_H0_creator(num_of_qubits), H_final
def show_state(state): """Shows the Hinton plot and Wigner function for the state""" fig, ax = plt.subplots(1, 2, figsize=(11, 5)) if state.shape[1] == 1: # State is a ket dm = Qobj(onp.array(jnp.dot(state, dag(state)))) hinton(dm, ax=ax[0]) plot_wigner(dm, ax=ax[1]) plt.show()
def arr2lqo(arr): d = int(np.sqrt(np.shape(arr)[0])) nbq = int(np.log2(d)) if (nbq > 1): dims = [[2, 2] for _ in range(nbq)] else: dims = [2, 2] return [Qobj(np.reshape(a, (d, d)), dims=dims) for a in np.transpose(arr)]
def testOperatorVectorNotSquare(self): """ Superoperator: Operator - vector - operator conversion for non-square matrix. """ op1 = Qobj(np.random.rand(6).reshape((3, 2))) op2 = vector_to_operator(operator_to_vector(op1)) assert_((op1 - op2).norm() < 1e-8)
def test_05_1_state_to_state(self): """ control.pulseoptim: state-to-state transfer linear initial pulse used assert that goal is achieved """ # 2 qubits with Ising interaction # some arbitary coupling constants alpha = [0.9, 0.7] beta = [0.8, 0.9] Sx = sigmax() Sz = sigmaz() H_d = (alpha[0] * tensor(Sx, identity(2)) + alpha[1] * tensor(identity(2), Sx) + beta[0] * tensor(Sz, identity(2)) + beta[1] * tensor(identity(2), Sz)) H_c = [tensor(Sz, Sz)] q1_0 = q2_0 = Qobj([[1], [0]]) q1_T = q2_T = Qobj([[0], [1]]) psi_0 = tensor(q1_0, q2_0) psi_T = tensor(q1_T, q2_T) n_ts = 10 evo_time = 18 # Run the optimisation result = cpo.optimize_pulse_unitary(H_d, H_c, psi_0, psi_T, n_ts, evo_time, fid_err_targ=1e-10, init_pulse_type='LIN', gen_stats=True) assert_(result.goal_achieved, msg="State-to-state goal not achieved. " "Terminated due to: {}, with infidelity: {}".format( result.termination_reason, result.fid_err)) assert_almost_equal(result.fid_err, 0.0, decimal=10, err_msg="Hadamard infidelity too high")
def test_bulk_Hamiltonians(self): """ lattice: Test the method Lattice1d.bulk_Hamiltonian_array(). """ # Coupled Resonator Optical Waveguide(CROW) Example(PhysRevB.99.224201) J = 2 eta = np.pi / 2 H_cell = Qobj(np.array([[0, J * np.sin(eta)], [J * np.sin(eta), 0]])) inter_cell_T0 = (J / 2) * Qobj( np.array([[np.exp(eta * 1j), 0], [0, np.exp(-eta * 1j)]])) inter_cell_T1 = (J / 2) * Qobj(np.array([[0, 1], [1, 0]])) inter_cell_T = [inter_cell_T0, inter_cell_T1] CROW_lattice = Lattice1d(num_cell=4, boundary="periodic", cell_num_site=1, cell_site_dof=[2], Hamiltonian_of_cell=H_cell, inter_hop=inter_cell_T) (knxA, qH_ks) = CROW_lattice.bulk_Hamiltonians() Hk0 = np.array([[0. + 0.j, 0. + 0.j], [0. + 0.j, 0. + 0.j]]) Hk1 = np.array([[2. + 0.j, 2. + 0.j], [2. + 0.j, -2. + 0.j]]) Hk2 = np.array([[0. + 0.j, 4. + 0.j], [4. + 0.j, 0. + 0.j]]) Hk3 = np.array([[-2. + 0.j, 2. + 0.j], [2. + 0.j, 2. + 0.j]]) qHks = np.array([None for i in range(4)]) qHks[0] = Qobj(Hk0) qHks[1] = Qobj(Hk1) qHks[2] = Qobj(Hk2) qHks[3] = Qobj(Hk3) for i in range(4): np.testing.assert_array_almost_equal(qH_ks[i], qHks[i], decimal=8)
def single_crosstalk_simulation(num_gates): """ A single simulation, with num_gates representing the number of rotations. Args: num_gates (int): The number of random gates to add in the simulation. Returns: result (qutip.solver.Result): A qutip Result object obtained from any of the solver methods such as mesolve. """ num_qubits = 2 # Qubit-0 is the target qubit. Qubit-1 suffers from crosstalk. myprocessor = ModelProcessor(model=MyModel(num_qubits)) # Add qubit frequency detuning 1.852MHz for the second qubit. myprocessor.add_drift(2 * np.pi * (sigmaz() + 1) / 2 * 1.852, targets=1) myprocessor.native_gates = None # Remove the native gates mycompiler = MyCompiler(num_qubits, { "pulse_amplitude": 0.02, "duration": 25 }) myprocessor.add_noise(ClassicalCrossTalk(1.0)) # Define a randome circuit. gates_set = [ Gate("ROT", 0, arg_value=0), Gate("ROT", 0, arg_value=np.pi / 2), Gate("ROT", 0, arg_value=np.pi), Gate("ROT", 0, arg_value=np.pi / 2 * 3), ] circuit = QubitCircuit(num_qubits) for ind in np.random.randint(0, 4, num_gates): circuit.add_gate(gates_set[ind]) # Simulate the circuit. myprocessor.load_circuit(circuit, compiler=mycompiler) init_state = tensor( [Qobj([[init_fid, 0], [0, 0.025]]), Qobj([[init_fid, 0], [0, 0.025]])]) options = SolverOptions(nsteps=10000) # increase the maximal allowed steps e_ops = [tensor([qeye(2), fock_dm(2)])] # observable # compute results of the run using a solver of choice with custom options result = myprocessor.run_state(init_state, solver="mesolve", options=options, e_ops=e_ops) result = result.expect[0][-1] # measured expectation value at the end return result
def trace_norm(self): """ Calculates trace norms of density state of matrix - to use this as a metric, take the difference (p_0 - p_1) and return the value of the trace distance Return: dist (float): trace distance of difference between density matrices """ current = Qobj(self.current_state) goal = Qobj(self.goal_state) density_1 = current * current.dag() density_2 = goal * goal.dag() dist = tracedist(density_1, density_2) return dist
def fidelity(self): """ Calculates fidelity of current and goal state/unitary. Return: fid (float): fidelity measure """ if self.is_unitary: assert self.current_unitary.shape == self.goal_unitary.shape fid = fidelity( Qobj(self.current_unitary) * self.basis_state, Qobj(self.goal_unitary) * self.basis_state) else: assert len(self.current_state) == len(self.goal_state) fid = fidelity(Qobj([self.current_state]), Qobj([self.goal_state])) return fid
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_1st_excited(self): h_site_j = hamiltonian_site_i(1) first_ex_state = h_site_j.eigenstates()[1][1] full_state = [] for i in range(self.no_of_elec): full_state.append(first_ex_state) full_state = tensor(full_state).data full_state = Qobj(full_state) return full_state
def basis(self, cell, site, dof_ind): """ Returns a single particle wavefunction ket with the particle localized at a specified dof at a specified site of a specified cell. Parameters ------- cell : int The cell at which the particle is to be localized. site : int The site of the cell at which the particle is to be localized. dof_ind : int/ list of int The index of the degrees of freedom with which the sigle particle is to be localized. Returns ---------- vec_i : qutip.Qobj ket type Quantum object representing the localized particle. """ if not isinstance(cell, int): raise Exception("cell needs to be int in basis().") elif cell >= self.num_cell: raise Exception("cell needs to less than Lattice1d.num_cell") if not isinstance(site, int): raise Exception("site needs to be int in basis().") elif site >= self.cell_num_site: raise Exception("site needs to less than Lattice1d.cell_num_site.") if isinstance(dof_ind, int): dof_ind = [dof_ind] if not isinstance(dof_ind, list): raise Exception("dof_ind in basis() needs to be an int or \ list of int") if np.shape(dof_ind) == np.shape(self.cell_site_dof): for i in range(len(dof_ind)): if dof_ind[i] >= self.cell_site_dof[i]: raise Exception("in basis(), dof_ind[", i, "] is required\ to be smaller than cell_num_site[", i, "]") else: raise Exception("dof_ind in basis() needs to be of the same \ dimensions as cell_site_dof.") doft = basis(self.cell_site_dof[0], dof_ind[0]) for i in range(1, len(dof_ind)): doft = tensor(doft, basis(self.cell_site_dof[i], dof_ind[i])) vec_i = tensor( basis(self.num_cell, cell), basis(self.cell_num_site, site), doft) ltc = self.lattice_tensor_config vec_i = Qobj(vec_i, dims=[ltc, [1 for i, j in enumerate(ltc)]]) return vec_i
def to_qobj(self) -> "qutip.Qobj": # noqa: F821 r"""Convert the operator to a qutip's Qobj. Returns: A `qutip.Qobj` object. """ from qutip import Qobj return Qobj(self.to_sparse(), dims=[list(self.hilbert.shape), list(self.hilbert.shape)])
def to_qobj(self): r"""Convert the variational state to a qutip's ket Qobj. Returns: A `qutip.Qobj` object. """ from qutip import Qobj q_dims = [list(self.hilbert.shape), [1 for i in range(self.hilbert.size)]] return Qobj(np.asarray(self.to_array()), dims=q_dims)
def to_qobj(self): r"""Convert this mixed state to a qutip density matrix Qobj. Returns: A `qutip.Qobj` object. """ from qutip import Qobj q_dims = [list(self.hilbert_physical.shape), list(self.hilbert_physical.shape)] return Qobj(np.asarray(self.to_matrix()), dims=q_dims)
def test_05_2_state_to_state_qobj(self): """ control.pulseoptim: state-to-state transfer (Qobj) linear initial pulse used assert that goal is achieved """ # 2 qubits with Ising interaction # some arbitary coupling constants alpha = [0.9, 0.7] beta = [0.8, 0.9] Sx = sigmax() Sz = sigmaz() H_d = (alpha[0] * tensor(Sx, identity(2)) + alpha[1] * tensor(identity(2), Sx) + beta[0] * tensor(Sz, identity(2)) + beta[1] * tensor(identity(2), Sz)) H_c = [tensor(Sz, Sz)] q1_0 = q2_0 = Qobj([[1], [0]]) q1_T = q2_T = Qobj([[0], [1]]) psi_0 = tensor(q1_0, q2_0) psi_T = tensor(q1_T, q2_T) n_ts = 10 evo_time = 18 #Try with Qobj propagation result = cpo.optimize_pulse_unitary(H_d, H_c, psi_0, psi_T, n_ts, evo_time, fid_err_targ=1e-10, init_pulse_type='LIN', dyn_params={'oper_dtype': Qobj}, gen_stats=True) assert_(result.goal_achieved, msg="State-to-state goal not achieved " "(Qobj propagation)" "Terminated due to: {}, with infidelity: {}".format( result.termination_reason, result.fid_err))
def _mc_dm_avg(psi_list): """ Private function that averages density matrices in parallel over all trajectores for a single time using parfor. """ ln = len(psi_list) dims = psi_list[0].dims shape = psi_list[0].shape out_data = mean([psi.data for psi in psi_list]) return Qobj(out_data, dims=dims, shape=shape, fast='mc-dm')
def __init__(self, lam, gamma, T, Nk): self.lam = lam self.gamma = gamma self.T = T self.Nk = Nk # we add a very weak system hamiltonian here to avoid having # singular system that causes problems for the scipy.sparse.linalg # superLU solver used in spsolve. self.H = Qobj(1e-5 * np.ones((2, 2))) self.Q = sigmaz()
def solve(self, rho0, tlist, options=None): """ Solve the ODE for the evolution of diagonal states and Hamiltonians. """ if options is None: options = Options() output = Result() output.solver = "pisolve" output.times = tlist output.states = [] output.states.append(Qobj(rho0)) rhs_generate = lambda y, tt, M: M.dot(y) rho0_flat = np.diag(np.real(rho0.full())) L = self.coefficient_matrix() rho_t = odeint(rhs_generate, rho0_flat, tlist, args=(L, )) for r in rho_t[1:]: diag = np.diag(r) output.states.append(Qobj(diag)) return output
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)