Beispiel #1
0
        def _get_splitting_elem(self):

            pos_in = self.instances["in"].ports["out"].position
            pos_out_1 = self.instances["out1"].ports["in"].position
            pos_out_2 = self.instances["out2"].ports["in"].position

            wg_width = self.wg_template.core_width

            waypoint_shape_top = i3.Shape(points=[
                pos_in + i3.Coord2(0, wg_width / 2), pos_in +
                i3.Coord2(self.small_straights, wg_width /
                          2), self.waypoint, pos_out_2 +
                i3.Coord2(-self.small_straights, +wg_width / 2), pos_out_2 +
                i3.Coord2(0, +wg_width / 2)
            ])

            shape_top = SplinedShape(waypoint_shape=waypoint_shape_top,
                                     resolution=0.05)
            shape_top_m = shape_top.v_mirror_copy()

            start_parabole = i3.Coord2(self.split_base_pos,
                                       self.split_base_width / 2)
            end_parabole = pos_out_2 - i3.Coord2(self.small_straights,
                                                 wg_width / 2)

            x_parabole = np.linspace(start_parabole[0], end_parabole[0], 50)
            y_parabole = (end_parabole[1] - start_parabole[1]) * 1 / (
                end_parabole[0] - x_parabole[0])**0.5 * (
                    x_parabole - x_parabole[0])**0.5 + start_parabole[1]

            points_parabole = [
                i3.Coord2(x, y) for x, y in zip(x_parabole, y_parabole)
            ]
            points_parabole = [
                i3.Coord2(start_parabole[0], 0)
            ] + points_parabole + [pos_out_2 - i3.Coord2(0, wg_width / 2)]
            shape_parabole = i3.Shape(points=points_parabole)
            shape_parabole_m = shape_parabole.v_mirror_copy()

            shape_parabole_final = shape_parabole.reversed() + shape_parabole_m
            shape_parabole_final.remove_identicals()
            shape_bot = SplinedShape(
                waypoint_shape=i3.Shape(points=shape_parabole_final),
                resolution=0.05)

            shape_elem = shape_top + shape_bot + shape_top_m.reversed()
            shape_elem.remove_identicals()
            elem = i3.Boundary(layer=self.wg_template.core_layer,
                               shape=shape_elem)

            return elem
        def _generate_instances(self, insts):
            # First create shapes
            # Break the channel that contain two obstacles into three segments
            # Obstacles need to intersect these three segments
            #  Obs 1. Segment 1:2,   Obs 2 Segment 2:3
            #define points will be helpful to make schematic
            p1 = (self.cInp.x + 0.0, self.cInp.y + 0.0)
            p2 = ((self.gap_btw_barriers * 0.5 + self.obstacle_trap_radius),
                  0.0)
            p3 = ((self.gap_btw_barriers * 0.5 + self.obstacle_trap_radius),
                  self.gap_btw_barriers + self.obstacle_trap_radius * 2)
            p4 = (0.0, self.gap_btw_barriers + self.obstacle_trap_radius * 2)

            sr1 = i3.Shape(points=[p1, p2, p3, p4], closed=True)

            #Internal holes as Circles  #to do: define position of SC2 as a function of perpendicular GAP
            sc1 = i3.ShapeCircle(center=(self.cInp.x + 0.0,
                                         self.gap_btw_barriers * 0.5 +
                                         self.obstacle_trap_radius),
                                 radius=(self.obstacle_trap_radius))

            #Define the boundaries for shapes
            br1 = i3.Boundary(layer=self.layer, shape=sr1)

            bc1 = i3.Boundary(layer=self.layer, shape=sc1)

            #Substruct boundaries and add to the element list
            b_sub = br1 - bc1

            s = i3.Structure(elements=b_sub)
            insts += i3.SRef(s)

            return insts
Beispiel #3
0
        def _generate_instances(self, insts):
            delta = self.trace_template.core_width + self.spacing
            bend_radius = self.bend_radius
            coupler_length = self.cell.get_default_view(
                i3.CircuitModelView).coupler_length

            shape = i3.Shape([
                (-coupler_length / 2.0 - bend_radius, bend_radius),
                (-coupler_length / 2.0 - bend_radius, 0.0),
                (-coupler_length / 2.0, 0.0), (coupler_length / 2.0, 0.0),
                (coupler_length / 2.0 + bend_radius, 0.0),
                (coupler_length / 2.0 + bend_radius, bend_radius)
            ])

            wg = i3.RoundedWaveguide(name=self.name + "_wg",
                                     trace_template=self.trace_template)
            wg_layout = wg.Layout(shape=shape)

            insts += i3.SRef(reference=wg_layout,
                             name="wav_top",
                             position=(0, delta / 2.0))

            insts += i3.SRef(reference=wg_layout,
                             name="wav_bot",
                             transformation=i3.VMirror() +
                             i3.Translation(translation=(0, -delta / 2.0)))
            return insts
Beispiel #4
0
        def _generate_elements(self, elems):

            # Center of the structure
            (x0, y0) = self.position

            elems += i3.Rectangle(layer=self.layer, center=(x0 + 7500, y0 + 4500),
                                  box_size=(15000, 1000))

            # elems += i3.Rectangle(layer=i3.TECH.PPLAYER.NONE.DOC, center=(x0 + 7500, y0 + 4500),
            #                       box_size=(15000, 1000))

            elems += i3.Rectangle(layer=self.layer, center=(x0 + 7500, y0 + 500),
                                  box_size=(15000, 1000))
            elems += i3.Rectangle(layer=self.layer, center=(x0 + 12500+1000, y0 + 2500), #change
                                  box_size=(self.length, self.width))

            if self.pocket:
                PO = i3.Rectangle(layer=self.layer_bool, center=(10001+2000, 2500), box_size=(2, 160)) #change
                elems += PO
                generated1 = self.layer - self.layer_bool
                mapping = {generated1: self.layer}
                elems = i3.get_elements_for_generated_layers(elems, mapping)

            if self.tilt:
                # TI = i3.Rectangle(layer=self.layer_bool, center=(10001, 2500), box_size=(2, 160))
                # elems += TI
                TI_shape = i3.Shape(points=[(10000.0+2000, 2470.0), (10010.58+2000, 2530.0), (10000.0+2000, 2530.0)], closed=True) #change
                TI = i3.Boundary(layer=self.layer_bool, shape=TI_shape)
                elems += TI

            generated1 = self.layer - self.layer_bool
            mapping = {generated1: self.layer}
            elems = i3.get_elements_for_generated_layers(elems, mapping)

            return elems
