quchip.devices.resonator

Linear-resonator device model.

Hamiltonian:

\[H = \omega \, \hat{n}\]

where \(\hat{n} = a^\dagger a\) is the Fock-basis number operator and \(\omega\) is the bare cavity frequency.

Approximation

Strictly harmonic / non-interacting: no Kerr, no cross-Kerr, no drive backaction beyond what couplings/drives themselves introduce. This is the ideal cavity / transmission-line-resonator mode — suitable for readout cavities, filter modes, photonic oscillators, and cavity-QED benchmarks where anharmonicity is either absent or modelled separately. For Kerr / anharmonic cavities, use a device that owns an explicit (K/2) n(n-1) term (see examples/kerr_cat_qubit.py).

Optional dissipation

Passing quality_factor = Q adds a single photon-loss collapse operator sqrt(kappa) a with \(\kappa = 2\pi\,f/Q\) (angular decay rate, rad/ns).

Quality-factor convention (physics, not a unit conversion). quality_factor is defined against the ordinary frequency freq (GHz) carried by this class. The resulting decay rate is \(\kappa = 2\pi\,f/Q\) (angular, rad/ns). The \(2\pi\) here is intrinsic to the physical definition of Q — not an ordinary→angular units conversion bolted on at the engine boundary. Concretely, Q counts cycles of the ordinary oscillation per e-folding of energy, so energy decays as \(e^{-t/\tau} = e^{-\kappa t}\) with \(\kappa = \omega/Q = 2\pi f/Q\). For this reason the \(2\pi\) lives in the resonator’s photon-loss noise channel and must not be moved to the units boundary in stage2_assembly.py.

Noise hooks inherited from BaseDevice (T1, T2, thermal_population) produce the Lindblad channels described in that base class. For circuit-QED conventions see Krantz et al., Applied Physics Reviews 6, 021318 (2019), §V.

References

  • Walls & Milburn, Quantum Optics, 2nd ed. (Springer, 2008), Ch. 7.

  • Blais, Grimsmo, Girvin & Wallraff, Circuit quantum electrodynamics, Reviews of Modern Physics 93, 025005 (2021).

Example

>>> from quchip.chip import Chip
>>> from quchip.devices import Resonator
>>> r = Resonator(freq=7.2, levels=6, label="readout")
>>> chip = Chip(devices=[r])
>>> r.freq, r.levels
(7.2, 6)

Classes

Resonator(freq[, quality_factor, levels, ...])

Linear microwave / photonic resonator — pure harmonic oscillator.

class quchip.devices.resonator.Resonator(freq, quality_factor=None, *, levels=10, label=None, T1=None, T2=None, thermal_population=None)[source]

Bases: DeviceModel

Linear microwave / photonic resonator — pure harmonic oscillator.

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

  • quality_factor (float | None, optional) – Loaded Q, defined against the ordinary frequency freq (GHz). When set, adds a photon-loss Lindblad channel sqrt(2*pi*freq/Q) a — i.e. decay rate kappa = 2*pi*freq/Q (angular, rad/ns). The 2*pi here is part of the physical definition of Q (energy e-folds per ordinary cycle divided by Q), not a units-boundary conversion. Must be positive. Like every noise parameter it may be set — or cleared with None — after construction; the next simulate reflects the current value.

  • levels (int, default 10) – Fock-space truncation. Choose comfortably above the maximum expected photon occupation.

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

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

Example

>>> from quchip.devices import Resonator
>>> r = Resonator(freq=7.2, quality_factor=10_000, levels=8)
>>> len(r.collapse_operators()) >= 1
True
tunable_param_names = ('freq',)

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").

freq: Scalar = Parameter(default=<object object>, positive=True, nonnegative=False, serialize=True, unit='GHz')
quality_factor: Scalar = Parameter(default=None, positive=True, nonnegative=False, serialize=True, unit=None)
approximation = 'Linear harmonic oscillator with no Kerr or cross-Kerr self-interaction.'

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.

local_hamiltonian(op)[source]

Return the harmonic oscillator Hamiltonian H = freq * n.

Parameters:

op (LocalOps)

Return type:

PhysicsExpr

physics_notes()[source]

Return declared harmonic-oscillator and dissipation assumptions.

Return type:

list[str]

intrinsic_decay_rate()[source]

Combined lowering-channel rate: κ = 2π·freq/Q photon loss plus the thermal-emission rate.

Both quality_factor and T1/thermal_population build independent lowering-operator collapse channels on this device (the photon_loss NoiseChannel, a pure loss channel unaffected by thermal_population, and the inherited thermal-emission channel — see intrinsic_decay_rate() for its (n̄+1)/T1 / n̄+1 formulas); this hook reports their summed rate rather than either alone, so a caller reading one scalar decay rate (e.g. an adiabatic-elimination Purcell fold) does not under-count decay when both are set. None only when neither is set.

Return type:

Any | None