Skip to content

Conversation

dmarek-flex
Copy link
Contributor

@dmarek-flex dmarek-flex commented Sep 23, 2025

add a ImpedanceSpec for controlling how characteristic impedance is calculated from modes

backend PR: https://github.com/flexcompute/compute/pull/2497

  • Finalize docs including the new Microwave components somewhere (monitors/mode_specs/path_specs)
  • Implement more precise mode plane bounds calculation raised by @dbochkov-flexcompute
  • Support ModeSimulation

Greptile Overview

Updated On: 2025-10-07 20:11:19 UTC

Summary

This PR introduces a comprehensive impedance calculation system for microwave mode solvers in Tidy3D. The implementation adds the ability to calculate characteristic impedance from electromagnetic modes, which is essential for microwave and RF transmission line analysis.

Key architectural changes:

  • New impedance specification system: Introduces ImpedanceSpecTypes union with AutoImpedanceSpec for automatic impedance calculation and CustomImpedanceSpec for user-defined voltage/current path integrals
  • Microwave mode specifications: Adds MicrowaveModeSpec extending the base mode specification with impedance calculation capabilities for each mode
  • Enhanced mode solver integration: Extends ModeSpec, ModeSolver, and related classes to support microwave specifications while maintaining backward compatibility
  • Path integral infrastructure: Comprehensive system for voltage and current path integral specifications including axis-aligned, custom 2D, and composite current integrals
  • New monitor types: Adds MicrowaveModeMonitor and MicrowaveModeSolverMonitor for microwave-specific data collection
  • Data extensions: New MicrowaveModeData and MicrowaveModeSolverData classes that include transmission line characteristics (impedance, voltage/current coefficients)

Implementation highlights:

  • Mode plane analysis: Automatic conductor detection and path generation for simple geometries through ModePlaneAnalyzer
  • Flexible impedance calculation: Supports both direct calculation (when voltage and current integrals are available) and fallback methods using power flux
  • Comprehensive validation: Multi-level validation ensures proper setup before expensive simulation runs
  • Clean refactoring: Established microwave component hierarchy with MicrowaveBaseModel base class for consistent RF licensing and functionality
  • API consistency improvements: Standardized naming conventions for path integral classes (e.g., VoltageIntegralAxisAlignedAxisAlignedVoltageIntegral)

The system integrates seamlessly with existing Tidy3D workflows - users can continue using standard mode specifications for basic electromagnetic analysis while accessing advanced impedance calculations through the new microwave specifications. The architecture properly separates automatic impedance calculation for common cases from custom path integral specifications for complex geometries.

PR Description Notes:

  • The PR description references an incomplete checklist item about finalizing documentation, but the migration guide and API documentation appear comprehensive

Important Files Changed

Changed Files
Filename Score Overview
tidy3d/components/microwave/path_integrals/impedance_spec.py 4/5 New impedance specification system with Auto and Custom variants, comprehensive validation
tidy3d/components/microwave/microwave_mode_spec.py 5/5 Clean microwave mode specification implementation with proper caching and validation
tidy3d/plugins/microwave/impedance_calculator.py 4/5 Core impedance calculator with voltage/current integral support, minor style improvements needed
tidy3d/components/mode_spec.py 3/5 Contains syntax error in validation message that needs fixing
tidy3d/components/microwave/path_integrals/mode_plane_analyzer.py 4/5 Sophisticated conductor analysis for automatic impedance calculation
tidy3d/components/mode/mode_solver.py 4/5 Major extension to support microwave impedance calculations while maintaining compatibility
tidy3d/components/microwave/path_integrals/base_spec.py 5/5 Well-designed base classes for path integral specifications
tidy3d/components/microwave/path_integrals/voltage_spec.py 4/5 Voltage path integral specifications with minor spelling error in docstring
tidy3d/components/microwave/path_integrals/current_spec.py 5/5 Comprehensive current path integral specifications including composite support
tidy3d/components/microwave/monitor.py 5/5 Clean microwave monitor implementations extending existing monitors
tidy3d/components/microwave/data/monitor_data.py 5/5 Well-structured microwave data classes with proper inheritance
tidy3d/components/microwave/base.py 5/5 Clean base class for microwave components with RF licensing warnings
tidy3d/components/simulation.py 4/5 Added microwave mode specification validation with proper error handling
tidy3d/components/geometry/utils.py 4/5 Enhanced geometry utilities with new snapping behaviors and flattening functions
tidy3d/plugins/microwave/path_integrals.py 4/5 Refactored path integral execution classes following spec/execution separation
tidy3d/plugins/microwave/custom_path_integrals.py 4/5 Complex custom path integrals with phase analysis and composite current support
docs/api/microwave/microwave_migration.rst 5/5 Comprehensive migration guide for API changes
tidy3d/__init__.py 5/5 Clean addition of microwave components to public API
CHANGELOG.md 4/5 Comprehensive changelog entries with minor duplicate entry cleanup needed
Multiple schema files 5/5 Properly updated JSON schemas for all new microwave components

