Source code for gdsfactory.components.quantum.flux_qubit

from __future__ import annotations

import numpy as np

import gdsfactory as gf
from gdsfactory.component import Component
from gdsfactory.typings import LayerSpec


[docs] @gf.cell_with_module_name def flux_qubit( loop_width: float = 50.0, loop_height: float = 50.0, junction_width: float = 0.15, junction_height: float = 0.3, alpha_junction_width: float = 0.12, alpha_junction_height: float = 0.25, wire_width: float = 2.0, layer_metal: LayerSpec = (1, 0), layer_junction: LayerSpec = (2, 0), layer_alpha_junction: LayerSpec = (3, 0), port_type: str = "electrical", ) -> Component: """Creates a flux qubit (persistent current qubit). A flux qubit consists of a superconducting loop interrupted by three Josephson junctions. Two junctions are identical (beta junctions) while the third is smaller (alpha junction) with roughly 0.5-0.8 times the critical current. Args: loop_width: Width of the superconducting loop in μm. loop_height: Height of the superconducting loop in μm. junction_width: Width of the beta Josephson junctions in μm. junction_height: Height of the beta Josephson junctions in μm. alpha_junction_width: Width of the alpha Josephson junction in μm. alpha_junction_height: Height of the alpha Josephson junction in μm. wire_width: Width of the superconducting wires in μm. layer_metal: Layer for the metal wires. layer_junction: Layer for the beta Josephson junctions. layer_alpha_junction: Layer for the alpha Josephson junction. port_type: Type of port to add to the component. Returns: Component: A gdsfactory component with the flux qubit geometry. """ c = Component() # Create the superconducting loop as a hollow rectangle outer_rect = gf.components.rectangle( size=(loop_width, loop_height), layer=layer_metal, ) inner_rect = gf.components.rectangle( size=(loop_width - 2 * wire_width, loop_height - 2 * wire_width), layer=layer_metal, ) # Create the loop by boolean difference loop = gf.boolean( outer_rect, inner_rect, operation="not", layer=layer_metal, ) loop_ref = c.add_ref(loop) loop_ref.move((-loop_width / 2, -loop_height / 2)) # Create gaps for junctions # Bottom gap for alpha junction alpha_gap = gf.components.rectangle( size=(alpha_junction_width + 0.1, wire_width + 0.1), layer=layer_metal, ) alpha_gap_ref = c.add_ref(alpha_gap) alpha_gap_ref.move((-alpha_junction_width / 2 - 0.05, -loop_height / 2 - 0.05)) # Left gap for beta junction beta_gap_left = gf.components.rectangle( size=(wire_width + 0.1, junction_height + 0.1), layer=layer_metal, ) beta_gap_left_ref = c.add_ref(beta_gap_left) beta_gap_left_ref.move((-loop_width / 2 - 0.05, -junction_height / 2 - 0.05)) # Right gap for beta junction beta_gap_right = gf.components.rectangle( size=(wire_width + 0.1, junction_height + 0.1), layer=layer_metal, ) beta_gap_right_ref = c.add_ref(beta_gap_right) beta_gap_right_ref.move( (loop_width / 2 - wire_width - 0.05, -junction_height / 2 - 0.05) ) # Remove gaps from the loop # Need to perform boolean operations sequentially loop_with_gaps = gf.boolean( loop_ref, alpha_gap_ref, operation="not", layer=layer_metal, ) loop_with_gaps = gf.boolean( loop_with_gaps, beta_gap_left_ref, operation="not", layer=layer_metal, ) loop_with_gaps = gf.boolean( loop_with_gaps, beta_gap_right_ref, operation="not", layer=layer_metal, ) c.add_ref(loop_with_gaps) # Create the alpha junction (smaller) alpha_junction = gf.components.rectangle( size=(alpha_junction_width, alpha_junction_height), layer=layer_alpha_junction, ) alpha_junction_ref = c.add_ref(alpha_junction) alpha_junction_ref.move( ( -alpha_junction_width / 2, -loop_height / 2 + wire_width / 2 - alpha_junction_height / 2, ) ) # Create the beta junctions (larger, identical) beta_junction_left = gf.components.rectangle( size=(junction_width, junction_height), layer=layer_junction, ) beta_junction_left_ref = c.add_ref(beta_junction_left) beta_junction_left_ref.move( (-loop_width / 2 + wire_width / 2 - junction_width / 2, -junction_height / 2) ) beta_junction_right = gf.components.rectangle( size=(junction_width, junction_height), layer=layer_junction, ) beta_junction_right_ref = c.add_ref(beta_junction_right) beta_junction_right_ref.move( (loop_width / 2 - wire_width / 2 - junction_width / 2, -junction_height / 2) ) # Add control lines for flux bias control_line_left = gf.components.rectangle( size=(20.0, 2.0), layer=layer_metal, ) control_line_left_ref = c.add_ref(control_line_left) control_line_left_ref.move((-loop_width / 2 - 30.0, -1.0)) control_line_right = gf.components.rectangle( size=(20.0, 2.0), layer=layer_metal, ) control_line_right_ref = c.add_ref(control_line_right) control_line_right_ref.move((loop_width / 2 + 10.0, -1.0)) c.flatten() # Add ports for flux control c.add_port( name="flux_control_left", center=(-loop_width / 2 - 40.0, 0), width=2.0, orientation=180, layer=layer_metal, port_type=port_type, ) c.add_port( name="flux_control_right", center=(loop_width / 2 + 40.0, 0), width=2.0, orientation=0, layer=layer_metal, port_type=port_type, ) # Add readout connection c.add_port( name="readout", center=(0, loop_height / 2 + 10.0), width=wire_width, orientation=90, layer=layer_metal, port_type=port_type, ) # Add metadata c.info["qubit_type"] = "flux_qubit" c.info["loop_width"] = loop_width c.info["loop_height"] = loop_height c.info["beta_junction_area"] = junction_width * junction_height c.info["alpha_junction_area"] = alpha_junction_width * alpha_junction_height c.info["alpha_beta_ratio"] = (alpha_junction_width * alpha_junction_height) / ( junction_width * junction_height ) return c
[docs] @gf.cell_with_module_name def flux_qubit_asymmetric( loop_width: float = 60.0, loop_height: float = 40.0, junction_width: float = 0.15, junction_height: float = 0.3, alpha_junction_width: float = 0.12, alpha_junction_height: float = 0.25, wire_width: float = 2.0, asymmetry_angle: float = 15.0, layer_metal: LayerSpec = (1, 0), layer_junction: LayerSpec = (2, 0), layer_alpha_junction: LayerSpec = (3, 0), port_type: str = "electrical", ) -> Component: """Creates an asymmetric flux qubit for reduced flux noise sensitivity. An asymmetric flux qubit has a loop geometry that is not perfectly symmetric, which can help reduce sensitivity to flux noise while maintaining controllability. Args: loop_width: Width of the superconducting loop in μm. loop_height: Height of the superconducting loop in μm. junction_width: Width of the beta Josephson junctions in μm. junction_height: Height of the beta Josephson junctions in μm. alpha_junction_width: Width of the alpha Josephson junction in μm. alpha_junction_height: Height of the alpha Josephson junction in μm. wire_width: Width of the superconducting wires in μm. asymmetry_angle: Angle of asymmetry in degrees. layer_metal: Layer for the metal wires. layer_junction: Layer for the beta Josephson junctions. layer_alpha_junction: Layer for the alpha Josephson junction. port_type: Type of port to add to the component. Returns: Component: A gdsfactory component with the asymmetric flux qubit geometry. """ c = Component() # Create the main loop structure points = [] angle_rad = np.radians(asymmetry_angle) # Create asymmetric loop shape # Bottom side points.extend( [ (-loop_width / 2, -loop_height / 2), (loop_width / 2, -loop_height / 2), (loop_width / 2, -loop_height / 2 + wire_width), (-loop_width / 2, -loop_height / 2 + wire_width), ] ) # Right side with angle x_offset = loop_height / 2 * np.tan(angle_rad) points.extend( [ (loop_width / 2 - wire_width, -loop_height / 2 + wire_width), (loop_width / 2 - wire_width, loop_height / 2 - wire_width), (loop_width / 2 - wire_width + x_offset, loop_height / 2 - wire_width), (loop_width / 2 + x_offset, loop_height / 2 - wire_width), (loop_width / 2 + x_offset, loop_height / 2), (loop_width / 2, loop_height / 2), (loop_width / 2, -loop_height / 2), ] ) # Top side points.extend( [ (loop_width / 2 + x_offset, loop_height / 2), (-loop_width / 2, loop_height / 2), (-loop_width / 2, loop_height / 2 - wire_width), (loop_width / 2 + x_offset, loop_height / 2 - wire_width), ] ) # Left side points.extend( [ (-loop_width / 2 + wire_width, loop_height / 2 - wire_width), (-loop_width / 2 + wire_width, -loop_height / 2 + wire_width), (-loop_width / 2, -loop_height / 2 + wire_width), (-loop_width / 2, loop_height / 2), ] ) # Create the loop polygon c.add_polygon(points, layer=layer_metal) # Create junctions in the gaps # alpha junction at bottom alpha_junction = gf.components.rectangle( size=(alpha_junction_width, alpha_junction_height), layer=layer_alpha_junction, ) alpha_junction_ref = c.add_ref(alpha_junction) alpha_junction_ref.move( ( -alpha_junction_width / 2, -loop_height / 2 + wire_width / 2 - alpha_junction_height / 2, ) ) # beta junctions at sides beta_junction_left = gf.components.rectangle( size=(junction_width, junction_height), layer=layer_junction, ) beta_junction_left_ref = c.add_ref(beta_junction_left) beta_junction_left_ref.move( (-loop_width / 2 + wire_width / 2 - junction_width / 2, 0) ) beta_junction_right = gf.components.rectangle( size=(junction_width, junction_height), layer=layer_junction, ) beta_junction_right_ref = c.add_ref(beta_junction_right) beta_junction_right_ref.move( (loop_width / 2 - wire_width / 2 - junction_width / 2, 0) ) # Add control and readout ports c.add_port( name="flux_control", center=(0, loop_height / 2 + 10.0), width=wire_width, orientation=90, layer=layer_metal, port_type=port_type, ) c.add_port( name="readout", center=(loop_width / 2 + x_offset + 10.0, 0), width=wire_width, orientation=0, layer=layer_metal, port_type=port_type, ) # Add metadata c.info["qubit_type"] = "flux_qubit_asymmetric" c.info["loop_width"] = loop_width c.info["loop_height"] = loop_height c.info["asymmetry_angle"] = asymmetry_angle c.info["beta_junction_area"] = junction_width * junction_height c.info["alpha_junction_area"] = alpha_junction_width * alpha_junction_height c.info["alpha_beta_ratio"] = (alpha_junction_width * alpha_junction_height) / ( junction_width * junction_height ) return c
if __name__ == "__main__": c = flux_qubit() # c = flux_qubit_asymmetric() c.show()