Example #1
0
if __name__ == "__main__":
    from . import *
    from picwriter.components.waveguide import WaveguideTemplate
    top = gdspy.Cell("top")
    wgt = WaveguideTemplate(wg_width=2.0, bend_radius=50, resist='+')

    # wg1=Waveguide([(0,0), (0, 20)], wgt)
    # tk.add(top, wg1)

    contradc_wgt = WaveguideTemplate(bend_radius=50, resist='+', wg_layer=3, wg_datatype=0)

    # cdc = ContraDirectionalCoupler(wgt, length=30.0, gap=1.0, period=0.5, dc=0.5, angle=np.pi/12.0, width_top=3.0, width_bot=2.0, input_bot=True, **wg1.portlist["output"])
    # tk.add(top, cdc)

    # wg1=Waveguide([(0,0), (0,100), (50,200), (50, 215)], wgt)
    wg1=Waveguide([(0,0), (100,0)], wgt)
    tk.add(top, wg1)

    cdc2 = ContraDirectionalCoupler(wgt, length=30.0, gap=1.0, period=0.5, dc=0.5, angle=np.pi/12.0, width_top=3.0, width_bot=2.0, dw_top=0.4, dw_bot=0.2, input_bot=False, contradc_wgt=contradc_wgt, fins=True, **wg1.portlist["output"])
    tk.add(top, cdc2)

    # x0,y0 = cdc2.portlist["input_bot"]["port"]
    # wg2=Waveguide([(x0,y0), (x0,y0-15), (x0+50,y0-115), (x0+50, y0-215)], wgt)
    # tk.add(top, wg2)

    # dc1 = ContraDirectionalCoupler(wgt, length=30.0, gap=0.5, period=0.220, dc=0.5, angle=np.pi/6.0, width_top=2.0, width_bot=0.75, input_bot=False, **wg1.portlist["output"])
    # dc2 = ContraDirectionalCoupler(wgt, length=30.0, gap=0.5, period=0.220, dc=0.5, angle=np.pi/6.0, width_top=2.0, width_bot=0.75, input_bot=True, **dc1.portlist["output_top"])
    # dc3 = ContraDirectionalCoupler(wgt, length=30.0, gap=0.5, period=0.220, dc=0.5, angle=np.pi/6.0, width_top=2.0, width_bot=0.75, input_bot=False, **dc1.portlist["output_bot"])
    # dc4 = ContraDirectionalCoupler(wgt, length=30.0, gap=0.5, period=0.220, dc=0.5, angle=np.pi/6.0, width_top=2.0, width_bot=0.75, input_bot=False, **dc2.portlist["output_bot"])
    # dc5 = ContraDirectionalCoupler(wgt, length=30.0, gap=0.5, period=0.220, dc=0.5, angle=np.pi/6.0, width_top=2.0, width_bot=0.75, input_bot=True, **dc2.portlist["output_top"])
    # dc6 = ContraDirectionalCoupler(wgt, length=30.0, gap=0.5, period=0.220, dc=0.5, angle=np.pi/6.0, width_top=2.0, width_bot=0.75, input_bot=False, **dc3.portlist["output_bot"])
