Skip to content

Commit 782bea8

Browse files
Add taper support to AntennaArrayCalculator and refactor array factor calculation
- Implemented taper integration to allow amplitude weighting in antenna arrays - Refactored array factor computation for improved clarity and efficiency - Updated relevant tests and documentation accordingly
1 parent 15d1342 commit 782bea8

File tree

4 files changed

+733
-37
lines changed

4 files changed

+733
-37
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## [Unreleased]
99

1010
### Added
11+
- Added rectangular and radial taper support to `RectangularAntennaArrayCalculator` for phased array amplitude weighting; refactored array factor calculation for improved clarity and performance.
1112
- Selective simulation capabilities to `TerminalComponentModeler` via `run_only` and `element_mappings` fields, allowing users to run fewer simulations and extract only needed scattering matrix elements.
1213
- Added KLayout plugin, with DRC functionality for running design rule checks in `plugins.klayout.drc`. Supports running DRC on GDS files as well as `Geometry`, `Structure`, and `Simulation` objects.
1314

tests/test_plugins/test_array_factor.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,3 +722,105 @@ def test_rectangular_array_calculator_simulation_data_from_array_factor():
722722

723723
sim_data_from_array_factor = array_calculator.simulation_data_from_array_factor(sim_data)
724724
assert len(sim_data_from_array_factor.data) == 2
725+
726+
727+
def test_rectangular_array_calculator_array_factor_taper():
728+
"""Test the array factor for a rectangular array."""
729+
730+
n_x = 1
731+
n_y = 2
732+
n_z = 3
733+
734+
d_x = 0.4
735+
d_y = 0.5
736+
d_z = 0.6
737+
738+
phi_x = np.pi / 6
739+
phi_y = np.pi / 4
740+
phi_z = np.pi / 3
741+
742+
with pytest.raises(pydantic.ValidationError):
743+
# Test for type mismatch
744+
taper = mw.RadialTaper(window=mw.ChebWindow(at=45))
745+
746+
array_calculator = mw.RectangularAntennaArrayCalculator(
747+
array_size=(n_x, n_y, n_z),
748+
spacings=(d_x, d_y, d_z),
749+
phase_shifts=(phi_x, phi_y, phi_z),
750+
taper=None,
751+
)
752+
753+
# Test basic array factor calculation
754+
theta = np.linspace(0, np.pi, 10)
755+
phi = np.linspace(0, 2 * np.pi, 10)
756+
theta_grid, phi_grid = np.meshgrid(theta, phi)
757+
theta_grid = theta_grid.flatten()
758+
phi_grid = phi_grid.flatten()
759+
medium = td.Medium(permittivity=1)
760+
freqs = np.array([1e9, 2e9, 3e9])
761+
762+
af = array_calculator.array_factor(theta_grid, phi_grid, freqs, medium)
763+
assert af.shape == (100, 3)
764+
765+
af_exact = analytical_array_factor(
766+
(n_x, n_y, n_z), (d_x, d_y, d_z), (phi_x, phi_y, phi_z), theta_grid, phi_grid, freqs, medium
767+
)
768+
769+
assert np.allclose(np.abs(af), np.abs(af_exact))
770+
771+
cheb_window = mw.ChebWindow(at=45)
772+
taper = mw.RectangularTaper.all_dims(window=cheb_window)
773+
774+
# Test array factor with amplitude multipliers
775+
array_calculator_amps = mw.RectangularAntennaArrayCalculator(
776+
array_size=(n_x, n_y, n_z),
777+
spacings=(d_x, d_y, d_z),
778+
phase_shifts=(phi_x, phi_y, phi_z),
779+
taper=taper,
780+
)
781+
af_amps = array_calculator_amps.array_factor(theta_grid, phi_grid, freqs, medium)
782+
assert af_amps.shape == (100, 3)
783+
784+
window = mw.TaylorWindow(sll=35, nbar=5)
785+
taper = mw.RadialTaper(window=window)
786+
787+
# Test array factor with radial taper
788+
n_x = 5
789+
n_y = 8
790+
n_z = 9
791+
array_calculator_amps_nonuniform = mw.RectangularAntennaArrayCalculator(
792+
array_size=(n_x, n_y, n_z),
793+
spacings=(d_x, d_y, d_z),
794+
phase_shifts=(phi_x, phi_y, phi_z),
795+
taper=taper,
796+
)
797+
798+
af_amps_nonuniform = array_calculator_amps_nonuniform.array_factor(
799+
theta_grid, phi_grid, freqs, medium
800+
)
801+
802+
assert af_amps_nonuniform.shape == (100, 3)
803+
804+
# test 1D Rectrangular Taper along x
805+
window = mw.TaylorWindow(sll=35, nbar=5)
806+
taper = mw.RectangularTaper(window_x=window)
807+
808+
array_calculator_amps_1d = mw.RectangularAntennaArrayCalculator(
809+
array_size=(n_x, n_y, n_z),
810+
spacings=(d_x, d_y, d_z),
811+
phase_shifts=(phi_x, phi_y, phi_z),
812+
taper=taper,
813+
)
814+
815+
af_amps_1d = array_calculator_amps_1d.array_factor(theta_grid, phi_grid, freqs, medium)
816+
817+
assert af_amps_1d.shape == (100, 3)
818+
819+
with pytest.raises(pydantic.ValidationError):
820+
# assert that Rectangular Taper has at least one set window
821+
taper = mw.RectangularTaper()
822+
823+
# Test validation
824+
with pytest.raises(ValueError):
825+
# Test mismatched theta/phi lengths
826+
array_calculator_amps_nonuniform.array_factor(theta, phi[:5], freqs, medium)

tidy3d/plugins/microwave/__init__.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,16 @@
44

55
from . import models
66
from .array_factor import (
7+
BlackmanHarrisWindow,
8+
BlackmanWindow,
9+
ChebWindow,
10+
HammingWindow,
11+
HannWindow,
12+
KaiserWindow,
13+
RadialTaper,
714
RectangularAntennaArrayCalculator,
15+
RectangularTaper,
16+
TaylorWindow,
817
)
918
from .auto_path_integrals import path_integrals_from_lumped_element
1019
from .custom_path_integrals import (
@@ -23,14 +32,23 @@
2332

2433
__all__ = [
2534
"AxisAlignedPathIntegral",
35+
"BlackmanHarrisWindow",
36+
"BlackmanWindow",
37+
"ChebWindow",
2638
"CurrentIntegralAxisAligned",
2739
"CurrentIntegralTypes",
2840
"CustomCurrentIntegral2D",
2941
"CustomPathIntegral2D",
3042
"CustomVoltageIntegral2D",
43+
"HammingWindow",
44+
"HannWindow",
3145
"ImpedanceCalculator",
46+
"KaiserWindow",
3247
"LobeMeasurer",
48+
"RadialTaper",
3349
"RectangularAntennaArrayCalculator",
50+
"RectangularTaper",
51+
"TaylorWindow",
3452
"VoltageIntegralAxisAligned",
3553
"VoltageIntegralTypes",
3654
"models",

0 commit comments

Comments
 (0)