Beam Splitter Loss
This example models loss of pulse in a Fock-state by mixing the pulse with a vacuum port on a beam splitter. We analyze the output mode $v(t)$ which is the same as the input mode $u(t)$.
using QuantumInputOutputusing SecondQuantizedAlgebrausing QuantumOpticsusing QuantumOpticsBase: daggerusing Plotsusing LinearAlgebra# symbolic Hilbert space and operators (virtual input and output modes)hu = FockSpace(:u)hv = FockSpace(:v)h = hu ⊗ hvau = Destroy(h, :a_u, 1)av = Destroy(h, :a_v, 2)# symbolic parameters@variables gu::Number gv::Number r::Real t::RealIn our example, we only have one input mode and one output mode, however, the beam splitter has two input and two output ports. Since the number of input and output ports needs to match to cascade a system we need to create a padding element and add concatenate it to the corresponding SLH elements. The padding element (1,0,0) represents vacuum input but also a non-tracked output, respectively.
# padding element for the unused portG_p = SLH(1, 0, 0)# beam splitter scattering matrixS_bs = [r t; t -r]# input cavity, beam splitter, and output cavityG_u = SLH(1, gu' * au, 0)G_in = G_u ⊞ G_pG_bs = SLH(S_bs, [0, 0], 0)G_v = SLH(1, gv' * av, 0)# G_out = G_v ⊞ G_p # reflection is trackedG_out = G_p ⊞ G_v # transmission is trackedG = G_in ▷ G_bs ▷ G_outH = hamiltonian(G)(-0.5conj(gu)*gv*t)im * a_u * a_v' + (0.5conj(gv)*gu*t)im * a_u' * a_vL = jump_operator(G)L[1]conj(gu)*r * a_uL[2]conj(gu)*t * a_u + conj(gv) * a_v# Gaussian input modeγ_ = 1.0σ = 1 / γ_T_end = 12σu(t) = 1/(sqrt(σ)*π^(1/4)) * exp(-(t - 4σ)^2 / (2*σ^2))T = [0:0.004:1;] * T_endΔT = T[2] - T[1]# time-dependent coupling for the virtual cavitiesgu_t = coupling_input(u, T)gv_t = coupling_output(u, T) # v(t) = u(t)dict_p_t = Dict(gu => gu_t, gv => gv_t)# beam splitter parametersη = 0.2 # lossr_ = sqrt(η) # reflectiont_ = sqrt(1 - η) # transmissiondict_p = Dict([t, r] .=> [t_, r_])As usual, we translate the symbolic system into numeric expressions and solve the dynamics with QuantumOptics.jl.
# numeric basisn_ph = 4bu = FockBasis(n_ph)bv = FockBasis(n_ph)b = bu ⊗ bvau_qo = destroy(bu) ⊗ one(bv)av_qo = one(bu) ⊗ destroy(bv)# translate to numeric operatorsH_QO = to_numeric(H, b; parameter = dict_p, time_parameter = dict_p_t)L_QO = [to_numeric(Li, b; parameter = dict_p, time_parameter = dict_p_t) for Li in L]function input_output(t, ρ) Ht = H_QO(t) J = [L_QO[1](t), L_QO[2](t)] return Ht, J, dagger.(J)end# time evolutionψ0 = fockstate(bu, n_ph) ⊗ fockstate(bv, 0)time, ρt = timeevolution.master_dynamic(T, ψ0, input_output)n_u_t = real(expect(au_qo'au_qo, ρt))n_v_t = real(expect(av_qo'av_qo, ρt))ρv_end = ptrace(ρt[end], 1)pop_n_ls = [real(ρv_end.data[i, i]) for i = 1:(n_ph+1)]We plot the mean photon number and the distribution of the Fock state components after the beam splitter interaction. We can see that the mean photon number is reduced by $\eta = 20 \%$.
p1 = plot( T, n_u_t .+ n_v_t; xlabel = "time", ylabel = "photon number", grid = true, label = "",)p2 = bar( 0:n_ph, pop_n_ls; xlabel = "Fock state component n", ylabel = "population", label = "",)plot(p1, p2; layout = (2, 1), size = (540, 420))Note that the calculation can also be performed in the interaction picture, which would be numerically beneficial and the loss of the input mode $u(t)$ can be directly observed.
Package versions
These results were obtained using the following versions:
using InteractiveUtilsversioninfo()using PkgPkg.status( [ "QuantumInputOutput", "SecondQuantizedAlgebra", "QuantumOptics", "Plots", "LaTeXStrings", ], mode = PKGMODE_MANIFEST,)Julia Version 1.13.0
Commit d1c37793dd2 (2026-09-09 19:00 UTC)
Build Info:
Official https://julialang.org release
Platform Info:
OS: Linux (x86_64-linux-gnu)
CPU: 4 × AMD EPYC 7763 64-Core Processor
WORD_SIZE: 64
LLVM: libLLVM-20.1.8 (ORCJIT, znver3)
GC: Built with stock GC
Threads: 1 default, 0 interactive, 1 GC (on 4 virtual cores)
Environment:
JULIA_PKG_SERVER_REGISTRY_PREFERENCE = eager
JULIA_DEBUG = Documenter,Literate
JULIA_NUM_THREADS = 1
Status `~/work/QuantumInputOutput.jl/QuantumInputOutput.jl/docs/Manifest.toml`
⌅ [7d9fca2a] Arpack v0.5.3
⌅ [861a8166] Combinatorics v1.0.2
[d38c429a] Contour v0.6.3
⌅ [82cc6244] DataInterpolations v9.5.0
[459566f4] DiffEqCallbacks v4.19.4
[77a26b50] DiffEqNoiseProcess v5.36.4
[c87230d0] FFMPEG v0.4.5
[7a1cc6ca] FFTW v1.10.0
⌅ [53c48c17] FixedPointNumbers v0.8.6
[069b7b12] FunctionWrappers v1.1.3
[28b8d3ca] GR v0.73.27
[42fd0dbc] IterativeSolvers v0.9.4
[1019f520] JLFzf v0.1.11
[682c06a0] JSON v1.9.0
[0b1a1467] KrylovKit v0.10.4
[b964fa9f] LaTeXStrings v1.4.1
[23fbe1c1] Latexify v0.16.12
[7a12625a] LinearMaps v3.11.4
[442fdcdd] Measures v0.3.3
[d8a4904e] MutableArithmetics v1.8.1
[77ba4419] NaNMath v1.1.4
[e7bfaba1] NumericalIntegration v0.3.4
[1dea7af3] OrdinaryDiffEq v7.8.1
[1344f307] OrdinaryDiffEqLowOrderRK v2.2.5
[ccf2f8ad] PlotThemes v3.3.0
[995b91a9] PlotUtils v1.5.0
[91a5bcdd] Plots v1.41.7
[aea7be01] PrecompileTools v1.3.4
[18f9eda6] QuantumInputOutput v0.5.3 `~/work/QuantumInputOutput.jl/QuantumInputOutput.jl`
[5717a53b] QuantumInterface v0.4.4
[6e0679c1] QuantumOptics v1.2.10
[4f57444f] QuantumOpticsBase v0.5.16
[3cdcf5f2] RecipesBase v1.3.4
[01d81517] RecipesPipeline v0.6.12
[731186ca] RecursiveArrayTools v4.5.3
[189a3867] Reexport v1.2.2
[05181044] RelocatableFolders v1.0.1
[ae029012] Requires v1.3.1
[0bca4576] SciMLBase v3.56.1
[431bcebd] SciMLPublic v1.3.0
[6c6a2e73] Scratch v1.3.0
⌅ [f7aa4685] SecondQuantizedAlgebra v0.11.0
[992d4aef] Showoff v1.1.1
[276daf66] SpecialFunctions v2.9.0
[90137ffa] StaticArrays v1.9.22
[10745b16] Statistics v1.11.5
[2913bbd2] StatsBase v0.34.13
[789caeaf] StochasticDiffEq v7.2.0
[d1185830] SymbolicUtils v4.48.0
[0c5d862f] Symbolics v7.41.1
[8ea1fca8] TermInterface v2.0.0
[1cfade01] UnicodeFun v0.4.1
[41fe7b60] Unzip v0.2.0
[2a0f44e3] Base64 v1.11.0
[ade2ca70] Dates v1.11.0
[f43a241f] Downloads v1.7.0
[37e2e46d] LinearAlgebra v1.13.0
[44cfe95a] Pkg v1.13.0
[de0858da] Printf v1.11.0
[3fa0cd96] REPL v1.11.0
[9a3f8284] Random v1.11.0
[2f01184e] SparseArrays v1.13.0
[fa267f1f] TOML v1.0.3
[cf7118a7] UUIDs v1.11.0
Info Packages marked with ⌅ have new versions available but compatibility constraints restrict them from upgrading. To see why use `status --outdated -m`
This page was generated using Literate.jl.