Example #2
0
    def __build_cell(self):
        # Determine the correct set of waypoints, then feed this over to a
        # Waveguide() class.
        # This is just one way of doing it... ¯\_(ツ)_/¯

        # Determine the number of spiral wraps
        skip_length_check = False
        n = self.__get_number_of_spirals()

        if n != None:
            """ Determine the corresponding spiral height
            """
            h = self.__get_spiral_height(n)

            w = self.width
            length = self.length
            br = self.bend_radius
            s = self.spacing

            """ Double check all parameters
            """
            if abs(length - self.get_length(h, n)) > 1e-6:
                raise ValueError(
                    "Warning! The computed length and desired length are not equal!"
                )

            """ Now that the parameters are all determined, build the corresponding
            waypoints """
            wcent = (w - s - br) / 2.0

            p = self.parity
            x0, y0 = 0, 0

            """ Start/end points corresponding to 'fixed_len' unit """
            start_points = [
                (x0, y0),
                (x0 + 2 * wcent, y0),
                (x0 + 2 * wcent, y0 - p * (h - s)),
            ]
            end_points = [
                (x0, y0 - p * s),
                (x0, y0 - p * h),
                (x0 + w - br, y0 - p * h),
                (x0 + w - br, y0),
                (x0 + w, y0),
            ]

            """ Generate the spiral going inwards """
            spiral_in_pts = []

            x_left_start, x_right_start = x0 + s, x0 + 2 * wcent - 2 * s
            y_top_start, y_bot_start = y0 - p * 2 * s, y0 - p * (h - s)

            for j in range(n):
                i = j + 1
                if i % 2 == 1:  # ODD, so add a segment on the LEFT
                    left_segment_index = (i - 1) / 2
                    spiral_in_pts.append(
                        (
                            x_left_start + 2 * s * left_segment_index,
                            y_bot_start + p * (2 * s * left_segment_index),
                        )
                    )
                    spiral_in_pts.append(
                        (
                            x_left_start + 2 * s * left_segment_index,
                            y_top_start - p * (2 * s * left_segment_index),
                        )
                    )
                    if j + 1 == n:  # This is the last one! Add the middle point now
                        spiral_in_pts.append(
                            (x0 + wcent, y_top_start - p * (2 * s * left_segment_index))
                        )
                if i % 2 == 0:  # EVEN, so add a segment on the RIGHT
                    right_segment_index = (i - 2) / 2
                    spiral_in_pts.append(
                        (
                            x_right_start - (2 * s * right_segment_index),
                            y_top_start - p * (2 * s * right_segment_index),
                        )
                    )
                    spiral_in_pts.append(
                        (
                            x_right_start - (2 * s * right_segment_index),
                            y_bot_start + p * (2 * s * right_segment_index + 2 * s),
                        )
                    )
                    if j + 1 == n:  # This is the last one! Add the middle point now
                        spiral_in_pts.append(
                            (
                                x0 + wcent,
                                y_bot_start + p * (2 * s * right_segment_index + 2 * s),
                            )
                        )

            if n == 0:
                spiral_in_pts.append((x0 + wcent, y_bot_start))

            """ Generate the spiral going outwards """
            spiral_out_pts = []

            x_left_start, x_right_start = x0 + 2 * s, x0 + 2 * wcent - s
            y_top_start, y_bot_start = y0 - p * s, y0 - p * (h - 2 * s)

            for j in range(n):
                i = j + 1
                if i % 2 == 1:  # ODD, so add a segment on the RIGHT
                    right_segment_index = (i - 1) / 2
                    spiral_out_pts.append(
                        (
                            x_right_start - 2 * s * right_segment_index,
                            y_top_start - p * 2 * s * right_segment_index,
                        )
                    )
                    spiral_out_pts.append(
                        (
                            x_right_start - 2 * s * right_segment_index,
                            y_bot_start + p * (2 * s * right_segment_index),
                        )
                    )
                    if j + 1 == n:  # This is the last one! Add the middle point now
                        spiral_out_pts.append(
                            (x0 + wcent, y_bot_start + p * 2 * s * right_segment_index)
                        )

                elif i % 2 == 0:  # EVEN, add a segment on the LEFT
                    left_segment_index = (i - 2) / 2
                    spiral_out_pts.append(
                        (
                            x_left_start + 2 * s * left_segment_index,
                            y_bot_start + p * 2 * s * left_segment_index,
                        )
                    )
                    spiral_out_pts.append(
                        (
                            x_left_start + 2 * s * left_segment_index,
                            y_top_start - p * (2 * s * left_segment_index + 2 * s),
                        )
                    )
                    if j + 1 == n:  # This is the last one! Add the middle point now
                        spiral_out_pts.append(
                            (
                                x0 + wcent,
                                y_top_start - p * (2 * s * left_segment_index + 2 * s),
                            )
                        )

            if n == 0:
                spiral_out_pts.append((x0 + wcent, y_top_start))

            spiral_out_pts.reverse()  # reverse order

            waypoints = start_points + spiral_in_pts + spiral_out_pts + end_points

        else:
            """ Make the waveguide waypoints just a U-bend, since the waveguide length is not long enough to spiral in on itself """

            length = self.length
            w = self.width
            br = self.bend_radius
            dl = self.corner_dl

            if length < w + 4 * br - 4 * dl:
                """ Route a sinusoidal s-bend waveguide with the desired length """
                # Goal:  Find the height of the s-bend

                from scipy.optimize import fsolve
                from scipy.special import ellipeinc

                # The equation below is the arc length of a sine curve, for a given height and width
                func = lambda s_height: length - ellipeinc(
                    2 * np.pi, 1 - 1 / (1 + (s_height ** 2 * np.pi ** 2 / w ** 2))
                ) / (
                    (2 * np.pi / w) / np.sqrt(1 + (s_height ** 2 * np.pi ** 2 / w ** 2))
                )

                h_guess = np.sqrt((length / 2.0) ** 2 - (w / 2) ** 2)

                h_solution = fsolve(func, h_guess)
                h = -self.parity * h_solution[0]

                sbend1 = SBend(self.wgt, w / 2.0, h, port=(0, 0), direction="EAST")
                self.add(sbend1)

                sbend2 = SBend(
                    self.wgt, w / 2.0, -h, port=(w / 2.0, h), direction="EAST"
                )
                self.add(sbend2)

                #                print("Added an SBend")
                #                print("h = "+str(h))
                #                print("w = "+str(w))
                #                print("length = "+str(length))

                self.actual_length = ellipeinc(
                    2 * np.pi, 1 - 1 / (1 + (h ** 2 * np.pi ** 2 / w ** 2))
                ) / ((2 * np.pi / w) / np.sqrt(1 + (h ** 2 * np.pi ** 2 / w ** 2)))

                skip_length_check = True

            else:
                p = self.parity
                x0, y0 = 0, 0

                extra_height = (length - (w + 4 * br - 4 * dl)) / 2.0

                max_turns = (w - 4 * br) // (
                    4 * br
                )  # one 'turn' is a turn segment added to the waveguide "U" (to get the length required without making the bend very tall)
                extra_length_per_turn = (
                    8 * br - 4 * dl - 4 * br
                )  # Extra length incurred by adding a turn (compared to a straight section)

                waypoints = [(x0, y0), (x0 + br, y0)]

                number_of_turns = (
                    extra_height // extra_length_per_turn
                )  # Max number of turns that could be formed from the extra_height

                if number_of_turns > max_turns:
                    """ Add *all* of the turns, plus some extra for the height, else add only the smaller number of turns. """
                    number_of_turns = max_turns

                dh = (
                    length
                    - (w + 4 * br - 4 * dl)
                    - number_of_turns * extra_length_per_turn
                ) / (number_of_turns * 2 + 2)

                waypoints.append((x0 + br, y0 - p * (2 * br + dh)))
                for i in range(int(number_of_turns)):
                    waypoints.append((x0 + 3 * br + i * br * 4, y0 - p * (2 * br + dh)))
                    waypoints.append((x0 + 3 * br + i * br * 4, y0))
                    waypoints.append((x0 + 5 * br + i * br * 4, y0))
                    waypoints.append((x0 + 5 * br + i * br * 4, y0 - p * (2 * br + dh)))

                waypoints.append((x0 + w - br, y0 - p * (2 * br + dh)))
                waypoints.append((x0 + w - br, y0))
                waypoints.append((x0 + w, y0))

        """ Independently verify that the length of the spiral structure generated is correct
        """
        if not skip_length_check:
            l = 0
            for i in range(len(waypoints) - 1):
                dx, dy = (
                    waypoints[i + 1][0] - waypoints[i][0],
                    waypoints[i + 1][1] - waypoints[i][1],
                )
                l += np.sqrt(dx ** 2 + dy ** 2)
            num_corners = len(waypoints) - 2
            l -= num_corners * self.corner_dl

            self.actual_length = l

            if abs(l - self.length) > 1e-6:
                print("Actual computed length = " + str(l))
                print("Expected length = " + str(self.length))
                raise ValueError(
                    "Warning! Spiral generated is significantly different from what is expected."
                )

            """ Generate the waveguide """
            wg = Waveguide(waypoints, self.wgt)

            self.add(wg)

        self.portlist_input = (0, 0)
        self.portlist_output = (self.width, 0)
