From b0c77dab5a7ec5eaaaac06f01877dc11fcd3a2fe Mon Sep 17 00:00:00 2001 From: Valentin Boettcher Date: Fri, 24 May 2024 21:26:28 -0400 Subject: [PATCH] =?UTF-8?q?CODE:=20make=20other=20parameters=20scale=20wit?= =?UTF-8?q?h=20=CE=A9=20and=20add=20real=20RWA=20and=20add=20sweep?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../experiments/.#002_rabi_detuning_scan.py | 1 - scripts/experiments/002_rabi_detuning_scan.py | 89 ++++++++++++++----- src/rabifun/plots.py | 7 +- src/rabifun/system.py | 53 +++++++---- 4 files changed, 107 insertions(+), 43 deletions(-) delete mode 120000 scripts/experiments/.#002_rabi_detuning_scan.py diff --git a/scripts/experiments/.#002_rabi_detuning_scan.py b/scripts/experiments/.#002_rabi_detuning_scan.py deleted file mode 120000 index 43ca834..0000000 --- a/scripts/experiments/.#002_rabi_detuning_scan.py +++ /dev/null @@ -1 +0,0 @@ -hiro@Lobsang.149236:1716554985 \ No newline at end of file diff --git a/scripts/experiments/002_rabi_detuning_scan.py b/scripts/experiments/002_rabi_detuning_scan.py index 5829d86..f85d1d7 100644 --- a/scripts/experiments/002_rabi_detuning_scan.py +++ b/scripts/experiments/002_rabi_detuning_scan.py @@ -11,33 +11,43 @@ def transient_rabi(): params = Params( η=0.7, - Ω=13.07, - δ=13.07 / 4, - d=13.07 / 4 * 1, - laser_detuning=0.1, - Δ=13.07 / 4 * 0.01, + Ω=13, + δ=1 / 4, + d=0.02, + laser_detuning=0, + Δ=0, N=3, measurement_detuning=1, rwa=False, ) - params.laser_off_time = params.lifetimes(10) + + params.laser_off_time = params.lifetimes(15) t = time_axis(params, 50, 0.1) solution = solve(t, params) signal = output_signal(t, solution.y, params) f, (_, ax) = plot_simulation_result( - make_figure(), t, signal, params, window=(params.lifetimes(10), t[-1]) + make_figure(), t, signal, params, window=(params.lifetimes(15), t[-1]) ) plot_sidebands(ax, params) - # ax.set_xlim(0.73, 0.77) f.suptitle("Transient Rabi oscillation") def steady_rabi(): """A steady state rabi oscillation without noise.""" - params = Params(η=0.001, d=0.1, laser_detuning=0, Δ=0.05) - t = time_axis(params, lifetimes=10, resolution=1) + params = Params( + η=0.7, + Ω=13, + δ=1 / 4, + d=0.02, + laser_detuning=0, + Δ=0, + N=3, + measurement_detuning=1, + rwa=False, + ) + t = time_axis(params, lifetimes=20, resolution=0.01) solution = solve(t, params) signal = output_signal(t, solution.y, params) @@ -53,15 +63,31 @@ def steady_rabi(): def noisy_transient_rabi(): """A transient rabi oscillation with noise.""" - params = Params(η=0.001, d=0.1, laser_detuning=0, Δ=0.05) - t = time_axis(params, 2, 1) + params = Params( + η=0.7, + Ω=13, + δ=1 / 4, + d=0.02, + laser_detuning=0, + Δ=0, + N=3, + measurement_detuning=1, + rwa=False, + ) + + t = time_axis(params, 20, 0.01) + + params.laser_off_time = params.lifetimes(5) + solution = solve(t, params) signal = output_signal(t, solution.y, params) - noise_strength = 0.1 + noise_strength = 5 signal = add_noise(signal, noise_strength) - f, (_, ax) = plot_simulation_result(make_figure(), t, signal, params) + f, (_, ax) = plot_simulation_result( + make_figure(), t, signal, params, window=(params.laser_off_time, t[-1]) + ) plot_sidebands(ax, params) f.suptitle(f"Transient Rabi oscillation with noise strength {noise_strength}.") @@ -69,14 +95,25 @@ def noisy_transient_rabi(): def ringdown_after_rabi(): """Demonstrates the nonstationary ringdown of the resonator after turning off the EOM and laser drive.""" - off_lifetime = 4 + off_lifetime = 5 laser_detuning = 0.1 - params = Params(η=0.0001, d=0.01, laser_detuning=laser_detuning, Δ=0.00, N=2) + + params = Params( + η=0.7, + Ω=13, + δ=1 / 4, + d=0.02, + laser_detuning=laser_detuning, + Δ=0, + N=3, + measurement_detuning=-2, + rwa=False, + ) params.laser_off_time = params.lifetimes(off_lifetime) params.drive_off_time = params.lifetimes(off_lifetime) - t = time_axis(params, lifetimes=5, resolution=1) + t = time_axis(params, lifetimes=20, resolution=0.01) solution = solve(t, params) signal = output_signal(t, solution.y, params) @@ -94,11 +131,21 @@ def ringdown_after_rabi(): def sweep(): - """A transient rabi oscillation without noise.""" + """A sweep of the laser over the spectrum.""" - params = Params(η=1, δ=1 / 4, d=0.0, laser_detuning=100, N=1) - t = time_axis(params, 1000, 0.001) - params.dynamic_detunting = -100, t[-1] + params = Params( + η=1, + Ω=1, + δ=1 / 4, + d=0.0, + laser_detuning=-2, + Δ=0, + N=3, + measurement_detuning=0, + rwa=False, + ) + t = time_axis(params, params.lifetimes(2000), 0.1) + params.dynamic_detunting = (2 * params.δ + params.N) * params.Ω, t[-1] solution = solve(t, params) signal = output_signal(t, solution.y, params) diff --git a/src/rabifun/plots.py b/src/rabifun/plots.py index 3c173cf..1d6c989 100644 --- a/src/rabifun/plots.py +++ b/src/rabifun/plots.py @@ -46,7 +46,7 @@ def plot_simulation_result( ax3.plot( freq, - np.unwrap(np.angle(fft) + np.pi, 2 * np.pi), + np.angle(fft), linestyle="--", color="C2", alpha=0.5, @@ -63,7 +63,7 @@ def plot_sidebands(ax, params: Params): :param ax: axis to plot on :param params: system parameters """ - energy = params.rabi_splitting / (2 * np.pi) + energy = params.rabi_splitting first_sidebands = np.abs( -(params.laser_detuning + params.measurement_detuning) @@ -71,8 +71,7 @@ def plot_sidebands(ax, params: Params): + params.Δ / 2 ) second_sidebands = ( - params.Ω - - params.δ + params.Ω * (1 - params.δ) - (params.laser_detuning + params.measurement_detuning) + np.array([1, -1]) * energy / 2 - params.Δ / 2 diff --git a/src/rabifun/system.py b/src/rabifun/system.py index 2c6091c..6df22bf 100644 --- a/src/rabifun/system.py +++ b/src/rabifun/system.py @@ -12,24 +12,26 @@ class Params: """Number of bath modes.""" Ω: float = 1 - """Free spectral range of the system.""" - - η: float = 0.1 - """Decay rate of the system.""" - - d: float = 0.01 - """Drive amplitude.""" - - Δ: float = 0.0 - """Detuning of the EOM drive.""" + """Free spectral range of the system in *frequency units*.""" δ: float = 1 / 4 - """Mode splitting.""" + """Mode splitting in units of :any:`Ω`.""" + + η: float = 0.1 + """Decay rate :math:`\eta/2` of the system in frequency units (no + :math:`2 \pi`).""" + + d: float = 0.01 + """Drive amplitude in units of :any:`Ω`.""" + + Δ: float = 0.0 + """Detuning of the EOM drive in *frequency units*.""" laser_detuning: float = 0.0 """Detuning of the laser relative to the _A_ mode.""" measurement_detuning: float = 0.0 + """Additional detuning of the measurement laser signal relative to the _A_ mode.""" laser_off_time: float | None = None """Time at which the laser is turned off.""" @@ -41,28 +43,42 @@ class Params: """Whether to use the rotating wave approximation.""" dynamic_detunting: tuple[float, float] = 0, 0 + """ + A tuple of the total amount and the timescale (``1/speed``) of the + detuning of the laser. + """ def periods(self, n: float): + """ + Returns the number of periods of the system that correspond to + `n` cycles. + """ return n / self.Ω def lifetimes(self, n: float): + """ + Returns the number of lifetimes of the system that correspond to + `n` cycles. + """ return n / self.η @property def rabi_splitting(self): - return np.sqrt(self.d**2 + self.Δ**2) + """The Rabi splitting of the system in *frequency units*.""" + return np.sqrt((self.Ω * self.d) ** 2 + self.Δ**2) @property def ω_eom(self): - return 2 * np.pi * (self.Ω - self.δ - self.Δ) + """The frequency of the EOM drive as *angular frequency*.""" + return 2 * np.pi * (self.Ω * (1 - self.δ) - self.Δ) class RuntimeParams: """Secondary Parameters that are required to run the simulation.""" def __init__(self, params: Params): - Ωs = 2 * np.pi * np.concatenate( - [[-1 * params.δ, params.δ], np.arange(1, params.N + 1) * params.Ω] + Ωs = 2 * np.pi * params.Ω * np.concatenate( + [[-1 * params.δ, params.δ], np.arange(1, params.N + 1)] ) - 1j * np.repeat(params.η / 2, params.N + 2) self.Ωs = Ωs @@ -103,7 +119,8 @@ def eom_drive(t, x, d, ω): def laser_frequency(params: Params, t: np.ndarray): - base = 2 * np.pi * (params.laser_detuning + params.δ) + """The frequency of the laser light as a function of time.""" + base = 2 * np.pi * (params.laser_detuning + params.Ω * params.δ) if params.dynamic_detunting[1] == 0: return base @@ -123,7 +140,9 @@ def make_righthand_side(runtime_params: RuntimeParams, params: Params): x[3:] = 0 if (params.drive_off_time is None) or (t < params.drive_off_time): - differential += eom_drive(t, x, params.d, params.ω_eom) + differential += eom_drive( + t, x, 2 * np.pi * params.Ω * params.d, params.ω_eom + ) if (params.laser_off_time is None) or (t < params.laser_off_time): laser = np.exp(-1j * laser_frequency(params, t) * t)