Skip to content

Commit 25f3ea4

Browse files
committed
feat(rf): support multimodal waveports
1 parent 09bfc5b commit 25f3ea4

File tree

16 files changed

+739
-689
lines changed

16 files changed

+739
-689
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3939
- `web.Batch(ComponentModeler)` and `web.Job(ComponentModeler)` native support
4040
- Simulation data of batch jobs are now automatically downloaded upon their individual completion in `Batch.run()`, avoiding waiting for the entire batch to reach completion.
4141
- Edge singularity correction at PEC and lossy metal edges defaults to `True`.
42+
- **[BREAKING]** `WavePort` in `tidy3d.plugins.smatrix` now supports multiple modes and has been refactored to use `MicrowaveModeSpec`. The fields `mode_index`, `voltage_integral`, and `current_integral` have been removed. Impedance specifications are now defined in `MicrowaveModeSpec.impedance_specs`. Please see our migration guide for details on updating your code.
4243

4344
### Fixed
4445
- More robust `Sellmeier` and `Debye` material model, and prevent very large pole parameters in `PoleResidue` material model.

docs/api/microwave/microwave_migration.rst

Lines changed: 308 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
11
.. _microwave_migration:
22

3-
v2.10 Refactor Migration
4-
-------------------------
3+
v2.10 Refactor Migration Guide
4+
-------------------------------
55

6-
In version ``v2.10.0``, microwave plugin path integral classes were renamed for improved consistency and clarity. Additionally, these classes (and the impedance calculator) were refactored out of the plugin and moved into ``tidy3d.components.microwave`` and re-exported at the top-level package for convenience. This guide helps you update your scripts to use the new class names and imports.
6+
In version ``v2.10.0``, the microwave and RF simulation capabilities underwent significant refactoring to improve consistency, clarity, and functionality. This guide covers two major sets of breaking changes:
77

8-
Key Changes
9-
~~~~~~~~~~~
8+
1. **Path Integral Class Renames** - Classes were renamed for consistency and moved to ``tidy3d.components.microwave``
9+
2. **WavePort API Changes** - WavePort was refactored to support multiple modes with cleaner impedance specification
10+
11+
This guide helps you update your scripts to work with v2.10+.
12+
13+
1. Path Integral Class Renames
14+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
15+
16+
Path integral classes were renamed for improved consistency and clarity. Additionally, these classes (and the impedance calculator) were refactored out of the plugin and moved into ``tidy3d.components.microwave`` and re-exported at the top-level package for convenience.
17+
18+
**Key changes:**
1019

1120
* **Renamed Classes**: Path integral classes have been renamed to follow a consistent naming pattern.
1221
* **New Import Path (simplified)**: The path integral classes and impedance calculator are now exported at the top level. Prefer importing directly from ``tidy3d`` (e.g., ``from tidy3d import AxisAlignedVoltageIntegral, ImpedanceCalculator``). Existing plugin imports continue to work for backwards compatibility where applicable.
1322

1423
Class Name Changes
15-
~~~~~~~~~~~~~~~~~~
24+
^^^^^^^^^^^^^^^^^^
1625

1726
The following classes have been renamed for consistency:
1827

@@ -31,7 +40,7 @@ The following classes have been renamed for consistency:
3140
* ``CustomPathIntegral2D`` → ``Custom2DPathIntegral``
3241

3342
Migration Examples
34-
~~~~~~~~~~~~~~~~~~
43+
^^^^^^^^^^^^^^^^^^
3544

3645
**Before (v2.9.x):**
3746

@@ -76,7 +85,7 @@ Migration Examples
7685
)
7786
7887
Custom 2D Path Integrals
79-
~~~~~~~~~~~~~~~~~~~~~~~~~
88+
""""""""""""""""""""""""
8089

8190
**Before:**
8291

@@ -125,6 +134,296 @@ Custom 2D Path Integrals
125134
)
126135
127136
Summary
128-
~~~~~~~
137+
^^^^^^^
129138

