Beispiel #1
0
def ring_factory(radius):
    """
    Creates a full ring (with terminator) from a half ring.

    Ports of a half ring are ordered like so:
    2           4
     |         |
      \       /
       \     /
     ---=====---
    1           3

    Resulting pins are ('in', 'out', 'pass').

    Parameters
    ----------
    radius : float
        The radius of the ring resonator, in nanometers.
    """
    # Have rings for selecting out frequencies from the data line.
    # See SiPANN's model API for argument order and units.
    half_ring = SimphonyWrapper(scee.HalfRing(500, 220, radius, 100))

    circuit = Subcircuit()
    circuit.add([(half_ring, 'input'), (half_ring, 'output'),
                 (term, 'terminator')])

    circuit.elements['input'].pins = ('pass', 'midb', 'in', 'midt')
    circuit.elements['output'].pins = ('out', 'midt', 'term', 'midb')

    circuit.connect_many([('input', 'midb', 'output', 'midb'),
                          ('input', 'midt', 'output', 'midt'),
                          ('terminator', 'n1', 'output', 'term')])

    return circuit
Beispiel #2
0
def add_gc(circuit,
           gc=gc1550te,
           cpi="input",
           cpo="output",
           gpi="port 1",
           gpo="port 2"):
    """ add input and output gratings

    Args:
        circuit: needs to have `input` and `output` pins
        gc: grating coupler
        cpi: circuit pin input name
        cpo: circuit pin output name
        gpi: grating pin input name
        gpo: grating pin output name

    .. code::
                    _______
                   |       |
        gpi-> gpo--|cpi cpo|--gpo <-gpi
                   |_______|
    """
    gc = pp.call_if_func(gc)
    c = Subcircuit(f"{circuit.name}_{gc.name}")
    c.add([(gc, "gci"), (gc, "gco"), (circuit, "circuit")])
    c.connect_many([("gci", gpo, "circuit", cpi),
                    ("gco", gpo, "circuit", cpo)])

    c.elements["gci"].pins[gpi] = "input"
    c.elements["gco"].pins[gpi] = "output"

    return c
Beispiel #3
0
def add_gc(circuit, gc=siepic.ebeam_gc_te1550):
    """ add input and output gratings

    Args:
        circuit: needs to have `input` and `output` pins
        gc: grating coupler
    """
    c = Subcircuit(f"{circuit}_gc")
    gc = pp.call_if_func(gc)
    c.add([
        (gc, "gci"),
        (gc, "gco"),
        (circuit, "circuit"),
    ])
    c.connect_many([
        ("gci", "n1", "circuit", "input"),
        ("gco", "n1", "circuit", "output"),
    ])

    # c.elements["circuit"].pins["input"] = "input_circuit"
    # c.elements["circuit"].pins["output"] = "output_circuit"
    c.elements["gci"].pins["n2"] = "input"
    c.elements["gco"].pins["n2"] = "output"

    return c
Beispiel #4
0
def ring_double_siepic(
    wg_width=0.5,
    gap=0.2,
    length_x=4,
    bend_radius=5,
    length_y=2,
    coupler=siepic.ebeam_dc_halfring_straight,
    waveguide=siepic.ebeam_wg_integral_1550,
):
    """ double bus ring made of two couplers (ct: top, cb: bottom)
    connected with two vertical waveguides (wyl: left, wyr: right)

    .. code::

         --==ct==--
          |      |
          wl     wr length_y
          |      |
         --==cb==-- gap

          length_x

    .. plot::
      :include-source:

      import pp

      c = pp.c.ring(wg_width=0.5, gap=0.2, length_x=4, bend_radius=5, length_y=2)
      pp.plotgds(c)


    .. plot::
        :include-source:

        import simphony.library.gdsfactory as cl
        c = cl.ring()
        cl.sweep_simulation(c)
    """

    waveguide = pp.call_if_func(waveguide)
    coupler = pp.call_if_func(coupler)

    # Create the circuit, add all individual instances
    circuit = Subcircuit("mzi")
    circuit.add([(coupler, "ct"), (coupler, "cb"), (waveguide, "wl"),
                 (waveguide, "wr")])

    # Circuits can be connected using the elements' string names:
    circuit.connect_many([
        ("cb", "2", "wl", "n1"),
        ("wl", "n2", "ct", "n4"),
        ("ct", "2", "wr", "n2"),
        ("wr", "n1", "cb", "n4"),
    ])
    circuit.elements["cb"].pins["n4"] = "input"
    circuit.elements["cb"].pins["n3"] = "output"
    circuit.elements["ct"].pins["n3"] = "drop"
    circuit.elements["ct"].pins["n4"] = "cdrop"
    return circuit
