Skip to content

Add taper support and refactor array-factor calculation #2726

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- Added rectangular and radial taper support to `RectangularAntennaArrayCalculator` for phased array amplitude weighting; refactored array factor calculation for improved clarity and performance.
- 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.
- 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.
- Added "mil" and "in" (inch) units to `plot_length_units`.
Expand Down
102 changes: 102 additions & 0 deletions tests/test_plugins/test_array_factor.py
Original file line number Diff line number Diff line change
Expand Up @@ -722,3 +722,105 @@ def test_rectangular_array_calculator_simulation_data_from_array_factor():

sim_data_from_array_factor = array_calculator.simulation_data_from_array_factor(sim_data)
assert len(sim_data_from_array_factor.data) == 2


def test_rectangular_array_calculator_array_factor_taper():
"""Test the array factor for a rectangular array."""

n_x = 1
n_y = 2
n_z = 3

d_x = 0.4
d_y = 0.5
d_z = 0.6

phi_x = np.pi / 6
phi_y = np.pi / 4
phi_z = np.pi / 3

with pytest.raises(pydantic.ValidationError):
# Test for type mismatch
taper = mw.RadialTaper(window=mw.ChebWindow(attenuation=45))

array_calculator = mw.RectangularAntennaArrayCalculator(
array_size=(n_x, n_y, n_z),
spacings=(d_x, d_y, d_z),
phase_shifts=(phi_x, phi_y, phi_z),
taper=None,
)

# Test basic array factor calculation
theta = np.linspace(0, np.pi, 10)
phi = np.linspace(0, 2 * np.pi, 10)
theta_grid, phi_grid = np.meshgrid(theta, phi)
theta_grid = theta_grid.flatten()
phi_grid = phi_grid.flatten()
medium = td.Medium(permittivity=1)
freqs = np.array([1e9, 2e9, 3e9])

af = array_calculator.array_factor(theta_grid, phi_grid, freqs, medium)
assert af.shape == (100, 3)

af_exact = analytical_array_factor(
(n_x, n_y, n_z), (d_x, d_y, d_z), (phi_x, phi_y, phi_z), theta_grid, phi_grid, freqs, medium
)

assert np.allclose(np.abs(af), np.abs(af_exact))

cheb_window = mw.ChebWindow(attenuation=45)
taper = mw.RectangularTaper.from_isotropic_window(window=cheb_window)

# Test array factor with amplitude multipliers
array_calculator_amps = mw.RectangularAntennaArrayCalculator(
array_size=(n_x, n_y, n_z),
spacings=(d_x, d_y, d_z),
phase_shifts=(phi_x, phi_y, phi_z),
taper=taper,
)
af_amps = array_calculator_amps.array_factor(theta_grid, phi_grid, freqs, medium)
assert af_amps.shape == (100, 3)

window = mw.TaylorWindow(sll=35, nbar=5)
taper = mw.RadialTaper(window=window)

# Test array factor with radial taper
n_x = 5
n_y = 8
n_z = 9
array_calculator_amps_nonuniform = mw.RectangularAntennaArrayCalculator(
array_size=(n_x, n_y, n_z),
spacings=(d_x, d_y, d_z),
phase_shifts=(phi_x, phi_y, phi_z),
taper=taper,
)

af_amps_nonuniform = array_calculator_amps_nonuniform.array_factor(
theta_grid, phi_grid, freqs, medium
)

assert af_amps_nonuniform.shape == (100, 3)

# test 1D Rectrangular Taper along x
window = mw.TaylorWindow(sll=35, nbar=5)
taper = mw.RectangularTaper(window_x=window)

array_calculator_amps_1d = mw.RectangularAntennaArrayCalculator(
array_size=(n_x, n_y, n_z),
spacings=(d_x, d_y, d_z),
phase_shifts=(phi_x, phi_y, phi_z),
taper=taper,
)

af_amps_1d = array_calculator_amps_1d.array_factor(theta_grid, phi_grid, freqs, medium)

assert af_amps_1d.shape == (100, 3)

with pytest.raises(pydantic.ValidationError):
# assert that Rectangular Taper has at least one set window
taper = mw.RectangularTaper()

# Test validation
with pytest.raises(ValueError):
# Test mismatched theta/phi lengths
array_calculator_amps_nonuniform.array_factor(theta, phi[:5], freqs, medium)
18 changes: 18 additions & 0 deletions tidy3d/plugins/microwave/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,16 @@

from . import models
from .array_factor import (
BlackmanHarrisWindow,
BlackmanWindow,
ChebWindow,
HammingWindow,
HannWindow,
KaiserWindow,
RadialTaper,
RectangularAntennaArrayCalculator,
RectangularTaper,
TaylorWindow,
)
from .auto_path_integrals import path_integrals_from_lumped_element
from .custom_path_integrals import (
Expand All @@ -23,14 +32,23 @@

__all__ = [
"AxisAlignedPathIntegral",
"BlackmanHarrisWindow",
"BlackmanWindow",
"ChebWindow",
"CurrentIntegralAxisAligned",
"CurrentIntegralTypes",
"CustomCurrentIntegral2D",
"CustomPathIntegral2D",
"CustomVoltageIntegral2D",
"HammingWindow",
"HannWindow",
"ImpedanceCalculator",
"KaiserWindow",
"LobeMeasurer",
"RadialTaper",
"RectangularAntennaArrayCalculator",
"RectangularTaper",
"TaylorWindow",
"VoltageIntegralAxisAligned",
"VoltageIntegralTypes",
"models",
Expand Down
Loading