def produce_impl(self):
        import math
        try:
            from SiEPIC.utils.layout import layout_waveguide_sbend, layout_taper
        except:
            from siepic_tools.utils.layout import layout_waveguide_sbend, layout_taper

        # fetch the parameters
        dbu = self.layout.dbu
        ly = self.layout
        shapes = self.cell.shapes

        LayerSi = self.layer
        LayerSiN = ly.layer(LayerSi)
        LayerPinRecN = ly.layer(self.pinrec)
        LayerDevRecN = ly.layer(self.devrec)

        from SiEPIC.extend import to_itype

        # Draw the Bragg grating (bottom):
        box_width = int(round(self.grating_period / 2 / dbu))
        grating_period = int(round(self.grating_period / dbu))

        w = to_itype(self.wg1_width, dbu)
        GaussianIndex = self.apodization_index
        half_w = w / 2
        half_corrugation_w = to_itype(self.corrugation_width1 / 2, dbu)

        y_offset_top = -w / 2 - to_itype(self.gap / 2, dbu)

        if self.AR:
            misalignment = grating_period / 2
        else:
            misalignment = 0

        N = self.number_of_periods
        if self.sinusoidal:
            npoints_sin = 40
            for i in range(0, self.number_of_periods):
                x = (round((i * self.grating_period) / dbu))
                profileFunction = math.exp(-0.5 * (2 * GaussianIndex *
                                                   (i - N / 2) / (N))**2)
                profile = int(round(
                    self.corrugation_width1 / 2 / dbu)) * profileFunction
                box1 = Box(x, y_offset_top, x + box_width,
                           y_offset_top + half_w + profile)
                pts1 = [Point(x, y_offset_top)]
                pts3 = [Point(x + misalignment, y_offset_top)]

                for i1 in range(0, npoints_sin + 1):
                    x1 = i1 * 2 * math.pi / npoints_sin
                    y1 = round(profile * math.sin(x1))
                    x1 = round(x1 / 2 / math.pi * grating_period)
                    pts1.append(Point(x + x1, y_offset_top + half_w + y1))
                    pts3.append(
                        Point(x + misalignment + x1,
                              y_offset_top - half_w - y1))

                pts1.append(Point(x + grating_period, y_offset_top))
                pts3.append(
                    Point(x + grating_period + misalignment, y_offset_top))
                shapes(LayerSiN).insert(Polygon(pts1))
                shapes(LayerSiN).insert(Polygon(pts3))
            length = x + grating_period + misalignment
            if misalignment > 0:
                # extra piece at the end:
                box2 = Box(x + grating_period, y_offset_top, length,
                           y_offset_top + half_w)
                shapes(LayerSiN).insert(box2)
                # extra piece at the beginning:
                box3 = Box(0, y_offset_top, misalignment,
                           y_offset_top - half_w)
                shapes(LayerSiN).insert(box3)

        else:
            for i in range(0, self.number_of_periods):
                x = int(round((i * self.grating_period) / dbu))

                profileFunction = math.exp(-0.5 * (2 * GaussianIndex *
                                                   (i - N / 2) / (N))**2)
                profile = int(round(
                    self.corrugation_width1 / 2 / dbu)) * profileFunction

                box1 = Box(
                    x, y_offset_top, x + box_width,
                    y_offset_top + to_itype(half_w + profile, dbu * 1000))
                box2 = Box(
                    x + box_width, y_offset_top, x + grating_period,
                    y_offset_top + to_itype(half_w - profile, dbu * 1000))
                box3 = Box(
                    x + misalignment, y_offset_top,
                    x + box_width + misalignment,
                    y_offset_top + to_itype(-half_w - profile, dbu * 1000))
                box4 = Box(
                    x + box_width + misalignment, y_offset_top,
                    x + grating_period + misalignment,
                    y_offset_top + to_itype(-half_w + profile, dbu * 1000))
                shapes(LayerSiN).insert(box1)
                shapes(LayerSiN).insert(box2)
                shapes(LayerSiN).insert(box3)
                shapes(LayerSiN).insert(box4)
            length = x + grating_period + misalignment
            if misalignment > 0:
                # extra piece at the end:
                box2 = Box(x + grating_period, y_offset_top, length,
                           y_offset_top + half_w)
                shapes(LayerSiN).insert(box2)
                # extra piece at the beginning:
                box3 = Box(0, y_offset_top, misalignment,
                           y_offset_top - half_w)
                shapes(LayerSiN).insert(box3)

        vertical_offset = int(round(self.wg2_width / 2 / dbu)) + int(
            round(self.gap / 2 / dbu))

        if misalignment > 0:
            t = Trans(Trans.R0, 0, vertical_offset)
        else:
            t = Trans(Trans.R0, 0, vertical_offset)

        # Draw the Bragg grating (top):
        box_width = int(round(self.grating_period / 2 / dbu))
        grating_period = int(round(self.grating_period / dbu))
        w = to_itype(self.wg2_width, dbu)
        half_w = w / 2
        half_corrugation_w = int(round(self.corrugation_width2 / 2 / dbu))

        N = self.number_of_periods
        if self.sinusoidal:
            npoints_sin = 40
            for i in range(0, self.number_of_periods):
                x = (round((i * self.grating_period) / dbu))
                profileFunction = math.exp(-0.5 * (2 * GaussianIndex *
                                                   (i - N / 2) / (N))**2)
                profile = int(round(
                    self.corrugation_width2 / 2 / dbu)) * profileFunction
                box1 = Box(x, 0, x + box_width,
                           -half_w + profile).transformed(t)
                pts1 = [Point(x, 0)]
                pts3 = [Point(x + misalignment, 0)]
                for i1 in range(0, npoints_sin + 1):
                    x1 = i1 * 2 * math.pi / npoints_sin
                    y1 = round(profile * math.sin(x1))
                    x1 = round(x1 / 2 / math.pi * grating_period)
                    #          print("x: %s, y: %s" % (x1,y1))
                    pts1.append(Point(x + x1, -half_w - y1))
                    pts3.append(Point(x + misalignment + x1, +half_w + y1))
                pts1.append(Point(x + grating_period, 0))
                pts3.append(Point(x + grating_period + misalignment, 0))
                shapes(LayerSiN).insert(Polygon(pts1).transformed(t))
                shapes(LayerSiN).insert(Polygon(pts3).transformed(t))
            length = x + grating_period + misalignment
            if misalignment > 0:
                # extra piece at the end:
                box2 = Box(x + grating_period, 0, length,
                           -half_w).transformed(t)
                shapes(LayerSiN).insert(box2)
                # extra piece at the beginning:
                box3 = Box(0, 0, misalignment, half_w).transformed(t)
                shapes(LayerSiN).insert(box3)

        else:
            for i in range(0, self.number_of_periods):
                x = int(round((i * self.grating_period) / dbu))
                profileFunction = math.exp(-0.5 * (2 * GaussianIndex *
                                                   (i - N / 2) / (N))**2)
                profile = int(round(
                    self.corrugation_width2 / 2 / dbu)) * profileFunction
                box1 = Box(x, 0, x + box_width,
                           -half_w - profile).transformed(t)
                box2 = Box(x + box_width, 0, x + grating_period,
                           -half_w + profile).transformed(t)
                box3 = Box(x + misalignment, 0, x + box_width + misalignment,
                           half_w + profile).transformed(t)
                box4 = Box(x + box_width + misalignment, 0,
                           x + grating_period + misalignment,
                           half_w - profile).transformed(t)
                shapes(LayerSiN).insert(box1)
                shapes(LayerSiN).insert(box2)
                shapes(LayerSiN).insert(box3)
                shapes(LayerSiN).insert(box4)
            length = x + grating_period + misalignment
            if misalignment > 0:
                # extra piece at the end:
                box2 = Box(x + grating_period, 0, length,
                           -half_w).transformed(t)
                shapes(LayerSiN).insert(box2)
                # extra piece at the beginning:
                box3 = Box(0, 0, misalignment, half_w).transformed(t)
                shapes(LayerSiN).insert(box3)

        # Create the pins on the waveguides, as short paths:
        from SiEPIC._globals import PIN_LENGTH as pin_length

        w1 = to_itype(self.wg1_width, dbu)
        w2 = to_itype(self.wg2_width, dbu)
        if self.sbend:

            port_w = to_itype(self.port_w, dbu)
            sbend_r = 25000
            sbend_length = 15000
            sbend_offset = 2 * port_w + port_w - (w1 + w2) / 2 - int(
                round(self.gap / dbu))
            taper_length = 20 * max(abs(w1 - port_w), abs(w2 - port_w))

            t = Trans(Trans.R180, 0, y_offset_top)
            layout_waveguide_sbend(self.cell, LayerSiN, t, w1, sbend_r,
                                   sbend_offset, sbend_length)
            t = Trans(Trans.R0, -sbend_length - taper_length,
                      y_offset_top - sbend_offset)
            layout_taper(self.cell, LayerSiN, t, port_w, w1, taper_length)
            x = -sbend_length - taper_length
            y = y_offset_top - sbend_offset
            make_pin(self.cell,
                     "opt1", [x, y],
                     port_w,
                     pin_length,
                     LayerPinRecN,
                     vertical=0)

            t = Trans(Trans.R180, 0, vertical_offset)
            layout_taper(self.cell, LayerSiN, t, w2, w2, sbend_length / 2)
            t = Trans(Trans.R180, -sbend_length / 2, vertical_offset)
            layout_taper(self.cell, LayerSiN, t, w2, port_w,
                         taper_length + sbend_length / 2)
            x = -taper_length - sbend_length
            y = vertical_offset
            make_pin(self.cell,
                     "opt2", [x, y],
                     port_w,
                     pin_length,
                     LayerPinRecN,
                     vertical=0)

            t = Trans(Trans.R0, length, y_offset_top)
            layout_waveguide_sbend(self.cell, LayerSiN, t, w1, sbend_r,
                                   -sbend_offset, sbend_length)
            t = Trans(Trans.R0, length + sbend_length,
                      y_offset_top - sbend_offset)
            layout_taper(self.cell, LayerSiN, t, w1, port_w, taper_length)
            x = length + sbend_length + taper_length
            y = y_offset_top - sbend_offset
            make_pin(self.cell,
                     "opt3", [x, y],
                     port_w,
                     -pin_length,
                     LayerPinRecN,
                     vertical=0)

            t = Trans(Trans.R0, length, vertical_offset)
            layout_taper(self.cell, LayerSiN, t, w2, w2, sbend_length / 2)
            t = Trans(Trans.R0, length + sbend_length / 2, vertical_offset)
            layout_taper(self.cell, LayerSiN, t, w2, port_w,
                         taper_length + sbend_length / 2)
            x = length + taper_length + sbend_length
            y = vertical_offset
            make_pin(self.cell,
                     "opt4", [x, y],
                     port_w,
                     -pin_length,
                     LayerPinRecN,
                     vertical=0)

        else:
            x = 0
            y = y_offset_top
            make_pin(self.cell,
                     "opt1", [x, y],
                     w1,
                     pin_length,
                     LayerPinRecN,
                     vertical=0)

            y = vertical_offset
            make_pin(self.cell,
                     "opt2", [x, y],
                     w2,
                     pin_length,
                     LayerPinRecN,
                     vertical=0)

            x = length
            y = y_offset_top
            make_pin(self.cell,
                     "opt3", [x, y],
                     w1,
                     -pin_length,
                     LayerPinRecN,
                     vertical=0)

            x = length
            y = vertical_offset
            make_pin(self.cell,
                     "opt4", [x, y],
                     w2,
                     -pin_length,
                     LayerPinRecN,
                     vertical=0)

        # Compact model information
        t = Trans(Trans.R0, 10, 0)
        text = Text('Lumerical_INTERCONNECT_library=Design kits/ebeam', t)
        shape = shapes(LayerDevRecN).insert(text)
        shape.text_size = 0.1 / dbu
        t = Trans(Trans.R0, 10, 500)
        text = Text('Component=contra_directional_coupler', t)
        shape = shapes(LayerDevRecN).insert(text)
        shape.text_size = 0.1 / dbu
        t = Trans(Trans.R0, 10, -500)
        text = Text \
          ('Spice_param:number_of_periods=%s grating_period=%.3fu wg1_width=%.3fu wg2_width=%.3fu corrugation_width1=%.3fu corrugation_width2=%.3fu gap=%.3fu apodization_index=%.3f AR=%s sinusoidal=%s accuracy=%s' %\
          (self.number_of_periods, self.grating_period, self.wg1_width, self.wg2_width, self.corrugation_width1, self.corrugation_width2, self.gap, self.apodization_index, int(self.AR), int(self.sinusoidal), int(self.accuracy)), t )
        shape = shapes(LayerDevRecN).insert(text)
        shape.text_size = 0.1 / dbu

        # Create the device recognition layer -- make it 1 * wg_width away from the waveguides.
        if self.sbend:
            box = pya.Box(
                pya.Point(-taper_length - sbend_length,
                          vertical_offset + 3 / 2 * port_w),
                pya.Point(length + taper_length + sbend_length,
                          y_offset_top - sbend_offset - 3 / 2 * port_w))
        else:
            box = pya.Box(
                pya.Point(0, vertical_offset + 3 / 2 * (w1 + w2) / 2),
                pya.Point(length, y_offset_top - 3 / 2 * (w1 + w2) / 2))
        shapes(LayerDevRecN).insert(box)
