Coverage for qpdk / models / perturbation.py: 86%

36 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-14 10:27 +0000

1r"""Perturbation theory helpers for superconducting quantum circuits. 

2 

3This module provides helper functions for computing effective Hamiltonians 

4and energy corrections using quasi-degenerate perturbation theory via 

5`pymablock <https://pymablock.readthedocs.io/>`_ 

6:cite:`arayaDayPymablockAlgorithmPackage2025`. 

7 

8The primary application is computing the **dispersive shift** :math:`\chi` 

9of a resonator coupled to a transmon qubit, which is the key quantity for 

10dispersive readout of superconducting qubits 

11:cite:`blaisCircuitQuantumElectrodynamics2021,kochChargeinsensitiveQubitDesign2007a`. 

12 

13The transmon-resonator Hamiltonian (without the rotating wave approximation) 

14is: 

15 

16.. math:: 

17 

18 \mathcal{H} = -\omega_t\, a_t^\dagger a_t 

19 + \frac{\alpha}{2}\, a_t^{\dagger 2} a_t^2 

20 + \omega_r\, a_r^\dagger a_r 

21 - g\,(a_t^\dagger - a_t)(a_r^\dagger - a_r) 

22 

23where :math:`\omega_t` is the transmon frequency, :math:`\omega_r` the resonator 

24frequency, :math:`\alpha` the anharmonicity, and :math:`g` the coupling strength. 

25 

26References: 

27 - :cite:`arayaDayPymablockAlgorithmPackage2025` 

28 - :cite:`blaisCircuitQuantumElectrodynamics2021` 

29 - :cite:`kochChargeinsensitiveQubitDesign2007a` 

30""" 

31 

32from __future__ import annotations 

33 

34from functools import partial 

35 

36import jax 

37import jax.numpy as jnp 

38import sympy 

39from jax.typing import ArrayLike 

40from sympy.physics.quantum import Dagger 

41from sympy.physics.quantum.boson import BosonOp 

42 

43 

44def transmon_resonator_hamiltonian() -> tuple[ 

45 sympy.Expr, sympy.Expr, tuple[sympy.Symbol, ...] 

46]: 

47 r"""Build the symbolic transmon-resonator Hamiltonian. 

48 

49 Constructs the unperturbed (:math:`H_0`) and perturbation (:math:`H_p`) 

50 parts of the transmon-resonator Hamiltonian using bosonic operators. 

51 

52 The Hamiltonian is split as :math:`H = H_0 + H_p` where: 

53 

54 .. math:: 

55 

56 \begin{aligned} 

57 H_0 &= -\omega_t\, a_t^\dagger a_t 

58 + \frac{\alpha}{2}\, a_t^{\dagger 2} a_t^2 

59 + \omega_r\, a_r^\dagger a_r \\ 

60 H_p &= -g\,(a_t^\dagger - a_t)(a_r^\dagger - a_r) 

61 \end{aligned} 

62 

63 Returns: 

64 A tuple ``(H_0, H_p, symbols)`` where ``symbols`` is 

65 ``(omega_t, omega_r, alpha, g)``. 

66 

67 Example: 

68 >>> H_0, H_p, (omega_t, omega_r, alpha, g) = transmon_resonator_hamiltonian() 

69 """ 

70 omega_t, omega_r, alpha, g = sympy.symbols( 

71 r"\omega_{t} \omega_{r} \alpha g", real=True, positive=True 

72 ) 

73 

74 a_t, a_r = BosonOp("a_t"), BosonOp("a_r") 

75 

76 H_0 = ( 

77 -omega_t * Dagger(a_t) * a_t 

78 + omega_r * Dagger(a_r) * a_r 

79 + alpha * Dagger(a_t) ** 2 * a_t**2 / 2 

80 ) 

81 

82 H_p = -g * (Dagger(a_t) - a_t) * (Dagger(a_r) - a_r) 

83 

84 return H_0, H_p, (omega_t, omega_r, alpha, g) 

85 

86 

87@partial(jax.jit, inline=True) 

88def dispersive_shift( 

89 ω_t_ghz: float | ArrayLike, 

90 ω_r_ghz: float | ArrayLike, 

91 α_ghz: float | ArrayLike, 

92 g_ghz: float | ArrayLike, 

93) -> float | jax.Array: 

