def simulate(self): self.netlist.to_spice('optimize.sp') ngspyce.source('optimize.sp') ngspyce.ac(**self.sim_params) fs = np.abs(ngspyce.vector('frequency')) vs = ngspyce.vector('vout') return fs, vs
def run_sim(varactor_voltage): ngspyce.cmd(f'alterparam varactor_bias_voltage = {varactor_voltage}') ngspyce.cmd('reset') # ngspyce.cmd('stop after 10000') step_ps = 1 #not always obeyed - ngspice sets its own timestep. sim_duration = 100000 n_steps = sim_duration / step_ps # ngspyce.cmd(" ") ngspyce.cmd(f'tran {step_ps}p {sim_duration}ps uic') timesteps = ngspyce.vector('time') v_collector = ngspyce.vector('v(E1)') v_base = ngspyce.vector('v(Base)') varactor_bias = ngspyce.vector('v(Vvaractor)') output = ngspyce.vector('v(output)') stable_running_point = -1 * len(v_collector) // 3 v_collector_trimmed = v_collector[ stable_running_point:] # lots of noise on startup. we want to trim that out of the FFT. spectrum = np.fft.fft(v_collector_trimmed) spectrum_freqs = np.fft.fftfreq( len(v_collector_trimmed), d=(timesteps[-1] - timesteps[stable_running_point]) / len(v_collector_trimmed)) spectrum_begin_indice = np.abs(spectrum_freqs - 100e6).argmin() spectrum_end_indice = np.abs(spectrum_freqs - 25e9).argmin() #normalize spectrum_norm = np.linalg.norm( spectrum[spectrum_begin_indice:spectrum_end_indice].clip(min=0)) if (spectrum_norm): fft_cleaned = spectrum[spectrum_begin_indice:spectrum_end_indice].clip( min=0) / spectrum_norm else: fft_cleaned = np.zeros_like( spectrum[spectrum_begin_indice:spectrum_end_indice]) spectrum_freqs = spectrum_freqs[spectrum_begin_indice:spectrum_end_indice] fft_cleaned = fft_cleaned[:int( 600)] # trim all spectra to the same length 2ps,800, 5ps, 600 spectrum_freqs = spectrum_freqs[:int(600)] return [ np.array(np.abs(fft_cleaned)), np.array(spectrum_freqs), timesteps, v_collector, v_base, varactor_bias, output ]
def simulate_waveform(freq, n_periods=2, t_skip_ms=25, steps_per_period=200): period = 1 / freq timestep = period / steps_per_period # set the input frequency printall(ns.cmd("let tmp = @v4[sin]")) printall(ns.cmd("let tmp[2] = %f" % freq)) printall(ns.cmd("alter @v4[sin] = tmp")) skip_periods = math.ceil(t_skip_ms / 1000 * freq) actual_t_skip_ms = skip_periods / freq * 1000 t_run_ms = actual_t_skip_ms + n_periods / freq * 1000 ns.destroy() print("tran %fu %fm %fm" % (timestep * 1000000, t_run_ms, actual_t_skip_ms)) ns.cmd("tran %fu %fm %fm" % (timestep * 1000000, t_run_ms, actual_t_skip_ms)) return ns.vector('signal_in'), ns.vector('signal_out'), ( ns.vector('time') - actual_t_skip_ms / 1000)
Plot the frequency response of an RC low-pass filter """ import ngspyce from matplotlib import pyplot as plt import numpy as np # Read netlist ngspyce.source('lowpass.net') # Calculate small-signal transfer function between 1 kHz and 10 MHz, with 5 # points per decade ngspyce.ac(mode='dec', npoints=7, fstart=1e3, fstop=10e6) # Read results freq = np.abs(ngspyce.vector('frequency')) vout = ngspyce.vector('vout') # And plot them fig, (ax1, ax2) = plt.subplots(2, sharex=True) fig.suptitle('Frequency response of an RC low-pass filter') ax1.semilogx(freq, 20 * np.log10(np.abs(vout))) ax1.set_ylabel('Magnitude [dB]') ax1.grid(True, which='both') ax2.semilogx(freq, np.angle(vout, True)) ax2.set_xlabel('Frequency [Hz]') ax2.set_ylabel('Phase [degrees]') ax2.grid(True, which='both') ax2.margins(x=0)
# Plot the frequency response of an RC low-pass filter import ngspyce from matplotlib import pyplot as plt import numpy as np # Reat netlist ngspyce.cmd('source lowpass.net') # Calculate small-signal transfer function between 10kHz and 100MHz, with 5 # points per decade ngspyce.cmd('ac dec 5 10k 100meg') # Read results freq = np.abs(ngspyce.vector('frequency')) vout = ngspyce.vector('vout') # And plot them fig = plt.figure() fig.suptitle('Frequency response of an RC low-pass filter') ax = fig.add_subplot(1,2,1) ax.semilogx(freq, 20*np.log10(np.abs(vout))) ax.set_xlabel('Frequency [Hz]') ax.set_ylabel('Magnitude [dB]') ax = fig.add_subplot(1,2,2) ax.semilogx(freq, np.angle(vout,True)) ax.set_xlabel('Frequency [Hz]') ax.set_ylabel('Phase [degrees]')
def test_vector(self): ns.cmd('let myvector = unitvec(4)') self.assertEqual(list(ns.vector('myvector')), [1, 1, 1, 1])
def _test_sweep(self, *args): ns.dc('va', *args) self.assertEqualNdarray(ns.vector('a'), ns.linear_sweep(*args))
def test_altermod(self): ns.circ(['r n 0 rmodel', '.model rmodel R res = 3']) ns.alter_model('r', res=4) ns.operating_point() self.assertEqual(ns.vector('@r[resistance]'), 4)
def test_alter(self): ns.circ('r n 0 1') ns.alter('r', resistance=2, temp=3) ns.operating_point() # Necessary for resistance to be calculated self.assertEqual(ns.vector('@r[resistance]'), 2) self.assertEqual(ns.vector('@r[temp]'), 3)