Beispiel #5
0
def ring_double_siepic(
    wg_width=0.5,
    gap=0.2,
    length_x=4,
    bend_radius=5,
    length_y=2,
    coupler=siepic.ebeam_dc_halfring_straight,
    waveguide=siepic.ebeam_wg_integral_1550,
    terminator=siepic.ebeam_terminator_te1550,
):
    """ double bus ring made of two couplers (ct: top, cb: bottom)
    connected with two vertical waveguides (wyl: left, wyr: right)

    .. code::

         --==ct==--
          |      |
          wl     wr length_y
          |      |
         --==cb==-- gap

          length_x


     drop   n1 _        _ n3 cdrop
                \______/
                 ______
     in     n2 _/      \_n4
               |        |
            n1 |        | n3
                \______/
                 ______
     in     n2 _/      \_n4 output


    """

    waveguide = pp.call_if_func(waveguide)
    coupler = pp.call_if_func(coupler)

    # Create the circuit, add all individual instances
    circuit = Subcircuit("mzi")
    circuit.add([(coupler, "ct"), (coupler, "cb"), (waveguide, "wl"),
                 (waveguide, "wr")])

    # Circuits can be connected using the elements' string names:
    circuit.connect_many([
        ("cb", "n1", "wl", "n1"),
        ("wl", "n2", "ct", "n2"),
        ("ct", "n4", "wr", "n1"),
        ("wr", "n2", "cb", "n3"),
    ])
    circuit.elements["cb"].pins["n2"] = "input"
    circuit.elements["cb"].pins["n4"] = "output"
    circuit.elements["ct"].pins["n1"] = "drop"
    circuit.elements["ct"].pins["n3"] = "cdrop"
    return circuit
Beispiel #6
0
def ring_double_sipann(
    wg_width=0.5,
    gap=0.2,
    length_x=4,
    bend_radius=5,
    length_y=2,
    coupler=siepic.ebeam_dc_halfring_straight,
    waveguide=siepic.ebeam_wg_integral_1550,
    terminator=ebeam.ebeam_terminator_te1550,
):
    """ double bus ring made of two couplers (ct: top, cb: bottom)
    connected with two vertical waveguides (wyl: left, wyr: right)

    .. code::

         --==ct==--
          |      |
          wl     wr length_y
          |      |
         --==cb==-- gap

          length_x

    .. plot::
      :include-source:

      import pp

      c = pp.c.ring(wg_width=0.5, gap=0.2, length_x=4, bend_radius=5, length_y=2)
      pp.plotgds(c)


    .. plot::
        :include-source:

        import simphony.library.gdsfactory as cl
        c = cl.ring()
        cl.sweep_simulation(c)
    """

    waveguide = pp.call_if_func(waveguide)
    half_ring = pp.call_if_func(coupler)
    term = pp.call_if_func(coupler)

    circuit = Subcircuit()
    circuit.add([(half_ring, "input"), (half_ring, "output"),
                 (term, "terminator")])

    circuit.elements["input"].pins = ("pass", "midb", "in", "midt")
    circuit.elements["output"].pins = ("out", "midt", "term", "midb")

    circuit.connect_many([
        ("input", "midb", "output", "midb"),
        ("input", "midt", "output", "midt"),
        ("terminator", "n1", "output", "term"),
    ])
    return circuit
