Skip to content

Add support for EME monitor data in outer_dot #2683

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
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

caseyflex
Copy link
Contributor

@caseyflex caseyflex commented Jul 18, 2025

Previously, to take outer_dot with EME data, you had to select a single eme_port_index, eme_cell_index, sweep_index, etc. This had to be done one field component at a time and was a pain. This PR makes outer_dot work directly with these additional fields, ensuring the input fields are aligned and broadcast appropriately. The additional fields end up as coords in the overlap DataArray.

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.

Reviewing changes made in this pull request

Copy link
Contributor

Diff Coverage

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

  • tidy3d/components/data/monitor_data.py (94.2%): Missing lines 981-982,1020

Summary

  • Total: 52 lines
  • Missing: 3 lines
  • Coverage: 94%

tidy3d/components/data/monitor_data.py

  977             mode_index_dim1 = None
  978             mode_index_dim2 = None
  979             for dim in field_1.dims:
  980                 if dim == "mode_index":
! 981                     mode_index_dim1 = "mode_index"
! 982                     mode_index_dim2 = "mode_index"
  983                 elif dim == "mode_index_0":
  984                     mode_index_dim1 = "mode_index_0"
  985                     mode_index_dim2 = "mode_index_1"
  986                 else:

  1016         # first, convert to numpy outside the loop to reduce xarray overhead
  1017         fields_1_numpy = {key: val.to_numpy() for key, val in fields_1.items()}
  1018         fields_2_numpy = {key: val.to_numpy() for key, val in fields_2.items()}
  1019         if d_area is None:
! 1020             d_area_numpy = 1
  1021         else:
  1022             d_area_numpy = d_area.to_numpy()
  1023 
  1024         # get one of the data arrays to look at for indexing

Copy link
Collaborator

@yaugenst-flex yaugenst-flex left a comment

Choose a reason for hiding this comment

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

Thanks @caseyflex! Looks good overall but had some questions particularly about the _align_fields method.

Comment on lines +993 to +994
fields_1[key] = field_1
fields_2[key] = field_2
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it intentional that this function mutates the input? That seems potentially unsafe..

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 see. It's fine with this usage but agreed not good practice unless made explicit in the function signature.

Comment on lines +958 to +960
def _align_fields(
fields_1: dict[str, xr.DataArray], fields_2: dict[str, xr.DataArray], d_area: xr.DataArray
) -> tuple[dict[str, xr.DataArray], dict[str, xr.DataArray], xr.DataArray]:
Copy link
Collaborator

Choose a reason for hiding this comment

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

I left two comments but overall I find this function to be pretty difficult to follow. Maybe we could look at breaking the function down into smaller helpers to clarify the main workflow and better distinguish between the 'dot' and 'outer_dot' cases?

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 can try to clean this up, comment it, split it up.

In the end I didn't include this in dot but maybe I can take another look at that.

@FilipeFcp
Copy link
Contributor

Hi @caseyflex Casey,

Thanks! I took a quick look at the code. It seems fine to me, but I’m sure Yaugenst will have much better insights than I do.

I tried a simple example, using the taper from our EME notebook. I placed a yz EMEFieldMonitor and tried to do a mode overlap with a Gaussian beam, in the same way as our mode overlap example.

The behavior seems the same as before: just calling eme_sim_data['field2'].outer_dot(gaussian_beam.field_data) returns the error: ValueError: operands could not be broadcast together with shapes (45,39,1,30,2) (45,39,1).

Maybe I’m doing something wrong, or this isn’t the goal of the PR and I misunderstood?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants