Esempio n. 1
0
    def _generate(self):
        if self._sep < self._wr:
            raise ValueError(
                'The separation gap must be larger than the branch width.')

        if self._implement_cadence_bug:
            v1 = Splitter._connect_two_points(
                [self._wl / 2, 0],
                [self._sep / 2 + self._wr / 2, self._total_length],
                self._n_points)
            if self._wl < 2 * self._wr:
                v2 = (v1 - [self._wr, 0])[::-1, :]
            else:
                # NOTE: In this obscure case, the generated splitter looks different than the cadence version.
                #       But probably it is better, since the paths are all smooth and curvy instead of just painting a
                #       triangle.
                v2 = Splitter._connect_two_points(
                    [-self._wr / 2, 0],
                    [self._sep / 2 - self._wr / 2, self._total_length],
                    self._n_points)[::-1, :]

            v = np.vstack((v1, v2))
            polygon1 = shapely.geometry.Polygon(v)
            polygon1 = polygon1.difference(
                shapely.geometry.box(-self._sep / 2, 0, 0, self._total_length))
            polygon2 = shapely.affinity.scale(polygon1,
                                              xfact=-1,
                                              origin=[0, 0, 0])

            polygon = polygon1.union(polygon2)

            polygon = shapely.affinity.rotate(polygon,
                                              -np.pi / 2 + self._angle,
                                              origin=[0, 0],
                                              use_radians=True)
            polygon = shapely.affinity.translate(polygon, self._origin[0],
                                                 self._origin[1])

            # Keep track of the ports
            port_points = shapely.geometry.MultiPoint([
                (0, 0), (-self._sep / 2, self._total_length),
                (+self._sep / 2, self._total_length)
            ])
            port_points = shapely.affinity.rotate(port_points,
                                                  -np.pi / 2 + self._angle,
                                                  origin=[0, 0],
                                                  use_radians=True)
            port_points = shapely.affinity.translate(port_points,
                                                     self._origin[0],
                                                     self._origin[1])

            self._polygon = polygon
            self._ports['root'] = Port(port_points[0].coords[0],
                                       self._angle + np.pi,
                                       width=self._wl)
            self._ports['left_branch'] = Port(port_points[1].coords[0],
                                              self._angle,
                                              width=self._wr)
            self._ports['right_branch'] = Port(port_points[2].coords[0],
                                               self._angle,
                                               width=self._wr)

        else:
            # Simpler version which also cares for a constant wave guide width
            alpha = np.arctan(4.0 * self._total_length * self._sep /
                              (4.0 * self._total_length**2.0 - self._sep**2.0))
            radius = 1.0 / 8.0 * (4.0 * self._total_length**2.0 +
                                  self._sep**2.0) / self._sep

            root_port = Port(self._origin, self._angle, self._wl)
            half_final_width = (self._wl + self._wr) / 2.

            upper_wg = Waveguide.make_at_port(root_port)
            upper_wg.add_bend(alpha, radius, final_width=half_final_width)
            upper_wg.add_bend(-alpha, radius, final_width=self._wr)

            lower_wg = Waveguide.make_at_port(root_port)
            lower_wg.add_bend(-alpha, radius, final_width=half_final_width)
            lower_wg.add_bend(alpha, radius, final_width=self._wr)

            self._polygon = geometric_union([upper_wg, lower_wg])
            self._ports['root'] = root_port.inverted_direction
            self._ports['left_branch'] = upper_wg.current_port
            self._ports['right_branch'] = lower_wg.current_port
Esempio n. 2
0
 def port_gate(self):
     return Port(self.origin, self._angle + np.pi, self._gate_width_1)
Esempio n. 3
0
    def __init__(self,
                 origin,
                 angle,
                 width,
                 lengthofcavity,
                 numberofholes=14,
                 holediameters=.5,
                 holedistances=0.5,
                 tapermode=None,
                 finalwidth=None,
                 taperlength=None,
                 samplepoints=1000,
                 holeparams=None,
                 underetching=True,
                 markers=True):
        """
        PhotonicCrystal Cavity

        :param origin: vector, Position of the center of the Photonic Crystal cavity
        :param angle: angle of the roation
        :param width: width of the waveguide
        :param lengthofcavity:  float, distance between the central two points, set to -1*holediameters for
            hole centered cavities
        :param numberofholes:  int, number of holes on each side
        :param holediameters: float or List of the diameters of the holes on each side.
            In case of linear increase use e.g. np.linespace
        :param holedistances: float or List of the distances of the holes on each side.
            In case of linear increase use e.g. np.linespace
        :param tapermode: None for constant widht, 'quadratic' for quadratic tapering
        :param finalwidth: width in the the center of the cavity
        :param taperlength: length over which the cavity will be tapered
        :param samplepoints: number of samplepoints to set the smoothness of the tapering
        """
        if holeparams:
            holetot2 = np.concatenate([
                np.linspace(holeparams['mindia'], holeparams['maxdia'],
                            holeparams['numholestap']),
                np.linspace(holeparams['maxdia'], holeparams['maxdia'],
                            holeparams['numholesmir'])
            ])
            distot2 = np.concatenate([
                np.linspace(holeparams['mindist'], holeparams['maxdist'],
                            holeparams['numholestap']),
                np.linspace(holeparams['maxdist'], holeparams['maxdist'],
                            (holeparams['numholesmir'] - 1))
            ])
            holediameters = holetot2
            holedistances = distot2
            numberofholes = holeparams['numholestap'] + holeparams[
                'numholesmir']

        self.origin = origin
        self.allholes = list()
        self.width = width
        self.angle = angle
        self._center_portr = Port(origin, angle, self.width)
        self._center_portl = Port(origin, (angle + np.pi), self.width)

        self.widthdiff = finalwidth - width if finalwidth else 0
        self.tapermode = tapermode
        self.lenofcav = lengthofcavity
        if type(holedistances) is float:
            meanholed = holedistances
            holedistances = [holedistances] * (numberofholes - 1)
        else:
            meanholed = np.mean(holedistances)

        if type(holediameters) is float:
            holediameters = [holediameters] * numberofholes

        lenoffset = holediameters[0] + holediameters[-1]

        self.holediameters = holediameters
        self.holedistances = holedistances
        self.numberofholes = len(holediameters)
        self.devlen = lengthofcavity + 2 * (
            (self.numberofholes - 1) * meanholed) + lenoffset
        self.taperlength = taperlength if taperlength else self.devlen / 2
        self.samplepoints = samplepoints
        self.underetchspace = 10
        self.invertmarker = False
        self.markersize = 20
        self.markerdistancex = 100
        self.markerdistancey = 100

        self.layer_photonic = []
        self.layer_photonic_cavity = []
        self.layer_underetch = []
        self.layer_marker = []
        if len(holediameters) != len(holedistances) + 1:
            print(
                'dimension of holediameters should be 1 more than holedistances!'
            )
            np.append(holediameters, [holediameters[-1]])
        self._generate()
        if underetching:
            self.generate_underetch()
        if markers:
            self.generate_marker()
        if markers == 'inverse':
            self.invertmarker = True
            self.generate_marker()
Esempio n. 4
0
def _example():
    import gdsCAD
    from gdshelpers.geometry import convert_to_gdscad

    devicename = 'Cavity'
    # cavitiyparameter_const = {'origin': [0, 0], 'angle': 0, 'width': 0.726, 'lengthofcavity': 0.26,
    #                          'numberofholes': 17, 'holediameters': 0.416, 'holedistances': 0.53}
    # cavitiyparameter_lin = {'origin': [100, 500], 'angle': 0, 'width': 0.726, 'lengthofcavity': 0.26,
    #                        'numberofholes': 17,
    #                        'holediameters': np.linspace(0.233, 0.416, 17),
    #                        'holedistances': np.linspace(0.53, 0.605, 16)}
    # taperlength = 15 * 0.414
    # cavitiyparameter_tap_width = {'origin': [-50, -30], 'angle': np.pi, 'width': 1.1, 'numberofholes': 25,
    #                              'taperlength': taperlength,
    #                              'lengthofcavity': -0.414, 'finalwidth': 1.55, 'tapermode': 'quadratic',
    #                              'holediameters': 0.414,
    #                              'holedistances': 0.620}
    holeparams_bg = {
        'mindia': 0.267,
        'maxdia': 0.267,
        'mindist': 0.512,
        'maxdist': 0.512,
        'numholestap': 1,
        'numholesmir': 10
    }
    bandgapparameter = {
        'origin': [0, 0],
        'angle': 0,
        'width': 1.015,
        'lengthofcavity': -0.512 / 2,
        'holeparams': holeparams_bg
    }

    # pccav1 = PhotonicCrystalCavity(**cavitiyparameter_const)
    bandgap = PhotonicCrystalCavity(**bandgapparameter)

    port1 = Port(origin=[10, 10], angle=np.pi / 2, width=1)
    # cav2 = PhotonicCrystalCavity.make_at_port(port=port1, **cavitiyparameter_tap_width)
    # pccav3 = PhotonicCrystalCavity(**cavitiyparameter_tap_width)
    wg = Waveguide.make_at_port(port1.inverted_direction)
    wg.add_straight_segment(length=5)

    cell = gdsCAD.core.Cell(devicename)
    # cell.add(convert_to_gdscad(pccav1.layer_photonic_cavity, layer=1))
    # cell.add(convert_to_gdscad(pccav2.layer_marker, layer=StandardLayers.lmarklayer))
    # cell.add(convert_to_gdscad(pccav2.layer_underetch, layer=StandardLayers.masklayer1))
    # cell.add(convert_to_gdscad(pccav2.layer_photonic_cavity, layer=StandardLayers.nanolayer))
    # cell.add(convert_to_gdscad(pccav3.layer_marker, layer=StandardLayers.lmarklayer))
    # cell.add(convert_to_gdscad(pccav3.layer_underetch, layer=StandardLayers.masklayer1))
    cell.add(
        convert_to_gdscad(bandgap.layer_underetch,
                          layer=StandardLayers.masklayer1))
    cell.add(
        convert_to_gdscad(bandgap.layer_photonic_cavity,
                          layer=StandardLayers.nanolayer))

    # cell.add(convert_to_gdscad(pccav2.layer_photonic_cavity, layer=1))
    # cell.add(convert_to_gdscad(pccav3.get_holes_list()))
    # holes = pccav3.get_holes_list()

    layout = gdsCAD.core.Layout()
    layout.add(cell=cell)
    layout.show()