Confidence score: 3/5

  • This PR requires careful review due to a syntax error that will cause runtime failures
  • Score lowered due to syntax error in validation message and extensive scope of changes requiring thorough testing
  • Pay close attention to tidy3d/components/mode_spec.py for the missing closing quote in the validation error message

Context used:

Rule from dashboard - Do not use markdown formatting in exception or warning messages; use single quotes to highlight vari... (source)
Rule from dashboard - Update the CHANGELOG.md file when making changes that affect user-facing functionality or fix bugs. (source)

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

28 files reviewed, 2 comments

Edit Code Review Bot Settings | Greptile

@dmarek-flex dmarek-flex force-pushed the dmarek/add_impedance_to_mode_data branch 2 times, most recently from ceccb9e to 18ced37 Compare September 23, 2025 19:21
@dmarek-flex dmarek-flex linked an issue Sep 23, 2025 that may be closed by this pull request
@dmarek-flex dmarek-flex self-assigned this Sep 23, 2025
@dmarek-flex dmarek-flex added the RF label Sep 23, 2025
Copy link
Contributor

github-actions bot commented Sep 24, 2025

Diff Coverage

Diff: origin/develop...HEAD, staged and unstaged changes

  • tidy3d/init.py (100%)
  • tidy3d/components/boundary.py (100%)
  • tidy3d/components/data/data_array.py (100%)
  • tidy3d/components/data/monitor_data.py (100%)
  • tidy3d/components/data/sim_data.py (100%)
  • tidy3d/components/eme/simulation.py (100%)
  • tidy3d/components/geometry/utils.py (98.0%): Missing lines 657
  • tidy3d/components/lumped_element.py (100%)
  • tidy3d/components/microwave/base.py (92.3%): Missing lines 27
  • tidy3d/components/microwave/data/dataset.py (100%)
  • tidy3d/components/microwave/data/monitor_data.py (100%)
  • tidy3d/components/microwave/mode_spec.py (100%)
  • tidy3d/components/microwave/monitor.py (100%)
  • tidy3d/components/microwave/path_integrals/base_spec.py (100%)
  • tidy3d/components/microwave/path_integrals/current_spec.py (100%)
  • tidy3d/components/microwave/path_integrals/impedance_spec.py (100%)
  • tidy3d/components/microwave/path_integrals/mode_plane_analyzer.py (100%)
  • tidy3d/components/microwave/path_integrals/path_integral_factory.py (96.4%): Missing lines 127-128
  • tidy3d/components/microwave/path_integrals/types.py (100%)
  • tidy3d/components/microwave/path_integrals/viz.py (100%)
  • tidy3d/components/microwave/path_integrals/voltage_spec.py (100%)
  • tidy3d/components/mode/mode_solver.py (96.6%): Missing lines 1387,2027
  • tidy3d/components/mode/simulation.py (100%)
  • tidy3d/components/mode_spec.py (100%)
  • tidy3d/components/monitor.py (100%)
  • tidy3d/components/simulation.py (100%)
  • tidy3d/components/source/field.py (100%)
  • tidy3d/components/types/mode_spec.py (100%)
  • tidy3d/components/types/monitor.py (100%)
  • tidy3d/components/types/monitor_data.py (100%)
  • tidy3d/plugins/microwave/array_factor.py (100%)
  • tidy3d/plugins/microwave/auto_path_integrals.py (100%)
  • tidy3d/plugins/microwave/custom_path_integrals.py (98.9%): Missing lines 233
  • tidy3d/plugins/microwave/impedance_calculator.py (100%)
  • tidy3d/plugins/microwave/lobe_measurer.py (100%)
  • tidy3d/plugins/microwave/path_integrals.py (100%)
  • tidy3d/plugins/smatrix/component_modelers/base.py (100%)
  • tidy3d/plugins/smatrix/component_modelers/terminal.py (100%)
  • tidy3d/plugins/smatrix/data/terminal.py (100%)
  • tidy3d/plugins/smatrix/ports/base_terminal.py (100%)
  • tidy3d/plugins/smatrix/ports/coaxial_lumped.py (100%)
  • tidy3d/plugins/smatrix/ports/rectangular_lumped.py (100%)
  • tidy3d/utils.py (100%)

