# Development notebook with tests for the fortran monte carlo solver¶

Copyright (C) 2011 and later, Paul D. Nation & Robert J. Johansson

In [1]:
%pylab inline

In [2]:
from qutip import *
from pylab import *


## ex24¶

In [3]:
def integrate(N, h, Jx, Jy, Jz, psi0, tlist, gamma, solver):

si = qeye(2)
sx = sigmax()
sy = sigmay()
sz = sigmaz()

sx_list = []
sy_list = []
sz_list = []
for n in range(N):
op_list = []
for m in range(N):
op_list.append(si)
op_list[n] = sx
sx_list.append(tensor(op_list))
op_list[n] = sy
sy_list.append(tensor(op_list))
op_list[n] = sz
sz_list.append(tensor(op_list))

# construct the hamiltonian
H = 0

# energy splitting terms
for n in range(N):
H += - 0.5 * h[n] * sz_list[n]

# interaction terms
for n in range(N-1):
H += - 0.5 * Jx[n] * sx_list[n] * sx_list[n+1]
H += - 0.5 * Jy[n] * sy_list[n] * sy_list[n+1]
H += - 0.5 * Jz[n] * sz_list[n] * sz_list[n+1]

# collapse operators
c_op_list = []

# spin dephasing
for n in range(N):
if gamma[n] > 0.0:
c_op_list.append(sqrt(gamma[n]) * sz_list[n])

# evolve and calculate expectation values
if solver == "me":
output = mesolve(H, psi0, tlist, c_op_list, sz_list)
elif solver == "mc":
output = mcsolve(H, psi0, tlist, c_op_list, sz_list)
elif solver == "mcf90":
output = mcsolve_f90(H, psi0, tlist, c_op_list, sz_list)

return output.expect

In [4]:
N = 4           # number of spins

# array of spin energy splittings and coupling strengths. here we use
# uniform parameters, but in general we don't have too
h  = 1.0 * 2 * pi * ones(N)
Jz = 0.1 * 2 * pi * ones(N)
Jx = 0.1 * 2 * pi * ones(N)
Jy = 0.1 * 2 * pi * ones(N)

# dephasing rate
gamma = 0.01 * ones(N)

# intial state, first spin in state |1>, the rest in state |0>
psi_list = []
psi_list.append(basis(2,1))
for n in range(N-1):
psi_list.append(basis(2,0))
psi0 = tensor(psi_list)

tlist = linspace(0, 50, 300)

sz_expt = integrate(N, h, Jx, Jy, Jz, psi0, tlist, gamma, "mcf90")

rc('font', family='Bitstream Vera Sans')
for n in range(N):
plot(tlist, real(sz_expt[n]), label=r'$\langle\sigma_z($'+str(n)+r'$)\rangle$',lw=2)
xlabel(r'Time [ns]',fontsize=14)
ylabel(r'$\langle\sigma_{z}\rangle$',fontsize=14)
title(r'Dynamics of a Heisenberg spin chain')
legend(loc = "lower right")

show()


## ex30¶

In [5]:
# set system parameters
kappa=2.0 # mirror coupling
gamma=0.2 # spontaneous emission rate
g=1       # atom/cavity coupling strength
wc=0      # cavity frequency
w0=0      # atom frequency
wl=0      # driving frequency
E=0.5     # driving amplitude
N=4 # number of cavity energy levels (0->3 Fock states)
tlist=linspace(0,10,101) #times for expectation values

# construct Hamiltonian
ida=qeye(N)
idatom=qeye(2)
a=tensor(destroy(N),idatom)
sm=tensor(ida,sigmam())
H=(w0-wl)*sm.dag()*sm+(wc-wl)*a.dag()*a+1j*g*(a.dag()*sm-sm.dag()*a)+E*(a.dag()+a)

# collapse operators
C1=sqrt(2*kappa)*a
C2=sqrt(gamma)*sm
C1dC1=C1.dag()*C1
C2dC2=C2.dag()*C2

# intial state
psi0=tensor(basis(N,0),basis(2,1))

# run monte-carlo solver with default 500 trajectories
data = mcsolve_f90(H, psi0, tlist, [C1,C2], [C1dC1,C2dC2])

# plot expectation values
plot(tlist,data.expect[0],tlist,data.expect[1],lw=2)
legend(('Transmitted Cavity Intensity','Spontaneous Emission'))
ylabel('Counts')
xlabel('Time')
show()


## ex31¶

