Skip to content

add target_neff parameter to mode solver#716

Merged
joamatab merged 7 commits into
mainfrom
target_neff
May 17, 2026
Merged

add target_neff parameter to mode solver#716
joamatab merged 7 commits into
mainfrom
target_neff

Conversation

@joamatab
Copy link
Copy Markdown
Contributor

@joamatab joamatab commented May 17, 2026

Summary

  • Add optional target_neff parameter to Waveguide model to control the target effective index used by the mode solver (relevant for bent and leaky modes)
  • Add track_modes option to sweep_bend_mismatch for tracking specific straight modes across bend radii
  • Use lossless SiO2 (Palik_Lossless) as default cladding material

Test plan

  • tidy3d mode solver tests pass
  • coupler neff test updated with new reference value
  • pre-commit formatting passes

Summary by Sourcery

Add configurability to the mode solver and bend mismatch analysis while updating default materials and tests.

New Features:

  • Allow configuring a target effective index for waveguide mode solving.
  • Add optional mode tracking in bend mismatch sweeps to follow specified straight modes across bend radii.

Enhancements:

  • Change the default SiO2 cladding material to the lossless Palik_Lossless model.

Tests:

  • Update the coupler effective index test reference value to match the new material and solver behavior.

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented May 17, 2026

Reviewer's Guide

Adds configurability to the Tidy3D mode solver via an optional target effective index, introduces mode tracking in bend mismatch sweeps, and switches the default SiO2 cladding material to a lossless model with corresponding test update.

File-Level Changes

Change Details Files
Make the target effective index for mode solving configurable on waveguide objects and propagate it into Tidy3D ModeSpec construction.
  • Extend Waveguide model schema with an optional target_neff field and associated docstring.
  • Introduce a helper method to resolve the effective target_neff value, defaulting to the real part of the core index when unset.
  • Use the resolved target_neff when constructing td.ModeSpec for both straight Waveguide and WaveguideCoupler instead of hard-coding n_core.real.
gplugins/tidy3d/modes.py
Add optional mode tracking behavior to bend mismatch sweeps to follow specific straight modes across bend radii.
  • Extend sweep_bend_mismatch signature with track_modes flag and modes_to_track sequence with defaults.
  • Add validation for modes_to_track and waveguide.num_modes when mode tracking is enabled.
  • Change the result accumulation logic so that when tracking is enabled, it records the maximum overlap per tracked mode index, otherwise preserves the existing diagonal-or-full behavior.
gplugins/tidy3d/modes.py
Update the default SiO2 material to a lossless library entry and align tests to the new effective index.
  • Change material_name_to_tidy3d mapping for sio2 to use Palik_Lossless instead of Horiba.
  • Adjust the coupler effective index regression test to the new reference value consistent with the updated cladding material.
gplugins/tidy3d/materials.py
gplugins/tidy3d/tests/test_modes_coupler.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@github-actions github-actions Bot added the enhancement New feature or request label May 17, 2026
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • In sweep_bend_mismatch, the track_modes validation currently requires waveguide.num_modes >= 2 even if modes_to_track only contains a single mode (e.g. (0,)), which seems unnecessarily restrictive; consider relaxing this check to require only waveguide.num_modes > max(modes_to_track).
  • The track_modes argument docs say modes_to_track is required when track_modes is True, but modes_to_track has a non-empty default; either adjust the docstring or simplify the len(modes_to_track) == 0 check to match the intended usage.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `sweep_bend_mismatch`, the `track_modes` validation currently requires `waveguide.num_modes >= 2` even if `modes_to_track` only contains a single mode (e.g. `(0,)`), which seems unnecessarily restrictive; consider relaxing this check to require only `waveguide.num_modes > max(modes_to_track)`.
- The `track_modes` argument docs say `modes_to_track` is required when `track_modes` is True, but `modes_to_track` has a non-empty default; either adjust the docstring or simplify the `len(modes_to_track) == 0` check to match the intended usage.

## Individual Comments

