def mcsolve_f90(H, psi0, tlist, c_ops, e_ops, ntraj=None, options=Options(), sparse_dms=True, serial=False, ptrace_sel=[], calc_entropy=False): """ Monte-Carlo wave function solver with fortran 90 backend. Usage is identical to qutip.mcsolve, for problems without explicit time-dependence, and with some optional input: 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. options : Options Instance of solver options. sparse_dms : boolean If averaged density matrices are returned, they will be stored as sparse (Compressed Row Format) matrices during computation if sparse_dms = True (default), and dense matrices otherwise. Dense matrices might be preferable for smaller systems. serial : boolean If True (default is False) the solver will not make use of the multiprocessing module, and simply run in serial. ptrace_sel: list This optional argument specifies a list of components to keep when returning a partially traced density matrix. This can be convenient for large systems where memory becomes a problem, but you are only interested in parts of the density matrix. calc_entropy : boolean If ptrace_sel is specified, calc_entropy=True will have the solver return the averaged entropy over trajectories in results.entropy. This can be interpreted as a measure of entanglement. See Phys. Rev. Lett. 93, 120408 (2004), Phys. Rev. A 86, 022310 (2012). Returns ------- results : Result Object storing all results from simulation. """ if ntraj is None: ntraj = options.ntraj if psi0.type != 'ket': raise Exception("Initial state must be a state vector.") config.options = options # set num_cpus to the value given in qutip.settings # if none in Options if not config.options.num_cpus: config.options.num_cpus = qutip.settings.num_cpus # set initial value data if options.tidy: config.psi0 = psi0.tidyup(options.atol).full() else: config.psi0 = psi0.full() config.psi0_dims = psi0.dims config.psi0_shape = psi0.shape # set general items config.tlist = tlist if isinstance(ntraj, (list, np.ndarray)): raise Exception("ntraj as list argument is not supported.") else: config.ntraj = ntraj # ntraj_list = [ntraj] # set norm finding constants config.norm_tol = options.norm_tol config.norm_steps = options.norm_steps if not options.rhs_reuse: config.soft_reset() # no time dependence config.tflag = 0 # check for collapse operators if len(c_ops) > 0: config.cflag = 1 else: config.cflag = 0 # Configure data _mc_data_config(H, psi0, [], c_ops, [], [], e_ops, options, config) # Load Monte Carlo class mc = _MC_class() # Set solver type if (options.method == 'adams'): mc.mf = 10 elif (options.method == 'bdf'): mc.mf = 22 else: if debug: print('Unrecognized method for ode solver, using "adams".') mc.mf = 10 # store ket and density matrix dims and shape for convenience mc.psi0_dims = psi0.dims mc.psi0_shape = psi0.shape mc.dm_dims = (psi0 * psi0.dag()).dims mc.dm_shape = (psi0 * psi0.dag()).shape # use sparse density matrices during computation? mc.sparse_dms = sparse_dms # run in serial? mc.serial_run = serial or (ntraj == 1) # are we doing a partial trace for returned states? mc.ptrace_sel = ptrace_sel if (ptrace_sel != []): if debug: print("ptrace_sel set to " + str(ptrace_sel)) print("We are using dense density matrices during computation " + "when performing partial trace. Setting sparse_dms = False") print("This feature is experimental.") mc.sparse_dms = False mc.dm_dims = psi0.ptrace(ptrace_sel).dims mc.dm_shape = psi0.ptrace(ptrace_sel).shape if (calc_entropy): if (ptrace_sel == []): if debug: print("calc_entropy = True, but ptrace_sel = []. Please set " + "a list of components to keep when calculating average" + " entropy of reduced density matrix in ptrace_sel. " + "Setting calc_entropy = False.") calc_entropy = False mc.calc_entropy = calc_entropy # construct output Result object output = Result() # Run mc.run() output.states = mc.sol.states output.expect = mc.sol.expect output.col_times = mc.sol.col_times output.col_which = mc.sol.col_which if (hasattr(mc.sol, 'entropy')): output.entropy = mc.sol.entropy output.solver = 'Fortran 90 Monte Carlo solver' # simulation parameters output.times = config.tlist output.num_expect = config.e_num output.num_collapse = config.c_num output.ntraj = config.ntraj return output
def rhs_generate(H, psi0, tlist, c_ops, e_ops, ntraj=500, args={}, options=Odeoptions(), solver="me", name=None): """ Used to generate the Cython functions for solving the dynamics of a given system before using the parfor function. 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. solver: str String indicating which solver "me" or "mc" name: str Name of generated RHS """ _reset_odeconfig() # clear odeconfig # ------------------------ # GENERATE MCSOLVER DATA # ------------------------ if solver == "mc": odeconfig.tlist = tlist if isinstance(ntraj, (list, ndarray)): odeconfig.ntraj = sort(ntraj)[-1] else: odeconfig.ntraj = ntraj # 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 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) 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) 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) odeconfig.tdfunc = cyq_td_ode_rhs try: os.remove(odeconfig.tdname + ".pyx") except: print("Error removing pyx file. File not found.") # ------------------------ # GENERATE MESOLVER STUFF # ------------------------ elif solver == "me": odeconfig.tdname = "rhs" + str(odeconfig.cgen_num) cgen = Codegen(h_terms=n_L_terms, h_tdterms=Lcoeff, args=args) cgen.generate(odeconfig.tdname + ".pyx") os.environ["CFLAGS"] = "-O3 -w" import pyximport pyximport.install(setup_args={"include_dirs": [numpy.get_include()]}) code = compile("from " + odeconfig.tdname + " import cyq_td_ode_rhs", "<string>", "exec") exec(code) odeconfig.tdfunc = cyq_td_ode_rhs
def mcsolve_f90(H, psi0, tlist, c_ops, e_ops, ntraj=None, options=Odeoptions(), sparse_dms=True, serial=False, ptrace_sel=[], calc_entropy=False): """ Monte-Carlo wave function solver with fortran 90 backend. Usage is identical to qutip.mcsolve, for problems without explicit time-dependence, and with some optional input: 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. options : Odeoptions Instance of ODE solver options. sparse_dms : boolean If averaged density matrices are returned, they will be stored as sparse (Compressed Row Format) matrices during computation if sparse_dms = True (default), and dense matrices otherwise. Dense matrices might be preferable for smaller systems. serial : boolean If True (default is False) the solver will not make use of the multiprocessing module, and simply run in serial. ptrace_sel: list This optional argument specifies a list of components to keep when returning a partially traced density matrix. This can be convenient for large systems where memory becomes a problem, but you are only interested in parts of the density matrix. calc_entropy : boolean If ptrace_sel is specified, calc_entropy=True will have the solver return the averaged entropy over trajectories in results.entropy. This can be interpreted as a measure of entanglement. See Phys. Rev. Lett. 93, 120408 (2004), Phys. Rev. A 86, 022310 (2012). Returns ------- results : Odedata Object storing all results from simulation. """ if ntraj is None: ntraj = options.ntraj 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, np.ndarray)): raise Exception("ntraj as list argument is not supported.") else: odeconfig.ntraj = ntraj # ntraj_list = [ntraj] # set norm finding constants odeconfig.norm_tol = options.norm_tol odeconfig.norm_steps = options.norm_steps if not options.rhs_reuse: odeconfig.soft_reset() # no time dependence odeconfig.tflag = 0 # check for collapse operators if len(c_ops) > 0: odeconfig.cflag = 1 else: odeconfig.cflag = 0 # Configure data _mc_data_config(H, psi0, [], c_ops, [], [], e_ops, options, odeconfig) # Load Monte Carlo class mc = _MC_class() # Set solver type if (options.method == 'adams'): mc.mf = 10 elif (options.method == 'bdf'): mc.mf = 22 else: if debug: print('Unrecognized method for ode solver, using "adams".') mc.mf = 10 # store ket and density matrix dims and shape for convenience mc.psi0_dims = psi0.dims mc.psi0_shape = psi0.shape mc.dm_dims = (psi0 * psi0.dag()).dims mc.dm_shape = (psi0 * psi0.dag()).shape # use sparse density matrices during computation? mc.sparse_dms = sparse_dms # run in serial? mc.serial_run = serial or (ntraj == 1) # are we doing a partial trace for returned states? mc.ptrace_sel = ptrace_sel if (ptrace_sel != []): if debug: print("ptrace_sel set to " + str(ptrace_sel)) print("We are using dense density matrices during computation " + "when performing partial trace. Setting sparse_dms = False") print("This feature is experimental.") mc.sparse_dms = False mc.dm_dims = psi0.ptrace(ptrace_sel).dims mc.dm_shape = psi0.ptrace(ptrace_sel).shape if (calc_entropy): if (ptrace_sel == []): if debug: print("calc_entropy = True, but ptrace_sel = []. Please set " + "a list of components to keep when calculating average " + "entropy of reduced density matrix in ptrace_sel. " + "Setting calc_entropy = False.") calc_entropy = False mc.calc_entropy = calc_entropy # construct output Odedata object output = Odedata() # Run mc.run() output.states = mc.sol.states output.expect = mc.sol.expect output.col_times = mc.sol.col_times output.col_which = mc.sol.col_which if (hasattr(mc.sol, 'entropy')): output.entropy = mc.sol.entropy output.solver = 'Fortran 90 Monte Carlo solver' # simulation parameters output.times = odeconfig.tlist output.num_expect = odeconfig.e_num output.num_collapse = odeconfig.c_num output.ntraj = odeconfig.ntraj return output
def rhs_generate(H, psi0, tlist, c_ops, e_ops, ntraj=500, args={}, options=Odeoptions(), solver='me', name=None): """ Used to generate the Cython functions for solving the dynamics of a given system before using the parfor function. 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. solver: str String indicating which solver "me" or "mc" name: str Name of generated RHS """ _reset_odeconfig() #clear odeconfig #------------------------ # GENERATE MCSOLVER DATA #------------------------ if solver == 'mc': odeconfig.tlist = tlist if isinstance(ntraj, (list, ndarray)): odeconfig.ntraj = sort(ntraj)[-1] else: odeconfig.ntraj = ntraj #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 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) 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) 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) odeconfig.tdfunc = cyq_td_ode_rhs try: os.remove(odeconfig.tdname + ".pyx") except: print("Error removing pyx file. File not found.") #------------------------ # GENERATE MESOLVER STUFF #------------------------ elif solver == 'me': odeconfig.tdname = "rhs" + str(odeconfig.cgen_num) cgen = Codegen(h_terms=n_L_terms, h_tdterms=Lcoeff, args=args) cgen.generate(odeconfig.tdname + ".pyx") os.environ['CFLAGS'] = '-O3 -w' import pyximport pyximport.install(setup_args={'include_dirs': [numpy.get_include()]}) code = compile('from ' + odeconfig.tdname + ' import cyq_td_ode_rhs', '<string>', 'exec') exec(code) odeconfig.tdfunc = cyq_td_ode_rhs