def AF_zeros(a, M, R, dist_type, nbar=False, alpha=0): r""" This function gives array-factor zeros corresponding to different types of array distributions. Unless you know what you are doing exactly, do not use this function directly. Instead, user can use the function :func:`dist`. :param a: separation between the elements along the x-axis in wavelengths :param M: number of elements along the x-axis :param R: side-lobe ratio in linear scale :param dist_type:type of the distribution, e.g., 'Dolph-Chebyshev', 'Riblet', etc. :param nbar: transition index for dilation :param alpha: Taylor's asymptotic tapering parameter :rtype: U0, a Numpy array of size (*,1) """ k = 2 * np.pi # (angular) wave-number, which is 2*pi when lambda = 1 m = np.ceil((M - 2) / 2) n = np.arange(1, 1 + m, 1) # number of zeros for symmetric array-factors na = np.arange(1, M, 1) # number of zeros for 'asymmetric' array-factors if(dist_type == "Dolph-Chebyshev"): # Dolph zeros c = np.cosh(np.arccosh(R) / (M - 1)) print c U0 = (2 / (a * k)) * np.arccos((np.cos(np.pi * (2 * n - 1) / (2 * M - 2))) / c) elif(dist_type == "Riblet"): # Riblet zeros c1 = np.cosh(np.arccosh(R) / m) c = np.sqrt((1 + c1) / (2 + (c1 - 1) * np.cos(k * a / 2) ** 2)) alph = c * np.cos(k * a / 2) xi = (1 / c) * np.sqrt(((1 + alph ** 2) / 2) + ((1 - alph ** 2) / 2) * np.cos(((2 * n - 1) * np.pi) / (2 * m))) U0 = (2 / (a * k)) * np.arccos(xi) elif(dist_type == "Duhamel-b"): # Duhamel bi-directional end-fire array zeros if(a < 0.5): c = np.cosh(np.arccosh(R) / (M - 1)) / np.sin((k * a) / 2) else: c = np.cosh(np.arccosh(R) / (M - 1)) U0 = (2 / (a * k)) * np.arcsin((np.cos(np.pi * (2 * n - 1) / (2 * M - 2))) / c) elif(dist_type == "Duhamel-u"): # Duhamel uni-directional end-fire array zeros Lamb = np.cosh(np.arccosh(R) / (M - 1)) xi = (2 / a) * (0.5 * np.pi - (np.arctan(np.tan(k * a / 2) * ((Lamb + 1) / (Lamb - 1))))) c = 1 / (np.sin((xi - k) * a / 2)) U0 = -(xi / k) + (2 / (a * k)) * np.arcsin(( np.cos(np.pi * (2 * na - 1) / (2 * M - 2))) / c) elif(dist_type == "McNamara-s"): # McNamara-Zolotarev sum-pattern zeros U0 = "Yet to be done" elif(dist_type == "McNamara-d"): # McNamara-Zolotarev difference-pattern zeros if(a < 0.5): c = 1 / np.sin((k * a) / 2) else: c = 1 m1 = Zol.z_m_frm_R(M - 1, R) xn = Zol.z_Zolotarev_poly(N=M - 1, m=m1)[1][m + 1:] U0 = (2 / (a * k)) * np.arcsin(xn / c) if(nbar): # Taylor's Dilation procedure if((dist_type == "Dolph-Chebyshev") or (dist_type == "Riblet") or (dist_type == "McNamara-s")): n_gen = np.arange(nbar, 1 + m, 1) # indices of the generic zeros U0_gen = (n_gen + alpha / 2) * (1 / (M * a)) # generic sum zeros elif(dist_type == "McNamara-d"): n_gen = np.arange(nbar, 1 + m, 1) # indices of the generic zeros U0_gen = (n_gen + (alpha + 1) / 2) * (1 / (M * a)) # generic difference zeros sigma = U0_gen[0] / U0[nbar - 1] # Dilation factor U0 = np.hstack((sigma * U0[0:nbar - 1], U0_gen)) # Dilated zeros U0 = np.reshape(U0, (len(U0), -1)) return U0
def AF_zeros(a, M, R, dist_type, nbar=False, alpha=0): r""" This function gives array-factor zeros corresponding to different types of array distributions. Unless you know what you are doing exactly, do not use this function directly. Instead, user can use the function :func:`dist`. :param a: separation between the elements along the x-axis in wavelengths :param M: number of elements along the x-axis :param R: side-lobe ratio in linear scale :param dist_type: type of the distribution, e.g., 'Dolph' for Dolph-Chebyshev :param nbar: transition index for dilation :param alpha: Taylor's asymptotic tapering parameter :rtype: U0, a Numpy array of size (*,1) """ k = 2 * np.pi # (angular) wave-number, which is 2*pi when lambda = 1 m = np.ceil((M - 2) / 2) n = np.arange(1, 1 + m, 1) # number of zeros for symmetric array-factors na = np.arange(1, M, 1) # number of zeros for 'asymmetric' array-factors if(dist_type == "Dolph"): # Dolph zeros c = np.cosh(np.arccosh(R) / (M - 1)) U0 = (2 / (a * k)) * np.arccos((np.cos(np.pi * (2 * n - 1) / (2 * M - 2))) / c) elif(dist_type == "Riblet"): # Riblet zeros c1 = np.cosh(np.arccosh(R) / m) c = np.sqrt((1 + c1) / (2 + (c1 - 1) * np.cos(k * a / 2) ** 2)) alph = c * np.cos(k * a / 2) xi = (1 / c) * np.sqrt(((1 + alph ** 2) / 2) + ((1 - alph ** 2) / 2) * np.cos(((2 * n - 1) * np.pi) / (2 * m))) U0 = (2 / (a * k)) * np.arccos(xi) elif(dist_type == "Duhamel-b"): # Duhamel bi-directional end-fire array zeros if(a < 0.5): c = np.cosh(np.arccosh(R) / (M - 1)) / np.sin((k * a) / 2) else: c = np.cosh(np.arccosh(R) / (M - 1)) U0 = (2 / (a * k)) * np.arcsin((np.cos(np.pi * (2 * n - 1) / (2 * M - 2))) / c) elif(dist_type == "Duhamel-u"): # Duhamel uni-directional end-fire array zeros Lamb = np.cosh(np.arccosh(R) / (M - 1)) xi = (2 / a) * (0.5 * np.pi - (np.arctan(np.tan(k * a / 2) * ((Lamb + 1) / (Lamb - 1))))) c = 1 / (np.sin((xi - k) * a / 2)) U0 = -(xi / k) + (2 / (a * k)) * np.arcsin(( np.cos(np.pi * (2 * na - 1) / (2 * M - 2))) / c) elif(dist_type == "McNamara-s"): # McNamara-Zolotarev sum-pattern zeros U0 = "Yet to be done" elif(dist_type == "McNamara-d"): # McNamara-Zolotarev difference-pattern zeros if(a < 0.5): c = 1 / np.sin((k * a) / 2) else: c = 1 m1 = Zol.z_m_frm_R(M - 1, R) xn = Zol.z_Zolotarev_poly(N=M - 1, m=m1)[1][m + 1:] U0 = (2 / (a * k)) * np.arcsin(xn / c) if(nbar): # Taylor's Dilation procedure if((dist_type == "Dolph") or (dist_type == "Riblet") or (dist_type == "McNamara-s")): n_gen = np.arange(nbar, 1 + m, 1) # indices of the generic zeros U0_gen = (n_gen + alpha / 2) * (1 / (M * a)) # generic sum zeros elif(dist_type == "McNamara-d"): n_gen = np.arange(nbar, 1 + m, 1) # indices of the generic zeros U0_gen = (n_gen + (alpha + 1) / 2) * (1 / (M * a)) # generic difference zeros sigma = U0_gen[0] / U0[nbar - 1] # Dilation factor U0 = np.hstack((sigma * U0[0:nbar - 1], U0_gen)) # Dilated zeros U0 = np.reshape(U0, (len(U0), -1)) return U0
def FS_Zolotarev(N, R, x_min, x_max, x_num, plot_far=False, dB_limit=-40): """Function to evaluate Fourier series coefficients of Chebyshev far-field pattern""" if (N % 2 == 0): print("Order needs to be an ODD number for null patterns") else: m_start = -N # make this (2*P+1) ... and take fourier for only half period m_stop = N m = zl.z_m_frm_R(N, R, a=0.1, b=0.9999999999999) m = str(m) N = str(N) fun_str_re = 'zl.z_Zolotarev(' + N + ',' + 'np.sin(x)' + ',' + m + ')' m_index, zm = FS(fun_str_re, m_start=m_start, m_stop=m_stop, err_lim=1e-5) if (plot_far): x, AF = IFS(zm, 2 * np.pi, m_start, m_stop, x_min, x_max, x_num) AF = 20 * np.log10(abs(AF)) AF = pl.cutoff(AF, dB_limit) plt.plot(x * (180 / np.pi), AF) plt.axis('tight') plt.grid(True) plt.title('Far-field Pattern') plt.xlabel(r'$\phi$') plt.ylabel('AF') plt.show() return m_index, zm
def FS_Zolotarev(N, R, x_min, x_max, x_num, plot_far=False, dB_limit= -40): """Function to evaluate Fourier series coefficients of Chebyshev far-field pattern""" if(N % 2 == 0): print "Order needs to be an ODD number for null patterns" else: m_start = -N # make this (2*P+1) ... and take fourier for only half period m_stop = N m = zl.z_m_frm_R(N, R, a=0.1, b=0.9999999999999) m = str(m) N = str(N) fun_str_re = 'zl.z_Zolotarev(' + N + ',' + 'np.sin(x)' + ',' + m +')' m_index, zm = FS(fun_str_re, m_start=m_start, m_stop=m_stop, err_lim=1e-5) if(plot_far): x, AF = IFS(zm, 2 * np.pi, m_start, m_stop, x_min, x_max, x_num) AF = 20 * np.log10(abs(AF)) AF = pl.cutoff(AF, dB_limit) plt.plot(x * (180 / np.pi), AF); plt.axis('tight'); plt.grid(True) plt.title('Far-field Pattern') plt.xlabel(r'$\phi$') plt.ylabel('AF') plt.show() return m_index, zm