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

Fix HangerResonator #70

Merged
merged 1 commit into from
Oct 20, 2023
Merged
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
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
Loading