def draw_cring(layer_num,origin,gap): ## PARAMETERS race_r = 20 # racetrack bent part inner radius [um] race_w = 0.45 # racetrack width [um] ring_i = 9.4 # racetrack linear semilength [um] #Inputs: #layer_num: layer number #origin: figure position #rrgap gap between racetrack and ring #ringp ring position parameter #Description: This function draws a (horizontal) racetrack of width race_w and linear semilength race_d, which center is localized at point origin. Also, it draws an inner microring and an outter one, with the same width and radii equals a half of racetrack radius. #The microrings are posicioned at the linear part of the racetrack, with a gap of rrgap. Their centers move in oposite direction, through the ringp parameter (0,1), so that 0 stands for align centers and 1 stands for a lngth difference of 2 microring's radius #Output: bool,a gdspy object ring0 = gdspy.Round(numpy.array(origin)+numpy.array([0,0]),race_r+race_w,race_r, initial_angle=0.0, final_angle=2.0*numpy.pi,number_of_points=pow(2,12)-1,max_points=pow(2,12)-1,layer=layer_num) ring1 = gdspy.Round(numpy.array(origin)+numpy.array([0,-gap-race_w-ring_i]),ring_i+race_w,ring_i, initial_angle=0.0, final_angle=2.0*numpy.pi,number_of_points=pow(2,12)-1,max_points=pow(2,12)-1,layer=layer_num) ring2 = gdspy.Round(numpy.array(origin)+numpy.array([0,gap+race_w+ring_i]),ring_i+race_w,ring_i, initial_angle=0.0, final_angle=2.0*numpy.pi,number_of_points=pow(2,12)-1,max_points=pow(2,12)-1,layer=layer_num) bool = gdspy.boolean([ring0,ring1],summ,max_points=pow(2,12)-1,layer=layer_num) bool = gdspy.boolean([bool,ring2],summ,max_points=pow(2,12)-1,**ims.wgcor) bool = bool.rotate(numpy.pi/2) return bool
def Generate(self, mode, middle_TL): #resonator, center = Resonator(self.x, top_TL , self.R3, self.outer_ground, self.R4, self.freq).Generate(DE, TL_ground, d) ground = gdspy.Round((self.center.x, self.center.y), self.outer_ground, self.R4, initial_angle=0, final_angle=2 * np.pi) #ground = gdspy.boolean(ground, r3, 'not') #substract incoming resonator from qubit ground coupler = gdspy.Round((self.center.x, self.center.y), self.R3, self.R2, initial_angle=(-self.arc - 1 / 2) * np.pi, final_angle=(-1 / 2 + self.arc) * np.pi) result = gdspy.boolean(ground, coupler, 'or') core = gdspy.Round((self.center.x, self.center.y), self.R1, inner_radius=0, initial_angle=0, final_angle=2 * np.pi) result = gdspy.boolean(result, core, 'or') self.JJ_coordinates = coordinates(self.center.x, self.center.y + self.R1) self.AB1_coordinates = coordinates(self.center.x, self.center.y + self.R4) self.AB2_coordinates = coordinates(self.center.x, self.center.y - self.outer_ground) if mode == 'up': return result else: result.mirror([self.center.x, middle_TL], [self.center.x + 100, middle_TL]) return result
def Vertical_Part(x, y, y_turn, d, rot, delta, right, mode='full'): r_outer = d * 2.5 r_inner = d * 1.5 if y_turn < y: direction = 1 else: direction = -1 if mode == 'cut': return gdspy.Rectangle((x - delta, y), (x + d + delta, y_turn)) if (rot.phi2 - rot.phi1) > 0: return gdspy.boolean( gdspy.Rectangle((x - delta, y), (x + d + delta, y_turn + r_outer * direction)), gdspy.Round((x + r_inner + d, y_turn + r_outer), r_outer + delta, r_inner - delta, rot.phi1, rot.phi2, tolerance=0.01), 'or'), coordinates(x + (r_inner + d), y_turn) else: return gdspy.boolean( gdspy.Rectangle((x - delta, y), (x + d + delta, y_turn - r_inner)), gdspy.Round((x + r_inner + d, y_turn - r_inner), r_outer + delta, r_inner - delta, rot.phi1, rot.phi2, tolerance=0.01), 'or'), coordinates(x + r_outer, y_turn)
def coupled_ring(layer_num, center, r1, r2, gap, wg2M, wg2m): ring1 = gdspy.Round(center, r1, r1 - wg_w, max_points=4094, number_of_points=0.1, layer=layer_num) pr2 = r1 - wg_w - gap - r2 #inner ring position ring2 = gdspy.Round((center[0], center[1] + pr2), r2, max_points=4094, number_of_points=0.1, layer=layer_num) rsub = r2 - (wg2M + wg2m) / 2.0 ring3 = gdspy.Round((center[0], center[1] + pr2 - r2 + rsub), rsub, max_points=4094, number_of_points=0.1, layer=layer_num) print('bug') bool = gdspy.boolean([ring2, ring3], subtraction, layer=layer_num) print('bug') bool = gdspy.boolean([bool, ring1], sum, max_points=4094, layer=layer_num) return bool
def Horizontal_Part(x, y, x_turn, d, rot, delta, right, mode='full'): r_outer = d * 2.5 r_inner = d * 1.5 if x_turn > x: direction = 1 else: direction = -1 if mode == 'cut': return gdspy.Rectangle((x, y - delta), (x_turn, y + d + delta)) if (rot.phi2 - rot.phi1) * direction > 0: return gdspy.boolean( gdspy.Rectangle((x, y - delta), (x_turn - r_inner * direction, y + d + delta)), gdspy.Round((x_turn - r_inner * direction, y + r_inner + d), r_outer + delta, r_inner - delta, rot.phi1, rot.phi2, tolerance=0.01), 'or'), coordinates(x_turn, y + r_inner + d) else: return gdspy.boolean( gdspy.Rectangle((x, y - delta), (x_turn - r_inner * direction, y + d + delta)), gdspy.Round((x_turn - r_inner * direction, y - r_inner), r_outer + delta, r_inner - delta, rot.phi1, rot.phi2, tolerance=0.01), 'or'), coordinates(x_turn, y - r_inner)
def render(self, center, r_init, r_final, rect_end, outer_ground): remove=None if self.coupler_type is None: arc = gdspy.Round(center, r_init, r_final, initial_angle=self.arc_start * np.pi, final_angle=self.arc_finish * np.pi) bug = 5# to fix intersection bug with the circle rect = gdspy.Rectangle((center[0] + r_final - bug, center[1] - self.w / 2), (center[0] + rect_end + bug, center[1] + self.w / 2)) rect.rotate(self.phi * np.pi, center) result = gdspy.boolean(arc, rect, 'or') elif self.coupler_type == 'grounded': result = gdspy.Round(center, r_init, outer_ground, initial_angle=self.arc_start * np.pi, final_angle=self.arc_finish * np.pi) elif self.coupler_type == 'coupler': arc = gdspy.Round(center, r_init, r_final, initial_angle=self.arc_start * np.pi, final_angle=self.arc_finish * np.pi) rect = gdspy.Rectangle((center[0] + r_final-1, center[1] - self.w / 2),# 1 to fix rounding bug (center[0] + rect_end, center[1] + self.w / 2)) rect.rotate(self.phi * np.pi, center) self.connection = (center[0] + rect_end * np.cos(self.phi * np.pi), center[1] + rect_end * np.sin(self.phi * np.pi)) part_to_remove = gdspy.Rectangle((center[0] + r_final, center[1] - self.w - self.g/2), (center[0] + outer_ground, center[1] + self.w + self.g/2)) remove = part_to_remove.rotate(self.phi * np.pi, center) result = gdspy.boolean(arc, rect, 'or') self.result_coupler = result return { 'positive': result, 'remove': remove } return { 'positive': result, }
def draw_racedring(layer_num, center, mean_radius, w, l_ratio, gap, displ_ratio): race1 = draw_racetrack(layer_num, center, mean_radius, w, l_ratio) ring1 = gdspy.Round( (-displ_ratio * mean_radius / 2.0, mean_radius / 2.0 - w - gap) + center, mean_radius / 2.0 + w / 2.0, mean_radius / 2.0 - w / 2.0, initial_angle=0, final_angle=2.0 * numpy.pi, number_of_points=2000, max_points=199, layer=layer_num) ring2 = gdspy.Round( (displ_ratio * mean_radius / 2.0, 3.0 * mean_radius / 2.0 + w + gap) + center, mean_radius / 2.0 + w / 2.0, mean_radius / 2.0 - w / 2.0, initial_angle=0, final_angle=2.0 * numpy.pi, number_of_points=2000, max_points=199, layer=layer_num) bool = gdspy.boolean([race1, ring1], summ, max_points=199, layer=layer_num) bool = gdspy.boolean([bool, ring2], summ, max_points=199, layer=layer_num) return bool
def bendLeftZhighRes(position,cell,l_Zhigh, l_Zlow, t_Zhigh, t_Zlow): R_inner=900/2 -gap_Zhigh R=R_inner + t_Zhigh l1=350 l2=0 l_residual=(l_Zhigh- numpy.pi*(R_inner+R)/2)-l1-l2 position.y=position.y +0.5*(t_Zlow-t_Zhigh) position.x=position.x-l_res Zlow2 = gdspy.Rectangle( (position.x, position.y), (position.x-l1, position.y+t_Zhigh) ) cell.add(Zlow2) position.x=position.x-l1 center_y=position.y-R_inner center_x=position.x Zlow1=gdspy.Round( (center_x, center_y), R, inner_radius=R_inner, initial_angle=-1.0*numpy.pi, final_angle=-1.5*numpy.pi, **spec) cell.add(Zlow1) position.y= center_y position.x=position.x-R Zlow2 = gdspy.Rectangle( (position.x, position.y), (position.x+t_Zhigh, position.y-l_residual) ) cell.add(Zlow2) position.y= position.y-l_residual center_y=position.y center_x=position.x+R Zlow3=gdspy.Round( (center_x, center_y), R, inner_radius=R_inner, initial_angle=-0.5*numpy.pi, final_angle=-1.0*numpy.pi, **spec) cell.add(Zlow3) position.y= center_y-R position.x=center_x Zlow4 = gdspy.Rectangle( (position.x, position.y), (position.x+l2, position.y+t_Zhigh) ) cell.add(Zlow4) position.y= center_y-R-0.5*(t_Zlow-t_Zhigh) position.x=position.x+l2 return cell
def __init__(self, rad, rad_in=None, layer=0, datatype=0): self.spec = {'layer': layer, 'datatype': datatype} self.rad = rad if rad_in == None: self.circle = gdspy.Round((0, 0), rad, **(self.spec)) else: self.circle = gdspy.Round((0, 0), rad, inner_radius=rad_in, **(self.spec)) self.rad_in = rad_in
def ringResonator(): # Initialize cell ringCell = gdspy.Cell('Ring') # Calculate center ring coordinates ringCenterX = racetrackLength / 2 ringCenterY = -(ringWL / 2 + ringGap + waveguideWidth) / 2 # create left ring ringRight = gdspy.Round((ringCenterX, ringCenterY), ringRadius + ringWL / 2, inner_radius=ringRadius - ringWL / 2, initial_angle=np.pi / 2, final_angle=-np.pi / 2, layer=layerNumber) # create right ring ringLeft = gdspy.Round((-ringCenterX, ringCenterY), ringRadius + ringWL / 2, inner_radius=ringRadius - ringWL / 2, initial_angle=np.pi / 2, final_angle=3 * np.pi / 2, layer=layerNumber) # create top race topRaceTrack topRaceTrack = gdspy.Rectangle( [-racetrackLength / 2, ringCenterY + ringRadius - ringWL / 2], [racetrackLength / 2, ringCenterY + ringRadius + ringWL / 2], layer=layerNumber) # create bottom racetrack bottomRaceTrack = gdspy.Rectangle( [-racetrackLength / 2, ringCenterY - ringRadius - ringWL / 2], [racetrackLength / 2, ringCenterY - ringRadius + ringWL / 2], layer=layerNumber) # create top waveguide bus busLength = 2 * ringRadius + racetrackLength busCenterY = ringCenterY + ringRadius + waveguideWidth / 2 + ringGap + waveguideWidth topBus = gdspy.Rectangle([-busLength / 2, busCenterY - waveguideWidth / 2], [busLength / 2, busCenterY + waveguideWidth / 2], layer=layerNumber) # Add all geometries ringCell.add(topBus) ringCell.add(topRaceTrack) ringCell.add(bottomRaceTrack) ringCell.add(ringRight) ringCell.add(ringLeft) # return Cells return ringCell
def photonic_crystal(normal_holes, taper_holes, radius, taper_depth, spacing, cell_name, input_taper_holes, input_taper_percent, layer): """ define a parabolically tapered photonic crystal cavity. hole size and length are tapered simulataneously. a certain number of input taper holes can be defined to reduce input scattering loss. also returns the length of the photonic crystal """ min_spacing = taper_depth * spacing dist = min_spacing / 2 holes = [] # add taper holes for i in range(taper_holes): if i > 0: dist += spacing * taper_depth + i**2 * ( 1 - taper_depth) * spacing / (taper_holes**2) rad = taper_depth * radius + ((i**2) * (1 - taper_depth) * radius / (taper_holes**2)) hole_pos = gdspy.Round((dist, 0), rad, number_of_points=199, **layer) hole_neg = gdspy.Round((-dist, 0), rad, number_of_points=199, **layer) # add all holes to a list holes.append(hole_pos) holes.append(hole_neg) # add untapered holes for i in range(normal_holes): dist += spacing hole_pos = gdspy.Round((dist, 0), radius, number_of_points=199, **layer) hole_neg = gdspy.Round((-dist, 0), radius, number_of_points=199, **layer) holes.append(hole_pos) holes.append(hole_neg) # add input taper for i in range(input_taper_holes): dist += spacing rad = radius - radius * ( 1 - input_taper_percent) / input_taper_holes * (i + 1) hole_neg = gdspy.Round((-dist, 0), rad, number_of_points=199, **layer) holes.append(hole_neg) l_tot = dist * 2 return holes, l_tot
def draw_bondaries(layer_num,origin,n,N): ##PARAMETERS y_shift = -10 l_width = 20 # l_sq = 0 # protection square side [um] lin_l = 50 # linear tapped waveguide length [um] tap_w = 0 # linear tapped waveguide width [um] tap_l = 50 # tapper length [um] wv_w = 5.45 # waveguide width [um] wv_l = 300 # waveguide length [um] wv_r = 30 # waveguide bend region radius [um] wv_v = 900 # waveguide vertical region length [um] vgap = 0 # vertical gap between waveguides [um] hgap = 10 # horizontal gap between waveguides [um] #Inputs: #layer_num: layer number #origin: figure position #n waveguide number #Description: This function draws a (horizontal) waveguide of width wv_w and tapered ends with width tap_w and length tap_l plus a square of size. The waveguides have a S-shape, so that the ends are vertically separeted by wv_v #Output: bool,a gdspy object sq1 = gdspy.Rectangle(numpy.array([0,0+y_shift])+numpy.array(origin),numpy.array([lin_l,l_width+y_shift])+numpy.array(origin),layer=layer_num) trap1 = gdspy.Polygon([numpy.array([lin_l,l_width+y_shift])+numpy.array(origin),numpy.array([lin_l+tap_l,l_width/2.0 +wv_w/2.0+y_shift])+numpy.array(origin),numpy.array([lin_l+tap_l,l_width/2.0 -wv_w/2.0+y_shift])+numpy.array(origin),numpy.array([lin_l,0+y_shift])+numpy.array(origin)],layer = layer_num) rect2 = gdspy.Rectangle(numpy.array([l_sq+lin_l+tap_l,l_sq/2.0 -wv_w/2.0])+numpy.array(origin),numpy.array([l_sq+lin_l+tap_l+wv_l,l_sq/2.0 +wv_w/2.0])+numpy.array(origin)-numpy.array([hgap*(N-n),0]),layer=layer_num) ben1 = gdspy.Round(numpy.array([l_sq+lin_l+tap_l+wv_l,l_sq/2.0 +wv_r])+numpy.array(origin)-numpy.array([hgap*(N-n),0]),wv_r+wv_w/2.0,wv_r-wv_w/2.0,initial_angle=-numpy.pi/2.0, final_angle=0,number_of_points=pow(2,12)-1,max_points=pow(2,12)-1,layer=layer_num) wgver = gdspy.Rectangle(numpy.array([l_sq+lin_l+tap_l+wv_l+wv_r-wv_w/2.0,l_sq/2.0 +wv_r])+numpy.array(origin)-numpy.array([hgap*(N-n),0]),numpy.array([l_sq+lin_l+tap_l+wv_l+wv_r-wv_w/2.0+wv_w,l_sq/2.0 +wv_r+ wv_v])+numpy.array(origin)-numpy.array([hgap*(N-n),vgap*n]),layer=layer_num) ben2 = gdspy.Round(numpy.array([l_sq+lin_l+tap_l+wv_l+wv_r-wv_w/2.0+wv_w/2.0+wv_r,l_sq/2.0 +wv_r+ wv_v])+numpy.array(origin)-numpy.array([hgap*(N-n),vgap*n]),wv_r+wv_w/2.0,wv_r-wv_w/2.0,initial_angle=numpy.pi/2.0, final_angle=numpy.pi,number_of_points=pow(2,12)-1,max_points=pow(2,12)-1,layer=layer_num) rect3 = gdspy.Rectangle(numpy.array([l_sq+lin_l+tap_l+wv_l+wv_r-wv_w/2.0+wv_w/2.0+wv_r,l_sq/2.0 +wv_r+ wv_v+wv_r+wv_w/2.0])+numpy.array(origin)-numpy.array([hgap*(N-n),vgap*n]),numpy.array([l_sq+lin_l+tap_l+wv_l+wv_r-wv_w/2.0+wv_w/2.0+wv_r+wv_l,l_sq/2.0 +wv_r+ wv_v+wv_r-wv_w/2.0])+numpy.array(origin)-numpy.array([0,vgap*n]),layer=layer_num) trap2 = gdspy.Polygon([numpy.array([l_sq+lin_l+tap_l+wv_l+wv_r-wv_w/2.0+wv_w/2.0+wv_r+wv_l,l_sq/2.0 +wv_r+ wv_v+wv_r-wv_w/2.0])+numpy.array(origin)-numpy.array([0,vgap*n]),numpy.array([l_sq+lin_l+tap_l+wv_l+wv_r-wv_w/2.0+wv_w/2.0+wv_r+wv_l,l_sq/2.0 +wv_r+ wv_v+wv_r+wv_w/2.0])+numpy.array(origin)-numpy.array([0,vgap*n]),numpy.array([l_sq+lin_l+tap_l+wv_l+wv_r-wv_w/2.0+wv_w/2.0+wv_r+wv_l+tap_l,l_sq/2.0 +wv_r+ wv_v+wv_r+l_width/2.0])+numpy.array(origin)-numpy.array([0,vgap*n]),numpy.array([l_sq+lin_l+tap_l+wv_l+wv_r-wv_w/2.0+wv_w/2.0+wv_r+wv_l+tap_l,l_sq/2.0 +wv_r+ wv_v+wv_r-l_width/2.0])+numpy.array(origin)-numpy.array([0,vgap*n])],layer = layer_num) sq2 = gdspy.Rectangle(numpy.array([l_sq+lin_l+tap_l+wv_l+wv_r-wv_w/2.0+wv_w/2.0+wv_r+wv_l+tap_l,l_sq/2.0 +wv_r+ wv_v+wv_r-l_width/2.0])+numpy.array(origin)-numpy.array([0,vgap*n]),numpy.array([l_sq+lin_l+tap_l+wv_l+wv_r-wv_w/2.0+wv_w/2.0+wv_r+wv_l+tap_l+tap_l,l_sq/2.0 +wv_r+ wv_v+wv_r+l_width/2.0])+numpy.array(origin)-numpy.array([0,vgap*n]),layer=layer_num) bool = gdspy.boolean([sq1,trap1],summ,max_points=199,layer=layer_num) bool = gdspy.boolean([bool,rect2],summ,max_points=199,layer=layer_num) bool = gdspy.boolean([bool,ben1],summ,max_points=199,layer=layer_num) bool = gdspy.boolean([bool,wgver],summ,max_points=199,layer=layer_num) bool = gdspy.boolean([bool,ben2],summ,max_points=199,layer=layer_num) bool = gdspy.boolean([bool,rect3],summ,max_points=199,layer=layer_num) bool = gdspy.boolean([bool,trap2],summ,max_points=199,layer=layer_num) bool = gdspy.boolean([bool,sq2],summ,max_points=199, **ims.wgcld) return bool
def bendLeftZhighEqual(position, cell, l_Zhigh, l_Zlow, t_Zhigh, t_Zlow, R_inner): # R_inner=900/2 R = R_inner + t_Zhigh l_residual = 0.5 * (l_Zhigh - numpy.pi * (R_inner + R) / 2) position.y = position.y + 0.5 * (t_Zlow - t_Zhigh) Zlow2 = gdspy.Rectangle((position.x, position.y), (position.x - l_residual, position.y + t_Zhigh)) cell.add(Zlow2) position.x = position.x - l_residual center_y = position.y - R_inner center_x = position.x Zlow1 = gdspy.Round((center_x, center_y), R, inner_radius=R_inner, initial_angle=-0.5 * numpy.pi, final_angle=-1.5 * numpy.pi, **spec) cell.add(Zlow1) position.y = center_y - R Zlow2 = gdspy.Rectangle((position.x, position.y), (position.x + l_residual, position.y + t_Zhigh)) cell.add(Zlow2) position.y = center_y - R - 0.5 * (t_Zlow - t_Zhigh) position.x = position.x + l_residual return cell
def bendLeftZlow(position, cell, l_Zhigh, l_Zlow, t_Zhigh, t_Zlow, R_inner): # R_inner=700/2 R = R_inner + t_Zlow l_residual = l_Zlow - numpy.pi * (R_inner + R) / 2 center_y = position.y - R_inner center_x = position.x Zlow1 = gdspy.Round((center_x, center_y), R, inner_radius=R_inner, initial_angle=-0.5 * numpy.pi, final_angle=-1.5 * numpy.pi, **spec) cell.add(Zlow1) l_residual = l_Zlow - numpy.pi * (R_inner + R) / 2 position.y = center_y - R position.x = center_x Zlow2 = gdspy.Rectangle((position.x, position.y), (position.x + l_residual, position.y + t_Zlow)) cell.add(Zlow2) position.x = position.x + l_residual return cell
def test_inside(): polygons = [ gdspy.Round((0, 0), 10, inner_radius=5, number_of_points=180), gdspy.Rectangle((20, -10), (40, 10)).polygons[0], gdspy.CellReference( gdspy.Cell("X").add(gdspy.Rectangle((-10, 0), (10, 20)))), ] assert gdspy.inside([(0, 0)], polygons[0]) == (False, ) assert gdspy.inside([(0, 0)], polygons[2]) == (True, ) assert gdspy.inside([(0, 0)], polygons) == (True, ) assert gdspy.inside([(0, 0), (0, 30), (30, 0), (0, -1)], polygons) == ( True, False, True, False, ) assert gdspy.inside( [[(0, 0), (0, 30), (30, 0), (0, -1)], [(0, -1), (0, 30)], [(0, 0), (30, 0)]], polygons, "any", ) == (True, False, True) assert gdspy.inside( [[(0, 0), (0, 30), (30, 0), (0, -1)], [(0, -1), (0, 30)], [(0, 0), (30, 0)]], polygons, "all", ) == (False, False, True)
def bendLeftZhigh(position,cell,l_Zhigh, l_Zlow, t_Zhigh, t_Zlow): R_inner=900/2-gap_Zhigh R=R_inner + t_Zhigh l_residual=l_Zlow- numpy.pi*(R_inner+R)/2 position.y=position.y +0.5*(t_Zlow-t_Zhigh) center_y=position.y-R_inner center_x=position.x Zlow1=gdspy.Round( (center_x, center_y), R, inner_radius=R_inner, initial_angle=-0.5*numpy.pi, final_angle=-1.5*numpy.pi, **spec) cell.add(Zlow1) l_residual=l_Zhigh- numpy.pi*(R_inner+R)/2 position.y=center_y-R position.x=center_x Zlow2 = gdspy.Rectangle( (position.x, position.y), (position.x+l_residual, position.y+t_Zhigh) ) cell.add(Zlow2) position.x=position.x+l_residual position.y=position.y -0.5*(t_Zlow-t_Zhigh) return cell
def bendRightZlowEqual(position,cell,l_Zhigh, l_Zlow, t_Zhigh, t_Zlow): R_inner=700/2-gap_Zlow R=R_inner + t_Zlow l_residual=0.5*(l_Zlow - numpy.pi*(R_inner+R)/2) Zlow2 = gdspy.Rectangle( (position.x, position.y), (position.x+l_residual, position.y+t_Zlow) ) cell.add(Zlow2) position.x=position.x+l_residual center_y=position.y-R_inner center_x=position.x Zlow1=gdspy.Round( (center_x, center_y), R, inner_radius=R_inner, initial_angle=-2.5*numpy.pi, final_angle=-1.5*numpy.pi, **spec) cell.add(Zlow1) position.y= center_y-R Zlow2 = gdspy.Rectangle( (position.x, position.y), (position.x-l_residual, position.y+t_Zlow) ) cell.add(Zlow2) position.y= center_y-R position.x=position.x-l_residual return cell
def test_gather(): def same_points(x, y): for px, py in zip(x, y): for ptx, pty in zip(px, py): for cx, cy in zip(ptx, pty): if cx != cy: return False return True pts = [(0, 0), (1, 1), (1, 0)] ps1 = gdspy.Round((10, 10), 1, inner_radius=0.2) ps2 = gdspy.Path(0.1, (-1, -1), 2, 1).segment(2, "-x") c = gdspy.Cell("C1").add(gdspy.Rectangle((-4, 3), (-5, 4))) cr = gdspy.CellReference(c, (10, -10)) ca = gdspy.CellArray(c, 2, 1, (2, 0)) assert gdspy.operation._gather_polys(None) == [] assert same_points(gdspy.operation._gather_polys([pts]), [pts]) assert same_points(gdspy.operation._gather_polys(ps1), ps1.polygons) assert same_points(gdspy.operation._gather_polys(ps2), ps2.polygons) assert same_points(gdspy.operation._gather_polys(cr), cr.get_polygons()) assert same_points(gdspy.operation._gather_polys(ca), ca.get_polygons()) result = [pts] result.extend(ps2.polygons) result.extend(cr.get_polygons()) assert same_points(gdspy.operation._gather_polys([pts, ps2, cr]), result)
def bendRightZhigh(position, cell, l_Zhigh, l_Zlow, t_Zhigh, t_Zlow, R_inner): # R_inner=900/2 R = R_inner + t_Zhigh position.y = position.y + 0.5 * (t_Zlow - t_Zhigh) center_y = position.y - R_inner center_x = position.x Zhigh1 = gdspy.Round((center_x, center_y), R, inner_radius=R_inner, initial_angle=-2.5 * numpy.pi, final_angle=-1.5 * numpy.pi, **spec) cell.add(Zhigh1) l_residual = l_Zhigh - numpy.pi * (R_inner + R) / 2 position.y = center_y - R position.x = center_x - l_residual Zhigh2 = gdspy.Rectangle((position.x, position.y), (position.x + l_residual, position.y + t_Zhigh)) cell.add(Zhigh2) position.y = position.y - 0.5 * (t_Zlow - t_Zhigh) return cell
def __convertDXFCircle2gds(topCell, circle, layerNumber): center = circle.center[:2] disk = gdspy.Round(center, circle.radius, number_of_points=199, layer=layerNumber) topCell.add(disk)
def gc_PC_apodized(lib, filename0, D, d_goal, period_num=29, l_taper_a=500, l_grating=30, w=10, w_wg=0.5, w_etch=3): a = 0.23 w_gc = w num_y = np.floor(w / (a * np.sqrt(3))) pitch_y = a * np.sqrt(3) # pitch in the y direction # create the main body of phtonic crystal grating coupler filename = filename0 grating = lib.new_cell(filename) for ii in range(period_num): # this is for a variable period if ii == 0: x_start = -l_taper_a else: x_start += -d_goal[(ii, 0)] # create the cell for reference D_temp = D[(ii, 0)] name_cell = "D" + str(int(D_temp * 1e3)) if name_cell not in lib.cells: circles = lib.new_cell(name_cell) circle = gdspy.Round((0, 0), D_temp / 2, number_of_points=128, **ld_grating) circles.add(circle) else: Cell_all = lib.cells circles = Cell_all[name_cell] # create the 3 column of hole for x_index in range(3): num_y = np.floor(w / pitch_y) if x_index == 1: num_y = num_y + 1 for y_index in range(int(num_y)): grating.add( gdspy.CellReference( circles, (x_start + x_index * a / 2, -(num_y - 1) * pitch_y / 2 + pitch_y * y_index))) # create the etche region of phtonic crystal grating coupler points = [(0, w_wg / 2), (-l_taper_a, w_gc / 2), (-l_taper_a - l_grating, w_gc / 2), (-l_taper_a - l_grating, w_gc / 2 + w_etch), (-l_taper_a, w_gc / 2 + w_etch), (0, w_wg / 2 + w_etch)] poly = gdspy.Polygon(points, **ld_fulletch) grating.add(poly) poly = gdspy.Polygon(points, **ld_fulletch).mirror((0, 0), (1, 0)) grating.add(poly) return grating
def gc_focusing(cell, pa, xp=22, theta=25): # xp is the length of taper GC_theta = (theta + 3) / 180 * np.pi GC_theta2 = theta / 180 * np.pi i = 0 while i < len(pa): a = float(pa[i]) b = float(pa[i + 1]) arc = gdspy.Round((0, 0), xp + a, inner_radius=xp, initial_angle=-GC_theta + np.pi, final_angle=GC_theta + np.pi, number_of_points=300, **ld_grating) cell.add(arc) pitch = a + b xp += pitch i += 2 GC_theta = GC_theta2 points = [(0, w_wg / 2), (-xp * np.cos(GC_theta), xp * np.sin(GC_theta)), (-xp * np.cos(GC_theta), xp * np.sin(GC_theta) + w_etch), (0, w_wg / 2 + w_etch)] poly = gdspy.Polygon(points, **ld_fulletch) cell.add(poly) poly = gdspy.Polygon(points, **ld_fulletch).mirror((0, 0), (1, 0)) cell.add(poly)
def nicrheat(layer_num, center, radius, hw, hh, ang, sqr): pos1 = (center[0] - radius * sin(ang), center[1] - radius * cos(ang)) pos2 = (center[0] + radius * sin(ang), center[1] - radius * cos(ang)) nch1 = gdspy.Round(center, radius + hw / 2, radius - hw / 2, initial_angle=-ang - pi / 2.0, final_angle=ang - pi / 2.0, layer=layer_num, max_points=4094, number_of_points=0.1) nch2 = gdspy.Rectangle((pos1[0] + hw, pos1[1]), (pos1[0], pos1[1] - hh), layer=layer_num) nch3 = gdspy.Rectangle((pos2[0], pos2[1]), (pos2[0], pos2[1] - hh), layer=layer_num) nch4 = gdspy.Rectangle( (pos1[0] + hw / 2.0 + sqr / 2.0, pos1[1] - hh), (pos1[0] + hw / 2.0 - sqr / 2.0, pos1[1] - hh - sqr), layer=layer_num) nch5 = gdspy.Rectangle( (pos2[0] + hw / 2.0 + sqr / 2.0, pos2[1] - hh), (pos2[0] + hw / 2.0 - sqr / 2.0, pos2[1] - hh - sqr), layer=layer_num) bool = gdspy.boolean([nch1, nch2], sum, max_points=199, layer=layer_num) bool = gdspy.boolean([bool, nch3], sum, max_points=199, layer=layer_num) bool = gdspy.boolean([bool, nch4], sum, max_points=199, layer=layer_num) bool = gdspy.boolean([bool, nch5], sum, max_points=199, layer=layer_num) return bool
def circle(r, resolution=100, layer=0): circle = gd.Round((0, 0), r, number_of_points=resolution, layer=layer) ends = {'CENTER': (0, 0), 'BOTTOM': (0, -r)} epsz = {'CENTER': r, 'BOTTOM': None} return gtools.classes.GDStructure(circle, ends, epsz)
def Waveguide(self, x1, y1, length, d_given): # , x_e, y_e): delta = (d_given - self.d) / 2 r_outer = self.r_outer r_inner = (self.d1 * 1.7 - self.d) / 2 # Difference between the two should be self.d r = 0.5 * (r_outer + r_inner) width = self.width l_reserved = self.l_vert + self.l_coupl + 0.5 * np.pi * r + np.pi * r # 0.5 pi for the quarter circle to the vertical piece N = floor((self.length - l_reserved) / (np.pi * r + width)) # number of curves l_horiz = self.length - l_reserved - (np.pi * r + width) * (N) if l_horiz > width: self.l_vert += l_horiz - width l_horiz = width rect = gdspy.Rectangle((x1 + r_outer, y1 - delta), (x1 + r_outer + self.l_coupl + delta / 2.5, y1 + self.d + delta)) sector = gdspy.Round((x1 + r_outer, y1 + r_outer), r_outer + delta, r_inner - delta, initial_angle=0.5 * np.pi, final_angle=1.5 * np.pi, tolerance=0.01) result = gdspy.boolean(rect, sector, 'or') for i in range(N): rect = gdspy.Rectangle((x1 + r_outer, y1 + (r_outer + r_inner) * (i + 1) - delta), (x1 + r_outer + width, y1 + (r_outer + r_inner) * (i + 1) + self.d + delta)) xr = x1 + width + r_outer if i % 2 == 0 else x1 + r_outer yr = y1 + r_outer * 2 + (2 * r_inner + self.d) * i + r_inner sector = gdspy.Round((xr, yr), r_outer + delta, r_inner - delta, initial_angle=1.5 * np.pi if i % 2 == 0 else 0.5 * np.pi, final_angle=2.5 * np.pi if i % 2 == 0 else 1.5 * np.pi, tolerance=0.01) result = gdspy.boolean(result, gdspy.boolean(sector, rect, 'or'), 'or') i = N - 1 xr1 = x1 + r_outer if i % 2 == 1 else x1 + width + r_outer xr2 = x1 + r_outer + l_horiz if i % 2 == 1 else x1 + width + r_outer - l_horiz rect = gdspy.Rectangle((xr1, y1 + (r_outer + r_inner) * (N + 1) - delta), (xr2, y1 + (r_outer + r_inner) * (N + 1) + self.d + delta)) xr = xr2 yr = y1 + r_outer * 2 + (2 * r_inner + self.d) * N + r_inner # print(l_horiz, xr1, xr2, xr, yr) sector = gdspy.Round((xr, yr), r_outer + delta, r_inner - delta, initial_angle=1.5 * np.pi if i % 2 == 1 else np.pi, final_angle=2 * np.pi if i % 2 == 1 else 1.5 * np.pi, tolerance=0.01) result = gdspy.boolean(result, gdspy.boolean(sector, rect, 'or'), 'or') xr1 = xr + r_inner - delta if i % 2 == 1 else xr - r_inner + delta xr2 = xr + r_outer + delta if i % 2 == 1 else xr - r_outer - delta rect = gdspy.Rectangle((xr1, yr), (xr2, yr + self.l_vert)) result = gdspy.boolean(result, rect, 'or') if delta == 0: result = gdspy.boolean(result, gdspy.Rectangle((x1 + r_outer + self.l_coupl, y1), ( x1 + r_outer + self.l_coupl + (self.d1 - self.d) / 5, y1 + self.d)), 'or') # this defines the resonator end closest to the TL return result, (xr2 - xr1) * 0.5 + xr1, yr + self.l_vert
def gc_PC_uniform(lib, filename0 ="UGC", a=0.23, D=0.150, d=0.665, period_num=29, w_gc=12, l_taper_a=500, l_grating=30, w_wg=0.5, w_etch=3 ): """ a is the length of the lattice \n D is the diameter of the hole \n d is the peorid of the gratings. """ # create the main body of phtonic crystal grating coupler d_all = np.ones(period_num)*d D_all = np.ones(period_num)*D # name the cell that include the grating filename = filename0 + "_a"+str(int(a*1e3)) +"_D"+str(int(D*1e3)) +"_d"+str(np.around(d*1e3,0).astype(int)) +"_wg"+ str(int(w_wg*1000)) grating = lib.new_cell(filename) num_y = np.floor(w_gc/(a*np.sqrt(3))) pitch_y = a*np.sqrt(3) # pitch in the y direction for ii in range(period_num): # this is for a variable period if ii == 0: x_start = -l_taper_a - 6 else: x_start += -d_all[ii] # create the cell for reference D_temp = D_all[ii] name_cell = "D"+str(int(D_temp*1e3)) if name_cell not in lib.cells: circles = lib.new_cell(name_cell) circle = gdspy.Round((0, 0), D_temp/2, number_of_points=128, **ld_grating) circles.add(circle) else: Cell_all = lib.cells circles = Cell_all[name_cell] # create the 3 column of hole for x_index in range(3): num_y = np.floor(w_gc/(a*np.sqrt(3))) if x_index == 1: num_y = num_y + 1 for y_index in range(int(num_y)): grating.add(gdspy.CellReference(circles, (x_start + x_index*a/2, -(num_y -1)*pitch_y/2+pitch_y*y_index))) # create the etche region of phtonic crystal grating coupler points = [(0, w_wg/2), (-l_taper_a, w_gc/2), (-l_taper_a-l_grating, w_gc/2), (-l_taper_a-l_grating, w_gc/2+w_etch), (-l_taper_a, w_gc/2+w_etch), (0, w_wg/2+w_etch)] poly = gdspy.Polygon(points, **ld_fulletch) grating.add(poly) poly = gdspy.Polygon(points, **ld_fulletch).mirror((0, 0), (1, 0)) grating.add(poly) isTaper_b = 0 if isTaper_b == 1: l_taper_b = 100 points = [(l_taper_a+l_grating, w_gc/2), (l_taper_a+l_grating+l_taper_b, 0.05), (l_taper_a+l_grating+l_taper_b, 0.05+w_etch), (l_taper_a+l_grating, w_gc/2+w_etch)] poly = gdspy.Polygon(points, **ld_fulletch) grating.add(poly) poly = gdspy.Polygon(points, **ld_fulletch).mirror((0, 0), (1, 0)) grating.add(poly) return grating
def generate_JJ(): root_width = 5 root_height = 15 tip_width = 2 tip_height = 4 taper_height=15 cross_dist = 5 cross_len = 8 cross_width = 0.2 uc_shift = 1 uc_tip_height = 2.5 base_layer = 30 uc_layer = 40 # base pattern base_path = gdspy.Path(root_width, (0, 0)) base_path.segment(root_height, '+y', layer=base_layer) base_path.segment(taper_height, '+y', final_width=tip_width, layer=base_layer) base_path.segment(tip_height, '+y', layer=base_layer) tip_cir = gdspy.Round((0, root_height+taper_height+tip_height), tip_width/2, initial_angle=0, final_angle=np.pi, layer=base_layer) JJ_base1 = gdspy.boolean(base_path, tip_cir, 'or', max_points=0, layer=base_layer) JJ_base2 = gdspy.copy(JJ_base1).rotate(np.pi, (0, root_height+taper_height+tip_height)).translate(cross_dist, cross_dist) JJ_base = gdspy.boolean(JJ_base1, JJ_base2, 'or', max_points=0, layer=base_layer) JJ_cross1 = gdspy.Path(cross_width, (0, root_height+taper_height+tip_height)) JJ_cross1.segment(cross_len, '+x', layer=base_layer) JJ_cross2 = gdspy.Path(cross_width, initial_point=(cross_dist, root_height+taper_height+tip_height+cross_dist)) JJ_cross2.segment(cross_len, '-y', layer=base_layer) JJ_cross = gdspy.boolean(JJ_cross1, JJ_cross2, 'or', max_points=0, layer=base_layer) JJ_total = gdspy.boolean(JJ_base, JJ_cross, 'or', max_points=0, layer=base_layer) # under cut uc_path = gdspy.Path(root_width+2*uc_shift, (0, -uc_shift)) uc_path.segment(root_height+uc_shift, '+y', layer=uc_layer) uc_path.segment(taper_height, '+y', final_width=tip_width+2*uc_shift, layer=uc_layer) uc_path.segment(tip_height+tip_width/2+uc_shift, '+y', layer=uc_layer) uc_base1 = uc_path uc_base2 = gdspy.copy(uc_base1).rotate(np.pi, (0, root_height+taper_height+tip_height)).translate(cross_dist, cross_dist) uc_base = gdspy.boolean(uc_base1, uc_base2, 'or', max_points=0, layer=uc_layer) uc_tip1 = gdspy.Path(uc_shift, (cross_len - uc_tip_height/2, root_height+taper_height+tip_height)) uc_tip1.segment(uc_tip_height, '+x', layer=uc_layer) uc_tip2 = gdspy.Path(uc_shift, (cross_dist, root_height+taper_height+tip_height+cross_dist-cross_len+uc_tip_height/2)) uc_tip2.segment(uc_tip_height, '-y', layer=uc_layer) uc_tip = gdspy.boolean(uc_tip1, uc_tip2, 'or', max_points=0, layer=uc_layer) uc = gdspy.boolean(uc_base, uc_tip, 'or', max_points=0, layer=uc_layer) dx = -cross_dist/2 dy = -(root_height+taper_height+tip_height+cross_dist/2) return [JJ_total.translate(dx, dy), uc.translate(dx, dy)]
def generate_coupler(self,coordinate,r_init,r_final,rect_end): #to fix bug bug=5 result = gdspy.Round(coordinate, r_init, r_final, initial_angle=(self.arc_start) * np.pi, final_angle=(self.arc_finish) * np.pi) rect = gdspy.Rectangle((coordinate[0]+r_final-bug,coordinate[1]-self.w/2),(coordinate[0]+rect_end+bug, coordinate[1]+self.w/2)) rect.rotate(self.phi*np.pi, coordinate) return gdspy.boolean(result,rect, 'or')
def nicrheat2(layer_num,center,radius,hw,ang): pos1 = (center[0]-radius*sin(ang),center[1]-radius*cos(ang)) pos2 = (center[0]+radius*sin(ang),center[1]-radius*cos(ang)) nch1=gdspy.Round(center,radius+hw/2,radius-hw/2,initial_angle=-ang-pi/2.0, final_angle=ang-pi/2.0,layer=layer_num,max_points=4094,number_of_points=0.1) return nch1
def disk(self, pos, radius, axis, number_of_points=None, **kwargs): pos, radius = parse_entry(pos, radius) name = kwargs['name'] layer = kwargs['layer'] assert axis=='Z', "axis must be 'Z' for the gdsModeler" round1 = gdspy.Round((pos[0],pos[1]), radius, layer=layer, tolerance=TOLERANCE, number_of_points=number_of_points) self.gds_object_instances[name] = round1 self.cell.add(round1)