def MZI_active_with_phase(coupler_sep, coupler_length, MZ_length, electrodes_sep, label):
    cell = Cell('MZI_active_withphase'+label)

    x_in = 0
    y_in = 0

    wg_sep = mod_params['wg_sep']

    wg_width_in_mod = wg_Expwidth
    taper_length = l_Exptaper

    ##Generating input and output grating couplers

    coupler_params = std_coupler_params.copy()

    for j in (0, 1):
        incoupler = GratingCoupler.make_traditional_coupler((x_in + j * opt_space, y_in), **coupler_params)
        cell.add_to_layer(wg_layer, incoupler)

    outcouplers = []
    for j in (3, 4):
        outcoupler = GratingCoupler.make_traditional_coupler((x_in + j * opt_space, y_in), **coupler_params)
        outcouplers.append(outcoupler)
        cell.add_to_layer(wg_layer, outcoupler)

    ###Generating waveguides

    inports = [Port((x_in + j * opt_space, y_in), np.deg2rad(90), std_coupler_params['width']) for j in (0, 1)]
    wg = [Waveguide.make_at_port(inport) for inport in inports]

    for j in (0, 1):
        # adding final tapers as suggested by Munster, SP 21/10/21
        wg[j].add_straight_segment(grating_added_taper_len, final_width=wg_width)
        # wg[j].add_straight_segment(bend_r-grating_added_taper_len)

        wg[j].add_bend(-np.pi / 2.0, bend_r + (1 - j) * wg_sep)
        wg[j].add_straight_segment((1 - j) * (opt_space - wg_sep))
        wg[j].add_bend(-np.pi / 2.0, bend_r + (1 - j) * wg_sep)

        wg[j].add_straight_segment(bend_r)

        ##directional coupler with sinusoidal s-bend
        x_length = 60
        y_length = wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - j * (wg_sep - wg_width - coupler_sep)
        wg[j].add_parameterized_path(path=lambda t: (t * x_length, .5 * (np.cos(np.pi * t) - 1) * y_length),
                                     path_derivative=lambda t: (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length))
        wg[j].add_straight_segment(coupler_length)
        y_length = -(wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - j * (wg_sep  - wg_width - coupler_sep))
        wg[j].add_parameterized_path(path=lambda t: (t * x_length, .5 * (np.cos(np.pi * t) - 1) * y_length),
                                     path_derivative=lambda t: (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length))

        #add taper to multimode wg
        wg[j].add_straight_segment(taper_length, final_width=wg_width_in_mod)

        ###reference port for electrodes in MZI
        ref_port = wg[j].current_port

        ###reference port for electrodes in PHASE
        ref_port_ph = wg[j].current_port

        ###straight section
        wg[j].add_straight_segment(MZ_length)

        #add taper to single-mode wg
        wg[j].add_straight_segment(taper_length, final_width=wg_width)

        ##directional coupler with sinusoidal s-bend
        x_length = 60
        y_length = wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - j * (wg_sep  - wg_width - coupler_sep)
        wg[j].add_parameterized_path(path=lambda t: (t * x_length, .5 * (np.cos(np.pi * t) - 1) * y_length),
                                     path_derivative=lambda t: (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length))
        wg[j].add_straight_segment(coupler_length)
        y_length = -(wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - j * (wg_sep  - wg_width - coupler_sep))
        wg[j].add_parameterized_path(path=lambda t: (t * x_length, .5 * (np.cos(np.pi * t) - 1) * y_length),
                                     path_derivative=lambda t: (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length))



        x_dist_inout=2*mod_params['electrode_width'] + 15
        wg[j].add_straight_segment(10)
        wg[j].add_bend(np.pi/2., bend_r + j * wg_sep)
        wg[j].add_straight_segment(x_dist_inout+wg_sep)
        wg[j].add_bend(np.pi, bend_r + j * wg_sep)
        wg[j].add_bend(-np.pi / 2., bend_r + (1-j) * wg_sep)
        wg[j].add_straight_segment_until_y(inports[0].y - 3*bend_r)
        wg[j].add_bend(-np.pi / 2., bend_r + (1 - j) * wg_sep)
        wg[j].add_straight_segment_until_x(outcouplers[-1].origin[0]+bend_r)
        wg[j].add_bend(np.pi / 2., bend_r + j * wg_sep)

        wg[j].add_straight_segment_until_y(inports[0].y)
        wg[j].add_straight_segment(grating_added_taper_len)
        wg[j].add_bend(np.pi / 2., bend_r + j* wg_sep)
        wg[j].add_straight_segment_until_x(outcouplers[1-j].origin[0]+(bend_r + j * wg_sep))
        wg[j].add_bend(np.pi / 2., bend_r + j*wg_sep)
        # # adding final tapers as suggested by Munster, SP 21/10/21
        wg[j].add_straight_segment(grating_added_taper_len, final_width=std_coupler_params['width'])

    for j in (0, 1):
        cell.add_to_layer(wg_layer, wg[j])

    ##MODULATOR ELECTRODES


    #### ELECTRODES IN MZI

    electr_width = mod_params['electrode_width']
    sep_econns = mod_params['electrode_sep_y']
    cross_width = mod_params['crossing_width']
    pads_pitch = mod_params['connector_probe_pitch']
    pads_width = mod_params['connector_probe_dims'][0]
    pads_width_gnd = mod_params['connector_probe_dims_gnd'][0]
    pads_len = mod_params['connector_probe_dims'][1]
    min_safedist_from_wg = 22
    x_safe_dist = ref_port.origin[0] - min_safedist_from_wg - pads_width

    ##left ground electrode
    Inport = Port((ref_port.origin[0] - electrodes_sep / 2.0 - wg_sep / 2.0, ref_port.origin[1]), np.deg2rad(-90), electr_width)
    g_left = Waveguide.make_at_port(Inport)
    g_left.add_straight_segment(MZ_length - cross_width/2. - 2 * sep_econns)
    g_left._current_port.angle = g_left.current_port.angle - np.pi / 2.0
    g_left._current_port.origin[0] = g_left.current_port.origin[0] + g_left.current_port.width / 2.0
    g_left.add_straight_segment_until_x(x_safe_dist)
    g_left.add_straight_segment(2 * pads_pitch + (pads_width-pads_width_gnd/2.))
    g_left._current_port.angle = g_left.current_port.angle + np.pi / 2.0
    g_left._current_port.origin[0] = g_left.current_port.origin[0] + pads_width_gnd / 2.0
    g_left._current_port.width = pads_width_gnd

    g_left.add_straight_segment(pads_len)
    cell.add_to_layer(electrode_layer, g_left)

    ## signal electrode
    Inport = Port((ref_port.origin[0] + wg_sep / 2.0, ref_port.origin[1]), np.deg2rad(-90), electr_width - electrodes_sep)
    s = Waveguide.make_at_port(Inport)
    s.add_straight_segment(MZ_length - cross_width/2. - sep_econns)
    s._current_port.angle = s.current_port.angle - np.pi / 2.0
    s._current_port.origin[0] = s.current_port.origin[0] + s.current_port.width / 2.0
    s._current_port.width = cross_width
    s.add_straight_segment(wg_sep+5)
    s.add_straight_segment(wg_sep, electr_width)
    s.add_straight_segment_until_x(x_safe_dist)
    s.add_straight_segment(pads_pitch+ (pads_width-pads_width_gnd/2.))
    s._current_port.angle = s.current_port.angle + np.pi / 2.0
    s._current_port.origin[0] = s.current_port.origin[0] + pads_width / 2.0
    s._current_port.width = pads_width

    s.add_straight_segment_until_y(g_left.current_port.origin[1] + 50)
    cell.add_to_layer(electrode_layer, s)

    ##right ground electrode
    Inport = Port((ref_port.origin[0] + wg_sep + wg_sep / 2.0 + electrodes_sep / 2.0, ref_port.origin[1]), np.deg2rad(-90), electr_width)
    g_right = Waveguide.make_at_port(Inport)
    g_right.add_straight_segment(MZ_length - cross_width/2.)
    g_right._current_port.angle = g_right.current_port.angle - np.pi / 2.0
    g_right._current_port.origin[0] = g_right.current_port.origin[0] + g_right.current_port.width / 2.0
    g_right._current_port.width = cross_width
    g_right.add_straight_segment(2*wg_sep+5)
    g_right.add_straight_segment(wg_sep, electr_width)
    g_right.add_straight_segment_until_x(x_safe_dist)
    g_right.add_straight_segment(pads_width_gnd/2.)
    g_right._current_port.angle = g_right.current_port.angle + np.pi / 2.0
    g_right._current_port.origin[0] = g_right.current_port.origin[0] + pads_width_gnd / 2.0
    g_right._current_port.width = pads_width_gnd
    g_right.add_straight_segment_until_y(g_left.current_port.origin[1])
    g_right._current_port.angle = g_right.current_port.angle - np.pi / 2.0
    g_right._current_port.origin[0] = g_right.current_port.origin[0] + g_right.current_port.width / 2.0
    g_right._current_port.width = pads_width / 2.
    g_right._current_port.origin[1] = g_right.current_port.origin[1] - g_right._current_port.width / 2.
    g_right.add_straight_segment(2 * pads_pitch + pads_width)

    cell.add_to_layer(electrode_layer, g_right)



    #### ELECTRODES FOR PHASE
    ref_port_ph = deepcopy(ref_port)
    ref_port_ph.origin[0] = ref_port.origin[0] + 2*wg_sep + x_dist_inout
    x_safe_dist_ph = ref_port_ph.origin[0] + min_safedist_from_wg + pads_width
    x_startpos_pads_ph = s._current_port.origin[0] + 4*pads_pitch + (pads_width_gnd - pads_width)/2. + (pads_width-pads_width_gnd/2.)
    y_startpos_pads_ph = s._current_port.origin[1] +280

    ##right ground electrode
    Inport = Port((ref_port_ph.origin[0] + electrodes_sep / 2.0 + wg_sep / 2.0, ref_port.origin[1]), np.deg2rad(-90), electr_width)
    g_right_ph = Waveguide.make_at_port(Inport)
    g_right_ph.add_straight_segment(MZ_length - cross_width/2. - 2 * sep_econns)
    g_right_ph._current_port.angle = g_right_ph.current_port.angle + np.pi / 2.0
    g_right_ph._current_port.origin[0] = g_right_ph.current_port.origin[0] - g_right_ph.current_port.width / 2.0
    g_right_ph.add_straight_segment_until_x(x_startpos_pads_ph)
    g_right_ph._current_port.angle = g_right_ph.current_port.angle - np.pi / 2.0
    g_right_ph._current_port.origin[0] = g_right_ph.current_port.origin[0] - g_right_ph.current_port.width / 2.0
    g_right_ph.add_straight_segment_until_y(y_startpos_pads_ph-2*sep_econns+ g_right_ph.current_port.width)
    g_right_ph._current_port.origin[0] = g_right_ph._current_port.origin[0] - (pads_width_gnd- g_right_ph.current_port.width) / 2.0
    g_right_ph._current_port.width = pads_width_gnd
    g_right_ph.add_straight_segment_until_y(g_left._current_port.origin[1])

    cell.add_to_layer(electrode_layer, g_right_ph)

    ## signal electrode
    Inport = Port((ref_port_ph.origin[0] - wg_sep / 2.0, ref_port_ph.origin[1]), np.deg2rad(-90), electr_width - electrodes_sep)
    s_ph = Waveguide.make_at_port(Inport)
    s_ph.add_straight_segment(MZ_length - cross_width/2. - sep_econns)
    s_ph._current_port.angle = s.current_port.angle + np.pi / 2.0
    s_ph._current_port.origin[0] = s_ph.current_port.origin[0] - s_ph.current_port.width / 2.0
    s_ph._current_port.width = cross_width
    s_ph.add_straight_segment(wg_sep+5)
    s_ph.add_straight_segment(wg_sep, electr_width)
    s_ph.add_straight_segment_until_x(x_startpos_pads_ph - sep_econns)
    s_ph._current_port.angle = s_ph.current_port.angle - np.pi / 2.0
    s_ph._current_port.origin[0] = s_ph.current_port.origin[0] - s_ph.current_port.width / 2.0
    s_ph.add_straight_segment_until_y(y_startpos_pads_ph-sep_econns)
    s_ph._current_port.angle = s_ph.current_port.angle - np.pi / 2.0
    s_ph._current_port.origin[1] = s_ph.current_port.origin[1] + s_ph.current_port.width / 2.0

    s_ph.add_straight_segment_until_x(s.current_port.origin[0] + 3*pads_pitch-pads_width / 2.0)
    s_ph._current_port.angle = s_ph.current_port.angle + np.pi / 2.0
    s_ph._current_port.origin[0] = s_ph.current_port.origin[0] + pads_width / 2.0
    s_ph._current_port.width = pads_width
    s_ph.add_straight_segment_until_y(s.current_port.origin[1])
    cell.add_to_layer(electrode_layer, s_ph)

    ##left ground electrode
    Inport = Port((ref_port_ph.origin[0] - wg_sep - wg_sep / 2.0 - electrodes_sep / 2.0, ref_port_ph.origin[1]), np.deg2rad(-90), electr_width)
    g_left_ph = Waveguide.make_at_port(Inport)
    g_left_ph.add_straight_segment(MZ_length - cross_width/2.)
    g_left_ph._current_port.angle = g_left_ph.current_port.angle + np.pi / 2.0
    g_left_ph._current_port.origin[0] = g_left_ph.current_port.origin[0] - g_left_ph.current_port.width / 2.0
    g_left_ph._current_port.width = cross_width
    g_left_ph.add_straight_segment(2*wg_sep+5)
    g_left_ph.add_straight_segment(wg_sep, electr_width)
    g_left_ph.add_straight_segment_until_x(x_startpos_pads_ph - 2*sep_econns)
    g_left_ph._current_port.angle = g_left_ph.current_port.angle - np.pi / 2.0
    g_left_ph._current_port.origin[0] = g_left_ph.current_port.origin[0] - g_left_ph.current_port.width / 2.0
    g_left_ph.add_straight_segment_until_y(y_startpos_pads_ph)

    g_left_ph._current_port.angle = g_left_ph.current_port.angle - np.pi / 2.0
    g_left_ph._current_port.origin[1] = g_left_ph.current_port.origin[1] + g_left_ph.current_port.width / 2.0
    g_left_ph.add_straight_segment_until_x(s.current_port.origin[0] + 2*pads_pitch - pads_width / 2.0)
    g_left_ph._current_port.angle = g_left_ph.current_port.angle + np.pi / 2.0
    g_left_ph._current_port.origin[0] = g_left_ph.current_port.origin[0] + pads_width_gnd / 2.0
    g_left_ph._current_port.width = pads_width_gnd
    g_left_ph.add_straight_segment_until_y(g_right_ph.current_port.origin[1])

    g_left_ph._current_port.angle = g_left_ph.current_port.angle + np.pi / 2.0
    g_left_ph._current_port.origin[0] = g_left_ph.current_port.origin[0] - g_left_ph.current_port.width / 2.0
    g_left_ph._current_port.width = pads_width / 2.
    g_left_ph._current_port.origin[1] = g_left_ph.current_port.origin[1] - g_left_ph._current_port.width / 2.
    g_left_ph.add_straight_segment(2 * pads_pitch + pads_width)

    cell.add_to_layer(electrode_layer, g_left_ph)



    ###WRITE FIELDs waveguide

    outer_corners = [(x_in - 80, y_in + 160), (x_in + 5 * 127 + 60, y_in + 160),
                     (x_in + 5 * 127 + 60, y_in + 160 - 1040), (x_in - 80, y_in + 160 - 1040)]
    polygon1 = Polygon(outer_corners)
    cell.add_to_layer(wg_wf_layer, polygon1)
    outer_corners = [(x_in - 80, y_in + 160 - 1040), (x_in + 5 * 127 + 60, y_in + 160 - 1040),
                     (x_in + 5 * 127 + 60, y_in + 160 - 1040 - (MZ_length + 2*taper_length + 660 - 1040)),
                     (x_in - 80, y_in + 160 - 1040 - ((MZ_length + 2*taper_length + 660 - 1040)))]
    polygon2 = Polygon(outer_corners)
    cell.add_to_layer(wg_wf_layer, polygon2)
    polygon = geometric_union([polygon1, polygon2])
    cell.add_to_layer(wg_reg_layer, polygon)

    ###WRITE FIELDs electrodes

    outer_corners = [(x_in - 210, y_in - 100), (x_in + 5 * 127 + 140, y_in - 100),
                     (x_in + 5 * 127 + 140, y_in - 100 - 1040), (x_in - 210, y_in - 100 - 1040)]
    polygon1 = Polygon(outer_corners)
    cell.add_to_layer(electrode_wf_layer, polygon1)
    outer_corners = [(x_in - 210, y_in - 100 - 1040), (x_in + 5 * 127 + 140, y_in - 100 - 1040),
                     (x_in + 5 * 127 + 140, y_in - 100 - 1040 - (MZ_length + 2*taper_length + 762 - 1040)),
                     (x_in - 210, y_in - 100 - 1040 - (MZ_length + 2*taper_length + 762 - 1040))]
    polygon2 = Polygon(outer_corners)
    cell.add_to_layer(electrode_wf_layer, polygon2)
    polygon = geometric_union([polygon1, polygon2])
    cell.add_to_layer(electrode_reg_layer, polygon)

    ####Local markers

    ### first set on layer 3
    positions = [(x_in, y_in - 320), (x_in + 5 * 127 - 60, y_in - 320), (x_in + 5 * 127 - 60, y_in - 320 - 450)]
    marker = [SquareMarker.make_marker(position, 20) for position in positions]
    cell.add_to_layer(3, geometric_union(marker))
    marker = [SquareMarker.make_marker(position, 30) for position in positions]
    cell.add_to_layer(9, geometric_union(marker))
    marker = [SquareMarker.make_marker(position, 40) for position in positions]
    cell.add_to_layer(15, geometric_union(marker))

    ### second set on layer 4
    positions = [(x_in, y_in - 320 - 150), (x_in + 5 * 127 - 60, y_in - 320 - 150), (x_in + 5 * 127-60, y_in - 320 - 300)]
    marker = [SquareMarker.make_marker(position, 20) for position in positions]
    cell.add_to_layer(marker_layer_1, geometric_union(marker))
    marker = [SquareMarker.make_marker(position, 30) for position in positions]
    cell.add_to_layer(wg_layer, geometric_union(marker))
    marker = [SquareMarker.make_marker(position, 40) for position in positions]
    cell.add_to_layer(marker_protection_layer, geometric_union(marker))

    ###Label
    device_label = Text(origin=(x_in, y_in - 700), height=30,
                        text=label, alignment='center-bottom', angle=np.pi)
    cell.add_to_layer(wg_layer, device_label)

    ###Device Info
    info_text = ('MZ_length = %.1f um\nElectrodes_sep = %.1f nm\nCoupler_length= %.1f um\n') \
                % (MZ_length, electrodes_sep, coupler_length)
    device_info = Text(origin=(x_in, y_in - 850), height=20, text=info_text, alignment='center-bottom' , angle=np.pi)
    cell.add_to_layer(comment_layer, device_info)

    return cell
