# Heat-pumped three-level maser

Consider a three-level atom that interacts with two heat baths at temperatures $T_\mathrm{c}$ and $T_\mathrm{h}$, respectively, and a single cavity field mode. The cavity mode is further coupled to an environment at temperature $T_\mathrm{env}$.

The atomic transition $|1\rangle \leftrightarrow |3\rangle$ at frequency $\omega_\mathrm{h}:=\omega_3-\omega_1$ is coupled to the hot bath, the atomic transition $|2\rangle \leftrightarrow |3\rangle$ at frequency $\omega_\mathrm{c}:=\omega_3-\omega_2$ is coupled to the cold bath and the atomic transition $|1\rangle \leftrightarrow |2\rangle$ at frequency $\omega_\mathrm{f}:=\omega_2-\omega_1$ (the lasing transition) is coupled to the cavity mode.

The Hamiltonian

$H=H_\mathrm{free}+H_\mathrm{int}$

consists of the "free" atomic and cavity Hamiltonian

$H_\mathrm{free}=\hbar\omega_1 |1\rangle\langle 1|+\hbar\omega_2 |2\rangle\langle 2|+\hbar\omega_3 |3\rangle\langle 3|+\hbar\omega_\mathrm{f}a^\dagger a$

and the Jaynes-Cummings interaction

$H_\mathrm{int}=\hbar g\left(\sigma_{12}a^\dagger+\sigma_{21} a\right).$

The interaction with the various environmental heat baths is described by the Liouvillian

$\mathcal{L}\rho = \frac{\gamma_\mathrm{h}}{2}[\bar{n}(\omega_\mathrm{h},T_\mathrm{h})+1] \mathcal{D}[\sigma_{13}] + \frac{\gamma_\mathrm{h}}{2}\bar{n}(\omega_\mathrm{h},T_\mathrm{h}) \mathcal{D}[\sigma_{31}]\\ \quad + \frac{\gamma_\mathrm{c}}{2}[\bar{n}(\omega_\mathrm{c},T_\mathrm{c})+1] \mathcal{D}[\sigma_{23}] + \frac{\gamma_\mathrm{c}}{2}\bar{n}(\omega_\mathrm{c},T_\mathrm{c}) \mathcal{D}[\sigma_{32}]\\ \quad + \kappa[\bar{n}(\omega_\mathrm{f},T_\mathrm{env})+1] \mathcal{D}[a] + \kappa\bar{n}(\omega_\mathrm{f},T_\mathrm{env}) \mathcal{D}[a^\dagger],$

where the dissipator is defined as $\mathcal{D}[A]:= 2A\rho A^\dagger - A^\dagger A \rho -\rho A^\dagger A$.

The time evolution of the joint atom-field state is then given by the master equation

$\dot{\rho}(t) = \frac{1}{i\hbar}[H,\rho] + \mathcal{L}\rho.$

using QuantumOptics
using PyPlot
using LinearAlgebra
const nph=50     # cavity mode photon cutoff

const Th=100.    # temperature of the hot bath
const Tc=20.     # temperature of the cold bath
const Tenv=0.    # environment temperature for the cavity

const omega1=0.
const omega2=30.
const omega3=150.

const omegaf=omega2-omega1  # cavity frequency (lasing frequency)
const omegah=omega3-omega1  # frequency of the atomic transition that is coupled to the hot bath
const omegac=omega3-omega2  # frequency of the atomic transition that is coupled to the cold bath

const g=5.
const kappa=0.1
const gammah=40.
const gammac=40.

const tmax=50.
const dt=.1
const tvec=[0.:dt:tmax;]        # output times for expectation values (high resolution)
const dtrho=10.
const trhovec=[0.:dtrho:tmax;]; # output times for the density matrix (low resolution)
const ba=NLevelBasis(3)
const bf=FockBasis(nph)
const b_comp=ba⊗bf