Beispiel #5
0
        def _get_cladding_elem(self):

            shape_cladding = i3.Shape(
                points=[(self.length_straights, self.wg_template.width / 2),
                        (self.length_straights + self.length_splitting_shape,
                         self.spacing / 2 + self.wg_template.width / 2)])

            shape_cladding_m = i3.Shape(
                points=[(self.length_straights, -self.wg_template.width / 2),
                        (self.length_straights + self.length_splitting_shape,
                         -self.spacing / 2 - self.wg_template.width / 2)])

            shape_elem = shape_cladding + shape_cladding_m.reversed()

            elem = i3.Boundary(layer=self.wg_template.windows[1].layer,
                               shape=shape_elem)
            return elem
Beispiel #6
0
        def _default_wgs_straights(self):
            wgs_cells = self.cell.wgs_straights
            wgs_layout = []

            for wgc in wgs_cells:
                wg_layout = wgc.get_default_view(i3.LayoutView)
                wg_layout.set(shape=i3.Shape(
                    points=[(0, 0), (self.length_straights, 0)]))
                wgs_layout.append(wg_layout)

            return wgs_layout
Beispiel #7
0
def route_sbend(start_port, end_port, bend_radius=20.0):
    """
    Calculates an sbend between ports, returns the route and the used bend radius
    """
    ports = start_port, end_port
    points = []
    points.append(start_port.position)
    points.append(start_port.position.move_polar_copy(bend_radius, start_port.angle))
    points.append(end_port.position.move_polar_copy(bend_radius, end_port.angle))
    points.append(end_port.position)

    return i3.Shape(points)
Beispiel #8
0
    def __example(self):

        for i, y in enumerate(yvalues):
            x = dist / len(yvalues) * (i + 1)
            points.append((x, y))

        waypoint_shape = i3.Shape(points=points)
        splined_shape = SplinedShape(waypoint_shape=waypoint_shape)

        plt.figure()
        plt.plot(waypoint_shape.x_coords(), waypoint_shape.y_coords(), 'x', splined_shape.x_coords(), splined_shape.y_coords())
        plt.legend(['Orig', 'Interp'])
        plt.title('Spline of parametrically-defined curve')
        plt.show()
Beispiel #9
0
        def _generate_instances(self, elems):  # insts):
            channel1 = microfluidics.Channel(
                trace_template=self.cell.channel_template)
            channel1_lo = channel1.Layout(
                shape=i3.Shape([(0, -self.tee_length), (0, self.tee_length)]))
            elems += i3.SRef(channel1, position=(0, 0))

            channel2 = microfluidics.Channel(
                trace_template=self.cell.channel_template)
            channel2_lo = channel2.Layout(shape=[(0, 0), (-self.tee_length,
                                                          0)])
            elems += i3.SRef(channel2, position=(self.tee_length, 0))

            return elems  #insts
Beispiel #10
0
        def _generate_elements(self, insts):

            block_width = self.channel_template.channel_width

            point_list = []

            point_list.append((-self.block_length * 0.5, -block_width * 0.5))
            point_list.insert(0, (-self.block_length * 0.5, block_width * 0.5))

            point_list.append((self.block_length * 0.5, -block_width * 0.5))
            point_list.insert(0, (self.block_length * 0.5, block_width * 0.5))

            t = i3.Shape(point_list, closed=True)
            bo = i3.Boundary(i3.TECH.PPLAYER.CH2.TRENCH, t)
            insts += bo  #comm/uncomm for debugging round stl

            return insts
Beispiel #11
0
def get_waveguide_shape(start_port,
                        end_port,
                        way_points=[],
                        distance_straight=10.0):
    original_points = [
        start_port.position,
        start_port.move_polar_copy(distance_straight,
                                   start_port.angle).position
    ]
    original_points.extend(way_points)
    original_points.extend([
        end_port.move_polar_copy(distance_straight, end_port.angle).position,
        end_port.position
    ])
    original_shape = i3.Shape(points=original_points,
                              start_face_angle=start_port.angle,
                              end_face_angle=end_port.angle + 180.0)
    s2 = i3.ShapeFitClampedCubicSpline(original_shape=original_shape,
                                       discretisation=1)

    return s2
        def _generate_elements(self, elems):
            elems += i3.CirclePath(layer=i3.TECH.PPLAYER.CH2.TRENCH,
                                   center=(0.0, 0.0),
                                   radius=self.diameter * 0.5,
                                   line_width=50)

            point_list = []

            point_list.append((0, -self.diameter * 0.5))
            point_list.insert(0, (0, self.diameter * 0.5))
            point_list.append(
                (self.diameter * self.cell.reduction_ratio,
                 -self.diameter * 0.5 * self.cell.reduction_ratio))
            point_list.insert(
                0, (self.diameter * self.cell.reduction_ratio,
                    self.diameter * 0.5 * self.cell.reduction_ratio))

            funnel = i3.Shape(point_list, closed=True)
            bo = i3.Boundary(i3.TECH.PPLAYER.CH2.TRENCH, funnel)
            elems += bo

            return elems