### Comment 1
<location path="gplugins/tidy3d/modes.py" line_range="897-906" />
<code_context>
+        modes_to_track: straight mode indices to track. Required when
+            track_modes is True.
     """
+    if track_modes:
+        if len(modes_to_track) == 0:
+            raise ValueError("modes_to_track must be provided when track_modes is True")
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Revisit squaring strategy to avoid double-squaring and align with the documented quantity.

In the `track_modes` branch you compute `best = [np.max(np.abs(overlap[:, m]) ** 2) ...]` and later return `np.abs(results) ** 2`, so the output is effectively `|overlap|**4`. This matches the non-tracking branch, but the docstring says it returns the “overlap integral squared”. Please decide whether the intended quantity is `|overlap|**2` or `|overlap|**4` and update both branches consistently. If only the squared magnitude is intended, remove the inner `** 2` (and possibly the final `** 2`) to avoid redundant work and mismatch with the documentation.

Suggested implementation:

```python
        # Take the maximum absolute overlap for each tracked straight mode.
        # The squaring to obtain |overlap|**2 is applied once at the end of the function.
        best = [np.max(np.abs(overlap[:, m]), axis=1) for m in modes_to_track]

```

```python
        # Take the maximum absolute overlap across all modes; squaring is done once at the end.
        results = np.max(np.abs(overlap), axis=1)

```

```python
    # Return the overlap integral squared, i.e. |overlap|**2, in line with the docstring.
    return np.abs(results) ** 2

```

These edits assume:
1. The tracked-modes branch contains a line like:
   `best = [np.max(np.abs(overlap[:, m]) ** 2, axis=1) for m in modes_to_track]`
2. The non-tracking branch contains a line like:
   `results = np.max(np.abs(overlap) ** 2, axis=1)`
3. The function currently ends with `return np.abs(results) ** 2`.

If the actual code uses slightly different variable names or shapes (e.g. `axis=0` vs `axis=1`, or builds `results` from `best` before returning), you should:
- Remove any inner `** 2` that is applied directly to `np.abs(overlap...)` in both the tracking and non-tracking branches.
- Keep a single squaring step right before returning, so the final returned quantity is `|overlap|**2`, matching the docstring “Overlap integral squared”.
- Ensure intermediate comments (if any) do not claim `|overlap|**4`.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread gplugins/tidy3d/modes.py
Comment on lines +897 to +906
if track_modes:
if len(modes_to_track) == 0:
raise ValueError("modes_to_track must be provided when track_modes is True")
if waveguide.num_modes < max(modes_to_track) + 1:
raise ValueError(
f"num_modes ({waveguide.num_modes}) must be >= "
f"{max(modes_to_track) + 1} to track modes {modes_to_track}"
)
if waveguide.num_modes < 2:
raise ValueError("Track modes requires num_modes >= 2")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

suggestion (bug_risk): Revisit squaring strategy to avoid double-squaring and align with the documented quantity.

In the track_modes branch you compute best = [np.max(np.abs(overlap[:, m]) ** 2) ...] and later return np.abs(results) ** 2, so the output is effectively |overlap|**4. This matches the non-tracking branch, but the docstring says it returns the “overlap integral squared”. Please decide whether the intended quantity is |overlap|**2 or |overlap|**4 and update both branches consistently. If only the squared magnitude is intended, remove the inner ** 2 (and possibly the final ** 2) to avoid redundant work and mismatch with the documentation.

Suggested implementation:

        # Take the maximum absolute overlap for each tracked straight mode.
        # The squaring to obtain |overlap|**2 is applied once at the end of the function.
        best = [np.max(np.abs(overlap[:, m]), axis=1) for m in modes_to_track]
        # Take the maximum absolute overlap across all modes; squaring is done once at the end.
        results = np.max(np.abs(overlap), axis=1)
    # Return the overlap integral squared, i.e. |overlap|**2, in line with the docstring.
    return np.abs(results) ** 2

These edits assume:

  1. The tracked-modes branch contains a line like:
    best = [np.max(np.abs(overlap[:, m]) ** 2, axis=1) for m in modes_to_track]
  2. The non-tracking branch contains a line like:
    results = np.max(np.abs(overlap) ** 2, axis=1)
  3. The function currently ends with return np.abs(results) ** 2.

If the actual code uses slightly different variable names or shapes (e.g. axis=0 vs axis=1, or builds results from best before returning), you should:

  • Remove any inner ** 2 that is applied directly to np.abs(overlap...) in both the tracking and non-tracking branches.
  • Keep a single squaring step right before returning, so the final returned quantity is |overlap|**2, matching the docstring “Overlap integral squared”.
  • Ensure intermediate comments (if any) do not claim |overlap|**4.

@joamatab joamatab merged commit 660b286 into main May 17, 2026
21 of 22 checks passed
@joamatab joamatab deleted the target_neff branch May 17, 2026 17:44
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request updates the default SiO2 material to Palik_Lossless and introduces a target_neff parameter for the mode solver in Waveguide and WaveguideCoupler classes. It also adds mode tracking functionality to the sweep_bend_mismatch function. The review feedback highlights a potential logic error involving double-squaring of the overlap values and suggests removing an unnecessary restriction that requires multiple modes for tracking.

Comment thread gplugins/tidy3d/modes.py
)

if track_modes:
best = [np.max(np.abs(overlap[:, m]) ** 2) for m in modes_to_track]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

There is a potential logic issue with double squaring when track_modes is enabled.

Line 918 calculates the power overlap as np.abs(overlap) ** 2. Then, line 925 squares the entire results list again: return np.abs(results) ** 2. This results in returning the overlap to the fourth power ($|\eta|^4$).

While the docstring mentions the loss is squared for a round trip, the naming 'Overlap integral squared' usually implies $|\eta|^2$. If $|\eta|^4$ is indeed the intended return value for this function (to represent the round-trip mismatch), then the implementation is consistent with the else branch. However, if the intention was to return the power overlap $|\eta|^2$, then line 918 should not be squared, or line 925 should be adjusted.

Comment thread gplugins/tidy3d/modes.py
Comment on lines +905 to +906
if waveguide.num_modes < 2:
raise ValueError("Track modes requires num_modes >= 2")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The restriction waveguide.num_modes < 2 for mode tracking seems unnecessary. Even if a waveguide has only one mode, a user might want to use the track_modes logic for consistency in their scripts, and the underlying overlap calculation overlap[:, m] works correctly for a single mode (where m=0).

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants