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)
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
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)
def s_parameters(self, freq): """Get the s-parameters of SCEE Model. Parameters ---------- freq : np.ndarray A frequency array to calculate s-parameters over (in Hz). Returns ------- s : np.ndarray Returns the calculated s-parameter matrix. """ # convert wavelength to frequency wl = freq2wl(freq) * 1e9 return self.model.sparams(wl)
def simulate(self, mode: Optional[str] = None, **kwargs) -> Tuple[np.array, np.array]: """Runs the sweep simulation for the circuit. Parameters ---------- dB : Returns the power ratios in deciBels when True. mode : Whether to return frequencies or wavelengths for the corresponding power ratios. Defaults to whatever values were passed in upon instantiation. Either 'freq' or 'wl'. """ freqs, power_ratios = super().simulate(**kwargs, freqs=self.freqs) mode = mode if mode else self.mode if mode == "wl": return (freq2wl(freqs), power_ratios) return (freqs, power_ratios)
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()
def monte_carlo_s_parameters(self, freq): """Get the s-parameters of SCEE Model with slightly changed parameters. Parameters ---------- freq : np.ndarray A frequency array to calculate s-parameters over (in Hz). Returns ------- s : np.ndarray Returns the calculated s-parameter matrix. """ wl = freq2wl(freq) * 1e9 # perturb params and get sparams self.model.update(**self.rand_params) sparams = self.model.sparams(wl) # restore parameters to originals self.model.update(**self.og_params) return sparams
('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') ax.plot(freq2wl(f) * 1e9, s, label='Output 1', lw='0.7') f, s = result.data('input', 'out2') ax.plot(freq2wl(f) * 1e9, s, label='Output 2', lw='0.7') f, s = result.data('input', 'out3') ax.plot(freq2wl(f) * 1e9, s, label='Output 3', lw='0.7') ax.set_ylabel("Fractional Optical Power") ax.set_xlabel("Wavelength (nm)") plt.legend(loc='upper right') ax = fig.add_subplot(gs[0, 2]) f, s = result.data('input', 'out1') ax.plot(freq2wl(f) * 1e9, s, label='Output 1', lw='0.7') f, s = result.data('input', 'out2') ax.plot(freq2wl(f) * 1e9, s, label='Output 2', lw='0.7') f, s = result.data('input', 'out3')
("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") ax.plot(freq2wl(f) * 1e9, s, label="Output 1", lw="0.7") f, s = result.data("input", "out2") ax.plot(freq2wl(f) * 1e9, s, label="Output 2", lw="0.7") f, s = result.data("input", "out3") ax.plot(freq2wl(f) * 1e9, s, label="Output 3", lw="0.7") ax.set_ylabel("Fractional Optical Power") ax.set_xlabel("Wavelength (nm)") plt.legend(loc="upper right") ax = fig.add_subplot(gs[0, 2]) f, s = result.data("input", "out1") ax.plot(freq2wl(f) * 1e9, s, label="Output 1", lw="0.7") f, s = result.data("input", "out2") ax.plot(freq2wl(f) * 1e9, s, label="Output 2", lw="0.7") f, s = result.data("input", "out3")
plt.ylabel("Fractional Optical Power") plt.show() # We're interested now in the phase offsets at our wavelength of interest. plt.figure() # port 0 is the input port. ports 4-7 are the output ports. freqs = np.argmax(simulator.freqs > set_freq) input = 0 outputs = slice(4, 8) s = simulator.circuit.s_parameters(simulator.freqs) offset = min(np.angle(s[freqs, outputs, input])) angles = np.angle(s[:, outputs, input]).T - offset for angle in angles: plt.plot(freq2wl(simulator.freqs) * 1e9, angle, linewidth="0.7") plt.axvline(1550, color="k", linestyle="--", linewidth="0.5") plt.legend([r"$\phi_4$", r"$\phi_5$", r"$\phi_6$", r"$\phi_7$"], loc="upper right") plt.xlabel("Wavelength (nm)") plt.ylabel("Phase") plt.show() plt.figure() angles = np.rad2deg(np.unwrap(np.angle(s[:, outputs, input]))).T angles = angles + ((angles[:, freqs] % 2 * np.pi) - angles[:, freqs]).reshape( (4, 1)) for i in range(4): plt.plot(freq2wl(simulator.freqs) * 1e9, angles[i])
plt.xlabel("Frequency (Hz)") plt.ylabel("Fractional Optical Power") plt.show() # We're interested now in the phase offsets at our wavelength of interest. plt.figure() freq, s = result.f, result.s idx = np.argmax(freq > set_freq) input_pin = result.pinlist['in1'].index outputs = [result.pinlist['out' + str(n)].index for n in range(1, 5)] offset = min(np.angle(s[idx, outputs, input_pin])) # angles = np.unwrap(np.angle(s[:, outputs, input_pin])).T - offset angles = np.angle(s[:, outputs, input_pin]).T - offset for angle in angles: plt.plot(freq2wl(freq) * 1e9, angle, linewidth='0.7') plt.axvline(1550, color='k', linestyle='--', linewidth='0.5') plt.legend([r'$\phi_4$', r'$\phi_5$', r'$\phi_6$', r'$\phi_7$'], loc='upper right') plt.xlabel("Wavelength (nm)") plt.ylabel("Phase") plt.show() import sys sys.exit() plt.figure() idx = np.argmax(freq > set_freq) print(idx, freq2wl(freq[idx])) angles = np.rad2deg(np.unwrap(np.angle(s[:, outputs, input_pin]))).T
plt.xlabel("Frequency (Hz)") plt.ylabel("Fractional Optical Power") plt.show() # We're interested now in the phase offsets at our wavelength of interest. plt.figure() freq, s = result.f, result.s idx = np.argmax(freq > set_freq) input_pin = result.pinlist["in1"].index outputs = [result.pinlist["out" + str(n)].index for n in range(1, 5)] offset = min(np.angle(s[idx, outputs, input_pin])) # angles = np.unwrap(np.angle(s[:, outputs, input_pin])).T - offset angles = np.angle(s[:, outputs, input_pin]).T - offset for angle in angles: plt.plot(freq2wl(freq) * 1e9, angle, linewidth="0.7") plt.axvline(1550, color="k", linestyle="--", linewidth="0.5") plt.legend([r"$\phi_4$", r"$\phi_5$", r"$\phi_6$", r"$\phi_7$"], loc="upper right") plt.xlabel("Wavelength (nm)") plt.ylabel("Phase") plt.show() import sys sys.exit() plt.figure() idx = np.argmax(freq > set_freq) print(idx, freq2wl(freq[idx])) angles = np.rad2deg(np.unwrap(np.angle(s[:, outputs, input_pin]))).T angles = angles + ((angles[:, idx] % 2 * np.pi) - angles[:, idx]).reshape((4, 1))
plt.xlabel("Frequency (Hz)") plt.ylabel("Fractional Optical Power") plt.show() # We're interested now in the phase offsets at our wavelength of interest. plt.figure() freq, s = result.f, result.s idx = np.argmax(freq > set_freq) input_pin = result.pinlist["in1"].index outputs = [result.pinlist["out" + str(n)].index for n in range(1, 5)] offset = min(np.angle(s[idx, outputs, input_pin])) # angles = np.unwrap(np.angle(s[:, outputs, input_pin])).T - offset angles = np.angle(s[:, outputs, input_pin]).T - offset for angle in angles: plt.plot(freq2wl(freq) * 1e9, angle, linewidth="0.7") plt.axvline(1550, color="k", linestyle="--", linewidth="0.5") plt.legend([r"$\phi_4$", r"$\phi_5$", r"$\phi_6$", r"$\phi_7$"], loc="upper right") plt.xlabel("Wavelength (nm)") plt.ylabel("Phase") plt.show() import sys sys.exit() plt.figure() idx = np.argmax(freq > set_freq) print(idx, freq2wl(freq[idx])) angles = np.rad2deg(np.unwrap(np.angle(s[:, outputs, input_pin]))).T