Skip to content

Commit

Permalink
Fix HangerResonator
Browse files Browse the repository at this point in the history
It uses the more efficient WaveguideCoplanar and thus also avoids recursive
element usage (disallowed by KLayout) when insertend in WaveguideComposite.

Fix #69
  • Loading branch information
iqmtestd committed Oct 20, 2023
1 parent a767105 commit ef928b2
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 38 deletions.
71 changes: 35 additions & 36 deletions klayout_package/python/kqcircuits/elements/hanger_resonator.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
# for individuals (meetiqm.com/developers/clas/individual) and organizations (meetiqm.com/developers/clas/organization).

from math import pi
from kqcircuits.pya_resolver import pya
from kqcircuits.util.parameters import Param, pdt
from kqcircuits.elements.element import Element
from kqcircuits.elements.waveguide_composite import WaveguideComposite
from kqcircuits.elements.waveguide_composite import Node
from kqcircuits.elements.waveguide_coplanar import WaveguideCoplanar
from kqcircuits.util.refpoints import WaveguideToSimPort


Expand All @@ -31,51 +31,49 @@ class HangerResonator(Element):
head_length = Param(pdt.TypeDouble, "Length of the resonator left waveguide (head) ", 300, unit="μm")
resonator_length = Param(pdt.TypeDouble, "Total length of the resonator", 1000, unit="μm")

pl_a = Param(pdt.TypeDouble, "Trace width of probe line", 10, unit="μm")
pl_b = Param(pdt.TypeDouble, "Gap width of probe line", 6, unit="μm")
res_a = Param(pdt.TypeDouble, "Trace width of resonator line", 10, unit="μm")
res_b = Param(pdt.TypeDouble, "Gap width of resonator line", 6, unit="μm")

ground_width = Param(pdt.TypeDouble, "Trace width of middle ground", 10, unit="μm")

def build(self):

# If turn radius is smaller than half of the trace width it will create some overlapping masks and sharp angles
if self.r < self.a/2:
self.raise_error_on_cell(f'Turn radius must be at least a/2, now given r={self.r}, a/2={self.a/2}')
if self.r < self.res_a / 2:
self.raise_error_on_cell(f'Turn radius must be at least res_a/2, now r={self.r}, res_a/2={self.res_a/2}')

# probe line, origin at the center of the trace
pl_p1 = (0, 0)
pl_p2 = (self.coupling_length, 0)
nodes_pl = [Node(pl_p1), Node(pl_p2)]
points_pl = [pya.DPoint(0, 0)]
points_pl.append(pya.DPoint(self.coupling_length, 0))

# distance from origin to start of the wg trace
wg_start_height = -self.pl_a/2-self.pl_b-self.ground_width-self.b
wg_start_height = -self.a / 2 - self.b - self.ground_width - self.res_b
# x distance from pl port to center trace of vertical waveguides
corner_x = self.r
# corner arc length
corner_length = pi*self.r/2
corner_length = pi * self.r/2
head_length_down = self.head_length - corner_length

nodes = []
points = []

if head_length_down > 0:
# left side, head
# left leg
p1 = (-corner_x, wg_start_height - self.a/2 - self.r - head_length_down)
nodes.append(Node(p1))
p1 = pya.DPoint(-corner_x, wg_start_height - self.res_a / 2 - self.r - head_length_down)
points.append(p1)
# corner
p2 = (-corner_x, wg_start_height-self.a/2)
p2 = pya.DPoint(-corner_x, wg_start_height - self.res_a / 2)

length_without_tail = self.head_length + self.coupling_length + corner_length

# If head lenght is too small don't create the curve on left side
else:
# Add a stub corresponding to head length if head length is shorter than the corner
p2 = (-max(self.head_length,0), wg_start_height-self.a/2)
p2 = pya.DPoint(-max(self.head_length, 0), wg_start_height - self.res_a/2)

length_without_tail = self.coupling_length + corner_length


nodes.append(Node(p2))
points.append(p2)


# If given resonator length is too small, don't create downwards tail
Expand All @@ -84,32 +82,33 @@ def build(self):
# Add a stub corresponding to tail length if head length is shorter than the corner
x_tail_offset = max(0, self.resonator_length - (length_without_tail - corner_length))

