Skip to content

Commit 0b23b05

Browse files
committed
Add interpolation to EME
1 parent aedc3a9 commit 0b23b05

File tree

3 files changed

+45
-11
lines changed

3 files changed

+45
-11
lines changed

tidy3d/components/eme/data/sim_data.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,11 +197,23 @@ def smatrix_in_basis(
197197
modes1 = port_modes1
198198
if not modes2_provided:
199199
modes2 = port_modes2
200-
f1 = list(modes1.field_components.values())[0].f.values
201-
f2 = list(modes2.field_components.values())[0].f.values
200+
f1 = list(modes1.monitor.freqs)
201+
f2 = list(modes2.monitor.freqs)
202202

203203
f = np.array(sorted(set(f1).intersection(f2).intersection(self.simulation.freqs)))
204204

205+
interp_spec1 = modes1.monitor.mode_spec.interp_spec
206+
interp_spec2 = modes2.monitor.mode_spec.interp_spec
207+
208+
interp_overlaps = False
209+
if interp_spec1 is not None and interp_spec2 is not None and interp_spec1 == interp_spec2:
210+
interp_overlaps = True
211+
else:
212+
if interp_spec1 is not None:
213+
modes1 = modes1.interpolated_copy
214+
if interp_spec2 is not None:
215+
modes2 = modes2.interpolated_copy
216+
205217
modes_in_1 = "mode_index" in list(modes1.field_components.values())[0].coords
206218
modes_in_2 = "mode_index" in list(modes2.field_components.values())[0].coords
207219

@@ -259,6 +271,10 @@ def smatrix_in_basis(
259271
overlaps1 = modes1.outer_dot(port_modes1, conjugate=False)
260272
if not modes_in_1:
261273
overlaps1 = overlaps1.expand_dims(dim={"mode_index_0": mode_index_1}, axis=1)
274+
if interp_overlaps:
275+
overlaps1 = modes1._interp_dataarray_in_freq(
276+
overlaps1, freqs=f, method=interp_spec1.method
277+
)
262278
O1 = overlaps1.sel(f=f, mode_index_1=keep_mode_inds1)
263279

264280
O1out = O1.rename(mode_index_0="mode_index_out", mode_index_1="mode_index_out_old")
@@ -288,6 +304,9 @@ def smatrix_in_basis(
288304
overlaps2 = modes2.outer_dot(port_modes2, conjugate=False)
289305
if not modes_in_2:
290306
overlaps2 = overlaps2.expand_dims(dim={"mode_index_0": mode_index_2}, axis=1)
307+
overlaps2 = modes2._interp_dataarray_in_freq(
308+
overlaps2, freqs=f, method=interp_spec2.method
309+
)
291310
O2 = overlaps2.sel(f=f, mode_index_1=keep_mode_inds2)
292311

293312
O2out = O2.rename(mode_index_0="mode_index_out", mode_index_1="mode_index_out_old")

tidy3d/components/eme/grid.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
from tidy3d.components.base import Tidy3dBaseModel, skip_if_fields_missing
1212
from tidy3d.components.geometry.base import Box
1313
from tidy3d.components.grid.grid import Coords1D
14-
from tidy3d.components.mode_spec import ModeSpec
14+
from tidy3d.components.mode_spec import ModeInterpSpec, ModeSpec, UniformSampling
1515
from tidy3d.components.structure import Structure
16-
from tidy3d.components.types import ArrayFloat1D, Axis, Coordinate, Size, TrackFreq
16+
from tidy3d.components.types import ArrayFloat1D, Axis, Coordinate, Size
1717
from tidy3d.constants import RADIAN, fp_eps, inf
1818
from tidy3d.exceptions import SetupError, ValidationError
1919

@@ -26,13 +26,16 @@
2626
class EMEModeSpec(ModeSpec):
2727
"""Mode spec for EME cells. Overrides some of the defaults and allowed values."""
2828

29-
track_freq: Union[TrackFreq, None] = pd.Field(
30-
None,
31-
title="Mode Tracking Frequency",
32-
description="Parameter that turns on/off mode tracking based on their similarity. "
33-
"Can take values ``'lowest'``, ``'central'``, or ``'highest'``, which correspond to "
34-
"mode tracking based on the lowest, central, or highest frequency. "
35-
"If ``None`` no mode tracking is performed, which is the default for best performance.",
29+
interp_spec: Optional[ModeInterpSpec] = pd.Field(
30+
ModeInterpSpec(
31+
method="cubic", sampling_spec=UniformSampling(num_points=4), reduce_data=True
32+
),
33+
title="Mode frequency interpolation specification",
34+
description="Specification for computing modes at a reduced set of frequencies and "
35+
"interpolating to obtain results at all requested frequencies. This can significantly "
36+
"reduce computational cost for broadband simulations where modes vary smoothly with "
37+
"frequency. Requires frequency tracking to be enabled (``sort_spec.track_freq`` must "
38+
"not be ``None``) to ensure consistent mode ordering across frequencies.",
3639
)
3740

3841
angle_theta: Literal[0.0] = pd.Field(

tidy3d/components/eme/simulation.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,18 @@ def _monitor_freqs(self, monitor: Monitor) -> list[pd.NonNegativeFloat]:
10071007
return list(self.freqs)
10081008
return list(monitor.freqs)
10091009

1010+
def _monitor_mode_freqs(self, monitor: EMEModeSolverMonitor) -> list[pd.NonNegativeFloat]:
1011+
"""Monitor frequencies."""
1012+
freqs = set()
1013+
cell_inds = self._monitor_eme_cell_indices(monitor=monitor)
1014+
for cell_ind in cell_inds:
1015+
interp_spec = self.eme_grid.mode_specs[cell_ind].interp_spec
1016+
if interp_spec is None:
1017+
freqs |= set(self.freqs)
1018+
else:
1019+
freqs |= set(interp_spec.sampling_points(self.freqs))
1020+
return list(freqs)
1021+
10101022
def _monitor_num_freqs(self, monitor: Monitor) -> int:
10111023
"""Total number of freqs included in monitor."""
10121024
return len(self._monitor_freqs(monitor=monitor))

0 commit comments

Comments
 (0)