Original author: David Banas capn.freako@gmail.com
Original date: October 12, 2019
Copyright (c) 2019 David Banas; all rights reserved World wide.
This iPython notebook is used to test the new integration of Simberian's Simbeor channel solver into PyBERT.
Note: You will need PyBERT installed, in order to run/modify this notebook. (See PyBERT's Quick Start Instructions.)
PyBERT has recently been modified to include the option of using 3rd-party channel solvers, instead of its built-in channel models. The first of these to be integrated/tested is the Simbeor tool from Simberian, Inc.. In this notebook, we test the predictions of PyBERT/Simbeor, using several test channels for which we have precise measurement data available.
Note: You won't need to change the import cell, below, unless you change any code after Sec. 2.
%matplotlib inline
from matplotlib import pyplot as plt
import skrf as rf
import numpy as np
import scipy.signal as sig
from time import sleep
from pybert import pybert
Edit the code block below, to customize this notebook to your interests.
Note: If you confine your code changes to just the code block below, you won't need to change the import code block, above.
# Set to your channel reference measurement data file.
ref_path = "C:\\Users\\dbanas\\Documents\\GitHub\\PyBERT\\misc\\Simberian\\CMP-28_Simbeor_Kit_Rev4\\8_StripSingle(1)\\Results\\SL_SE_2inch_J6J5_SL_SE_2inch_J6J5_TlineOnly_Simulation(1).s2p"
# Instantiate a PyBERT instance.
myPyBERT = pybert.PyBERT(run_simulation=False)
# And customize it to your needs here.
myPyBERT.lic_path = "C:\\Users\\dbanas\\Downloads\\simbeor_DavidBanas_09152019.lic"
myPyBERT.l_ch = 0.05 # Channel length (m).
myPyBERT.ch_type = 'stripline_se' # Choose from: {'microstrip_se', 'microstrip_diff',
# 'stripline_se', 'stripline_diff'}.
myPyBERT.des_freq = 1e9 # Channel "design frequency" (Hz).
myPyBERT.diel_const = 3.8 # Insulator dielectric constant (rel.).
myPyBERT.loss_tan = 0.015 # Insulator loss tangent.
myPyBERT.height = 0.287 # Trace height above(/below) plane (mm).
myPyBERT.width = 0.267 # Trace width (mm).
myPyBERT.thickness = 0.033 # Trace thickness (mm).
myPyBERT.separation = 1.27 # Trace separation (mm) (for stripline only).
myPyBERT.roughness = 0.005 # Trace surface roughness (mm).
Note: If you're just using this notebook to run/validate channels, don't change any code below.
# An indirect way to get a reasonable frequency vector length, for Simbeor.
myPyBERT.nspb = 16
myPyBERT.nbits = 2000
# Set the PyBERT instance up to use Simbeor.
myPyBERT.use_native = False
myPyBERT.solver = "simbeor"
# Launch solver.
print("Launching solver...")
myPyBERT._btn_solve_fired()
while(myPyBERT.chnl_solve_thread.isAlive()):
print(".", end="", flush=True)
sleep(1)
print("\nSolver finished.")
f = myPyBERT.f
ix = np.where(f >= 0)
fig, ax1 = plt.subplots()
color = 'tab:red'
ax1.set_xlabel('frequency (Hz)')
ax1.set_ylabel(r'Zc ($\Omega$)', color=color)
ax1.semilogx(f[ix], abs(myPyBERT.Zc)[ix], color=color)
ax1.tick_params(axis='y', labelcolor=color)
ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis
color = 'tab:blue'
ax2.set_ylabel(r'$\gamma$ (Nep./m)', color=color) # we already handled the x-label with ax1
ax2.semilogx(f[ix], abs(myPyBERT.gamma)[ix], color=color)
ax2.tick_params(axis='y', labelcolor=color)
fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.title("Simbeor Channel Solver Results")
plt.show()
fmax = 40e9
ch_len = myPyBERT.l_ch
ntwk = rf.Network(ref_path)
f_ref = ntwk.f
ix_ref = np.where(f_ref <= fmax)
f_dut = myPyBERT.f
ix_dut = np.where((f_dut >= 0) & (f_dut <= fmax))
fig, ax1 = plt.subplots()
ax1.set_xlabel('Freq. (GHz)')
color = 'tab:red'
ax1.semilogx(f_ref[ix_ref]/1.e9, 20*np.log10(abs(ntwk.s[:,1,0][ix_ref])), '--',
label="Ref.", color=color)
ax1.semilogx(f_dut[ix_dut]/1.e9, 20*np.log10(abs(np.exp(-1. * myPyBERT.gamma[ix_dut] * ch_len))),
label="DUT", color=color)
ax1.legend()
ax1.set_ylabel('|S[2,1]| (dBV)', color=color)
ax1.tick_params(axis='y', labelcolor=color)
ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis
color = 'tab:blue'
ax2.semilogx(f_ref[ix_ref]/1.e9,
np.unwrap(np.angle(ntwk.s[:,1,0][ix_ref]))*180/np.pi, '--',
label="Ref.", color=color)
ax2.semilogx(f_dut[ix_dut]/1.e9,
np.unwrap(np.angle(np.exp(-1. * myPyBERT.gamma[ix_dut] * ch_len)))*180/np.pi,
label="DUT", color=color, )
ax2.set_ylabel('Phase(S[2,1]) (deg.)', color=color)
ax2.tick_params(axis='y', labelcolor=color)
fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.title('PyBERT/Simbeor vs. Reference - S[2,1]')
plt.axis(xmin=0.1)
plt.show(),