def spiral_with_coupler(cell, origin=(0, 0), width=0.5, angle=0, gap=3, num=4): l_wg = 100 left_wg = Waveguide(origin, angle, width) left_wg.add_straight_segment(l_wg) spiral = Spiral.make_at_port(left_wg.current_port, num=num, gap=gap, inner_gap=30) print(spiral.length, "um") print(spiral.out_port) right_wg = Waveguide.make_at_port(spiral.out_port) right_wg.add_straight_segment(l_wg) layout = positive_resist.convert_to_positive_resist([left_wg, spiral, right_wg], gap, outer_resolution=1e-3) outer_corners = [origin, (origin[0], origin[1]+2*gap), (origin[0]-2*gap, origin[1]+2*gap), (origin[0]-2*gap, origin[1]-2*gap), (origin[0], origin[1]-2*gap)] polygon1 = Polygon(outer_corners) origin = spiral.out_port.origin origin[0] = origin[0] + l_wg + 2*gap outer_corners = [origin, (origin[0], origin[1]+2*gap), (origin[0]-2*gap, origin[1]+2*gap), (origin[0]-2*gap, origin[1]-2*gap), (origin[0], origin[1]-2*gap)] polygon2 = Polygon(outer_corners) polygon = polygon1.union(polygon2) layout_fixed = layout.difference(polygon) cell.add_to_layer(1, layout_fixed) # add the text of the length of spiral cell.add_to_layer(101, Text((origin[0], origin[1]-50), 20, str(spiral.length) ) )
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 test_waveguide_multiple_widths(self): widths = [1, 2, 1] wg = Waveguide([0, 0], 0, widths) wg.add_straight_segment(100) wg.add_parameterized_path(lambda t: [10 * t, t]) wg.get_shapely_object()
def _example(): import gdsCAD.core from gdshelpers.geometry import convert_to_gdscad from gdshelpers.parts.waveguide import Waveguide mpsv2 = MultiPortSwitch(origin=[0, 0], angle=np.deg2rad(0.), in_ports=4, out_ports=7, port_spacing=10, taper_length=40, taper_function=lambda t: t * (1.0 - 0.05) + 0.05, radius=50., displacement=0., wg_bend_radius=40., minimal_final_spacing=20) wg = Waveguide([100, 100], np.pi / 4, 1) wg.add_straight_segment(100) # mpsv2_2 = MultiPortSwitch.make_at_out_port(wg.current_port, 3, # in_ports=2, out_ports=7, # port_spacing=10, # taper_length=10, taper_function=lambda t: t * (1.0 - 0.05) + 0.05, # radius=50., displacement=00., # wg_bend_radius=40., ) cell = gdsCAD.core.Cell('TEST') cell.add(convert_to_gdscad([ mpsv2, wg, ])) cell.show()
def _generate(self): left = Port(self._origin, self._angle, self._wg_width) wg = Waveguide.make_at_port(left, width=self._width) wg.add_straight_segment(self._length) self._wgs.append(wg) right = wg.current_port input_positions, output_positions = self._calculate_positions( self.num_inputs, self.num_outputs) self._sep = input_positions[-1] - input_positions[0] for pos in input_positions: wg = Waveguide([ self._origin[0] - pos * self._width * np.sin(self._angle), self._origin[1] + pos * self._width * np.cos(self._angle) ], angle=self._angle - np.pi, width=self._taper_width) wg.add_straight_segment(self._taper_length, final_width=self._wg_width) self._wgs.append(wg) self.input_ports.append(wg.current_port) for pos in output_positions: wg = Waveguide([ right.origin[0] - pos * self._width * np.sin(self._angle), right.origin[1] + pos * self._width * np.cos(self._angle) ], angle=self._angle, width=self._taper_width) wg.add_straight_segment(self._taper_length, final_width=self._wg_width) self._wgs.append(wg) self.output_ports.append(wg.current_port)
def _example(): from gdshelpers.geometry.chip import Cell from gdshelpers.parts.waveguide import Waveguide from gdshelpers.parts.resonator import RingResonator # ==== create some sample structures (straight line with ring resonator) wg = Waveguide(origin=(0, 0), angle=np.deg2rad(-90), width=1) wg.add_straight_segment(length=5) wg.add_bend(np.pi / 2, 5) wg2 = Waveguide.make_at_port(wg.current_port) wg2.add_straight_segment(15) reso = RingResonator.make_at_port(port=wg2.current_port, gap=0.2, radius=5) wg2.add_straight_segment(length=15) coupler2 = GratingCoupler.make_traditional_coupler_from_database_at_port( wg2.current_port, db_id='si220', wavelength=1550) underetching_parts = geometric_union([wg2, reso, coupler2]) structure = geometric_union([underetching_parts, wg]) # create the holes with a radius of 0.5 microns, a distance of 2 microns to the structure borders and # a distance of 2 microns between the holes holes = create_holes_for_under_etching(underetch_parts=underetching_parts, complete_structure=structure, hole_radius=0.5, hole_distance=2, hole_spacing=3, hole_length=3) # create a cell with the structures in layer 1 and the holes in layer 2 cell = Cell('CELL') cell.add_to_layer(1, structure) cell.add_to_layer(2, holes) # Show the cell cell.show()
def test_waveguide_construction(self): wg = Waveguide([0, 0], 0, 1) self.assertAlmostEqual(wg.length, 0) # Add straight waveguide wg.add_straight_segment(10) self.assertAlmostEqual(wg.x, 10) self.assertAlmostEqual(wg.y, 0) self.assertAlmostEqual(wg.angle, 0) self.assertAlmostEqual(wg.length, 10) # Add upwards 90 degree bend wg.add_bend(math.pi / 2, 5) self.assertAlmostEqual(wg.current_port.origin[0], 15) self.assertAlmostEqual(wg.current_port.origin[1], 5) self.assertAlmostEqual(wg.current_port.angle, math.pi / 2) self.assertAlmostEqual(wg.length_last_segment, math.pi / 2 * 5, delta=10e-5) # Add another arc, so that we are finally pointing 180 degree backwards wg.add_arc(math.pi, 5) self.assertAlmostEqual(wg.current_port.origin[0], 10) self.assertAlmostEqual(wg.current_port.origin[1], 10) self.assertAlmostEqual(abs(wg.current_port.angle), math.pi)
def test_region_layers(self): cell = Cell("test_device") wg1 = Waveguide([0, 0], 0, 1) wg1.add_straight_segment(10) wg1_shapely = wg1.get_shapely_object() cell.add_to_layer(1, wg1) wg2 = Waveguide([40, 0], 0, 1) wg2.add_straight_segment(10) wg2_shapely = wg2.get_shapely_object() cell.add_to_layer(2, wg2) cell.add_region_layer(100) cell.add_region_layer(101, [1]) cell.add_region_layer(102, [1, 2]) self.assertTrue(100 in cell.layer_dict) self.assertTrue(cell.layer_dict[100][0].contains(wg1_shapely)) self.assertTrue(cell.layer_dict[100][0].contains(wg2_shapely)) self.assertTrue(101 in cell.layer_dict) self.assertTrue(cell.layer_dict[101][0].contains(wg1_shapely)) self.assertFalse(cell.layer_dict[101][0].contains(wg2_shapely)) self.assertTrue(102 in cell.layer_dict) self.assertTrue(cell.layer_dict[102][0].contains(wg1_shapely)) self.assertTrue(cell.layer_dict[102][0].contains(wg2_shapely))
def coupler_coupler(origin, width=0.5, angle=0, gap=3): l_wg = 100 left_wg = Waveguide(origin, angle, width) left_wg.add_straight_segment(l_wg) right_wg = Waveguide.make_at_port(left_wg.port) right_wg.add_straight_segment(l_wg) layout = positive_resist.convert_to_positive_resist([left_wg, right_wg], gap, outer_resolution=1e-3) outer_corners = [ origin, (origin[0], origin[1] + 2 * gap), (origin[0] - 2 * gap, origin[1] + 2 * gap), (origin[0] - 2 * gap, origin[1] - 2 * gap), (origin[0], origin[1] - 2 * gap) ] polygon1 = Polygon(outer_corners) origin = (origin[0] + 2 * l_wg + 2 * gap, origin[1]) outer_corners = [ origin, (origin[0], origin[1] + 2 * gap), (origin[0] - 2 * gap, origin[1] + 2 * gap), (origin[0] - 2 * gap, origin[1] - 2 * gap), (origin[0], origin[1] - 2 * gap) ] polygon2 = Polygon(outer_corners) polygon = polygon1.union(polygon2) layout_fixed = layout.difference(polygon) cell.add_to_layer(1, layout_fixed)
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 example_bend_coupling(): from gdshelpers.parts.waveguide import Waveguide waveguide_straight = Waveguide((0, 0), 0, width=1) waveguide_straight.add_straight_segment(5) bend_port = waveguide_straight.current_port.parallel_offset(1.1) waveguides_bend_1 = Waveguide.make_at_port(bend_port) waveguides_bend_1.add_bend(angle=np.pi / 2, radius=15, n_points=30) waveguides_bend_2 = Waveguide.make_at_port(bend_port.inverted_direction) waveguides_bend_2.add_bend(angle=-np.pi / 5, radius=15, n_points=20) waveguide_straight.add_straight_segment(5) wgs = [ Waveguide.make_at_port(port).add_straight_segment(40) for port in [ waveguide_straight.in_port, waveguide_straight.current_port, waveguides_bend_1.current_port, waveguides_bend_2.current_port ] ] sim = Simulation(resolution=20, reduce_to_2d=True, padding=2, pml_thickness=.5) sim.add_structure([waveguide_straight, waveguides_bend_1], wgs + [waveguides_bend_2], mp.Medium(index=1.666), z_min=0, z_max=.33) # GaussianSource or ContinousSource source = sim.add_eigenmode_source( mp.ContinuousSource(wavelength=1.55, width=2), waveguide_straight.in_port.longitudinal_offset(1), z=0.33 / 2, height=1, eig_band=2) sim.init_sim(subpixel_maxeval=0) # subpixel_maxeval=0 for quick testing monitors_out = [ sim.add_eigenmode_monitor(port, 1.55, 2, 1, z=0.33 / 2, height=1) for port in [waveguide_straight.current_port, waveguides_bend_1.current_port] ] # sim.plot(mp.Hz) sim.run(until=150) sim.plot(mp.Hz) transmissions = [ np.abs( sim.get_eigenmode_coefficients(monitors_out[i], [2]).alpha[0, 0, 0])**2 / source.eig_power(1 / 1.55) for i in range(2) ] print('transmission in bus waveguide: {:.3f}'.format(transmissions[0])) print('transmission to bent waveguide: {:.3f}'.format(transmissions[1]))
def _example(): from gdshelpers.geometry.chip import Cell wg = Waveguide((0, 0), 1, 1) wg.add_straight_segment(30) spiral = Spiral.make_at_port(wg.current_port, 2, 5, 50) wg2 = Waveguide.make_at_port(spiral.out_port) wg2.add_straight_segment(100) print(spiral.length) cell = Cell('Spiral') cell.add_to_layer(1, wg, spiral, wg2) cell.show()
def test_cell_bounds(self): cell = Cell('test_cell') wg1 = Waveguide([0, 0], 0, 1) wg1.add_straight_segment(10) cell.add_to_layer(1, wg1) wg2 = Waveguide([40, 0], 0, 1) wg2.add_straight_segment(10) cell.add_to_layer(2, wg2) cell.add_region_layer(100, [1]) cell.add_region_layer(101, [1, 2]) self.assertTrue(100 in cell.layer_dict) self.assertEqual(cell.bounds, (0.0, -0.5, 50.0, 0.5)) subcell = Cell('subcell') subcell.add_to_layer(3, box(0, 0, 60, 70)) self.assertEqual(subcell.bounds, (0.0, 0, 60.0, 70)) # add subcell cell.add_cell(subcell, origin=(0, 0)) self.assertEqual(cell.bounds, (0.0, -0.5, 60.0, 70.)) subcell2 = Cell('subcell2') subcell2.add_to_layer(3, box(0, 0, 60, 70)) # add subcell at different origin cell.add_cell(subcell2, origin=(20, 0)) self.assertEqual(cell.bounds, (0.0, -0.5, 80.0, 70.)) # add object to subcell after adding the subcell to cell subcell2.add_to_layer(4, box(60, 0, 70, 10)) self.assertEqual(subcell2.bounds, (0.0, 0, 70.0, 70)) self.assertEqual(cell.bounds, (0.0, -0.5, 90.0, 70.)) # check total region layer cell.add_region_layer(102) self.assertTrue(102 in cell.layer_dict) self.assertEqual(cell.get_bounds(layers=[102]), cell.bounds)
def _example(): from gdshelpers.geometry.chip import Cell cell = Cell('test') wg1 = Waveguide((0, 0), 0.5 * np.pi, 1.) wg1.add_straight_segment(10.) cell.add_to_layer(3, wg1) detector = SNSPD.make_at_port(wg1.current_port, nw_width=0.1, nw_gap=0.1, nw_length=70, passivation_buffer=0.2, waveguide_tapering=True) cell.add_to_layer(1, detector) cell.add_to_layer(2, detector.get_waveguide()) cell.add_to_layer(5, detector.get_passivation_layer()) # cell.add_to_layer(6, detector.right_electrode_port.debug_shape) # cell.add_to_layer(6, detector.left_electrode_port.debug_shape) wg2 = Waveguide.make_at_port(detector.current_port) wg2.add_straight_segment(20.) cell.add_to_layer(3, wg2) cell.save('SNSPD_test.gds') cell.show()
def test_dlw(self): # Make sure that cells with DLW data only exist once top = Cell('parent_cell') child = Cell('child1') wg1 = Waveguide([0, 0], 0, 1) wg1.add_straight_segment(10) child.add_to_layer(1, wg1) # This should be ok, as child contains no DLW data top.add_cell(child, [0, 0]) top.add_cell(child, [100, 0]) child2 = Cell('child2') child2.add_to_layer(1, wg1) child2.add_dlw_taper_at_port("foo", 1, wg1.current_port, taper_length=40.) top.add_cell(child2, [0, 0]) with self.assertRaises(ValueError): top.add_cell(child2, [100, 0])
pos = interior.interpolate(distance=dist) if not no_hole_zone.contains(pos): holes.append(pos.buffer(hole_radius)) return geometric_union(holes) if __name__ == '__main__': import gdsCAD.core from gdshelpers.parts.waveguide import Waveguide from gdshelpers.parts.resonator import RingResonator from gdshelpers.geometry import convert_to_gdscad # ==== create some sample structures (straight line with ring resonator) wg = Waveguide(origin=(0, 0), angle=np.deg2rad(-90), width=1) wg.add_straight_segment(length=5) wg.add_bend(np.pi / 2, 5) wg2 = Waveguide.make_at_port(wg.current_port) wg2.add_straight_segment(15) reso = RingResonator.make_at_port(port=wg2.current_port, gap=0.2, radius=5) wg2.add_straight_segment(length=15) coupler2 = GratingCoupler.make_traditional_coupler_from_database_at_port( wg2.current_port, db_id='si220', wavelength=1550) underetching_parts = geometric_union([wg2, reso, coupler2]) structure = geometric_union([underetching_parts, wg]) # create the holes with a radius of 0.5 microns, a distance of 2 microns to the structure borders and # a distance of 2 microns between the holes holes = create_holes_for_under_etching(underetch_parts=underetching_parts, complete_structure=structure, hole_radius=0.5,
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
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
diff = np.array(center_coordinates.interpolate(pos + padding / 2)) - np.array( center_coordinates.interpolate(pos - padding / 2)) d1 = np.array((-diff[1], diff[0])) / np.linalg.norm(diff) for direction in [-1, 1]: point = Point(xy + direction * (offset + spacing / 2 * (i % 2)) * d1) if outline.contains(point): new_circles = True if area_for_holes.contains(point): circles.append(point.buffer(hole_radius)) offset += spacing return unary_union(circles) if __name__ == '__main__': from gdshelpers.geometry.chip import Cell from gdshelpers.parts.waveguide import Waveguide wg = Waveguide((0, 0), 0, [3, 3, 3, 3, 3]) wg.add_straight_segment(5) wg.add_bend(np.pi / 2, 20) wg.width = 15 wg.add_straight_segment(4) wg.add_bend(-np.pi / 2, 20) cell = Cell('vortex_traps') cell.add_to_layer(1, wg) cell.add_to_layer(2, fill_waveguide_with_holes_in_honeycomb_lattice(wg, 1, .1, .15)) cell.add_to_layer(2, surround_with_holes(wg.get_shapely_outline(), 3, 1, 1, 15)) cell.show() cell.save()
def IL_mmi(origin=(0, 0), len_in=500, radius=10, num_roundtrip=3, len_deltaL=250, w_etch=3): """ total delta L = 4*len_delta_L * num_rountrip """ # coupler_params = { # 'width': 0.45, # 'full_opening_angle': np.deg2rad(40), # 'grating_period': 0.64, # 'grating_ff': 0.546875, # 'n_gratings': 20, # 'taper_length': 16, # } mmi_params = { 'length': 31.37, 'width': 6, 'taper_width': 2.9, 'taper_length': 20, } # gc_start # gc_start = GratingCoupler.make_traditional_coupler(origin, angle=-np.pi, **coupler_params) # staright wg wg_start = Waveguide(origin, angle=0, width=0.5) wg_start.add_straight_segment(10) # mmi_in mmi_in = MMI.make_at_port(wg_start.port, num_inputs=1, num_outputs=2, **mmi_params) # mmi_in. # len_in is the length of the input straight wg # len_out is the length of the out straight wg # # len_in = 500 len_out = len_in # len_deltaL = 400 # radius = 10 gap = 10 # num_roundtrip = 3 # port 1 wg1 = Waveguide.make_at_port(mmi_in.left_branch_port) wg1.add_straight_segment(len_in) i = 0 while i < num_roundtrip: wg1.add_bend(np.pi, radius) wg1.add_straight_segment(len_deltaL) wg1.add_bend(-np.pi, radius) wg1.add_straight_segment(len_deltaL) i += 1 wg1.add_straight_segment(6 * radius + 3 * gap) i = 0 while i < num_roundtrip: wg1.add_straight_segment(len_deltaL) wg1.add_bend(-np.pi, radius) wg1.add_straight_segment(len_deltaL) wg1.add_bend(np.pi, radius) i += 1 wg1.add_straight_segment(len_out) # port 2 wg2 = Waveguide.make_at_port(mmi_in.right_branch_port) wg2.add_straight_segment(len_in + 2 * radius + gap) i = 0 while i < num_roundtrip: wg2.add_bend(np.pi, radius) wg2.add_bend(-np.pi, radius) i += 1 wg2.add_straight_segment(2 * radius + gap) i = 0 while i < num_roundtrip: wg2.add_bend(-np.pi, radius) wg2.add_bend(np.pi, radius) i += 1 wg2.add_straight_segment(len_out + 2 * radius + gap) # mmi_out mmi_out = MMI.make_at_port(wg1.port, num_inputs=2, num_outputs=1, **mmi_params) # straight wg wg_end = Waveguide.make_at_port(mmi_out.right_branch_port) wg_end.add_straight_segment(10) # convert to positive resist layout = positive_resist.convert_to_positive_resist( [mmi_in, mmi_out, wg1, wg2, wg_end, wg_start], w_etch, outer_resolution=1e-3) gap = 10 outer_corners = [ origin, (origin[0], origin[1] + 2 * gap), (origin[0] - 2 * gap, origin[1] + 2 * gap), (origin[0] - 2 * gap, origin[1] - 2 * gap), (origin[0], origin[1] - 2 * gap) ] polygon1 = Polygon(outer_corners) origin = wg_end._current_port.origin print("End Point: ", origin) origin[0] = origin[0] + 2 * gap outer_corners = [ origin, (origin[0], origin[1] + 2 * gap), (origin[0] - 2 * gap, origin[1] + 2 * gap), (origin[0] - 2 * gap, origin[1] - 2 * gap), (origin[0], origin[1] - 2 * gap) ] polygon2 = Polygon(outer_corners) polygon = polygon1.union(polygon2) layout_fixed = layout.difference(polygon) return layout_fixed