Beispiel #13
0
        def _generate_instances(self, insts):
            # Generates taper pairs

            tp_name_list = []

            # temporary? pick taper properties
            taper_prop_dict = {
                'length': 79.0,
                'width1': 0.50,
                'width2': 6.50,
                'width_etch': 2.0
            }

            # generate a huge taper row
            tp_rows_layout = TaperPairRow().Layout(
                taper_prop_dict=taper_prop_dict,
                connect_length=0.0,
                pair_connect_length=10.0,
                n_pairs=self.n_pairs)

            # load the aim gds just to get its positions and stuff
            # main chip GDS
            fname = os.path.dirname(
                os.path.realpath(__file__)) + '/gds/ap_suny_v20a_chipframe.gds'
            main_chip_gds_cell = i3.GDSCell(filename=fname)

            # grab layout size info
            main_chip_gds_lay = main_chip_gds_cell.Layout()
            main_chip_gds_lay_size_info = main_chip_gds_lay.size_info()

            # grab relevant positions
            chip_edge_east = main_chip_gds_lay_size_info.east
            chip_edge_west = main_chip_gds_lay_size_info.west

            # make edge coupler and add to layout
            # edge coupler
            edge_coupler_gds_lay = EdgeCoupler(name=self.name +
                                               'edge_coupler_si').Layout()

            # add and route input/west edgecoupler
            # position edge coupler on west side of chip
            chip_port_west = i3.OpticalPort(position=(chip_edge_west, 0.0),
                                            angle_deg=0.0)
            edge_coupler_west_port = edge_coupler_gds_lay.ports['out']
            t = i3.vector_match_transform(edge_coupler_west_port,
                                          chip_port_west)
            edge_coupler_west_name = self.name + '_EDGE_COUPLER_WEST'
            west_edge_coupler = i3.SRef(name=edge_coupler_west_name,
                                        reference=edge_coupler_gds_lay,
                                        transformation=t,
                                        flatten=False)

            # add a small linear taper to go from 0.4 to 0.5um wg
            lin_taper_lay = LinearTaper().get_default_view(i3.LayoutView)
            lin_taper_lay.set(wg_width_in=0.4, wg_width_out=0.5, length=10.0)
            t = i3.vector_match_transform(lin_taper_lay.ports['in'],
                                          west_edge_coupler.ports['in'])
            lin_taper_lay_name = self.name + '_EDGETAPER_WEST'
            insts += i3.SRef(name=lin_taper_lay_name,
                             reference=lin_taper_lay,
                             transformation=t,
                             flatten=True)

            # add taper rows
            taper_row_name = self.name + '_TAPERSSSSSSSS'
            t = i3.vector_match_transform(
                tp_rows_layout.ports['left'],
                insts[lin_taper_lay_name].ports['out'])
            insts += i3.SRef(name=taper_row_name,
                             reference=tp_rows_layout,
                             transformation=t,
                             flatten=True)

            # add east coupler
            chip_port_east = i3.OpticalPort(position=(chip_edge_east, 0.0),
                                            angle_deg=180.0)
            edge_coupler_east_port = edge_coupler_gds_lay.ports['out']
            t = i3.vector_match_transform(edge_coupler_east_port,
                                          chip_port_east,
                                          mirrored=True)
            edge_coupler_east_name = self.name + '_EDGE_COUPLER_EAST'
            east_edge_coupler = i3.SRef(name=edge_coupler_east_name,
                                        reference=edge_coupler_gds_lay,
                                        transformation=t,
                                        flatten=False)

            # add a small linear taper to go from 0.4 to 0.5um wg
            lin_taper_lay = LinearTaper().get_default_view(i3.LayoutView)
            lin_taper_lay.set(wg_width_in=0.4, wg_width_out=0.5, length=10.0)
            t = i3.vector_match_transform(lin_taper_lay.ports['in'],
                                          east_edge_coupler.ports['in'],
                                          mirrored=True)
            lin_taper_lay_name = self.name + '_EDGETAPER_EAST'
            insts += i3.SRef(name=lin_taper_lay_name,
                             reference=lin_taper_lay,
                             transformation=t,
                             flatten=True)

            # route the east coupler to the east edge of the taper pairs
            route_wg_row_taper = i3.Shape([
                insts[taper_row_name].ports['right'].position,
                insts[lin_taper_lay_name].ports['out'].position
            ])
            wg_name = self.name + '_WG'
            wg_lay = i3.Waveguide(trace_template=StripWgTemplate(),
                                  name=wg_name).get_default_view(i3.LayoutView)
            wg_lay.set(shape=route_wg_row_taper)
            insts += i3.SRef(name=wg_name, reference=wg_lay, flatten=True)

            return insts
        def _generate_instances(self, insts):
            # Generates taper pairs w edge couplers

            # load the aim gds just to get its positions and stuff
            # main chip GDS
            fname = '../PDK_Library_Layout_GDS/ap_suny_v20a_chipframe.gds'
            main_chip_gds_cell = i3.GDSCell(filename=fname)

            # grab layout size info
            main_chip_gds_lay = main_chip_gds_cell.Layout()
            main_chip_gds_lay_size_info = main_chip_gds_lay.size_info()

            # grab relevant positions
            chip_edge_east = main_chip_gds_lay_size_info.east
            chip_edge_west = main_chip_gds_lay_size_info.west

            # make edge coupler
            edge_coupler_gds_lay = EdgeCoupler(name=self.name +
                                               'edge_coupler_sffdfi').Layout()

            # add and route input/west edgecoupler
            # position edge coupler on west side of chip
            chip_port_west = i3.OpticalPort(position=(chip_edge_west, 0.0),
                                            angle_deg=0.0)
            edge_coupler_west_port = edge_coupler_gds_lay.ports['out']
            t = i3.vector_match_transform(edge_coupler_west_port,
                                          chip_port_west)
            edge_coupler_west_name = self.name + '_EDGE_COUPLER_WEST'
            west_edge_coupler = i3.SRef(name=edge_coupler_west_name,
                                        reference=edge_coupler_gds_lay,
                                        transformation=t,
                                        flatten=False)

            # add a small linear taper to go from 0.4 to 0.5um wg
            lin_taper_lay = LinearTaper().get_default_view(i3.LayoutView)
            lin_taper_lay.set(wg_width_in=0.4, wg_width_out=0.5, length=10.0)
            t = i3.vector_match_transform(lin_taper_lay.ports['in'],
                                          west_edge_coupler.ports['in'])
            lin_taper_lay_name = self.name + '_EDGETAPER_WEST'
            insts += i3.SRef(name=lin_taper_lay_name,
                             reference=lin_taper_lay,
                             transformation=t,
                             flatten=True)

            # route wg to wg with arc
            bend_radius = 10.0
            arc_center_1 = (
                insts[lin_taper_lay_name].ports['out'].position[0],
                insts[lin_taper_lay_name].ports['out'].position[1] +
                bend_radius)
            route_wg_shape_arc1 = i3.ShapeArc(radius=bend_radius,
                                              angle_step=1.0,
                                              center=arc_center_1,
                                              start_angle=269.5,
                                              end_angle=0.5,
                                              closed=False,
                                              clockwise=False)
            wg_name_arc1 = self.name + '_ARC1'
            wg_lay_arc1 = i3.Waveguide(trace_template=StripWgTemplate(),
                                       name=wg_name_arc1).get_default_view(
                                           i3.LayoutView)
            wg_lay_arc1.set(shape=route_wg_shape_arc1)
            insts += i3.SRef(name=wg_name_arc1,
                             reference=wg_lay_arc1,
                             flatten=True)

            # add the bends
            bend_clip_lay = BendClip(
                name=self.name + '_BEND_CLIP').get_default_view(i3.LayoutView)
            bend_clip_lay.set(n_pairs=self.n_pairs)

            # add to insts
            bend_clip_lay_name = self.name + '_BEND_CLIP'
            t = i3.vector_match_transform(bend_clip_lay.ports['in'],
                                          insts[wg_name_arc1].ports['out'])
            insts += i3.SRef(name=bend_clip_lay_name,
                             reference=bend_clip_lay,
                             transformation=t,
                             flatten=True)

            # add output bend
            arc_center_2 = (
                insts[bend_clip_lay_name].ports['out'].position[0] +
                bend_radius,
                insts[bend_clip_lay_name].ports['out'].position[1])
            route_wg_shape_arc2 = i3.ShapeArc(radius=bend_radius,
                                              angle_step=1.0,
                                              center=arc_center_2,
                                              start_angle=180.5,
                                              end_angle=89.5,
                                              closed=False,
                                              clockwise=True)
            wg_name_arc2 = self.name + '_ARC2'
            wg_lay_arc2 = i3.Waveguide(trace_template=StripWgTemplate(),
                                       name=wg_name_arc2).get_default_view(
                                           i3.LayoutView)
            wg_lay_arc2.set(shape=route_wg_shape_arc2)
            insts += i3.SRef(name=wg_name_arc2,
                             reference=wg_lay_arc2,
                             flatten=True)

            # add east coupler
            chip_port_east = i3.OpticalPort(
                position=(chip_edge_east,
                          insts[wg_name_arc2].ports['out'].position[1]),
                angle_deg=180.0)
            edge_coupler_east_port = edge_coupler_gds_lay.ports['out']
            t = i3.vector_match_transform(edge_coupler_east_port,
                                          chip_port_east,
                                          mirrored=True)
            edge_coupler_east_name = self.name + '_EDGE_COUPLER_EAST'
            east_edge_coupler = i3.SRef(name=edge_coupler_east_name,
                                        reference=edge_coupler_gds_lay,
                                        transformation=t,
                                        flatten=False)

            # add a small linear taper to go from 0.4 to 0.5um wg
            lin_taper_lay = LinearTaper().get_default_view(i3.LayoutView)
            lin_taper_lay.set(wg_width_in=0.4, wg_width_out=0.5, length=10.0)
            t = i3.vector_match_transform(lin_taper_lay.ports['in'],
                                          east_edge_coupler.ports['in'],
                                          mirrored=True)
            lin_taper_lay_name = self.name + '_EDGETAPER_EAST'
            insts += i3.SRef(name=lin_taper_lay_name,
                             reference=lin_taper_lay,
                             transformation=t,
                             flatten=True)

            # route arc to arc with straight section
            route_wg_shape_out = i3.Shape([
                insts[wg_name_arc2].ports['out'].position,
                insts[lin_taper_lay_name].ports['out'].position
            ])
            wg_name_out = self.name + '_WG_CON_OUT'
            wg_lay_out = i3.Waveguide(trace_template=StripWgTemplate(),
                                      name=wg_name_out).get_default_view(
                                          i3.LayoutView)
            wg_lay_out.set(shape=route_wg_shape_out)
            insts += i3.SRef(name=wg_name_out,
                             reference=wg_lay_out,
                             flatten=True)

            return insts
        def _generate_instances(self, insts):
            # First create shapes
            # Break the block containig the feature into two segments
            # Block need to intersect these two segments
            #  Feature 1. Segment 1:2
            #define points will be helpful to make schematic
            p1 = ((self.feature_width + self.gap_horiz + self.vacuum_width) *
                  (-0.5), 0.0)
            p2 = (self.cInp.x + 0.0, self.cInp.y + 0.0)
            p3 = (self.cInp.x, self.feature_height * 0.5 + self.vacuum_width)
            p4 = ((self.feature_width + self.gap_horiz + self.vacuum_width) *
                  (-0.5), self.feature_height * 0.5 + self.vacuum_width)
            p5 = ((self.feature_width + self.gap_horiz + self.vacuum_width) *
                  (0.5), 0.0)
            p6 = ((self.feature_width + self.gap_horiz + self.vacuum_width) *
                  (0.5), self.feature_height * 0.5 + self.vacuum_width)
            p7 = ((self.feature_width + self.gap_horiz + self.vacuum_width) *
                  (-0.5), -(self.feature_height * 0.5 + self.vacuum_width))
            p8 = (self.cInp.x,
                  -(self.feature_height * 0.5 + self.vacuum_width))
            p9 = ((self.feature_width + self.gap_horiz + self.vacuum_width) *
                  (0.5), -(self.feature_height * 0.5 + self.vacuum_width))

            sr1 = i3.Shape(points=[p1, p2, p3, p4], closed=True)
            sr2 = i3.Shape(points=[p2, p5, p6, p3], closed=True)
            sr3 = i3.Shape(points=[p7, p8, p2, p1], closed=True)
            sr4 = i3.Shape(points=[p8, p9, p5, p2], closed=True)

            #Internal holes as Circles  #It is needed to define position of SC2 as a function of perpendicular GAP
            #sc1 = i3.ShapeCircle(center = (self.cInp.x+(self.gap_btw_barriers+self.obstacle_trap_length)*0.65, 0.0), radius = (self.obstacle_trap_width))
            #sc2 = i3.ShapeCircle(center = (self.cInp.x+(self.gap_btw_barriers+self.obstacle_trap_length)*1.35,self.cInp.y+self.channel_trap_width), radius = (self.obstacle_trap_width))

            #Internal holes as Rectangles
            sc1 = i3.ShapeRectangle(
                center=(self.cInp.x, self.cInp.y),
                box_size=(self.feature_width + self.gap_horiz,
                          self.feature_height + self.gap_vertical))

            #Define the boundaries for shapes
            br1 = i3.Boundary(layer=self.layer, shape=sr1)
            br2 = i3.Boundary(layer=self.layer, shape=sr2)
            br3 = i3.Boundary(layer=self.layer, shape=sr3)
            br4 = i3.Boundary(layer=self.layer, shape=sr4)

            bc1 = i3.Boundary(layer=self.layer, shape=sc1)

            #Substruct boundaries and add to the element list
            b_sub = br1 - bc1

            s = i3.Structure(elements=b_sub)
            insts += i3.SRef(s)

            b_sub = br2 - bc1
            b_sub = b_sub[0] - bc1

            s = i3.Structure(elements=b_sub)
            insts += i3.SRef(s)

            b_sub = br3 - bc1

            s = i3.Structure(elements=b_sub)
            insts += i3.SRef(s)

            b_sub = br4 - bc1

            s = i3.Structure(elements=b_sub)
            insts += i3.SRef(s)
            return insts
