Relaxation time T1 of the bosonic mode (coherent state decay)

Using pulsed mode, we measure the energy-relaxation time \(T_1\) of the bosonic mode. We first displace the memory with a pulse at the memory frequency with a \(\sin^2\) envelope. Then the memory enegy decays during the delay time \(\delta\). The qubit-control pulse is a selective \(\pi\) pulse with a \(\sin^2\) envelope whose frequency is the frequency of the qubit when the memory is in the Fock state \(|0\rangle\). The readout pulse is at the frequency of the readout resonator and has a square envelope. By probing the state of the qubit, we directly get the probablility that the memory is in state \(|0\rangle\).

T1 memory coherent pulse sequence

The class for performing the \(T_1\) experiment is available at presto-measure/t1_memory_coherent.py. Here, we run the experiment and observe the qubit population exponentially approaching the excited state. This translates in the memory starting in the Fock state \(|1\rangle\) and exponentially approaching the ground state \(|0\rangle\). We then have a look at the main parts of the code.

You can create a new experiment and run it on your Presto. Be sure to change the parameters of T1_memory_coherent to match your experiment and change presto_address to match the IP address of your Presto:

from t1_memory_coherent import T1_memory_coherent
import numpy as np

experiment = T1_memory_coherent(
    readout_freq=6.2e9,
    control_freq=4.2e9,
    memory_freq=3.5e9,
    readout_amp=0.1,
    control_amp=0.5,
    memory_amp=0.2,
    readout_duration=2.5e-6,
    control_duration=2000e-9,
    memory_duration=50e-9,
    sample_duration=2.5e-6,
    delay_arr=np.linspace(0, 2000e-6, 101),
    readout_port=1,
    control_port=2,
    memory_port=5,
    sample_port=1,
    wait_delay=5e-3,
    readout_sample_delay=0e-9,
    num_averages=100,
)

presto_address = "192.168.88.65"  # your Presto IP address
save_filename = experiment.run(presto_address)

Or you can also load older data:

experiment = T1_memory_coherent.load("../data/t1_memory_coherent_20230704_150826.h5")

In either case, we analyze the data to get a nice plot. In odrer to fit the data, we should know the amplitude of the displacement beta.

experiment.analyze(beta=3.31)

It is also possible to fit beta by not providing it to the analyze method.

experiment.analyze()

Note

To convert amplitudes from Presto units into displacement amplitude units perform Displacement calibration experiment and extract the conversion factor.

../_images/t1_memory_coherent_light.svg ../_images/t1_memory_coherent_dark.svg

The qubit starts in the ground state at zero delay \(\delta = 0~\mu s\) as there is no population of Fock state \(|0\rangle\) since the displacement amplitude is relatively large and the selective qubit \(\pi\) pulse does not affect the qubit state. The amplitude of the coherent state exponentially decays for increasing \(\delta\) \(\alpha(\delta)=\alpha_0 \exp(-\delta/(2T_1))\). Hence, the probability to find the Fock state \(|0\rangle\) is \(P_{|0\rangle}(\delta)=\exp(-|\alpha(\delta)|^2)\). We qubit population is proportional to Fock state \(|0\rangle\) population after the selective \(\pi\) pulse, so the relaxation time \(T_1\) of the memory is extracted from the fit. The complex-valued readout signal is rotated using utils.rotate_opt() so that all the information about the qubit state is in the I quadrature.

Code explanation

Here we discuss the main part of the code of the t1_memory_coherent class: the definition of the experiment sequence. The full source is available at presto-measure/t1_memory_coherent.py.

We implement the variable delay in the measurement with a single for loop:

T = 0.0  # s, start at time zero ...
for delay in self.delay_arr:
	pls.output_pulse(T, memory_pulse)  # displace memory
	T += self.memory_duration
	T += delay  # increasing delay
	pls.output_pulse(T, control_pulse)  # pi pulse conditioned on memory in |0>
	T += self.control_duration
	pls.output_pulse(T, readout_pulse)  # Readout
	pls.store(T + self.readout_sample_delay)
	T += self.readout_duration
	T += self.wait_delay  # Wait for decay

We first displace the memory. After waiting a variable amount of time, we output qubit-control \(\pi\) pulse that maps the population of Fock state \(|0\rangle\) in the memory onto qubit population. Finally, we perform the readout.


run() executes the experiment sequence. We set repeat_count=1 since the whole pulse sequence is already programmed in the for loop.

pls.run(period=T, repeat_count=1, num_averages=self.num_averages)