tidy3d.EMESimulation#

class EMESimulation[source]#

Bases: AbstractYeeGridSimulation

EigenMode Expansion (EME) simulation.

Parameters:
  • center (tuple[Union[float, autograd.tracer.Box], Union[float, autograd.tracer.Box], Union[float, autograd.tracer.Box]] = (0.0, 0.0, 0.0)) – [units = um]. Center of object in x, y, and z.

  • size (tuple[Union[NonNegativeFloat, autograd.tracer.Box], Union[NonNegativeFloat, autograd.tracer.Box], Union[NonNegativeFloat, autograd.tracer.Box]]) – [units = um]. Size in x, y, and z directions.

  • medium (Union[Medium, AnisotropicMedium, PECMedium, PMCMedium, PoleResidue, Sellmeier, Lorentz, Debye, Drude, FullyAnisotropicMedium, CustomMedium, CustomPoleResidue, CustomSellmeier, CustomLorentz, CustomDebye, CustomDrude, CustomAnisotropicMedium, PerturbationMedium, PerturbationPoleResidue, LossyMetalMedium] = Medium()) – Background medium of simulation, defaults to vacuum if not specified.

  • structures (tuple[Structure, …] = ()) – Tuple of structures present in simulation. Note: Structures defined later in this list override the simulation material properties in regions of spatial overlap.

  • symmetry (tuple[Literal[0, -1, 1], Literal[0, -1, 1], Literal[0, -1, 1]] = (0, 0, 0)) – Tuple of integers defining reflection symmetry across a plane bisecting the simulation domain normal to the x-, y-, and z-axis at the simulation center of each axis, respectively.

  • sources (tuple[None, ...] = ()) – Sources in the simulation. NOTE: sources are not currently supported for EME simulations. Instead, the simulation performs full bidirectional propagation in the β€˜port_mode’ basis. After running the simulation, use β€˜smatrix_in_basis’ to use another set of modes or input field.

  • boundary_spec (BoundarySpec = BoundarySpec(x=Boundary(plus=PECBoundary(), minus=PECBoundary()), y=Boundary(plus=PECBoundary(), minus=PECBoundary()), z=Boundary(plus=PECBoundary(), minus=PECBoundary()))) – Specification of boundary conditions along each dimension. By default, PEC boundary conditions are applied on all sides. This field is for consistency with FDTD simulations; however, please note that regardless of the β€˜boundary_spec’, the mode solver terminates the mode plane with PEC boundary. The β€˜EMEModeSpec’ can be used to apply PML layers in the mode solver.

  • monitors (tuple[Union[EMEModeSolverMonitor, EMEFieldMonitor, EMECoefficientMonitor, ModeSolverMonitor, PermittivityMonitor, MediumMonitor], …] = ()) – Tuple of monitors in the simulation. Supported types: β€˜EMEModeSolverMonitor’, β€˜EMEFieldMonitor’, β€˜EMECoefficientMonitor’, β€˜ModeSolverMonitor’, β€˜PermittivityMonitor’, and β€˜MediumMonitor’. Note: monitor names are used to access data after simulation is run.

  • grid_spec (GridSpec = GridSpec()) – Specifications for the simulation grid along each of the three directions. This is distinct from β€˜eme_grid_spec’, which defines the 1D EME grid in the propagation direction.

  • version (str = 2.11.2) – String specifying the front end version number.

  • plot_length_units (Optional[Literal['nm', 'ΞΌm', 'um', 'mm', 'cm', 'm', 'mil', 'in']] = ΞΌm) – When set to a supported LengthUnit, plots will be produced with proper scaling of axes and include the desired unit specifier in labels.

  • structure_priority_mode (Literal['equal', 'conductor'] = equal) – This field only affects structures of priority=None. If equal, the priority of those structures is set to 0; if conductor, the priority of structures made of LossyMetalMedium is set to 90, PECMedium to 100, and others to 0.

  • lumped_elements (tuple[Union[LumpedResistor, CoaxialLumpedResistor, LinearLumpedElement], …] = ()) – Tuple of lumped elements in the simulation. Note: only LumpedResistor is supported currently.

  • subpixel (Union[bool, SubpixelSpec] = SubpixelSpec()) – Apply subpixel averaging methods of the permittivity on structure interfaces to result in much higher accuracy for a given grid size. Supply a SubpixelSpec to this field to select subpixel averaging methods separately on dielectric, metal, and PEC material interfaces. Alternatively, user may supply a boolean value: True to apply the default subpixel averaging methods corresponding to SubpixelSpec() , or False to apply staircasing.

  • simulation_type (Optional[Literal['autograd_fwd', 'autograd_bwd', 'tidy3d']] = tidy3d) – Tag used internally to distinguish types of simulations for autograd gradient processing.

  • post_norm (Union[float, FreqDataArray] = 1.0) – Factor to multiply the fields by after running, given the adjoint source pipeline used. Note: this is used internally only.

  • internal_absorbers (tuple = ()) – Planes with the first order absorbing boundary conditions placed inside the computational domain. Note: absorbers are not supported in EME simulations.

  • freqs (ArrayLike[dtype=float, ndim=1]) – Frequencies for the EME simulation. The field is propagated independently at each provided frequency, but the modes are only computed at a few sampling points and interpolated. To change this behavior, you can use β€˜EMEModeSpec.interp_spec’.

  • axis (Literal[0, 1, 2]) – Propagation axis (0, 1, or 2) for the EME simulation.

  • eme_grid_spec (Union[EMEUniformGrid, EMECompositeGrid, EMEExplicitGrid]) – Specification for the EME propagation grid. The simulation is divided into cells in the propagation direction; this parameter specifies the layout of those cells. Mode solving is performed in each cell, and then propagation between cells is performed to determine the complete solution. This is distinct from β€˜grid_spec’, which defines the grid in the two tangential directions, as well as the grid used for field monitors.

  • store_port_modes (bool = True) – Whether to store the modes associated with the two ports. Required to find scattering matrix in basis besides the computational basis.

  • store_coeffs (bool = False) – Whether to store the internal coefficients from the EME simulation. The results are stored in β€˜EMESimulationData.coeffs’.

  • normalize (bool = True) – Whether to normalize the port modes to unity flux, thereby normalizing the scattering matrix and expansion coefficients.

  • port_offsets (tuple[NonNegativeFloat, NonNegativeFloat] = (0, 0)) – Offsets for the two ports, relative to the simulation bounds along the propagation axis.

  • sweep_spec (Optional[Union[EMELengthSweep, EMEModeSweep, EMEFreqSweep, EMEPeriodicitySweep]] = None) – Specification for a parameter sweep to be performed during the EME propagation step. The results are stored in β€˜sim_data.smatrix’. Other simulation monitor data is not included in the sweep.

  • constraint (Optional[Literal['passive', 'unitary']] = passive) – Constraint for EME propagation, imposed at cell interfaces. A constraint of β€˜passive’ means that energy can be dissipated but not created at interfaces. A constraint of β€˜unitary’ means that energy is conserved at interfaces (but not necessarily within cells). The option β€˜none’ may be faster for a large number of modes. The option β€˜passive’ can serve as regularization for the field continuity requirement and give more physical results.

