Exemple #1
0
def sweep_simulation(circuit,
                     iport="input",
                     oport="output",
                     start=1500e-9,
                     stop=1600e-9,
                     num=2000,
                     logscale=True,
                     **kwargs):
    """ Plot Sparameter circuit transmission over wavelength

    Args:
        num: number of sampled points
    """
    circuit = pp.call_if_func(circuit)

    simulation = SweepSimulation(circuit, start, stop, num)
    result = simulation.simulate()

    f, s = result.data(iport, oport)
    w = freq2wl(f) * 1e9

    if logscale:
        s = 20 * np.log10(abs(s))
        ylabel = "|S| (dB)"
    else:
        ylabel = "|S|"

    f, ax = plt.subplots()
    ax.plot(w, s)
    plt.xlabel("wavelength (nm)")
    plt.ylabel(ylabel)
    plt.title(circuit.name)
    return ax
Exemple #2
0
def mzi_simulation(**kwargs):
    """ Run a simulation on the netlist """
    circuit = mzi_circuit(**kwargs)

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

    f, s = result.data("input", "output")
    w = speed_of_light / f
    plt.plot(w * 1e9, s)
    plt.title("MZI")
    plt.xlabel("wavelength (nm)")
    plt.tight_layout()
    plt.show()
Exemple #3
0
def get_transmission(circuit,
                     iport="input",
                     oport="output",
                     start=1500e-9,
                     stop=1600e-9,
                     num=2000):

    circuit = pp.call_if_func(circuit)

    simulation = SweepSimulation(circuit, start, stop, num)
    result = simulation.simulate()

    f, s = result.data(iport, oport)
    w = freq2wl(f) * 1e9
    return dict(wavelength_nm=w, s=s)
Exemple #4
0
def sweep_simulation(circuit,
                     iport="input",
                     oport="output",
                     start=1500e-9,
                     stop=1600e-9,
                     logscale=True,
                     **kwargs):
    """ Run a simulation on the circuit
    """
    circuit = pp.call_if_func(circuit)

    simulation = SweepSimulation(circuit, start, stop)
    result = simulation.simulate()

    f, s = result.data(iport, oport)
    w = freq2wl(f) * 1e9
    if logscale:
        s = 20 * np.log10(abs(s))
    plt.plot(w, s)
    plt.title(circuit.name)
    plt.tight_layout()
    plt.show()
Exemple #5
0
def result_norm():
    # 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 = SweepSimulation(circuit)
    return sim.simulate()
Exemple #6
0
    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


# Behold, we can run a simulation on a single ring resonator.
cir1 = ring_factory(10000)
sim1 = SweepSimulation(cir1, 1500e-9, 1600e-9)
res1 = sim1.simulate()

f1, s = res1.data(res1.pinlist['in'], res1.pinlist['pass'])
plt.plot(f1, s)
plt.title("10-micron Ring Resonator")
plt.tight_layout()
plt.show()

