Additional Examples¶
In the following section more examples for using pytalises will be explored
[34]:
import pytalises as pt
import numpy as np
from matplotlib import pyplot as plt
Time-dependent Rabi model¶
[35]:
psi = pt.Wavefunction(["exp(-x**2)","0"], number_of_grid_points=(256,),
spatial_ext=(-5,5), normalize_const=1.0)
V = ["0", "Omega_Rabi/2*exp(-1j*omega*t)", "omega"]
f_Rabi = 1
Omega_Rabi = 2*np.pi*f_Rabi
pulse_length = 1/f_Rabi # One complete inversion
num_time_steps = 100
pop = np.zeros((num_time_steps, 2)) # vector that saves the state population
time = np.zeros(num_time_steps)
We simulate the time-propagation for one time unit. Since the Rabi frequency is \(2\pi\) we will achieve exactly one inversion.
[36]:
for i in range(num_time_steps):
psi.propagate(V, num_time_steps=1,
delta_t=pulse_length/num_time_steps,
variables={'Omega_Rabi': Omega_Rabi, 'omega': 10})
pop[i,:] = psi.state_occupation()
time[i] = psi.t
lines = plt.plot(time, pop)
plt.legend(lines, ('|g>', '|e>'))
plt.xlabel("time")
plt.title("A Rabi cycle")
[36]:
Text(0.5, 1.0, 'A Rabi cycle')
Excitation with momentum transfer¶
One can also achieve excitation with momentum transfer \(|p\rangle \leftrightarrow |p+k\rangle\) with periodic potentials with spatial periodicity \(k\). Ultimately this is what happens with monochromatic laser light that is \(\propto \exp i(kx-\omega t)\). Let us look a that in a concrete example:
Note: In many examples we set \(\hbar=m\). Thus, the Schrödinger equation svoled is \(\partial_t \psi = \frac{1}{2}\nabla^2 \psi + \frac{V}{\hbar} \psi\). Furthermore, this implies that in these simulations velocity and wave vector are the same \(v = \frac{p}{m} = \frac{\hbar k}{m} = k\). The numeric value for the mass of the simulated particle can be changed with the keyword argumentm
in thepytalises.Wavefunction
class.
[37]:
psi = pt.Wavefunction(["exp(-(x+5)**2)","0"], number_of_grid_points=(256,),
spatial_ext=(-10,10), normalize_const=1.0)
lines = plt.plot(psi.r, np.abs(psi.amp)**2)
plt.legend(lines, ('|g>', '|e>'))
plt.xlabel("position")
plt.title("Prob. amplitude of wave function")
[37]:
Text(0.5, 1.0, 'Prob. amplitude of wave function')
Again, we have a two level system. We will excite the ground state to the excited state but this time the excited state will gain momentum. The potential for a resonant excitation is
[38]:
V = ["0", "Omega_Rabi/2*exp(-1j*((omega+k**2/2)*t-k*x))", "omega"]
f_Rabi = 10
Omega_Rabi = 2*np.pi*f_Rabi
pulse_length = 1/f_Rabi/4 # length for 50:50 beamsplitter pulse
num_time_steps = 100
pop = np.zeros((num_time_steps, 2))
time = np.zeros(num_time_steps)
for i in range(num_time_steps):
psi.propagate(V, num_time_steps=1,
delta_t=pulse_length/num_time_steps,
variables={'Omega_Rabi': Omega_Rabi, 'omega': 10, 'k':10})
pop[i,:] = psi.state_occupation()
time[i] = psi.t
lines = plt.plot(time, pop)
plt.legend(lines, ('|g>', '|e>'))
plt.xlabel("time")
plt.title("Half Rabi cycle")
[38]:
Text(0.5, 1.0, 'Half Rabi cycle')
Indeed, we achieve an equal superposition. Lets have a look at our wave function in momentum space:
[39]:
psi.fft()
lines = plt.plot(psi.k, np.abs(psi.amp)**2)
plt.legend(lines, ('|g>', '|e>'))
plt.xlabel("k")
plt.title("Prob. amplitude of wave function")
[39]:
Text(0.5, 1.0, 'Prob. amplitude of wave function')
in momentum space we also have an equal superposition of the states \(|p\rangle\) and \(|p+k\rangle=|p+10\rangle\). Of course this can also be seen by looking at the simple free propagation in position space:
[40]:
psi.ifft() # transform back into r-space
for i in range(6):
line1, = plt.plot(psi.r, np.abs(psi.amp[:,0])**2, 'C0-', alpha=.1+i*.15)
line2, = plt.plot(psi.r, np.abs(psi.amp[:,1])**2, 'C1', alpha=.1+i*.15)
plt.grid(True)
psi.freely_propagate(num_time_steps=1, delta_t=0.2)
plt.legend([line1, line2], ('|g>', '|e>'))
plt.xlabel("position")
plt.title("Prob. amplitude of wave function")
[40]:
Text(0.5, 1.0, 'Prob. amplitude of wave function')
Three-level Raman transitions¶
In this section we derive the standard three-level Hamiltonian for Raman transitions and simulate the transition. First we do this with no spatial dependency on the electromagnetic field (and therefore no momentum transfer) and then extend this model to the physically relevant situation of imparting a large momentum via two-photon transition on the wave-packet.
Raman transitions with no momentum transfer
The general aim of a Raman transition is to transfer probability amplitudes between two states via a third intermediate state. In this example the three states are \(|\omega_g\rangle\), \(|\omega_e\rangle\) and \(|\omega_i\rangle\). The ground and excited state will be coupled to the intermediate state with monochromatic light of frequencies \(\omega_1\) and \(\omega_2\), but no direct coupling between the excited and ground state is present.
\(\Delta\) is the so called one-photon detuning. The Hamiltonian can be written as follow:
[41]:
from sympy import *
x, t = symbols('x t', real=True)
Omega_1, Omega_2 = symbols('\Omega_1 \Omega_2', real=True)
k_1, k_2 = symbols('k_1 k_2', real=True)
omega_1, omega_2 = symbols('\omega_1 \omega_2', real=True)
omega_g, omega_e, omega_i = symbols('\omega_g \omega_e \omega_i', real=True)
hbar = symbols('\hbar', constant=True)
H02 = Omega_1/2*exp(I*(k_1*x-omega_1*t))
H12 = Omega_1/2*exp(I*(k_1*x-omega_2*t))
H = Matrix([
[omega_g, 0, conjugate(H02)],
[0, omega_e, conjugate(H12)],
[H02, H12, omega_i]])
H
[41]:
[42]:
R = Matrix([
[exp(I*(omega_i-omega_1)*t), 0, 0],
[0, exp(I*(omega_i-omega_2)*t), 0],
[0, 0, exp(I*omega_i*t)]
])
R
[42]:
\(R\) can be somewhat arbitrarily chosen. This choice will yield a Hamiltonian only dependent on \(\Delta\). Let us perform the transformation:
[43]:
H_I = R*H*conjugate(R) - I*R*conjugate(diff(R,t))
simplify(H_I)
[43]:
[44]:
m = 1.4447e-25 # Mass of a Rubidium atom
psi = pt.Wavefunction(["exp(-((x-x0)/(2*sigma_x))**2)","0","0"],
number_of_grid_points=(128,), spatial_ext=(-10e-6,10e-6),
normalize_const=1.0, m=m,
variables={'x0': 0, 'sigma_x': 1e-6})
# List of strings describing the lower triangular part of V
V = ["-Delta", "0", "Omega/2", "-Delta", "Omega/2", "0"]
# omega_i-omega_g: energy difference between F'=3 and F=2 Rubidium-87 D2-lines
omega_ig = 2*np.pi*384.230484468e12
# omega_e-omega_g: energy difference betwwen F=2 and F=1 of the 5^2 S_{1/2} manifold
omega_eg = 2*np.pi*6.8e9
# One-photon detuning of 700 MHz
Delta = 2*np.pi*700e6
The general Rabi frequency for such two-photon transitions is different from the Rabi frequency of the single-photon transitions. It is \(\Omega = \frac{\Omega_1 \Omega_2}{2\Delta}\). We calculate the single-photon Rabi frequencies \(\Omega_i\) from the fact that we aim to achieve Rabi cycles of the two-photon transition of length \(100\; \mathrm{ms}\).
[45]:
f_Rabi = 1/100e-6
Omega = np.sqrt(2*2*np.pi*f_Rabi * Delta)
pulse_length = 1/f_Rabi/4 # length for beamsplitter
num_time_steps = 100
pop = np.zeros((num_time_steps, 3))
time = np.zeros(num_time_steps)
for i in range(num_time_steps):
psi.propagate(V, num_time_steps=1,
delta_t=pulse_length/num_time_steps,
variables={'Omega': Omega, 'Delta': Delta})
pop[i,:] = psi.state_occupation()
time[i] = psi.t
lines = plt.plot(time, pop)
plt.legend(lines, ('|g>', '|e>', '|i>'))
plt.xlabel("time")
plt.title("Half Rabi cycle")
[45]:
Text(0.5, 1.0, 'Half Rabi cycle')
[46]:
fig, axs = plt.subplots(2,1)
axs[0].plot(psi.r, np.abs(psi.amp)**2)
axs[0].set_xlabel("position")
psi.fft() # Fouriier transform
axs[1].plot(psi.k, np.abs(psi.amp)**2)
axs[1].set_xlabel("k")
plt.tight_layout()
Excited (orange) and ground (blue, but covered by orange) state cover exactly the same position and momentum states. That is of course boring. In the next calculation we will impart a large momentum on the wave-packet via the two-photon transition.
Raman transitions with momentum transfer
[47]:
m = 1.4447e-25
hbar = 1.0545718e-34
c = 299792458
psi = pt.Wavefunction(["exp(-((x-x0)/(2*sigma_x))**2)","0","0"],
number_of_grid_points=(512,), spatial_ext=(-20e-6,20e-6),
normalize_const=1.0, m=m,
variables={'x0': 0, 'sigma_x': 3e-6})
V = ["-Delta", "0", "Omega_Rabi/2*exp(1j*k_1*x)", "-(Delta+delta)", "Omega_Rabi/2*exp(1j*k_2*x)", "0"]
omega_ig = 2*np.pi*384.230484468e12
omega_eg = 2*np.pi*6.8e9
Delta = 2*np.pi*700e6
f_Rabi = 1/100e-6
Omega_Rabi = np.sqrt(2*2*np.pi*f_Rabi * Delta)
omega_1 = omega_ig-Delta
k_1 = omega_1/c
# solve resonance condition to acquire k_2
from scipy.optimize import root
k_2 = root(lambda k_2: hbar/2/m*(k_1-k_2)**2 - (omega_1 - c*np.abs(k_2)) + omega_eg, -k_1).x
omega_2 = c*np.abs(k_2)
delta = omega_1-omega_2-omega_eg
pulse_length = 3/f_Rabi/4 # length for 3*pi/2 beamsplitter pulse, just for fun
num_time_steps = 100
pop = np.zeros((num_time_steps, 3))
time = np.zeros(num_time_steps)
for i in range(num_time_steps):
psi.propagate(V, num_time_steps=1,
delta_t=pulse_length/num_time_steps,
variables={'Omega_Rabi': Omega_Rabi, 'c': c,
'omega_1': omega_1, 'k_1': k_1,
'omega_2': omega_2, 'k_2': k_2,
'Delta': Delta, 'delta': delta})
pop[i,:] = psi.state_occupation()
time[i] = psi.t
lines = plt.plot(time, pop)
plt.legend(lines, ('|g>', '|e>', '|i>'))
plt.xlabel("time")
plt.title("One and a half Rabi cycle")
[47]:
Text(0.5, 1.0, 'One and a half Rabi cycle')
Now if we take a look at the wave function ampltidues in \(k\)-space we will see that they are not only in a superposition of energy states, but also momentum states.
[48]:
psi.fft()
lines = plt.plot(psi.k, np.abs(psi.amp)**2)
plt.legend(lines, ('|g>', '|e>', '|i>'))
plt.xlabel("k")
plt.title("Prob. amplitude of wave function")
[48]:
Text(0.5, 1.0, 'Prob. amplitude of wave function')
The momentum is
[49]:
print(k_1-k_2)
[16105579.10347923]
[50]:
psi.ifft() # transform back into r-space
for i in range(6):
line1, = plt.plot(psi.r, np.abs(psi.amp[:,0])**2, 'C0-', alpha=.1+i*.15)
line2, = plt.plot(psi.r, np.abs(psi.amp[:,1])**2, 'C1', alpha=.1+i*.15)
plt.grid(True)
psi.freely_propagate(num_time_steps=1, delta_t=2e-4)
plt.legend((line1, line2), ('|g>', '|e>'))
plt.xlabel("position")
plt.title("Prob. amplitude of wave function")
[50]:
Text(0.5, 1.0, 'Prob. amplitude of wave function')
Single-Bragg diffraction¶
A very similar case to that of the three-level Raman transition is that of Bragg diffraction. Instead of coupling two different states to achieve a momentum transfer, the Bragg transition just requires a ground state that is coupled to an intermediate state with far detuned lasers.
Again, we will derive the Hamiltonian in the rotating frame. The Hamiltonian is a \(2\times 2\) matrix with off diagonal elements constituent of the eletro-magnetic field of the two laser sources.
[51]:
x, t = symbols('x t', real=True)
Omega_1, Omega_2 = symbols('\Omega_1 \Omega_2', real=True)
k_1, k_2 = symbols('k_1 k_2', real=True)
omega_1, omega_2 = symbols('\omega_1 \omega_2', real=True)
omega_g, omega_i = symbols('\omega_g \omega_i', real=True)
hbar = symbols('\hbar', constant=True)
H01 = simplify((Omega_1/2*exp(I*(k_1*x-omega_1*t)) + Omega_2/2*exp(I*(k_2*x-omega_2*t))))
H = Matrix([
[omega_g, conjugate(H01) ],
[H01, omega_i ]])
H
[51]:
Applying the rotating frame yields
[52]:
R = Matrix([[exp(I*(omega_i-omega_1)*t), 0],
[0, exp(I*(omega_i+0*omega_2)*t)]])
H_I = R*H*conjugate(R) - I*R*conjugate(diff(R,t))
simplify(H_I)
[52]:
Substituting the definitions from the sketch for \(\Delta\) and \(\delta\) this gives
[53]:
from scipy.optimize import root
m = 1.4447e-25
hbar = 1.0545718e-34
c = 299792458
psi = pt.Wavefunction(["exp(-((x-x0)/(2*sigma_x))**2)","0"],
number_of_grid_points=(256,), spatial_ext=(-10e-6,10e-6),
normalize_const=1.0, m=m,
variables={'x0': 0, 'sigma_x': 1e-6})
V = ["-Delta", "Omega/2 * (exp(1j*k_1*(x+v*t))+exp(1j*(k_2*(x+v*t)+delta*t)))", "0"]
v = 10
omega_ig = 2*np.pi*384.230484468e12
Delta = 2*np.pi*700e6
f_Rabi = 1/300e-6
Omega = np.sqrt(2*2*np.pi*f_Rabi * Delta)
omega_1 = omega_ig-Delta
k_1 = omega_1/c
k_2 = root(lambda k_2: hbar/2/m*(k_1-k_2)**2 + (k_1-k_2)*v - (omega_1 - c*np.abs(k_2)) , -k_1).x
omega_2 = c*np.abs(k_2)
delta = omega_1-omega_2
pulse_length = 1/f_Rabi/4 # length for 50:50 beamsplitter pulse
num_time_steps = 100
[54]:
plt.plot(psi.r, np.abs(psi.amp[:,0])**2, 'C0-', alpha=.1)
plt.plot(psi.r, np.abs(psi.amp[:,1])**2, 'C1', alpha=.1)
psi.propagate(V, num_time_steps=num_time_steps,
delta_t=pulse_length/num_time_steps,
variables={'Omega': Omega, 'c': c, 'v': v,
'omega_1': omega_1, 'k_1': k_1,
'omega_2': omega_2, 'k_2': k_2,
'Delta': Delta, 'delta': delta})
for i in range(1,6):
line1, = plt.plot(psi.r, np.abs(psi.amp[:,0])**2, 'C0-', alpha=.1+i*.15)
line2, = plt.plot(psi.r, np.abs(psi.amp[:,1])**2, 'C1', alpha=.1+i*.15)
plt.grid(True)
psi.freely_propagate(num_time_steps=1, delta_t=1e-4)
plt.legend([line1, line2], ('|g>', '|e>'))
plt.xlabel("position")
plt.title("Prob. amplitude of wave function")
[54]:
Text(0.5, 1.0, 'Prob. amplitude of wave function')
[55]:
psi.fft()
line = plt.plot(psi.k, np.abs(psi.amp)**2)
plt.legend(line, ('|g>', '|e>'))
plt.xlabel("k")
plt.title("Prob. amplitude of wave function")
[55]:
Text(0.5, 1.0, 'Prob. amplitude of wave function')
one can see that there is also a very small population in the momentum state \(-(k_1-k_2)\). This is due to the finite pulse length of the laser pulse. Shorter pulses populate different momentum states even more. Try it out!
2D Single-Bragg diffraction with Gaussian beam¶
[56]:
psi = pt.Wavefunction(["exp(-((x-x0)/(2*sigma_x))**2)*exp(-((y-y0)/(2*sigma_y))**2)","0"],
number_of_grid_points=(2048,256), spatial_ext=[(-30e-6,90e-6),(-40e-6,40e-6)],
normalize_const=1.0, m=m,
variables={'x0': 0e-6, 'sigma_x': 10e-6, 'y0': 0e-6, 'sigma_y': 10e-6})
fig = plt.figure(figsize=(6.4, 4.8))
ax = fig.add_subplot()
ax.pcolormesh(psi.r[0], psi.r[1], np.abs(psi.amp[:,:,0].T)**2, rasterized=True)
ax.set_aspect("equal")
ax.set_title("Initial wave function density")
[56]:
Text(0.5, 1.0, 'Initial wave function density')
[57]:
m = 1.4447e-25
hbar = 1.0545718e-34
c = 299792458
v = 0
omega_ig = 2*np.pi*384.230484468e12
Delta = 2*np.pi*700e6
f_Rabi = 1/400e-6
Omega = np.sqrt(2*2*np.pi*f_Rabi * Delta)
omega_1 = omega_ig-Delta
k_1 = omega_1/c
k_2 = root(lambda k_2: hbar/2/m*(k_1-k_2)**2 + (k_1-k_2)*v - (omega_1 - c*np.abs(k_2)) , -k_1).x
omega_2 = c*np.abs(k_2)
delta = omega_1-omega_2
pulse_length = 1/f_Rabi/4 # length for 50:50 beamsplitter pulse
num_time_steps = 10
w0_1 = 7.5e-6 # width of first Gaussian beam
zR_1 = w0_1**2 * k_1 / 2 # Rayleigh range
w0_2 = 7.5e-6 # width of second Gaussian beam
zR_2 = w0_2**2 * k_2 / 2
Amp_gauss_1 = "1/sqrt(1+(x/zR_1)**2) * exp(-(y/(w0_1*sqrt(1+(x/zR_1)**2)))**2 + 1j*(k_1*y**2/(2*x*(1+(zR_1/x)**2)) + k_1*x - arctan(x/zR_1)) )"
Amp_gauss_2 = "1/sqrt(1+(x/zR_2)**2) * exp(-(y/(w0_2*sqrt(1+(x/zR_2)**2)))**2 + 1j*(k_2*y**2/(2*x*(1+(zR_2/x)**2)) + k_2*x - arctan(x/zR_2)) )"
V = ["-Delta", "Omega/2 * ("+Amp_gauss_1+"+"+Amp_gauss_2+"*exp(1j*delta*t) )", "0"]
We take a look at the absolute magnitude of the potential’s nondiagonal element:
[58]:
U = pt.Propagator(psi, V, variables={'Omega': Omega, 'c': c, 'v': v,
'omega_1': omega_1, 'k_1': k_1, 'w0_1': w0_1, 'zR_1': zR_1,
'omega_2': omega_2, 'k_2': k_2, 'w0_2': w0_2, 'zR_2': zR_2,
'Delta': Delta, 'delta': delta})
U.eval_V()
fig = plt.figure()
ax = fig.add_subplot()
ax.pcolormesh(psi.r[0], psi.r[1], np.abs(U.V_eval_array[:,:,0,1,0].T)**2, rasterized=True)
ax.set_aspect("equal")
ax.set_title("Intensity of interfering Gaussian beams")
[58]:
Text(0.5, 1.0, 'Intensity of interfering Gaussian beams')
pytalises.Propagator
class for this. This class is used in the backend to propagate a pytalises.Wavefunction
object, but otherwise not used in the examples. You can read more about it in the API.)[59]:
psi.propagate(V, num_time_steps=num_time_steps,
delta_t=pulse_length/num_time_steps,
variables={'Omega': Omega, 'c': c, 'v': v,
'omega_1': omega_1, 'k_1': k_1, 'w0_1': w0_1, 'zR_1': zR_1,
'omega_2': omega_2, 'k_2': k_2, 'w0_2': w0_2, 'zR_2': zR_2,
'Delta': Delta, 'delta': delta})
n_plots = 5
vmax = np.max(np.abs(psi.amp[:,:,0].T)**2)
fig = plt.figure(figsize=(6.4, n_plots*4.8))
for i in range(n_plots-1):
psi.freely_propagate(num_time_steps=1, delta_t=1e-3)
ax = fig.add_subplot(n_plots,1,i+1, adjustable="box")
ax.pcolormesh(psi.r[0], psi.r[1], np.abs(psi.amp[:,:,0].T)**2, rasterized=True, vmax=vmax)
ax.set_aspect("equal")
Since we made the Gaussian beams’ waists smaller than the wave function it is only partially subjected to the Bragg transition and a big part of it stays unaffected. However, the inner part experiences the momentum kick.
Light-pulse atom interferometry with single Bragg diffraction¶
[60]:
psi = pt.Wavefunction("exp(-((x-x0)/(2*sigmax))**2)", number_of_grid_points=(1024,),
spatial_ext=(-75,75), variables={'x0': -25, 'sigmax': 5})
def init_plot():
fig = plt.figure()
axs = fig.subplots(2,1)
line1, = axs[0].plot(psi.r, np.abs(psi.amp)**2)
axs[0].grid()
axs[0].set_ylim(0,1)
axs[0].set_xlabel("position")
psi.fft();
line2, = axs[1].plot(psi.k, np.abs(psi.amp)**2)
axs[1].grid()
axs[1].set_xlabel("momentum")
psi.ifft();
fig.tight_layout()
return fig, axs, line1, line2
fig, axs, line1, line2 = init_plot()
You see the wave function in position and momentum representation. In position space it is ineed offset and in momentum space centered at 0.
We will now perform the first Bragg pulse. The effective potential is
with Rabi frequency \(\Omega\) and wave vector \(k\). This potential drives transitions between the momentum states \(|p\rangle \leftrightarrow |p+2k\rangle\). In this case we set \(k=5\) and \(\Omega=2\pi\). A beamsplitter \(\pi/2\) pulse is achieved after \(t=\frac{\pi/2}{\Omega}\)
[61]:
from matplotlib import animation, rc
from IPython.display import HTML
def animate_bragg_pulse(i):
psi.propagate("2*Omega*cos(k*(x-k*t))**2", num_time_steps=1,
delta_t=t_end/num_time_steps, variables={"Omega": 2*np.pi*f_R, "k": 5}, diag=True)
line1.set_ydata(np.abs(psi.amp)**2)
psi.fft()
line2.set_ydata(np.abs(psi.amp)**2)
psi.ifft()
return (line1, line2)
fig, axs, line1, line2 = init_plot()
f_R = 2 # Rabi frequency in Hertz
t_end = 1/(4*f_R) # 50:50 beamsplitter
num_time_steps = 100
anim = animation.FuncAnimation(fig, animate_bragg_pulse, frames=num_time_steps, interval=20, blit=True)
plt.close()
HTML(anim.to_html5_video())
[61]:
[62]:
def animate_freeprop(i):
psi.freely_propagate(num_time_steps=1, delta_t=t_end/num_time_steps)
line1.set_ydata(np.abs(psi.amp)**2)
psi.fft()
line2.set_ydata(np.abs(psi.amp)**2)
psi.ifft()
return (line1, line2)
fig, axs, line1, line2 = init_plot()
t_end = 5
anim = animation.FuncAnimation(fig, animate_freeprop, frames=num_time_steps, interval=20, blit=True)
plt.close()
HTML(anim.to_html5_video())
[62]:
Now we will apply a mirror \(\pi\) pulse that will invert the momentum states in order to recombine both wave packets.
[63]:
fig, axs, line1, line2 = init_plot()
t_end = 1/(2*f_R) # mirror pulse
anim = animation.FuncAnimation(fig, animate_bragg_pulse, frames=num_time_steps, interval=20, blit=True)
plt.close()
HTML(anim.to_html5_video())
[63]:
Now the right wave packet will be in momentum state \(|p\rangle\) and the left in \(|p+2k\rangle\). They propagate freely for the same time they were seperating after the first pulse.
[64]:
fig, axs, line1, line2 = init_plot()
t_end = 5
anim = animation.FuncAnimation(fig, animate_freeprop, frames=num_time_steps, interval=20, blit=True)
plt.close()
HTML(anim.to_html5_video())
[64]:
Now that they are spatially overlapping we can recombine them with a final beamsplitter pulse.
[65]:
fig, axs, line1, line2 = init_plot()
t_end = 1/(4*f_R) # 50:50 beamspliter pulse
anim = animation.FuncAnimation(fig, animate_bragg_pulse, frames=num_time_steps, interval=20, blit=True)
plt.close()
HTML(anim.to_html5_video())
[65]:
Let’s have a final look at the wave function
[66]:
init_plot();
The wave function is, again, completely in its initial momentum state but has travelled the 50 position units. One can also see some interference due to imperfect beamsplitter operations to auxiliary states.