Exemplo n.º 1
0
    def __init__(self,
                 start: float = 1.5e-6,
                 stop: float = 1.6e-6,
                 num: int = 2000) -> None:
        """Initializes the SweepSimulator instance.

        The start and stop values can be given in either wavelength or
        frequency. The simulation will output results in the same mode.

        Parameters
        ----------
        start :
            The starting frequency/wavelength.
        stop :
            The stopping frequency/wavelength.
        num :
            The number of points between start and stop.
        """
        super().__init__()

        # automatically detect mode
        self.mode = "wl" if start < 1 else "freq"

        # if mode is wavelength, convert to frequencies
        if self.mode == "wl":
            temp_start = start
            start = wl2freq(stop)
            stop = wl2freq(temp_start)

        if start > stop:
            raise ValueError(
                "Starting frequency cannot be greater than stopping frequency."
            )

        self.freqs = np.linspace(start, stop, num)
Exemplo n.º 2
0
 def __init__(
     self,
     circuit: Subcircuit,
     start: float = 1.5e-6,
     stop: float = 1.6e-6,
     num: int = 2000,
     mode="wl",
 ):
     super().__init__(circuit)
     if start > stop:
         raise ValueError("simulation 'start' value must be less than 'stop' value.")
     if mode == "wl":
         tmp_start = start
         tmp_stop = stop
         start = wl2freq(tmp_stop)
         stop = wl2freq(tmp_start)
     elif mode == "freq":
         pass
     else:
         err = "mode '{}' is not one of 'freq' or 'wl'".format(mode)
         raise ValueError(err)
     if start > stop:
         raise ValueError(
             "starting frequency cannot be greater than stopping frequency"
         )
     self.freq = np.linspace(start, stop, num)
     self.wl = freq2wl(self.freq)
Exemplo n.º 3
0
def test_ebeam_wg_integral_1550(tmpdir):
    """Tests whether the results of `s_parameters()` for the same frequency on
    an exported and reloaded model are (close) to the same."""
    p = tmpdir.mkdir("persist").join("export")
    wg1 = ebeam_wg_integral_1550(100e-9)
    export_model(wg1, p, wl=np.linspace(1520e-9, 1580e-9, 51))

    wg = import_model(p + ".mdl")
    wg2 = wg()
    freq = np.linspace(wl2freq(1540e-9), wl2freq(1560e-9), 50)
    assert np.allclose(wg1.s_parameters(freq), wg2.s_parameters(freq))
Exemplo n.º 4
0
def export_model(model, filename, wl=None, freq=None):
    """Exports a simphony model (using pickle) for the given
    frequency/wavelength range to a '.mdl' file.

    Must include either the wavelength or frequency argument. If both are
    included, defaults to frequency argument.

    Parameters
    -----------
    model : Model
        Any class inheriting from simphony.elements.Model
    filename : str
        The filename (may include path to directory) to save the model to.
        Note that the suffix '.mdl' will be appended to the filename.
    wl : ndarray, optional
        Wavelengths you want to save sparameters for (in meters).
    freq : ndarray, optional
        Frequencies you want to save sparameters for (in Hz).

    Examples
    --------
    We can write a model for a ``ebeam_wg_integral_1550`` instantiated with a
    length of 100 nanometers to a file  named ``wg100nm.mdl``.

    >>> import numpy as np
    >>> from simphony.library.ebeam import ebeam_wg_integral_1550
    >>> wg1 = ebeam_wg_integral_1550(100e-9)
    >>> export_model(wg1, 'wg100nm', wl=np.linspace(1520e-9, 1580e-9, 51))
    """
    if not issubclass(model.__class__, Model):
        raise ValueError("{} does not extend {}".format(model, Model))

    if wl is None and freq is None:
        raise ValueError("Frequency or wavelength range not defined.")

    # Convert wavelength to frequency
    if freq is None:
        freq = wl2freq(wl)[::-1]

    # Load all data into a dictionary.
    attributes = inspect.getmembers(model, lambda a: not (inspect.isroutine(a)))
    attributes = dict(
        [
            a
            for a in attributes
            if not (a[0].startswith("__") and a[0].endswith("__"))
            and not a[0].startswith("_")
        ]
    )

    params = dict()
    params["model"] = model.__class__.__name__
    params["attributes"] = attributes
    params["f"] = freq
    params["s"] = model.s_parameters(freq)

    # Dump to pickle.
    pickle.dump(
        params, io.open(filename + ".mdl", "wb"), protocol=pickle.HIGHEST_PROTOCOL
    )
