What's the goal:
Fix and polish the Dynamiqs backend in TrICal so that it reliably runs AtomicCircuit programs end-to-end and is usable as a JAX-native, GPU-capable, jit-compilable alternative to the QuTiP backend.
TrICal exposes two light-matter interaction backends for simulating an AtomicCircuit: a QuTiP-based backend (the reliable default) and a Dynamiqs-based backend (JAX + Diffrax under the hood). The Dynamiqs path is what unlocks GPU acceleration and jit-compiled simulation — things the QuTiP backend can't do. Today, that path doesn't reliably reproduce the QuTiP results, and the suspicion is around how timescales are being handed to Dynamiqs' sesolve.
Some details:
The Dynamiqs backend lives under src/oqd_trical/backend/dynamiqs and lowers an AtomicCircuit (defined in oqd-core) into a Dynamiqs simulation by:
- Building the time-dependent Hamiltonian from the system's ions, phonon modes, and beams via the compiler-infrastructure passes (
oqd-compiler-infrastructure).
- Constructing Dynamiqs operators and integrating with
dq.sesolve.
- Returning final states and metric expectation values back to the user through the
Task API.
Suspected timescale handling in sesolve
The current backend produces dynamics that don't cleanly match the QuTiP reference on simple test cases (e.g., a single-ion Rabi flop), and the suspicion is in how time/frequency units flow into dq.sesolve. Things to look at:
- The atomic-interface inputs (level energies, beam Rabi frequencies, detunings, pulse durations) carry SI units and factors of $2\pi$. The lowering needs to consistently produce a Hamiltonian and a
tsave array in matching units (typically Hamiltonian in angular frequency, time in seconds, or both rescaled to a dimensionless reference).
- Diffrax's adaptive step-size controller is sensitive to the absolute scale of
t0/t1 and dt0. With $H \sim 2\pi \cdot 10^{12}$ rad/s and $t \sim 10^{-6}$ s, mismatched rtol/atol defaults can silently under-resolve fast oscillations. Step-size controller and solver defaults should be set explicitly and documented.
- Time-dependent coefficients (pulse envelopes, modulation) should be expressed using Dynamiqs' time-array / modulated formats rather than reconstructed via Python closures, so the simulation stays
jit-able.
A useful test: pick one or two minimal cases (single-ion Rabi flop on the carrier, single-ion + COM phonon sideband transition), run both backends, and confirm the populations agree to a documented tolerance.
Requirements
Other rough edges
- Make sure the backend is
jax.jit-compatible, with no Python-side branching on traced values.
- Sensible, explicit defaults for the Diffrax solver and step-size controller (e.g.,
Tsit5 + PIDController with documented rtol / atol), overridable via TaskArgs.
- Resolving #26 (
DynamiqsBackend failing with ZMQError) would be a nice bonus along the way, if possible
What's the goal:
Fix and polish the Dynamiqs backend in TrICal so that it reliably runs
AtomicCircuitprograms end-to-end and is usable as a JAX-native, GPU-capable,jit-compilable alternative to the QuTiP backend.TrICal exposes two light-matter interaction backends for simulating an
AtomicCircuit: a QuTiP-based backend (the reliable default) and a Dynamiqs-based backend (JAX + Diffrax under the hood). The Dynamiqs path is what unlocks GPU acceleration andjit-compiled simulation — things the QuTiP backend can't do. Today, that path doesn't reliably reproduce the QuTiP results, and the suspicion is around how timescales are being handed to Dynamiqs'sesolve.Some details:
The Dynamiqs backend lives under
src/oqd_trical/backend/dynamiqsand lowers anAtomicCircuit(defined inoqd-core) into a Dynamiqs simulation by:oqd-compiler-infrastructure).dq.sesolve.TaskAPI.Suspected timescale handling in
sesolveThe current backend produces dynamics that don't cleanly match the QuTiP reference on simple test cases (e.g., a single-ion Rabi flop), and the suspicion is in how time/frequency units flow into
dq.sesolve. Things to look at:tsavearray in matching units (typically Hamiltonian in angular frequency, time in seconds, or both rescaled to a dimensionless reference).t0/t1anddt0. Withrtol/atoldefaults can silently under-resolve fast oscillations. Step-size controller and solver defaults should be set explicitly and documented.jit-able.A useful test: pick one or two minimal cases (single-ion Rabi flop on the carrier, single-ion + COM phonon sideband transition), run both backends, and confirm the populations agree to a documented tolerance.
Requirements
AtomicCircuitinputs, the lowered Hamiltonian, and Dynamiqs'sesolveis consistent and documented in code.TaskArgs.QutipBackendfromoqd-analog-emulator; any breaking changes are documented.Other rough edges
jax.jit-compatible, with no Python-side branching on traced values.Tsit5+PIDControllerwith documentedrtol/atol), overridable viaTaskArgs.DynamiqsBackend failing with ZMQError) would be a nice bonus along the way, if possible