From 347c0093935dd65e3fc42106126c087ecf53988d Mon Sep 17 00:00:00 2001 From: Will Boxx Date: Wed, 18 May 2022 17:11:04 -0500 Subject: [PATCH] updated ff radiation and correction factor funcs --- docs/_static/ffPattern.png | Bin 0 -> 52046 bytes src/antenna_intensity_modeler/parabolic.py | 438 ++++++++++++++++----- 2 files changed, 334 insertions(+), 104 deletions(-) create mode 100644 docs/_static/ffPattern.png diff --git a/docs/_static/ffPattern.png b/docs/_static/ffPattern.png new file mode 100644 index 0000000000000000000000000000000000000000..6a6953cd2dc53234ce272fc3196824384af705fc GIT binary patch literal 52046 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 dict: """Parameters for parabolic dish @@ -48,78 +64,90 @@ def parameters( efficiency (float): efficiency of antenna. side_lobe_ratio (float): side lobe ratio of antenna. - Returns: + Returns: dict: parameter dictionary needed for parabolic functions. Example: >>> from antenna_intensity_modeler import parabolic >>> params = parabolic.parameters(2.4, 8400., 400.0, 0.62, 20.0) >>> params - {'radius_meters': 2.4, 'freq_mhz': 8400.0, 'power_watts': 400.0, 'efficiency': 0.62, - 'side_lobe_ratio':20.0, 'H': 0.4872, 'ffmin': 1290.24, 'ffpwrden': 2.1134, 'k': 175.929} + {'radius_meters': 2.4, 'freq_mhz': 8400.0, 'power_watts': 400.0, + 'efficiency': 0.62, 'side_lobe_ratio':20.0, 'H': 0.4872, + 'ffmin': 1290.24, 'ffpwrden': 2.1134, 'k': 175.929} """ """Constants""" - C = 3e8 * m / s - - # Sidelobe Ratios (illummination) - # n = 0: slr = 17.57 - # n = 1: slr = 25 - # n = 2: slr = 30 - # n = 3: slr = 35 - # n = 4: slr = 40 - # n = 5: slr = 45 - HDICT = { - 17.57: 0, - 20: 0.4872, - 25: 0.8899, - 30: 1.1977, - 35: 1.4708, - 40: 1.7254, - 45: 1.9681, - 50: 2.2026, - } - freq_hz = freq_mhz * 1e6 - DIAM = 2 * radius_meters - LAMDA = C / freq_hz - GAIN = 10 * np.log10(efficiency * (pi * DIAM / LAMDA) ** 2) - EIRP = power_watts * 10 ** (0.1 * GAIN) + + freq_hz = freq_mhz * MHZ + diam = 2 * radius_meters + _lamda = C / freq_hz + if gain is None: + gain = 10 * np.log10(efficiency * (PI * diam / _lamda) ** 2) + eirp = power_watts * 10 ** (0.1 * gain) + + # Check aperture size limitation + if diam < 10 * _lamda: + ratio = diam / _lamda + print( + ( + "WARNING - Diameter should be at least ten times " + + + "the wavelength for this method to work. Currently " + + + "the diameter is {} times the wavelength." + ).format(ratio) + ) """Properties""" - H = HDICT[side_lobe_ratio] - ffmin = 2 * DIAM ** 2 / LAMDA - ffpwrden = EIRP / (4 * pi * ffmin ** 2) - k = 2 * pi / LAMDA + # h = hdict[side_lobe_ratio] + # First find h given side lobe ratio + # using the following relationship + # slr = 17.57 dB + 20 * log10(( 2 * I_1(pi * H)) / (pi * H)) + hansons_fun = ( + lambda x: side_lobe_ratio + - 17.57 + - 20 * np.log10((2 * scipy.special.i1(PI * x)) / (PI * x)) + ) + h_value = scipy.optimize.newton(hansons_fun, 0.1) + + ffmin = 2 * diam**2 / _lamda + ffpwrden = eirp / (4 * PI * ffmin**2) + k = 2 * PI / _lamda + + min_range = 0.5 * diam * (diam / _lamda)**(1/3) return_dict = { "radius_meters": radius_meters, "freq_mhz": freq_mhz, + "lamda": _lamda, "power_watts": power_watts, "efficiency": efficiency, "side_lobe_ratio": side_lobe_ratio, - "H": H, + "H": h_value, "ffmin": ffmin, "ffpwrden": ffpwrden, "k": k, + "a_value": a_value, + "n_value": n_value, + "min_range": min_range } return return_dict - # return radius_meters, freq_mhz, power_watts, efficiency, side_lobe_ratio, H, ffmin, ffpwrden, k -def bessel_func( +def _bessel_func( x: float, f: Union[np.cos, np.sin], H: float, u: float, d: float ) -> Callable: return ( - 1 - * scipy.special.iv(0, pi * H * (1 - x ** 2)) # **(1 / 2)) + 1. + * scipy.special.i0(PI * H * (1. - x ** 2)) # **(1 / 2)) # * (1 - x**2) - * scipy.special.jv(0, u * x) - * f(pi * x ** 2 / 8 / d) + * scipy.special.j0(u * x) + * f(PI * x ** 2 / 8. / d) * x ) -def romberg_integration( +def _romberg_integration( fun: Callable, lower: int = 0, upper: int = 1, divmax: int = 20 ) -> Either: try: @@ -128,78 +156,94 @@ def romberg_integration( return Left(err) -def run_near_field_corrections(d: float, parameters: dict, xbar: float) -> float: +def _check_theta(theta, a, z, lamda): + if (PI * a**2 / lamda / z) * SIN(theta)**2 > 0.08: + print( + ( + "WARNING - Failed theta check for theta = {}, " + + + "a = {}, and z = {}" + ).format(theta * TO_DEG, a, z) + ) + + +def _run_near_field_corrections( + d: float, + parameters: dict, + xbar: float +) -> float: # Get parameters radius = parameters.get("radius_meters") - freq_mhz = parameters.get("freq_mhz") - power_watts = parameters.get("power_watts") - efficiency = parameters.get("efficiency") - side_lobe_ratio = parameters.get("side_lobe_ratio") H = parameters.get("H") ffmin = parameters.get("ffmin") - ffpwrden = parameters.get("ffpwrden") k = parameters.get("k") + lamda = parameters.get("lamda") xbarR = xbar * radius theta = np.arctan(xbarR / (d * ffmin)) + _check_theta(theta, xbarR, d*ffmin, lamda) u = k * radius * np.sin(theta) # Get Bessel Functions - bessel_func_cos = partial(bessel_func, f=np.cos, H=H, u=u, d=d) - bessel_func_sin = partial(bessel_func, f=np.sin, H=H, u=u, d=d) + bessel_func_cos = partial(_bessel_func, f=np.cos, H=H, u=u, d=d) + bessel_func_sin = partial(_bessel_func, f=np.sin, H=H, u=u, d=d) # Calculate Powers - Ep1 = romberg_integration(bessel_func_cos, 0, 1, divmax=20) - Ep2 = romberg_integration(bessel_func_sin, 0, 1, divmax=20) + Ep1 = _romberg_integration(bessel_func_cos, 0, 1, divmax=20) + Ep2 = _romberg_integration(bessel_func_sin, 0, 1, divmax=20) # Ep1_1 = scipy.integrate.romberg(bessel_func_cos, 0, 1, divmax=20) # Ep2_1 = scipy.integrate.romberg(bessel_func_sin, 0, 1, divmax=20) @curry(2) def final_reduction(x, y): - return (1 + np.cos(theta)) / d * abs(x - 1j * y) + return (1. + np.cos(theta)) / d * abs(x - 1.j * y) # return (1 + np.cos(theta)) / d * abs(Ep1_1 - 1j * Ep2_1) - return final_reduction << Ep1 & Ep2 + return (final_reduction << Ep1 & Ep2).then(_square) -def square(x): - return x ** 2 +def _square(x): + return Just(x ** 2) -def squared(x): - return square << x +def _squared(x): + return _square << x @curry(2) -def divide(x, y): - return x / y +def _divide(x, y): + return Just(x / y) @curry(2) -def normalized(y, x): - return Nothing if y == Just(0) else divide << x & y +def _normalize(y, x): + if y == 0: + return Nothing + else: + return x / y -def unpacked(x): +def _unpack(x): return x.value def near_field_corrections( - parameters: dict, xbar: float, resolution: int = 1000 + parameters: dict, xbar: float, resolution: int = 1000, use_light_pipes: bool = False ) -> np.array: """Near field corrections for parabolic dish. Receives user input parameters and normalized off axis distance - for parabolic dish. Computes and returns plot of near field correction - factors. + (tangental from plane of propagation) from parabolic dish center. + Computes and returns the near field correction factors. Args: - parameters (tuple): parameters tuple created with parameters function. - xbar (float) : normalized off-axis distance. + parameters (dict): parameters dictionary created with parameters + function. + xbar (float) : normalized off-axis distance from dish center. resolution (float): number of points used in array. Returns: - pandas.DataFrame: A dataframe with "delta" and "Pcorr" columns + numpy.Array: An array with axial correction factors Example: >>> from antenna_intensity_modeler import parabolic @@ -225,28 +269,51 @@ def near_field_corrections( """ run_with_params = partial( - run_near_field_corrections, parameters=parameters, xbar=xbar + _run_near_field_corrections, parameters=parameters, xbar=xbar ) + + min_range = parameters.get("min_range") + ffmin = parameters.get("ffmin") + + if min_range < 0.1 * ffmin: + my_func = (lambda x: min_range - (10**x * ffmin)) + pow = scipy.optimize.newton(my_func, -2) + else: + pow = -2 + delta = np.logspace(-2, 0, resolution) - # with ProcessPoolExecutor() as p: - # Ep = np.array(list(p.map(run_with_params, delta))) - # power_norm = Ep ** 2 / Ep[-1] ** 2 # * parameters["ffpwrden"] - with ProcessPoolExecutor() as p: - Ep = list(p.map(run_with_params, delta)) - # Ep = list(map(run_with_params, delta)) - ff_val = Ep[-1] + + def run(f, my_iter): + iter_length = len(my_iter) + with tqdm(total=iter_length) as pbar: + # let's give it some more threads: + with ProcessPoolExecutor(max_workers=5) as executor: + futures = {executor.submit(f, arg): arg for arg in my_iter} + results = {} + for future in as_completed(futures): + arg = futures[future] + results[arg] = future.result() + pbar.update(1) + return results + + Ep = [] + + Ep_dict = run(run_with_params, delta) + for key in sorted(Ep_dict.keys()): + Ep.append(Ep_dict[key]) + + ff_val = Ep[-1].value Ep_monad = ListMonad(*Ep) - power_norm = Ep_monad * squared * normalized(square << ff_val) * unpacked + power_norm = Ep_monad * _unpack * _normalize(ff_val) - # return pd.DataFrame(dict(delta=delta, Pcorr=Pcorr)) # power_norm = Ep ** 2 / Ep[-1] ** 2 # * parameters["ffpwrden"] return power_norm def delta_xbar_split(delta_xbar: tuple, parameters: dict): (d, xbar) = delta_xbar[0], delta_xbar[1] - return run_near_field_corrections(d, parameters, xbar) + return _run_near_field_corrections(d, parameters, xbar) def get_normalized_power_tensor( @@ -266,7 +333,13 @@ def get_normalized_power_tensor( with ProcessPoolExecutor() as p: # map each delta, xbars tuple to the run_with_params partial function mtrx = np.array( - list(p.map(run_corrections_with_params, delta_xbars, chunksize=chunksize)) + list( + p.map( + run_corrections_with_params, + delta_xbars, + chunksize=chunksize + ) + ) ) # Reshape the resulting flattened array into a 2-d tensor representing # 2-d space from txr center to farfield and down to txr edge @@ -437,9 +510,9 @@ def hazard_plot( def fun1(x): return ( 1 - # * sp.special.iv(0, pi * H * (1 - x**2)**(1 / 2)) + # * sp.special.iv(0, PI * H * (1 - x**2)**(1 / 2)) * sp.special.jv(0, u * x) - * np.cos(pi * x ** 2 / 8 / d) + * np.cos(PI * x ** 2 / 8 / d) * x ) @@ -449,9 +522,9 @@ def fun1(x): def fun2(x): return ( 1 - # * sp.special.iv(0, pi * H * (1 - x**2)**(1 / 2)) + # * sp.special.iv(0, PI * H * (1 - x**2)**(1 / 2)) * sp.special.jv(0, u * x) - * np.sin(pi * x ** 2 / 8 / d) + * np.sin(PI * x ** 2 / 8 / d) * x ) @@ -480,8 +553,8 @@ def fun2(x): # _y_neg = -1 * _y # degree = 0 # rotate = [ - # [np.cos(degree * np.pi / 180), np.sin(degree * np.pi / 180)], - # [-np.sin(degree * np.pi / 180), np.cos(degree * np.pi / 180)] + # [np.cos(degree * np.PI / 180), np.sin(degree * np.PI / 180)], + # [-np.sin(degree * np.PI / 180), np.cos(degree * np.PI / 180)] # ] # top = np.dot(np.column_stack((_x, _y)), rotate) # bottom = np.dot(np.column_stack((_x, _y_neg)), rotate) @@ -562,9 +635,9 @@ def combined_hazard_plot(parameters, limit, density=1000): def fun1(x): return ( 1 - # * scipy.special.iv(0, pi * H * (1 - x**2)) + # * scipy.special.iv(0, PI * H * (1 - x**2)) * scipy.special.jv(0, u * x) - * np.cos(pi * x ** 2 / 8 / d) + * np.cos(PI * x ** 2 / 8 / d) * x ) @@ -574,9 +647,9 @@ def fun1(x): def fun2(x): return ( 1 - # * scipy.special.iv(0, pi * H * (1 - x**2)) + # * scipy.special.iv(0, PI * H * (1 - x**2)) * scipy.special.jv(0, u * x) - * np.sin(pi * x ** 2 / 8 / d) + * np.sin(PI * x ** 2 / 8 / d) * x ) @@ -598,9 +671,9 @@ def fun2(x): def fun1(x): return ( 1 - # * scipy.special.iv(0, pi * H * (1 - x**2)) + # * scipy.special.iv(0, PI * H * (1 - x**2)) * scipy.special.jv(0, u * x) - * np.cos(pi * x ** 2 / 8 / abs(X[i, j] - _x)) + * np.cos(PI * x ** 2 / 8 / abs(X[i, j] - _x)) * x ) @@ -610,9 +683,9 @@ def fun1(x): def fun2(x): return ( 1 - # * scipy.special.iv(0, pi * H * (1 - x**2)) + # * scipy.special.iv(0, PI * H * (1 - x**2)) * scipy.special.jv(0, u * x) - * np.sin(pi * x ** 2 / 8 / abs(X[i, j] - _x)) + * np.sin(PI * x ** 2 / 8 / abs(X[i, j] - _x)) * x ) @@ -629,6 +702,103 @@ def fun2(x): return X, Y, pd_field +def _run_far_field_radiation_pattern(theta: float, parameters: dict) -> float: + # Get parameters + radius = parameters.get("radius_meters") + H = parameters.get("H") + k = parameters.get("k") + + u = k * radius * np.sin(theta) + + # Get Bessel Functions + bessel_func_cos = partial(_bessel_func, f=np.cos, H=H, u=u, d=1) + bessel_func_sin = partial(_bessel_func, f=np.sin, H=H, u=u, d=1) + + # Calculate Powers + Ep1 = _romberg_integration(bessel_func_cos, 0, 1, divmax=20) + Ep2 = _romberg_integration(bessel_func_sin, 0, 1, divmax=20) + + @curry(2) + def final_reduction(x, y): + return (1 + np.cos(theta)) * abs(x - 1j * y) + + # return (1 + np.cos(theta)) / d * abs(Ep1_1 - 1j * Ep2_1) + return (final_reduction << Ep1 & Ep2).then(_square) + + +def far_field_radiation_pattern(parameters, theta, N): + """Far field radiation pattern for parabolic dish. + + Receives user input parameters, the angle in radians the user wants + the pattern for, and the number of points required in the plot. + Computes and returns the normalized power values for the far field + radiation pattern. + + Args: + parameters (dict): parameters dictionary created from the parameters + function. + theta (float) : angle in radians to indicate edge of pattern. + N (float): number of points used in array. + + Returns: + numpy.Array: An array that contains the one sided normalized array + pattern + + Example: + >>> from antenna_intensity_modeler import parabolic + >>> import matplotlib.pyplot as plt + >>> import numpy as np + + >>> params = parameters(2.4, 8400, 400.0, 0.62, 20.0) + >>> theta = 4.0 * np.pi / 180 + >>> resolution = 1024 + >>> power_norm = far_field_radiation_pattern(params, theta, resolution) + >>> fig, ax = plt.subplots() + >>> theta_array = np.linspace(0, theta * 180 / np.pi, resolution) + >>> ax.plot(theta_array, 10 * np.log10(power_norm)) + >>> ax.set_xlim([0.0, 4.0]) + >>> ax.grid(True, which="both") + >>> ax.minorticks_on() + >>> slr = params.get('side_lobe_ratio') + >>> ax.set_title("Far Field Radiation Pattern, slr: {}".format(slr)) + >>> ax.set_xlabel("Angle Off Boresight (deg)") + >>> ax.set_ylabel("Normalized Power Density (dB)") + >>> plt.show() + + .. image:: _static/ffPattern.png + """ + + run_with_params = partial( + _run_far_field_radiation_pattern, parameters=parameters + ) + + def run(f, my_iter): + iter_length = len(my_iter) + with tqdm(total=iter_length) as pbar: + # let's give it some more threads: + with ProcessPoolExecutor(max_workers=5) as executor: + futures = {executor.submit(f, arg): arg for arg in my_iter} + results = {} + for future in as_completed(futures): + arg = futures[future] + results[arg] = future.result() + pbar.update(1) + return results + + angles = np.linspace(0, theta, N) + Ep_dict = run(run_with_params, angles) + Ep = [] + for key in sorted(Ep_dict.keys()): + Ep.append(Ep_dict[key]) + + ff_val = Ep[0].value + Ep_monad = ListMonad(*Ep) + + power_norm = Ep_monad * _unpack * _normalize(ff_val) + + return power_norm + + def print_parameters(parameters: dict): """Prints formated parameter list. @@ -638,17 +808,77 @@ def print_parameters(parameters: dict): none """ radius_meters = parameters.get("radius_meters") - freq_mhz = parameters.get("freq_mhz") power_watts = parameters.get("power_watts") efficiency = parameters.get("efficiency") side_lobe_ratio = parameters.get("side_lobe_ratio") - H = parameters.get("H") ffmin = parameters.get("ffmin") ffpwrden = parameters.get("ffpwrden") - k = parameters.get("k") + print("Aperture Radius: %.2f" % radius_meters) print("Output Power (w): %.2f" % power_watts) print("Antenna Efficiency: %.2f" % efficiency) print("Side Lobe Ratio: %.2f" % side_lobe_ratio) print("Far Field (m): %.2f" % ffmin) print("Far Field (w/m^2): %.2f" % ffpwrden) + + +def _next_pow_2(x): + return 1 << (int(x) - 1).bit_length() + + +if __name__ == "__main__": + + params = parameters(2.4, 8400, 400.0, 0.62, 20.0) + limit = 10.0 + df = test_hazard_plot(params, limit) + rng = df.range.values + positives = df.positives.values + negatives = df.negatives.values + fig, ax = plt.subplots() + ax.plot(rng, positives, rng, negatives) + ax.grid(True, which='both') + ax.minorticks_on() + ax.set_title('Hazard Plot with limit: %s w/m^2' % limit) + ax.set_xlabel('Distance From Antenna(m)') + ax.set_ylabel('Off Axis Distance (m)') + + freq = 44.5 * GHZ + lamda = C / freq + R = 6.5 * METER + D = 2 * R + P0 = 130 + + params = parameters( + radius_meters=R, + freq_mhz=freq / MHZ, + power_watts=P0, + efficiency=0.62, + side_lobe_ratio=35, + ) + + xbar = 0.0 + npix = 1024 + length = 100 + size = int(_next_pow_2(10 * D)) + resolution = size / npix + + theta = 1 * DEG + power_norm = far_field_radiation_pattern(params, theta, npix) + fig, ax = plt.subplots() + delta = params.get("k") * R * SIN(np.linspace(0, 1 * DEG, npix)) + # ax.set_xlim([0, 12]) + # ax.set_ylim([-40, 0]) + ax.plot(delta, 10*np.log10(power_norm)) + + # power_norm = near_field_corrections(params, xbar, length) + # delta = np.logspace(-2, 0, npix) + # ax.semilogx(delta, 10*np.log10(power_norm)) + # ax.set_xlim([0.01, 1.0]) + + ax.grid(True, which="both") + ax.minorticks_on() + slr = params.get("side_lobe_ratio") + ax.set_title("Near Field Corrections xbar: {}, slr: {}".format(xbar, slr)) + ax.set_xlabel("Normalized On Axis Distance") + ax.set_ylabel("Normalized On Axis Power Density") + plt.show()