mirror of
https://github.com/vale981/fibre_walk_project_code
synced 2025-03-04 17:31:39 -05:00
WIP: fix units in sim, seems to work
This commit is contained in:
parent
5d46f00475
commit
a45e71e21f
4 changed files with 101 additions and 35 deletions
1
scripts/experiments/.#002_rabi_detuning_scan.py
Symbolic link
1
scripts/experiments/.#002_rabi_detuning_scan.py
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
hiro@Lobsang.149236:1716554985
|
|
@ -9,12 +9,25 @@ from plot_utils import wrap_plot
|
||||||
def transient_rabi():
|
def transient_rabi():
|
||||||
"""A transient rabi oscillation without noise."""
|
"""A transient rabi oscillation without noise."""
|
||||||
|
|
||||||
params = Params(η=0.0001, δ=1 / 4, d=0.1, laser_detuning=0.1, Δ=0.005, N=2)
|
params = Params(
|
||||||
t = time_axis(params, 3, 0.1)
|
η=0.7,
|
||||||
|
Ω=13.07,
|
||||||
|
δ=13.07 / 4,
|
||||||
|
d=13.07 / 4 * 1,
|
||||||
|
laser_detuning=0.1,
|
||||||
|
Δ=13.07 / 4 * 0.01,
|
||||||
|
N=3,
|
||||||
|
measurement_detuning=1,
|
||||||
|
rwa=False,
|
||||||
|
)
|
||||||
|
params.laser_off_time = params.lifetimes(10)
|
||||||
|
t = time_axis(params, 50, 0.1)
|
||||||
solution = solve(t, params)
|
solution = solve(t, params)
|
||||||
signal = output_signal(t, solution.y, params.laser_detuning)
|
signal = output_signal(t, solution.y, params)
|
||||||
|
|
||||||
f, (_, ax) = plot_simulation_result(make_figure(), t, signal, params)
|
f, (_, ax) = plot_simulation_result(
|
||||||
|
make_figure(), t, signal, params, window=(params.lifetimes(10), t[-1])
|
||||||
|
)
|
||||||
plot_sidebands(ax, params)
|
plot_sidebands(ax, params)
|
||||||
# ax.set_xlim(0.73, 0.77)
|
# ax.set_xlim(0.73, 0.77)
|
||||||
f.suptitle("Transient Rabi oscillation")
|
f.suptitle("Transient Rabi oscillation")
|
||||||
|
@ -27,7 +40,7 @@ def steady_rabi():
|
||||||
t = time_axis(params, lifetimes=10, resolution=1)
|
t = time_axis(params, lifetimes=10, resolution=1)
|
||||||
|
|
||||||
solution = solve(t, params)
|
solution = solve(t, params)
|
||||||
signal = output_signal(t, solution.y, params.laser_detuning)
|
signal = output_signal(t, solution.y, params)
|
||||||
|
|
||||||
f, (_, ax) = plot_simulation_result(
|
f, (_, ax) = plot_simulation_result(
|
||||||
make_figure(), t, signal, params, window=(params.lifetimes(8), t[-1])
|
make_figure(), t, signal, params, window=(params.lifetimes(8), t[-1])
|
||||||
|
@ -43,7 +56,7 @@ def noisy_transient_rabi():
|
||||||
params = Params(η=0.001, d=0.1, laser_detuning=0, Δ=0.05)
|
params = Params(η=0.001, d=0.1, laser_detuning=0, Δ=0.05)
|
||||||
t = time_axis(params, 2, 1)
|
t = time_axis(params, 2, 1)
|
||||||
solution = solve(t, params)
|
solution = solve(t, params)
|
||||||
signal = output_signal(t, solution.y, params.laser_detuning)
|
signal = output_signal(t, solution.y, params)
|
||||||
|
|
||||||
noise_strength = 0.1
|
noise_strength = 0.1
|
||||||
signal = add_noise(signal, noise_strength)
|
signal = add_noise(signal, noise_strength)
|
||||||
|
@ -54,7 +67,6 @@ def noisy_transient_rabi():
|
||||||
f.suptitle(f"Transient Rabi oscillation with noise strength {noise_strength}.")
|
f.suptitle(f"Transient Rabi oscillation with noise strength {noise_strength}.")
|
||||||
|
|
||||||
|
|
||||||
@autoclose
|
|
||||||
def ringdown_after_rabi():
|
def ringdown_after_rabi():
|
||||||
"""Demonstrates the nonstationary ringdown of the resonator after turning off the EOM and laser drive."""
|
"""Demonstrates the nonstationary ringdown of the resonator after turning off the EOM and laser drive."""
|
||||||
off_lifetime = 4
|
off_lifetime = 4
|
||||||
|
@ -66,7 +78,7 @@ def ringdown_after_rabi():
|
||||||
|
|
||||||
t = time_axis(params, lifetimes=5, resolution=1)
|
t = time_axis(params, lifetimes=5, resolution=1)
|
||||||
solution = solve(t, params)
|
solution = solve(t, params)
|
||||||
signal = output_signal(t, solution.y, params.laser_detuning)
|
signal = output_signal(t, solution.y, params)
|
||||||
|
|
||||||
# noise_strength = 0.1
|
# noise_strength = 0.1
|
||||||
# signal = add_noise(signal, noise_strength)
|
# signal = add_noise(signal, noise_strength)
|
||||||
|
@ -79,3 +91,18 @@ def ringdown_after_rabi():
|
||||||
fftax.axvline(params.laser_detuning, color="black")
|
fftax.axvline(params.laser_detuning, color="black")
|
||||||
|
|
||||||
f.suptitle(f"Ringdown after rabi osci EOM after {off_lifetime} lifetimes.")
|
f.suptitle(f"Ringdown after rabi osci EOM after {off_lifetime} lifetimes.")
|
||||||
|
|
||||||
|
|
||||||
|
def sweep():
|
||||||
|
"""A transient rabi oscillation without noise."""
|
||||||
|
|
||||||
|
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]
|
||||||
|
solution = solve(t, params)
|
||||||
|
signal = output_signal(t, solution.y, params)
|
||||||
|
|
||||||
|
f, (_, ax) = plot_simulation_result(make_figure(), t, signal, params)
|
||||||
|
plot_sidebands(ax, params)
|
||||||
|
# ax.set_xlim(0.73, 0.77)
|
||||||
|
f.suptitle("Transient Rabi oscillation")
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from plot_utils import *
|
from plot_utils import *
|
||||||
from .system import Params, output_signal
|
from .system import Params
|
||||||
from .analysis import fourier_transform
|
from .analysis import fourier_transform
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
@ -34,18 +34,24 @@ def plot_simulation_result(
|
||||||
freq, fft = fourier_transform(t, signal, window)
|
freq, fft = fourier_transform(t, signal, window)
|
||||||
fft = fft / np.max(np.abs(fft))
|
fft = fft / np.max(np.abs(fft))
|
||||||
|
|
||||||
freq *= 2 * np.pi
|
|
||||||
ax2.set_xlim(0, params.Ω * (params.N))
|
ax2.set_xlim(0, params.Ω * (params.N))
|
||||||
ax3 = ax2.twinx()
|
ax3 = ax2.twinx()
|
||||||
|
|
||||||
ax2.plot(freq, np.abs(fft) ** 2)
|
ax2.plot(freq, np.abs(fft))
|
||||||
ax2.set_yscale("log")
|
# ax2.set_yscale("log")
|
||||||
ax2.set_title("FFT")
|
ax2.set_title("FFT")
|
||||||
ax2.set_xlabel("ω [angular]")
|
ax2.set_xlabel("ω [linear]")
|
||||||
ax2.set_ylabel("Power")
|
ax2.set_ylabel("Power")
|
||||||
ax2.legend()
|
ax2.legend()
|
||||||
|
|
||||||
ax3.plot(freq, np.angle(fft), linestyle="--", color="C2", alpha=0.5, zorder=-10)
|
ax3.plot(
|
||||||
|
freq,
|
||||||
|
np.unwrap(np.angle(fft) + np.pi, 2 * np.pi),
|
||||||
|
linestyle="--",
|
||||||
|
color="C2",
|
||||||
|
alpha=0.5,
|
||||||
|
zorder=-10,
|
||||||
|
)
|
||||||
ax3.set_ylabel("Phase")
|
ax3.set_ylabel("Phase")
|
||||||
|
|
||||||
return (ax1, ax2)
|
return (ax1, ax2)
|
||||||
|
@ -57,20 +63,26 @@ def plot_sidebands(ax, params: Params):
|
||||||
:param ax: axis to plot on
|
:param ax: axis to plot on
|
||||||
:param params: system parameters
|
:param params: system parameters
|
||||||
"""
|
"""
|
||||||
energy = params.rabi_splitting
|
energy = params.rabi_splitting / (2 * np.pi)
|
||||||
|
|
||||||
first_sidebands = np.abs(
|
first_sidebands = np.abs(
|
||||||
-params.laser_detuning + np.array([1, -1]) * energy / 2 + params.Δ / 2
|
-(params.laser_detuning + params.measurement_detuning)
|
||||||
|
+ np.array([1, -1]) * energy / 2
|
||||||
|
+ params.Δ / 2
|
||||||
)
|
)
|
||||||
second_sidebands = (
|
second_sidebands = (
|
||||||
params.Ω
|
params.Ω
|
||||||
- params.δ
|
- params.δ
|
||||||
- params.laser_detuning
|
- (params.laser_detuning + params.measurement_detuning)
|
||||||
+ np.array([1, -1]) * energy / 2
|
+ np.array([1, -1]) * energy / 2
|
||||||
- params.Δ / 2
|
- params.Δ / 2
|
||||||
)
|
)
|
||||||
|
|
||||||
ax.axvline(params.ω_eom, color="black", label="steady state")
|
ax.axvline(
|
||||||
|
params.ω_eom / (2 * np.pi) - params.measurement_detuning,
|
||||||
|
color="black",
|
||||||
|
label="steady state",
|
||||||
|
)
|
||||||
|
|
||||||
for n, sideband in enumerate(first_sidebands):
|
for n, sideband in enumerate(first_sidebands):
|
||||||
ax.axvline(
|
ax.axvline(
|
||||||
|
|
|
@ -29,6 +29,8 @@ class Params:
|
||||||
laser_detuning: float = 0.0
|
laser_detuning: float = 0.0
|
||||||
"""Detuning of the laser relative to the _A_ mode."""
|
"""Detuning of the laser relative to the _A_ mode."""
|
||||||
|
|
||||||
|
measurement_detuning: float = 0.0
|
||||||
|
|
||||||
laser_off_time: float | None = None
|
laser_off_time: float | None = None
|
||||||
"""Time at which the laser is turned off."""
|
"""Time at which the laser is turned off."""
|
||||||
|
|
||||||
|
@ -38,8 +40,10 @@ class Params:
|
||||||
rwa: bool = False
|
rwa: bool = False
|
||||||
"""Whether to use the rotating wave approximation."""
|
"""Whether to use the rotating wave approximation."""
|
||||||
|
|
||||||
|
dynamic_detunting: tuple[float, float] = 0, 0
|
||||||
|
|
||||||
def periods(self, n: float):
|
def periods(self, n: float):
|
||||||
return n * 2 * np.pi / self.Ω
|
return n / self.Ω
|
||||||
|
|
||||||
def lifetimes(self, n: float):
|
def lifetimes(self, n: float):
|
||||||
return n / self.η
|
return n / self.η
|
||||||
|
@ -50,15 +54,16 @@ class Params:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ω_eom(self):
|
def ω_eom(self):
|
||||||
return self.Ω - self.δ - self.Δ
|
return 2 * np.pi * (self.Ω - self.δ - self.Δ)
|
||||||
|
|
||||||
|
|
||||||
class RuntimeParams:
|
class RuntimeParams:
|
||||||
"""Secondary Parameters that are required to run the simulation."""
|
"""Secondary Parameters that are required to run the simulation."""
|
||||||
|
|
||||||
def __init__(self, params: Params):
|
def __init__(self, params: Params):
|
||||||
Ωs = np.arange(0, params.N) * params.Ω - 1j * np.repeat(params.η, params.N)
|
Ωs = 2 * np.pi * np.concatenate(
|
||||||
Ωs[1:] -= params.δ
|
[[-1 * params.δ, params.δ], np.arange(1, params.N + 1) * params.Ω]
|
||||||
|
) - 1j * np.repeat(params.η / 2, params.N + 2)
|
||||||
|
|
||||||
self.Ωs = Ωs
|
self.Ωs = Ωs
|
||||||
|
|
||||||
|
@ -80,14 +85,13 @@ def time_axis(params: Params, lifetimes: float, resolution: float = 1):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def eom_drive(t, x, d, ω, rwa):
|
def eom_drive(t, x, d, ω):
|
||||||
"""The electrooptical modulation drive.
|
"""The electrooptical modulation drive.
|
||||||
|
|
||||||
:param t: time
|
:param t: time
|
||||||
:param x: amplitudes
|
:param x: amplitudes
|
||||||
:param d: drive amplitude
|
:param d: drive amplitude
|
||||||
:param ω: drive frequency
|
:param ω: drive frequency
|
||||||
:param rwa: whether to use the rotating wave approximation
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
stacked = np.repeat([x], len(x), 0)
|
stacked = np.repeat([x], len(x), 0)
|
||||||
|
@ -95,25 +99,40 @@ def eom_drive(t, x, d, ω, rwa):
|
||||||
stacked = np.sum(stacked, axis=1)
|
stacked = np.sum(stacked, axis=1)
|
||||||
driven_x = d * np.sin(ω * t) * stacked
|
driven_x = d * np.sin(ω * t) * stacked
|
||||||
|
|
||||||
if rwa and len(x) > 2:
|
|
||||||
driven_x[2:] = 0
|
|
||||||
|
|
||||||
return driven_x
|
return driven_x
|
||||||
|
|
||||||
|
|
||||||
|
def laser_frequency(params: Params, t: np.ndarray):
|
||||||
|
base = 2 * np.pi * (params.laser_detuning + params.δ)
|
||||||
|
if params.dynamic_detunting[1] == 0:
|
||||||
|
return base
|
||||||
|
|
||||||
|
return base + 2 * np.pi * (
|
||||||
|
params.dynamic_detunting[0] * t / params.dynamic_detunting[1]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def make_righthand_side(runtime_params: RuntimeParams, params: Params):
|
def make_righthand_side(runtime_params: RuntimeParams, params: Params):
|
||||||
"""The right hand side of the equation of motion."""
|
"""The right hand side of the equation of motion."""
|
||||||
|
|
||||||
def rhs(t, x):
|
def rhs(t, x):
|
||||||
differential = runtime_params.Ωs * x
|
differential = runtime_params.Ωs * x
|
||||||
|
|
||||||
|
if params.rwa:
|
||||||
|
x[0] = 0
|
||||||
|
x[3:] = 0
|
||||||
|
|
||||||
if (params.drive_off_time is None) or (t < params.drive_off_time):
|
if (params.drive_off_time is None) or (t < params.drive_off_time):
|
||||||
differential += eom_drive(t, x, params.d, params.ω_eom, params.rwa)
|
differential += eom_drive(t, x, params.d, params.ω_eom)
|
||||||
|
|
||||||
if (params.laser_off_time is None) or (t < params.laser_off_time):
|
if (params.laser_off_time is None) or (t < params.laser_off_time):
|
||||||
laser = np.exp(-1j * params.laser_detuning * t)
|
laser = np.exp(-1j * laser_frequency(params, t) * t)
|
||||||
differential[0] += laser / np.sqrt(2)
|
differential[0:2] += laser / np.sqrt(2)
|
||||||
differential[1:] += laser
|
differential[2:] += laser
|
||||||
|
|
||||||
|
if params.rwa:
|
||||||
|
differential[0] = 0
|
||||||
|
differential[3:] = 0
|
||||||
|
|
||||||
return -1j * differential
|
return -1j * differential
|
||||||
|
|
||||||
|
@ -130,14 +149,14 @@ def solve(t: np.ndarray, params: Params):
|
||||||
runtime = RuntimeParams(params)
|
runtime = RuntimeParams(params)
|
||||||
rhs = make_righthand_side(runtime, params)
|
rhs = make_righthand_side(runtime, params)
|
||||||
|
|
||||||
initial = np.zeros(params.N, np.complex128)
|
initial = np.zeros(params.N + 2, np.complex128)
|
||||||
|
|
||||||
return scipy.integrate.solve_ivp(
|
return scipy.integrate.solve_ivp(
|
||||||
rhs,
|
rhs,
|
||||||
(np.min(t), np.max(t)),
|
(np.min(t), np.max(t)),
|
||||||
initial,
|
initial,
|
||||||
vectorized=False,
|
vectorized=False,
|
||||||
# max_step=0.1 * np.pi / (params.Ω * params.N),
|
# max_step=0.01 * np.pi / (params.Ω * params.N),
|
||||||
t_eval=t,
|
t_eval=t,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -151,9 +170,16 @@ def in_rotating_frame(
|
||||||
return amplitudes * np.exp(1j * Ωs[:, None].real * t[None, :])
|
return amplitudes * np.exp(1j * Ωs[:, None].real * t[None, :])
|
||||||
|
|
||||||
|
|
||||||
def output_signal(t: np.ndarray, amplitudes: np.ndarray, laser_detuning: float):
|
def output_signal(t: np.ndarray, amplitudes: np.ndarray, params: Params):
|
||||||
"""
|
"""
|
||||||
Calculate the output signal when mixing with laser light of
|
Calculate the output signal when mixing with laser light of
|
||||||
frequency `laser_detuning`.
|
frequency `laser_detuning`.
|
||||||
"""
|
"""
|
||||||
return (np.sum(amplitudes, axis=0) * np.exp(1j * laser_detuning * t)).imag
|
return (
|
||||||
|
np.sum(amplitudes, axis=0)
|
||||||
|
* np.exp(
|
||||||
|
1j
|
||||||
|
* (laser_frequency(params, t) + 2 * np.pi * params.measurement_detuning)
|
||||||
|
* t
|
||||||
|
)
|
||||||
|
).imag
|
||||||
|
|
Loading…
Add table
Reference in a new issue