import numpy as np import matplotlib.pyplot as plt from bessel import ric_besselh, ric_besselh_derivative # Custom functions to compute Riccati-Hankel functions import pandas as pd # -------------------------------------------------------- # This script computes the monostatic RCS of a PEC sphere # using the analytical Mie series solution. # # The normalized RCS is also computed by dividing by the # physical cross-sectional area of the sphere (πR²). # -------------------------------------------------------- # Define frequency sweep from 50 MHz to 5 GHz (1000 points) frequency = np.linspace(0.05e9, 5e9, 1000) # Compute corresponding wavelengths wavelength = 3e8 / frequency # λ = c / f # Sphere radius in meters Radius = 0.1 # 10 cm # Order of expansion (controls accuracy of Mie series) OrderN = 100 # Cross-sectional area of sphere (used for normalization) AreaOfCircle = np.pi * Radius**2 # Initialize result arrays RCS = np.zeros(len(wavelength), dtype=complex) # Raw monostatic RCS RCS_NORM = np.zeros(len(wavelength)) # Normalized RCS (RCS / πR²) # -------------------------------------------------------- # Loop over all frequencies # -------------------------------------------------------- for index, w in enumerate(wavelength): k = 2 * np.pi / w # Wavenumber kr = k * Radius # Size parameter (non-dimensional) sum_ = 0.0 + 0.0j # Initialize series sum for current frequency kr_vec = kr * np.ones(1) # Required format for bessel function input # Generate orders from 0 to OrderN as column vector Order = np.transpose(np.linspace(0, OrderN, OrderN + 1)) # Evaluate Riccati-Hankel function and its derivative at all orders H = ric_besselh(Order, kr_vec, 2) # Hankel function of 2nd kind Hp = ric_besselh_derivative(Order, kr_vec, 2) # -------------------------------------------------------- # Evaluate Mie series sum for monostatic RCS # -------------------------------------------------------- for n_ in range(OrderN): n = n_ + 1 # Mie series starts from n = 1 # Series term from Mie theory: # RCS component = (-1)^n * (2n + 1) / (Hn * Hn') term = (-1.0)**n * (2.0 * n + 1.0) / (H[n] * Hp[n]) sum_ += term # Accumulate into total sum # Final RCS value for this frequency (in m²) RCS[index] = abs(sum_)**2 * w**2 / (4 * np.pi) # Normalize RCS by area (unitless quantity) RCS_NORM[index] = RCS[index] / AreaOfCircle # -------------------------------------------------------- # Plot Normalized RCS vs Circumference (2πR / λ) # -------------------------------------------------------- Normalized_circumference = 2 * np.pi * Radius / wavelength plt.figure() plt.plot(Normalized_circumference, RCS_NORM) plt.grid() plt.xticks(np.linspace(0, 10, 11)) plt.xlabel("Normalized Circumference (2πR/λ)") plt.ylabel("Normalized RCS by Area of Circle") plt.title("Normalized Monostatic RCS of PEC Sphere") plt.show() # -------------------------------------------------------- # Plot Monostatic RCS in dB vs Frequency # -------------------------------------------------------- plt.figure() plt.plot(frequency / 1e9, 10 * np.log10(RCS)) plt.grid() plt.xticks(np.linspace(0, 10, 21)) plt.xlim([min(frequency / 1e9), max(frequency / 1e9)]) plt.xlabel("Frequency (GHz)") plt.ylabel("Monostatic RCS (dBsm)") plt.title("Monostatic RCS of PEC Sphere") plt.show() # -------------------------------------------------------- # Export Results to Excel # -------------------------------------------------------- output_df = pd.DataFrame({ 'Frequency (GHz)': frequency / 1e9, 'Monostatic RCS (dBsm)': np.real(10 * np.log10(RCS)) }) output_df.to_csv("RCS_ANALYTIC.xlsx", index=False) print("✅ Computation complete. RCS results saved to 'RCS_ANALYTIC.xlsx'")