Beispiel #16
0
        def _generate_instances(self, insts):
            # Generates taper clip

            # make my OWN custom waveguide trace template
            # wg_trace = f_MyIMECWaveguideTemplate(core_width=self.taper_prop_dict['width1'],
            #                                      cladding_width=self.taper_prop_dict['width1'] + 2.0 * self.taper_prop_dict['width_etch'])

            # make waveguide
            wg = i3.Waveguide(trace_template=StripWgTemplate(),
                              name=self.name + '_WG')
            wg_round = i3.RoundedWaveguide(trace_template=StripWgTemplate(),
                                           name=self.name + '_WG_ROUND')

            # how much to translate bends left/right
            # t_left = i3.Translation((self.bend_radius + (float(self.n_rows)/2.0) ))
            t_left = i3.Translation((-2.5 * self.bend_radius, 0.0))
            t_right = i3.Translation((2.5 * self.bend_radius, 0.0))

            # draw taper pair rows
            for ii in range(self.n_rows):

                # add rows
                tp_rows_layout = TaperPairRow(name=self.name + '_TProw' +
                                              str(ii)).get_default_view(
                                                  i3.LayoutView)
                tp_rows_layout.set(
                    taper_prop_dict=self.taper_prop_dict,
                    connect_length=self.connect_length,
                    pair_connect_length=self.pair_connect_length,
                    n_pairs=self.n_taper_pairs_per_row)

                # set translation
                t = i3.Translation((0.0, float(ii) * self.row_spacing))

                # place taper pair row
                tp_row_name = self.name + '_TP_ROW' + str(ii)
                insts += i3.SRef(name=tp_row_name,
                                 reference=tp_rows_layout,
                                 transformation=t)

                # draw connecting arcs
                if ii > 0:

                    if (ii % 2) == 1:
                        # bend on the right
                        # make shape bend
                        row_name = self.name + '_TP_ROW' + str(ii - 1)
                        shape_bend = i3.ShapeBend(start_point=insts[row_name].
                                                  ports['right'].position,
                                                  radius=self.bend_radius,
                                                  start_angle=-90.05,
                                                  end_angle=90.05,
                                                  angle_step=0.1)

                        # add 180 deg bend
                        wg_copy = i3.Waveguide(
                            trace_template=StripWgTemplate(),
                            name=self.name + '_arc_r' + str(ii))
                        arc_name = self.name + '_arc' + str(ii)
                        insts += i3.SRef(
                            name=arc_name,
                            reference=wg_copy.Layout(shape=shape_bend),
                            transformation=t_right)

                        # connect bottom wgs

                        # get coords
                        in_port_coords = insts[arc_name].ports['in'].position
                        out_port_coords = insts[row_name].ports[
                            'right'].position

                        # draw bezier curve
                        bez = BezierCurve(
                            N=100,
                            P0=(in_port_coords[0] + 0.01, in_port_coords[1]),
                            P1=(in_port_coords[0] - self.bend_radius / 2.0,
                                in_port_coords[1]),
                            P2=(out_port_coords[0] + self.bend_radius / 2.0,
                                out_port_coords[1]),
                            P3=(out_port_coords[0] - 0.01, out_port_coords[1]),
                            R=(-self.bend_radius, +self.bend_radius),
                            dy_dx=(0.0, -0.0))
                        bez_coords = bez.bezier_coords()

                        # make ipkiss shape
                        s = i3.Shape(bez_coords)

                        # add bottom wg connector
                        wg_copy = i3.Waveguide(
                            trace_template=StripWgTemplate(),
                            name=self.name + '_arc_r_con' + str(ii))
                        insts += i3.SRef(name=self.name + '_con_wg_r_b_' +
                                         str(ii),
                                         reference=wg_copy.Layout(shape=s))

                        # connect top wgs
                        next_row_name = self.name + '_TP_ROW' + str(ii)
                        in_port_coords = insts[arc_name].ports['out'].position
                        out_port_coords = insts[next_row_name].ports[
                            'right'].position

                        # draw bezier curve
                        bez = BezierCurve(
                            N=500,
                            P0=(in_port_coords[0] + 0.01, in_port_coords[1]),
                            P1=(in_port_coords[0] - self.bend_radius / 2.0,
                                in_port_coords[1]),
                            P2=(out_port_coords[0] + self.bend_radius / 2.0,
                                out_port_coords[1]),
                            P3=(out_port_coords[0] - 0.01, out_port_coords[1]),
                            R=(self.bend_radius, -self.bend_radius),
                            dy_dx=(0.0, -0.0))
                        bez_coords = bez.bezier_coords()

                        # make ipkiss shape
                        s = i3.Shape(bez_coords)

                        # add wg bend
                        wg_copy = i3.Waveguide(
                            trace_template=StripWgTemplate(),
                            name=self.name + '_bez_r' + str(ii))
                        insts += i3.SRef(name=self.name + '_con_wg_r_t_' +
                                         str(ii),
                                         reference=wg_copy.Layout(shape=s))

                    else:
                        # bend on the left
                        # make shape bend
                        row_name = self.name + '_TP_ROW' + str(ii - 1)
                        shape_bend = i3.ShapeBend(start_point=(
                            insts[row_name].ports['left'].position),
                                                  radius=self.bend_radius,
                                                  start_angle=90.05,
                                                  end_angle=-90.05,
                                                  angle_step=0.1,
                                                  clockwise=False)

                        # add 180 deg bend
                        wg_copy = i3.Waveguide(
                            trace_template=StripWgTemplate(),
                            name=self.name + '_arc_l' + str(ii))
                        arc_name = self.name + '_arc' + str(ii)
                        insts += i3.SRef(
                            name=arc_name,
                            reference=wg_copy.Layout(shape=shape_bend),
                            transformation=t_left)

                        # connect bottom wgs

                        # get coords
                        in_port_coords = insts[arc_name].ports['out'].position
                        out_port_coords = insts[row_name].ports[
                            'left'].position

                        # draw bezier curve
                        bez = BezierCurve(
                            N=100,
                            P0=(in_port_coords[0] - 0.01, in_port_coords[1]),
                            P1=(in_port_coords[0] + self.bend_radius / 2.0,
                                in_port_coords[1]),
                            P2=(out_port_coords[0] - self.bend_radius / 2.0,
                                out_port_coords[1]),
                            P3=(out_port_coords[0] + 0.01, out_port_coords[1]),
                            R=(-self.bend_radius, +self.bend_radius),
                            dy_dx=(0.0, -0.0))
                        bez_coords = bez.bezier_coords()

                        # make ipkiss shape
                        s = i3.Shape(bez_coords)

                        # add bottom wg connector
                        wg_copy = i3.Waveguide(
                            trace_template=StripWgTemplate(),
                            name=self.name + '_arc_l_con' + str(ii))
                        insts += i3.SRef(name=self.name + '_con_wg_l_b_' +
                                         str(ii),
                                         reference=wg_copy.Layout(shape=s))

                        # connect top wgs
                        next_row_name = self.name + '_TP_ROW' + str(ii)
                        in_port_coords = insts[arc_name].ports['in'].position
                        out_port_coords = insts[next_row_name].ports[
                            'left'].position

                        # draw bezier curve
                        bez = BezierCurve(
                            N=500,
                            P0=(in_port_coords[0] - 0.01, in_port_coords[1]),
                            P1=(in_port_coords[0] + self.bend_radius / 2.0,
                                in_port_coords[1]),
                            P2=(out_port_coords[0] - self.bend_radius / 2.0,
                                out_port_coords[1]),
                            P3=(out_port_coords[0] + 0.01, out_port_coords[1]),
                            R=(-self.bend_radius, +self.bend_radius),
                            dy_dx=(0.0, -0.0))
                        bez_coords = bez.bezier_coords()

                        # make ipkiss shape
                        s = i3.Shape(bez_coords)

                        # add wg bend
                        wg_copy = i3.Waveguide(
                            trace_template=StripWgTemplate(),
                            name=self.name + '_bez_l' + str(ii))
                        insts += i3.SRef(name=self.name + '_con_wg_l_t_' +
                                         str(ii),
                                         reference=wg_copy.Layout(shape=s))

                    # end if bend

                # end drawing connecting arcs

            # end for ii in range(self.rows)

            # # connect the input grating
            # # pick grating layout to return
            # grating_layout = {
            #     'FGCCTE_FC1DC_625_313':     FGCCTE_FC1DC_625_313().Layout(),
            #     'FGCCTE_FCWFC1DC_630_378':  FGCCTE_FCWFC1DC_630_378().Layout(),
            #     'FGCCTM_FC1DC_984_492':     FGCCTM_FC1DC_984_492().Layout(),
            # }[self.grating_name]
            #
            #
            #
            # # place bottom grating
            # # always assuming bottom grating starts on the left
            # bot_grating_name = self.name+'_bot_grating'
            # t = i3.vector_match_transform( grating_layout.ports['waveguide'],
            #                                insts[self.name + '_TP_ROW0'].ports['left'] ) + \
            #     i3.Translation( ( -self.bot_gc_connect_length, 0.0 ) )
            #
            # insts += i3.SRef(   name            = bot_grating_name,
            #                     reference       = grating_layout,
            #                     transformation  = t )
            #
            # # connect bottom grating to taper
            # route_wg_bot = i3.RouteManhattan( input_port  = insts[bot_grating_name].ports['waveguide'],
            #                                   output_port = insts[self.name + '_TP_ROW0'].ports['left'] )
            #
            # # add wg
            # wg_bot = i3.Waveguide( trace_template = StripWgTemplate(), name = self.name + '_WG_BOT')
            # insts += i3.SRef(name=self.name + '_connect_wg_bot', reference=wg_bot.Layout(shape=route_wg_bot))
            #
            #
            #
            # # place top grating
            # top_grating_name = self.name + '_top_grating'
            # if (self.n_rows % 2) == 1:
            #     # even # of rows, output is to the right
            #     t = i3.vector_match_transform(  grating_layout.ports['waveguide'],
            #                                     insts[self.name + '_TP_ROW' + str(self.n_rows-1)].ports['right'],
            #                                     mirrored = True ) + \
            #         i3.Translation((self.top_gc_connect_length, 0.0))
            #
            #     insts += i3.SRef( name              = top_grating_name,
            #                       reference         = grating_layout,
            #                       transformation    = t)
            #
            #     # connect top grating to taper
            #     route_wg_top = i3.RouteManhattan(   input_port  = insts[top_grating_name].ports['waveguide'],
            #                                         output_port = insts[self.name + '_TP_ROW' + str(self.n_rows-1)].ports['right'])
            #
            #     # add wg
            #     wg_top = i3.Waveguide( trace_template = StripWgTemplate(), name = self.name + '_WG_TOP')
            #     insts += i3.SRef(name=self.name + '_connect_wg_top', reference=wg_top.Layout(shape=route_wg_top))
            #
            # else:
            #     # odd # of rows, output is to the left
            #     t = i3.vector_match_transform(  grating_layout.ports['waveguide'],
            #                                     insts[self.name + '_TP_ROW' + str(self.n_rows-1)].ports['left'],
            #                                     mirrored = False ) + \
            #         i3.Translation((-self.top_gc_connect_length, 0.0))
            #
            #     insts += i3.SRef( name              = top_grating_name,
            #                       reference         = grating_layout,
            #                       transformation    = t)
            #
            #     # connect top grating to taper
            #     route_wg_top = i3.RouteManhattan(   input_port  = insts[top_grating_name].ports['waveguide'],
            #                                         output_port = insts[self.name + '_TP_ROW' + str(self.n_rows-1)].ports['left'])
            #
            #     # add wg
            #     wg_top = i3.Waveguide( trace_template = StripWgTemplate(), name = self.name + '_WG_TOP')
            #     insts += i3.SRef(name=self.name + '_connect_wg_top', reference=wg_top.Layout(shape=route_wg_top))

            return insts