# Now, we'll create the circuit (using several ring resonator subcircuits)
# and add all individual instances.
circuit = Subcircuit('Add-Drop Filter')
e = circuit.add([(wg_data, 'input'), (ring_factory(10000), 'ring10'),
                 (wg_data, 'out1'), (wg_data, 'connect1'),
                 (ring_factory(11000), 'ring11'), (wg_data, 'out2'),
                 (wg_data, 'connect2'), (ring_factory(12000), 'ring12'),
Exemple #7
0
def build_circuit(data, libraries):
    """
    Parameters
    ----------
    data : dict
        The dictionary defining all the circuits and analyzers, as exported
        by SiEPIC and parsed by the parser.
    libraries : list or str
        A string or list of strings of python module names containing the 
        model libraries for the components in the circuit.

    Returns
    -------
    built : dict
        A dictionary of constructed Python objects, with the following keys:
            - `circuits`: dictionary of circuit names to their corresponding
              instantiated Subcircuit objects.
            - `subcircuits`: instantiated Subcircuit objects for all 
              subcircuits found in the spice data.
            - `analyses`: instantiated Simulation objects for all network
              analyzers found in the spice data.
    """
    # Make sure `libraries` is a list
    libraries = libraries if type(libraries) is list else [libraries]

    # Create a dictionary from component names to their models
    available_comps = get_components(libraries)

    # Create all the defined subcircuits
    # [`name`, `ports`, `components`, `params`]
    subcircuits = {}
    for sub in data['subcircuits']:
        circuit = Subcircuit(sub['name'])
        connections = {}

        # Create all the components in the subcircuit and compile all the connections
        # [`name`, `model`, `ports`, `params`]
        for component in sub['components']:
            # Add each component
            kwargs = rearg(component['model'], component['params'])
            circuit.add([(available_comps[component['model']](**kwargs),
                          component['name'])])
            circuit.elements[component['name']].pins = tuple(
                pin for pin in component['ports'])

            # Track all it's nets
            for port in component['ports']:
                if port in connections:
                    connections[port].append(component['name'])
                else:
                    connections[port] = [component['name']]

        # Create all the connections between components
        for port, comps in connections.items():
            circuit.connect(comps[0], port, comps[1],
                            port) if len(comps) == 2 else None

        subcircuits[sub['name']] = circuit

    # Create circuits, since they're composed of subcircuits
    # [`name`, `ports`, `subcircuits`, `params`]
    circuits = {}
    # TODO: What if one day a circuit contains more than one subcircuit?
    for circ in data['circuits']:
        subs = subcircuits[circ['subcircuits']]
        if len(circ['ports']) != len(subs.pins):
            raise ValueError(
                'Ports on circuit do not match ports on subcircuit.')
        circuits[circ['name']] = subs

    # Create all the simulation objects
    # [`definition`, `params`].
    analyses = []
    for analysis in data['analyses']:
        # [`input_unit`, `input_parameter`]
        if analysis['definition']['input_parameter'] == 'start_and_stop':
            # [`minimum_loss`, `analysis_type`, `multithreading`,
            #  `number_of_threads`, `orthogonal_identifier`, `start`, `stop`,
            #  `number_of_points`, `input`, `output`]
            circ, inp = analysis['params']['output'].split(',')
            start = analysis['params']['start']
            stop = analysis['params']['stop']
            points = int(analysis['params']['number_of_points'])
            mode = 'wl' if analysis['definition'][
                'input_unit'] == 'wavelength' else 'freq'
            sim = SweepSimulation(circuits[circ], start, stop, points, mode)
            analyses.append(sim)

    return {
        'circuits': circuits,
        'subcircuits': subcircuits,
        'analyses': analyses
    }
Exemple #8
0
    ('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'),
])

# Run a simulation on our circuit.
simulation = SweepSimulation(circuit, 1549.9e-9, 1550.1e-9)
# simulation = SweepSimulation(circuit, 1510e-9, 1590e-9)
result = simulation.simulate()

# Get the simulation results
# f, s = result.data(result.pinlist['in1'], result.pinlist['out1'])

# The Green Machine is optimized for 1550 nanometers. We'd like to investigate
# its behavior at that specific frequency:
set_freq = wl2freq(1550e-9)

in_port = 'in1'
plt.figure()
plt.plot(*result.data(result.pinlist[in_port], result.pinlist['out1']),
         label='1 to 5')
plt.plot(*result.data(result.pinlist[in_port], result.pinlist['out2']),
Exemple #9
0
    ('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()

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

# We can run a monte carlo simulation on the circuit, too
simulation = MonteCarloSweepSimulation(circuit, 1500e-9, 1600e-9)
runs = 10
result = simulation.simulate(runs=runs)
for i in range(1, runs + 1):
    f, s = result.data('input', 'output', i)
    plt.plot(f, s)