Skip to content

Commit 2b4e107

Browse files
First structural refactor complete
1 parent a161de7 commit 2b4e107

File tree

19 files changed

+333
-309
lines changed

19 files changed

+333
-309
lines changed

Untitled.ipynb

Lines changed: 79 additions & 58 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test_task.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import tidy3d as td
1+
from __future__ import annotations
2+
23
import tidy3d.web as web
34

45
task = web.load("he-172a2b2e-f576-4a3e-a90b-06a64194ed51")

tests/test_plugins/smatrix/test_terminal_component_modeler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,7 @@ def test_antenna_helpers(monkeypatch, tmp_path):
765765
# Run simulation to get data
766766
_ = run_component_modeler(monkeypatch, modeler)
767767
batch_data = modeler.batch_data
768-
sim_data = batch_data[modeler._task_name(modeler.ports[0])]
768+
sim_data = batch_data[modeler.get_task_name(modeler.ports[0])]
769769
rad_mon_data = sim_data[radiation_monitor.name]
770770

771771
# Test monitor helper
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
"""
2+
Tool for generating an S matrix automatically from a Tidy3d simulation and lumped port definitions.
3+
"""
4+
5+
from __future__ import annotations
6+
7+
import numpy as np
8+
9+
from tidy3d.plugins.smatrix.data.data_array import ModalPortDataArray
10+
from tidy3d.plugins.smatrix.data.modal import ComponentModelerData
11+
12+
13+
def modal_construct_smatrix(modeler_data: ComponentModelerData) -> ModalPortDataArray:
14+
"""Post process :class:`.BatchData` to generate scattering matrix, for internal use only."""
15+
16+
max_mode_index_out, max_mode_index_in = modeler_data.modeler.max_mode_index
17+
num_modes_out = max_mode_index_out + 1
18+
num_modes_in = max_mode_index_in + 1
19+
port_names_out, port_names_in = modeler_data.modeler.port_names
20+
21+
values = np.zeros(
22+
(
23+
len(port_names_out),
24+
len(port_names_in),
25+
num_modes_out,
26+
num_modes_in,
27+
len(modeler_data.modeler.freqs),
28+
),
29+
dtype=complex,
30+
)
31+
coords = {
32+
"port_out": port_names_out,
33+
"port_in": port_names_in,
34+
"mode_index_out": range(num_modes_out),
35+
"mode_index_in": range(num_modes_in),
36+
"f": np.array(modeler_data.modeler.freqs),
37+
}
38+
s_matrix = ModalPortDataArray(values, coords=coords)
39+
40+
# loop through source ports
41+
for col_index in modeler_data.modeler.matrix_indices_run_sim:
42+
port_name_in, mode_index_in = col_index
43+
port_in = modeler_data.modeler.get_port_by_name(port_name=port_name_in)
44+
45+
sim_data = modeler_data.data[
46+
modeler_data.modeler.get_task_name(port=port_in, mode_index=mode_index_in)
47+
]
48+
49+
for row_index in modeler_data.modeler.matrix_indices_monitor:
50+
port_name_out, mode_index_out = row_index
51+
port_out = modeler_data.modeler.get_port_by_name(port_name=port_name_out)
52+
53+
# directly compute the element
54+
mode_amps_data = sim_data[port_out.name].copy().amps
55+
dir_out = "-" if port_out.direction == "+" else "+"
56+
amp = mode_amps_data.sel(f=coords["f"], direction=dir_out, mode_index=mode_index_out)
57+
source_norm = modeler_data.modeler._normalization_factor(port_in, sim_data)
58+
s_matrix_elements = np.array(amp.data) / np.array(source_norm)
59+
s_matrix.loc[
60+
{
61+
"port_in": port_name_in,
62+
"mode_index_in": mode_index_in,
63+
"port_out": port_name_out,
64+
"mode_index_out": mode_index_out,
65+
}
66+
] = s_matrix_elements
67+
68+
# element can be determined by user-defined mapping
69+
for (row_in, col_in), (row_out, col_out), mult_by in modeler_data.modeler.element_mappings:
70+
port_out_from, mode_index_out_from = row_in
71+
port_in_from, mode_index_in_from = col_in
72+
coords_from = {
73+
"port_in": port_in_from,
74+
"mode_index_in": mode_index_in_from,
75+
"port_out": port_out_from,
76+
"mode_index_out": mode_index_out_from,
77+
}
78+
79+
port_out_to, mode_index_out_to = row_out
80+
port_in_to, mode_index_in_to = col_out
81+
coords_to = {
82+
"port_in": port_in_to,
83+
"mode_index_in": mode_index_in_to,
84+
"port_out": port_out_to,
85+
"mode_index_out": mode_index_out_to,
86+
}
87+
s_matrix.loc[coords_to] = mult_by * s_matrix.loc[coords_from].values
88+
89+
return s_matrix

tidy3d/plugins/smatrix/run/terminal.py renamed to tidy3d/plugins/smatrix/analysis/terminal.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
import numpy as np
44