Beispiel #17
0
d_phi = np.pi / 2.
delay_length = d_phi * wavelength / (2 * np.pi * n_eff)

mzm = demo.TW_MZM()
lay = mzm.Layout(delta=50., additional_length=150., delay=delay_length)

fig = lay.visualize(annotate=True, show=False)
fig.canvas.set_window_title('Modulator layout')

fig = lay.visualize_2d(show=False)
fig.canvas.set_window_title('Virtual fabrication of the modulator')
ax = fig.get_axes()[0]
ax.vlines(0, -75, 75)
ax.annotate('Cross-section',
            xy=(0, 0),
            xytext=(100, 100),
            arrowprops=dict(facecolor='black', shrink=0.05))

xs = lay.cross_section(cross_section_path=i3.Shape([(0., -75.), (0., 75.)]),
                       path_origin=-75.)
fig = xs.visualize(show=False)
fig.canvas.set_window_title('Cross-section from y=-75 --> y=75 um.')

xs = lay.cross_section(cross_section_path=i3.Shape([(0., 36.), (0., 60.)]),
                       path_origin=36.)
fig = xs.visualize(show=False)
fig.canvas.set_window_title('Cross-section from y=36 --> y=60 um.')

from pylab import plt
plt.show()
Beispiel #18
0
 def _default_wg1b_shape(self):
     return i3.Shape(points=[(0, -self.coupler_spacing / 2), (+1 * self.bend_radius + self.coupler_length / 2, -self.coupler_spacing / 2)])