Example #3
0
    def build_cell(self):
        # Sequentially build all the geometric shapes using gdspy path functions
        # for waveguide, then add it to the Cell

        x0, y0 = 0,0 #shift to port location after rotation later

        # X-distance of horizontal waveguide
        dlx = abs(self.wgt.bend_radius*np.tan((self.angle)/2.0))
        padding = 0.01 #Add extra 10nm to allow room for curves
        angle_x_dist = 2.0*(dlx+padding)*np.cos(self.angle)
        angle_y_dist = 2.0*(dlx+padding)*np.sin(self.angle)*self.parity
        tracelist_top = [(x0, y0),
                         (x0+dlx+padding, y0),
                         (x0+dlx+padding+angle_x_dist, y0-angle_y_dist),
                         (x0+3*dlx+padding+angle_x_dist+self.length, y0-angle_y_dist),
                         (x0+3*dlx+padding+2*angle_x_dist+self.length, y0),
                         (x0+4*dlx+2*padding+2*angle_x_dist+self.length, y0)]
        wg_top = Waveguide(tracelist_top, self.wgt)

        y_bot_start = y0 - (2*abs(angle_y_dist) + self.gap + self.wgt.wg_width)*self.parity
        tracelist_bot = [(x0, y_bot_start),
                         (x0+dlx+padding, y_bot_start),
                         (x0+dlx+padding+angle_x_dist, y_bot_start+angle_y_dist),
                         (x0+3*dlx+padding+angle_x_dist+self.length, y_bot_start+angle_y_dist),
                         (x0+3*dlx+padding+2*angle_x_dist+self.length, y_bot_start),
                         (x0+4*dlx+2*padding+2*angle_x_dist+self.length, y_bot_start)]
        wg_bot = Waveguide(tracelist_bot, self.wgt)

        distx = 4*dlx+2*angle_x_dist+self.length
        disty = (2*abs(angle_y_dist) + self.gap + self.wgt.wg_width)*self.parity
        if self.direction=="WEST":
            wgr_top = gdspy.CellReference(wg_top, rotation=180)
            wgr_bot = gdspy.CellReference(wg_bot, rotation=180)
            self.portlist_output_straight = (self.port[0]-distx, self.port[1])
            self.portlist_output_cross = (self.port[0]-distx, self.port[1] + disty)
            self.portlist_input_cross = (self.port[0], self.port[1] + disty)
        elif self.direction=="SOUTH":
            wgr_top = gdspy.CellReference(wg_top, rotation=-90/0)
            wgr_bot = gdspy.CellReference(wg_bot, rotation=-90.0)
            self.portlist_output_straight = (self.port[0], self.port[1]-distx)
            self.portlist_output_cross = (self.port[0]-disty, self.port[1]-distx)
            self.portlist_input_cross = (self.port[0]-disty, self.port[1])
        elif self.direction=="EAST":
            wgr_top = gdspy.CellReference(wg_top)
            wgr_bot = gdspy.CellReference(wg_bot)
            self.portlist_output_straight = (self.port[0]+distx, self.port[1])
            self.portlist_output_cross = (self.port[0]+distx, self.port[1]-disty)
            self.portlist_input_cross = (self.port[0], self.port[1]-disty)
        elif self.direction=="NORTH":
            wgr_top = gdspy.CellReference(wg_top, rotation=90.0)
            wgr_bot = gdspy.CellReference(wg_bot, rotation=90.0)
            self.portlist_output_straight = (self.port[0], self.port[1]+distx)
            self.portlist_output_cross = (self.port[0]+disty, self.port[1]+distx)
            self.portlist_input_cross = (self.port[0]+disty, self.port[1])
        elif isinstance(self.direction, float):
            wgr_top = gdspy.CellReference(wg_top, rotation=(self.direction*180/np.pi))
            wgr_bot = gdspy.CellReference(wg_bot, rotation=(self.direction*180/np.pi))
            self.portlist_output_straight = (self.port[0]+distx*np.cos(self.direction), self.port[1]+distx*np.sin(self.direction))
            self.portlist_input_cross = (self.port[0]-(-disty)*np.sin(self.direction), self.port[1]+(-disty)*np.cos(self.direction))
            self.portlist_output_cross = (self.port[0]-(-disty)*np.sin(self.direction)+distx*np.cos(self.direction), self.port[1]+(-disty)*np.cos(self.direction)+distx*np.sin(self.direction))

        wgr_top.translate(self.port[0], self.port[1])
        wgr_bot.translate(self.port[0], self.port[1])
        self.add(wgr_top)
        self.add(wgr_bot)