130139
All functionality remains the same—only class names and preferred import paths have changed. Update your imports to the top level (``from tidy3d import ...``) and class names according to the table above, and your code will work with v2.10. For impedance calculations, import ``ImpedanceCalculator`` directly via ``from tidy3d import ImpedanceCalculator``.
140+
141+
2. WavePort API Changes for Multimodal Support
142+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
143+
144+
The ``WavePort`` class was refactored to support multiple modes and to provide cleaner integration with the microwave mode solver. This required several breaking changes to the API.
145+
146+
Overview of Changes
147+
^^^^^^^^^^^^^^^^^^^
148+
149+
The key improvements in v2.10 include:
150+
151+
* **Multimodal support**: WavePorts can now excite and monitor multiple modes simultaneously
152+
* **Cleaner impedance specification**: Voltage and current path integrals are now specified via ``MicrowaveModeSpec`` instead of directly on the port
153+
* **Mode selection at source creation**: The mode to excite is now specified when creating a source, not when defining the port
154+
* **Improved type safety**: Uses ``MicrowaveModeSpec`` and ``MicrowaveModeMonitor`` for clearer RF-specific behavior
155+
156+
Removed Fields
157+
^^^^^^^^^^^^^^
158+
159+
The following fields have been **removed** from ``WavePort``:
160+
161+
* ``mode_index: int`` - Previously specified which mode to excite (default: 0)
162+
* ``voltage_integral: Optional[VoltageIntegralType]`` - Path integral for voltage calculation
163+
* ``current_integral: Optional[CurrentIntegralType]`` - Path integral for current calculation
164+
165+
New MicrowaveModeSpec Integration
166+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
167+
168+
The ``mode_spec`` field now requires a ``MicrowaveModeSpec`` (instead of the generic ``ModeSpec``). This new class includes:
169+
170+
* ``impedance_specs``: Defines how to compute voltage, current, and characteristic impedance for each mode
171+
172+
Migration Examples
173+
^^^^^^^^^^^^^^^^^^
174+
175+
Single-Mode WavePort
176+
""""""""""""""""""""
177+
178+
**Before (v2.9.x):**
179+
180+
.. code-block:: python
181+
182+
import tidy3d as td
183+
from tidy3d.plugins.smatrix import WavePort
184+
185+
# Define path integrals
186+
voltage_path = td.AxisAlignedVoltageIntegralSpec(
187+
center=(0, 0, 0),
188+
size=(1.0, 0, 0),
189+
sign="+",
190+
)
191+
192+
current_path = td.Custom2DCurrentIntegralSpec.from_circular_path(
193+
center=(0, 0, 0),
194+
radius=0.5,
195+
num_points=21,
196+
normal_axis=2,
197+
clockwise=False
198+
)
199+
200+
# Create WavePort - path integrals attached directly to port
201+
port = WavePort(
202+
center=(0, 0, -5),
203+
size=(2, 2, 0),
204+
direction="+",
205+
mode_spec=td.ModeSpec(num_modes=1), # Generic ModeSpec
206+
mode_index=0, # Which mode to excite
207+
voltage_integral=voltage_path, # Attached to port
208+
current_integral=current_path, # Attached to port
209+
name="port1"
210+
)
211+
212+
**After (v2.10+):**
213+
214+
.. code-block:: python
215+
216+
import tidy3d as td
217+
from tidy3d.plugins.smatrix import WavePort
218+
219+
# Define path integrals (same as before)
220+
voltage_path = td.AxisAlignedVoltageIntegralSpec(
221+
center=(0, 0, 0),
222+
size=(1.0, 0, 0),
223+
sign="+",
224+
)
225+
226+
current_path = td.Custom2DCurrentIntegralSpec.from_circular_path(
227+
center=(0, 0, 0),
228+
radius=0.5,
229+
num_points=21,
230+
normal_axis=2,
231+
clockwise=False
232+
)
233+
234+
# Create WavePort - path integrals now in MicrowaveModeSpec
235+
port = WavePort(
236+
center=(0, 0, -5),
237+
size=(2, 2, 0),
238+
direction="+",
239+
mode_spec=td.MicrowaveModeSpec( # Use MicrowaveModeSpec
240+
num_modes=1,
241+
impedance_specs=td.CustomImpedanceSpec(
242+
voltage_spec=voltage_path, # Moved to impedance_specs
243+
current_spec=current_path
244+
)
245+
),
246+
name="port1"
247+
# Note: mode_index, voltage_integral, current_integral removed
248+
)
249+
250+
# Mode selection now happens at source creation
251+
source_time = td.GaussianPulse(freq0=10e9, fwidth=1e9)
252+
source = port.to_source(source_time, mode_index=0) # Mode selected here
253+
254+
Multi-Mode WavePort (New Feature!)
255+
"""""""""""""""""""""""""""""""""""
256+
257+
The new API enables WavePorts to support multiple modes simultaneously:
258+
259+
.. code-block:: python
260+
261+
import tidy3d as td
262+
from tidy3d.plugins.smatrix import WavePort
263+
264+
# Create a 3-mode WavePort
265+
port = WavePort(
266+
center=(0, 0, -5),
267+
size=(4, 4, 0),
268+
direction="+",
269+
mode_spec=td.MicrowaveModeSpec(
270+
num_modes=3, # Solve for 3 modes
271+
impedance_specs=td.AutoImpedanceSpec() # Auto-compute impedance for all modes
272+
),
273+
name="multimode_port"
274+
)
275+
276+
# Create sources for different modes
277+
source_time = td.GaussianPulse(freq0=10e9, fwidth=1e9)
278+
source_mode0 = port.to_source(source_time, mode_index=0) # Excite mode 0
279+
source_mode1 = port.to_source(source_time, mode_index=1) # Excite mode 1
280+
source_mode2 = port.to_source(source_time, mode_index=2) # Excite mode 2
281+
282+
Per-Mode Impedance Specifications
283+
""""""""""""""""""""""""""""""""""
284+
285+
For advanced use cases, you can specify different impedance calculation methods for each mode:
286+
287+
.. code-block:: python
288+
289+
# Define custom specs for mode 0, auto for modes 1 and 2
290+
port = WavePort(
291+
center=(0, 0, -5),
292+
size=(4, 4, 0),
293+
direction="+",
294+
mode_spec=td.MicrowaveModeSpec(
295+
num_modes=3,
296+
impedance_specs=(
297+
td.CustomImpedanceSpec(
298+
voltage_spec=custom_voltage_path,
299+
current_spec=custom_current_path
300+
), # Mode 0 uses custom specs
301+
td.AutoImpedanceSpec(), # Mode 1 uses auto
302+
td.AutoImpedanceSpec(), # Mode 2 uses auto
303+
)
304+
),
305+
name="mixed_impedance_port"
306+
)
307+
308+
Method Changes
309+
^^^^^^^^^^^^^^
310+
311+
``compute_port_impedance()`` → ``get_port_impedance()``
312+
""""""""""""""""""""""""""""""""""""""""""""""""""""""""
313+
314+
The method for retrieving port impedance has been renamed and now requires a ``mode_index`` parameter:
315+
316+
**Before (v2.9.x):**
317+
318+
.. code-block:: python
319+
320+
# Get impedance - implicitly used port.mode_index
321+
Z0 = port.compute_port_impedance(sim_data)
322+
323+
**After (v2.10+):**
324+
325+
.. code-block:: python
326+
327+
# Get impedance for mode 0
328+
Z0_mode0 = port.get_port_impedance(sim_data, mode_index=0)
329+
330+
# Get impedance for mode 1 (multimodal port)
331+
Z0_mode1 = port.get_port_impedance(sim_data, mode_index=1)
332+
333+
Voltage and Current Computation Shape Changes
334+
""""""""""""""""""""""""""""""""""""""""""""""
335+
336+
For multimodal ports, ``compute_voltage()`` and ``compute_current()`` now return data for **all modes** with a ``mode_index`` dimension:
337+
338+
**Before (v2.9.x):**
339+
340+
.. code-block:: python
341+
342+
# Returns shape: (n_freqs,) - single mode only
343+
voltage = port.compute_voltage(sim_data)
344+
current = port.compute_current(sim_data)
345+
346+
**After (v2.10+):**
347+
348+
.. code-block:: python
349+
350+
# For single-mode port: Returns shape: (n_freqs, 1)
351+
# For multi-mode port: Returns shape: (n_freqs, n_modes)
352+
voltage = port.compute_voltage(sim_data)
353+
current = port.compute_current(sim_data)
354+
355+
# Select specific mode using xarray selection
356+
voltage_mode0 = voltage.sel(mode_index=0)
357+
voltage_mode1 = voltage.sel(mode_index=1)
358+
359+
Using AutoImpedanceSpec for Simplified Setup
360+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
361+
362+
For most cases, you can use ``AutoImpedanceSpec`` which automatically computes voltage, current, and impedance from the electromagnetic fields:
363+
364+
.. code-block:: python
365+
366+
# Simplest form - let Tidy3D auto-compute everything
367+
port = WavePort(
368+
center=(0, 0, -5),
369+
size=(2, 2, 0),
370+
direction="+",
371+
mode_spec=td.MicrowaveModeSpec(
372+
num_modes=2,
373+
impedance_specs=td.AutoImpedanceSpec() # Works for all modes
374+
),
375+
name="simple_port"
376+
)
377+
378+
Breaking Changes Summary
379+
^^^^^^^^^^^^^^^^^^^^^^^^
380+
381+
The following table summarizes all breaking changes to the ``WavePort`` API:
382+
383+
.. list-table::
384+
:header-rows: 1
385+
:widths: 30 30 40
386+
387+
* - Change
388+
- Old (v2.9.x)
389+
- New (v2.10+)
390+
* - Port field: mode_index
391+
- ``mode_index=0``
392+
- Removed. Use ``to_source(mode_index=0)``
393+
* - Port field: voltage_integral
394+
- ``voltage_integral=path``
395+
- Removed. Use ``mode_spec.impedance_specs``
396+
* - Port field: current_integral
397+
- ``current_integral=path``
398+
- Removed. Use ``mode_spec.impedance_specs``
399+
* - mode_spec type
400+
- ``ModeSpec``
401+
- ``MicrowaveModeSpec``
402+
* - Impedance method
403+
- ``compute_port_impedance(sim_data)``
404+
- ``get_port_impedance(sim_data, mode_index)``
405+
* - Monitor type
406+
- Returns ``ModeMonitor``
407+
- Returns ``MicrowaveModeMonitor``
408+
* - Voltage/current shape
409+
- ``(n_freqs,)`` - single mode
410+
- ``(n_freqs, n_modes)`` - all modes
411+
* - Multimodal support
412+
- Not supported
413+
- Fully supported via ``num_modes``
414+
415+
Benefits of the New API
416+
^^^^^^^^^^^^^^^^^^^^^^^^
417+
418+
The refactored API provides several advantages:
419+
420+
* **Multimodal ports**: Support for multiple modes enables more accurate modeling of multimode waveguides and transmission lines
421+
* **Cleaner separation of concerns**: Mode selection happens at excitation time, not port definition time
422+
* **Type safety**: ``MicrowaveModeSpec`` and ``MicrowaveModeMonitor`` make RF-specific behavior explicit
423+
* **Flexibility**: Per-mode impedance specifications allow fine-grained control
424+
* **Consistency**: Aligns with the general pattern of ``ModeSource`` where ``mode_index`` is a source parameter
425+
426+
Backward Compatibility
427+
^^^^^^^^^^^^^^^^^^^^^^
428+
429+
There is **no backward compatibility** for WavePort instantiation with the old field names (``mode_index``, ``voltage_integral``, ``current_integral``). Attempting to use these fields will result in a Pydantic validation error. All code using ``WavePort`` must be updated to the new API when upgrading to v2.10.

0 commit comments

Comments
 (0)