Esempio n. 6
0
def Demux_active(coupler_sep,
                 coupler_length,
                 Mod_length,
                 electrodes_sep,
                 label,
                 exp_wg_width=wg_Expwidth,
                 grating_coupler_period=std_coupler_params['grating_period']):
    cell = Cell('Demux_active' + label)

    x_in = 0
    y_in = 0

    MZ_length = Mod_length + 50

    wg_sep = mod_params['wg_sep']
    wg_sep_out = 60
    wg_sep_small = 10

    wg_width_in_mod = wg_Expwidth
    taper_length = l_Exptaper

    ##Generating input and output grating couplers

    coupler_params = std_coupler_params.copy()
    coupler_params['grating_period'] = grating_coupler_period

    for j in range(4):
        incoupler = GratingCoupler.make_traditional_coupler(
            (x_in + j * opt_space, y_in), **coupler_params)
        cell.add_to_layer(wg_layer, incoupler)

    outcouplers = []
    empty_gratcouplers = 0

    for j in range(4):
        outcoupler = GratingCoupler.make_traditional_coupler(
            (x_in + (j + 4 + empty_gratcouplers) * opt_space, y_in),
            **coupler_params)
        outcouplers.append(outcoupler)
        cell.add_to_layer(wg_layer, outcoupler)

    ###Generating waveguides

    inports = [
        Port((x_in + j * opt_space, y_in), np.deg2rad(90),
             std_coupler_params['width']) for j in (0, 1, 2, 3)
    ]
    wg = [Waveguide.make_at_port(inport) for inport in inports]

    x_ref0 = x_in + 1.5 * opt_space
    # y_ref0 = y_in - 3*bend_r

    x_refout = x_ref0 + (4 + empty_gratcouplers) * opt_space

    x_lastout = x_in + (7 + empty_gratcouplers) * opt_space
    x_centre = (x_in + x_lastout) / 2.
    y_start_epads = y_in - MZ_length - 930

    ########## Input Connections

    for j in range(4):
        # adding final tapers as suggested by Munster, SP 21/10/21
        wg[j].add_straight_segment(grating_added_taper_len,
                                   final_width=wg_width)
        wg[j].add_bend(np.pi / 2.0, bend_r + j * wg_sep_small)
        wg[j].add_straight_segment_until_x(x_in - bend_r - 1)
        wg[j].add_bend(np.pi / 2.0, bend_r + j * wg_sep_small)
        wg[j].add_straight_segment(grating_added_taper_len + 20)
        wg[j].add_bend(np.pi / 2.0, bend_r + j * wg_sep_small)
        wg[j].add_straight_segment_until_x(x_ref0 - (j - 1.5) * wg_sep_out -
                                           bend_r)
        wg[j].add_bend(-np.pi / 2.0, bend_r)

    y_ref0 = wg[-1].current_port.origin[1] - 1
    for j in range(4):
        wg[j].add_straight_segment_until_y(y_ref0)

        ########## Zero-th MZI
        mzi0_xstart = x_ref0
        mzi0_ystart = y_ref0

    for j in (1, 2):
        wgAdd_EulerSBend(wg[j],
                         offset=(j - 1.5) * (wg_sep_out - wg_sep),
                         radius=bend_r)

        ##directional coupler with sinusoidal s-bend
        x_length = 60
        y_length = wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - (j - 1) * (
            wg_sep - wg_width - coupler_sep)
        wg[j].add_parameterized_path(
            path=lambda t: (t * x_length, .5 *
                            (np.cos(np.pi * t) - 1) * y_length),
            path_derivative=lambda t:
            (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length))
        wg[j].add_straight_segment(coupler_length)
        y_length = -(wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - (j - 1) *
                     (wg_sep - wg_width - coupler_sep))
        wg[j].add_parameterized_path(
            path=lambda t: (t * x_length, .5 *
                            (np.cos(np.pi * t) - 1) * y_length),
            path_derivative=lambda t:
            (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length))

        #add taper to multimode wg
        wg[j].add_straight_segment(taper_length, final_width=wg_width_in_mod)

        ###reference port for electrodes in MZI
        ref_port0 = wg[j].current_port

        ###straight section
        wg[j].add_straight_segment(MZ_length)

        #add taper to single-mode wg
        wg[j].add_straight_segment(taper_length, final_width=wg_width)

        ##directional coupler with sinusoidal s-bend
        x_length = 60
        y_length = wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - (j - 1) * (
            wg_sep - wg_width - coupler_sep)
        wg[j].add_parameterized_path(
            path=lambda t: (t * x_length, .5 *
                            (np.cos(np.pi * t) - 1) * y_length),
            path_derivative=lambda t:
            (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length))
        wg[j].add_straight_segment(coupler_length)
        y_length = -(wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - (j - 1) *
                     (wg_sep - wg_width - coupler_sep))
        wg[j].add_parameterized_path(
            path=lambda t: (t * x_length, .5 *
                            (np.cos(np.pi * t) - 1) * y_length),
            path_derivative=lambda t:
            (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length))

        wgAdd_EulerSBend(wg[j],
                         offset=-(j - 1.5) * (wg_sep_out - wg_sep),
                         radius=bend_r)

    mzi0_xend = x_ref0
    mzi0_yend = wg[j].current_port.origin[1]
    for j in (0, 3):
        wg[j].add_straight_segment(l_Exptaper, final_width=exp_wg_width)
        wg[j].add_straight_segment_until_y(mzi0_yend + l_Exptaper)
        wg[j].add_straight_segment(l_Exptaper, final_width=wg_width)

    ########## Turn
    for j in range(4):
        wg[j].add_bend(np.pi / 2.0, bend_r + j * wg_sep_small)
        wg[j].add_straight_segment(l_Exptaper, final_width=exp_wg_width)
        wg[j].add_straight_segment_until_x(x_refout - 1.5 * wg_sep_out -
                                           bend_r + j *
                                           (wg_sep_out - wg_sep_small) -
                                           l_Exptaper)
        wg[j].add_straight_segment(l_Exptaper, final_width=wg_width)
        wg[j].add_bend(np.pi / 2.0, bend_r + j * wg_sep_small)

    ########## First MZI (left)
    mzi1_xstart = wg[0].current_port.origin[0]
    mzi1_ystart = wg[0].current_port.origin[1]

    for j in (0, 1):
        wgAdd_EulerSBend(wg[j],
                         offset=(j - 0.5) * (wg_sep_out - wg_sep),
                         radius=bend_r)

        #directional coupler with sinusoidal s-bend
        x_length = 60
        y_length = wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - j * (
            wg_sep - wg_width - coupler_sep)
        wg[j].add_parameterized_path(
            path=lambda t: (t * x_length, .5 *
                            (np.cos(np.pi * t) - 1) * y_length),
            path_derivative=lambda t:
            (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length))
        wg[j].add_straight_segment(coupler_length)
        y_length = -(wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - j *
                     (wg_sep - wg_width - coupler_sep))
        wg[j].add_parameterized_path(
            path=lambda t: (t * x_length, .5 *
                            (np.cos(np.pi * t) - 1) * y_length),
            path_derivative=lambda t:
            (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length))

        # add taper to multimode wg
        wg[j].add_straight_segment(taper_length, final_width=wg_width_in_mod)

        ###reference port for electrodes in MZI
        ref_port1 = wg[j].current_port

        ###straight section
        wg[j].add_straight_segment(MZ_length)

        # add taper to single-mode wg
        wg[j].add_straight_segment(taper_length, final_width=wg_width)

        ##directional coupler with sinusoidal s-bend
        x_length = 60
        y_length = wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - j * (
            wg_sep - wg_width - coupler_sep)
        wg[j].add_parameterized_path(
            path=lambda t: (t * x_length, .5 *
                            (np.cos(np.pi * t) - 1) * y_length),
            path_derivative=lambda t:
            (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length))
        wg[j].add_straight_segment(coupler_length)
        y_length = -(wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - j *
                     (wg_sep - wg_width - coupler_sep))
        wg[j].add_parameterized_path(
            path=lambda t: (t * x_length, .5 *
                            (np.cos(np.pi * t) - 1) * y_length),
            path_derivative=lambda t:
            (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length))

        wgAdd_EulerSBend(wg[j],
                         offset=-(j - 0.5) * (wg_sep_out - wg_sep),
                         radius=bend_r)

    ########## Second MZI (left)
    mzi1_xstart = wg[2].current_port.origin[0]
    mzi1_ystart = wg[2].current_port.origin[1]

    for j in (2, 3):
        wgAdd_EulerSBend(wg[j],
                         offset=(j - 2.5) * (wg_sep_out - wg_sep),
                         radius=bend_r)

        ##directional coupler with sinusoidal s-bend
        x_length = 60
        y_length = wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - (j - 2) * (
            wg_sep - wg_width - coupler_sep)
        wg[j].add_parameterized_path(
            path=lambda t: (t * x_length, .5 *
                            (np.cos(np.pi * t) - 1) * y_length),
            path_derivative=lambda t:
            (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length))
        wg[j].add_straight_segment(coupler_length)
        y_length = -(wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - (j - 2) *
                     (wg_sep - wg_width - coupler_sep))
        wg[j].add_parameterized_path(
            path=lambda t: (t * x_length, .5 *
                            (np.cos(np.pi * t) - 1) * y_length),
            path_derivative=lambda t:
            (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length))

        # add taper to multimode wg
        wg[j].add_straight_segment(taper_length, final_width=wg_width_in_mod)

        ###reference port for electrodes in MZI
        ref_port2 = wg[j].current_port

        ###straight section
        wg[j].add_straight_segment(MZ_length)

        # add taper to single-mode wg
        wg[j].add_straight_segment(taper_length, final_width=wg_width)

        ##directional coupler with sinusoidal s-bend
        x_length = 60
        y_length = wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - (j - 2) * (
            wg_sep - wg_width - coupler_sep)
        wg[j].add_parameterized_path(
            path=lambda t: (t * x_length, .5 *
                            (np.cos(np.pi * t) - 1) * y_length),
            path_derivative=lambda t:
            (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length))
        wg[j].add_straight_segment(coupler_length)
        y_length = -(wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - (j - 2) *
                     (wg_sep - wg_width - coupler_sep))
        wg[j].add_parameterized_path(
            path=lambda t: (t * x_length, .5 *
                            (np.cos(np.pi * t) - 1) * y_length),
            path_derivative=lambda t:
            (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length))

        wgAdd_EulerSBend(wg[j],
                         offset=-(j - 2.5) * (wg_sep_out - wg_sep),
                         radius=bend_r)

    ########## Output Connections

    for j in range(4):
        wg[j].add_straight_segment((3 - j) * wg_sep_small + 1)
        wg[j].add_bend(-np.pi / 2.0, bend_r)
        wg[j].add_straight_segment_until_x(x_lastout + bend_r + 1)
        wg[j].add_bend(np.pi / 2.0, bend_r + j * wg_sep_small)
        wg[j].add_straight_segment(grating_added_taper_len + 20)
        wg[j].add_bend(np.pi / 2.0, bend_r + j * wg_sep_small)
        wg[j].add_straight_segment_until_x(x_lastout - j * (opt_space) +
                                           bend_r + j * wg_sep_small)
        wg[j].add_bend(np.pi / 2.0, bend_r + j * wg_sep_small)
        wg[j].add_straight_segment(grating_added_taper_len,
                                   final_width=std_coupler_params['width'])

        #
    for j in range(4):
        cell.add_to_layer(wg_layer, wg[j])

    ##MODULATORs ELECTRODES

    electr_width = mod_params['electrode_width']
    sep_econns = mod_params['electrode_sep_y']
    cross_width = mod_params['crossing_width']
    pads_pitch = mod_params['connector_probe_pitch']
    pads_width = mod_params['connector_probe_dims'][0]
    pads_width_gnd = mod_params['connector_probe_dims_gnd'][0]
    pads_len = mod_params['connector_probe_dims'][1] - 200
    min_safedist_from_wg = 22

    x_start_epads = x_centre - 3 * pads_pitch

    #### ELECTRODES IN ZEROTH MZI
    x_safe_dist = ref_port0.origin[
        0] - min_safedist_from_wg - pads_width - wg_sep / 2.0 - wg_sep_out

    ##left ground electrode
    Inport = Port((ref_port0.origin[0] - electrodes_sep / 2.0 - wg_sep / 2.0,
                   ref_port0.origin[1]), np.deg2rad(-90), electr_width)
    g_left0 = Waveguide.make_at_port(Inport)
    g_left0.add_straight_segment(Mod_length - cross_width / 2. -
                                 2 * sep_econns)
    g_left0._current_port.angle = g_left0.current_port.angle - np.pi / 2.0
    g_left0._current_port.origin[
        0] = g_left0.current_port.origin[0] + g_left0.current_port.width / 2.0
    g_left0._current_port.width = cross_width
    g_left0.add_straight_segment_until_x(x_safe_dist + wg_sep_out)
    g_left0.add_straight_segment(wg_sep, electr_width)
    g_left0.add_straight_segment_until_x(x_safe_dist)

    g_left0.add_straight_segment(2 * sep_econns)
    g_left0._current_port.angle = g_left0.current_port.angle + np.pi / 2.0
    g_left0._current_port.origin[
        1] = g_left0.current_port.origin[1] + g_left0.current_port.width / 2.0
    g_left0.add_straight_segment_until_y(y_start_epads - 2 * sep_econns)
    g_left0._current_port.angle = g_left0.current_port.angle + np.pi / 2.0
    g_left0._current_port.origin[
        0] = g_left0.current_port.origin[0] - g_left0.current_port.width / 2.0
    g_left0._current_port.origin[
        1] = g_left0.current_port.origin[1] + g_left0.current_port.width / 2.0
    g_left0.add_straight_segment_until_x(x_start_epads)

    g_left0._current_port.angle = g_left0.current_port.angle - np.pi / 2.0
    g_left0._current_port.origin[0] = g_left0.current_port.origin[
        0]  #+ pads_width_gnd / 2.0
    # g_left0._current_port.origin[1] = g_left0.current_port.origin[1] + g_left0.current_port.width / 2.0
    g_left0._current_port.width = pads_width_gnd
    g_left0.add_straight_segment(pads_len)

    cell.add_to_layer(electrode_layer, g_left0)

    ## signal electrode
    Inport = Port((ref_port0.origin[0] + wg_sep / 2.0, ref_port0.origin[1]),
                  np.deg2rad(-90), electr_width - electrodes_sep)
    s0 = Waveguide.make_at_port(Inport)
    s0.add_straight_segment(Mod_length - cross_width / 2. - sep_econns)
    s0._current_port.angle = s0.current_port.angle - np.pi / 2.0
    s0._current_port.origin[
        0] = s0.current_port.origin[0] + s0.current_port.width / 2.0
    s0._current_port.width = cross_width
    s0.add_straight_segment_until_x(x_safe_dist + wg_sep_out)
    s0.add_straight_segment(wg_sep, electr_width)
    s0.add_straight_segment_until_x(x_safe_dist)

    s0.add_straight_segment(sep_econns)
    s0._current_port.angle = s0.current_port.angle + np.pi / 2.0
    s0._current_port.origin[
        1] = s0.current_port.origin[1] + s0.current_port.width / 2.0
    s0.add_straight_segment_until_y(y_start_epads - sep_econns)
    s0._current_port.angle = s0.current_port.angle + np.pi / 2.0
    s0._current_port.origin[
        0] = s0.current_port.origin[0] - s0.current_port.width / 2.0
    s0.add_straight_segment_until_x(x_start_epads + pads_pitch)
    #
    s0._current_port.angle = s0.current_port.angle - np.pi / 2.0
    s0._current_port.origin[0] = s0.current_port.origin[0]  #+ pads_width / 2.0
    s0._current_port.origin[
        1] = s0.current_port.origin[1] + s0.current_port.width / 2.0
    s0._current_port.width = pads_width
    s0.add_straight_segment_until_y(g_left0.current_port.origin[1] + 50)

    cell.add_to_layer(electrode_layer, s0)

    # ##right ground electrode
    Inport = Port(
        (ref_port0.origin[0] + wg_sep + wg_sep / 2.0 + electrodes_sep / 2.0,
         ref_port0.origin[1]), np.deg2rad(-90), electr_width)
    g_right0 = Waveguide.make_at_port(Inport)
    g_right0.add_straight_segment(Mod_length - cross_width / 2.)
    g_right0._current_port.angle = g_right0.current_port.angle - np.pi / 2.0
    g_right0._current_port.origin[0] = g_right0.current_port.origin[
        0] + g_right0.current_port.width / 2.0
    g_right0._current_port.width = cross_width
    g_right0.add_straight_segment_until_x(x_safe_dist + wg_sep_out)
    g_right0.add_straight_segment(wg_sep, electr_width)
    g_right0.add_straight_segment_until_x(x_safe_dist)

    g_right0._current_port.angle = g_right0.current_port.angle + np.pi / 2.0
    g_right0._current_port.origin[1] = g_right0.current_port.origin[
        1] + g_right0.current_port.width / 2.0
    g_right0.add_straight_segment_until_y(y_start_epads)
    g_right0._current_port.angle = g_right0.current_port.angle + np.pi / 2.0
    g_right0._current_port.origin[0] = g_right0.current_port.origin[
        0] - g_right0.current_port.width / 2.0
    g_right0.add_straight_segment_until_x(x_start_epads + 2 * pads_pitch)

    g_right0._current_port.angle = g_right0.current_port.angle - np.pi / 2.0
    g_right0._current_port.origin[0] = g_right0.current_port.origin[
        0]  #+ 5. #+ pads_width_gnd / 2.0
    g_right0._current_port.origin[1] = g_right0.current_port.origin[
        1] + g_right0.current_port.width / 2.0
    g_right0._current_port.width = pads_width_gnd
    g_right0.add_straight_segment_until_y(g_left0.current_port.origin[1])
    g_right0._current_port.angle = g_right0.current_port.angle - np.pi / 2.0
    g_right0._current_port.origin[0] = g_right0.current_port.origin[
        0] + g_right0.current_port.width / 2.0
    g_right0._current_port.width = pads_width / 2.
    g_right0._current_port.origin[1] = g_right0.current_port.origin[
        1] - g_right0._current_port.width / 2.
    # g_right0.add_straight_segment(2 * pads_pitch + pads_width)
    g_right0.add_straight_segment(2 * pads_pitch + pads_width_gnd)

    cell.add_to_layer(electrode_layer, g_right0)

    # #### ELECTRODES FOR FIRST MZI
    elec_offset = 90
    x_safe_dist = ref_port1.origin[
        0] + min_safedist_from_wg + pads_width + wg_sep / 2.0 + 2 * wg_sep_out

    ##right ground electrode
    Inport = Port(
        (ref_port1.origin[0] + wg_sep - wg_sep / 2.0 + electrodes_sep / 2.0,
         ref_port1.origin[1] + MZ_length - elec_offset), np.deg2rad(-90),
        electr_width)
    g_right1 = Waveguide.make_at_port(Inport)
    g_right1.add_straight_segment(Mod_length - cross_width / 2. -
                                  2 * sep_econns)
    g_right1._current_port.angle = g_right1.current_port.angle + np.pi / 2.0
    g_right1._current_port.origin[0] = g_right1.current_port.origin[
        0] - g_right1.current_port.width / 2.0
    g_right1._current_port.width = cross_width
    g_right1.add_straight_segment_until_x(x_safe_dist - wg_sep_out)
    g_right1.add_straight_segment(wg_sep, electr_width)
    g_right1.add_straight_segment_until_x(x_safe_dist)

    g_right1.add_straight_segment(2 * sep_econns)
    g_right1._current_port.angle = g_right1.current_port.angle - np.pi / 2.0
    g_right1._current_port.origin[1] = g_right1.current_port.origin[
        1] + g_right1.current_port.width / 2.0
    g_right1.add_straight_segment_until_y(y_start_epads - 2 * sep_econns)
    g_right1._current_port.angle = g_right1.current_port.angle - np.pi / 2.0
    g_right1._current_port.origin[0] = g_right1.current_port.origin[
        0] + g_right1.current_port.width / 2.0
    g_right1.add_straight_segment_until_x(x_start_epads + 4 * pads_pitch)

    g_right1._current_port.angle = g_right1.current_port.angle + np.pi / 2.0
    g_right1._current_port.origin[0] = g_right1.current_port.origin[
        0]  #+ 5. #+ pads_width_gnd / 2.0
    g_right1._current_port.origin[1] = g_right1.current_port.origin[
        1] + g_right1.current_port.width / 2.0
    g_right1._current_port.width = pads_width_gnd
    g_right1.add_straight_segment_until_y(g_left0.current_port.origin[1])
    g_right1._current_port.angle = g_right1.current_port.angle - np.pi / 2.0
    g_right1._current_port.origin[0] = g_right1.current_port.origin[
        0] + g_right1.current_port.width / 2.0
    g_right1._current_port.width = pads_width / 2.
    g_right1._current_port.origin[1] = g_right1.current_port.origin[
        1] - g_right1._current_port.width / 2.
    g_right1.add_straight_segment(2 * pads_pitch + pads_width)

    cell.add_to_layer(electrode_layer, g_right1)

    ## signal electrode
    Inport = Port((ref_port1.origin[0] - wg_sep / 2.0,
                   ref_port1.origin[1] + MZ_length - elec_offset),
                  np.deg2rad(-90), electr_width - electrodes_sep)
    s1 = Waveguide.make_at_port(Inport)
    s1.add_straight_segment(Mod_length - cross_width / 2. - sep_econns)
    s1._current_port.angle = s1.current_port.angle + np.pi / 2.0
    s1._current_port.origin[
        0] = s1.current_port.origin[0] - s1.current_port.width / 2.0
    s1._current_port.width = cross_width
    s1.add_straight_segment_until_x(x_safe_dist - wg_sep_out)
    s1.add_straight_segment(wg_sep, electr_width)
    s1.add_straight_segment_until_x(x_safe_dist)

    s1.add_straight_segment(sep_econns)
    s1._current_port.angle = s1.current_port.angle - np.pi / 2.0
    s1._current_port.origin[
        1] = s1.current_port.origin[1] + s1.current_port.width / 2.0
    s1.add_straight_segment_until_y(y_start_epads - sep_econns)
    s1._current_port.angle = s1.current_port.angle - np.pi / 2.0
    s1._current_port.origin[
        0] = s1.current_port.origin[0] + s1.current_port.width / 2.0
    s1.add_straight_segment_until_x(x_start_epads + 3 * pads_pitch)

    s1._current_port.angle = s1.current_port.angle + np.pi / 2.0
    s1._current_port.origin[0] = s1.current_port.origin[0]  #+ pads_width / 2.0
    s1._current_port.origin[
        1] = s1.current_port.origin[1] + s1.current_port.width / 2.0
    s1._current_port.width = pads_width
    s1.add_straight_segment_until_y(g_left0.current_port.origin[1] + 50)

    cell.add_to_layer(electrode_layer, s1)

    # ##left ground electrode
    Inport = Port(
        (ref_port1.origin[0] - wg_sep - wg_sep / 2.0 - electrodes_sep / 2.0,
         ref_port1.origin[1] + MZ_length - elec_offset), np.deg2rad(-90),
        electr_width)
    g_left1 = Waveguide.make_at_port(Inport)
    g_left1.add_straight_segment(Mod_length - cross_width / 2.)
    g_left1._current_port.angle = g_left1.current_port.angle + np.pi / 2.0
    g_left1._current_port.origin[
        0] = g_left1.current_port.origin[0] - g_left1.current_port.width / 2.0
    g_left1._current_port.width = cross_width
    g_left1.add_straight_segment_until_x(x_safe_dist - wg_sep_out)
    g_left1.add_straight_segment(wg_sep, electr_width)
    g_left1.add_straight_segment_until_x(x_safe_dist)

    g_left1._current_port.angle = g_left1.current_port.angle - np.pi / 2.0
    g_left1._current_port.origin[
        1] = g_left1.current_port.origin[1] + g_left1.current_port.width / 2.0
    g_left1.add_straight_segment_until_y(y_start_epads)
    g_left1._current_port.angle = g_left1.current_port.angle - np.pi / 2.0
    g_left1._current_port.origin[
        0] = g_left1.current_port.origin[0] + g_left1.current_port.width / 2.0
    g_left1.add_straight_segment_until_x(x_start_epads + 2 * pads_pitch)

    # g_left1._current_port.angle = g_left1.current_port.angle + np.pi / 2.0
    # g_left1._current_port.origin[0] = g_left1.current_port.origin[0] + pads_width_gnd / 2.0
    # g_left1._current_port.origin[1] = g_left1.current_port.origin[1] + g_left1.current_port.width / 2.0
    # g_left1._current_port.width = pads_width_gnd
    # g_left1.add_straight_segment_until_y(g_left0.current_port.origin[1])

    cell.add_to_layer(electrode_layer, g_left1)

    # #### ELECTRODES FOR SECOND MZI
    # x_safe_dist = x_safe_dist + 3*sep_econns

    ##right ground electrode
    Inport = Port(
        (ref_port2.origin[0] + wg_sep - wg_sep / 2.0 + electrodes_sep / 2.0,
         ref_port2.origin[1] + elec_offset), np.deg2rad(90), electr_width)
    g_right2 = Waveguide.make_at_port(Inport)
    g_right2.add_straight_segment(Mod_length - cross_width / 2. -
                                  2 * sep_econns)
    g_right2._current_port.angle = g_right2.current_port.angle - np.pi / 2.0
    g_right2._current_port.origin[0] = g_right2.current_port.origin[
        0] - g_right2.current_port.width / 2.0
    g_right2._current_port.width = cross_width
    g_right2.add_straight_segment_until_x(x_safe_dist - wg_sep_out)
    g_right2.add_straight_segment(wg_sep, electr_width)
    g_right2.add_straight_segment_until_x(x_safe_dist)

    g_right2.add_straight_segment(3 * sep_econns)
    g_right2._current_port.angle = g_right2.current_port.angle - np.pi / 2.0
    g_right2._current_port.origin[1] = g_right2.current_port.origin[
        1] + g_right2.current_port.width / 2.0
    g_right2.add_straight_segment_until_y(y_start_epads - 2 * sep_econns)
    g_right2._current_port.angle = g_right2.current_port.angle - np.pi / 2.0
    g_right2._current_port.origin[0] = g_right2.current_port.origin[
        0] + g_right2.current_port.width / 2.0
    g_right2.add_straight_segment_until_x(x_start_epads + 4 * pads_pitch)

    # g_right2._current_port.angle = g_right2.current_port.angle + np.pi / 2.0
    # g_right2._current_port.origin[0] = g_right2.current_port.origin[0] #+ pads_width_gnd / 2.0
    # g_right2._current_port.origin[1] = g_right2.current_port.origin[1] + g_right2.current_port.width / 2.0
    # g_right2._current_port.width = pads_width_gnd
    # g_right2.add_straight_segment_until_y(g_left0.current_port.origin[1])

    cell.add_to_layer(electrode_layer, g_right2)

    ## signal electrode
    Inport = Port((ref_port2.origin[0] - wg_sep / 2.0,
                   ref_port2.origin[1] + elec_offset), np.deg2rad(90),
                  electr_width - electrodes_sep)
    s2 = Waveguide.make_at_port(Inport)
    s2.add_straight_segment(Mod_length - cross_width / 2. - sep_econns)
    s2._current_port.angle = s2.current_port.angle - np.pi / 2.0
    s2._current_port.origin[
        0] = s2.current_port.origin[0] - s2.current_port.width / 2.0
    s2._current_port.width = cross_width
    s2.add_straight_segment_until_x(x_safe_dist - wg_sep_out)
    s2.add_straight_segment(wg_sep, electr_width)
    s2.add_straight_segment_until_x(x_safe_dist)

    s2.add_straight_segment(4 * sep_econns)
    s2._current_port.angle = s2.current_port.angle - np.pi / 2.0
    s2._current_port.origin[
        1] = s2.current_port.origin[1] + s2.current_port.width / 2.0
    s2.add_straight_segment_until_y(y_start_epads - 3 * sep_econns)
    s2._current_port.angle = s2.current_port.angle - np.pi / 2.0
    s2._current_port.origin[
        0] = s2.current_port.origin[0] + s2.current_port.width / 2.0
    s2.add_straight_segment_until_x(x_start_epads + 5 * pads_pitch)
    #
    s2._current_port.angle = s2.current_port.angle + np.pi / 2.0
    s2._current_port.origin[0] = s2.current_port.origin[0]  #+ pads_width / 2.0
    s2._current_port.origin[
        1] = s2.current_port.origin[1] + s2.current_port.width / 2.0
    s2._current_port.width = pads_width
    s2.add_straight_segment_until_y(g_left0.current_port.origin[1] + 50)

    cell.add_to_layer(electrode_layer, s2)

    # ##left ground electrode
    Inport = Port(
        (ref_port2.origin[0] - wg_sep - wg_sep / 2.0 - electrodes_sep / 2.0,
         ref_port2.origin[1] + elec_offset), np.deg2rad(90), electr_width)
    g_left2 = Waveguide.make_at_port(Inport)
    g_left2.add_straight_segment(Mod_length - cross_width / 2.)
    g_left2._current_port.angle = g_left2.current_port.angle - np.pi / 2.0
    g_left2._current_port.origin[
        0] = g_left2.current_port.origin[0] - g_left2.current_port.width / 2.0
    g_left2._current_port.width = cross_width
    g_left2.add_straight_segment_until_x(x_safe_dist - wg_sep_out)
    g_left2.add_straight_segment(wg_sep, electr_width)
    g_left2.add_straight_segment_until_x(x_safe_dist)

    g_left2.add_straight_segment(5 * sep_econns)
    g_left2._current_port.angle = g_left2.current_port.angle - np.pi / 2.0
    g_left2._current_port.origin[
        1] = g_left2.current_port.origin[1] + g_left2.current_port.width / 2.0
    g_left2.add_straight_segment_until_y(y_start_epads - 4 * sep_econns)
    g_left2._current_port.angle = g_left2.current_port.angle - np.pi / 2.0
    g_left2._current_port.origin[
        0] = g_left2.current_port.origin[0] + g_left2.current_port.width / 2.0
    # g_left2._current_port.origin[1] = g_left2.current_port.origin[1] + g_left2.current_port.width / 2.0
    g_left2.add_straight_segment_until_x(x_start_epads + 6 * pads_pitch)
    g_left2._current_port.origin[
        1] = g_left2.current_port.origin[1] - g_left2.current_port.width / 2.0

    g_left2._current_port.angle = g_left2.current_port.angle + np.pi / 2.0
    g_left2._current_port.origin[0] = g_left2.current_port.origin[
        0]  #+ 5. #+ pads_width_gnd / 2.0
    g_left2._current_port.origin[
        1] = g_left2.current_port.origin[1] + g_left2.current_port.width
    g_left2._current_port.width = pads_width_gnd
    g_left2.add_straight_segment_until_y(g_left0.current_port.origin[1])
    g_left2._current_port.angle = g_left2.current_port.angle - np.pi / 2.0
    g_left2._current_port.origin[
        0] = g_left2.current_port.origin[0] + g_left2.current_port.width / 2.0
    g_left2._current_port.width = pads_width / 2.
    g_left2._current_port.origin[
        1] = g_left2.current_port.origin[1] - g_left2._current_port.width / 2.
    g_left2.add_straight_segment(2 * pads_pitch + pads_width)

    cell.add_to_layer(electrode_layer, g_left2)

    #
    #
    #
    # ###WRITE FIELDs waveguide
    #
    # outer_corners = [(x_in - 80, y_in + 160), (x_in + 5 * 127 + 60, y_in + 160),
    #                  (x_in + 5 * 127 + 60, y_in + 160 - 1040), (x_in - 80, y_in + 160 - 1040)]
    # polygon1 = Polygon(outer_corners)
    # cell.add_to_layer(wg_wf_layer, polygon1)
    # outer_corners = [(x_in - 80, y_in + 160 - 1040), (x_in + 5 * 127 + 60, y_in + 160 - 1040),
    #                  (x_in + 5 * 127 + 60, y_in + 160 - 1040 - (MZ_length + 2*taper_length + 660 - 1040)),
    #                  (x_in - 80, y_in + 160 - 1040 - ((MZ_length + 2*taper_length + 660 - 1040)))]
    # polygon2 = Polygon(outer_corners)
    # cell.add_to_layer(wg_wf_layer, polygon2)
    # polygon = geometric_union([polygon1, polygon2])
    # cell.add_to_layer(wg_reg_layer, polygon)
    #
    # ###WRITE FIELDs electrodes
    #
    # outer_corners = [(x_in - 210, y_in - 100), (x_in + 5 * 127 + 140, y_in - 100),
    #                  (x_in + 5 * 127 + 140, y_in - 100 - 1040), (x_in - 210, y_in - 100 - 1040)]
    # polygon1 = Polygon(outer_corners)
    # cell.add_to_layer(electrode_wf_layer, polygon1)
    # outer_corners = [(x_in - 210, y_in - 100 - 1040), (x_in + 5 * 127 + 140, y_in - 100 - 1040),
    #                  (x_in + 5 * 127 + 140, y_in - 100 - 1040 - (MZ_length + 2*taper_length + 762 - 1040)),
    #                  (x_in - 210, y_in - 100 - 1040 - (MZ_length + 2*taper_length + 762 - 1040))]
    # polygon2 = Polygon(outer_corners)
    # cell.add_to_layer(electrode_wf_layer, polygon2)
    # polygon = geometric_union([polygon1, polygon2])
    # cell.add_to_layer(electrode_reg_layer, polygon)
    #
    # ####Local markers
    #
    # ### first set on layer 3
    # positions = [(x_in, y_in - 320), (x_in + 5 * 127 - 60, y_in - 320), (x_in + 5 * 127 - 60, y_in - 320 - 450)]
    # marker = [SquareMarker.make_marker(position, 20) for position in positions]
    # cell.add_to_layer(3, geometric_union(marker))
    # marker = [SquareMarker.make_marker(position, 30) for position in positions]
    # cell.add_to_layer(9, geometric_union(marker))
    # marker = [SquareMarker.make_marker(position, 40) for position in positions]
    # cell.add_to_layer(15, geometric_union(marker))
    #
    # ### second set on layer 4
    # positions = [(x_in, y_in - 320 - 150), (x_in + 5 * 127 - 60, y_in - 320 - 150), (x_in + 5 * 127-60, y_in - 320 - 300)]
    # marker = [SquareMarker.make_marker(position, 20) for position in positions]
    # cell.add_to_layer(marker_layer_1, geometric_union(marker))
    # marker = [SquareMarker.make_marker(position, 30) for position in positions]
    # cell.add_to_layer(wg_layer, geometric_union(marker))
    # marker = [SquareMarker.make_marker(position, 40) for position in positions]
    # cell.add_to_layer(marker_protection_layer, geometric_union(marker))

    ###Label
    device_label = Text(origin=(x_in, y_in - 700),
                        height=30,
                        text=label,
                        alignment='center-bottom',
                        angle=np.pi)
    cell.add_to_layer(wg_layer, device_label)

    ###Device Info
    info_text = ('Mod_length = %.1f um\nElectrodes_sep = %.1f nm\nCoupler_length= %.1f um\n') \
                % (Mod_length, electrodes_sep, coupler_length)
    device_info = Text(origin=(x_in, y_in - 850),
                       height=20,
                       text=info_text,
                       alignment='center-bottom',
                       angle=np.pi)
    cell.add_to_layer(comment_layer, device_info)

    return cell