Exemplo n.º 5
0
def export_interconnect(sparams, wavelength, filename, clear=True):
    """Exports scattering parameters to a file readable by interconnect.

    Parameters
    -----------
    sparams : ndarray
        Numpy array of size (N, d, d) where N is the number of frequency points and d the number of ports
    wavelength : ndarray
        Numpy array of wavelengths (in nm, like the rest of SCEE) of size (N)
    filename : string
        Location to save file
    clear : bool, optional
        If True, empties the file first. Defaults to True.
    """
    # set things up
    _, d, _ = sparams.shape
    if clear:
        open(filename, "w").close()
    file = open(filename, "ab")

    # make frequencies
    freq = wl2freq(wavelength * 1e-9)

    # iterate through sparams saving
    for in_ in range(d):
        for out in range(d):
            # put things together
            sp = sparams[:, in_, out]
            temp = np.vstack((freq, np.abs(sp), np.unwrap(np.angle(sp)))).T

            # Save header
            header = f'("port {out+1}", "TE", 1, "port {in_+1}", 1, "transmission")\n'
            header += f"{temp.shape}"

            # save data
            np.savetxt(file, temp, header=header, comments="")

    file.close()
Exemplo n.º 6
0
# -*- coding: utf-8 -*-
#
# Copyright © Simphony Project Contributors
# Licensed under the terms of the MIT License
# (see simphony/__init__.py for details)

import pytest
import numpy as np

from simphony.library import ebeam, siepic
from simphony.tools import wl2freq

f = np.linspace(wl2freq(1600e-9), wl2freq(1500e-9))


def is_equal(c1, c2):
    return np.array_equal(c1.s_parameters(f), c2.s_parameters(f))


class TestReimplementedComponents:
    def test_ebeam_y_1550(self):
        assert is_equal(siepic.ebeam_y_1550(), ebeam.ebeam_y_1550())

    def test_ebeam_bdc_te1550(self):
        assert is_equal(siepic.ebeam_bdc_te1550(), ebeam.ebeam_bdc_te1550())

    def test_ebeam_dc_halfring_straight(self):
        d1 = siepic.ebeam_dc_halfring_straight(gap=30e-9,
                                               radius=3e-6,
                                               width=520e-9,
                                               thickness=210e-9)
Exemplo n.º 7
0
You can see that in the final network, our input port is port 3, our through
port is port 2, and our drop port is port 0.

To get the transmission from input to output in the s-matrix, the indexing is
``s[out, in]``.
"""

import matplotlib.pyplot as plt
import numpy as np
from simphony.connect import connect_s, innerconnect_s
from simphony.library import ebeam, sipann
from simphony.tools import freq2wl, wl2freq

# First, we'll set up the frequency range we wish to perform the simulation on.
freq = np.linspace(wl2freq(1600e-9), wl2freq(1500e-9), 2000)

# Get the scattering parameters for each of the elements in our network.
half_ring_left = sipann.sipann_dc_halfring(radius=10).s_parameters(freq)
half_ring_right = sipann.sipann_dc_halfring(radius=10).s_parameters(freq)
term = ebeam.ebeam_terminator_te1550().s_parameters(freq)

### CONFIGURATION 1 ###
n1 = connect_s(half_ring_left, 1, half_ring_right, 3)
n2 = innerconnect_s(n1, 2, 4)
n3 = connect_s(n2, 1, term, 0)

### CONFIGURATION 2 ###
m1 = connect_s(half_ring_right, 1, half_ring_left, 3)
m2 = innerconnect_s(m1, 2, 4)
m3 = connect_s(term, 0, m2, 3)
Exemplo n.º 8
0
wg_in2.multiconnect(dc2, crossing)
wg_out1.multiconnect(crossing, dc3)
wg_out2.multiconnect(crossing, dc4)
wg_pass2.multiconnect(dc2, dc4)

# connect output grating couplers to directional couplers
wg5.multiconnect(dc3, out1)
wg6.multiconnect(dc3, out2)
wg7.multiconnect(dc4, out3)
wg8.multiconnect(dc4, out4)

simulator = SweepSimulator(1549.9e-9, 1550.1e-9)

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

plt.figure()

simulator.multiconnect(in1["pin2"], out1)
plt.plot(*simulator.simulate(), label="1 to 5")

simulator.multiconnect(in1["pin2"], out2)
plt.plot(*simulator.simulate(), label="1 to 6")

simulator.multiconnect(in1["pin2"], out3)
plt.plot(*simulator.simulate(), label="1 to 7")

simulator.multiconnect(in1["pin2"], out4)
plt.plot(*simulator.simulate(), label="1 to 8")
Exemplo n.º 9
0
def freqs():
    return np.linspace(wl2freq(1600e-9), wl2freq(1500e-9))
Exemplo n.º 10
0
    def test_auto_mode_conversion(self, mzi, sweep_wl):
        _, gc_input, _, _, _, gc_output = mzi
        sweep_wl.multiconnect(gc_input, gc_output)

        wl, p = sweep_wl.simulate()
        assert np.allclose(wl2freq(wl), sweep_freqs)
Exemplo n.º 11
0
    def test_modes(self, mzi, sweep):
        _, gc_input, _, _, _, gc_output = mzi
        sweep.multiconnect(gc_input, gc_output)

        wl, p = sweep.simulate(mode="wl")
        assert np.allclose(wl2freq(wl), sweep_freqs)