Notes

EME is a frequency-domain method for propagating the electromagnetic field along a specified axis. The method is well-suited for propagation of guided waves. The electromagnetic fields are expanded locally in the basis of eigenmodes of the waveguide; they are then propagated by imposing continuity conditions in this basis.

The solver computes the full bidirectional scattering matrix, accounting for reflections and mode coupling at every cell interface, with optional passivity or unitarity constraints. Supported features include bent waveguides (via bend_radius in EMEModeSpec), diagonal anisotropy (AnisotropicMedium), reciprocal full anisotropy (FullyAnisotropicMedium with symmetric permittivity and conductivity tensors), broadband frequency interpolation, and efficient parameter sweeps over cell lengths, number of modes, and periodic repetitions.

Bent-cell material interpretation is controlled by EMEModeSpec.bend_medium_frame. With "global", material tensors remain fixed in physical space; with "co_rotating", the material profile bends with the local waveguide frame. Bent custom media, including CustomAnisotropicMedium, are only supported with bend_medium_frame="co_rotating". For bent anisotropic media in the global-frame interpretation, reusing a single cell through num_reps or EMEPeriodicitySweep is only valid when the reused mode sees the same local tensor orientation; similarly, EMELengthSweep is rejected when changing bent cell lengths would require anisotropic modes to be recomputed at new absolute bend angles. When such bends are instead resolved with multiple cells, check convergence with respect to the number of EME cells.