In [6]:
wa  = 1.0 * 2 * pi   # frequency of system a
wb  = 1.0 * 2 * pi   # frequency of system a
wab = 0.2 * 2 * pi   # coupling frequency
ga = 0.2 * 2 * pi    # dissipation rate of system a
gb = 0.1 * 2 * pi    # dissipation rate of system b
Na = 10              # number of states in system a
Nb = 10              # number of states in system b
E = 1.0 * 2 * pi     # Oscillator A driving strength

a = tensor(destroy(Na), qeye(Nb))
b = tensor(qeye(Na), destroy(Nb))
na = a.dag() * a
nb = b.dag() * b
H = wa*na + wb*nb + wab*(a.dag()*b+a*b.dag()) + E*(a.dag()+a)

psi0 = tensor(basis(Na), basis(Nb))

c_op_list = []
c_op_list.append(sqrt(ga) * a)
c_op_list.append(sqrt(gb) * b)

tlist = linspace(0, 5, 101)

data = mcsolve_f90(H, psi0, tlist, c_op_list, [na,nb])

# plot results
figure()
plot(tlist,data.expect[0],'b',tlist,data.expect[1],'r',lw=2)
xlabel('Time',fontsize=14)
ylabel('Excitations',fontsize=14)
legend(('Oscillator A', 'Oscillator B'))
show()


## ex32¶

In [7]:
N = 4             # number of basis states to consider
kappa = 1.0/0.129 # coupling to heat bath
nth = 0.063       # temperature with <n>=0.063

# create operators and initial |1> state
a = destroy(N)    # cavity destruction operator
H = a.dag()*a     # harmonic oscillator Hamiltonian
psi0 = basis(N,1) # initial Fock state with one photon

# collapse operators
c_op_list = []
c_op_list.append(sqrt(kappa * (1 + nth)) * a)
c_op_list.append(sqrt(kappa * nth) * a.dag())

# run monte carlo simulation
tlist = linspace(0,0.6,100)
ex1 = mcsolve_f90(H,psi0,tlist,c_op_list,[a.dag()*a], ntraj=1).expect[0]
ex5 = mcsolve_f90(H,psi0,tlist,c_op_list,[a.dag()*a], ntraj=5).expect[0]
ex15 = mcsolve_f90(H,psi0,tlist,c_op_list,[a.dag()*a], ntraj=15).expect[0]
ex904 = mcsolve_f90(H,psi0,tlist,c_op_list,[a.dag()*a], ntraj=904).expect[0]

## run master equation to get ensemble average expectation values ##
me = mesolve(H,psi0,tlist,c_op_list, [a.dag()*a])

#  calulate final state using steadystate solver
fexpt = expect(a.dag()*a,final_state)

#
# plot results using vertically stacked plots
#

# set legend fontsize
import matplotlib.font_manager
leg_prop = matplotlib.font_manager.FontProperties(size=10)

figure(figsize=(6,9))

# subplot 1 (top)
ax1 = subplot(411)
ax1.plot(tlist,ex1,'b',lw=2)
ax1.axhline(y=fexpt,color='k',lw=1.5)
yticks(linspace(0,2,5))
ylim([-0.1,1.5])
ylabel('$\left< N \\right>$',fontsize=14)
title("Ensemble Averaging of Monte Carlo Trajectories")

# subplot 2
ax2=subplot(412,sharex=ax1)
ax2.plot(tlist,ex5,'b',lw=2)
ax2.axhline(y=fexpt,color='k',lw=1.5)
yticks(linspace(0,2,5))
ylim([-0.1,1.5])
ylabel('$\left< N \\right>$',fontsize=14)

# subplot 3
ax3=subplot(413,sharex=ax1)
ax3.plot(tlist,ex15,'b',lw=2)
ax3.plot(tlist,me.expect[0],'r--',lw=1.5)
ax3.axhline(y=fexpt,color='k',lw=1.5)
yticks(linspace(0,2,5))
ylim([-0.1,1.5])
ylabel('$\left< N \\right>$',fontsize=14)

# subplot 4 (bottom)
ax4=subplot(414,sharex=ax1)
ax4.plot(tlist,ex904,'b',lw=2)
ax4.plot(tlist,me.expect[0],'r--',lw=1.5)
ax4.axhline(y=fexpt,color='k',lw=1.5)
yticks(linspace(0,2,5))
ylim([-0.1,1.5])
ylabel('$\left< N \\right>$',fontsize=14)

# remove x-axis tick marks from top 3 subplots
xticklabels = ax1.get_xticklabels()+ax2.get_xticklabels()+ax3.get_xticklabels()
setp(xticklabels, visible=False)

