Example #1
0
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
Example #2
0
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
Example #4
0
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)
Example #5
0
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
Example #6
0
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)
Example #7
0
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