def smesolve_generic(H, rho0, tlist, c_ops, e_ops, rhs, d1, d2, ntraj, nsubsteps): """ internal .. note:: Experimental. """ if debug: print inspect.stack()[0][3] N_store = len(tlist) N_substeps = nsubsteps N = N_store * N_substeps dt = (tlist[1]-tlist[0]) / N_substeps print("N = %d. dt=%.2e" % (N, dt)) data = Odedata() data.expect = np.zeros((len(e_ops), N_store), dtype=complex) # pre-compute collapse operator combinations that are commonly needed # when evaluating the RHS of stochastic master equations A_ops = [] for c_idx, c in enumerate(c_ops): # xxx: precompute useful operator expressions... cdc = c.dag() * c Ldt = spre(c) * spost(c.dag()) - 0.5 * spre(cdc) - 0.5 * spost(cdc) LdW = spre(c) + spost(c.dag()) Lm = spre(c) + spost(c.dag()) # currently same as LdW A_ops.append([Ldt.data, LdW.data, Lm.data]) # Liouvillian for the unitary part L = -1.0j*(spre(H) - spost(H)) # XXX: should we split the ME in stochastic # and deterministic collapse operators here? progress_acc = 0.0 for n in range(ntraj): if debug and (100 * float(n)/ntraj) >= progress_acc: print("Progress: %.2f" % (100 * float(n)/ntraj)) progress_acc += 10.0 rho_t = mat2vec(rho0.full()) states_list = _smesolve_single_trajectory(L, dt, tlist, N_store, N_substeps, rho_t, A_ops, e_ops, data, rhs, d1, d2) # if average -> average... data.states.append(states_list) # average data.expect = data.expect/ntraj return data
def brmesolve(H, psi0, tlist, c_ops, e_ops=[], spectra_cb=[], args={}, options=Odeoptions()): """ Solve the dynamics for the system using the Bloch-Redfeild master equation. .. note:: This solver does not currently support time-dependent Hamiltonian or collapse operators. Parameters ---------- H : :class:`qutip.Qobj` System Hamiltonian. rho0 / psi0: :class:`qutip.Qobj` Initial density matrix or state vector (ket). tlist : *list* / *array* List of times for :math:`t`. c_ops : list of :class:`qutip.Qobj` List of collapse operators. expt_ops : list of :class:`qutip.Qobj` / callback function List of operators for which to evaluate expectation values. args : *dictionary* Dictionary of parameters for time-dependent Hamiltonians and collapse operators. options : :class:`qutip.Qdeoptions` Options for the ODE solver. Returns ------- output: :class:`qutip.Odedata` An instance of the class :class:`qutip.Odedata`, which contains either an *array* of expectation values for the times specified by `tlist`. """ if len(spectra_cb) == 0: for n in range(len(c_ops)): spectra_cb.append(lambda w: 1.0) # add white noise callbacks if absent R, ekets = bloch_redfield_tensor(H, c_ops, spectra_cb) output = Odedata() output.times = tlist output.expect = bloch_redfield_solve(R, ekets, psi0, tlist, e_ops, options) return output
def ssesolve_generic(H, psi0, tlist, c_ops, e_ops, rhs, d1, d2, ntraj, nsubsteps): """ internal .. note:: Experimental. """ if debug: print inspect.stack()[0][3] N_store = len(tlist) N_substeps = nsubsteps N = N_store * N_substeps dt = (tlist[1] - tlist[0]) / N_substeps print("N = %d. dt=%.2e" % (N, dt)) data = Odedata() data.expect = np.zeros((len(e_ops), N_store), dtype=complex) # pre-compute collapse operator combinations that are commonly needed # when evaluating the RHS of stochastic Schrodinger equations A_ops = [] for c_idx, c in enumerate(c_ops): A_ops.append([c.data, (c + c.dag()).data, (c.dag() * c).data]) progress_acc = 0.0 for n in range(ntraj): if debug and (100 * float(n) / ntraj) >= progress_acc: print("Progress: %.2f" % (100 * float(n) / ntraj)) progress_acc += 10.0 psi_t = psi0.full() states_list = _ssesolve_single_trajectory(H, dt, tlist, N_store, N_substeps, psi_t, A_ops, e_ops, data, rhs, d1, d2) # if average -> average... data.states.append(states_list) # average data.expect = data.expect / ntraj return data
def ssesolve_generic(H, psi0, tlist, c_ops, e_ops, rhs, d1, d2, ntraj, nsubsteps): """ internal .. note:: Experimental. """ if debug: print inspect.stack()[0][3] N_store = len(tlist) N_substeps = nsubsteps N = N_store * N_substeps dt = (tlist[1]-tlist[0]) / N_substeps print("N = %d. dt=%.2e" % (N, dt)) data = Odedata() data.expect = np.zeros((len(e_ops), N_store), dtype=complex) # pre-compute collapse operator combinations that are commonly needed # when evaluating the RHS of stochastic Schrodinger equations A_ops = [] for c_idx, c in enumerate(c_ops): A_ops.append([c.data, (c+c.dag()).data, (c.dag()*c).data]) progress_acc = 0.0 for n in range(ntraj): if debug and (100 * float(n)/ntraj) >= progress_acc: print("Progress: %.2f" % (100 * float(n)/ntraj)) progress_acc += 10.0 psi_t = psi0.full() states_list = _ssesolve_single_trajectory(H, dt, tlist, N_store, N_substeps, psi_t, A_ops, e_ops, data, rhs, d1, d2) # if average -> average... data.states.append(states_list) # average data.expect = data.expect/ntraj return data
def brmesolve(H, psi0, tlist, c_ops, e_ops=[], spectra_cb=[], args={}, options=Odeoptions()): """ Solve the dynamics for the system using the Bloch-Redfeild master equation. .. note:: This solver does not currently support time-dependent Hamiltonian or collapse operators. Parameters ---------- H : :class:`qutip.Qobj` system Hamiltonian. rho0 / psi0: :class:`qutip.Qobj` initial density matrix or state vector (ket). tlist : *list* / *array* list of times for :math:`t`. c_ops : list of :class:`qutip.Qobj` list of collapse operators. expt_ops : list of :class:`qutip.Qobj` / callback function list of operators for which to evaluate expectation values. args : *dictionary* dictionary of parameters for time-dependent Hamiltonians and collapse operators. options : :class:`qutip.Qdeoptions` with options for the ODE solver. Returns ------- output: :class:`qutip.Odedata` An instance of the class :class:`qutip.Odedata`, which contains either an *array* of expectation values for the times specified by `tlist`. """ if len(spectra_cb) == 0: for n in range(len(c_ops)): spectra_cb.append( lambda w: 1.0) # add white noise callbacks if absent R, ekets = bloch_redfield_tensor(H, c_ops, spectra_cb) output = Odedata() output.times = tlist output.expect = bloch_redfield_solve(R, ekets, psi0, tlist, e_ops, options) return output
def _generic_ode_solve(r, psi0, tlist, expt_ops, opt, state_vectorize, state_norm_func=None): """ Internal function for solving ODEs. """ # # prepare output array # n_tsteps = len(tlist) dt = tlist[1]-tlist[0] output = Odedata() output.solver = "mesolve" output.times = tlist if isinstance(expt_ops, types.FunctionType): n_expt_op = 0 expt_callback = True elif isinstance(expt_ops, list): n_expt_op = len(expt_ops) expt_callback = False if n_expt_op == 0: output.states = [] else: output.expect = [] output.num_expect = n_expt_op for op in expt_ops: if op.isherm and psi0.isherm: output.expect.append(np.zeros(n_tsteps)) else: output.expect.append(np.zeros(n_tsteps,dtype=complex)) else: raise TypeError("Expectation parameter must be a list or a function") # # start evolution # psi = Qobj(psi0) t_idx = 0 for t in tlist: if not r.successful(): break; if state_norm_func: psi.data = state_vectorize(r.y) state_norm = state_norm_func(psi.data) psi.data = psi.data / state_norm r.set_initial_value(r.y/state_norm, r.t) else: psi.data = state_vectorize(r.y) if expt_callback: # use callback method expt_ops(t, Qobj(psi)) else: # calculate all the expectation values, or output rho if no operators if n_expt_op == 0: output.states.append(Qobj(psi)) # copy psi/rho else: for m in range(0, n_expt_op): output.expect[m][t_idx] = expect(expt_ops[m], psi) r.integrate(r.t + dt) t_idx += 1 if not opt.rhs_reuse and odeconfig.tdname != None: try: os.remove(odeconfig.tdname+".pyx") except: pass return output
def floquet_markov_mesolve(R, ekets, rho0, tlist, e_ops, options=None): """ Solve the dynamics for the system using the Floquet-Markov master equation. """ if options == None: opt = Odeoptions() else: opt=options if opt.tidy: R.tidyup() # # check initial state # if isket(rho0): # Got a wave function as initial state: convert to density matrix. rho0 = ket2dm(rho0) # # prepare output array # n_tsteps = len(tlist) dt = tlist[1]-tlist[0] output = Odedata() output.times = tlist if isinstance(e_ops, FunctionType): n_expt_op = 0 expt_callback = True elif isinstance(e_ops, list): n_expt_op = len(e_ops) expt_callback = False if n_expt_op == 0: output.states = [] else: output.expect = [] output.num_expect = n_expt_op for op in e_ops: if op.isherm: output.expect.append(np.zeros(n_tsteps)) else: output.expect.append(np.zeros(n_tsteps,dtype=complex)) else: raise TypeError("Expectation parameter must be a list or a function") # # transform the initial density matrix and the e_ops opterators to the # eigenbasis: from computational basis to the floquet basis # if ekets != None: rho0 = rho0.transform(ekets, True) if isinstance(e_ops, list): for n in np.arange(len(e_ops)): # not working e_ops[n] = e_ops[n].transform(ekets) # # # setup integrator # initial_vector = mat2vec(rho0.full()) r = scipy.integrate.ode(cyq_ode_rhs) r.set_f_params(R.data.data, R.data.indices, R.data.indptr) r.set_integrator('zvode', method=opt.method, order=opt.order, atol=opt.atol, rtol=opt.rtol, max_step=opt.max_step) r.set_initial_value(initial_vector, tlist[0]) # # start evolution # rho = Qobj(rho0) t_idx = 0 for t in tlist: if not r.successful(): break; rho.data = vec2mat(r.y) if expt_callback: # use callback method e_ops(t, Qobj(rho)) else: # calculate all the expectation values, or output rho if no operators if n_expt_op == 0: output.states.append(Qobj(rho)) # copy psi/rho else: for m in range(0, n_expt_op): output.expect[m][t_idx] = expect(e_ops[m], rho) # basis OK? r.integrate(r.t + dt) t_idx += 1 return output
def mcsolve(H,psi0,tlist,c_ops,e_ops,ntraj=500,args={},options=Odeoptions()): """Monte-Carlo evolution of a state vector :math:`|\psi \\rangle` for a given Hamiltonian and sets of collapse operators, and possibly, operators for calculating expectation values. Options for the underlying ODE solver are given by the Odeoptions class. mcsolve supports time-dependent Hamiltonians and collapse operators using either Python functions of strings to represent time-dependent coefficients. Note that, the system Hamiltonian MUST have at least one constant term. As an example of a time-dependent problem, consider a Hamiltonian with two terms ``H0`` and ``H1``, where ``H1`` is time-dependent with coefficient ``sin(w*t)``, and collapse operators ``C0`` and ``C1``, where ``C1`` is time-dependent with coeffcient ``exp(-a*t)``. Here, w and a are constant arguments with values ``W`` and ``A``. Using the Python function time-dependent format requires two Python functions, one for each collapse coefficient. Therefore, this problem could be expressed as:: def H1_coeff(t,args): return sin(args['w']*t) def C1_coeff(t,args): return exp(-args['a']*t) H=[H0,[H1,H1_coeff]] c_op_list=[C0,[C1,C1_coeff]] args={'a':A,'w':W} or in String (Cython) format we could write:: H=[H0,[H1,'sin(w*t)']] c_op_list=[C0,[C1,'exp(-a*t)']] args={'a':A,'w':W} Constant terms are preferably placed first in the Hamiltonian and collapse operator lists. Parameters ---------- H : qobj System Hamiltonian. psi0 : qobj Initial state vector tlist : array_like Times at which results are recorded. ntraj : int Number of trajectories to run. c_ops : array_like ``list`` or ``array`` of collapse operators. e_ops : array_like ``list`` or ``array`` of operators for calculating expectation values. args : dict Arguments for time-dependent Hamiltonian and collapse operator terms. options : Odeoptions Instance of ODE solver options. Returns ------- results : Odedata Object storing all results from simulation. """ if psi0.type!='ket': raise Exception("Initial state must be a state vector.") odeconfig.options=options #set num_cpus to the value given in qutip.settings if none in Odeoptions if not odeconfig.options.num_cpus: odeconfig.options.num_cpus=qutip.settings.num_cpus #set initial value data if options.tidy: odeconfig.psi0=psi0.tidyup(options.atol).full() else: odeconfig.psi0=psi0.full() odeconfig.psi0_dims=psi0.dims odeconfig.psi0_shape=psi0.shape #set general items odeconfig.tlist=tlist if isinstance(ntraj,(list,ndarray)): odeconfig.ntraj=sort(ntraj)[-1] else: odeconfig.ntraj=ntraj #---- #---------------------------------------------- # SETUP ODE DATA IF NONE EXISTS OR NOT REUSING #---------------------------------------------- if (not options.rhs_reuse) or (not odeconfig.tdfunc): #reset odeconfig collapse and time-dependence flags to default values _reset_odeconfig() #check for type of time-dependence (if any) time_type,h_stuff,c_stuff=_ode_checks(H,c_ops,'mc') h_terms=len(h_stuff[0])+len(h_stuff[1])+len(h_stuff[2]) c_terms=len(c_stuff[0])+len(c_stuff[1])+len(c_stuff[2]) #set time_type for use in multiprocessing odeconfig.tflag=time_type #-Check for PyObjC on Mac platforms if sys.platform=='darwin': try: import Foundation except: odeconfig.options.gui=False #check if running in iPython and using Cython compiling (then no GUI to work around error) if odeconfig.options.gui and odeconfig.tflag in array([1,10,11]): try: __IPYTHON__ except: pass else: odeconfig.options.gui=False if qutip.settings.qutip_gui=="NONE": odeconfig.options.gui=False #check for collapse operators if c_terms>0: odeconfig.cflag=1 else: odeconfig.cflag=0 #Configure data _mc_data_config(H,psi0,h_stuff,c_ops,c_stuff,args,e_ops,options) if odeconfig.tflag in array([1,10,11]): #compile time-depdendent RHS code os.environ['CFLAGS'] = '-w' import pyximport pyximport.install(setup_args={'include_dirs':[numpy.get_include()]}) if odeconfig.tflag in array([1,11]): code = compile('from '+odeconfig.tdname+' import cyq_td_ode_rhs,col_spmv,col_expect', '<string>', 'exec') exec(code, globals()) odeconfig.tdfunc=cyq_td_ode_rhs odeconfig.colspmv=col_spmv odeconfig.colexpect=col_expect else: code = compile('from '+odeconfig.tdname+' import cyq_td_ode_rhs', '<string>', 'exec') exec(code, globals()) odeconfig.tdfunc=cyq_td_ode_rhs try: os.remove(odeconfig.tdname+".pyx") except: print("Error removing pyx file. File not found.") elif odeconfig.tflag==0: odeconfig.tdfunc=cyq_ode_rhs else:#setup args for new parameters when rhs_reuse=True and tdfunc is given #string based if odeconfig.tflag in array([1,10,11]): if any(args): odeconfig.c_args=[] arg_items=args.items() for k in range(len(args)): odeconfig.c_args.append(arg_items[k][1]) #function based elif odeconfig.tflag in array([2,3,20,22]): odeconfig.h_func_args=args #load monte-carlo class mc=MC_class() #RUN THE SIMULATION mc.run() #AFTER MCSOLVER IS DONE -------------------------------------- #-------COLLECT AND RETURN OUTPUT DATA IN ODEDATA OBJECT --------------# output=Odedata() output.solver='mcsolve' #state vectors if any(mc.psi_out) and odeconfig.options.mc_avg: output.states=mc.psi_out #expectation values if any(mc.expect_out) and odeconfig.cflag and odeconfig.options.mc_avg:#averaging if multiple trajectories if isinstance(ntraj,int): output.expect=mean(mc.expect_out,axis=0) elif isinstance(ntraj,(list,ndarray)): output.expect=[] for num in ntraj: expt_data=mean(mc.expect_out[:num],axis=0) data_list=[] if any([op.isherm==False for op in e_ops]): for k in range(len(e_ops)): if e_ops[k].isherm: data_list.append(real(expt_data[k])) else: data_list.append(expt_data[k]) else: data_list=[data for data in expt_data] output.expect.append(data_list) else:#no averaging for single trajectory or if mc_avg flag (Odeoptions) is off output.expect=mc.expect_out #simulation parameters output.times=odeconfig.tlist output.num_expect=odeconfig.e_num output.num_collapse=odeconfig.c_num output.ntraj=odeconfig.ntraj output.col_times=mc.collapse_times_out output.col_which=mc.which_op_out return output
def _generic_ode_solve(r, psi0, tlist, expt_ops, opt, state_vectorize, state_norm_func=None): """ Internal function for solving ODEs. """ # # prepare output array # n_tsteps = len(tlist) dt = tlist[1] - tlist[0] output = Odedata() output.solver = "mesolve" output.times = tlist if isinstance(expt_ops, types.FunctionType): n_expt_op = 0 expt_callback = True elif isinstance(expt_ops, list): n_expt_op = len(expt_ops) expt_callback = False if n_expt_op == 0: output.states = [] else: output.expect = [] output.num_expect = n_expt_op for op in expt_ops: if op.isherm and psi0.isherm: output.expect.append(np.zeros(n_tsteps)) else: output.expect.append(np.zeros(n_tsteps, dtype=complex)) else: raise TypeError("Expectation parameter must be a list or a function") # # start evolution # psi = Qobj(psi0) t_idx = 0 for t in tlist: if not r.successful(): break if state_norm_func: psi.data = state_vectorize(r.y) state_norm = state_norm_func(psi.data) psi.data = psi.data / state_norm r.set_initial_value(r.y / state_norm, r.t) else: psi.data = state_vectorize(r.y) if expt_callback: # use callback method expt_ops(t, Qobj(psi)) else: # calculate all the expectation values, or output rho if no operators if n_expt_op == 0: output.states.append(Qobj(psi)) # copy psi/rho else: for m in range(0, n_expt_op): output.expect[m][t_idx] = expect(expt_ops[m], psi) r.integrate(r.t + dt) t_idx += 1 if not opt.rhs_reuse and odeconfig.tdname != None: try: os.remove(odeconfig.tdname + ".pyx") except: pass return output
def floquet_markov_mesolve(R, ekets, rho0, tlist, e_ops, options=None): """ Solve the dynamics for the system using the Floquet-Markov master equation. """ if options == None: opt = Odeoptions() else: opt = options if opt.tidy: R.tidyup() # # check initial state # if isket(rho0): # Got a wave function as initial state: convert to density matrix. rho0 = ket2dm(rho0) # # prepare output array # n_tsteps = len(tlist) dt = tlist[1] - tlist[0] output = Odedata() output.times = tlist if isinstance(e_ops, FunctionType): n_expt_op = 0 expt_callback = True elif isinstance(e_ops, list): n_expt_op = len(e_ops) expt_callback = False if n_expt_op == 0: output.states = [] else: output.expect = [] output.num_expect = n_expt_op for op in e_ops: if op.isherm: output.expect.append(np.zeros(n_tsteps)) else: output.expect.append(np.zeros(n_tsteps, dtype=complex)) else: raise TypeError("Expectation parameter must be a list or a function") # # transform the initial density matrix and the e_ops opterators to the # eigenbasis: from computational basis to the floquet basis # if ekets != None: rho0 = rho0.transform(ekets, True) if isinstance(e_ops, list): for n in np.arange(len(e_ops)): # not working e_ops[n] = e_ops[n].transform(ekets) # # # setup integrator # initial_vector = mat2vec(rho0.full()) r = scipy.integrate.ode(cyq_ode_rhs) r.set_f_params(R.data.data, R.data.indices, R.data.indptr) r.set_integrator('zvode', method=opt.method, order=opt.order, atol=opt.atol, rtol=opt.rtol, max_step=opt.max_step) r.set_initial_value(initial_vector, tlist[0]) # # start evolution # rho = Qobj(rho0) t_idx = 0 for t in tlist: if not r.successful(): break rho.data = vec2mat(r.y) if expt_callback: # use callback method e_ops(t, Qobj(rho)) else: # calculate all the expectation values, or output rho if no operators if n_expt_op == 0: output.states.append(Qobj(rho)) # copy psi/rho else: for m in range(0, n_expt_op): output.expect[m][t_idx] = expect(e_ops[m], rho) # basis OK? r.integrate(r.t + dt) t_idx += 1 return output
def smesolve_generic(H, rho0, tlist, c_ops, e_ops, rhs, d1, d2, ntraj, nsubsteps): """ internal .. note:: Experimental. """ if debug: print inspect.stack()[0][3] N_store = len(tlist) N_substeps = nsubsteps N = N_store * N_substeps dt = (tlist[1] - tlist[0]) / N_substeps print("N = %d. dt=%.2e" % (N, dt)) data = Odedata() data.expect = np.zeros((len(e_ops), N_store), dtype=complex) # pre-compute collapse operator combinations that are commonly needed # when evaluating the RHS of stochastic master equations A_ops = [] for c_idx, c in enumerate(c_ops): # xxx: precompute useful operator expressions... cdc = c.dag() * c Ldt = spre(c) * spost(c.dag()) - 0.5 * spre(cdc) - 0.5 * spost(cdc) LdW = spre(c) + spost(c.dag()) Lm = spre(c) + spost(c.dag()) # currently same as LdW A_ops.append([Ldt.data, LdW.data, Lm.data]) # Liouvillian for the unitary part L = -1.0j * (spre(H) - spost(H) ) # XXX: should we split the ME in stochastic # and deterministic collapse operators here? progress_acc = 0.0 for n in range(ntraj): if debug and (100 * float(n) / ntraj) >= progress_acc: print("Progress: %.2f" % (100 * float(n) / ntraj)) progress_acc += 10.0 rho_t = mat2vec(rho0.full()) states_list = _smesolve_single_trajectory(L, dt, tlist, N_store, N_substeps, rho_t, A_ops, e_ops, data, rhs, d1, d2) # if average -> average... data.states.append(states_list) # average data.expect = data.expect / ntraj return data
def mcsolve(H, psi0, tlist, c_ops, e_ops, ntraj=500, args={}, options=Odeoptions()): """Monte-Carlo evolution of a state vector :math:`|\psi \\rangle` for a given Hamiltonian and sets of collapse operators, and possibly, operators for calculating expectation values. Options for the underlying ODE solver are given by the Odeoptions class. mcsolve supports time-dependent Hamiltonians and collapse operators using either Python functions of strings to represent time-dependent coefficients. Note that, the system Hamiltonian MUST have at least one constant term. As an example of a time-dependent problem, consider a Hamiltonian with two terms ``H0`` and ``H1``, where ``H1`` is time-dependent with coefficient ``sin(w*t)``, and collapse operators ``C0`` and ``C1``, where ``C1`` is time-dependent with coeffcient ``exp(-a*t)``. Here, w and a are constant arguments with values ``W`` and ``A``. Using the Python function time-dependent format requires two Python functions, one for each collapse coefficient. Therefore, this problem could be expressed as:: def H1_coeff(t,args): return sin(args['w']*t) def C1_coeff(t,args): return exp(-args['a']*t) H=[H0,[H1,H1_coeff]] c_op_list=[C0,[C1,C1_coeff]] args={'a':A,'w':W} or in String (Cython) format we could write:: H=[H0,[H1,'sin(w*t)']] c_op_list=[C0,[C1,'exp(-a*t)']] args={'a':A,'w':W} Constant terms are preferably placed first in the Hamiltonian and collapse operator lists. Parameters ---------- H : qobj System Hamiltonian. psi0 : qobj Initial state vector tlist : array_like Times at which results are recorded. ntraj : int Number of trajectories to run. c_ops : array_like ``list`` or ``array`` of collapse operators. e_ops : array_like ``list`` or ``array`` of operators for calculating expectation values. args : dict Arguments for time-dependent Hamiltonian and collapse operator terms. options : Odeoptions Instance of ODE solver options. Returns ------- results : Odedata Object storing all results from simulation. """ if psi0.type != 'ket': raise Exception("Initial state must be a state vector.") odeconfig.options = options #set num_cpus to the value given in qutip.settings if none in Odeoptions if not odeconfig.options.num_cpus: odeconfig.options.num_cpus = qutip.settings.num_cpus #set initial value data if options.tidy: odeconfig.psi0 = psi0.tidyup(options.atol).full() else: odeconfig.psi0 = psi0.full() odeconfig.psi0_dims = psi0.dims odeconfig.psi0_shape = psi0.shape #set general items odeconfig.tlist = tlist if isinstance(ntraj, (list, ndarray)): odeconfig.ntraj = sort(ntraj)[-1] else: odeconfig.ntraj = ntraj #---- #---------------------------------------------- # SETUP ODE DATA IF NONE EXISTS OR NOT REUSING #---------------------------------------------- if (not options.rhs_reuse) or (not odeconfig.tdfunc): #reset odeconfig collapse and time-dependence flags to default values _reset_odeconfig() #check for type of time-dependence (if any) time_type, h_stuff, c_stuff = _ode_checks(H, c_ops, 'mc') h_terms = len(h_stuff[0]) + len(h_stuff[1]) + len(h_stuff[2]) c_terms = len(c_stuff[0]) + len(c_stuff[1]) + len(c_stuff[2]) #set time_type for use in multiprocessing odeconfig.tflag = time_type #-Check for PyObjC on Mac platforms if sys.platform == 'darwin': try: import Foundation except: odeconfig.options.gui = False #check if running in iPython and using Cython compiling (then no GUI to work around error) if odeconfig.options.gui and odeconfig.tflag in array([1, 10, 11]): try: __IPYTHON__ except: pass else: odeconfig.options.gui = False if qutip.settings.qutip_gui == "NONE": odeconfig.options.gui = False #check for collapse operators if c_terms > 0: odeconfig.cflag = 1 else: odeconfig.cflag = 0 #Configure data _mc_data_config(H, psi0, h_stuff, c_ops, c_stuff, args, e_ops, options) if odeconfig.tflag in array([1, 10, 11]): #compile time-depdendent RHS code os.environ['CFLAGS'] = '-w' import pyximport pyximport.install( setup_args={'include_dirs': [numpy.get_include()]}) if odeconfig.tflag in array([1, 11]): code = compile( 'from ' + odeconfig.tdname + ' import cyq_td_ode_rhs,col_spmv,col_expect', '<string>', 'exec') exec(code, globals()) odeconfig.tdfunc = cyq_td_ode_rhs odeconfig.colspmv = col_spmv odeconfig.colexpect = col_expect else: code = compile( 'from ' + odeconfig.tdname + ' import cyq_td_ode_rhs', '<string>', 'exec') exec(code, globals()) odeconfig.tdfunc = cyq_td_ode_rhs try: os.remove(odeconfig.tdname + ".pyx") except: print("Error removing pyx file. File not found.") elif odeconfig.tflag == 0: odeconfig.tdfunc = cyq_ode_rhs else: #setup args for new parameters when rhs_reuse=True and tdfunc is given #string based if odeconfig.tflag in array([1, 10, 11]): if any(args): odeconfig.c_args = [] arg_items = args.items() for k in range(len(args)): odeconfig.c_args.append(arg_items[k][1]) #function based elif odeconfig.tflag in array([2, 3, 20, 22]): odeconfig.h_func_args = args #load monte-carlo class mc = MC_class() #RUN THE SIMULATION mc.run() #AFTER MCSOLVER IS DONE -------------------------------------- #-------COLLECT AND RETURN OUTPUT DATA IN ODEDATA OBJECT --------------# output = Odedata() output.solver = 'mcsolve' #state vectors if any(mc.psi_out) and odeconfig.options.mc_avg: output.states = mc.psi_out #expectation values if any( mc.expect_out ) and odeconfig.cflag and odeconfig.options.mc_avg: #averaging if multiple trajectories if isinstance(ntraj, int): output.expect = mean(mc.expect_out, axis=0) elif isinstance(ntraj, (list, ndarray)): output.expect = [] for num in ntraj: expt_data = mean(mc.expect_out[:num], axis=0) data_list = [] if any([op.isherm == False for op in e_ops]): for k in range(len(e_ops)): if e_ops[k].isherm: data_list.append(real(expt_data[k])) else: data_list.append(expt_data[k]) else: data_list = [data for data in expt_data] output.expect.append(data_list) else: #no averaging for single trajectory or if mc_avg flag (Odeoptions) is off output.expect = mc.expect_out #simulation parameters output.times = odeconfig.tlist output.num_expect = odeconfig.e_num output.num_collapse = odeconfig.c_num output.ntraj = odeconfig.ntraj output.col_times = mc.collapse_times_out output.col_which = mc.which_op_out return output