Example #4
0
    def build_cell(self):
        # Determine the correct set of waypoints, then feed this over to a
        # Waveguide() class.
        # This is just one way of doing it... ¯\_(ツ)_/¯

        # Determine the number of spiral wraps
        n = self.get_number_of_spirals()

        """ Determine the corresponding spiral height
        """
        h = self.get_spiral_height(n)

        w = self.width
        length = self.length
        br = self.wgt.bend_radius
        s = self.spacing

        """ Double check all parameters
        """
        if abs(length - self.get_length(h, n)) > 1E-6:
            raise ValueError("Warning! The computed length and desired length are not equal!")

        """ Now that the parameters are all determined, build the corresponding
        waypoints """
        wcent = (w-s-br)/2.0

        p = self.parity
        x0, y0 = 0,0

        """ Start/end points corresponding to 'fixed_len' unit """
        start_points = [(x0, y0),
                        (x0 + 2*wcent, y0),
                        (x0 + 2*wcent, y0 - p*(h - s))]
        end_points = [(x0, y0 - p*s),
                      (x0, y0 - p*h),
                      (x0 + w - br, y0 - p*h),
                      (x0 + w - br, y0),
                      (x0 + w, y0)]

        """ Generate the spiral going inwards """
        spiral_in_pts = []

        x_left_start, x_right_start = x0 + s, x0+2*wcent-2*s
        y_top_start, y_bot_start = y0 - p*2*s, y0 - p*(h-s)

        for j in range(n):
            i = j+1
            if i%2==1: #ODD, so add a segment on the LEFT
                left_segment_index = (i-1)/2
                spiral_in_pts.append((x_left_start + 2*s*left_segment_index, y_bot_start + p*(2*s*left_segment_index)))
                spiral_in_pts.append((x_left_start + 2*s*left_segment_index, y_top_start - p*(2*s*left_segment_index)))
                if j+1==n: #This is the last one! Add the middle point now
                    spiral_in_pts.append((x0+wcent, y_top_start - p*(2*s*left_segment_index)))
            if i%2==0: #EVEN, so add a segment on the RIGHT
                right_segment_index = (i-2)/2
                spiral_in_pts.append((x_right_start - (2*s*right_segment_index), y_top_start - p*(2*s*right_segment_index)))
                spiral_in_pts.append((x_right_start - (2*s*right_segment_index), y_bot_start + p*(2*s*right_segment_index + 2*s)))
                if j+1==n: #This is the last one! Add the middle point now
                    spiral_in_pts.append((x0+wcent, y_bot_start + p*(2*s*right_segment_index + 2*s)))

        if n==0:
            spiral_in_pts.append((x0+wcent, y_bot_start))

        """ Generate the spiral going outwards """
        spiral_out_pts = []

        x_left_start, x_right_start = x0 + 2*s, x0+2*wcent - s
        y_top_start, y_bot_start = y0 - p*s, y0 - p*(h-2*s)

        for j in range(n):
            i = j+1
            if i%2==1: #ODD, so add a segment on the RIGHT
                right_segment_index = (i-1)/2
                spiral_out_pts.append((x_right_start - 2*s*right_segment_index, y_top_start - p*2*s*right_segment_index))
                spiral_out_pts.append((x_right_start - 2*s*right_segment_index, y_bot_start + p*(2*s*right_segment_index)))
                if j+1==n: #This is the last one! Add the middle point now
                    spiral_out_pts.append((x0+wcent, y_bot_start + p*2*s*right_segment_index))

            elif i%2==0: #EVEN, add a segment on the LEFT
                left_segment_index = (i-2)/2
                spiral_out_pts.append((x_left_start + 2*s*left_segment_index, y_bot_start + p*2*s*left_segment_index))
                spiral_out_pts.append((x_left_start + 2*s*left_segment_index, y_top_start - p*(2*s*left_segment_index + 2*s)))
                if j+1==n: #This is the last one! Add the middle point now
                    spiral_out_pts.append((x0+wcent, y_top_start - p*(2*s*left_segment_index + 2*s)))

        if n==0:
            spiral_out_pts.append((x0+wcent, y_top_start))

        spiral_out_pts.reverse() #reverse order

        waypoints = start_points+spiral_in_pts+spiral_out_pts+end_points

        """ Independently verify that the length of the spiral structure generated is correct
        """
        l=0
        for i in range(len(waypoints)-1):
            dx, dy = waypoints[i+1][0]-waypoints[i][0], waypoints[i+1][1]-waypoints[i][1]
            l += np.sqrt(dx**2 + dy**2)
        num_corners = len(waypoints)-2
        l -= num_corners*self.corner_dl

        self.actual_length = l

        if abs(l - self.length) > 1E-6:
            print("Actual computed length = "+str(l))
            print("Expected length = "+str(self.length))
            raise ValueError("Warning! Spiral generated is significantly different from what is expected.")

        """ Generate the waveguide """
        wg = Waveguide(waypoints, self.wgt)

        dist = self.width
        if self.direction=="WEST":
            wgr = gdspy.CellReference(wg, rotation=180)
            self.portlist_output = (self.port[0]-dist, self.port[1])
        elif self.direction=="SOUTH":
            wgr = gdspy.CellReference(wg, rotation=-90)
            self.portlist_output = (self.port[0], self.port[1]-dist)
        elif self.direction=="EAST":
            wgr = gdspy.CellReference(wg, rotation=0.0)
            self.portlist_output = (self.port[0]+dist, self.port[1])
        elif self.direction=="NORTH":
            wgr = gdspy.CellReference(wg, rotation=90)
            self.portlist_output = (self.port[0], self.port[1]+dist)
        elif isinstance(self.direction, float) or isinstance(self.direction, int):
            wgr = gdspy.CellReference(wg, rotation=(float(self.direction)*180/np.pi))
            self.portlist_output = (self.port[0]+dist*np.cos(float(self.direction)), self.port[1]+dist*np.sin(float(self.direction)))

        wgr.translate(self.port[0], self.port[1])
        self.add(wgr)