The EME simulation is performed along the propagation axis axis at frequencies freqs. The simulation is divided into cells along the propagation axis, as defined by eme_grid_spec. Mode solving is performed at cell centers, and boundary conditions are imposed between cells. The EME ports are defined to be the boundaries of the first and last cell in the EME grid. These can be moved using port_offsets.

An EME simulation always computes the full scattering matrix of the structure. Additional data can be recorded by adding β€˜monitors’ to the simulation.

Monitors

The following monitor types are supported:

Other Bases

By default, the scattering matrix is expressed in the basis of EME modes at the two ports. It is sometimes useful to use alternative bases. For example, in a waveguide splitter, we might want the scattering matrix in the basis of modes of the individual waveguides. The functions smatrix_in_basis and field_in_basis in EMESimulationData can be used for this purpose after the simulation has been run.

Frequency Sweeps

Frequency sweeps are supported by including multiple frequencies in the freqs field. To avoid recomputing the modes at each frequency, the modes are interpolated according to the EMEModeSpec.interp_spec in the cells eme_grid_spec. By setting this interp_spec, the interpolation can be changed or disabled (repeating the solve at each frequency, which can be slow).

Passivity and Unitarity Constraints

Passivity and unitarity constraints can be imposed via the constraint field. These constraints are imposed at interfaces between cells, possibly at the expense of field continuity. Passivity means that the interface can only dissipate energy, and unitarity means the interface will conserve energy (energy may still be dissipated inside cells when the propagation constant is complex). Adding constraints can slow down the simulation significantly, especially for a large number of modes (more than 30 or 40).

Too Many Modes

It is important to use enough modes to capture the physics of the device and to ensure that the results have converged (see below). However, using too many modes can slow down the simulation and result in numerical issues. If too many modes are used, it is common to see a warning about invalid modes in the simulation log. While these modes are not included in the EME propagation, this can indicate some other issue with the setup, especially if the results have not converged. In this case, extending the simulation size in the transverse directions and increasing the grid resolution may help by creating more valid modes that can be used in convergence testing.

Mode Convergence Sweeps

It is a good idea to check that the number of modes is large enough by running a mode convergence sweep. This can be done using EMEModeSweep.

Example

>>> from tidy3d import Box, Medium, Structure, C_0, inf
>>> from tidy3d import EMEModeSpec, EMEUniformGrid, GridSpec
>>> from tidy3d import EMEFieldMonitor
>>> lambda0 = 1550e-9
>>> freq0 = C_0 / lambda0
>>> sim_size = 3*lambda0, 3*lambda0, 3*lambda0
>>> waveguide_size = (lambda0/2, lambda0, inf)
>>> waveguide = Structure(
...     geometry=Box(center=(0,0,0), size=waveguide_size),
...     medium=Medium(permittivity=2)
... )
>>> eme_grid_spec = EMEUniformGrid(num_cells=5, mode_spec=EMEModeSpec(num_modes=10))
>>> grid_spec = GridSpec(wavelength=lambda0)
>>> field_monitor = EMEFieldMonitor(
...     size=(0, sim_size[1], sim_size[2]),
...     name="field_monitor"
... )
>>> sim = EMESimulation(
...     size=sim_size,
...     monitors=[field_monitor],
...     structures=[waveguide],
...     axis=2,
...     freqs=[freq0],
...     eme_grid_spec=eme_grid_spec,
...     grid_spec=grid_spec
... )

See also

Notebooks:

Attributes

cell_index_pairs

Adjacent EME cell pairs needed for interface computation.

coeffs_full_monitor

EME coefficient monitor for storing all coefficients without downsampling.

eme_grid

The EME grid as defined by 'eme_grid_spec'.

grid

Grid spatial locations and information as defined by grid_spec.

max_num_modes

Max number of modes in the simulation.

max_port_modes

Max number of modes at the two ports.

mode_simulations

One ModeSimulation per EME cell, at full mode count.

mode_solver_monitors

A list of mode solver monitors at the cell centers.

monitors_data_size

Dictionary mapping monitor names to their estimated storage size in bytes.

port_modes_monitor

EME Mode solver monitor for only the port modes.

solver_field_bounds

Per-axis bounds where mode solver field data is physically valid.

freqs

axis

eme_grid_spec

monitors

boundary_spec

sources

internal_absorbers

grid_spec

Specifications for the simulation grid along each of the three directions.