Beispiel #7
0
def mzi_gc(L0=1, L1=100, L2=10, y_model_factory=mmi1x2):
    """ MZI with grating couplers
    Deprecated!
    use add_gc instead
    """
    y = pp.call_if_func(y_model_factory)
    gc = siepic.ebeam_gc_te1550()
    wg_long = siepic.ebeam_wg_integral_1550(length=(2 * L0 + 2 * L1 + L2) *
                                            1e-6)
    wg_short = siepic.ebeam_wg_integral_1550(length=(2 * L0 + L2) * 1e-6)

    # Create the circuit, add all individual instances
    circuit = Subcircuit("MZI")
    circuit.add([
        (gc, "input"),
        (gc, "output"),
        (y, "splitter"),
        (y, "recombiner"),
        (wg_long, "wg_long"),
        (wg_short, "wg_short"),
    ])

    # You can set pin names individually:
    circuit.elements["input"].pins["n2"] = "input"
    circuit.elements["output"].pins["n2"] = "output"

    # Or you can rename all the pins simultaneously:
    # circuit.elements["splitter"].pins = ("in1", "out1", "out2")
    # circuit.elements["recombiner"].pins = ("out1", "in2", "in1")

    # Circuits can be connected using the elements' string names:
    circuit.connect_many([
        ("input", "n1", "splitter", "W0"),
        ("splitter", "E0", "wg_long", "n1"),
        ("splitter", "E1", "wg_short", "n1"),
        ("recombiner", "E0", "wg_long", "n2"),
        ("recombiner", "E1", "wg_short", "n2"),
        ("output", "n1", "recombiner", "W0"),
    ])
    return circuit
Beispiel #8
0
def ring_factory(radius):
    """
    Creates a full ring (with terminator) from a half ring.

    Ports of a half ring are ordered like so:
    2           4
     |         |
      \       /
       \     /
     ---=====---
    1           3

    Resulting pins are ('in', 'out', 'pass').

    Parameters
    ----------
    radius : float
        The radius of the ring resonator, in microns.
    """
    # Have rings for selecting out frequencies from the data line.
    half_ring = sipann.sipann_dc_halfring(radius=radius)

    circuit = Subcircuit()
    circuit.add([
        (half_ring, 'input'),
        (half_ring, 'output'),
        (term, 'terminator')
    ])

    circuit.elements['input'].pins = ('pass', 'midb', 'in', 'midt')
    circuit.elements['output'].pins = ('out', 'midt', 'term', 'midb')
    
    circuit.connect_many([
        ('input', 'midb', 'output', 'midb'),
        ('input', 'midt', 'output', 'midt'),
        ('terminator', 'n1', 'output', 'term')
    ])

    return circuit
Beispiel #9
0
def result_monte():
    # Declare the models used in the circuit
    gc = siepic.ebeam_gc_te1550()
    y = siepic.ebeam_y_1550()
    wg150 = siepic.ebeam_wg_integral_1550(length=150e-6)
    wg50 = siepic.ebeam_wg_integral_1550(length=50e-6)

    # Create the circuit, add all individual instances
    circuit = Subcircuit("MZI")
    e = circuit.add([
        (gc, "input"),
        (gc, "output"),
        (y, "splitter"),
        (y, "recombiner"),
        (wg150, "wg_long"),
        (wg50, "wg_short"),
    ])

    # You can set pin names individually:
    circuit.elements["input"].pins["n2"] = "input"
    circuit.elements["output"].pins["n2"] = "output"

    # Or you can rename all the pins simultaneously:
    circuit.elements["splitter"].pins = ("in1", "out1", "out2")
    circuit.elements["recombiner"].pins = ("out1", "in2", "in1")

    # Circuits can be connected using the elements' string names:
    circuit.connect_many([
        ("input", "n1", "splitter", "in1"),
        ("splitter", "out1", "wg_long", "n1"),
        ("splitter", "out2", "wg_short", "n1"),
        ("recombiner", "in1", "wg_long", "n2"),
        ("recombiner", "in2", "wg_short", "n2"),
        ("output", "n1", "recombiner", "out1"),
    ])
    sim = MonteCarloSweepSimulation(circuit)
    return sim.simulate()
