def d1_psi_heterodyne(A, psi): """ Todo: cythonize .. math:: D_1(\psi, t) = -\\frac{1}{2}(C^\\dagger C - \\langle C^\\dagger \\rangle C + \\frac{1}{2}\\langle C \\rangle\\langle C^\\dagger \\rangle))\psi """ e_C = cy_expect_psi_csr(A[0].data, A[0].indices, A[0].indptr, psi) # e_C B = A[0].T.conj() e_Cd = cy_expect_psi_csr(B.data, B.indices, B.indptr, psi) # e_Cd return (-0.5 * spmv(A[3], psi) + 0.5 * e_Cd * spmv(A[0], psi) - 0.25 * e_C * e_Cd * psi)
def d2_psi_heterodyne(A, psi): """ Todo: cythonize X = \\frac{1}{2}(C + C^\\dagger) Y = \\frac{1}{2}(C - C^\\dagger) D_{2,1}(\psi, t) = \\sqrt(1/2) * (C - \\langle X \\rangle) \\psi D_{2,2}(\psi, t) = -i\\sqrt(1/2) * (C - \\langle Y \\rangle) \\psi """ X = 0.5 * cy_expect_psi_csr(A[1].data, A[1].indices, A[1].indptr, psi) Y = 0.5 * cy_expect_psi_csr(A[2].data, A[2].indices, A[2].indptr, psi) d2_1 = np.sqrt(0.5) * (spmv(A[0], psi) - X * psi) d2_2 = -1.0j * np.sqrt(0.5) * (spmv(A[0], psi) - Y * psi) return [d2_1, d2_2]
def d2_psi_homodyne(A, psi): """ OK Todo: cythonize .. math:: D_2(\psi, t) = (C - \\frac{1}{2}\\langle C + C^\\dagger\\rangle)\\psi """ e1 = cy_expect_psi_csr(A[1].data, A[1].indices, A[1].indptr, psi) return [spmv(A[0], psi) - 0.5 * e1 * psi]
def d1_psi_homodyne(A, psi): """ OK Todo: cythonize .. math:: D_1(\psi, t) = \\frac{1}{2}(\\langle C + C^\\dagger\\rangle\\psi - C^\\dagger C\\psi - \\frac{1}{4}\\langle C + C^\\dagger\\rangle^2\\psi) """ e1 = cy_expect_psi_csr(A[1].data, A[1].indices, A[1].indptr, psi) return 0.5 * (e1 * spmv(A[0], psi) - spmv(A[3], psi) - 0.25 * e1 ** 2 * psi)
def _mc_alg_evolve(nt, config, opt, seeds): """ Monte Carlo algorithm returning state-vector or expectation values at times tlist for a single trajectory. """ global _cy_rhs_func global _cy_col_spmv_func, _cy_col_expect_func global _cy_col_spmv_call_func, _cy_col_expect_call_func tlist = config.tlist num_times = len(tlist) if not _cy_rhs_func: _mc_func_load(config) if config.options.steady_state_average: states_out = np.zeros((1), dtype=object) else: states_out = np.zeros((num_times), dtype=object) temp = sp.csr_matrix( np.reshape(config.psi0, (config.psi0.shape[0], 1)), dtype=complex) if (config.options.average_states and not config.options.steady_state_average): # output is averaged states, so use dm states_out[0] = Qobj(temp*temp.conj().transpose(), [config.psi0_dims[0], config.psi0_dims[0]], [config.psi0_shape[0], config.psi0_shape[0]], fast='mc-dm') elif (not config.options.average_states and not config.options.steady_state_average): # output is not averaged, so write state vectors states_out[0] = Qobj(temp, config.psi0_dims, config.psi0_shape, fast='mc') elif config.options.steady_state_average: states_out[0] = temp * temp.conj().transpose() # PRE-GENERATE LIST FOR EXPECTATION VALUES expect_out = [] for i in range(config.e_num): if config.e_ops_isherm[i]: # preallocate real array of zeros expect_out.append(np.zeros(num_times, dtype=float)) else: # preallocate complex array of zeros expect_out.append(np.zeros(num_times, dtype=complex)) expect_out[i][0] = \ cy_expect_psi_csr(config.e_ops_data[i], config.e_ops_ind[i], config.e_ops_ptr[i], config.psi0, config.e_ops_isherm[i]) collapse_times = [] which_oper = [] # SEED AND RNG AND GENERATE prng = RandomState(seeds[nt]) # first rand is collapse norm, second is which operator rand_vals = prng.rand(2) # CREATE ODE OBJECT CORRESPONDING TO DESIRED TIME-DEPENDENCE if config.tflag in [1, 10, 11]: ODE = ode(_cy_rhs_func) code = compile('ODE.set_f_params(' + config.string + ')', '<string>', 'exec') exec(code) elif config.tflag == 2: ODE = ode(_cRHStd) ODE.set_f_params(config) elif config.tflag in [20, 22]: if config.options.rhs_with_state: ODE = ode(_tdRHStd_with_state) else: ODE = ode(_tdRHStd) ODE.set_f_params(config) elif config.tflag == 3: if config.options.rhs_with_state: ODE = ode(_pyRHSc_with_state) else: ODE = ode(_pyRHSc) ODE.set_f_params(config) else: ODE = ode(_cy_rhs_func) ODE.set_f_params(config.h_data, config.h_ind, config.h_ptr) # initialize ODE solver for RHS ODE._integrator = qutip_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 not len(ODE._y): ODE.t = 0.0 ODE._y = np.array([0.0], complex) ODE._integrator.reset(len(ODE._y), ODE.jac is not None) # set initial conditions ODE.set_initial_value(config.psi0, tlist[0]) # make array for collapse operator inds cinds = np.arange(config.c_num) # RUN ODE UNTIL EACH TIME IN TLIST for k in range(1, num_times): # ODE WHILE LOOP FOR INTEGRATE UP TO TIME TLIST[k] while ODE.t < tlist[k]: t_prev = ODE.t y_prev = ODE.y norm2_prev = dznrm2(ODE._y) ** 2 # integrate up to tlist[k], one step at a time. ODE.integrate(tlist[k], step=1) if not ODE.successful(): raise Exception("ZVODE failed!") norm2_psi = dznrm2(ODE._y) ** 2 if norm2_psi <= rand_vals[0]: # collapse has occured: # find collapse time to within specified tolerance # ------------------------------------------------ ii = 0 t_final = ODE.t while ii < config.norm_steps: ii += 1 t_guess = t_prev + \ np.log(norm2_prev / rand_vals[0]) / \ np.log(norm2_prev / norm2_psi) * (t_final - t_prev) ODE._y = y_prev ODE.t = t_prev ODE._integrator.call_args[3] = 1 ODE.integrate(t_guess, step=0) if not ODE.successful(): raise Exception( "ZVODE failed after adjusting step size!") norm2_guess = dznrm2(ODE._y)**2 if (np.abs(rand_vals[0] - norm2_guess) < config.norm_tol * rand_vals[0]): break elif (norm2_guess < rand_vals[0]): # t_guess is still > t_jump t_final = t_guess norm2_psi = norm2_guess else: # t_guess < t_jump t_prev = t_guess y_prev = ODE.y norm2_prev = norm2_guess if ii > config.norm_steps: raise Exception("Norm tolerance not reached. " + "Increase accuracy of ODE solver or " + "Options.norm_steps.") collapse_times.append(ODE.t) # some string based collapse operators if config.tflag in [1, 11]: n_dp = [cy_expect_psi_csr(config.n_ops_data[i], config.n_ops_ind[i], config.n_ops_ptr[i], ODE._y, 1) for i in config.c_const_inds] _locals = locals() # calculates the expectation values for time-dependent # norm collapse operators exec(_cy_col_expect_call_func, globals(), _locals) n_dp = np.array(_locals['n_dp']) elif config.tflag in [2, 20, 22]: # some Python function based collapse operators n_dp = [cy_expect_psi_csr(config.n_ops_data[i], config.n_ops_ind[i], config.n_ops_ptr[i], ODE._y, 1) for i in config.c_const_inds] n_dp += [abs(config.c_funcs[i]( ODE.t, config.c_func_args)) ** 2 * cy_expect_psi_csr(config.n_ops_data[i], config.n_ops_ind[i], config.n_ops_ptr[i], ODE._y, 1) for i in config.c_td_inds] n_dp = np.array(n_dp) else: # all constant collapse operators. n_dp = np.array( [cy_expect_psi_csr(config.n_ops_data[i], config.n_ops_ind[i], config.n_ops_ptr[i], ODE._y, 1) for i in range(config.c_num)]) # determine which operator does collapse and store it kk = np.cumsum(n_dp / np.sum(n_dp)) j = cinds[kk >= rand_vals[1]][0] which_oper.append(j) if j in config.c_const_inds: state = spmv_csr(config.c_ops_data[j], config.c_ops_ind[j], config.c_ops_ptr[j], ODE._y) else: if config.tflag in [1, 11]: _locals = locals() # calculates the state vector for collapse by a # time-dependent collapse operator exec(_cy_col_spmv_call_func, globals(), _locals) state = _locals['state'] else: state = \ config.c_funcs[j](ODE.t, config.c_func_args) * \ spmv_csr(config.c_ops_data[j], config.c_ops_ind[j], config.c_ops_ptr[j], ODE._y) state = state / dznrm2(state) ODE._y = state ODE._integrator.call_args[3] = 1 rand_vals = prng.rand(2) # after while loop # ---------------- out_psi = ODE._y / dznrm2(ODE._y) if config.e_num == 0 or config.options.store_states: out_psi_csr = sp.csr_matrix(np.reshape(out_psi, (out_psi.shape[0], 1)), dtype=complex) if (config.options.average_states and not config.options.steady_state_average): states_out[k] = Qobj( out_psi_csr * out_psi_csr.conj().transpose(), [config.psi0_dims[0], config.psi0_dims[0]], [config.psi0_shape[0], config.psi0_shape[0]], fast='mc-dm') elif config.options.steady_state_average: states_out[0] = ( states_out[0] + (out_psi_csr * out_psi_csr.conj().transpose())) else: states_out[k] = Qobj(out_psi_csr, config.psi0_dims, config.psi0_shape, fast='mc') for jj in range(config.e_num): expect_out[jj][k] = cy_expect_psi_csr( config.e_ops_data[jj], config.e_ops_ind[jj], config.e_ops_ptr[jj], out_psi, config.e_ops_isherm[jj]) # Run at end of mc_alg function # ----------------------------- if config.options.steady_state_average: states_out = np.array([Qobj(states_out[0] / float(len(tlist)), [config.psi0_dims[0], config.psi0_dims[0]], [config.psi0_shape[0], config.psi0_shape[0]], fast='mc-dm')]) return (states_out, expect_out, np.array(collapse_times, dtype=float), np.array(which_oper, dtype=int))
def _evolve_no_collapse_expect_out(config): """ Calculates expect.values at times tlist if no collapse ops. given """ global _cy_rhs_func global _cy_col_spmv_func, _cy_col_expect_func global _cy_col_spmv_call_func, _cy_col_expect_call_func if debug: print(inspect.stack()[0][3]) num_times = len(config.tlist) expect_out = [] for i in range(config.e_num): if config.e_ops_isherm[i]: # preallocate real array of zeros expect_out.append(np.zeros(num_times, dtype=float)) else: # preallocate complex array of zeros expect_out.append(np.zeros(num_times, dtype=complex)) expect_out[i][0] = \ cy_expect_psi_csr(config.e_ops_data[i], config.e_ops_ind[i], config.e_ops_ptr[i], config.psi0, config.e_ops_isherm[i]) if not _cy_rhs_func: _mc_func_load(config) opt = config.options if config.tflag in [1, 10, 11]: ODE = ode(_cy_rhs_func) code = compile('ODE.set_f_params(' + config.string + ')', '<string>', 'exec') exec(code) elif config.tflag == 2: ODE = ode(_cRHStd) ODE.set_f_params(config) elif config.tflag in [20, 22]: if config.options.rhs_with_state: ODE = ode(_tdRHStd_with_state) else: ODE = ode(_tdRHStd) ODE.set_f_params(config) elif config.tflag == 3: if config.options.rhs_with_state: ODE = ode(_pyRHSc_with_state) else: ODE = ode(_pyRHSc) ODE.set_f_params(config) else: ODE = ode(cy_ode_rhs) ODE.set_f_params(config.h_data, config.h_ind, config.h_ptr) ODE.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) ODE.set_initial_value(config.psi0, config.tlist[0]) for jj in range(config.e_num): expect_out[jj][0] = cy_expect_psi_csr( config.e_ops_data[jj], config.e_ops_ind[jj], config.e_ops_ptr[jj], config.psi0, config.e_ops_isherm[jj]) for k in range(1, num_times): ODE.integrate(config.tlist[k], step=0) # integrate up to tlist[k] if ODE.successful(): state = ODE.y / dznrm2(ODE.y) for jj in range(config.e_num): expect_out[jj][k] = cy_expect_psi_csr( config.e_ops_data[jj], config.e_ops_ind[jj], config.e_ops_ptr[jj], state, config.e_ops_isherm[jj]) else: raise ValueError('Error in ODE solver') return expect_out
def _ssepdpsolve_single_trajectory(data, Heff, dt, times, N_store, N_substeps, psi_t, dims, c_ops, e_ops): """ Internal function. See ssepdpsolve. """ states_list = [] phi_t = np.copy(psi_t) prng = RandomState() # todo: seed it r_jump, r_op = prng.rand(2) jump_times = [] jump_op_idx = [] for t_idx, t in enumerate(times): if e_ops: for e_idx, e in enumerate(e_ops): s = cy_expect_psi_csr(e.data.data, e.data.indices, e.data.indptr, psi_t, 0) data.expect[e_idx, t_idx] += s data.ss[e_idx, t_idx] += s**2 else: states_list.append(Qobj(psi_t, dims=dims)) for j in range(N_substeps): if norm(phi_t)**2 < r_jump: # jump occurs p = np.array([norm(c.data * psi_t)**2 for c in c_ops]) p = np.cumsum(p / np.sum(p)) n = np.where(p >= r_op)[0][0] # apply jump psi_t = c_ops[n].data * psi_t psi_t /= norm(psi_t) phi_t = np.copy(psi_t) # store info about jump jump_times.append(times[t_idx] + dt * j) jump_op_idx.append(n) # get new random numbers for next jump r_jump, r_op = prng.rand(2) # deterministic evolution wihtout correction for norm decay dphi_t = (-1.0j * dt) * (Heff.data * phi_t) # deterministic evolution with correction for norm decay dpsi_t = (-1.0j * dt) * (Heff.data * psi_t) A = 0.5 * np.sum([norm(c.data * psi_t)**2 for c in c_ops]) dpsi_t += dt * A * psi_t # increment wavefunctions phi_t += dphi_t psi_t += dpsi_t # ensure that normalized wavefunction remains normalized # this allows larger time step than otherwise would be possible psi_t /= norm(psi_t) return states_list, jump_times, jump_op_idx
def _mc_alg_evolve(nt, args, config): """ Monte-Carlo algorithm returning state-vector or expectation values at times tlist for a single trajectory. """ global _cy_rhs_func global _cy_col_spmv_func, _cy_col_expect_func global _cy_col_spmv_call_func, _cy_col_expect_call_func if not _cy_rhs_func: _mc_func_load(config) try: # get input data mc_alg_out, opt, tlist, num_times, seeds = args collapse_times = [] # times of collapses which_oper = [] # which operator did the collapse # SEED AND RNG AND GENERATE prng = RandomState(seeds[nt]) # first rand is collapse norm, second is which operator rand_vals = prng.rand(2) # CREATE ODE OBJECT CORRESPONDING TO DESIRED TIME-DEPENDENCE if config.tflag in array([1, 10, 11]): ODE = ode(_cy_rhs_func) code = compile("ODE.set_f_params(" + config.string + ")", "<string>", "exec") exec(code) elif config.tflag == 2: ODE = ode(_cRHStd) ODE.set_f_params(config) elif config.tflag in array([20, 22]): if config.options.rhs_with_state: ODE = ode(_tdRHStd_with_state) else: ODE = ode(_tdRHStd) ODE.set_f_params(config) elif config.tflag == 3: if config.options.rhs_with_state: ODE = ode(_pyRHSc_with_state) else: ODE = ode(_pyRHSc) ODE.set_f_params(config) else: ODE = ode(_cy_rhs_func) ODE.set_f_params(config.h_data, config.h_ind, config.h_ptr) # initialize ODE solver for RHS ODE.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, ) # set initial conditions ODE.set_initial_value(config.psi0, tlist[0]) # make array for collapse operator inds cinds = np.arange(config.c_num) # RUN ODE UNTIL EACH TIME IN TLIST for k in range(1, num_times): # ODE WHILE LOOP FOR INTEGRATE UP TO TIME TLIST[k] while ODE.t < tlist[k]: t_prev = ODE.t y_prev = ODE.y norm2_prev = dznrm2(ODE.y) ** 2 # integrate up to tlist[k], one step at a time. ODE.integrate(tlist[k], step=1) if not ODE.successful(): raise Exception("ZVODE failed!") # check if ODE jumped over tlist[k], if so, # integrate until tlist exactly if ODE.t > tlist[k]: ODE.set_initial_value(y_prev, t_prev) ODE.integrate(tlist[k], step=0) if not ODE.successful(): raise Exception("ZVODE failed!") norm2_psi = dznrm2(ODE.y) ** 2 if norm2_psi <= rand_vals[0]: # <== collapse has occured # find collapse time to within specified tolerance # --------------------------------------------------- ii = 0 t_final = ODE.t while ii < config.norm_steps: ii += 1 t_guess = t_prev + np.log(norm2_prev / rand_vals[0]) / np.log(norm2_prev / norm2_psi) * ( t_final - t_prev ) ODE.set_initial_value(y_prev, t_prev) ODE.integrate(t_guess, step=0) if not ODE.successful(): raise Exception("ZVODE failed after adjusting step size!") norm2_guess = dznrm2(ODE.y) ** 2 if np.abs(rand_vals[0] - norm2_guess) < config.norm_tol * rand_vals[0]: break elif norm2_guess < rand_vals[0]: # t_guess is still > t_jump t_final = t_guess norm2_psi = norm2_guess else: # t_guess < t_jump t_prev = t_guess y_prev = ODE.y norm2_prev = norm2_guess if ii > config.norm_steps: raise Exception( "Norm tolerance not reached. " + "Increase accuracy of ODE solver or " + "Options.norm_steps." ) # --------------------------------------------------- collapse_times.append(ODE.t) # some string based collapse operators if config.tflag in array([1, 11]): n_dp = [ cy_expect_psi_csr(config.n_ops_data[i], config.n_ops_ind[i], config.n_ops_ptr[i], ODE.y, 1) for i in config.c_const_inds ] _locals = locals() # calculates the expectation values for time-dependent # norm collapse operators exec(_cy_col_expect_call_func, globals(), _locals) n_dp = array(_locals["n_dp"]) # some Python function based collapse operators elif config.tflag in array([2, 20, 22]): n_dp = [ cy_expect_psi_csr(config.n_ops_data[i], config.n_ops_ind[i], config.n_ops_ptr[i], ODE.y, 1) for i in config.c_const_inds ] n_dp += [ abs(config.c_funcs[i](ODE.t, config.c_func_args)) ** 2 * cy_expect_psi_csr( config.n_ops_data[i], config.n_ops_ind[i], config.n_ops_ptr[i], ODE.y, 1 ) for i in config.c_td_inds ] n_dp = array(n_dp) # all constant collapse operators. else: n_dp = array( [ cy_expect_psi_csr( config.n_ops_data[i], config.n_ops_ind[i], config.n_ops_ptr[i], ODE.y, 1 ) for i in range(config.c_num) ] ) # determine which operator does collapse and store it kk = cumsum(n_dp / sum(n_dp)) j = cinds[kk >= rand_vals[1]][0] which_oper.append(j) if j in config.c_const_inds: state = spmv_csr(config.c_ops_data[j], config.c_ops_ind[j], config.c_ops_ptr[j], ODE.y) else: if config.tflag in array([1, 11]): _locals = locals() # calculates the state vector for collapse by a # time-dependent collapse operator exec(_cy_col_spmv_call_func, globals(), _locals) state = _locals["state"] else: state = config.c_funcs[j](ODE.t, config.c_func_args) * spmv_csr( config.c_ops_data[j], config.c_ops_ind[j], config.c_ops_ptr[j], ODE.y ) state = state / dznrm2(state) ODE.set_initial_value(state, ODE.t) rand_vals = prng.rand(2) # ------------------------------------------------------- # -- after while loop -- out_psi = ODE.y / dznrm2(ODE.y) if config.e_num == 0: out_psi = sp.csr_matrix(np.reshape(out_psi, (out_psi.shape[0], 1)), dtype=complex) if config.options.average_states and not config.options.steady_state_average: mc_alg_out[k] = Qobj( out_psi * out_psi.conj().transpose(), [config.psi0_dims[0], config.psi0_dims[0]], [config.psi0_shape[0], config.psi0_shape[0]], fast="mc-dm", ) elif config.options.steady_state_average: mc_alg_out[0] = mc_alg_out[0] + (out_psi * out_psi.conj().transpose()) else: mc_alg_out[k] = Qobj(out_psi, config.psi0_dims, config.psi0_shape, fast="mc") else: for jj in range(config.e_num): mc_alg_out[jj][k] = cy_expect_psi_csr( config.e_ops_data[jj], config.e_ops_ind[jj], config.e_ops_ptr[jj], out_psi, config.e_ops_isherm[jj], ) # Run at end of mc_alg function # ------------------------------ if config.options.steady_state_average: mc_alg_out = array( [ Qobj( mc_alg_out[0] / float(len(tlist)), [config.psi0_dims[0], config.psi0_dims[0]], [config.psi0_shape[0], config.psi0_shape[0]], fast="mc-dm", ) ] ) return (nt, mc_alg_out, np.array(collapse_times, dtype=float), np.array(which_oper, dtype=int)) except Exception as e: print("failed to run _mc_alg_evolve: " + str(e))
def _no_collapse_expect_out(num_times, expect_out, config): """ Calculates expect.values at times tlist if no collapse ops. given """ global _cy_rhs_func global _cy_col_spmv_func, _cy_col_expect_func global _cy_col_spmv_call_func, _cy_col_expect_call_func if debug: print(inspect.stack()[0][3]) if not _cy_rhs_func: _mc_func_load(config) opt = config.options if config.tflag in array([1, 10, 11]): ODE = ode(_cy_rhs_func) code = compile("ODE.set_f_params(" + config.string + ")", "<string>", "exec") exec(code) elif config.tflag == 2: ODE = ode(_cRHStd) ODE.set_f_params(config) elif config.tflag in array([20, 22]): if config.options.rhs_with_state: ODE = ode(_tdRHStd_with_state) else: ODE = ode(_tdRHStd) ODE.set_f_params(config) elif config.tflag == 3: if config.options.rhs_with_state: ODE = ode(_pyRHSc_with_state) else: ODE = ode(_pyRHSc) ODE.set_f_params(config) else: ODE = ode(cy_ode_rhs) ODE.set_f_params(config.h_data, config.h_ind, config.h_ptr) ODE.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, ) ODE.set_initial_value(config.psi0, config.tlist[0]) for jj in range(config.e_num): expect_out[jj][0] = cy_expect_psi_csr( config.e_ops_data[jj], config.e_ops_ind[jj], config.e_ops_ptr[jj], config.psi0, config.e_ops_isherm[jj] ) for k in range(1, num_times): ODE.integrate(config.tlist[k], step=0) # integrate up to tlist[k] if ODE.successful(): state = ODE.y / dznrm2(ODE.y) for jj in range(config.e_num): expect_out[jj][k] = cy_expect_psi_csr( config.e_ops_data[jj], config.e_ops_ind[jj], config.e_ops_ptr[jj], state, config.e_ops_isherm[jj] ) else: raise ValueError("Error in ODE solver") return expect_out
def run(self): if debug: print(inspect.stack()[0][3]) if self.config.c_num == 0: if self.config.ntraj != 1: # ntraj != 1 is pointless for no collapse operators self.config.ntraj = 1 if self.config.e_num == 0: # return psi at each requested time self.psi_out = _no_collapse_psi_out(self.num_times, self.psi_out, self.config) else: # return expectation values of requested operators self.expect_out = _no_collapse_expect_out(self.num_times, self.expect_out, self.config) elif self.config.c_num != 0: if self.seeds is None: self.seeds = random_integers(1e8, size=self.config.ntraj) # else: # if len(self.seeds) != self.config.ntraj: # raise "Incompatible size of seeds vector in config." if self.config.e_num == 0: if config.options.steady_state_average: mc_alg_out = zeros((1), dtype=object) else: mc_alg_out = zeros((self.num_times), dtype=object) temp = sp.csr_matrix(np.reshape(self.config.psi0, (self.config.psi0.shape[0], 1)), dtype=complex) if self.config.options.average_states and not config.options.steady_state_average: # output is averaged states, so use dm mc_alg_out[0] = Qobj( temp * temp.conj().transpose(), [config.psi0_dims[0], config.psi0_dims[0]], [config.psi0_shape[0], config.psi0_shape[0]], fast="mc-dm", ) elif not self.config.options.average_states and not config.options.steady_state_average: # output is not averaged, so write state vectors mc_alg_out[0] = Qobj(temp, config.psi0_dims, config.psi0_shape, fast="mc") elif config.options.steady_state_average: mc_alg_out[0] = temp * temp.conj().transpose() else: # PRE-GENERATE LIST OF EXPECTATION VALUES mc_alg_out = [] for i in range(self.config.e_num): if self.config.e_ops_isherm[i]: # preallocate real array of zeros mc_alg_out.append(zeros(self.num_times, dtype=float)) else: # preallocate complex array of zeros mc_alg_out.append(zeros(self.num_times, dtype=complex)) mc_alg_out[i][0] = cy_expect_psi_csr( self.config.e_ops_data[i], self.config.e_ops_ind[i], self.config.e_ops_ptr[i], self.config.psi0, self.config.e_ops_isherm[i], ) # set arguments for input to monte-carlo args = (mc_alg_out, self.config.options, self.config.tlist, self.num_times, self.seeds) self.config.progress_bar.start(self.config.ntraj) self.parallel(args, self) self.config.progress_bar.finished()
def __init__(self, config): # ----------------------------------- # INIT MC CLASS # ----------------------------------- self.config = config # ----MAIN OBJECT PROPERTIES-------------------- # holds instance of the ProgressBar class self.bar = None # holds instance of the Pthread class self.thread = None # Number of completed trajectories self.count = 0 # step-size for count attribute self.step = 1 # Percent of trajectories completed self.percent = 0.0 # used in implimenting the command line progress ouput self.level = 0.1 # times at which to output state vectors or expectation values # number of time steps in tlist self.num_times = len(self.config.tlist) # holds seed for random number generator self.seeds = self.config.options.seeds # number of cpus to be used self.cpus = self.config.options.num_cpus # set output variables, even if they are not used to simplify output # code. self.psi_out = None self.expect_out = [] self.collapse_times_out = None self.which_op_out = None # FOR EVOLUTION FOR NO COLLAPSE OPERATORS if config.c_num == 0: if config.e_num == 0: # Output array of state vectors calculated at times in tlist self.psi_out = array([Qobj()] * self.num_times) elif config.e_num != 0: # no collapse expectation values # List of output expectation values calculated at times in # tlist self.expect_out = [] for i in range(config.e_num): if config.e_ops_isherm[i]: # preallocate real array of zeros self.expect_out.append(zeros(self.num_times, dtype=float)) else: # preallocate complex array of zeros self.expect_out.append(zeros(self.num_times, dtype=complex)) self.expect_out[i][0] = cy_expect_psi_csr( config.e_ops_data[i], config.e_ops_ind[i], config.e_ops_ptr[i], config.psi0, config.e_ops_isherm[i], ) # FOR EVOLUTION WITH COLLAPSE OPERATORS elif config.c_num != 0: # preallocate #ntraj arrays for state vectors, collapse times, and # which operator self.collapse_times_out = zeros((config.ntraj), dtype=ndarray) self.which_op_out = zeros((config.ntraj), dtype=ndarray) if config.e_num == 0: # if no expectation operators, preallocate #ntraj arrays # for state vectors if self.config.options.steady_state_average: self.psi_out = array([zeros((1), dtype=object) for q in range(config.ntraj)]) else: self.psi_out = array([zeros((self.num_times), dtype=object) for q in range(config.ntraj)]) else: # preallocate array of lists for expectation values self.expect_out = [[] for x in range(config.ntraj)]
def _sepdpsolve_single_trajectory(data, Heff, dt, tlist, N_store, N_substeps, psi_t, c_ops, e_ops): """ Internal function. """ states_list = [] phi_t = np.copy(psi_t) prng = RandomState() # todo: seed it r_jump, r_op = prng.rand(2) jump_times = [] jump_op_idx = [] for t_idx, t in enumerate(tlist): if e_ops: for e_idx, e in enumerate(e_ops): s = cy_expect_psi_csr( e.data.data, e.data.indices, e.data.indptr, psi_t) data.expect[e_idx, t_idx] += s data.ss[e_idx, t_idx] += s ** 2 else: states_list.append(Qobj(psi_t)) for j in range(N_substeps): if norm(phi_t) ** 2 < r_jump: # jump occurs p = np.array([norm(c.data * psi_t) ** 2 for c in c_ops]) p = np.cumsum(p / np.sum(p)) n = np.where(p >= r_op)[0][0] # apply jump psi_t = c_ops[n].data * psi_t psi_t /= norm(psi_t) phi_t = np.copy(psi_t) # store info about jump jump_times.append(tlist[t_idx] + dt * j) jump_op_idx.append(n) # get new random numbers for next jump r_jump, r_op = prng.rand(2) # deterministic evolution wihtout correction for norm decay dphi_t = (-1.0j * dt) * (Heff.data * phi_t) # deterministic evolution with correction for norm decay dpsi_t = (-1.0j * dt) * (Heff.data * psi_t) A = 0.5 * np.sum([norm(c.data * psi_t) ** 2 for c in c_ops]) dpsi_t += dt * A * psi_t # increment wavefunctions phi_t += dphi_t psi_t += dpsi_t # ensure that normalized wavefunction remains normalized # this allows larger time step than otherwise would be possible psi_t /= norm(psi_t) return states_list, jump_times, jump_op_idx
def _ssesolve_single_trajectory(data, H, dt, tlist, N_store, N_substeps, psi_t, A_ops, e_ops, m_ops, rhs, d1, d2, d2_len, dW_factors, homogeneous, distribution, args, store_measurement=False, noise=None, normalize=True): """ Internal function. See ssesolve. """ if noise is None: if homogeneous: if distribution == 'normal': dW = np.sqrt( dt) * scipy.randn(len(A_ops), N_store, N_substeps, d2_len) else: raise TypeError('Unsupported increment distribution for homogeneous process.') else: if distribution != 'poisson': raise TypeError('Unsupported increment distribution for inhomogeneous process.') dW = np.zeros((len(A_ops), N_store, N_substeps, d2_len)) else: dW = noise states_list = [] measurements = np.zeros((len(tlist), len(m_ops), d2_len), dtype=complex) for t_idx, t in enumerate(tlist): if e_ops: for e_idx, e in enumerate(e_ops): s = cy_expect_psi_csr(e.data.data, e.data.indices, e.data.indptr, psi_t, 0) data.expect[e_idx, t_idx] += s data.ss[e_idx, t_idx] += s ** 2 else: states_list.append(Qobj(psi_t)) psi_prev = np.copy(psi_t) for j in range(N_substeps): if noise is None and not homogeneous: for a_idx, A in enumerate(A_ops): dw_expect = norm(spmv(A[0], psi_t)) ** 2 * dt dW[a_idx, t_idx, j, :] = np.random.poisson(dw_expect, d2_len) psi_t = rhs(H.data, psi_t, t + dt * j, A_ops, dt, dW[:, t_idx, j, :], d1, d2, args) # optionally renormalize the wave function if normalize: psi_t /= norm(psi_t) if store_measurement: for m_idx, m in enumerate(m_ops): for dW_idx, dW_factor in enumerate(dW_factors): if m[dW_idx]: m_expt = norm(spmv(m[dW_idx].data, psi_prev)) ** 2 else: m_expt = 0 measurements[t_idx, m_idx, dW_idx] = (m_expt + dW_factor * dW[m_idx, t_idx, :, dW_idx].sum() / (dt * N_substeps)) if d2_len == 1: measurements = measurements.squeeze(axis=(2)) return states_list, dW, measurements