def _steadystate_svd_dense(L, ss_args): """ Find the steady state(s) of an open quantum system by solving for the nullspace of the Liouvillian. """ ss_args['info'].pop('weight', None) atol = 1e-12 rtol = 1e-12 if settings.debug: logger.debug('Starting SVD solver.') _svd_start = time.time() u, s, vh = svd(L.full(), full_matrices=False) tol = max(atol, rtol * s[0]) nnz = (s >= tol).sum() ns = vh[nnz:].conj().T _svd_end = time.time() ss_args['info']['solution_time'] = _svd_end - _svd_start if ss_args['all_states']: rhoss_list = [] for n in range(ns.shape[1]): rhoss = Qobj(vec2mat(ns[:, n]), dims=L.dims[0]) rhoss_list.append(rhoss / rhoss.tr()) if ss_args['return_info']: return rhoss_list, ss_args['info'] else: if ss_args['return_info']: return rhoss_list, ss_args['info'] else: return rhoss_list else: rhoss = Qobj(vec2mat(ns[:, 0]), dims=L.dims[0]) return rhoss / rhoss.tr()
def _steadystate_direct_dense(L, ss_args): """ Direct solver that use numpy dense matrices. Suitable for small system, with a few states. """ if settings.debug: logger.debug('Starting direct dense solver.') dims = L.dims[0] n = int(np.sqrt(L.shape[0])) b = np.zeros(n ** 2) b[0] = ss_args['weight'] L = L.data.todense() L[0, :] = np.diag(ss_args['weight'] * np.ones(n)).reshape((1, n ** 2)) _dense_start = time.time() v = np.linalg.solve(L, b) _dense_end = time.time() ss_args['info']['solution_time'] = _dense_end - _dense_start if ss_args['return_info']: ss_args['info']['residual_norm'] = la.norm(b - L * v, np.inf) data = vec2mat(v) data = 0.5 * (data + data.conj().T) return Qobj(data, dims=dims, isherm=True)
def _steadystate_eigen(L, ss_args): """ Internal function for solving the steady state problem by finding the eigenvector corresponding to the zero eigenvalue of the Liouvillian using ARPACK. """ ss_args['info'].pop('weight', None) if settings.debug: logger.debug('Starting Eigen solver.') dims = L.dims[0] L = L.data.tocsc() if ss_args['use_rcm']: ss_args['info']['perm'].append('rcm') if settings.debug: old_band = sp_bandwidth(L)[0] logger.debug('Original bandwidth: %i' % old_band) perm = reverse_cuthill_mckee(L) rev_perm = np.argsort(perm) L = sp_permute(L, perm, perm, 'csc') if settings.debug: rcm_band = sp_bandwidth(L)[0] logger.debug('RCM bandwidth: %i' % rcm_band) logger.debug('Bandwidth reduction factor: %f' % (old_band / rcm_band)) _eigen_start = time.time() eigval, eigvec = eigs(L, k=1, sigma=1e-15, tol=ss_args['tol'], which='LM', maxiter=ss_args['maxiter']) _eigen_end = time.time() ss_args['info']['solution_time'] = _eigen_end - _eigen_start if ss_args['return_info']: ss_args['info']['residual_norm'] = la.norm(L * eigvec, np.inf) if ss_args['use_rcm']: eigvec = eigvec[np.ix_(rev_perm,)] _temp = vec2mat(eigvec) data = dense2D_to_fastcsr_fmode(_temp, _temp.shape[0], _temp.shape[1]) data = 0.5 * (data + data.H) out = Qobj(data, dims=dims, isherm=True) if ss_args['return_info']: return out / out.tr(), ss_args['info'] else: return out / out.tr()
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, 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_iterative(L, ss_args): """ Iterative steady state solver using the GMRES, LGMRES, or BICGSTAB algorithm and a sparse incomplete LU preconditioner. """ ss_iters = {'iter': 0} def _iter_count(r): ss_iters['iter'] += 1 return if settings.debug: logger.debug('Starting %s solver.' % ss_args['method']) dims = L.dims[0] n = int(np.sqrt(L.shape[0])) b = np.zeros(n ** 2) b[0] = ss_args['weight'] L, perm, perm2, rev_perm, ss_args = _steadystate_LU_liouvillian(L, ss_args) if np.any(perm): b = b[np.ix_(perm,)] if np.any(perm2): b = b[np.ix_(perm2,)] use_solver(assumeSortedIndices=True) if ss_args['M'] is None and ss_args['use_precond']: ss_args['M'], ss_args = _iterative_precondition(L, n, ss_args) if ss_args['M'] is None: warnings.warn("Preconditioning failed. Continuing without.", UserWarning) # Select iterative solver type _iter_start = time.time() if ss_args['method'] == 'iterative-gmres': v, check = gmres(L, b, tol=ss_args['tol'], M=ss_args['M'], x0=ss_args['x0'], restart=ss_args['restart'], maxiter=ss_args['maxiter'], callback=_iter_count) elif ss_args['method'] == 'iterative-lgmres': v, check = lgmres(L, b, tol=ss_args['tol'], M=ss_args['M'], x0=ss_args['x0'], maxiter=ss_args['maxiter'], callback=_iter_count) elif ss_args['method'] == 'iterative-bicgstab': v, check = bicgstab(L, b, tol=ss_args['tol'], M=ss_args['M'], x0=ss_args['x0'], maxiter=ss_args['maxiter'], callback=_iter_count) else: raise Exception("Invalid iterative solver method.") _iter_end = time.time() ss_args['info']['iter_time'] = _iter_end - _iter_start if ss_args['info']['precond_time'] is not None: ss_args['info']['solution_time'] = (ss_args['info']['iter_time'] + ss_args['info']['precond_time']) else: ss_args['info']['solution_time'] = ss_args['info']['iter_time'] ss_args['info']['iterations'] = ss_iters['iter'] if ss_args['return_info']: ss_args['info']['residual_norm'] = la.norm(b - L * v, np.inf) if settings.debug: logger.debug('Number of Iterations: %i' % ss_iters['iter']) logger.debug('Iteration. time: %f' % (_iter_end - _iter_start)) if check > 0: raise Exception("Steadystate error: Did not reach tolerance after " + str(ss_args['maxiter']) + " steps." + "\nResidual norm: " + str(ss_args['info']['residual_norm'])) elif check < 0: raise Exception( "Steadystate error: Failed with fatal error: " + str(check) + ".") if ss_args['use_rcm']: v = v[np.ix_(rev_perm,)] data = vec2mat(v) data = 0.5 * (data + data.conj().T) if ss_args['return_info']: return Qobj(data, dims=dims, isherm=True), ss_args['info'] else: return Qobj(data, dims=dims, isherm=True)
def _steadystate_direct_sparse(L, ss_args): """ Direct solver that uses scipy sparse matrices """ if settings.debug: logger.debug('Starting direct LU solver.') dims = L.dims[0] n = int(np.sqrt(L.shape[0])) b = np.zeros(n ** 2, dtype=complex) b[0] = ss_args['weight'] if settings.has_mkl: has_mkl = 1 else: has_mkl = 0 L, perm, perm2, rev_perm, ss_args = _steadystate_LU_liouvillian( L, ss_args, has_mkl) if np.any(perm): b = b[np.ix_(perm,)] if np.any(perm2): b = b[np.ix_(perm2,)] ss_args['info']['permc_spec'] = ss_args['permc_spec'] ss_args['info']['drop_tol'] = ss_args['drop_tol'] ss_args['info']['diag_pivot_thresh'] = ss_args['diag_pivot_thresh'] ss_args['info']['fill_factor'] = ss_args['fill_factor'] ss_args['info']['ILU_MILU'] = ss_args['ILU_MILU'] if not has_mkl: # Use superLU solver orig_nnz = L.nnz _direct_start = time.time() 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'])) v = lu.solve(b) _direct_end = time.time() ss_args['info']['solution_time'] = _direct_end - _direct_start if (settings.debug or ss_args['return_info']) and _scipy_check: L_nnz = lu.L.nnz U_nnz = lu.U.nnz ss_args['info']['l_nnz'] = L_nnz ss_args['info']['u_nnz'] = U_nnz ss_args['info']['lu_fill_factor'] = (L_nnz + U_nnz) / L.nnz if settings.debug: logger.debug('L NNZ: %i ; U NNZ: %i' % (L_nnz, U_nnz)) logger.debug('Fill factor: %f' % ((L_nnz + U_nnz) / orig_nnz)) else: # Use MKL solver if len(ss_args['info']['perm']) != 0: in_perm = np.arange(n**2, dtype=np.int32) else: in_perm = None _direct_start = time.time() v = mkl_spsolve(L, b, perm=in_perm, verbose=ss_args['verbose']) _direct_end = time.time() ss_args['info']['solution_time'] = _direct_end - _direct_start if ss_args['return_info']: ss_args['info']['residual_norm'] = la.norm(b - L * v, np.inf) if ss_args['use_rcm']: v = v[np.ix_(rev_perm,)] data = dense2D_to_fastcsr_fmode(vec2mat(v), n, n) data = 0.5 * (data + data.H) if ss_args['return_info']: return Qobj(data, dims=dims, isherm=True), ss_args['info'] else: return Qobj(data, dims=dims, isherm=True)
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 _ode_super_func(t, y, data): ym = vec2mat(y) return (data*ym).ravel('F')