-
Notifications
You must be signed in to change notification settings - Fork 54
Allow 2D simulations with meep in X- and Y- normal planes #672
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
base: main
Are you sure you want to change the base?
Conversation
- remove is_3d parameter in get_meep_geometry_from_component (geometry for 2D simulation just sliced out of 3D geometry) - add parameters normal_2d and point_2d to specify 2D simulation plane - adjust simulation volume, source and monitor sizes to fit 2D dimensions - check sources & monitors to be in simulation volume - in write_sparameters_meep.py do not iterate over component ports which are not in simulation domain
Reviewer's GuideAdds support for running Meep 2D simulations on arbitrary X/Y/Z-normal planes without re-centering components, by configuring cell size and geometry slicing from full 3D geometry, enforcing that sources/monitors lie in the chosen 2D plane, and updating S-parameter calculation and plotting to use the new behavior. Sequence diagram for write_sparameters_meep and 2D-plane-aware simulation and S-parameter flowsequenceDiagram
participant UserScript
participant write_sparameters_meep
participant get_simulation
participant is_point_in_plane
participant MeepSimulation as Meep_Simulation
participant sparameter_calculation
participant parse_port_eigenmode_coeff
UserScript->>write_sparameters_meep: call(component, is_3d, normal_2d, point_2d, ...)
write_sparameters_meep->>get_simulation: get_simulation(component, is_3d, normal_2d, point_2d, ...)
get_simulation->>get_simulation: compute_normal_vec_from_normal_2d
get_simulation->>get_simulation: compute_cell_size_with_zero_dim_for_2D
get_simulation->>is_point_in_plane: check_source_center(test_point=center, plane_support=point_2d, plane_normal=normal_vec)
is_point_in_plane-->>get_simulation: bool
get_simulation->>get_simulation: raise_error_if_source_not_in_plane
loop for_each_port_for_monitor
get_simulation->>is_point_in_plane: check_monitor_center
is_point_in_plane-->>get_simulation: bool
alt in_plane
get_simulation->>MeepSimulation: sim.add_mode_monitor
else not_in_plane
get_simulation->>get_simulation: warn_monitor_ignored
end
end
get_simulation-->>write_sparameters_meep: sim_dict(sim, cell_size, monitors, freqs)
write_sparameters_meep->>sparameter_calculation: sparameter_calculation(..., sim_dict, ...)
sparameter_calculation->>MeepSimulation: run_simulation_until_energy_decayed
loop for_each_port_in_sim_dict_monitors
loop for_each_port_mode
sparameter_calculation->>parse_port_eigenmode_coeff: parse_port_eigenmode_coeff(port_name, ports, sim_dict, port_mode)
parse_port_eigenmode_coeff-->>sparameter_calculation: (entering, exiting)
sparameter_calculation->>sparameter_calculation: update_smatrix_entries
end
end
sparameter_calculation-->>write_sparameters_meep: sparameters
write_sparameters_meep-->>UserScript: sparameters_results
Class diagram for updated Meep simulation helpers with 2D plane supportclassDiagram
class get_simulation {
+dict get_simulation(component, resolution, extend_ports_length, port_margin, port_source_name, port_source_mode, layer_stack, material_name_to_meep, dispersive, zmargin_top, zmargin_bot, xmargin, ymargin, tpml, clad_material, is_3d, normal_2d, point_2d, wavelength_start, wavelength_stop, wavelength_points, dfcen, port_symmetries, port_names, port_modes, distance_source_to_monitors, port_monitor_offset, port_source_offset, port_symmetries, **settings)
}
class is_point_in_plane {
+bool is_point_in_plane(test_point, plane_support, plane_normal, tolerance)
}
class get_meep_geometry_from_component {
+list get_meep_geometry_from_component(component, layer_stack, material_name_to_meep, wavelength, dispersive, exclude_layers, **kwargs)
}
class write_sparameters_meep {
+dict write_sparameters_meep(component, layer_stack, material_name_to_meep, resolution, is_3d, normal_2d, point_2d, wavelength_start, wavelength_stop, wavelength_points, port_source_name, port_source_mode, port_symmetries, port_source_names, port_monitor_names, port_names, port_modes, xmargin, ymargin, zmargin, tpml, clad_material, extend_ports_length, distance_source_to_monitors, port_monitor_offset, port_source_offset, animate, animate_size, animate_center, decay_by, plot_args, exclude_layers, dispersive, **settings)
}
class sparameter_calculation {
+dict sparameter_calculation(port_source_names, component, port_symmetries, port_source_mode, wavelength_start, wavelength_stop, wavelength_points, normal_2d, point_2d, is_3d, animate, decay_by, **settings)
}
class parse_port_eigenmode_coeff {
+tuple parse_port_eigenmode_coeff(port_name, ports, sim_dict, port_mode)
}
class MeepSimulation {
+mp.Simulation sim
+mp.Vector3 cell_size
+dict monitors
+list freqs
}
get_simulation --> get_meep_geometry_from_component : uses
get_simulation --> is_point_in_plane : validates_sources_and_monitors
get_simulation --> MeepSimulation : builds
write_sparameters_meep --> get_simulation : obtains_initial_sim
write_sparameters_meep --> sparameter_calculation : computes_sparameters
sparameter_calculation --> parse_port_eigenmode_coeff : reads_coefficients
sparameter_calculation --> MeepSimulation : uses
parse_port_eigenmode_coeff --> MeepSimulation : accesses_monitors
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
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.
Hey - I've found 1 issue, and left some high level feedback:
- Now that
get_meep_geometry_from_componentalways useslevel.zminand a nonzerosidewall_angle, the geometry for Z-normal "2D" simulations is no longer flattened to z=0 – if this isn’t intentional you may want to conditionally zerozmin/sidewall_anglewhen running a Z-normal 2D setup so objects remain inside a zero-thickness z cell. - The change from a conditional
extend_ports(..., centered=True)to always callingextend_ports(component=component, length=extend_ports_length)withoutcentered=Truewill shift port extensions relative to the original behavior; if callers rely on symmetric extensions orextend_ports_lengthbeing optional/False-y, consider restoring the conditional call or explicitly handling theNone/0case and thecenteredoption.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Now that `get_meep_geometry_from_component` always uses `level.zmin` and a nonzero `sidewall_angle`, the geometry for Z-normal "2D" simulations is no longer flattened to z=0 – if this isn’t intentional you may want to conditionally zero `zmin`/`sidewall_angle` when running a Z-normal 2D setup so objects remain inside a zero-thickness z cell.
- The change from a conditional `extend_ports(..., centered=True)` to always calling `extend_ports(component=component, length=extend_ports_length)` without `centered=True` will shift port extensions relative to the original behavior; if callers rely on symmetric extensions or `extend_ports_length` being optional/False-y, consider restoring the conditional call or explicitly handling the `None/0` case and the `centered` option.
## Individual Comments
### Comment 1
<location> `gplugins/gmeep/get_simulation.py:29-38` </location>
<code_context>
settings_meep = set(sig.parameters.keys())
+def is_point_in_plane(
+ test_point: Float3,
+ plane_support: Float3,
+ plane_normal: Float3,
+ tolerance: float = 1e-6, # 1 pm for coordinates in µm
+):
+ a, b, c = plane_normal
+ xt, yt, zt = test_point
+ x0, y0, z0 = plane_support
+ distance = (a*(xt-x0) + b*(yt-y0) + c*(zt-z0)) / np.linalg.norm(plane_normal)
+ return bool(abs(distance) <= tolerance)
+
</code_context>
<issue_to_address>
**issue:** Guard against a zero-length plane_normal in is_point_in_plane.
`is_point_in_plane` will divide by `np.linalg.norm(plane_normal)` without handling the zero (or near-zero) case. Since this is a general helper, please add a guard (e.g., raise if the norm is below a small threshold) to avoid silent NaNs when called with invalid normals.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| def is_point_in_plane( | ||
| test_point: Float3, | ||
| plane_support: Float3, | ||
| plane_normal: Float3, | ||
| tolerance: float = 1e-6, # 1 pm for coordinates in µm | ||
| ): | ||
| a, b, c = plane_normal | ||
| xt, yt, zt = test_point | ||
| x0, y0, z0 = plane_support | ||
| distance = (a*(xt-x0) + b*(yt-y0) + c*(zt-z0)) / np.linalg.norm(plane_normal) |
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.
issue: Guard against a zero-length plane_normal in is_point_in_plane.
is_point_in_plane will divide by np.linalg.norm(plane_normal) without handling the zero (or near-zero) case. Since this is a general helper, please add a guard (e.g., raise if the norm is below a small threshold) to avoid silent NaNs when called with invalid normals.
PR makes the following changes:
is_3dparameter inget_meep_geometry_from_component(geometry for 2D simulation just sliced out of 3D geometry)normal_2dandpoint_2dto specify 2D simulation planewrite_sparameters_meep.pydo not iterate over component ports which are not in simulation domainUsing the example script
all simulations are working as expected (where actual S-parameters may not be meaningful/comparable as this is just an example),
Summary by Sourcery
Support 2D Meep simulations in arbitrary X-, Y-, or Z-normal planes while keeping component coordinates fixed and ensuring only in-domain ports participate in S-parameter calculations.
New Features:
Bug Fixes:
Enhancements: