You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
3.9 KiB
108 lines
3.9 KiB
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'")
|
|
|
|
|