def __call__(self, H, state, dt, c_ops=None, backwards=False, initialize=False): """Evaluation of a single propagation step Args: H (list): A Liouvillian superoperator in qutip's nested-list format, with a scalar value in the place of a time-dependency. For example, ``[L0, [L1, u]]`` for a drift Liouvillian ``L0``, a control Liouvillian ``H1``, and a scalar value ``u`` that is a time-dependent control evaluated for a particular point in time. If `initialize` is False, only the control values are taken into account; any operators are assumed to be identical to the internally cached values of `H` during initialization. state (qutip.Qobj): The density matrix to propagate. The passed value is ignored unless `initialize` is given as True. Otherwise, it is assumed that `state` matches the (internally stored) state that was the result from the previous propagation step. dt (float): The time step over which to propagate c_ops (list or None): An empty list, or None. Since this propagator assumes a full Liouvillian, it cannot be combined with Lindblad operators. backwards (bool): Whether the propagation is forward in time or backward in time. Since the equation of motion for a Liouvillian and conjugate Liouvillian is the same, this parameter has no effect. Instead, for the backward propagation, the conjugate Liouvillian must be passed for `L`. initialize (bool): Whether to (re-)initialize for a new propagation. This caches `H` (except for the control values) and `state` internally. """ # H is really an L, but it's a very bad idea for a subclass not to # follow the interface of the parent (including argument names). # Internally, however, we'll use L instead of H if initialize or self.reentrant: self._initialize(H, state, dt, c_ops, backwards) else: if self.reentrant: self._initialize_integrator(self._y) # only update the control values for i in self._control_indices: self._L_list[i][1] = H[i][1] self._t += dt self._r.integrate(self._t) self._y = self._r.y return qutip.Qobj( dense2D_to_fastcsr_fmode(vec2mat(self._y), state.shape[0], state.shape[1]), dims=state.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 = sp.csgraph.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_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_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 ss_args['solver'] == 'mkl': has_mkl = 1 else: has_mkl = 0 ss_lu_liouv_list = _steadystate_LU_liouvillian(L, ss_args, has_mkl) L, perm, perm2, rev_perm, ss_args = ss_lu_liouv_list if np.any(perm): b = b[np.ix_(perm, )] if np.any(perm2): b = b[np.ix_(perm2, )] if ss_args['solver'] == 'scipy': 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 ss_args['solver'] == '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'], max_iter_refine=ss_args['max_iter_refine'], scaling_vectors=ss_args['scaling_vectors'], weighted_matching=ss_args['weighted_matching']) _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) 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 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(func, ode_args, rho0, tlist, e_ops, opt, progress_bar, dims=None): """ Internal function for solving ME. Calculate the required expectation values or invoke callback function at each time step. """ # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # This function is made similar to sesolve's one for futur merging in a # solver class # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # prepare output array n_tsteps = len(tlist) output = Result() output.solver = "mesolve" output.times = tlist size = rho0.shape[0] initial_vector = rho0.full().ravel('F') r = scipy.integrate.ode(func) r.set_integrator('zvode', method=opt.method, order=opt.order, atol=opt.atol, rtol=opt.rtol, nsteps=opt.nsteps, first_step=opt.first_step, min_step=opt.min_step, max_step=opt.max_step) if ode_args: r.set_f_params(*ode_args) r.set_initial_value(initial_vector, tlist[0]) e_ops_data = [] output.expect = [] if callable(e_ops): n_expt_op = 0 expt_callback = True output.num_expect = 1 elif isinstance(e_ops, list): n_expt_op = len(e_ops) expt_callback = False output.num_expect = n_expt_op if n_expt_op == 0: # fall back on storing states opt.store_states = True else: for op in e_ops: if not isinstance(op, Qobj) and callable(op): output.expect.append(np.zeros(n_tsteps, dtype=complex)) continue if op.dims != rho0.dims: raise TypeError(f"e_ops dims ({op.dims}) are not " f"compatible with the state's " f"({rho0.dims})") e_ops_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") if opt.store_states: output.states = [] def get_curr_state_data(r): return vec2mat(r.y) # # start evolution # dt = np.diff(tlist) cdata = None progress_bar.start(n_tsteps) 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: cdata = get_curr_state_data(r) fdata = dense2D_to_fastcsr_fmode(cdata, size, size) # Try to guess if there is a fast path for rho_t if issuper(rho0) or not rho0.isherm: rho_t = Qobj(fdata, dims=dims) else: rho_t = Qobj(fdata, dims=dims, fast="mc-dm") if opt.store_states: output.states.append(rho_t) if expt_callback: # use callback method output.expect.append(e_ops(t, rho_t)) for m in range(n_expt_op): if not isinstance(e_ops[m], Qobj) and callable(e_ops[m]): output.expect[m][t_idx] = e_ops[m](t, rho_t) continue output.expect[m][t_idx] = expect_rho_vec( e_ops_data[m], r.y, e_ops[m].isherm and rho0.isherm) if t_idx < n_tsteps - 1: r.integrate(r.t + dt[t_idx]) progress_bar.finished() if opt.store_final_state: cdata = get_curr_state_data(r) output.final_state = Qobj(cdata, dims=dims, isherm=rho0.isherm or None) return output
def _td_brmesolve(H, psi0, tlist, a_ops=[], e_ops=[], c_ops=[], use_secular=True, tol=qset.atol, options=None, progress_bar=None, _safe_mode=True): 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 = [] C_obj = [] spline_count = [0, 0] 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 specifiction.') 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): C_obj.append(c[1].coeffs) spline_count[0] += 1 C_td_terms.append(c[1]) else: raise Exception('Invalid collape operator specifiction.') for kk, a in enumerate(a_ops): if isinstance(a, list): 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 else: raise Exception('Invalid bath-coupling specifiction.') 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(C_obj): string_list.append("C_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') parameter_string = ",".join(string_list) # # 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 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=C_obj, a_terms=len(A_terms), a_td_terms=A_td_terms, spline_count=spline_count, config=config, sparse=False, use_secular=use_secular, 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 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 # 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 (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 bloch_redfield_solve(R, ekets, rho0, tlist, e_ops=[], options=None, progress_bar=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.solver` An instance of the class :class:`qutip.solver`, which contains either an *array* of expectation values for the times specified by `tlist`. """ if options is None: options = Options() if options.tidy: R.tidyup() if progress_bar is None: progress_bar = BaseProgressBar() elif progress_bar is True: progress_bar = TextProgressBar() # # 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_tsteps = len(tlist) dt = tlist[1] - tlist[0] result_list = [] # # transform the initial density matrix and the e_ops opterators to the # eigenbasis # rho_eb = rho0.transform(ekets) e_eb_ops = [e.transform(ekets) for e in e_ops] for e_eb in e_eb_ops: if e_eb.isherm: result_list.append(np.zeros(n_tsteps, dtype=float)) else: result_list.append(np.zeros(n_tsteps, dtype=complex)) # # setup integrator # initial_vector = mat2vec(rho_eb.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 # dt = np.diff(tlist) progress_bar.start(n_tsteps) for t_idx, _ in enumerate(tlist): progress_bar.update(t_idx) if not r.successful(): break rho_eb.data = dense2D_to_fastcsr_fmode(vec2mat(r.y), rho0.shape[0], rho0.shape[1]) # calculate all the expectation values, or output rho_eb if no # expectation value operators are given if e_ops: rho_eb_tmp = Qobj(rho_eb) for m, e in enumerate(e_eb_ops): result_list[m][t_idx] = expect(e, rho_eb_tmp) else: result_list.append(rho_eb.transform(ekets, True)) if t_idx < n_tsteps - 1: r.integrate(r.t + dt[t_idx]) progress_bar.finished() return result_list
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(func, ode_args, psi0, tlist, e_ops, opt, progress_bar, dims=None): """ Internal function for solving ODEs. """ # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # This function is made similar to mesolve's one for futur merging in a # solver class # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # prepare output array n_tsteps = len(tlist) output = Result() output.solver = "sesolve" output.times = tlist if psi0.isunitary: initial_vector = psi0.full().ravel('F') oper_evo = True size = psi0.shape[0] # oper_n = dims[0][0] # norm_dim_factor = np.sqrt(oper_n) elif psi0.isket: initial_vector = psi0.full().ravel() oper_evo = False # norm_dim_factor = 1.0 r = scipy.integrate.ode(func) r.set_integrator('zvode', method=opt.method, order=opt.order, atol=opt.atol, rtol=opt.rtol, nsteps=opt.nsteps, first_step=opt.first_step, min_step=opt.min_step, max_step=opt.max_step) if ode_args: r.set_f_params(*ode_args) r.set_initial_value(initial_vector, tlist[0]) e_ops_data = [] output.expect = [] if callable(e_ops): n_expt_op = 0 expt_callback = True output.num_expect = 1 elif isinstance(e_ops, list): n_expt_op = len(e_ops) expt_callback = False output.num_expect = n_expt_op if n_expt_op == 0: # fallback on storing states opt.store_states = True else: for op in e_ops: if not isinstance(op, Qobj) and callable(op): output.expect.append(np.zeros(n_tsteps, dtype=complex)) continue if op.isherm: output.expect.append(np.zeros(n_tsteps)) else: output.expect.append(np.zeros(n_tsteps, dtype=complex)) if oper_evo: for e in e_ops: if isinstance(e, Qobj): e_ops_data.append(e.dag().data) continue e_ops_data.append(e) else: for e in e_ops: if isinstance(e, Qobj): e_ops_data.append(e.data) continue e_ops_data.append(e) else: raise TypeError("Expectation parameter must be a list or a function") if opt.store_states: output.states = [] if oper_evo: def get_curr_state_data(r): return vec2mat(r.y) else: def get_curr_state_data(r): return r.y # # start evolution # dt = np.diff(tlist) cdata = None progress_bar.start(n_tsteps) 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.") # get the current state / oper data if needed if opt.store_states or opt.normalize_output \ or n_expt_op > 0 or expt_callback: cdata = get_curr_state_data(r) if opt.normalize_output: # normalize per column if oper_evo: cdata /= la_norm(cdata, axis=0) #cdata *= norm_dim_factor / la_norm(cdata) r.set_initial_value(cdata.ravel('F'), r.t) else: #cdata /= la_norm(cdata) norm = normalize_inplace(cdata) if norm > 1e-12: # only reset the solver if state changed r.set_initial_value(cdata, r.t) else: r._y = cdata if opt.store_states: if oper_evo: fdata = dense2D_to_fastcsr_fmode(cdata, size, size) output.states.append(Qobj(fdata, dims=dims)) else: fdata = dense1D_to_fastcsr_ket(cdata) output.states.append(Qobj(fdata, dims=dims, fast='mc')) if expt_callback: # use callback method output.expect.append(e_ops(t, Qobj(cdata, dims=dims))) if oper_evo: for m in range(n_expt_op): if callable(e_ops_data[m]): func = e_ops_data[m] output.expect[m][t_idx] = func(t, Qobj(cdata, dims=dims)) continue output.expect[m][t_idx] = (e_ops_data[m] * cdata).trace() else: for m in range(n_expt_op): if callable(e_ops_data[m]): func = e_ops_data[m] output.expect[m][t_idx] = func(t, Qobj(cdata, dims=dims)) continue output.expect[m][t_idx] = cy_expect_psi(e_ops_data[m], cdata, e_ops[m].isherm) if t_idx < n_tsteps - 1: r.integrate(r.t + dt[t_idx]) progress_bar.finished() if opt.store_final_state: cdata = get_curr_state_data(r) if opt.normalize_output: cdata /= la_norm(cdata, axis=0) # cdata *= norm_dim_factor / la_norm(cdata) output.final_state = Qobj(cdata, dims=dims) return output
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_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 ss_args['solver'] == 'mkl': has_mkl = 1 else: has_mkl = 0 ss_lu_liouv_list = _steadystate_LU_liouvillian(L, ss_args, has_mkl) L, perm, perm2, rev_perm, ss_args = ss_lu_liouv_list if np.any(perm): b = b[np.ix_(perm,)] if np.any(perm2): b = b[np.ix_(perm2,)] if ss_args['solver'] == 'scipy': 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 ss_args['solver'] == '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'], max_iter_refine=ss_args['max_iter_refine'], scaling_vectors=ss_args['scaling_vectors'], weighted_matching=ss_args['weighted_matching']) _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) 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 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 liouvillian_sim_alt(job_index, output_directory='./results', eigenvalue=None, eigenstate=None, eliminated=False, transmon=True): default_eigenvalue = 0 if eigenvalue is None: eigenvalue = default_eigenvalue with open('stack.csv', 'r') as f: header = f.readline() stack_name = header.split('\n')[0] stack_frame = pd.read_csv(f) stack_directory = output_directory kappa_phi = 0.0 sys_params = stack_frame.iloc[job_index] frame_params = sys_params print(stack_directory) directory = stack_directory + '/' + sys_params.group_folder + '/' + str( sys_params.job_index) if not os.path.exists(directory): os.makedirs(directory) cwd = os.getcwd() os.chdir(directory) print(directory) sys_params.to_csv('settings.csv') if not eliminated: if transmon is True: packaged_params = Parameters( frame_params.fc, frame_params.Ej, frame_params.g, frame_params.Ec, frame_params.eps, frame_params.fd, frame_params.kappa, frame_params.gamma, frame_params.t_levels, frame_params.c_levels, frame_params.gamma_phi, kappa_phi, frame_params.n_t, frame_params.n_c) H = hamiltonian(packaged_params, transmon=transmon) c_ops = collapse_operators(packaged_params) else: packaged_params = Parameters( frame_params.fc, None, frame_params.g, None, frame_params.eps, frame_params.fd, frame_params.kappa, frame_params.gamma, frame_params.t_levels, frame_params.c_levels, frame_params.gamma_phi, kappa_phi, frame_params.n_t, frame_params.n_c, frame_params.f01) H = hamiltonian(packaged_params, transmon=transmon) c_ops = collapse_operators(packaged_params) else: packaged_params = Parameters( frame_params.fc, None, frame_params.g, None, frame_params.eps, frame_params.fd, frame_params.kappa, frame_params.gamma, frame_params.t_levels, frame_params.c_levels, frame_params.gamma_phi, kappa_phi, frame_params.n_t, frame_params.n_c, frame_params.f01, frame_params.chi) eliminated_params = eliminate(packaged_params) H = hamiltonian_eliminated(eliminated_params) c_ops = collapse_operators(eliminated_params) L = liouvillian(H, c_ops) data = L.data csc = data.tocsc() if eigenstate is not None: if csc.shape[0] != eigenstate.shape[0]: eigenstate = None eigenvalue = default_eigenvalue k = 10 eigvalues, states = lin.eigs(csc, k=k, sigma=eigenvalue, v0=eigenstate) sort_indices = np.argsort(np.abs(eigvalues)) eigvalues = eigvalues[sort_indices] states = states[:, sort_indices] values = pd.DataFrame(eigvalues) values.columns = ['eigenvalues'] states = pd.DataFrame(states) values.to_csv('eigenvalues.csv', index=False) attempts = 0 written = False while not written and attempts < 3: try: states.iloc[:, 0:3].to_hdf('states.h5', 'states', mode='w') trial_opening = pd.read_hdf('states.h5') written = True except: attempts += 1 print('failed to open') if not written: states.iloc[:, 0:3].to_csv('states.csv') mask = np.abs(values) > 1e-10 mask = mask.values[:, 0] pruned_values = values.iloc[mask] chosen_index = pruned_values.index[np.argmin(np.abs(pruned_values).values)] tuples = [] arrays = [] for i in range(k): indices = list(frame_params.values) indices.append(i) tuples.append(tuple(indices)) arrays.append(indices) names = list(frame_params.index) names.append('index') mi = pd.MultiIndex.from_tuples(tuples, names=names) os.chdir(stack_directory) n = packaged_params.t_levels * packaged_params.c_levels dims = [packaged_params.c_levels, packaged_params.t_levels] ground_state_vector = states.values[:, 0] data = dense2D_to_fastcsr_fmode( np.asfortranarray(vec2mat(ground_state_vector)), n, n) rho = Qobj(data, dims=[dims, dims], isherm=True) rho = rho + rho.dag() rho /= rho.tr() a = tensor(destroy(packaged_params.c_levels), qeye(packaged_params.t_levels)) b = tensor(qeye(packaged_params.c_levels), destroy(packaged_params.t_levels)) dims = a.dims a_exp_point = expect(a, rho) b_exp_point = expect(b, rho) num_op_a = a.dag() * a num_op_a.dims = dims num_op_b = b.dag() * b num_op_b.dims = dims n_a_exp_point = expect(num_op_a, rho) n_b_exp_point = expect(num_op_b, rho) a_exp_point = pd.DataFrame([a_exp_point], index=mi[0:1]) b_exp_point = pd.DataFrame([b_exp_point], index=mi[0:1]) n_a_exp_point = pd.DataFrame([n_a_exp_point], index=mi[0:1]) n_b_exp_point = pd.DataFrame([n_b_exp_point], index=mi[0:1]) values_frame = pd.DataFrame([eigvalues], index=mi[0:1]) hdf_append('results.h5', a_exp_point, 'a') hdf_append('results.h5', b_exp_point, 'b') hdf_append('results.h5', n_a_exp_point, 'n_a') hdf_append('results.h5', n_b_exp_point, 'n_b') hdf_append('results.h5', values_frame, 'eigenvalues') os.chdir(cwd) return values.values[chosen_index, 0], states.values[:, chosen_index]
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 steady_state(self, use_mkl=True, mkl_max_iter_refine=100, mkl_weighted_matching=False): """ Compute the steady state of the system. Parameters ---------- use_mkl : bool, default=False Whether to use mkl or not. If mkl is not installed or if this is false, use the scipy splu solver instead. mkl_max_iter_refine : int Specifies the the maximum number of iterative refinement steps that the MKL PARDISO solver performs. For a complete description, see iparm(8) in http://cali2.unilim.fr/intel-xe/mkl/mklman/GUID-264E311E-ACED-4D56-AC31-E9D3B11D1CBF.htm. mkl_weighted_matching : bool MKL PARDISO can use a maximum weighted matching algorithm to permute large elements close the diagonal. This strategy adds an additional level of reliability to the factorization methods. For a complete description, see iparm(13) in http://cali2.unilim.fr/intel-xe/mkl/mklman/GUID-264E311E-ACED-4D56-AC31-E9D3B11D1CBF.htm. Returns ------- steady_state : Qobj The steady state density matrix of the system. steady_ados : :class:`HierarchyADOsState` The steady state of the full ADO hierarchy. A particular ADO may be extracted from the full state by calling :meth:`.extract`. """ n = self._sys_shape b_mat = np.zeros(n**2 * self._n_ados, dtype=complex) b_mat[0] = 1.0 L = deepcopy(self.RHSmat) L = L.tolil() L[0, 0:n**2 * self._n_ados] = 0.0 L = L.tocsr() L += sp.csr_matrix( (np.ones(n), (np.zeros(n), [num * (n + 1) for num in range(n)])), shape=(n**2 * self._n_ados, n**2 * self._n_ados)) if mkl_spsolve is not None and use_mkl: L.sort_indices() solution = mkl_spsolve( L, b_mat, perm=None, verbose=False, max_iter_refine=mkl_max_iter_refine, scaling_vectors=True, weighted_matching=mkl_weighted_matching, ) else: L = L.tocsc() solution = spsolve(L, b_mat) data = dense2D_to_fastcsr_fmode(vec2mat(solution[:n**2]), n, n) data = 0.5 * (data + data.H) steady_state = Qobj(data, dims=self._sys_dims) solution = solution.reshape((self._n_ados, n, n)) steady_ados = HierarchyADOsState(steady_state, self.ados, solution) return steady_state, steady_ados
def steady_state(self, max_iter_refine = 100, use_mkl = False, weighted_matching = False, series_method = False): """ Computes steady state dynamics max_iter_refine : Int Parameter for the mkl LU solver. If pardiso errors are returned this should be increased. use_mkl : Boolean Optional override default use of mkl if mkl is installed. weighted_matching : Boolean Setting this true may increase run time, but reduce stability (pardisio may not converge). """ nstates = self._N_he sup_dim = self._sup_dim n = int(np.sqrt(sup_dim)) unit_h_elems = sp.identity(nstates, format='csr') L = deepcopy(self.RHSmat)# + sp.kron(unit_h_elems, #liouvillian(H).data) b_mat = np.zeros(sup_dim*nstates, dtype=complex) b_mat[0] = 1. L = L.tolil() L[0, 0 : n**2*nstates] = 0. L = L.tocsr() if settings.has_mkl & use_mkl == True: print("Using Intel mkl solver") from qutip._mkl.spsolve import (mkl_splu, mkl_spsolve) L = L.tocsr() + \ sp.csr_matrix((np.ones(n), (np.zeros(n), [num*(n+1)for num in range(n)])), shape=(n**2*nstates, n**2*nstates)) L.sort_indices() solution = mkl_spsolve(L, b_mat, perm = None, verbose = True, \ max_iter_refine = max_iter_refine, \ scaling_vectors = True, \ weighted_matching = weighted_matching) else: if series_method == False: L = L.tocsc() + \ sp.csc_matrix((np.ones(n), (np.zeros(n), [num*(n+1)for num in range(n)])), shape=(n**2*nstates, n**2*nstates)) # Use superLU solver LU = splu(L) solution = LU.solve(b_mat) else: L = L.tocsc() + \ sp.csc_matrix((np.ones(n), (np.zeros(n), [num*(n+1)for num in range(n)])), shape=(n**2*nstates, n**2*nstates)) # Use series method L.sort_indices() solution,fidelity = lgmres(L, b_mat) dims = self.H_sys.dims data = dense2D_to_fastcsr_fmode(vec2mat(solution[:sup_dim]), n, n) data = 0.5*(data + data.H) solution = solution.reshape((nstates, self.H_sys.shape[0]**2)) return Qobj(data, dims=dims), solution