const psi1=nlevelstate(ba,1)
const psi2=nlevelstate(ba,2)
const psi3=nlevelstate(ba,3)

const proj1=projector(psi1)⊗one(bf)
const proj2=projector(psi2)⊗one(bf)
const proj3=projector(psi3)⊗one(bf)

const sigma13=transition(ba,1,3)⊗one(bf)
const sigma23=transition(ba,2,3)⊗one(bf)
const sigma12=transition(ba,1,2)⊗one(bf)

const a=one(ba)⊗destroy(bf)
const Hfree=omega1*proj1+omega2*proj2+omega3*proj3+omegaf*dagger(a)*a

const Hint=g*(sigma12*dagger(a)+a*dagger(sigma12))

const H=Hfree+Hint
const R=Array{Float64}(undef,6)
nbar(omega::Float64,T::Float64)=(exp(omega/T)-1)^(-1) # hbar=k_B=1

R[1]=gammah*(nbar(omegah,Th)+1)
R[2]=gammah* nbar(omegah,Th)

R[3]=gammac*(nbar(omegac,Tc)+1)
R[4]=gammac* nbar(omegac,Tc)

R[5]=2*kappa*(nbar(omegaf,Tenv)+1)
R[6]=2*kappa* nbar(omegaf,Tenv)

const J=[sqrt(R[1])*sigma13,sqrt(R[2])*dagger(sigma13),
sqrt(R[3])*sigma23,sqrt(R[4])*dagger(sigma23),
sqrt(R[5])*a,sqrt(R[6])*dagger(a)]
const trho=Array{Float64}(undef,length(trhovec))
const rho=[DenseOperator(b_comp) for k=1:length(trhovec)]

# This dictionary contains the operators whose expectation values should be
# computed with high resolution during the time evolution
:population1=>proj1,
:population2=>proj2,
:population3=>proj3)

function compute_expvalues(τ,ρ)
index=findfirst(isapprox.(τ,trhovec)) # The comparison of floats is problematic
if !isnothing(index) # save ρ if τ is contained in throvec
trho[index]=τ
rho[index]=copy(ρ)
end
return Dict{Symbol,ComplexF64}(key=>expect(value,ρ) for (key,value) in operators)
end
const r0=dm(psi1)⊗dm(fockstate(bf,0))
normalize!(r0)

t,expvalues=timeevolution.master(tvec,r0,H,J;fout=compute_expvalues)
g2=real.(getindex.(expvalues,:adagger_adagger_a_a)./getindex.(expvalues,:adagger_a).^2)
rhof=[ptrace(r,1) for r in rho]

x=[-7.5:0.01:7.5;]
qfunc_ss=qfunc(rhof[end],x,x); # steady-state Q function
figure(figsize=[12.8,8.6])

subplot(2,2,1)
plot(t,real.(getindex.(expvalues,:population1)),label="population of level "*L"|1\rangle")
plot(t,real.(getindex.(expvalues,:population2)),label="population of level "*L"|2\rangle")
plot(t,real.(getindex.(expvalues,:population3)),label="population of level "*L"|3\rangle")
title("atomic populations")
xlabel("t")
legend()
grid()

subplot(2,2,2)
title("photon number")
xlabel("t")
ylabel(L"\langle a^\dagger a\rangle")
grid()

subplot(2,2,3)
plot(tvec,g2)
title(L"g^{(2)}"*" function")
xlabel("t")
ylabel(L"g^{(2)}(0)")
grid()

subplot(2,2,4)
pcolormesh(x,x,transpose(real(qfunc_ss)),cmap="jet")
axis("equal")
title(L"Q"*" function at "*L"t="*string(tvec[end]))
xlabel(L"$\mathrm{Re}\,\alpha$")
ylabel(L"$\mathrm{Im}\,\alpha$")

tight_layout()

bar([0:nph;],real.(diag(rhof[end].data)))
title("photon statistics at "*L"t="*string(tvec[end]))
xlabel("n")
grid()