Example #5
0
    def build_cell(self):
        # Determine the correct set of waypoints, then feed this over to a
        # Waveguide() class.
        # I'm sure there's better ways of generating spiral structures, though
        # this seems to work, so... ¯\_(ツ)_/¯

        width = self.width
        height = self.height
        length = self.length
        bend_radius = self.wgt.bend_radius
        spacing = self.spacing
        corner_dl = 2 * bend_radius - 0.25 * (2 * np.pi * bend_radius)
        n, lengthmin = self.get_number_of_spirals(corner_dl)
        print("Desired length=" + str(length) + " obtained with n=" + str(n) +
              " loops")

        if length < lengthmin:
            raise ValueError(
                "Spiral length is too small for desired spiral width/height.  Please specify either (1) smaller height/width or (2) larger spiral length inputs."
            )

        hnew = self.get_dh(corner_dl, n)
        height = hnew
        if self.parity == 1:
            x0, y0 = 0, height / 2.0
        else:
            x0, y0 = 0, height / 2.0
        y0 = y0 - hnew / 2.0
        h, w, s = height, width, spacing
        p = self.parity
        start_points = [(x0, y0), (x0, y0 + h - s),
                        (x0 + p * (w - s), y0 + h - s),
                        (x0 + p * (w - s), y0 + s)]
        end_points = [(x0 + p * s, y0 + h - 2 * s), (x0 + p * s, y0),
                      (x0 + p * w, y0), (x0 + p * w, y0 + h), (x0, y0 + h),
                      (x0, y0 + h + self.bend_radius)]
        """ Now solve for the middle points given n loops """
        mid_points = []
        x0p, y0p, hp, wp = x0 + p * s, y0 + s, h - 3 * s, w - 2 * s
        cur_point = (x0p + p * wp, y0p)
        """ Spiral inwards """
        for i in range(int(n - 1)):
            i = i + 1  #start at 1
            if i % 2 == 1:  #ODD
                cur_point = (cur_point[0] - p * (wp + s - 2 * i * s),
                             cur_point[1])
                mid_points.append(cur_point)
                cur_point = (cur_point[0], cur_point[1] + (hp + s - 2 * i * s))
                mid_points.append(cur_point)
            elif i % 2 == 0:  #EVEN
                cur_point = (cur_point[0] + p * (wp + s - 2 * i * s),
                             cur_point[1])
                mid_points.append(cur_point)
                cur_point = (cur_point[0], cur_point[1] - (hp + s - 2 * i * s))
                mid_points.append(cur_point)
        """ Middle points """
        if n % 2 == 1:  #ODD -> upwards
            cur_point = (x0p + p * wp / 2.0, cur_point[1])
            mid_points.append(cur_point)
            cur_point = (x0p + p * wp / 2.0,
                         cur_point[1] + (hp - (n - 1) * 2 * s))
            mid_points.append(cur_point)
        elif n % 2 == 0:  #EVEN
            cur_point = (x0p + p * wp / 2.0, cur_point[1])
            mid_points.append(cur_point)
            cur_point = (x0p + p * wp / 2.0,
                         cur_point[1] - (hp - (n - 1) * 2 * s))
            mid_points.append(cur_point)
        """ Spiral outwards (first do other version of inwards, then reverse list) """
        cur_point = (x0p, y0p + hp)
        mid_points2 = []
        for i in range(int(n - 1)):
            i = i + 1  #start at 1
            if i % 2 == 1:  #ODD
                cur_point = (cur_point[0] + p * (wp + s - 2 * i * s),
                             cur_point[1])
                mid_points2.append(cur_point)
                cur_point = (cur_point[0], cur_point[1] - (hp + s - 2 * i * s))
                mid_points2.append(cur_point)
            elif i % 2 == 0:  #EVEN
                cur_point = (cur_point[0] - p * (wp + s - 2 * i * s),
                             cur_point[1])
                mid_points2.append(cur_point)
                cur_point = (cur_point[0], cur_point[1] + (hp + s - 2 * i * s))
                mid_points2.append(cur_point)
        mid_points2.reverse()

        waypoints = start_points + mid_points + mid_points2 + end_points

        wg = Waveguide(waypoints, self.wgt)

        dist = h + self.bend_radius
        if self.direction == "WEST":
            wgr = gdspy.CellReference(wg, rotation=90)
            self.portlist_output = (self.port[0] - dist, self.port[1])
        elif self.direction == "SOUTH":
            wgr = gdspy.CellReference(wg, rotation=180)
            self.portlist_output = (self.port[0], self.port[1] - dist)
        elif self.direction == "EAST":
            wgr = gdspy.CellReference(wg, rotation=-90)
            self.portlist_output = (self.port[0] + dist, self.port[1])
        elif self.direction == "NORTH":
            wgr = gdspy.CellReference(wg)
            self.portlist_output = (self.port[0], self.port[1] + dist)
        elif isinstance(self.direction, float):
            wgr = gdspy.CellReference(wg,
                                      rotation=(self.direction * 180 / np.pi) -
                                      90.0)
            self.portlist_output = (self.port[0] +
                                    dist * np.cos(self.direction),
                                    self.port[1] +
                                    dist * np.sin(self.direction))

        wgr.translate(self.port[0], self.port[1])
        self.add(wgr)
