def _via_iterable(via_spacing, wire_width, wiring1_layer, wiring2_layer, via_layer, via_width): VI = pp.Component() wire1 = VI.add_ref( pc.compass(size=(via_spacing, wire_width), layer=wiring1_layer)) wire2 = VI.add_ref( pc.compass(size=(via_spacing, wire_width), layer=wiring2_layer)) via1 = VI.add_ref(pc.compass(size=(via_width, via_width), layer=via_layer)) via2 = VI.add_ref(pc.compass(size=(via_width, via_width), layer=via_layer)) wire1.connect(port="E", destination=wire2.ports["W"], overlap=wire_width) via1.connect(port="W", destination=wire1.ports["E"], overlap=(wire_width + via_width) / 2) via2.connect(port="W", destination=wire2.ports["E"], overlap=(wire_width + via_width) / 2) VI.add_port(name="W", port=wire1.ports["W"]) VI.add_port(name="E", port=wire2.ports["E"]) VI.add_port( name="S", midpoint=[(1 * wire_width) + wire_width / 2, -wire_width / 2], width=wire_width, orientation=-90, ) VI.add_port( name="N", midpoint=[(1 * wire_width) + wire_width / 2, wire_width / 2], width=wire_width, orientation=90, ) return VI
def grating_coupler_uniform( num_teeth: int = 20, period: float = 0.75, fill_factor: float = 0.5, width_grating: float = 11.0, length_taper: float = 150.0, width: float = 0.5, partial_etch: bool = False, layer: Tuple[int, int] = pp.LAYER.WG, layer_partial_etch: Tuple[int, int] = pp.LAYER.SLAB150, polarization="te", wavelength=1500, ) -> Component: """Grating coupler uniform Args: num_teeth: 20 period: 0.75 fill_factor: 0.5 width_grating: 11 length_taper: 150 width: 0.5 partial_etch: False .. plot:: :include-source: import pp c = pp.c.grating_coupler_uniform() pp.plotgds(c) """ # returns a fiber grating G = Component() if partial_etch: partetch_overhang = 5 _compass = compass( size=[period * (1 - fill_factor), width_grating + partetch_overhang * 2], layer=layer_partial_etch, ) # make the etched areas (opposite to teeth) for i in range(num_teeth): cgrating = G.add_ref(_compass) cgrating.x += i * period # draw the deep etched square around the grating deepbox = G.add_ref( compass(size=[num_teeth * period, width_grating], layer=layer) ) deepbox.movex(num_teeth * period / 2) else: for i in range(num_teeth): cgrating = G.add_ref( compass(size=[period * fill_factor, width_grating], layer=layer) ) cgrating.x += i * period # make the taper tgrating = G.add_ref( taper( length=length_taper, width1=width_grating, width2=width, port=None, layer=layer, ) ) tgrating.xmin = cgrating.xmax G.add_port(port=tgrating.ports["2"], name="W0") G.polarization = polarization G.wavelength = wavelength G.rotate(180) return G
def test_comb( pad_size=(200, 200), wire_width=1, wire_gap=3, comb_layer=0, overlap_zigzag_layer=1, comb_pad_layer=None, comb_gnd_layer=None, overlap_pad_layer=None, ): """ Superconducting heater device from phidl.geometry Args: pad_size=(200, 200) wire_width=1 wire_gap=3 comb_layer=0 overlap_zigzag_layer=1 comb_pad_layer=None comb_gnd_layer=None overlap_pad_layer=None """ CI = pp.Component() if comb_pad_layer is None: comb_pad_layer = comb_layer if comb_gnd_layer is None: comb_gnd_layer = comb_layer if overlap_pad_layer is None: overlap_pad_layer = overlap_zigzag_layer wire_spacing = wire_width + wire_gap * 2 # %% pad overlays overlay_padb = CI.add_ref( pc.rectangle(size=(pad_size[0] * 9 / 10, pad_size[1] * 9 / 10), layer=overlap_pad_layer)) overlay_padl = CI.add_ref( pc.rectangle(size=(pad_size[0] * 9 / 10, pad_size[1] * 9 / 10), layer=comb_pad_layer)) overlay_padt = CI.add_ref( pc.rectangle(size=(pad_size[0] * 9 / 10, pad_size[1] * 9 / 10), layer=comb_pad_layer)) overlay_padr = CI.add_ref( pc.rectangle(size=(pad_size[0] * 9 / 10, pad_size[1] * 9 / 10), layer=comb_gnd_layer)) overlay_padl.xmin = 0 overlay_padl.ymin = 0 overlay_padb.ymax = 0 overlay_padb.xmin = overlay_padl.xmax + pad_size[1] / 5 overlay_padr.ymin = overlay_padl.ymin overlay_padr.xmin = overlay_padb.xmax + pad_size[1] / 5 overlay_padt.xmin = overlay_padl.xmax + pad_size[1] / 5 overlay_padt.ymin = overlay_padl.ymax # %% pads padl = CI.add_ref(pc.rectangle(size=pad_size, layer=comb_layer)) padt = CI.add_ref(pc.rectangle(size=pad_size, layer=comb_layer)) padr = CI.add_ref(pc.rectangle(size=pad_size, layer=comb_layer)) padb = CI.add_ref(pc.rectangle(size=pad_size, layer=overlap_zigzag_layer)) padl_nub = CI.add_ref( pc.rectangle(size=(pad_size[0] / 4, pad_size[1] / 2), layer=comb_layer)) padr_nub = CI.add_ref( pc.rectangle(size=(pad_size[0] / 4, pad_size[1] / 2), layer=comb_layer)) padl.xmin = overlay_padl.xmin padl.center = [padl.center[0], overlay_padl.center[1]] padt.ymax = overlay_padt.ymax padt.center = [overlay_padt.center[0], padt.center[1]] padr.xmax = overlay_padr.xmax padr.center = [padr.center[0], overlay_padr.center[1]] padb.ymin = overlay_padb.ymin padb.center = [overlay_padb.center[0], padb.center[1]] padl_nub.xmin = padl.xmax padl_nub.center = [padl_nub.center[0], padl.center[1]] padr_nub.xmax = padr.xmin padr_nub.center = [padr_nub.center[0], padr.center[1]] # %% connected zig head = CI.add_ref( pc.compass(size=(pad_size[0] / 12, wire_width), layer=comb_layer)) head.xmin = padl_nub.xmax head.ymax = padl_nub.ymax connector = CI.add_ref( pc.compass(size=(wire_width, wire_width), layer=comb_layer)) connector.connect(port="W", destination=head.ports["E"]) old_port = connector.ports["S"] top = True obj = connector while obj.xmax + pad_size[0] / 12 < padr_nub.xmin: # long zig zag rectangle obj = CI.add_ref( pc.compass(size=(pad_size[1] / 2 - 2 * wire_width, wire_width), layer=comb_layer)) obj.connect(port="W", destination=old_port) old_port = obj.ports["E"] if top: # zig zag edge rectangle obj = CI.add_ref( pc.compass(size=(wire_width, wire_width), layer=comb_layer)) obj.connect(port="N", destination=old_port) top = False else: # zig zag edge rectangle obj = CI.add_ref( pc.compass(size=(wire_width, wire_width), layer=comb_layer)) obj.connect(port="S", destination=old_port) top = True # comb rectange comb = CI.add_ref( pc.rectangle( size=( (padt.ymin - head.ymax) + pad_size[1] / 2 - (wire_spacing + wire_width) / 2, wire_width, ), layer=comb_layer, )) comb.rotate(90) comb.ymax = padt.ymin comb.xmax = obj.xmax - (wire_spacing + wire_width) / 2 old_port = obj.ports["E"] obj = CI.add_ref( pc.compass(size=(wire_spacing, wire_width), layer=comb_layer)) obj.connect(port="W", destination=old_port) old_port = obj.ports["E"] obj = CI.add_ref( pc.compass(size=(wire_width, wire_width), layer=comb_layer)) obj.connect(port="W", destination=old_port) if top: old_port = obj.ports["S"] else: old_port = obj.ports["N"] old_port = obj.ports["E"] if padr_nub.xmin - obj.xmax > 0: tail = CI.add_ref( pc.compass(size=(padr_nub.xmin - obj.xmax, wire_width), layer=comb_layer)) else: tail = CI.add_ref( pc.compass(size=(wire_width, wire_width), layer=comb_layer)) tail.connect(port="W", destination=old_port) # %% disconnected zig dhead = CI.add_ref( pc.compass( size=(padr_nub.ymin - padb.ymax - wire_width, wire_width), layer=overlap_zigzag_layer, )) dhead.rotate(90) dhead.ymin = padb.ymax dhead.xmax = tail.xmin - (wire_spacing + wire_width) / 2 connector = CI.add_ref( pc.compass(size=(wire_width, wire_width), layer=overlap_zigzag_layer)) connector.connect(port="S", destination=dhead.ports["E"]) old_port = connector.ports["N"] right = True obj = connector while obj.ymax + wire_spacing + wire_width < head.ymax: obj = CI.add_ref( pc.compass(size=(wire_spacing, wire_width), layer=overlap_zigzag_layer)) obj.connect(port="W", destination=old_port) old_port = obj.ports["E"] if right: obj = CI.add_ref( pc.compass(size=(wire_width, wire_width), layer=overlap_zigzag_layer)) obj.connect(port="W", destination=old_port) right = False else: obj = CI.add_ref( pc.compass(size=(wire_width, wire_width), layer=overlap_zigzag_layer)) obj.connect(port="E", destination=old_port) right = True old_port = obj.ports["N"] obj = CI.add_ref( pc.compass( size=( dhead.xmin - (head.xmax + head.xmin + wire_width) / 2, wire_width, ), layer=overlap_zigzag_layer, )) obj.connect(port="E", destination=old_port) old_port = obj.ports["W"] obj = CI.add_ref( pc.compass(size=(wire_width, wire_width), layer=overlap_zigzag_layer)) obj.connect(port="S", destination=old_port) if right: old_port = obj.ports["W"] else: old_port = obj.ports["E"] return CI
def test_via( num_vias=100, wire_width=10, via_width=15, via_spacing=40, pad_size=(300, 300), min_pad_spacing=0, pad_layer=0, wiring1_layer=1, wiring2_layer=2, via_layer=3, ): """ Via cutback to extract via resistance from phidl.geometry Args: num_vias=100 wire_width=10 via_width=15 via_spacing=40 pad_size=(300, 300) min_pad_spacing=0 pad_layer=0 wiring1_layer=1 wiring2_layer=2 via_layer=3 Usage: Call via_route_test_structure() by indicating the number of vias you want drawn. You can also change the other parameters however if you do not specifiy a value for a parameter it will just use the default value Ex:: via_route_test_structure(num_vias=54) - or -:: via_route_test_structure(num_vias=12, pad_size=(100,100),wire_width=8) total requested vias (num_vias) -> this needs to be even pad size (pad_size) -> given in a pair (width, height) wire_width -> how wide each wire should be pad_layer -> GDS layer number of the pads wiring1_layer -> GDS layer number of the top wiring wiring2_layer -> GDS layer number of the bottom wiring via_layer -> GDS layer number of the vias ex: via_route(54, min_pad_spacing=300) .. plot:: :include-source: import pp c = pp.c.test_via() pp.plotgds(c) """ VR = pp.Component() pad1 = VR.add_ref(pc.rectangle(size=pad_size, layer=pad_layer)) pad1_overlay = VR.add_ref(pc.rectangle(size=pad_size, layer=wiring1_layer)) pad2 = VR.add_ref(pc.rectangle(size=pad_size, layer=pad_layer)) pad2_overlay = VR.add_ref(pc.rectangle(size=pad_size, layer=wiring1_layer)) nub = VR.add_ref( pc.compass(size=(3 * wire_width, wire_width), layer=pad_layer)) nub_overlay = VR.add_ref( pc.compass(size=(3 * wire_width, wire_width), layer=wiring1_layer)) head = VR.add_ref( pc.compass(size=(wire_width, wire_width), layer=pad_layer)) head_overlay = VR.add_ref( pc.compass(size=(wire_width, wire_width), layer=wiring1_layer)) nub.ymax = pad1.ymax - 5 nub.xmin = pad1.xmax nub_overlay.ymax = pad1.ymax - 5 nub_overlay.xmin = pad1.xmax head.connect(port="W", destination=nub.ports["E"]) head_overlay.connect(port="W", destination=nub_overlay.ports["E"]) pad1_overlay.xmin = pad1.xmin pad1_overlay.ymin = pad1.ymin old_port = head.ports["S"] count = 0 width_via_iter = 2 * via_spacing - 2 * wire_width pad2.xmin = pad1.xmax + min_pad_spacing up = False down = True edge = True current_width = 3 * wire_width + wire_width # width of nub and 1 overlap obj_old = head obj = head via_iterable = _via_iterable( via_spacing=via_spacing, wire_width=wire_width, wiring1_layer=wiring1_layer, wiring2_layer=wiring2_layer, via_layer=via_layer, via_width=via_width, ) while (count + 2) <= num_vias: obj = VR.add_ref(via_iterable) obj.connect(port="W", destination=old_port, overlap=wire_width) old_port = obj.ports["E"] edge = False if obj.ymax > pad1.ymax: obj.connect(port="W", destination=obj_old.ports["S"], overlap=wire_width) old_port = obj.ports["S"] current_width += width_via_iter down = True up = False edge = True elif obj.ymin < pad1.ymin: obj.connect(port="W", destination=obj_old.ports["N"], overlap=wire_width) old_port = obj.ports["N"] current_width += width_via_iter up = True down = False edge = True count = count + 2 obj_old = obj if (current_width < min_pad_spacing and (min_pad_spacing - current_width) > 3 * wire_width): tail = VR.add_ref( pc.compass( size=(min_pad_spacing - current_width + wire_width, wire_width), layer=wiring1_layer, )) tail_overlay = VR.add_ref( pc.compass( size=(min_pad_spacing - current_width + wire_width, wire_width), layer=pad_layer, )) else: tail = VR.add_ref( pc.compass(size=(3 * wire_width, wire_width), layer=wiring1_layer)) tail_overlay = VR.add_ref( pc.compass(size=(3 * wire_width, wire_width), layer=wiring1_layer)) if up == True and edge != True: tail.connect(port="W", destination=obj.ports["S"], overlap=wire_width) tail_overlay.connect(port="W", destination=obj.ports["S"], overlap=wire_width) elif down == True and edge != True: tail.connect(port="W", destination=obj.ports["N"], overlap=wire_width) tail_overlay.connect(port="W", destination=obj.ports["N"], overlap=wire_width) else: tail.connect(port="W", destination=obj.ports["E"], overlap=wire_width) tail_overlay.connect(port="W", destination=obj.ports["E"], overlap=wire_width) pad2.xmin = tail.xmax pad2_overlay.xmin = pad2.xmin pad2_overlay.ymin = pad2.ymin return VR