# generated_layout = i3.LayoutCell("generated_mask").Layout(elements=generated_elements)
# generated_layout.visualize()
# generated_layout.write_gdsii("boolean_ops_photonics.gds")

# use as a generated mask layer
generated_elements = get_elements_for_generated_layers(
    ring_lo.layout, {wg_mask: TECH.PPLAYER.NONE.DOC})
generated_layout = i3.LayoutCell("generated_mask").Layout(
    elements=generated_elements)
generated_layout.visualize()
generated_layout.write_gdsii("boolean_ops_photonics.gds")

# define a virtual fabrication flow, using the material stacks in the silicon_photonics technology
vfab_process = VFabricationProcessFlow(
    active_processes=[wg_process],
    process_layer_map={wg_process: wg_mask},
    is_lf_fabrication={wg_process: False},
    process_to_material_stack_map=[
        ((0, ), TECH.MATERIAL_STACKS.MSTACK_SOI_SI_220nm),
        ((1, ), TECH.MATERIAL_STACKS.MSTACK_SOI_SI_100nm),
    ])
# visualize the result of the virtual fabrication
# top-down
ring_lo.visualize_2d(vfabrication_process_flow=vfab_process)
ring_xs = ring_lo.cross_section(process_flow=vfab_process,
                                cross_section_path=i3.Shape([(0.0, 4.0),
                                                             (0.0, 7.0)]))
ring_xs.visualize()

