qtcad.device.epr module
EPR analysis of Maxwell eigenmodes.
This analysis starts from Maxwell eigenmodes computed with linearized Josephson junctions represented as lumped inductors. It extracts the linear quantities needed for EPR quantization, including energy participations, mode energies, and phase-aligned currents.
The extracted linear data are then used to compute superconducting-circuit Hamiltonian parameters, including dressed mode frequencies, Kerr coefficients, and zero-point fluctuations.
- Reference:
Minev, Zlatko K., et al. “Energy-participation quantization of Josephson circuits.” npj Quantum Information 7.1 (2021): 131.
- class DielectricSpec(region: str, loss_tangent: float | None = None)
Bases:
DielectricSpecDescribe a volume dielectric region for EPR loss analysis.
- Attributes:
region – Name of the QTCAD volume region. The region must be available to
qtcad.device.Device.energy_e().loss_tangent – Optional dielectric loss tangent. If provided, the analysis computes \(Q = 1 / (p\,\mathrm{loss\_tangent})\) for each mode.
- loss_tangent: float | None = None
- region: str
- class EPRAnalysis(device: Device, junctions: Sequence[JunctionSpec] | JunctionSpec, modes: Sequence[int] | None = None, renormalize: bool = True, phase_reference: str | int = 'largest_current', balance_warn_threshold: float = 0.05, dielectrics: Sequence[DielectricSpec] | DielectricSpec | None = None, surface_dielectrics: Sequence[SurfaceDielectricSpec] | SurfaceDielectricSpec | None = None)
Bases:
EPRAnalysisCompute the EPR result from the solved Maxwell eigenmodes.
solvecomputes the linear EPR quantities (mode energies, junction energies, participation, signs, currents, and voltages) and the Hamiltonian quantities (dressed frequencies, Kerr coefficients, and zero-point fluctuations).The key formulas are:
\(E_j = 0.25 L_j |I_{mj}|^2\)
\(E_\mathrm{ind} = E_b + \sum_j E_j\)
\(E_\mathrm{cap} = E_e\)
\(p^\mathrm{raw}_{mj} = E_j / E_\mathrm{ind}\)
Here, \(E_j\) is the lumped inductive energy stored in junction \(j\) by mode \(m\), \(L_j\) is the junction inductance, \(I_{mj}\) is the phase-aligned junction current, \(E_b\) is the distributed magnetic-field energy, and \(E_e\) is the distributed electric-field energy.
- Attributes:
device – Device containing a solved Maxwell eigenmode result.
junctions – Junction specifications included in the EPR analysis.
modes – Maxwell mode indices included in the analysis. If
None, all solved modes are used.renormalize – Whether to rescale each mode’s junction participation row to match the expected total junction inductive participation.
phase_reference – Junction used to fix each mode’s arbitrary global phase. This may be
"largest_current", a junction boundary name, or a junction index.balance_warn_threshold – Relative capacitive/inductive energy-imbalance threshold above which a warning is emitted. The default
0.05means a 5% mismatch. It is a warning-only diagnostic chosen to flag modes whose energy balance is visibly poor.dielectrics – Volume dielectric regions included in the electric participation and quality-factor analysis.
surface_dielectrics – Thin surface dielectric specifications included in the electric-field participation and dielectric-loss quality-factor analysis.
result – Complete
EPRResultproduced bysolve(), orNonebefore the analysis is solved.
- __init__(device: Device, junctions: Sequence[JunctionSpec] | JunctionSpec, modes: Sequence[int] | None = None, renormalize: bool = True, phase_reference: str | int = 'largest_current', balance_warn_threshold: float = 0.05, dielectrics: Sequence[DielectricSpec] | DielectricSpec | None = None, surface_dielectrics: Sequence[SurfaceDielectricSpec] | SurfaceDielectricSpec | None = None)
Instantiate an EPR analysis.
- Parameters:
device – Device for which the Maxwell eigenmode solver has already been run.
junctions – One junction specification or a sequence of them.
modes – Maxwell mode indices to analyze. If
None, all solved modes are used.renormalize – Whether to rescale each mode’s junction participation row to match the expected total junction inductive participation.
phase_reference – Rule used to fix the current phase before extracting signs. Default:
"largest_current".balance_warn_threshold – Relative capacitive/inductive energy-imbalance threshold above which a warning is emitted. The default
0.05means a 5% mismatch. It is a warning-only diagnostic chosen to flag modes whose energy balance is visibly poor.dielectrics – Optional volume dielectric region specifications for electric participation and quality-factor analysis.
surface_dielectrics – Optional thin surface dielectric layer specifications for electric participation and quality-factor analysis.
- solve() EPRResult
Compute the EPR result from the solved Maxwell eigenmodes.
- Returns:
The complete
EPRResult, including energy participations, mode energies, phase-aligned currents, dressed mode frequencies, Kerr coefficients, and zero-point fluctuations.- Raises:
RuntimeError – If required Maxwell frequencies, fields, or inductor currents are missing from the device.
ValueError – If the perturbation order, requested modes, or junction data are invalid.
- class EPRResult(junctions: tuple[~qtcad.device.epr.JunctionSpec, ...], junction_inductances: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]], mode_indices: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.int64]], mode_frequencies: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], participation_raw: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], participation: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], signs: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.int64]], currents: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], voltages: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], electric_energy: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], magnetic_energy: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], junction_energy: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], inductive_energy: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], capacitive_energy: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], energy_imbalance: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]], current_phases: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], bare_frequencies: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], detuning: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], lamb_shift: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], dressed_frequencies: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], chi_raw: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], chi: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], anharmonicity: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], cross_kerr: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], phi_zpf: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]], ej_over: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]], dielectrics: tuple[~qtcad.device.epr.DielectricSpec, ...] = <factory>, dielectric_energy: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]] = <factory>, dielectric_participation: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]] = <factory>, dielectric_quality_factors: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] = <factory>, surface_dielectrics: tuple[~qtcad.device.epr.SurfaceDielectricSpec, ...] = <factory>, surface_dielectric_energy: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]] = <factory>, surface_dielectric_participation: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.complex128]] = <factory>, surface_dielectric_quality_factors: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] = <factory>, mode_quality_factors: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] = <factory>, metadata: dict[str, ~typing.Any] = <factory>)
Bases:
EPRResultStore complete EPR and Hamiltonian data extracted from Maxwell modes.
- Shape convention:
M,J,D, andSare shape symbols used in this docstring, not class attributes.Mis the number of selected Maxwell modes,Jis the number of junction boundaries,Dis the number of volume dielectric regions, andSis the number of thin surface dielectric layers included in the EPR analysis.Index
mselects a mode entry in 1D arrays such asmode_indices[m]and selects rowmin mode-indexed matrices such asparticipation[m, :]. The Maxwell mode number represented by rowmismode_indices[m].Index
jselects a junction entry in 1D arrays such asjunctions[j]and selects columnjin mode-by-junction matrices such asparticipation[:, j]. Indexdsimilarly selects a volume dielectric entry and column in(M, D)arrays, while indexsselects a surface dielectric entry and column in(M, S)arrays.
- Attributes:
junctions – Junction specifications used in the analysis.
junction_inductances – Junction inductances resolved from the device, with shape
(J,).mode_indices – Indices of the Maxwell modes included in the result, with shape
(M,).mode_frequencies – Bare Maxwell eigenfrequencies in hertz, with shape
(M,).participation_raw – Raw current-based participation, \(E_j / E_\mathrm{ind}\), where \(E_j\) is the lumped inductive energy stored in junction \(j\) and \(E_\mathrm{ind}\) is the total inductive energy of the mode, with shape
(M, J).participation – Participation matrix used for Hamiltonian analysis, with the same shape as
participation_raw.signs – Lossless-compatibility sign matrix extracted from phase-aligned junction currents, with the same shape as
participation_raw.currents – Complex junction currents for each mode and junction, with the same shape as
participation_raw.voltages – Junction voltages, computed from \(V_j = i\,2\pi f_m L_j I_j\), with the same shape as
participation_raw. Here, \(f_m\) is the mode frequency, \(L_j\) is the junction inductance, and \(I_j\) is the junction current.This is the frequency-domain inductor phasor relation \(V = i\omega L I\), matching QTCAD’s inductor-current extraction convention \(I = V / (i\omega L)\).
In lossless workflows that use voltage magnitudes, the factor of
ionly changes the stored phase.electric_energy – Electric energy in joules for each mode (i.e. the energy stored in the electric field, excluding any lumped elements), with shape
(M,). This can be complex for lossy eigenmodes.magnetic_energy – Magnetic energy in joules for each mode (i.e. the energy stored in the magnetic field, excluding any lumped elements), with shape
(M,). This can be complex for lossy eigenmodes.junction_energy – Junction inductive energy in joules for each mode (i.e. the kinetic energy stored in the lumped inductor representing the Josephson junction) and junction, with the same shape as
participation_raw.inductive_energy – Total inductive energy in joules, \(E_b + \sum_j E_j\), where \(E_b\) is the distributed magnetic-field energy and \(E_j\) is the lumped junction inductive energy, with shape
(M,).capacitive_energy – Total capacitive energy \(E_e\) in joules, with shape
(M,). It is computed from the distributed electric-field energy; lumped capacitive contributions are not considered.dielectrics – Volume dielectric region specifications used for electric participation and quality-factor analysis. Column
din the dielectric arrays corresponds todielectrics[d].dielectric_energy – Electric energy in joules stored in each requested volume dielectric region, with shape
(M, D).dielectric_participation – Electric-energy participation ratio for each requested volume dielectric region, \(E_\mathrm{dielectric} / E_\mathrm{cap}\), with shape
(M, D).dielectric_quality_factors – Per-region dielectric-loss-limited quality factors, with shape
(M, D). Entries arenp.infwhen a dielectric has no loss tangent or zero loss participation.surface_dielectrics – Thin surface dielectric specifications used for electric participation and quality-factor analysis. For a surface dielectric index
s, columnsin arrays with shape(M, S)corresponds tosurface_dielectrics[s].surface_dielectric_energy – Electric energy in joules stored in each requested thin surface dielectric layer, with shape
(M, S). This uses the thin-film approximation \(0.25\,\epsilon_0\epsilon_r t\int_\mathrm{surface} \vec{E}^*\cdot\vec{E}\,dA\), where the integrand reduces to \(|\vec{E}|^2\) for real fields.surface_dielectric_participation – Electric-energy participation ratio for each requested thin surface dielectric layer, with shape
(M, S).surface_dielectric_quality_factors – Per-surface dielectric-loss-limited quality factors, with shape
(M, S). Entries arenp.infwhen a surface dielectric has no loss tangent or zero loss participation.mode_quality_factors – Total dielectric-loss-limited quality factor for each mode, combining all provided volume and surface dielectric losses. Entries are
np.infwhen no lossy dielectric specifications are supplied.energy_imbalance – Absolute relative mismatch between capacitive and inductive energies, \(|E_\mathrm{cap} - E_\mathrm{ind}| / [0.5(|E_\mathrm{cap}| + |E_\mathrm{ind}|)]\), with shape
(M,).current_phases – Complex relative current phase factors extracted after mode-level phase alignment, with the same shape as
participation_raw. For lossless modes this reduces tosigns.bare_frequencies – Bare linear mode frequencies in hertz, with shape
(M,). This is equal tomode_frequenciesand is stored under the Hamiltonian naming convention for readability.detuning – Pairwise bare-mode frequency differences in hertz, with shape
(M, M). Entrydetuning[m, n]is \(\Delta_{mn} = f_m - f_n\), where \(f_m\) is the frequency of row modemand \(f_n\) is the frequency of column moden. The matrix is antisymmetric:detuning[m, n] = -detuning[n, m].lamb_shift – Leading-order Lamb shift \(\Delta_m\) in hertz, with shape
(M,).From Eq. (B.9) of [1]’s supplementary material, \(\Delta_m = 0.5\sum_n \chi^\mathrm{raw}_{mn}\). The effective Hamiltonian subtracts this shift from the bare frequency.
dressed_frequencies – First-order dressed mode frequencies in hertz, with shape
(M,).These are the bare frequencies shifted by the leading-order Lamb shift from Eq. (B.9) of [1]’s supplementary material. In other words,
dressed_frequenciesequalsbare_frequenciesminus \(0.5\sum_n \chi^\mathrm{raw}_{mn}\). The minus sign comes from the effective Hamiltonian in Eq. (B.2), where the Lamb-shift term appears as \(-h\Delta_m a_m^\dagger a_m\).chi_raw – Leading-order Kerr matrix in hertz units before any post-processing of the diagonal, with shape
(M, M).This is the matrix that corresponds most directly to Eq. (B.6) of [1]’s supplementary material, rewritten from angular frequencies to hertz. Its full row sum is what enters Eq. (B.9).
chi – Kerr matrix, with shape
(M, M).anharmonicity – Anharmonicity magnitude, \(-\mathrm{diag}(\chi)\), with shape
(M,).cross_kerr – Off-diagonal part of \(\chi\), with shape
(M, M).phi_zpf – Reduced-flux zero-point fluctuations, with shape
(M, J).ej_over – Josephson energies divided by Planck’s constant, with shape
(J,).metadata – Cached intermediate matrices. The current implementation stores
frequency_matrixwith shape(M, M)andinverse_ej_overwith shape(J, J).
- anharmonicity: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- bare_frequencies: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- capacitive_energy: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- chi: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- chi_raw: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- cross_kerr: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- current_phases: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- currents: ndarray[tuple[Any, ...], dtype[complex128]]
- detuning: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- dielectric_energy: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- dielectric_participation: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- dielectric_quality_factors: ndarray[tuple[Any, ...], dtype[float64]]
- dielectrics: tuple[DielectricSpec, ...]
- dressed_frequencies: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- ej_over: ndarray[tuple[Any, ...], dtype[float64]]
- electric_energy: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- energy_imbalance: ndarray[tuple[Any, ...], dtype[float64]]
- inductive_energy: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- junction_energy: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- junction_inductances: ndarray[tuple[Any, ...], dtype[float64]]
- junctions: tuple[JunctionSpec, ...]
- lamb_shift: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- magnetic_energy: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- metadata: dict[str, Any]
- mode_frequencies: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- mode_indices: ndarray[tuple[Any, ...], dtype[int64]]
- mode_quality_factors: ndarray[tuple[Any, ...], dtype[float64]]
- participation: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- participation_raw: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- phi_zpf: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- signs: ndarray[tuple[Any, ...], dtype[int64]]
- surface_dielectric_energy: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- surface_dielectric_participation: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[Any, ...], dtype[complex128]]
- surface_dielectric_quality_factors: ndarray[tuple[Any, ...], dtype[float64]]
- surface_dielectrics: tuple[SurfaceDielectricSpec, ...]
- voltages: ndarray[tuple[Any, ...], dtype[complex128]]
- class JunctionSpec(boundary: str)
Bases:
JunctionSpecIdentify a Josephson junction boundary.
- Attributes:
boundary – Name of the QTCAD inductor boundary. This should match the corresponding physical-group label in the mesh file.
- boundary: str
- class SurfaceDielectricSpec(surface: str, thickness: float, relative_permittivity: float, loss_tangent: float | None = None)
Bases:
SurfaceDielectricSpecDescribe one thin dielectric loss layer on a QTCAD surface.
- Attributes:
surface – Name of the QTCAD boundary/surface over which \(|\vec{E}|^2\) is integrated.
thickness – Physical thickness of the thin dielectric layer in meters.
relative_permittivity – Relative permittivity of the thin dielectric layer.
loss_tangent – Optional surface dielectric loss tangent. If provided, the analysis computes \(Q = 1 / (p\,\mathrm{loss\_tangent})\) for each mode.
- loss_tangent: float | None = None
- relative_permittivity: float
- surface: str
- thickness: float