Beispiel #10
0
)

# You can set pin names individually (here I'm naming all the outputs that
# I'll want to access after the simulation has been run):
circuit.elements["input"].pins["n1"] = "input"
circuit.elements["out1"].pins["n2"] = "out1"
circuit.elements["out2"].pins["n2"] = "out2"
circuit.elements["out3"].pins["n2"] = "out3"

circuit.connect_many(
    [
        ("input", "n2", "ring10", "in"),
        ("out1", "n1", "ring10", "out"),
        ("connect1", "n1", "ring10", "pass"),
        ("connect1", "n2", "ring11", "in"),
        ("out2", "n1", "ring11", "out"),
        ("connect2", "n1", "ring11", "pass"),
        ("connect2", "n2", "ring12", "in"),
        ("out3", "n1", "ring12", "out"),
        ("terminator", "n1", "ring12", "pass"),
    ]
)

# Run a simulation on the netlist.
simulation = SweepSimulation(circuit, 1524.5e-9, 1551.15e-9)
result = simulation.simulate()

fig = plt.figure(tight_layout=True)
gs = gridspec.GridSpec(1, 3)

ax = fig.add_subplot(gs[0, :2])
Beispiel #11
0
Datei: mzi.py Projekt: tvt173/ubc
def mzi(
    L0=1,
    L1=100,
    L2=10,
    y_model_factory=siepic.ebeam_y_1550,
    wg=siepic.ebeam_wg_integral_1550,
):
    """ Mzi circuit model

    Args:
        L0 (um): vertical length for both and top arms
        L1 (um): bottom arm extra length, delta_length = 2*L1
        L2 (um): L_top horizontal length

    .. code::

               __L2__
               |      |
               L0     L0r
               |      |
     splitter==|      |==recombiner
               |      |
               L0     L0r
               |      |
               L1     L1
               |      |
               |__L2__|


    .. plot::
      :include-source:

      import pp

      c = pp.c.mzi(L0=0.1, L1=0, L2=10)
      pp.plotgds(c)


    .. plot::
        :include-source:

        import ubc

        c = ubc.cm.mzi()
        gl.sweep_simulation(c)


    """
    y = pp.call_if_func(y_model_factory)
    wg_long = wg(length=(2 * L0 + 2 * L1 + L2) * 1e-6)
    wg_short = wg(length=(2 * L0 + L2) * 1e-6)

    # Create the circuit, add all individual instances
    circuit = Subcircuit("mzi")
    circuit.add([
        (y, "splitter"),
        (y, "recombiner"),
        (wg_long, "wg_long"),
        (wg_short, "wg_short"),
    ])
    circuit.elements["splitter"].pins = ("in1", "out1", "out2")
    circuit.elements["recombiner"].pins = ("out1", "in2", "in1")

    # Circuits can be connected using the elements' string names:
    circuit.connect_many([
        ("splitter", "out1", "wg_long", "n1"),
        ("splitter", "out2", "wg_short", "n1"),
        ("recombiner", "in1", "wg_long", "n2"),
        ("recombiner", "in2", "wg_short", "n2"),
    ])
    circuit.elements["splitter"].pins["in1"] = "input"
    circuit.elements["recombiner"].pins["out1"] = "output"
    return circuit
