-
Notifications
You must be signed in to change notification settings - Fork 65
feat(rf): FXC-3725 add voltage-based selection of modes to the ModeSolver #2948
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
dmarek-flex
wants to merge
2
commits into
develop
Choose a base branch
from
dmarek/FXC-3725-voltage-based-mode-selection
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
c6b771b to
fac5487
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
7 files reviewed, 8 comments
tidy3d/components/microwave/path_integrals/mode_plane_analyzer.py
Outdated
Show resolved
Hide resolved
tidy3d/components/microwave/path_integrals/mode_plane_analyzer.py
Outdated
Show resolved
Hide resolved
tidy3d/components/microwave/path_integrals/mode_plane_analyzer.py
Outdated
Show resolved
Hide resolved
fac5487 to
90a1ac0
Compare
Diff CoverageDiff: origin/develop...HEAD, staged and unstaged changes
Summary
tidy3d/components/microwave/path_integrals/mode_plane_analyzer.pyLines 255-298 255
256 def _convert_terminal_specifications_to_candidate_geometry(
257 self, structures: list[Structure], terminal_specs: list[TerminalSpec]
258 ) -> list[TerminalSpecShapes]:
! 259 def find_structure_by_name(target_name):
260 """Find first element where name matches target_name."""
! 261 return next(
262 (item for item in structures if item.name is not None and item.name == target_name),
263 None,
264 )
265
! 266 def convert_terminal(terminal_specifier) -> Shapely:
! 267 if isinstance(terminal_specifier, tuple):
! 268 return Point(*terminal_specifier)
! 269 elif isinstance(terminal_specifier, str):
! 270 structure = find_structure_by_name(terminal_specifier)
! 271 if structure is None:
! 272 raise SetupError(
273 f"No structure found with name '{terminal_specifier}'. "
274 "Please ensure that a `Structure` with the same name has been added to the simulation."
275 )
! 276 shapes_plane = self.intersections_with(structure.geometry)
! 277 return shapes_plane
! 278 elif terminal_specifier.shape[0] == 1:
! 279 return Point(*terminal_specifier)
! 280 elif terminal_specifier.shape[0] == 2:
! 281 return LineString(terminal_specifier)
282 else:
! 283 return Polygon(terminal_specifier)
284
! 285 terminal_spec_shapes = []
! 286 for terminal_spec in terminal_specs:
! 287 plus_spec_shapes = [
288 convert_terminal(plus_terminal) for plus_terminal in terminal_spec.plus_terminals
289 ]
! 290 minus_spec_shapes = [
291 convert_terminal(minus_terminal) for minus_terminal in terminal_spec.minus_terminals
292 ]
! 293 terminal_spec_shapes.append((plus_spec_shapes, minus_spec_shapes))
! 294 return terminal_spec_shapes
295
296 def _find_conductor_terminals(
297 self,
298 conductor_shapely: list[Shapely],Lines 315-326 315 list[VoltageSets]
316 List of (positive_conductor_indices, negative_conductor_indices) for each terminal spec.
317 """
318
! 319 def validate_conductor_intersection(indices: list[int], terminal_type: str) -> None:
320 """Validate that exactly one conductor intersects with the terminal."""
! 321 if len(indices) == 0:
! 322 raise SetupError(
323 f"No conductor found intersecting with the {terminal_type}_terminal. "
324 "Please ensure that your terminal specification (coordinate, line, or polygon) "
325 "intersects with at least one conductive structure in the mode plane. "
326 "Check that the terminal coordinates are within the bounds of a conductor."Lines 324-333 324 "Please ensure that your terminal specification (coordinate, line, or polygon) "
325 "intersects with at least one conductive structure in the mode plane. "
326 "Check that the terminal coordinates are within the bounds of a conductor."
327 )
! 328 elif len(indices) > 1:
! 329 raise SetupError(
330 f"Multiple conductors ({len(indices)}) found intersecting with the {terminal_type}_terminal. "
331 "Please ensure that your terminal specification intersects with exactly one conductor. "
332 "Consider making your terminal specification more precise (e.g., using a smaller region or point) "
333 "to uniquely identify a single conductor."Lines 332-357 332 "Consider making your terminal specification more precise (e.g., using a smaller region or point) "
333 "to uniquely identify a single conductor."
334 )
335
! 336 terminals = []
! 337 for term_spec in terminal_specs:
! 338 all_plus_indices = set()
! 339 all_minus_indices = set()
! 340 for plus_terminal in term_spec[0]:
! 341 plus_indices = [
342 i for i, geom in enumerate(conductor_shapely) if geom.intersects(plus_terminal)
343 ]
! 344 validate_conductor_intersection(plus_indices, "plus")
! 345 all_plus_indices.update(plus_indices)
! 346 for minus_terminal in term_spec[1]:
! 347 minus_indices = [
348 i for i, geom in enumerate(conductor_shapely) if geom.intersects(minus_terminal)
349 ]
! 350 validate_conductor_intersection(minus_indices, "minus")
! 351 all_minus_indices.update(minus_indices)
! 352 terminals.append((all_plus_indices, all_minus_indices))
! 353 return terminals
354
355 def _validate_conductor_voltage_configurations(
356 self, conductor_voltage_sets: list[VoltageSets]
357 ) -> None:tidy3d/components/mode/mode_solver.pyLines 377-396 377 f"Failed to automatically place paths around conductors in the mode plane. {e!s}"
378 ) from e
379
380 if mode_spec.terminal_specs is not None:
! 381 try:
! 382 terminal_spec_shapes = (
383 mode_plane_analyzer._convert_terminal_specifications_to_candidate_geometry(
384 sim.structures, mode_spec.terminal_specs
385 )
386 )
! 387 voltage_sets = mode_plane_analyzer._find_conductor_terminals(
388 conductor_shapes, terminal_spec_shapes
389 )
! 390 mode_plane_analyzer._validate_conductor_voltage_configurations(voltage_sets)
! 391 except SetupError as e:
! 392 raise SetupError(f"'TerminalSpec' was not setup correctly. {e!s}") from e
393
394 @cached_property
395 def normal_axis(self) -> Axis:
396 """Axis normal to the mode plane."""Lines 1457-1465 1457 self,
1458 mode_solver_data: MicrowaveModeSolverData,
1459 ) -> MicrowaveModeSolverData:
1460 """Select, sort and post process modes to match terminal specifications."""
! 1461 raise SetupError("Terminal-based mode setup is not available for the local mode solver.")
1462
1463 def _add_microwave_data(
1464 self, mode_solver_data: MicrowaveModeSolverData
1465 ) -> MicrowaveModeSolverData:Lines 1466-1474 1466 """Calculate and add microwave data to ``mode_solver_data`` which uses the path specifications."""
1467
1468 # Check if terminal specifications are present and will be used to drive the mode ordering and selection
1469 if self.mode_spec.terminal_specs is not None:
! 1470 mode_solver_data = self._post_process_modes_with_terminal_specs(mode_solver_data)
1471
1472 voltage_integrals, current_integrals = self._make_path_integrals()
1473 # Need to operate on the full symmetry expanded fields
1474 mode_solver_data_expanded = mode_solver_data.symmetry_expanded_copy |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
backend: https://github.com/flexcompute/compute/pull/2764
Greptile Overview
Updated On: 2025-11-04 21:24:30 UTC
Greptile Summary
This PR adds voltage-based mode selection capability to the ModeSolver through a new
TerminalSpecclass that allows users to specify which conductors should be at positive or negative voltage for transmission line modes.Key changes:
TerminalSpecclass to specify voltage patterns across conductors using coordinate points, structure names, or geometric regionsterminal_specsfield toMicrowaveModeSpecfor mode selection and orderingModePlaneAnalyzerto convert terminal specifications to conductor indices and validate configurationsModeSolver._validate_mode_plane_analysis()to catch configuration errors before submissionSimulation._validate_microwave_mode_specs()to reuse validation logicCritical issues found:
convert_terminal()(line 273-276): incorrect conditions for creating Point/LineString/Polygon geometries will cause runtime errorsAttributeErrorif structure not foundValueErrorbut code raisesSetupErrorConfidence Score: 1/5
Important Files Changed
File Analysis
Sequence Diagram
sequenceDiagram participant User participant ModeSolver participant MicrowaveModeSpec participant ModePlaneAnalyzer participant TerminalSpec User->>ModeSolver: Create with terminal_specs ModeSolver->>ModeSolver: _post_init_validators() ModeSolver->>ModeSolver: _validate_mode_plane_analysis() ModeSolver->>ModePlaneAnalyzer: get_conductor_bounding_boxes() ModePlaneAnalyzer-->>ModeSolver: conductor_shapes alt terminal_specs is not None ModeSolver->>ModePlaneAnalyzer: _convert_terminal_specifications_to_candidate_geometry() ModePlaneAnalyzer->>TerminalSpec: Read plus/minus terminals TerminalSpec-->>ModePlaneAnalyzer: terminal identifiers ModePlaneAnalyzer->>ModePlaneAnalyzer: convert to Points/Lines/Polygons ModePlaneAnalyzer-->>ModeSolver: terminal_spec_shapes ModeSolver->>ModePlaneAnalyzer: _find_conductor_terminals() ModePlaneAnalyzer->>ModePlaneAnalyzer: Match terminals to conductors ModePlaneAnalyzer-->>ModeSolver: voltage_sets ModeSolver->>ModePlaneAnalyzer: _validate_conductor_voltage_configurations() ModePlaneAnalyzer->>ModePlaneAnalyzer: Check for conflicts/duplicates end User->>ModeSolver: solve() ModeSolver->>ModeSolver: _add_microwave_data() alt terminal_specs is not None ModeSolver->>ModeSolver: _post_process_modes_with_terminal_specs() Note over ModeSolver: Raises SetupError<br/>(not available locally) end ModeSolver->>ModeSolver: _make_path_integrals() ModeSolver-->>User: MicrowaveModeSolverData