Parameters and Noise

Parametric simulations

AtomTwin uses a lightweight symbolic parameter system to separate model structure from numerical values. Rather than hard-coding frequencies, detunings, and other quantities, you wrap them in a Parameter and pass them to add_coupling!, add_detuning!, and similar functions. At play time the values are resolved — either to their defaults or to values you supply — without rebuilding the system.

Parameter objects can be combined with standard arithmetic to build ParametricExpression trees:

Ω = Parameter(:Omega, 2π * 1.0e6)       # 1 MHz Rabi frequency
δ = Parameter(:delta, 0.0; std = 0.1e6) # detuning with 100 kHz shot-to-shot disorder

amp = 0.5 * Ω + δ                       # ParametricExpression

Pass these expressions directly to physics functions, then sweep or sample at run time:

coupling = add_coupling!(system, atom, g => e, amp)

# sweep Omega over a grid
for Ω_val in range(0, 4π*1e6; length = 50)
    out = play(system, seq; initial_state = g, Omega = Ω_val)
end
AtomTwin.ParameterType
Parameter(name::Symbol, default; std = 0.0)

Scalar simulation parameter with an optional static-noise standard deviation.

Parameter stores a symbolic name, a default (mean) value and a standard deviation std. The default std = 0.0 corresponds to a deterministic, noise‑free parameter; nonzero std values are typically used to draw static random offsets for disorder or calibration errors. switchable=true indicates that this parameter can be turned off for error budget calculations.

Parameters can be combined arithmetically (e.g. 2*Ω + δ) to build ParametricExpressions which are resolved to concrete numbers at run time for each noise realization or sweep point.

AtomTwin.ParametricExpressionType
ParametricExpression

Symbolic expression tree built from Parameters, numeric literals, and basic arithmetic operations.

A ParametricExpression pairs an operator symbol (e.g. :+, :*, :abs) with a tuple of argument nodes, which can themselves be Parameters, ParametricExpressions, or plain numbers. These expressions are not evaluated immediately; instead they are resolved later given a concrete dictionary of parameter values.

Laser phase noise

Realistic laser phase noise is added by attaching a LaserPhaseNoiseModel to a coupling. The model synthesizes a time-domain noise realization from a parameterized frequency-noise power spectral density (PSD) that combines a Gaussian servo bump with a power-law background.

noise_model = LaserPhaseNoiseModel(
    bump_ampl   = 2.0e5,    # Hz²
    bump_center = 1.0e6,    # Hz — servo resonance at 1 MHz
    bump_width  = 2.0e5,    # Hz — Gaussian σ
    powerlaw_ampl = 0.25e5, # Hz² — white noise floor
)

coupling = add_coupling!(system, atom, g => e, Ω;
                         noise_model = noise_model)

Each Monte Carlo shot draws an independent noise realization; averaging over many shots (via shots = N in play) recovers ensemble-averaged dynamics.

The helper functions laser_freq_psd and laser_phase_psd evaluate the model's PSD at arbitrary frequencies, which is useful for plotting noise spectra before committing to a simulation:

freqs = range(0.1e6, 10e6; length = 500)
psd   = laser_freq_psd.(Ref(noise_model), freqs)
AtomTwin.LaserPhaseNoiseModelType
LaserPhaseNoiseModel(; bump_ampl, bump_center, bump_width,
                      powerlaw_ampl, powerlaw_exp = 0.0, n_freqs = 100)

Realistic laser phase noise model using a parameterized frequency-noise power spectral density (PSD) in Hz²/Hz.

The PSD model combines a Gaussian “servo bump” and a power-law background:

  • Servo bump: centered at bump_center with width bump_width and amplitude bump_ampl.
  • Power-law: powerlaw_ampl * f^powerlaw_exp (white frequency noise for powerlaw_exp = 0).

Fields:

  • bump_ampl::Float64: Servo bump amplitude (Hz²).
  • bump_center::Float64: Center frequency of the servo bump (Hz).
  • bump_width::Float64: Gaussian width σ of the bump (Hz).
  • powerlaw_ampl::Float64: Amplitude of the power-law background.
  • powerlaw_exp::Float64: Exponent d of the power law.
  • n_freqs::Int: Number of frequency components used when synthesizing noise.
