def __init__(self, wgt, poles, start_width=None, end_width=None): tk.Component.__init__(self, "BBend", locals()) self.portlist = {} self.port = (0, 0) if start_width != None: self.start_width = start_width else: self.start_width = wgt.wg_width if end_width != None: self.end_width = end_width else: self.end_width = wgt.wg_width self.input_port = (poles[0][0], poles[0][1]) self.output_port = (poles[-1][0], poles[-1][1]) self.poles = poles self.input_direction = tk.get_exact_angle(poles[1], poles[0]) self.output_direction = tk.get_exact_angle(poles[-2], poles[-1]) self.wgt = wgt self.wg_spec = {"layer": wgt.wg_layer, "datatype": wgt.wg_datatype} self.clad_spec = {"layer": wgt.clad_layer, "datatype": wgt.clad_datatype} self.__build_cell() self.__build_ports() """ Translate & rotate the ports corresponding to this specific component object
def build_ports(self): # Portlist format: # example: example: {'port':(x_position, y_position), 'direction': 'NORTH'} self.portlist["input"] = { 'port': (self.trace[0][0], self.trace[0][1]), 'direction': tk.get_exact_angle(self.trace[1], self.trace[0]) } self.portlist["output"] = { 'port': (self.trace[-1][0], self.trace[-1][1]), 'direction': tk.get_exact_angle(self.trace[-2], self.trace[-1]) }
def build_cell(self): # Sequentially build all the geometric shapes using gdspy path functions # for waveguide, then add it to the Cell angle = tk.get_exact_angle(self.trace[0], self.trace[1]) angle_opp = tk.get_exact_angle(self.trace[1], self.trace[0]) # Add strip waveguide taper path_strip = gdspy.Path(self.wgt_strip.wg_width, self.trace[0]) path_strip.segment(self.length, final_width=self.end_strip_width, direction=angle, **self.wg_spec) # Add slot waveguide taper path_slot = gdspy.Path(self.wgt_slot.rail, self.trace[1], number_of_paths=2, distance=self.wgt_slot.rail_dist) path_slot.segment(self.length, final_width=self.end_slot_width, final_distance=(self.wgt_strip.wg_width + 2 * self.d + self.end_slot_width), direction=angle_opp, **self.wg_spec) # Cladding for waveguide taper path_clad = gdspy.Path( 2 * self.wgt_strip.clad_width + self.wgt_strip.wg_width, self.trace[0]) path_clad.segment(self.length, final_width=2 * self.wgt_slot.clad_width + self.wgt_slot.wg_width, direction=angle, **self.clad_spec) if not self.input_strip: center_pt = ((self.trace[0][0] + self.trace[1][0]) / 2.0, (self.trace[0][1] + self.trace[1][1]) / 2.0) path_strip.rotate(np.pi, center_pt) path_slot.rotate(np.pi, center_pt) path_clad.rotate(np.pi, center_pt) self.add(path_strip) self.add(path_slot) self.add(path_clad)
def build_cell(self): # Sequentially build all the geometric shapes using gdspy path functions # for waveguide, then add it to the Cell angle = tk.get_exact_angle(self.trace[0], self.trace[1]) # Add MMI region path_mmi = gdspy.Path(self.w_mmi, self.trace[0]) path_mmi.segment(self.l_mmi, direction=angle, **self.wg_spec) print("path_mmi_coords = "+str((path_mmi.x, path_mmi.y))) # Add slot tapered region path_taper = gdspy.Path((self.w_mmi - self.wgt_slot.slot)/2.0, initial_point=(path_mmi.x, path_mmi.y), number_of_paths=2, distance=(self.w_mmi + self.wgt_slot.slot)/2.0) path_taper.segment(self.length - self.l_mmi, final_width = self.wgt_slot.rail, final_distance = self.wgt_slot.rail_dist, direction=angle, **self.wg_spec) # Cladding for waveguide taper path_clad = gdspy.Path(2*self.wgt_strip.clad_width+self.wgt_strip.wg_width, self.trace[0]) path_clad.segment(self.length, final_width=2*self.wgt_slot.clad_width+self.wgt_slot.wg_width, direction=angle, **self.clad_spec) if not self.input_strip: center_pt = ((self.trace[0][0]+self.trace[1][0])/2.0, (self.trace[0][1]+self.trace[1][1])/2.0) path_mmi.rotate(np.pi, center_pt) path_taper.rotate(np.pi, center_pt) path_clad.rotate(np.pi, center_pt) self.add(path_mmi) self.add(path_taper) self.add(path_clad)
def build_cell(self): # Sequentially build all the geometric shapes using gdspy path functions # for waveguide, then add it to the Cell br = self.wgt.bend_radius if len(self.trace) == 2: if self.wgt.wg_type == 'strip': path = gdspy.Path(self.wgt.wg_width, self.trace[0]) path.segment(tk.dist(self.trace[0], self.trace[1]), direction=tk.get_exact_angle( self.trace[0], self.trace[1]), **self.wg_spec) elif self.wgt.wg_type == 'slot': path = gdspy.Path(self.wgt.rail, self.trace[0], number_of_paths=2, distance=self.wgt.rail_dist) path.segment(tk.dist(self.trace[0], self.trace[1]), direction=tk.get_exact_angle( self.trace[0], self.trace[1]), **self.wg_spec) path2 = gdspy.Path(self.wgt.wg_width + 2 * self.wgt.clad_width, self.trace[0]) path2.segment(tk.dist(self.trace[0], self.trace[1]), direction=tk.get_exact_angle(self.trace[0], self.trace[1]), **self.clad_spec) else: if self.wgt.wg_type == 'strip': path = gdspy.Path(self.wgt.wg_width, self.trace[0]) elif self.wgt.wg_type == 'slot': path = gdspy.Path(self.wgt.rail, self.trace[0], number_of_paths=2, distance=self.wgt.rail_dist) path2 = gdspy.Path(self.wgt.wg_width + 2 * self.wgt.clad_width, self.trace[0]) prev_dl = 0.0 for i in range(len(self.trace) - 2): start_angle = tk.get_exact_angle(self.trace[i], self.trace[i + 1]) next_angle = tk.get_exact_angle(self.trace[i + 1], self.trace[i + 2]) #dl is the amount of distance that is taken *off* the waveguide from the curved section dl = abs(br * np.tan((next_angle - start_angle) / 2.0)) if (dl + prev_dl) > tk.dist(self.trace[i], self.trace[i + 1]): raise ValueError("Warning! The waypoints " + str(self.trace[i]) + " and " + str(self.trace[i + 1]) + " are too close to accommodate " " the necessary bend-radius of " + str(br) + ", the points were closer than " + str(dl + prev_dl)) path.segment(tk.dist(self.trace[i], self.trace[i + 1]) - dl - prev_dl, direction=start_angle, **self.wg_spec) path2.segment(tk.dist(self.trace[i], self.trace[i + 1]) - dl - prev_dl, direction=start_angle, **self.clad_spec) # The following makes sure the turn-by angle is *always* between -pi and +pi turnby = (next_angle - start_angle) % (2 * np.pi) turnby = turnby - 2 * np.pi if turnby > np.pi else turnby path.turn(br, turnby, number_of_points=0.1, **self.wg_spec) path2.turn(br, turnby, number_of_points=0.1, **self.clad_spec) prev_dl = dl path.segment(tk.dist(self.trace[-2], self.trace[-1]) - prev_dl, direction=next_angle, **self.wg_spec) path2.segment(tk.dist(self.trace[-2], self.trace[-1]) - prev_dl, direction=next_angle, **self.clad_spec) self.add(path) self.add(path2)
def build_cell(self): # Sequentially build all the geometric shapes using gdspy path functions # for waveguide, then add it to the Cell br = self.wgt.bend_radius # add waveguide if self.wgt.wg_type == 'swg': # SWG waveguides consist of both straight segments and bends that are built individually segments = [[None, None] for i in range(len(self.trace) - 1) ] # list of endpoints for all straight segments bends = [ [None, None, None] for i in range(len(self.trace) - 2) ] # list of arc-centers, start angular positions, and end angular positions for all bends prev_dl = 0.0 for i in range(len(self.trace)): if i == 0: segments[i][0] = self.trace[ i] # if first point in trace, just add as start point of first segment elif i == len(self.trace) - 1: segments[i - 1][1] = self.trace[ i] # if last point in trace, just add as end point of last segment else: start_angle = tk.get_exact_angle(self.trace[i - 1], self.trace[i]) next_angle = tk.get_exact_angle(self.trace[i], self.trace[i + 1]) angle_change = tk.normalize_angle(next_angle - start_angle) #dl is the amount of distance that is taken *off* the waveguide from the curved section dl = abs(br * np.tan(angle_change / 2.0)) if (dl + prev_dl) > tk.dist(self.trace[i - 1], self.trace[i]) + 1E-6: raise ValueError("Warning! The waypoints " + str(self.trace[i - 1]) + " and " + str(self.trace[i]) + " are too close to accommodate " " the necessary bend-radius of " + str(br) + ", the points were closer than " + str(dl + prev_dl)) # assign start and end points for segments around this trace point segments[i - 1][1] = tk.translate_point( self.trace[i], dl, start_angle + np.pi) segments[i][0] = tk.translate_point( self.trace[i], dl, next_angle) # calculate arc-center for the bend chord_angle = tk.get_exact_angle(segments[i - 1][1], segments[i][0]) bisect_len = abs(br / np.cos(angle_change / 2.0)) if angle_change > 0: bends[i - 1][0] = tk.translate_point( self.trace[i], bisect_len, chord_angle + np.pi / 2) else: bends[i - 1][0] = tk.translate_point( self.trace[i], bisect_len, chord_angle - np.pi / 2) # calculate start and end angular positions for the bend if angle_change > 0: bends[i - 1][1] = tk.normalize_angle(start_angle - np.pi / 2) bends[i - 1][2] = tk.normalize_angle(next_angle - np.pi / 2) else: bends[i - 1][1] = tk.normalize_angle(start_angle + np.pi / 2) bends[i - 1][2] = tk.normalize_angle(next_angle + np.pi / 2) prev_dl = dl # need to account for partial periods in the following segment and bend building # so need to do them interleaving remaining_period = 0.0 for i in range(len(segments)): # add straight segment segment = segments[i] direction = tk.get_exact_angle(segment[0], segment[1]) direction_deg = direction / np.pi * 180 total_dist = tk.dist(segment[0], segment[1]) curr_point = segment[0] if total_dist > remaining_period: # if the total distance will complete the remaining period from before # finish any partial period leftover from previous segment/bend if remaining_period > self.wgt.period * ( 1 - self.wgt.duty_cycle): first_path = gdspy.Path(self.wgt.wg_width, initial_point=curr_point) first_path.segment(remaining_period - self.wgt.period * (1 - self.wgt.duty_cycle), direction=direction, **self.wg_spec) self.add(first_path) # add in all whole periods in remaining length curr_point = tk.translate_point(curr_point, remaining_period, direction) remaining_length = total_dist - remaining_period num_periods = int(remaining_length // self.wgt.period) for j in range(num_periods): self.add( gdspy.CellReference(self.wgt.straight_period_cell, origin=curr_point, rotation=direction_deg)) curr_point = tk.translate_point( curr_point, self.wgt.period, direction) # finish any partial period at end of this segment if tk.dist(curr_point, segment[1] ) < self.wgt.period * self.wgt.duty_cycle: last_path = gdspy.Path(self.wgt.wg_width, initial_point=curr_point) last_path.segment(tk.dist(curr_point, segment[1]), direction=direction, **self.wg_spec) self.add(last_path) else: self.add( gdspy.CellReference(self.wgt.straight_period_cell, origin=curr_point, rotation=direction_deg)) remaining_period = self.wgt.period - tk.dist( curr_point, segment[1]) else: # if total distance did not complete the remaining period from before if remaining_period > self.wgt.period * ( 1 - self.wgt.duty_cycle): if total_dist > remaining_period - self.wgt.period * ( 1 - self.wgt.duty_cycle): first_path = gdspy.Path(self.wgt.wg_width, initial_point=curr_point) first_path.segment(remaining_period - self.wgt.period * (1 - self.wgt.duty_cycle), direction=direction, **self.wg_spec) self.add(first_path) elif total_dist > 0: first_path = gdspy.Path(self.wgt.wg_width, initial_point=curr_point) first_path.segment(total_dist, direction=direction, **self.wg_spec) self.add(first_path) remaining_period = remaining_period - total_dist # add bend if i != len(bends): bend = bends[i] angle_change = tk.normalize_angle(bend[2] - bend[1]) angular_period = self.wgt.period / br curr_angle = bend[1] remaining_angle = remaining_period / br if abs( angle_change ) > remaining_angle: # if the angle change will complete the remaining period from before # finish any partial period leftover from previous segment/bend if angle_change > 0: if remaining_angle > angular_period * ( 1 - self.wgt.duty_cycle): first_path = gdspy.Path( self.wgt.wg_width, initial_point=tk.translate_point( bend[0], br, curr_angle)) first_path.arc( br, curr_angle, curr_angle + remaining_angle - angular_period * (1 - self.wgt.duty_cycle), **self.wg_spec) self.add(first_path) curr_angle += remaining_angle else: if remaining_angle > angular_period * ( 1 - self.wgt.duty_cycle): first_path = gdspy.Path( self.wgt.wg_width, initial_point=tk.translate_point( bend[0], br, curr_angle)) first_path.arc( br, curr_angle, curr_angle - (remaining_angle - angular_period * (1 - self.wgt.duty_cycle)), **self.wg_spec) self.add(first_path) curr_angle -= remaining_angle # add in all whole periods in remaining angle num_periods = int( br * (abs(angle_change) - remaining_angle) // self.wgt.period) if angle_change > 0: for j in range(num_periods): self.add( gdspy.CellReference( self.wgt.bend_period_cell, origin=bend[0], rotation=curr_angle / np.pi * 180)) curr_angle += angular_period # finish any partial period at end of this bend if abs(tk.normalize_angle(bend[2] - curr_angle) ) < angular_period * self.wgt.duty_cycle: last_path = gdspy.Path( self.wgt.wg_width, initial_point=tk.translate_point( bend[0], br, curr_angle)) last_path.arc(br, curr_angle, bend[2], **self.wg_spec) self.add(last_path) else: self.add( gdspy.CellReference( self.wgt.bend_period_cell, origin=bend[0], rotation=curr_angle / np.pi * 180)) else: for j in range(num_periods): self.add( gdspy.CellReference( self.wgt.bend_period_cell, origin=bend[0], rotation=curr_angle / np.pi * 180, x_reflection=True)) curr_angle -= angular_period # finish any partial period at end of this bend if abs(tk.normalize_angle(bend[2] - curr_angle) ) < angular_period * self.wgt.duty_cycle: last_path = gdspy.Path( self.wgt.wg_width, initial_point=tk.translate_point( bend[0], br, bend[2])) last_path.arc( br, bend[2], bend[2] + abs( tk.normalize_angle(bend[2] - curr_angle)), **self.wg_spec) self.add(last_path) else: self.add( gdspy.CellReference( self.wgt.bend_period_cell, origin=bend[0], rotation=curr_angle / np.pi * 180, x_reflection=True)) remaining_period = self.wgt.period - br * abs( tk.normalize_angle(bend[2] - curr_angle)) else: # if the angle change did not complete the remaining period from before if remaining_angle > angular_period * ( 1 - self.wgt.duty_cycle): if abs(angle_change ) > remaining_angle - angular_period * ( 1 - self.wgt.duty_cycle): if angle_change > 0: first_path = gdspy.Path( self.wgt.wg_width, initial_point=tk.translate_point( bend[0], br, curr_angle)) first_path.arc( br, curr_angle, curr_angle + remaining_angle - angular_period * (1 - self.wgt.duty_cycle), **self.wg_spec) self.add(first_path) else: first_path = gdspy.Path( self.wgt.wg_width, initial_point=tk.translate_point( bend[0], br, curr_angle)) first_path.arc( br, curr_angle, curr_angle - (remaining_angle - angular_period * (1 - self.wgt.duty_cycle)), **self.wg_spec) self.add(first_path) else: if angle_change > 0: first_path = gdspy.Path( self.wgt.wg_width, initial_point=tk.translate_point( bend[0], br, curr_angle)) first_path.arc(br, curr_angle, curr_angle + angle_change, **self.wg_spec) self.add(first_path) else: first_path = gdspy.Path( self.wgt.wg_width, initial_point=tk.translate_point( bend[0], br, curr_angle + angle_change)) first_path.arc(br, curr_angle + angle_change, curr_angle, **self.wg_spec) self.add(first_path) remaining_period = remaining_period - br * abs( angle_change) else: # Strip and slot waveguide generation below if len(self.trace) == 2: if self.wgt.wg_type == 'strip': path = gdspy.Path(self.wgt.wg_width, self.trace[0]) path.segment(tk.dist(self.trace[0], self.trace[1]), direction=tk.get_exact_angle( self.trace[0], self.trace[1]), **self.wg_spec) elif self.wgt.wg_type == 'slot': path = gdspy.Path(self.wgt.rail, self.trace[0], number_of_paths=2, distance=self.wgt.rail_dist) path.segment(tk.dist(self.trace[0], self.trace[1]), direction=tk.get_exact_angle( self.trace[0], self.trace[1]), **self.wg_spec) else: if self.wgt.wg_type == 'strip': path = gdspy.Path(self.wgt.wg_width, self.trace[0]) elif self.wgt.wg_type == 'slot': path = gdspy.Path(self.wgt.rail, self.trace[0], number_of_paths=2, distance=self.wgt.rail_dist) prev_dl = 0.0 for i in range(len(self.trace) - 2): start_angle = tk.get_exact_angle(self.trace[i], self.trace[i + 1]) next_angle = tk.get_exact_angle(self.trace[i + 1], self.trace[i + 2]) #dl is the amount of distance that is taken *off* the waveguide from the curved section dl = abs(br * np.tan((next_angle - start_angle) / 2.0)) if (dl + prev_dl) > tk.dist(self.trace[i], self.trace[i + 1]) + 1E-6: raise ValueError("Warning! The waypoints " + str(self.trace[i]) + " and " + str(self.trace[i + 1]) + " are too close to accommodate " " the necessary bend-radius of " + str(br) + ", the points were closer than " + str(dl + prev_dl)) path.segment(tk.dist(self.trace[i], self.trace[i + 1]) - dl - prev_dl, direction=start_angle, **self.wg_spec) # The following makes sure the turn-by angle is *always* between -pi and +pi turnby = tk.normalize_angle(next_angle - start_angle) path.turn(br, turnby, number_of_points=0.1, **self.wg_spec) prev_dl = dl path.segment(tk.dist(self.trace[-2], self.trace[-1]) - prev_dl, direction=next_angle, **self.wg_spec) self.add(path) # add cladding if len(self.trace) == 2: path2 = gdspy.Path(self.wgt.wg_width + 2 * self.wgt.clad_width, self.trace[0]) path2.segment(tk.dist(self.trace[0], self.trace[1]), direction=tk.get_exact_angle(self.trace[0], self.trace[1]), **self.clad_spec) else: path2 = gdspy.Path(self.wgt.wg_width + 2 * self.wgt.clad_width, self.trace[0]) prev_dl = 0.0 for i in range(len(self.trace) - 2): start_angle = tk.get_exact_angle(self.trace[i], self.trace[i + 1]) next_angle = tk.get_exact_angle(self.trace[i + 1], self.trace[i + 2]) #dl is the amount of distance that is taken *off* the waveguide from the curved section dl = abs(br * np.tan((next_angle - start_angle) / 2.0)) if (dl + prev_dl) > tk.dist(self.trace[i], self.trace[i + 1]) + 1E-6: raise ValueError("Warning! The waypoints " + str(self.trace[i]) + " and " + str(self.trace[i + 1]) + " are too close to accommodate " " the necessary bend-radius of " + str(br) + ", the points were closer than " + str(dl + prev_dl)) path2.segment(tk.dist(self.trace[i], self.trace[i + 1]) - dl - prev_dl, direction=start_angle, **self.clad_spec) turnby = tk.normalize_angle(next_angle - start_angle) path2.turn(br, turnby, number_of_points=0.1, **self.clad_spec) prev_dl = dl path2.segment(tk.dist(self.trace[-2], self.trace[-1]) - prev_dl, direction=next_angle, **self.clad_spec) self.add(path2)
def build_cell(self): # Sequentially build all the geometric shapes using gdspy path functions # for waveguide, then add it to the Cell angle = tk.get_exact_angle(self.trace[0], self.trace[1]) # Add waveguide tapers leading to DBR region taper = gdspy.Path(self.wgt.wg_width, self.trace[0]) taper.segment(self.taper_length, direction=angle, final_width=self.w_phc, **self.wg_spec) taper.segment(self.length, **self.wg_spec) taper.segment(self.taper_length, final_width=self.wgt.wg_width, **self.wg_spec) # Cladding for DBR region clad = gdspy.Path(2 * self.wgt.clad_width + self.wgt.wg_width, self.trace[0]) clad.segment(tk.dist(self.trace[0], self.trace[1]), direction=angle, **self.clad_spec) self.add(taper) self.add(clad) """ Now add the periodic PhC components """ num_blocks = (2 * self.taper_length + self.length) // self.period blockx = self.period * self.dc startx = self.trace[0][0] + self.taper_length + self.length / 2.0 - ( num_blocks - 1) * self.period / 2.0 - blockx / 2.0 y0 = self.trace[0][1] block_list = [] for i in range(int(num_blocks)): x = startx + i * self.period block_list.append( gdspy.Rectangle((x, y0 - self.wgt.wg_width / 2.0), (x + blockx, y0 + self.wgt.wg_width / 2.0), **self.wg_spec)) """ And add the 'fins' if self.fins==True """ if self.fins: num_fins = self.wgt.wg_width // (2 * self.fin_size[1]) x0, y0 = self.trace[0][0], self.trace[0][1] - num_fins * ( 2 * self.fin_size[1]) / 2.0 + self.fin_size[1] / 2.0 xend = self.trace[0][0] + 2 * self.taper_length + self.length for i in range(int(num_fins)): y = y0 + i * 2 * self.fin_size[1] block_list.append( gdspy.Rectangle( (x0, y), (x0 + self.fin_size[0], y + self.fin_size[1]), **self.fin_spec)) block_list.append( gdspy.Rectangle((xend - self.fin_size[0], y), (xend, y + self.fin_size[1]), **self.fin_spec)) angle = 0 if self.direction == "NORTH": angle = np.pi / 2.0 elif self.direction == "WEST": angle = np.pi elif self.direction == "SOUTH": angle = -np.pi / 2.0 elif isinstance(self.direction, float): angle = self.direction for block in block_list: block.rotate(angle, self.trace[0]) self.add(block)
def build_cell(self): # Sequentially build all the geometric shapes using gdspy path functions # for waveguide, then add it to the Cell angle = tk.get_exact_angle(self.trace[0], self.trace[1]) # Add bus waveguide, and cladding bus = gdspy.Path(self.wgt.wg_width, self.trace[0]) bus.segment(self.total_length, direction=angle, **self.wg_spec) # Cladding for bus waveguide bus_clad = gdspy.Path(2*self.wgt.clad_width+self.wgt.wg_width, self.trace[0]) bus_clad.segment(self.total_length, direction=angle, **self.clad_spec) self.add(bus) self.add(bus_clad) # Add nanobeam waveguide beam_x = self.trace[0][0] - np.sin(angle)*(self.gap + 2*self.wgt.wg_width) beam_y = self.trace[0][1] + np.cos(angle)*(self.gap + 2*self.wgt.wg_width) nanobeam = gdspy.Path(self.wgt.wg_width, (beam_x,beam_y)) nanobeam.segment(self.total_length, direction=angle, **self.wg_spec) # Cladding for nanobeam nanobeam_clad = gdspy.Path(2*self.wgt.clad_width+self.wgt.wg_width, (beam_x,beam_y)) nanobeam_clad.segment(self.total_length, direction=angle, **self.clad_spec) """ Add the mirror holes """ startx = beam_x + np.cos(angle)*(self.wgt_beam_length + self.taper_length + self.period/2) starty = beam_y + np.sin(angle)*(self.wgt_beam_length + self.taper_length + self.period/2) hole_list = [] for i in range(int(self.nbr_holes)): x = startx + i*np.cos(angle)*self.period y = starty + i*np.sin(angle)*self.period hole_list.append(gdspy.Round((x,y), self.radius)) """ Add the taper holes """ if self.taper_type=="FF": startx_in = beam_x + np.cos(angle)*(self.wgt_beam_length + self.period/2) startx_out = beam_x + np.cos(angle)*(self.total_length - self.wgt_beam_length - self.period/2) starty_in = beam_y + np.sin(angle)*(self.wgt_beam_length + self.period/2) starty_out = beam_y + np.sin(angle)*(self.total_length - self.wgt_beam_length - self.period/2) taper_list_in = [] taper_list_out = [] for i in range(int(self.nbr_taper)): fill_factor = np.pi*np.square(self.radius_taper/self.period) + i*np.pi*(np.square(self.radius/self.period) - np.square(self.radius_taper/self.period))/(self.nbr_taper - 1) taper_radii = np.sqrt(fill_factor/np.pi)*self.period x_in = startx_in + i*np.cos(angle)*self.period y_in = starty_in + i*np.sin(angle)*self.period taper_list_in.append(gdspy.Round((x_in,y_in), taper_radii)) x_out = startx_out - i*np.cos(angle)*self.period y_out = starty_out - i*np.sin(angle)*self.period taper_list_out.append(gdspy.Round((x_out,y_out), taper_radii)) elif self.taper_type=="ratio": startx_in = beam_x + np.cos(angle)*self.wgt_beam_length startx_out = beam_x + np.cos(angle)*(self.total_length - self.wgt_beam_length) starty_in = beam_y + np.sin(angle)*self.wgt_beam_length starty_out = beam_y + np.sin(angle)*(self.total_length - self.wgt_beam_length) taper_list_in = [] taper_list_out = [] for i in range(int(self.nbr_taper)): ratio = self.period/self.radius taper_radii = self.radius_taper + i*(self.radius-self.radius_taper)/(self.nbr_taper-1) taper_period = taper_radii*ratio x_in = startx_in + i*np.cos(angle)*taper_period y_in = starty_in + i*np.sin(angle)*taper_period taper_list_in.append(gdspy.Round((x_in,y_in), taper_radii)) x_out = startx_out - i*np.cos(angle)*taper_period y_out = starty_out - i*np.sin(angle)*taper_period taper_list_out.append(gdspy.Round((x_out,y_out), taper_radii)) for hole in hole_list: nanobeam = gdspy.fast_boolean(nanobeam,hole,'xor') for hole_in in taper_list_in: nanobeam = gdspy.fast_boolean(nanobeam,hole_in,'xor') for hole_out in taper_list_out: nanobeam = gdspy.fast_boolean(nanobeam,hole_out,'xor') self.add(nanobeam) self.add(nanobeam_clad)