diff --git a/klayout/EBeam/pymacros/pcells_EBeam_Beta/e_skid.py b/klayout/EBeam/pymacros/pcells_EBeam_Beta/e_skid.py new file mode 100644 index 00000000..e1637904 --- /dev/null +++ b/klayout/EBeam/pymacros/pcells_EBeam_Beta/e_skid.py @@ -0,0 +1,271 @@ +import pya +from . import * +from SiEPIC.utils import get_technology_by_name +from SiEPIC._globals import PIN_LENGTH as pin_length +from pya import DPolygon +import math + +#==================================================================================================== +# File: e_skid.py +# Author: Hang (Bobby) Zou +# Purpose: PCell in EBeam library for a common parallel e-skid design that have adjustable period +# and fill factor +# Version: V2.0 +# Date: 2023-11-09 +#==================================================================================================== + +class e_skid(pya.PCellDeclarationHelper): + + def __init__(self): + + # Important: initialize the super class + super(e_skid, self).__init__() + self.technology_name = 'EBeam' + + TECHNOLOGY = get_technology_by_name(self.technology_name) + + # e_skid Parameters: + # core parameter + self.param('divider0', self.TypeNone, '==============Core Parameter==============') + + self.param('w', self.TypeDouble, 'Core Waveguide Width [um]' , default = 0.3) + + self.param('divider1', self.TypeNone, '==============Clad Parameter==============') + + # clad parameter + self.param('p', self.TypeDouble, 'e-skid Period [um]' , default = 0.1) + self.param('ff', self.TypeDouble, 'e-skid Fill Factor [0.2-0.8]' , default = 0.5) + self.param('p_num', self.TypeInt, 'e-skid Period Number' , default = 5) + self.param('length', self.TypeDouble, 'Length of e-skid Waveguide [um]' , default = 10) + + self.param('divider2', self.TypeNone, '==============Taper Parameter=============') + + # taper + self.param('taper_True', self.TypeBoolean, 'Taper [T/F]' , default = True) + self.param('taperL', self.TypeDouble, 'Strip -> e-skid Taper Length [um]' , default = 5) + self.param('taperW', self.TypeDouble, 'Strip Width [um]' , default = 0.5) + + self.param('divider3', self.TypeNone, '============Extended Clad Parameter==========') + + # extended clad parameter + self.param('clad_taper_L', self.TypeDouble, 'Extended e-skid Length [um]' , default = 5) + self.param('clad_taper_angle', self.TypeDouble,'Extended e-skid Angle [degree]' , default = 2) + + self.param('divider4', self.TypeNone, '=====================================') + + # Layer Parameters - Don't touch + self.param("layer", self.TypeLayer, "Layer", default = TECHNOLOGY['Si']) + self.param("pinrec", self.TypeLayer, "PinRec Layer", default = TECHNOLOGY['PinRec']) + self.param("devrec", self.TypeLayer, "DevRec Layer", default = TECHNOLOGY['DevRec']) + self.param("oxideopen", self.TypeLayer, "Oxide Open Layer", default = TECHNOLOGY['Oxide open (to BOX)']) + + def display_text_impl(self): + # Provide a descriptive text for the cell + return "configurable_e_skid" + + # Creating the layout + def produce_impl(self): + + # Layout Parameters + dbu = self.layout.dbu + ly = self.layout + shapes = self.cell.shapes + + LayerSi = self.layer + LayerSiN = ly.layer(LayerSi) + LayerPinRecN = ly.layer(self.pinrec) + LayerDevRecN = ly.layer(self.devrec) + + w = self.w # Core Waveguide Width [um] + p = self.p # e-skid Period [um] + ff = self.ff # e-skid Duty Cycle [%] + p_num = self.p_num # e-skid Period Number + length = self.length # e-skid Waveguide Length [um] + + taper_True = self.taper_True # e-skid Taper [T/F] + taperW = self.taperW # e-skid Taper Width [um] + taperL = self.taperL # e-skid Taper Length [um] + + clad_taper_L = self.clad_taper_L # Extended e-skid length [nm] + clad_taper_angle_radians = self.clad_taper_angle*math.pi/180 # Extended e-skid angle [degrees] + + + + ############################### + ########### e-skid ############ + ############################### + + # 1. e-skid main body + + # x, y coordinates of the core + x_core = [0, length, length, 0] + y_core = [-w/2, - w/2, w/2, w/2] + + dpts = [pya.DPoint(x_core[i], y_core[i]) for i in range(len(x_core))] # Core body + dpolygon = DPolygon(dpts) + element = Polygon.from_dpoly(dpolygon*(1/dbu)) + shapes(LayerSiN).insert(element) + + # draw multiple clad for both top and bottom + for i in range (1, p_num+1): + + # x, y coordinates of the top clad + x_clad_top = [0, length, length, 0] + y_clad_top = [w/2+i*p-(p*ff), w/2+i*p-(p*ff), w/2+i*p, w/2+i*p] + + dpts = [pya.DPoint(x_clad_top[i], y_clad_top[i]) for i in range(len(x_clad_top))] # Core body + dpolygon = DPolygon(dpts) + element = Polygon.from_dpoly(dpolygon*(1/dbu)) + shapes(LayerSiN).insert(element) + + # x, y coordinates of the bottom clad + x_clad_bottom = [0, length, length, 0] + y_clad_bottom = [-w/2-i*p+(p*ff), -w/2-i*p+(p*ff), -w/2-i*p, -w/2-i*p] + + dpts = [pya.DPoint(x_clad_bottom[i], y_clad_bottom[i]) for i in range(len(x_clad_bottom))] # Core body + dpolygon = DPolygon(dpts) + element = Polygon.from_dpoly(dpolygon*(1/dbu)) + shapes(LayerSiN).insert(element) + + # 2. taper + Pins + + if taper_True: + # Top clad + if clad_taper_L > taperL: + # Prevent the clad_taper_L to be larger than taperL + clad_taper_L = taperL + + # Calculate the required offset + w_offset = taperW * clad_taper_L / taperL + + # fetch the taper angle at the set point + taper_angle = math.atan(((taperW-w)/2)/(taperL)) + + if clad_taper_angle_radians <= taper_angle: + clad_taper_angle_radians = taper_angle + + + for i in range (1, p_num+1): + + # draw the right clad, angle method + # locate the end points of the extended clad + clad_end_point_position = w/2+i*p + i*(clad_taper_L*math.tan(clad_taper_angle_radians)) + + + # x, y coordinates of the top clad + x_clad_top = [length, length+clad_taper_L, length+clad_taper_L, length] + y_clad_top = [w/2+i*p-(p*ff) , clad_end_point_position-(p*ff),clad_end_point_position, w/2+i*p] + + dpts = [pya.DPoint(x_clad_top[i], y_clad_top[i]) for i in range(len(x_clad_top))] # Core body + dpolygon = DPolygon(dpts) + element = Polygon.from_dpoly(dpolygon*(1/dbu)) + shapes(LayerSiN).insert(element) + + # x, y coordinates of the bottom clad + x_clad_bottom = [length, length+clad_taper_L, length+clad_taper_L, length] + y_clad_bottom = [-w/2-i*p+(p*ff) , -clad_end_point_position+(p*ff),-clad_end_point_position, -w/2-i*p] + + dpts = [pya.DPoint(x_clad_bottom[i], y_clad_bottom[i]) for i in range(len(x_clad_bottom))] # Core body + dpolygon = DPolygon(dpts) + element = Polygon.from_dpoly(dpolygon*(1/dbu)) + shapes(LayerSiN).insert(element) + + + # draw the left clad, angle method + # locate the end points of the extended clad + clad_end_point_position = w/2+i*p + i*(clad_taper_L*math.tan(clad_taper_angle_radians)) + + # x, y coordinates of the top clad + x_clad_top = [0, -clad_taper_L, -clad_taper_L, 0] + y_clad_top = [w/2+i*p-(p*ff) , clad_end_point_position-(p*ff),clad_end_point_position, w/2+i*p] + + dpts = [pya.DPoint(x_clad_top[i], y_clad_top[i]) for i in range(len(x_clad_top))] # Core body + dpolygon = DPolygon(dpts) + element = Polygon.from_dpoly(dpolygon*(1/dbu)) + shapes(LayerSiN).insert(element) + + # x, y coordinates of the bottom clad + x_clad_bottom = [0, -clad_taper_L, -clad_taper_L, 0] + y_clad_bottom = [-w/2-i*p+(p*ff) , -clad_end_point_position+(p*ff),-clad_end_point_position, -w/2-i*p] + + dpts = [pya.DPoint(x_clad_bottom[i], y_clad_bottom[i]) for i in range(len(x_clad_bottom))] # Core body + dpolygon = DPolygon(dpts) + element = Polygon.from_dpoly(dpolygon*(1/dbu)) + shapes(LayerSiN).insert(element) + + # left taper + x_taper_left = [0, 0, -taperL, -taperL] + y_taper_left = [-w/2, w/2, taperW/2, -taperW/2] + + dpts = [pya.DPoint(x_taper_left[i], y_taper_left[i]) for i in range(len(x_taper_left))] # Core body + dpolygon = DPolygon(dpts) + element = Polygon.from_dpoly(dpolygon*(1/dbu)) + shapes(LayerSiN).insert(element) + + # right taper + x_taper_right = [length, length, length+taperL, length+taperL] + y_taper_right = [-w/2, w/2, taperW/2, -taperW/2] + + dpts = [pya.DPoint(x_taper_right[i], y_taper_right[i]) for i in range(len(x_taper_right))] # Core body + dpolygon = DPolygon(dpts) + element = Polygon.from_dpoly(dpolygon*(1/dbu)) + shapes(LayerSiN).insert(element) + + # Adding Pins for mating + # Pin 1 + t = pya.DTrans(pya.Trans.R90, -taperL/dbu, 0/dbu) + pin = pya.Path([pya.DPoint(0, -pin_length/2), pya.DPoint(0, pin_length/2)], taperW/dbu) + pin_t = pin.transformed(t) + shapes(LayerPinRecN).insert(pin_t) + text = pya.Text ("opt1", pya.DTrans(pya.Trans.R0, -taperL/dbu, 0/dbu)) + shape = shapes(LayerPinRecN).insert(text) + shape.text_size = 0.2/dbu + + # Pin 2 + t = pya.DTrans(pya.Trans.R270, (taperL + length)/dbu, 0/dbu) + pin = pya.Path([pya.DPoint(0, -pin_length/2), pya.DPoint(0, pin_length/2)], taperW/dbu) + pin_t = pin.transformed(t) + shapes(LayerPinRecN).insert(pin_t) + text = pya.Text ("opt2", pya.DTrans(pya.Trans.R0, (taperL + length)/dbu, 0/dbu)) + shape = shapes(LayerPinRecN).insert(text) + shape.text_size = 0.2/dbu + + # Devbox + dev = pya.DBox(-taperL, + clad_end_point_position + 0.5, + length + taperL, + -clad_end_point_position - 0.5) + + shapes(LayerDevRecN).insert(dev) + + else: + # Adding Pins for mating + # Pin 1 + t = pya.DTrans(pya.Trans.R90, 0, 0/dbu) + pin = pya.Path([pya.DPoint(0, -pin_length/2), pya.DPoint(0, pin_length/2)], w/dbu) + pin_t = pin.transformed(t) + shapes(LayerPinRecN).insert(pin_t) + text = pya.Text ("opt1", pya.DTrans(pya.Trans.R0, 0, 0/dbu)) + shape = shapes(LayerPinRecN).insert(text) + shape.text_size = 0.2/dbu + + # Pin 2 + t = pya.DTrans(pya.Trans.R270, length/dbu, 0/dbu) + pin = pya.Path([pya.DPoint(0, -pin_length/2), pya.DPoint(0, pin_length/2)], w/dbu) + pin_t = pin.transformed(t) + shapes(LayerPinRecN).insert(pin_t) + text = pya.Text ("opt2", pya.DTrans(pya.Trans.R0, length/dbu, 0/dbu)) + shape = shapes(LayerPinRecN).insert(text) + shape.text_size = 0.2/dbu + + # Devbox + dev = pya.DBox(0, + w/2 + p_num*p + 0.5, + length, + -w/2 - p_num*p - 0.5) + + shapes(LayerDevRecN).insert(dev) + +#==================================================================================================== +# END OF DOCUMENT +#==================================================================================================== \ No newline at end of file diff --git a/klayout/EBeam/pymacros/pcells_EBeam_Beta/e_skid_ring.py b/klayout/EBeam/pymacros/pcells_EBeam_Beta/e_skid_ring.py new file mode 100644 index 00000000..58f7dd25 --- /dev/null +++ b/klayout/EBeam/pymacros/pcells_EBeam_Beta/e_skid_ring.py @@ -0,0 +1,173 @@ +from . import * +import pya +from SiEPIC.utils import get_technology_by_name, arc_wg_xy +from SiEPIC._globals import PIN_LENGTH as pin_length +from pya import DPolygon + +class e_skid_ring(pya.PCellDeclarationHelper): + + """ + Author: Ben Cohen (UBC), Hang Bobby Zou (UBC) + bcohenkl@ece.ubc.ca + Nov 9, 2023 + + - This Pcell creates a single-bus ring resonator modified with e-skid concentric rings + - Design control over number of inner/outer concentric rings. Gap between two rings and width is parameterized + as an input list. + - If a 0 is found in any entry of the list, the cell will automatically delete every element in the list + - If the number of entries in the gap and width lists are different, the list with the minimum number of elements is considered + + - Controllable coupling. Bus length is designed as the outer most radius of the e-skid ring resonator + """ + + def __init__(self): + + # Important: initialize the super class + super(e_skid_ring, self).__init__() + self.technology_name = 'EBeam' + TECHNOLOGY = get_technology_by_name(self.technology_name) + + # Main Ring Parameters + self.param("r", self.TypeDouble, "Ring Radii [um]", default = 10) + self.param("w", self.TypeDouble, "Ring Waveguide Width [um]", default = 0.5) + self.param("cg", self.TypeDouble, "Coupling Gap [um]", default = 0.2) + + # Bus Parameters: + self.param("bus_w", self.TypeDouble, "Bus Waveguide Width [um]", default = 0.5) + + # e-skid parameter + self.param("gap_out", self.TypeList, "Outer Gap List [um] (0 if none)", default = [0]) + self.param("w_out", self.TypeList, "Outer Width List [um] (0 if none)", default = [0]) + + self.param("gap_in", self.TypeList, "Inner Gap List [um] (0 if none)", default = [0.3, 0.3]) + self.param("w_in", self.TypeList, "Inner Width List [um] (0 if none)", default = [0.1, 0.1]) + + # Layer Parameters + self.param("layer", self.TypeLayer, "Layer", default = TECHNOLOGY['Si'], hidden = True) + self.param("pinrec", self.TypeLayer, "PinRec Layer", default = TECHNOLOGY['PinRec'], hidden = True) + self.param("devrec", self.TypeLayer, "DevRec Layer", default = TECHNOLOGY['DevRec'], hidden = True) + self.param("oxideopen", self.TypeLayer, "Oxide Open Layer", default = TECHNOLOGY['Oxide open (to BOX)'], hidden = True) + + def display_text_impl(self): + # Provide a descriptive text for the cell + return "ring_resonator_with_e_skid_pillar" + + # Creating the layout + def produce_impl(self): + + # Layout Parameters + dbu = self.layout.dbu + ly = self.layout + shapes = self.cell.shapes + + # Layers + LayerSi = self.layer + LayerSiN = ly.layer(LayerSi) + LayerPinRecN = ly.layer(self.pinrec) + LayerDevRecN = ly.layer(self.devrec) + + # Main Ring Parameters + r = self.r # Ring radii [um] + w = self.w # Ring waveguide width [um] + cg = self.cg # Coupling gap + + # Bus Parameters: + bus_w = self.bus_w # Bus width [um] + bus_l = 2*(r + w) # Bus length [um] + + # e-skid parameters + gap_out = self.gap_out # Gap between different widths for rings outside of the main ring resonator [um] + w_out = self.w_out # Width of each ring outside of the main ring resonator [um] + gap_in = self.gap_in # Gap between different widths for rings inside of the main ring resonator [um] + w_in = self.w_in # Width of each ring inside of the main ring resonator [um] + + + # Converting the list elements from str (klayout default) to float + # No entries in either array should be 0, deleting every entry after 0 is found + for i in range(len(w_out)): + w_out[i] = float(w_out[i]) + if w_out[i] == 0: + w_out = w_out[:i] + break + + for i in range(len(gap_out)): + gap_out[i] = float(gap_out[i]) + if gap_out[i] == 0: + w_out = w_out[:i] + break + + for i in range(len(w_in)): + w_in[i] = float(w_in[i]) + if w_in[i] == 0: + w_in = w_in[:i] + break + + for i in range(len(gap_in)): + gap_in[i] = float(gap_in[i]) + if gap_in[i] == 0: + gap_in = gap_in[:i] + break + + # Ring Resonator + if (r != 0): + shapes(LayerSiN).insert(arc_wg_xy(0, 0, (r + w/2)/dbu, w/dbu, 0, 360)) + + # Bus Waveguide + bus_x = [-bus_l/2, bus_l/2, bus_l/2, -bus_l/2] + bus_y = [r + w + cg, r + w + cg, r + w + cg + bus_w, r + w + cg + bus_w] + + dpts = [pya.DPoint(bus_x[i], bus_y[i]) for i in range(len(bus_x))] # Core body + dpolygon = DPolygon(dpts) + element = Polygon.from_dpoly(dpolygon*(1/dbu)) + shapes(LayerSiN).insert(element) + + + # Adding outer concetric rings + """ + rad0_out = r + w + for i in range(min(len(gap_out), len(w_out))): + ring = pya.Region() + ring.insert(arc_wg_xy(0, 0, (rad0_out + gap_out[i] + w_out[i]/2)/dbu, w_out[i]/dbu, 0, 360)) + + # CONSIDERATION FOR TAPERS + box_subtract = + shapes(LayerSiN).insert(ring) + + #shapes(LayerSiN).insert(arc_wg_xy(0, 0, (rad0_out + gap_out[i] + w_out[i]/2)/dbu, w_out[i]/dbu, 0, 360)) + rad0_out = rad0_out + gap_out[i] + w_out[i] + """ + + # Adding inner concetric rings + if (r != 0): + rad0_in = r + for i in range(min(len(gap_in), len(w_in))): + + ring = pya.Region() + ring.insert(arc_wg_xy(0, 0, (rad0_in - gap_in[i] - w_in[i]/2)/dbu, w_in[i]/dbu, 0, 360)) + shapes(LayerSiN).insert(ring) + + rad0_in = rad0_in - gap_in[i] - w_in[i] + + + # Pins for mating: + t = pya.DTrans(pya.Trans.R90, min(bus_x)/dbu, (min(bus_y) + max(bus_y))/2/dbu) + pin = pya.Path([pya.DPoint(0, -pin_length/2), pya.DPoint(0, pin_length/2)], bus_w/dbu) + pin_t = pin.transformed(t) + shapes(LayerPinRecN).insert(pin_t) + text = pya.Text("opt1", pya.DTrans(pya.Trans.R0, min(bus_x)/dbu, (min(bus_y) + max(bus_y))/2/dbu)) + shape = shapes(LayerPinRecN).insert(text) + shape.text_size = 0.4/dbu + + t = pya.DTrans(pya.Trans.R90, max(bus_x)/dbu, (min(bus_y) + max(bus_y))/2/dbu) + pin = pya.Path([pya.DPoint(0, pin_length/2), pya.DPoint(0, -pin_length/2)], bus_w/dbu) + pin_t = pin.transformed(t) + shapes(LayerPinRecN).insert(pin_t) + text = pya.Text("opt2", pya.DTrans(pya.Trans.R90, max(bus_x)/dbu, (min(bus_y) + max(bus_y))/2/dbu)) + shape = shapes(LayerPinRecN).insert(text) + shape.text_size = 0.4/dbu + + # Dev box + # Encapsulate the pcell within a box for error checking + w = self.w + dev = pya.DBox(-(r + w), r + w + cg + bus_w + 0.5, r + w, -(r + w) - 0.5) + shapes(LayerDevRecN).insert(dev) \ No newline at end of file diff --git a/klayout/EBeam/pymacros/pcells_EBeam_Beta/e_skid_single_side_taper.py b/klayout/EBeam/pymacros/pcells_EBeam_Beta/e_skid_single_side_taper.py new file mode 100644 index 00000000..48906cee --- /dev/null +++ b/klayout/EBeam/pymacros/pcells_EBeam_Beta/e_skid_single_side_taper.py @@ -0,0 +1,239 @@ +import pya +from . import * +from SiEPIC.utils import get_technology_by_name +from SiEPIC._globals import PIN_LENGTH as pin_length +from pya import DPolygon +import math + +#==================================================================================================== +# File: e_skid_single_side_taper.py +# Author: Hang (Bobby) Zou +# Purpose: PCell in EBeam library for a common parallel e-skid design that have adjustable period +# and fill factor +# Version: V2.0 +# Date: 2023-11-09 +#==================================================================================================== + +class e_skid_single_side_taper(pya.PCellDeclarationHelper): + + def __init__(self): + + # Important: initialize the super class + super(e_skid_single_side_taper, self).__init__() + self.technology_name = 'EBeam' + + TECHNOLOGY = get_technology_by_name(self.technology_name) + + # e_skid Parameters: + # core parameter + self.param('divider0', self.TypeNone, '==============Core Parameter==============') + + self.param('w', self.TypeDouble, 'Core Waveguide Width [um]' , default = 0.3) + + self.param('divider1', self.TypeNone, '==============Clad Parameter==============') + + # clad parameter + self.param('p', self.TypeDouble, 'e-skid Period [um]' , default = 0.1) + self.param('ff', self.TypeDouble, 'e-skid Fill Factor [0.2-0.8]' , default = 0.5) + self.param('p_num', self.TypeInt, 'e-skid Period Number' , default = 5) + self.param('length', self.TypeDouble, 'Length of e-skid Waveguide [um]' , default = 10) + + self.param('divider2', self.TypeNone, '==============Taper Parameter=============') + + # taper + self.param('taper_True', self.TypeBoolean, 'Taper [T/F]' , default = True) + self.param('taperL', self.TypeDouble, 'Strip -> e-skid Taper Length [um]' , default = 5) + self.param('taperW', self.TypeDouble, 'Strip Width [um]' , default = 0.5) + + self.param('divider3', self.TypeNone, '============Extended Clad Parameter==========') + + # extended clad parameter + self.param('clad_taper_L', self.TypeDouble, 'Extended e-skid Length [um]' , default = 5) + self.param('clad_taper_angle', self.TypeDouble,'Extended e-skid Angle [degree]' , default = 2) + + self.param('divider4', self.TypeNone, '=====================================') + + # Layer Parameters - Don't touch + self.param("layer", self.TypeLayer, "Layer", default = TECHNOLOGY['Si']) + self.param("pinrec", self.TypeLayer, "PinRec Layer", default = TECHNOLOGY['PinRec']) + self.param("devrec", self.TypeLayer, "DevRec Layer", default = TECHNOLOGY['DevRec']) + self.param("oxideopen", self.TypeLayer, "Oxide Open Layer", default = TECHNOLOGY['Oxide open (to BOX)']) + + def display_text_impl(self): + # Provide a descriptive text for the cell + return "e_skid_with_a_single_side_taper" + + + # Creating the layout + def produce_impl(self): + + # Layout Parameters + dbu = self.layout.dbu + ly = self.layout + shapes = self.cell.shapes + + LayerSi = self.layer + LayerSiN = ly.layer(LayerSi) + LayerPinRecN = ly.layer(self.pinrec) + LayerDevRecN = ly.layer(self.devrec) + + w = self.w # Core Waveguide Width [um] + p = self.p # e-skid Period [um] + ff = self.ff # e-skid Duty Cycle [%] + p_num = self.p_num # e-skid Period Number + length = self.length # e-skid Waveguide Length [um] + + taper_True = self.taper_True # e-skid Taper [T/F] + taperW = self.taperW # e-skid Taper Width [um] + taperL = self.taperL # e-skid Taper Length [um] + + clad_taper_L = self.clad_taper_L # Extended e-skid length [nm] + clad_taper_angle_radians = self.clad_taper_angle*math.pi/180 # Extended e-skid angle [degrees] + + + + ############################### + ########### e-skid ############ + ############################### + + # 1. e-skid main body + + # x, y coordinates of the core + x_core = [0, length, length, 0] + y_core = [-w/2, - w/2, w/2, w/2] + + dpts = [pya.DPoint(x_core[i], y_core[i]) for i in range(len(x_core))] # Core body + dpolygon = DPolygon(dpts) + element = Polygon.from_dpoly(dpolygon*(1/dbu)) + shapes(LayerSiN).insert(element) + + # draw multiple clad for both top and bottom + for i in range (1, p_num+1): + + # x, y coordinates of the top clad + x_clad_top = [0, length, length, 0] + y_clad_top = [w/2+i*p-(p*ff), w/2+i*p-(p*ff), w/2+i*p, w/2+i*p] + + dpts = [pya.DPoint(x_clad_top[i], y_clad_top[i]) for i in range(len(x_clad_top))] # Core body + dpolygon = DPolygon(dpts) + element = Polygon.from_dpoly(dpolygon*(1/dbu)) + shapes(LayerSiN).insert(element) + + # x, y coordinates of the bottom clad + x_clad_bottom = [0, length, length, 0] + y_clad_bottom = [-w/2-i*p+(p*ff), -w/2-i*p+(p*ff), -w/2-i*p, -w/2-i*p] + + dpts = [pya.DPoint(x_clad_bottom[i], y_clad_bottom[i]) for i in range(len(x_clad_bottom))] # Core body + dpolygon = DPolygon(dpts) + element = Polygon.from_dpoly(dpolygon*(1/dbu)) + shapes(LayerSiN).insert(element) + + # 2. taper + Pins + + if taper_True: + # Top clad + if clad_taper_L > taperL: + # Prevent the clad_taper_L to be larger than taperL + clad_taper_L = taperL + + # Calculate the required offset + w_offset = taperW * clad_taper_L / taperL + + # fetch the taper angle at the set point + taper_angle = math.atan(((taperW-w)/2)/(taperL)) + + if clad_taper_angle_radians <= taper_angle: + clad_taper_angle_radians = taper_angle + + + for i in range (1, p_num+1): + + # draw the left clad, angle method + # locate the end points of the extended clad + clad_end_point_position = w/2+i*p + i*(clad_taper_L*math.tan(clad_taper_angle_radians)) + + # x, y coordinates of the top clad + x_clad_top = [0, -clad_taper_L, -clad_taper_L, 0] + y_clad_top = [w/2+i*p-(p*ff) , clad_end_point_position-(p*ff),clad_end_point_position, w/2+i*p] + + dpts = [pya.DPoint(x_clad_top[i], y_clad_top[i]) for i in range(len(x_clad_top))] # Core body + dpolygon = DPolygon(dpts) + element = Polygon.from_dpoly(dpolygon*(1/dbu)) + shapes(LayerSiN).insert(element) + + # x, y coordinates of the bottom clad + x_clad_bottom = [0, -clad_taper_L, -clad_taper_L, 0] + y_clad_bottom = [-w/2-i*p+(p*ff) , -clad_end_point_position+(p*ff),-clad_end_point_position, -w/2-i*p] + + dpts = [pya.DPoint(x_clad_bottom[i], y_clad_bottom[i]) for i in range(len(x_clad_bottom))] # Core body + dpolygon = DPolygon(dpts) + element = Polygon.from_dpoly(dpolygon*(1/dbu)) + shapes(LayerSiN).insert(element) + + # left taper + x_taper_left = [0, 0, -taperL, -taperL] + y_taper_left = [-w/2, w/2, taperW/2, -taperW/2] + + dpts = [pya.DPoint(x_taper_left[i], y_taper_left[i]) for i in range(len(x_taper_left))] # Core body + dpolygon = DPolygon(dpts) + element = Polygon.from_dpoly(dpolygon*(1/dbu)) + shapes(LayerSiN).insert(element) + + # Adding Pins for mating + # Pin 1 + t = pya.DTrans(pya.Trans.R90, -taperL/dbu, 0/dbu) + pin = pya.Path([pya.DPoint(0, -pin_length/2), pya.DPoint(0, pin_length/2)], taperW/dbu) + pin_t = pin.transformed(t) + shapes(LayerPinRecN).insert(pin_t) + text = pya.Text ("opt1", pya.DTrans(pya.Trans.R0, -taperL/dbu, 0/dbu)) + shape = shapes(LayerPinRecN).insert(text) + shape.text_size = 0.2/dbu + + # Pin 2 + t = pya.DTrans(pya.Trans.R270, (length)/dbu, 0/dbu) + pin = pya.Path([pya.DPoint(0, -pin_length/2), pya.DPoint(0, pin_length/2)], w/dbu) + pin_t = pin.transformed(t) + shapes(LayerPinRecN).insert(pin_t) + text = pya.Text ("opt2", pya.DTrans(pya.Trans.R0, (length)/dbu, 0/dbu)) + shape = shapes(LayerPinRecN).insert(text) + shape.text_size = 0.2/dbu + + # Devbox + dev = pya.DBox(-taperL, + clad_end_point_position + 0.5, + length, + -clad_end_point_position - 0.5) + + shapes(LayerDevRecN).insert(dev) + + else: + # Adding Pins for mating + # Pin 1 + t = pya.DTrans(pya.Trans.R90, 0, 0/dbu) + pin = pya.Path([pya.DPoint(0, -pin_length/2), pya.DPoint(0, pin_length/2)], w/dbu) + pin_t = pin.transformed(t) + shapes(LayerPinRecN).insert(pin_t) + text = pya.Text ("opt1", pya.DTrans(pya.Trans.R0, 0, 0/dbu)) + shape = shapes(LayerPinRecN).insert(text) + shape.text_size = 0.2/dbu + + # Pin 2 + t = pya.DTrans(pya.Trans.R270, length/dbu, 0/dbu) + pin = pya.Path([pya.DPoint(0, -pin_length/2), pya.DPoint(0, pin_length/2)], w/dbu) + pin_t = pin.transformed(t) + shapes(LayerPinRecN).insert(pin_t) + text = pya.Text ("opt2", pya.DTrans(pya.Trans.R0, length/dbu, 0/dbu)) + shape = shapes(LayerPinRecN).insert(text) + shape.text_size = 0.2/dbu + + # Devbox + dev = pya.DBox(0, + w/2 + p_num*p + 0.5, + length, + -w/2 - p_num*p - 0.5) + + shapes(LayerDevRecN).insert(dev) + +#==================================================================================================== +# END OF DOCUMENT +#==================================================================================================== \ No newline at end of file