Systems
A System is an object that contains one or more Modes, defines the coupling between them, and generates the drift (time-independent) Hamiltonian in the Hilbert space consisting of all of its Modes
, or any subset of them.
The Hilbert space used in generating the drift Hamiltonian is determined by the list system.active_modes
, the elements of which must all be in system.modes
. Upon initialization, system.active_modes
is set to be equal to system.modes
.
Setting system.active_modes = list_of_modes
automatically updates the space
for each Mode
in list_of_modes
to be equal to list_of_modes
, so that each Mode
is now aware of the Hilbert space in which it exists.
[1]:
%config InlineBackend.figure_formats = ['svg']
%matplotlib inline
import inspect
import numpy as np
import qutip
from sequencing import Transmon, Cavity, System, CouplingTerm
[2]:
qubit = Transmon('qubit', levels=3, kerr=-200e-3)
cavity = Cavity('cavity', levels=10, kerr=-10e-6)
print('Before system initialization:')
for mode in [qubit, cavity]:
print(f'\t{mode.name}.space is', [m.name for m in mode.space])
print(f'\t{mode.name} Hilbert space dimension is', mode.I.dims)
system = System('system', modes=[qubit, cavity])
print('\nAfter system initialization:')
print(f'\t{system.name}.active_modes is', [m.name for m in system.active_modes])
print(f'\t{system.name} Hilbert space dimension is', system.I().dims)
for mode in [qubit, cavity]:
print(f'\t{mode.name}.space is', [m.name for m in mode.space])
print(f'\t{mode.name} Hilbert space dimension is', mode.I.dims)
Before system initialization:
qubit.space is ['qubit']
qubit Hilbert space dimension is [[3], [3]]
cavity.space is ['cavity']
cavity Hilbert space dimension is [[10], [10]]
After system initialization:
system.active_modes is ['qubit', 'cavity']
system Hilbert space dimension is [[3, 10], [3, 10]]
qubit.space is ['qubit', 'cavity']
qubit Hilbert space dimension is [[3, 10], [3, 10]]
cavity.space is ['qubit', 'cavity']
cavity Hilbert space dimension is [[3, 10], [3, 10]]
Using a subset of the full system space
Systems
have a method called System.use_modes()
, which is a contextmanager that allows you to temporarily set system.active_modes
to some subset of system.modes
and then automatically revert the state of the system
when you are done.
[3]:
print('Using full system space:')
print(system.I().dims)
for mode in ['qubit', 'cavity']:
with system.use_modes([mode]):
print(f'\nUsing just the {mode} subspace:')
print(system.I().dims)
print('\nUsing full system space (again):')
print(system.I().dims)
Using full system space:
[[3, 10], [3, 10]]
Using just the qubit subspace:
[[3], [3]]
Using just the cavity subspace:
[[10], [10]]
Using full system space (again):
[[3, 10], [3, 10]]
Coupling Modes
together
Couplings between Modes
are defined in the dictionary system.coupling_terms
, the keys of which are of the form frozenset({mode0_name, mode1_name})
(the mode order does not matter here), and the values of which are a list of CouplingTerm objects. A list of operators representing all multi-mode couplings in the system is returned by System.couplings()
.
Cross-Kerrs, which are proportional to mode1.n * mode2.n
for two distinct Modes
, can be defined using the method System.set_cross_kerr()
.
[4]:
print('class CouplingTerm:')
print('\n\t'.join([''] + inspect.getdoc(CouplingTerm).split('\n')))
class CouplingTerm:
An object representing a coupling between multiple ``Modes``,
given by a Hamiltonian term of the form ``strength * product(operators)``.
If the keyword argument ``add_hc`` is provided and is True,
then the Hamiltonian term takes the form
``strength * (product(operators) + product(operators).dag())``.
Args:
terms (list[tuple[Mode, str]]): List of tuples of ``(mode, expr)``,
which defines the coupling. Each ``expr`` is a string containing an
algebraic expression involving the Mode's operators.
See :func:`Mode.operator_expr` for more details.
The resulting operators are given by ``mode.operator_expr(expr)``.
strength (optional, float): Coefficient parameterizing the
strength of the coupling. Strength should be given in
units of 2 * pi * GHz. Default: 1.
add_hc (optional, bool): Whether to add the Hermitian conjugate
of the product of the operators. Default: False.
[5]:
system.set_cross_kerr(qubit, cavity, chi=-2e-3)
print('Cross-Kerrs (in GHz):\n\t', system.cross_kerrs)
print('Coupling terms (strength in 2 * pi * GHz):\n\t', dict(system.coupling_terms))
display(system.couplings()[0])
Cross-Kerrs (in GHz):
{frozenset({'qubit', 'cavity'}): -0.002}
Coupling terms (strength in 2 * pi * GHz):
{frozenset({'qubit', 'cavity'}): [CouplingTerm([(qubit, 'n'), (cavity, 'n')], strength=-1.257e-02, add_hc=False)]}
Drift Hamiltonian
The system time-indenependent (drift) Hamiltonian includes the self-Kerr (anharmonicity) of each mode, the detuning of each mode relative to the frame in which its operators are defined, and all couplings between modes. The method System.H0()
returns all of these operators in a list, which can be summed to get the full drift Hamiltonian operator. By default, System.H0()
returns a list containing only those operators which have nonzero elements, but the full list of operators can be
returned by using the keyword argument clean=False
.
Similarly, the method System.c_ops()
returns a list of all operators representing loss and dephasing of all modes.
[6]:
len(system.H0()) == 3
# [qubit.self_kerr, cavity.self_kerr, qubit-cavity cross-Kerr]
[6]:
True
[7]:
len(system.H0(clean=False)) == 5
# [qubit.self_kerr, cavity.self_kerr, qubit.detuning, cavity.detuning, qubit-cavity cross-Kerr]
[7]:
True
[8]:
for t1 in ['inf', 100e3]:
qubit.t1 = float(t1)
print(f'With {qubit.name}.t1 = {t1}, there are {len(system.c_ops(clean=True))} nonzero c_ops')
qubit.t2 = 100e3
print(
f'With {qubit.name}.t1 = {t1}, {qubit.name}.t2 = {qubit.t2}, '
f'there are {len(system.c_ops(clean=True))} nonzero c_ops'
)
With qubit.t1 = inf, there are 0 nonzero c_ops
With qubit.t1 = 100000.0, there are 1 nonzero c_ops
With qubit.t1 = 100000.0, qubit.t2 = 100000.0, there are 2 nonzero c_ops
[9]:
from qutip.ipynbtools import version_table
version_table()
[9]:
Software | Version |
---|---|
QuTiP | 4.7.0 |
Numpy | 1.23.2 |
SciPy | 1.9.1 |
matplotlib | 3.5.3 |
Cython | 0.29.32 |
Number of CPUs | 2 |
BLAS Info | OPENBLAS |
IPython | 8.4.0 |
Python | 3.8.6 (default, Oct 19 2020, 15:10:29) [GCC 7.5.0] |
OS | posix [linux] |
Tue Aug 30 19:15:33 2022 UTC |
[ ]: