Author: J. R. Johansson (robert@riken.jp), http://dml.riken.jp/~rob/
The latest version of this IPython notebook lecture is available at http://github.com/jrjohansson/qutip-lectures.
The other notebooks in this lecture series are indexed at http://jrjohansson.github.com.
# setup the matplotlib graphics library and configure it to show
# figures inline in the notebook
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
# make qutip available in the rest of the notebook
from qutip import *
from IPython.display import Image
Consider a single atom coupled to a single cavity mode, as illustrated in the figure below. If there atom excitation rate $\Gamma$ exceeds the relaxation rate, a population inversion can occur in the atom, and if coupled to the cavity the atom can then act as a photon pump on the cavity.
Image(filename='images/schematic-lasing-model.png')
The coherent dynamics in this model is described by the Hamiltonian
$H = \hbar \omega_0 a^\dagger a + \frac{1}{2}\hbar\omega_a\sigma_z + \hbar g\sigma_x(a^\dagger + a)$
where $\omega_0$ is the cavity energy splitting, $\omega_a$ is the atom energy splitting and $g$ is the atom-cavity interaction strength.
In addition to the coherent dynamics the following incoherent processes are also present:
The Lindblad master equation for the model is:
$\frac{d}{dt}\rho = -i[H, \rho] + \Gamma\left(\sigma_+\rho\sigma_- - \frac{1}{2}\sigma_-\sigma_+\rho - \frac{1}{2}\rho\sigma_-\sigma_+\right)
in units where $\hbar = 1$.
References:
w0 = 1.0 * 2 * pi # cavity frequency
wa = 1.0 * 2 * pi # atom frequency
g = 0.05 * 2 * pi # coupling strength
kappa = 0.04 # cavity dissipation rate
gamma = 0.00 # atom dissipation rate
Gamma = 0.35 # atom pump rate
N = 50 # number of cavity fock states
n_th_a = 0.0 # avg number of thermal bath excitation
tlist = np.linspace(0, 150, 101)
# intial state
psi0 = tensor(basis(N,0), basis(2,0)) # start without excitations
# operators
a = tensor(destroy(N), qeye(2))
sm = tensor(qeye(N), destroy(2))
sx = tensor(qeye(N), sigmax())
# Hamiltonian
H = w0 * a.dag() * a + wa * sm.dag() * sm + g * (a.dag() + a) * sx
H
# collapse operators
c_ops = []
rate = kappa * (1 + n_th_a)
if rate > 0.0:
c_ops.append(sqrt(rate) * a)
rate = kappa * n_th_a
if rate > 0.0:
c_ops.append(sqrt(rate) * a.dag())
rate = gamma
if rate > 0.0:
c_ops.append(sqrt(rate) * sm)
rate = Gamma
if rate > 0.0:
c_ops.append(sqrt(rate) * sm.dag())
Here we evolve the system with the Lindblad master equation solver, and we request that the expectation values of the operators $a^\dagger a$ and $\sigma_+\sigma_-$ are returned by the solver by passing the list [a.dag()*a, sm.dag()*sm]
as the fifth argument to the solver.
opt = Odeoptions(nsteps=2000) # allow extra time-steps
output = mesolve(H, psi0, tlist, c_ops, [a.dag() * a, sm.dag() * sm], options=opt)
Here we plot the excitation probabilities of the cavity and the atom (these expectation values were calculated by the mesolve
above).
n_c = output.expect[0]
n_a = output.expect[1]
fig, axes = plt.subplots(1, 1, figsize=(8,6))
axes.plot(tlist, n_c, label="Cavity")
axes.plot(tlist, n_a, label="Atom excited state")
axes.set_xlim(0, 150)
axes.legend(loc=0)
axes.set_xlabel('Time')
axes.set_ylabel('Occupation probability');
rho_ss = steadystate(H, c_ops)
fig, axes = plt.subplots(1, 2, figsize=(12,6))
xvec = np.linspace(-5,5,200)
rho_cavity = ptrace(rho_ss, 0)
W = wigner(rho_cavity, xvec, xvec)
wlim = abs(W).max()
axes[1].contourf(xvec, xvec, W, 100, norm=mpl.colors.Normalize(-wlim,wlim), cmap=plt.get_cmap('RdBu'))
axes[1].set_xlabel(r'Im $\alpha$', fontsize=18)
axes[1].set_ylabel(r'Re $\alpha$', fontsize=18)
axes[0].bar(arange(0, N), real(rho_cavity.diag()), color="blue", alpha=0.6)
axes[0].set_ylim(0, 1)
axes[0].set_xlim(0, N)
axes[0].set_xlabel('Fock number', fontsize=18)
axes[0].set_ylabel('Occupation probability', fontsize=18);
tlist = np.linspace(0, 25, 5)
output = mesolve(H, psi0, tlist, c_ops, [], options=Odeoptions(nsteps=5000))
rho_ss_sublist = output.states
xvec = np.linspace(-5,5,200)
fig, axes = plt.subplots(2, len(rho_ss_sublist), figsize=(3*len(rho_ss_sublist), 6))
for idx, rho_ss in enumerate(rho_ss_sublist):
# trace out the cavity density matrix
rho_ss_cavity = ptrace(rho_ss, 0)
# calculate its wigner function
W = wigner(rho_ss_cavity, xvec, xvec)
# plot its wigner function
wlim = abs(W).max()
axes[0,idx].contourf(xvec, xvec, W, 100, norm=mpl.colors.Normalize(-wlim,wlim), cmap=plt.get_cmap('RdBu'))
axes[0,idx].set_title(r'$t = %.1f$' % tlist[idx])
# plot its fock-state distribution
axes[1,idx].bar(arange(0, N), real(rho_ss_cavity.diag()), color="blue", alpha=0.8)
axes[1,idx].set_ylim(0, 1)
axes[1,idx].set_xlim(0, 15)
References:
def calulcate_avg_photons(N, Gamma):
# collapse operators
c_ops = []
rate = kappa * (1 + n_th_a)
if rate > 0.0:
c_ops.append(sqrt(rate) * a)
rate = kappa * n_th_a
if rate > 0.0:
c_ops.append(sqrt(rate) * a.dag())
rate = gamma
if rate > 0.0:
c_ops.append(sqrt(rate) * sm)
rate = Gamma
if rate > 0.0:
c_ops.append(sqrt(rate) * sm.dag())
# Ground state and steady state for the Hamiltonian: H = H0 + g * H1
rho_ss = steadystate(H, c_ops)
# cavity photon number
n_cavity = expect(a.dag() * a, rho_ss)
# cavity second order coherence function
g2_cavity = expect(a.dag() * a.dag() * a * a, rho_ss) / (n_cavity ** 2)
return n_cavity, g2_cavity
Gamma_max = 2 * (4*g**2) / kappa
Gamma_vec = np.linspace(0.1, Gamma_max, 50)
n_avg_vec = []
g2_vec = []
for Gamma in Gamma_vec:
n_avg, g2 = calulcate_avg_photons(N, Gamma)
n_avg_vec.append(n_avg)
g2_vec.append(g2)
fig, axes = plt.subplots(1, 1, figsize=(12,6))
axes.plot(Gamma_vec * kappa / (4*g**2), n_avg_vec, color="blue", alpha=0.6, label="numerical")
axes.set_xlabel(r'$\Gamma\kappa/(4g^2)$', fontsize=18)
axes.set_ylabel(r'Occupation probability $\langle n \rangle$', fontsize=18)
axes.set_xlim(0, 2);
fig, axes = plt.subplots(1, 1, figsize=(12,6))
axes.plot(Gamma_vec * kappa / (4*g**2), g2_vec, color="blue", alpha=0.6, label="numerical")
axes.set_xlabel(r'$\Gamma\kappa/(4g^2)$', fontsize=18)
axes.set_ylabel(r'$g^{(2)}(0)$', fontsize=18)
axes.set_xlim(0, 2)
axes.text(0.1, 1.1, "Lasing regime", fontsize=16)
axes.text(1.5, 1.8, "Thermal regime", fontsize=16);
Here we see that lasing is suppressed for $\Gamma\kappa/(4g^2) > 1$.
Let's look at the fock-state distribution at $\Gamma\kappa/(4g^2) = 0.5$ (lasing regime) and $\Gamma\kappa/(4g^2) = 1.5$ (suppressed regime):
Gamma = 0.5 * (4*g**2) / kappa
c_ops = [sqrt(kappa * (1 + n_th_a)) * a, sqrt(kappa * n_th_a) * a.dag(), sqrt(gamma) * sm, sqrt(Gamma) * sm.dag()]
rho_ss = steadystate(H, c_ops)
fig, axes = plt.subplots(1, 2, figsize=(16,6))
xvec = np.linspace(-10,10,200)
rho_cavity = ptrace(rho_ss, 0)
W = wigner(rho_cavity, xvec, xvec)
wlim = abs(W).max()
axes[1].contourf(xvec, xvec, W, 100, norm=mpl.colors.Normalize(-wlim,wlim), cmap=plt.get_cmap('RdBu'))
axes[1].set_xlabel(r'Im $\alpha$', fontsize=18)
axes[1].set_ylabel(r'Re $\alpha$', fontsize=18)
axes[0].bar(arange(0, N), real(rho_cavity.diag()), color="blue", alpha=0.6)
axes[0].set_xlabel(r'$n$', fontsize=18)
axes[0].set_ylabel(r'Occupation probability', fontsize=18)
axes[0].set_ylim(0, 1)
axes[0].set_xlim(0, N);
Gamma = 1.5 * (4*g**2) / kappa
c_ops = [sqrt(kappa * (1 + n_th_a)) * a, sqrt(kappa * n_th_a) * a.dag(), sqrt(gamma) * sm, sqrt(Gamma) * sm.dag()]
rho_ss = steadystate(H, c_ops)
fig, axes = plt.subplots(1, 2, figsize=(16,6))
xvec = np.linspace(-10,10,200)
rho_cavity = ptrace(rho_ss, 0)
W = wigner(rho_cavity, xvec, xvec)
wlim = abs(W).max()
axes[1].contourf(xvec, xvec, W, 100, norm=mpl.colors.Normalize(-wlim,wlim), cmap=plt.get_cmap('RdBu'))
axes[1].set_xlabel(r'Im $\alpha$', fontsize=18)
axes[1].set_ylabel(r'Re $\alpha$', fontsize=18)
axes[0].bar(arange(0, N), real(rho_cavity.diag()), color="blue", alpha=0.6)
axes[0].set_xlabel(r'$n$', fontsize=18)
axes[0].set_ylabel(r'Occupation probability', fontsize=18)
axes[0].set_ylim(0, 1)
axes[0].set_xlim(0, N);
Too large pumping rate $\Gamma$ kills the lasing process: reversed threshold.
from qutip.ipynbtools import version_table
version_table()
Software | Version |
---|---|
IPython | 2.0.0 |
OS | posix [linux] |
Python | 3.4.1 (default, Jun 9 2014, 17:34:49) [GCC 4.8.3] |
QuTiP | 3.0.0.dev-5a88aa8 |
Numpy | 1.8.1 |
matplotlib | 1.3.1 |
Cython | 0.20.1post0 |
SciPy | 0.13.3 |
Thu Jun 26 14:28:35 2014 JST |