94 r"""Compute the dispersive shift numerically. 

95 

96 Evaluates the second-order dispersive shift for a transmon coupled 

97 to a resonator. Uses the analytical formula derived from perturbation 

98 theory (without the rotating wave approximation) 

99 :cite:`kochChargeinsensitiveQubitDesign2007a,blaisCircuitQuantumElectrodynamics2021`: 

100 

101 .. math:: 

102 

103 \chi = \frac{2g^2}{\Delta - \alpha} 

104 - \frac{2g^2}{\Delta} 

105 - \frac{2g^2}{\omega_t + \omega_r + \alpha} 

106 + \frac{2g^2}{\omega_t + \omega_r} 

107 

108 where :math:`\Delta = \omega_t - \omega_r`. The first two terms give 

109 the rotating-wave-approximation (RWA) contribution 

110 

111 .. math:: 

112 

113 \chi_\text{RWA} = \frac{2 \alpha g^2}{\Delta(\Delta - \alpha)} 

114 

115 and the last two are corrections from the counter-rotating terms. 

116 

117 All parameters are in GHz, and the returned value is also in GHz. 

118 

119 Args: 

120 ω_t_ghz: Transmon frequency in GHz. 

121 ω_r_ghz: Resonator frequency in GHz. 

122 α_ghz: Transmon anharmonicity in GHz (positive value). 

123 g_ghz: Coupling strength in GHz. 

124 

125 Returns: 

126 Dispersive shift :math:`\chi` in GHz. 

127 

128 Example: 

129 >>> χ = dispersive_shift(5.0, 7.0, 0.2, 0.1) 

130 >>> print(f"χ = {χ * 1e3:.2f} MHz") 

131 """ 

132 Δ = ω_t_ghz - ω_r_ghz 

133 

134 # Full expression including counter-rotating terms 

135 return ( 

136 2 * g_ghz**2 / (Δ - α_ghz) 

137 - 2 * g_ghz**2 / Δ 

138 - 2 * g_ghz**2 / (ω_t_ghz + ω_r_ghz + α_ghz) 

139 + 2 * g_ghz**2 / (ω_t_ghz + ω_r_ghz) 

140 ) 

141 

142 

143@partial(jax.jit, inline=True) 

144def dispersive_shift_to_coupling( 

145 χ_ghz: float | ArrayLike, 

146 ω_t_ghz: float | ArrayLike, 

147 ω_r_ghz: float | ArrayLike, 

148 α_ghz: float | ArrayLike, 

149) -> float | jax.Array: 

150 r"""Compute the coupling strength from a target dispersive shift. 

151 

152 Inverts the dispersive shift relation to find the coupling strength 

153 :math:`g` required to achieve a desired :math:`\chi`. Uses only the 

154 dominant rotating-wave term 

155 :cite:`kochChargeinsensitiveQubitDesign2007a`: 

156 

157 .. math:: 

158 

159 g \approx \sqrt{\frac{-\chi\,\Delta\,(\Delta - \alpha)}{2\alpha}} 

160 

161 where :math:`\Delta = \omega_t - \omega_r`. 

162 

163 Note: 

164 The expression under the square root may be negative when the 

165 sign of the target :math:`\chi` is inconsistent with the detuning 

166 and anharmonicity (e.g., positive :math:`\chi` with 

167 :math:`\Delta < 0`). In that case the absolute value is taken 

168 so that the returned coupling strength is always real and 

169 non-negative, but the caller should verify self-consistency 

170 via :func:`dispersive_shift`. 

171 

172 Args: 

173 χ_ghz: Target dispersive shift in GHz (typically negative). 

174 ω_t_ghz: Transmon frequency in GHz. 

175 ω_r_ghz: Resonator frequency in GHz. 

176 α_ghz: Transmon anharmonicity in GHz (positive value; 

177 the physical anharmonicity of a transmon is negative, but 

178 following the Hamiltonian convention used throughout this 

179 module, :math:`\alpha` is taken as positive). 

180 

181 Returns: 

182 Coupling strength :math:`g` in GHz. 

183 

184 Example: 

185 >>> g = dispersive_shift_to_coupling(-0.001, 5.0, 7.0, 0.2) 

186 >>> print(f"g = {g * 1e3:.1f} MHz") 

187 """ 

188 Δ = ω_t_ghz - ω_r_ghz 

189 g_squared = -χ_ghz * Δ * (Δ - α_ghz) / (2 * α_ghz) 

190 return jnp.sqrt(jnp.abs(g_squared)) 

191 

192 

193@partial(jax.jit, inline=True) 

194def ej_ec_to_frequency_and_anharmonicity( 

195 ej_ghz: float | ArrayLike, ec_ghz: float | ArrayLike 

196) -> tuple[float | jax.Array, float | jax.Array]: 

197 r"""Convert :math:`E_J` and :math:`E_C` to qubit frequency and anharmonicity. 

198 

199 Uses the standard transmon approximations 

200 :cite:`kochChargeinsensitiveQubitDesign2007a`: 

201 

202 .. math:: 

203 

204 \begin{aligned} 

205 \omega_q &\approx \sqrt{8 E_J E_C} - E_C \\ 

206 \alpha &\approx E_C 

207 \end{aligned} 

208 

209 Note: 

210 The physical anharmonicity of a transmon is *negative* 

211 (:math:`\alpha = -E_C`), but the Hamiltonian convention used 

212 in this module and in pymablock takes :math:`\alpha` as positive. 

213 

214 Args: 

215 ej_ghz: Josephson energy in GHz. 

216 ec_ghz: Charging energy in GHz. 

217 

218 Returns: 

219 Tuple of ``(ω_q_ghz, α_ghz)``. 

220 

221 Example: 

222 >>> ω_q, α = ej_ec_to_frequency_and_anharmonicity(20.0, 0.2) 

223 >>> print(f"ω_q = {ω_q:.2f} GHz, α = {α:.1f} GHz") 

224 """ 

