def floquet_master_equation_tensor(Alist, f_energies): """ Construct a tensor that represents the master equation in the floquet basis (with constant Hamiltonian and collapse operators). Simplest RWA approximation [Grifoni et al, Phys.Rep. 304 229 (1998)] Parameters ---------- Alist : list A list of Floquet-Markov master equation rate matrices. f_energies : array The Floquet energies. Returns ------- output : array The Floquet-Markov master equation tensor `R`. """ if isinstance(Alist, list): # Alist can be a list of rate matrices corresponding # to different operators that couple to the environment N, M = np.shape(Alist[0]) else: # or a simple rate matrix, in which case we put it in a list Alist = [Alist] N, M = np.shape(Alist[0]) R = Qobj(scipy.sparse.csr_matrix((N * N, N * N)), [[N, N], [N, N]], [N * N, N * N]) R.data = R.data.tolil() for I in range(N * N): a, b = vec2mat_index(N, I) for J in range(N * N): c, d = vec2mat_index(N, J) R.data[I, J] = -1.0j * (f_energies[a] - f_energies[b]) * \ (a == c) * (b == d) for A in Alist: s1 = s2 = 0 for n in range(N): s1 += A[a, n] * (n == c) * (n == d) - A[n, a] * \ (a == c) * (a == d) s2 += (A[n, a] + A[n, b]) * (a == c) * (b == d) dR = (a == b) * s1 - 0.5 * (1 - (a == b)) * s2 if dR != 0.0: R.data[I, J] += dR R.data = R.data.tocsr() return R
def vector_to_operator(op): """ Create a matrix representation given a quantum operator in vector form. """ q = Qobj() q.dims = op.dims[0] q.data = sp_reshape(op.data.T, q.shape).T return q
def operator_to_vector(op): """ Create a vector representation of a quantum operator given the matrix representation. """ q = Qobj() q.dims = [op.dims, [1]] q.data = sp_reshape(op.data.T, (np.prod(op.shape), 1)) return q
def vector_to_operator(op): """ Create a matrix representation given a quantum operator in vector form. """ q = Qobj() q.dims = op.dims[0] n = int(np.sqrt(op.shape[0])) q.data = sp_reshape(op.data.T, (n, n)).T return q
def steadystate_nonlinear(L_func, rho0, args={}, maxiter=10, random_initial_state=False, tol=1e-6, itertol=1e-5, use_umfpack=True, verbose=False): """ Steady state for the evolution subject to the nonlinear Liouvillian (which depends on the density matrix). .. note:: Experimental. Not at all certain that the inverse power method works for state-dependent Liouvillian operators. """ use_solver(assumeSortedIndices=True, useUmfpack=use_umfpack) if random_initial_state: rhoss = rand_dm(rho0.shape[0], 1.0, dims=rho0.dims) elif isket(rho0): rhoss = ket2dm(rho0) else: rhoss = Qobj(rho0) v = mat2vec(rhoss.full()) n = prod(rhoss.shape) tr_vec = sp.eye(rhoss.shape[0], rhoss.shape[0], format='coo') tr_vec = tr_vec.reshape((1, n)) it = 0 while it < maxiter: L = L_func(rhoss, args) L = L.data.tocsc() - (tol ** 2) * sp.eye(n, n, format='csc') L.sort_indices() v = spsolve(L, v, use_umfpack=use_umfpack) v = v / la.norm(v, np.inf) data = v / sum(tr_vec.dot(v)) data = reshape(data, (rhoss.shape[0], rhoss.shape[1])).T rhoss.data = sp.csr_matrix(data) it += 1 if la.norm(L * v, np.inf) <= tol: break if it >= maxiter: raise ValueError('Failed to find steady state after ' + str(maxiter) + ' iterations') rhoss = 0.5 * (rhoss + rhoss.dag()) return rhoss.tidyup() if qset.auto_tidyup else rhoss
def _steadystate_power(L, maxiter=10, tol=1e-6, itertol=1e-5, verbose=False): """ Inverse power method for steady state solving. """ if verbose: print('Starting iterative power method Solver...') use_solver(assumeSortedIndices=True) rhoss = Qobj() sflag = issuper(L) if sflag: rhoss.dims = L.dims[0] rhoss.shape = [prod(rhoss.dims[0]), prod(rhoss.dims[1])] else: rhoss.dims = [L.dims[0], 1] rhoss.shape = [prod(rhoss.dims[0]), 1] n = prod(rhoss.shape) L = L.data.tocsc() - (tol ** 2) * sp.eye(n, n, format='csc') L.sort_indices() v = mat2vec(rand_dm(rhoss.shape[0], 0.5 / rhoss.shape[0] + 0.5).full()) if verbose: start_time = time.time() it = 0 while (la.norm(L * v, np.inf) > tol) and (it < maxiter): v = spsolve(L, v) v = v / la.norm(v, np.inf) it += 1 if it >= maxiter: raise Exception('Failed to find steady state after ' + str(maxiter) + ' iterations') # normalise according to type of problem if sflag: trow = sp.eye(rhoss.shape[0], rhoss.shape[0], format='coo') trow = sp_reshape(trow, (1, n)) data = v / sum(trow.dot(v)) else: data = data / la.norm(v) data = sp.csr_matrix(vec2mat(data)) rhoss.data = 0.5 * (data + data.conj().T) rhoss.isherm = True if verbose: print('Power solver time: ', time.time() - start_time) if qset.auto_tidyup: return rhoss.tidyup() else: return rhoss
def _steadystate_power(L, ss_args): """ Inverse power method for steady state solving. """ if settings.debug: print('Starting iterative power method Solver...') tol=ss_args['tol'] maxiter=ss_args['maxiter'] use_solver(assumeSortedIndices=True) rhoss = Qobj() sflag = issuper(L) if sflag: rhoss.dims = L.dims[0] else: rhoss.dims = [L.dims[0], 1] n = prod(rhoss.shape) L = L.data.tocsc() - (tol ** 2) * sp.eye(n, n, format='csc') L.sort_indices() v = mat2vec(rand_dm(rhoss.shape[0], 0.5 / rhoss.shape[0] + 0.5).full()) it = 0 while (la.norm(L * v, np.inf) > tol) and (it < maxiter): v = spsolve(L, v) v = v / la.norm(v, np.inf) it += 1 if it >= maxiter: raise Exception('Failed to find steady state after ' + str(maxiter) + ' iterations') # normalise according to type of problem if sflag: trow = sp.eye(rhoss.shape[0], rhoss.shape[0], format='coo') trow = sp_reshape(trow, (1, n)) data = v / sum(trow.dot(v)) else: data = data / la.norm(v) data = sp.csr_matrix(vec2mat(data)) rhoss.data = 0.5 * (data + data.conj().T) rhoss.isherm = True return rhoss
def spre(A): """Superoperator formed from pre-multiplication by operator A. Parameters ---------- A : qobj Quantum operator for pre-multiplication. Returns -------- super :qobj Superoperator formed from input quantum object. """ if not isinstance(A, Qobj): raise TypeError('Input is not a quantum object') if not A.isoper: raise TypeError('Input is not a quantum operator') S = Qobj(isherm=A.isherm, superrep='super') S.dims = [[A.dims[0], A.dims[1]], [A.dims[0], A.dims[1]]] S.data = sp.kron(sp.identity(np.prod(A.shape[1])), A.data, format='csr') return S
def spost(A): """Superoperator formed from post-multiplication by operator A Parameters ---------- A : qobj Quantum operator for post multiplication. Returns ------- super : qobj Superoperator formed from input qauntum object. """ if not isinstance(A, Qobj): raise TypeError('Input is not a quantum object') if not A.isoper: raise TypeError('Input is not a quantum operator') S = Qobj(isherm=A.isherm, superrep='super') S.dims = [[A.dims[0], A.dims[1]], [A.dims[0], A.dims[1]]] S.data = zcsr_kron(A.data.T, fast_identity(np.prod(A.shape[0]))) return S
def tensor(*args): """Calculates the tensor product of input operators. Parameters ---------- args : array_like ``list`` or ``array`` of quantum objects for tensor product. Returns -------- obj : qobj A composite quantum object. Examples -------- >>> tensor([sigmax(), sigmax()]) Quantum object: dims = [[2, 2], [2, 2]], shape = [4, 4], type = oper, isHerm = True Qobj data = [[ 0.+0.j 0.+0.j 0.+0.j 1.+0.j] [ 0.+0.j 0.+0.j 1.+0.j 0.+0.j] [ 0.+0.j 1.+0.j 0.+0.j 0.+0.j] [ 1.+0.j 0.+0.j 0.+0.j 0.+0.j]] """ if not args: raise TypeError("Requires at least one input argument") num_args=len(args) step=0 for n in range(num_args): if isinstance(args[n],Qobj): qos=args[n] if step==0: dat=qos.data dim=qos.dims shp=qos.shape step=1 else: dat=sp.kron(dat,qos.data, format='csr') #sparse Kronecker product dim=[dim[0]+qos.dims[0],dim[1]+qos.dims[1]] #append dimensions of Qobjs shp=[dat.shape[0],dat.shape[1]] #new shape of matrix elif isinstance(args[n],(list,ndarray)):#checks if input is list/array of Qobjs qos=args[n] items=len(qos) #number of inputs if not all([isinstance(k,Qobj) for k in qos]): #raise error if one of the inputs is not a quantum object raise TypeError("One of inputs is not a quantum object") if items==1:# if only one Qobj, do nothing if step==0: dat=qos[0].data dim=qos[0].dims shp=qos[0].shape step=1 else: dat=sp.kron(dat,qos[0].data, format='csr') #sparse Kronecker product dim=[dim[0]+qos[0].dims[0],dim[1]+qos[0].dims[1]] #append dimensions of Qobjs shp=[dat.shape[0],dat.shape[1]] #new shape of matrix elif items!=1: if step==0: dat=qos[0].data dim=qos[0].dims shp=qos[0].shape step=1 for k in range(items-1): #cycle over all items dat=sp.kron(dat,qos[k+1].data, format='csr') #sparse Kronecker product dim=[dim[0]+qos[k+1].dims[0],dim[1]+qos[k+1].dims[1]] #append dimensions of Qobjs shp=[dat.shape[0],dat.shape[1]] #new shape of matrix out=Qobj() out.data=dat out.dims=dim out.shape=shp if qutip.settings.auto_tidyup: return Qobj(out).tidyup() #returns tidy Qobj else: return Qobj(out)
def _td_brmesolve(H, psi0, tlist, a_ops=[], e_ops=[], c_ops=[], args={}, use_secular=True, sec_cutoff=0.1, tol=qset.atol, options=None, progress_bar=None,_safe_mode=True, verbose=False, _prep_time=0): if isket(psi0): rho0 = ket2dm(psi0) else: rho0 = psi0 nrows = rho0.shape[0] H_terms = [] H_td_terms = [] H_obj = [] A_terms = [] A_td_terms = [] C_terms = [] C_td_terms = [] CA_obj = [] spline_count = [0,0] coupled_ops = [] coupled_lengths = [] coupled_spectra = [] if isinstance(H, Qobj): H_terms.append(H.full('f')) H_td_terms.append('1') else: for kk, h in enumerate(H): if isinstance(h, Qobj): H_terms.append(h.full('f')) H_td_terms.append('1') elif isinstance(h, list): H_terms.append(h[0].full('f')) if isinstance(h[1], Cubic_Spline): H_obj.append(h[1].coeffs) spline_count[0] += 1 H_td_terms.append(h[1]) else: raise Exception('Invalid Hamiltonian specification.') for kk, c in enumerate(c_ops): if isinstance(c, Qobj): C_terms.append(c.full('f')) C_td_terms.append('1') elif isinstance(c, list): C_terms.append(c[0].full('f')) if isinstance(c[1], Cubic_Spline): CA_obj.append(c[1].coeffs) spline_count[0] += 1 C_td_terms.append(c[1]) else: raise Exception('Invalid collapse operator specification.') coupled_offset = 0 for kk, a in enumerate(a_ops): if isinstance(a, list): if isinstance(a[0], Qobj): A_terms.append(a[0].full('f')) A_td_terms.append(a[1]) if isinstance(a[1], tuple): if not len(a[1])==2: raise Exception('Tuple must be len=2.') if isinstance(a[1][0],Cubic_Spline): spline_count[1] += 1 if isinstance(a[1][1],Cubic_Spline): spline_count[1] += 1 elif isinstance(a[0], tuple): if not isinstance(a[1], tuple): raise Exception('Invalid bath-coupling specification.') if (len(a[0])+1) != len(a[1]): raise Exception('BR a_ops tuple lengths not compatible.') coupled_ops.append(kk+coupled_offset) coupled_lengths.append(len(a[0])) coupled_spectra.append(a[1][0]) coupled_offset += len(a[0])-1 if isinstance(a[1][0],Cubic_Spline): spline_count[1] += 1 for nn, _a in enumerate(a[0]): A_terms.append(_a.full('f')) A_td_terms.append(a[1][nn+1]) if isinstance(a[1][nn+1],Cubic_Spline): CA_obj.append(a[1][nn+1].coeffs) spline_count[1] += 1 else: raise Exception('Invalid bath-coupling specification.') string_list = [] for kk,_ in enumerate(H_td_terms): string_list.append("H_terms[{0}]".format(kk)) for kk,_ in enumerate(H_obj): string_list.append("H_obj[{0}]".format(kk)) for kk,_ in enumerate(C_td_terms): string_list.append("C_terms[{0}]".format(kk)) for kk,_ in enumerate(CA_obj): string_list.append("CA_obj[{0}]".format(kk)) for kk,_ in enumerate(A_td_terms): string_list.append("A_terms[{0}]".format(kk)) #Add nrows to parameters string_list.append('nrows') for name, value in args.items(): if isinstance(value, np.ndarray): raise TypeError('NumPy arrays not valid args for BR solver.') else: string_list.append(str(value)) parameter_string = ",".join(string_list) if verbose: print('BR prep time:', time.time()-_prep_time) # # generate and compile new cython code if necessary # if not options.rhs_reuse or config.tdfunc is None: if options.rhs_filename is None: config.tdname = "rhs" + str(os.getpid()) + str(config.cgen_num) else: config.tdname = opt.rhs_filename if verbose: _st = time.time() cgen = BR_Codegen(h_terms=len(H_terms), h_td_terms=H_td_terms, h_obj=H_obj, c_terms=len(C_terms), c_td_terms=C_td_terms, c_obj=CA_obj, a_terms=len(A_terms), a_td_terms=A_td_terms, spline_count=spline_count, coupled_ops = coupled_ops, coupled_lengths = coupled_lengths, coupled_spectra = coupled_spectra, config=config, sparse=False, use_secular = use_secular, sec_cutoff = sec_cutoff, args=args, use_openmp=options.use_openmp, omp_thresh=qset.openmp_thresh if qset.has_openmp else None, omp_threads=options.num_cpus, atol=tol) cgen.generate(config.tdname + ".pyx") code = compile('from ' + config.tdname + ' import cy_td_ode_rhs', '<string>', 'exec') exec(code, globals()) config.tdfunc = cy_td_ode_rhs if verbose: print('BR compile time:', time.time()-_st) initial_vector = mat2vec(rho0.full()).ravel() _ode = scipy.integrate.ode(config.tdfunc) code = compile('_ode.set_f_params(' + parameter_string + ')', '<string>', 'exec') _ode.set_integrator('zvode', method=options.method, order=options.order, atol=options.atol, rtol=options.rtol, nsteps=options.nsteps, first_step=options.first_step, min_step=options.min_step, max_step=options.max_step) _ode.set_initial_value(initial_vector, tlist[0]) exec(code, locals()) # # prepare output array # n_tsteps = len(tlist) e_sops_data = [] output = Result() output.solver = "brmesolve" output.times = tlist if options.store_states: output.states = [] if isinstance(e_ops, types.FunctionType): n_expt_op = 0 expt_callback = True elif isinstance(e_ops, list): n_expt_op = len(e_ops) expt_callback = False if n_expt_op == 0: # fall back on storing states output.states = [] options.store_states = True else: output.expect = [] output.num_expect = n_expt_op for op in e_ops: e_sops_data.append(spre(op).data) if op.isherm: output.expect.append(np.zeros(n_tsteps)) else: output.expect.append(np.zeros(n_tsteps, dtype=complex)) else: raise TypeError("Expectation parameter must be a list or a function") # # start evolution # if type(progress_bar)==BaseProgressBar and verbose: _run_time = time.time() progress_bar.start(n_tsteps) rho = Qobj(rho0) dt = np.diff(tlist) for t_idx, t in enumerate(tlist): progress_bar.update(t_idx) if not _ode.successful(): raise Exception("ODE integration error: Try to increase " "the allowed number of substeps by increasing " "the nsteps parameter in the Options class.") if options.store_states or expt_callback: rho.data = dense2D_to_fastcsr_fmode(vec2mat(_ode.y), rho.shape[0], rho.shape[1]) if options.store_states: output.states.append(Qobj(rho, isherm=True)) if expt_callback: # use callback method e_ops(t, rho) for m in range(n_expt_op): if output.expect[m].dtype == complex: output.expect[m][t_idx] = expect_rho_vec(e_sops_data[m], _ode.y, 0) else: output.expect[m][t_idx] = expect_rho_vec(e_sops_data[m], _ode.y, 1) if t_idx < n_tsteps - 1: _ode.integrate(_ode.t + dt[t_idx]) progress_bar.finished() if type(progress_bar)==BaseProgressBar and verbose: print('BR runtime:', time.time()-_run_time) if (not options.rhs_reuse) and (config.tdname is not None): _cython_build_cleanup(config.tdname) if options.store_final_state: rho.data = dense2D_to_fastcsr_fmode(vec2mat(_ode.y), rho.shape[0], rho.shape[1]) output.final_state = Qobj(rho, dims=rho0.dims, isherm=True) return output
def _steadystate_power(L, ss_args): """ Inverse power method for steady state solving. """ ss_args['info'].pop('weight', None) if settings.debug: logger.debug('Starting iterative inverse-power method solver.') tol = ss_args['tol'] mtol = ss_args['mtol'] if mtol is None: mtol = max(0.1*tol, 1e-15) maxiter = ss_args['maxiter'] use_solver(assumeSortedIndices=True) rhoss = Qobj() sflag = issuper(L) if sflag: rhoss.dims = L.dims[0] else: rhoss.dims = [L.dims[0], 1] n = L.shape[0] # Build Liouvillian if ss_args['solver'] == 'mkl' and ss_args['method'] == 'power': has_mkl = 1 else: has_mkl = 0 L, perm, perm2, rev_perm, ss_args = _steadystate_power_liouvillian(L, ss_args, has_mkl) orig_nnz = L.nnz # start with all ones as RHS v = np.ones(n, dtype=complex) if ss_args['use_rcm']: v = v[np.ix_(perm2,)] # Do preconditioning if ss_args['solver'] == 'scipy': if ss_args['M'] is None and ss_args['use_precond'] and \ ss_args['method'] in ['power-gmres', 'power-lgmres', 'power-bicgstab']: ss_args['M'], ss_args = _iterative_precondition(L, int(np.sqrt(n)), ss_args) if ss_args['M'] is None: warnings.warn("Preconditioning failed. Continuing without.", UserWarning) ss_iters = {'iter': 0} def _iter_count(r): ss_iters['iter'] += 1 return _power_start = time.time() # Get LU factors if ss_args['method'] == 'power': if ss_args['solver'] == 'mkl': lu = mkl_splu(L, max_iter_refine=ss_args['max_iter_refine'], scaling_vectors=ss_args['scaling_vectors'], weighted_matching=ss_args['weighted_matching']) else: lu = splu(L, permc_spec=ss_args['permc_spec'], diag_pivot_thresh=ss_args['diag_pivot_thresh'], options=dict(ILU_MILU=ss_args['ILU_MILU'])) if settings.debug and _scipy_check: L_nnz = lu.L.nnz U_nnz = lu.U.nnz logger.debug('L NNZ: %i ; U NNZ: %i' % (L_nnz, U_nnz)) logger.debug('Fill factor: %f' % ((L_nnz+U_nnz)/orig_nnz)) it = 0 # FIXME: These atol keyword except checks can be removed once scipy 1.1 # is a minimum requirement while (la.norm(L * v, np.inf) > tol) and (it < maxiter): check = 0 if ss_args['method'] == 'power': v = lu.solve(v) elif ss_args['method'] == 'power-gmres': try: v, check = gmres(L, v, tol=mtol, atol=ss_args['matol'], M=ss_args['M'], x0=ss_args['x0'], restart=ss_args['restart'], maxiter=ss_args['maxiter'], callback=_iter_count) except TypeError as e: if "unexpected keyword argument 'atol'" in str(e): v, check = gmres(L, v, tol=mtol, M=ss_args['M'], x0=ss_args['x0'], restart=ss_args['restart'], maxiter=ss_args['maxiter'], callback=_iter_count) elif ss_args['method'] == 'power-lgmres': try: v, check = lgmres(L, v, tol=mtol, atol=ss_args['matol'], M=ss_args['M'], x0=ss_args['x0'], maxiter=ss_args['maxiter'], callback=_iter_count) except TypeError as e: if "unexpected keyword argument 'atol'" in str(e): v, check = lgmres(L, v, tol=mtol, M=ss_args['M'], x0=ss_args['x0'], maxiter=ss_args['maxiter'], callback=_iter_count) elif ss_args['method'] == 'power-bicgstab': try: v, check = bicgstab(L, v, tol=mtol, atol=ss_args['matol'], M=ss_args['M'], x0=ss_args['x0'], maxiter=ss_args['maxiter'], callback=_iter_count) except TypeError as e: if "unexpected keyword argument 'atol'" in str(e): v, check = bicgstab(L, v, tol=mtol, M=ss_args['M'], x0=ss_args['x0'], maxiter=ss_args['maxiter'], callback=_iter_count) else: raise Exception("Invalid iterative solver method.") if check > 0: raise Exception("{} failed to find solution in " "{} iterations.".format(ss_args['method'], check)) if check < 0: raise Exception("Breakdown in {}".format(ss_args['method'])) v = v / la.norm(v, np.inf) it += 1 if ss_args['method'] == 'power' and ss_args['solver'] == 'mkl': lu.delete() if ss_args['return_info']: ss_args['info']['max_iter_refine'] = ss_args['max_iter_refine'] ss_args['info']['scaling_vectors'] = ss_args['scaling_vectors'] ss_args['info']['weighted_matching'] = ss_args['weighted_matching'] if it >= maxiter: raise Exception('Failed to find steady state after ' + str(maxiter) + ' iterations') _power_end = time.time() ss_args['info']['solution_time'] = _power_end-_power_start ss_args['info']['iterations'] = it if ss_args['return_info']: ss_args['info']['residual_norm'] = la.norm(L*v, np.inf) if settings.debug: logger.debug('Number of iterations: %i' % it) if ss_args['use_rcm']: v = v[np.ix_(rev_perm,)] # normalise according to type of problem if sflag: trow = v[::rhoss.shape[0]+1] data = v / np.sum(trow) else: data = data / la.norm(v) data = dense2D_to_fastcsr_fmode(vec2mat(data), rhoss.shape[0], rhoss.shape[0]) rhoss.data = 0.5 * (data + data.H) rhoss.isherm = True if ss_args['return_info']: return rhoss, ss_args['info'] else: return rhoss
def _steadystate_power(L, ss_args): """ Inverse power method for steady state solving. """ ss_args['info'].pop('weight', None) if settings.debug: print('Starting iterative inverse-power method solver...') tol = ss_args['tol'] maxiter = ss_args['maxiter'] use_solver(assumeSortedIndices=True) rhoss = Qobj() sflag = issuper(L) if sflag: rhoss.dims = L.dims[0] else: rhoss.dims = [L.dims[0], 1] n = prod(rhoss.shape) L = L.data.tocsc() - (1e-15) * sp.eye(n, n, format='csc') L.sort_indices() orig_nnz = L.nnz # start with all ones as RHS v = np.ones(n,dtype=complex) if ss_args['use_rcm']: if settings.debug: old_band = sp_bandwidth(L)[0] print('Original bandwidth:', old_band) perm = reverse_cuthill_mckee(L) rev_perm = np.argsort(perm) L = sp_permute(L, perm, perm, 'csc') v = v[np.ix_(perm,)] if settings.debug: new_band = sp_bandwidth(L)[0] print('RCM bandwidth:', new_band) print('Bandwidth reduction factor:', round(old_band/new_band, 2)) # Get LU factors lu = splu(L, permc_spec=ss_args['permc_spec'], diag_pivot_thresh=ss_args['diag_pivot_thresh'], options=dict(ILU_MILU=ss_args['ILU_MILU'])) if settings.debug and _scipy_check: L_nnz = lu.L.nnz U_nnz = lu.U.nnz print('L NNZ:', L_nnz, ';', 'U NNZ:', U_nnz) print('Fill factor:', (L_nnz+U_nnz)/orig_nnz) _power_start = time.time() it = 0 while (la.norm(L * v, np.inf) > tol) and (it < maxiter): v = lu.solve(v) v = v / la.norm(v, np.inf) it += 1 if it >= maxiter: raise Exception('Failed to find steady state after ' + str(maxiter) + ' iterations') _power_end = time.time() ss_args['info']['solution_time'] = _power_end-_power_start ss_args['info']['iterations'] = it if settings.debug: print('Number of iterations:', it) if ss_args['use_rcm']: v = v[np.ix_(rev_perm,)] # normalise according to type of problem if sflag: trow = sp.eye(rhoss.shape[0], rhoss.shape[0], format='coo') trow = sp_reshape(trow, (1, n)) data = v / sum(trow.dot(v)) else: data = data / la.norm(v) data = sp.csr_matrix(vec2mat(data)) rhoss.data = 0.5 * (data + data.conj().T) rhoss.isherm = True if ss_args['return_info']: return rhoss, ss_args['info'] else: return rhoss
def _generic_ode_solve(r, rho0, tlist, e_ops, opt, progress_bar): """ Internal function for solving ME. Solve an ODE which solver parameters already setup (r). Calculate the required expectation values or invoke callback function at each time step. """ # # prepare output array # n_tsteps = len(tlist) e_sops_data = [] output = Result() output.solver = "mesolve" output.times = tlist if opt.store_states: output.states = [] if isinstance(e_ops, types.FunctionType): n_expt_op = 0 expt_callback = True elif isinstance(e_ops, list): n_expt_op = len(e_ops) expt_callback = False if n_expt_op == 0: # fall back on storing states output.states = [] opt.store_states = True else: output.expect = [] output.num_expect = n_expt_op for op in e_ops: e_sops_data.append(spre(op).data) if op.isherm and rho0.isherm: output.expect.append(np.zeros(n_tsteps)) else: output.expect.append(np.zeros(n_tsteps, dtype=complex)) else: raise TypeError("Expectation parameter must be a list or a function") # # start evolution # progress_bar.start(n_tsteps) rho = Qobj(rho0) dt = np.diff(tlist) for t_idx, t in enumerate(tlist): progress_bar.update(t_idx) if not r.successful(): break if opt.store_states or expt_callback: rho.data = vec2mat(r.y) if opt.store_states: output.states.append(Qobj(rho)) if expt_callback: # use callback method e_ops(t, rho) for m in range(n_expt_op): if output.expect[m].dtype == complex: output.expect[m][t_idx] = expect_rho_vec( e_sops_data[m], r.y, 0) else: output.expect[m][t_idx] = expect_rho_vec( e_sops_data[m], r.y, 1) if t_idx < n_tsteps - 1: r.integrate(r.t + dt[t_idx]) progress_bar.finished() if not opt.rhs_reuse and config.tdname is not None: try: os.remove(config.tdname + ".pyx") except: pass if opt.store_final_state: rho.data = vec2mat(r.y) output.final_state = Qobj(rho) return output
def _steadystate_power(L, ss_args): """ Inverse power method for steady state solving. """ ss_args['info'].pop('weight', None) if settings.debug: logger.debug('Starting iterative inverse-power method solver.') tol = ss_args['tol'] maxiter = ss_args['maxiter'] use_solver(assumeSortedIndices=True) rhoss = Qobj() sflag = issuper(L) if sflag: rhoss.dims = L.dims[0] else: rhoss.dims = [L.dims[0], 1] n = L.shape[0] # Build Liouvillian if settings.has_mkl and ss_args['method'] == 'power': has_mkl = 1 else: has_mkl = 0 L, perm, perm2, rev_perm, ss_args = _steadystate_power_liouvillian(L, ss_args, has_mkl) orig_nnz = L.nnz # start with all ones as RHS v = np.ones(n, dtype=complex) if ss_args['use_rcm']: v = v[np.ix_(perm2,)] # Do preconditioning if ss_args['M'] is None and ss_args['use_precond'] and \ ss_args['method'] in ['power-gmres', 'power-lgmres', 'power-bicgstab']: ss_args['M'], ss_args = _iterative_precondition(L, int(np.sqrt(n)), ss_args) if ss_args['M'] is None: warnings.warn("Preconditioning failed. Continuing without.", UserWarning) ss_iters = {'iter': 0} def _iter_count(r): ss_iters['iter'] += 1 return _power_start = time.time() # Get LU factors if ss_args['method'] == 'power': if settings.has_mkl: lu = mkl_splu(L) else: lu = splu(L, permc_spec=ss_args['permc_spec'], diag_pivot_thresh=ss_args['diag_pivot_thresh'], options=dict(ILU_MILU=ss_args['ILU_MILU'])) if settings.debug and _scipy_check: L_nnz = lu.L.nnz U_nnz = lu.U.nnz logger.debug('L NNZ: %i ; U NNZ: %i' % (L_nnz, U_nnz)) logger.debug('Fill factor: %f' % ((L_nnz+U_nnz)/orig_nnz)) it = 0 _tol = max(ss_args['tol']/10, 1e-15) # Should make this user accessible while (la.norm(L * v, np.inf) > tol) and (it < maxiter): if ss_args['method'] == 'power': v = lu.solve(v) elif ss_args['method'] == 'power-gmres': v, check = gmres(L, v, tol=_tol, M=ss_args['M'], x0=ss_args['x0'], restart=ss_args['restart'], maxiter=ss_args['maxiter'], callback=_iter_count) elif ss_args['method'] == 'power-lgmres': v, check = lgmres(L, v, tol=_tol, M=ss_args['M'], x0=ss_args['x0'], maxiter=ss_args['maxiter'], callback=_iter_count) elif ss_args['method'] == 'power-bicgstab': v, check = bicgstab(L, v, tol=_tol, M=ss_args['M'], x0=ss_args['x0'], maxiter=ss_args['maxiter'], callback=_iter_count) else: raise Exception("Invalid iterative solver method.") v = v / la.norm(v, np.inf) it += 1 if ss_args['method'] == 'power' and settings.has_mkl: lu.delete() if it >= maxiter: raise Exception('Failed to find steady state after ' + str(maxiter) + ' iterations') _power_end = time.time() ss_args['info']['solution_time'] = _power_end-_power_start ss_args['info']['iterations'] = it if ss_args['return_info']: ss_args['info']['residual_norm'] = la.norm(L*v) if settings.debug: logger.debug('Number of iterations: %i' % it) if ss_args['use_rcm']: v = v[np.ix_(rev_perm,)] # normalise according to type of problem if sflag: trow = sp.eye(rhoss.shape[0], rhoss.shape[0], format='coo') trow = sp_reshape(trow, (1, n)) data = v / sum(trow.dot(v)) else: data = data / la.norm(v) data = sp.csr_matrix(vec2mat(data)) rhoss.data = 0.5 * (data + data.conj().T) rhoss.isherm = True if ss_args['return_info']: return rhoss, ss_args['info'] else: return rhoss
def _td_brmesolve(H, psi0, tlist, a_ops=[], e_ops=[], c_ops=[], args={}, use_secular=True, sec_cutoff=0.1, tol=qset.atol, options=None, progress_bar=None, _safe_mode=True, verbose=False, _prep_time=0): if isket(psi0): rho0 = ket2dm(psi0) else: rho0 = psi0 nrows = rho0.shape[0] H_terms = [] H_td_terms = [] H_obj = [] A_terms = [] A_td_terms = [] C_terms = [] C_td_terms = [] CA_obj = [] spline_count = [0, 0] coupled_ops = [] coupled_lengths = [] coupled_spectra = [] if isinstance(H, Qobj): H_terms.append(H.full('f')) H_td_terms.append('1') else: for kk, h in enumerate(H): if isinstance(h, Qobj): H_terms.append(h.full('f')) H_td_terms.append('1') elif isinstance(h, list): H_terms.append(h[0].full('f')) if isinstance(h[1], Cubic_Spline): H_obj.append(h[1].coeffs) spline_count[0] += 1 H_td_terms.append(h[1]) else: raise Exception('Invalid Hamiltonian specification.') for kk, c in enumerate(c_ops): if isinstance(c, Qobj): C_terms.append(c.full('f')) C_td_terms.append('1') elif isinstance(c, list): C_terms.append(c[0].full('f')) if isinstance(c[1], Cubic_Spline): CA_obj.append(c[1].coeffs) spline_count[0] += 1 C_td_terms.append(c[1]) else: raise Exception('Invalid collapse operator specification.') coupled_offset = 0 for kk, a in enumerate(a_ops): if isinstance(a, list): if isinstance(a[0], Qobj): A_terms.append(a[0].full('f')) A_td_terms.append(a[1]) if isinstance(a[1], tuple): if not len(a[1]) == 2: raise Exception('Tuple must be len=2.') if isinstance(a[1][0], Cubic_Spline): spline_count[1] += 1 if isinstance(a[1][1], Cubic_Spline): spline_count[1] += 1 elif isinstance(a[0], tuple): if not isinstance(a[1], tuple): raise Exception('Invalid bath-coupling specification.') if (len(a[0]) + 1) != len(a[1]): raise Exception('BR a_ops tuple lengths not compatible.') coupled_ops.append(kk + coupled_offset) coupled_lengths.append(len(a[0])) coupled_spectra.append(a[1][0]) coupled_offset += len(a[0]) - 1 if isinstance(a[1][0], Cubic_Spline): spline_count[1] += 1 for nn, _a in enumerate(a[0]): A_terms.append(_a.full('f')) A_td_terms.append(a[1][nn + 1]) if isinstance(a[1][nn + 1], Cubic_Spline): CA_obj.append(a[1][nn + 1].coeffs) spline_count[1] += 1 else: raise Exception('Invalid bath-coupling specification.') string_list = [] for kk, _ in enumerate(H_td_terms): string_list.append("H_terms[{0}]".format(kk)) for kk, _ in enumerate(H_obj): string_list.append("H_obj[{0}]".format(kk)) for kk, _ in enumerate(C_td_terms): string_list.append("C_terms[{0}]".format(kk)) for kk, _ in enumerate(CA_obj): string_list.append("CA_obj[{0}]".format(kk)) for kk, _ in enumerate(A_td_terms): string_list.append("A_terms[{0}]".format(kk)) #Add nrows to parameters string_list.append('nrows') for name, value in args.items(): if isinstance(value, np.ndarray): raise TypeError('NumPy arrays not valid args for BR solver.') else: string_list.append(str(value)) parameter_string = ",".join(string_list) if verbose: print('BR prep time:', time.time() - _prep_time) # # generate and compile new cython code if necessary # if not options.rhs_reuse or config.tdfunc is None: if options.rhs_filename is None: config.tdname = "rhs" + str(os.getpid()) + str(config.cgen_num) else: config.tdname = opt.rhs_filename if verbose: _st = time.time() cgen = BR_Codegen( h_terms=len(H_terms), h_td_terms=H_td_terms, h_obj=H_obj, c_terms=len(C_terms), c_td_terms=C_td_terms, c_obj=CA_obj, a_terms=len(A_terms), a_td_terms=A_td_terms, spline_count=spline_count, coupled_ops=coupled_ops, coupled_lengths=coupled_lengths, coupled_spectra=coupled_spectra, config=config, sparse=False, use_secular=use_secular, sec_cutoff=sec_cutoff, args=args, use_openmp=options.use_openmp, omp_thresh=qset.openmp_thresh if qset.has_openmp else None, omp_threads=options.num_cpus, atol=tol) cgen.generate(config.tdname + ".pyx") code = compile('from ' + config.tdname + ' import cy_td_ode_rhs', '<string>', 'exec') exec(code, globals()) config.tdfunc = cy_td_ode_rhs if verbose: print('BR compile time:', time.time() - _st) initial_vector = mat2vec(rho0.full()).ravel() _ode = scipy.integrate.ode(config.tdfunc) code = compile('_ode.set_f_params(' + parameter_string + ')', '<string>', 'exec') _ode.set_integrator('zvode', method=options.method, order=options.order, atol=options.atol, rtol=options.rtol, nsteps=options.nsteps, first_step=options.first_step, min_step=options.min_step, max_step=options.max_step) _ode.set_initial_value(initial_vector, tlist[0]) exec(code, locals()) # # prepare output array # n_tsteps = len(tlist) e_sops_data = [] output = Result() output.solver = "brmesolve" output.times = tlist if options.store_states: output.states = [] if isinstance(e_ops, types.FunctionType): n_expt_op = 0 expt_callback = True elif isinstance(e_ops, list): n_expt_op = len(e_ops) expt_callback = False if n_expt_op == 0: # fall back on storing states output.states = [] options.store_states = True else: output.expect = [] output.num_expect = n_expt_op for op in e_ops: e_sops_data.append(spre(op).data) if op.isherm: output.expect.append(np.zeros(n_tsteps)) else: output.expect.append(np.zeros(n_tsteps, dtype=complex)) else: raise TypeError("Expectation parameter must be a list or a function") # # start evolution # if type(progress_bar) == BaseProgressBar and verbose: _run_time = time.time() progress_bar.start(n_tsteps) rho = Qobj(rho0) dt = np.diff(tlist) for t_idx, t in enumerate(tlist): progress_bar.update(t_idx) if not _ode.successful(): raise Exception("ODE integration error: Try to increase " "the allowed number of substeps by increasing " "the nsteps parameter in the Options class.") if options.store_states or expt_callback: rho.data = dense2D_to_fastcsr_fmode(vec2mat(_ode.y), rho.shape[0], rho.shape[1]) if options.store_states: output.states.append(Qobj(rho, isherm=True)) if expt_callback: # use callback method e_ops(t, rho) for m in range(n_expt_op): if output.expect[m].dtype == complex: output.expect[m][t_idx] = expect_rho_vec( e_sops_data[m], _ode.y, 0) else: output.expect[m][t_idx] = expect_rho_vec( e_sops_data[m], _ode.y, 1) if t_idx < n_tsteps - 1: _ode.integrate(_ode.t + dt[t_idx]) progress_bar.finished() if type(progress_bar) == BaseProgressBar and verbose: print('BR runtime:', time.time() - _run_time) if (not options.rhs_reuse) and (config.tdname is not None): _cython_build_cleanup(config.tdname) if options.store_final_state: rho.data = dense2D_to_fastcsr_fmode(vec2mat(_ode.y), rho.shape[0], rho.shape[1]) output.final_state = Qobj(rho, dims=rho0.dims, isherm=True) return output
def _steadystate_power(L, ss_args): """ Inverse power method for steady state solving. """ ss_args['info'].pop('weight', None) if settings.debug: print('Starting iterative inverse-power method solver...') tol = ss_args['tol'] maxiter = ss_args['maxiter'] use_solver(assumeSortedIndices=True) rhoss = Qobj() sflag = issuper(L) if sflag: rhoss.dims = L.dims[0] else: rhoss.dims = [L.dims[0], 1] n = prod(rhoss.shape) L = L.data.tocsc() - (1e-15) * sp.eye(n, n, format='csc') L.sort_indices() orig_nnz = L.nnz # start with all ones as RHS v = np.ones(n, dtype=complex) if ss_args['use_rcm']: if settings.debug: old_band = sp_bandwidth(L)[0] print('Original bandwidth:', old_band) perm = reverse_cuthill_mckee(L) rev_perm = np.argsort(perm) L = sp_permute(L, perm, perm, 'csc') v = v[np.ix_(perm, )] if settings.debug: new_band = sp_bandwidth(L)[0] print('RCM bandwidth:', new_band) print('Bandwidth reduction factor:', round(old_band / new_band, 2)) # Get LU factors lu = splu(L, permc_spec=ss_args['permc_spec'], diag_pivot_thresh=ss_args['diag_pivot_thresh'], options=dict(ILU_MILU=ss_args['ILU_MILU'])) if settings.debug and _scipy_check: L_nnz = lu.L.nnz U_nnz = lu.U.nnz print('L NNZ:', L_nnz, ';', 'U NNZ:', U_nnz) print('Fill factor:', (L_nnz + U_nnz) / orig_nnz) _power_start = time.time() it = 0 while (la.norm(L * v, np.inf) > tol) and (it < maxiter): v = lu.solve(v) v = v / la.norm(v, np.inf) it += 1 if it >= maxiter: raise Exception('Failed to find steady state after ' + str(maxiter) + ' iterations') _power_end = time.time() ss_args['info']['solution_time'] = _power_end - _power_start ss_args['info']['iterations'] = it if settings.debug: print('Number of iterations:', it) if ss_args['use_rcm']: v = v[np.ix_(rev_perm, )] # normalise according to type of problem if sflag: trow = sp.eye(rhoss.shape[0], rhoss.shape[0], format='coo') trow = sp_reshape(trow, (1, n)) data = v / sum(trow.dot(v)) else: data = data / la.norm(v) data = sp.csr_matrix(vec2mat(data)) rhoss.data = 0.5 * (data + data.conj().T) rhoss.isherm = True if ss_args['return_info']: return rhoss, ss_args['info'] else: return rhoss
def _generic_ode_solve(r, rho0, tlist, e_ops, opt, progress_bar): """ Internal function for solving ME. Solve an ODE which solver parameters already setup (r). Calculate the required expectation values or invoke callback function at each time step. """ # # prepare output array # n_tsteps = len(tlist) e_sops_data = [] output = Result() output.solver = "mesolve" output.times = tlist if opt.store_states: output.states = [] if isinstance(e_ops, types.FunctionType): n_expt_op = 0 expt_callback = True elif isinstance(e_ops, list): n_expt_op = len(e_ops) expt_callback = False if n_expt_op == 0: # fall back on storing states output.states = [] opt.store_states = True else: output.expect = [] output.num_expect = n_expt_op for op in e_ops: e_sops_data.append(spre(op).data) if op.isherm and rho0.isherm: output.expect.append(np.zeros(n_tsteps)) else: output.expect.append(np.zeros(n_tsteps, dtype=complex)) else: raise TypeError("Expectation parameter must be a list or a function") # # start evolution # progress_bar.start(n_tsteps) rho = Qobj(rho0) dt = np.diff(tlist) for t_idx, t in enumerate(tlist): progress_bar.update(t_idx) if not r.successful(): raise Exception("ODE integration error: Try to increase " "the allowed number of substeps by increasing " "the nsteps parameter in the Options class.") if opt.store_states or expt_callback: rho.data = dense2D_to_fastcsr_fmode(vec2mat(r.y), rho.shape[0], rho.shape[1]) if opt.store_states: output.states.append(Qobj(rho, isherm=True)) if expt_callback: # use callback method e_ops(t, rho) for m in range(n_expt_op): if output.expect[m].dtype == complex: output.expect[m][t_idx] = expect_rho_vec( e_sops_data[m], r.y, 0) else: output.expect[m][t_idx] = expect_rho_vec( e_sops_data[m], r.y, 1) if t_idx < n_tsteps - 1: r.integrate(r.t + dt[t_idx]) progress_bar.finished() if (not opt.rhs_reuse) and (config.tdname is not None): _cython_build_cleanup(config.tdname) if opt.store_final_state: rho.data = dense2D_to_fastcsr_fmode(vec2mat(r.y), rho.shape[0], rho.shape[1]) output.final_state = Qobj(rho, dims=rho0.dims, isherm=True) return output
def _generic_ode_solve(r, rho0, tlist, e_ops, opt, progress_bar): """ Internal function for solving ME. Solve an ODE which solver parameters already setup (r). Calculate the required expectation values or invoke callback function at each time step. """ # # prepare output array # n_tsteps = len(tlist) e_sops_data = [] output = Result() output.solver = "mesolve" output.times = tlist if opt.store_states: output.states = [] if isinstance(e_ops, types.FunctionType): n_expt_op = 0 expt_callback = True elif isinstance(e_ops, list): n_expt_op = len(e_ops) expt_callback = False if n_expt_op == 0: # fall back on storing states output.states = [] opt.store_states = True else: output.expect = [] output.num_expect = n_expt_op for op in e_ops: e_sops_data.append(spre(op).data) if op.isherm and rho0.isherm: output.expect.append(np.zeros(n_tsteps)) else: output.expect.append(np.zeros(n_tsteps, dtype=complex)) else: raise TypeError("Expectation parameter must be a list or a function") # # start evolution # progress_bar.start(n_tsteps) rho = Qobj(rho0) dt = np.diff(tlist) for t_idx, t in enumerate(tlist): progress_bar.update(t_idx) if not r.successful(): raise Exception("ODE integration error: Try to increase " "the allowed number of substeps by increasing " "the nsteps parameter in the Options class.") if opt.store_states or expt_callback: rho.data = dense2D_to_fastcsr_fmode(vec2mat(r.y), rho.shape[0], rho.shape[1]) if opt.store_states: output.states.append(Qobj(rho, isherm=True)) if expt_callback: # use callback method e_ops(t, rho) for m in range(n_expt_op): if output.expect[m].dtype == complex: output.expect[m][t_idx] = expect_rho_vec(e_sops_data[m], r.y, 0) else: output.expect[m][t_idx] = expect_rho_vec(e_sops_data[m], r.y, 1) if t_idx < n_tsteps - 1: r.integrate(r.t + dt[t_idx]) progress_bar.finished() if (not opt.rhs_reuse) and (config.tdname is not None): _cython_build_cleanup(config.tdname) if opt.store_final_state: rho.data = dense2D_to_fastcsr_fmode(vec2mat(r.y), rho.shape[0], rho.shape[1]) output.final_state = Qobj(rho, dims=rho0.dims, isherm=True) return output
def tensor(*args): """Calculates the tensor product of input operators. Parameters ---------- args : array_like ``list`` or ``array`` of quantum objects for tensor product. Returns ------- obj : qobj A composite quantum object. Examples -------- >>> tensor([sigmax(), sigmax()]) Quantum object: dims = [[2, 2], [2, 2]], \ shape = [4, 4], type = oper, isHerm = True Qobj data = [[ 0.+0.j 0.+0.j 0.+0.j 1.+0.j] [ 0.+0.j 0.+0.j 1.+0.j 0.+0.j] [ 0.+0.j 1.+0.j 0.+0.j 0.+0.j] [ 1.+0.j 0.+0.j 0.+0.j 0.+0.j]] """ if not args: raise TypeError("Requires at least one input argument") if len(args) == 1 and isinstance(args[0], (list, np.ndarray)): # this is the case when tensor is called on the form: # tensor([q1, q2, q3, ...]) qlist = args[0] elif len(args) == 1 and isinstance(args[0], Qobj): # tensor is called with a single Qobj as an argument, do nothing return args[0] else: # this is the case when tensor is called on the form: # tensor(q1, q2, q3, ...) qlist = args if not all([isinstance(q, Qobj) for q in qlist]): # raise error if one of the inputs is not a quantum object raise TypeError("One of inputs is not a quantum object") out = Qobj() if qlist[0].issuper: out.superrep = qlist[0].superrep if not all([q.superrep == out.superrep for q in qlist]): raise TypeError("In tensor products of superroperators, all must" + "have the same representation") out.isherm = True for n, q in enumerate(qlist): if n == 0: out.data = q.data out.dims = q.dims else: out.data = sp.kron(out.data, q.data, format='csr') out.dims = [out.dims[0] + q.dims[0], out.dims[1] + q.dims[1]] out.isherm = out.isherm and q.isherm if not out.isherm: out._isherm = None return out.tidyup() if qutip.settings.auto_tidyup else out
def _steadystate_power(L, ss_args): """ Inverse power method for steady state solving. """ ss_args['info'].pop('weight', None) if settings.debug: logger.debug('Starting iterative inverse-power method solver.') tol = ss_args['tol'] mtol = ss_args['mtol'] if mtol is None: mtol = max(0.1 * tol, 1e-15) maxiter = ss_args['maxiter'] use_solver(assumeSortedIndices=True) rhoss = Qobj() sflag = issuper(L) if sflag: rhoss.dims = L.dims[0] else: rhoss.dims = [L.dims[0], 1] n = L.shape[0] # Build Liouvillian if ss_args['solver'] == 'mkl' and ss_args['method'] == 'power': has_mkl = 1 else: has_mkl = 0 L, perm, perm2, rev_perm, ss_args = _steadystate_power_liouvillian( L, ss_args, has_mkl) orig_nnz = L.nnz # start with all ones as RHS v = np.ones(n, dtype=complex) if ss_args['use_rcm']: v = v[np.ix_(perm2, )] # Do preconditioning if ss_args['solver'] == 'scipy': if ss_args['M'] is None and ss_args['use_precond'] and \ ss_args['method'] in ['power-gmres', 'power-lgmres', 'power-bicgstab']: ss_args['M'], ss_args = _iterative_precondition( L, int(np.sqrt(n)), ss_args) if ss_args['M'] is None: warnings.warn("Preconditioning failed. Continuing without.", UserWarning) ss_iters = {'iter': 0} def _iter_count(r): ss_iters['iter'] += 1 return _power_start = time.time() # Get LU factors if ss_args['method'] == 'power': if ss_args['solver'] == 'mkl': lu = mkl_splu(L, max_iter_refine=ss_args['max_iter_refine'], scaling_vectors=ss_args['scaling_vectors'], weighted_matching=ss_args['weighted_matching']) else: lu = splu(L, permc_spec=ss_args['permc_spec'], diag_pivot_thresh=ss_args['diag_pivot_thresh'], options=dict(ILU_MILU=ss_args['ILU_MILU'])) if settings.debug and _scipy_check: L_nnz = lu.L.nnz U_nnz = lu.U.nnz logger.debug('L NNZ: %i ; U NNZ: %i' % (L_nnz, U_nnz)) logger.debug('Fill factor: %f' % ((L_nnz + U_nnz) / orig_nnz)) it = 0 # FIXME: These atol keyword except checks can be removed once scipy 1.1 # is a minimum requirement while (la.norm(L * v, np.inf) > tol) and (it < maxiter): check = 0 if ss_args['method'] == 'power': v = lu.solve(v) elif ss_args['method'] == 'power-gmres': try: v, check = gmres(L, v, tol=mtol, atol=ss_args['matol'], M=ss_args['M'], x0=ss_args['x0'], restart=ss_args['restart'], maxiter=ss_args['maxiter'], callback=_iter_count) except TypeError as e: if "unexpected keyword argument 'atol'" in str(e): v, check = gmres(L, v, tol=mtol, M=ss_args['M'], x0=ss_args['x0'], restart=ss_args['restart'], maxiter=ss_args['maxiter'], callback=_iter_count) elif ss_args['method'] == 'power-lgmres': try: v, check = lgmres(L, v, tol=mtol, atol=ss_args['matol'], M=ss_args['M'], x0=ss_args['x0'], maxiter=ss_args['maxiter'], callback=_iter_count) except TypeError as e: if "unexpected keyword argument 'atol'" in str(e): v, check = lgmres(L, v, tol=mtol, M=ss_args['M'], x0=ss_args['x0'], maxiter=ss_args['maxiter'], callback=_iter_count) elif ss_args['method'] == 'power-bicgstab': try: v, check = bicgstab(L, v, tol=mtol, atol=ss_args['matol'], M=ss_args['M'], x0=ss_args['x0'], maxiter=ss_args['maxiter'], callback=_iter_count) except TypeError as e: if "unexpected keyword argument 'atol'" in str(e): v, check = bicgstab(L, v, tol=mtol, M=ss_args['M'], x0=ss_args['x0'], maxiter=ss_args['maxiter'], callback=_iter_count) else: raise Exception("Invalid iterative solver method.") if check > 0: raise Exception("{} failed to find solution in " "{} iterations.".format(ss_args['method'], check)) if check < 0: raise Exception("Breakdown in {}".format(ss_args['method'])) v = v / la.norm(v, np.inf) it += 1 if ss_args['method'] == 'power' and ss_args['solver'] == 'mkl': lu.delete() if ss_args['return_info']: ss_args['info']['max_iter_refine'] = ss_args['max_iter_refine'] ss_args['info']['scaling_vectors'] = ss_args['scaling_vectors'] ss_args['info']['weighted_matching'] = ss_args['weighted_matching'] if it >= maxiter: raise Exception('Failed to find steady state after ' + str(maxiter) + ' iterations') _power_end = time.time() ss_args['info']['solution_time'] = _power_end - _power_start ss_args['info']['iterations'] = it if ss_args['return_info']: ss_args['info']['residual_norm'] = la.norm(L * v, np.inf) if settings.debug: logger.debug('Number of iterations: %i' % it) if ss_args['use_rcm']: v = v[np.ix_(rev_perm, )] # normalise according to type of problem if sflag: trow = v[::rhoss.shape[0] + 1] data = v / np.sum(trow) else: data = data / la.norm(v) data = dense2D_to_fastcsr_fmode(vec2mat(data), rhoss.shape[0], rhoss.shape[0]) rhoss.data = 0.5 * (data + data.H) rhoss.isherm = True if ss_args['return_info']: return rhoss, ss_args['info'] else: return rhoss
def floquet_markov_mesolve(R, ekets, rho0, tlist, e_ops, f_modes_table=None, options=None, floquet_basis=True): """ Solve the dynamics for the system using the Floquet-Markov master equation. """ if options is None: opt = Options() else: opt = options if opt.tidy: R.tidyup() # # check initial state # if isket(rho0): # Got a wave function as initial state: convert to density matrix. rho0 = ket2dm(rho0) # # prepare output array # n_tsteps = len(tlist) dt = tlist[1] - tlist[0] output = Result() output.solver = "fmmesolve" output.times = tlist if isinstance(e_ops, FunctionType): n_expt_op = 0 expt_callback = True elif isinstance(e_ops, list): n_expt_op = len(e_ops) expt_callback = False if n_expt_op == 0: output.states = [] else: if not f_modes_table: raise TypeError("The Floquet mode table has to be provided " + "when requesting expectation values.") output.expect = [] output.num_expect = n_expt_op for op in e_ops: if op.isherm: output.expect.append(np.zeros(n_tsteps)) else: output.expect.append(np.zeros(n_tsteps, dtype=complex)) else: raise TypeError("Expectation parameter must be a list or a function") # # transform the initial density matrix to the eigenbasis: from # computational basis to the floquet basis # if ekets is not None: rho0 = rho0.transform(ekets) # # setup integrator # initial_vector = mat2vec(rho0.full()) r = scipy.integrate.ode(cy_ode_rhs) r.set_f_params(R.data.data, R.data.indices, R.data.indptr) r.set_integrator('zvode', method=opt.method, order=opt.order, atol=opt.atol, rtol=opt.rtol, max_step=opt.max_step) r.set_initial_value(initial_vector, tlist[0]) # # start evolution # rho = Qobj(rho0) t_idx = 0 for t in tlist: if not r.successful(): break rho.data = vec2mat(r.y) if expt_callback: # use callback method if floquet_basis: e_ops(t, Qobj(rho)) else: f_modes_table_t, T = f_modes_table f_modes_t = floquet_modes_t_lookup(f_modes_table_t, t, T) e_ops(t, Qobj(rho).transform(f_modes_t, True)) else: # calculate all the expectation values, or output rho if # no operators if n_expt_op == 0: if floquet_basis: output.states.append(Qobj(rho)) else: f_modes_table_t, T = f_modes_table f_modes_t = floquet_modes_t_lookup(f_modes_table_t, t, T) output.states.append(Qobj(rho).transform(f_modes_t, True)) else: f_modes_table_t, T = f_modes_table f_modes_t = floquet_modes_t_lookup(f_modes_table_t, t, T) for m in range(0, n_expt_op): output.expect[m][t_idx] = \ expect(e_ops[m], rho.transform(f_modes_t, False)) r.integrate(r.t + dt) t_idx += 1 return output
def _steadystate_power(L, ss_args): """ Inverse power method for steady state solving. """ ss_args['info'].pop('weight', None) if settings.debug: logger.debug('Starting iterative inverse-power method solver.') tol = ss_args['tol'] maxiter = ss_args['maxiter'] use_solver(assumeSortedIndices=True) rhoss = Qobj() sflag = issuper(L) if sflag: rhoss.dims = L.dims[0] else: rhoss.dims = [L.dims[0], 1] n = L.shape[0] # Build Liouvillian L, perm, perm2, rev_perm, ss_args = _steadystate_power_liouvillian(L, ss_args) orig_nnz = L.nnz # start with all ones as RHS v = np.ones(n, dtype=complex) if ss_args['use_rcm']: v = v[np.ix_(perm2,)] # Do preconditioning if ss_args['M'] is None and ss_args['use_precond'] and \ ss_args['method'] in ['power-gmres', 'power-lgmres', 'power-bicgstab']: ss_args['M'], ss_args = _iterative_precondition(L, int(np.sqrt(n)), ss_args) if ss_args['M'] is None: warnings.warn("Preconditioning failed. Continuing without.", UserWarning) ss_iters = {'iter': 0} def _iter_count(r): ss_iters['iter'] += 1 return _power_start = time.time() # Get LU factors if ss_args['method'] == 'power': lu = splu(L, permc_spec=ss_args['permc_spec'], diag_pivot_thresh=ss_args['diag_pivot_thresh'], options=dict(ILU_MILU=ss_args['ILU_MILU'])) if settings.debug and _scipy_check: L_nnz = lu.L.nnz U_nnz = lu.U.nnz logger.debug('L NNZ: %i ; U NNZ: %i' % (L_nnz, U_nnz)) logger.debug('Fill factor: %f' % ((L_nnz+U_nnz)/orig_nnz)) it = 0 _tol = np.max(ss_args['tol']/10,1e-15) # Should make this user accessible while (la.norm(L * v, np.inf) > tol) and (it < maxiter): if ss_args['method'] == 'power': v = lu.solve(v) elif ss_args['method'] == 'power-gmres': v, check = gmres(L, v, tol=_tol, M=ss_args['M'], x0=ss_args['x0'], restart=ss_args['restart'], maxiter=ss_args['maxiter'], callback=_iter_count) elif ss_args['method'] == 'power-lgmres': v, check = lgmres(L, v, tol=_tol, M=ss_args['M'], x0=ss_args['x0'], maxiter=ss_args['maxiter'], callback=_iter_count) elif ss_args['method'] == 'power-bicgstab': v, check = bicgstab(L, v, tol=_tol, M=ss_args['M'], x0=ss_args['x0'], maxiter=ss_args['maxiter'], callback=_iter_count) else: raise Exception("Invalid iterative solver method.") v = v / la.norm(v, np.inf) it += 1 if it >= maxiter: raise Exception('Failed to find steady state after ' + str(maxiter) + ' iterations') _power_end = time.time() ss_args['info']['solution_time'] = _power_end-_power_start ss_args['info']['iterations'] = it if ss_args['return_info']: ss_args['info']['residual_norm'] = la.norm(L*v) if settings.debug: logger.debug('Number of iterations: %i' % it) if ss_args['use_rcm']: v = v[np.ix_(rev_perm,)] # normalise according to type of problem if sflag: trow = sp.eye(rhoss.shape[0], rhoss.shape[0], format='coo') trow = sp_reshape(trow, (1, n)) data = v / sum(trow.dot(v)) else: data = data / la.norm(v) data = sp.csr_matrix(vec2mat(data)) rhoss.data = 0.5 * (data + data.conj().T) rhoss.isherm = True if ss_args['return_info']: return rhoss, ss_args['info'] else: return rhoss
def generic_ode_solve_checkpoint(r, rho0, tlist, e_ops, opt, progress_bar, save, subdir): """ Internal function for solving ME. Solve an ODE which solver parameters already setup (r). Calculate the required expectation values or invoke callback function at each time step. """ # # prepare output array # n_tsteps = len(tlist) e_sops_data = [] output = Result() output.solver = "mesolve" output.times = tlist if opt.store_states: output.states = [] e_ops_dict = e_ops e_ops = [e for e in e_ops_dict.values()] headings = [key for key in e_ops_dict.keys()] if isinstance(e_ops, types.FunctionType): n_expt_op = 0 expt_callback = True elif isinstance(e_ops, list): n_expt_op = len(e_ops) expt_callback = False if n_expt_op == 0: # fall back on storing states output.states = [] opt.store_states = True else: output.expect = [] output.num_expect = n_expt_op for op in e_ops: e_sops_data.append(spre(op).data) if op.isherm and rho0.isherm: output.expect.append(np.zeros(n_tsteps)) else: output.expect.append(np.zeros(n_tsteps, dtype=complex)) else: raise TypeError("Expectation parameter must be a list or a function") results_row = np.zeros(n_expt_op) # # start evolution # progress_bar.start(n_tsteps) rho = Qobj(rho0) dims = rho.dims dt = np.diff(tlist) end_time = tlist[-1] for t_idx, t in tqdm(enumerate(tlist)): progress_bar.update(t_idx) if not r.successful(): raise Exception("ODE integration error: Try to increase " "the allowed number of substeps by increasing " "the nsteps parameter in the Options class.") if opt.store_states or expt_callback: rho.data = vec2mat(r.y) if opt.store_states: output.states.append(Qobj(rho)) if expt_callback: # use callback method e_ops(t, rho) for m in range(n_expt_op): if output.expect[m].dtype == complex: output.expect[m][t_idx] = expect_rho_vec( e_sops_data[m], r.y, 0) results_row[m] = output.expect[m][t_idx] else: output.expect[m][t_idx] = expect_rho_vec( e_sops_data[m], r.y, 1) results_row[m] = output.expect[m][t_idx] results = pd.DataFrame(results_row).T results.columns = headings results.index = [t] results.index.name = 'times' if t == 0: first_row = True else: first_row = False if save: rho_checkpoint = Qobj(vec2mat(r.y)) rho_checkpoint.dims = dims if t_idx % 200 == 0: rho_c = rho_checkpoint.ptrace(0) with open('./cavity_states.pkl', 'ab') as f: pickle.dump(rho_c, f) with open('./results.csv', 'a') as file: results.to_csv(file, header=first_row, float_format='%.15f') qsave(rho_checkpoint, './state_checkpoint') save = True if t_idx < n_tsteps - 1: r.integrate(r.t + dt[t_idx]) progress_bar.finished() if not opt.rhs_reuse and config.tdname is not None: _cython_build_cleanup(config.tdname) return output
def _generic_ode_solve(r, rho0, tlist, e_ops, opt, progress_bar): """ Internal function for solving ME. Solve an ODE which solver parameters already setup (r). Calculate the required expectation values or invoke callback function at each time step. """ # # prepare output array # n_tsteps = len(tlist) e_sops_data = [] output = Result() output.solver = "mesolve" output.times = tlist if opt.store_states: output.states = [] if isinstance(e_ops, types.FunctionType): n_expt_op = 0 expt_callback = True elif isinstance(e_ops, list): n_expt_op = len(e_ops) expt_callback = False if n_expt_op == 0: # fall back on storing states output.states = [] opt.store_states = True else: output.expect = [] output.num_expect = n_expt_op for op in e_ops: e_sops_data.append(spre(op).data) if op.isherm and rho0.isherm: output.expect.append(np.zeros(n_tsteps)) else: output.expect.append(np.zeros(n_tsteps, dtype=complex)) else: raise TypeError("Expectation parameter must be a list or a function") # # start evolution # progress_bar.start(n_tsteps) rho = Qobj(rho0) dt = np.diff(tlist) for t_idx, t in enumerate(tlist): progress_bar.update(t_idx) if not r.successful(): break if opt.store_states or expt_callback: rho.data = vec2mat(r.y) if opt.store_states: output.states.append(Qobj(rho)) if expt_callback: # use callback method e_ops(t, rho) for m in range(n_expt_op): if output.expect[m].dtype == complex: output.expect[m][t_idx] = expect_rho_vec(e_sops_data[m], r.y, 0) else: output.expect[m][t_idx] = expect_rho_vec(e_sops_data[m], r.y, 1) if t_idx < n_tsteps - 1: r.integrate(r.t + dt[t_idx]) progress_bar.finished() if not opt.rhs_reuse and config.tdname is not None: try: os.remove(config.tdname + ".pyx") except: pass if opt.store_final_state: rho.data = vec2mat(r.y) output.final_state = Qobj(rho) return output
def liouvillian(H, c_ops=[], data_only=False, chi=None): """Assembles the Liouvillian superoperator from a Hamiltonian and a ``list`` of collapse operators. Like liouvillian, but with an experimental implementation which avoids creating extra Qobj instances, which can be advantageous for large systems. Parameters ---------- H : Qobj or QobjEvo System Hamiltonian. c_ops : array_like of Qobj or QobjEvo A ``list`` or ``array`` of collapse operators. Returns ------- L : Qobj or QobjEvo Liouvillian superoperator. """ if isinstance(c_ops, (Qobj, QobjEvo)): c_ops = [c_ops] if chi and len(chi) != len(c_ops): raise ValueError('chi must be a list with same length as c_ops') h = None if H is not None: if isinstance(H, QobjEvo): h = H.cte else: h = H if h.isoper: op_dims = h.dims op_shape = h.shape elif h.issuper: op_dims = h.dims[0] op_shape = [np.prod(op_dims[0]), np.prod(op_dims[0])] else: raise TypeError("Invalid type for Hamiltonian.") else: # no hamiltonian given, pick system size from a collapse operator if isinstance(c_ops, list) and len(c_ops) > 0: if isinstance(c_ops[0], QobjEvo): c = c_ops[0].cte else: c = c_ops[0] if c.isoper: op_dims = c.dims op_shape = c.shape elif c.issuper: op_dims = c.dims[0] op_shape = [np.prod(op_dims[0]), np.prod(op_dims[0])] else: raise TypeError("Invalid type for collapse operator.") else: raise TypeError("Either H or c_ops must be given.") sop_dims = [[op_dims[0], op_dims[0]], [op_dims[1], op_dims[1]]] sop_shape = [np.prod(op_dims), np.prod(op_dims)] spI = fast_identity(op_shape[0]) td = False L = None if isinstance(H, QobjEvo): td = True def H2L(H): if H.isoper: return -1.0j * (spre(H) - spost(H)) else: return H L = H.apply(H2L) data = L.cte.data elif isinstance(H, Qobj): if H.isoper: Ht = H.data.T data = -1j * zcsr_kron(spI, H.data) data += 1j * zcsr_kron(Ht, spI) else: data = H.data else: data = fast_csr_matrix(shape=(sop_shape[0], sop_shape[1])) td_c_ops = [] for idx, c_op in enumerate(c_ops): if isinstance(c_op, QobjEvo): td = True if c_op.const: c_ = c_op.cte elif chi: td_c_ops.append(lindblad_dissipator(c_op, chi=chi[idx])) continue else: td_c_ops.append(lindblad_dissipator(c_op)) continue else: c_ = c_op if c_.issuper: data = data + c_.data else: cd = c_.data.H c = c_.data if chi: data = data + np.exp(1j * chi[idx]) * \ zcsr_kron(c.conj(), c) else: data = data + zcsr_kron(c.conj(), c) cdc = cd * c cdct = cdc.T data = data - 0.5 * zcsr_kron(spI, cdc) data = data - 0.5 * zcsr_kron(cdct, spI) if not td: if data_only: return data else: L = Qobj() L.dims = sop_dims L.data = data L.superrep = 'super' return L else: if not L: l = Qobj() l.dims = sop_dims l.data = data l.superrep = 'super' L = QobjEvo(l) else: L.cte.data = data for c_op in td_c_ops: L += c_op return L
def _generic_ode_solve(r, rho0, tlist, expt_ops, opt, progress_bar): """ Internal function for solving ME. """ # # prepare output array # n_tsteps = len(tlist) dt = tlist[1] - tlist[0] output = Odedata() output.solver = "mesolve" output.times = tlist if opt.store_states: output.states = [] if isinstance(expt_ops, types.FunctionType): n_expt_op = 0 expt_callback = True elif isinstance(expt_ops, list): n_expt_op = len(expt_ops) expt_callback = False if n_expt_op == 0: # fallback on storing states output.states = [] opt.store_states = True else: output.expect = [] output.num_expect = n_expt_op for op in expt_ops: if op.isherm and rho0.isherm: output.expect.append(np.zeros(n_tsteps)) else: output.expect.append(np.zeros(n_tsteps, dtype=complex)) else: raise TypeError("Expectation parameter must be a list or a function") # # start evolution # progress_bar.start(n_tsteps) rho = Qobj(rho0) for t_idx, t in enumerate(tlist): progress_bar.update(t_idx) if not r.successful(): break rho.data = vec2mat(r.y) if opt.store_states: output.states.append(Qobj(rho)) if expt_callback: # use callback method expt_ops(t, Qobj(rho)) for m in range(n_expt_op): output.expect[m][t_idx] = expect(expt_ops[m], rho) r.integrate(r.t + dt) progress_bar.finished() if not opt.rhs_reuse and odeconfig.tdname is not None: try: os.remove(odeconfig.tdname + ".pyx") except: pass if opt.store_final_state: output.final_state = Qobj(rho) return output
def tensor(*args): """Calculates the tensor product of input operators. Parameters ---------- args : array_like ``list`` or ``array`` of quantum objects for tensor product. Returns -------- obj : qobj A composite quantum object. Examples -------- >>> tensor([sigmax(), sigmax()]) Quantum object: dims = [[2, 2], [2, 2]], \ shape = [4, 4], type = oper, isHerm = True Qobj data = [[ 0.+0.j 0.+0.j 0.+0.j 1.+0.j] [ 0.+0.j 0.+0.j 1.+0.j 0.+0.j] [ 0.+0.j 1.+0.j 0.+0.j 0.+0.j] [ 1.+0.j 0.+0.j 0.+0.j 0.+0.j]] """ if not args: raise TypeError("Requires at least one input argument") num_args = len(args) step = 0 for n in range(num_args): if isinstance(args[n], Qobj): qos = args[n] if step == 0: dat = qos.data dim = qos.dims shp = qos.shape step = 1 else: dat = sp.kron(dat, qos.data, format='csr') dim = [dim[0] + qos.dims[0], dim[1] + qos.dims[1]] # append dimensions of Qobjs shp = [dat.shape[0], dat.shape[1]] # new shape of matrix elif isinstance(args[n], (list, ndarray)): qos = args[n] items = len(qos) # number of inputs if not all([isinstance(k, Qobj) for k in qos]): # raise error if one of the inputs is not a quantum object raise TypeError("One of inputs is not a quantum object") if items == 1: # if only one Qobj, do nothing if step == 0: dat = qos[0].data dim = qos[0].dims shp = qos[0].shape step = 1 else: dat = sp.kron(dat, qos[0].data, format='csr') dim = [dim[0] + qos[0].dims[0], dim[1] + qos[0].dims[1]] # append dimensions of qos shp = [dat.shape[0], dat.shape[1]] # new shape of matrix elif items != 1: if step == 0: dat = qos[0].data dim = qos[0].dims shp = qos[0].shape step = 1 for k in range(items - 1): # cycle over all items dat = sp.kron(dat, qos[k + 1].data, format='csr') dim = [ dim[0] + qos[k + 1].dims[0], dim[1] + qos[k + 1].dims[1] ] shp = [dat.shape[0], dat.shape[1]] # new shape of matrix out = Qobj() out.data = dat out.dims = dim out.shape = shp if qutip.settings.auto_tidyup: return Qobj(out).tidyup() # returns tidy Qobj else: return Qobj(out)
def bloch_redfield_solve(R, ekets, rho0, tlist, e_ops=[], options=None): """ Evolve the ODEs defined by Bloch-Redfield master equation. The Bloch-Redfield tensor can be calculated by the function :func:`bloch_redfield_tensor`. Parameters ---------- R : :class:`qutip.qobj` Bloch-Redfield tensor. ekets : array of :class:`qutip.qobj` Array of kets that make up a basis tranformation for the eigenbasis. rho0 : :class:`qutip.qobj` Initial density matrix. tlist : *list* / *array* List of times for :math:`t`. e_ops : list of :class:`qutip.qobj` / callback function List of operators for which to evaluate expectation values. options : :class:`qutip.Qdeoptions` Options for the ODE solver. Returns ------- output: :class:`qutip.odedata` An instance of the class :class:`qutip.odedata`, which contains either an *array* of expectation values for the times specified by `tlist`. """ if options is None: options = Odeoptions() options.nsteps = 2500 if options.tidy: R.tidyup() # # check initial state # if isket(rho0): # Got a wave function as initial state: convert to density matrix. rho0 = rho0 * rho0.dag() # # prepare output array # n_e_ops = len(e_ops) n_tsteps = len(tlist) dt = tlist[1] - tlist[0] if n_e_ops == 0: result_list = [] else: result_list = [] for op in e_ops: if op.isherm and rho0.isherm: result_list.append(np.zeros(n_tsteps)) else: result_list.append(np.zeros(n_tsteps, dtype=complex)) # # transform the initial density matrix and the e_ops opterators to the # eigenbasis # if ekets is not None: rho0 = rho0.transform(ekets) for n in arange(len(e_ops)): e_ops[n] = e_ops[n].transform(ekets, False) # # setup integrator # initial_vector = mat2vec(rho0.full()) r = scipy.integrate.ode(cy_ode_rhs) r.set_f_params(R.data.data, R.data.indices, R.data.indptr) r.set_integrator('zvode', method=options.method, order=options.order, atol=options.atol, rtol=options.rtol, #nsteps=options.nsteps, #first_step=options.first_step, min_step=options.min_step, max_step=options.max_step) r.set_initial_value(initial_vector, tlist[0]) # # start evolution # rho = Qobj(rho0) t_idx = 0 for t in tlist: if not r.successful(): break rho.data = vec2mat(r.y) # calculate all the expectation values, or output rho if no operators if n_e_ops == 0: result_list.append(Qobj(rho)) else: for m in range(0, n_e_ops): result_list[m][t_idx] = expect(e_ops[m], rho) r.integrate(r.t + dt) t_idx += 1 return result_list
def floquet_markov_mesolve(R, ekets, rho0, tlist, e_ops, options=None): """ Solve the dynamics for the system using the Floquet-Markov master equation. """ if options is None: opt = Odeoptions() else: opt = options if opt.tidy: R.tidyup() # # check initial state # if isket(rho0): # Got a wave function as initial state: convert to density matrix. rho0 = ket2dm(rho0) # # prepare output array # n_tsteps = len(tlist) dt = tlist[1] - tlist[0] output = Odedata() output.times = tlist if isinstance(e_ops, FunctionType): n_expt_op = 0 expt_callback = True elif isinstance(e_ops, list): n_expt_op = len(e_ops) expt_callback = False if n_expt_op == 0: output.states = [] else: output.expect = [] output.num_expect = n_expt_op for op in e_ops: if op.isherm: output.expect.append(np.zeros(n_tsteps)) else: output.expect.append(np.zeros(n_tsteps, dtype=complex)) else: raise TypeError("Expectation parameter must be a list or a function") # # transform the initial density matrix and the e_ops opterators to the # eigenbasis: from computational basis to the floquet basis # if ekets is not None: rho0 = rho0.transform(ekets, True) if isinstance(e_ops, list): for n in np.arange(len(e_ops)): # not working e_ops[n] = e_ops[n].transform(ekets) # # setup integrator # initial_vector = mat2vec(rho0.full()) r = scipy.integrate.ode(cyq_ode_rhs) r.set_f_params(R.data.data, R.data.indices, R.data.indptr) r.set_integrator("zvode", method=opt.method, order=opt.order, atol=opt.atol, rtol=opt.rtol, max_step=opt.max_step) r.set_initial_value(initial_vector, tlist[0]) # # start evolution # rho = Qobj(rho0) t_idx = 0 for t in tlist: if not r.successful(): break rho.data = vec2mat(r.y) if expt_callback: # use callback method e_ops(t, Qobj(rho)) else: # calculate all the expectation values, or output rho if # no operators if n_expt_op == 0: output.states.append(Qobj(rho)) # copy psi/rho else: for m in range(0, n_expt_op): output.expect[m][t_idx] = expect(e_ops[m], rho) # basisOK? r.integrate(r.t + dt) t_idx += 1 return output
def liouvillian(H, c_ops=[], data_only=False, chi=None): """Assembles the Liouvillian superoperator from a Hamiltonian and a ``list`` of collapse operators. Like liouvillian, but with an experimental implementation which avoids creating extra Qobj instances, which can be advantageous for large systems. Parameters ---------- H : qobj System Hamiltonian. c_ops : array_like A ``list`` or ``array`` of collapse operators. Returns ------- L : qobj Liouvillian superoperator. """ if chi and len(chi) != len(c_ops): raise ValueError('chi must be a list with same length as c_ops') if H is not None: if H.isoper: op_dims = H.dims op_shape = H.shape elif H.issuper: op_dims = H.dims[0] op_shape = [np.prod(op_dims[0]), np.prod(op_dims[0])] else: raise TypeError("Invalid type for Hamiltonian.") else: # no hamiltonian given, pick system size from a collapse operator if isinstance(c_ops, list) and len(c_ops) > 0: c = c_ops[0] if c.isoper: op_dims = c.dims op_shape = c.shape elif c.issuper: op_dims = c.dims[0] op_shape = [np.prod(op_dims[0]), np.prod(op_dims[0])] else: raise TypeError("Invalid type for collapse operator.") else: raise TypeError("Either H or c_ops must be given.") sop_dims = [[op_dims[0], op_dims[0]], [op_dims[1], op_dims[1]]] sop_shape = [np.prod(op_dims), np.prod(op_dims)] spI = sp.identity(op_shape[0], format='csr') if H: if H.isoper: data = -1j * (sp.kron(spI, H.data, format='csr') - sp.kron(H.data.T, spI, format='csr')) else: data = H.data else: data = sp.csr_matrix((sop_shape[0], sop_shape[1]), dtype=complex) for idx, c_op in enumerate(c_ops): if c_op.issuper: data = data + c_op.data else: cd = c_op.data.T.conj() c = c_op.data if chi: data = data + np.exp(1j * chi[idx]) * sp.kron(cd.T, c, format='csr') else: data = data + sp.kron(cd.T, c, format='csr') cdc = cd * c data = data - 0.5 * sp.kron(spI, cdc, format='csr') data = data - 0.5 * sp.kron(cdc.T, spI, format='csr') if data_only: return data else: L = Qobj() L.dims = sop_dims L.data = data L.isherm = False L.superrep = 'super' return L
def _generic_ode_solve(r, psi0, tlist, expt_ops, opt, state_vectorize, state_norm_func=None): """ Internal function for solving ODEs. """ # # prepare output array # n_tsteps = len(tlist) dt = tlist[1] - tlist[0] output = Odedata() output.solver = "mesolve" output.times = tlist if isinstance(expt_ops, types.FunctionType): n_expt_op = 0 expt_callback = True elif isinstance(expt_ops, list): n_expt_op = len(expt_ops) expt_callback = False if n_expt_op == 0: output.states = [] else: output.expect = [] output.num_expect = n_expt_op for op in expt_ops: if op.isherm and psi0.isherm: output.expect.append(np.zeros(n_tsteps)) else: output.expect.append(np.zeros(n_tsteps, dtype=complex)) else: raise TypeError("Expectation parameter must be a list or a function") # # start evolution # psi = Qobj(psi0) t_idx = 0 for t in tlist: if not r.successful(): break if state_norm_func: psi.data = state_vectorize(r.y) state_norm = state_norm_func(psi.data) psi.data = psi.data / state_norm r.set_initial_value(r.y / state_norm, r.t) else: psi.data = state_vectorize(r.y) if expt_callback: # use callback method expt_ops(t, Qobj(psi)) else: # calculate all the expectation values, # or output rho if no operators if n_expt_op == 0: output.states.append(Qobj(psi)) # copy psi/rho else: for m in range(0, n_expt_op): output.expect[m][t_idx] = expect(expt_ops[m], psi) r.integrate(r.t + dt) t_idx += 1 if not opt.rhs_reuse and odeconfig.tdname is not None: try: os.remove(odeconfig.tdname + ".pyx") except: pass return output