Quick Start Guide

Installation

AtomTwin is a Julia package. The easiest way to use it is via the Julia package manager.

Requirements

  • Julia 1.11 or later
  • Internet access to download dependencies from the General registry

Install Julia with juliaup

juliaup is the recommended way to install and manage Julia on all major platforms.

  • Windows: Install “Julia” from the Microsoft Store or via the Windows package manager (winget), which also installs juliaup. Then open a new terminal and run julia to start the Julia REPL.
  • Linux: Use your distribution’s instructions for installing juliaup (typically a single shell command from the official Julia download page), then open a terminal and run julia.

If you want Julia to use multiple CPU threads, start it with julia --threads auto (or set the JULIA_NUM_THREADS environment variable), then follow the steps below to add AtomTwin.

Install AtomTwin from the registry

Start Julia, enter the package mode with ], and add AtomTwin:

julia> ]
pkg> add AtomTwin

Then, in your code:

using AtomTwin

Your first simulation: driven two‑level atom

An AtomTwin simulation usually follows three steps:

  1. Define the system (atoms, tweezers, interactions, noise, …)
  2. Build a sequence of operations and attach detectors
  3. Run the simulation with play and inspect the outputs

1. Define a two‑level atom and system

using AtomTwin

g, e = Level(; label = "g"), Level(; label = "e")
atom  = Atom(; levels = [g, e])
system = System(atom)
AtomTwin.System
├─ Atoms (1): GenericAtom[g,e]
├─ Beams (0)
├─ Nodes (0)
├─ Detectors (0)
├─ Basis: dim = 2
└─ State: empty

2. Add physics and a detector

Add a resonant coupling between |g⟩ and |e⟩ with a Rabi frequency of 1 MHz:

add_coupling!(system, atom, g => e, 2π * 1e6)
AtomTwin.GlobalCoupling(1→2, Ω=6.283185307179586e6 + 0.0im)
├─ Transition: 1 → 2
├─ Coefficient: 1.0 + 0.0im
└─ H:          2×2 operator (2 nonzero elements

Register a population detector on the excited state so we can plot the dynamics later:

add_detector!(system, PopulationDetectorSpec(atom, e; name = "P_e"))
AtomTwin.System
├─ Atoms (1): GenericAtom[g,e]
├─ Beams (0)
├─ Nodes (1)
├─ Detectors (1): PopulationDetector
├─ Basis: dim = 2
└─ State: empty

Now define a simple sequence with a fixed time step of 1 ns and a 5 µs wait:

seq = Sequence(1e-9)  # fixed time step of 1 nanosecond
@sequence seq begin
    Wait(5e-6)        # duration of 5 microseconds
end
Sequence(AbstractInstruction[Wait(5.0e-6)], 1.0e-9)

3. Run the simulation

out = play(system, seq; initial_state = g)
(detectors = Dict{String, Any}("P_e" => [9.869571931419052e-6, 3.947789809187577e-5, 8.882380959535094e-5, 0.00015790535834975207, 0.00024671981713382096, 0.0003552636797047994, 0.00048353266093685023, 0.0006315216969902259, 0.0007992249455111807, 0.0009866357858626174  …  0.0006315216976315857, 0.00048353266149810093, 0.0003552636801859175, 0.00024671981753478564, 0.000157905358670546, 8.882380983595985e-5, 3.94778982522886e-5, 9.869572011627851e-6, 1.629666288772325e-22, 9.869571851208647e-6]), times = [1.0e-9, 2.0e-9, 3.0000000000000004e-9, 4.0e-9, 5.0e-9, 6.0e-9, 7.000000000000001e-9, 8.0e-9, 9.000000000000001e-9, 1.0000000000000002e-8  …  4.992e-6, 4.993e-6, 4.994e-6, 4.995e-6, 4.996e-6, 4.997e-6, 4.998e-6, 4.999e-6, 4.9999999999999996e-6, 5.001e-6], final_states = Vector{ComplexF64}[])

Detector outputs are stored in out.detectors by name. For the excited‑state population:

out.detectors["P_e"]
5001-element Vector{Float64}:
 9.869571931419052e-6
 3.947789809187577e-5
 8.882380959535094e-5
 0.00015790535834975207
 0.00024671981713382096
 0.0003552636797047994
 0.00048353266093685023
 0.0006315216969902259
 0.0007992249455111807
 0.0009866357858626174
 ⋮
 0.00048353266149810093
 0.0003552636801859175
 0.00024671981753478564
 0.000157905358670546
 8.882380983595985e-5
 3.94778982522886e-5
 9.869572011627851e-6
 1.629666288772325e-22
 9.869571851208647e-6

You can now plot out.detectors["P_e"] against out.times using your plotting package of choice.


Using AtomTwin in a project environment

For a new project directory:

mkdir my_atom_project
cd my_atom_project
julia --project=.

Then in the Julia REPL:

julia> ]
pkg> add AtomTwin

Your Project.toml will now list AtomTwin as a dependency, and you can use it in any script inside this directory:

using AtomTwin

Example workflows

Once AtomTwin is installed, you can:

  • Explore more examples such as Rabi oscillations with noise and dissipation.
  • Design and optimize your own sequences including quantum and classical dynamics of atoms in tweezer arrays.
  • Prototype your own quantum instructions, estimate fidelities and error budgets.