Esempio n. 7
0
    fig, ax = plt.subplots()
    ax.plot([el[0] for el in asd], [el[1] for el in asd],
            alpha=0.7,
            lw=3,
            label='Abs')
    # ax.plot([el[0] for el in asd_rel], [el[1] for el in asd_rel], alpha=0.7, lw=2, label='Rel')
    # print(asd[-1], asd_rel[-1], end_pt)
    ax.legend()
    ax.set_aspect('equal')
    plt.show()

    #########################################################
    ##########       Tests with GDShelpers          #########
    #########################################################

    wg = Waveguide.make_at_port(Port((0, 0), angle=np.pi / 2, width=1.3))
    wg.add_straight_segment(radius)
    wg.add_bend(-np.pi / 3, radius, final_width=1.5)

    wgAdd_EulerWiggle(wg,
                      radius=radius,
                      target_path_length=target_path_length,
                      target_crow_length=target_crow_length,
                      internal_angle_mod=0.0,
                      N_turns=N_turns,
                      mirrored=mirrored,
                      resolution=resolution)

    cell = Cell('CELL')
    cell.add_to_layer(1, wg)  # red
    cell.show()
Esempio n. 8
0
# bottom left
shape1 = iop.port_shape_polar(20)
# ^square with sides of length = 40, centre to side distance = 20
shape2 = iop.port_shape_polar(20, radial_type='to_corner')
# ^square with centre to corner distance = 20