Beispiel #12
0
# work on the circuit connnections.
circuit.connect_many([
    ('in1', 'n2', 'wg1', 'in'),
    ('in2', 'n2', 'wg2', 'in'),
    ('in3', 'n2', 'wg3', 'in'),
    ('in4', 'n2', 'wg4', 'in'),
    ('wg1', 'out', 'dc1', 'in1'),
    ('wg2', 'out', 'dc1', 'in2'),
    ('wg3', 'out', 'dc2', 'in1'),
    ('wg4', 'out', 'dc2', 'in2'),
    ('dc1', 'out1', 'wg_pass1', 'in'),
    ('dc1', 'out2', 'wg_in1', 'in'),
    ('wg_in1', 'out', 'crossing', 'in1'),
    ('crossing', 'out1', 'wg_out1', 'in'),
    ('dc2', 'out1', 'wg_in2', 'in'),
    ('wg_in2', 'out', 'crossing', 'in2'),
    ('crossing', 'out2', 'wg_out2', 'in'),
    ('dc2', 'out2', 'wg_pass2', 'in'),
    ('wg_pass1', 'out', 'dc3', 'in1'),
    ('wg_out1', 'out', 'dc3', 'in2'),
    ('wg_out2', 'out', 'dc4', 'in1'),
    ('wg_pass2', 'out', 'dc4', 'in2'),
    ('dc3', 'out1', 'wg5', 'in'),
    ('dc3', 'out2', 'wg6', 'in'),
    ('dc4', 'out1', 'wg7', 'in'),
    ('dc4', 'out2', 'wg8', 'in'),
    ('wg5', 'out', 'out1', 'n1'),
    ('wg6', 'out', 'out2', 'n1'),
    ('wg7', 'out', 'out3', 'n1'),
    ('wg8', 'out', 'out4', 'n1'),
])
Beispiel #13
0
def mzi(L0=1, L1=100, L2=10, y_model_factory=mmi1x2):
    """ Mzi

    Args:
        L0: vertical length for both and top arms
        L1: bottom arm extra length, delta_length = 2*L1
        L2: L_top horizontal length

    .. code::

               __L2__
               |      |
               L0     L0r
               |      |
     splitter==|      |==recombiner
               |      |
               L0     L0r
               |      |
               L1     L1
               |      |
               |__L2__|


    .. plot::
      :include-source:

      import pp

      c = pp.c.mzi(L0=0.1, L1=0, L2=10)
      pp.plotgds(c)


    .. plot::
        :include-source:

        import simphony.library.gdsfactory as cl
        c = cl.mzi()

        simulation = SweepSimulation(circuit, 1500e-9, 1600e-9)
        result = simulation.simulate()

        f, s = result.data("input", "output")
        plt.plot(f, s)
        plt.title("MZI")
        plt.tight_layout()
        plt.show()

    """
    y = pp.call_if_func(y_model_factory)
    wg_long = siepic.ebeam_wg_integral_1550(length=(2 * L0 + 2 * L1 + L2) *
                                            1e-6)
    wg_short = siepic.ebeam_wg_integral_1550(length=(2 * L0 + L2) * 1e-6)

    # Create the circuit, add all individual instances
    circuit = Subcircuit("mzi")
    circuit.add([
        (y, "splitter"),
        (y, "recombiner"),
        (wg_long, "wg_long"),
        (wg_short, "wg_short"),
    ])

    # Circuits can be connected using the elements' string names:
    circuit.connect_many([
        ("splitter", "E0", "wg_long", "n1"),
        ("splitter", "E1", "wg_short", "n1"),
        ("recombiner", "E0", "wg_long", "n2"),
        ("recombiner", "E1", "wg_short", "n2"),
    ])
    circuit.elements["splitter"].pins["W0"] = "input"
    circuit.elements["recombiner"].pins["W0"] = "output"
    return circuit