Summary

  • Total: 918 lines
  • Missing: 7 lines
  • Coverage: 99%

tidy3d/components/geometry/utils.py

Lines 653-661

  653                 strict_bounds=strict_bounds,
  654                 margin=-snap_margin,
  655             )
  656             if max_snap < min_snap:
! 657                 raise SetupError("The supplied 'snap_margin' is too large for this contraction.")
  658         return (min_snap, max_snap)
  659 
  660     # Iterate over each axis and apply the specified snapping behavior.
  661     min_b, max_b = (list(f) for f in box.bounds)

tidy3d/components/microwave/base.py

Lines 23-31

  23     def _warn_rf_license(cls, values):
  24         suppress_instantiation_warnings = values.get("suppress_instantiation_warnings")
  25         # Skip warning during test runs or when built with suppression
  26         if not is_running_pytest() and not suppress_instantiation_warnings:
! 27             log.warning(
  28                 "ℹ️ ⚠️ RF simulations are subject to new license requirements in the future. You have instantiated at least one RF-specific component.",
  29                 log_once=True,
  30             )
  31         return values

tidy3d/components/microwave/path_integrals/path_integral_factory.py

Lines 123-132

  123             v_integrals.append(None)
  124             i_integrals.append(None)
  125             continue
  126         elif isinstance(impedance_spec, AutoImpedanceSpec):
! 127             v_spec = None
! 128             i_spec = auto_spec.current_spec
  129         else:
  130             v_spec = impedance_spec.voltage_spec
  131             i_spec = impedance_spec.current_spec

tidy3d/components/mode/mode_solver.py

Lines 1383-1391

  1383     ) -> tuple[tuple[Optional[VoltageIntegralTypes]], tuple[Optional[CurrentIntegralTypes]]]:
  1384         """Wrapper for making path integrals from the MicrowaveModeSpec. Note: overriden in the backend to support
  1385         auto creation of path integrals."""
  1386         if not self._has_microwave_mode_spec:
! 1387             raise ValueError(
  1388                 "Cannot make path integrals for when 'mode_spec' is not a 'MicrowaveModeSpec'."
  1389             )
  1390         return make_path_integrals(self.mode_spec)

Lines 2023-2031

  2023             )
  2024 
  2025         mode_solver_monitor_type = ModeMonitor
  2026         if isinstance(self.mode_spec, MicrowaveModeSpec):