# top left
shape3 = iop.port_shape_polar(20, offset=(0, 60), sides=5, rotate=np.pi/5)
# ^ create pentagon rotated 36 degrees.
shape4 = iop.port_shape_polar(20, offset=(0, 60), sides=5, radial_type="to_corner")
# ^ create pentagon using to_corner type to show that it corners touch shape 3's sides.

# top right
shape5 = iop.port_shape_polar((20, 15), offset=(60, 60))
# ^ specify multiple radii to create more complex shapes
shape6 = iop.port_shape_polar((20, 5), offset=(60, 60), sides=6)
# ^ specify multiple radii to create more complex shapes, regardless of sides

# bottom right
shape7 = iop.port_shape_polar(20, port=Port((60, 0), 0, 1), offset=(0, 0))
# ^ define shape position based off port
shape8 = iop.port_shape_polar(10, port=Port((30, 0), 0, 1), offset=(30, 0))
# ^ define shape position based off port and offset

cell = Cell('port_shape_polar_example')
cell.add_to_layer(1, shape1[0], shape3[0], shape5[0], shape7[0])  # red shapes
cell.add_to_layer(2, shape2[0], shape4[0], shape6[0], shape8[0])  # green shapes

cell.show()
def RectangularSpiral(label, num, add_xlength=0., add_ylength=100., sep=4., r_curve=50., return_xmax=False, grating_angle = None, exp_wg_width=wg_Expwidth, grating_coupler_period = std_coupler_params['grating_period']):
    cell = Cell('DC_Test' + label)

    r_eff = r_curve / euler_to_bend_coeff

    delta = 2 * sep
    orizontal_length = add_xlength + 2 * sep

    coupler_params = std_coupler_params.copy()
    coupler_params['grating_period'] = grating_coupler_period
    if grating_angle is not None:
        coupler_params['full_opening_angle'] = grating_angle

    grating_coupl_pos = np.array((0, 0))

    couplers = [
        GratingCoupler.make_traditional_coupler(grating_coupl_pos + (opt_space * x, 0), **coupler_params) for x
        in
        (0, 1)]

    # ports = [Port(grating_coupl_pos - (opt_space * x, 0), np.pi / 2, wg_width) for x in (0, 1)]
    ### Adding final tapers as suggested by Munster, SP 21/10/21
    ports = [Port(grating_coupl_pos - (opt_space * x, 0), np.pi / 2, std_coupler_params['width']) for x in (0, 1)]

    couplers = [GratingCoupler.make_traditional_coupler_at_port(port, **coupler_params) for port in ports]

    waveguides = [Waveguide.make_at_port(port.inverted_direction) for port in ports]
    ### Adding final tapers as suggested by Munster, SP 21/10/21
    waveguides[0].add_straight_segment(grating_added_taper_len, final_width=wg_width)
    waveguides[0].add_straight_segment(sep, final_width=wg_width)
    wgAdd_EulerBend(waveguides[0], -np.pi / 2, r_eff, True)
    waveguides[0].add_straight_segment(sep + opt_space)
    wgAdd_EulerBend(waveguides[0], -np.pi / 2., r_eff, True)

    ### Adding final tapers as suggested by Munster, SP 21/10/21
    waveguides[1].add_straight_segment(grating_added_taper_len, final_width=wg_width)
    wgAdd_EulerBend(waveguides[1], -np.pi / 2., r_eff, True)
    wgAdd_EulerBend(waveguides[1], -np.pi / 2., r_eff, True)
    waveguides[1].add_straight_segment(grating_added_taper_len, final_width=wg_width)

    origin_spiral = Port((-opt_space / 2., 320 + add_ylength / 2. + num * sep), 0, wg_width)

    wg1 = Waveguide.make_at_port(origin_spiral)
    wgAdd_EulerBend(wg1, -np.pi / 2., r_eff, True)
    if add_ylength > (4 * l_Exptaper):
        wg1.add_straight_segment(l_Exptaper, final_width=exp_wg_width)
        wg1.add_straight_segment(add_ylength / 2. - 2 * l_Exptaper)
        wg1.add_straight_segment(l_Exptaper, final_width=wg_width)
    else:
        wg1.add_straight_segment(add_ylength / 2.)
    wgAdd_EulerBend(wg1, -np.pi / 2., r_eff, True)
    if (add_xlength / 2. + sep) > (2 * l_Exptaper):
        wg1.add_straight_segment(l_Exptaper, final_width=exp_wg_width)
        wg1.add_straight_segment(add_xlength / 2. + sep - 2 * l_Exptaper)
        wg1.add_straight_segment(l_Exptaper, final_width=wg_width)
    else:
        wg1.add_straight_segment(add_xlength / 2. + sep)
    wgAdd_EulerBend(wg1, -np.pi / 2., r_eff, True)
    if (sep + add_ylength + 2 * r_curve) > (2 * l_Exptaper):
        wg1.add_straight_segment(l_Exptaper, final_width=exp_wg_width)
        wg1.add_straight_segment(sep + add_ylength + 2 * r_curve - 2 * l_Exptaper)
        wg1.add_straight_segment(l_Exptaper, final_width=wg_width)
    else:
        wg1.add_straight_segment(sep + add_ylength + 2 * r_curve)
    wgAdd_EulerBend(wg1, -np.pi / 2., r_eff, True)

    wg2 = Waveguide.make_at_port(origin_spiral.inverted_direction)
    wgAdd_EulerBend(wg2, -np.pi / 2., r_eff, True)
    if add_ylength > (4 * l_Exptaper):
        wg2.add_straight_segment(l_Exptaper, final_width=exp_wg_width)
        wg2.add_straight_segment(add_ylength / 2. - 2 * l_Exptaper)
        wg2.add_straight_segment(l_Exptaper, final_width=wg_width)
    else:
        wg2.add_straight_segment(add_ylength / 2.)
    wgAdd_EulerBend(wg2, -np.pi / 2., r_eff, True)
    if (add_xlength / 2. + sep) > (2 * l_Exptaper):
        wg2.add_straight_segment(l_Exptaper, final_width=exp_wg_width)
        wg2.add_straight_segment(add_xlength / 2. + sep - 2 * l_Exptaper)
        wg2.add_straight_segment(l_Exptaper, final_width=wg_width)
    else:
        wg2.add_straight_segment(add_xlength / 2. + sep)
    wgAdd_EulerBend(wg2, -np.pi / 2., r_eff, True)
    if (sep + add_ylength + 2 * r_curve) > (2 * l_Exptaper):
        wg2.add_straight_segment(l_Exptaper, final_width=exp_wg_width)
        wg2.add_straight_segment(sep + add_ylength + 2 * r_curve - 2 * l_Exptaper)
        wg2.add_straight_segment(l_Exptaper, final_width=wg_width)
    else:
        wg2.add_straight_segment(sep + add_ylength + 2 * r_curve)
    wgAdd_EulerBend(wg2, -np.pi / 2., r_eff, True)
    if (orizontal_length + sep) > (2 * l_Exptaper):
        wg2.add_straight_segment(l_Exptaper, final_width=exp_wg_width)
        wg2.add_straight_segment(orizontal_length + sep - 2 * l_Exptaper)
        wg2.add_straight_segment(l_Exptaper, final_width=wg_width)
    else:
        wg2.add_straight_segment(orizontal_length + sep)
    wgAdd_EulerBend(wg2, -np.pi / 2., r_eff, True)
    if (sep + delta + add_ylength + 2 * r_curve) > (2 * l_Exptaper):
        wg2.add_straight_segment(l_Exptaper, final_width=exp_wg_width)
        wg2.add_straight_segment(sep + delta + add_ylength + 2 * r_curve - 2 * l_Exptaper)
        wg2.add_straight_segment(l_Exptaper, final_width=wg_width)
    else:
        wg2.add_straight_segment(sep + delta + add_ylength + 2 * r_curve)
    wgAdd_EulerBend(wg2, -np.pi / 2., r_eff, True)

    for i in np.arange(1, num):
        if (orizontal_length + delta * i - sep) > (2 * l_Exptaper):
            wg1.add_straight_segment(l_Exptaper, final_width=exp_wg_width)
            wg1.add_straight_segment(orizontal_length + delta * i - sep - 2 * l_Exptaper)
            wg1.add_straight_segment(l_Exptaper, final_width=wg_width)
        else:
            wg1.add_straight_segment(orizontal_length + delta * i - sep)
        wgAdd_EulerBend(wg1, -np.pi / 2., r_eff, True)
        if (delta * i + sep + add_ylength + 2 * r_curve) > (2 * l_Exptaper):
            wg1.add_straight_segment(l_Exptaper, final_width=exp_wg_width)
            wg1.add_straight_segment(delta * i + sep + add_ylength + 2 * r_curve - 2 * l_Exptaper)
            wg1.add_straight_segment(l_Exptaper, final_width=wg_width)
        else:
            wg1.add_straight_segment(delta * i + sep + add_ylength + 2 * r_curve)
        wgAdd_EulerBend(wg1, -np.pi / 2., r_eff, True)

    for j in np.arange(2, num):
        if (orizontal_length + j * delta - sep) > (2 * l_Exptaper):
            wg2.add_straight_segment(l_Exptaper, final_width=exp_wg_width)
            wg2.add_straight_segment(orizontal_length + j * delta - sep - 2 * l_Exptaper)
            wg2.add_straight_segment(l_Exptaper, final_width=wg_width)
        else:
            wg2.add_straight_segment(orizontal_length + j * delta - sep)
        wgAdd_EulerBend(wg2, -np.pi / 2., r_eff, True)
        if (delta * (j + 1) - sep + add_ylength + 2 * r_curve) > (2 * l_Exptaper):
            wg2.add_straight_segment(l_Exptaper, final_width=exp_wg_width)
            wg2.add_straight_segment(delta * (j + 1) - sep + add_ylength + 2 * r_curve - 2 * l_Exptaper)
            wg2.add_straight_segment(l_Exptaper, final_width=wg_width)
        else:
            wg2.add_straight_segment(delta * (j + 1) - sep + add_ylength + 2 * r_curve)
        wgAdd_EulerBend(wg2, -np.pi / 2., r_eff, True)

    waveguides[0].add_straight_segment(l_Exptaper, final_width=exp_wg_width)
    waveguides[0].add_straight_segment_until_y(wg1.y - r_curve - l_Exptaper)
    waveguides[0].add_straight_segment(l_Exptaper, final_width=wg_width)
    wgAdd_EulerBend(waveguides[0], -np.pi / 2., r_eff, True)
    waveguides[0].add_straight_segment(l_Exptaper, final_width=exp_wg_width)
    waveguides[0].add_straight_segment_until_x(wg1.x - l_Exptaper)
    waveguides[0].add_straight_segment(l_Exptaper, final_width=wg_width)

    waveguides[1].add_straight_segment(r_curve / 2., final_width=wg_width)
    wgAdd_EulerBend(waveguides[1], -np.pi / 2., r_eff, True)
    #
    if (num * delta - sep + orizontal_length) > 2 * l_Exptaper:
        wg2.add_straight_segment(l_Exptaper, final_width=exp_wg_width)
        wg2.add_straight_segment(num * delta - sep + orizontal_length - 2 * l_Exptaper)
        wg2.add_straight_segment(l_Exptaper, final_width=wg_width)
    else:
        wg2.add_straight_segment(num * delta - sep + orizontal_length)
    wgAdd_EulerBend(wg2, -np.pi / 2., r_eff, True)

    waveguides[1].add_straight_segment(l_Exptaper, final_width=exp_wg_width)
    waveguides[1].add_straight_segment_until_x(wg2.x - r_curve - l_Exptaper)
    waveguides[1].add_straight_segment(l_Exptaper, final_width=wg_width)
    wgAdd_EulerBend(waveguides[1], np.pi / 2., r_eff, False)
    waveguides[1].add_straight_segment(l_Exptaper, final_width=exp_wg_width)
    waveguides[1].add_straight_segment_until_y(wg2.y - l_Exptaper)
    waveguides[1].add_straight_segment(l_Exptaper, final_width=wg_width)

    label_txt = Text(origin_spiral.origin + (0, -r_curve), 25, label, alignment='center-top')

    shapely_object = geometric_union(waveguides + [wg1, wg2, label_txt] + couplers)
    cell.add_to_layer(wg_layer, shapely_object)

    comments = Text((-100, -10), 30,
                    'length={:.2f}'.format(
                        (wg1.length + wg2.length + waveguides[1].length + waveguides[0].length) * 1e-4),
                    alignment='center-top')
    cell.add_to_layer(comment_layer, comments)

    x_cords = []
    y_cords = []
    for this_poly in shapely_object.geoms:
        temp_x_cords, temp_y_cords = this_poly.exterior.coords.xy
        x_cords = x_cords + list(temp_x_cords)
        y_cords = y_cords + list(temp_y_cords)
    x_max = max(x_cords) + box_dist
    x_min = min(x_cords) - box_dist
    y_max = max(y_cords) + box_dist
    y_min = min(y_cords) - box_dist
    box_size = (x_max - x_min, y_max - y_min)

    num_boxes = int(box_size[1] / max_box_size[1]) + 1
    box_x_dim = box_size[0]
    box_y_dim = box_size[1] / num_boxes
    box_list = []
    for i in range(num_boxes):
        box = Waveguide(((x_min + x_max) / 2., y_min + i * box_y_dim), np.pi / 2, box_x_dim)
        box.add_straight_segment(box_y_dim)
        box_list.append(box)
    # self.box = geometric_union(box_list)
    for this_box in box_list:
        cell.add_to_layer(wg_wf_layer, this_box)
    all_boxes = geometric_union(box_list)
    cell.add_to_layer(wg_reg_layer, all_boxes)

    if return_xmax:
        return cell, x_max
    else:
        return cell