Beispiel #14
0
def mzi_circuit(L0=1, L1=100, L2=10):
    """ Mzi

    Args:
        L0: vertical length for both and top arms
        L1: bottom arm extra length
        L2: L_top horizontal length

    .. code::

               __L2__
               |      |
               L0     L0r
               |      |
     splitter==|      |==recombiner
               |      |
               L0     L0r
               |      |
               L1     L1
               |      |
               |__L2__|


    .. plot::
      :include-source:

      import pp

      c = pp.c.mzi(L0=0.1, L1=0, L2=10)
      pp.plotgds(c)

    """
    gc = siepic.ebeam_gc_te1550()
    y = siepic.ebeam_y_1550()
    wg_long = siepic.ebeam_wg_integral_1550(length=(2 * L0 + +L1 + L2) * 1e-6)
    wg_short = siepic.ebeam_wg_integral_1550(length=(2 * L0 + L2) * 1e-6)

    # Create the circuit, add all individual instances
    circuit = Subcircuit("MZI")
    circuit.add([
        (gc, "input"),
        (gc, "output"),
        (y, "splitter"),
        (y, "recombiner"),
        (wg_long, "wg_long"),
        (wg_short, "wg_short"),
    ])

    # You can set pin names individually:
    circuit.elements["input"].pins["n2"] = "input"
    circuit.elements["output"].pins["n2"] = "output"

    # Or you can rename all the pins simultaneously:
    circuit.elements["splitter"].pins = ("in1", "out1", "out2")
    circuit.elements["recombiner"].pins = ("out1", "in2", "in1")

    # Circuits can be connected using the elements' string names:
    circuit.connect_many([
        ("input", "n1", "splitter", "in1"),
        ("splitter", "out1", "wg_long", "n1"),
        ("splitter", "out2", "wg_short", "n1"),
        ("recombiner", "in1", "wg_long", "n2"),
        ("recombiner", "in2", "wg_short", "n2"),
        ("output", "n1", "recombiner", "out1"),
    ])
    return circuit
Beispiel #15
0
circuit.connect_many(
    [
        ("in1", "n2", "wg1", "in"),
        ("in2", "n2", "wg2", "in"),
        ("in3", "n2", "wg3", "in"),
        ("in4", "n2", "wg4", "in"),
        ("wg1", "out", "dc1", "in1"),
        ("wg2", "out", "dc1", "in2"),
        ("wg3", "out", "dc2", "in1"),
        ("wg4", "out", "dc2", "in2"),
        ("dc1", "out1", "wg_pass1", "in"),
        ("dc1", "out2", "wg_in1", "in"),
        ("wg_in1", "out", "crossing", "in1"),
        ("crossing", "out1", "wg_out1", "in"),
        ("dc2", "out1", "wg_in2", "in"),
        ("wg_in2", "out", "crossing", "in2"),
        ("crossing", "out2", "wg_out2", "in"),
        ("dc2", "out2", "wg_pass2", "in"),
        ("wg_pass1", "out", "dc3", "in1"),
        ("wg_out1", "out", "dc3", "in2"),
        ("wg_out2", "out", "dc4", "in1"),
        ("wg_pass2", "out", "dc4", "in2"),
        ("dc3", "out1", "wg5", "in"),
        ("dc3", "out2", "wg6", "in"),
        ("dc4", "out1", "wg7", "in"),
        ("dc4", "out2", "wg8", "in"),
        ("wg5", "out", "out1", "n1"),
        ("wg6", "out", "out2", "n1"),
        ("wg7", "out", "out3", "n1"),
        ("wg8", "out", "out4", "n1"),
    ]
)
Beispiel #16
0
    (wg50, 'wg_short'),
])

# You can set pin names individually:
circuit.elements['input'].pins['n2'] = 'input'
circuit.elements['output'].pins['n2'] = 'output'

# Or you can rename all the pins simultaneously:
circuit.elements['splitter'].pins = ('in1', 'out1', 'out2')
circuit.elements['recombiner'].pins = ('out1', 'in2', 'in1')

