def anneal_bath_4(L,Nb,T,gamma=0.2,omega=1.0,path="."): ti = time.time() filename = os.path.join(path,"spin_bath_exact_L_{}_Nb_{}_T_{}_gamma_{}_omega_{}.npz".format(L,Nb,T,gamma,omega)) if os.path.isfile(filename): print "file_exists...exiting run." exit() if Nb%2 == 1: S = "{}/2".format(Nb) else: S = "{}".format(Nb//2) print "creating basis" spin_basis = spin_basis_1d(L,pauli=True,kblock=0,pblock=1) bath_basis = spin_basis_1d(1,S=S) basis = tensor_basis(spin_basis,bath_basis) print "L={}, H-space size: {}".format(L,basis.Ns) bath_energy=[[-omega/Nb,0,0]] SB_1_list = [[-gamma/Nb,i,0] for i in range(L)] SB_2_list = [[-gamma/np.sqrt(Nb),i,0] for i in range(L)] B_h_list = [[-1,0]] h_list = [[-1,i] for i in range(L)] J_list = [[-1,i,(i+1)%L] for i in range(L)] A = lambda t:(t/T)**2 B = lambda t:(1-t/T)**2 static = [ ["+|-",SB_2_list], ["-|+",SB_2_list], ] dynamic = [ ["x|",h_list,B,()], ["|+",B_h_list,B,()], ["|-",B_h_list,B,()], ["zz|",J_list,A,()], ["z|z",SB_1_list,A,()], ["|zz",bath_energy,A,()], ] print "creating hamiltonian" kwargs=dict(basis=basis,dtype=np.float64, check_symm=False,check_pcon=False,check_herm=False) H = hamiltonian(static,dynamic,**kwargs) print "solving initial state" E0,psi_0 = H.eigsh(k=1,which="SA",time=0) psi_0 = psi_0.ravel() print "evolving" out = np.zeros(psi_0.shape,dtype=np.complex128) psi_f = evolve(psi_0,0,T,H._hamiltonian__omp_SO,f_params = (out,),solver_name="dop853",atol=1.1e-10,rtol=1.1e-10) print "saving" np.savez_compressed(filename,psi=psi_f) print "dome......{} sec".format(time.time()-ti)
# dynamic single-particle for func,Hd in H.dynamic.items(): V_dot[:Ns] += func(time)*Hd.dot(V[Ns:]) V_dot[Ns:] -= func(time)*Hd.dot(V[:Ns]) return V_dot ##### time evolutino t=Floquet_t_vec(Omega,20,len_T=1) for stack_state in [0,1]: y_genevolve = evolve(V[:,0],t.i,t.f,SO_real,real=True,stack_state=True,f_params=(H,)) y = H.evolve(V[:,0],t.i,t.f,stack_state=stack_state) np.testing.assert_allclose(y-y_genevolve,0.0,atol=1E-6,err_msg='Failed evolve_scalar comparison!') y_genevolve = evolve(V[:,0],t.i,t.vals,SO_real,real=True,stack_state=True,f_params=(H,)) y = H.evolve(V[:,0],t.i,t.vals,stack_state=stack_state) np.testing.assert_allclose(y-y_genevolve,0.0,atol=1E-6,err_msg='Failed evolve_list comparison!') y_genevolve = evolve(V[:,0],t.i,t.vals,SO_real,real=True,stack_state=True,iterate=True,f_params=(H,)) y = H.evolve(V[:,0],t.i,t.vals,iterate=True,stack_state=stack_state)
def anneal_bath(L, T, gamma=0.01, path="."): ti = time.time() filename = os.path.join( path, "spin_bath_exact_L_{}_T_{}_gamma_{}.npz".format(L, T, gamma)) if os.path.isfile(filename): print "file_exists...exiting run." exit() N = 2 * L Tx = (np.arange(L) + 1) % L Tx = np.hstack((Tx, Tx + L)) P = np.arange(L)[::-1] P = np.hstack((P, P + L)) print "creating basis" basis = spin_basis_general(N, pblk=(P, 0), kblk=(Tx, 0)) print "L={}, H-space size: {}".format(L, basis.Ns) Jzz_list = [[-1, i, (i + 1) % L] for i in range(L)] hx_list = [[-1, i] for i in range(L)] hop_bath_list = [[-1.0, L + i, L + (i + 1) % L] for i in range(L)] hop_bath_list += [[-1.0, L + i, L + (i + 1) % L] for i in range(L)] int_2_list = [[1.0, L + i, L + (i + 1) % L] for i in range(L)] int_2_list += [[1.0, L + i, L + (i + 2) % L] for i in range(L)] int_1_list = [[2.0, L + i] for i in range(L)] bath_sys_list = [[gamma, i, i + L] for i in range(L)] Jb_list = [[gamma, i, L + i] for i in range(L)] A = lambda t: (t / T)**2 B = lambda t: (1 - t / T)**2 static = [["+-", hop_bath_list], ["-+", hop_bath_list], ["zz", int_2_list], ["z", int_1_list]] dynamic = [ ["zz", Jzz_list, A, ()], ["x", hx_list, B, ()], ["+-", bath_sys_list, B, ()], ["-+", bath_sys_list, B, ()], ] kwargs = dict(basis=basis, dtype=np.float64, check_symm=False, check_pcon=False, check_herm=False) H = hamiltonian(static, dynamic, **kwargs) print "creating hamiltonian" kwargs = dict(basis=basis, dtype=np.float64, check_symm=False, check_pcon=False, check_herm=False) H = hamiltonian([], dynamic, **kwargs) print "solving initial state" E0, psi_0 = H.eigsh(k=1, which="SA", time=0) psi_0 = psi_0.ravel() print "evolving" out = np.zeros(psi_0.shape, dtype=np.complex128) psi_f = evolve(psi_0, 0, T, H._hamiltonian__omp_SO, f_params=(out, ), solver_name="dop853", atol=1.1e-15, rtol=1.1e-15) psi_f /= np.linalg.norm(psi_f) print "saving" np.savez_compressed(filename, psi=psi_f) print "dome.... {} sec".format(time.time() - ti)
def anneal_bath_1(n, m, Nb, T, gamma=0.2, omega=1.0, path="."): ti = time.time() n, m = min(n, m), max(n, m) filename = os.path.join( path, "spin_bath_exact_n_{}_m_{}_Nb_{}_T_{}_gamma_{}_omega_{}.npz".format( n, m, Nb, T, gamma, omega)) if os.path.isfile(filename): print "file_exists...exiting run." exit() if Nb % 2 == 1: S = "{}/2".format(Nb) else: S = "{}".format(Nb // 2) print "creating basis" bath_basis = spin_basis_general(1, S=S) N = n**2 + m**2 Ns_block_est = max((2**N) / (N), 1000) if n != 0: T1, t1, T2, t2, Pr, pr, Tx, Ty = tilted_square_transformations(n, m) blocks = dict(tx=(Tx, 0), ty=(Ty, 0), pb=(Pr, 0)) spin_basis = spin_basis_general(N, S="1/2", pauli=True, Ns_block_est=Ns_block_est, **blocks) else: L = m tr = square_lattice_trans(L, L) Tx = tr.T_x Ty = tr.T_y blocks = dict(tx=(Tx, 0), ty=(Ty, 0), px=(tr.P_x, 0), py=(tr.P_y, 0), pd=(tr.P_d, 0)) spin_basis = spin_basis_general(N, S="1/2", pauli=True, Ns_block_est=Ns_block_est, **blocks) basis = tensor_basis(spin_basis, bath_basis) print "n,m={},{}, H-space size: {}".format(n, m, basis.Ns) J_list = [[-1.0, i, Tx[i]] for i in range(N)] J_list.extend([-1.0, i, Ty[i]] for i in range(N)) h_list = [[-1.0, i] for i in range(N)] bath_energy = [[omega / Nb, 0]] SB_xy_list = [[gamma / (4.0 * Nb), i, 0] for i in range(N)] SB_zz_list = [[gamma / (2.0 * Nb), i, 0] for i in range(N)] A = lambda t: (t / T)**2 B = lambda t: (1 - t / T)**2 static = [ ["|z", bath_energy], ] dynamic = [ ["zz|", J_list, A, ()], ["x|", h_list, B, ()], ["+|-", SB_xy_list, B, ()], ["-|+", SB_xy_list, B, ()], ["z|z", SB_zz_list, B, ()], ] print "creating hamiltonian" kwargs = dict(basis=basis, dtype=np.float64, check_symm=False, check_pcon=False, check_herm=False) H = hamiltonian(static, dynamic, **kwargs) print "solving initial state" E0, psi_0 = H.eigsh(k=1, which="SA", time=0) psi_0 = psi_0.ravel() print "evolving" out = np.zeros(psi_0.shape, dtype=np.complex128) psi_f = evolve(psi_0, 0, T, H._hamiltonian__omp_SO, f_params=(out, ), solver_name="dop853", atol=1.1e-15, rtol=1.1e-15) print "saving" np.savez_compressed(filename, psi=psi_f) print "dome......{} sec".format(time.time() - ti)
def anneal(self, psi_i, ti, tf, J_func, h_func, **solver_args): f_params = (self._psi_out, J_func, h_func) return evolve(psi_i, ti, tf, _SE_1d, f_params=f_params, **solver_args)
def current_expectation(x, params, return_time=False): U, a = x # contains all important variables lat = hhg(field=params.field, nup=params.nup, ndown=params.ndown, nx=params.nx, ny=0, U=U, t=params.t, F0=params.F0, a=a, pbc=params.pbc) # gets times to evaluate at cycles = 10 n_steps = 2000 start = 0 stop = cycles / lat.freq times, delta = np.linspace(start, stop, num=n_steps, endpoint=True, retstep=True) no_checks = dict(check_pcon=False, check_symm=False, check_herm=False) int_list = [[1.0, i, i] for i in range(params.nx)] static_Hamiltonian_list = [["n|n", int_list] # onsite interaction ] # n_j,up n_j,down onsite = hamiltonian(static_Hamiltonian_list, [], basis=params.basis, **no_checks) hop = [[1.0, i, i + 1] for i in range(params.nx - 1)] if lat.pbc: hop.append([1.0, params.nx - 1, 0]) # c^dag_j,sigma c_j+1,sigma hop_left = hamiltonian([["+-|", hop], ["|+-", hop]], [], basis=params.basis, **no_checks) # c^dag_j+1,sigma c_j,sigma hop_right = hop_left.getH() H = -lat.t * (hop_left + hop_right) + lat.U * onsite """build ground state""" # print("calculating ground state") E, psi_0 = H.eigsh(k=1, which='SA') psi_0 = np.squeeze(psi_0) # print("ground state calculated, energy is {:.2f}".format(E[0])) # evolve the system psi_t = evolution.evolve(psi_0, 0.0, times, evolve_psi, f_params=(onsite, hop_left, hop_right, lat, cycles)) psi_t = np.squeeze(psi_t) # get the expectation value of J J_expec = expec.J_expec(psi_t, times, hop_left, hop_right, lat, cycles) if return_time: return times, J_expec else: return J_expec
def anneal_bath(L, T, gamma=0.2, omega=1.0, path="."): filename = os.path.join( path, "spin_bath_exact_L_{}_T_{}_gamma_{}_omega_{}.npz".format( L, T, gamma, omega)) if os.path.isfile(filename): print "file_exists...exiting run." exit() if L % 2 == 1: S = "{}/2".format(L) else: S = "{}".format(L // 2) print "creating basis" spin_basis = spin_basis_1d(L, pauli=True, kblock=0, pblock=1) bath_basis = spin_basis_1d(1, S=S) basis = tensor_basis(spin_basis, bath_basis) print "L={}, H-space size: {}".format(L, basis.Ns) # exit() bath_energy = [[omega / L, 0]] # photon energy SB_list = [[gamma / np.sqrt(L), i, 0] for i in range(L)] h_list = [[-1, i] for i in range(L)] J_list = [[-1, i, (i + 1) % L] for i in range(L)] static_SB = [["+|-", SB_list], ["-|+", SB_list]] static = [["|z", bath_energy]] dynamic = [ ["x|", h_list, lambda t: (1 - t / T)**2, ()], ["zz|", J_list, lambda t: (t / T)**2, ()], ] print "creating hamiltonian" kwargs = dict(basis=basis, dtype=np.float64, check_symm=False, check_pcon=False, check_herm=False) H_B = hamiltonian(static, [], **kwargs) H_S = hamiltonian([], dynamic, **kwargs) V = hamiltonian(static_SB, [], **kwargs) n = H_B * (L / omega) H = H_B + H_S + V print "solving initial state" E0, psi_0 = H.eigsh(k=1, which="SA", time=0) psi_0 = psi_0.ravel() print "evolving" out = np.zeros(psi_0.shape, dtype=np.complex128) psi_f = evolve(psi_0, 0, T, H._hamiltonian__omp_SO, f_params=(out, ), solver_name="dop853") print "saving" np.savez_compressed(filename, psi=psi_f) print "dome."
# psi_0 = np.load('./Data/psi_0.npy') # psi_0 = psi_0 / np.linalg.norm(psi_0) # psi_plus_dU = np.load('./Data/psi_plus_dU.npy') # psi_minus_dU = np.load('./Data/psi_minus_dU.npy') # dpsi_dU_0 = np.load('./Data/dpsi_dU_0.npy') # dpsi_dU_0 = dpsi_dU_0 / np.linalg.norm(dpsi_dU_0) print('evolving system') ti = time() """evolving system, using our own solver for derivatives""" # object containing all 3 wavefunctions big_psi = np.concatenate([psi_0, dpsi_dU_0, dpsi_da_0]) psis_t = evolution.evolve(big_psi, 0.0, times, big_evolve, f_params=(onsite, hop_left, hop_right, lat, cycles)) psis_t = np.squeeze(psis_t) print("Evolution done! This one took {:.2f} seconds".format(time() - ti)) psi_t = psis_t[:int(len(psis_t) / 3)] dpsi_dU_t = psis_t[int(len(psis_t) / 3):int(2 * len(psis_t) / 3)] dpsi_da_t = psis_t[int(2 * len(psis_t) / 3):] ti = time() expectations = {} expectations['H'] = expec.H_expec(psi_t, times, onsite, hop_left, hop_right, lat, cycles) expectations['J'] = expec.J_expec(psi_t, times, hop_left, hop_right, lat, cycles)
A = lambda x: (1 - x)**2 B = lambda x: x**2 s = lambda t: t / T tfim_H = TFIM_general(L, A, B, s, (), J=J0, h=-1) E, V = tfim_H.eigh(h=1.0, J=0.0) psi0 = np.array(V[:, :L], dtype=np.complex128, copy=True) y0 = np.hstack((eta0.ravel(), psi0.ravel())) yout = np.zeros_like(y0) f_params = (yout, T, gamma, omegas, omegas2, damp, work, J_func, h_func, No, L) yf = evolve(y0, 0, T, SO, f_params=f_params, solver_name="dop853", atol=1.1e-15, rtol=1.1e-15) etaf = yf[:L * No].reshape((No, L)) psif = yf[L * No:].reshape((2 * L, L)) AA, BB, AB, BA = get_C_fermion(L, psif) m2 = get_C_spin(AA, BB, AB, BA).real.sum() / L**2 q = tfim_H.expt_value(psif, J=1.0, h=0.0).real + L print m2, q, np.linalg.norm(etaf, axis=0)
obs = observables( gamma_t[:-1], J_target(0.0), phi_J_track(lat_track, 0.0, J_target, FHM_track, gamma_t[:-1]), FHM_track) R_current = [ J_target(0.0), ] # generate the current through runga-kutta of the state for newtime in tqdm(t_p.times[:-1]): solver_args = dict(atol=1e-3) gamma_t = evolve(v0=gamma_t, t0=newtime, times=np.array([newtime + t_p.delta]), f=R_tracking_evolution_equation, f_params=[FHM_track, obs, J_target], solver_name='dop853', **solver_args) gamma_t = gamma_t.reshape(-1) D = FHM.operator_dict['hop_left_op'].expt_value(gamma_t[:-1]) phi_t = (obs.phi_init + np.angle(D) - gamma_t[-1]).real R_current.append( -1j * lat_track.a * lat_track.t * (np.exp(-1j * phi_t) * D - np.exp(1j * phi_t) * D.conj())) gamma_t = np.append(np.squeeze(psi_0), 0.0) obs = observables( gamma_t[:-1], J_target(0.0), phi_J_track(lat_track, 0.0, J_target, FHM_track, gamma_t[:-1]), FHM_track)
def schrod_evol(start_time, psi_0, t_p, j_target, param, l, obs, branch_num, branch_string, split_check, imp_step): """ Handles the Schrodinger equation evolution. Built in recursion for handling all branches that the function will hit. When the control field is near an odd multiple of half pi: (2k + 1)*(pi/2), scoop will spawn a new worker to continue the evolution on that branch. This was built to use quspin's architecture for the FHM wavefunction and operators, it was also build for scoop's built in parallelization. """ # :param start_time: the start time for the evolution, important when passing off a branch to a new worker # # :param psi_0: initial wavefunction for the evolution # # :param t_p: time parameters class # # :param fhm: Fermi-Hubbard operator class # # :param j_target: target current function for tracking control # # :param param: unscaled parameters class, needed when saving our expectations to file # # :param l: scaled parameters for constants used in the model # # :param obs: observables class, used to save our observables in memory # # :param branch_num: branch number for the arcsine in our control tracking scheme # # :param branch_string: string used to classify which branch we should be on # # :param split_check: a check to prevent newly spawned workers from immediately spawning another worker leading to # infinitely many workers being spawned # # :results: creates files labelled with each parameter and which branch points it crossed by using a binary number # with the following format: "0" for a kinking of the control field, "1" for a clean crossing of the control # field. fhm = obs.fermihubbard # assign initial wavefunction if imp_step == 0: psi_t = psi_0 elif imp_step == 2: psi_t = psi_0[0] psi_nm1 = psi_0[1] elif imp_step == 4: psi_t = psi_0[0] psi_nm1 = psi_0[1] psi_nm2 = psi_0[2] psi_nm3 = psi_0[3] elif imp_step == 6: psi_t = psi_0[0] psi_nm1 = psi_0[1] psi_nm2 = psi_0[2] psi_nm3 = psi_0[3] psi_nm4 = psi_0[4] psi_nm5 = psi_0[5] elif imp_step == -4: psi_t = psi_0[0] k1_0 = psi_0[1] k2_0 = psi_0[2] k3_0 = psi_0[3] # start evolution of wavefunction newtime = start_time tasks = [] # print(start_time) while newtime < t_p.times[-1]: newtime += t_p.delta ## Original evolution method if imp_step == 0: solver_args = dict(atol=1e-8) psi_t = evolve(v0=psi_t, t0=newtime, times=np.array([newtime + t_p.delta]), f=original_tracking_evolution_with_branches, f_params=[fhm, j_target, l, branch_num], solver_name='dopri5', **solver_args) # reshape the wavefunction to take expectations of it psi_t = psi_t.reshape(-1) # # Alternative dumber euler evolution # psi_t = psi_t + (t_p.delta) * original_tracking_evolution_with_branches(newtime, psi_t, fhm, j_target, l, # branch_num) ## slightly less dumb rk2 evolution # k1 = (t_p.delta) * original_tracking_evolution_with_branches(newtime, psi_t, fhm, j_target, l, # branch_num) # k2 = (t_p.delta) * original_tracking_evolution_with_branches(newtime + (t_p.delta)/2, # psi_t + k1/2, fhm, j_target, l, # branch_num) # psi_t = psi_t + k2 ## crude RK4 evolution # psi_t = original_tracking_RK4(newtime, psi_t, fhm, j_target, l, branch_num, t_p) ## Implicit Adams-Moulton two step method if imp_step == 2: if newtime < t_p.times[2]: psi_nm1 = psi_t.copy() psi_t = original_tracking_RK4(newtime, psi_t, fhm, j_target, l, branch_num, t_p) else: psi_t, psi_nm1 = original_tracking_implicit_two_step( current_time=newtime, psi=psi_t, psi_nm1=psi_nm1, fhm=fhm, J_target=J_target, l=l, bn=branch_num, tp=t_p) ## Implicit Adams-Moulton four step method if imp_step == 4: if newtime < t_p.times[2]: psi_nm1 = psi_t.copy() psi_t = original_tracking_RK4(newtime, psi_t, fhm, j_target, l, branch_num, t_p) elif newtime < t_p.times[3]: psi_nm2 = psi_nm1.copy() psi_nm1 = psi_t.copy() psi_t = original_tracking_RK4(newtime, psi_t, fhm, j_target, l, branch_num, t_p) elif newtime < t_p.times[4]: psi_nm3 = psi_nm2.copy() psi_nm2 = psi_nm1.copy() psi_nm1 = psi_t.copy() psi_t = original_tracking_RK4(newtime, psi_t, fhm, j_target, l, branch_num, t_p) else: psi_t, psi_nm1, psi_nm2, psi_nm3 = original_tracking_implicit_bd_four_step( current_time=newtime, psi=psi_t, psi_nm1=psi_nm1, psi_nm2=psi_nm2, psi_nm3=psi_nm3, fhm=fhm, J_target=j_target, l=l, bn=branch_num, tp=t_p) # Implicit six step backwards differentiation if imp_step == 6: if newtime < t_p.times[2]: psi_nm1 = psi_t.copy() psi_t = original_tracking_RK4(newtime, psi_t, fhm, j_target, l, branch_num, t_p) elif newtime < t_p.times[3]: psi_nm2 = psi_nm1.copy() psi_nm1 = psi_t.copy() psi_t = original_tracking_RK4(newtime, psi_t, fhm, j_target, l, branch_num, t_p) elif newtime < t_p.times[4]: psi_nm3 = psi_nm2.copy() psi_nm2 = psi_nm1.copy() psi_nm1 = psi_t.copy() psi_t = original_tracking_RK4(newtime, psi_t, fhm, j_target, l, branch_num, t_p) elif newtime < t_p.times[5]: psi_nm4 = psi_nm3.copy() psi_nm3 = psi_nm2.copy() psi_nm2 = psi_nm1.copy() psi_nm1 = psi_t.copy() psi_t = original_tracking_RK4(newtime, psi_t, fhm, j_target, l, branch_num, t_p) elif newtime < t_p.times[6]: psi_nm5 = psi_nm4.copy() psi_nm4 = psi_nm3.copy() psi_nm3 = psi_nm2.copy() psi_nm2 = psi_nm1.copy() psi_nm1 = psi_t.copy() psi_t = original_tracking_RK4(newtime, psi_t, fhm, j_target, l, branch_num, t_p) else: psi_t, psi_nm1, psi_nm2, psi_nm3, psi_nm4, psi_nm5 = original_tracking_implicit_bd_six_step( current_time=newtime, psi=psi_t, psi_nm1=psi_nm1, psi_nm2=psi_nm2, psi_nm3=psi_nm3, psi_nm4=psi_nm4, psi_nm5=psi_nm5, fhm=fhm, J_target=j_target, l=l, bn=branch_num, tp=t_p) # Implicit Radau IIa 5th order method if imp_step == -4: psi_t, k1_0, k2_0, k3_0 = original_tracking_radau_IIa_5th( newtime, psi_t, fhm, j_target, l, branch_num, t_p, k1_0, k2_0, k3_0) # find control field at the given time and wavefunction phi = phi_J_track_with_branches(l, newtime + t_p.delta, j_target, fhm, psi_t, branch_num) # save expectations given wavefunction and control field obs.append_observables(psi_t, phi) # obs.append_work(t_p.times) # checks to see if the control field is sufficiently far away from the branch point to update the check theta = np.angle(obs.neighbour[-1]) phi_p = ((-1)**(branch_num)) * (phi - theta - branch_num * PI) pi_tol = 9e-3 if split_check: if (PI / 2 - (1.1 * pi_tol)) > phi_p > -(PI / 2 - (1.1 * pi_tol)): split_check = False # check to see if the control field is near a branch point by using the formula # phi - theta = Arcsin(X) = (-1)^(branch_number)*arcsin(X) + branch_number * pi # to see if phi - theta is near half pi on its particular branch. else: if (PI / 2 + pi_tol) > phi_p > (PI / 2 - pi_tol): print("Branch point detected at t={}".format(newtime * l.freq)) # make a copy of observables class and update the branch number and string. obs_jump = obs.deepcopy() branch_num_jump = branch_num + 1 branch_string_jump = branch_string + "+" branch_string += "0" # spawn new worker to run this function if imp_step == 0: args = (newtime, psi_t, t_p, j_target, param, l, obs_jump, branch_num_jump, branch_string_jump, True, imp_step) elif imp_step == 2: args = (newtime, np.array([psi_t, psi_nm1]), t_p, j_target, param, l, obs_jump, branch_num_jump, branch_string_jump, True, imp_step) elif imp_step == 4: args = (newtime, np.array([psi_t, psi_nm1, psi_nm2, psi_nm3]), t_p, j_target, param, l, obs_jump, branch_num_jump, branch_string_jump, True, imp_step) elif imp_step == 6: args = (newtime, np.array([ psi_t, psi_nm1, psi_nm2, psi_nm3, psi_nm4, psi_nm5 ]), t_p, j_target, param, l, obs_jump, branch_num_jump, branch_string_jump, True, imp_step) elif imp_step == -4: args = (newtime, np.array([psi_t, k1_0, k2_0, k3_0]), t_p, j_target, param, l, obs_jump, branch_num_jump, branch_string_jump, True, imp_step) # print("Spawned a new worker") split_check = True tasks.append(futures.submit(schrod_evol, *args)) elif -(PI / 2 + pi_tol) < phi_p < -(PI / 2 - pi_tol): print("Branch point detected at t={}".format(newtime * l.freq)) # make a deep copy of observables class and update the branch number and string. obs_jump = obs.deepcopy() branch_num_jump = branch_num - 1 branch_string_jump = branch_string + "-" branch_string += "0" # spawn new worker to run this function if imp_step == 0: args = (newtime, psi_t, t_p, j_target, param, l, obs_jump, branch_num_jump, branch_string_jump, True, imp_step) elif imp_step == 2: args = (newtime, np.array([psi_t, psi_nm1]), t_p, j_target, param, l, obs_jump, branch_num_jump, branch_string_jump, True, imp_step) elif imp_step == 4: args = (newtime, np.array([psi_t, psi_nm1, psi_nm2, psi_nm3]), t_p, j_target, param, l, obs_jump, branch_num_jump, branch_string_jump, True, imp_step) elif imp_step == 6: args = (newtime, np.array([ psi_t, psi_nm1, psi_nm2, psi_nm3, psi_nm4, psi_nm5 ]), t_p, j_target, param, l, obs_jump, branch_num_jump, branch_string_jump, True, imp_step) elif imp_step == -4: args = (newtime, np.array([psi_t, k1_0, k2_0, k3_0]), t_p, j_target, param, l, obs_jump, branch_num_jump, branch_string_jump, True, imp_step) # print("Spawned a new worker") split_check = True tasks.append(futures.submit(schrod_evol, *args)) # update the evolution time # print(newtime) # when the loop is finished, save expectations to a file. expect = {} obs.save_observables(expect) # obs.save_work(expectation_dict=expect) savefile = 'scoop_branch_tracking/Data/{}sites-{}up-{}down-{}t0-{}U-{}cycles-{}steps-{}pbcF0={:.2f}-J_scale={:.2f}' \ '/expectations:bstring={}.npz'.format(param.L, param.N_up, param.N_down, param.t0, param.U, t_p.cycles, t_p.n_steps, param.pbc, param.F0, param.J_scale, branch_string) print("Saving an expectation") expect['bstring'] = branch_string np.savez(savefile, **expect) assert all(task.result() for task in tasks), "Tasks did not exit properly" # for task in tasks: # task.result() return True
# psi_dot += 1j*lat_track.t*np.exp(-1j*phi)*hop_left_op.dot(psi) # psi_dot += 1j*lat_track.t*np.exp(1j*phi)*hop_right_op.dot(psi) # return psi_dot """pre evolution to get a non zero angle""" psi_t = psi_0 phi_track = [] neighbour_track = [] J_track = [] for newtime in tqdm(times[:int(len(times) / 3.2)]): # evolve forward by a single step. This is almost certainly not efficient, but is a first pass. """this version uses Quspin default, dop853""" # print(psi_t.shape) # solver_args=dict(atol=1e-3) # psi_t = evolve(psi_t, newtime, np.array([newtime + delta]), tracking_evolution,**solver_args) psi_t = evolve(psi_t, newtime, np.array([newtime + delta]), prevolution) # neighbour_track.append(hop_left_op.expt_value(psi_t)) # newphi = phi_mimic_zero_track(lat_track, neighbour_track[-1]) # if newphi - phi_track[-1] > 1.2 * np.pi: # newphi = newphi - 2 * np.pi # elif newphi - phi_track[-1] < -1.2 * np.pi: # newphi = newphi + 2 * np.pi # phi_track.append(newphi) # current_partial = lat_track.a * lat_track.t * np.exp(-1j * phi_track[-1]) * neighbour_track[-1] # current = -1j * (current_partial - current_partial.conjugate()) # J_track.append(current) # print(psi_t.shape) """this version uses lsoda. It is unforgivably slow""" # solver_args=dict(method='bdf') # psi_t = evolve(psi_t, newtime, np.array([newtime + delta]), tracking_evolution,solver_name='dopri5') # psi_t = np.squeeze(psi_t)
def scoopfunction(newtime, t_p, psi, fhm, j_target, l, branch_num, branch_string, psigroup): """ Uses Schrodinger equation to find the wavefunction at a time step forward and appends it to a greater wavefunction array. Function stops if it has evolved to the target endpoint or if the wavefunction reproduces a control field value near the branch points at phi - theta = (2k+1)*pi/2. Returns the current time, wavefunction, and how to switch the branch number in the jumped worker. Base level function to use with scoop in order to find the wavefunction for all possible branch decisions for a given target current function. This implementation uses quspin's architecture for the wavefunction of a Fermi-Hubbard lattice. """ # :param newtime: the current time step of the evolution # :param t_p: the class which holds our lattice of time, number of steps, and time lattice size. # :param psi: the wavefunction for the Fermi Hubbard lattice # :param fhm: class for operators of our Fermi Hubbard lattice using quspin's architecture # :param j_target: UnivariateSpline of our target current function. # :param l: perimeter parameters used in our fermi hubbard model # :param branch_num: the branch number of the arcsine within the control field # start the while loop corresponding to getting the wavefunction at each of the points defined in times while newtime < t_p.times[-1]: # solve Schrodinger equation using the original arcsine tracking equation for the wavefunction at time = # t + delta solver_args = dict(atol=1e-12) print(psi) psi_t = evolve(v0=psi[-1], t0=newtime, times=np.array([newtime + t_p.delta]), f=original_tracking_evolution_with_branches, f_params=[fhm, j_target, l, branch_num], **solver_args) # append the new wavefunction at t + delta psi.append(psi_t) # reshape the wavefunction in order to take expectations using it psi_t = psi_t.reshape(-1) # update the time for the next step newtime = newtime + t_p.delta # get the control field given the wavefunction and the target current phi = phi_J_track_with_branches(l, newtime + t_p.delta, j_target, fhm, psi_t, branch_num) # get nearest neighbour expectation for the branch check neighbour = fhm.operator_dict['hop_left_op'].expt_value(psi_t) # checks if phi - theta = Arcsin(X) = (-1)^(branch_number)*arcsin(X) + branch_number * pi is near an odd # multiple of pi/2. if so, return the function with the current time, all wavefunctions from previous times, # and which direction should the branch switch. if ((-1)**branch_num) * (phi - np.angle(neighbour) - branch_num * np.pi) > (np.pi / 2 - 1e-2): return [newtime, psi, +1] elif ((-1)**branch_num) * (phi - np.angle(neighbour) - branch_num * np.pi) < -(np.pi / 2 - 1e-2): return [newtime, psi, -1] # if the current worker doesn't find a branch point return the function with the current time, all wavefunctions # previously found, and no direction of branch switching. return [newtime, psi, 0]
####### def GPE(time, phi): '''Solves the complex-valued time-dependent Gross-Pitaevskii equation: ''' # integrate static part of GPE phi_dot = -1j * (H.static.dot(phi) + U * np.abs(phi)**2 * phi) # integrate dynamic part of GPE for fun, Hdyn in iteritems(H.dynamic): phi_dot += -1j * fun(time) * Hdyn.dot(phi) return phi_dot # solving the complex-valued GPE takes one line phi_t = evolve(phi0, t.i, t.vals, GPE) ######## def GPE_real(time, phi, H, U): '''Solves the Gross-Pitaevskii equation, cast into real-valued form so it can be solved with a real-valued ODE solver. ''' # preallocate memory for phi_dot phi_dot = np.zeros_like(phi) # read off number of lattice sites (array dimension of phi) Ns = H.Ns # static single-particle part phi_dot[:Ns] = H.static.dot(phi[Ns:]).real phi_dot[Ns:] = -H.static.dot(phi[:Ns]).real
print( "Generating Initial states by kicking the ground state of the two systems." ) ti = time() t_p_kick = time_evolution_params(perimeter_params=lat, cycles=10, nsteps=int(2e3)) psi1_init = psi1_0.copy() psi2_init = psi2_0.copy() for current_time in tqdm(t_p_kick.times[:]): solver_args = dict(atol=1e-12) # print(psi_t.shape) psi1_init = evolve(v0=psi1_init, t0=current_time, times=np.array([current_time + t_p.delta]), f=initial_kick_evolution, f_params=[FHM1, lat, t_p_kick.cycles], **solver_args) psi2_init = evolve(v0=psi2_init, t0=current_time, times=np.array([current_time + t_p.delta]), f=initial_kick_evolution, f_params=[FHM2, lat2, t_p_kick.cycles], **solver_args) psi1_init = np.squeeze(psi1_init) psi2_init = np.squeeze(psi2_init) # psi1_init = FHM1.operator_dict["H"].evolve(psi1_0, 0.0, t_p_kick.times[:int(len(t_p_kick.times)/5)]) # psi1_init = np.squeeze(psi1_init) # psi2_init = FHM2.operator_dict["H"].evolve(psi2_0, 0.0, t_p_kick.times[:int(len(t_p_kick.times)/5)]) # psi2_init = np.squeeze(psi2_init)
def anneal_MF(L, T, sigma=0.01, path=".", n_chains=1): ti = time.time() print "creating basis" basis = spin_basis_1d(L, pauli=True, kblock=0, pblock=1) hx_list = [[-1, i] for i in range(L)] hz_list = [[1, i] for i in range(L)] J_list = [[-1, i, (i + 1) % L] for i in range(L)] M_list = [[1.0 / L**2, i, j] for i in range(L) for j in range(L)] ops_dict = dict(J=[["zz", J_list]], h=[["x", hx_list]]) H0 = quantum_operator(ops_dict, basis=basis, dtype=np.float64) Hz = hamiltonian([["z", hz_list]], [], basis=basis, dtype=np.float64) M2 = hamiltonian([["zz", M_list]], [], basis=basis, dtype=np.float64) def B(t, T): return (1 - t / T)**2 def A(t, T, J0, eta): return (J0 + eta(t)) * (t / T)**2 _, psi0 = H0.eigsh(k=1, which="SA", pars=dict(J=0, h=1)) psi0 = psi0.astype(np.complex128).ravel() y0 = np.hstack([psi0 for i in range(n_chains)]) yout = y0.reshape((n_chains, basis.Ns)).copy() for i in range(3): H_list = [] eta2_list = [] for j in range(n_chains): omega1 = get_samples(1000, omega_max=10) omega2 = get_samples(1000, omega_max=10) eta1 = fourier_noise(0.0, lambda t: 1.0, sigma, omega1) eta2 = fourier_noise(0.0, lambda t: 1.0, sigma, omega2) # if j==0: # pars = dict(J=(A,(T,1.0,eta1)),h=(B,(T,))) # else: # pars = dict(J=(A,(T,sigma,eta1)),h=(B,(T,))) pars = dict(J=(A, (T, 1.0, eta1)), h=(B, (T, ))) H_list.append(H0.tohamiltonian(pars=pars)) eta2_list.append(eta2) f_params = (yout, H_list, Hz.tocsr(), eta2_list, L, T, sigma) psif = evolve(y0.reshape((-1, basis.Ns)), 0, T, SO_MF, f_params=f_params, solver_name="dop853", atol=1.1e-15, rtol=1.1e-15) psif = psif[0] q, m2 = H0.matrix_ele(psif, psif, pars=dict(J=1, h=0), diagonal=True).real + L, M2.expt_value(psif).real line = "{:30.15e} {:30.15e}".format(q, m2) print i + 1, line
hop_right = hop_left.getH() """Create complete Hamiltonian""" H = -lat.t * (hop_left + hop_right) + lat.U * onsite """get ground state as the eigenstate corresponding to the lowest eigenergy""" print("calculating ground state") E, psi_0 = H.eigsh(k=1, which='SA') psi_0 = np.squeeze(psi_0) psi_0 = psi_0 / np.linalg.norm(psi_0) print("ground state calculated, energy is {:.2f}".format(E[0])) print('evolving system') ti = time() """evolving system, using our own solver for derivatives""" psi_t = evolution.evolve(psi_0, 0.0, times, evolve_psi, f_params=(onsite, hop_left, hop_right, lat, cycles)) psi_t = np.squeeze(psi_t) print("Evolution done! This one took {:.2f} seconds".format(time() - ti)) """Calculate Expectation Values""" ti = time() expectations = {'H': expec.H_expec(psi_t, times, onsite, hop_left, hop_right, lat, cycles), 'J': expec.J_expec(psi_t, times, hop_left, hop_right, lat, cycles)} print("Expectations calculated! This took {:.2f} seconds".format(time() - ti)) np.save('./Data/H_expec'+parameters+'.npy', expectations['H']) np.save('./Data/J_expec'+parameters+'.npy', expectations['J']) print('All finished. Total time was {:.2f} seconds'.format((time() - t_init)))
$$ -\dot\phi(\tau) = Hsp(t=0)\phi(\tau) + U |\phi(\tau)|^2 \phi(\tau) $$ """ return -(Hsp.dot(phi, time=0) + U * np.abs(phi)**2 * phi) # define ODE parameters GPE_params = (Hsp, U) # define initial state to flow to GS from phi0 = V[:, 0] * np.sqrt(L) # initial state normalised to 1 particle per site # define imaginary time vector tau = np.linspace(0.0, 35.0, 71) # evolve state in imaginary time psi_tau = evolve(phi0, tau[0], tau, GPE_imag_time, f_params=GPE_params, imag_time=True, real=True, iterate=True) # # display state evolution for i, psi0 in enumerate(psi_tau): # compute energy E_GS = (Hsp.matrix_ele(psi0, psi0, time=0) + 0.5 * U * np.sum(np.abs(psi0)**4)).real # plot wave function plt.plot(sites, abs(phi0)**2, color='r', marker='s', alpha=0.2,
def objective(x, J_target, params, graph=False, fname=None): """ Our objective function that we want to minimize: E(U,a) = int(JT - <J>)^2 :param x: input array [U,a] :param J_target: tuple of (frequencies, spectrum) :param params: an instance of Parameters class :param graph: if True, the target and calculated current will be graphed together :param fname: name of the file to save the graph to :return: The cost of the function """ # optimization parameters oU = x[0] oa = x[1] # unpack J_target target_freqs, target_spectrum = J_target # contains all important variables lat = hhg(field=params.field, nup=params.nup, ndown=params.ndown, nx=params.nx, ny=0, U=oU, t=params.t, F0=params.F0, a=oa, pbc=params.pbc) # gets times to evaluate at cycles = 10 n_steps = 2000 start = 0 stop = cycles / lat.freq times, delta = np.linspace(start, stop, num=n_steps, endpoint=True, retstep=True) no_checks = dict(check_pcon=False, check_symm=False, check_herm=False) int_list = [[1.0, i, i] for i in range(params.nx)] static_Hamiltonian_list = [["n|n", int_list] # onsite interaction ] # n_j,up n_j,down onsite = hamiltonian(static_Hamiltonian_list, [], basis=params.basis, **no_checks) hop = [[1.0, i, i + 1] for i in range(params.nx - 1)] if lat.pbc: hop.append([1.0, params.nx - 1, 0]) # c^dag_j,sigma c_j+1,sigma hop_left = hamiltonian([["+-|", hop], ["|+-", hop]], [], basis=params.basis, **no_checks) # c^dag_j+1,sigma c_j,sigma hop_right = hop_left.getH() H = -lat.t * (hop_left + hop_right) + lat.U * onsite """build ground state""" E, psi_0 = H.eigsh(k=1, which='SA') psi_0 = np.squeeze(psi_0) """evolve the system""" psi_t = evolution.evolve(psi_0, 0.0, times, evolve_psi, f_params=(onsite, hop_left, hop_right, lat, cycles)) psi_t = np.squeeze(psi_t) # get the expectation value of J J_expec = expec.J_expec(psi_t, times, hop_left, hop_right, lat, cycles) expec_freqs, J_expec_spectrum = spectrum(J_expec, delta) fval = np.linalg.norm( np.log10(target_spectrum) - np.log10(J_expec_spectrum)) # just some graphing stuff if graph: plt.plot(J_expec_spectrum, color='red', label='$\\langle\\hat{J}(t)\\rangle$') plt.plot(target_spectrum, color='blue', linestyle='dashed', label='$J^{T}(t)$') plt.legend(loc='upper left') plt.xlabel("Time") plt.ylabel("Current") plt.title("Target Current vs Best Fit Current") if fname is not None: plt.savefig(fname) plt.show() # print("Fval =", fval, "for x =", x) return fval
order="C"), # auxiliary variable rho_out np.zeros((H.Ns, H.Ns), dtype=np.complex128, order="C")) # auxiliary variable rho_aux # ##### time-evolve state according to Lindlad equation # define real time vector # define initial state # rho0 = np.array([[0.5, 0.5j], [-0.5j, 0.5]], dtype=np.complex128) # # evolution rho_t = evolve(rho_0, times[0], times, Lindblad_EOM_v2, f_params=EOM_args, iterate=False, atol=1E-12, rtol=1E-12, verbose=True) print(rho_t.shape) # this version returns the generator for psi # psi_t=ham.evolve(psi_0,0.0,times,iterate=True) # this version returns psi directly, last dimension contains time dynamics. The squeeze is necessary for the # obs_vs_time to work properly # psi_t = H.evolve(psi_0, 0.0, times) # psi_t = np.squeeze(psi_t) print("Evolution done! This one took {:.2f} seconds".format(time() - ti)) # calculate the expectations for every bastard in the operator dictionary ti = time()
# ##### time-evolve state according to Lindlad equation # define real time vector t_max = 6.0 time = np.linspace(0.0, t_max, 101) # define initial state rho0 = np.array([[0.5, 0.5j], [-0.5j, 0.5]], dtype=np.complex128) # slow solution, uses Lindblad_EOM_v1 #rho_t = evolve(rho0,time[0],time,Lindblad_EOM_v1,iterate=True,atol=1E-12,rtol=1E-12) # intermediate function, uses Lindblad_EOM_v2 #rho_t = evolve(rho0,time[0],time,Lindblad_EOM_v2,f_params=EOM_args,iterate=True,atol=1E-12,rtol=1E-12) # fast solution (but 3 times as memory intensive), uses Lindblad_EOM_v3 rho_t = evolve(rho0, time[0], time, Lindblad_EOM_v3, f_params=EOM_args, iterate=True, atol=1E-12, rtol=1E-12) # # compute state evolution population_down = np.zeros(time.shape, dtype=np.float64) for i, rho_flattened in enumerate(rho_t): rho = rho_flattened.reshape(H.Ns, H.Ns) population_down[i] = rho_flattened[1, 1] print("time={0:.2f}, population of down state = {1:0.8f}".format( time[i], population_down[i])) # ##### plot population dynamics of down state # plt.plot(Omega_Rabi * time, population_down)
E, psi_0 = FHM.operator_dict['ham_init'].eigsh(k=1, which='SA') psi_t = np.squeeze(psi_0) print( "Initial state and energy calculated. It took {:.2f} seconds to calculate". format(time() - ti)) print("Ground state energy was calculated to be {:.2f}".format(E[0])) """create our observables class""" obs = observables(psi_t, J_target(0.0), phi_J_track(lat, 0.0, J_target, FHM, psi_t), FHM) """evolve that energy and state""" for newtime in tqdm(t_p.times[:-1]): solver_args = dict(atol=1e-12) psi_t = evolve(v0=psi_t, t0=newtime, times=np.array([newtime + t_p.delta]), f=original_tracking_evolution, f_params=[FHM, J_target, lat], **solver_args) psi_t = psi_t.reshape(-1) obs.append_observables( psi_t, phi_J_track(lat, newtime + t_p.delta, J_target, FHM, psi_t)) """save all observables to a file""" outfile = './Data/expectations:{}sites-{}up-{}down-{}t0-{}U-{}cycles-{}steps-{}pbc:a_scale={:.2f}-J_scale={:.2f}.npz'.\ format(param.L, param.N_up, param.N_down, param.t0, param.U, t_p.cycles, t_p.n_steps, param.pbc, param.a_scale , param.J_scale) obs.save_observables(expectations) print('Saving our expectations.') ti = time() np.savez(outfile, **expectations) print('Expectations saved. It took {:.2f} seconds.'.format(time() - ti))