def init_sim(self, **kwargs): """ Initializes the simulation. This has to be done after adding all structures in order to correctly determine the size of the simulation. :param kwargs: Parameters which are directly passed to Meep """ z_min = np.min([ structure['z_min'] for structure in self.structures if structure['structure'] ]) z_max = np.max([ structure['z_max'] for structure in self.structures if structure['structure'] ]) bounds = geometric_union( (geometric_union(x['structure']) for x in self.structures)).bounds size = np.array( (bounds[2] - bounds[0], bounds[3] - bounds[1], (z_max - z_min))) self.center = np.round([(bounds[2] + bounds[0]) / 2, (bounds[3] + bounds[1]) / 2, (z_max + z_min) / 2]) self.size = np.ceil(size + self.padding * 2 + self.pml_thickness * 2) if self.reduce_to_2d: self.center[2] = self.size[2] = 0 structures = [] for structure in self.structures: polygon = geometric_union(structure['structure'] + structure['extra_structures']) \ .buffer(np.finfo(np.float32).eps, resolution=0).simplify(np.finfo(np.float32).eps) objs = shapely_collection_to_basic_objs(polygon) for obj in objs: if obj.is_empty: continue for polygon in fracture_intelligently(obj, np.inf, np.inf): structures += [ mp.Prism(vertices=[ mp.Vector3( *point, 0 if self.reduce_to_2d else structure['z_min']) for point in polygon.exterior.coords[:-1] ], material=structure['material'], height=structure['z_max'] - structure['z_min']) ] self.sim = mp.Simulation(mp.Vector3(*self.size), self.resolution, geometry=structures, geometry_center=mp.Vector3(*self.center), sources=self.sources, boundary_layers=[mp.PML(self.pml_thickness)], **kwargs) self.sim.init_sim()
def create_holes_for_under_etching(underetch_parts, complete_structure, hole_radius, hole_distance, hole_spacing, hole_length=0, cap_style='round'): """ Creates holes around given parts which can be used for underetching processes :param underetch_parts: List of gdshelpers parts around which the holes shall be placed :param complete_structure: geometric union of the complete structure, needed to avoid collisions between underetching holes and other structures, e.g. waveguides :param hole_radius: Radius of the holes in microns :param hole_distance: Distance between the holes edges from the the structures in microns :param hole_spacing: Distance between the holes in microns :param hole_length: Length of the holes (if 0 creates circles, else rectangle like) :param cap_style: CAP_STYLE of the holes (i.e. 'round' or 'square', see Shapely Docs) :return: Geometric union of the created holes """ cap_style = { 'round': CAP_STYLE.round, 'square': CAP_STYLE.square }[cap_style] union = geometric_union(underetch_parts) no_hole_zone = complete_structure.buffer(0.9 * (hole_distance + hole_radius), resolution=32, cap_style=3) poly = union.buffer(hole_distance + hole_radius, resolution=32, cap_style=CAP_STYLE.square) base_polygon = shapely_adapter.shapely_collection_to_basic_objs(poly) holes = [] for obj in base_polygon: for interior in [obj.exterior] + list(obj.interiors): dist = 0 while dist < interior.length: if hole_length == 0: hole = interior.interpolate(distance=dist) dist += hole_spacing + 2 * hole_radius else: positions = [ interior.interpolate(distance=d) for d in np.linspace( dist - hole_length / 2 + hole_radius, dist + hole_length / 2 - hole_radius, 10) ] dist += hole_spacing + hole_length hole = LineString(positions) if not no_hole_zone.contains(hole): holes.append(hole.buffer(hole_radius, cap_style=cap_style)) return geometric_union(holes)
def __init__(self, poly, extrude_val_min, extrude_val_max, rgb=(255, 255, 255)): if type(poly) in (list, tuple): self.poly = shapely_adapter.geometric_union(poly) self.poly = shapely_adapter.shapely_collection_to_basic_objs(poly) self.rgb = rgb self.extrude_val_min = extrude_val_min self.extrude_val_max = extrude_val_max
def get_fractured_layer_dict(self, max_points=4000, max_line_points=4000): from gdshelpers.geometry.shapely_adapter import shapely_collection_to_basic_objs, fracture_intelligently fractured_layer_dict = {} for layer, geometries in self.layer_dict.items(): fractured_geometries = [] for geometry in geometries: geometry = geometry.get_shapely_object() if hasattr(geometry, 'get_shapely_object') else geometry if type(geometry) in [list, tuple]: geometry = geometric_union(geometry) geometry = shapely_collection_to_basic_objs(geometry) geometry = itertools.chain( *[fracture_intelligently(geo, max_points, max_line_points) for geo in geometry if not geo.is_empty]) fractured_geometries.append(geometry) fractured_layer_dict[layer] = itertools.chain(*fractured_geometries) return fractured_layer_dict
def create_holes_for_under_etching(underetch_parts, complete_structure, hole_radius, hole_distance, hole_spacing): """ Creates holes around given parts which can be used for underetching processes :param underetch_parts: List of gdshelpers parts around which the holes shall be placed :param complete_structure: geometric union of the complete structure, needed to avoid collisions between underetching holes and other structures, e.g. waveguides :param hole_radius: Radius of the holes in microns :param hole_distance: Distance of the holes center from the the structures in microns :param hole_spacing: Distance between the holes in microns :return: Geometric union of the created holes """ union = geometric_union(underetch_parts) no_hole_zone = complete_structure.buffer(0.9 * hole_distance, resolution=32, cap_style=3) poly = union.buffer(hole_distance, resolution=32, cap_style=3) base_polygon = shapely_adapter.shapely_collection_to_basic_objs(poly) holes = [] for obj in base_polygon: ext = obj.exterior for dist in np.arange(0, ext.length, hole_spacing): pos = ext.interpolate(distance=dist) if not no_hole_zone.contains(pos): holes.append(pos.buffer(hole_radius)) for interior in obj.interiors: for dist in np.arange(0, interior.length, hole_spacing): pos = interior.interpolate(distance=dist) if not no_hole_zone.contains(pos): holes.append(pos.buffer(hole_radius)) return geometric_union(holes)