# Circuits can be connected using the elements' string names:
circuit.connect_many([
    ('input', 'n1', 'splitter', 'in1'),
    ('splitter', 'out1', 'wg_long', 'n1'),
    ('splitter', 'out2', 'wg_short', 'n1'),
    ('recombiner', 'in1', 'wg_long', 'n2'),
    ('recombiner', 'in2', 'wg_short', 'n2'),
    ('output', 'n1', 'recombiner', 'out1'),
])

# or by using the actual object reference.
# circuit.connect(e[0], e[0].pin[0], e[2], e[2].pin[0])

# At this point, your circuit is defined. This file can serve as a description
# for a subcircuit that is used in a larger circuit, and can simply be imported
# using the Python import system (``from mzi import circuit``).

# Run a simulation on the netlist.
simulation = SweepSimulation(circuit, 1500e-9, 1600e-9)
result = simulation.simulate()
Beispiel #17
0
)

# You can set pin names individually:
circuit.elements["input"].pins["n2"] = "input"
circuit.elements["output"].pins["n2"] = "output"

# Or you can rename all the pins simultaneously:
circuit.elements["splitter"].pins = ("in1", "out1", "out2")
circuit.elements["recombiner"].pins = ("out1", "in2", "in1")

# Circuits can be connected using the elements' string names:
circuit.connect_many(
    [
        ("input", "n1", "splitter", "in1"),
        ("splitter", "out1", "wg_long", "n1"),
        ("splitter", "out2", "wg_short", "n1"),
        ("recombiner", "in1", "wg_long", "n2"),
        ("recombiner", "in2", "wg_short", "n2"),
        ("output", "n1", "recombiner", "out1"),
    ]
)

# or by using the actual object reference.
# circuit.connect(e[0], e[0].pin[0], e[2], e[2].pin[0])

# At this point, your circuit is defined. This file can serve as a description
# for a subcircuit that is used in a larger circuit, and can simply be imported
# using the Python import system (``from mzi import circuit``).

# Run a simulation on the netlist.
simulation = SweepSimulation(circuit, 1500e-9, 1600e-9)
result = simulation.simulate()
Beispiel #18
0
                 (wg_data, 'connect2'), (ring_factory(12000), 'ring12'),
                 (wg_data, 'out3'), (term, 'terminator')])

# You can set pin names individually (here I'm naming all the outputs that
# I'll want to access after the simulation has been run):
circuit.elements['input'].pins['n1'] = 'input'
circuit.elements['out1'].pins['n2'] = 'out1'
circuit.elements['out2'].pins['n2'] = 'out2'
circuit.elements['out3'].pins['n2'] = 'out3'

circuit.connect_many([
    ('input', 'n2', 'ring10', 'in'),
    ('out1', 'n1', 'ring10', 'out'),
    ('connect1', 'n1', 'ring10', 'pass'),
    ('connect1', 'n2', 'ring11', 'in'),
    ('out2', 'n1', 'ring11', 'out'),
    ('connect2', 'n1', 'ring11', 'pass'),
    ('connect2', 'n2', 'ring12', 'in'),
    ('out3', 'n1', 'ring12', 'out'),
    ('terminator', 'n1', 'ring12', 'pass'),
])

# Run a simulation on the netlist.
simulation = SweepSimulation(circuit, 1524.5e-9, 1551.15e-9)
result = simulation.simulate()

fig = plt.figure(tight_layout=True)
gs = gridspec.GridSpec(1, 3)