def phase_shifter_electrodes(cell, reference_port, crossing_goal_position,
                             direction, electrode_wf_layer, param):
    bounds = (np.inf, np.inf, -np.inf, -np.inf)
    wf_line_bounds = (np.inf, np.inf, -np.inf, -np.inf)

    if np.isclose(reference_port.angle, np.pi / 2):
        crossing_angle = np.pi
        if direction == -1:
            reference_port.origin[1] = (reference_port.origin[1] +
                                        param['electrode_length'])
    elif np.isclose(reference_port.angle, -np.pi / 2):
        crossing_angle = 0
        if direction == 1:
            reference_port.origin[1] = (reference_port.origin[1] -
                                        param['electrode_length'])

    left_inport = Port(
        (reference_port.origin[0] -
         (param['electrode_sep'] / 2.0 + param['electrode_width'] / 2),
         reference_port.origin[1]), direction * np.pi / 2.0,
        param['electrode_width'])

    signal_electrode_width = min(param['electrode_width'],
                                 param['wg_sep'] - param['electrode_sep'])
    signal_inport = Port((reference_port.origin[0] + param['wg_sep'] / 2.0,
                          reference_port.origin[1]), direction * np.pi / 2.0,
                         signal_electrode_width)
    right_inport = Port(
        (reference_port.origin[0] + param['wg_sep'] +
         param['electrode_sep'] / 2.0 + param['electrode_width'] / 2.0,
         reference_port.origin[1]), direction * np.pi / 2.0,
        param['electrode_width'])

    signal_wg = Waveguide.make_at_port(signal_inport)

    if crossing_angle == 0:
        long_wg = Waveguide.make_at_port(left_inport)
        short_wg = Waveguide.make_at_port(right_inport)
    else:
        long_wg = Waveguide.make_at_port(right_inport)
        short_wg = Waveguide.make_at_port(left_inport)

    # short waveguide
    # the shorter waveguide must be shorter
    # to accomodate for the other two waveguides
    short_wg.add_straight_segment(param['electrode_length'] -
                                  2 * param['electrode_sep_y'] -
                                  2 * param['electrode_width'])
    # 90 degree turn
    short_wg._current_port.angle = crossing_angle
    short_wg._current_port.origin[0] = (
        short_wg.current_port.origin[0] -
        np.cos(crossing_angle) * short_wg.current_port.width / 2.0)
    short_wg._current_port.width = param['crossing_width']
    short_wg._current_port.origin[1] = (
        short_wg.current_port.origin[1] -
        direction * short_wg.current_port.width / 2.0)
    wf_line_bounds = update_bounds(wf_line_bounds,
                                   short_wg.get_shapely_outline().bounds)
    short_wg.add_straight_segment(
        abs(crossing_goal_position - short_wg.current_port.origin[0]))
    short_wg.add_straight_segment(param['electrode_taper_length'],
                                  param['electrode_width'])
    bounds = update_bounds(bounds, short_wg.get_shapely_outline().bounds)

    # signal waveguide (always in the middle)
    # the signal waveguide must also be slightly shorter
    # to accomodate for the longest waveguide
    signal_wg.add_straight_segment(param['electrode_length'] -
                                   param['electrode_sep_y'] -
                                   param['electrode_width'])
    # 90 degree turn
    signal_wg._current_port.angle = crossing_angle
    signal_wg._current_port.origin[0] = (
        signal_wg.current_port.origin[0] -
        np.cos(crossing_angle) * signal_wg.current_port.width / 2.0)
    signal_wg._current_port.width = param['crossing_width']
    signal_wg._current_port.origin[1] = (
        signal_wg.current_port.origin[1] -
        direction * signal_wg.current_port.width / 2.0)
    wf_line_bounds = update_bounds(wf_line_bounds,
                                   signal_wg.get_shapely_outline().bounds)
    # crossing segment + taper
    signal_wg.add_straight_segment(
        abs(crossing_goal_position - signal_wg.current_port.origin[0]))
    signal_wg.add_straight_segment(param['electrode_taper_length'],
                                   param['electrode_width'])
    bounds = update_bounds(bounds, signal_wg.get_shapely_outline().bounds)

    # long waveguide
    long_wg.add_straight_segment(param['electrode_length'])
    # 90 degree turn
    long_wg._current_port.angle = crossing_angle
    long_wg._current_port.origin[0] = (
        long_wg.current_port.origin[0] -
        np.cos(crossing_angle) * long_wg.current_port.width / 2.0)
    long_wg._current_port.width = param['crossing_width']
    long_wg._current_port.origin[1] = (
        long_wg.current_port.origin[1] -
        direction * long_wg.current_port.width / 2.0)
    wf_line_bounds = update_bounds(wf_line_bounds,
                                   long_wg.get_shapely_outline().bounds)
    # crossing segment + taper
    long_wg.add_straight_segment(
        abs(crossing_goal_position - long_wg.current_port.origin[0]))
    long_wg.add_straight_segment(param['electrode_taper_length'],
                                 param['electrode_width'])
    bounds = update_bounds(bounds, long_wg.get_shapely_outline().bounds)
    # the extra width ensures no tapers are clipped
    extra_width = (param['electrode_width'] / 2 - param['crossing_width'] / 2)
    wf_line_bounds = (wf_line_bounds[0], wf_line_bounds[1] - extra_width,
                      wf_line_bounds[2], wf_line_bounds[3] + extra_width)
    _, _ = wf_line_from_bounds(cell=cell,
                               bounds=wf_line_bounds,
                               wf_maxlength=param['wf_maxlength'],
                               wf_layer=electrode_wf_layer)

    cell.add_to_layer(param['electrode_layer'], short_wg, signal_wg, long_wg)
    return (short_wg, signal_wg, long_wg, direction, wf_line_bounds)
