def get_f_pulse_double_sided(self): half_CZ_A = wf.martinis_flux_pulse( length=self.fluxlutman.cz_length() * self.fluxlutman.czd_length_ratio(), lambda_2=self.fluxlutman.cz_lambda_2(), lambda_3=self.fluxlutman.cz_lambda_3(), theta_f=self.fluxlutman.cz_theta_f(), f_01_max=self.fluxlutman.cz_freq_01_max(), J2=self.fluxlutman.cz_J2(), # E_c=self.fluxlutman.cz_E_c(), f_interaction=self.fluxlutman.cz_freq_interaction(), sampling_rate=self.fluxlutman.sampling_rate(), return_unit='f01') half_amp_A = self.fluxlutman.detuning_to_amp( (self.fluxlutman.cz_freq_01_max() - half_CZ_A) / (2 * np.pi)) # first half is mapped to positive voltage # NOTE: negative part of the flux arc is ignored # Generate the second CZ pulse. If the params are np.nan, default # to the main parameter if not np.isnan(self.fluxlutman.czd_theta_f()): d_theta_f = self.fluxlutman.czd_theta_f() else: d_theta_f = self.fluxlutman.cz_theta_f() if not np.isnan(self.fluxlutman.czd_lambda_2()): d_lambda_2 = self.fluxlutman.czd_lambda_2() else: d_lambda_2 = self.fluxlutman.cz_lambda_2() if not np.isnan(self.fluxlutman.czd_lambda_3()): d_lambda_3 = self.fluxlutman.czd_lambda_3() else: d_lambda_3 = self.fluxlutman.cz_lambda_3() half_CZ_B = wf.martinis_flux_pulse( length=self.fluxlutman.cz_length() * (1 - self.fluxlutman.czd_length_ratio()), lambda_2=d_lambda_2, lambda_3=d_lambda_3, theta_f=d_theta_f, f_01_max=self.fluxlutman.cz_freq_01_max(), J2=self.fluxlutman.cz_J2(), f_interaction=self.fluxlutman.cz_freq_interaction(), sampling_rate=self.fluxlutman.sampling_rate(), return_unit='f01') half_amp_B = self.fluxlutman.detuning_to_amp( (self.fluxlutman.cz_freq_01_max() - half_CZ_B) / (2 * np.pi), positive_branch=False) # second half is mapped to negative voltage # NOTE: negative part of the flux arc is ignored # N.B. No amp scaling and offset present f_pulse = np.concatenate([half_CZ_A, half_CZ_B]) amp = np.concatenate([half_amp_A, half_amp_B]) return f_pulse, amp
def acquire_data_point(self, **kw): tlist = (np.arange(0, self.fluxlutman.cz_length(), 1/self.fluxlutman.sampling_rate())) if not self.fluxlutman.czd_double_sided(): f_pulse = wf.martinis_flux_pulse( length=self.fluxlutman.cz_length(), lambda_2=self.fluxlutman.cz_lambda_2(), lambda_3=self.fluxlutman.cz_lambda_3(), theta_f=self.fluxlutman.cz_theta_f(), f_01_max=self.fluxlutman.cz_freq_01_max(), J2=self.fluxlutman.cz_J2(), f_interaction=self.fluxlutman.cz_freq_interaction(), sampling_rate=self.fluxlutman.sampling_rate(), return_unit='f01') else: f_pulse = self.get_f_pulse_double_sided() # extract base frequency from the Hamiltonian w_q0 = np.real(self.H_0[1,1]) eps_vec = f_pulse - w_q0 qoi = simulate_quantities_of_interest( H_0=self.H_0, tlist=tlist, eps_vec=eps_vec, sim_step=1e-9, verbose=False) cost_func_val = abs(qoi['phi_cond']-180) + qoi['L1']*100 * 5 return cost_func_val, qoi['phi_cond'], qoi['L1']*100, qoi['L2']*100
def test_QWG_flux_lutman_basic_wfs_CZ(self): """ Test the basic waveform CZ and CZ with phase correction """ self.QWG_flux_lutman.sampling_rate(1e9) self.QWG_flux_lutman.F_amp(0.5) self.QWG_flux_lutman.F_length(1e-6) self.QWG_flux_lutman.F_compensation_delay(500e-9) self.QWG_flux_lutman.Z_amp(0.05) corr_len = 10 self.QWG_flux_lutman.Z_length(corr_len * 1e-9) CZ = self.QWG_flux_lutman.standard_waveforms()['adiabatic'] CZ_expected = wf.martinis_flux_pulse( length=self.QWG_flux_lutman.F_length(), lambda_2=self.QWG_flux_lutman.F_lambda_2(), lambda_3=self.QWG_flux_lutman.F_lambda_3(), theta_f=self.QWG_flux_lutman.F_theta_f(), f_01_max=self.QWG_flux_lutman.F_f_01_max(), J2=self.QWG_flux_lutman.F_J2(), E_c=self.QWG_flux_lutman.F_E_c(), V_per_phi0=self.QWG_flux_lutman.V_per_phi0(), f_interaction=self.QWG_flux_lutman.F_f_interaction(), f_bus=None, asymmetry=self.QWG_flux_lutman.F_asymmetry(), sampling_rate=self.QWG_flux_lutman.sampling_rate(), return_unit='V') np.testing.assert_array_equal(CZ, CZ_expected) CZ_phase_corr = \ self.QWG_flux_lutman.standard_waveforms()['adiabatic_Z'] # Test CZ_with_phase_correction Z_corr = np.ones(corr_len) * 0.05 CZ_phase_corr_expected = np.concatenate([CZ, Z_corr]) np.testing.assert_array_equal(CZ_phase_corr, CZ_phase_corr_expected)
def get_f_pulse_double_sided(self): half_CZ_A = wf.martinis_flux_pulse( length=self.fluxlutman.cz_length() * self.fluxlutman.czd_length_ratio(), lambda_2=self.fluxlutman.cz_lambda_2(), lambda_3=self.fluxlutman.cz_lambda_3(), theta_f=self.fluxlutman.cz_theta_f(), f_01_max=self.fluxlutman.cz_freq_01_max(), J2=self.fluxlutman.cz_J2(), # E_c=self.fluxlutman.cz_E_c(), f_interaction=self.fluxlutman.cz_freq_interaction(), sampling_rate=self.fluxlutman.sampling_rate(), return_unit='f01') # Generate the second CZ pulse. If the params are np.nan, default # to the main parameter if not np.isnan(self.fluxlutman.czd_theta_f()): d_theta_f = self.fluxlutman.czd_theta_f() else: d_theta_f = self.fluxlutman.cz_theta_f() if not np.isnan(self.fluxlutman.czd_lambda_2()): d_lambda_2 = self.fluxlutman.czd_lambda_2() else: d_lambda_2 = self.fluxlutman.cz_lambda_2() if not np.isnan(self.fluxlutman.czd_lambda_3()): d_lambda_3 = self.fluxlutman.czd_lambda_3() else: d_lambda_3 = self.fluxlutman.cz_lambda_3() half_CZ_B = wf.martinis_flux_pulse( length=self.fluxlutman.cz_length() * (1 - self.fluxlutman.czd_length_ratio()), lambda_2=d_lambda_2, lambda_3=d_lambda_3, theta_f=d_theta_f, f_01_max=self.fluxlutman.cz_freq_01_max(), J2=self.fluxlutman.cz_J2(), f_interaction=self.fluxlutman.cz_freq_interaction(), sampling_rate=self.fluxlutman.sampling_rate(), return_unit='f01') # N.B. No amp scaling and offset present f_pulse = np.concatenate([half_CZ_A, half_CZ_B]) return f_pulse
def standard_waveforms(self): ''' Returns standard waveforms, without delays or distortions applied. ''' # Block pulses # Pulse is not IQ modulated, so block_Q is not used. block = wf.single_channel_block(self.F_amp(), self.F_length(), sampling_rate=self.sampling_rate()) gaussI, gaussQ = wf.gauss_pulse(self.S_amp(), self.S_gauss_sigma(), nr_sigma=4, sampling_rate=self.sampling_rate(), axis='x', phase=0, motzoi=0, delay=0, subtract_offset='first') # New version of fast adiabatic pulse martinis_pulse_v2 = wf.martinis_flux_pulse( length=self.F_length(), lambda_2=self.F_lambda_2(), lambda_3=self.F_lambda_3(), theta_f=self.F_theta_f(), f_01_max=self.F_f_01_max(), J2=self.F_J2(), E_c=self.F_E_c(), V_per_phi0=self.V_per_phi0(), V_offset=self.V_offset(), f_interaction=self.F_f_interaction(), f_bus=None, asymmetry=self.F_asymmetry(), sampling_rate=self.sampling_rate(), return_unit='V') # Flux pulse for single qubit phase correction z_nr_samples = int(np.round(self.Z_length() * self.sampling_rate())) single_qubit_phase_correction = np.ones(z_nr_samples) * self.Z_amp() single_qubit_phase_correction_grover = \ np.ones(z_nr_samples) * self.Z_amp_grover() if self.disable_CZ(): martinis_pulse_v2 *= 0 # Construct phase corrected pulses martinis_phase_corrected = np.concatenate( [martinis_pulse_v2, single_qubit_phase_correction]) martinis_phase_corrected_grover = np.concatenate( [martinis_pulse_v2, single_qubit_phase_correction_grover]) return {'square': block, 'adiabatic': martinis_pulse_v2, 'adiabatic_Z': martinis_phase_corrected, 'adiabatic_Z_grover': martinis_phase_corrected_grover, 'gauss': gaussI}
def chan_wf(self, chan, tvals): t = tvals - tvals[0] martinis_pulse = martinis_flux_pulse( length=self.length, lambda_coeffs=self.lambda_coeffs, theta_f=self.theta_f, g2=self.g2, E_c=self.E_c, f_bus=self.f_bus, f_01_max=self.f_01_max, dac_flux_coefficient=self.dac_flux_coefficient, return_unit='V') # amplitude is not used because of parameterization but # we use the sign of the amplitude to set the flux compensation return martinis_pulse * np.sign(self.amplitude)
def test_simulate_quantities_of_interest(self): # Hamiltonian pars alpha_q0 = 250e6 * 2 * np.pi J = 2.5e6 * 2 * np.pi w_q0 = 6e9 * 2 * np.pi w_q1 = 7e9 * 2 * np.pi H_0 = czu.coupled_transmons_hamiltonian(w_q0, w_q1, alpha_q0=alpha_q0, J=J) f_interaction = w_q0 + alpha_q0 f_01_max = w_q1 J2 = np.sqrt(2) * J length = 180e-9 sampling_rate = 1e9 #2.4e9 lambda_2 = 0 lambda_3 = 0 V_per_phi0 = 2 E_c = 250e6 theta_f = 60 tlist = (np.arange(0, length, 1 / sampling_rate)) f_pulse = martinis_flux_pulse(length, lambda_2=lambda_2, lambda_3=lambda_3, theta_f=theta_f, f_01_max=f_01_max, E_c=E_c, V_per_phi0=V_per_phi0, f_interaction=f_interaction, J2=J2, return_unit='f01', sampling_rate=sampling_rate) eps_vec = f_pulse - w_q1 qoi = czu.simulate_quantities_of_interest(H_0=H_0, tlist=tlist, eps_vec=eps_vec, sim_step=1e-9) self.assertAlmostEqual(qoi['phi_cond'], 260.5987691809, places=0) self.assertAlmostEqual(qoi['L1'], 0.001272424, places=3)
def test_martinis_flux_pulse(self): length = 200e-9 lambda_2 = 0.015 lambda_3 = 0 theta_f = 8 f_01_max = 6.089e9 J2 = 4.2e6 E_c = 0 V_per_phi0 = np.pi / 1.7178 f_interaction = 4.940e9 f_bus = None asymmetry = 0 sampling_rate = 1e9 return_unit = 'V' theta_wave = wf.martinis_flux_pulse(length=length, lambda_2=lambda_2, lambda_3=lambda_3, theta_f=theta_f, f_01_max=f_01_max, J2=J2, E_c=E_c, V_per_phi0=V_per_phi0, f_interaction=f_interaction, f_bus=f_bus, asymmetry=asymmetry, sampling_rate=sampling_rate, return_unit=return_unit) test_wave = np.array([ 0., 0.03471175, 0.06891321, 0.10213049, 0.13395662, 0.16407213, 0.19225372, 0.21837228, 0.24238259, 0.26430828, 0.28422502, 0.30224448, 0.31850026, 0.33313676, 0.34630067, 0.35813509, 0.36877569, 0.37834846, 0.38696864, 0.39474049, 0.40175751, 0.40810307, 0.41385119, 0.41906739, 0.42380953, 0.42812868, 0.43206986, 0.43567281, 0.43897257, 0.44200007, 0.44478268, 0.4473446, 0.44970728, 0.45188975, 0.45390895, 0.45577993, 0.45751613, 0.45912955, 0.46063093, 0.46202989, 0.46333506, 0.46455423, 0.46569439, 0.46676186, 0.46776234, 0.468701, 0.46958252, 0.47041115, 0.47119076, 0.47192487, 0.47261668, 0.47326913, 0.4738849, 0.47446644, 0.47501598, 0.47553561, 0.47602721, 0.47649252, 0.47693314, 0.47735057, 0.47774615, 0.47812115, 0.47847674, 0.47881399, 0.47913389, 0.47943738, 0.4797253, 0.47999845, 0.48025757, 0.48050334, 0.4807364, 0.48095734, 0.48116671, 0.48136502, 0.48155275, 0.48173034, 0.48189819, 0.4820567, 0.48220622, 0.48234707, 0.48247957, 0.48260399, 0.48272061, 0.48282967, 0.48293139, 0.48302598, 0.48311363, 0.48319452, 0.4832688, 0.48333663, 0.48339813, 0.48345343, 0.48350263, 0.48354583, 0.4835831, 0.48361452, 0.48364015, 0.48366003, 0.48367421, 0.4836827, 0.48368553, 0.4836827, 0.48367421, 0.48366003, 0.48364015, 0.48361452, 0.4835831, 0.48354583, 0.48350263, 0.48345343, 0.48339813, 0.48333663, 0.4832688, 0.48319452, 0.48311363, 0.48302598, 0.48293139, 0.48282967, 0.48272061, 0.48260399, 0.48247957, 0.48234707, 0.48220622, 0.4820567, 0.48189819, 0.48173034, 0.48155275, 0.48136502, 0.48116671, 0.48095734, 0.4807364, 0.48050334, 0.48025757, 0.47999845, 0.4797253, 0.47943738, 0.47913389, 0.47881399, 0.47847674, 0.47812115, 0.47774615, 0.47735057, 0.47693314, 0.47649252, 0.47602721, 0.47553561, 0.47501598, 0.47446644, 0.4738849, 0.47326913, 0.47261668, 0.47192487, 0.47119076, 0.47041115, 0.46958252, 0.468701, 0.46776234, 0.46676186, 0.46569439, 0.46455423, 0.46333506, 0.46202989, 0.46063093, 0.45912955, 0.45751613, 0.45577993, 0.45390895, 0.45188975, 0.44970728, 0.4473446, 0.44478268, 0.44200007, 0.43897257, 0.43567281, 0.43206986, 0.42812868, 0.42380953, 0.41906739, 0.41385119, 0.40810307, 0.40175751, 0.39474049, 0.38696864, 0.37834846, 0.36877569, 0.35813509, 0.34630067, 0.33313676, 0.31850026, 0.30224448, 0.28422502, 0.26430828, 0.24238259, 0.21837228, 0.19225372, 0.16407213, 0.13395662, 0.10213049, 0.06891321, 0.03471175 ]) # FIXME: Only testing for the shape as the waveform has been updated self.assertEqual(np.shape(theta_wave), np.shape(test_wave)) # np.testing.assert_almost_equal(theta_wave, test_wave) lambda_2 = -0.02 # FIXME: we should test if the right warning is raised. # with warnings.catch_warnings(record=True) as w: theta_wave = wf.martinis_flux_pulse(length=length, lambda_2=lambda_2, lambda_3=lambda_3, theta_f=theta_f, f_01_max=f_01_max, J2=J2, E_c=E_c, V_per_phi0=V_per_phi0, f_interaction=f_interaction, f_bus=f_bus, asymmetry=asymmetry, sampling_rate=sampling_rate, return_unit=return_unit) test_wave_2 = np.array([ 0., 0.03234928, 0.06428708, 0.09542742, 0.12543163, 0.1540241, 0.18100034, 0.20622772, 0.22964031, 0.25122954, 0.2710329, 0.28912228, 0.30559317, 0.32055543, 0.33412579, 0.34642229, 0.35756021, 0.3676494, 0.37679261, 0.38508466, 0.39261214, 0.3994535, 0.40567941, 0.41135325, 0.41653169, 0.42126526, 0.42559899, 0.42957296, 0.43322283, 0.43658032, 0.43967369, 0.44252809, 0.44516595, 0.44760729, 0.44987001, 0.45197009, 0.45392188, 0.45573822, 0.45743067, 0.45900961, 0.4604844, 0.46186349, 0.46315449, 0.46436431, 0.4654992, 0.46656483, 0.46756635, 0.46850846, 0.46939543, 0.47023115, 0.47101919, 0.47176279, 0.47246495, 0.47312839, 0.47375563, 0.47434897, 0.47491052, 0.47544225, 0.47594595, 0.47642329, 0.47687579, 0.47730487, 0.47771185, 0.47809794, 0.47846427, 0.47881187, 0.47914172, 0.47945471, 0.47975169, 0.48003341, 0.48030062, 0.48055396, 0.48079408, 0.48102155, 0.4812369, 0.48144065, 0.48163325, 0.48181516, 0.48198676, 0.48214843, 0.48230053, 0.48244338, 0.48257727, 0.48270249, 0.4828193, 0.48292792, 0.48302858, 0.48312148, 0.4832068, 0.48328471, 0.48335536, 0.48341888, 0.4834754, 0.48352503, 0.48356785, 0.48360394, 0.48363339, 0.48365623, 0.48367252, 0.48368228, 0.48368553, 0.48368228, 0.48367252, 0.48365623, 0.48363339, 0.48360394, 0.48356785, 0.48352503, 0.4834754, 0.48341888, 0.48335536, 0.48328471, 0.4832068, 0.48312148, 0.48302858, 0.48292792, 0.4828193, 0.48270249, 0.48257727, 0.48244338, 0.48230053, 0.48214843, 0.48198676, 0.48181516, 0.48163325, 0.48144065, 0.4812369, 0.48102155, 0.48079408, 0.48055396, 0.48030062, 0.48003341, 0.47975169, 0.47945471, 0.47914172, 0.47881187, 0.47846427, 0.47809794, 0.47771185, 0.47730487, 0.47687579, 0.47642329, 0.47594595, 0.47544225, 0.47491052, 0.47434897, 0.47375563, 0.47312839, 0.47246495, 0.47176279, 0.47101919, 0.47023115, 0.46939543, 0.46850846, 0.46756635, 0.46656483, 0.4654992, 0.46436431, 0.46315449, 0.46186349, 0.4604844, 0.45900961, 0.45743067, 0.45573822, 0.45392188, 0.45197009, 0.44987001, 0.44760729, 0.44516595, 0.44252809, 0.43967369, 0.43658032, 0.43322283, 0.42957296, 0.42559899, 0.42126526, 0.41653169, 0.41135325, 0.40567941, 0.3994535, 0.39261214, 0.38508466, 0.37679261, 0.3676494, 0.35756021, 0.34642229, 0.33412579, 0.32055543, 0.30559317, 0.28912228, 0.2710329, 0.25122954, 0.22964031, 0.20622772, 0.18100034, 0.1540241, 0.12543163, 0.09542742, 0.06428708, 0.03234928 ]) # FIXME: Only testing for the shape as the waveform has been updated self.assertEqual(np.shape(theta_wave), np.shape(test_wave_2))
def acquire_data_point(self, **kw): tlist = (np.arange(0, self.fluxlutman.cz_length(), 1 / self.fluxlutman.sampling_rate())) if not self.fluxlutman.czd_double_sided(): f_pulse = wf.martinis_flux_pulse( length=self.fluxlutman.cz_length(), lambda_2=self.fluxlutman.cz_lambda_2(), lambda_3=self.fluxlutman.cz_lambda_3(), theta_f=self.fluxlutman.cz_theta_f(), f_01_max=self.fluxlutman.cz_freq_01_max(), J2=self.fluxlutman.cz_J2(), f_interaction=self.fluxlutman.cz_freq_interaction(), sampling_rate=self.fluxlutman.sampling_rate(), return_unit='f01') else: f_pulse = self.get_f_pulse_double_sided() # extract base frequency from the Hamiltonian w_q0 = np.real(self.H_0[1, 1]) eps_vec = f_pulse - w_q0 T1_q0 = self.noise_parameters_CZ.T1_q0() T1_q1 = self.noise_parameters_CZ.T1_q1() T2_q0_sweetspot = self.noise_parameters_CZ.T2_q0_sweetspot() T2_q0_interaction_point = self.noise_parameters_CZ.T2_q0_interaction_point( ) T2_q1 = self.noise_parameters_CZ.T2_q1() def Tphi_from_T1andT2(T1, T2): return 1 / (-1 / (2 * T1) + 1 / T2) if T2_q0_sweetspot != 0: Tphi01_q0_sweetspot = Tphi_from_T1andT2(T1_q0, T2_q0_sweetspot) else: Tphi01_q0_sweetspot = 0 if T2_q0_interaction_point != 0: Tphi01_q0_interaction_point = Tphi_from_T1andT2( T1_q0, T2_q0_interaction_point) else: Tphi01_q0_interaction_point = 0 # Tphi01=Tphi12=2*Tphi02 if T2_q1 != 0: Tphi01_q1 = Tphi_from_T1andT2(T1_q1, T2_q1) else: Tphi01_q1 = 0 def omega_prime(omega): # derivative of f_pulse ''' frequency is w = w_0 * cos(phi_e/2) where phi_e is the external flux through the SQUID. So the derivative wrt phi_e is w_prime = - w_0/2 sin(phi_e/2) = - w_0/2 * sqrt(1-cos(phi_e/2)**2) = - w_0/2 * sqrt(1-(w/w_0)**2) Note: no need to know what phi_e is. ''' return np.abs( (w_q0 / 2) * np.sqrt(1 - (omega / w_q0)**2) ) # we actually return the absolute value because it's the only one who matters later if Tphi01_q0_interaction_point != 0: # mode where the pure dephazing is amplitude-dependent w_min = np.nanmin(f_pulse) omega_prime_min = omega_prime(w_min) f_pulse = np.clip(f_pulse, 0, w_q0) f_pulse_prime = omega_prime(f_pulse) Tphi01_q0_vec = Tphi01_q0_sweetspot - f_pulse_prime / omega_prime_min * ( Tphi01_q0_sweetspot - Tphi01_q0_interaction_point) # we interpolate Tphi from the sweetspot to the interaction point (=worst point in terms of Tphi) # by weighting depending on the derivative of f_pulse compared to the derivative at the interaction point c_ops = c_ops_interpolating(T1_q0, T1_q1, Tphi01_q0_vec, Tphi01_q1) else: # mode where the collapse operators are time-independent, and possibly are 0 c_ops = jump_operators(T1_q0, T1_q1, 0, 0, 0, 0, 0, Tphi01_q0_sweetspot, Tphi01_q0_sweetspot, Tphi01_q0_sweetspot / 2, Tphi01_q1, Tphi01_q1, Tphi01_q1 / 2) qoi = simulate_quantities_of_interest_superoperator( H_0=self.H_0, tlist=tlist, c_ops=c_ops, eps_vec=eps_vec, sim_step=1 / self.fluxlutman.sampling_rate(), verbose=False) cost_func_val = -np.log10( 1 - qoi['avgatefid_compsubspace_pc']) # new cost function: infidelity #np.abs(qoi['phi_cond']-180) + qoi['L1']*100 * 5 return cost_func_val, qoi[ 'phi_cond'], qoi['L1'] * 100, qoi['L2'] * 100, qoi[ 'avgatefid_pc'] * 100, qoi['avgatefid_compsubspace_pc'] * 100
def acquire_data_point(self, **kw): tlist = (np.arange(0, self.fluxlutman.cz_length(), 1 / self.fluxlutman.sampling_rate())) if not self.fluxlutman.czd_double_sided(): theta_i = np.arctan(2 * self.fluxlutman.cz_J2() / (self.fluxlutman.cz_freq_01_max() - self.fluxlutman.cz_freq_interaction())) theta_f = fix_theta_f(self.fluxlutman.cz_lambda_3(), theta_i) f_pulse = wf.martinis_flux_pulse( length=self.fluxlutman.cz_length(), lambda_2=self.fluxlutman.cz_lambda_2(), lambda_3=self.fluxlutman.cz_lambda_3(), theta_f=theta_f, #self.fluxlutman.cz_theta_f(), f_01_max=self.fluxlutman.cz_freq_01_max(), J2=self.fluxlutman.cz_J2(), f_interaction=self.fluxlutman.cz_freq_interaction(), sampling_rate=self.fluxlutman.sampling_rate(), return_unit='f01') # return in terms of omega #amp = self.fluxlutman.detuning_to_amp((self.fluxlutman.cz_freq_01_max() - f_pulse)/(2*np.pi)) # transform detuning frequency to (positive) amplitude else: f_pulse, amp = self.get_f_pulse_double_sided() sim_step = 1 / self.fluxlutman.sampling_rate() # extract base frequency from the Hamiltonian w_q0 = np.real(self.H_0[1, 1]) w_q1 = np.real(self.H_0[3, 3]) alpha_q0 = np.real(self.H_0[2, 2]) - 2 * w_q0 eps_vec = f_pulse - w_q0 detuning = -eps_vec / (2 * np.pi ) # we express detuning in terms of frequency Vo = 1 / np.arccos(((w_q1 - 2 * alpha_q0) / (w_q0 - alpha_q0))**2) amp = Vo * np.arccos(((f_pulse - alpha_q0) / (w_q0 - alpha_q0))**2) # transformations used to match with Leo's simulations # we scale the amplitude and then recompute the pulse in detuning amp = amp * self.noise_parameters_CZ.voltage_scaling_factor() eps_vec_convolved_new = (w_q0 - 0 * alpha_q0) * np.sqrt( np.cos(amp / Vo)) + 0 * alpha_q0 - w_q0 f_pulse_convolved_new = eps_vec_convolved_new + w_q0 '''J_new=list() for eps in eps_vec: H=hamiltonian_timedependent(self.H_0,eps) J_new.append(np.real(H[1,3])) plot(x_plot_vec=[tlist*1e9], y_plot_vec=[np.array(J_new)/(2*np.pi)/1e6], title='Coupling during pulse', xlabel='Time (ns)',ylabel='J (MHz)',legend_labels=['J(t)'])''' ''' ####### functions that were used to convert from detuning to voltage but now we use functions from fluxlutman which are the same as those used in the experiment def invert_parabola(polynomial_coefficients,y): # useless a=polynomial_coefficients[0] b=polynomial_coefficients[1] c=polynomial_coefficients[2] return (-b+np.sqrt(b**2-4*a*(c-y)))/(2*a) voltage_frompoly = invert_parabola(self.fluxlutman.polycoeffs_freq_conv(),detuning) voltage_frompoly_interp = interp1d(tlist,voltage_frompoly) voltage_frompoly_convol = voltage_frompoly_interp(tlist_convol1) convolved_voltage=scipy.signal.convolve(voltage_frompoly_convol,impulse_response_convol)/sum(impulse_response_convol) convolved_detuning=give_parabola(self.fluxlutman.polycoeffs_freq_conv(),convolved_voltage) eps_vec_convolved=-convolved_detuning*(2*np.pi) eps_vec_convolved=eps_vec_convolved[0:np.size(tlist_convol1)] f_pulse_convolved=eps_vec_convolved+w_q0 ''' if self.noise_parameters_CZ.distortions(): impulse_response = np.gradient(self.fitted_stepresponse_ty[1]) # plot(x_plot_vec=[self.fitted_stepresponse_ty[0]],y_plot_vec=[self.fitted_stepresponse_ty[1]], # title='Step response', # xlabel='Time (ns)') # plot(x_plot_vec=[self.fitted_stepresponse_ty[0]],y_plot_vec=[impulse_response], # title='Impulse response', # xlabel='Time (ns)') # use interpolation to be sure that amp and impulse_response have the same delta_t separating two values amp_interp = interp1d(tlist, amp) impulse_response_interp = interp1d(self.fitted_stepresponse_ty[0], impulse_response) tlist_convol1 = tlist tlist_convol2 = np.arange(0, self.fluxlutman.cz_length(), 1 / self.fluxlutman.sampling_rate()) amp_convol = amp_interp(tlist_convol1) impulse_response_convol = impulse_response_interp(tlist_convol2) # plot(x_plot_vec=[tlist_convol1*1e9],y_plot_vec=[amp_convol], # title='Pulse in voltage, length=240ns', # xlabel='Time (ns)',ylabel='Amplitude (V)') # plot(x_plot_vec=[tlist_convol*1e9],y_plot_vec=[impulse_response_convol], # title='Impulse response', # xlabel='Time (ns)') convolved_amp = scipy.signal.convolve( amp_convol, impulse_response_convol) / sum(impulse_response_convol) # plot(x_plot_vec=[tlist_convol1*1e9,np.arange(np.size(convolved_amp))*sim_step*1e9], # y_plot_vec=[amp_convol, convolved_amp], # title='Net-zero, Pulse_length=240ns', # xlabel='Time (ns)',ylabel='Amplitude (V)',legend_labels=['Ideal','Distorted']) def give_parabola(polynomial_coefficients, x): a = polynomial_coefficients[0] b = polynomial_coefficients[1] c = polynomial_coefficients[2] return a * x**2 + b * x + c convolved_detuning_new = give_parabola( self.fluxlutman.polycoeffs_freq_conv(), convolved_amp) # plot(x_plot_vec=[tlist*1e9,np.arange(np.size(convolved_amp))*sim_step*1e9], # y_plot_vec=[detuning/1e9, convolved_detuning_new/1e9], # title='Net-zero, Pulse_length=240ns', # xlabel='Time (ns)',ylabel='Detuning (GHz)',legend_labels=['Ideal','Distorted']) eps_vec_convolved_new = -convolved_detuning_new * (2 * np.pi) eps_vec_convolved_new = eps_vec_convolved_new[0:np. size(tlist_convol1)] f_pulse_convolved_new = eps_vec_convolved_new + w_q0 # else: # eps_vec_convolved_new=eps_vec # f_pulse_convolved_new=f_pulse T1_q0 = self.noise_parameters_CZ.T1_q0() T1_q1 = self.noise_parameters_CZ.T1_q1() T2_q0_sweetspot = self.noise_parameters_CZ.T2_q0_sweetspot() T2_q0_interaction_point = self.noise_parameters_CZ.T2_q0_interaction_point( ) T2_q1 = self.noise_parameters_CZ.T2_q1() def Tphi_from_T1andT2(T1, T2): return 1 / (-1 / (2 * T1) + 1 / T2) if T2_q0_sweetspot != 0: Tphi01_q0_sweetspot = Tphi_from_T1andT2(T1_q0, T2_q0_sweetspot) else: Tphi01_q0_sweetspot = 0 if T2_q0_interaction_point != 0: Tphi01_q0_interaction_point = Tphi_from_T1andT2( T1_q0, T2_q0_interaction_point) else: Tphi01_q0_interaction_point = 0 # Tphi01=Tphi12=2*Tphi02 if T2_q1 != 0: Tphi01_q1 = Tphi_from_T1andT2(T1_q1, T2_q1) else: Tphi01_q1 = 0 def omega_prime(omega): # derivative of f_pulse ''' frequency is w = w_0 * cos(phi_e/2) where phi_e is the external flux through the SQUID. So the derivative wrt phi_e is w_prime = - w_0/2 sin(phi_e/2) = - w_0/2 * sqrt(1-cos(phi_e/2)**2) = - w_0/2 * sqrt(1-(w/w_0)**2) Note: no need to know what phi_e is. ''' return np.abs( (w_q0 / 2) * np.sqrt(1 - (omega / w_q0)**2) ) # we actually return the absolute value because it's the only one who matters later if Tphi01_q0_interaction_point != 0: # mode where the pure dephazing is amplitude-dependent w_min = np.nanmin(f_pulse_convolved_new) omega_prime_min = omega_prime(w_min) f_pulse_convolved_new = np.clip(f_pulse_convolved_new, 0, w_q0) f_pulse_convolved_new_prime = omega_prime(f_pulse_convolved_new) Tphi01_q0_vec = Tphi01_q0_sweetspot - f_pulse_convolved_new_prime / omega_prime_min * ( Tphi01_q0_sweetspot - Tphi01_q0_interaction_point) # we interpolate Tphi from the sweetspot to the interaction point (=worst point in terms of Tphi) # by weighting depending on the derivative of f_pulse compared to the derivative at the interaction point c_ops = c_ops_interpolating(T1_q0, T1_q1, Tphi01_q0_vec, Tphi01_q1) else: # mode where the collapse operators are time-independent, and possibly are 0 c_ops = jump_operators(T1_q0, T1_q1, 0, 0, 0, 0, 0, Tphi01_q0_sweetspot, Tphi01_q0_sweetspot, Tphi01_q0_sweetspot / 2, Tphi01_q1, Tphi01_q1, Tphi01_q1 / 2) qoi = simulate_quantities_of_interest_superoperator( H_0=self.H_0, tlist=tlist, c_ops=c_ops, eps_vec=eps_vec_convolved_new, sim_step=1 / self.fluxlutman.sampling_rate(), verbose=False) cost_func_val = np.abs(qoi['phi_cond'] - 180) # new cost function: infidelity #np.abs(qoi['phi_cond']-180) + qoi['L1']*100 * 5 return cost_func_val, qoi[ 'phi_cond'], qoi['L1'] * 100, qoi['L2'] * 100, qoi[ 'avgatefid_pc'] * 100, qoi['avgatefid_compsubspace_pc'] * 100
def _gen_cz(self): dac_scale_factor = self.get_amp_to_dac_val_scale_factor() if not self.czd_double_sided(): CZ = wf.martinis_flux_pulse( length=self.cz_length(), lambda_2=self.cz_lambda_2(), lambda_3=self.cz_lambda_3(), theta_f=self.cz_theta_f(), f_01_max=self.cz_freq_01_max(), J2=self.cz_J2(), f_interaction=self.cz_freq_interaction(), sampling_rate=self.sampling_rate(), return_unit='f01') return dac_scale_factor*self.detuning_to_amp( self.cz_freq_01_max() - CZ) else: # Simple double sided CZ pulse implemented in most basic form. # repeats the same CZ gate twice and sticks it together. half_CZ_A = wf.martinis_flux_pulse( length=self.cz_length()*self.czd_length_ratio(), lambda_2=self.cz_lambda_2(), lambda_3=self.cz_lambda_3(), theta_f=self.cz_theta_f(), f_01_max=self.cz_freq_01_max(), # V_per_phi0=self.cz_V_per_phi0(), J2=self.cz_J2(), # E_c=self.cz_E_c(), f_interaction=self.cz_freq_interaction(), sampling_rate=self.sampling_rate(), return_unit='f01') half_CZ_A = dac_scale_factor*self.detuning_to_amp( self.cz_freq_01_max() - half_CZ_A) # Generate the second CZ pulse. If the params are np.nan, default # to the main parameter if not np.isnan(self.czd_theta_f()): d_theta_f = self.czd_theta_f() else: d_theta_f = self.cz_theta_f() if not np.isnan(self.czd_lambda_2()): d_lambda_2 = self.czd_lambda_2() else: d_lambda_2 = self.cz_lambda_2() if not np.isnan(self.czd_lambda_3()): d_lambda_3 = self.czd_lambda_3() else: d_lambda_3 = self.cz_lambda_3() half_CZ_B = wf.martinis_flux_pulse( length=self.cz_length()*(1-self.czd_length_ratio()), lambda_2=d_lambda_2, lambda_3=d_lambda_3, theta_f=d_theta_f, f_01_max=self.cz_freq_01_max(), # V_per_phi0=self.cz_V_per_phi0(), J2=self.cz_J2(), # E_c=self.cz_E_c(), f_interaction=self.cz_freq_interaction(), sampling_rate=self.sampling_rate(), return_unit='f01') half_CZ_B = dac_scale_factor*self.detuning_to_amp( self.cz_freq_01_max() - half_CZ_B, positive_branch=False) amp_rat = self.czd_amp_ratio() waveform = np.concatenate( [half_CZ_A, amp_rat*half_CZ_B + self.czd_amp_offset()]) return waveform
def acquire_data_point(self, **kw): '''# BENCHMARK FOR HOW THE COUPLING IMPACTS THE HAMILTONIAN PARAMETERS eigs,eigvectors = self.H_0.eigenstates() eigs=eigs/(2*np.pi) print('omegaA =',eigs[1]) print('omegaB =',eigs[2]) print(eigs[4]-eigs[1]-eigs[2]) print('etaA =',eigs[3]-2*eigs[1]) print('etaB =',eigs[5]-2*eigs[2]) print(eigvectors[4],'\n fidelity with 1 /otimes 1=',np.abs(eigvectors[4].dag().overlap(qtp.basis(9,4)))**2) print(eigvectors[5],'\n fidelity with 0 /otimes 2=',np.abs(eigvectors[5].dag().overlap(qtp.basis(9,2)))**2) ''' sim_step = 1 / self.fluxlutman.sampling_rate() subdivisions_of_simstep = 4 sim_step_new = sim_step / subdivisions_of_simstep # waveform is generated according to sampling rate of AWG, # but we can use a different step for simulating the time evolution tlist = (np.arange(0, self.fluxlutman.cz_length(), sim_step)) tlist_new = (np.arange(0, self.fluxlutman.cz_length(), sim_step_new)) #theta_i = np.arctan(2*self.fluxlutman.cz_J2() / (self.fluxlutman.cz_freq_01_max() - self.fluxlutman.cz_freq_interaction())) #theta_f=fix_theta_f(self.fluxlutman.cz_lambda_3(),theta_i) #theta_i=theta_i*360/(2*np.pi) #self.fluxlutman.cz_theta_f(theta_f) if not self.fluxlutman.czd_double_sided(): f_pulse = wf.martinis_flux_pulse( length=self.fluxlutman.cz_length(), lambda_2=self.fluxlutman.cz_lambda_2(), lambda_3=self.fluxlutman.cz_lambda_3(), theta_f=self.fluxlutman.cz_theta_f(), f_01_max=self.fluxlutman.cz_freq_01_max(), J2=self.fluxlutman.cz_J2(), f_interaction=self.fluxlutman.cz_freq_interaction(), sampling_rate=self.fluxlutman.sampling_rate(), return_unit='f01') # return in terms of omega amp = self.fluxlutman.detuning_to_amp( (self.fluxlutman.cz_freq_01_max() - f_pulse) / (2 * np.pi)) # transform detuning frequency to (positive) amplitude else: f_pulse, amp = self.get_f_pulse_double_sided() # For better accuracy in simulations, redefine f_pulse and amp in trems of sim_step_new tlist_temp = np.concatenate( (tlist, np.array([self.fluxlutman.cz_length()]))) f_pulse_temp = np.concatenate((f_pulse, np.array([f_pulse[-1]]))) amp_temp = np.concatenate((amp, np.array([amp[-1]]))) f_pulse_interp = interp1d(tlist_temp, f_pulse_temp) amp_interp = interp1d(tlist_temp, amp_temp) f_pulse = f_pulse_interp(tlist_new) amp = amp_interp(tlist_new) # plot(x_plot_vec=[tlist_new*1e9], # y_plot_vec=[f_pulse/(2*np.pi)/1e9], # title='Freq. of fluxing qubit during pulse', # xlabel='Time (ns)',ylabel='Freq. (GHz)',legend_labels=['omega_B(t)']) amp = amp * self.noise_parameters_CZ.voltage_scaling_factor() # extract base frequency from the Hamiltonian w_q0 = np.real(self.H_0[1, 1]) #w_q1=np.real(self.H_0[3,3]) #alpha_q0=np.real(self.H_0[2,2])-2*w_q0 #eps_vec = f_pulse - w_q0 #detuning = -eps_vec/(2*np.pi) # we express detuning in terms of frequency '''#BENCHMARK TO CHECK HOW THE COUPLING VARIES AS A FUNCTION OF DETUNING J_new=list() for eps in eps_vec: H=hamiltonian_timedependent(self.H_0,eps) J_new.append(np.real(H[1,3])) plot(x_plot_vec=[tlist_new*1e9], y_plot_vec=[np.array(J_new)/(2*np.pi)/1e6], title='Coupling during pulse', xlabel='Time (ns)',ylabel='J (MHz)',legend_labels=['J(t)'])''' ''' USELESS ####### functions that were used to convert from detuning to voltage but now we use functions from fluxlutman which are the same as those used in the experiment def invert_parabola(polynomial_coefficients,y): # useless a=polynomial_coefficients[0] b=polynomial_coefficients[1] c=polynomial_coefficients[2] return (-b+np.sqrt(b**2-4*a*(c-y)))/(2*a) voltage_frompoly = invert_parabola(self.fluxlutman.polycoeffs_freq_conv(),detuning) voltage_frompoly_interp = interp1d(tlist,voltage_frompoly) voltage_frompoly_convol = voltage_frompoly_interp(tlist_convol1) convolved_voltage=scipy.signal.convolve(voltage_frompoly_convol,impulse_response_convol)/sum(impulse_response_convol) convolved_detuning=give_parabola(self.fluxlutman.polycoeffs_freq_conv(),convolved_voltage) eps_vec_convolved=-convolved_detuning*(2*np.pi) eps_vec_convolved=eps_vec_convolved[0:np.size(tlist_convol1)] f_pulse_convolved=eps_vec_convolved+w_q0 ''' def give_parabola(polynomial_coefficients, x): a = polynomial_coefficients[0] b = polynomial_coefficients[1] c = polynomial_coefficients[2] return a * x**2 + b * x + c if self.noise_parameters_CZ.distortions(): impulse_response = np.gradient(self.fitted_stepresponse_ty[1]) # plot(x_plot_vec=[self.fitted_stepresponse_ty[0]],y_plot_vec=[self.fitted_stepresponse_ty[1]], # title='Step response', # xlabel='Time (ns)') # plot(x_plot_vec=[self.fitted_stepresponse_ty[0]],y_plot_vec=[impulse_response], # title='Impulse response', # xlabel='Time (ns)') # use interpolation to be sure that amp and impulse_response have the same delta_t separating two values amp_interp = interp1d(tlist_new, amp) # amp is now managed already above impulse_response_interp = interp1d(self.fitted_stepresponse_ty[0], impulse_response) tlist_convol1 = tlist_new tlist_convol2 = np.arange(0, self.fitted_stepresponse_ty[0][-1], sim_step_new) amp_convol = amp_interp(tlist_convol1) impulse_response_convol = impulse_response_interp(tlist_convol2) # plot(x_plot_vec=[tlist_convol1*1e9],y_plot_vec=[amp_convol], # title='Pulse in voltage, length=240ns', # xlabel='Time (ns)',ylabel='Amplitude (V)') # plot(x_plot_vec=[tlist_convol*1e9],y_plot_vec=[impulse_response_convol], # title='Impulse response', # xlabel='Time (ns)') convolved_amp = scipy.signal.convolve( amp_convol, impulse_response_convol) / sum(impulse_response_convol) # plot(x_plot_vec=[tlist_convol1*1e9,np.arange(np.size(convolved_amp))*sim_step*1e9], # y_plot_vec=[amp_convol, convolved_amp], # title='Net-zero, Pulse_length=240ns', # xlabel='Time (ns)',ylabel='Amplitude (V)',legend_labels=['Ideal','Distorted']) convolved_detuning_new = give_parabola( self.fluxlutman.polycoeffs_freq_conv(), convolved_amp) # plot(x_plot_vec=[tlist*1e9,np.arange(np.size(convolved_amp))*sim_step*1e9], # y_plot_vec=[detuning/1e9, convolved_detuning_new/1e9], # title='Net-zero, Pulse_length=240ns', # xlabel='Time (ns)',ylabel='Detuning (GHz)',legend_labels=['Ideal','Distorted']) eps_vec_convolved_new = -convolved_detuning_new * (2 * np.pi) eps_vec_convolved_new = eps_vec_convolved_new[0:np. size(tlist_convol1)] f_pulse_convolved_new = eps_vec_convolved_new + w_q0 else: detuning_new = give_parabola( self.fluxlutman.polycoeffs_freq_conv(), amp) eps_vec_convolved_new = -detuning_new * (2 * np.pi) f_pulse_convolved_new = eps_vec_convolved_new + w_q0 T1_q0 = self.noise_parameters_CZ.T1_q0() T1_q1 = self.noise_parameters_CZ.T1_q1() T2_q0_sweetspot = self.noise_parameters_CZ.T2_q0_sweetspot() T2_q0_interaction_point = self.noise_parameters_CZ.T2_q0_interaction_point( ) T2_q0_amplitude_dependent = self.noise_parameters_CZ.T2_q0_amplitude_dependent( ) T2_q1 = self.noise_parameters_CZ.T2_q1() def Tphi_from_T1andT2(T1, T2): return 1 / (-1 / (2 * T1) + 1 / T2) if T2_q0_sweetspot != 0: Tphi01_q0_sweetspot = Tphi_from_T1andT2(T1_q0, T2_q0_sweetspot) else: Tphi01_q0_sweetspot = 0 if T2_q0_interaction_point != 0: Tphi01_q0_interaction_point = Tphi_from_T1andT2( T1_q0, T2_q0_interaction_point) else: Tphi01_q0_interaction_point = 0 # Tphi01=Tphi12=2*Tphi02 if T2_q1 != 0: Tphi01_q1 = Tphi_from_T1andT2(T1_q1, T2_q1) else: Tphi01_q1 = 0 if T2_q0_amplitude_dependent[0] != -1: def expT2(x, gc, amp, tau): return gc + gc * amp * np.exp(-x / tau) T2_q0_vec = expT2(f_pulse_convolved_new / (2 * np.pi), T2_q0_amplitude_dependent[0], T2_q0_amplitude_dependent[1], T2_q0_amplitude_dependent[2]) Tphi01_q0_vec = Tphi_from_T1andT2(T1_q0, T2_q0_vec) c_ops = c_ops_interpolating(T1_q0, T1_q1, Tphi01_q0_vec, Tphi01_q1) else: def omega_prime(omega): # derivative of f_pulse ''' frequency is w = w_0 * cos(phi_e/2) where phi_e is the external flux through the SQUID. So the derivative wrt phi_e is w_prime = - w_0/2 sin(phi_e/2) = - w_0/2 * sqrt(1-cos(phi_e/2)**2) = - w_0/2 * sqrt(1-(w/w_0)**2) Note: no need to know what phi_e is. ''' return np.abs( (w_q0 / 2) * np.sqrt(1 - (omega / w_q0)**2) ) # we actually return the absolute value because it's the only one who matters later if Tphi01_q0_interaction_point != 0: # mode where the pure dephazing is amplitude-dependent w_min = np.nanmin(f_pulse_convolved_new) omega_prime_min = omega_prime(w_min) f_pulse_convolved_new = np.clip(f_pulse_convolved_new, 0, w_q0) f_pulse_convolved_new_prime = omega_prime( f_pulse_convolved_new) Tphi01_q0_vec = Tphi01_q0_sweetspot - f_pulse_convolved_new_prime / omega_prime_min * ( Tphi01_q0_sweetspot - Tphi01_q0_interaction_point) # we interpolate Tphi from the sweetspot to the interaction point (=worst point in terms of Tphi) # by weighting depending on the derivative of f_pulse compared to the derivative at the interaction point c_ops = c_ops_interpolating(T1_q0, T1_q1, Tphi01_q0_vec, Tphi01_q1) else: # mode where the collapse operators are time-independent, and possibly are 0 c_ops = jump_operators(T1_q0, T1_q1, 0, 0, 0, 0, 0, Tphi01_q0_sweetspot, Tphi01_q0_sweetspot, Tphi01_q0_sweetspot / 2, Tphi01_q1, Tphi01_q1, Tphi01_q1 / 2) qoi = simulate_quantities_of_interest_superoperator( H_0=self.H_0, tlist=tlist_new, c_ops=c_ops, w_bus=self.noise_parameters_CZ.w_bus(), eps_vec=eps_vec_convolved_new, sim_step=sim_step_new, verbose=False) cost_func_val = -np.log10( 1 - qoi['avgatefid_compsubspace_pc']) # new cost function: infidelity #np.abs(qoi['phi_cond']-180) + qoi['L1']*100 * 5 return cost_func_val, qoi['phi_cond'], qoi['L1'] * 100, qoi[ 'L2'] * 100, qoi['avgatefid_pc'] * 100, qoi[ 'avgatefid_compsubspace_pc'] * 100, qoi['phase_q0'], qoi[ 'phase_q1']
def simulate_CZ_trajectory(length, lambda_2, lambda_3, theta_f, f_01_max, f_interaction, J2, E_c, V_per_phi0=1, dac_flux_coefficient=None, asymmetry=0, sampling_rate=2e9, return_all=False, verbose=False): """ Input args: length (float) :parameter for waveform (s) lambda_2 (float): parameter for waveform lambda_3 (float): parameter for waveform theta_f (float): parameter for waveform (deg) f_01_max (float): parameter for waveform (Hz) f_interaction (float): parameter for waveform (Hz) J2 (float): parameter for waveform (Hz) E_c (float): parameter for waveform (Hz) V_per_phi0 (float): parameter for waveform (V) asymmetry (float): parameter for waveform sampling_rate (float): sampling rate used in simulation (Hz) verbose (bool) : enables optional print statements return_all (bool) : if True returns internal params of the simulation (see below). Returns: picked_up_phase in degree leakage population leaked to the 02 state N.B. the function only returns the quantities below if return_all is True res1: vector of qutip results for 1 excitation res2: vector of qutip results for 1 excitation eps_vec : vector of detunings as function of time tlist: vector of times used in the simulation """ if dac_flux_coefficient is not None: logging.warning('dac_flux_coefficient deprecated. Please use the ' 'physically meaningful V_per_phi0 instead.') V_per_phi0 = np.pi / dac_flux_coefficient Hx = qtp.sigmax() * 2 * np.pi # so that freqs are real and not radial Hz = qtp.sigmaz() * 2 * np.pi # so that freqs are real and not radial def J1_t(t, args=None): # if there is only one excitation, there is no interaction return 0 def J2_t(t, args=None): return J2 tlist = (np.arange(0, length, 1 / sampling_rate)) f_pulse = martinis_flux_pulse(length, lambda_2=lambda_2, lambda_3=lambda_3, theta_f=theta_f, f_01_max=f_01_max, E_c=E_c, V_per_phi0=V_per_phi0, f_interaction=f_interaction, J2=J2, return_unit='eps', sampling_rate=sampling_rate) eps_vec = f_pulse # function used for qutip simulation def eps_t(t, args=None): idx = np.argmin(abs(tlist - t)) return float(eps_vec[idx]) H1_t = [[Hx, J1_t], [Hz, eps_t]] H2_t = [[Hx, J2_t], [Hz, eps_t]] try: psi0 = qtp.basis(2, 0) res1 = qtp.mesolve(H1_t, psi0, tlist, [], []) # ,progress_bar=False ) res2 = qtp.mesolve(H2_t, psi0, tlist, [], []) # ,progress_bar=False ) except Exception as e: logging.warning(e) # This is exception handling to be able to use this in a loop return 0, 0 phases1 = (ket_to_phase(res1.states) % (2 * np.pi)) / (2 * np.pi) * 360 phases2 = (ket_to_phase(res2.states) % (2 * np.pi)) / (2 * np.pi) * 360 phase_diff_deg = (phases2 - phases1) % 360 leakage_vec = np.zeros(len(res2.states)) for i in range(len(res2.states)): leakage_vec[i] = 1 - (psi0.dag() * res2.states[i]).norm() leakage = leakage_vec[-1] picked_up_phase = phase_diff_deg[-1] if verbose: print('Picked up phase: {:.1f} (deg) \nLeakage: \t {:.3f} (%)'.format( picked_up_phase, leakage * 100)) if return_all: return picked_up_phase, leakage, res1, res2, eps_vec, tlist else: return picked_up_phase, leakage
def test_time_dependent_fast_adiabatic_pulse(self): # Hamiltonian pars alpha_q0 = 250e6 * 2 * np.pi J = 2.5e6 * 2 * np.pi w_q0 = 6e9 * 2 * np.pi w_q1 = 7e9 * 2 * np.pi H_0 = czu.coupled_transmons_hamiltonian(w_q0, w_q1, alpha_q0=alpha_q0, J=J) # Parameters f_interaction = w_q0 + alpha_q0 f_01_max = w_q1 length = 240e-9 sampling_rate = 2.4e9 lambda_2 = 0 lambda_3 = 0 V_per_phi0 = 2 E_c = 250e6 theta_f = 85 J2 = J * np.sqrt(2) tlist = (np.arange(0, length, 1 / sampling_rate)) f_pulse = martinis_flux_pulse(length, lambda_2=lambda_2, lambda_3=lambda_3, theta_f=theta_f, f_01_max=f_01_max, E_c=E_c, V_per_phi0=V_per_phi0, f_interaction=f_interaction, J2=J2, return_unit='f01', sampling_rate=sampling_rate) eps_vec = f_pulse - w_q1 def eps_t(t, args=None): idx = np.argmin(abs(tlist - t)) return float(eps_vec[idx]) H_c = czu.n_q1 H_t = [H_0, [H_c, eps_t]] # Calculate the trajectory t0 = time.time() U_t = qtp.propagator(H_t, tlist) t1 = time.time() print('simulation took {:.2f}s'.format(t1 - t0)) test_indices = range(len(tlist))[::50] phases = np.asanyarray([ czu.phases_from_unitary( czu.rotating_frame_transformation(U_t[t_idx], tlist[t_idx], w_q0, w_q1)) for t_idx in test_indices ]) t2 = time.time() print('Extracting phases took {:.2f}s'.format(t2 - t1)) cond_phases = phases[:, 4] expected_phases = np.array([ 0., 356.35610703, 344.93107947, 326.69596131, 303.99108914, 279.5479871, 254.95329258, 230.67722736, 207.32417721, 186.68234108, 171.38527544, 163.55444707 ]) np.testing.assert_array_almost_equal(cond_phases, expected_phases) L1 = [czu.leakage_from_unitary(U_t[t_idx]) for t_idx in test_indices] L2 = [czu.seepage_from_unitary(U_t[t_idx]) for t_idx in test_indices] expected_L1 = np.array([ 0.0, 0.026757049282008727, 0.06797292824458401, 0.09817896580396734, 0.11248845556751286, 0.11574586085284067, 0.11484563049326857, 0.11243390482702287, 0.1047153697736567, 0.08476542786503238, 0.04952861565413047, 0.00947869831231718 ]) # This condition holds for unital (and unitary) processes and depends # on the dimension of the subspace see Woods Gambetta 2018 expected_L2 = 2 * expected_L1 np.testing.assert_array_almost_equal(L1, expected_L1) np.testing.assert_array_almost_equal(L2, expected_L2)