# generated_layout.visualize(vfabrication_process_flow=vfab_process)
# generated_layout.write_gdsii("boolean_ops_photonics.gds")
        def _generate_elements(self, elems):
            cell_trap_width = self.channel_template.channel_width
            entry_Lfd = self.cell_trap_length * 0.5  # 1000.0
            exit_Lfd = self.cell_trap_length * 0.5  # 500.0
            beta = math.radians(self.out_angle)

            lf = self.funnel_length
            wi = cell_trap_width
            wf = self.cell_trap_gap
            #lfd = 0

            taper_samples = 200
            a = lf / (wi / wf - 1.0)

            dx = lf / taper_samples
            x = 0.0
            xl = []
            wl = []

            point_list = []
            x_offset = self.funnel_length + self.cell_trap_gap_length  # all expansion will be at 0.0x
            a = 0.5
            b = .35
            point_list.append(
                self.cInp +
                (-(self.cell_trap_length * b), wi * 0.5))  # end of array
            point_list.insert(0, self.cInp +
                              (-(self.cell_trap_length * b),
                               -wi * 0.5))  # begging of array, position 0

            for i in reversed(range(1, taper_samples + 1)):
                #xa = lf * math.exp(10.0 * (i / taper_samples - 1.0))  #discretization
                radius = 0.5 * wi  ### this needs to be improved
                xa = (radius) * math.cos(0.5 * math.pi * i / taper_samples)
                #w = wi / (1.0 + xa / a)    #function value
                w = (radius) * math.sin(0.5 * math.pi * i / taper_samples)
                p = (xa - radius - self.cell_trap_gap_length * 0.5,
                     0.5 * (w + 0.5 * wi))
                point_list.append(self.cInp + p)
                p = (xa - radius - self.cell_trap_gap_length * 0.5,
                     -0.5 * (w + 0.5 * wi))
                point_list.insert(0, self.cInp + p)

            # GAP LENGTH
            p = (
                point_list[-1][0], wf * 0.5
            )  #wGet last point, coordX use it for next point with wf as coordY
            point_list.append(self.cInp +
                              p)  # Insert it at the bottom of point_list
            p = point_list[-1] + (0.0, (-wf))  # Get last point, add -wf
            point_list.insert(0, self.cInp +
                              p)  # Insert it at the bottom of point_list

            p = point_list[-1] + (self.cell_trap_gap_length, 0.0
                                  )  # Get last point and add length
            point_list.append(self.cInp +
                              p)  # Insert it at [0] in the point_list

            p = point_list[-1] + (0.0, -wf)  # Get last point and add length
            point_list.insert(0, self.cInp +
                              p)  # Insert it at [0] in the point_list

            # EXIT ANGLE
            p = point_list[-1] + (
                0.5 * (cell_trap_width - self.cell_trap_gap) / math.tan(beta),
                -cell_trap_width * 0.5 - wf * .50
            )  # Get last point and add length of angle
            point_list.insert(0, self.cInp +
                              p)  # Insert it at [0] in the point_list

            p = point_list[0] + (0, wi)
            point_list.append(self.cInp +
                              p)  # Insert it at the bottom of point_list

            # EXIT LENGTH
            p = (self.cell_trap_length * b, point_list[-1][1]
                 )  # get first point (last point added) and add length
            point_list.append(self.cInp + p)

            p = point_list[-1] + (0, -wi)  ##get last point and add length
            point_list.insert(0, self.cInp + p)

            t = i3.Shape(point_list, closed=True)

            rectang = i3.ShapeRound(original_shape=t,
                                    start_face_angle=0,
                                    end_face_angle=0,
                                    radius=self.radius_fillet)
            bo = i3.Boundary(self.channel_template.layer, rectang)

            #creating an inlet rectangle boundary to avoid round corners
            point_list = []
            point_list.append(
                (-self.cell_trap_length * a, -cell_trap_width * 0.5))
            point_list.insert(
                0, (-self.cell_trap_length * a, cell_trap_width * 0.5))

            point_list.append((-self.cell_trap_length * b + self.radius_fillet,
                               -cell_trap_width * 0.5))
            point_list.insert(0,
                              (-self.cell_trap_length * b + self.radius_fillet,
                               cell_trap_width * 0.5))

            t = i3.Shape(point_list, closed=True)
            bo1 = i3.Boundary(self.channel_template.layer, t)

            #creating an outlet rectangle boundary to avoid round corners
            point_list = []
            point_list.append((self.cell_trap_length * b - self.radius_fillet,
                               -cell_trap_width * 0.5))
            point_list.insert(0,
                              (self.cell_trap_length * b - self.radius_fillet,
                               cell_trap_width * 0.5))

            point_list.append(
                (self.cell_trap_length * a, -cell_trap_width * 0.5))
            point_list.insert(
                0, (self.cell_trap_length * a, cell_trap_width * 0.5))

            t = i3.Shape(point_list, closed=True)
            bo2 = i3.Boundary(self.channel_template.layer, t)

            #boolean operation adding main geometry and inlet rectangle
            b_add = bo | bo1

            #boolean operation adding main geometry and outlet rectangle
            b_add2 = b_add[0] | bo2
            #s2 = i3.Structure(elements=b_add2)
            elems += b_add2
            #insts += bo
            return elems
        def _generate_elements(self, elems):

            cell_trap_width = self.channel_template.channel_width

            alpha = math.radians(self.in_angle)
            beta = math.radians(self.out_angle)

            point_list = []

            point_list.append(
                (-self.cell_trap_length * 0.25, -cell_trap_width * 0.5))
            point_list.insert(
                0, (-self.cell_trap_length * 0.25, cell_trap_width * 0.5))

            point_list.append(
                (-(cell_trap_width - self.cell_trap_gap) / math.tan(alpha) -
                 self.cell_trap_gap_length * 0.5, -(cell_trap_width * 0.5)))
            point_list.insert(
                0, (-(cell_trap_width - self.cell_trap_gap) / math.tan(alpha) -
                    self.cell_trap_gap_length * 0.5, (cell_trap_width * 0.5)))

            point_list.append((-self.cell_trap_gap_length * 0.25,
                               -self.cell_trap_gap * 0.5))  # end of array
            point_list.insert(
                0, (-self.cell_trap_gap_length * 0.25,
                    self.cell_trap_gap * 0.5))  # begging of array, position 0

            point_list.append(
                (self.cell_trap_gap_length * 0.25, -self.cell_trap_gap * 0.5))
            point_list.insert(
                0,
                (self.cell_trap_gap_length * 0.25, self.cell_trap_gap * 0.5))

            point_list.append(
                ((cell_trap_width - self.cell_trap_gap) / math.tan(beta) +
                 self.cell_trap_gap_length * 0.25, -(cell_trap_width * 0.5)))
            point_list.insert(
                0, ((cell_trap_width - self.cell_trap_gap) / math.tan(beta) +
                    self.cell_trap_gap_length * 0.25, (cell_trap_width * 0.5)))

            point_list.append(
                (-self.cell_trap_length * 0.25 + self.cell_trap_length * 0.5,
                 -cell_trap_width * 0.5))
            point_list.insert(
                0,
                (-self.cell_trap_length * 0.25 + self.cell_trap_length * 0.5,
                 cell_trap_width * 0.5))

            t = i3.Shape(point_list, closed=True)

            rectang = i3.ShapeRound(original_shape=t,
                                    start_face_angle=0,
                                    end_face_angle=0,
                                    radius=self.radius_fillet)
            bo = i3.Boundary(self.channel_template.layer, rectang)
            #insts += bo  #comm/uncomm for debugging round stl

            #creating an inlet rectangle boundary to avoid round corners
            point_list = []
            #w = 3
            point_list.append(
                (-self.cell_trap_length * 0.5, -cell_trap_width * 0.5))
            point_list.insert(
                0, (-self.cell_trap_length * 0.5, cell_trap_width * 0.5))

            point_list.append(
                (-self.cell_trap_length * 0.25 + self.radius_fillet,
                 -cell_trap_width * 0.5))
            point_list.insert(0, (-self.cell_trap_length * 0.25 +
                                  self.radius_fillet, cell_trap_width * 0.5))

            t = i3.Shape(point_list, closed=True)
            bo1 = i3.Boundary(self.channel_template.layer, t)

            #creating an outlet rectangle boundary to avoid round corners
            point_list = []
            point_list.append(
                (self.cell_trap_length * 0.25 - self.radius_fillet,
                 -cell_trap_width * 0.5))
            point_list.insert(0, (self.cell_trap_length * 0.25 -
                                  self.radius_fillet, cell_trap_width * 0.5))

            point_list.append(
                (self.cell_trap_length * 0.5, -cell_trap_width * 0.5))
            point_list.insert(0,
                              (-self.cell_trap_length * 0.5 +
                               self.cell_trap_length, cell_trap_width * 0.5))

            t = i3.Shape(point_list, closed=True)
            bo2 = i3.Boundary(self.channel_template.layer, t)

            #boolean operation adding main geometry and inlet rectangle
            b_add = bo1 | bo

            #boolean operation adding main geometry and outlet rectangle
            b_add2 = bo2 | b_add[0]
            elems += b_add2
            return elems