store_port_modes

store_coeffs

normalize

port_offsets

sweep_spec

constraint

lumped_elements

Tuple of lumped elements in the simulation.

subpixel

Supply SubpixelSpec to select subpixel averaging methods separately for dielectric, metal, and PEC material interfaces.

simulation_type

post_norm

medium

Background medium of simulation, defaults to vacuum if not specified.

structures

Tuple of structures present in simulation.

symmetry

version

plot_length_units

structure_priority_mode

Validating setup

size

center

Methods

compute_cell_overlap(cell_modes)

Compute self-overlap, complex refractive index, and flux for one cell.

compute_cell_smatrix(cell_overlap[,Β sweep_index])

Compute homogeneous propagation S-matrix for one cell at one sweep point.

compute_interface_overlap(left_modes,Β ...)

Compute cross-cell overlaps for one interface.

compute_interface_smatrix(left_overlap,Β ...)

Compute interface S-matrix for one interface at one sweep point.

compute_overlaps(mode_data)

Stage modes and compute all per-cell and per-interface overlaps.

compute_smatrix(cell_overlaps,Β ...[,Β ...])

Stack cell and interface S-matrices into the final device S-matrix.

from_scene(scene,Β **kwargs)

Create an EME simulation from a :.Scene instance.

plot([x,Β y,Β z,Β ax,Β source_alpha,Β ...])

Plot each of simulation's components on a plane defined by one nonzero x,y,z coordinate.

plot_eme_grid([x,Β y,Β z,Β ax,Β hlim,Β vlim])

Plot the EME cell boundaries on a cross-sectional plane.

plot_eme_ports([x,Β y,Β z,Β ax,Β hlim,Β vlim])

Plot the EME port locations on a cross-sectional plane.

plot_eme_subgrid_boundaries(eme_grid_spec[,Β ...])

Plot the EME subgrid boundaries on a cross-sectional plane.

propagate(mode_data)

Propagate modes through the device to compute the full S-matrix.

propagate_from_overlaps(cell_overlaps,Β ...)

Propagate to the device S-matrix using pre-computed overlaps.

smatrix_in_basis(smatrix,Β port_modes[,Β ...])

Express a locally propagated S-matrix in another modal basis.

stage_cell_modes(mode_data,Β cell_index)

Validate, filter, and stamp mode data for one cell.

subsection(region[,Β grid_spec,Β ...])

Generate a simulation instance containing only the region.

validate_pre_upload()

Validate the fully initialized EME simulation is ok for upload to our servers.

freqs#
axis#
eme_grid_spec#
monitors#
boundary_spec#
sources#
internal_absorbers#
grid_spec#

Specifications for the simulation grid along each of the three directions.

Example

Simple application reference:

Simulation(
   ...
    grid_spec=GridSpec(
       grid_x = AutoGrid(min_steps_per_wvl = 20),
       grid_y = AutoGrid(min_steps_per_wvl = 20),
       grid_z = AutoGrid(min_steps_per_wvl = 20)
   ),
   ...
)

See also

GridSpec

Collective grid specification for all three dimensions.

UniformGrid

Uniform 1D grid.

AutoGrid

Specification for non-uniform grid along a given dimension.

Notebooks:
store_port_modes#
store_coeffs#
normalize#
port_offsets#
sweep_spec#
constraint#
plot_eme_ports(x=None, y=None, z=None, ax=None, hlim=None, vlim=None, **kwargs)[source]#

Plot the EME port locations on a cross-sectional plane.

Parameters:
  • x (float = None) – Position of plane in x direction, only one of x, y, z must be specified to define plane.

  • y (float = None) – Position of plane in y direction, only one of x, y, z must be specified to define plane.

  • z (float = None) – Position of plane in z direction, only one of x, y, z must be specified to define plane.

  • ax (matplotlib.axes._subplots.Axes = None) – Matplotlib axes to plot on, if not specified, one is created.

  • hlim (tuple[float, float] = None) – The x range if plotting on xy or xz planes, y range if plotting on yz plane.

  • vlim (tuple[float, float] = None) – The z range if plotting on xz or yz planes, y range if plotting on xy plane.

Returns:

The supplied or created matplotlib axes.

Return type:

matplotlib.axes._subplots.Axes

plot_eme_subgrid_boundaries(eme_grid_spec, x=None, y=None, z=None, ax=None, hlim=None, vlim=None, **kwargs)[source]#

