class Layout(WireWaveguideTemplate.Layout): core_process = ProcessProperty(locked=True, default=TECH.PROCESS.WG) core_purpose = PurposeProperty(locked=True, default=TECH.PURPOSE.CORE) cladding_process = ProcessProperty(locked=True, default=TECH.PROCESS.WG) cladding_purpose = PurposeProperty(locked=True, default=TECH.PURPOSE.CLADDING) core_width = PositiveNumberProperty(default=TECH.WG.CORE_WIDTH) cladding_width = PositiveNumberProperty(default=TECH.WG.CLADDING_WIDTH)
class InvertedTaperShallow(InvertedTaper): process = DefinitionProperty(fdef_name = "define_process") wg_def_sh_start = WaveguideDefProperty(default = WgElDefinition(wg_width = 1.0 ,trench_width = TECH.WG.TRENCH_WIDTH)) wg_def_sh_end = WaveguideDefProperty(default = WgElDefinition(wg_width = 0.080 ,trench_width = TECH.WG.TRENCH_WIDTH)) deep_process = ProcessProperty(default = TECH.PROCESS.WG) shallow_process = ProcessProperty(default = TECH.PROCESS.FC) shallow_tip_width = PositiveNumberProperty(default = 0.080) shallow_tip_start_width = PositiveNumberProperty(default = 1.0) shallow_tip_length = PositiveNumberProperty(default = 150.0) def define_process(self): return self.deep_process def define_elements(self, elems): # WG wg_def_stop = WgElDefinition(wg_width = self.wg_def_end.wg_width,trench_width = self.wg_def_start.trench_width) shallow_tip_width = self.wg_def_sh_end.wg_width shallow_tip_start_width = self.wg_def_sh_start.wg_width elems += WgElTaperLinear(start_position = (self.shallow_tip_length + self.tip_offset + self.tip_length, 0.0), end_position = (self.tip_offset + self.tip_length, 0.0), start_wg_def = self.wg_def_start, end_wg_def = self.wg_def_end) # FC s_o_length = self.tip_offset + self.tip_length # draw taper to tip wg_def_sh_start = WgElDefinition(wg_width = self.wg_def_sh_start.wg_width+1.0, trench_width = self.wg_def_start.trench_width) wg_def_sh_end = WgElDefinition(wg_width = self.wg_def_sh_end.wg_width, trench_width = 0.5*(self.y_spacing-self.wg_def_sh_end.wg_width)-1.0) elems += WgElTaperLinear( start_position = (self.shallow_tip_length + s_o_length, 0.0), end_position = (s_o_length, 0.0), start_wg_def = wg_def_sh_start, end_wg_def = wg_def_sh_end, process = self.shallow_process) if self.extension > 0: wg_def = WgElDefinition(wg_width = self.shallow_tip_width, trench_width = 0.5*(self.y_spacing-shallow_tip_width)-1.0, process = self.shallow_process) elems += wg_def([(s_o_length - self.extension , 0.0), (s_o_length, 0.0)]) #assist lines for tip for i in range(self.assist_lines): elems += Path(PPLayer(self.shallow_process, TECH.PURPOSE.LF.LINE), [(self.shallow_tip_length + s_o_length, (0.5*shallow_tip_start_width +0.5 + (i+1)*(self.assist_width+ self.assist_spacing) - 0.5*self.assist_width)), (s_o_length, + (0.5*shallow_tip_width + (i+1)*(self.assist_width+ self.assist_spacing) - 0.5*self.assist_width)), (s_o_length- self.extension , + (0.5*shallow_tip_width + (i+1)*(self.assist_width+ self.assist_spacing) - 0.5*self.assist_width)) ], self.assist_width) elems += Path(PPLayer(self.shallow_process, TECH.PURPOSE.LF.LINE), [(self.shallow_tip_length + s_o_length, - (0.5*shallow_tip_start_width+0.5+ (i+1)*(self.assist_width+ self.assist_spacing) - 0.5*self.assist_width)), (s_o_length, - (0.5*shallow_tip_width + (i+1)*(self.assist_width+ self.assist_spacing) - 0.5*self.assist_width)), (s_o_length- self.extension , - (0.5*shallow_tip_width + (i+1)*(self.assist_width+ self.assist_spacing) - 0.5*self.assist_width)) ], self.assist_width) return elems def define_ports(self, ports): wg_def = WgElDefinition(wg_width = self.shallow_tip_start_width, trench_width = self.wg_def_start.trench_width, process = self.deep_process) ports += [OpticalPort(position = (self.tip_length + self.tip_offset+ self.shallow_tip_length , 0.0), angle = 0.0, wg_definition = wg_def)] return ports
class Layout(rib_wg.RibWaveguideTemplate.Layout): core_process = ProcessProperty( locked=True, doc="Process used for the core layer of the MSN rib_old waveguide." ) core_purpose = PurposeProperty( locked=True, doc="Purpose used for the core layer of the MSN rib_old waveguide." ) exclusion_process = ProcessProperty( locked=True, doc= "Process used for the exclusion layer of the silicon wire waveguide." ) exclusion_purpose = PurposeProperty( locked=True, doc= "Purpose used for the exclusion layer of the silicon wire waveguide." ) cladding_process = ProcessProperty( locked=True, doc= "Process used for the cladding layer of the MSN rib_old waveguide." ) cladding_purpose = PurposeProperty( locked=True, doc= "Purpose used for the cladding layer of the MSN rib_old waveguide." ) core_width = PositiveNumberProperty( doc="Width of the core of the rib_old waveguide.") cladding_width = PositiveNumberProperty( doc="Cladding width of the rib_old waveguide.") def _default_core_process(self): return TECH.PROCESS.MSN def _default_core_purpose(self): return TECH.PURPOSE.DRAWING def _default_exclusion_process(self): return TECH.PROCESS.MSN def _default_exclusion_purpose(self): return TECH.PURPOSE.DRAWING def _default_cladding_process(self): return TECH.PROCESS.SHALLOW def _default_cladding_purpose(self): return TECH.PURPOSE.DRAWING def _default_core_width(self): return TECH.RIBWG.RIB_WIDTH def _default_cladding_width(self): return TECH.WIREWG.CLADDING_WIDTH
class Layout(WindowWaveguideTemplate.Layout): core_process = ProcessProperty(default=TECH.PROCESS.WG, doc="process for the waveguide core") core_purpose = PurposeProperty(default=TECH.PURPOSE.LF.LINE, doc="drawing purpose for the waveguide core") cladding_process = ProcessProperty(doc="process for the waveguide cladding, defaults to the core process") cladding_purpose = PurposeProperty(default=TECH.PURPOSE.LF_AREA, doc="drawing purpose layer for the cladding") # core_width = PositiveNumberProperty(default=TECH.WG.CORE_WIDTH) cladding_width = PositiveNumberProperty(default=TECH.WG.CLADDING_WIDTH, doc="total width of the waveguide with cladding") def _default_cladding_process(self): return self.core_process def _default_cover_layers(self): # Layer for Manhattan rectangles return [PPLayer(self.cladding_process, self.cladding_purpose)] def validate_properties(self): if self.cladding_width < self.core_width: raise PropertyValidationError( "The waveguide cladding should be at least of as wide as the core. core={:f}, cladding={:f}".format( self.core_width, self.cladding_width)) return True def _default_width(self): return self.cladding_width def _default_windows(self): # populate the cladding PPlayers clad_pp_layers_list = [ TECH.PPLAYER.AIM.BESAMFILL, TECH.PPLAYER.AIM.BCAAMFILL, TECH.PPLAYER.AIM.BSEAMFILL, TECH.PPLAYER.AIM.BFNAMFILL, TECH.PPLAYER.AIM.BSNAMFILL, TECH.PPLAYER.AIM.BM1AMFILL, TECH.PPLAYER.AIM.BMLAMFILL, TECH.PPLAYER.AIM.BM2AMFILL, ] windows = [] # add cladding windows for pplayer in clad_pp_layers_list: windows.append(PathTraceWindow(layer=pplayer, start_offset=-0.5 * self.cladding_width, end_offset=+0.5 * self.cladding_width, shape_property_name="cladding_shape")) # add core layer windows.append(PathTraceWindow( layer = TECH.PPLAYER.WG.COR, start_offset = -0.5 * self.core_width, end_offset = +0.5 * self.core_width)) return windows
class ThreePort(Structure): __name_prefix__ = "3PORT" width = PositiveNumberProperty(required=True) height = PositiveNumberProperty(required=True) wg_width = PositiveNumberProperty(default=TECH.WG.WIRE_WIDTH) trench_width = PositiveNumberProperty(default=TECH.WG.TRENCH_WIDTH) process = ProcessProperty(default=TECH.PROCESS.WG) # this init function is optional def __init__(self, **kwargs): # init functions should have **kwargs as last argument (to pass on arguments from subclasses) # and it should pass all arguments to its parent class # add initialization code here that should be executed BEFORE all properties are assigned # ..... super(ThreePort, self).__init__(**kwargs) # add initialization code here that should be executed AFTER all properties are assigned # ..... # method for determining the name (it is an autoname structure) def define_name(self): return "%s_W%d_H%d_W%d_T%d" % (self.__name_prefix__, self.width * 1000, self.height * 1000, self.wg_width * 1000, self.trench_width * 1000) def define_elements(self, elems): # add shape elements and stuff that should only be on the waveguide layer elems += Rectangle(PPLayer(self.process, TECH.PURPOSE.LF.LINE), (0.0, 0.0), (self.width, self.height)) elems += Rectangle(PPLayer(self.process, TECH.PURPOSE.LF_AREA), (0.0, 0.0), (self.width + 2 * self.trench_width, self.height + 2 * self.trench_width)) return elems def define_ports(self, ports): wg_def = WgElDefinition(wg_width=self.wg_width, trench_width=self.trench_width) ports += InOpticalPort(position=(-0.5 * self.width, 0.0), wg_definition=wg_def, angle=180.0) ports += OutOpticalPort(position=(0.0, 0.5 * self.height), wg_definition=wg_def, angle=90.0) ports += OutOpticalPort(position=(0.5 * self.width, 0.0), wg_definition=wg_def, angle=0.0) return ports
class InvertedTaper(FiberCoupler): process = ProcessProperty(default = TECH.PROCESS.WG) wg_def_start = WaveguideDefProperty(default = WgElDefinition(wg_width = TECH.WG.WIRE_WIDTH,trench_width = TECH.WG.TRENCH_WIDTH)) wg_def_end = WaveguideDefProperty(default = WgElDefinition(wg_width = 0.080 ,trench_width = 11.46)) tip_length = PositiveNumberProperty(default = 250.0) tip_offset = NonNegativeNumberProperty(default = 300.0) nitride_clearance = NonNegativeNumberProperty(default = 50.0) nitride_width = PositiveNumberProperty(default = 3.0) y_spacing = PositiveNumberProperty(default = 25.0) assist_lines = IntProperty(restriction = RESTRICT_NONNEGATIVE, default = 0) assist_spacing = PositiveNumberProperty(default = 0.160) assist_width = PositiveNumberProperty(default = 0.080) extension = NonNegativeNumberProperty(default = 1.0) def define_elements(self, elems): # draw tip ## Warning: end-waveguide definition is calculated using y_spacing and tip_width, only wg-width is extracted from wg_def wg_def_stop = WgElDefinition(wg_width = self.wg_def_end.wg_width, trench_width = 0.5*(self.y_spacing-self.wg_def_end.wg_width)-1.0) elems += WgElTaperLinear(start_position = (self.tip_length + self.tip_offset, 0.0), end_position = (self.tip_offset, 0.0), start_wg_def = self.wg_def_start, end_wg_def = wg_def_stop) if self.extension > 0: wg_def = WgElDefinition(wg_width = self.wg_def_end.wg_width, trench_width = 0.5*(self.y_spacing-self.wg_def_end.wg_width)-1.0, process = self.process) elems += wg_def([(self.tip_offset - self.extension , 0.0), (self.tip_offset, 0.0)]) #assist lines for tip for i in range(self.assist_lines): elems += Path(PPLayer(self.process, TECH.PURPOSE.LF.LINE), [(self.tip_length + self.tip_offset, 0.0 + (0.5*self.tip_start_width + (i+1)*(self.assist_width+ self.assist_spacing) - 0.5*self.assist_width)), (self.tip_offset, 0.0 + (0.5*self.tip_width + (i+1)*(self.assist_width+ self.assist_spacing) - 0.5*self.assist_width)), (self.tip_offset - self.extension, 0.0 + (0.5*self.tip_width + (i+1)*(self.assist_width+ self.assist_spacing) - 0.5*self.assist_width)), ], self.assist_width) elems += Path(PPLayer(self.process, TECH.PURPOSE.LF.LINE), [(self.tip_length + self.tip_offset, 0.0 - (0.5*self.tip_start_width+ (i+1)*(self.assist_width+ self.assist_spacing) - 0.5*self.assist_width)), (self.tip_offset, 0.0 - (0.5*self.tip_width + (i+1)*(self.assist_width+ self.assist_spacing) - 0.5*self.assist_width)), (self.tip_offset- self.extension, 0.0 - (0.5*self.tip_width + (i+1)*(self.assist_width+ self.assist_spacing) - 0.5*self.assist_width)), ], self.assist_width) return elems def define_ports(self, prts): wg_def = WgElDefinition(wg_width = self.wg_def_start.wg_width, trench_width = self.wg_def_start.trench_width, process = self.process) prts += [OpticalPort(position = (self.tip_length + self.tip_offset, 0.0), angle = 0.0, wg_definition = wg_def)] return prts
class NitrideInvertedTaper(InvertedTaper): nitride_only_length = PositiveNumberProperty(default = 300.0) nitride_clearance = PositiveNumberProperty(default = 50.0) nitride_width = PositiveNumberProperty(default = 3.0) nt_process = ProcessProperty(default = TECH.PROCESS.NT) tip_offset = DefinitionProperty(fdef_name = "define_tip_offset") def define_tip_offset(self): return self.nitride_only_length def define_elements(self, elems): elems += super(NitrideInvertedTaper,self).define_elements(elems) # WG elems += Line(PPLayer(self.process,TECH.PURPOSE.LF_AREA), (0.0, 0.0), (self.nitride_only_length - self.extension , 0.0), self.y_spacing) # NT elems += Line(PPLayer(self.nt_process, TECH.PURPOSE.LF.LINE), (0.0, 0.0), (self.nitride_only_length + self.tip_length + 100.0 , 0.0), self.nitride_width ) return elems
class NitrideInvertedTaperShallow(InvertedTaperShallow): nitride_only_length = PositiveNumberProperty(default = 300.0) nitride_clearance = PositiveNumberProperty(default = 50.0) nitride_width = PositiveNumberProperty(default = 3.0) nt_process = ProcessProperty(default = TECH.PROCESS.NT) def define_elements(self, elems): # WG elems += Line(PPLayer(self.deep_process,TECH.PURPOSE.LF_AREA), (0.0, 0.0), (self.nitride_only_length - self.extension , 0.0), self.y_spacing) # FC s_o_length = self.tip_offset + self.tip_length elems += Line(PPLayer(self.shallow_process, TECH.PURPOSE.LF_AREA), (0.0, 0.0), (s_o_length- self.extension , 0.0), self.y_spacing) # NT elems += Line(PPLayer(self.nt_process, TECH.PURPOSE.LF.LINE), (0.0, 0.0), (self.nitride_only_length + self.tip_length + self.shallow_tip_length + 50.0 , 0.0), self.nitride_width ) return elems