ax = fig.add_subplot(gs[0, :2])
f, s = result.data('input', 'out1')
Beispiel #19
0
def mzi(
    length_y: float = 1.0,
    delta_length: float = 100.0,
    length_x: float = 10.0,
    y_model_factory: ModelFactory = siepic.ebeam_y_1550,
    waveguide: ModelFactory = siepic.ebeam_wg_integral_1550,
) -> Subcircuit:
    """Mzi circuit model

    Args:
        length_y: vertical length for both and top arms (um)
        delta_length: bottom arm extra length
        length_x: horizontal length for both and top arms (um)
        waveguide: waveguide_model

    .. code::

                   __Lx__
                  |      |
                  Ly     Lyr (not a parameter)
                  |      |
        splitter==|      |==combiner
                  |      |
                  Ly     Lyr (not a parameter)
                  |      |
                  | delta_length/2
                  |      |
                  |__Lx__|



    .. plot::
      :include-source:

      import pp

      c = pp.c.mzi(length_y=0.1, delta_length=0, length_x=10)
      pp.plotgds(c)


    .. plot::
        :include-source:

        import ubc
        import gdslib as gl

        c = ubc.circuits.mzi()
        gl.plot_circuit(c)

    """
    y = pp.call_if_func(y_model_factory)
    wg_long = waveguide(length=(2 * length_y + delta_length + length_x) * 1e-6)
    wg_short = waveguide(length=(2 * length_y + length_x) * 1e-6)

    # Create the circuit, add all individual instances
    circuit = Subcircuit("mzi")
    circuit.add([
        (y, "splitter"),
        (y, "recombiner"),
        (wg_long, "wg_long"),
        (wg_short, "wg_short"),
    ])
    circuit.elements["splitter"].pins = ("in1", "out1", "out2")
    circuit.elements["recombiner"].pins = ("out1", "in2", "in1")

    # Circuits can be connected using the elements' string names:
    circuit.connect_many([
        ("splitter", "out1", "wg_long", "n1"),
        ("splitter", "out2", "wg_short", "n1"),
        ("recombiner", "in1", "wg_long", "n2"),
        ("recombiner", "in2", "wg_short", "n2"),
    ])
    circuit.elements["splitter"].pins["in1"] = "input"
    circuit.elements["recombiner"].pins["out1"] = "output"
    return circuit
Beispiel #20
0
def ring_double(
    wg_width=0.5,
    gap=0.2,
    length_x=4,
    bend_radius=5,
    length_y=2,
    coupler=coupler_ring,
    waveguide=siepic.ebeam_wg_integral_1550,
):
    """ double bus ring made of two couplers (ct: top, cb: bottom)
    connected with two vertical waveguides (wyl: left, wyr: right)

    .. code::

         --==ct==--
          |      |
          wl     wr length_y
          |      |
         --==cb==-- gap

          length_x


           ---=========---
        E0    length_x    W0
             /         \
            /           \
           |             |
           N1           N0

           N0            N1
           |             |
            \           /
             \         /
           ---=========---
        W0    length_x    E0



    .. plot::
      :include-source:

      import pp

      c = pp.c.ring_double(wg_width=0.5, gap=0.2, length_x=4, bend_radius=5, length_y=2)
      pp.plotgds(c)


    .. plot::
        :include-source:

        import gdslib as gl

        c = gl.ring_double()
        gl.sweep_simulation(c)
    """

    waveguide = pp.call_if_func(waveguide)
    coupler = pp.call_if_func(coupler,
                              length_x=length_x,
                              bend_radius=bend_radius,
                              gap=gap,
                              wg_width=wg_width)

    # Create the circuit, add all individual instances
    circuit = Subcircuit("ring_double")
    circuit.add([(coupler, "ct"), (coupler, "cb"), (waveguide, "wl"),
                 (waveguide, "wr")])

    # Circuits can be connected using the elements' string names:
    circuit.connect_many([
        ("cb", "N0", "wl", "n1"),
        ("wl", "n2", "ct", "N1"),
        ("ct", "N0", "wr", "n1"),
        ("wr", "n2", "cb", "N1"),
    ])
    circuit.elements["cb"].pins["W0"] = "input"
    circuit.elements["cb"].pins["E0"] = "output"
    circuit.elements["ct"].pins["E0"] = "drop"
    circuit.elements["ct"].pins["W0"] = "cdrop"
    return circuit