def spiral_external_io(N: int = 6, x_inner_length_cutback: float = 300.0, x_inner_offset: float = 0.0, y_straight_inner_top: float = 0.0, dx: float = 3.0, dy: float = 3.0, bend90_function: Callable = bend_circular, bend180_function: Callable = bend_circular180, bend_radius: float = 50.0, wg_width: float = 0.5, straight_factory: Callable = waveguide, straight_factory_fall_back_no_taper: None = None, taper: Optional[Callable] = None, cutback_length: Optional[float] = None, **kwargs_round_corner) -> Component: """ Args: cutback_length: length in um, it is the approximates total length N: number of loops x_straight_inner_right: x_straight_inner_left: y_straight_inner_top: dx: center to center x-spacing dy: center to center y-spacing grating_coupler bend90_function bend180_function bend_radius wg_width straight_factory taper .. plot:: :include-source: import pp c = pp.c.spiral_external_io() pp.plotgds(c) """ if straight_factory_fall_back_no_taper is None: straight_factory_fall_back_no_taper = straight_factory if cutback_length: x_inner_length_cutback = cutback_length / (4 * (N - 1)) y_straight_inner_top += 5 x_inner_length_cutback += x_inner_offset _bend180 = pp.call_if_func(bend180_function, radius=bend_radius, width=wg_width) _bend90 = pp.call_if_func(bend90_function, radius=bend_radius, width=wg_width) rx, ry = get_bend_port_distances(_bend90) _, rx180 = get_bend_port_distances( _bend180) # rx180, second arg since we rotate component = pp.Component() inner_loop_spacing = 2 * bend_radius + 5.0 # Create manhattan path going from west grating to westest port of bend 180 x_inner_length = x_inner_length_cutback + 5.0 + dx y_inner_bend = y_straight_inner_top - bend_radius - 5.0 x_inner_loop = x_inner_length - 5.0 p1 = (x_inner_loop, y_inner_bend) p2 = (x_inner_loop + inner_loop_spacing, y_inner_bend) _pt = np.array(p1) pts_w = [_pt] for i in range(N): y1 = y_straight_inner_top + ry + (2 * i + 1) * dy x2 = inner_loop_spacing + 2 * rx + x_inner_length + (2 * i + 1) * dx y3 = -ry - (2 * i + 2) * dy x4 = -(2 * i + 1) * dx if i == N - 1: x4 = x4 - rx180 + dx _pt1 = np.array([_pt[0], y1]) _pt2 = np.array([x2, _pt1[1]]) _pt3 = np.array([_pt2[0], y3]) _pt4 = np.array([x4, _pt3[1]]) _pt5 = np.array([_pt4[0], 0]) _pt = _pt5 pts_w += [_pt1, _pt2, _pt3, _pt4, _pt5] pts_w = pts_w[:-2] # Create manhattan path going from east grating to eastest port of bend 180 _pt = np.array(p2) pts_e = [_pt] for i in range(N): y1 = y_straight_inner_top + ry + (2 * i) * dy x2 = inner_loop_spacing + 2 * rx + x_inner_length + 2 * i * dx y3 = -ry - (2 * i + 1) * dy x4 = -2 * i * dx _pt1 = np.array([_pt[0], y1]) _pt2 = np.array([x2, _pt1[1]]) _pt3 = np.array([_pt2[0], y3]) _pt4 = np.array([x4, _pt3[1]]) _pt5 = np.array([_pt4[0], 0]) _pt = _pt5 pts_e += [_pt1, _pt2, _pt3, _pt4, _pt5] pts_e = pts_e[:-2] # Join the two bits of paths and extrude the spiral geometry route = round_corners( pts_w[::-1] + pts_e, bend90=_bend90, straight_factory=straight_factory, straight_factory_fall_back_no_taper=straight_factory_fall_back_no_taper, taper=taper, **kwargs_round_corner, ) component.add(route["references"]) component.ports = route["ports"] length = route["settings"]["length"] component.length = length return component
def spiral_inner_io( N: int = 6, x_straight_inner_right: float = 150.0, x_straight_inner_left: float = 150.0, y_straight_inner_top: float = 50.0, y_straight_inner_bottom: float = 10.0, grating_spacing: float = 127.0, dx: float = 3.0, dy: float = 3.0, bend90_function: Callable = bend_circular, bend180_function: Callable = bend_circular180, bend_radius: float = 50.0, wg_width: float = 0.5, wg_width_grating_coupler: float = 0.5, straight_factory: Callable = waveguide, taper: Optional[Callable] = None, length: Optional[float] = None, ) -> Component: """Spiral with ports inside the spiral circle. Args: N: number of loops x_straight_inner_right: x_straight_inner_left: y_straight_inner_top: y_straight_inner_bottom: grating_spacing: dx: center to center x-spacing dy: center to center y-spacing bend90_function bend180_function bend_radius wg_width straight_factory taper: length: cm .. plot:: :include-source: import pp from pp.components.spiral_inner_io import spiral_inner_io c = spiral_inner_io() pp.plotgds(c) """ if length: if bend180_function == bend_circular180: y_straight_inner_top = get_straight_length( length_cm=length, spiral_function=spiral_inner_io, N=N, x_straight_inner_right=x_straight_inner_right, x_straight_inner_left=x_straight_inner_left, y_straight_inner_top=y_straight_inner_top, y_straight_inner_bottom=y_straight_inner_bottom, grating_spacing=grating_spacing, dx=dx, dy=dy, straight_factory=waveguide, bend90_function=bend_euler90, bend180_function=bend_euler180, wg_width=wg_width, ) else: y_straight_inner_top = get_straight_length( length_cm=length, spiral_function=spiral_inner_io_euler, N=N, x_straight_inner_right=x_straight_inner_right, x_straight_inner_left=x_straight_inner_left, y_straight_inner_top=y_straight_inner_top, y_straight_inner_bottom=y_straight_inner_bottom, grating_spacing=grating_spacing, dx=dx, dy=dy, wg_width=wg_width, ) _bend180 = pp.call_if_func(bend180_function, radius=bend_radius, width=wg_width) _bend90 = pp.call_if_func(bend90_function, radius=bend_radius, width=wg_width) rx, ry = get_bend_port_distances(_bend90) _, rx180 = get_bend_port_distances(_bend180) # rx180, second arg since we rotate component = pp.Component() # gc_port_lbl = "W0" # gc1 = _gc.ref(port_id=gc_port_lbl, position=(0, 0), rotation=-90) # gc2 = _gc.ref(port_id=gc_port_lbl, position=(grating_spacing, 0), rotation=-90) # component.add([gc1, gc2]) p1 = pp.Port( name="S0", midpoint=(0, y_straight_inner_top), orientation=270, width=wg_width, layer=pp.LAYER.WG, ) p2 = pp.Port( name="S1", midpoint=(grating_spacing, y_straight_inner_top), orientation=270, width=wg_width, layer=pp.LAYER.WG, ) taper = pp.c.taper( width1=wg_width_grating_coupler, width2=_bend180.ports["W0"].width, length=TAPER_LENGTH + y_straight_inner_top - 15 - 35, ) taper_ref1 = component.add_ref(taper) taper_ref1.connect("2", p1) taper_ref2 = component.add_ref(taper) taper_ref2.connect("2", p2) component.absorb(taper_ref1) component.absorb(taper_ref2) component.add_port(name="S0", port=taper_ref1.ports["1"]) component.add_port(name="S1", port=taper_ref2.ports["1"]) # Create manhattan path going from west grating to westest port of bend 180 _pt = np.array(p1.position) pts_w = [_pt] for i in range(N): y1 = y_straight_inner_top + ry + (2 * i + 1) * dy x2 = grating_spacing + 2 * rx + x_straight_inner_right + (2 * i + 1) * dx y3 = -y_straight_inner_bottom - ry - (2 * i + 3) * dy x4 = -x_straight_inner_left - (2 * i + 1) * dx if i == N - 1: x4 = x4 - rx180 + dx _pt1 = np.array([_pt[0], y1]) _pt2 = np.array([x2, _pt1[1]]) _pt3 = np.array([_pt2[0], y3]) _pt4 = np.array([x4, _pt3[1]]) _pt5 = np.array([_pt4[0], 0]) _pt = _pt5 pts_w += [_pt1, _pt2, _pt3, _pt4, _pt5] route_west = round_corners( pts_w, bend90=_bend90, straight_factory=straight_factory, taper=taper ) component.add(route_west["references"]) # Add loop back bend180_ref = _bend180.ref( port_id="W1", position=route_west["ports"]["output"], rotation=90 ) component.add(bend180_ref) component.absorb(bend180_ref) # Create manhattan path going from east grating to eastest port of bend 180 _pt = np.array(p2.position) pts_e = [_pt] for i in range(N): y1 = y_straight_inner_top + ry + (2 * i) * dy x2 = grating_spacing + 2 * rx + x_straight_inner_right + 2 * i * dx y3 = -y_straight_inner_bottom - ry - (2 * i + 2) * dy x4 = -x_straight_inner_left - (2 * i) * dx _pt1 = np.array([_pt[0], y1]) _pt2 = np.array([x2, _pt1[1]]) _pt3 = np.array([_pt2[0], y3]) _pt4 = np.array([x4, _pt3[1]]) _pt5 = np.array([_pt4[0], 0]) _pt = _pt5 pts_e += [_pt1, _pt2, _pt3, _pt4, _pt5] route_east = round_corners( pts_e, bend90=_bend90, straight_factory=straight_factory, taper=taper ) component.add(route_east["references"]) length = ( route_east["settings"]["length"] + route_west["settings"]["length"] + bend180_ref.info["length"] ) component.length = pp.drc.snap_to_1nm_grid(length + 2 * y_straight_inner_top) return component