ax1.xaxis.set_major_locator(MaxNLocator(4))
xlabel('Time (sec)',fontsize=14)
show()


## ex33¶

In [8]:
# number of states for each mode
N0=15
N1=15
N2=15

# define operators
a0=tensor(destroy(N0),qeye(N1),qeye(N2))
a1=tensor(qeye(N0),destroy(N1),qeye(N2))
a2=tensor(qeye(N0),qeye(N1),destroy(N2))

# number operators for each mode
num0=a0.dag()*a0
num1=a1.dag()*a1
num2=a2.dag()*a2

# initial state: coherent mode 0 & vacuum for modes #1 & #2
alpha=sqrt(7)#initial coherent state param for mode 0
psi0=tensor(coherent(N0,alpha),basis(N1,0),basis(N2,0))

# trilinear Hamiltonian
H=1.0j*(a0*a1.dag()*a2.dag()-a0.dag()*a1*a2)

# run Monte-Carlo
tlist = linspace(0,2.5,50)
output = mcsolve_f90(H,psi0,tlist,[],[],ntraj=1, serial=True)
#output=mcsolve(H,psi0,tlist,[],[],ntraj=1)

# extrace mode 1 using ptrace
mode1=[psi.ptrace(1) for psi in output.states]
# get diagonal elements
diags1=[k.diag() for k in mode1]
# calculate num of particles in mode 1
num1=[expect(num1,k) for k in output.states]
# generate thermal state with same # of particles
thermal=[thermal_dm(N1,k).diag() for k in num1]

# plot results
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
colors=['m', 'g','orange','b', 'y','pink']
x=arange(N1)
params = {'axes.labelsize': 14,'text.fontsize': 14,'legend.fontsize': 12,'xtick.labelsize': 14,'ytick.labelsize': 14}
rcParams.update(params)

fig = figure()

ax = Axes3D(fig)
for j in range(5):
ax.bar(x, diags1[10*j], zs=tlist[10*j], zdir='y', color=colors[j], linewidth=1.0, alpha=0.6, align='center')
ax.plot(x, thermal[10*j], zs=tlist[10*j], zdir='y', color='r', linewidth=3, alpha=1)
ax.set_zlabel(r'Probability')
ax.set_xlabel(r'Number State')
ax.set_ylabel(r'Time')
ax.set_zlim3d(0,1)
show()


## ex34¶

In [9]:
N0 = N1 = N2 = 6
gamma0 = 0.1
gamma1 = 0.4
gamma2 = 0.1
alpha = sqrt(2)
tlist = linspace(0,4,200)
ntraj = 500

# define operators
a0=tensor(destroy(N0),qeye(N1),qeye(N2))
a1=tensor(qeye(N0),destroy(N1),qeye(N2))
a2=tensor(qeye(N0),qeye(N1),destroy(N2))

# number operators for each mode
num0=a0.dag()*a0
num1=a1.dag()*a1
num2=a2.dag()*a2

# dissipative operators for zero-temp. baths
C0=sqrt(2.0*gamma0)*a0
C1=sqrt(2.0*gamma1)*a1
C2=sqrt(2.0*gamma2)*a2

# initial state: coherent mode 0 & vacuum for modes #1 & #2
psi0=tensor(coherent(N0,alpha),basis(N1,0),basis(N2,0))

# trilinear Hamiltonian
H=1j*(a0*a1.dag()*a2.dag()-a0.dag()*a1*a2)

# run Monte-Carlo
data = mcsolve_f90(H,psi0,tlist,[C0,C1,C2],[num0,num1,num2])

# plot results
fig = figure()
cs=['b','r','g']
for k in range(ntraj):
if len(data.col_times[k])>0:
colors=[cs[j] for j in data.col_which[k]]
xdat=[k for x in range(len(data.col_times[k]))]
ax.scatter(xdat,data.col_times[k],marker='o',c=colors)
ax.set_xlim([-1,ntraj+1])
ax.set_ylim([0,tlist[-1]])
ax.set_xlabel('Trajectory',fontsize=14)
ax.set_ylabel('Collpase Time',fontsize=14)
ax.set_title('Blue = C0, Red = C1, Green= C2')
show()


### Software versions¶

In [10]:
from qutip.ipynbtools import version_table
version_table()

Out[10]:
SoftwareVersion
Cython0.16
SciPy0.10.1
QuTiP2.2.0
Python2.7.3 (default, Sep 26 2012, 21:51:14) [GCC 4.7.2]
IPython0.13
OSposix [linux2]
Numpy1.7.0.dev-3f45eaa
matplotlib1.3.x
Tue Feb 26 13:57:11 2013