From ef928b26ad856e723f4a98f83ec3d26cae6cc42e Mon Sep 17 00:00:00 2001 From: David Janzso Date: Wed, 18 Oct 2023 13:50:36 +0300 Subject: [PATCH] Fix HangerResonator It uses the more efficient WaveguideCoplanar and thus also avoids recursive element usage (disallowed by KLayout) when insertend in WaveguideComposite. Fix #69 --- .../kqcircuits/elements/hanger_resonator.py | 71 +++++++++---------- .../generate/test_waveguide_composite.lym | 4 ++ .../simulations/hanger_resonator_sim.py | 4 +- 3 files changed, 41 insertions(+), 38 deletions(-) diff --git a/klayout_package/python/kqcircuits/elements/hanger_resonator.py b/klayout_package/python/kqcircuits/elements/hanger_resonator.py index 7a3f344c2..c10490319 100644 --- a/klayout_package/python/kqcircuits/elements/hanger_resonator.py +++ b/klayout_package/python/kqcircuits/elements/hanger_resonator.py @@ -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 @@ -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 @@ -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)] diff --git a/klayout_package/python/scripts/macros/generate/test_waveguide_composite.lym b/klayout_package/python/scripts/macros/generate/test_waveguide_composite.lym index c632059d8..95221b1a9 100644 --- a/klayout_package/python/scripts/macros/generate/test_waveguide_composite.lym +++ b/klayout_package/python/scripts/macros/generate/test_waveguide_composite.lym @@ -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() @@ -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) diff --git a/klayout_package/python/scripts/simulations/hanger_resonator_sim.py b/klayout_package/python/scripts/simulations/hanger_resonator_sim.py index d9d019c88..4de56d0c2 100644 --- a/klayout_package/python/scripts/simulations/hanger_resonator_sim.py +++ b/klayout_package/python/scripts/simulations/hanger_resonator_sim.py @@ -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