Plot the EME subgrid boundaries on a cross-sectional plane.

Does nothing if eme_grid_spec is not EMECompositeGrid. Operates recursively on nested subgrids.

Parameters:
  • eme_grid_spec (EMEGridSpec) – The EME grid spec whose subgrid boundaries to plot.

  • x (float = None) – Position of plane in x direction, only one of x, y, z must be specified to define plane.

  • y (float = None) – Position of plane in y direction, only one of x, y, z must be specified to define plane.

  • z (float = None) – Position of plane in z direction, only one of x, y, z must be specified to define plane.

  • ax (matplotlib.axes._subplots.Axes = None) – Matplotlib axes to plot on, if not specified, one is created.

  • hlim (tuple[float, float] = None) – The x range if plotting on xy or xz planes, y range if plotting on yz plane.

  • vlim (tuple[float, float] = None) – The z range if plotting on xz or yz planes, y range if plotting on xy plane.

Returns:

The supplied or created matplotlib axes.

Return type:

matplotlib.axes._subplots.Axes

plot_eme_grid(x=None, y=None, z=None, ax=None, hlim=None, vlim=None, **kwargs)[source]#

Plot the EME cell boundaries on a cross-sectional plane.

Parameters:
  • x (float = None) – Position of plane in x direction, only one of x, y, z must be specified to define plane.

  • y (float = None) – Position of plane in y direction, only one of x, y, z must be specified to define plane.

  • z (float = None) – Position of plane in z direction, only one of x, y, z must be specified to define plane.

  • ax (matplotlib.axes._subplots.Axes = None) – Matplotlib axes to plot on, if not specified, one is created.

  • hlim (tuple[float, float] = None) – The x range if plotting on xy or xz planes, y range if plotting on yz plane.

  • vlim (tuple[float, float] = None) – The z range if plotting on xz or yz planes, y range if plotting on xy plane.

Returns:

The supplied or created matplotlib axes.

Return type:

matplotlib.axes._subplots.Axes

plot(x=None, y=None, z=None, ax=None, source_alpha=None, monitor_alpha=None, hlim=None, vlim=None, **patch_kwargs)[source]#

Plot each of simulation’s components on a plane defined by one nonzero x,y,z coordinate.

Parameters:
  • x (float = None) – position of plane in x direction, only one of x, y, z must be specified to define plane.

  • y (float = None) – position of plane in y direction, only one of x, y, z must be specified to define plane.

  • z (float = None) – position of plane in z direction, only one of x, y, z must be specified to define plane.

  • source_alpha (float = None) – Opacity of the sources. If None, uses Tidy3d default.

  • monitor_alpha (float = None) – Opacity of the monitors. If None, uses Tidy3d default.

  • ax (matplotlib.axes._subplots.Axes = None) – Matplotlib axes to plot on, if not specified, one is created.

  • hlim (tuple[float, float] = None) – The x range if plotting on xy or xz planes, y range if plotting on yz plane.

  • vlim (tuple[float, float] = None) – The z range if plotting on xz or yz planes, y plane if plotting on xy plane.

Returns:

The supplied or created matplotlib axes.

Return type:

matplotlib.axes._subplots.Axes

property eme_grid#

The EME grid as defined by β€˜eme_grid_spec’. An EME grid is a 1D grid aligned with the propagation axis, dividing the simulation into cells. Modes and mode coefficients are defined at the central plane of each cell. Typically, cell boundaries are aligned with interfaces between structures in the simulation.

This is distinct from β€˜grid’, which is the grid used in the tangential directions as well as the grid used for field monitors.

property solver_field_bounds#

Per-axis bounds where mode solver field data is physically valid.

EME always colocates symmetry-expanded data, so symmetry is not passed here; the bounds represent only the physical (PEC) domain edges, not the symmetry centre.

classmethod from_scene(scene, **kwargs)[source]#

Create an EME simulation from a :.Scene instance. Must provide additional parameters to define a valid EME simulation (for example, size, grid_spec, etc).

Parameters:
  • scene (Scene) – Scene containing structures information.

  • **kwargs – Other arguments passed to the EMESimulation constructor.

Returns:

An EME simulation with structures and medium from the provided scene.

Return type:

EMESimulation

property mode_solver_monitors#

