EMEPy Complete User Library
Mode
- class emepy.mode.Mode(x: Optional[ndarray] = None, y: Optional[ndarray] = None, wl: Optional[float] = None, neff: Optional[float] = None, Hx: Optional[ndarray] = None, Hy: Optional[ndarray] = None, Hz: Optional[ndarray] = None, Ex: Optional[ndarray] = None, Ey: Optional[ndarray] = None, Ez: Optional[ndarray] = None, n: Optional[ndarray] = None)
Object that holds the field profiles and effective index for a 2D eigenmode
- __init__(x: Optional[ndarray] = None, y: Optional[ndarray] = None, wl: Optional[float] = None, neff: Optional[float] = None, Hx: Optional[ndarray] = None, Hy: Optional[ndarray] = None, Hz: Optional[ndarray] = None, Ex: Optional[ndarray] = None, Ey: Optional[ndarray] = None, Ez: Optional[ndarray] = None, n: Optional[ndarray] = None) None
Constructor for Mode Object
- Parameters
x ((ndarray float)) – array of grid points in x direction (propogation in z)
y ((ndarray float)) – array of grid points in y direction (propogation in z)
wl ((float)) – wavelength (meters)
neff ((float)) – effective index
Hx ((ndarray float)) – Hx field profile
Hy ((ndarray float)) – Hy field profile
Hz ((ndarray float)) – Hz field profile
Ex ((ndarray float)) – Ex field profile
Ey ((ndarray float)) – Ey field profile
Ez ((ndarray float)) – Ez field profile
n ((ndarray float)) – refractive index profile
- TE_polarization_fraction()
Returns the fraction of power in the TE polarization
- TM_polarization_fraction()
Returns the fraction of power in the TE polarization
- effective_area()
Returns the effective area of the mode
- effective_area_ratio()
Returns the ratio of the effective area to the cross-sectional area
- get_confined_power(num_pixels: Optional[int] = None) float
Takes in a mode and returns the percentage of power confined in the core
- Parameters
num_pixels (int) – number of pixels outside of the core to expand the mask to capture power just outside the core (mask dilation)
- Returns
Percentage of confined power
- Return type
float
- overlap(m2: EigenMode)
Returns the overlap of the mode with another mode
- plot(operation: str = 'Real', colorbar: bool = True, normalize: bool = True) None
Plots the fields in the mode using pyplot. Should call plt.figure() before and plt.show() or plt.savefig() after
- Parameters
operation (string or function) – the operation to perform on the fields from (“Real”, “Imaginary”, “Abs”, “Abs^2”) (default:”Real”) or a function such as np.abs
colorbar (bool) – if true, will show a colorbar for each field
normalize (bool) – if true, will normalize biggest field to 1
- plot_material() None
Plots the index of refraction profile
- plot_power() None
Plots the power profile
- spurious_value()
Returns the spurious value of the mode
- zero_phase() None
Changes the phase such that the z components are all imaginary and the xy components are all real.
EME
- class emepy.eme.EME(layers: list = [], num_periods: int = 1, mesh_z: int = 200, parallel: bool = False, quiet: bool = False, **kwargs)
The EME class is the heart of the package. It provides the algorithm that cascades sections modes together to provide the s-parameters for a geometric structure. The object is dependent on the Layer objects that are fed inside.
- __init__(layers: list = [], num_periods: int = 1, mesh_z: int = 200, parallel: bool = False, quiet: bool = False, **kwargs) None
EME class constructor
- Parameters
layers (list [Layer]) – An list of Layer objects, arranged in the order they belong geometrically. (default: [])
num_periods (int) – Number of periods if defining a periodic structure (default: 1)
mesh_z (int) – Number of mesh points in z per period for default monitors (default: 200)
parallel (bool) – If true, will allocate parallelized processes for solving modes, propagating layers, and filling monitors with field data (default: False)
quiet (bool) – If true, will not print current state and status of the solver (default: False)
- add_layer(layer: Layer) None
The add_layer method will add a Layer object to the EME object. The object will be geometrically added to the very right side of the structure. Using this method after propagate is useless as the solver has already been called.
- Parameters
layer (Layer) – Layer object to be appended to the list of Layers inside the EME object.
- add_layers(*layers) None
Calls add layers for the layers provided
- add_monitor(axes: str = 'xz', sources: list = [], mesh_z: Optional[int] = None, z_range: Optional[tuple] = None, location: Optional[float] = None, components: Optional[list] = None, exempt: bool = True) Monitor
Creates a monitor associated with the eme object BEFORE the simulation is ran
- Parameters
axes (str) – the spacial axes to capture fields in. Options : ‘xz’ (default), ‘xy’, ‘xz’, ‘xyz’, ‘x’, ‘y’, ‘z’. Currently only ‘xz’ is implemented. Note, propagation is always in z.
sources (list[Source]) – the user can specify custom mode sources to use for this monitor (default: input left)
mesh_z (int) – number of mesh points in z (for periodic structures, will be z * num_periods), warning: if different than global value for EME, a separate run will have to take place for this monitor (default: EME global defined)
z_range (tuple) – tuple or list of the form (start, end) representing the range of the z values to extract
location (float) – z coordinate where to save data for a ‘xy’ monitor
components (list[string]) – a list of the field components to include. Unless the user is worried about memory, this is best left alone. (Default: [“Ex”, “Ey”, “Ez”, “Hx”, “Hy”, “Hz”, “n”])
exempt (bool) – flag used for very specific case when using PML for MSEMpy. The user never has to change this value.
- Returns
the newly created Monitor object
- Return type
- am_master() bool
Returns true for the master process if the user is running a parallel process using mpi. This is essential for I/O
- batch_gather(data, root=0, limit=1073741824)
Gathers data to all workers in a batched manner that will not exceed the MPI integer limit
- batch_scatter(data, root=0, limit=1073741824)
Scatters data to all workers in a batched manner that will not exceed the MPI integer limit
- build_network() None
Builds the full network from the cascaded layers. This is the third step in the solving process.
- draw(z_range: Optional[tuple] = None, mesh_z: int = 200, plot_sources: bool = True, plot_xy_sources=True) AxesImage
The draw method sketches a rough approximation for the xz geometry of the structure using pyplot where x is the width of the structure and z is the length. This will change in the future.
- Parameters
z_range (tuple) – tuple or list of the form (start, end) representing the range of the z values to extract
mesh_z (int) – the number of mesh points in z to calculate index profiles for
- Returns
the image used to plot the index profile
- Return type
matplotlib.image.AxesImage
- field_propagate(left_coeffs: list, right_coeffs: list) None
Propagates the modes through the device to calculate the field profile everywhere
- Parameters
left_coeffs (list) – A list of floats that represent the mode coefficients for the left side of the full geometry
right_coeffs (list) – A list of floats that represent the mode coefficients for the right side of the full geometry
- get_sources() dict
Returns a dictionary of each period and the Source objects that can be found inside each
- propagate(left_coeffs: Optional[list] = None, right_coeffs: list = []) Model
The propagate method should be called once all Layer objects have been added. This method will call the EME solver and produce s-parameters. The defulat
- Parameters
left_coeffs (list) – A list of floats that represent the mode coefficients for the left side of the full geometry. The default is determined on whether or not any custom mode sources or right_coeffs are defined. If they are, (default:[]) else (default”[1])
right_coeffs (list) – A list of floats that represent the mode coefficients for the right side of the full geometry. (default:[])
- Returns
The simphony model that represents the entire device
- Return type
simphony.models.Model
- propagate_layers() None
Propagates each layer with the next by creating interface models and cascading all in parallel. This is the second step for the solver
- reset(full_reset: bool = True, parallel: bool = False, configure_parallel: bool = True) None
Clears out the layers and s params so the user can reuse the object in memory on a new geometry
- Parameters
full_reset (boolean) – If true, will reset everything inside of the object and allow for reinstancing without memory issues (default: True)
parallel (boolean) – If configure_parallel is True, after reset this method will set the value of parallel. Similar to the constructor (default: False)
configure_parallel (boolean) – If configure_parallel is True, after reset this method will set the value of parallel. Similar to the constructor (default: True)
- s_parameters(freqs=None) ndarray
Returns the s_parameters if they exist. If they don’t exist yet, propagate() will be called first.
- Returns
The s_params acquired during propagation
- Return type
numpy array
- solve_modes() None
Solves for the modes in the system and is the first step in the solver’s process all in parallel
- class emepy.lumerical.LumEME(layers=[], num_periods=1)
This class is a wrapper for EME, it performs the same operations but uses Lumerical MODE to solve for the modes at the interfaces
- __init__(layers=[], num_periods=1)
EME class constructor
- Parameters
layers (list [Layer]) – An list of Layer objects, arranged in the order they belong geometrically. (default: [])
num_periods (int) – Number of periods if defining a periodic structure (default: 1)
mesh_z (int) – Number of mesh points in z per period for default monitors (default: 200)
parallel (bool) – If true, will allocate parallelized processes for solving modes, propagating layers, and filling monitors with field data (default: False)
quiet (bool) – If true, will not print current state and status of the solver (default: False)
Models
- class emepy.models.Layer(mode_solver: ModeSolver, num_modes: int, wavelength: float, length: float)
Layer objects form the building blocks inside of an EME or PeriodicEME. These represent geometric layers of rectangular waveguides that approximate continuous structures.
- __init__(mode_solver: ModeSolver, num_modes: int, wavelength: float, length: float) None
Layer class constructor
- Parameters
mode_solver (Modesolver) – ModeSolver object used to solve for the modes
num_modes (int) – Number of total modes for the layer.
wavelength (number) – Wavelength of eigenmode to solve for (m).
length (number) – Geometric length of the Layer (m). The length affects the phase of the eigenmodes inside the layer via the complex phasor $e^(jβz)$.
- activate_layer(sources: list = [], start: float = 0.0, period_length: float = 0.0, compute_modes=True) dict
Solves for the modes in the layer and creates an ActivatedLayer object
- Parameters
sources (list[Source]) – the Sources used to indicate where periodic layers are needed
start (number) – the starting z value
periodic_length (number) – the length of a single period
- Returns
a dictionary that maps the period number to the activated layers. If there is no source in a period, it will be None instead at that index
- Return type
dict
- clear() ndarray
Empties the modes in the ModeSolver to clear memory
- Returns
the edited image
- Return type
numpy array
- get_activated_layer(sources: list = [], start: float = 0.0) dict
Gets the activated layer if it exists or calls activate_layer first
- Parameters
sources (list[Source]) – a list of Source objects for this layer
- Returns
a dictionary that maps the period number to the activated layers. If there is no source in a period, it will be None instead at that index
- Return type
dict
ModeSolver
- class emepy.fd.ModeSolver(**kwargs)
The ModeSolver object is the heart of finding eigenmodes for use in eigenmode expansion or simple examination. This parent class should be inherited and used as a wrapper for certain modules such as EMpy, Lumerical, Pickled data, Neural Networks, etc.
- __init__(**kwargs) None
ModeSolver class constructor
- clear() None
Clears the modesolver’s eigenmodes to make memory
- get_mode(mode_num: int) EigenMode
Must extract the mode of choice
- Parameters
mode_num (int) – index of the mode of choice
- solve() None
Solves the eigenmode solver for the specific eigenmodes of desire
- class emepy.lumerical.MSLumerical(wl=1.55e-06, width=5e-07, thickness=2.2e-07, num_modes=1, cladding_width=5e-06, cladding_thickness=5e-06, core_index=None, cladding_index=None, mesh=300, mode=None, eme_modes=False, polygons=[], PML=False, **kwargs)
Outdated Lumerical Modesolver. Uses the lumapi Lumerical API. See Modesolver. Parameterizes the cross section as a rectangular waveguide.
- __init__(wl=1.55e-06, width=5e-07, thickness=2.2e-07, num_modes=1, cladding_width=5e-06, cladding_thickness=5e-06, core_index=None, cladding_index=None, mesh=300, mode=None, eme_modes=False, polygons=[], PML=False, **kwargs)
MSLumerical class constructor
- Parameters
wl (number) – wavelength of the eigenmodes
width (number) – width of the core in the cross section
thickness (number) – thickness of the core in the cross section
num_modes (int) – number of modes to solve for (default:1)
cladding_width (number) – width of the cladding in the cross section (default:5e-6)
cladding_thickness (number) – thickness of the cladding in the cross section (default:5e-6)
core_index (number) – refractive index of the core (default:Si)
cladding_index (number) – refractive index of the cladding (default:SiO2)
mesh (int) – number of mesh points in each direction (xy)
mode (lumapi.MODE) – MODE object that contains the file information
eme_modes (boolean) – if true, will utilize the lumerical eme wrapped fde solver which is not normalized to one. Produces slightly different results purely due to roundoff error during normalization.
PML (boolean) – if true, will enable PML boundary conditions, note: this will increase the mesh and grid space
- clear()
Clears the modesolver’s eigenmodes to make memory
- get_mode(mode_num=0)
Get the indexed mode number
- Parameters
mode_num (int) – index of the mode of choice
- Returns
the eigenmode of index mode_num
- Return type
- solve()
Solves for the eigenmodes
- class emepy.fd.MSEMpy(wl: float = 1.55, width: Optional[float] = None, thickness: Optional[float] = None, num_modes: int = 1, cladding_width: float = 2.5, cladding_thickness: float = 2.5, core_index: Optional[float] = None, cladding_index: Optional[float] = None, x: Optional[ndarray] = None, y: Optional[ndarray] = None, mesh: int = 128, accuracy: float = 1e-08, boundary: str = '0000', epsfunc: Optional[Callable[[ndarray, ndarray], ndarray]] = None, n: Optional[ndarray] = None, PML: bool = False, subpixel: bool = True, center: tuple = (0, 0), **kwargs)
Electromagnetic Python Modesolver. Uses the EMpy library See Modesolver. Parameterizes the cross section as a rectangular waveguide.
- __init__(wl: float = 1.55, width: Optional[float] = None, thickness: Optional[float] = None, num_modes: int = 1, cladding_width: float = 2.5, cladding_thickness: float = 2.5, core_index: Optional[float] = None, cladding_index: Optional[float] = None, x: Optional[ndarray] = None, y: Optional[ndarray] = None, mesh: int = 128, accuracy: float = 1e-08, boundary: str = '0000', epsfunc: Optional[Callable[[ndarray, ndarray], ndarray]] = None, n: Optional[ndarray] = None, PML: bool = False, subpixel: bool = True, center: tuple = (0, 0), **kwargs) None
MSEMpy class constructor
- Parameters
wl (number) – wavelength of the eigenmodes
width (number) – width of the core in the cross section
thickness (number) – thickness of the core in the cross section
num_modes (int) – number of modes to solve for (default:1)
cladding_width (number) – width of the cladding in the cross section (default:5)
cladding_thickness (number) – thickness of the cladding in the cross section (default:5)
core_index (number) – refractive index of the core (default:Si)
cladding_index (number) – refractive index of the cladding (default:SiO2)
mesh (int) – number of mesh points in each direction (xy)
x (numpy array) – the cross section grid in the x direction (z propagation) (default:None)
y (numpy array) – the cross section grid in the y direction (z propagation) (default:None)
mesh – the number of mesh points in each xy direction
accuracy (number) – the minimum accuracy of the finite difference solution (default:1e-8)
boundary (string) – the boundaries according to the EMpy library (default:”0000”)
epsfunc (function) – the function which defines the permittivity based on a grid (see EMpy library) (default:”0000”)
n (numpy array) – 2D profile of the refractive index
PML (bool) – if True, will use PML boundaries. Only works for Tidy3D, not EMpy. Default : False, PEC
subpixel (bool) – if true, will use subpixel smoothing, assuming asking for a waveguide cross section and not providing an index map (recommended)
- clear() ModeSolver
Clears the modesolver’s eigenmodes to make memory
- get_mode(mode_num: int = 0) EigenMode
Get the indexed mode number
- Parameters
mode_num (int) – index of the mode of choice
- Returns
the eigenmode of index mode_num
- Return type
- plot_material() None
Plots the index of refraction profile
- solve() ModeSolver
Solves for the eigenmodes
Geometry
EMEPy now offers geometry abstractions that allow users to more easily implement the layers needed for their system. This is currently under development and subject to changing. Check out emepy.geometry.py for more examples available for users.
- class emepy.geometries.Geometry(layers: list)
Geoemtries are not required for users, however they do allow for easier creation of complex structures
- __init__(layers: list) None
Constructors should take in parameters from the user and build the layers
- class emepy.geometries.Waveguide(params: ~emepy.geometries.Params = <emepy.geometries.EMpyGeometryParameters object>, width: float = 0.5, thickness: float = 0.22, length: float = 1, num_modes: int = 1, center: tuple = (0, 0))
Block forms the simplest geometry in emepy, a single layer with a single waveguide defined
- __init__(params: ~emepy.geometries.Params = <emepy.geometries.EMpyGeometryParameters object>, width: float = 0.5, thickness: float = 0.22, length: float = 1, num_modes: int = 1, center: tuple = (0, 0)) None
Creates an instance of block which can be called to access the required layers for solving
- Parameters
params (Params) – Geometry Parameters object containing large scale parameters
width (number) – width of the core in the cross section
thickness (number) – thickness of the core in the cross section
length (number) – length of the structure
num_modes (int) – number of modes to solve for (default:1)
Monitors
- class emepy.monitors.Monitor(axes: str = 'xz', dimensions: tuple = (1, 1), components: list = ['E'], z_range: Optional[tuple] = None, grid_x: Optional[array] = None, grid_y: Optional[array] = None, grid_z: Optional[array] = None, location: Optional[float] = None, sources: list = [], adjoint_n: bool = True, total_length: float = 0.0)
Monitor objects store fields during propagation for user visualization. Three types of monitors exist: 3D, 2D, and 1D.
- __init__(axes: str = 'xz', dimensions: tuple = (1, 1), components: list = ['E'], z_range: Optional[tuple] = None, grid_x: Optional[array] = None, grid_y: Optional[array] = None, grid_z: Optional[array] = None, location: Optional[float] = None, sources: list = [], adjoint_n: bool = True, total_length: float = 0.0) None
Monitor class constructor0
- Parameters
axes (string) – the spacial axes to capture fields in. Options : ‘xz’ (default), ‘xy’, ‘yz’, ‘xyz’, ‘x’, ‘y’, ‘z’. Note, propagation is always in z. (default: “xy”)
dimensions (tuple) – the spacial dimensions of the resulting field (default: (1,1))
components (list) – list of the field components to store from (‘E’,’H’,’Ex’,’Ey’,’Ez’,’Hx’,’Hy’,’Hz) (default: [“E”])
z_range (tuple) – tuple or list of the form (start, end) representing the range of the z values to extract (default: None)
grid_x (numpy array (default: None)) – 1d x grid
grid_y (numpy array (default: None)) – 1d y grid
grid_z (numpy array (default: None)) – 1d z grid
location (float) – the location in z if the monitor represents “xy” axes (default: None)
sources (list[Source]) – sources to use for the monitor (default:[])
adjoint_n (bool) – if true will use the “continuous” n used for adjoint
- get_array(component: str = 'Hy', axes: Optional[str] = None, location: Optional[float] = None, z_range: Optional[tuple] = None, grid_x: Optional[array] = None, grid_y: Optional[array] = None) ndarray
Creates a matplotlib axis displaying the provides field component
- Parameters
component (str) – field component from “[‘Ex’,’Ey’,’Ez’,’Hx’,’Hy’,’Hz’,’E’,’H’]”
axes (str) – the spacial axes to capture fields in. Options : ‘xz’ (default), ‘xy’, ‘yz’, ‘xyz’, ‘x’, ‘y’, ‘z’. Note, propagation is always in z.
location (float) – if taken from 3D fields, users can specify where to take their 2D slice. If axes is ‘xz’, location refers to the location in y and ‘yz’ refers to a location in x and ‘xy’ refers to a location in z
z_range (tuple) – tuple or list of the form (start, end) representing the range of the z values to extract
grid_x (numpy array) – custom x grid to interpolate onto
grid_y (numpy array) – custom y grid to interpolate onto
- Returns
the requested field
- Return type
numpy array
- get_source_visual(min, max) ndarray
Returns a mask with lines indicating where a source is
- get_xy_monitor_visual(min, max) ndarray
Returns a mask with lines indicating where a source is
- get_z_list(start: float, end: float) list
Finds all the points in z between start and end
- Parameters
start (float) – starting point in z
end (float) – ending point in z
- Returns
A list of tuples that take the format (i, l) where i is the index of the z point and l is the z point for all z points in the range
- Return type
list[tuples]
- normalize() None
Normalizes the entire field to 1
- reset_monitor() None
Resets the fields in the monitor
- visualize(ax: Optional[AxesImage] = None, component: str = 'Hy', axes: Optional[str] = None, location: float = 0, z_range: Optional[tuple] = None, show_geometry: bool = True, show_sources: bool = True, show_xy_monitors: bool = False) AxesImage
Creates a matplotlib axis displaying the provides field component
- Parameters
ax (matplotlib axis) – the axis object created when calling plt.figure() or plt.subplots(), if None (default) then the plt interface will be used
component (string) – field component from “[‘Ex’,’Ey’,’Ez’,’Hx’,’Hy’,’Hz’,’E’,’H’]”
axes (string) – the spacial axes to capture fields in. Options : ‘xz’ (default), ‘xy’, ‘yz’, ‘xyz’, ‘x’, ‘y’, ‘z’. Note, propagation is always in z.
location (float) – if taken from 3D fields, users can specify where to take their 2D slice. If axes is ‘xz’, location refers to the location in y and ‘yz’ refers to a location in x and ‘xy’ refers to a location in z.
z_range (tuple) – tuple or list of the form (start, end) representing the range of the z values to extract
show_geometry (bool) – if true, will display the geometry faintly under the field profiles (default: True)
show_sources (bool) – if true, will display a red line indicating where a source is (default: True)
- Returns
the image used to plot the index profile
- Return type
matplotlib.image.AxesImage
Neural Network Acceleration
Tools
EMEPy offers functions to the user that can be called. These are mostly important for the library backend however.
- emepy.tools.get_epsfunc(width: float, thickness: float, cladding_width: float, cladding_thickness: float, core_index: float, cladding_index: float, compute: bool = False, profile: np.ndarray = None, nx: int = None, ny: int = None)
Callable class for getting epsilon on a grid
- emepy.tools.create_polygon(x: ndarray, y: ndarray, n: ndarray, detranslate: bool = True) list
Given a grid and a refractive index profile, will return the vertices of the polygon for importing into libraries such as Lumerical
- Parameters
x ("np.ndarray") – the x grid
y ("np.ndarray") – the y grid
n ("np.ndarray") – the refractive index profile
detranslate (bool) – if True, will detranslate the vertices
- Returns
the resulting vertices
- Return type
list[tuples]
- emepy.tools.interp(x: ndarray, y: ndarray, x0: ndarray, y0: ndarray, f: ndarray, centered: bool) ndarray
Interpolate a 2D complex array.
- Parameters
x ("np.ndarray") – the new x grid
y ("np.ndarray") – the new y grid
x0 ("np.ndarray") – the original x grid
y0 ("np.ndarray") – the original y grid
f ("np.ndarray") – the field to interpolate
centered (bool) – whether or not it needs to stil be shifted
- Returns
the interpolated field
- Return type
np.ndarray
- emepy.tools.interp1d(x: ndarray, x0: ndarray, f: ndarray, centered: bool) ndarray
Interpolate a 1D complex array.
- Parameters
x ("np.ndarray") – the new grid
x0 ("np.ndarray") – the original grid
f ("np.ndarray") – the field to interpolate
centered (bool) – whether or not it needs to stil be shifted
- Returns
the interpolated field
- Return type
np.ndarray
- emepy.tools.into_chunks(location: str, name: str, chunk_size: int = 20000000) None
Takes a large serialized file and breaks it up into smaller chunk files
- Parameters
location (string) – the absolute or relative path of the large file
name (string) – the name of the serialized smaller components (will have _chunk_# appended to it)
chunk_size (int) – how big each save chunk should be
- emepy.tools.from_chunks(location: str, name: str) None
Takes a directory of serialized chunks that were made using into_chunks and combines them back into a large serialized file
- Parameters
location (string) – the path of the directory where the chunks are located
name (string) – the name of the serialized file to create (make sure to include file extension if it matters)
- emepy.tools._get_eps(xc: ndarray, yc: ndarray, epsfunc: Callable[[ndarray, ndarray], ndarray]) tuple
Used by compute_other_fields and adapted from the EMpy library