Ring filter

Contents

Ring filter#

Calculations#

For a ring resonator we need to define:

Optical parameters:

  • coupling coefficient: will define resonance extinction ratio for a particular ring loss.

  • Free spectral range.

Electrical parameters:

  • VpiL

  • Resistance

import gdsfactory as gf
import numpy as np


def ring(
    wl: np.ndarray,
    wl0: float,
    neff: float,
    ng: float,
    ring_length: float,
    coupling: float,
    loss: float,
) -> np.ndarray:
    """Returns Frequency Domain Response of an all pass filter.

    Args:
        wl: wavelength in  um.
        wl0: center wavelength at which neff and ng are defined.
        neff: effective index.
        ng: group index.
        ring_length: in um.
        loss: dB/um.

    """
    transmission = 1 - coupling
    neff_wl = (
        neff + (wl0 - wl) * (ng - neff) / wl0
    )  # we expect a linear behavior with respect to wavelength
    out = np.sqrt(transmission) - 10 ** (-loss * ring_length / 20.0) * np.exp(
        2j * np.pi * neff_wl * ring_length / wl
    )
    out /= 1 - np.sqrt(transmission) * 10 ** (-loss * ring_length / 20.0) * np.exp(
        2j * np.pi * neff_wl * ring_length / wl
    )
    return abs(out) ** 2


if __name__ == "__main__":
    import matplotlib.pyplot as plt

    loss = 0.03  # [dB/μm] (alpha) waveguide loss
    neff = 2.46  # Effective index of the waveguides
    wl0 = 1.55  # [μm] the wavelength at which neff and ng are defined
    radius = 5
    ring_length = 2 * np.pi * radius  # [μm] Length of the ring
    coupling = 0.5  # [] coupling of the coupler
    wl = np.linspace(1.5, 1.6, 1000)  # [μm] Wavelengths to sweep over
    wl = np.linspace(1.55, 1.60, 1000)  # [μm] Wavelengths to sweep over
    ngs = [4.182551, 4.169563, 4.172917]
    thicknesses = [210, 220, 230]

    # widths = np.array([0.4, 0.45, 0.5, 0.55, 0.6])
    # ngs = np.array([4.38215238, 4.27254985, 4.16956338, 4.13283219, 4.05791982])

    widths = np.array([0.495, 0.5, 0.505])
    neffs = np.array([2.40197253, 2.46586378, 2.46731758])
    ng = 4.2  # Group index of the waveguides

    for width, neff in zip(widths, neffs):
        p = ring(
            wl=wl,
            wl0=wl0,
            neff=neff,
            ng=ng,
            ring_length=ring_length,
            coupling=coupling,
            loss=loss,
        )
        plt.plot(wl, p, label=f"{int(width*1e3)}nm")

    plt.title("ring resonator vs waveguide width")
    plt.xlabel("wavelength (um)")
    plt.ylabel("Power Transmission")
    plt.grid()
    plt.legend()
    plt.show()
../_images/22122e64a75eae71f0591f7f68a5fe44a93353f07014e5b09fd703084c9ac02a.png

Layout#

gdsfactory easily enables you to layout Component with as many levels of hierarchy as you need.

A Component is a canvas where we can add polygons, references to other components or ports.

Lets add two references in a component.

c = gf.components.ring_single_heater(gap=0.2, radius=10, length_x=4)
c.plot()
../_images/912ca135eacebfd01751356520ea9bd6c4d2875f85db9c456ab5324c310e0abd.png
scene = c.to_3d()
scene.show()

Lets define a ring function that also accepts other component specs for the subcomponents (straight, coupler, bend)

xs = gf.cross_section.metal3(width=5)

ring = gf.components.ring_single_heater(gap=0.2, radius=10, length_x=4)
ring_with_pads = gf.routing.add_pads_top(
    ring,
    port_names=["r_e3", "l_e1"],
    cross_section=xs,
    fanout_length=100,
)
ring_with_pads_grating_couplers = gf.routing.add_fiber_array(
    ring_with_pads, with_loopback=True
)
ring_with_pads_grating_couplers.show()
ring_with_pads_grating_couplers.plot()
../_images/bc1ee38d2ba28c83368a371123a5d77ad824b7bcb4f09da04c96d155be4e01d9.png
ring = gf.components.ring_single_heater(gap=0.2, radius=10, length_x=4)
ring_with_grating_couplers = gf.routing.add_fiber_array(ring, with_loopback=True)
c = gf.routing.add_electrical_pads_top(
    ring_with_grating_couplers, port_names=("l_e1", "r_e3")
)
c.plot()
../_images/6b9ad25fa1b9440932d404e0c9b4044ed6786d839290bc41c864c150feb76bd5.png