A list of mode solver monitors at the cell centers. Each monitor has a mode spec. The cells and mode specs are specified by β€˜eme_grid_spec’.

property port_modes_monitor#

EME Mode solver monitor for only the port modes.

property coeffs_full_monitor#

EME coefficient monitor for storing all coefficients without downsampling.

validate_pre_upload()[source]#

Validate the fully initialized EME simulation is ok for upload to our servers.

property monitors_data_size#

Dictionary mapping monitor names to their estimated storage size in bytes.

property max_num_modes#

Max number of modes in the simulation.

property max_port_modes#

Max number of modes at the two ports.

property grid#

Grid spatial locations and information as defined by grid_spec. This is the grid used in the tangential directions as well as the grid used for field monitors. This is distinct from β€˜eme_grid’, which is the grid used for mode solving and EME propagation.

Returns:

Grid storing the spatial locations relevant to the simulation.

Return type:

Grid

subsection(region, grid_spec=None, eme_grid_spec=None, symmetry=None, warn_symmetry_expansion=True, monitors=None, remove_outside_structures=True, remove_outside_custom_mediums=False, **kwargs)[source]#

Generate a simulation instance containing only the region. Same as in AbstractYeeGridSimulation, except also restricting EME grid.

Parameters:
  • region (Box) – New simulation domain.

  • grid_spec (GridSpec = None) – New grid specification. If None, then it is inherited from the original simulation. If identical, then the original grid is transferred directly as a CustomGrid. Note that in the latter case the region of the new simulation is snapped to the original grid lines.

  • eme_grid_spec (EMEGridSpec = None) – New EME grid specification. If None, then it is inherited from the original simulation. If identical, then the original grid is transferred directly as a EMEExplicitGrid. Noe that in the latter case the region of the new simulation is expanded to contain full EME cells.

  • symmetry (tuple[Literal[0, -1, 1], Literal[0, -1, 1], Literal[0, -1, 1]] = None) – New simulation symmetry. If None, then it is inherited from the original simulation. Note that in this case the size and placement of new simulation domain must be commensurate with the original symmetry.

  • warn_symmetry_expansion (bool = True) – Whether to warn when the subsection is expanded to preserve symmetry.

  • monitors (tuple[MonitorType, ...] = None) – New list of monitors. If None, then the monitors intersecting the new simulation domain are inherited from the original simulation.

  • remove_outside_structures (bool = True) – Remove structures outside of the new simulation domain.

  • remove_outside_custom_mediums (bool = True) – Remove custom medium data outside of the new simulation domain.

  • **kwargs – Other arguments passed to new simulation instance.

property cell_index_pairs#

Adjacent EME cell pairs needed for interface computation.

Returns a sorted list of (left, right) tuples covering all sweep indices. Use this to iterate when building the explicit staged pipeline.

property mode_simulations#

One ModeSimulation per EME cell, at full mode count.

Call .run_local() on each returned simulation and pass the results to propagate():

mode_data = [ms.run_local() for ms in sim.mode_simulations]
smatrix = sim.propagate(mode_data)

The returned tuple is in canonical EME cell order. Each simulation shares the parent geometry and grid specification, with the mode plane and mode spec set per cell. Modes are always solved at the full (untruncated) count; sweep-dependent truncation is applied at the S-matrix computation stage.

All simulations use direction="+" and colocate=False. Direction is irrelevant for EME (modes are bidirectional); colocation is handled internally by the overlap integrals.

Bent anisotropic media in bend_medium_frame="global" are not supported by the local path because subpixel averaging is applied before the bend rotation and does not yet handle fully anisotropic tensors. Use bend_medium_frame="co_rotating" or the remote backend path instead.

Return type:

tuple[ModeSimulation, …]

stage_cell_modes(mode_data, cell_index)[source]#

Validate, filter, and stamp mode data for one cell.

Checks that frequencies match, drops NaN and increasing modes, and returns a stamped EMEStageCellModes. See propagate() for the one-shot alternative.

Parameters:
Return type:

EMEStageCellModes

compute_cell_overlap(cell_modes)[source]#

Compute self-overlap, complex refractive index, and flux for one cell.

The result feeds into compute_cell_smatrix() and compute_smatrix(). See propagate() for the one-shot alternative.

Parameters:

cell_modes (EMEStageCellModes)

Return type:

EMEStageCellOverlap

compute_interface_overlap(left_modes, right_modes)[source]#

