Source code for qpdk.cells.junction

"""Josephson junction components."""

from __future__ import annotations

import gdsfactory as gf
from gdsfactory.component import Component
from gdsfactory.typings import ComponentSpec, CrossSectionSpec, LayerSpec
from klayout.db import DCplxTrans

from qpdk.cells.waveguides import straight
from qpdk.helper import show_components
from qpdk.tech import (
    LAYER,
    josephson_junction_cross_section_narrow,
    josephson_junction_cross_section_wide,
)


[docs] @gf.cell def single_josephson_junction_wire( wide_straight_length: float = 8.3, narrow_straight_length: float = 0.5, taper_length: float = 4.7, cross_section_wide: CrossSectionSpec = josephson_junction_cross_section_wide, cross_section_narrow: CrossSectionSpec = josephson_junction_cross_section_narrow, layer_patch: LayerSpec = LAYER.JJ_PATCH, size_patch: tuple[float, float] = (1.5, 1.0), ) -> Component: r"""Creates a single wire to use in a Josephson junction. .. svgbob:: ┌───┐ │o1 │━━━━────╶╶╶╶╶ o2 └───┘ wide narrow Args: wide_straight_length: Length of the wide straight section in µm. narrow_straight_length: Length of the narrow straight section in µm. taper_length: Length of the taper section in µm. cross_section_wide: Cross-section specification for the wide section. cross_section_narrow: Cross-section specification for the narrow section. layer_patch: Layer for the patch that creates the overlap region. size_patch: Size of the patch that creates the overlap region. """ c = Component() # Widest straight section with patch wide_straight_ref = c << straight( length=wide_straight_length, cross_section=cross_section_wide ) # Add the tapered transition section taper_ref = c << gf.c.taper_cross_section( length=taper_length, cross_section1=cross_section_wide, cross_section2=cross_section_narrow, linear=True, ) # Narrow straight section with overlap narrow_straight_ref = c << straight( length=narrow_straight_length, cross_section=cross_section_narrow ) # Connect all taper_ref.connect("o1", wide_straight_ref.ports["o2"]) narrow_straight_ref.connect("o1", taper_ref.ports["o2"]) # Add patch to wide section if layer_patch: patch = c << gf.components.rectangle( size=size_patch, layer=layer_patch, centered=True, ) # Overlap with one fourth offset to one side patch.move( (wide_straight_ref.dbbox().p1.x - size_patch[0] / 4, wide_straight_ref.y) ) # Add port at wide end c.add_port( port=wide_straight_ref.ports["o1"], name="o1", cross_section=cross_section_wide ) # Add port at narrow end c.add_port( port=narrow_straight_ref.ports["o2"], name="o2", cross_section=cross_section_narrow, ) return c
[docs] @gf.cell def josephson_junction( junction_overlap_displacement: float = 1.8, wide_straight_length: float = 8.3, narrow_straight_length: float = 0.5, taper_length: float = 4.7, cross_section_wide: CrossSectionSpec = josephson_junction_cross_section_wide, cross_section_narrow: CrossSectionSpec = josephson_junction_cross_section_narrow, layer_patch: LayerSpec = LAYER.JJ_PATCH, size_patch: tuple[float, float] = (1.5, 1.0), ) -> Component: r"""Creates a single Josephson junction component. A Josephson junction consists of two superconducting electrodes separated by a thin insulating barrier allowing tunnelling. .. svgbob:: right_wide ┌───┐ ╷ overlap │ │━━━━────╶╶╷╶╶ └───┘ ╷ ┌───┐ │ │ └───┘ left_wide Args: junction_overlap_displacement: Displacement of the overlap region in µm. Measured from the centers of the junction ports. wide_straight_length: Length of the wide straight section in µm. narrow_straight_length: Length of the narrow straight section in µm. taper_length: Length of the taper section in µm. cross_section_wide: Cross-section specification for the wide section. cross_section_narrow: Cross-section specification for the narrow section. layer_patch: Layer for the patch that creates the overlap region. size_patch: Size of the patch that creates the overlap region. """ c = Component() # Left wire left_wire = c << single_josephson_junction_wire( wide_straight_length=wide_straight_length, narrow_straight_length=narrow_straight_length, taper_length=taper_length, cross_section_wide=cross_section_wide, cross_section_narrow=cross_section_narrow, layer_patch=layer_patch, size_patch=size_patch, ) # Right wire right_wire = c << single_josephson_junction_wire( wide_straight_length=wide_straight_length, narrow_straight_length=narrow_straight_length, taper_length=taper_length, cross_section_wide=cross_section_wide, cross_section_narrow=cross_section_narrow, layer_patch=layer_patch, size_patch=size_patch, ) total_length = wide_straight_length + narrow_straight_length + taper_length # Position left wire on top of right wire with rotation left_wire.dcplx_trans = ( right_wire.ports["o2"].dcplx_trans * DCplxTrans.R90 * DCplxTrans( -total_length + junction_overlap_displacement, 0, ) ) right_wire.dcplx_trans *= DCplxTrans(junction_overlap_displacement, 0) # Add ports at wide ends c.add_port( name="left_wide", port=left_wire.ports["o1"], ) c.add_port( name="right_wide", port=right_wire.ports["o1"], ) # One port at overlap c.add_port( name="overlap", center=( left_wire.ports["o2"].dcplx_trans * DCplxTrans(-junction_overlap_displacement, 0) ).disp.to_p(), width=left_wire.ports["o2"].width, orientation=left_wire.ports["o2"].orientation, layer=left_wire.ports["o2"].layer, port_type=left_wire.ports["o2"].port_type, ) # breakpoint() return c
[docs] @gf.cell def squid_junction( junction_spec: ComponentSpec = josephson_junction, loop_area: float = 4, ) -> Component: """Creates a SQUID (Superconducting Quantum Interference Device) junction component. A SQUID consists of two Josephson junctions connected in parallel, forming a loop. See :cite:`clarkeSQUIDHandbook2004` for details. Args: junction_spec: Component specification for the Josephson junction component. loop_area: Area of the SQUID loop in µm². This does not take into account the junction wire widths. """ c = Component() junction_comp = gf.get_component(junction_spec) left_junction = c << junction_comp right_junction = c << junction_comp # Form a cross by positioning overlaps on top of each other right_junction.dcplx_trans = ( left_junction.ports["overlap"].dcplx_trans * DCplxTrans.R90 * DCplxTrans( -left_junction.xmax + (left_junction.xmax - left_junction.ports["overlap"].x), 0, ) ) # Start adding area by displacing junctions displacement_xy = loop_area**0.5 right_junction.dcplx_trans *= DCplxTrans((displacement_xy,) * 2) # Add ports from junctions with descriptive names for junction_name, junction in [("left", left_junction), ("right", right_junction)]: for port_side in ["left", "right"]: port_name = f"{junction_name}_{port_side}_wide" c.add_port(name=port_name, port=junction.ports[f"{port_side}_wide"]) # Overlaps and their center c.add_port(name="left_overlap", port=left_junction.ports["overlap"]) c.add_port(name="right_overlap", port=right_junction.ports["overlap"]) c.add_port( name="loop_center", center=( ( left_junction.ports["overlap"].dcplx_trans.disp + right_junction.ports["overlap"].dcplx_trans.disp ) / 2 ).to_p(), layer=left_junction.ports["overlap"].layer, width=left_junction.ports["overlap"].width, ) return c
if __name__ == "__main__": show_components(josephson_junction, squid_junction)