def Ring_Test(label, gap, ring_r, ring_wg_width=wg_width): cell = Cell('Ring_Test' + label) r_bend = 60 #bend_r r_eff = r_bend / euler_to_bend_coeff outports = [Port((opt_space * i, 0), np.pi / 2, std_coupler_params['width']) for i in (0, 1)] gratingcouplers = [GratingCoupler.make_traditional_coupler_at_port(outport, **std_coupler_params) for outport in outports] port = outports[0].inverted_direction wg = Waveguide.make_at_port(port) wg.add_straight_segment(grating_added_taper_len, wg_width) # wgAdd_EulerBend(wg, np.pi / 2., r_eff, False) wg.add_bend(np.pi / 2., r_bend) dist_straight = opt_space - 2 * r_bend wg.add_straight_segment(dist_straight / 2.) ring_res = RingResonator.make_at_port(wg.current_port.inverted_direction, gap=gap, radius=ring_r, res_wg_width=ring_wg_width) wg.add_straight_segment(dist_straight / 2.) # wgAdd_EulerBend(wg, np.pi / 2., r_eff, False) wg.add_bend(np.pi / 2., r_bend) wg.add_straight_segment_until_y(outports[1].origin[1]-grating_added_taper_len) wg.add_straight_segment(grating_added_taper_len, std_coupler_params['width']) label_txt = Text((opt_space / 2., -6), 25, label, alignment='center-top') shapely_object = geometric_union(gratingcouplers + [label_txt] + [wg] + [ring_res]) cell.add_to_layer(wg_layer, shapely_object) comments = Text((60, 40), 10, 'gap={:.2f}\nrad={:.2f}\nwg_width={:.2f}'.format(gap, ring_r, ring_wg_width), alignment='center-top') cell.add_to_layer(comment_layer, comments) x_cords = [] y_cords = [] box_disty = 2 for this_poly in shapely_object.geoms: temp_x_cords, temp_y_cords = this_poly.exterior.coords.xy x_cords = x_cords + list(temp_x_cords) y_cords = y_cords + list(temp_y_cords) x_max = max(x_cords) + box_dist x_min = min(x_cords) - box_dist y_max = max(y_cords) + box_disty y_min = min(y_cords) - box_disty box_size = (x_max - x_min, y_max - y_min) box = Waveguide(((x_min + x_max) / 2., y_min), np.pi / 2, box_size[0]) box.add_straight_segment(box_size[1]) total_box = geometric_union([box]) cell.add_to_layer(wg_wf_layer, total_box) cell.add_to_layer(wg_reg_layer, total_box) return cell
def Efficiency_Grating(label, period, ff, grating_angle = None): cell = Cell('GC_Test' + label) r_bend = 60 #bend_r r_eff = r_bend / euler_to_bend_coeff coupler_params = std_coupler_params.copy() coupler_params['grating_period'] = period coupler_params['grating_ff'] = ff if grating_angle is not None: coupler_params['full_opening_angle'] = grating_angle outports = [Port((opt_space * i, 0), np.pi / 2, std_coupler_params['width']) for i in (0, 1)] gratingcouplers = [GratingCoupler.make_traditional_coupler_at_port(outport, **coupler_params) for outport in outports] port = outports[0].inverted_direction wg = Waveguide.make_at_port(port) wg.add_straight_segment(grating_added_taper_len, wg_width) wg.add_bend(np.pi / 2., r_bend) wg.add_straight_segment(opt_space - 2 * r_bend) wg.add_bend(np.pi / 2., r_bend) wg.add_straight_segment_until_y(outports[1].origin[1]-grating_added_taper_len) wg.add_straight_segment(grating_added_taper_len, std_coupler_params['width']) label_txt = Text((opt_space / 2., -6), 25, label, alignment='center-top') # self.shapely_object = geometric_union([wg] + [label] + gratingcouplers) shapely_object = geometric_union(gratingcouplers + [label_txt] + [wg]) cell.add_to_layer(wg_layer, shapely_object) comments = Text((60, 40), 10, 'period={:.2f}\nff={:.2f}'.format(coupler_params['grating_period'], coupler_params['grating_ff']), alignment='center-top') cell.add_to_layer(comment_layer, comments) x_cords = [] y_cords = [] box_disty = 2 # 2.5 * marker_dims for this_poly in shapely_object.geoms: temp_x_cords, temp_y_cords = this_poly.exterior.coords.xy x_cords = x_cords + list(temp_x_cords) y_cords = y_cords + list(temp_y_cords) x_max = max(x_cords) + box_dist x_min = min(x_cords) - box_dist y_max = max(y_cords) + box_disty y_min = min(y_cords) - box_disty box_size = (x_max - x_min, y_max - y_min) box = Waveguide(((x_min + x_max) / 2., y_min), np.pi / 2, box_size[0]) box.add_straight_segment(box_size[1]) total_box = geometric_union([box]) cell.add_to_layer(wg_wf_layer, total_box) cell.add_to_layer(wg_reg_layer, total_box) return cell
def init_sim(self, **kwargs): """ Initializes the simulation. This has to be done after adding all structures in order to correctly determine the size of the simulation. :param kwargs: Parameters which are directly passed to Meep """ z_min = np.min([ structure['z_min'] for structure in self.structures if structure['structure'] ]) z_max = np.max([ structure['z_max'] for structure in self.structures if structure['structure'] ]) bounds = geometric_union( (geometric_union(x['structure']) for x in self.structures)).bounds size = np.array( (bounds[2] - bounds[0], bounds[3] - bounds[1], (z_max - z_min))) self.center = np.round([(bounds[2] + bounds[0]) / 2, (bounds[3] + bounds[1]) / 2, (z_max + z_min) / 2]) self.size = np.ceil(size + self.padding * 2 + self.pml_thickness * 2) if self.reduce_to_2d: self.center[2] = self.size[2] = 0 structures = [] for structure in self.structures: polygon = geometric_union(structure['structure'] + structure['extra_structures']) \ .buffer(np.finfo(np.float32).eps, resolution=0).simplify(np.finfo(np.float32).eps) objs = shapely_collection_to_basic_objs(polygon) for obj in objs: if obj.is_empty: continue for polygon in fracture_intelligently(obj, np.inf, np.inf): structures += [ mp.Prism(vertices=[ mp.Vector3( *point, 0 if self.reduce_to_2d else structure['z_min']) for point in polygon.exterior.coords[:-1] ], material=structure['material'], height=structure['z_max'] - structure['z_min']) ] self.sim = mp.Simulation(mp.Vector3(*self.size), self.resolution, geometry=structures, geometry_center=mp.Vector3(*self.center), sources=self.sources, boundary_layers=[mp.PML(self.pml_thickness)], **kwargs) self.sim.init_sim()
def example_cavity_harminv(): from gdshelpers.parts.waveguide import Waveguide from shapely.geometry import Point wg = Waveguide((-6, 0), 0, 1.2) start_port = wg.current_port wg.add_straight_segment(6) center_port = wg.current_port wg.add_straight_segment(6) wgs = [Waveguide.make_at_port(port).add_straight_segment(4) for port in [start_port.inverted_direction, wg.current_port]] holes = geometric_union( [Point(x * sign, 0).buffer(.36) for x in [1.4 / 2 + x * 1 for x in range(3)] for sign in [-1, 1]]) sim = Simulation(resolution=20, reduce_to_2d=True, padding=2, pml_thickness=1) sim.add_structure([wg.get_shapely_object().difference(holes)], wgs, mp.Medium(epsilon=13), z_min=0, z_max=.33) sim.add_source(mp.GaussianSource(wavelength=1 / .25, fwidth=.2), mp.Hz, center_port, z=0) sim.init_sim() sim.plot(fields=mp.Hz) mp.simulation.display_run_data = lambda *args, **kwargs: None harminv = mp.Harminv(mp.Hz, mp.Vector3(), .25, .2) sim.run(mp.after_sources(harminv._collect_harminv()(harminv.c, harminv.pt)), until_after_sources=300) sim.plot(fields=mp.Hz) print(harminv._analyze_harminv(sim.sim, 100))
def example_cavity(): from gdshelpers.parts.waveguide import Waveguide from shapely.geometry import Point wg = Waveguide((-6, 0), 0, 1.2) start_port = wg.current_port wg.add_straight_segment(12) wgs = [Waveguide.make_at_port(port).add_straight_segment(4) for port in [start_port.inverted_direction, wg.current_port]] holes = geometric_union( [Point(x * sign, 0).buffer(.36) for x in [1.4 / 2 + x * 1 for x in range(3)] for sign in [-1, 1]]) sim = Simulation(resolution=20, reduce_to_2d=True, padding=2) sim.add_structure([wg.get_shapely_object().difference(holes)], wgs, mp.Medium(epsilon=13), z_min=0, z_max=.33) sim.add_eigenmode_source(mp.GaussianSource(wavelength=1 / .25, fwidth=.35), start_port, z=0.33 / 2, height=1, eig_band=2) sim.init_sim() monitors_out = [sim.add_eigenmode_monitor(port.longitudinal_offset(1), 1 / .25, .2, 500, z=0.33 / 2, height=1) for port in [start_port, wg.current_port.inverted_direction]] sim.plot(mp.Hz) sim.run(until=1500) sim.plot(mp.Hz) frequencies = np.array(mp.get_eigenmode_freqs(monitors_out[0])) transmissions = [np.abs(sim.get_eigenmode_coefficients(monitors_out[i], [2]).alpha[0, :, 0]) ** 2 for i in range(2)] plt.plot(frequencies, transmissions[1] / transmissions[0]) plt.show()
def __init__(self, poly, extrude_val_min, extrude_val_max, rgb=(255, 255, 255)): if type(poly) in (list, tuple): self.poly = shapely_adapter.geometric_union(poly) self.poly = shapely_adapter.shapely_collection_to_basic_objs(poly) self.rgb = rgb self.extrude_val_min = extrude_val_min self.extrude_val_max = extrude_val_max
def wf_line_from_bounds(cell, bounds, wf_maxlength, wf_layer, wf_additions={}, axis=1, region_marker=None, direction=1): # assumes x direction is fine and that leeways have # been included in the bounds dir_idx = 1 if direction == -1: dir_idx = 0 current_position = bounds[axis + 2 * (1 - dir_idx)] if direction == 1: current_limit = min(current_position + wf_maxlength, bounds[axis + 2]) else: current_limit = max(current_position - wf_maxlength, bounds[axis]) wf_bounds = list(bounds).copy() iteration = 0 while current_limit != bounds[axis + 2 * dir_idx]: wf_bounds[axis + 2 * (1 - dir_idx)] = current_position wf_bounds[axis + 2 * dir_idx] = current_limit wf_addition = (0, 0, 0, 0) if iteration in wf_additions.keys(): wf_addition = wf_additions[iteration] bounds = np.add(bounds, wf_addition) single_wf_from_bounds(cell, np.add(wf_bounds, wf_addition), wf_layer) current_position = current_limit if direction == 1: current_limit = min(current_position + wf_maxlength, bounds[axis + 2]) else: current_limit = max(current_position - wf_maxlength, bounds[axis]) iteration += 1 wf_addition = (0, 0, 0, 0) if -1 in wf_additions.keys(): wf_addition = wf_additions[-1] bounds = np.add(bounds, wf_addition) wf_bounds[axis + 2 * (1 - dir_idx)] = current_position wf_bounds[axis + 2 * dir_idx] = current_limit single_wf_from_bounds(cell, np.add(wf_bounds, wf_addition), wf_layer) if region_marker is not None: region_marker = geometric_union( [region_marker, bounds_to_polygon(bounds)]) return bounds, region_marker
def MZI_active_with_phase(coupler_sep, coupler_length, MZ_length, electrodes_sep, label): cell = Cell('MZI_active_withphase'+label) x_in = 0 y_in = 0 wg_sep = mod_params['wg_sep'] wg_width_in_mod = wg_Expwidth taper_length = l_Exptaper ##Generating input and output grating couplers coupler_params = std_coupler_params.copy() for j in (0, 1): incoupler = GratingCoupler.make_traditional_coupler((x_in + j * opt_space, y_in), **coupler_params) cell.add_to_layer(wg_layer, incoupler) outcouplers = [] for j in (3, 4): outcoupler = GratingCoupler.make_traditional_coupler((x_in + j * opt_space, y_in), **coupler_params) outcouplers.append(outcoupler) cell.add_to_layer(wg_layer, outcoupler) ###Generating waveguides inports = [Port((x_in + j * opt_space, y_in), np.deg2rad(90), std_coupler_params['width']) for j in (0, 1)] wg = [Waveguide.make_at_port(inport) for inport in inports] for j in (0, 1): # adding final tapers as suggested by Munster, SP 21/10/21 wg[j].add_straight_segment(grating_added_taper_len, final_width=wg_width) # wg[j].add_straight_segment(bend_r-grating_added_taper_len) wg[j].add_bend(-np.pi / 2.0, bend_r + (1 - j) * wg_sep) wg[j].add_straight_segment((1 - j) * (opt_space - wg_sep)) wg[j].add_bend(-np.pi / 2.0, bend_r + (1 - j) * wg_sep) wg[j].add_straight_segment(bend_r) ##directional coupler with sinusoidal s-bend x_length = 60 y_length = wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - j * (wg_sep - wg_width - coupler_sep) wg[j].add_parameterized_path(path=lambda t: (t * x_length, .5 * (np.cos(np.pi * t) - 1) * y_length), path_derivative=lambda t: (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length)) wg[j].add_straight_segment(coupler_length) y_length = -(wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - j * (wg_sep - wg_width - coupler_sep)) wg[j].add_parameterized_path(path=lambda t: (t * x_length, .5 * (np.cos(np.pi * t) - 1) * y_length), path_derivative=lambda t: (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length)) #add taper to multimode wg wg[j].add_straight_segment(taper_length, final_width=wg_width_in_mod) ###reference port for electrodes in MZI ref_port = wg[j].current_port ###reference port for electrodes in PHASE ref_port_ph = wg[j].current_port ###straight section wg[j].add_straight_segment(MZ_length) #add taper to single-mode wg wg[j].add_straight_segment(taper_length, final_width=wg_width) ##directional coupler with sinusoidal s-bend x_length = 60 y_length = wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - j * (wg_sep - wg_width - coupler_sep) wg[j].add_parameterized_path(path=lambda t: (t * x_length, .5 * (np.cos(np.pi * t) - 1) * y_length), path_derivative=lambda t: (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length)) wg[j].add_straight_segment(coupler_length) y_length = -(wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - j * (wg_sep - wg_width - coupler_sep)) wg[j].add_parameterized_path(path=lambda t: (t * x_length, .5 * (np.cos(np.pi * t) - 1) * y_length), path_derivative=lambda t: (x_length, -np.pi * .5 * np.sin(np.pi * t) * y_length)) x_dist_inout=2*mod_params['electrode_width'] + 15 wg[j].add_straight_segment(10) wg[j].add_bend(np.pi/2., bend_r + j * wg_sep) wg[j].add_straight_segment(x_dist_inout+wg_sep) wg[j].add_bend(np.pi, bend_r + j * wg_sep) wg[j].add_bend(-np.pi / 2., bend_r + (1-j) * wg_sep) wg[j].add_straight_segment_until_y(inports[0].y - 3*bend_r) wg[j].add_bend(-np.pi / 2., bend_r + (1 - j) * wg_sep) wg[j].add_straight_segment_until_x(outcouplers[-1].origin[0]+bend_r) wg[j].add_bend(np.pi / 2., bend_r + j * wg_sep) wg[j].add_straight_segment_until_y(inports[0].y) wg[j].add_straight_segment(grating_added_taper_len) wg[j].add_bend(np.pi / 2., bend_r + j* wg_sep) wg[j].add_straight_segment_until_x(outcouplers[1-j].origin[0]+(bend_r + j * wg_sep)) wg[j].add_bend(np.pi / 2., bend_r + j*wg_sep) # # adding final tapers as suggested by Munster, SP 21/10/21 wg[j].add_straight_segment(grating_added_taper_len, final_width=std_coupler_params['width']) for j in (0, 1): cell.add_to_layer(wg_layer, wg[j]) ##MODULATOR ELECTRODES #### ELECTRODES IN MZI electr_width = mod_params['electrode_width'] sep_econns = mod_params['electrode_sep_y'] cross_width = mod_params['crossing_width'] pads_pitch = mod_params['connector_probe_pitch'] pads_width = mod_params['connector_probe_dims'][0] pads_width_gnd = mod_params['connector_probe_dims_gnd'][0] pads_len = mod_params['connector_probe_dims'][1] min_safedist_from_wg = 22 x_safe_dist = ref_port.origin[0] - min_safedist_from_wg - pads_width ##left ground electrode Inport = Port((ref_port.origin[0] - electrodes_sep / 2.0 - wg_sep / 2.0, ref_port.origin[1]), np.deg2rad(-90), electr_width) g_left = Waveguide.make_at_port(Inport) g_left.add_straight_segment(MZ_length - cross_width/2. - 2 * sep_econns) g_left._current_port.angle = g_left.current_port.angle - np.pi / 2.0 g_left._current_port.origin[0] = g_left.current_port.origin[0] + g_left.current_port.width / 2.0 g_left.add_straight_segment_until_x(x_safe_dist) g_left.add_straight_segment(2 * pads_pitch + (pads_width-pads_width_gnd/2.)) g_left._current_port.angle = g_left.current_port.angle + np.pi / 2.0 g_left._current_port.origin[0] = g_left.current_port.origin[0] + pads_width_gnd / 2.0 g_left._current_port.width = pads_width_gnd g_left.add_straight_segment(pads_len) cell.add_to_layer(electrode_layer, g_left) ## signal electrode Inport = Port((ref_port.origin[0] + wg_sep / 2.0, ref_port.origin[1]), np.deg2rad(-90), electr_width - electrodes_sep) s = Waveguide.make_at_port(Inport) s.add_straight_segment(MZ_length - cross_width/2. - sep_econns) s._current_port.angle = s.current_port.angle - np.pi / 2.0 s._current_port.origin[0] = s.current_port.origin[0] + s.current_port.width / 2.0 s._current_port.width = cross_width s.add_straight_segment(wg_sep+5) s.add_straight_segment(wg_sep, electr_width) s.add_straight_segment_until_x(x_safe_dist) s.add_straight_segment(pads_pitch+ (pads_width-pads_width_gnd/2.)) s._current_port.angle = s.current_port.angle + np.pi / 2.0 s._current_port.origin[0] = s.current_port.origin[0] + pads_width / 2.0 s._current_port.width = pads_width s.add_straight_segment_until_y(g_left.current_port.origin[1] + 50) cell.add_to_layer(electrode_layer, s) ##right ground electrode Inport = Port((ref_port.origin[0] + wg_sep + wg_sep / 2.0 + electrodes_sep / 2.0, ref_port.origin[1]), np.deg2rad(-90), electr_width) g_right = Waveguide.make_at_port(Inport) g_right.add_straight_segment(MZ_length - cross_width/2.) g_right._current_port.angle = g_right.current_port.angle - np.pi / 2.0 g_right._current_port.origin[0] = g_right.current_port.origin[0] + g_right.current_port.width / 2.0 g_right._current_port.width = cross_width g_right.add_straight_segment(2*wg_sep+5) g_right.add_straight_segment(wg_sep, electr_width) g_right.add_straight_segment_until_x(x_safe_dist) g_right.add_straight_segment(pads_width_gnd/2.) g_right._current_port.angle = g_right.current_port.angle + np.pi / 2.0 g_right._current_port.origin[0] = g_right.current_port.origin[0] + pads_width_gnd / 2.0 g_right._current_port.width = pads_width_gnd g_right.add_straight_segment_until_y(g_left.current_port.origin[1]) g_right._current_port.angle = g_right.current_port.angle - np.pi / 2.0 g_right._current_port.origin[0] = g_right.current_port.origin[0] + g_right.current_port.width / 2.0 g_right._current_port.width = pads_width / 2. g_right._current_port.origin[1] = g_right.current_port.origin[1] - g_right._current_port.width / 2. g_right.add_straight_segment(2 * pads_pitch + pads_width) cell.add_to_layer(electrode_layer, g_right) #### ELECTRODES FOR PHASE ref_port_ph = deepcopy(ref_port) ref_port_ph.origin[0] = ref_port.origin[0] + 2*wg_sep + x_dist_inout x_safe_dist_ph = ref_port_ph.origin[0] + min_safedist_from_wg + pads_width x_startpos_pads_ph = s._current_port.origin[0] + 4*pads_pitch + (pads_width_gnd - pads_width)/2. + (pads_width-pads_width_gnd/2.) y_startpos_pads_ph = s._current_port.origin[1] +280 ##right ground electrode Inport = Port((ref_port_ph.origin[0] + electrodes_sep / 2.0 + wg_sep / 2.0, ref_port.origin[1]), np.deg2rad(-90), electr_width) g_right_ph = Waveguide.make_at_port(Inport) g_right_ph.add_straight_segment(MZ_length - cross_width/2. - 2 * sep_econns) g_right_ph._current_port.angle = g_right_ph.current_port.angle + np.pi / 2.0 g_right_ph._current_port.origin[0] = g_right_ph.current_port.origin[0] - g_right_ph.current_port.width / 2.0 g_right_ph.add_straight_segment_until_x(x_startpos_pads_ph) g_right_ph._current_port.angle = g_right_ph.current_port.angle - np.pi / 2.0 g_right_ph._current_port.origin[0] = g_right_ph.current_port.origin[0] - g_right_ph.current_port.width / 2.0 g_right_ph.add_straight_segment_until_y(y_startpos_pads_ph-2*sep_econns+ g_right_ph.current_port.width) g_right_ph._current_port.origin[0] = g_right_ph._current_port.origin[0] - (pads_width_gnd- g_right_ph.current_port.width) / 2.0 g_right_ph._current_port.width = pads_width_gnd g_right_ph.add_straight_segment_until_y(g_left._current_port.origin[1]) cell.add_to_layer(electrode_layer, g_right_ph) ## signal electrode Inport = Port((ref_port_ph.origin[0] - wg_sep / 2.0, ref_port_ph.origin[1]), np.deg2rad(-90), electr_width - electrodes_sep) s_ph = Waveguide.make_at_port(Inport) s_ph.add_straight_segment(MZ_length - cross_width/2. - sep_econns) s_ph._current_port.angle = s.current_port.angle + np.pi / 2.0 s_ph._current_port.origin[0] = s_ph.current_port.origin[0] - s_ph.current_port.width / 2.0 s_ph._current_port.width = cross_width s_ph.add_straight_segment(wg_sep+5) s_ph.add_straight_segment(wg_sep, electr_width) s_ph.add_straight_segment_until_x(x_startpos_pads_ph - sep_econns) s_ph._current_port.angle = s_ph.current_port.angle - np.pi / 2.0 s_ph._current_port.origin[0] = s_ph.current_port.origin[0] - s_ph.current_port.width / 2.0 s_ph.add_straight_segment_until_y(y_startpos_pads_ph-sep_econns) s_ph._current_port.angle = s_ph.current_port.angle - np.pi / 2.0 s_ph._current_port.origin[1] = s_ph.current_port.origin[1] + s_ph.current_port.width / 2.0 s_ph.add_straight_segment_until_x(s.current_port.origin[0] + 3*pads_pitch-pads_width / 2.0) s_ph._current_port.angle = s_ph.current_port.angle + np.pi / 2.0 s_ph._current_port.origin[0] = s_ph.current_port.origin[0] + pads_width / 2.0 s_ph._current_port.width = pads_width s_ph.add_straight_segment_until_y(s.current_port.origin[1]) cell.add_to_layer(electrode_layer, s_ph) ##left ground electrode Inport = Port((ref_port_ph.origin[0] - wg_sep - wg_sep / 2.0 - electrodes_sep / 2.0, ref_port_ph.origin[1]), np.deg2rad(-90), electr_width) g_left_ph = Waveguide.make_at_port(Inport) g_left_ph.add_straight_segment(MZ_length - cross_width/2.) g_left_ph._current_port.angle = g_left_ph.current_port.angle + np.pi / 2.0 g_left_ph._current_port.origin[0] = g_left_ph.current_port.origin[0] - g_left_ph.current_port.width / 2.0 g_left_ph._current_port.width = cross_width g_left_ph.add_straight_segment(2*wg_sep+5) g_left_ph.add_straight_segment(wg_sep, electr_width) g_left_ph.add_straight_segment_until_x(x_startpos_pads_ph - 2*sep_econns) g_left_ph._current_port.angle = g_left_ph.current_port.angle - np.pi / 2.0 g_left_ph._current_port.origin[0] = g_left_ph.current_port.origin[0] - g_left_ph.current_port.width / 2.0 g_left_ph.add_straight_segment_until_y(y_startpos_pads_ph) g_left_ph._current_port.angle = g_left_ph.current_port.angle - np.pi / 2.0 g_left_ph._current_port.origin[1] = g_left_ph.current_port.origin[1] + g_left_ph.current_port.width / 2.0 g_left_ph.add_straight_segment_until_x(s.current_port.origin[0] + 2*pads_pitch - pads_width / 2.0) g_left_ph._current_port.angle = g_left_ph.current_port.angle + np.pi / 2.0 g_left_ph._current_port.origin[0] = g_left_ph.current_port.origin[0] + pads_width_gnd / 2.0 g_left_ph._current_port.width = pads_width_gnd g_left_ph.add_straight_segment_until_y(g_right_ph.current_port.origin[1]) g_left_ph._current_port.angle = g_left_ph.current_port.angle + np.pi / 2.0 g_left_ph._current_port.origin[0] = g_left_ph.current_port.origin[0] - g_left_ph.current_port.width / 2.0 g_left_ph._current_port.width = pads_width / 2. g_left_ph._current_port.origin[1] = g_left_ph.current_port.origin[1] - g_left_ph._current_port.width / 2. g_left_ph.add_straight_segment(2 * pads_pitch + pads_width) cell.add_to_layer(electrode_layer, g_left_ph) ###WRITE FIELDs waveguide outer_corners = [(x_in - 80, y_in + 160), (x_in + 5 * 127 + 60, y_in + 160), (x_in + 5 * 127 + 60, y_in + 160 - 1040), (x_in - 80, y_in + 160 - 1040)] polygon1 = Polygon(outer_corners) cell.add_to_layer(wg_wf_layer, polygon1) outer_corners = [(x_in - 80, y_in + 160 - 1040), (x_in + 5 * 127 + 60, y_in + 160 - 1040), (x_in + 5 * 127 + 60, y_in + 160 - 1040 - (MZ_length + 2*taper_length + 660 - 1040)), (x_in - 80, y_in + 160 - 1040 - ((MZ_length + 2*taper_length + 660 - 1040)))] polygon2 = Polygon(outer_corners) cell.add_to_layer(wg_wf_layer, polygon2) polygon = geometric_union([polygon1, polygon2]) cell.add_to_layer(wg_reg_layer, polygon) ###WRITE FIELDs electrodes outer_corners = [(x_in - 210, y_in - 100), (x_in + 5 * 127 + 140, y_in - 100), (x_in + 5 * 127 + 140, y_in - 100 - 1040), (x_in - 210, y_in - 100 - 1040)] polygon1 = Polygon(outer_corners) cell.add_to_layer(electrode_wf_layer, polygon1) outer_corners = [(x_in - 210, y_in - 100 - 1040), (x_in + 5 * 127 + 140, y_in - 100 - 1040), (x_in + 5 * 127 + 140, y_in - 100 - 1040 - (MZ_length + 2*taper_length + 762 - 1040)), (x_in - 210, y_in - 100 - 1040 - (MZ_length + 2*taper_length + 762 - 1040))] polygon2 = Polygon(outer_corners) cell.add_to_layer(electrode_wf_layer, polygon2) polygon = geometric_union([polygon1, polygon2]) cell.add_to_layer(electrode_reg_layer, polygon) ####Local markers ### first set on layer 3 positions = [(x_in, y_in - 320), (x_in + 5 * 127 - 60, y_in - 320), (x_in + 5 * 127 - 60, y_in - 320 - 450)] marker = [SquareMarker.make_marker(position, 20) for position in positions] cell.add_to_layer(3, geometric_union(marker)) marker = [SquareMarker.make_marker(position, 30) for position in positions] cell.add_to_layer(9, geometric_union(marker)) marker = [SquareMarker.make_marker(position, 40) for position in positions] cell.add_to_layer(15, geometric_union(marker)) ### second set on layer 4 positions = [(x_in, y_in - 320 - 150), (x_in + 5 * 127 - 60, y_in - 320 - 150), (x_in + 5 * 127-60, y_in - 320 - 300)] marker = [SquareMarker.make_marker(position, 20) for position in positions] cell.add_to_layer(marker_layer_1, geometric_union(marker)) marker = [SquareMarker.make_marker(position, 30) for position in positions] cell.add_to_layer(wg_layer, geometric_union(marker)) marker = [SquareMarker.make_marker(position, 40) for position in positions] cell.add_to_layer(marker_protection_layer, geometric_union(marker)) ###Label device_label = Text(origin=(x_in, y_in - 700), height=30, text=label, alignment='center-bottom', angle=np.pi) cell.add_to_layer(wg_layer, device_label) ###Device Info info_text = ('MZ_length = %.1f um\nElectrodes_sep = %.1f nm\nCoupler_length= %.1f um\n') \ % (MZ_length, electrodes_sep, coupler_length) device_info = Text(origin=(x_in, y_in - 850), height=20, text=info_text, alignment='center-bottom' , angle=np.pi) cell.add_to_layer(comment_layer, device_info) return cell
def electrode_connector(cell, left_wg, signal_wg, right_wg, direction, kink, wg_top, electrode_wf_layer, region_marker, connector_coordinates, previous_line_bounds, left_side, initial_point, param, probe_connector=True): # Collect electrodes to save space next_kink = [-1, -1] new_region_marker = bounds_to_polygon(previous_line_bounds) end_point = [0, 0] if left_side: end_point[0] = previous_line_bounds[2] else: end_point[0] = previous_line_bounds[0] if direction == -1: end_point[1] = previous_line_bounds[1] + 20 else: end_point[1] = previous_line_bounds[3] - 20 region_marker = connect_writefields(cell, initial_point, end_point, electrode_wf_layer, region_marker, param) region_marker = geometric_union([region_marker, new_region_marker]) if kink != [-1, -1]: if (left_side and not ( kink[0] + param['electrode_pitch'] > (connector_coordinates[0] + param['connector_probe_pitch']))): previous_line_bounds, next_kink, region_marker = build_wrap_kinks( cell, left_wg, signal_wg, right_wg, kink, region_marker, wg_top, electrode_wf_layer, previous_line_bounds, left_side, param) left_side = False elif (not left_side and not (kink[0] - param['electrode_pitch'] < connector_coordinates[0] - param['connector_probe_pitch'])): previous_line_bounds, next_kink, region_marker = build_wrap_kinks( cell, left_wg, signal_wg, right_wg, kink, region_marker, wg_top, electrode_wf_layer, previous_line_bounds, left_side, param) left_side = True else: previous_line_bounds, next_kink, region_marker = build_kinks( cell, left_wg, signal_wg, right_wg, kink, region_marker, electrode_wf_layer, previous_line_bounds, left_side, param) else: if (left_side and connector_coordinates[0] > signal_wg.current_port.origin[0]): previous_line_bounds, next_kink, region_marker = build_wrap_kinks( cell, left_wg, signal_wg, right_wg, kink, region_marker, wg_top, electrode_wf_layer, previous_line_bounds, left_side, param) left_side = False elif (not left_side and connector_coordinates[0] < signal_wg.current_port.origin[0]): previous_line_bounds, next_kink, region_marker = build_wrap_kinks( cell, left_wg, signal_wg, right_wg, kink, region_marker, wg_top, electrode_wf_layer, previous_line_bounds, left_side, param) left_side = True if left_side: first_line_bounds = [ -1, (left_wg.current_port.origin[1] - left_wg.current_port.width / 2 - param['electrode_wf_leeways'][1] / 2), previous_line_bounds[0], (right_wg.current_port.origin[1] + right_wg.current_port.width / 2 + param['electrode_wf_leeways'][1] / 2) ] wf_direction = -1 else: first_line_bounds = [ previous_line_bounds[2], (right_wg.current_port.origin[1] - right_wg.current_port.width / 2 - param['electrode_wf_leeways'][1] / 2), -1, (left_wg.current_port.origin[1] + left_wg.current_port.width / 2 + param['electrode_wf_leeways'][1] / 2) ] wf_direction = 1 # left_wg if probe_connector: ground_signal_pad_sep = 0.5 * 3 / 5 * ( 2 * param['connector_probe_pitch'] - param['contact_pad_dims'][0]) left_wg_goal_x = (connector_coordinates[0] - param['connector_probe_pitch']) else: left_wg_goal_x = (connector_coordinates[0] - param['contact_pad_dims'][0] / 2 - param['electrode_pad_seps'][0] - left_wg.current_port.width / 2) left_wg.add_straight_segment_until_x(left_wg_goal_x) if not left_side: first_line_bounds[2] = ( left_wg.current_port.origin[0] # The following was in the code before, but # is possibly not necessary # - left_wg.current_port.width/2 - param['connector_probe_dims'][0] / 2 - param['electrode_wf_leeways'][0] / 8) if (first_line_bounds[2] - first_line_bounds[0] < param['electrode_pitch'] + param['electrode_width']): first_line_bounds[2] = first_line_bounds[0] else: _, region_marker = wf_line_from_bounds( cell=cell, bounds=first_line_bounds, region_marker=region_marker, wf_maxlength=param['wf_maxlength'], wf_layer=electrode_wf_layer, axis=0, direction=wf_direction) # 90 degree turn left_wg._current_port.angle = np.pi / 2 left_wg._current_port.origin[1] = (left_wg._current_port.origin[1] - left_wg.current_port.width / 2.0) # signal_wg (which is also the center wg) signal_wg_goal_x = connector_coordinates[0] signal_wg.add_straight_segment_until_x(signal_wg_goal_x) # 90 degree turn signal_wg._current_port.angle = np.pi / 2 signal_wg._current_port.origin[1] = (signal_wg._current_port.origin[1] - signal_wg.current_port.width / 2.0) # right_wg if probe_connector: right_wg_goal_x = (connector_coordinates[0] - param['connector_probe_pitch'] / 2 + param['contact_pad_dims'][0] / 2 + ground_signal_pad_sep) else: right_wg_goal_x = (connector_coordinates[0] + param['contact_pad_dims'][0] / 2 + param['electrode_pad_seps'][0] + right_wg.current_port.width / 2) # the wfs for the rightmost case has to be handled by itself rightmost1 = False rightmost2 = False if left_side: right_wg_goal_x = (connector_coordinates[0] + param['connector_probe_pitch'] - param['connector_probe_dims'][0] / 2) if right_wg_goal_x - right_wg.current_port.origin[0] < 0: y_distance = (right_wg.current_port.origin[1] - signal_wg.current_port.origin[1] - right_wg.current_port.width / 2) right_wg.add_straight_segment_until_x(right_wg_goal_x) right_wg._current_port.origin[1] = ( right_wg._current_port.origin[1] - right_wg.current_port.width / 2.0) right_wg._current_port.origin[ 0] += right_wg.current_port.width / 2.0 right_wg._current_port.angle = np.pi / 2 right_wg.add_straight_segment(y_distance) first_line_bounds[3] = (right_wg.current_port.origin[1] + param['electrode_wf_leeways'][1]) else: # Rightmost ground electrode right_wg._current_port.angle = 0 right_wg._current_port.origin[ 0] -= right_wg.current_port.width / 2.0 right_wg._current_port.origin[ 1] -= right_wg.current_port.width / 2.0 right_wg.add_straight_segment_until_x( connector_coordinates[0] + param['connector_probe_pitch'] - param['connector_probe_dims'][0] / 2) rightmost1 = True right_limit = right_wg.current_port.origin[0] # Can't be routed into the electrode to the right for the # rightmost interferometer (the rightmost of the rightmost) if param['last_interferometer']: rightmost2 = True right_wg.add_straight_segment_until_x( connector_coordinates[0] + param['contact_pad_dims'][0] / 2.0 + param['electrode_pad_seps'][0] + param['crossing_width'] / 2.0) right_wg._current_port.angle = np.pi / 2 right_wg._current_port.origin[1] -= ( right_wg.current_port.width / 2.0) right_wg._current_port.width = param['crossing_width'] right_limit = (right_wg.current_port.origin[0] + right_wg.current_port.width) right_wg.add_straight_segment_until_y( connector_coordinates[1] + param['connector_probe_dims'][1] + param['electrode_pad_seps'][1] + param['contact_pad_sep'] + 2 * param['contact_pad_dims'][1]) right_wg._current_port.angle = np.pi right_wg._current_port.origin[0] += ( right_wg.current_port.width / 2.0) right_wg._current_port.width = param['contact_pad_dims'][1] right_wg._current_port.origin[1] -= ( right_wg.current_port.width / 2.0) right_wg.add_straight_segment(param['ground_pad_width']) first_line_bounds[0] = (right_wg.current_port.origin[0] - right_wg.current_port.width / 2 + param['electrode_wf_leeways'][0] / 8) if (first_line_bounds[2] - first_line_bounds[0] < param['electrode_pitch'] + param['electrode_width']): first_line_bounds[0] = first_line_bounds[2] first_line_bounds[0] += param['electrode_width'] / 2 elif not rightmost2: _, region_marker = wf_line_from_bounds( cell=cell, bounds=first_line_bounds, region_marker=region_marker, wf_maxlength=param['wf_maxlength'], wf_layer=electrode_wf_layer, axis=0, direction=wf_direction) else: right_wg.add_straight_segment_until_x( connector_coordinates[0] + param['connector_probe_pitch'] - param['connector_probe_dims'][0] / 2) # 90 degree turn if rightmost1: first_line_bounds[2] = right_limit # Tells where the next electrodes should branch in order # to run alongside this one if next_kink == [-1, -1]: if left_side: next_kink = [ right_wg_goal_x - param['electrode_pitch'], left_wg.current_port.origin[1] - 2 * param['electrode_pitch'] - left_wg.current_port.width / 2.0 ] else: next_kink = [ left_wg_goal_x + param['electrode_pitch'], right_wg.current_port.origin[1] - 2 * param['electrode_pitch'] ] if probe_connector: electrode_probe_and_pad(cell, left_wg, signal_wg, right_wg, region_marker, electrode_wf_layer, connector_coordinates, (rightmost1, rightmost2), first_line_bounds, left_side, param) else: electrode_pad(cell, left_wg, signal_wg, right_wg, region_marker, electrode_wf_layer, connector_coordinates, first_line_bounds, left_side, param) return next_kink
def RectangularSpiral(label, num, add_xlength=0., add_ylength=100., sep=4., r_curve=50., return_xmax=False, grating_angle = None, exp_wg_width=wg_Expwidth, grating_coupler_period = std_coupler_params['grating_period']): cell = Cell('DC_Test' + label) r_eff = r_curve / euler_to_bend_coeff delta = 2 * sep orizontal_length = add_xlength + 2 * sep coupler_params = std_coupler_params.copy() coupler_params['grating_period'] = grating_coupler_period if grating_angle is not None: coupler_params['full_opening_angle'] = grating_angle grating_coupl_pos = np.array((0, 0)) couplers = [ GratingCoupler.make_traditional_coupler(grating_coupl_pos + (opt_space * x, 0), **coupler_params) for x in (0, 1)] # ports = [Port(grating_coupl_pos - (opt_space * x, 0), np.pi / 2, wg_width) for x in (0, 1)] ### Adding final tapers as suggested by Munster, SP 21/10/21 ports = [Port(grating_coupl_pos - (opt_space * x, 0), np.pi / 2, std_coupler_params['width']) for x in (0, 1)] couplers = [GratingCoupler.make_traditional_coupler_at_port(port, **coupler_params) for port in ports] waveguides = [Waveguide.make_at_port(port.inverted_direction) for port in ports] ### Adding final tapers as suggested by Munster, SP 21/10/21 waveguides[0].add_straight_segment(grating_added_taper_len, final_width=wg_width) waveguides[0].add_straight_segment(sep, final_width=wg_width) wgAdd_EulerBend(waveguides[0], -np.pi / 2, r_eff, True) waveguides[0].add_straight_segment(sep + opt_space) wgAdd_EulerBend(waveguides[0], -np.pi / 2., r_eff, True) ### Adding final tapers as suggested by Munster, SP 21/10/21 waveguides[1].add_straight_segment(grating_added_taper_len, final_width=wg_width) wgAdd_EulerBend(waveguides[1], -np.pi / 2., r_eff, True) wgAdd_EulerBend(waveguides[1], -np.pi / 2., r_eff, True) waveguides[1].add_straight_segment(grating_added_taper_len, final_width=wg_width) origin_spiral = Port((-opt_space / 2., 320 + add_ylength / 2. + num * sep), 0, wg_width) wg1 = Waveguide.make_at_port(origin_spiral) wgAdd_EulerBend(wg1, -np.pi / 2., r_eff, True) if add_ylength > (4 * l_Exptaper): wg1.add_straight_segment(l_Exptaper, final_width=exp_wg_width) wg1.add_straight_segment(add_ylength / 2. - 2 * l_Exptaper) wg1.add_straight_segment(l_Exptaper, final_width=wg_width) else: wg1.add_straight_segment(add_ylength / 2.) wgAdd_EulerBend(wg1, -np.pi / 2., r_eff, True) if (add_xlength / 2. + sep) > (2 * l_Exptaper): wg1.add_straight_segment(l_Exptaper, final_width=exp_wg_width) wg1.add_straight_segment(add_xlength / 2. + sep - 2 * l_Exptaper) wg1.add_straight_segment(l_Exptaper, final_width=wg_width) else: wg1.add_straight_segment(add_xlength / 2. + sep) wgAdd_EulerBend(wg1, -np.pi / 2., r_eff, True) if (sep + add_ylength + 2 * r_curve) > (2 * l_Exptaper): wg1.add_straight_segment(l_Exptaper, final_width=exp_wg_width) wg1.add_straight_segment(sep + add_ylength + 2 * r_curve - 2 * l_Exptaper) wg1.add_straight_segment(l_Exptaper, final_width=wg_width) else: wg1.add_straight_segment(sep + add_ylength + 2 * r_curve) wgAdd_EulerBend(wg1, -np.pi / 2., r_eff, True) wg2 = Waveguide.make_at_port(origin_spiral.inverted_direction) wgAdd_EulerBend(wg2, -np.pi / 2., r_eff, True) if add_ylength > (4 * l_Exptaper): wg2.add_straight_segment(l_Exptaper, final_width=exp_wg_width) wg2.add_straight_segment(add_ylength / 2. - 2 * l_Exptaper) wg2.add_straight_segment(l_Exptaper, final_width=wg_width) else: wg2.add_straight_segment(add_ylength / 2.) wgAdd_EulerBend(wg2, -np.pi / 2., r_eff, True) if (add_xlength / 2. + sep) > (2 * l_Exptaper): wg2.add_straight_segment(l_Exptaper, final_width=exp_wg_width) wg2.add_straight_segment(add_xlength / 2. + sep - 2 * l_Exptaper) wg2.add_straight_segment(l_Exptaper, final_width=wg_width) else: wg2.add_straight_segment(add_xlength / 2. + sep) wgAdd_EulerBend(wg2, -np.pi / 2., r_eff, True) if (sep + add_ylength + 2 * r_curve) > (2 * l_Exptaper): wg2.add_straight_segment(l_Exptaper, final_width=exp_wg_width) wg2.add_straight_segment(sep + add_ylength + 2 * r_curve - 2 * l_Exptaper) wg2.add_straight_segment(l_Exptaper, final_width=wg_width) else: wg2.add_straight_segment(sep + add_ylength + 2 * r_curve) wgAdd_EulerBend(wg2, -np.pi / 2., r_eff, True) if (orizontal_length + sep) > (2 * l_Exptaper): wg2.add_straight_segment(l_Exptaper, final_width=exp_wg_width) wg2.add_straight_segment(orizontal_length + sep - 2 * l_Exptaper) wg2.add_straight_segment(l_Exptaper, final_width=wg_width) else: wg2.add_straight_segment(orizontal_length + sep) wgAdd_EulerBend(wg2, -np.pi / 2., r_eff, True) if (sep + delta + add_ylength + 2 * r_curve) > (2 * l_Exptaper): wg2.add_straight_segment(l_Exptaper, final_width=exp_wg_width) wg2.add_straight_segment(sep + delta + add_ylength + 2 * r_curve - 2 * l_Exptaper) wg2.add_straight_segment(l_Exptaper, final_width=wg_width) else: wg2.add_straight_segment(sep + delta + add_ylength + 2 * r_curve) wgAdd_EulerBend(wg2, -np.pi / 2., r_eff, True) for i in np.arange(1, num): if (orizontal_length + delta * i - sep) > (2 * l_Exptaper): wg1.add_straight_segment(l_Exptaper, final_width=exp_wg_width) wg1.add_straight_segment(orizontal_length + delta * i - sep - 2 * l_Exptaper) wg1.add_straight_segment(l_Exptaper, final_width=wg_width) else: wg1.add_straight_segment(orizontal_length + delta * i - sep) wgAdd_EulerBend(wg1, -np.pi / 2., r_eff, True) if (delta * i + sep + add_ylength + 2 * r_curve) > (2 * l_Exptaper): wg1.add_straight_segment(l_Exptaper, final_width=exp_wg_width) wg1.add_straight_segment(delta * i + sep + add_ylength + 2 * r_curve - 2 * l_Exptaper) wg1.add_straight_segment(l_Exptaper, final_width=wg_width) else: wg1.add_straight_segment(delta * i + sep + add_ylength + 2 * r_curve) wgAdd_EulerBend(wg1, -np.pi / 2., r_eff, True) for j in np.arange(2, num): if (orizontal_length + j * delta - sep) > (2 * l_Exptaper): wg2.add_straight_segment(l_Exptaper, final_width=exp_wg_width) wg2.add_straight_segment(orizontal_length + j * delta - sep - 2 * l_Exptaper) wg2.add_straight_segment(l_Exptaper, final_width=wg_width) else: wg2.add_straight_segment(orizontal_length + j * delta - sep) wgAdd_EulerBend(wg2, -np.pi / 2., r_eff, True) if (delta * (j + 1) - sep + add_ylength + 2 * r_curve) > (2 * l_Exptaper): wg2.add_straight_segment(l_Exptaper, final_width=exp_wg_width) wg2.add_straight_segment(delta * (j + 1) - sep + add_ylength + 2 * r_curve - 2 * l_Exptaper) wg2.add_straight_segment(l_Exptaper, final_width=wg_width) else: wg2.add_straight_segment(delta * (j + 1) - sep + add_ylength + 2 * r_curve) wgAdd_EulerBend(wg2, -np.pi / 2., r_eff, True) waveguides[0].add_straight_segment(l_Exptaper, final_width=exp_wg_width) waveguides[0].add_straight_segment_until_y(wg1.y - r_curve - l_Exptaper) waveguides[0].add_straight_segment(l_Exptaper, final_width=wg_width) wgAdd_EulerBend(waveguides[0], -np.pi / 2., r_eff, True) waveguides[0].add_straight_segment(l_Exptaper, final_width=exp_wg_width) waveguides[0].add_straight_segment_until_x(wg1.x - l_Exptaper) waveguides[0].add_straight_segment(l_Exptaper, final_width=wg_width) waveguides[1].add_straight_segment(r_curve / 2., final_width=wg_width) wgAdd_EulerBend(waveguides[1], -np.pi / 2., r_eff, True) # if (num * delta - sep + orizontal_length) > 2 * l_Exptaper: wg2.add_straight_segment(l_Exptaper, final_width=exp_wg_width) wg2.add_straight_segment(num * delta - sep + orizontal_length - 2 * l_Exptaper) wg2.add_straight_segment(l_Exptaper, final_width=wg_width) else: wg2.add_straight_segment(num * delta - sep + orizontal_length) wgAdd_EulerBend(wg2, -np.pi / 2., r_eff, True) waveguides[1].add_straight_segment(l_Exptaper, final_width=exp_wg_width) waveguides[1].add_straight_segment_until_x(wg2.x - r_curve - l_Exptaper) waveguides[1].add_straight_segment(l_Exptaper, final_width=wg_width) wgAdd_EulerBend(waveguides[1], np.pi / 2., r_eff, False) waveguides[1].add_straight_segment(l_Exptaper, final_width=exp_wg_width) waveguides[1].add_straight_segment_until_y(wg2.y - l_Exptaper) waveguides[1].add_straight_segment(l_Exptaper, final_width=wg_width) label_txt = Text(origin_spiral.origin + (0, -r_curve), 25, label, alignment='center-top') shapely_object = geometric_union(waveguides + [wg1, wg2, label_txt] + couplers) cell.add_to_layer(wg_layer, shapely_object) comments = Text((-100, -10), 30, 'length={:.2f}'.format( (wg1.length + wg2.length + waveguides[1].length + waveguides[0].length) * 1e-4), alignment='center-top') cell.add_to_layer(comment_layer, comments) x_cords = [] y_cords = [] for this_poly in shapely_object.geoms: temp_x_cords, temp_y_cords = this_poly.exterior.coords.xy x_cords = x_cords + list(temp_x_cords) y_cords = y_cords + list(temp_y_cords) x_max = max(x_cords) + box_dist x_min = min(x_cords) - box_dist y_max = max(y_cords) + box_dist y_min = min(y_cords) - box_dist box_size = (x_max - x_min, y_max - y_min) num_boxes = int(box_size[1] / max_box_size[1]) + 1 box_x_dim = box_size[0] box_y_dim = box_size[1] / num_boxes box_list = [] for i in range(num_boxes): box = Waveguide(((x_min + x_max) / 2., y_min + i * box_y_dim), np.pi / 2, box_x_dim) box.add_straight_segment(box_y_dim) box_list.append(box) # self.box = geometric_union(box_list) for this_box in box_list: cell.add_to_layer(wg_wf_layer, this_box) all_boxes = geometric_union(box_list) cell.add_to_layer(wg_reg_layer, all_boxes) if return_xmax: return cell, x_max else: return cell
def DirectionalCouplersTest(label, gap, length, AMZI_DeltaL, r_curve=50, grating_angle = None): cell = Cell('DC_Test' + label) couplerList = [] outports = [] wgs = [] coupler_params = std_coupler_params.copy() if grating_angle is not None: coupler_params['full_opening_angle'] = grating_angle r_eff = r_curve / euler_to_bend_coeff port = Port((0, 0), 0, wg_width) couplerList.append(DirectionalCoupler.make_at_port(port, length=length, gap=gap, bend_radius=r_curve)) wg = Waveguide.make_at_port(couplerList[0].right_ports[1]) wg.add_straight_segment(2 * r_curve) wgs.append(wg) wg = Waveguide.make_at_port(couplerList[0].right_ports[0]) wg.add_straight_segment(2 * r_curve) couplerList.append(DirectionalCoupler.make_at_port(wg.current_port, length=length, gap=gap, bend_radius=r_curve)) sep = 5 len_eulers = EulerLength(r_eff, np.pi / 2.) Delta_L = max(0, (AMZI_DeltaL - 12 * len_eulers - 5 * sep) / 4.) wg = Waveguide.make_at_port(couplerList[0].right_ports[0]) wgAdd_EulerBend(wg, -np.pi / 2., r_eff, True) wg.add_straight_segment(Delta_L + sep) wgAdd_EulerBend(wg, -np.pi / 2., r_eff, True) wgAdd_EulerBend(wg, -np.pi / 2., r_eff, True) wg.add_straight_segment(Delta_L) wgAdd_EulerBend(wg, np.pi / 2., r_eff, False) wgAdd_EulerBend(wg, np.pi / 2., r_eff, False) wg.add_straight_segment(Delta_L + sep) wgAdd_EulerBend(wg, np.pi / 2., r_eff, False) wg.add_straight_segment(6 * r_curve + sep) wgAdd_EulerBend(wg, np.pi / 2., r_eff, False) wg.add_straight_segment(Delta_L + sep) wgAdd_EulerBend(wg, np.pi / 2., r_eff, False) wgAdd_EulerBend(wg, np.pi / 2., r_eff, False) wg.add_straight_segment(Delta_L) wgAdd_EulerBend(wg, -np.pi / 2., r_eff, True) wgAdd_EulerBend(wg, -np.pi / 2., r_eff, True) wg.add_straight_segment(Delta_L + sep) wgAdd_EulerBend(wg, -np.pi / 2., r_eff, True) wgs.append(wg) # wg = Waveguide.make_at_port(couplerList[0].left_ports[0]) wgAdd_EulerBend(wg, -np.pi / 2., r_eff, True) wgs.append(wg) outports.append(wg.port) outports.append(outports[0].parallel_offset(-3 * opt_space)) wg = Waveguide.make_at_port(couplerList[1].right_ports[0]) wg.add_bezier_to(np.array(outports[1].origin), bend_strength=r_curve / 1.2, final_angle=np.pi / 2.) wgs.append(wg) wg = Waveguide.make_at_port(couplerList[0].left_ports[1]) wg.add_bend(angle=-np.pi, radius=r_curve / 4) wg.add_straight_segment(50, final_width=0.1) wgs.append(wg) wg = Waveguide.make_at_port(couplerList[1].right_ports[1]) wg.add_bend(angle=np.pi, radius=r_curve / 4) wg.add_straight_segment(50, final_width=0.1) wgs.append(wg) gratingcouplers = [GratingCoupler.make_traditional_coupler_at_port(outport, **coupler_params) for outport in outports] label_txt = Text((180, 70), 25, label, alignment='center-top') box = Waveguide((+520, -40), np.pi / 2., 1025) box.add_straight_segment(730) shapely_object = geometric_union(wgs + [label_txt] + couplerList + gratingcouplers) cell.add_to_layer(wg_layer, shapely_object) comments = Text((105, 70), 10, 'gap={:.2f}\nlength={:.2f}'.format(gap, length), alignment='center-top') cell.add_to_layer(comment_layer, comments) x_cords = [] y_cords = [] for this_poly in shapely_object.geoms: temp_x_cords, temp_y_cords = this_poly.exterior.coords.xy x_cords = x_cords + list(temp_x_cords) y_cords = y_cords + list(temp_y_cords) x_max = max(x_cords) + box_dist x_min = min(x_cords) - box_dist y_max = max(y_cords) + box_dist y_min = min(y_cords) - box_dist box_size = (x_max - x_min, y_max - y_min) box = Waveguide(((x_min + x_max) / 2., y_min), np.pi / 2, box_size[0]) box.add_straight_segment(box_size[1]) total_box = geometric_union([box]) cell.add_to_layer(wg_wf_layer, total_box) cell.add_to_layer(wg_reg_layer, total_box) return cell