Open-system quantum dynamics of trapped-ion spin-motion systems.
New here? See docs/overview.md for an accessible introduction to what we do, how we work, and what we don't claim — written with three reading levels for students, collaborators, and curious visitors.
iontrap-dynamics is a domain-specific Python library for modelling trapped-ion
spin-motion physics with explicit, typed configuration objects for species,
drives, modes, and measurement conventions. The project is built around a hard
separation between physics, apparatus, and observation layers. QuTiP is the
reference backend; a JAX / Dynamiqs backend is available on the same public
solver surface via backend="jax".
v0.6.0 released 2026-06-04 — adds the reduced light–matter models
surface (Jaynes–Cummings / anti-Jaynes–Cummings / quantum-Rabi builders
plus a model_deviation comparison harness) and completes the two-mode /
motional surface, on top of the v0.5.0 estimation / quantum-Darwinism and
two-mode / motional service surfaces and the device-neutral JAX spectrum
backend. Phase 0 foundations, Phase 1
(dynamics core + measurement layer + systematics layer + registered
entanglement observables), Phase 2 (performance track + JAX / Dynamiqs
backend end-to-end), the Clos 2016 integration (full-Lamb–Dicke carrier
dynamics, exact-diagonalization spectrum tools, N = 1 / 2 / 3 reproduction
inside declared tolerances), and the v0.5.0 / v0.6.0 service surfaces
are all shipped on main. CONVENTIONS.md carries
§1–25: §19–24 (Fisher information / quantum Darwinism, two-mode
squeezing / SU(1,1), motional CPTP channels) sealed at the v0.3 Convention
Freeze (CONVENTION_VERSION 0.2 → 0.3), and §25 (reduced light–matter
models) sealed by WP-03 (CONVENTION_VERSION 0.3 → 0.4). Additive only:
existing v0.2.0 callers see no behaviour change — every new backend=
kwarg defaults to "qutip", every channels= argument defaults to none,
every JAX entry is behind an opt-in backend="jax".
The v0.6.0 cut bundles two things. The two-mode / motional service
surface is complete: interferometric fringe observables (MCD),
Lamb–Dicke regime helpers — Debye–Waller factor, a deep/intermediate/beyond
classifier, and the all-orders sideband-Rabi forms (MCE), a probe-QFI
benchmark that consumes the estimation primitive (MCF), and a motional
ModeFrequencyDrift systematic (MCG). And the reduced light–matter
models surface (WP-03) is new: the reduced_models JC / AJC / QRM
builders, a model_deviation comparison helper, an analytic oracle suite
(the four hierarchy cases), Tutorial 18 with a deterministic comparison
benchmark, and the vendored model-hierarchy companion note
(docs/models-hierarchy.md), anchored by CONVENTIONS §25 — all additive.
End-to-end stacks work dynamics-through-statistics, on either backend:
DriveConfig→carrier_hamiltonian→solve(...)→ expected π-pulse flip (Phase 1 core; QuTiP default, orbackend="jax"for the Dynamiqs path — cross-backend agreement under 1e-3 across all builder families).TrajectoryResult→SpinReadout.run→MeasurementResult→ Wilson CI band on finite-shot estimator (Phase 1 measurement).- Base
DriveConfig→perturb_carrier_rabi→ ensemble of solves → inhomogeneous-dephasing signature (Phase 1 systematics). detuned_carrier_hamiltonian(..., backend="jax")→solve(..., backend="jax")→TrajectoryResult(backend_name="jax-dynamiqs")withStorageMode.LAZYper-index loader (Phase 2 JAX backend end-to-end).
Phase 0 + Phase 1 + Phase 2 artefacts delivered:
- Public conventions frozen in
CONVENTIONS.mdv0.3 (§1–24 complete; §19–24 added at the v0.3 Convention Freeze, post-v0.4.0). - Three-layer regression harness populated: migration (5 / 5 scenarios
with legacy
qc.py-generated references, bit-identical across three runs; 3 / 5 active comparisons, 2 / 5 skipped with probe-informed blockers), analytic (6 closed-form formulas), invariant (9 checks). - Cache-integrity contract + tests.
- CI with ruff, ruff-format, mypy strict, pytest, pa11y WCAG 2 Level A (hard gate, AA advisory per v0.3.2 amendment).
Today the importable code surface covers:
Foundation (Phase 0)
iontrap_dynamics.exceptions— canonical exception hierarchy (IonTrapError,ConventionError,BackendError,IntegrityError,ConvergenceError)iontrap_dynamics.results— frozenTrajectoryResultschema with storage-mode consistency enforcementiontrap_dynamics.cache— hash-verified.npz+ JSON persistenceiontrap_dynamics.conventions—CONVENTION_VERSIONmarkeriontrap_dynamics.invariants— density-matrix / state-vector validatorsiontrap_dynamics.analytic— closed-form reference formulas (carrier Rabi, sideband rates, Lamb–Dicke parameter, coherent-state occupation), plus the Lamb–Dicke regime helpers (debye_waller_factor,lamb_dicke_regime→LambDickeRegime, all-orders{red,blue}_sideband_rabi_frequency_full_ld)
Configuration layer (Phase 1)
iontrap_dynamics.operators— single-ion Pauli set in the atomic-physics convention (sigma_z_ion,sigma_plus_ion, ...; see CONVENTIONS.md §3)iontrap_dynamics.species—IonSpecies,Transition,TransitionTypeand factories for ²⁵Mg⁺, ⁴⁰Ca⁺, ⁴³Ca⁺iontrap_dynamics.drives—DriveConfig(wavevector, Rabi, detuning, ...)iontrap_dynamics.modes—ModeConfigwith CONVENTIONS.md §11 normalisation enforced at constructioniontrap_dynamics.system—IonSystemcomposition with cross-validationiontrap_dynamics.hilbert—HilbertSpaceimplementing the §2 tensor ordering, operator embedding helpers, motional primitives (a, a†, n̂)iontrap_dynamics.states—ground_stateket,compose_density,coherent_mode/squeezed_vacuum_mode/squeezed_coherent_modefactories (CONVENTIONS.md §6, §7), the two-modetwo_mode_squeezed_vacuumfactory (§23), and theghz_state/cat_modeentangled-probe factoriesiontrap_dynamics.observables— namedObservablerecords andexpectations_over_time(...); spin x/y/z, multi-ion parity (σ_zproduct), mode number, plus the interferometric fringe analysisfringe_visibility/fit_fringe→FringeFitiontrap_dynamics.entanglement— nonlinear trajectory evaluators forconcurrence,entanglement_of_formation, andlog_negativity(withpartition="spins" | "modes"for bipartite splits). ConsumeTrajectoryResult.statesunderstorage_mode=EAGERiontrap_dynamics.systematics— dynamics-side noise models (§18 — frozen at v0.2). Jitter primitivesRabiJitter(multiplicative on Ω),DetuningJitter(additive on δ),PhaseJitter(additive on φ) withperturb_*ensemble helpers. Parallel drift primitivesRabiDrift,DetuningDrift,PhaseDrift(deterministic single-value offsets) withapply_*_driftcomposition helpers — plus the motionalModeFrequencyDrift(ω_m → ω_m·(1+δ)on aModeConfig) and the correlatedCommonModePhasechannel. SPAM primitivesSpinPreparationError,ThermalPreparationErrorproduce per-subsystem density matrices viaimperfect_spin_ground/imperfect_motional_groundthat compose into a full initial state viastates.compose_density.iontrap_dynamics.information— the estimation surface (§19–20): SLD quantum Fisher information, classical Fisher information, Cramér–Rao bound and a linear-Gaussian oracle (quantum_fisher_information_trajectory,classical_fisher_information,cramer_rao_bound), plus quantum-Darwinism redundancy and Schumacher–Nielsen recoverability.
Dynamics (Phase 1, full builder family)
The public Hamiltonian surface is symmetric across four families:
| exact (time-indep. Qobj) | detuned (list format) | |
|---|---|---|
| carrier | carrier_hamiltonian |
detuned_carrier_hamiltonian |
| red sideband | red_sideband_hamiltonian |
detuned_red_sideband_hamiltonian |
| blue sideband | blue_sideband_hamiltonian |
detuned_blue_sideband_hamiltonian |
| MS gate | ms_gate_hamiltonian |
detuned_ms_gate_hamiltonian |
Plus modulated_carrier_hamiltonian (time-dependent envelope primitive),
two_ion_{red,blue}_sideband_hamiltonian (single-tone shared-mode), the
two-mode two_mode_squeezing_hamiltonian / beamsplitter_hamiltonian
(SU(1,1) / SU(2), §23), and a full_lamb_dicke: bool flag on the sideband
builders (Wineland–Itano all-orders operator via matrix exponentiation).
Solver entry point: iontrap_dynamics.sequences.solve(...) — accepts both
Qobj and QuTiP list-format Hamiltonians, enforces the §13 Fock-saturation
ladder on every call, and accepts typed motional CPTP channels via
solve(channels=…) (iontrap_dynamics.channels: AmplitudeDamping,
Heating, Dephasing, with optional time windows; §24).
Measurement (Phase 1, v0.2 — frozen)
iontrap_dynamics.results.MeasurementResult—Resultsibling carrying the ideal / sampled dual-view mandated by WORKPLAN §5; enforcesshots ≥ 1andstorage_mode = OMITTEDat construction.iontrap_dynamics.measurement.BernoulliChannel— per-shot Bernoulli sampler; returns(shots, n_inputs)bits with leading shot axis (CONVENTIONS.md §17.1).iontrap_dynamics.measurement.BinomialChannel— aggregated sampler; returns(n_inputs,)int64 counts (CONVENTIONS.md §17.7, shape classes). Distributionally equivalent to summing Bernoulli bits, not bit-identical under matched seed.iontrap_dynamics.measurement.PoissonChannel— per-shot photon- counting channel; consumes non-negative rates (not probabilities) and returns(shots, n_inputs)int64 counts viarng.poisson(λ).iontrap_dynamics.measurement.DetectorConfig— detector-response parameters (efficiencyη, dark-count rateγ_d, thresholdN̂) withapply(rate),discriminate(counts), andclassification_fidelity(lambda_bright, lambda_dark)methods. Composes explicitly withPoissonChannelvia Poisson thinning plus additive background (exact; §17.8).iontrap_dynamics.measurement.sample_outcome(channel, inputs=..., shots, seed, upstream)— orchestrator that seeds the RNG, dispatches uniformly on channel type, storesinputsunderideal_outcome[channel.ideal_label]("probability"or"rate"), and inherits upstream-trajectory metadata when supplied.iontrap_dynamics.measurement.SpinReadout— first protocol-layer composer..run(trajectory, shots, seed)executes the projective- shot readout model (§17.9) and returns aMeasurementResultwith per-shot counts / bits / bright-fraction plus the idealp_↑andTP · p_↑ + (1 − TN) · (1 − p_↑)envelope.iontrap_dynamics.measurement.ParityScan— two-ion joint readout protocol (§17.10). ReconstructsP(s_0, s_1)from⟨σ_z^i⟩,⟨σ_z^j⟩, and⟨σ_z^i σ_z^j⟩, draws joint categorical samples so entangled-state correlations survive, and returns parity estimate- envelope shrunk by
(TP + TN − 1)². Requires the newiontrap_dynamics.observables.parityfactory.
- envelope shrunk by
iontrap_dynamics.measurement.SidebandInference— motional-state thermometry protocol (§17.11). Takes paired RSB / BSB trajectories and reports fidelity-correctedn̄ = r / (1 − r)via the short-time Leibfried–Wineland ratio; independent RNG streams per sideband; NaN propagates on singular ratios.iontrap_dynamics.measurement.wilson_interval,clopper_pearson_interval, andbinomial_summary/ theBinomialSummarydataclass (§17.12) — vectorised confidence intervals on binomial shot counts. Wilson is the recommended default; Clopper–Pearson is exact and conservative.
The measurement track is complete: CONVENTIONS.md §17.1–17.12
close the read-through, with §17 frozen at the v0.2.0 Convention
Freeze gate.
Phase 2 — performance and JAX backend (v0.3)
sequences.solve(...)gains abackend: str = "qutip"keyword- only parameter;backend="jax"dispatches to the Dynamiqs integrator viaiontrap_dynamics.backends.jax. Solver / backend compatibility is validated (explicitsolver="sesolve"or"mesolve"withbackend="jax"raisesConventionError; onlysolver="auto"is accepted on the JAX path).iontrap_dynamics.backends.jax.solve_via_jax(...)— opt-in JAX-backend entry. Dispatches todynamiqs.sesolvefor ket inputs,dynamiqs.mesolvefor density matrices. Honours all threeStorageModevalues (OMITTED / EAGER / LAZY — the LAZY loader closes over the Dynamiqs-returned JAX array, materialises oneQobjper index on demand, bounds-checks against JAX's silent-clamp behaviour). Forces JAX x64 at solve entry for complex128 arithmetic (CONVENTIONS.md §1 unit commitment).- Results on the JAX backend are tagged with
ResultMetadata.backend_name="jax-dynamiqs"andbackend_version=f"dynamiqs-{ver}+jax-{ver}". Thebackend_namestring is a schema-commitment tag: a future integrator swap requires a new string (not a suffix), so users' cache manifests stay consistent.convention_versionis read fromhilbert.system.convention_version, honouring archival pins exactly like the QuTiP path. - Every time-dependent Hamiltonian builder gains a
backend=kwarg on the same pattern (carrier, RSB, BSB, MS gate, modulated carrier). The four structured detuning builders sharebackends.jax._coefficients.timeqarray_cos_sinfordq.modulated(cos, H_static) + dq.modulated(sin, H_quadrature)assembly;modulated_carrier_hamiltoniantakes a user-suppliedenvelope_jaxkeyword (JAX-traceable mirror ofenvelope) for arbitrary pulse shapes. Missingenvelope_jaxonbackend="jax"raisesConventionError— no silent translation. - Cross-backend numeric equivalence validated at library-default
integrator tolerances across all five time-dependent builders:
worst-case 1.35e-5 absolute expectation delta, well under the
1e-3 design-target tolerance. Honest performance null result
at dim ≥ 100 / 5000 steps (QuTiP 5 is ~2.8× faster than
Dynamiqs + JAX on CPU at current library scales; see
docs/benchmarks.md). The JAX backend's value is positioning, cross-backend consistency checking, and forward-looking capability (autograd scaffolding ready viaenvelope_jaxcoefficients; GPU / TPU dispatch if the user installs a CUDA / Metal JAX build).
Demo tools (tools/run_*.py with canonical manifest.json +
arrays.npz + demo_report.json artefacts under benchmarks/data/):
run_benchmark_sideband, run_demo_carrier, run_demo_gaussian_pulse,
run_demo_ms_gate, run_demo_bernoulli_readout, run_demo_binomial_readout,
run_demo_poisson_readout, run_demo_detected_readout,
run_demo_spin_readout, run_demo_parity_scan,
run_demo_sideband_inference, run_demo_wilson_ci,
run_demo_bell_entanglement, run_demo_rabi_jitter,
run_demo_detuning_jitter, run_demo_rabi_drift_scan,
run_demo_spam_prep.
Phase 2 benchmark tools (tools/run_benchmark_*.py with
report.json + plot.png artefacts under benchmarks/data/):
run_benchmark_sesolve_speedup (Dispatch X — sesolve / mesolve
parity on QuTiP 5), run_benchmark_ensemble_parallel (Dispatch Y —
serial / loky / threading crossover), run_benchmark_sparse_vs_dense
(Dispatch OO — CSR / dense operator-dtype baseline; closes the
Phase 2 sparse-matrix-tuning open item),
run_benchmark_jax_timedep (Dispatch YY / β.4.5 — cross-backend
QuTiP-vs-JAX at dim ≥ 100 / 5000 steps across all five
time-dependent builders; needs the [jax] extras).
Test suite at v0.6.0 (base CI, no extras):
- 1319 passed, 3 skipped. Two skipped
tests are migration-tier builder-comparison slots (scenarios 3
and 4) with probe-informed blockers (see
CHANGELOG.md); one skipped module is the Dynamiqs-gated integration test file (tests/unit/test_backends_jax_dynamiqs.py, gated onpytest.importorskip("dynamiqs")). - With the
[jax]extras the suite additionally runs the Dynamiqs-gated integration tests (cross-backend numeric equivalence, result metadata, storage modes, Fock-saturation check, time-dependent builders, user-envelope dual-callable contract, andsolve_ensembleon JAX); run under the extra to confirm the current total.
Docs site scaffold:
mkdocs.ymlconfigures the public-facing documentation builddocs/index.md— welcome pagedocs/getting-started.md— install + first rundocs/framework.md— high-level design rulesdocs/conventions.md— rendered live from rootCONVENTIONS.md(single source of truth viapymdownx.snippets)docs/phase-1-architecture.md— concrete public-API reference (module map, per-module surface, extension points, non-goals; now also hosts the result-family vs backend-variety decision record from D5 / Dispatch NN)docs/phase-2-jax-backend-design.md— deliberation note for the Phase 2 JAX / Dynamiqs backend (design axes A-D, chosen Option β, ten open questions + their recorded answers)docs/phase-2-jax-time-dep-design.md— β.4 staging note for the time-dependent Hamiltonian track (Option X parallel JAX-native builders; 5-sub-dispatch plan; scope inventory)docs/benchmarks.md— honest performance baselines for every Phase 2 dispatch including the β.4.5 cross-backend benchmark at dim ≥ 100 / 5000 stepsdocs/boundary-decision-tree.md— contributor scope rules (closes D8)docs/tutorials/— task-oriented walkthroughs. Twelve tutorials shipped (Tutorials 1–12 cover the full public-surface pipeline end-to-end, from carrier Rabi + Wilson CIs through two-ion Bell-state entanglement); seedocs/tutorials/index.mddocs/stylesheets/tokens.css— vendored fromthreehouse-plus-ec/cd-rules
The authoritative project documents are:
WORKPLAN_v0.3.mdfor scope, architecture, milestones, and governanceCONVENTIONS.mdfor physical, numerical, and notational rulesLICENCEfor the repository split-licence declaration
Planned capabilities include:
- Unitary and dissipative dynamics for coupled spin-motion systems
- Standard ion-trap Hamiltonians: carrier, sideband, Mølmer-Sørensen, parametric modulation, and stroboscopic drives
- Standard state preparations and observables for spins and motional modes
- Backend-agnostic architecture: QuTiP reference backend + JAX /
Dynamiqs backend (opt-in via
backend="jax"— seedocs/benchmarks.mdfor when each is the right choice)
Explicitly out of scope:
- Trap geometry simulation
- Molecular dynamics of ion crystals
- Pulse-sequence compilers and hardware-control stacks
- Electromagnetic field modelling
Python 3.11+ is required.
Editable install:
python -m pip install -e ".[dev]"Optional groups:
.[docs]for documentation tooling.[plot]for plotting helpers used by examples and tutorials.[jax]for the JAX / Dynamiqs backend (Phase 2 β.1–β.4 onmain: opt in viabackend="jax"onsolveand on the time-dependent Hamiltonian builders)
Example:
python -m pip install -e ".[dev,docs]"src/iontrap_dynamics/— Python package (core +measurement/subpackage)tests/—unit/,conventions/,regression/{analytic,invariants,migration}/,benchmarks/tools/— maintenance scripts (asset fetch / checksum, SPDX check, pa11y config, migration-reference generator) and demo runnersbenchmarks/data/— canonical manifest + arrays + report artefacts per demo / benchmarkdocs/— mkdocs-material source for the documentation siteassets/— design assets consumed fromthreehouse-plus-ec/cd-ruleslegacy/— pinned legacyqc.pyused by migration-tier regressionWORKPLAN_v0.3.md— project workplan (v0.3.7 amendments applied: §4.0 repo-hosting, §5.0 release-mapping, §5.1 v0.2 release, §5.2 post-v0.2 on-main, §5.3 β.4 as v0.3.x follow-up, §5.4 estimation/Darwinism and §5.5 two-mode/motional open-system surfaces)CONVENTIONS.md— binding conventions document (v0.3 frozen: §17 measurement and §18 systematics closed at the v0.2.0 release; §19–24 estimation/Darwinism + two-mode/motional closed at the v0.3 Convention Freeze, post-v0.4.0)CHANGELOG.md— Keep-a-Changelog log of dispatches onmain
The distributable Python package is MIT-licensed. The repository as a whole
uses a split-licence architecture declared in LICENCE; design documents and
tutorial material do not all share the same terms.
Local candidate framework under active stewardship. No external endorsement is implied.