def _example(): from gdshelpers.geometry.chip import Cell devicename = 'MZI' mzi = MachZehnderInterferometer(origin=(0, 0), angle=0, width=1.2, splitter_length=10, splitter_separation=5, bend_radius=50, upper_vertical_length=50, lower_vertical_length=0, horizontal_length=0) mzi_mmi = MachZehnderInterferometerMMI(origin=(300, 0), angle=0, width=1.2, splitter_length=33, splitter_width=7.7, bend_radius=50, upper_vertical_length=50, lower_vertical_length=0, horizontal_length=0) print(mzi_mmi.device_width) wg = Waveguide.make_at_port(mzi_mmi.port) wg.add_straight_segment(length=50) cell = Cell(devicename) cell.add_to_layer(1, mzi) cell.add_to_layer(1, mzi_mmi) cell.add_to_layer(1, wg) cell.save('%s.gds' % devicename)
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 generate_bunch_of_guides(number_of_lines, line_widths, length): guides = Cell('guides') line_widths = iop.fill_list(number_of_lines, line_widths, sorting='ascending') for y in range(0, number_of_lines): guide = Waveguide.make_at_port(Port((0, y*5), 0, line_widths[y])) guide.add_straight_segment(length) guides.add_to_layer(1, guide) return guides
def test_coupler_apodized_period(self): coupler1 = GratingCoupler.make_traditional_coupler( origin=[0, 0], width=1, full_opening_angle=np.deg2rad(40), grating_period=3, grating_ff=0.5, n_gratings=22, ap_max_ff=0.25, n_ap_gratings=10, taper_length=22, angle=-0.5 * np.pi, ap_start_period=1., ) coupler2 = GratingCoupler.make_traditional_coupler( origin=[100, 0], width=1, full_opening_angle=np.deg2rad(40), grating_period=3, grating_ff=0.5, n_gratings=22, ap_max_ff=0.25, n_ap_gratings=10, taper_length=22, angle=-0.5 * np.pi, ap_start_period=3., ) coupler3 = GratingCoupler.make_traditional_coupler( origin=[200, 0], width=1, full_opening_angle=np.deg2rad(40), grating_period=3, grating_ff=0.5, n_gratings=22, ap_max_ff=0.25, n_ap_gratings=10, taper_length=22, angle=-0.5 * np.pi, ap_start_period=None, ) self.assertAlmostEqual(coupler2.maximal_radius, coupler3.maximal_radius) layout = Cell('LIBRARY') cell = Cell('TOP') cell.add_to_layer(1, coupler1) cell.add_to_layer(1, coupler2) cell.add_to_layer(1, coupler3) layout.add_cell(cell)
def test_bounds_subcell(self): cell = Cell('test_cell') subcell = Cell('subcell') subcell.add_to_layer(3, box(0, 0, 100, 100)) cell.add_cell(subcell, origin=(100, 100)) self.assertEqual(cell.bounds, (100, 100, 200, 200)) cell.add_cell(subcell, origin=(500, 100), angle=np.pi) # cell.save('test_bounds_subcell') self.assertEqual(cell.bounds, (100, 0, 500, 200))
def test_frame(self): # Add frame cell = Cell('test_frame') cell.add_to_layer(4, box(0, 0, 10, 10)) cell.add_frame(padding=10, line_width=1., frame_layer=5) self.assertEqual(cell.bounds, (-11, -11, 21, 21)) self.assertEqual(cell.get_bounds(layers=[4]), (0, 0, 10, 10)) self.assertEqual(cell.get_bounds(layers=[5]), (-11, -11, 21, 21)) cell.add_frame(padding=10, line_width=1., frame_layer=99, bounds=(0, 0, 2, 3)) self.assertEqual(cell.get_bounds(layers=[99]), (-11, -11, 13, 14))
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_parallel_export(self): waveguide = Waveguide([0, 0], 0, 1) for i_bend in range(9): waveguide.add_bend(angle=np.pi, radius=60 + i_bend * 40) cells = [Cell('main')] for i in range(10): cell = Cell('sub_cell_' + str(i)) cell.add_to_layer(waveguide) cells[-1].add_cell(cell, (10, 10)) cells[0].save('serial.gds', library='gdshelpers', parallel=False) cells[0].save('parallel.gds', library='gdshelpers', parallel=True) self.assertTrue(filecmp.cmp('serial.gds', 'parallel.gds'))
def generate_layout_cell(size=50, line_width=10): cell = Cell('templateMembraneAlign, size = {}, line_width = {}'.format( size, line_width)) # ring, ring_location = iop.port_ring(15, 10, offset=(100, 200)) corners = [-30, -10, -30, 10, 30, 10, 30, -10] shape, shape_port = iop.port_shape_cartesian(corners, rotate=np.pi * 0, port=Port((-100, 250), 0, 1), offset=(100, 200)) # ============================================ cell.add_to_layer(1, shape) return cell
def _example(): from gdshelpers.geometry.chip import Cell kit_logo = KITLogo([0, 0], 1) wwu_logo = WWULogo([0, 0], 1, 1) cell = Cell('LOGOS') cell.add_to_layer(1, kit_logo) cell.add_to_layer(1, translate(wwu_logo.get_shapely_object(), 2.5)) cell.show()
def _example(): text = Text([100, 100], 10, 'The quick brown fox jumps over the lazy dog\n123\n4567', alignment='left-bottom', angle=0.1) print(text.bounding_box) from gdshelpers.geometry.chip import Cell cell = Cell('FONTS') cell.add_to_layer(2, shapely.geometry.box(*text.bounding_box.reshape(4))) cell.add_to_layer(1, text) cell.show()
def _example(): from gdshelpers.geometry.chip import Cell cell = Cell('test') wg1 = Waveguide.make_at_port(Port((0, 0), 0, 1.)) wg1.add_straight_segment(100) ring1 = RingResonator.make_at_port(wg1.current_port, 1., 50., race_length=30, straight_feeding=True, draw_opposite_side_wg=True) wg2 = Waveguide.make_at_port(ring1.port) wg2.add_straight_segment(100) ring2 = RingResonator.make_at_port(wg2.current_port, 1., 50., vertical_race_length=30, straight_feeding=True, draw_opposite_side_wg=True) wg3 = Waveguide.make_at_port(ring2.port) wg3.add_straight_segment(100) ring3 = RingResonator.make_at_port(wg3.current_port, -1., 50., vertical_race_length=30, straight_feeding=True, draw_opposite_side_wg=True) cell.add_to_layer(1, wg1, ring1, wg2, ring2, wg3, ring3) cell.show()
def _example(): from gdshelpers.geometry.chip import Cell from gdshelpers.parts.port import Port from gdshelpers.parts.waveguide import Waveguide from gdshelpers.parts.mode_converter import StripToSlotModeConverter wg_1 = Waveguide.make_at_port( Port(origin=(0, 0), angle=0, width=1.2)) # scalar as width -> strip waveguide wg_1.add_straight_segment(5) mc_1 = StripToSlotModeConverter.make_at_port( wg_1.current_port, 5, [0.4, 0.2, 0.4], 2, 0.2) # array as width -> slot waveguide wg_2 = Waveguide.make_at_port(mc_1.out_port) wg_2.add_bend(angle=np.pi, radius=5) mc_2 = StripToSlotModeConverter.make_at_port( wg_2.current_port, 5, 1, 2, 0.2) # scalar as width -> strip waveguide wg_3 = Waveguide.make_at_port(mc_2.out_port) wg_3.add_straight_segment(5) cell = Cell('CELL') cell.add_to_layer(1, wg_1, mc_1, wg_2, mc_2, wg_3) cell.show()
def test_empty_cell(self): # An empty cell should have 'None' as bounding box cell = Cell('test_cell') # self.assertEqual(cell.bounds, None) cell.add_to_layer(4, box(60, 0, 70, 10)) self.assertEqual(cell.bounds, (60, 0, 70, 10)) subcell = Cell('subcell') cell.add_cell(subcell, origin=(0, 0)) # bounding box of cell should still be the the original bbox self.assertEqual(cell.bounds, (60, 0, 70, 10))
def _example(): from gdshelpers.geometry.chip import Cell img = GdsImage([0, 0], "wolfram_monochrome_100.png", 10) cell = Cell('TEST_IMAGE') cell.add_to_layer(1, img) cell.show() return cell
def _example(): layout = GridLayout('Test layout\nwith very cool features' + 'long! ' * 50, tight=False, region_layer_type=None) layout.add_column_label_row(['c0', 'c1'], 'col_labels') layout.begin_new_row('row1') test_cell_1 = Cell('TC1') test_cell_1.add_to_layer(1, shapely.geometry.box(0, 00, 335, 125)) test_cell_2 = Cell('TC2') # test_cell_2.add_to_layer(1, shapely.geometry.box(101, 101, 335, 125)) test_cell_2.add_to_layer(1, shapely.geometry.box(0, 0, 600, 400)) layout.add_to_row(test_cell_1, realign=False) # , alignment='left-bottom') layout.add_to_row(test_cell_1, realign=True) # , alignment='center-center') layout.begin_new_row('row2') layout.add_to_row(test_cell_2, realign=True) # , alignment='left-bottom') layout.add_to_row(test_cell_2, realign=True) # , alignment='left-bottom') layout.add_to_row(test_cell_2, realign=True) # , alignment='left-bottom') layout.add_to_row(test_cell_2, realign=True) # , alignment='left-bottom') layout.add_to_row(test_cell_2, realign=True) # , alignment='left-bottom') layout.add_to_row(test_cell_2, realign=True) # , alignment='left-bottom') layout.add_to_row(test_cell_2, realign=True) # , alignment='left-bottom') layout.begin_new_row('row3') layout.add_to_row(test_cell_2, realign=True) # , alignment='left-bottom') layout.add_to_row(test_cell_2, realign=True) # , alignment='left-bottom') layout.add_to_row(test_cell_2, realign=True) # , alignment='left-bottom') layout.add_to_row(test_cell_2, realign=True) # , alignment='left-bottom') layout.add_to_row(test_cell_2, realign=True) # , alignment='left-bottom') layout.add_to_row(test_cell_2, realign=True) # , alignment='left-bottom') layout.add_to_row(test_cell_2, realign=True) # , alignment='left-bottom') # layout.add_to_row(test_cell_1, realign=True)#, alignment='left-bottom') layout_cell, mapping = layout.generate_layout() layout_cell.show() layout_cell.save()
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()
import numpy as np from gdshelpers.geometry.chip import Cell from gdshelpers.parts.text import Text from gdshelpers.parts.marker import DLWMarker, SquareMarker, CrossMarker from gdshelpers.parts.waveguide import Waveguide from gdshelpers.parts.port import Port from gdshelpers.geometry.shapely_adapter import geometric_union from gdshelpers.parts.coupler import GratingCoupler from gdshelpers.parts.spiral import Spiral from shapely.geometry import Polygon from utils import * from parts import interferometer_and_fiber_array cell = Cell('4x4 interferometer') wg_width = 0.5 electrode_wg_sep = 62.5 second_x_middle = 8 * 2 * 127 inport_0 = Port((-electrode_wg_sep / 2 - 25, 0), np.pi / 2, wg_width) inport_1 = Port((-electrode_wg_sep / 2, 0), np.pi / 2, wg_width) inport_2 = Port((electrode_wg_sep / 2, 0), np.pi / 2, wg_width) inport_3 = Port((electrode_wg_sep / 2 + 25, 0), np.pi / 2, wg_width) device_inports = [inport_0, inport_1, inport_2, inport_3] # fiber_array gc_pitch = 127 wg_sep = 25 min_radius = 50 starting_point = second_x_middle / 2 - gc_pitch * 3.5 gc_y = 100
(timestamp, ) * num): outfile.write(binary) else: for c in cells: outfile.write( _cell_to_gdsii_binary(c, grid_steps_per_unit, max_points, max_line_points, timestamp)) outfile.write(pack('>2H', 4, 0x0400)) # ENDLIB N0_DATA if __name__ == '__main__': from gdshelpers.parts.port import Port from gdshelpers.parts.waveguide import Waveguide from gdshelpers.geometry.chip import Cell device_cell = Cell('cell') start_port = Port(origin=(10, 0), width=1, angle=0) waveguide = Waveguide.make_at_port(start_port) for i_bend in range(9): waveguide.add_bend(angle=np.pi, radius=60 + i_bend * 40) device_cell.add_dlw_taper_at_port('A', 2, waveguide.in_port, 30) device_cell.add_dlw_taper_at_port('B', 2, waveguide.current_port, 30) device_cell.add_to_layer(1, waveguide) sub_cell = Cell('sub_cell') sub_cell.add_to_layer(1, waveguide) sub_cell.add_to_layer(3, LineString(((0, 0), (100, 100)))) line = LineString(((0, 0), (-100, 100))) line.width = 3
# fiber_array gc_pitch = 127 wg_sep = 25 min_radius = 70 gc_starting_point = second_x_middle / 2 - gc_pitch * 3.5 gc_starting_point_2 = (0.5 * (first_x_middle_2 + second_x_middle_2) - gc_pitch * 3.5) gc_y = 100 grating_coupler_positions = [(gc_starting_point + idx * gc_pitch, gc_y) for idx in range(8)] grating_coupler_positions_2 = [(gc_starting_point_2 + idx * gc_pitch, gc_y) for idx in range(8)] # Adding Left 4x4 interferometer left4x4_cell = Cell('4x4 interferometer_Left') left_electrode_wf_layers = np.arange(110, 140 + 1, 10) right_electrode_wf_layers = np.arange(150, 200 + 1, 10) _, left_init_wf_point, left_in_bounds = interferometer_and_fiber_array( cell=left4x4_cell, inports=device_inports, gc_positions=grating_coupler_positions, electrode_length=1250, coupler_sep=0.5, coupler_length=30, sm_wg_width=wg_width, delay_lines=False, wg_layer=9, wf_layer=100,
datatype) if sub_geometry.is_empty: continue sub_geometry = scale( sub_geometry, *[reference.magnification] * 2) if reference.magnification else sub_geometry sub_geometry = scale( sub_geometry, -1) if reference.x_reflection else sub_geometry sub_geometry = rotate( sub_geometry, reference.rotation, origin=(0, 0)) if reference.rotation else sub_geometry sub_geometry = translate(sub_geometry, *reference.origin) geometry.extend(sub_geometry) return MultiPolygon(geometry) def get_shapely_object(self): return self.get_as_shapely(self.cell_name, self.layer, self.datatype) if __name__ == '__main__': from gdshelpers.parts.waveguide import _example from gdshelpers.geometry.chip import Cell _example() # make sure the "output.gds" exists test_cell = Cell('test') test_cell.add_to_layer(1, GDSIIImport('output.gds', cell_name='TOP', layer=1)) test_cell.show()
def _example(): from gdshelpers.geometry.chip import Cell from gdshelpers.parts.splitter import Splitter from gdshelpers.parts.coupler import GratingCoupler port = Port([0, 0], 0, 1) path = Waveguide.make_at_port(port) path.add_straight_segment(10) path.add_bend(np.pi / 2, 10, final_width=0.5) path.add_bend(-np.pi / 2, 10, final_width=1) path.add_arc( np.pi * 3 / 4, 10, ) splitter = Splitter.make_at_root_port(path.current_port, 30, 10) path2 = Waveguide.make_at_port(splitter.right_branch_port) path2.add_bend(-np.pi / 4, 10) n = 10 path2.add_parameterized_path( lambda t: (n * 10 * t, np.cos(n * 2 * np.pi * t) - 1), path_derivative=lambda t: (n * 10, -n * 2 * np.pi * np.sin(n * 2 * np.pi * t)), width=lambda t: np.cos(n * 2 * np.pi * t) * 0.2 + np.exp(-t ) * 0.3 + 0.5, width_function_supports_numpy=True) path2.add_straight_segment(10, width=[.5, .5, .5]) print(path2.length) print(path2.length_last_segment) path2.add_cubic_bezier_path((0, 0), (5, 0), (10, 10), (5, 10)) path2.add_bend(-np.pi, 40) coupler1 = GratingCoupler([100, 50], 0, 1, np.deg2rad(30), [10, 0.1, 2, 0.1, 2], start_radius_absolute=True) path3 = Waveguide((0, -50), np.deg2rad(0), 1) path3.add_bezier_to(coupler1.port.origin, coupler1.port.inverted_direction.angle, bend_strength=50) splitter2 = Splitter.make_at_left_branch_port(splitter.left_branch_port, 30, 10, wavelength_root=2) path4 = Waveguide.make_at_port(splitter2.root_port) path4.add_straight_segment(20) path4.width = 1 path4.add_straight_segment(20) empty_path = Waveguide.make_at_port(path4.current_port) whole_layout = (path, splitter, path2, splitter2, coupler1, path3, path4, empty_path) layout = Cell('LIBRARY') cell = Cell('TOP') cell.add_to_layer(1, *whole_layout) cell.add_to_layer(2, empty_path) cell.add_to_layer(4, splitter.root_port.debug_shape) layout.add_cell(cell) cell_df = Cell('TOP_DF') cell_df.add_to_layer( 1, convert_to_positive_resist(whole_layout, buffer_radius=1.5)) layout.add_cell(cell_df) layout.save('output.gds') cell.show()
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 _example(): from gdshelpers.geometry.chip import Cell from gdshelpers.geometry import geometric_union # Generate a coupler, which ought to be identical to # coupler_sn330_1550_bf_ff_ap( 0:0 1550 0.7 22 0.96 10 22 1 "active") # also known as # coupler_bf_ap_mff( 0:0 1 40.0 1.13 0.7 22 0.96 10 22 200 "active") coupler = GratingCoupler.make_traditional_coupler([150, 0], 1, np.deg2rad(40), 1.13, 0.7, 22, 0.96, 10, 22, angle=-np.pi) coupler2 = GratingCoupler.make_traditional_coupler_from_database([0, 0], 1, 'sn330', 1550) print(coupler.get_description_str()) whole_layout = (coupler, coupler2) layout = Cell('LIBRARY') cell = Cell('TOP') cell.add_to_layer(1, *whole_layout) cell.add_to_layer(StandardLayers.parnamelayer1, coupler.get_description_text()) cell.add_to_layer(StandardLayers.parnamelayer1, coupler2.get_description_text()) cell.add_to_layer(1, coupler.get_description_text()) cell.add_to_layer(1, coupler2.get_description_text()) cell.add_to_layer(1, coupler2.get_description_text(side='left')) layout.add_cell(cell) # We could also easily generate a dark field layout out of this def make_dark_field(obj, buffer_size=1.5): return obj.buffer(buffer_size).difference(obj) cell_df = Cell('TOP_DF') cell_df.add_to_layer(2, make_dark_field(geometric_union(whole_layout))) layout.add_cell(cell_df) layout.save('coupler.gds') cell.show()
def Demux_active(coupler_sep, coupler_length, Mod_length, electrodes_sep, label, exp_wg_width=wg_Expwidth, grating_coupler_period=std_coupler_params['grating_period']): cell = Cell('Demux_active' + label) x_in = 0 y_in = 0 MZ_length = Mod_length + 50 wg_sep = mod_params['wg_sep'] wg_sep_out = 60 wg_sep_small = 10 wg_width_in_mod = wg_Expwidth taper_length = l_Exptaper ##Generating input and output grating couplers coupler_params = std_coupler_params.copy() coupler_params['grating_period'] = grating_coupler_period for j in range(4): incoupler = GratingCoupler.make_traditional_coupler( (x_in + j * opt_space, y_in), **coupler_params) cell.add_to_layer(wg_layer, incoupler) outcouplers = [] empty_gratcouplers = 0 for j in range(4): outcoupler = GratingCoupler.make_traditional_coupler( (x_in + (j + 4 + empty_gratcouplers) * 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, 2, 3) ] wg = [Waveguide.make_at_port(inport) for inport in inports] x_ref0 = x_in + 1.5 * opt_space # y_ref0 = y_in - 3*bend_r x_refout = x_ref0 + (4 + empty_gratcouplers) * opt_space x_lastout = x_in + (7 + empty_gratcouplers) * opt_space x_centre = (x_in + x_lastout) / 2. y_start_epads = y_in - MZ_length - 930 ########## Input Connections for j in range(4): # 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_bend(np.pi / 2.0, bend_r + j * wg_sep_small) wg[j].add_straight_segment_until_x(x_in - bend_r - 1) wg[j].add_bend(np.pi / 2.0, bend_r + j * wg_sep_small) wg[j].add_straight_segment(grating_added_taper_len + 20) wg[j].add_bend(np.pi / 2.0, bend_r + j * wg_sep_small) wg[j].add_straight_segment_until_x(x_ref0 - (j - 1.5) * wg_sep_out - bend_r) wg[j].add_bend(-np.pi / 2.0, bend_r) y_ref0 = wg[-1].current_port.origin[1] - 1 for j in range(4): wg[j].add_straight_segment_until_y(y_ref0) ########## Zero-th MZI mzi0_xstart = x_ref0 mzi0_ystart = y_ref0 for j in (1, 2): wgAdd_EulerSBend(wg[j], offset=(j - 1.5) * (wg_sep_out - wg_sep), radius=bend_r) ##directional coupler with sinusoidal s-bend x_length = 60 y_length = wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - (j - 1) * ( 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 - 1) * (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_port0 = 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 - 1) * ( 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 - 1) * (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)) wgAdd_EulerSBend(wg[j], offset=-(j - 1.5) * (wg_sep_out - wg_sep), radius=bend_r) mzi0_xend = x_ref0 mzi0_yend = wg[j].current_port.origin[1] for j in (0, 3): wg[j].add_straight_segment(l_Exptaper, final_width=exp_wg_width) wg[j].add_straight_segment_until_y(mzi0_yend + l_Exptaper) wg[j].add_straight_segment(l_Exptaper, final_width=wg_width) ########## Turn for j in range(4): wg[j].add_bend(np.pi / 2.0, bend_r + j * wg_sep_small) wg[j].add_straight_segment(l_Exptaper, final_width=exp_wg_width) wg[j].add_straight_segment_until_x(x_refout - 1.5 * wg_sep_out - bend_r + j * (wg_sep_out - wg_sep_small) - l_Exptaper) wg[j].add_straight_segment(l_Exptaper, final_width=wg_width) wg[j].add_bend(np.pi / 2.0, bend_r + j * wg_sep_small) ########## First MZI (left) mzi1_xstart = wg[0].current_port.origin[0] mzi1_ystart = wg[0].current_port.origin[1] for j in (0, 1): wgAdd_EulerSBend(wg[j], offset=(j - 0.5) * (wg_sep_out - wg_sep), radius=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_port1 = 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)) wgAdd_EulerSBend(wg[j], offset=-(j - 0.5) * (wg_sep_out - wg_sep), radius=bend_r) ########## Second MZI (left) mzi1_xstart = wg[2].current_port.origin[0] mzi1_ystart = wg[2].current_port.origin[1] for j in (2, 3): wgAdd_EulerSBend(wg[j], offset=(j - 2.5) * (wg_sep_out - wg_sep), radius=bend_r) ##directional coupler with sinusoidal s-bend x_length = 60 y_length = wg_sep / 2.0 - (coupler_sep + wg_width) / 2.0 - (j - 2) * ( 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 - 2) * (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_port2 = 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 - 2) * ( 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 - 2) * (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)) wgAdd_EulerSBend(wg[j], offset=-(j - 2.5) * (wg_sep_out - wg_sep), radius=bend_r) ########## Output Connections for j in range(4): wg[j].add_straight_segment((3 - j) * wg_sep_small + 1) wg[j].add_bend(-np.pi / 2.0, bend_r) wg[j].add_straight_segment_until_x(x_lastout + bend_r + 1) wg[j].add_bend(np.pi / 2.0, bend_r + j * wg_sep_small) wg[j].add_straight_segment(grating_added_taper_len + 20) wg[j].add_bend(np.pi / 2.0, bend_r + j * wg_sep_small) wg[j].add_straight_segment_until_x(x_lastout - j * (opt_space) + bend_r + j * wg_sep_small) wg[j].add_bend(np.pi / 2.0, bend_r + j * wg_sep_small) wg[j].add_straight_segment(grating_added_taper_len, final_width=std_coupler_params['width']) # for j in range(4): cell.add_to_layer(wg_layer, wg[j]) ##MODULATORs ELECTRODES 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] - 200 min_safedist_from_wg = 22 x_start_epads = x_centre - 3 * pads_pitch #### ELECTRODES IN ZEROTH MZI x_safe_dist = ref_port0.origin[ 0] - min_safedist_from_wg - pads_width - wg_sep / 2.0 - wg_sep_out ##left ground electrode Inport = Port((ref_port0.origin[0] - electrodes_sep / 2.0 - wg_sep / 2.0, ref_port0.origin[1]), np.deg2rad(-90), electr_width) g_left0 = Waveguide.make_at_port(Inport) g_left0.add_straight_segment(Mod_length - cross_width / 2. - 2 * sep_econns) g_left0._current_port.angle = g_left0.current_port.angle - np.pi / 2.0 g_left0._current_port.origin[ 0] = g_left0.current_port.origin[0] + g_left0.current_port.width / 2.0 g_left0._current_port.width = cross_width g_left0.add_straight_segment_until_x(x_safe_dist + wg_sep_out) g_left0.add_straight_segment(wg_sep, electr_width) g_left0.add_straight_segment_until_x(x_safe_dist) g_left0.add_straight_segment(2 * sep_econns) g_left0._current_port.angle = g_left0.current_port.angle + np.pi / 2.0 g_left0._current_port.origin[ 1] = g_left0.current_port.origin[1] + g_left0.current_port.width / 2.0 g_left0.add_straight_segment_until_y(y_start_epads - 2 * sep_econns) g_left0._current_port.angle = g_left0.current_port.angle + np.pi / 2.0 g_left0._current_port.origin[ 0] = g_left0.current_port.origin[0] - g_left0.current_port.width / 2.0 g_left0._current_port.origin[ 1] = g_left0.current_port.origin[1] + g_left0.current_port.width / 2.0 g_left0.add_straight_segment_until_x(x_start_epads) g_left0._current_port.angle = g_left0.current_port.angle - np.pi / 2.0 g_left0._current_port.origin[0] = g_left0.current_port.origin[ 0] #+ pads_width_gnd / 2.0 # g_left0._current_port.origin[1] = g_left0.current_port.origin[1] + g_left0.current_port.width / 2.0 g_left0._current_port.width = pads_width_gnd g_left0.add_straight_segment(pads_len) cell.add_to_layer(electrode_layer, g_left0) ## signal electrode Inport = Port((ref_port0.origin[0] + wg_sep / 2.0, ref_port0.origin[1]), np.deg2rad(-90), electr_width - electrodes_sep) s0 = Waveguide.make_at_port(Inport) s0.add_straight_segment(Mod_length - cross_width / 2. - sep_econns) s0._current_port.angle = s0.current_port.angle - np.pi / 2.0 s0._current_port.origin[ 0] = s0.current_port.origin[0] + s0.current_port.width / 2.0 s0._current_port.width = cross_width s0.add_straight_segment_until_x(x_safe_dist + wg_sep_out) s0.add_straight_segment(wg_sep, electr_width) s0.add_straight_segment_until_x(x_safe_dist) s0.add_straight_segment(sep_econns) s0._current_port.angle = s0.current_port.angle + np.pi / 2.0 s0._current_port.origin[ 1] = s0.current_port.origin[1] + s0.current_port.width / 2.0 s0.add_straight_segment_until_y(y_start_epads - sep_econns) s0._current_port.angle = s0.current_port.angle + np.pi / 2.0 s0._current_port.origin[ 0] = s0.current_port.origin[0] - s0.current_port.width / 2.0 s0.add_straight_segment_until_x(x_start_epads + pads_pitch) # s0._current_port.angle = s0.current_port.angle - np.pi / 2.0 s0._current_port.origin[0] = s0.current_port.origin[0] #+ pads_width / 2.0 s0._current_port.origin[ 1] = s0.current_port.origin[1] + s0.current_port.width / 2.0 s0._current_port.width = pads_width s0.add_straight_segment_until_y(g_left0.current_port.origin[1] + 50) cell.add_to_layer(electrode_layer, s0) # ##right ground electrode Inport = Port( (ref_port0.origin[0] + wg_sep + wg_sep / 2.0 + electrodes_sep / 2.0, ref_port0.origin[1]), np.deg2rad(-90), electr_width) g_right0 = Waveguide.make_at_port(Inport) g_right0.add_straight_segment(Mod_length - cross_width / 2.) g_right0._current_port.angle = g_right0.current_port.angle - np.pi / 2.0 g_right0._current_port.origin[0] = g_right0.current_port.origin[ 0] + g_right0.current_port.width / 2.0 g_right0._current_port.width = cross_width g_right0.add_straight_segment_until_x(x_safe_dist + wg_sep_out) g_right0.add_straight_segment(wg_sep, electr_width) g_right0.add_straight_segment_until_x(x_safe_dist) g_right0._current_port.angle = g_right0.current_port.angle + np.pi / 2.0 g_right0._current_port.origin[1] = g_right0.current_port.origin[ 1] + g_right0.current_port.width / 2.0 g_right0.add_straight_segment_until_y(y_start_epads) g_right0._current_port.angle = g_right0.current_port.angle + np.pi / 2.0 g_right0._current_port.origin[0] = g_right0.current_port.origin[ 0] - g_right0.current_port.width / 2.0 g_right0.add_straight_segment_until_x(x_start_epads + 2 * pads_pitch) g_right0._current_port.angle = g_right0.current_port.angle - np.pi / 2.0 g_right0._current_port.origin[0] = g_right0.current_port.origin[ 0] #+ 5. #+ pads_width_gnd / 2.0 g_right0._current_port.origin[1] = g_right0.current_port.origin[ 1] + g_right0.current_port.width / 2.0 g_right0._current_port.width = pads_width_gnd g_right0.add_straight_segment_until_y(g_left0.current_port.origin[1]) g_right0._current_port.angle = g_right0.current_port.angle - np.pi / 2.0 g_right0._current_port.origin[0] = g_right0.current_port.origin[ 0] + g_right0.current_port.width / 2.0 g_right0._current_port.width = pads_width / 2. g_right0._current_port.origin[1] = g_right0.current_port.origin[ 1] - g_right0._current_port.width / 2. # g_right0.add_straight_segment(2 * pads_pitch + pads_width) g_right0.add_straight_segment(2 * pads_pitch + pads_width_gnd) cell.add_to_layer(electrode_layer, g_right0) # #### ELECTRODES FOR FIRST MZI elec_offset = 90 x_safe_dist = ref_port1.origin[ 0] + min_safedist_from_wg + pads_width + wg_sep / 2.0 + 2 * wg_sep_out ##right ground electrode Inport = Port( (ref_port1.origin[0] + wg_sep - wg_sep / 2.0 + electrodes_sep / 2.0, ref_port1.origin[1] + MZ_length - elec_offset), np.deg2rad(-90), electr_width) g_right1 = Waveguide.make_at_port(Inport) g_right1.add_straight_segment(Mod_length - cross_width / 2. - 2 * sep_econns) g_right1._current_port.angle = g_right1.current_port.angle + np.pi / 2.0 g_right1._current_port.origin[0] = g_right1.current_port.origin[ 0] - g_right1.current_port.width / 2.0 g_right1._current_port.width = cross_width g_right1.add_straight_segment_until_x(x_safe_dist - wg_sep_out) g_right1.add_straight_segment(wg_sep, electr_width) g_right1.add_straight_segment_until_x(x_safe_dist) g_right1.add_straight_segment(2 * sep_econns) g_right1._current_port.angle = g_right1.current_port.angle - np.pi / 2.0 g_right1._current_port.origin[1] = g_right1.current_port.origin[ 1] + g_right1.current_port.width / 2.0 g_right1.add_straight_segment_until_y(y_start_epads - 2 * sep_econns) g_right1._current_port.angle = g_right1.current_port.angle - np.pi / 2.0 g_right1._current_port.origin[0] = g_right1.current_port.origin[ 0] + g_right1.current_port.width / 2.0 g_right1.add_straight_segment_until_x(x_start_epads + 4 * pads_pitch) g_right1._current_port.angle = g_right1.current_port.angle + np.pi / 2.0 g_right1._current_port.origin[0] = g_right1.current_port.origin[ 0] #+ 5. #+ pads_width_gnd / 2.0 g_right1._current_port.origin[1] = g_right1.current_port.origin[ 1] + g_right1.current_port.width / 2.0 g_right1._current_port.width = pads_width_gnd g_right1.add_straight_segment_until_y(g_left0.current_port.origin[1]) g_right1._current_port.angle = g_right1.current_port.angle - np.pi / 2.0 g_right1._current_port.origin[0] = g_right1.current_port.origin[ 0] + g_right1.current_port.width / 2.0 g_right1._current_port.width = pads_width / 2. g_right1._current_port.origin[1] = g_right1.current_port.origin[ 1] - g_right1._current_port.width / 2. g_right1.add_straight_segment(2 * pads_pitch + pads_width) cell.add_to_layer(electrode_layer, g_right1) ## signal electrode Inport = Port((ref_port1.origin[0] - wg_sep / 2.0, ref_port1.origin[1] + MZ_length - elec_offset), np.deg2rad(-90), electr_width - electrodes_sep) s1 = Waveguide.make_at_port(Inport) s1.add_straight_segment(Mod_length - cross_width / 2. - sep_econns) s1._current_port.angle = s1.current_port.angle + np.pi / 2.0 s1._current_port.origin[ 0] = s1.current_port.origin[0] - s1.current_port.width / 2.0 s1._current_port.width = cross_width s1.add_straight_segment_until_x(x_safe_dist - wg_sep_out) s1.add_straight_segment(wg_sep, electr_width) s1.add_straight_segment_until_x(x_safe_dist) s1.add_straight_segment(sep_econns) s1._current_port.angle = s1.current_port.angle - np.pi / 2.0 s1._current_port.origin[ 1] = s1.current_port.origin[1] + s1.current_port.width / 2.0 s1.add_straight_segment_until_y(y_start_epads - sep_econns) s1._current_port.angle = s1.current_port.angle - np.pi / 2.0 s1._current_port.origin[ 0] = s1.current_port.origin[0] + s1.current_port.width / 2.0 s1.add_straight_segment_until_x(x_start_epads + 3 * pads_pitch) s1._current_port.angle = s1.current_port.angle + np.pi / 2.0 s1._current_port.origin[0] = s1.current_port.origin[0] #+ pads_width / 2.0 s1._current_port.origin[ 1] = s1.current_port.origin[1] + s1.current_port.width / 2.0 s1._current_port.width = pads_width s1.add_straight_segment_until_y(g_left0.current_port.origin[1] + 50) cell.add_to_layer(electrode_layer, s1) # ##left ground electrode Inport = Port( (ref_port1.origin[0] - wg_sep - wg_sep / 2.0 - electrodes_sep / 2.0, ref_port1.origin[1] + MZ_length - elec_offset), np.deg2rad(-90), electr_width) g_left1 = Waveguide.make_at_port(Inport) g_left1.add_straight_segment(Mod_length - cross_width / 2.) g_left1._current_port.angle = g_left1.current_port.angle + np.pi / 2.0 g_left1._current_port.origin[ 0] = g_left1.current_port.origin[0] - g_left1.current_port.width / 2.0 g_left1._current_port.width = cross_width g_left1.add_straight_segment_until_x(x_safe_dist - wg_sep_out) g_left1.add_straight_segment(wg_sep, electr_width) g_left1.add_straight_segment_until_x(x_safe_dist) g_left1._current_port.angle = g_left1.current_port.angle - np.pi / 2.0 g_left1._current_port.origin[ 1] = g_left1.current_port.origin[1] + g_left1.current_port.width / 2.0 g_left1.add_straight_segment_until_y(y_start_epads) g_left1._current_port.angle = g_left1.current_port.angle - np.pi / 2.0 g_left1._current_port.origin[ 0] = g_left1.current_port.origin[0] + g_left1.current_port.width / 2.0 g_left1.add_straight_segment_until_x(x_start_epads + 2 * pads_pitch) # g_left1._current_port.angle = g_left1.current_port.angle + np.pi / 2.0 # g_left1._current_port.origin[0] = g_left1.current_port.origin[0] + pads_width_gnd / 2.0 # g_left1._current_port.origin[1] = g_left1.current_port.origin[1] + g_left1.current_port.width / 2.0 # g_left1._current_port.width = pads_width_gnd # g_left1.add_straight_segment_until_y(g_left0.current_port.origin[1]) cell.add_to_layer(electrode_layer, g_left1) # #### ELECTRODES FOR SECOND MZI # x_safe_dist = x_safe_dist + 3*sep_econns ##right ground electrode Inport = Port( (ref_port2.origin[0] + wg_sep - wg_sep / 2.0 + electrodes_sep / 2.0, ref_port2.origin[1] + elec_offset), np.deg2rad(90), electr_width) g_right2 = Waveguide.make_at_port(Inport) g_right2.add_straight_segment(Mod_length - cross_width / 2. - 2 * sep_econns) g_right2._current_port.angle = g_right2.current_port.angle - np.pi / 2.0 g_right2._current_port.origin[0] = g_right2.current_port.origin[ 0] - g_right2.current_port.width / 2.0 g_right2._current_port.width = cross_width g_right2.add_straight_segment_until_x(x_safe_dist - wg_sep_out) g_right2.add_straight_segment(wg_sep, electr_width) g_right2.add_straight_segment_until_x(x_safe_dist) g_right2.add_straight_segment(3 * sep_econns) g_right2._current_port.angle = g_right2.current_port.angle - np.pi / 2.0 g_right2._current_port.origin[1] = g_right2.current_port.origin[ 1] + g_right2.current_port.width / 2.0 g_right2.add_straight_segment_until_y(y_start_epads - 2 * sep_econns) g_right2._current_port.angle = g_right2.current_port.angle - np.pi / 2.0 g_right2._current_port.origin[0] = g_right2.current_port.origin[ 0] + g_right2.current_port.width / 2.0 g_right2.add_straight_segment_until_x(x_start_epads + 4 * pads_pitch) # g_right2._current_port.angle = g_right2.current_port.angle + np.pi / 2.0 # g_right2._current_port.origin[0] = g_right2.current_port.origin[0] #+ pads_width_gnd / 2.0 # g_right2._current_port.origin[1] = g_right2.current_port.origin[1] + g_right2.current_port.width / 2.0 # g_right2._current_port.width = pads_width_gnd # g_right2.add_straight_segment_until_y(g_left0.current_port.origin[1]) cell.add_to_layer(electrode_layer, g_right2) ## signal electrode Inport = Port((ref_port2.origin[0] - wg_sep / 2.0, ref_port2.origin[1] + elec_offset), np.deg2rad(90), electr_width - electrodes_sep) s2 = Waveguide.make_at_port(Inport) s2.add_straight_segment(Mod_length - cross_width / 2. - sep_econns) s2._current_port.angle = s2.current_port.angle - np.pi / 2.0 s2._current_port.origin[ 0] = s2.current_port.origin[0] - s2.current_port.width / 2.0 s2._current_port.width = cross_width s2.add_straight_segment_until_x(x_safe_dist - wg_sep_out) s2.add_straight_segment(wg_sep, electr_width) s2.add_straight_segment_until_x(x_safe_dist) s2.add_straight_segment(4 * sep_econns) s2._current_port.angle = s2.current_port.angle - np.pi / 2.0 s2._current_port.origin[ 1] = s2.current_port.origin[1] + s2.current_port.width / 2.0 s2.add_straight_segment_until_y(y_start_epads - 3 * sep_econns) s2._current_port.angle = s2.current_port.angle - np.pi / 2.0 s2._current_port.origin[ 0] = s2.current_port.origin[0] + s2.current_port.width / 2.0 s2.add_straight_segment_until_x(x_start_epads + 5 * pads_pitch) # s2._current_port.angle = s2.current_port.angle + np.pi / 2.0 s2._current_port.origin[0] = s2.current_port.origin[0] #+ pads_width / 2.0 s2._current_port.origin[ 1] = s2.current_port.origin[1] + s2.current_port.width / 2.0 s2._current_port.width = pads_width s2.add_straight_segment_until_y(g_left0.current_port.origin[1] + 50) cell.add_to_layer(electrode_layer, s2) # ##left ground electrode Inport = Port( (ref_port2.origin[0] - wg_sep - wg_sep / 2.0 - electrodes_sep / 2.0, ref_port2.origin[1] + elec_offset), np.deg2rad(90), electr_width) g_left2 = Waveguide.make_at_port(Inport) g_left2.add_straight_segment(Mod_length - cross_width / 2.) g_left2._current_port.angle = g_left2.current_port.angle - np.pi / 2.0 g_left2._current_port.origin[ 0] = g_left2.current_port.origin[0] - g_left2.current_port.width / 2.0 g_left2._current_port.width = cross_width g_left2.add_straight_segment_until_x(x_safe_dist - wg_sep_out) g_left2.add_straight_segment(wg_sep, electr_width) g_left2.add_straight_segment_until_x(x_safe_dist) g_left2.add_straight_segment(5 * sep_econns) g_left2._current_port.angle = g_left2.current_port.angle - np.pi / 2.0 g_left2._current_port.origin[ 1] = g_left2.current_port.origin[1] + g_left2.current_port.width / 2.0 g_left2.add_straight_segment_until_y(y_start_epads - 4 * sep_econns) g_left2._current_port.angle = g_left2.current_port.angle - np.pi / 2.0 g_left2._current_port.origin[ 0] = g_left2.current_port.origin[0] + g_left2.current_port.width / 2.0 # g_left2._current_port.origin[1] = g_left2.current_port.origin[1] + g_left2.current_port.width / 2.0 g_left2.add_straight_segment_until_x(x_start_epads + 6 * pads_pitch) g_left2._current_port.origin[ 1] = g_left2.current_port.origin[1] - g_left2.current_port.width / 2.0 g_left2._current_port.angle = g_left2.current_port.angle + np.pi / 2.0 g_left2._current_port.origin[0] = g_left2.current_port.origin[ 0] #+ 5. #+ pads_width_gnd / 2.0 g_left2._current_port.origin[ 1] = g_left2.current_port.origin[1] + g_left2.current_port.width g_left2._current_port.width = pads_width_gnd g_left2.add_straight_segment_until_y(g_left0.current_port.origin[1]) g_left2._current_port.angle = g_left2.current_port.angle - np.pi / 2.0 g_left2._current_port.origin[ 0] = g_left2.current_port.origin[0] + g_left2.current_port.width / 2.0 g_left2._current_port.width = pads_width / 2. g_left2._current_port.origin[ 1] = g_left2.current_port.origin[1] - g_left2._current_port.width / 2. g_left2.add_straight_segment(2 * pads_pitch + pads_width) cell.add_to_layer(electrode_layer, g_left2) # # # # ###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 = ('Mod_length = %.1f um\nElectrodes_sep = %.1f nm\nCoupler_length= %.1f um\n') \ % (Mod_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
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 ####################################################################################### if __name__ == "__main__": devices = [] #### ADD Modulators global_cell = Cell('Demux_Tests') # global_cell.add_to_layer(marker_protection_layer, device.get_markers_protection()) coupler_sep = 0.5 coupler_length = 30 electrodes_sep = 1.1 for j, MZ_length in enumerate(np.linspace(1250, 1500, 2)): temp_cell = Demux_active(coupler_sep, coupler_length, MZ_length, electrodes_sep, 'D%i' % j) temp_cell.name = 'Demux_test_' + str(j) # global_cell.add_cell(temp_cell, origin=(-2000 + j * 1000, -1500), angle=np.pi) global_cell.add_cell(temp_cell, origin=(-2000 + j * 3000, -1500)) print('starting device saving')
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
x_off = self.origin[0] + np.cos(self._angle) * x - np.sin( self._angle) * y y_off = self.origin[1] + np.sin(self._angle) * x + np.cos( self._angle) * y return Port((x_off, y_off), self._angle - np.pi / 2, self._outer_channel_width) if __name__ == '__main__': from gdshelpers.geometry.chip import Cell part1 = Ntron(origin=(5, -5), angle=0, gate_width_1=0.3, gate_width_2=0.06, choke_width_1=0.06, choke_width_2=0.015, choke_length_2=0.06, choke_length_3=0.03) wgdrain = Waveguide.make_at_port(part1.port_drain) wgdrain.add_straight_segment(0.5) wggate = Waveguide.make_at_port(part1.port_gate) wggate.add_straight_segment(0.5) wgsource = Waveguide.make_at_port(part1.port_source) wgsource.add_straight_segment(0.5) cell = Cell('_channel') cell.add_to_layer(1, part1) cell.show()
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 ####################################################################################### if __name__ == "__main__": devices = [] #### ADD Modulators global_cell = Cell('Modulators_Tests') # global_cell.add_to_layer(marker_protection_layer, device.get_markers_protection()) coupler_sep = 0.4 coupler_length = 22 electrodes_sep = 1.1 for j, MZ_length in enumerate(np.linspace(500, 1250, 4)): temp_cell = MZI_active_with_phase(coupler_sep, coupler_length, MZ_length, electrodes_sep, 'D%i' % j) temp_cell.name = 'MZI_test_' + str(j) # global_cell.add_cell(temp_cell, origin=(-2000 + j * 1000, -1500), angle=np.pi) global_cell.add_cell(temp_cell, origin=(-2000 + j * 1000, -1500))