def dipole(): s1p_file = './resource/single_dipole.s1p' freq, n, z_data, s_data, z0_data = vecfit.read_snp(s1p_file) cs = freq * 2j * np.pi # Try to fit S # f_out = vecfit.fit_s(s_data, cs, n_pole=3, n_iter=20, s_inf=-1) # f_out = vecfit.fit_s(s_data, cs, n_pole=6, n_iter=20, s_inf=-1, bound_wt=0.3) # f_out = vecfit.bound_tightening(s_data, cs) # np.inf, -1 f_out, log = vecfit.bound_tightening_sweep(s_data, cs) bound, bw = f_out.bound(np.inf, f0=2.4e9) bound_error = f_out.bound_error(s_data, cs, reflect=np.inf) # ant_integral = f_out.bound_integral(cs, reflect=np.inf) ant_integral = vecfit.bound_integral(s_data, cs, np.inf) print( 'Bound is {:.5e}, BW is {:.5e}, Bound error is {:.5e}, The integral of the antenna is {:.5e}' .format(bound, bw, bound_error, ant_integral)) ax1 = vecfit.plot_freq_resp(cs, s_data, y_scale='db') f_out.plot(cs, ax=ax1, y_scale='db', linestyle='--') vecfit.plot_freq_resp(cs, s_data - f_out.model(cs), ax=ax1, y_scale='db', linestyle='--') ax2 = f_out.plot_improved_bound(1e11, 4e10)
def single_siw(): s1p_file = './resource/single_SIW_antenna_39GHz_50mil.s1p' freq, n, z_data, s_data, z0_data = vecfit.read_snp(s1p_file) z0 = 190 s_data = (z_data - z0) / (z_data + z0) cs = freq * 2j * np.pi # Try to fit S # f_out = vecfit.fit_s(s_data, cs, n_pole=18, n_iter=20, s_dc=0, s_inf=1, bound_wt=0.27) f_out = vecfit.bound_tightening(s_data, cs) bound, bw = f_out.bound(np.inf, f0=39e9) bound_error = f_out.bound_error(s_data, cs, reflect=np.inf) # ant_integral = f_out.bound_integral(cs, reflect=np.inf) ant_integral = vecfit.bound_integral(s_data, cs, np.inf) print( 'Bound is {:.5e}, BW is {:.5e}, Bound error is {:.5e}, The integral of the antenna is {:.5e}' .format(bound, bw, bound_error, ant_integral)) ax1 = vecfit.plot_freq_resp(cs, s_data, x_scale='log', y_scale='db') f_out.plot(cs, ax=ax1, x_scale='log', y_scale='db', linestyle='--') vecfit.plot_freq_resp(cs, s_data - f_out.model(cs), ax=ax1, x_scale='log', y_scale='db', linestyle='--') ax2 = f_out.plot_improved_bound(1.2e10, 4e11)
def coupled_dipole(): s2p_file = './resource/coupled_dipoles.s2p' freq, n, z_data, s_data, z0_data = vecfit.read_snp(s2p_file) cs = freq * 2j * np.pi # Fit even and odd mode separately s_even = ((s_data[0, 0, :] + s_data[0, 1, :] + s_data[1, 0, :] + s_data[1, 1, :]) / 2).reshape(len(freq)) s_odd = ((s_data[0, 0, :] - s_data[0, 1, :] - s_data[1, 0, :] + s_data[1, 1, :]) / 2).reshape(len(freq)) # Even and odd mode # f_even = vecfit.fit_s(s_even, cs, n_pole=3, n_iter=20, s_inf=-1) # f_odd = vecfit.fit_s(s_odd, cs, n_pole=3, n_iter=20, s_inf=-1) # f_even = vecfit.bound_tightening(s_even, cs) # f_odd = vecfit.bound_tightening(s_odd, cs) f_even, log_even = vecfit.bound_tightening_sweep(s_even, cs, np.inf) f_odd, log_odd = vecfit.bound_tightening_sweep(s_odd, cs, np.inf) bound_even, bw_even = f_even.bound(np.inf, f0=2.4e9) bound_error_even = f_even.bound_error(s_even, cs, reflect=np.inf) bound_odd, bw_odd = f_odd.bound(np.inf, f0=2.4e9) bound_error_odd = f_odd.bound_error(s_odd, cs, reflect=np.inf) print('Manual even/odd mode decomposition:') print( 'Even mode, # poles {}, bound {:.5e}, bound error {:.5e}, sum {:.5e}'. format(len(f_even.pole), bound_even, bound_error_even, bound_even + bound_error_even)) print('Odd mode, # poles {}, bound {:.5e}, bound error {:.5e}, sum {:.5e}'. format(len(f_odd.pole), bound_odd, bound_error_odd, bound_odd + bound_error_odd)) fig = plt.figure(figsize=(8, 5.5)) ax1 = fig.add_subplot(211) ax2 = fig.add_subplot(212) vecfit.plot_freq_resp(cs, s_even, ax=ax1, y_scale='db') f_even.plot(cs, ax=ax1, y_scale='db', linestyle='--') vecfit.plot_freq_resp(cs, s_odd, ax=ax2, y_scale='db') f_odd.plot(cs, ax=ax2, y_scale='db', linestyle='--') # Try to fit S # fixed_pole = np.concatenate([f_even.pole, f_odd.pole]) # s_model = vecfit.matrix_fitting_rescale(s_data, cs, n_pole=6, n_iter=20, has_const=True, has_linear=False, fixed_pole=fixed_pole) # s_model = s_model.rank_one() # s_model = vecfit.matrix_fitting_rank_one_rescale(s_data, cs, n_pole=6, n_iter=50, has_const=True, has_linear=True) s_model, bound = vecfit.mode_fitting(s_data, cs, True) bound_error = s_model.bound_error(s_data, cs, reflect=np.inf) ant_integral = vecfit.bound_integral(s_data, cs, np.inf) print( 'Bound is {:.5e}, Bound error is {:.5e}, The integral of the antenna is {:.5e}' .format(bound, bound_error, ant_integral)) axs = vecfit.plot_freq_resp_matrix(cs, s_data, y_scale='db') s_model.plot(cs, axs=axs, y_scale='db', linestyle='--')
def transmission_line_model(): # load: r // c + l r = 60 l = 5e-9 c = 1e-12 # z0 = sqrt(l0 / c0) = 50 Ohm z0 = 50 c0 = 1e-12 l0 = 2.5e-9 n = 9 # number of stages freq = np.linspace(1e8, 3e9, 1000) cs = freq * 2j * np.pi zl = 1 / (c * cs + 1 / r) + l * cs for i in range(n): zl = zl + l0 * cs zl = 1 / (c0 * cs + 1 / zl) sl = (zl - z0) / (zl + z0) s_data = sl # Try to fit S # f_out = vecfit.fit_s(s_data, cs, n_pole=19, n_iter=20, s_inf=-1) # f_out = vecfit.bound_tightening(s_data, cs) f_out, log = vecfit.bound_tightening_sweep(s_data, cs, np.inf) bound, bw = f_out.bound(np.inf, f0=2.4e9) bound_error = f_out.bound_error(s_data, cs, reflect=np.inf) # ant_integral = f_out.bound_integral(cs, reflect=np.inf) ant_integral = vecfit.bound_integral(s_data, cs, np.inf) print('Model has {} poles'.format(f_out.pole.shape[0])) print( 'Bound is {:.5e}, BW is {:.5e}, Bound error is {:.5e}, sum is {:.5e}, The integral of the antenna is {:.5e}' .format(bound, bw, bound_error, bound + bound_error, ant_integral)) ax1 = vecfit.plot_freq_resp(cs, s_data, y_scale='db') f_out.plot(cs, ax=ax1, y_scale='db', linestyle='--') vecfit.plot_freq_resp(cs, s_data - f_out.model(cs), ax=ax1, y_scale='db', linestyle='--') ax2 = f_out.plot_improved_bound(1e11, 4e10)
def coupled_siw_even_odd(): s2p_file = './resource/two_SIW_antenna_39GHz_50mil.s2p' freq, n, z, s, z0 = vecfit.read_snp(s2p_file) s_z0 = np.zeros(z.shape, dtype=z.dtype) cs = freq * 2j * np.pi # z0 = 50 z0 = 190 for i in range(len(freq)): s_z0[:, :, i] = np.matrix(z[:, :, i] / z0 - np.identity(n)) * np.linalg.inv( np.matrix(z[:, :, i] / z0 + np.identity(n))) # Fit even and odd mode separately s_even = ((s_z0[0, 0, :] + s_z0[0, 1, :] + s_z0[1, 0, :] + s_z0[1, 1, :]) / 2).reshape(len(freq)) s_odd = ((s_z0[0, 0, :] - s_z0[0, 1, :] - s_z0[1, 0, :] + s_z0[1, 1, :]) / 2).reshape(len(freq)) # Even mode # f_even = vecfit.fit_s(s_even, cs, n_pole=19, n_iter=20, s_inf=1, bound_wt=1.1) f_even = vecfit.bound_tightening(s_even, cs) bound_even, bw_even = f_even.bound(np.inf, f0=39e9) bound_error_even = f_even.bound_error(s_even, cs, reflect=np.inf) # integral_even = f_even.bound_integral(cs, reflect=np.inf) integral_even = vecfit.bound_integral(s_even, cs, np.inf) # Odd mode # f_odd = vecfit.fit_s(s_odd, cs, n_pole=17, n_iter=20, s_inf=1, bound_wt=0.62) f_odd = vecfit.bound_tightening(s_odd, cs) bound_odd, bw_odd = f_odd.bound(np.inf, f0=39e9) bound_error_odd = f_odd.bound_error(s_odd, cs, reflect=np.inf) # integral_odd = f_odd.bound_integral(cs, reflect=np.inf) integral_odd = vecfit.bound_integral(s_odd, cs, np.inf) print( 'Even mode: bound is {:.5e}, BW is {:.5e}, Bound error is {:.5e}, The integral of the antenna is {:.5e}' .format(bound_even, bw_even, bound_error_even, integral_even)) print( 'Odd mode: bound is {:.5e}, BW is {:.5e}, Bound error is {:.5e}, The integral of the antenna is {:.5e}' .format(bound_odd, bw_odd, bound_error_odd, integral_odd)) # plots ax1 = vecfit.plot_freq_resp(cs, s_even, y_scale='db') f_even.plot(cs, ax=ax1, y_scale='db', linestyle='--') vecfit.plot_freq_resp(cs, s_even - f_even.model(cs), ax=ax1, y_scale='db', linestyle='--') ax2 = f_even.plot_improved_bound(2e10, 4e11) ax3 = vecfit.plot_freq_resp(cs, s_odd, y_scale='db') f_odd.plot(cs, ax=ax3, y_scale='db', linestyle='--') vecfit.plot_freq_resp(cs, s_odd - f_odd.model(cs), ax=ax3, y_scale='db', linestyle='--') ax4 = f_odd.plot_improved_bound(2e10, 4e11)
def long_dipole_paper(): s1p_file = './resource/single_dipole_wideband.s1p' freq, n, z_data, s_data, z0_data = vecfit.read_snp(s1p_file) cs = freq * 2j * np.pi z0 = 50 z_data = (1 + s_data) / (1 - s_data) * z0 fz = interp1d(freq, z_data) fr = interp1d(freq, np.real(z_data)) fx = interp1d(freq, np.imag(z_data)) f0 = 2.4e9 f1 = optimize.bisect(fx, 2e9, 2.5e9) f2 = optimize.bisect(fx, 4e9, 4.2e9) f3 = optimize.bisect(fx, 6.8e9, 7.2e9) f4 = optimize.bisect(fx, 8.5e9, 8.8e9) # Equivalent circuit of dipole antenna of arbitrary length # proposed structure: C0 + L0 + (R1 // L1 // C1) + (R2 // L2 // C2) C0 = -1 / (2 * np.pi * f0 / 10 * fx(f0 / 10)) # determined by 0.1 * lambda L0 = 1 / (2 * np.pi * (3 * f1))**2 / C0 # determined by 0.5 * lambda and C0 R1 = fr(f2) # determined by 1 * lambda C1 = 1e-13 # determined by 0.5 * lambda and 1 * lambda L1 = 1 / (2 * np.pi * f2)**2 / C1 # determined by 0.5 * lambda and 1 * lambda R2 = fr(f4) # determined by 2 * lambda C2 = 1.2e-13 # determined by 1.5 * lambda and 2 * lambda L2 = 1 / ( 2 * np.pi * (1.018 * f4))**2 / C2 # determined by 1.5 * lambda and 2 * lambda p1 = (-1 / R1 / C1 + cmath.sqrt(1 / R1**2 / C1**2 - 4 / L1 / C1)) / 2 p2 = (-1 / R1 / C1 - cmath.sqrt(1 / R1**2 / C1**2 - 4 / L1 / C1)) / 2 r1 = 1 / C1 / (1 - p2 / p1) r2 = 1 / C1 / (1 - p1 / p2) p3 = (-1 / R2 / C2 + cmath.sqrt(1 / R2**2 / C2**2 - 4 / L2 / C2)) / 2 p4 = (-1 / R2 / C2 - cmath.sqrt(1 / R2**2 / C2**2 - 4 / L2 / C2)) / 2 r3 = 1 / C2 / (1 - p4 / p3) r4 = 1 / C2 / (1 - p3 / p4) pole_model = [0, p1, p2, p3, p4] zero_model = [1 / C0, r1, r2, r3, r4] z_model = vecfit.RationalFct(pole_model, zero_model, 0, L0) s_tmp = (z_model.model(cs) - z0) / (z_model.model(cs) + z0) s_model = vecfit.fit_s(s_tmp, cs, n_pole=6, n_iter=20, s_inf=1) paper_bound, paper_bw = s_model.bound(np.inf, f0=2.4e9) paper_bound_error = s_model.bound_error(s_data, cs, reflect=np.inf) zl = z_model.model(cs) zl2 = 1 / (cs * C0) + cs * L0 + 1 / (1 / R1 + 1 / (cs * L1) + cs * C1) + 1 / (1 / R2 + 1 / (cs * L2) + cs * C2) # zl2 = 1/(cs*C0) + cs*L0 + 1/(1/R1 + 1/(cs*L1) + cs*C1) # zl2 = 1/(cs*C0) + cs*L0 # zl2 = 1/(1/R1 + 1/(cs*L1) + cs*C1) # Use algorithm to fit S # f_out = vecfit.fit_s(s_data, cs, n_pole=6, n_iter=20, s_inf=1) # f_out = vecfit.bound_tightening(s_data, cs) f_out, log = vecfit.bound_tightening_sweep(s_data, cs, np.inf) # -1 z_fit = (1 + f_out.model(cs)) / (1 - f_out.model(cs)) * z0 bound, bw = f_out.bound(np.inf, f0=2.4e9) bound_error = f_out.bound_error(s_data, cs, reflect=np.inf) # Use manual algorithm to fit S # f_out2 = vecfit.fit_s(s_data, cs, n_pole=6, n_iter=20, s_inf=1) f_out2 = vecfit.fit_s_v2(s_data, cs, n_pole=6, n_iter=20, s_inf=1) z_fit2 = (1 + f_out2.model(cs)) / (1 - f_out2.model(cs)) * z0 bound2, bw2 = f_out2.bound(np.inf, f0=2.4e9) bound_error2 = f_out2.bound_error(s_data, cs, reflect=np.inf) # plots ax = vecfit.plot_freq_resp(cs, s_data, y_scale='db') vecfit.plot_freq_resp(cs, s_tmp, ax=ax, y_scale='db', linestyle='--') f_out.plot(cs, ax=ax, y_scale='db', linestyle='--') f_out2.plot(cs, ax=ax, y_scale='db', linestyle='--') ax.set_ylabel(r'Reflection coefficient $\Gamma$ (dB)') ax.legend(['Simulation', 'Paper [16?]', 'Algorithm 2', 'Impedance Method']) ax.grid(True, which='both', linestyle='--') # bound values print('Paper:') print('Poles {}, bound {:.5e}, error {:.5e}, sum {:.5e}'.format( len(s_model.pole), paper_bound, paper_bound_error, paper_bound + paper_bound_error)) print('Algorithm:') print('Poles {}, bound {:.5e}, error {:.5e}, sum {:.5e}'.format( len(f_out.pole), bound, bound_error, bound + bound_error)) print('Manual comparison:') print('Poles {}, bound {:.5e}, error {:.5e}, sum {:.5e}'.format( len(f_out2.pole), bound2, bound_error2, bound2 + bound_error2))
def dipole_paper(): # Equivalent circuit of a dipole antenna using frequency-independent lumped elements # https://ieeexplore.ieee.org/document/210122 s1p_file = './resource/single_dipole.s1p' freq, n, z_data, s_data, z0_data = vecfit.read_snp(s1p_file) cs = freq * 2j * np.pi z0 = 50 # [2] three-element # [3] four-element # proposed four-element: C1 + (C2 // L1 // R1) h = 62.5e-3 / 2 a = 2.5e-3 / 2 # h = 0.9 # a = 0.00264 C1 = 12.0674 * h / (np.log10(2 * h / a) - 0.7245) * 1e-12 # pF C2 = 2 * h * (0.89075 / (np.power(np.log10(2 * h / a), 0.8006) - 0.861) - 0.02541) * 1e-12 # pF L1 = 0.2 * h * (np.power(1.4813 * np.log10(2 * h / a), 1.012) - 0.6188) * 1e-6 # uH R1 = (0.41288 * np.power(np.log10(2 * h / a), 2) + 7.40754 * np.power(2 * h / a, -0.02389) - 7.27408) * 1e3 # k Ohm C1 *= z0 C2 *= z0 L1 /= z0 R1 /= z0 p1 = (-1 / R1 / C2 + cmath.sqrt(1 / R1**2 / C2**2 - 4 / L1 / C2)) / 2 p2 = (-1 / R1 / C2 - cmath.sqrt(1 / R1**2 / C2**2 - 4 / L1 / C2)) / 2 r1 = 1 / C2 / (1 - p2 / p1) r2 = 1 / C2 / (1 - p1 / p2) pole_model = [0, p1, p2] zero_model = [1 / C1, r1, r2] z_model = vecfit.RationalFct(pole_model, zero_model, 0, 0) s_model = (z_model.model(cs) - 1) / (z_model.model(cs) + 1) # Try to fit S # f_out = vecfit.bound_tightening(s_data, cs) f_out, log = vecfit.bound_tightening_sweep(s_data, cs) bound, bw = f_out.bound(np.inf, f0=2.4e9) bound_error = f_out.bound_error(s_data, cs, reflect=np.inf) # ant_integral = f_out.bound_integral(cs, reflect=np.inf) ant_integral = vecfit.bound_integral(s_data, cs, np.inf) print( 'Bound is {:.5e}, BW is {:.5e}, Bound error is {:.5e}, The integral of the antenna is {:.5e}' .format(bound, bw, bound_error, ant_integral)) ax1 = vecfit.plot_freq_resp(cs, s_data, y_scale='db') f_out.plot(cs, ax=ax1, y_scale='db', linestyle='--') vecfit.plot_freq_resp(cs, s_model, ax=ax1, y_scale='db') vecfit.plot_freq_resp(cs, s_data - f_out.model(cs), ax=ax1, y_scale='db', linestyle='--') vecfit.plot_freq_resp(cs, s_data - s_model, ax=ax1, y_scale='db', linestyle='--') ax2 = f_out.plot_improved_bound(1e11, 4e10)
def transmission_line_model_vs_freq_range(): # load: r // c + l r = 60 l = 5e-9 c = 1e-12 # z0 = sqrt(l0 / c0) = 50 Ohm z0 = 50 c0 = 1e-12 l0 = 2.5e-9 n = 9 # number of stages # start freq 0.1 GHz, end freq 3/4/5 GHz f1 = 1e8 f2_list = [3e9, 4e9, 5e9, 6e9] bound_list = [] bound_error_list = [] f_out_list = [] pole_num_list = [] for f2 in f2_list: freq = np.linspace(f1, f2, 1000) cs = freq * 2j * np.pi zl = 1 / (c * cs + 1 / r) + l * cs for i in range(n): zl = zl + l0 * cs zl = 1 / (c0 * cs + 1 / zl) sl = (zl - z0) / (zl + z0) s_data = sl # Try to fit S # f_out = vecfit.fit_s(s_data, cs, n_pole=19, n_iter=20, s_inf=-1) # f_out = vecfit.bound_tightening(s_data, cs) f_out, log = vecfit.bound_tightening_sweep(s_data, cs, np.inf, -1) bound, bw = f_out.bound(np.inf, f0=2.4e9) bound_error = f_out.bound_error(s_data, cs, reflect=np.inf) f_out_list.append(f_out) bound_list.append(bound) bound_error_list.append(bound_error) pole_num_list.append(f_out.pole.shape[0]) print('Poles {}, bound {:.5e}, error {:.5e}, sum {:.5e}'.format( len(f_out.pole), bound, bound_error, bound + bound_error)) f_out = vecfit.fit_s(s_data, cs, n_pole=19, n_iter=20, s_inf=-1) bound, bw = f_out.bound(np.inf, f0=2.4e9) bound_error = f_out.bound_error(s_data, cs, reflect=np.inf) print('Poles {}, bound {:.5e}, error {:.5e}, sum {:.5e}'.format( len(f_out.pole), bound, bound_error, bound + bound_error)) fig = plt.figure(figsize=(8, 5.5)) ax1 = fig.add_subplot(111) vecfit.plot_freq_resp(cs, s_data, ax=ax1, y_scale='db', color=colors(0)) i = 1 for f_out, f2 in zip(f_out_list, f2_list): f_band = copy.copy(freq) f_band[freq > f2] = np.nan cs = f_band * 2j * np.pi f_out.plot(cs, ax=ax1, y_scale='db', color=colors(i)) vecfit.plot_freq_resp(cs, s_data - f_out.model(cs), ax=ax1, y_scale='db', linestyle='--', color=colors(i)) i += 1 legend_text = ['S-param data'] for i, pole_num in enumerate(pole_num_list): legend_text += [ 'Model {} ({} poles)'.format(i + 1, pole_num), 'Model {} error'.format(i + 1) ] ax1.legend(legend_text) # pole vs bound fig = plt.figure(figsize=(8, 5.5)) ax2 = fig.add_subplot(111) ax2.plot(pole_num_list, np.array(bound_list) + np.array(bound_error_list)) ax2.plot(pole_num_list, bound_list, '--') ax2.plot(pole_num_list, bound_error_list, '--') ax2.legend([r'$B+\delta B$', r'$B$', r'$\delta B$'])