55
from tidy3d.components.data.sim_data import SimulationData
6-
from tidy3d.plugins.smatrix.data.terminal import TerminalComponentModelerData
6+
from tidy3d.plugins.smatrix.component_modelers.terminal import TerminalComponentModeler
77
from tidy3d.plugins.smatrix.data.data_array import PortDataArray, TerminalPortDataArray
8+
from tidy3d.plugins.smatrix.data.terminal import TerminalComponentModelerData
9+
from tidy3d.plugins.smatrix.ports.wave import WavePort
810
from tidy3d.plugins.smatrix.utils import (
911
ab_to_s,
1012
check_port_impedance_sign,
@@ -13,9 +15,7 @@
1315
)
1416

1517

16-
def terminal_construct_smatrix(
17-
modeler_data: TerminalComponentModelerData
18-
) -> TerminalPortDataArray:
18+
def terminal_construct_smatrix(modeler_data: TerminalComponentModelerData) -> TerminalPortDataArray:
1919
"""
2020
Constructs the scattering matrix (S-matrix) from raw simulation data.
2121
@@ -50,12 +50,14 @@ def terminal_construct_smatrix(
5050
b_matrix = a_matrix.copy(deep=True)
5151

5252
# Tabulate the reference impedances at each port and frequency
53-
port_impedances = port_reference_impedances(modeler=modeler_data.modeler)
53+
port_impedances = port_reference_impedances(modeler_data=modeler_data)
5454

5555
# loop through source ports
56-
for port_in in modeler.ports:
57-
sim_data = batch_data[modeler._task_name(port=port_in)]
58-
a, b = compute_power_wave_amplitudes_at_each_port(modeler, port_impedances, sim_data)
56+
for port_in in modeler_data.modeler.ports:
57+
sim_data = modeler_data.data[port_in]
58+
a, b = compute_power_wave_amplitudes_at_each_port(
59+
modeler_data.modeler, port_impedances, sim_data
60+
)
5961
indexer = {"f": a.f, "port_in": port_in.name, "port_out": a.port}
6062
a_matrix.loc[indexer] = a
6163
b_matrix.loc[indexer] = b
@@ -64,9 +66,7 @@ def terminal_construct_smatrix(
6466
return s_matrix
6567

6668

67-
def port_reference_impedances(
68-
modeler_data: TerminalComponentModelerData
69-
) -> PortDataArray:
69+
def port_reference_impedances(modeler_data: TerminalComponentModelerData) -> PortDataArray:
7070
"""
7171
Calculates the reference impedance for each port across all frequencies.
7272
@@ -98,17 +98,19 @@ def port_reference_impedances(
9898
)
9999
coords = {"f": np.array(modeler_data.modeler.freqs), "port": port_names}
100100
port_impedances = PortDataArray(values, coords=coords)
101-
for port in modeler.ports:
101+
for port in modeler_data.modeler.ports:
102102
if isinstance(port, WavePort):
103103
# Mode solver data for each wave port is stored in its associated SimulationData
104-
sim_data_port = batch_data[modeler._task_name(port=port)]
104+
sim_data_port = modeler_data.data[port]
105105
# WavePorts have a port impedance calculated from its associated modal field distribution
106106
# and is frequency dependent.
107107
impedances = port.compute_port_impedance(sim_data_port).values
108108
port_impedances.loc[{"port": port.name}] = impedances.squeeze()
109109
else:
110110
# LumpedPorts have a constant reference impedance
111-
port_impedances.loc[{"port": port.name}] = np.full(len(modeler.freqs), port.impedance)
111+
port_impedances.loc[{"port": port.name}] = np.full(
112+
len(modeler_data.modeler.freqs), port.impedance
113+
)
112114

113115
port_impedances = modeler_data.modeler._set_port_data_array_attributes(port_impedances)
114116
return port_impedances

tidy3d/plugins/smatrix/component_modelers/base.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from tidy3d.exceptions import SetupError, Tidy3dKeyError
1717
from tidy3d.log import log
1818
from tidy3d.plugins.smatrix.ports.modal import Port
19+
from tidy3d.plugins.smatrix.ports.types import TerminalPortType
1920
from tidy3d.plugins.smatrix.ports.wave import WavePort
2021

2122
# fwidth of gaussian pulse in units of central frequency
@@ -86,7 +87,7 @@ def _warn_rf_license(cls, val):
8687
return val
8788

8889
@staticmethod
89-
def _task_name(port: Port, mode_index: Optional[int] = None) -> str:
90+
def get_task_name(port: Port, mode_index: Optional[int] = None) -> str:
9091
"""The name of a task, determined by the port of the source and mode index, if given."""
9192
if mode_index is not None:
9293
return f"smatrix_{port.name}_{mode_index}"

tidy3d/plugins/smatrix/component_modelers/modal.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ def sim_dict(self) -> dict[str, Simulation]:
9393

9494
new_mnts = list(self.simulation.monitors) + mode_monitors
9595
sim_copy = self.simulation.copy(update={"sources": [mode_source], "monitors": new_mnts})
96-
task_name = self._task_name(port=port, mode_index=mode_index)
96+
task_name = self.get_task_name(port=port, mode_index=mode_index)
9797
sim_dict[task_name] = sim_copy
9898
return sim_dict
9999

0 commit comments

Comments
 (0)