EME
Every section function below accepts a ports argument, which names, windows, or displaces the ports on either end of the section, in place of its default left and right ports. Sections are otherwise connected in the order they are declared; use connect_ports to wire named ports explicitly instead, including into branching topologies. See Ports for the port model, the Port and Bounds classes, and make_angled_facet_port() for declaring an angled facet on a port.
- EME_settings
Declare global EME defaults that are inherited by sections created afterward. Each parameter left unspecified leaves the corresponding stored default unchanged. A section’s own
settingsargument at creation still overrides these globals. Sections created before this call are not affected.- Parameters:
apply_scattering (bool or list[float]) – whether interfacial scattering loss is automatically applied to the S-matrix, either for every wavelength (True), no wavelengths (False), or only the listed wavelengths, default: False
beta_interpolation (str) – either ‘uniform’ or ‘linear’ to specify how the propagation constant is interpolated between z-slices of a taper/gds section, default: ‘uniform’
junction_normalization (bool or str or dict) – controls how junction S-matrices are power-normalized; either a single bool/’gain’ value applied to both junction kinds, or a dict with ‘inter_section’ and ‘intra_section’ keys, each accepting True (full SVD unitarization), False (raw, unnormalized), or ‘gain’ (clip singular values at 1 while keeping the raw lossy mode-matching), default: ‘gain’ for inter-section junctions and True for intra-section junctions
overlap_variation (float) – threshold of mode-list overlap between z-slices used by the automatic z-slicing bisection for taper/gds sections, default: 0.01
minimum_z_step (float) – [nm] the minimum allowed z-step for the automatic z-slicing bisection, default: 0.1
simulation_name (str) – simulation name, default: ‘emode’
- straight_section
Define a uniform-cross-section waveguide section for the EME solver. Sections are placed sequentially in the z-direction in the order they are declared (or updated, if
namealready exists).- Parameters:
name (str) – section name, default: an auto-generated number
profile (str) – name of the profile that defines the section’s cross-section
length (float) – [nm] the length of the section
offset (float or tuple[float, float]) – [nm] transverse displacement of this section relative to whatever its ports connect to; if only a single value is given it is assumed to be the x-offset, default: (0, 0). Legacy: this is the same displacement as
Port’s ownoffsetapplied to every port of the section at once, and setting both on one section raises an error. Prefer declaringoffseton the specific port that sits off-axis.ports (list[Port] or None) – replace the section’s default
[Port('left', None, 'left'), Port('right', None, 'right')]on a per-side basis, where a supplied port replaces every existing port on the same side, and multiple ports may share a side. SeePort, default: None (keep existing/default ports)nonlinear (SHGProcess or SFGProcess or DFGProcess or None) – declare a \(\chi^{(2)}\) process on this section (EMode3D only), one of
SHGProcess(pump_wavelength=...),SFGProcess(pump_wavelength_1=..., pump_wavelength_2=...)orDFGProcess(pump_wavelength=..., signal_wavelength=...)fromemodeconnection. You name the process’s input wavelength(s); the remaining one follows from energy conservation and is matched against the section’s own profile wavelengths. Quasi-phase matching is declared on the process withpoling_period[nm], plusduty_cycle(default: 0.5) andqpm_order(default: 1);inverted=Trueinstead flips the local \(\chi^{(2)}\) sign for this section alone, the building block for poling assembled by hand from alternating sections. The two routes agree. Omittingnonlinearwhen updating an existing section leaves the declared process in place, and passing a new one replaces it. A declared process cannot currently be removed –nonlinear=Noneis indistinguishable from omitting the argument – so redeclare the section under a new name instead. A pump must also be declared, seeexcitationinsettings, and the power-dependent result is read back withget('response'). The process also carriesz_samples(default: 100), the number of points at which the forward amplitudes are recorded along each slice of this section once the driven solve converges. Those reach the caller asget('response').power_vs_z(wavelength), which returns the pump or signal power against position from a single solve rather than one solve per length. Set it to 0 to skip the sampling. Default: Nonesettings (dict or None) – per-section overrides of the
EME_settings, merged onto the current global EME settings (or onto the section’s existing settings, when updating), e.g.settings={'overlap_variation': 0.005}, default: Nonesimulation_name (str) – simulation name, default: ‘emode’
- pwd_section
Define a free space section, in which the field is expanded in plane waves (a plane-wave decomposition, PWD) over a uniform material, rather than in the guided modes of a cross-section. This is intended for gaps, facets, and free space propagation between waveguide sections; the junctions between a free space section and its neighbors are computed analytically instead of from a mode solve.
The basis is the set of plane-wave harmonics of the section window, with transverse wavevectors
kx = 2*pi*m/window_widthandky = 2*pi*n/window_height, each harmonic carrying both a TE and a TM polarization. At least one ofmax_order,max_kt, ornum_modesis required to truncate the basis; when more than one is given, they are applied in the ordermax_order,max_kt,num_modes.- Parameters:
name (str) – section name, default: an auto-generated number
length (float) – [nm] the length of the section
material (str or ~MaterialProperties or ~MaterialSpec) – the material filling the section, either a material name (from the material database) or a ~MaterialProperties or ~MaterialSpec object; must be isotropic, default: “Vacuum”
profile (str) – name of the profile that supplies the default window and the wavelength(s) of the section, default: ‘_default’
window (tuple[float, float] or None) – [nm] the (width, height) of the plane-wave window, which overrides the window of
profile, default: None (use thewindow_widthandwindow_heightofprofile)offset (tuple[float, float]) – [nm] transverse displacement of the window’s origin, which is its horizontal center and bottom edge, default: (0, 0)
max_order (tuple[int, int] or None) – the largest harmonic order to keep in the x- and y-directions, so that
|m| <= max_order[0]and|n| <= max_order[1], default: Nonemax_kt (float) – [1/nm] the largest transverse wavevector magnitude to keep, default: None
num_modes (int) – the largest number of modes to keep, counting both polarizations of each harmonic, and applied after
max_orderandmax_kt; the basis always keeps a harmonic together with its opposite-direction pair, so the resulting count can land slightly below the requested value, default: Noneports (list[Port] or None) – replace the section’s default
[Port('left', None, 'left'), Port('right', None, 'right')]on a per-side basis, where a supplied port replaces every existing port on the same side, and multiple ports may share a side. SeePort, default: None (keep existing/default ports)settings (dict or None) – per-section overrides of the
EME_settings, default: Nonesimulation_name (str) – simulation name, default: ‘emode’
- taper_section
Define a section that linearly interpolates its cross-section between two profiles for the EME solver, automatically slicing the z-direction to track the mode evolution.
- Parameters:
name (str) – section name, default: an auto-generated number
profile (str) – name of the profile that defines the section beginning
profile_end (str) – name of the profile that defines the section ending
length (float) – [nm] the length of the section
ports (list[Port] or None) – replace the section’s default
[Port('left', None, 'left'), Port('right', None, 'right')]on a per-side basis, where a supplied port replaces every existing port on the same side, and multiple ports may share a side. SeePort, default: None (keep existing/default ports)nonlinear (SHGProcess or SFGProcess or DFGProcess or None) – declare a \(\chi^{(2)}\) process on this section (EMode3D only), one of
SHGProcess(pump_wavelength=...),SFGProcess(pump_wavelength_1=..., pump_wavelength_2=...)orDFGProcess(pump_wavelength=..., signal_wavelength=...)fromemodeconnection. You name the process’s input wavelength(s); the remaining one follows from energy conservation and is matched against the section’s own profile wavelengths. Quasi-phase matching is declared on the process withpoling_period[nm], plusduty_cycle(default: 0.5) andqpm_order(default: 1);inverted=Trueinstead flips the local \(\chi^{(2)}\) sign for this section alone, the building block for poling assembled by hand from alternating sections. The two routes agree. Omittingnonlinearwhen updating an existing section leaves the declared process in place, and passing a new one replaces it. A declared process cannot currently be removed –nonlinear=Noneis indistinguishable from omitting the argument – so redeclare the section under a new name instead. A pump must also be declared, seeexcitationinsettings, and the power-dependent result is read back withget('response'). The process also carriesz_samples(default: 100), the number of points at which the forward amplitudes are recorded along each slice of this section once the driven solve converges. Those reach the caller asget('response').power_vs_z(wavelength), which returns the pump or signal power against position from a single solve rather than one solve per length. Set it to 0 to skip the sampling. Default: Nonesettings (dict or None) – per-section overrides of the
EME_settings(notablyoverlap_variationandminimum_z_step, which control the automatic z-slicing), default: Nonesimulation_name (str) – simulation name, default: ‘emode’
- gds_section
Define a section whose cross-section varies along z according to a mask imported from a GDS file, for more complex geometries defined with third-party layout tools.
- Parameters:
name (str) – section name, default: an auto-generated number
profile (str) – name of the profile that defines the section’s cross-section outside of the GDS mask
gds_path (str) – path to the GDS file used to mask the section
layer_map (dict[str, int]) – mapping of profile shape names to GDS layer numbers, used to determine which shapes in
profileare masked by which GDS layerlength (float) – [nm] the length of the section, default: derived from the GDS bounding box
cell_index (int or str) – the cell index (or name) in the specified GDS file, default: 0
scale (float) – unit scale factor applied to the GDS coordinates (e.g. use 1000 if the GDS file is drawn in microns but the simulation is in nanometers), default: 1
port_poses (dict) – explicit port positions/orientations at the section boundaries, default: derived from the GDS bounding box (left port at w=0, right port at w=length)
heal (bool) – whether to heal small gaps/self-intersections in the imported GDS polygons before meshing, default: True
grow (float) – amount to grow imported GDS polygons by, to close small gaps, default: 1e-3
ports (list[Port] or None) – replace the section’s default
[Port('left', None, 'left'), Port('right', None, 'right')]on a per-side basis, where a supplied port replaces every existing port on the same side, and multiple ports may share a side. SeePort, default: None (keep existing/default ports)settings (dict or None) – per-section overrides of the
EME_settings, default: Nonesimulation_name (str) – simulation name, default: ‘emode’
Note
Once sections are declared, call plot() with plane='z-x' or plane='z-y' to preview a geometry-only ‘Outline’ of the section layout before running EME.
- copy_section
Place a second instance of an already-declared section in the chain, reusing its already-computed S-matrix instead of re-solving it.
- Parameters:
name (str) – section name, default: an auto-generated number
section_name (str) – name of the existing section to copy
mirror (bool) – whether to reverse the placement along the propagation direction (swapping the left/right ports), default: False
port_swap (dict) – explicit port-name mapping to use instead of the automatically computed left/right swap when
mirroris True, default: Noneports (list[Port] or None) – relabel/window this copy’s own left/right boundary, with the same semantics as any other section’s
ports, independent ofport_swapand of the source section’s own ports. SeePort, default: None (keep existing/default ports)settings (dict or None) – per-section overrides of the
EME_settings, default: Nonesimulation_name (str) – simulation name, default: ‘emode’
- connect_ports
Override the default left/right adjacency wiring between named ports declared with the
portsargument of any section function.Connecting two ports also pins their coordinate systems together: the two ports’ origins (the horizontal centre and bottom edge of each cross-section) are made to coincide, so the connection is what positions one section relative to the other. Use
Port’soffsetto displace a section off that shared origin, and itswindowto choose which part of a wider cross-section the port exposes. The first section you declare defines the global frame that plots are drawn in.- Parameters:
pairs (list[tuple[str, str]] or list[tuple[str, str, JunctionOverride]]) – a list of
('<section_name>.<port_name>', '<section_name>.<port_name>')pairs to connect, e.g.[('a.right', 'b.left'), ('c.right', 'd.left')]. A port can only have one connection, so declaring a new connection for a port that already had one supersedes it. Names are resolved against the actual declared sections/ports atEMEbuild time. An entry may carry an optional third element, aJunctionOverride, configuring the junction that connection forms, e.g.[('a.right', 'b.left', JunctionOverride(junction_normalization=False))].simulation_name (str) – simulation name, default: ‘emode’
- class JunctionOverride
Settings for a single junction, passed as the optional third element of a
connect_portsentry. Every parameter left unspecified inherits the value the junction’s sections resolved, so setting one does not disturb the others.These settings belong to the connection rather than to either port because each one describes the interface between the two sections – which algebra joins their mode sets, how the resulting scattering matrix is normalized – and not one side of it.
Only an explicitly connected junction can carry these. A junction formed by the default left/right adjacency has nowhere to declare them, so name that pair in
connect_portsto configure it, which supersedes the adjacency. The internal junctions of a taper or GDS section’s automatic z-slicing are controlled by that section’ssettingsinstead.- Parameters:
junction_normalization (bool or str or None) – how this junction’s scattering matrix is power-normalized – True (full SVD unitarization), False (raw, unnormalized), or ‘gain’ (clip singular values at 1 while keeping the raw lossy mode-matching), default: None (inherit)
- EME
Calculate the complete scattering matrix of all defined sections using the eigenmode expansion method (EME).
- Parameters:
warm_start (bool) – whether to seed each taper/gds section’s automatic z-slice refinement from the previously solved chain (when available), instead of re-refining from scratch, default: False
simulation_name (str) – simulation name, default: ‘emode’
- chi2_spectrum
Conversion spectrum of a \(\chi^{(2)}\) section, solved sparsely in wavelength (EMode3D only). Returns the signal power out over the pump power in at every wavelength in
values.A nonlinear spectrum oscillates with the phase mismatch, so it cannot be interpolated – at any useful resolution it has to be evaluated point by point. What can be interpolated is what the coupled-mode equations consume: the coupling and the propagation constants, which vary smoothly with wavelength. So the modes are solved at a handful of wavelengths chosen by how fast the mode list is actually moving, and the response is then evaluated at every requested wavelength from interpolated coupling. Against a directly solved 13-point spectrum across a phase-matching peak, five solves reproduce every point to four decimals, sidelobes included.
Quasi-phase matching is included: the grating enters as a wavevector shift and a Fourier coefficient built from
poling_period,duty_cycleandqpm_order, none of which depend on wavelength, so a poled section keeps its exact grating while its phase mismatch moves with the interpolated propagation constants.Requires a chain with a declared \(\chi^{(2)}\) section (see
nonlinearonstraight_section/taper_section) and a declared pump (excitationinsettings).- Parameters:
values (list or array) – pump wavelengths [nm] to report at; the signal wavelength follows the declared process
section (str) – which nonlinear section to scan, default: the only one declared
tolerance (float) – the largest mode-list change tolerated between adjacent solves, default: 1e-3
minimum_step (float) – [nm] the smallest wavelength gap the sampler will bisect into, default: the output spacing, since resolving finer than you asked to see cannot change the reported curve
initial_points (int) – solves to place before any bisection, default: 5
power (float) – [W] pump power, default: the declared excitation’s
simulation_name (str) – simulation name, default: ‘emode’
Returns a dictionary with
values,conversion(signal out over pump in),solved_wavelengths(where the solver actually ran), andunconverged– the intervals, if any, the sampler could not resolve totolerancebefore reachingminimum_step.
- free_space_field
Declare, or update, a free-space field: a Gaussian beam launched into a port of the chain. This is an excitation, not a section – it does not appear in the scattering matrix or in the layout.
After
EME,plot(excitation=name)(or the plot window’s Mode menu,'<name> (free space)') renders the field the beam launches, projected onto the target port’s modes with the same pairing the junctions use. Re-declaring an existingnameupdates only the arguments you give.- Parameters:
name (str) – free-space field name, default: the next number
port (str) – the external port the beam enters, either a bare side
'left'(default) or'right', or a qualified'<section>.<port>'name. The beam travels inbound from that port.waist (float) – [nm] the 1/e field radius \(w\) in \(\exp(-r^2/w^2)\); required when declaring a new field
center (tuple[float, float]) – [nm] beam centre
(x, y)in the port’s cross-section coordinates, default: (0, 0)tilt (tuple[float, float]) – [degrees]
(theta_x, theta_y); a positivetheta_xsteers the beam toward +x. This is the angle inside the medium the beam travels through, default: (0, 0)component (str) – the one transverse E component the beam carries,
'Ex'(default) or'Ey'amplitude (float) – peak field value, default: 1
wavelength (float) – [nm], default: None (each port’s own wavelength)
simulation_name (str) – simulation name, default: ‘emode’
- free_space_field_diagnostics
How much of a declared free-space field’s power the target port’s modal basis actually captures, after
EMEhas solved the chain. The solver already warns when this falls below 90%; this returns it as a value a script can check or plot instead of parsing a log line.A low captured fraction means the port’s modes cannot represent the beam – raise that section’s
num_modes, or widen its window, before trusting a coupling number computed from it.- Parameters:
name (str) – the free-space field to diagnose
wavelength (float) – [nm] which of a multi-wavelength chain’s ports to diagnose, default: None (the lowest wavelength present)
simulation_name (str) – simulation name, default: ‘emode’
Returns a
FreeSpaceProjectionwithcaptured_fraction, its complementdropped_fraction, the resolvedportandwavelength, and the launch basis’snum_modes.
- plot_S_matrix
Colormap plot of the transmission or reflection component of the EME scattering matrix.
- Parameters:
input (int or str) – input field (first number of the scattering matrix identifier), default: 0
output (int or str) – output field (second number of the scattering matrix identifier), default: 1
plot_function (str or None) – specify the function to apply to the plot data (‘abs^2’, ‘angle’, ‘real’, ‘imag’), default: ‘abs^2’
file_name (str) – if specified, forces the function to save a file with the given parameters and will not display the interactive plot, file is saved under a directory called EM_figures, default: None
file_type (str) – file type for saving a plot, ‘pdf’ or ‘png’, default: ‘’ (no extension is added to
file_nameunless a file type is given)simulation_name (str) – simulation name, default: ‘emode’