Beispiel #22
0
        def _generate_instances(self, insts):
            # First create shapes
            # Break the channel that contain two obstacles into three segments
            # Obstacles need to intersect these three segments
            #  Obs 1. Segment 1:2,   Obs 2 Segment 2:3
            #define points will be helpful to make schematic
            p1 = (self.cInp.x+0.0,self.cInp.y+0.0)
            p2 = ((self.gap_btw_barriers+self.obstacle_trap_length)*0.5,0.0)
            p3 = ((self.gap_btw_barriers+self.obstacle_trap_length)*0.5,self.channel_trap_width)
            p4 = (0.0,self.channel_trap_width)
            p5 = ((self.gap_btw_barriers+self.obstacle_trap_length)*1.5, 0.0)
            p6 = ((self.gap_btw_barriers+self.obstacle_trap_length)*2, 0.0)
            p7 = ((self.gap_btw_barriers+self.obstacle_trap_length)*2, self.channel_trap_width)
            p8 = ((self.gap_btw_barriers+self.obstacle_trap_length)*1.5,self.channel_trap_width)

            sr1 = i3.Shape(points = [p1,p2,p3,p4], closed =True)
            sr2 = i3.Shape(points = [p2,p5,p8,p3], closed =True)
            sr3 = i3.Shape(points = [p5,p6,p7,p8], closed =True)

            #Internal holes as Circles  #to do: define position of SC2 as a function of perpendicular GAP
            sc1 = i3.ShapeCircle(center = (self.cInp.x+(self.gap_btw_barriers+self.obstacle_trap_length)*0.65, 0.0), radius = (self.obstacle_trap_width))
            sc2 = i3.ShapeCircle(center = (self.cInp.x+(self.gap_btw_barriers+self.obstacle_trap_length)*1.35,self.cInp.y+self.channel_trap_width), radius = (self.obstacle_trap_width))

            #Internal holes as Rectangles
            '''
            sc1 = i3.ShapeRectangle(center = (self.cInp.x+(self.gap_btw_barriers
                                                           +self.obstacle_trap_length)*0.5,
                                              self.cInp.y+self.obstacle_trap_width*0.5),
                                    box_size = (self.obstacle_trap_length,
                                                self.obstacle_trap_width))
            sc2 = i3.ShapeRectangle(center = (self.cInp.x+(self.gap_btw_barriers
                                                           +self.obstacle_trap_length)*1.5,
                                              self.cInp.y+self.channel_trap_width-self.obstacle_trap_width*0.5),
                                    box_size = (self.obstacle_trap_length,
                                                self.obstacle_trap_width))
            '''
            #Define the boundaries for shapes
            br1 = i3.Boundary(layer = self.layer, shape = sr1)
            br2 = i3.Boundary(layer = self.layer, shape = sr2)
            br3 = i3.Boundary(layer = self.layer, shape = sr3)

            bc1 = i3.Boundary(layer = self.layer, shape = sc1)
            bc2 = i3.Boundary(layer = self.layer, shape = sc2)

            #Substruct boundaries and add to the element list
            b_sub = br1-bc1

            s= i3.Structure(elements = b_sub)
            insts += i3.SRef(s)

            b_sub = br2-bc1
            b_sub = b_sub[0] - bc2

            s= i3.Structure(elements = b_sub)
            insts += i3.SRef(s)

            b_sub = br3-bc2

            s= i3.Structure(elements = b_sub)
            insts += i3.SRef(s)

            return insts
from siepicfab import all as pdk
from ipkiss3 import all as i3
import numpy as np
import pylab as plt

splitter = pdk.EbeamY1550()

# 1. Layout
splitter_layout = splitter.Layout()
splitter_layout.visualize(annotate=True)
splitter_layout.visualize_2d()
splitter_layout.cross_section(
    cross_section_path=i3.Shape([(-0.5, -1.5), (-0.5, 1.5)])).visualize()

# 2. Circuit
splitter_circuit = splitter.CircuitModel()

# 3. Plotting
wavelengths = np.linspace(1.5, 1.58, 51)
S = splitter_circuit.get_smatrix(wavelengths=wavelengths)
plt.plot(wavelengths,
         10 * np.log10(np.abs(S["opt2", "opt1"])**2),
         '-',
         linewidth=2.2,
         label="T(opt2)")
plt.plot(wavelengths,
         10 * np.log10(np.abs(S["opt3", "opt1"])**2),
         '-',
         linewidth=2.2,
         label="T(opt1)")
plt.ylim(-5., 0.)