p3 = (self.coupling_length + x_tail_offset, wg_start_height-self.a/2)
p3 = pya.DPoint(self.coupling_length + x_tail_offset, wg_start_height - self.res_a / 2)

nodes.append(Node(p3))
points.append(p3)

else:
tail_length = self.resonator_length - length_without_tail
# right leg (tail)
p3 = (self.coupling_length + corner_x, wg_start_height - self.a/2)
p4 = (self.coupling_length + corner_x, wg_start_height - self.a/2 - self.r - tail_length)
p3 = pya.DPoint(self.coupling_length + corner_x, wg_start_height - self.res_a / 2)
p4 = pya.DPoint(self.coupling_length + corner_x, wg_start_height - self.res_a / 2 - self.r - tail_length)

nodes.append(Node(p3))
nodes.append(Node(p4))
points.append(p3)
points.append(p4)

cells_pl, _ = self.insert_cell(WaveguideComposite, nodes=nodes_pl, a=self.pl_a, b=self.pl_b, r=self.r)
cells_resonator, _ = self.insert_cell(WaveguideComposite, nodes=nodes, a=self.a, b=self.b, r=self.r)
cells_pl, _ = self.insert_cell(WaveguideCoplanar, path=points_pl)
cells_resonator, _ = self.insert_cell(WaveguideCoplanar, path=points, a=self.res_a, b=self.res_b)

self.copy_port("a", cells_pl, "pl_a")
self.copy_port("b", cells_pl, "pl_b")
self.copy_port("a", cells_resonator)
self.copy_port("b", cells_resonator)
self.copy_port("a", cells_pl)
self.copy_port("b", cells_pl)
self.copy_port("a", cells_resonator, "resonator_a")
self.copy_port("b", cells_resonator, "resonator_b")
# these are needed for simulations
self.copy_port("a", cells_pl, "sim_a")
self.copy_port("b", cells_pl, "sim_b")

@classmethod
def get_sim_ports(cls, simulation):
return [WaveguideToSimPort("port_pl_a", use_internal_ports=False,
a=simulation.pl_a, b=simulation.pl_b, turn_radius=0),
WaveguideToSimPort("port_pl_b", use_internal_ports=False,
a=simulation.pl_a, b=simulation.pl_b, turn_radius=0),
WaveguideToSimPort("port_a", side="left", a=simulation.a, b=simulation.b),
WaveguideToSimPort("port_b", side="right", a=simulation.a, b=simulation.b)]
return [WaveguideToSimPort("port_sim_a", use_internal_ports=False, a=simulation.a, b=simulation.b),
WaveguideToSimPort("port_sim_b", use_internal_ports=False, a=simulation.a, b=simulation.b),
WaveguideToSimPort("port_resonator_a", a=simulation.res_a, b=simulation.res_b),
WaveguideToSimPort("port_resonator_b", a=simulation.res_a, b=simulation.res_b)]
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ from kqcircuits.elements.finger_capacitor_taper import FingerCapacitorTaper
from kqcircuits.elements.waveguide_coplanar_splitter import WaveguideCoplanarSplitter, t_cross_parameters
from kqcircuits.elements.flip_chip_connectors.flip_chip_connector_rf import FlipChipConnectorRf
from kqcircuits.defaults import default_faces
from kqcircuits.elements.hanger_resonator import HangerResonator


view = KLayoutView()
Expand Down Expand Up @@ -115,6 +116,9 @@ nodes = [
Node(pya.DPoint(600, -1800), face_id="1t1", a=20, b=4, round_connector=True, n_center_bumps=3, output_rotation=90),
Node(pya.DPoint(700, -2100), face_id="2b1", output_rotation=90, angle=270, a=10, b=6),
Node(pya.DPoint(0, -2100)),
Node(pya.DPoint(0, -2300)),
Node(pya.DPoint(200, -2300), HangerResonator),
Node(pya.DPoint(900, -2100)),
]

view.insert_cell(WaveguideComposite, nodes=nodes)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@
'head_length': head_length,
'resonator_length': resonator_length,
'r': turn_radius,
'pl_a': 10,
'pl_b': 6,
'res_a': 10,
'res_b': 6,
'a': 10,
'b': 6,
'ground_width': 10
Expand Down

0 comments on commit ef928b2

Please sign in to comment.