Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/voltagegates ramprate as a QUA variable #244

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- wirer - Support for fixed-frequency transmons, i.e., cross-resonant drive lines and zz drive lines
- examples/Qcodes_drivers: Added examples with the OPX1000.
- external_frameworks/qcodes - Added the `readout_sampling_rate` parameter for the OPX1000.
- voltage_gates - Added the ability to set the ramp duration as a QUA variable.

### Fixed
- external_frameworks/qcodes - Fixed the connection message and OPX identification to include the OPX1000 and QOP 2.4.
Expand Down
54 changes: 41 additions & 13 deletions qualang_tools/voltage_gates/voltage_gate_sequence.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import numpy as np

from qm.qua._dsl import QuaVariable, QuaExpression
from qm.qua import declare, assign, play, fixed, Cast, amp, wait, ramp, ramp_to_zero
from qm.qua import declare, assign, play, fixed, Cast, amp, wait, ramp, ramp_to_zero, Math
from typing import Union, List, Dict
from warnings import warn


class VoltageGateSequence:
Expand Down Expand Up @@ -72,7 +73,14 @@ def _add_op_to_config(self, el: str, name: str, amplitude: float, length: int) -
@staticmethod
def _check_duration(duration: int):
if duration is not None and not isinstance(duration, (QuaVariable, QuaExpression)):
assert duration >= 4, "The duration must be a larger than 16 ns."
if duration == 0:
warn(
"\nThe duration of one level is set to zero which can cause gaps, use with care or set it it to at least 16ns.",
stacklevel=2,
)
else:
assert duration >= 4, "The duration must be a larger than 16 ns."
assert duration % 4 != 0, "The duration must be a multiple integer of 4ns."

def _update_averaged_power(self, level, duration, ramp_duration=None, current_level=None):
if self.is_QUA(level):
Expand Down Expand Up @@ -101,7 +109,7 @@ def _update_averaged_power(self, level, duration, ramp_duration=None, current_le
new_average += int(np.round(1024 * (level + current_level) * ramp_duration / 2))

else:
pass
new_average += Cast.mul_int_by_fixed(ramp_duration << 10, (level + current_level) / 2)
return new_average

@staticmethod
Expand All @@ -110,7 +118,7 @@ def is_QUA(var):

def add_step(
self,
level: list[Union[int, QuaExpression, QuaVariable]] = None,
level: list[Union[float, QuaExpression, QuaVariable]] = None,
duration: Union[int, QuaExpression, QuaVariable] = None,
voltage_point_name: str = None,
ramp_duration: Union[int, QuaExpression, QuaVariable] = None,
Expand All @@ -126,6 +134,13 @@ def add_step(
"""
self._check_duration(duration)
self._check_duration(ramp_duration)
if ramp_duration is not None:
if self.is_QUA(ramp_duration):
warn(
"\nYou are using a QUA variable for the ramp duration, make sure to stay at the final voltage level for more than 52ns otherwise you will have a gap or an error.",
stacklevel=2,
)

if level is not None:
if type(level) is not list or len(level) != len(self._elements):
raise TypeError(
Expand Down Expand Up @@ -163,13 +178,14 @@ def add_step(
wait((_duration - 16) >> 2, gate)
# if constant duration --> new operation and play(*amp(..))
else:
operation = self._add_op_to_config(
gate,
"step",
amplitude=0.25,
length=_duration,
)
play(operation * amp((voltage_level - self.current_level[i]) * 4), gate)
if _duration > 0:
operation = self._add_op_to_config(
gate,
"step",
amplitude=0.25,
length=_duration,
)
play(operation * amp((voltage_level - self.current_level[i]) * 4), gate)

# Fixed amplitude but dynamic duration --> new operation and play(duration=..)
elif isinstance(_duration, (QuaVariable, QuaExpression)):
Expand Down Expand Up @@ -200,8 +216,20 @@ def add_step(
if not self.is_QUA(ramp_duration):
ramp_rate = 1 / ramp_duration
play(ramp((voltage_level - self.current_level[i]) * ramp_rate), gate, duration=ramp_duration >> 2)
wait(_duration >> 2, gate)

if not self.is_QUA(_duration):
if _duration > 0:
wait(_duration >> 2, gate)
else:
wait(_duration >> 2, gate)
else:
ramp_rate = declare(fixed)
assign(ramp_rate, (voltage_level - self.current_level[i]) * Math.div(1, ramp_duration))
play(ramp(ramp_rate), gate, duration=ramp_duration >> 2)
if self.is_QUA(_duration):
wait((_duration >> 2) - 9, gate)
else:
if _duration > 0:
wait(_duration >> 2, gate)
self.current_level[i] = voltage_level

def add_compensation_pulse(self, duration: int) -> None:
Expand Down
Loading