def _mesolve_QobjEvo(H, c_ops, tlist, args, opt): """ Prepare the system for the solver, H can be an QobjEvo. """ H_td = QobjEvo(H, args, tlist=tlist) if not issuper(H_td.cte): L_td = liouvillian(H_td) else: L_td = H_td for op in c_ops: op_td = QobjEvo(op, args, tlist=tlist) if not issuper(op_td.cte): op_td = lindblad_dissipator(op_td) L_td += op_td if opt.rhs_with_state: L_td._check_old_with_state() nthread = opt.openmp_threads if opt.use_openmp else 0 L_td.compile(omp=nthread) ss = SolverSystem() ss.H = L_td ss.makefunc = _qobjevo_set solver_safe["mesolve"] = ss return ss
def _generate_A_ops_Euler(sc, L, dt): """ combine precomputed operators in one long operator for the Euler method """ A_len = len(sc) out = [] out += [spre(c).data + spost(c.dag()).data for c in sc] out += [(L + np.sum([lindblad_dissipator(c, data_only=True) for c in sc], axis=0))*dt] out1 = [[sp.vstack(out).tocsr(), sc[0].shape[0]]] #the following hack is required for compatibility with old A_ops out1 += [[] for n in xrange(A_len-1)] return out1
def test_lindblad_dissipator_td(self): "Superoperator: lindblad_dissipator, time-dependent" assert_(lindblad_dissipator(self.t2)(.5) == lindblad_dissipator(self.t2(.5))) assert_(lindblad_dissipator(self.t2, self.q1)(.5) == lindblad_dissipator(self.t2(.5), self.q1)) assert_(lindblad_dissipator(self.q1, self.t2)(.5) == lindblad_dissipator(self.q1, self.t2(.5)))
def _generate_rho_A_ops(sc, L, dt): """ pre-compute superoperator operator combinations that are commonly needed when evaluating the RHS of stochastic master equations """ out = [] for c_idx, c in enumerate(sc): n = c.dag() * c out.append([spre(c).data, spost(c).data, spre(c.dag()).data, spost(c.dag()).data, spre(n).data, spost(n).data, (spre(c) * spost(c.dag())).data, lindblad_dissipator(c, data_only=True)]) return out
def _generate_A_ops_Milstein(sc, L, dt): """ combine precomputed operators in one long operator for the Milstein method with commuting stochastic jump operators. """ A_len = len(sc) temp = [spre(c).data + spost(c.dag()).data for c in sc] out = [] out += temp out += [temp[n]*temp[n] for n in xrange(A_len)] out += [temp[n]*temp[m] for (n,m) in np.ndindex(A_len,A_len) if n > m] out += [(L + np.sum([lindblad_dissipator(c, data_only=True) for c in sc], axis=0))*dt] out1 = [[sp.vstack(out).tocsr(), sc[0].shape[0]]] #the following hack is required for compatibility with old A_ops out1 += [[] for n in xrange(A_len-1)] return out1
def _mesolve_func_td(L_func, c_op_list, rho0, tlist, args, opt): """ Evolve the density matrix using an ODE solver with time dependent Hamiltonian. """ if type(c_op_list) is list: c_ops = [] for op in c_op_list: op_td = QobjEvo(op, args, tlist=tlist, copy=False) if not issuper(op_td.cte): c_ops += [lindblad_dissipator(op_td)] else: c_ops += [op_td] if c_op_list: c_ops_ = [sum(c_ops)] else: c_ops_ = [] elif callable(c_op_list): c_ops_ = c_op_list if opt.rhs_with_state: state0 = rho0.full().ravel("F") obj = L_func(0., state0, args) if not issuper(obj): L_func = _LiouvillianFromFunc(L_func, c_ops_).H2L_with_state else: L_func = _LiouvillianFromFunc(L_func, c_ops_).L_with_state else: obj = L_func(0., args) if callable(c_ops_): if not issuper(obj): L_func = _LiouvillianFromFunc(L_func, c_ops_).H2L_c else: L_func = _LiouvillianFromFunc(L_func, c_ops_).L_c else: if not issuper(obj): L_func = _LiouvillianFromFunc(L_func, c_ops_).H2L else: L_func = _LiouvillianFromFunc(L_func, c_ops_).L ss = SolverSystem() ss.L = L_func ss.makefunc = _Lfunc_set solver_safe["mesolve"] = ss return ss
def _mesolve_func_td(L_func, c_op_list, rho0, tlist, args, opt): """ Evolve the density matrix using an ODE solver with time dependent Hamiltonian. """ c_ops = [] for op in c_op_list: td = QobjEvo(op, args, tlist=tlist, copy=False) c_ops.append(td if td.cte.issuper else lindblad_dissipator(td)) c_ops_ = [sum(c_ops)] if c_op_list else [] L_api = _LiouvillianFromFunc(L_func, c_ops_, rho0.dims) if opt.rhs_with_state: obj = L_func(0., rho0.full().ravel("F"), args) L_func = L_api.L_with_state if issuper(obj) else L_api.H2L_with_state else: obj = L_func(0., args) L_func = L_api.L if issuper(obj) else L_api.H2L ss = SolverSystem() ss.L = L_func ss.makefunc = _Lfunc_set solver_safe["mesolve"] = ss return ss
def _mesolve_QobjEvo(H, c_ops, tlist, args, opt): """ Prepare the system for the solver, H can be an QobjEvo. """ H_td = QobjEvo(H, args, tlist=tlist) if not issuper(H_td.cte): L_td = liouvillian(H_td) else: L_td = H_td for op in c_ops: # We want to avoid passing tlist where it isn't necessary, to allow a # Hamiltonian/Liouvillian which already _has_ time-dependence not equal # to the mesolve evaluation times to be used in conjunction with # time-independent c_ops. If we _always_ pass it, it may appear to # QobjEvo that there is a tlist mismatch, even though it is not used. if isinstance(op, Qobj): op_td = QobjEvo(op) elif isinstance(op, QobjEvo): op_td = QobjEvo(op, args) else: op_td = QobjEvo(op, args, tlist=tlist) if not issuper(op_td.cte): op_td = lindblad_dissipator(op_td) L_td += op_td if opt.rhs_with_state: L_td._check_old_with_state() nthread = opt.openmp_threads if opt.use_openmp else 0 L_td.compile(omp=nthread) ss = SolverSystem() ss.H = L_td ss.makefunc = _qobjevo_set solver_safe["mesolve"] = ss return ss
def smesolve_generic(ssdata, options, progress_bar): """ internal .. note:: Experimental. """ if debug: print(inspect.stack()[0][3]) N_store = len(ssdata.tlist) N_substeps = ssdata.nsubsteps N = N_store * N_substeps dt = (ssdata.tlist[1] - ssdata.tlist[0]) / N_substeps NT = ssdata.ntraj data = Odedata() data.solver = "smesolve" data.times = ssdata.tlist data.expect = np.zeros((len(ssdata.e_ops), N_store), dtype=complex) data.ss = np.zeros((len(ssdata.e_ops), N_store), dtype=complex) data.noise = [] data.measurement = [] # pre-compute suporoperator operator combinations that are commonly needed # when evaluating the RHS of stochastic master equations A_ops = [] for c_idx, c in enumerate(ssdata.sc_ops): n = c.dag() * c A_ops.append([spre(c).data, spost(c).data, spre(c.dag()).data, spost(c.dag()).data, spre(n).data, spost(n).data, (spre(c) * spost(c.dag())).data, lindblad_dissipator(c, data_only=True)]) s_e_ops = [spre(e) for e in ssdata.e_ops] # Liouvillian for the deterministic part. # needs to be modified for TD systems L = liouvillian_fast(ssdata.H, ssdata.c_ops) progress_bar.start(ssdata.ntraj) for n in range(ssdata.ntraj): progress_bar.update(n) rho_t = mat2vec(ssdata.state0.full()).ravel() noise = ssdata.noise[n] if ssdata.noise else None states_list, dW, m = _smesolve_single_trajectory( L, dt, ssdata.tlist, N_store, N_substeps, rho_t, A_ops, s_e_ops, data, ssdata.rhs, ssdata.d1, ssdata.d2, ssdata.d2_len, ssdata.homogeneous, ssdata.distribution, ssdata.args, store_measurement=ssdata.store_measurement, store_states=ssdata.store_states, noise=noise) data.states.append(states_list) data.noise.append(dW) data.measurement.append(m) progress_bar.finished() # average density matrices if options.average_states and np.any(data.states): data.states = [sum(state_list).unit() for state_list in data.states] # average data.expect = data.expect / NT # standard error if NT > 1: data.se = (data.ss - NT * (data.expect ** 2)) / (NT * (NT - 1)) else: data.se = None # convert complex data to real if hermitian data.expect = [np.real(data.expect[n,:]) if e.isherm else data.expect[n,:] for n, e in enumerate(ssdata.e_ops)] return data