def DirectionalCouplersTest_standard(label, coupler_sep, coupler_length, grating_angle = None):
    cell = Cell('DC_standard_test'+label)

    coupler_params = std_coupler_params.copy()
    if grating_angle is not None:
        coupler_params['full_opening_angle'] = grating_angle

    x_in = 0
    y_in = 0

    ##Generating input and output grating couplers

    for j in (0, 1):
        incoupler = GratingCoupler.make_traditional_coupler((x_in + j * 127, y_in), **coupler_params)
        cell.add_to_layer(9, incoupler)

    for j in (0, 3):
        outcoupler = GratingCoupler.make_traditional_coupler((x_in - 127 + j * 127, y_in), **coupler_params)
        cell.add_to_layer(9, outcoupler)

    ###Generating waveguides

    inports = [Port((x_in + j * 127, y_in), np.deg2rad(90), std_coupler_params['width']) for j in (0, 1)]
    wg = [Waveguide.make_at_port(inport) for inport in inports]

    for j in (0, 1):
        wg[j].add_straight_segment(grating_added_taper_len, wg_width)

        ##directional coupler with sinusoidal s-bend
        x_length = 130
        y_length = 127 / 2.0 - (coupler_sep + wg_width) / 2.0 - j * (127 - wg_width - coupler_sep)
        wg[j].add_parameterized_path(path=lambda t: (t * x_length, .5 * (np.cos(np.pi * t) - 1) * y_length),
                                     path_derivative=lambda t: (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length))
        wg[j].add_straight_segment(coupler_length)
        y_length = -(127 / 2.0 - (coupler_sep + wg_width) / 2.0 - j * (127 - wg_width - coupler_sep))
        wg[j].add_parameterized_path(path=lambda t: (t * x_length, .5 * (np.cos(np.pi * t) - 1) * y_length),
                                     path_derivative=lambda t: (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length))

        wg[j].add_straight_segment(30)

        wg[j].add_bend(np.pi - j * 2 * np.pi, 127 / 2.0)
        wg[j].add_straight_segment_until_y(y_in+grating_added_taper_len)
        wg[j].add_straight_segment(grating_added_taper_len, std_coupler_params['width'])

    for j in (0, 1):
        cell.add_to_layer(wg_layer, wg[j])

    ##write field
    outer_corners = [(x_in - 127 - 127 / 2.0, y_in - 50), (x_in + 2 * 127 + 127 / 2.0, y_in - 50),
                     (x_in + 2 * 127 + 127 / 2.0, y_in + 400 + coupler_length),
                     (x_in - 127 - 127 / 2.0, y_in + 400 + coupler_length)]
    polygon = Polygon(outer_corners)
    cell.add_to_layer(wg_wf_layer, polygon)
    cell.add_to_layer(wg_reg_layer, polygon)

    ###Label
    device_label = Text(origin=(x_in + 127 + 127 / 2.0, y_in + 200), height=30,
                        text=label, alignment='center-bottom', angle=np.pi)
    cell.add_to_layer(wg_layer, device_label)

    ###Device Info
    info_text = ('Coupler length = %.2f um\nCoupler sep= %.2f') \
                % (coupler_length, coupler_sep)
    device_info = Text(origin=(x_in + 127 + 127 / 2.0, y_in + 100), height=20, text=info_text,
                       alignment='center-bottom', angle=np.pi)
    cell.add_to_layer(comment_layer, device_info)

    return cell
def DirectionalCouplersTest(label, gap, length, AMZI_DeltaL, r_curve=50, grating_angle = None):
    cell = Cell('DC_Test' + label)
    couplerList = []
    outports = []
    wgs = []

    coupler_params = std_coupler_params.copy()
    if grating_angle is not None:
        coupler_params['full_opening_angle'] = grating_angle

    r_eff = r_curve / euler_to_bend_coeff

    port = Port((0, 0), 0, wg_width)

    couplerList.append(DirectionalCoupler.make_at_port(port, length=length, gap=gap, bend_radius=r_curve))
    wg = Waveguide.make_at_port(couplerList[0].right_ports[1])
    wg.add_straight_segment(2 * r_curve)
    wgs.append(wg)

    wg = Waveguide.make_at_port(couplerList[0].right_ports[0])
    wg.add_straight_segment(2 * r_curve)
    couplerList.append(DirectionalCoupler.make_at_port(wg.current_port, length=length, gap=gap, bend_radius=r_curve))

    sep = 5
    len_eulers = EulerLength(r_eff, np.pi / 2.)
    Delta_L = max(0, (AMZI_DeltaL - 12 * len_eulers - 5 * sep) / 4.)

    wg = Waveguide.make_at_port(couplerList[0].right_ports[0])
    wgAdd_EulerBend(wg, -np.pi / 2., r_eff, True)
    wg.add_straight_segment(Delta_L + sep)
    wgAdd_EulerBend(wg, -np.pi / 2., r_eff, True)
    wgAdd_EulerBend(wg, -np.pi / 2., r_eff, True)
    wg.add_straight_segment(Delta_L)
    wgAdd_EulerBend(wg, np.pi / 2., r_eff, False)
    wgAdd_EulerBend(wg, np.pi / 2., r_eff, False)
    wg.add_straight_segment(Delta_L + sep)
    wgAdd_EulerBend(wg, np.pi / 2., r_eff, False)
    wg.add_straight_segment(6 * r_curve + sep)
    wgAdd_EulerBend(wg, np.pi / 2., r_eff, False)
    wg.add_straight_segment(Delta_L + sep)
    wgAdd_EulerBend(wg, np.pi / 2., r_eff, False)
    wgAdd_EulerBend(wg, np.pi / 2., r_eff, False)
    wg.add_straight_segment(Delta_L)
    wgAdd_EulerBend(wg, -np.pi / 2., r_eff, True)
    wgAdd_EulerBend(wg, -np.pi / 2., r_eff, True)
    wg.add_straight_segment(Delta_L + sep)
    wgAdd_EulerBend(wg, -np.pi / 2., r_eff, True)
    wgs.append(wg)
    #
    wg = Waveguide.make_at_port(couplerList[0].left_ports[0])
    wgAdd_EulerBend(wg, -np.pi / 2., r_eff, True)
    wgs.append(wg)
    outports.append(wg.port)

    outports.append(outports[0].parallel_offset(-3 * opt_space))

    wg = Waveguide.make_at_port(couplerList[1].right_ports[0])
    wg.add_bezier_to(np.array(outports[1].origin), bend_strength=r_curve / 1.2,
                     final_angle=np.pi / 2.)
    wgs.append(wg)

    wg = Waveguide.make_at_port(couplerList[0].left_ports[1])
    wg.add_bend(angle=-np.pi, radius=r_curve / 4)
    wg.add_straight_segment(50, final_width=0.1)
    wgs.append(wg)

    wg = Waveguide.make_at_port(couplerList[1].right_ports[1])
    wg.add_bend(angle=np.pi, radius=r_curve / 4)
    wg.add_straight_segment(50, final_width=0.1)
    wgs.append(wg)

    gratingcouplers = [GratingCoupler.make_traditional_coupler_at_port(outport, **coupler_params) for outport in
                       outports]

    label_txt = Text((180, 70), 25, label, alignment='center-top')

    box = Waveguide((+520, -40), np.pi / 2., 1025)
    box.add_straight_segment(730)

    shapely_object = geometric_union(wgs + [label_txt] + couplerList + gratingcouplers)
    cell.add_to_layer(wg_layer, shapely_object)

    comments = Text((105, 70), 10, 'gap={:.2f}\nlength={:.2f}'.format(gap, length),
                    alignment='center-top')
    cell.add_to_layer(comment_layer, comments)

    x_cords = []
    y_cords = []
    for this_poly in shapely_object.geoms:
        temp_x_cords, temp_y_cords = this_poly.exterior.coords.xy
        x_cords = x_cords + list(temp_x_cords)
        y_cords = y_cords + list(temp_y_cords)
    x_max = max(x_cords) + box_dist
    x_min = min(x_cords) - box_dist
    y_max = max(y_cords) + box_dist
    y_min = min(y_cords) - box_dist
    box_size = (x_max - x_min, y_max - y_min)

    box = Waveguide(((x_min + x_max) / 2., y_min), np.pi / 2, box_size[0])
    box.add_straight_segment(box_size[1])
    total_box = geometric_union([box])
    cell.add_to_layer(wg_wf_layer, total_box)
    cell.add_to_layer(wg_reg_layer, total_box)

    return cell