! 2027             mode_solver_monitor_type = MicrowaveModeMonitor
  2028 
  2029         return mode_solver_monitor_type(
  2030             center=self.plane.center,
  2031             size=self.plane.size,

tidy3d/plugins/microwave/custom_path_integrals.py

Lines 229-237

  229 
  230         # Perform phase splitting into in and out of phase for each frequency separately
  231         for term in path_currents:
  232             if np.all(term.abs == 0):
! 233                 continue
  234 
  235             # Compare phase to reference for each frequency
  236             phase_diff = term.angle - phase_reference
  237             # Wrap phase difference to [-pi, pi]

Copy link
Collaborator

@weiliangjin2021 weiliangjin2021 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most went through code structures, and the structure looks in good shape. Some minor comments:

Copy link
Contributor

@dbochkov-flexcompute dbochkov-flexcompute left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very impressive work, finished the first pass and left some comments. Additionally, it seems like many new classes AxisAlignedPathIntegralSpec, CustomPathIntegral2DSpec, CurrentIntegralAxisAlignedSpec, CustomCurrentIntegral2DSpec, CompositeCurrentIntegralSpec, CustomImpedanceSpec, etc are missing examples in docstrings

@dmarek-flex dmarek-flex force-pushed the dmarek/add_impedance_to_mode_data branch from 7ad7a12 to 2727e2f Compare September 30, 2025 13:11
@dmarek-flex dmarek-flex added the rc2 2nd pre-release label Sep 30, 2025
@dmarek-flex dmarek-flex force-pushed the dmarek/add_impedance_to_mode_data branch from 917c3ad to d23f936 Compare September 30, 2025 17:52
@dmarek-flex
Copy link
Contributor Author

Thanks @dbochkov-flexcompute for finding those docstring mistakes. It was a little bit harder than expected to get doc tests running correctly because of the log warning we have for rf and microwave components. I got it working by introducing the MicrowaveBaseModel class. @daquinteroflex does this approach make sense for replacing the duplicated method for warning.

Copy link
Collaborator

@daquinteroflex daquinteroflex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good @dmarek-flex ! Just a few questions on very few API design considerations

GROUP_INDEX_STEP = 0.005


class ModeSpec(Tidy3dBaseModel):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So yeah why simply not make a class MicrowaveModeSpec(ModeSpec) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did try this approach and it worked ok for the ModeSpec/MicrowaveModeSpec side of things. But then I felt like I would need to have a MicrowaveModeData/MicrowaveModeSolverData and that would require modifications all over the code base (frontend and backend) to provide the correct type hints and Pydantic fields.

And then following that logic we would need a MicrowaveModeMonitor/MicrowaveModeSolverMonitor/MicrowaveModeSimulation and it felt like maintaining the proper type hints would be a lot of extra work. From trying this out, inheritance did not seem the easiest approach for maintenance, and I decided that composition would be a better approach.

Copy link
Collaborator

@daquinteroflex daquinteroflex Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yaugenst-flex @tylerflex it'd be good to get your input here in terms of how we do separation of scope rather than mixing RF into the general ModeSpec as currently implemented in this PR per the following lines in this file. It is concievable that MicrowaveModeSpec(ModeSpec) keeps getting extended as well as future classes that Damian mentioned in order to provide custom RF functionality eventually, but it is a larger effort in terms of the API restructure that we also have to consider. The benefit though is a stronger separation of API, which is related to previous conversations we've had privately about product scope.

microwave_spec: Optional[MicrowaveModeSpec] = pd.Field(
None,
title="Microwave Mode Specification",
description="Optional field with additional parameters for RF and microwave applications. "
"Includes impedance specifications that enable the calculation of characteristic impedances "
"for transmission line modes.",
)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea I'd rather make a dedicated MicrowaveModeSpec(ModeSpec) in a separate place vs mixing it into the component as microwave_spec: Optional[MicrowaveModeSpec] = pd.Field

eventually I think all of the RF-specific components should be moved into their own separate namespace, like a tidy3d.rf, and that includes terminal component modeler, MicrowaveModeSpec, and probably a separate RFSimulation.

To me that seems like the long term direction (a separate rf python package that extends tidy3d, but tidy3d proper can be independent of it)

Copy link
Contributor Author

@dmarek-flex dmarek-flex Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MicrowaveModeSpec makes sense but then I need to create new classes that accept it, which will lead to MicrowaveModeData/MicrowaveModeSolverData/MicrowaveModeMonitor/MicrowaveModeSolverMonitor/MicrowaveModeSimulation versions?

Or do I allow a ModeMonitor to accept both mode_specs but produce either ModeData or MicrowaveModeData depending on the spec?

Copy link
Collaborator

@daquinteroflex daquinteroflex Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ultimately, sounds like we should go this way in the long run @dmarek-flex though, and try to have a cleaner separation for RF. Happy to chat to scope this out if we want to do this for 2.10 too before getting to MicrowaveSimulation? This said it'd be good for the product council to discuss the extra effort this might take to start doing this separation in the RF product plans @tylerflex ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea, it's a tough call, because we will start to have tons of classes, but I also feel it should happen eventually. Hopefully most of these could be very thin wrappers around the tidy3d objects that they inherit from?

Ideally we can get to a place where tidy3d just contains stuff for basic fdtd + photonics. and tidy3d.rf extends tidy3d and adds anything specific to microwave. I think we'll necessarily have to add more classes there but hopefully most things can be shared.

@dmarek-flex dmarek-flex force-pushed the dmarek/add_impedance_to_mode_data branch 2 times, most recently from 837a080 to c685b6b Compare October 2, 2025 17:28
@dmarek-flex dmarek-flex added rc3 3rd pre-release and removed rc2 2nd pre-release labels Oct 7, 2025
@dmarek-flex dmarek-flex changed the title add impedance calculations to mode solver FXC-3517 add impedance calculations to mode solver Oct 7, 2025
@dmarek-flex dmarek-flex force-pushed the dmarek/add_impedance_to_mode_data branch 2 times, most recently from bee9d40 to 008ab9f Compare October 7, 2025 19:09
@dmarek-flex
Copy link
Contributor Author

Alright lets have another go @greptileai. Also since @daquinteroflex is away, can @tylerflex or @yaugenst-flex take a look at this refactoring of the MicrowaveModeSpec and monitors/monitor data

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (1)

  1. tidy3d/plugins/microwave/auto_path_integrals.py, line 32-34 (link)

    logic: Parameter descriptions don't match parameter names - lumped_element and grid descriptions are incorrect

    Context Used: Rule from dashboard - Keep docstrings and comments synchronized with code changes to ensure they are always accurate and n... (source)

63 files reviewed, 9 comments

Edit Code Review Agent Settings | Greptile

@dmarek-flex dmarek-flex force-pushed the dmarek/add_impedance_to_mode_data branch 2 times, most recently from b2458d6 to 40bcc17 Compare October 8, 2025 14:29
add a ImpedanceSpec for controlling how characteristic impedance is calculated from modes

add MicrowaveModeMonitor and MicrowaveModeSolverMonitor that accepts the new MicrowaveModeSpec

BREAKING CHANGE: changed path integral class names in plugins/microwave
refactor impedance results into MicrowaveModeData and associated classes

refactor monitors in progress

finishing monitor/data refactor

fix changelog

improve coverage

changelog and migration guide update

fix mode limits calc and improve snapping helpers
@dmarek-flex dmarek-flex force-pushed the dmarek/add_impedance_to_mode_data branch from 40bcc17 to e9ca7aa Compare October 8, 2025 14:47
Copy link
Collaborator

@weiliangjin2021 weiliangjin2021 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very impressive work! All look solid. One question: all integral_specs are defined in component/microwave, but the actual integration computation is defined in plugin/microwave. Should we unify this by moving them from plugin to component?

@tylerflex
Copy link
Collaborator

tylerflex commented Oct 10, 2025

@dmarek-flex @weiliangjin2021

One question: all integral_specs are defined in component/microwave, but the actual integration computation is defined in plugin/microwave. Should we unify this by moving them from plugin to component?

We should figure out a plan regarding the RF/Tidy3D separation and organization long term.

@weiliangjin2021 just for a sense, here are some related discussions #2837 (comment)

My feeling is that the best long term solution is a complete separation of RF from the main tidy3d components. Meaning perhaps a tidy3d.rf namespace where all of the RF components, TerminalComponentModeler, microwave plugin, etc. can live.

But for this to be a reality, we would need to (at least):

  • Figure out how we want to extend tidy3d components / schemas to RF, eg. that ModeSpec discussion. Perhaps inheritance for start? with RF then having it's own schema that extends the tidy3d schema
  • Write the web API in a more generic way so we can easily extend it. Maybe using Protocol.
  • We may need dedicated web endpoints for RF, which we should eventually have but will be a bigger effort.

Could you guys think about this a bit in terms of requirements from your side and any preferences? @weiliangjin2021 let's discuss together with yannick and Lucas at the tech council meeting monday to get a general feeling because the same issues arise in photonforge.

@tylerflex
Copy link
Collaborator

I just started looking at this:

One idea occurred to me, which is that if we eventually do want to import rf components through a tidy3d.rf namespace, and this helps with organization, we could already create this namespace, eg tidy3d/rf/__init__.py that imports all RF related things directly, including TerminalComponentModeler. And then deprecate or leave out of the main tidy3d/__init__.py

While underlying things would still be all mixed without any changes, this would at least give us an ability to start crafting the user-facing side of the package.

note sure if worth doing here since this is a needed feature, but wanted to make a note.

@yaugenst-flex @daquinteroflex FYI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rc3 3rd pre-release RF

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Automatic setup of path integrals

5 participants