Example #6
0
            "direction": "EAST",
        }
        self.portlist["output_bot"] = {
            "port": self.portlist_output_bot,
            "direction": "EAST",
        }


if __name__ == "__main__":
    from . import *
    from picwriter.components.waveguide import WaveguideTemplate

    top = gdspy.Cell("top")
    wgt = WaveguideTemplate(wg_width=0.5, bend_radius=100, resist="+")

    wg1 = Waveguide([(0, 0), (0.1, 0)], wgt)
    tk.add(top, wg1)

    ac = AdiabaticCoupler(wgt,
                          length1=30.0,
                          length2=50.0,
                          length3=20.0,
                          wg_sep=1.0,
                          input_wg_sep=3.0,
                          output_wg_sep=3.0,
                          dw=0.1,
                          **wg1.portlist["output"])
    tk.add(top, ac)

    ac2 = AdiabaticCoupler(wgt,
                           length1=20.0,
Example #7
0
            clad_path.rotate(-np.pi/2.0, self.port)
        elif isinstance(self.direction, float):
            teeth.rotate(self.direction - np.pi/2.0, self.port)
            path.rotate(self.direction -np.pi/2.0, self.port)
            clad_path.rotate(self.direction-np.pi/2.0, self.port)
        self.add(teeth)
        self.add(path)
        self.add(clad_path)

    def build_ports(self):
        # Portlist format:
        #    example:  {'port':(x_position, y_position), 'direction': 'NORTH'}
        self.portlist["output"] = {'port':self.port, 'direction':tk.flip_direction(self.direction)}

if __name__ == "__main__":
    from picwriter.components.waveguide import Waveguide, WaveguideTemplate
    top = gdspy.Cell("top")
    wgt = WaveguideTemplate(bend_radius=50, resist='+', fab='ETCH')

    wg1=Waveguide([(0,0), (250,0), (250,500), (500,500)], wgt)
    tk.add(top, wg1)

    gc1 = GratingCouplerStraight(wgt, width=20, length=50, taper_length=20, period=1.0, dutycycle=0.7, **wg1.portlist["output"])
    tk.add(top, gc1)

    gc2 = GratingCouplerFocusing(wgt, focus_distance=20.0, width=20, length=50, period=1.0, dutycycle=0.7, **wg1.portlist["input"])
    tk.add(top,gc2)

    gdspy.LayoutViewer()
    # gdspy.write_gds('gratingcoupler.gds', unit=1.0e-6, precision=1.0e-9)
            
        self.add(nanobeam)
        self.add(nanobeam_clad)

    def build_ports(self):
        # Portlist format:
        # example: example:  {'port':(x_position, y_position), 'direction': 'NORTH'}
        self.portlist["input"] = {'port':self.trace[0], 'direction':tk.flip_direction(self.direction)}
        self.portlist["output"] = {'port':self.trace[1], 'direction':self.direction}

if __name__ == "__main__":
    from picwriter.components import *
    top = gdspy.Cell("top")
    wgt = WaveguideTemplate(wg_width=1.0, clad_width=10.0, bend_radius=50, resist='+')

    wg1=Waveguide([(0,0), (100,0)], wgt)
    tk.add(top, wg1)

    zlc1 = ZeroLengthCavity(wgt, 8, 0.4, 0.1, 0.08, 0.05, 1, **wg1.portlist["output"])
    tk.add(top, zlc1)

    (x1, y1) = zlc1.portlist["output"]["port"]
    wg2=Waveguide([(x1,y1),
                   (x1+100,y1),
                   (x1+100,y1+100)], wgt)
    tk.add(top, wg2)

    zlc2 = ZeroLengthCavity(wgt, 20, 0.4, 0.1, 0.08, 0.05, 1, 6, taper_type='ratio', **wg2.portlist["output"])
    tk.add(top, zlc2)

    (x2, y2) = zlc2.portlist["output"]["port"]
Example #9
0
    def build_cell(self):
        # Sequentially build all the geometric shapes using gdspy path functions
        # then add it to the Cell

        mmi1 = MMI1x2(self.wgt,
                      self.MMI1x2length,
                      self.MMI1x2width,
                      angle=self.angle,
                      taper_width=self.MMI1x2taper_width,
                      taper_length=self.MMI1x2taper_length,
                      wg_sep=self.MMI1x2wg_sep,
                      port=(0, 0),
                      direction='EAST')
        mmi2 = MMI2x2(self.wgt,
                      self.MMI2x2length,
                      self.MMI2x2width,
                      angle=self.angle,
                      taper_width=self.MMI2x2taper_width,
                      taper_length=self.MMI2x2taper_length,
                      wg_sep=self.MMI2x2wg_sep,
                      port=(self.mmi2x2length + self.mmi1x2length +
                            4 * self.wgt.bend_radius,
                            -self.MMI2x2wg_sep / 2.0 - self.angle_y_dist),
                      direction='WEST')

        y_end_top, y_end_bot = mmi2.portlist["output_top"]["port"][
            1], mmi2.portlist["output_bot"]["port"][1]

        (x0, y0) = mmi1.portlist["output_top"]["port"]
        trace1 = [
            (x0, y0), (x0 + self.wgt.bend_radius, y0),
            (x0 + self.wgt.bend_radius, y0 + 2 * self.wgt.bend_radius +
             self.arm1 / 2.0 + self.heater_length / 2.0),
            (x0 + 3 * self.wgt.bend_radius, y0 + 2 * self.wgt.bend_radius +
             self.arm1 / 2.0 + self.heater_length / 2.0),
            (x0 + 3 * self.wgt.bend_radius, y_end_bot),
            (x0 + 4 * self.wgt.bend_radius, y_end_bot)
        ]
        wg_top = Waveguide(trace1, self.wgt)

        (x1, y1) = mmi1.portlist["output_bot"]["port"]
        print("(x1, y1)=" + str((x1, y1)))
        trace2 = [
            (x1, y1), (x1 + self.wgt.bend_radius, y1),
            (x1 + self.wgt.bend_radius, y1 - 2 * self.wgt.bend_radius -
             self.arm2 / 2.0 - self.heater_length / 2.0),
            (x1 + 3 * self.wgt.bend_radius, y1 - 2 * self.wgt.bend_radius -
             self.arm2 / 2.0 - self.heater_length / 2.0),
            (x1 + 3 * self.wgt.bend_radius, y_end_top),
            (x1 + 4 * self.wgt.bend_radius, y_end_top)
        ]
        wg_bot = Waveguide(trace2, self.wgt)

        if self.heater:
            heater_trace1 = [
                (x0 + self.wgt.bend_radius,
                 y0 + self.arm1 / 2.0 + self.wgt.bend_radius),
                (x0 + self.wgt.bend_radius, y0 + 2 * self.wgt.bend_radius +
                 self.arm1 / 2.0 + self.heater_length / 2.0),
                (x0 + 3 * self.wgt.bend_radius, y0 + 2 * self.wgt.bend_radius +
                 self.arm1 / 2.0 + self.heater_length / 2.0),
                (x0 + 3 * self.wgt.bend_radius,
                 y0 + self.arm1 / 2.0 + self.wgt.bend_radius)
            ]
            heater_top = MetalRoute(heater_trace1, self.mt)
            heater_trace2 = [
                (x0 + self.wgt.bend_radius,
                 y1 - self.arm2 / 2.0 - self.wgt.bend_radius),
                (x0 + self.wgt.bend_radius, y1 - 2 * self.wgt.bend_radius -
                 self.arm2 / 2.0 - self.heater_length / 2.0),
                (x0 + 3 * self.wgt.bend_radius, y1 - 2 * self.wgt.bend_radius -
                 self.arm2 / 2.0 - self.heater_length / 2.0),
                (x0 + 3 * self.wgt.bend_radius,
                 y1 - self.arm2 / 2.0 - self.wgt.bend_radius)
            ]
            heater_bot = MetalRoute(heater_trace2, self.mt)

        totalxlen = self.mmi2x2length + self.mmi1x2length + 4 * self.wgt.bend_radius
        if self.direction == 'EAST':
            angle = 0
            self.port_output_top = (self.port[0] + totalxlen,
                                    self.port[1] + self.MMI2x2wg_sep / 2.0 +
                                    self.angle_y_dist)
            self.port_output_bot = (self.port[0] + totalxlen,
                                    self.port[1] - self.MMI2x2wg_sep / 2.0 -
                                    self.angle_y_dist)
            self.htr_top_in_dir = 'WEST'
            self.htr_top_out_dir = 'EAST'
            self.htr_bot_in_dir = 'WEST'
            self.htr_bot_out_dir = 'EAST'
        elif self.direction == 'NORTH':
            angle = 90
            self.port_output_top = (self.port[0] - self.MMI2x2wg_sep / 2.0 -
                                    self.angle_y_dist,
                                    self.port[1] + totalxlen)
            self.port_output_bot = (self.port[0] + self.MMI2x2wg_sep / 2.0 +
                                    self.angle_y_dist,
                                    self.port[1] + totalxlen)
            self.htr_top_in_dir = 'SOUTH'
            self.htr_top_out_dir = 'NORTH'
            self.htr_bot_in_dir = 'SOUTH'
            self.htr_bot_out_dir = 'NORTH'
        elif self.direction == 'WEST':
            angle = 180
            self.port_output_top = (self.port[0] - totalxlen,
                                    self.port[1] - self.MMI2x2wg_sep / 2.0 -
                                    self.angle_y_dist)
            self.port_output_bot = (self.port[0] - totalxlen,
                                    self.port[1] + self.MMI2x2wg_sep / 2.0 +
                                    self.angle_y_dist)
            self.htr_top_in_dir = 'EAST'
            self.htr_top_out_dir = 'WEST'
            self.htr_bot_in_dir = 'EAST'
            self.htr_bot_out_dir = 'WEST'
        elif self.direction == 'SOUTH':
            angle = -90
            self.port_output_top = (self.port[0] + self.MMI2x2wg_sep / 2.0 +
                                    self.angle_y_dist,
                                    self.port[1] - totalxlen)
            self.port_output_bot = (self.port[0] - self.MMI2x2wg_sep / 2.0 -
                                    self.angle_y_dist,
                                    self.port[1] - totalxlen)
            self.htr_top_in_dir = 'NORTH'
            self.htr_top_out_dir = 'SOUTH'
            self.htr_bot_in_dir = 'NORTH'
            self.htr_bot_out_dir = 'SOUTH'
        elif isinstance(self.direction, float):
            angle = 180.0 * self.direction / np.pi
            self.port_output_top = (
                self.port[0] + totalxlen * np.cos(self.direction) -
                (self.MMI2x2wg_sep / 2.0 + self.angle_y_dist) *
                np.sin(self.direction),
                self.port[1] + totalxlen * np.sin(self.direction) +
                (self.MMI2x2wg_sep / 2.0 + self.angle_y_dist) *
                np.cos(self.direction))
            self.port_output_bot = (
                self.port[0] + totalxlen * np.cos(self.direction) -
                (-self.MMI2x2wg_sep / 2.0 - self.angle_y_dist) *
                np.sin(self.direction),
                self.port[1] + totalxlen * np.sin(self.direction) +
                (-self.MMI2x2wg_sep / 2.0 - self.angle_y_dist) *
                np.cos(self.direction))

            self.htr_top_in_dir = self.direction + np.pi / 2.0
            self.htr_top_out_dir = self.direction + 3 * np.pi / 2.0
            self.htr_bot_in_dir = self.direction + np.pi / 2.0
            self.htr_bot_out_dir = self.direction + 3 * np.pi / 2.0

        htr_top_in = (x0 + self.wgt.bend_radius, y0 + self.arm1 / 2.0 +
                      self.wgt.bend_radius + self.mt.width / 2.0)
        htr_top_out = (x0 + 3 * self.wgt.bend_radius, y0 + self.arm1 / 2.0 +
                       self.wgt.bend_radius + self.mt.width / 2.0)
        htr_bot_in = (x0 + self.wgt.bend_radius, y1 - self.arm2 / 2.0 -
                      self.wgt.bend_radius - self.mt.width / 2.0)
        htr_bot_out = (x0 + 3 * self.wgt.bend_radius, y1 - self.arm2 / 2.0 -
                       self.wgt.bend_radius - self.mt.width / 2.0)
        R = np.array(
            [[np.cos(angle * np.pi / 180.0), -np.sin(angle * np.pi / 180.0)],
             [np.sin(angle * np.pi / 180.0),
              np.cos(angle * np.pi / 180.0)]])
        hti = np.dot(R, htr_top_in)
        hto = np.dot(R, htr_top_out)
        hbi = np.dot(R, htr_bot_in)
        hbo = np.dot(R, htr_bot_out)
        self.htr_top_in = (hti[0] + self.port[0], hti[1] + self.port[1])
        self.htr_top_out = (hto[0] + self.port[0], hto[1] + self.port[1])
        self.htr_bot_in = (hbi[0] + self.port[0], hbi[1] + self.port[1])
        self.htr_bot_out = (hbo[0] + self.port[0], hbo[1] + self.port[1])
        """ Add all the components """
        components = [mmi1, mmi2, wg_top, wg_bot, heater_top, heater_bot]
        for c in components:
            self.add(gdspy.CellReference(c, origin=self.port, rotation=angle))
Example #10
0
                           resist='+',
                           fab="ETCH",
                           metal_layer=13,
                           metal_datatype=0,
                           clad_layer=14,
                           clad_datatype=0)
    mt = MetalTemplate(width=25,
                       clad_width=25,
                       resist='+',
                       fab="ETCH",
                       metal_layer=11,
                       metal_datatype=0,
                       clad_layer=12,
                       clad_datatype=0)

    wg_in = Waveguide([(0, 0), (300, 0)], wgt)
    tk.add(top, wg_in)
    #    mzi = MachZehnder(wgt, MMIlength=50, MMIwidth=10, MMItaper_width=2.0, MMIwg_sep=3, arm1=0, arm2=100, heater=True, heater_length=400, mt=htr_mt, **wg_in.portlist["output"])
    mzi = MachZehnderSwitch(wgt,
                            MMI1x2length=50,
                            MMI1x2width=10,
                            MMI1x2taper_width=2.0,
                            MMI1x2wg_sep=3,
                            MMI2x2length=100,
                            MMI2x2width=10,
                            MMI2x2taper_width=2.0,
                            MMI2x2wg_sep=3,
                            arm1=0,
                            arm2=100,
                            heater=True,
                            heater_length=400,