Esempio n. 13
0
# and also allows for rotation.

# example 1
# create a 1 layer cell, that demonstrates different functionality of iop.port_shape_cartesian

corners = [(20, 10), (20, -10), (-20, -10),
           (-20, 10)]  # rectangle centred around (0, 0)

# bottom left
shape1 = iop.port_shape_cartesian(corners)
# ^ rectangle at (0, 0)

# top left
shape2 = iop.port_shape_cartesian(corners, offset=(0, 60))
# ^ rectangle at (0, 60) based off offset

# top right
shape3 = iop.port_shape_cartesian(corners,
                                  port=Port((60, 0), 0, 1),
                                  offset=(0, 60))
# ^ rectangle at (60, 60) based off port position and offset

# bottom right
shape4 = iop.port_shape_cartesian(corners, offset=(60, 0), rotate=np.pi / 5)
# ^ rectangle at (60, 0) and rotated 36 degrees

cell = Cell('port_shape_cartesian_example')
cell.add_to_layer(1, shape1[0], shape2[0], shape3[0], shape4[0])  # red shapes

cell.show()
Esempio n. 14
0
from TestStructures.tests_DC_Grating_Delays import RectangularSpiral, \
    DirectionalCouplersTest, Efficiency_Grating, Ring_Test, DirectionalCouplersTest_standard
from TestStructures.tests_Modulators import MZI_active
from TestStructures.test_TimeBinBS import TimeBin_BS
from TestStructures.tests_ModulatorsWithPhase import MZI_active_with_phase
from TestStructures.test_Demux import Demux_active

from tech.LiNb01 import *

wg_Expwidth = 0.5
std_coupler_params['grating_period'] = 0.49

electrode_wg_sep = 62.5
second_x_middle = 8 * 2 * 127

inport_0 = Port((-electrode_wg_sep / 2 - 25, 0), np.pi / 2, wg_width)
inport_1 = Port((-electrode_wg_sep / 2, 0), np.pi / 2, wg_width)
inport_2 = Port((electrode_wg_sep / 2, 0), np.pi / 2, wg_width)
inport_3 = Port((electrode_wg_sep / 2 + 25, 0), np.pi / 2, wg_width)
device_inports = [inport_0, inport_1, inport_2, inport_3]

start_x = inport_0.origin[0] + 3500  # should be + 3500 for 150 probe pitch
device_inports_2 = [None, None, None, None]
device_inports_2[:2] = [
    Port((start_x + idx * 25, 0), np.pi / 2, wg_width) for idx in range(2)
]
start_x += 25 + electrode_wg_sep
first_x_middle_2 = start_x - electrode_wg_sep / 2
second_x_middle_2 = first_x_middle_2 + second_x_middle
device_inports_2[2:] = [
    Port((start_x + idx * 25, 0), np.pi / 2, wg_width) for idx in range(2)
Esempio n. 15
0
def wgs_to_fiber_array(cell,
                       ports,
                       coupler_positions,
                       region_marker,
                       is_incoupling,
                       param,
                       all_wf_layers=[],
                       all_region_markers=[],
                       alignment_test=False):
    total_bounds = (np.inf, np.inf, -np.inf, -np.inf)
    first_line_bounds = list(total_bounds).copy()
    wgs = [Waveguide.make_at_port(prt) for prt in ports]
    first_bend = -np.pi / 2
    if is_incoupling:
        first_bend = np.pi / 2
    coupler_positions = coupler_positions[::-1]
    for idx, wg in enumerate(wgs):
        if is_incoupling:
            wg._current_port.angle = -np.pi / 2
            wg.add_straight_segment(param['wg_sep'] * (3 - idx))
        else:
            wg.add_straight_segment(param['wg_sep'] * (idx))
        # first bend then heading away from structure
        wg.add_bend(first_bend, param['min_radius'])
        if is_incoupling:
            wg.add_straight_segment_until_x(coupler_positions[-1][0] -
                                            param['min_radius'])
            if idx == 0:
                first_line_bounds = list(
                    update_bounds(first_line_bounds,
                                  wg.get_shapely_outline().bounds))
                # if alignment_test:
                first_line_bounds[2] -= 2 * 127
                first_line_bounds[0] -= 10
                first_line_bounds[1] -= 10
                if region_marker is None:
                    region_marker = bounds_to_polygon(first_line_bounds)
                _, region_marker = wf_line_from_bounds(
                    cell=cell,
                    bounds=first_line_bounds,
                    region_marker=region_marker,
                    wf_maxlength=1040,
                    wf_layer=param['wf_layer'],
                    axis=0,
                    direction=1)

            wg.add_straight_segment_until_x(coupler_positions[idx][0] -
                                            param['min_radius'])
            wg.add_bend(first_bend, param['min_radius'])
            # adiabatic taper
            wg.add_straight_segment(40, final_width=0.75)
            wg.add_straight_segment_until_y(coupler_positions[idx][1])
            gc = GratingCoupler.make_traditional_coupler_at_port(
                wg.current_port, **param['gc_params'])
            if idx == 0:
                second_line_bounds = [
                    first_line_bounds[2], first_line_bounds[1],
                    (wg.current_port.origin[0] + 127 / 2 - 10),
                    first_line_bounds[1] + 1040
                ]
            cell.add_to_layer(param['wg_layer'], gc, wg)
            add_markers_to_top(
                cell=cell,
                wf_bounds=second_line_bounds,
                device_top_bound=(wgs[0].current_port.origin[1] + 70),
                marker_dims=20,
                wg_layer=param['wg_layer'],
                marker_layer_1=3,
                marker_layer_2=4,
                marker_protection_layer=15)

        else:
            wg.add_straight_segment_until_x(coupler_positions[0][0] +
                                            param['min_radius'])
            if idx == 3:
                first_line_bounds = list(
                    update_bounds(first_line_bounds,
                                  wg.get_shapely_outline().bounds))
                first_line_bounds[1] -= 10
                first_line_bounds[2] += 10
                # if alignment_test:
                first_line_bounds[0] += 1.5 * 127
                if region_marker is None:
                    region_marker = bounds_to_polygon(first_line_bounds)
                _, region_marker = wf_line_from_bounds(
                    cell=cell,
                    bounds=first_line_bounds,
                    region_marker=region_marker,
                    wf_maxlength=1040,
                    wf_layer=param['wf_layer'],
                    axis=0,
                    direction=-1)

            wg.add_straight_segment_until_x(coupler_positions[idx][0] +
                                            param['min_radius'])
            wg.add_bend(first_bend, param['min_radius'])
            # adiabatic taper
            wg.add_straight_segment(40, final_width=0.75)
            wg.add_straight_segment_until_y(coupler_positions[idx][1])
            gc = GratingCoupler.make_traditional_coupler_at_port(
                wg.current_port, **param['gc_params'])
            cell.add_to_layer(param['wg_layer'], gc, wg)
            if idx == 3:
                second_line_bounds = [
                    (wg.current_port.origin[0] - 127 / 2 + 10),
                    first_line_bounds[1], first_line_bounds[0],
                    first_line_bounds[1] + 1040
                ]
    if alignment_test:
        test_coupler_positions = [
            [coupler_positions[-1][0] - 127, coupler_positions[-1][1]],
            [
                coupler_positions[-1][0] - 2 * 127,  # +8*127
                coupler_positions[-1][1]
            ]
        ]
        test_port = Port(test_coupler_positions[0], np.pi / 2.0, wgs[0].width)
        test_gc_0 = GratingCoupler.make_traditional_coupler_at_port(
            test_port, **param['gc_params'])
        test_wg = Waveguide.make_at_port(test_gc_0.port)
        test_wg._current_port.angle = -np.pi / 2
        test_wg.add_bend(-np.pi / 2, param['min_radius'])
        test_wg.add_straight_segment_until_x(test_coupler_positions[1][0] +
                                             param['min_radius'])
        test_wg.add_bend(-np.pi / 2, param['min_radius'])
        test_gc_1 = GratingCoupler.make_traditional_coupler_at_port(
            test_wg.current_port, **param['gc_params'])
        cell.add_to_layer(param['wg_layer'], test_wg, test_gc_0, test_gc_1)

    _, region_marker = wf_line_from_bounds(cell=cell,
                                           bounds=second_line_bounds,
                                           region_marker=region_marker,
                                           wf_maxlength=1040,
                                           wf_layer=param['wf_layer'],
                                           axis=1,
                                           direction=1)
    if is_incoupling:
        for idx in range(len(all_wf_layers)):
            all_region_markers[idx] = bounds_to_polygon(second_line_bounds)
            _, all_region_markers[idx] = wf_line_from_bounds(
                cell=cell,
                bounds=second_line_bounds,
                region_marker=all_region_markers[idx],
                wf_maxlength=1040,
                wf_layer=all_wf_layers[idx],
                axis=1,
                direction=1)

    total_bounds = update_bounds(first_line_bounds, second_line_bounds)
    return total_bounds, region_marker
Esempio n. 16
0
                outfile.write(binary)
    else:
        for c in cells:
            outfile.write(
                _cell_to_gdsii_binary(c, grid_steps_per_unit, max_points,
                                      max_line_points, timestamp))
    outfile.write(pack('>2H', 4, 0x0400))  # ENDLIB N0_DATA


if __name__ == '__main__':
    from gdshelpers.parts.port import Port
    from gdshelpers.parts.waveguide import Waveguide
    from gdshelpers.geometry.chip import Cell

    device_cell = Cell('cell')
    start_port = Port(origin=(10, 0), width=1, angle=0)
    waveguide = Waveguide.make_at_port(start_port)
    for i_bend in range(9):
        waveguide.add_bend(angle=np.pi, radius=60 + i_bend * 40)
    device_cell.add_dlw_taper_at_port('A', 2, waveguide.in_port, 30)
    device_cell.add_dlw_taper_at_port('B', 2, waveguide.current_port, 30)
    device_cell.add_to_layer(1, waveguide)

    sub_cell = Cell('sub_cell')
    sub_cell.add_to_layer(1, waveguide)

    sub_cell.add_to_layer(3, LineString(((0, 0), (100, 100))))

    line = LineString(((0, 0), (-100, 100)))
    line.width = 3
    sub_cell.add_to_layer(3, line)
Esempio n. 17
0
        self.add_dlw_data('taper', str(label), {'origin': taper_port.origin.tolist(), 'angle': port.angle,
                                                'starting_width': port.width, 'taper_length': taper_length})
        if with_markers:
            for i, (v, l) in enumerate(itertools.product((-20, 20), (taper_length, 0))):
                self.add_dlw_marker(str(label) + '-' + str(i), layer,
                                    port.parallel_offset(v).longitudinal_offset(l).origin)


if __name__ == '__main__':
    from gdshelpers.parts.port import Port
    from gdshelpers.parts.waveguide import Waveguide
    from gdshelpers.geometry.chip import Cell

    # Create a cell-like object that offers a save output command '.save' which creates the .gds or .oas file by using
    # gdsCAD,gdspy or fatamorgana
    device_cell = Cell('my_cell')
    # Create a port to connect waveguide structures to
    port = Port(origin=(0, 0), width=1, angle=0)
    waveguide = Waveguide.make_at_port(port)
    for i in range(9):
        waveguide.add_bend(angle=np.pi, radius=60 + i * 40)
    # Add direct laser writing taper and alignment marker for postprocessing with a dlw printer to the cell-like object.
    # The cell dlw files will be saved with the cell.
    device_cell.add_dlw_taper_at_port('A0', 2, port.inverted_direction, 30)
    device_cell.add_dlw_taper_at_port('A1', 2, waveguide.current_port, 30)
    device_cell.add_to_layer(1, waveguide)
    device_cell.show()
    # Creates the output file by using gdspy,gdsCAD or fatamorgana. To use the implemented parallell processing, set
    # parallel=True.
    device_cell.save(name='my_design', parallel=True, library='gdspy')