def grating_coupler_elliptical2( wgt=wg_strip, theta=np.pi / 4.0, length=30.0, taper_length=10.0, period=1.0, dutycycle=0.7, ridge=True, ridge_layers=(2, 0), teeth_list=None, port=(0, 0), direction="EAST", polarization="te", wavelength=1550, **kwargs ): """ Grating coupler Args: waveguide_template: object or function port (tuple): Cartesian coordinate of the input port direction (string): Direction that the component will point *towards*, can be of type `'NORTH'`, `'WEST'`, `'SOUTH'`, `'EAST'`, OR an angle (float, in radians) theta (float): Angle of the waveguide. Defaults to pi/4.0 length (float): Length of the total grating coupler region, measured from the output port. Defaults to 30.0 taper_length (float): Length of the taper before the grating coupler. Defaults to 10.0 period (float): Grating period. Defaults to 1.0 dutycycle (float): dutycycle, determines the size of the 'gap' by dutycycle=(period-gap)/period. Defaults to 0.7 ridge (boolean): If True, adds another layer to the grating coupler that can be used for partial etched gratings ridge_layers (tuple): Tuple specifying the layer/datatype of the ridge region. Defaults to (3,0) teeth_list (list): Can optionally pass a list of (gap, width) tuples to be used as the gap and teeth widths for irregularly spaced gratings. For example, [(0.6, 0.2), (0.7, 0.3), ...] would be a gap of 0.6, then a tooth of width 0.2, then gap of 0.7 and tooth of 0.3, and so on. Overrides *period*, *dutycycle*, and *length*. Defaults to None. .. plot:: :include-source: import pp c = pp.c.grating_coupler_elliptical2() pp.plotgds(c) """ c = pc.GratingCoupler( pp.call_if_func(wg_strip, **kwargs), theta=theta, length=length, taper_length=taper_length, period=period, dutycycle=dutycycle, ridge=ridge, ridge_layers=ridge_layers, teeth_list=teeth_list, port=port, direction=direction, ) c = picwriter2component(c) c.polarization = polarization c.wavelength = wavelength return c
def disk( radius: float = 10.0, gap: float = 0.2, wrap_angle: int = 0, parity: int = 1, port: Tuple[int, int] = (0, 0), direction: str = "EAST", waveguide_template: Callable = wg_strip, **kwargs ) -> Component: """Disk Resonator Args: radius (float): Radius of the disk resonator gap (float): Distance between the bus waveguide and resonator wrap_angle (float): Angle in radians between 0 and pi (defaults to 0) determines how much the bus waveguide wraps along the resonator. 0 corresponds to a straight bus waveguide, pi corresponds to a bus waveguide wrapped around half of the resonator. parity (1 or -1): If 1, resonator to left of bus waveguide, if -1 resonator to the right port (tuple): Cartesian coordinate of the input port (x1, y1) direction (string): Direction that the component will point *towards*, can be of type 'NORTH'`, `'WEST'`, `'SOUTH'`, `'EAST'`, OR an angle (float, in radians) waveguide_template (WaveguideTemplate): Picwriter WaveguideTemplate object Other Parameters: wg_width: 0.5 wg_layer: pp.LAYER.WG[0] wg_datatype: pp.LAYER.WG[1] clad_layer: pp.LAYER.WGCLAD[0] clad_datatype: pp.LAYER.WGCLAD[1] bend_radius: 10 cladding_offset: 3 .. plot:: :include-source: import pp c = pp.c.disk(radius=10, wrap_angle=3.14/4) pp.plotgds(c) """ c = pc.Disk( pp.call_if_func(wg_strip, **kwargs), radius=radius, coupling_gap=gap, wrap_angle=wrap_angle, parity=parity, port=port, direction=direction, ) return picwriter2component(c)
def coupler_adiabatic(length1: float = 20.0, length2: float = 50.0, length3: float = 30.0, wg_sep: float = 1.0, input_wg_sep: float = 3.0, output_wg_sep: float = 3.0, dw: float = 0.1, port: Tuple[int, int] = (0, 0), direction: str = "EAST", waveguide_template: Callable = wg_strip, **kwargs) -> Component: """ 50/50 adiabatic coupler Adiabatic Coupler Cell class. Design based on asymmetric adiabatic 3dB coupler designs, such as those from https://doi.org/10.1364/CLEO.2010.CThAA2, https://doi.org/10.1364/CLEO_SI.2017.SF1I.5, and https://doi.org/10.1364/CLEO_SI.2018.STh4B.4. Uses Bezier curves for the input, with poles set to half of the x-length of the S-bend. In this design, Region I is the first half of the input S-bend waveguide where the input waveguides widths taper by +dw and -dw, Region II is the second half of the S-bend waveguide with constant, unbalanced widths, Region III is the region where the two asymmetric waveguides gradually come together, Region IV is the coupling region where the waveguides taper back to the original width at a fixed distance from one another, and Region IV is the output S-bend waveguide. Args: length1 (float): Length of the region that gradually brings the two assymetric waveguides together. In this region the waveguide widths gradually change to be different by `dw`. length2 (float): Length of the coupling region, where the asymmetric waveguides gradually become the same width. length3 (float): Length of the output region where the two waveguides separate. wg_sep (float): Distance between the two waveguides, center-to-center, in the coupling region (Region 2). input_wg_sep (float): Separation of the two waveguides at the input, center-to-center. output_wg_sep (float): Separation of the two waveguides at the output, center-to-center. dw (float): Change in waveguide width. In Region 1, the top arm tapers to the waveguide width+dw/2.0, bottom taper to width-dw/2.0. port (tuple): Cartesian coordinate of the input port (top left). Defaults to (0,0). direction (string): Direction that the component will point *towards*, can be of type `'NORTH'`, `'WEST'`, `'SOUTH'`, `'EAST'`, OR an angle (float, in radians). Defaults to 'EAST'. waveguide_template: object or function Other Parameters: wg_width: 0.5 wg_layer: pp.LAYER.WG[0] wg_datatype: pp.LAYER.WG[1] clad_layer: pp.LAYER.WGCLAD[0] clad_datatype: pp.LAYER.WGCLAD[1] bend_radius: 10 cladding_offset: 3 """ c = pc.AdiabaticCoupler( pp.call_if_func(waveguide_template, **kwargs), length1=length1, length2=length2, length3=length3, wg_sep=wg_sep, input_wg_sep=input_wg_sep, output_wg_sep=output_wg_sep, dw=dw, port=port, direction=direction, ) c = picwriter2component(c) c = auto_rename_ports(c) return c
def coupler_full(length: float = 40.0, gap: float = 0.5, dw: float = 0.1, angle: float = np.pi / 6, parity: int = 1, port: Tuple[int, int] = (0, 0), direction: str = "EAST", waveguide_template: Callable = wg_strip, **kwargs) -> Component: """ Adiabatic Full Coupler. Design based on asymmetric adiabatic full coupler designs, such as the one reported in 'Integrated Optic Adiabatic Devices on Silicon' by Y. Shani, et al (IEEE Journal of Quantum Electronics, Vol. 27, No. 3 March 1991). In this design, Region I is the first half of the input S-bend waveguide where the input waveguides widths taper by +dw and -dw, Region II is the second half of the S-bend waveguide with constant, unbalanced widths, Region III is the coupling region where the waveguides from unbalanced widths to balanced widths to reverse polarity unbalanced widths, Region IV is the fixed width waveguide that curves away from the coupling region, and Region V is the final curve where the waveguides taper back to the regular width specified in the waveguide template. Args: length (float): Length of the coupling region. gap (float): Distance between the two waveguides. dw (float): Change in waveguide width. Top arm tapers to the waveguide width - dw, bottom taper to width - dw. angle (float): Angle in radians (between 0 and pi/2) at which the waveguide bends towards the coupling region. Default=pi/6. parity (integer -1 or 1): If -1, mirror-flips the structure so that the input port is actually the *bottom* port. Default = 1. port (tuple): Cartesian coordinate of the input port (AT TOP if parity=1, AT BOTTOM if parity=-1). Defaults to (0,0). direction (string): Direction that the component will point *towards*, can be of type `'NORTH'`, `'WEST'`, `'SOUTH'`, `'EAST'`, OR an angle (float, in radians). Defaults to 'EAST'. waveguide_template (WaveguideTemplate): Picwriter WaveguideTemplate object Other Parameters: wg_width: 0.5 wg_layer: pp.LAYER.WG[0] wg_datatype: pp.LAYER.WG[1] clad_layer: pp.LAYER.WGCLAD[0] clad_datatype: pp.LAYER.WGCLAD[1] bend_radius: 10 cladding_offset: 3 .. plot:: :include-source: import pp c = pp.c.coupler_full(length=40, gap=0.2, dw=0.1) pp.plotgds(c) """ c = pc.FullCoupler( pp.call_if_func(waveguide_template, **kwargs), length=length, gap=gap, dw=dw, angle=angle, parity=parity, port=port, direction=direction, ) return picwriter2component(c)
def spiral(width: float = 500.0, length: float = 10e3, spacing: Optional[float] = None, parity: int = 1, port: Tuple[int, int] = (0, 0), direction: str = "NORTH", waveguide_template: Callable = wg_strip, **kwargs) -> Component: """ Picwriter Spiral Args: width (float): width of the spiral (i.e. distance between input/output ports) length (float): desired length of the waveguide (um) spacing (float): distance between parallel waveguides parity (int): If 1 spiral on right side, if -1 spiral on left side (mirror flip) port (tuple): Cartesian coordinate of the input port direction (string): Direction that the component will point *towards*, can be of type `'NORTH'`, `'WEST'`, `'SOUTH'`, `'EAST'`, OR an angle (float, in radians) waveguide_template (WaveguideTemplate): Picwriter WaveguideTemplate object wg_width: 0.5 wg_layer: pp.LAYER.WG[0] wg_datatype: pp.LAYER.WG[1] clad_layer: pp.LAYER.WGCLAD[0] clad_datatype: pp.LAYER.WGCLAD[1] bend_radius: 10 cladding_offset: 3 .. plot:: :include-source: import pp c = pp.c.spiral(width=500, length=10e3) pp.plotgds(c) """ c = pc.Spiral( pp.call_if_func(waveguide_template, **kwargs), width=width, length=length, spacing=spacing, parity=parity, port=port, direction=direction, ) # print(f'length = {length/1e4:.2f}cm') c = picwriter2component(c) c = auto_rename_ports(c) return c
def dbr2( length: float = 10.0, period: float = 0.85, dc: float = 0.5, w1: float = 0.4, w2: float = 1.0, taper_length: float = 20.0, fins: bool = False, fin_size: Tuple[float, float] = (0.2, 0.05), port: Tuple[int, int] = (0, 0), direction: str = "EAST", waveguide_template: Callable = wg_strip, waveguide_template_dbr: Optional[Callable] = None, **kwargs ) -> Component: """ Distributed Bragg Reflector Cell class. Tapers the input waveguide to a periodic waveguide structure with varying width (1-D photonic crystal). Args: wgt (WaveguideTemplate): WaveguideTemplate object length (float): Length of the DBR region. period (float): Period of the repeated unit. dc (float): Duty cycle of the repeated unit (must be a float between 0 and 1.0). w1 (float): Width of the thin section of the waveguide. w1 = 0 corresponds to disconnected periodic blocks. w2 (float): Width of the wide section of the waveguide taper_length (float): Length of the taper between the input/output waveguide and the DBR region. Defaults to 20.0. fins (boolean): If `True`, adds fins to the input/output waveguides. In this case a different template for the component must be specified. This feature is useful when performing electron-beam lithography and using different beam currents for fine features (helps to reduce stitching errors). Defaults to `False` fin_size ((x,y) Tuple): Specifies the x- and y-size of the `fins`. Defaults to 200 nm x 50 nm dbr_wgt (WaveguideTemplate): If `fins` above is True, a WaveguideTemplate (dbr_wgt) must be specified. This defines the layertype / datatype of the DBR (which will be separate from the input/output waveguides). Defaults to `None` port (tuple): Cartesian coordinate of the input port. Defaults to (0,0). direction (string): Direction that the component will point *towards*, can be of type `'NORTH'`, `'WEST'`, `'SOUTH'`, `'EAST'`, OR an angle (float, in radians) waveguide_template (WaveguideTemplate): Picwriter WaveguideTemplate object wg_width: 0.5 wg_layer: pp.LAYER.WG[0] wg_datatype: pp.LAYER.WG[1] clad_layer: pp.LAYER.WGCLAD[0] clad_datatype: pp.LAYER.WGCLAD[1] bend_radius: 10 cladding_offset: 3 .. code:: period <-----><--------> _________ _______| w1 w2 ... n times _______ |_________ .. plot:: :include-source: import pp c = pp.c.dbr2(length=10, period=0.85, dc=0.5, w2=1, w1=0.4) pp.plotgds(c) """ waveguide_template_dbr = waveguide_template_dbr or waveguide_template(wg_width=w2) c = pc.DBR( wgt=pp.call_if_func(waveguide_template, wg_width=w2, **kwargs), length=length, period=period, dc=dc, w_phc=w1, taper_length=taper_length, fins=fins, fin_size=fin_size, dbr_wgt=waveguide_template_dbr, port=port, direction=direction, ) return picwriter2component(c)
def cdc(length: float = 30.0, gap: float = 0.5, period: float = 0.220, dc: float = 0.5, angle: float = np.pi / 6.0, width_top: float = 2.0, width_bot: float = 0.75, input_bot: bool = False, dw_top: Optional[float] = None, dw_bot: Optional[float] = None, fins: bool = False, fin_size: Tuple[float, float] = (0.2, 0.05), contradc_wgt: None = None, port_midpoint: Tuple[int, int] = (0, 0), direction: str = "EAST", waveguide_template: Callable = wg_strip, **kwargs) -> Component: """Grating-Assisted Contra-Directional Coupler Args: length (float): Length of the coupling region. gap (float): Distance between the two waveguides. period (float): Period of the grating. dc (float): Duty cycle of the grating. Must be between 0 and 1. angle (float): Angle in radians (between 0 and pi/2) at which the waveguide bends towards the coupling region. Default=pi/6. width_top (float): Width of the top waveguide in the coupling region. Defaults to the WaveguideTemplate wg width. width_bot (float): Width of the bottom waveguide in the coupling region. Defaults to the WaveguideTemplate wg width. dw_top (float): Amplitude of the width variation on the top. Default=gap/2.0. dw_bot (float): Amplitude of the width variation on the bottom. Default=gap/2.0. input_bot (boolean): If `True`, will make the default input the bottom waveguide (rather than the top). Default=`False` fins (boolean): If `True`, adds fins to the input/output waveguides. In this case a different template for the component must be specified. This feature is useful when performing electron-beam lithography and using different beam currents for fine features (helps to reduce stitching errors). Defaults to `False` fin_size ((x,y) Tuple): Specifies the x- and y-size of the `fins`. Defaults to 200 nm x 50 nm contradc_wgt (WaveguideTemplate): If `fins` above is True, a WaveguideTemplate (contradc_wgt) must be specified. This defines the layertype / datatype of the ContraDC (which will be separate from the input/output waveguides). Defaults to `None` port_midpoint (tuple): Cartesian coordinate of the input port (AT TOP if input_bot=False, AT BOTTOM if input_bot=True). Defaults to (0,0). direction (string): Direction that the component will point *towards*, can be of type `'NORTH'`, `'WEST'`, `'SOUTH'`, `'EAST'`, OR an angle (float, in radians). Defaults to 'EAST'. waveguide_template (WaveguideTemplate): Picwriter WaveguideTemplate object .. plot:: :include-source: import pp c = pp.c.cdc() pp.plotgds(c) """ c = pc.ContraDirectionalCoupler( pp.call_if_func(wg_strip, **kwargs), length=length, gap=gap, period=period, dc=dc, angle=angle, width_top=width_top, width_bot=width_bot, dw_top=dw_top, dw_bot=dw_bot, input_bot=input_bot, fins=fins, fin_size=fin_size, contradc_wgt=contradc_wgt, port=port_midpoint, direction=direction, ) component = picwriter2component(c) pp.port.rename_ports_by_orientation(component) return component