AtomTwin.NoisyFieldType
NoisyField{A,T,N} <: Dynamiq.AbstractField

Wrapper that adds time-correlated noise to an underlying field or coupling.

Type parameters:

  • A: Atom type associated with the coupling.
  • T: Type of the wrapped field/coupling (e.g. GlobalCoupling, Detuning).
  • N <: AbstractNoiseModel: Noise model type (e.g. LaserPhaseNoiseModel).

Fields:

  • coupling::T: Original coupling/field object.
  • noise::N: Noise model and parameters.
  • global_time_ref::Ref{Float64}: Reference to the global simulation time, used to maintain temporal continuity across segments.
  • n_freqs::Int: Number of frequency components used in the noise synthesis.
  • rng::AbstractRNG: Random-number generator used to draw noise phases.
AtomTwin.laser_freq_psdFunction
laser_freq_psd(freqs, noise::AbstractNoiseModel) -> psd

Compute the laser frequency-noise power spectral density S_ν(f) in Hz²/Hz for one or more frequencies freqs, given a noise model.

Arguments:

  • freqs: Single frequency (Number) or an array of frequencies (Hz).
  • noise: Noise model, typically LaserPhaseNoiseModel.

Returns:

  • A single PSD value if freqs is a scalar, or a vector of PSD values matching freqs otherwise.

Internally this:

  • Constructs a time span consistent with the requested frequency range.
  • Uses get_noise_spectrum to evaluate the canonical frequency-noise PSD on a grid.
  • Interpolates the result to the requested frequencies.

Example:

noise = LaserPhaseNoiseModel()
f = 10 .^ range(2, 7; length = 500) # 100 Hz to 10 MHz
Sν = laser_freq_psd(f, noise) # frequency noise PSD in Hz^2/Hz
AtomTwin.laser_phase_psdFunction
laser_phase_psd(freqs, noise::AbstractNoiseModel) -> psd_phase

Compute the laser phase-noise power spectral density Sφ(f) in rad²/Hz from the frequency-noise PSD Sν(f) in Hz²/Hz, using

[ S\phi(f) = \frac{S\nu(f)}{(2\pi f)^2}. ]

Arguments:

  • freqs: Single frequency (Number) or an array of frequencies (Hz).
  • noise: Noise model, typically LaserPhaseNoiseModel.

Returns:

  • Phase-noise PSD values S_φ(f) with the same shape as freqs.

Example:

noise = LaserPhaseNoiseModel()
f = 10 .^ range(2, 7; length = 500)
Sφ = laser_phase_psd(f, noise) # phase noise PSD in rad^2/Hz

Gate tomography

process_tomography runs a complete set of input states through a compiled sequence and returns the Choi matrix of the resulting quantum channel. This is useful for computing gate fidelities and diagnosing error mechanisms.

choi = process_tomography(system, seq)

The returned matrix is in the standard column-vectorisation convention and can be used with any quantum-information library that accepts Choi matrices.

AtomTwin.process_tomographyFunction
process_tomography(
    sys, seq, atom, computational_levels;
    output_levels=computational_levels,
    kwargs...
)

Perform single-qubit quantum process tomography for atom in system sys under the pulse sequence seq.

The channel is characterized by simulating its action on the standard set of input states |0⟩, |1⟩, |+⟩, and |+i⟩ defined by computational_levels. The dynamics are obtained using play, and the output is projected onto the output_levels subspace.

Keyword arguments are forwarded to the underlying simulation calls, e.g. to control density-matrix vs. trajectory evolution or the number of shots.

Returns a named tuple with fields:

input_states – list of prepared input states in the full Hilbert space • output_states – list of simulated output density matrices • choi_matrix – Choi matrix of the reconstructed quantum channel • ptm_matrix – Pauli transfer matrix (PTM) of the channel • kraus_operators – vector of Kraus operators

Typical usage:

res = process_tomography(sys, seq, atom, [g, e]; shots=256)
res.ptm_matrix
res.kraus_operators