def define_waveguides(self): wgdef1 = WaveguidePointRoundedConnectElementDefinition(wg_definition = self.wg_definition1, bend_radius = self.bend_radius, manhattan = self.manhattan, rounding_algorithm = self.rounding_algorithm) wgdef2 = WaveguidePointRoundedConnectElementDefinition(wg_definition = self.wg_definition2, bend_radius = self.bend_radius, manhattan = self.manhattan, rounding_algorithm = self.rounding_algorithm) bs1, bs2 = self.get_bend90_size() waveguides = [wgdef1(shape = [(-bs1 - bs2, -0.5*self.spacing -bs1-bs2-self.min_straight), (-bs2, -0.5*self.spacing - bs1 - bs2 -self.min_straight), (-bs2, -0.5*self.spacing ), (self.length+bs1, -0.5*self.spacing), (self.length+bs1, -0.5*self.spacing - bs1 - bs2-self.min_straight), (self.length+bs1+bs2, -0.5*self.spacing - bs1 - bs2 -self.min_straight) ]), wgdef2(shape = [(-bs1-bs2, 0.5*self.spacing+ bs1 + bs2 +self.min_straight), (-bs2, 0.5*self.spacing +bs1 + bs2+self.min_straight), (-bs2, +0.5*self.spacing ), (self.length+bs1, +0.5*self.spacing ), (self.length+bs1, +0.5*self.spacing + bs1 + bs2+self.min_straight), (self.length+bs1+bs2, +0.5*self.spacing + bs1 + bs2 +self.min_straight) ]) ] return waveguides
def get_waveguide(self): wgdef = WaveguidePointRoundedConnectElementDefinition( wg_definition=self.wg_definition, bend_radius=self.bend_radius, rounding_algorithm=self.rounding_algorithm, manhattan=self.manhattan) return wgdef(shape=self.shape)
def define_waveguides(self): waveguides = [] for (S,w,t, r) in zip(self.shapes, self.wg_widths, self.trench_widths, self.bend_radii): wg_def = WgElDefinition(wg_width = w, trench_width = t, process = self.process) connector_wg_def = WaveguidePointRoundedConnectElementDefinition(wg_definition = wg_def, bend_radius = r, manhattan = self.manhattan, rounding_algorithm = self.rounding_algorithm) waveguides.append(connector_wg_def(shape = S)) return waveguides
def define_connectors(self): wg_def = WaveguidePointRoundedConnectElementDefinition( wg_definition=self.wg_definition, bend_radius=self.bend_radius, rounding_algorithm=self.rounding_algorithm, manhattan=self.manhattan) connectors = [ WgSpiralFixedLength(wg_definition=wg_def, total_length=self.total_length, n_o_loops=self.no_loops, spacing=self.spacing) ] return connectors
def define_connectors(self): wg_def = WaveguidePointRoundedConnectElementDefinition( wg_definition=self.wg_definition, bend_radius=self.bend_radius, rounding_algorithm=self.rounding_algorithm, manhattan=self.manhattan) spiral = WgSpiralFixedLength(wg_definition=wg_def, total_length=self.total_length, n_o_loops=self.no_loops, spacing=self.spacing) spiral_ref = SRef(reference=spiral, transformation=VMirror()) struct = Structure(name=spiral.name + "_flipped", elements=[spiral_ref], ports=spiral_ref.ports) connectors = [struct] return connectors
def define_connectors(self): bs1, bs2 = self.get_bend90_size() s = Shape() s += (-self.extension, 0.0) s += (0.0, 0.0) s += (bs1, 0.0) s += (bs1, bs1 + bs2 + self.straight) s += (2 * bs1 + bs2, bs1 + bs2 + self.straight) s += (2 * bs1 + bs2, 0.0) s += (2 * bs1 + 2 * bs2, 0.0) s += (2 * bs1 + 2 * bs2 + self.extension, 0.0) wgdef = WaveguidePointRoundedConnectElementDefinition( wg_definition=self.wg_definition, bend_radius=self.bend_radius, rounding_algorithm=self.rounding_algorithm, manhattan=self.manhattan) return [wgdef(shape=s)]
def define_elements(self, elems): from picazzo.io.fibcoup import IoFibcoup from picazzo.io.column import IoColumn layout = IoColumn(name="EXAMPLE_WINDOW_WAVEGUIDE", y_spacing=35.0, south_west=(0.0, 0.0), south_east=(3500.0, 0.0), adapter=IoFibcoup) # define a shape my_path_shape = Shape([(0.0, 0.0), (50.0, 0.0), (100.0, 30.0), (150.0, 5.0)]) # Example 1: # Make a standard wire waveguide by using the well-know regular class 'WgElDefinition' wire_wg_def = WgElDefinition(wg_width=0.6, trench_width=0.9) wire_wg = wire_wg_def(shape=my_path_shape) layout += Structure(name="wire", elements=[wire_wg], ports=wire_wg.ports) layout.add_blocktitle("REGULAR_WIRE", center_clearout=(500.0, 0.0)) layout.add_emptyline(2) # Example 2: # Make wire waveguide by directly using the raw base class 'WindowWaveguideDefinition' from ipkiss.plugins.photonics.wg.window import WindowWaveguideDefinition, PathWindow raw_wg_def = WindowWaveguideDefinition( wg_width=0.45, #no function except for ports trench_width=2.0, #no function except for ports process=TECH.PROCESS.WG, #no function except for ports windows=[ PathWindow(layer=PPLayer(TECH.PROCESS.WG, TECH.PURPOSE.LF.LINE), start_offset=-0.225, end_offset=0.225), # waveguide PathWindow(layer=PPLayer(TECH.PROCESS.WG, TECH.PURPOSE.LF_AREA), start_offset=-0.225 - 2.0, end_offset=0.225 + 2.0) # add additional layers if needed ]) raw_wg = raw_wg_def(shape=my_path_shape) layout += Structure(name="raw", elements=[raw_wg], ports=raw_wg.ports) layout.add_blocktitle("RAW", center_clearout=(500.0, 0.0)) layout.add_emptyline(2) # Example 3: # implanted waveguide: doping window on top of other waveguide definition doped_wg_def = DopedWaveguideDefinition(wg_definition=wire_wg_def, doping_width=1.5, doping_process=TECH.PROCESS.P1) doped_wg = doped_wg_def(shape=my_path_shape) layout += Structure(name="doped", elements=[doped_wg], ports=doped_wg.ports) layout.add_blocktitle("DOP", center_clearout=(500.0, 0.0)) layout.add_emptyline(2) # Example 4: # Add new windows to another waveguide definition from ipkiss.plugins.photonics.wg.window import WindowsOnWaveguideDefinition win_wg_def = WindowsOnWaveguideDefinition( wg_definition=wire_wg_def, windows=[ PathWindow(layer=PPLayer(TECH.PROCESS.FC, TECH.PURPOSE.DF.TRENCH), start_offset=0.0, end_offset=1.0) ] # etch an FC window in one side of the waveguide ) win_wg = win_wg_def(shape=my_path_shape) layout += Structure(name="window", elements=[win_wg], ports=win_wg.ports) layout.add_blocktitle("WIN", center_clearout=(500.0, 0.0)) layout.add_emptyline(2) # Example 5: # Modulator : use of JunctionWaveguideDefinition mod_wg_def = JunctionWaveguideDefinition() mod_wg = mod_wg_def(shape=my_path_shape) layout += Structure(name="modulator", elements=[mod_wg], ports=mod_wg.ports) layout.add_blocktitle("MOD", center_clearout=(500.0, 0.0)) layout.add_emptyline(2) # Example 6: # Use new waveguide in a rounded connector from ipkiss.plugins.photonics.wg.connect import WaveguidePointRoundedConnectElementDefinition rounded_wg_def = WaveguidePointRoundedConnectElementDefinition( wg_definition=mod_wg_def, # previous definition, with the junction bend_radius= 20.0, # needs to be sufficiently large with the broad windows ) rounded_wg = rounded_wg_def(shape=my_path_shape) layout += Structure(name="rounded", elements=[rounded_wg], ports=rounded_wg.ports) layout.add_blocktitle("ROUND", center_clearout=(500.0, 0.0)) layout.add_emptyline(2) # Example 7: # Use new waveguide in a spiral from picazzo.wg.spiral import WaveguideDoubleSpiralWithIncoupling from picazzo.container.taper_ports import TaperShallowPorts spiral = WaveguideDoubleSpiralWithIncoupling( wg_definition=rounded_wg_def, spacing=12.0, n_o_loops=2, inner_size=(100.0, 100.0)) layout += TaperShallowPorts(structure=spiral) layout.add_blocktitle("SPIRAL", center_clearout=(500.0, 0.0)) elems += SRef(reference=layout) return elems
def define_elements(self, elems): layout = IoColumnGroup(y_spacing=25.0, south_east=(6000.0, 0.0)) # define a shape my_path_shape = Shape([(0.0, 0.0), (50.0, 0.0), (100.0, 30.0), (150.0, 5.0)]) # Example 2: # Make a standard wire waveguide by using the well-know regular class 'WgElDefinition' wire_wg_def = WgElDefinition(wg_width=0.6, trench_width=0.9) layout += Structure(name="wire", elements=[wire_wg_def(shape=my_path_shape)]) layout.add_blocktitle("REGULAR_WIRE", center_clearout=(500.0, 0.0)) layout.add_emptyline(2) # Example 2: # Make wire waveguide by directly using the raw base class 'WindowWaveguideDefinition' from ipkiss.plugins.photonics.wg.window import WindowWaveguideDefinition, PathWindow raw_wg_def = WindowWaveguideDefinition( wg_width=0.45, #no function except for ports trench_width=2.0, #no function except for ports process=TECH.PROCESS.WG, #no function except for ports windows=[ PathWindow(layer=PPLayer(TECH.PROCESS.WG, TECH.PURPOSE.LF.LINE), start_offset=-0.225, end_offset=0.225), # waveguide PathWindow(layer=PPLayer(TECH.PROCESS.WG, TECH.PURPOSE.LF_AREA), start_offset=-0.225 - 2.0, end_offset=0.225 + 2.0) # add additional layers if needed ]) layout += Structure(name="raw", elements=[raw_wg_def(shape=my_path_shape)]) layout.add_blocktitle("RAW", center_clearout=(500.0, 0.0)) layout.add_emptyline(2) # Example 3: # Use Advanced Passive waveguide which subclasses from the raw base class # Note that no taper classes have been provided yet ts_wg_def = RaisedWgElDefinition(wg_width=0.8, trench_width=3.0, top_process=TECH.PROCESS.FCW, top_width=0.4) layout.add_blocktitle("TWO STEP", center_clearout=(500.0, 0.0)) layout += Structure( name="two_step", elements=[ts_wg_def(shape=Shape([(0.0, 0.0), (50.0, 0.0)]))]) layout.add_emptyline(2) # Example 4: # implanted waveguide: doping window on top of other waveguide definition doped_wg_def = DopedWaveguideDefinition(wg_definition=wire_wg_def, doping_width=1.5, doping_process=TECH.PROCESS.P1) # taper to deep waveguides from picazzo.container.taper_ports import TaperShallowPorts layout += TaperShallowPorts(structure=Structure( name="doped", elements=[doped_wg_def(shape=my_path_shape)])) layout.add_blocktitle("DOP", center_clearout=(500.0, 0.0)) layout.add_emptyline(2) # Example 5: # Add new windows to another waveguide definition from ipkiss.plugins.photonics.wg.window import WindowsOnWaveguideDefinition win_wg_def = WindowsOnWaveguideDefinition( wg_definition=wire_wg_def, windows=[ PathWindow(layer=PPLayer(TECH.PROCESS.FC, TECH.PURPOSE.DF.TRENCH), start_offset=0.0, end_offset=1.0) ] # etch an FC window in one side of the waveguide ) layout += Structure(name="window", elements=[win_wg_def(shape=my_path_shape)]) layout.add_blocktitle("WIN", center_clearout=(500.0, 0.0)) layout.add_emptyline(2) # Example 6: # Modulator : Shallow Waveguide with Junction which subclasses from the raw base class mod_wg_def = JunctionWaveguideDefinition() layout += TaperShallowPorts(structure=Structure( name="modulator", elements=[mod_wg_def(shape=my_path_shape)])) layout.add_blocktitle("MOD", center_clearout=(500.0, 0.0)) layout.add_emptyline(2) # Example 7: # Use new waveguide in a rounded connector from ipkiss.plugins.photonics.wg.connect import WaveguidePointRoundedConnectElementDefinition rounded_wg_def = WaveguidePointRoundedConnectElementDefinition( wg_definition=mod_wg_def, # previous definition, with the junction bend_radius= 20.0, # needs to be sufficiently large with the broad windows ) layout.add_emptyline(2) # taper to deep waveguides from picazzo.container.taper_ports import TaperShallowPorts layout += TaperShallowPorts(structure=Structure( name="rounded", elements=[rounded_wg_def(shape=my_path_shape)])) layout.add_blocktitle("CON", center_clearout=(500.0, 0.0)) layout.add_emptyline(2) # Example 8: # Use new waveguide in a spiral from picazzo.wg.spiral import WaveguideDoubleSpiralWithIncoupling from picazzo.container.taper_ports import TaperShallowPorts spiral = WaveguideDoubleSpiralWithIncoupling( wg_definition=rounded_wg_def, spacing=12.0, n_o_loops=2, inner_size=(100.0, 100.0)) layout += TaperShallowPorts(structure=spiral) layout.add_blocktitle("SPIRAL", center_clearout=(500.0, 0.0)) elems += layout return elems
def define_elements(self, elems): super(IoFibcoupGeneric, self).define_elements(elems) T = HMirror() # for east couplers for fc, pos, tf in self.west_fibcoups_transforms_and_positions: elems += SRef(fc, pos, tf) for fc, pos, tf in self.east_fibcoups_transforms_and_positions: elems += SRef(fc, pos, tf) #i = 0 #for ypos in self.y_west: #fc = self.west_fibcoups[i%len(self.west_fibcoups)] #west_fibcoup_position = (self.west_fibcoup_offsets[i%len(self.west_fibcoup_offsets)], ypos - fc.east_ports[0].y) #elems += SRef(fc, west_fibcoup_position) #i+= 1 #i = 0 #for ypos in self.y_east: #fc = self.east_fibcoups[i%len(self.east_fibcoups)] #east_fibcoup_position = (self.width - self.east_fibcoup_offsets[i%len(self.east_fibcoup_offsets)], ypos - fc.east_ports[0].y) #elems += SRef(fc, east_fibcoup_position, T) #i+= 1 i = 0 west_process_match = True shapes = [] wg_widths = [] trench_widths = [] radiuses = [] processes = [] # get westmost position for ports west = 100000000.0 for ip in self.struct_west_ports: west = min(west, ip.position.x) for i in range(len(self.struct_west_ports)): west_fibcoup = self.west_fibcoups[i % len(self.west_fibcoups)] west_fibcoup_port = west_fibcoup.east_ports[0] west_fibcoup_length = west_fibcoup_port.position[ 0] + self.west_fibcoup_offsets[i % len(self.west_fibcoup_offsets)] west_fibcoup_width = west_fibcoup_port.wg_definition.wg_width west_fibcoup_trench = west_fibcoup_port.wg_definition.trench_width west_connect_length = self.west_connect_lengths[i % len( self.west_connect_lengths)] west_taper_length = self.west_taper_lengths[i % len( self.west_taper_lengths)] west_trench_width = self.west_trench_widths[i % len( self.west_trench_widths)] west_fibcoup_taper_length = self.west_fibcoup_taper_lengths[ i % len(self.west_fibcoup_taper_lengths)] west_wg_width = self.west_wg_widths[i % len(self.west_wg_widths)] west_bend_radius = self.west_bend_radiuses[i % len( self.west_bend_radiuses)] west_minimum_straight = self.west_minimum_straights[i % len( self.west_minimum_straights)] west_process = west_fibcoup_port.wg_definition.process ip = self.struct_west_ports[i] if not ip.wg_definition.process == west_process: west_process_match = False # position center taper t_pos = (west - west_connect_length - TECH.WG.SHORT_STRAIGHT, self.y_west[i]) #small piece of waveguide at the end wg_def = WgElDefinition(wg_width=ip.wg_definition.wg_width, trench_width=ip.wg_definition.trench_width, process=west_process) W = wg_def([t_pos, (t_pos[0] + TECH.WG.SHORT_STRAIGHT, t_pos[1])]) elems += W # taper to the cleave waveguide start_wg_def1 = WgElDefinition( wg_width=ip.wg_definition.wg_width, trench_width=ip.wg_definition.trench_width, process=west_process) end_wg_def1 = WgElDefinition(wg_width=west_wg_width, trench_width=west_trench_width, process=west_process) T = WgElTaperLinear(start_position=t_pos, end_position=(t_pos[0] - west_taper_length, t_pos[1]), start_wg_def=start_wg_def1, end_wg_def=end_wg_def1) elems += T # draw cleave waveguide (the wider waveguide, connected to the grating coupler) wg_def = WgElDefinition(wg_width=west_wg_width, trench_width=west_trench_width, process=west_process) elems += wg_def([ T.west_ports[0].position, (west_fibcoup_length + west_fibcoup_taper_length, t_pos[1]) ]) # draw fibcoup taper (between grating coupler and the cleave waveguide) start_wg_def2 = WgElDefinition(wg_width=west_wg_width, trench_width=west_trench_width, process=west_process) end_wg_def2 = WgElDefinition(wg_width=west_fibcoup_width, trench_width=west_fibcoup_trench, process=west_process) elems += WgElTaperLinear(start_position=(west_fibcoup_length + west_fibcoup_taper_length, t_pos[1]), end_position=(west_fibcoup_length, t_pos[1]), start_wg_def=start_wg_def2, end_wg_def=end_wg_def2) # generic connector between structure port and taper port tp = W.east_ports[0] S = Shape( RouteToWestAtY(input_port=ip, y_position=tp.position.y, bend_radius=west_bend_radius, min_straight=west_minimum_straight)) if len(S) > 2: S[-2] = S[-2].translate(tp.position - S[-1]) S[-1] = tp.position shapes += [S] wg_widths += [ip.wg_definition.wg_width] trench_widths += [ip.wg_definition.trench_width] radiuses += [west_bend_radius] processes += [west_process] #blocking trenches elems += Line( PPLayer(west_process, TECH.PURPOSE.LF_AREA), (self.block_trench_position, t_pos[1] + 0.5 * west_wg_width + west_trench_width), (self.block_trench_position, t_pos[1] + 0.5 * self.y_spacing), self.block_trench_width) elems += Line( PPLayer(west_process, TECH.PURPOSE.LF_AREA), (self.block_trench_position, t_pos[1] - 0.5 * west_wg_width - west_trench_width), (self.block_trench_position, t_pos[1] - 0.5 * self.y_spacing), self.block_trench_width) if len(self.struct_west_ports): if self.west_merged_waveguides: # TO DO: Sort this out for different processes elems += WgElBundleConnectRoundedGeneric( shapes=shapes, wg_widths=wg_widths, trench_widths=trench_widths, bend_radii=radiuses, process=west_process) else: for (s, w, t, r, p) in zip(shapes, wg_widths, trench_widths, radiuses, processes): wg_def = WgElDefinition(wg_width=w, trench_width=t, process=p) connector_wg_def = WaveguidePointRoundedConnectElementDefinition( wg_definition=wg_def, bend_radius=r, manhattan=False) elems += connector_wg_def(shape=s) shapes = [] wg_widths = [] trench_widths = [] radiuses = [] processes = [] east_process_match = True # get rigthmost position for ports east = -100000000.0 for op in self.struct_east_ports: east = max(east, op.position.x) for i in range(len(self.struct_east_ports)): east_fibcoup = self.east_fibcoups[i % len(self.east_fibcoups)] east_fibcoup_port = east_fibcoup.east_ports[0] east_fibcoup_length = east_fibcoup_port.position[ 0] + self.east_fibcoup_offsets[i % len(self.east_fibcoup_offsets)] east_fibcoup_width = east_fibcoup_port.wg_definition.wg_width east_fibcoup_trench = east_fibcoup_port.wg_definition.trench_width east_connect_length = self.east_connect_lengths[i % len( self.east_connect_lengths)] east_taper_length = self.east_taper_lengths[i % len( self.east_taper_lengths)] east_trench_width = self.east_trench_widths[i % len( self.east_trench_widths)] east_fibcoup_taper_length = self.east_fibcoup_taper_lengths[ i % len(self.east_fibcoup_taper_lengths)] east_wg_width = self.east_wg_widths[i % len(self.east_wg_widths)] east_bend_radius = self.east_bend_radiuses[i % len( self.east_bend_radiuses)] east_minimum_straight = self.east_minimum_straights[i % len( self.east_minimum_straights)] east_process = east_fibcoup_port.wg_definition.process op = self.struct_east_ports[i] if not op.wg_definition.process == east_process: east_process_match = False # position taper t_pos = (east + east_connect_length + TECH.WG.SHORT_STRAIGHT, self.y_east[i]) wg_def = WgElDefinition(wg_width=op.wg_definition.wg_width, trench_width=op.wg_definition.trench_width, process=east_process) W = wg_def([t_pos, (t_pos[0] - TECH.WG.SHORT_STRAIGHT, t_pos[1])]) elems += W start_wg_def3 = WgElDefinition( wg_width=op.wg_definition.wg_width, trench_width=op.wg_definition.trench_width, process=east_process) end_wg_def3 = WgElDefinition(wg_width=east_wg_width, trench_width=east_trench_width, process=east_process) T = WgElTaperLinear(start_position=t_pos, end_position=(t_pos[0] + east_taper_length, t_pos[1]), start_wg_def=start_wg_def3, end_wg_def=end_wg_def3) elems += T # draw cleave waveguides wg_def = WgElDefinition(wg_width=east_wg_width, trench_width=east_trench_width, process=east_process) elems += wg_def([ T.east_ports[0].position, (self.width - east_fibcoup_length - east_fibcoup_taper_length, t_pos[1]) ]) # draw fibcoup taper start_wg_def4 = WgElDefinition(wg_width=east_wg_width, trench_width=east_trench_width, process=east_process) end_wg_def4 = WgElDefinition(wg_width=east_fibcoup_width, trench_width=east_fibcoup_trench, process=east_process) elems += WgElTaperLinear( start_position=(self.width - east_fibcoup_length - east_fibcoup_taper_length, t_pos[1]), end_position=(self.width - east_fibcoup_length, t_pos[1]), start_wg_def=start_wg_def4, end_wg_def=end_wg_def4) # generic connector between structure port and taper port tp = W.west_ports[0] S = Shape( RouteToEastAtY(input_port=op, y_position=tp.position.y, bend_radius=east_bend_radius, min_straight=east_minimum_straight)) if len(S) > 2: S[-2] = S[-2].translate(tp.position - S[-1]) S[-1] = tp.position shapes += [S] wg_widths += [op.wg_definition.wg_width] trench_widths += [op.wg_definition.trench_width] radiuses += [east_bend_radius] processes += [east_process] if len(self.struct_east_ports): if self.east_merged_waveguides: # TODO: Correct the bundling to support multiple process layers elems += WgElBundleConnectRoundedGeneric( shapes=shapes, wg_widths=wg_widths, trench_widths=trench_widths, bend_radii=radiuses, process=processes[0]) else: for (s, w, t, r, p) in zip(shapes, wg_widths, trench_widths, radiuses, processes): wg_def = WgElDefinition(wg_width=w, trench_width=t, process=p) connector_wg_def = WaveguidePointRoundedConnectElementDefinition( wg_definition=wg_def, bend_radius=r, manhattan=False) elems += connector_wg_def(shape=s) if not (west_process_match and east_process_match): if not (west_process_match or east_process_match): lr = "west and east" elif not west_process_match: lr = "west" else: lr = "east" LOG.warning( "Some of the %s ports of structure %s are not on the same process layer as the %s fiber couplers" % (lr, self.struct.name, lr)) return elems
def get_connect_wg_definition(self): return WaveguidePointRoundedConnectElementDefinition( wg_definition=self.wg_definition, bend_radius=self.bend_radius, rounding_algorithm=self.rounding_algorithm, manhattan=self.manhattan)