quchip.devices.transmon.duffing

Duffing-approximation transmon qubit.

Hamiltonian:

\[H = \omega \, \hat{n} + \tfrac{\alpha}{2} \, \hat{n}\,(\hat{n} - \mathbb{1})\]

where \(\hat{n} = a^\dagger a\), \(\omega\) is the bare 0 -> 1 transition frequency and \(\alpha\) is the anharmonicity (conventionally negative for a transmon, \(\alpha \sim -200\ \text{MHz}\)).

Approximation & regime of validity

This is the Kerr / Duffing expansion of the transmon’s cosine Josephson potential truncated at quartic order:

\[H_{\text{full}} = 4 E_C (\hat{n} - n_g)^2 - E_J \cos \hat{\phi}\]

expanded to \(\hat{\phi}^4\) after rotating-frame normal ordering. Validity conditions (Koch et al. 2007):

  • Transmon regime, \(E_J / E_C \gtrsim 50\) — charge-dispersion of the lowest levels becomes exponentially small in \(\sqrt{8 E_J / E_C}\), so offset-charge noise is suppressed and the qubit is well-approximated by a weakly anharmonic oscillator.

  • Low-lying levels only — higher levels probe progressively more of the cosine nonlinearity and deviate from the quartic truncation.

  • Anharmonicity \(\alpha \approx -E_C\), with \(\omega_{01} \approx \sqrt{8 E_J E_C} - E_C\).

Not captured: full charge-basis spectrum, higher-order nonlinearities (\(\hat{\phi}^6\) and beyond), flux-tunability, two-qubit dispersive shifts beyond what couplings/drives provide.

References

  • Koch, Yu, Gambetta, Houck, Schuster, Majer, Blais, Devoret, Girvin & Schoelkopf, Charge-insensitive qubit design derived from the Cooper pair box, Physical Review A 76, 042319 (2007), Eq. 2.6 (Duffing form); Eqs. 2.11–2.12 (regime of validity).

  • Didier, Sete, da Silva & Rigetti, Analytical modeling of parametrically modulated transmon qubits, Physical Review A 97, 022330 (2018) — anharmonic-oscillator sector used in pulse-level modelling.

  • Krantz, Kjaergaard, Yan, Orlando, Gustavsson & Oliver, A quantum engineer’s guide to superconducting qubits, Applied Physics Reviews 6, 021318 (2019) — §III.B for the Duffing form, §V for the T1 / T2 / thermal channels that the base class attaches.

Noise hooks inherited from BaseDevice (T1, T2, thermal_population) produce the standard Lindblad channels described in that base class.

Example

>>> from quchip.chip import Chip
>>> from quchip.devices import DuffingTransmon, Resonator
>>> q = DuffingTransmon(freq=5.0, anharmonicity=-0.25, levels=3, label="q")
>>> r = Resonator(freq=7.0, levels=6, label="r")
>>> chip = Chip(devices=[q, r])
>>> q.computational, q.freq, q.anharmonicity
(True, 5.0, -0.25)

Functions

duffing_expr(op, freq, anharmonicity)

Shared Duffing local Hamiltonian H = omega n + (alpha/2) n (n - I).

Classes

DuffingTransmon(freq, anharmonicity, *[, ...])

Transmon modelled as a weakly anharmonic Duffing oscillator.

quchip.devices.transmon.duffing.duffing_expr(op, freq, anharmonicity)[source]

Shared Duffing local Hamiltonian H = omega n + (alpha/2) n (n - I).

Both DuffingTransmon and FluxTunableTransmon build their static local Hamiltonian from this single expression, so the two produce the identical declarative term.

Parameters:
Return type:

PhysicsExpr

class quchip.devices.transmon.duffing.DuffingTransmon(freq, anharmonicity, *, levels=3, label=None, T1=None, T2=None, thermal_population=None)[source]

Bases: DeviceModel

Transmon modelled as a weakly anharmonic Duffing oscillator.

Parameters:
  • freq (float) – Bare 0 -> 1 transition frequency ω in GHz. Must be positive. May be a JAX tracer for sweeps / gradients.

  • anharmonicity (float) – Anharmonicity α in GHz. Typically negative for superconducting transmons (e.g. -0.25 GHz). May be a JAX tracer.

  • levels (int, default 3) – Fock-space truncation. Three levels suffice for leakage-aware single-qubit modelling; increase for higher-level physics (e.g. iSWAP-family gates via the |02>-|11> crossing).

  • label (str | None, default None) – If omitted, auto-generated as duffing_{idx} via the shared labeling counter.

  • **noise_kwargs – Forwarded to BaseDeviceT1, T2, thermal_population.

Example

>>> from quchip.devices import DuffingTransmon
>>> q = DuffingTransmon(freq=5.0, anharmonicity=-0.25, T1=30_000.0, T2=20_000.0)
>>> len(q.collapse_operators()) >= 1
True
tunable_param_names = ('freq', 'anharmonicity')

Bare parameters this device exposes as differentiable / tunable scalars. fit_a_dress walks this tuple to discover what it is allowed to optimize on each device, decoupling the inverse-design surface from any specific device model. Three states, keyed on whether the value is explicitly declared:

  • No explicit declaration anywhere in the DeviceModel lineage — the default is derived: every declared parameter() field, in declaration order (see DeviceModel.__init_subclass__).

  • Explicit tuple on the class or an ancestor — exact curation, validated at class-definition time; authoritative and inherited until a subclass explicitly replaces it.

  • Explicit empty tuple — deliberately freezes the device (and its subclasses, until one replaces it) out of inverse design.

On a plain (non-DeviceModel) BaseDevice subclass there is no derivation; the default stays empty unless the subclass declares its own tuple — e.g. Fluxonium uses ("E_C", "E_J", "E_L", "phi_ext").

approximation = 'Duffing expansion: cosine Josephson potential truncated at 4th order.'

Declared approximation-regime statement surfaced by physics_notes() — the mechanism that keeps a model’s stated validity range attached to the class rather than buried in a docstring a caller may not read.

computational = True

Whether this device represents a computational qubit, as opposed to e.g. a bus resonator or a coupler element.

freq: Scalar = Parameter(default=<object object>, positive=True, nonnegative=False, serialize=True, unit='GHz')
anharmonicity: Scalar = Parameter(default=<object object>, positive=False, nonnegative=False, serialize=True, unit='GHz')
local_hamiltonian(op)[source]

Return the local Duffing Hamiltonian H = omega n + (alpha/2) n (n - I).

Parameters:

op (LocalOps)

Return type:

PhysicsExpr

physics_notes()[source]

Return declared Duffing-approximation validity notes.

Return type:

list[str]