Compute cross-cell overlaps for one interface.

The result feeds into compute_interface_smatrix(). See propagate() for the one-shot alternative.

Parameters:
Return type:

EMEStageInterfaceOverlap

compute_overlaps(mode_data)[source]#

Stage modes and compute all per-cell and per-interface overlaps.

Convenience wrapper around stage_cell_modes(), compute_cell_overlap(), and compute_interface_overlap(). Under the supported sweep types (EMELengthSweep, EMEModeSweep, EMEPeriodicitySweep) the returned overlaps are sweep-invariant, so compute them once and pass the results to propagate_from_overlaps() as many times as you want β€” one per iterative design probe.

Parameters:

mode_data (Sequence[ModeSimulationData | ModeSolverData]) – One mode result per EME cell, in cell order. Typically [ms.run_local() for ms in sim.mode_simulations].

Returns:

compute_cell_smatrix(cell_overlap, sweep_index=0)[source]#

Compute homogeneous propagation S-matrix for one cell at one sweep point.

See propagate() for the one-shot alternative.

Parameters:
  • cell_overlap (EMEStageCellOverlap)

  • sweep_index (int) – Index into the sweep (0 to sweep_spec.num_sweep - 1). Ignored when no sweep_spec is set.

Return type:

EMEStageCellSMatrix

compute_interface_smatrix(left_overlap, right_overlap, interface_overlap, sweep_index=0)[source]#

Compute interface S-matrix for one interface at one sweep point.

See propagate() for the one-shot alternative.

Parameters:
Return type:

EMEStageInterfaceSMatrix

compute_smatrix(cell_overlaps, cell_smatrices, interface_smatrices, sweep_index=0)[source]#

Stack cell and interface S-matrices into the final device S-matrix.

See propagate() for the one-shot alternative.

Parameters:
  • cell_overlaps (list[EMEStageCellOverlap] or None) – One per cell. Required when self.normalize is True (port flux normalization); may be None otherwise.

  • cell_smatrices (list[EMEStageCellSMatrix]) – One per cell.

  • interface_smatrices (list[EMEStageInterfaceSMatrix]) – One per interface, ordered to match cell_index_pairs.

  • sweep_index (int) – Index into the sweep (0 to sweep_spec.num_sweep - 1). Ignored when no sweep_spec is set.

Return type:

EMESMatrixDataset

propagate_from_overlaps(cell_overlaps, interface_overlaps)[source]#

Propagate to the device S-matrix using pre-computed overlaps.

Runs the S-matrix stages (cell / interface / stack) for every sweep point of self.sweep_spec and concatenates the results. Use this instead of propagate() when you want to reuse overlap integrals across several sweeps on the same modal basis β€” the overlaps are sweep-invariant under EMELengthSweep, EMEModeSweep, and EMEPeriodicitySweep, so recomputing them per sweep wastes work.

EMEFreqSweep is not supported; specify target frequencies in EMESimulation.freqs instead.

Parameters:
Return type:

EMESMatrixDataset

propagate(mode_data)[source]#

Propagate modes through the device to compute the full S-matrix.

One-shot helper around compute_overlaps() and propagate_from_overlaps(). If you plan to run several sweeps against the same modal basis (e.g. coarse length scan, then zoom in), call compute_overlaps() once and propagate_from_overlaps() per sweep instead β€” overlaps are sweep-invariant under the supported sweep types, so propagate would redo that work each time.

Supports EMELengthSweep, EMEModeSweep, and EMEPeriodicitySweep. EMEFreqSweep is not supported; specify target frequencies in EMESimulation.freqs instead.

To override constraint, normalize, or sweep_spec, use sim.updated_copy(...) before calling.

Parameters:

mode_data (Sequence[ModeSimulationData | ModeSolverData]) – One mode result per EME cell, in cell order. Typically [ms.run_local() for ms in sim.mode_simulations].

Return type:

EMESMatrixDataset

smatrix_in_basis(smatrix, port_modes, modes1=None, modes2=None)[source]#

Express a locally propagated S-matrix in another modal basis.

Pass the mode data for the left and right EME ports, typically (mode_data[0], mode_data[-1]) from the sequence used by propagate(). If modes1 or modes2 is None, that port is left unchanged.

Parameters:
Returns:

S-matrix in the new basis.

Return type:

EMESMatrixDataset