Ejemplo n.º 2
0
    def produce_impl(self):

        # fetch the parameters
        dbu = self.layout.dbu
        ly = self.layout
        shapes = self.cell.shapes

        from SiEPIC.utils.layout import layout_waveguide_sbend

        LayerSi = self.layer
        LayerSiN = ly.layer(LayerSi)
        LayerPinRecN = ly.layer(self.pinrec)
        LayerDevRecN = ly.layer(self.devrec)

        length = self.length / dbu
        w = self.wg_width / dbu
        r = self.radius / dbu
        h = self.height / dbu

        waveguide_length = layout_waveguide_sbend(self.cell, LayerSiN,
                                                  pya.Trans(Trans.R0, 0, 0), w,
                                                  r, h, length) * dbu

        from SiEPIC._globals import PIN_LENGTH as pin_length

        # Pins on the waveguide:
        x = self.length / dbu
        t = Trans(Trans.R0, x, h)
        pin = Path([Point(-pin_length / 2, 0), Point(pin_length / 2, 0)], w)
        pin_t = pin.transformed(t)
        shapes(LayerPinRecN).insert(pin_t)
        text = Text("pin2", t)
        shape = shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu
        shape.text_halign = 2

        x = 0
        t = Trans(Trans.R0, x, 0)
        pin = Path([Point(pin_length / 2, 0), Point(-pin_length / 2, 0)], w)
        pin_t = pin.transformed(t)
        shapes(LayerPinRecN).insert(pin_t)
        text = Text("pin1", t)
        shape = shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu

        # Compact model information
        t = Trans(Trans.R0, 0, 0)
        text = Text('Lumerical_INTERCONNECT_library=Design kits/EBeam', t)
        shape = shapes(LayerDevRecN).insert(text)
        shape.text_size = 0.1 / dbu
        t = Trans(Trans.R0, 0, w * 2)
        text = Text('Component=ebeam_wg_integral_1550', t)
        shape = shapes(LayerDevRecN).insert(text)
        shape.text_size = 0.1 / dbu
        t = Trans(Trans.R0, 0, -w * 2)
        text = Text \
          ('Spice_param:wg_length=%.3fu wg_width=%.3fu' %\
          (waveguide_length, self.wg_width), t )
        shape = shapes(LayerDevRecN).insert(text)
        shape.text_size = 0.1 / dbu
        #    t = Trans(Trans.R0, 0, -w*3)
        #    text = Text ('Extra length = %.4fu, Shortest length = %.4fu' % (straight_l*dbu, (length-2*straight_l)*dbu), t )
        #    shape = shapes(LayerDevRecN).insert(text)
        #    shape.text_size = 0.1/dbu

        # Create the device recognition layer -- make it 1 * wg_width away from the waveguides.
        box1 = Box(0, min(-w * 3, h - w * 3), length, max(w * 3, h + w * 3))
        shapes(LayerDevRecN).insert(box1)