def qeye(N): """ Identity operator Parameters ---------- N : int or list of ints Dimension of Hilbert space. If provided as a list of ints, then the dimension is the product over this list, but the ``dims`` property of the new Qobj are set to this list. Returns ------- oper : qobj Identity operator Qobj. Examples -------- >>> qeye(3) Quantum object: dims = [[3], [3]], \ shape = [3, 3], type = oper, isHerm = True Qobj data = [[ 1. 0. 0.] [ 0. 1. 0.] [ 0. 0. 1.]] """ if isinstance(N, list): return tensor(*[identity(n) for n in N]) N = int(N) if N < 0: raise ValueError("N must be integer N>=0") return Qobj(fast_identity(N), isherm=True, isunitary=True)
def spre(A): """Superoperator formed from pre-multiplication by operator A. Parameters ---------- A : Qobj or QobjEvo Quantum operator for pre-multiplication. Returns -------- super :Qobj or QobjEvo Superoperator formed from input quantum object. """ if isinstance(A, QobjEvo): return A.apply(spre) 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(fast_identity(np.prod(A.shape[1])), A.data) return S
def __init__( self, H_sys, bath, max_depth, options=None, progress_bar=None, ): self.H_sys = self._convert_h_sys(H_sys) self.options = Options() if options is None else options self._is_timedep = isinstance(self.H_sys, QobjEvo) self._H0 = self.H_sys.to_list()[0] if self._is_timedep else self.H_sys self._is_hamiltonian = self._H0.type == "oper" self._L0 = liouvillian(self._H0) if self._is_hamiltonian else self._H0 self._sys_shape = (self._H0.shape[0] if self._is_hamiltonian else int( np.sqrt(self._H0.shape[0]))) self._sup_shape = self._L0.shape[0] self._sys_dims = (self._H0.dims if self._is_hamiltonian else self._H0.dims[0]) self.ados = HierarchyADOs( self._combine_bath_exponents(bath), max_depth, ) self._n_ados = len(self.ados.labels) self._n_exponents = len(self.ados.exponents) # pre-calculate identity matrix required by _grad_n self._sId = fast_identity(self._sup_shape) # pre-calculate superoperators required by _grad_prev and _grad_next: Qs = [exp.Q for exp in self.ados.exponents] self._spreQ = [spre(op).data for op in Qs] self._spostQ = [spost(op).data for op in Qs] self._s_pre_minus_post_Q = [ self._spreQ[k] - self._spostQ[k] for k in range(self._n_exponents) ] self._s_pre_plus_post_Q = [ self._spreQ[k] + self._spostQ[k] for k in range(self._n_exponents) ] self._spreQdag = [spre(op.dag()).data for op in Qs] self._spostQdag = [spost(op.dag()).data for op in Qs] self._s_pre_minus_post_Qdag = [ self._spreQdag[k] - self._spostQdag[k] for k in range(self._n_exponents) ] self._s_pre_plus_post_Qdag = [ self._spreQdag[k] + self._spostQdag[k] for k in range(self._n_exponents) ] if progress_bar is None: self.progress_bar = BaseProgressBar() if progress_bar is True: self.progress_bar = TextProgressBar() self._configure_solver()
def qeye(dimensions): """ Identity operator. Parameters ---------- dimensions : (int) or (list of int) or (list of list of int) Dimension of Hilbert space. If provided as a list of ints, then the dimension is the product over this list, but the ``dims`` property of the new Qobj are set to this list. This can produce either `oper` or `super` depending on the passed `dimensions`. Returns ------- oper : qobj Identity operator Qobj. Examples -------- >>> qeye(3) # doctest: +SKIP Quantum object: dims = [[3], [3]], shape = (3, 3), type = oper, \ isherm = True Qobj data = [[ 1. 0. 0.] [ 0. 1. 0.] [ 0. 0. 1.]] >>> qeye([2,2]) # doctest: +SKIP Quantum object: dims = [[2, 2], [2, 2]], shape = (4, 4), type = oper, \ isherm = True Qobj data = [[1. 0. 0. 0.] [0. 1. 0. 0.] [0. 0. 1. 0.] [0. 0. 0. 1.]] """ size, dimensions = _implicit_tensor_dimensions(dimensions) return Qobj(fast_identity(size), dims=dimensions, isherm=True, isunitary=True)
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 = zcsr_kron(fast_identity(np.prod(A.shape[1])), A.data) 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 test_zcsr_isherm_compare_implicit_zero(): """ Regression test for gh-1350, comparing explicitly stored values in the matrix (but below the tolerance for allowable Hermicity) to implicit zeros. """ tol = 1e-12 n = 10 base = sp.csr_matrix(np.array([[1, tol * 1e-3j], [0, 1]])) base = fast_csr_matrix((base.data, base.indices, base.indptr), base.shape) # If this first line fails, the zero has been stored explicitly and so the # test is invalid. assert base.data.size == 3 assert zcsr_isherm(base, tol=tol) assert zcsr_isherm(base.T, tol=tol) # A similar test if the structures are different, but it's not # Hermitian. base = sp.csr_matrix(np.array([[1, 1j], [0, 1]])) base = fast_csr_matrix((base.data, base.indices, base.indptr), base.shape) assert base.data.size == 3 assert not zcsr_isherm(base, tol=tol) assert not zcsr_isherm(base.T, tol=tol) # Catch possible edge case where it shouldn't be Hermitian, but faulty loop # logic doesn't fully compare all rows. base = sp.csr_matrix( np.array([ [0, 0, 0, 0], [0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0], ], dtype=np.complex128)) base = fast_csr_matrix((base.data, base.indices, base.indptr), base.shape) assert base.data.size == 1 assert not zcsr_isherm(base, tol=tol) assert not zcsr_isherm(base.T, tol=tol) # Pure diagonal matrix. base = fast_identity(n) base.data *= np.random.rand(n) assert zcsr_isherm(base, tol=tol) assert not zcsr_isherm(base * 1j, tol=tol) # Larger matrices where all off-diagonal elements are below the absolute # tolerance, so everything should always appear Hermitian, but with random # patterns of non-zero elements. It doesn't matter that it isn't Hermitian # if scaled up; everything is below absolute tolerance, so it should appear # so. We also set the diagonal to be larger to the tolerance to ensure # isherm can't just compare everything to zero. for density in np.linspace(0.2, 1, 21): base = tol * 1e-2 * (np.random.rand(n, n) + 1j * np.random.rand(n, n)) # Mask some values out to zero. base[np.random.rand(n, n) > density] = 0 np.fill_diagonal(base, tol * 1000) nnz = np.count_nonzero(base) base = sp.csr_matrix(base) base = fast_csr_matrix((base.data, base.indices, base.indptr), (n, n)) assert base.data.size == nnz assert zcsr_isherm(base, tol=tol) assert zcsr_isherm(base.T, tol=tol) # Similar test when it must be non-Hermitian. We set the diagonal to # be real because we want to test off-diagonal implicit zeros, and # having an imaginary first element would automatically fail. nnz = 0 while nnz <= n: # Ensure that we don't just have the real diagonal. base = tol * 1000j * np.random.rand(n, n) # Mask some values out to zero. base[np.random.rand(n, n) > density] = 0 np.fill_diagonal(base, tol * 1000) nnz = np.count_nonzero(base) base = sp.csr_matrix(base) base = fast_csr_matrix((base.data, base.indices, base.indptr), (n, n)) assert base.data.size == nnz assert not zcsr_isherm(base, tol=tol) assert not zcsr_isherm(base.T, tol=tol)
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 = fast_identity(op_shape[0]) if H: 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])) for idx, c_op in enumerate(c_ops): if c_op.issuper: data = data + c_op.data else: cd = c_op.data.H c = c_op.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 data_only: return data else: L = Qobj() L.dims = sop_dims L.data = data L.isherm = False L.superrep = 'super' return L
def configure(self, H_sys, coup_op, coup_strength, temperature, N_cut, N_exp, cut_freq, planck=None, boltzmann=None, renorm=None, bnd_cut_approx=None, options=None, progress_bar=None, stats=None): """ Calls configure from :class:`HEOMSolver` and sets any attributes that are specific to this subclass """ start_config = timeit.default_timer() HEOMSolver.configure(self, H_sys, coup_op, coup_strength, temperature, N_cut, N_exp, planck=planck, boltzmann=boltzmann, options=options, progress_bar=progress_bar, stats=stats) self.cut_freq = cut_freq if renorm is not None: self.renorm = renorm if bnd_cut_approx is not None: self.bnd_cut_approx = bnd_cut_approx # Load local values for optional parameters # Constants and Hamiltonian. hbar = self.planck options = self.options progress_bar = self.progress_bar stats = self.stats if stats: ss_conf = stats.sections.get('config') if ss_conf is None: ss_conf = stats.add_section('config') c, nu = self._calc_matsubara_params() if renorm: norm_plus, norm_minus = self._calc_renorm_factors() if stats: stats.add_message('options', 'renormalisation', ss_conf) # Dimensions et by system sup_dim = H_sys.dims[0][0]**2 unit_sys = qeye(H_sys.dims[0]) # Use shorthands (mainly as in referenced PRL) lam0 = self.coup_strength gam = self.cut_freq N_c = self.N_cut N_m = self.N_exp Q = coup_op # Q as shorthand for coupling operator beta = 1.0 / (self.boltzmann * self.temperature) # Ntot is the total number of ancillary elements in the hierarchy # Ntot = factorial(N_c + N_m) / (factorial(N_c)*factorial(N_m)) # Turns out to be the same as nstates from state_number_enumerate N_he, he2idx, idx2he = enr_state_dictionaries([N_c + 1] * N_m, N_c) unit_helems = fast_identity(N_he) if self.bnd_cut_approx: # the Tanimura boundary cut off operator if stats: stats.add_message('options', 'boundary cutoff approx', ss_conf) op = -2 * spre(Q) * spost(Q.dag()) + spre(Q.dag() * Q) + spost( Q.dag() * Q) approx_factr = ((2 * lam0 / (beta * gam * hbar)) - 1j * lam0) / hbar for k in range(N_m): approx_factr -= (c[k] / nu[k]) L_bnd = -approx_factr * op.data L_helems = zcsr_kron(unit_helems, L_bnd) else: L_helems = fast_csr_matrix(shape=(N_he * sup_dim, N_he * sup_dim)) # Build the hierarchy element interaction matrix if stats: start_helem_constr = timeit.default_timer() unit_sup = spre(unit_sys).data spreQ = spre(Q).data spostQ = spost(Q).data commQ = (spre(Q) - spost(Q)).data N_he_interact = 0 for he_idx in range(N_he): he_state = list(idx2he[he_idx]) n_excite = sum(he_state) # The diagonal elements for the hierarchy operator # coeff for diagonal elements sum_n_m_freq = 0.0 for k in range(N_m): sum_n_m_freq += he_state[k] * nu[k] op = -sum_n_m_freq * unit_sup L_he = cy_pad_csr(op, N_he, N_he, he_idx, he_idx) L_helems += L_he # Add the neighour interations he_state_neigh = copy(he_state) for k in range(N_m): n_k = he_state[k] if n_k >= 1: # find the hierarchy element index of the neighbour before # this element, for this Matsubara term he_state_neigh[k] = n_k - 1 he_idx_neigh = he2idx[tuple(he_state_neigh)] op = c[k] * spreQ - np.conj(c[k]) * spostQ if renorm: op = -1j * norm_minus[n_k, k] * op else: op = -1j * n_k * op L_he = cy_pad_csr(op, N_he, N_he, he_idx, he_idx_neigh) L_helems += L_he N_he_interact += 1 he_state_neigh[k] = n_k if n_excite <= N_c - 1: # find the hierarchy element index of the neighbour after # this element, for this Matsubara term he_state_neigh[k] = n_k + 1 he_idx_neigh = he2idx[tuple(he_state_neigh)] op = commQ if renorm: op = -1j * norm_plus[n_k, k] * op else: op = -1j * op L_he = cy_pad_csr(op, N_he, N_he, he_idx, he_idx_neigh) L_helems += L_he N_he_interact += 1 he_state_neigh[k] = n_k if stats: stats.add_timing('hierarchy contruct', timeit.default_timer() - start_helem_constr, ss_conf) stats.add_count('Num hierarchy elements', N_he, ss_conf) stats.add_count('Num he interactions', N_he_interact, ss_conf) # Setup Liouvillian if stats: start_louvillian = timeit.default_timer() H_he = zcsr_kron(unit_helems, liouvillian(H_sys).data) L_helems += H_he if stats: stats.add_timing('Liouvillian contruct', timeit.default_timer() - start_louvillian, ss_conf) if stats: start_integ_conf = timeit.default_timer() r = scipy.integrate.ode(cy_ode_rhs) r.set_f_params(L_helems.data, L_helems.indices, L_helems.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) if stats: time_now = timeit.default_timer() stats.add_timing('Liouvillian contruct', time_now - start_integ_conf, ss_conf) if ss_conf.total_time is None: ss_conf.total_time = time_now - start_config else: ss_conf.total_time += time_now - start_config self._ode = r self._N_he = N_he self._sup_dim = sup_dim self._configured = True
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 configure(self, H_sys, coup_op, coup_strength, temperature, N_cut, N_exp, cut_freq, planck=None, boltzmann=None, renorm=None, bnd_cut_approx=None, options=None, progress_bar=None, stats=None): """ Calls configure from :class:`HEOMSolver` and sets any attributes that are specific to this subclass """ start_config = timeit.default_timer() HEOMSolver.configure(self, H_sys, coup_op, coup_strength, temperature, N_cut, N_exp, planck=planck, boltzmann=boltzmann, options=options, progress_bar=progress_bar, stats=stats) self.cut_freq = cut_freq if renorm is not None: self.renorm = renorm if bnd_cut_approx is not None: self.bnd_cut_approx = bnd_cut_approx # Load local values for optional parameters # Constants and Hamiltonian. hbar = self.planck options = self.options progress_bar = self.progress_bar stats = self.stats if stats: ss_conf = stats.sections.get('config') if ss_conf is None: ss_conf = stats.add_section('config') c, nu = self._calc_matsubara_params() if renorm: norm_plus, norm_minus = self._calc_renorm_factors() if stats: stats.add_message('options', 'renormalisation', ss_conf) # Dimensions et by system N_temp = 1 for i in H_sys.dims[0]: N_temp *= i sup_dim = N_temp**2 unit_sys = qeye(N_temp) # Use shorthands (mainly as in referenced PRL) lam0 = self.coup_strength gam = self.cut_freq N_c = self.N_cut N_m = self.N_exp Q = coup_op # Q as shorthand for coupling operator beta = 1.0/(self.boltzmann*self.temperature) # Ntot is the total number of ancillary elements in the hierarchy # Ntot = factorial(N_c + N_m) / (factorial(N_c)*factorial(N_m)) # Turns out to be the same as nstates from state_number_enumerate N_he, he2idx, idx2he = enr_state_dictionaries([N_c + 1]*N_m , N_c) unit_helems = fast_identity(N_he) if self.bnd_cut_approx: # the Tanimura boundary cut off operator if stats: stats.add_message('options', 'boundary cutoff approx', ss_conf) op = -2*spre(Q)*spost(Q.dag()) + spre(Q.dag()*Q) + spost(Q.dag()*Q) approx_factr = ((2*lam0 / (beta*gam*hbar)) - 1j*lam0) / hbar for k in range(N_m): approx_factr -= (c[k] / nu[k]) L_bnd = -approx_factr*op.data L_helems = zcsr_kron(unit_helems, L_bnd) else: L_helems = fast_csr_matrix(shape=(N_he*sup_dim, N_he*sup_dim)) # Build the hierarchy element interaction matrix if stats: start_helem_constr = timeit.default_timer() unit_sup = spre(unit_sys).data spreQ = spre(Q).data spostQ = spost(Q).data commQ = (spre(Q) - spost(Q)).data N_he_interact = 0 for he_idx in range(N_he): he_state = list(idx2he[he_idx]) n_excite = sum(he_state) # The diagonal elements for the hierarchy operator # coeff for diagonal elements sum_n_m_freq = 0.0 for k in range(N_m): sum_n_m_freq += he_state[k]*nu[k] op = -sum_n_m_freq*unit_sup L_he = cy_pad_csr(op, N_he, N_he, he_idx, he_idx) L_helems += L_he # Add the neighour interations he_state_neigh = copy(he_state) for k in range(N_m): n_k = he_state[k] if n_k >= 1: # find the hierarchy element index of the neighbour before # this element, for this Matsubara term he_state_neigh[k] = n_k - 1 he_idx_neigh = he2idx[tuple(he_state_neigh)] op = c[k]*spreQ - np.conj(c[k])*spostQ if renorm: op = -1j*norm_minus[n_k, k]*op else: op = -1j*n_k*op L_he = cy_pad_csr(op, N_he, N_he, he_idx, he_idx_neigh) L_helems += L_he N_he_interact += 1 he_state_neigh[k] = n_k if n_excite <= N_c - 1: # find the hierarchy element index of the neighbour after # this element, for this Matsubara term he_state_neigh[k] = n_k + 1 he_idx_neigh = he2idx[tuple(he_state_neigh)] op = commQ if renorm: op = -1j*norm_plus[n_k, k]*op else: op = -1j*op L_he = cy_pad_csr(op, N_he, N_he, he_idx, he_idx_neigh) L_helems += L_he N_he_interact += 1 he_state_neigh[k] = n_k if stats: stats.add_timing('hierarchy contruct', timeit.default_timer() - start_helem_constr, ss_conf) stats.add_count('Num hierarchy elements', N_he, ss_conf) stats.add_count('Num he interactions', N_he_interact, ss_conf) # Setup Liouvillian if stats: start_louvillian = timeit.default_timer() H_he = zcsr_kron(unit_helems, liouvillian(H_sys).data) L_helems += H_he if stats: stats.add_timing('Liouvillian contruct', timeit.default_timer() - start_louvillian, ss_conf) if stats: start_integ_conf = timeit.default_timer() r = scipy.integrate.ode(cy_ode_rhs) r.set_f_params(L_helems.data, L_helems.indices, L_helems.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) if stats: time_now = timeit.default_timer() stats.add_timing('Liouvillian contruct', time_now - start_integ_conf, ss_conf) if ss_conf.total_time is None: ss_conf.total_time = time_now - start_config else: ss_conf.total_time += time_now - start_config self._ode = r self._N_he = N_he self._sup_dim = sup_dim self._configured = True