225 return jnp.sqrt(8 * ej_ghz * ec_ghz) - ec_ghz, ec_ghz 

226 

227 

228@partial(jax.jit, inline=True) 

229def purcell_decay_rate( 

230 g_ghz: float | ArrayLike, 

231 ω_t_ghz: float | ArrayLike, 

232 ω_r_ghz: float | ArrayLike, 

233 κ_ghz: float | ArrayLike, 

234) -> float | jax.Array: 

235 r"""Estimate the Purcell decay rate of a transmon through a resonator. 

236 

237 The Purcell effect limits qubit lifetime when coupled to a lossy 

238 resonator. In the dispersive regime 

239 :cite:`houckControllingSpontaneousEmission2008,blaisCircuitQuantumElectrodynamics2021`: 

240 

241 .. math:: 

242 

243 \gamma_\text{Purcell} = \kappa \left(\frac{g}{\Delta}\right)^2 

244 

245 where :math:`\kappa` is the resonator decay rate and 

246 :math:`\Delta = \omega_t - \omega_r`. 

247 

248 Args: 

249 g_ghz: Coupling strength in GHz. 

250 ω_t_ghz: Transmon frequency in GHz. 

251 ω_r_ghz: Resonator frequency in GHz. 

252 κ_ghz: Resonator linewidth (decay rate) in GHz. 

253 

254 Returns: 

255 Purcell decay rate in GHz. 

256 

257 Example: 

258 >>> γ = purcell_decay_rate(0.1, 5.0, 7.0, 0.001) 

259 >>> T_purcell = 1 / (γ * 1e9) 

260 >>> print(f"T_Purcell = {T_purcell * 1e6:.0f} µs") 

261 """ 

262 Δ = ω_t_ghz - ω_r_ghz 

263 return κ_ghz * (g_ghz / Δ) ** 2 

264 

265 

266@partial(jax.jit, inline=True) 

267def resonator_linewidth_from_q( 

268 ω_r_ghz: float | ArrayLike, q_ext: float | ArrayLike 

269) -> float | jax.Array: 

270 r"""Compute resonator linewidth from external quality factor. 

271 

272 Converts external quality factor to linewidth (half-linewidth at half-maximum) 

273 :cite:`gopplCoplanarWaveguideResonators2008a,m.pozarMicrowaveEngineering2012`: 

274 

275 .. math:: 

276 

277 \kappa = \frac{\omega_r}{Q_\text{ext}} 

278 

279 Args: 

280 ω_r_ghz: Resonator frequency in GHz. 

281 q_ext: External quality factor. 

282 

283 Returns: 

284 Resonator linewidth :math:`\kappa` in GHz. 

285 

286 Example: 

287 >>> κ = resonator_linewidth_from_q(7.0, 10_000) 

288 >>> print(f"κ = {κ * 1e6:.1f} kHz") 

289 """ 

290 return ω_r_ghz / q_ext 

291 

292 

293@partial(jax.jit, inline=True) 

294def measurement_induced_dephasing( 

295 χ_ghz: float | ArrayLike, κ_ghz: float | ArrayLike, n_bar: float | ArrayLike 

296) -> float | jax.Array: 

297 r"""Estimate measurement-induced dephasing rate. 

298 

299 During dispersive readout, photons in the resonator cause 

300 additional dephasing of the qubit 

301 :cite:`gambettaQubitphotonInteractionsCavity2006,blaisCircuitQuantumElectrodynamics2021`: 

302 

303 .. math:: 

304 

305 \Gamma_\phi = \frac{8 \chi^2 \bar{n}}{\kappa} 

306 

307 where :math:`\bar{n}` is the mean photon number in the resonator. 

308 

309 Args: 

310 χ_ghz: Dispersive shift in GHz. 

311 κ_ghz: Resonator linewidth in GHz. 

312 n_bar: Mean photon number in the resonator during measurement. 

313 

314 Returns: 

315 Measurement-induced dephasing rate in GHz. 

316 

317 Example: 

318 >>> Γ_φ = measurement_induced_dephasing(-0.001, 0.001, 5.0) 

319 >>> print(f"Γ_φ = {Γ_φ * 1e6:.1f} kHz") 

320 """ 

321 return 8 * χ_ghz**2 * n_bar / κ_ghz