simphox package¶
Submodules¶
simphox.circuit module¶
simphox.fdfd module¶
- class simphox.fdfd.FDFD(size, spacing, wavelength=1.55, eps=1, bloch_phase=0.0, pml=None, pml_sep=5, pml_params=(4, -16, 1.0), name='fdfd')[source]¶
Bases:
SimGridFinite Difference Frequency Domain (FDFD) simulator
Notes
Finite difference frequency domain works by performing a linear solve of discretized Maxwell’s equations at a single frequency (wavelength).
The discretized version of Maxwell’s equations in frequency domain is:
\[\nabla \times \mu^{-1} \nabla \times \mathbf{e} - k_0^2 \epsilon \mathbf{e} = k_0 \mathbf{j},\]which can be written in the form \(A \mathbf{e} = \mathbf{b}\), where:
\[ \begin{align}\begin{aligned}A &= \nabla \times \mu^{-1} \nabla \times - k_0^2 \epsilon\\\mathbf{b} &= k_0 \mathbf{j}\end{aligned}\end{align} \]is an operator representing the discretized EM wave operator at frequency \(\omega = k_0 = \frac{2\pi}{\lambda}\).
Therefore, \(\mathbf{e} = A^{-1}\mathbf{b}\).
For 2D simulations, it can be more efficient to solve for just the \(z\)-component of the fields since only \(\mathbf{e}_z\) is non-zero. In this case, we can solve a smaller problem to improve the efficiency. The form of this problem is \(A_z \mathbf{e}_z = \mathbf{b}_z\), where:
\[ \begin{align}\begin{aligned}A &= (\nabla \times \mu^{-1} \nabla \times)_z + k_0^2 \epsilon_z\\\mathbf{b}_z &= k_0 \mathbf{j}_z\end{aligned}\end{align} \]- size¶
Tuple of size 1, 2, or 3 representing the size in the grid in arbitrary units
- spacing¶
Spacing (microns) between each pixel along each axis (must be same dim as
size)
- eps¶
Relative permittivity \(\epsilon_r\)
- bloch_phase¶
Bloch phase (generally useful for angled scattering sims, not yet implemented!)
- pml¶
Perfectly matched layer (PML) of thickness on both sides of the form
(x_pml, y_pml, z_pml)
- pml_sep¶
The PML separation distance in number of pixels for sources
- pml_params¶
The PML parameters of the form
(exp_scale, log_reflectivity, pml_eps).
- property A: csr_matrix¶
Build the discrete Maxwell operator \(A(k_0)\) acting on \(\mathbf{e}\).
- Return type:
csr_matrix- Returns:
Electric field operator \(A\) for solving Maxwell’s equations at frequency \(omega\).
- e2h(e, beta=None)[source]¶
Convert magnetic field \(\mathbf{e}\) to electric field \(\mathbf{h}\).
Usage is:
h = fdfd.e2h(e), whereeis grid-shaped (not flattened). Ifeis flattened, this function attempts to reshape it.Mathematically, this represents rearranging the Maxwell equation in the frequency domain: ..math:
i \omega \mu \mathbf{h} &= \nabla imes \mathbf{e}.
- Return type:
ndarray- Returns:
The h-field converted from the e-field.
- classmethod from_pattern(component, core_eps, clad_eps, spacing, boundary, pml, wavelength, component_t=0, component_zmin=None, rib_t=0, sub_z=0, height=0, bg_eps=1, name='fdfd')[source]¶
Initialize an FDFD from a Pattern defined in DPhox.
- Parameters:
component (Pattern) – component provided by DPhox
core_eps (
float) – core epsilon (in the pattern region)clad_eps (
float) – clad epsilonspacing (
float) – spacing requiredboundary (
Union[Tuple[float,float],Tuple[float,float,float]]) – boundary size around componentpml (
float) – PML boundary sizewavelength (
float) – Wavelength for the simulation (specific to FDFD).height (
float) – height for 3d simulationsub_z (
float) – substrate minimum heightcomponent_zmin (
Optional[float]) – component height (defaults to substrate_z)component_t (
float) – component thicknessrib_t (
float) – rib thickness for component (partial etch)bg_eps (
float) – background epsilon (usually 1 or air/vacuum)name (
str) – Name of the component
- Returns:
A Grid object for the component
- classmethod from_simgrid(simgrid, wavelength)[source]¶
Prepare an
FDFDinstance from a genericSimGridand wavelength \(\lambda\).- Parameters:
simgrid (
SimGrid) –SimGridinstance.wavelength (
float) – Wavelength (\(\lambda\)).
- Returns:
The
FDFDinstance
- get_fields_fn(src, transform_fn=None, tm_2d=True)[source]¶
Build a fields function of a set of parameters (e.g., density, epsilon, etc.) given the source and transform function.
A numpy array source
src.The JAX-transformable transform function
transform_fn(e.g. transform) that yields the epsilon distribution used by jax.
- Parameters:
src (
ndarray) – Source for the solver.transform_fn (
Optional[Callable]) – Transforms parameters to yield the epsilon parameters used by jax (if None, use identity).tm_2d (
bool) – Whether to solve the TM polarization for this FDFD (only relevant for 2D, ignored for 3D).
- Return type:
Callable- Returns:
A solve function (2d or 3d based on defined
ndimspecified for the instance ofFDFD).
- h2e(h, beta=None)[source]¶
Convert magnetic field \(\mathbf{h}\) to electric field \(\mathbf{e}\).
Usage is:
e = fdfd.h2e(h), wherehis grid-shaped (not flattened). Ifhis flattened, this function attempts to reshape it.Mathematically, this represents rearranging the Maxwell equation in the frequency domain: ..math:
-i \omega \epsilon \mathbf{e} &= \nabla \times \mathbf{h}.
- Return type:
ndarray- Returns:
The e-field converted from the h-field.
- property mat: csr_matrix¶
Build the discrete Maxwell operator \(A(k_0)\) acting on \(\mathbf{e}\).
- Return type:
csr_matrix- Returns:
Electric field operator \(A\) for solving Maxwell’s equations at frequency \(omega\).
- property mat_ez: csr_matrix¶
Build the discrete Maxwell operator \(A_z(k_0)\) acting on \(\mathbf{e}_z\) (for 1D/2D problems).
- Return type:
csr_matrix- Returns:
Electric field operator \(A_z\) for a source with ez-polarized field.
- property mat_hz: csr_matrix¶
Build the discrete Maxwell operator \(A_z(k_0)\) acting on \(\mathbf{h}_z\) (for 2D problems).
- Return type:
csr_matrix- Returns:
Magnetic field operator \(A_z\) for a source with hz-polarized field.
- solve(src, solver_fn=None, iterative=-1, tm_2d=True, callback=None)[source]¶
Solves the FDFD problem (see class description for math).
- Parameters:
src (
ndarray) – normalized source (can be wgm or tfsf)solver_fn (
Optional[Callable[[spmatrix,ndarray],ndarray]]) – any function that performs a sparse linalg solveiterative (
int) – default = -1, direct = 0, gmres = 1, bicgstabtm_2d (
bool) – use the TM polarization (only relevant for 2D, ignored for 3D)callback (
Optional[Callable]) – a function to run during the solve (only applies in 3d iterative solver case, not yet implemented)
- Return type:
ndarray- Returns:
Electric fields that solve the problem \(A\mathbf{e} = \mathbf{b} = i \omega \mathbf{j}\).
- sparams(port_name, mode_idx=0, measure_info=None)[source]¶
Measure sparams using a port profile provided for a given port and mode index.
- Parameters:
port_name (
str) – The source port name for the sparams to measure.mode_idx (
int) – Mode index to access for the source.measure_info (
Optional[Dict[str,List[int]]]) – A list ofport_name,mode_idxto get mode measurements at each port.
- Returns:
Sparams measured at the ports specified in the class.
- to_2d(wavelength=None, slab_x=None, slab_y=None, tm=False)[source]¶
Project a 3D FDFD into a 2D FDFD using the variational 2.5D method laid out in the [paper](https://ris.utwente.nl/ws/files/5413011/ishpiers09.pdf).
- Parameters:
wavelength (
Optional[float]) – The wavelength to use for calculating the effective 2.5 FDFD (useful to stabilize multi-wavelength optimizations)slab_x (
Union[Tuple[int,int],Tuple[float,float],None]) – Port location x (if None, the port is provided by reading the port location specified by the component)slab_y (
Union[Tuple[int,int],Tuple[float,float],None]) – Port location y (if None, the port is provided by reading the port location specified by the component)tm (
bool) – Whether the mode in the 2D simulation is a TM mode (dominated by Hz component).
- Returns:
A 2D FDFD to approximate the 3D FDFD
simphox.grid module¶
- class simphox.grid.Grid(size, spacing, eps=1.0)[source]¶
Bases:
object- add(component, eps, zmin=None, thickness=None)[source]¶
Add a component to the grid.
- Parameters:
component (Pattern) – component to add
eps (
float) – permittivity of the component being added (isotropic only, for now)zmin (
float) – minimum z extent of the componentthickness (
float) – component thickness (zmax = zmin + thickness)
- Return type:
- Returns:
The modified
Gridfor chaining (self)
- block_design(waveguide, wg_height=None, sub_eps=1, sub_height=0, gap=0, block=None, sep=(0, 0), vertical=False, rib_y=0)[source]¶
A helper function for designing a useful port or cross section for a mode solver.
- Parameters:
waveguide (
Box) – The base waveguide material and size in the form ofBox.wg_height (
Optional[float]) – The waveguide height.sub_eps (
float) – The substrate epsilon (defaults to air)sub_height (
float) – The height of the substrate (or the min height of the waveguide built on top of it)gap (
float) – The coupling gap specified means we get a pair of base blocks
:param separated by
coupling_gap.: :type block:Optional[Box] :param block: Perturbing block that is to be aligned either vertically or horizontally with waveguide (MEMS). :type sep:Union[Tuple[float,float],Tuple[float,float,float]] :param sep: Separation of the block from the base waveguide layer. :type vertical:bool:param vertical: Whether the perturbing block moves vertically, or laterally otherwise. :type rib_y:float:param rib_y: Rib section.- Returns:
The resulting
Gridwith the modifiedepsproperty.
- fill(height, eps)[source]¶
Fill grid up to height, typically used for substrate + cladding epsilon settings
- Parameters:
height (
float) – Maximum final dimension of the fill operation (y if 2D, z if 3D).eps (
float) – Relative permittivity to fill.
- Return type:
- Returns:
The modified
Gridfor chaining (self)
- mask(center, size)[source]¶
Given a size and center, this function defines a mask which sets pixels in the region corresponding to
centerandsizeto 1 and all other pixels to zero.- Parameters:
center (
Tuple[float,float,float]) – position of the mask in (x, y, z) in the units of the simulation (note: NOT in terms of array index)size (
Tuple[float,float,float]) – size of the mask box in (x, y, z) in the units of the simulation (note: NOT in terms of array index)
- Returns:
The mask array of size
grid.shape.
- mask_fn(size, center=None)[source]¶
Given a box with
sizeandcenter, return a function that sets pixels inrho, whererho.shape == grid.eps.shape, outside the box toeps. This is important in inverse design to avoid modifying the material region near the source and measurement regions.- Parameters:
center (
Optional[Tuple[float,float,float]]) – position of the mask in (x, y, z) in the units of the simulation (note: NOT in terms of array index)size (
Tuple[float,float,float]) – size of the mask box in (x, y, z) in the units of the simulation (note: NOT in terms of array index)
- Returns:
The mask function
- reshape(v)[source]¶
A simple method to reshape flat 3d field array into the grid shape
- Parameters:
v (
ndarray) – vector of size3nto rearrange into array of size(3, nx, ny, nz)- Return type:
ndarray- Returns:
The reshaped array
- set_eps(center, size, eps)[source]¶
Set the region specified by
center,size(in grid units) toeps.- Parameters:
center (
Tuple[float,float,float]) – Center of the region.size (
Tuple[float,float,float]) – Size of the region.eps (
float) – Epsilon (relative permittivity) to set.
- Returns:
The modified
Gridfor chaining (self)
- slice(center, size, squeezed=True)[source]¶
Pick a slide of this grid
- Parameters:
center (
Tuple[float,float,float]) – center of the slice in (x, y, z) in the units of the simulation (note: NOT in terms of array index)size (
Tuple[float,float,float]) – size of the slice in (x, y, z) in the units of the simulation (note: NOT in terms of array index)squeezed (
bool) – whether to squeeze the slice to the minimum dimension (the squeeze order is z, then y).
- Returns:
The slices to access the array
- view_fn(center, size, use_jax=True)[source]¶
Return a function that views a field at specific region.
The view function is specified by center and size in the grid. This is typically used for mode-based sources and measurements. Once a slice is found, the fields need to be reoriented such that the field components point in the right direction despite a change in axis assignment. This function will handle this logic automatically in 1d, 2d, and 3d cases.
- Parameters:
center (
Tuple[float,float,float]) – Center of the regionsize (
Tuple[float,float,float]) – Size of the regionuse_jax (
bool) – Use jax
- Returns:
A view callable function that orients the field and finds the appropriate slice.
- class simphox.grid.Port(x, y, a=0, w=0, z=0, h=0)[source]¶
Bases:
objectPort to define where sources and measurements lie in photonic simulations.
A port defines the center and angle/orientation in a design.
- Parameters:
x (
float) – x position of the porty (
float) – y position of the porta (
float) – angle (orientation) of the port (in degrees)w (
float) – the width of the port (specified in design, mostly used for simulation)z (
float) – z position of the port (not specified in design, mostly used for simulation)h (
float) – the height of the port (not specified in design, mostly used for simulation)
- a: float = 0¶
- h: float = 0¶
- property size¶
- w: float = 0¶
- x: float¶
- y: float¶
- z: float = 0¶
- class simphox.grid.YeeGrid(size, spacing, eps=1, bloch_phase=0.0, pml=None, pml_sep=5, pml_params=(4, -16, 1.0), name='simgrid')[source]¶
Bases:
Grid- curl_fn(beta=None, of_h=False, use_jax=False)[source]¶
Get the function that computes curl of the electric field \(\mathbf{E}\).
- Parameters:
beta (
Optional[float]) – Propagation constant in the z direction (note: x, y are the cross section axes).of_h (
bool) – Whether to take the curl of huse_jax (
bool) – Whether the returned function should use jax.
- Return type:
Callable[[ndarray],ndarray]- Returns:
A function that computes discretized curl \(\nabla \times \mathbf{E}\).
- deriv(back=False)[source]¶
Calculate directional derivative.
- Parameters:
back (
bool) – Return backward derivative.- Return type:
List[spmatrix]- Returns:
Discrete directional derivative
dof the form(d_x, d_y, d_z)
- property deriv_backward¶
The backward derivative
- Returns:
The backward derivative
- property deriv_forward¶
The forward derivative
- Returns:
The forward derivative
- diff_fn(of_h=False, use_jax=False)[source]¶
Return a function that takes the discrete derivative of a field in a functional manner based on grid.
- Parameters:
of_h (
bool) – Take the derivative of \(\mathbf{H}\), otherwise \(\mathbf{E}\).use_jax (
bool) – Whether to use jax.
- Returns:
The discrete derivative function
- property eps_t¶
This attribute specifies the grid-averaged epsilon in the grid.
- Returns:
The grid-averaged epsilon.
- pml_safe_placement(loc)[source]¶
Specifies a source/ measurement placement that is safe from the PML region / edge of the simulation.
- Parameters:
loc (
Tuple[float,float,float]) – Location of the form (x, y, z) to move safely away from the PML- Return type:
Tuple[float,float,float]- Returns:
New x, y, z tuple that is safe from PML (at least one Yee grid point away from the pml region).
simphox.mkl module¶
simphox.mode module¶
- class simphox.mode.ModeLibrary(solver, max_num_modes=6)[source]¶
Bases:
objectA data structure to contain the information about \(num_modes\) cross-sectional modes
- Parameters:
max_num_modes (
int) – Maximum number of modes that should be solved.
- beta(mode_idx=0)[source]¶
Fundamental mode propagation constant \(\beta\) for mode indexed by
mode_idx.- Parameters:
mode_idx (
int) – The mode index \(m \leq M\)- Return type:
float- Returns:
\(\beta_m\) for mode \(m \leq M\)
- property dbeta¶
- property dn¶
- e(mode_idx=0, tm_2d=True)[source]¶
Electric field \(\mathbf{E}\) for the mode of specified index
- Parameters:
mode_idx (
int) – The mode index \(m \leq M\)tm_2d (
bool) – If the mode is using a 1d distribution, this specifies if the mode is TM (otherwise TE)
- Return type:
ndarray- Returns:
\(\mathbf{E}_m\), an
ndarrayof shape(3, X, Y, Z)for mode \(m \leq M\)
- evolve(length, mode_weights=(1,), use_h=True)[source]¶
Evolve a mode in time according to
mode_weights.- Parameters:
length (
Union[float,ndarray]) – The length (or time) over which the mode is evolving. If a 1d array is provided, output the mode evaluated at all the lengths in the array.mode_weights (
Tuple[float,...]) – The mode weights.use_h (
bool) – Use the h field as the mode profile.
- Returns:
The evolved mode profile(s).
- evolve_viz(max_length, mode_weights=(1,), power=True)[source]¶
Use holoviews to dynamically visualize the evolution of a multimode field
- Parameters:
max_length (
float) – Maximum length for the evolution of modes.mode_weights (
Tuple[float,...]) – Mode weights for the mode evolution.power (
bool) – Visualize the power, otherwise visualize the field.
Returns:
- classmethod from_block_design(size, spacing, waveguide, num_modes=6, wavelength=1.55, wg_height=None, sub_eps=1, sub_height=0, coupling_gap=0, block=None, sep=(0, 0), vertical=False, rib_y=0)[source]¶
A helper function for designing a useful port or cross section for a mode solver.
- Parameters:
size (
Union[Tuple[float,float],Tuple[float,float,float]]) – Size of the overall simulation.spacing (
Union[float,Tuple[float,float,float]]) – Spacing between points in the grid for the mode solver.waveguide (
Box) – The base waveguide material and size in the form ofBox.wavelength (
float) – Wavelength for the mode solver.num_modes (
int) – Number of modes that should be solved.wg_height (
Optional[float]) – The waveguide height.sub_eps (
float) – The substrate epsilon (defaults to air)sub_height (
float) – The height of the substrate (or the min height of the waveguide built on top of it)coupling_gap (
float) – The coupling gap specified means we get a pair of base blocks
:param separated by
coupling_gap.: :type block:Optional[Box] :param block: Perturbing block. :type sep:Union[Tuple[float,float],Tuple[float,float,float]] :param sep: Separation of the block from the base waveguide layer. :type vertical:bool:param vertical: Whether the perturbing block moves vertically, or laterally otherwise. :type rib_y:float:param rib_y: Rib section- Returns:
The resulting
ModeLibrarywith the modifiedepsproperty.
- h(mode_idx=0, tm_2d=True)[source]¶
Magnetic field \(\mathbf{H}\) for the mode of specified index
- Parameters:
mode_idx (
int) – The mode index \(m \leq M\)tm_2d (
bool) – If the mode is using a 1d distribution, this specifies if the mode is TM (otherwise TE)
- Return type:
ndarray- Returns:
\(\mathbf{H}_m\), an
ndarrayof the form(3, X, Y)for mode \(m \leq M\)
- measure_fn(mode_idx=0, use_jax=False, tm_2d=True)[source]¶
Measure flux provided a mode indexed at
mode_index.- Parameters:
mode_idx (
int) – Mode index for the measurement.use_jax (
bool) – Use jax.tm_2d (
bool) – Use TM polarization (only relevant in the case of 2D simulations (i.e., 1D modes)).
- Returns:
A function that takes e, h fields and outputs the a and b terms
- n(mode_idx=0)[source]¶
Effective index \(n\) for mode indexed by
mode_idx.- Returns:
The effective index \(n\)
- property ns¶
The refractive index for all modes corresponding to
betas.- Returns:
\(\mathbf{n}\), an
ndarrayfor the refractive index of shape(M,)
- phase(length=1, mode_idx=0)[source]¶
Measure the phase delay propagated over a length
- Parameters:
length (
float) – The length over which to propagate the modemode_idx (
int) – The mode idx to propagate
- Returns:
The aggregate phase delay over a length.
- place(mode_idx, grid, center, size)[source]¶
Place at mode_idx in device with \(shape\) and \(region\).
- Parameters:
mode_idx (
int) – Mode index to place.grid (
YeeGrid) – Finite-difference grid to place the mode.center (
Union[Tuple[float,float],Tuple[float,float,float]]) – Specified center for placement.size (
Union[Tuple[float,float],Tuple[float,float,float]]) – Specified size for placement.
- Return type:
ndarray- Returns:
Places the mode into the provided grid at the requested center and size, with orientation of the mode automatically determined from the center and size provided.
- plot_field(ax, idx=0, axis=1, use_h=True, title='Field', include_n=True, title_size=16, label_size=16)[source]¶
Plot field overlaid on the material.
- Parameters:
ax – Matplotlib axis handle.
idx (
int) – Mode index to plot.axis (
Union[int,str]) – Field axis to plot.use_h (
bool) – Plot magnetic field \(\mathbf{H}\).title (
str) – Title of the plot/subplot.include_n (
bool) – Include the refractive index in the title.title_size (
float) – Fontsize of the title.label_size – Fontsize of the label.
- plot_power(ax, idx=0, title='Power', include_n=True, title_size=16, label_size=16)[source]¶
Plot sz overlaid on the material
- Parameters:
ax – Matplotlib axis handle.
idx (
int) – Mode index to plot.title (
str) – Title of the plot/subplot.include_n (
bool) – Include the refractive index in the title.title_size (
float) – Fontsize of the title.label_size – Fontsize of the label.
- sz(mode_idx=0)[source]¶
Poynting vector \(\mathbf{S}_z\) for the mode of specified index
- Parameters:
mode_idx (
int) – The mode index \(m \leq M\)- Return type:
ndarray- Returns:
\(\mathbf{S}_{m, z}\), the z-component of Poynting vector (correspoding to power), of shape
(X, Y)
- update_wavelength(wavelength)[source]¶
Update the wavelength for the mode solver.
This method updates the wavelength for the mode solver and proceeds to solve at that new wavelength. This is useful for dispersion simulations.
- Parameters:
wavelength (
float) – The new wavelength for the mode solver- Returns:
The current ModeLibrary object with the modified wavelength.
- class simphox.mode.ModeSolver(size, spacing, wavelength=1.55, eps=1, name='mode')[source]¶
Bases:
YeeGridFDFD-based waveguide mode solver
Notes
This class is capable of finding 1d or 2d cross-sectional modes, which are useful for defining sources and calculating the number of propagating modes that exist in multi-mode interferometers (MMIs).
We can solve either the 1d or 2d case using 1 or 2 components of the field respectively. Note that in simphox units, we assume \(k_0 = \frac{2\pi}{\lambda} = \omega\), letting \(c = \epsilon_0 = \mu_0 = 1\) for simplicity. We define the wavenumber :math`:beta_m` for mode \(m\) to be the square root of the eigenvalue (hence the \(eta^2\) terms in the later equations) of \(C_{\mathrm{1d}}\) and \(C_{\mathrm{2d}}\) for the respective problems.
For the 1d case, we consider the case where the simulation is a line cross-section of a 2d grid in the \(xy\)-plane. In that case, we solve for the $z$-component of an \(h_z\)-polarized mode of the form \(\mathbf{h}_m = (0, 0, h_z(y)) e^{-i\beta_m x}\). The solutions for \(h_z(y)\) correspond to the simple equation:
\[ \begin{align}\begin{aligned}\beta^2 h_z &= \partial_y^2 h_z + k_0^2 \epsilon_z h_z\\\beta_m^2 \mathbf{h}_{m} &= C_{\mathrm{1d}} \mathbf{h}_{m}\end{aligned}\end{align} \]For the 2d case, we cannot make this type of assumption. Instead we solve the frequency-domain Maxwell’s equations for the case of \(z\)-translation symmetry (here, we consider propagation along $z$ instead of $x$ to match convention). This time, we solve for an \(\mathbf{h}\)-field of the form \(\mathbf{h}_m = \mathbf{h}(x, y) e^{-i\beta_m z}\). This is made possible by the following set of coupled differential equations:
\[ \begin{align}\begin{aligned}\beta^2 h_x &= \partial_x(\partial_x h_x + \partial_y h_y) - \epsilon_y (\epsilon_z^{-1} (\partial_y h_x - \partial_x h_y) + k_0^2) = C_{xy} \begin{bmatrix} h_x \ h_y\end{bmatrix}\\\beta^2 h_y &= \partial_y(\partial_x h_x + \partial_y h_y) - \epsilon_x (\epsilon_z^{-1} (\partial_x h_y - \partial_y h_x) + k_0^2) = C_{yx} \begin{bmatrix} h_x \ h_y\end{bmatrix}\\\beta^2 \begin{bmatrix} h_x \ h_y\end{bmatrix} &= \begin{bmatrix} C_{xy} \ C_{yx}\end{bmatrix} \begin{bmatrix} h_x \ h_y\end{bmatrix}\\\beta_m^2 \mathbf{h}_{m} &= C_{\mathrm{2d}} \mathbf{h}_{m}\end{aligned}\end{align} \]- size¶
Tuple of size 1, or 2 representing the size in arbitrary units.
- spacing¶
Spacing (microns) between each pixel along each axis (MUST be in same units as size)
- wavelength¶
Wavelength for the mode solver.
- eps¶
Relative permittivity \(\epsilon\).
- property C: spmatrix¶
Build the WaveGuide Mode (WGM) operator (for 1D or 2D grid only)
The WGM operator \(C(\omega)\) acts on the magnetic field \(\mathbf{h}\) of the form
(hx, hy), which assumes cross-section translational x-symmetry:\[C \mathbf{h}_m &= \lambda_m \mathbf{h}_m,\]where \(0 \leq m < M\) for the \(M\) modes with the largest wavenumbers (\(\beta_m = \sqrt{\lambda_m}\)).
- Return type:
spmatrix- Returns:
Magnetic field operator \(C\).
- dispersion_sweep(wavelengths, m=6, pbar=None)[source]¶
Dispersion sweep for cross sectional modes
- Parameters:
wavelengths (
ndarray) – Wavelengths \(\lambda\) of length \(L\)m (
int) – Number of modes to solvepbar (
Optional[Callable]) – Progress bar handle (to show progress using e.g. tqdm)
- Returns:
A list of \(L\)
Modessolution objects
- e2h(e, beta=None)[source]¶
Convert magnetic field \(\mathbf{e}\) to electric field \(\mathbf{h}\).
Usage is:
h = mode.e2h(e), whereeis grid-shaped (not flattened)Mathematically, this represents rearranging the Maxwell equation in the frequency domain:
\[i \omega \mu \mathbf{h} &= \nabla \times \mathbf{e}\]- Return type:
ndarray- Returns:
The h-field converted from the e-field.
- h2e(h, beta=None)[source]¶
Convert magnetic field \(\mathbf{h}\) to electric field \(\mathbf{e}\).
Usage is:
e = mode.h2e(h), wherehis grid-shaped (not flattened)Mathematically, this represents rearranging the Maxwell equation in the frequency domain:
\[-i \omega \epsilon \mathbf{e} = \nabla \times \mathbf{h}.\]- Return type:
ndarray- Returns:
Function to convert h-field to e-field.
- property k0¶
- solve(max_num_modes=6, beta_guess=None, mode_guess=None, tol=1e-07)[source]¶
FDFD waveguide mode solver
Solve for waveguide modes (x-translational symmetry) by finding the eigenvalues of \(C\).
\[C \mathbf{h}_m &= \lambda_m \mathbf{h}_m,\]where \(0 \leq m < M\) for the \(M\) (num_modes) modes with the largest wavenumbers (\(\beta_m = \pm \sqrt{\lambda_m}\)).
- Parameters:
max_num_modes (
int) – Maximum number of modes to return (less are returned if they correspond to an imaginary \(\beta\)).beta_guess (
Union[float,Tuple[float,float],None]) – Guess for propagation constant \(\beta\) (the eigenvalue).mode_guess (
Optional[ndarray]) – Guess for the mode \(\boldsymbol{h}\)tol (
float) – Tolerance of the mode eigensolver.
- Return type:
Tuple[ndarray,ndarray]- Returns:
num_modes (\(M\)) largest propagation constants (\(\sqrt{\lambda_m(C)}\)) and corresponding modes (\(\mathbf{h}_m\)) of shape
(num_modes, n).
- property waveguide_mode_matrix: spmatrix¶
Build the WaveGuide Mode (WGM) operator (for 1D or 2D grid only)
The WGM operator \(C(\omega)\) acts on the magnetic field \(\mathbf{h}\) of the form
(hx, hy), which assumes cross-section translational x-symmetry:\[C \mathbf{h}_m &= \lambda_m \mathbf{h}_m,\]where \(0 \leq m < M\) for the \(M\) modes with the largest wavenumbers (\(\beta_m = \sqrt{\lambda_m}\)).
- Return type:
spmatrix- Returns:
Magnetic field operator \(C\).
simphox.opt module¶
simphox.primitives module¶
- class simphox.primitives.TMOperator(df, db)[source]¶
Bases:
objectThis class generates some helpful TE primitives based on the input discrete derivatives provided by the FDFD class for a 2D problem.
- df¶
A list of forward discrete derivative in order (
df_x,df_y,df_z).
- db¶
A list of backward discrete derivative in order (
db_x,db_y,db_z).
simphox.sim module¶
- class simphox.sim.SimCrossSection(io, center, size, wavelength)[source]¶
Bases:
object- center: Union[Tuple[float, float], Tuple[float, float, float]]¶
- io: ModeLibrary¶
- profile(mode_idx, use_h=False)[source]¶
Returns the mode profile oriented based on specified xyz size of the profile.
- Parameters:
mode_idx (
int) – The mode index of the profileuse_h (
float) – Return the h field for the profile
- Returns:
The oriented profile.
- property prop_axis: int¶
The propagation axis (the poynting direction where the port slice size should be 0)
- Return type:
int- Returns:
The propagation axis for the mode in the simulation cross section.
- size: Union[Tuple[float, float], Tuple[float, float, float]]¶
- wavelength: float¶
- class simphox.sim.SimGrid(size, spacing, eps=1, bloch_phase=0.0, pml=None, pml_params=(4, -16, 1.0, 5), pml_sep=5, use_jax=False, name='simgrid')[source]¶
Bases:
YeeGrid- decorate(sparams, fields)[source]¶
Decorates the
sparamsandfieldsusingxarray.DataArray- Parameters:
sparams (
ndarray) – The sparams resulting from a call to the returned callable fromget_sim_sparams_fn.fields (
ndarray) – The fields resulting from a call to the returned callable fromget_sim_sparams_fn.
- Return type:
Tuple[DataArray,DataArray,DataArray]- Returns:
The decorated
sparamsandfields.
- fidelity(desired_sparams, measure_info=None, insertion_weight=0)[source]¶
Returns the fidelity for the
sparams.- Parameters:
desired_sparams (
Union[Dict[Tuple[str,int],complex128],Dict[str,complex128]]) – The desired sparams, provided in dictionary form mapping port to relative magnitude; if not an ndarray and/or not normalized, it is converted to a normalized ndarray.measure_info (
Optional[List[Tuple[str,int]]]) – Measurement info consisting of a list of port name and mode index pairs (used to index s)insertion_weight (
float) – Renormalize s-params to separate insertion loss and sparams. Then, weight insertion byinsertion_weightand sparams by1 - insertion_weight. If zero, ignore.
- Return type:
Callable- Returns:
The fidelity based on the desired sparams
s.
- get_fields_fn(src, transform_fn=None, tm_2d=True)[source]¶
Returns a function that yields the fields given a transform function and source.
We first initialize the problem solver given two callable functions:
A numpy array source
srcThe JAX-transformable transform function
transform_fn(e.g. transform) (identity if None)
- Parameters:
src (
Union[ndarray,Callable]) – source for the solver (either a callable for time domain or array for frequency domain)transform_fn (
Optional[Callable]) – Transforms parameters to yield the epsilon function used by jax
- Return type:
Callable- Returns:
A solve function (2d or 3d based on defined
ndimspecified for the instance ofFDFD)
- get_measure_fn(measure_port=None, wavelength=1.55, profile_size_factor=3, use_jax=False, tm_2d=True)[source]¶
Measure function: measure the fields using the Modes object provided for each port.
- Parameters:
measure_port (
Union[str,Tuple[str,int],Dict[str,List[int]],Iterable[Union[str,Tuple[str,int]]],None]) – List of port name and mode index at that port.wavelength (
float) – The wavelength for the measurement.profile_size_factor (
float) – Factor to rescale the mode view slice compared to the port.use_jax (
bool) – Whether to use jax in the measure function (relevant for simulations).tm_2d (
bool) – Whether to use TM polarization (applies to the 2D case only).
- Return type:
Callable[[ndarray],ndarray]- Returns:
Callable function that gives port-wise measurements.
- get_sim_fn(src, transform_fn=None, tm_2d=True)[source]¶
Returns a function that measures the sparams and fields.
We first initialize the optimization problem solver given two callable functions:
A numpy array or callable source
src(only an array is needed in fdfd).The JAX-transformable transform function
transform_fn(e.g. transform) (identity if None)
We then extract the sparams using the port locations provided in this class.
- Parameters:
src (
Union[ndarray,Callable]) – source for the solvertransform_fn (
Optional[Callable]) – Transforms parameters to yield the epsilon function used by jaxtm_2d (
bool) – Whether to use TM polarization (applies to the 2D case only).
- Return type:
Callable- Returns:
A solve function (2d or 3d based on defined
ndimspecified for the instance ofFDFD)
- get_sim_sparams_fn(port_name=None, transform_fn=None, mode_idx=0, profile_size_factor=3, measure_info=None, tm_2d=True)[source]¶
Returns a function that measures the sparams and fields.
We first initialize the optimization problem solver given a JAX-transformable transform function
transform_fn(e.g. transform) and the port, mode pair for the input source (used to normalize the output measurements to get the s params). We then extract the sparams using the port locations provided in this class.- Parameters:
port_name (
Optional[str]) – Port name for the sourcemode_idx (
int) – Mode index for the sourcetransform_fn (
Optional[Callable]) – Transforms parameters to yield the epsilon function used by jax (identity if None)profile_size_factor (
int) – Profile size factor to rescale the port size to get mode sizemeasure_info (
Optional[Dict[str,List[int]]]) – Measurement info consisting of a list of port name and mode index pairstm_2d (
bool) – Whether to use TM polarization (applies to the 2D case only).
- Return type:
Callable- Returns:
A solve function (2d or 3d based on defined
ndimspecified for the instance ofFDFD)
- modes(center, size, wavelength=1.55, num_modes=1)[source]¶
Eigenmode profile of a 2d or 3d
SimGridobject. This function is cached so that it only computes the modes if the input parameters are provided.- Parameters:
center (
Tuple[float,float,float]) – center tuple of the form(x, y, z)(in sim units, NOT pixels)size (
Tuple[float,float,float]) – size of the source (in sim units, NOT pixels)wavelength (
float) – wavelength (arb. units, should match with spacing)num_modes (
int) – number of modes to find
- Return type:
- Returns:
A Tuple of a Modes object and view function for measuring the fields.
- port_modes(excitation=None, profile_size_factor=3, wavelength=1.55)[source]¶
Profile for all the ports in the grid (always assumed to be along x or y axes!).
- Parameters:
excitation (
Optional[List[Tuple[str,int]]]) – Dictionary mapping port to mode index for excitationsprofile_size_factor (
float) – Factor to rescale the mode view slice compared to the portwavelength (
float) – Wavelength for the modes
- Return type:
Dict[Union[str,int],SimCrossSection]- Returns:
A dictionary from mode to SimCrossSection containing the mode, and its center and size in this grid needed to reconstruct the source using
mode.place.
- port_source(source=None, profile_size_factor=3, unidirectional=True, wavelength=1.55)[source]¶
Return a non-sparse source array based on the ports defined in the simulation grid.
- Parameters:
source (
Union[Dict[Tuple[str,int],float],Dict[str,float],None]) – Map each port and mode index to a weight to yield a weighted port source. If a dictionary is specified, it can be of the form{(port_name, mode_idx): weight}or{port_name: weight}, where in the latter case, a default mode index of 0 is used. A source is then created by summing the contributions from all of those ports.profile_size_factor (
float) – Factor to rescale the mode view slice compared to the portunidirectional (
bool) – In FDFD, this specifies whether to send the mode in unidirectionally, determined using the port angle.wavelength (
float) – Wavelength for the source
- Return type:
ndarray- Returns:
The non-sparse source array that can be used as a source profile for either FDFD or FDTD
- to_2d(wavelength=None, slab_loc=None, tm=True)[source]¶
Project a 3D simulation into a 2D simulation using the variational 2.5D method.
- Parameters:
wavelength (
Optional[float]) – The wavelength to use for calculating the effective 2.5 FDFD (useful to stabilize multi-wavelength optimizations)slab_loc (
Optional[Tuple[float,float]]) – Slab location x (if None, the first port location (in alphanumeric order) specified by component)tm (
bool) – Whether the 2D simulation is a TM mode simulation
- Return type:
- Returns:
A 2D simulation to approximate the 3D simulation.
- viz_panel(img_width=700, xs_axis=2)[source]¶
Visualizes a 2D slice of a simulation.
- Parameters:
img_width (
float) – Width of the visualization panel for the simulationxs_axis (
int) – Axis for the intersection
- Return type:
Tuple[Panel,Tuple[Pipe,Pipe,Pipe]]- Returns:
Panel / dashboard for visualizing the permittivity and field overlay and Tuple of Pipes for feeding data to the panel (e.g. from an optimization or FDTD real-time simulation).
simphox.transform module¶
- simphox.transform.get_mask_fn(rho_init, box)[source]¶
Given an initial param set, this function defines the box region(s) where the params are allowed to change.
- simphox.transform.get_smooth_fn(beta, radius, eta=0.5)[source]¶
- Using the sigmoid function and convolutional kernel provided in jax, we return a function that
effectively binarizes the design respectively and smooths the density parameters.
- Parameters:
beta (
float) – A multiplicative factor in the tanh function to effectively define how binarized the design should beradius (
float) – The radius of the convolutional kernel for smoothingeta (
float) – The average value of the design
- Returns:
The smoothing function
- simphox.transform.get_symmetry_fn(ortho_x=False, ortho_y=False, diag_p=False, diag_n=False, avg=False)[source]¶
Get the array-based reflection symmetry function based on orthogonal or diagonal axes.
- Parameters:
ortho_x (
bool) – symmetry along x-axis (axis 0)ortho_y (
bool) – symmetry along y-axis (axis 1)diag_p (
bool) – symmetry along positive ([1, 1] plane) diagonal (shape of params must be square)diag_n (
bool) – symmetry along negative ([1, -1] plane) diagonal (shape of params must be square)avg (
bool) – Whether the symmetry should take the average (applies to ortho symmetries ONLY)
- Returns:
The overall symmetry function
simphox.utils module¶
- class simphox.utils.Box(size, material=None, spacing=1, min=(0.0, 0.0))[source]¶
Bases:
objectHelper class for quickly generating functions for design region placements.
- size¶
size of box
- Type:
Union[float, Tuple[float, float]]
- spacing¶
spacing for pixelation
- Type:
float
- material¶
Materialfor this Box- Type:
Optional[simphox.utils.Material]
- min¶
min x and min y of box
- Type:
Tuple[float, float]
- property center: Tuple[float, float]¶
- Return type:
Tuple[float,float]
- property max¶
- property max_i¶
- min: Tuple[float, float] = (0.0, 0.0)¶
- property min_i¶
- property shape¶
- size: Union[float, Tuple[float, float]]¶
- spacing: float = 1¶
- class simphox.utils.Material(name, eps=1.0, facecolor=(0, 0, 0))[source]¶
Bases:
objectHelper class for materials.
- name¶
Name of the material.
- Type:
str
- eps¶
Constant epsilon (relative permittivity) assigned for the material.
- Type:
float
- facecolor¶
Facecolor in red-green-blue (RGB) for drawings (default is black or
(0, 0, 0)).- Type:
Tuple[float, float, float]
- eps: float = 1.0¶
- facecolor: Tuple[float, float, float] = (0, 0, 0)¶
- name: str¶
- simphox.utils.fix_dataclass_init_docs(cls)[source]¶
Fix the
__init__documentation for adataclasses.dataclass.- simphox.utils.cls¶
The class whose docstring needs fixing
- Returns:
The class that was passed so this function can be used as a decorator
- simphox.utils.gaussian_fft(profiles, pulse_width, center_wavelength, dt, t0=None, linear_chirp=0)[source]¶
Gaussian FFT for measurement.
- Parameters:
profiles (
ndarray) – profiles measured over timepulse_width (
float) – Gaussian pulse widthcenter_wavelength (
float) – center wavelengthdt (
float) – time step sizet0 (
Optional[float]) – peak time (default to be central time step)linear_chirp (
float) – linear chirp coefficient (default to be 0)
- Returns:
the Gaussian source discretized in time
- simphox.utils.gaussian_fn(wavelength, pulse_width=0, fwidth=inf, start_time=0, center_time_factor=5.0, linear_chirp=0)[source]¶
A Gaussian function for sources.
- Parameters:
wavelength (
float) – The carrier wavelength for the electromagnetic radiation.pulse_width (
float) – The Gaussian envelope pulse width \(w\) in wavelength units.fwidth (
float) – The Gaussian envelope pulse width in \(w_f = 2 \pi / w\) frequency units.start_time (
float) – The start time for the Gaussian.center_time_factor (
float) – Decide the time \(t_0\): to center the Gaussian, such thatt0 = center_factor * k0.linear_chirp (
float) – linear chirp coefficient (default to be 0)
Returns:
- simphox.utils.normalized_error(u, use_jax=False)[source]¶
Normalized fidelity cost function.
- Parameters:
u (
ndarray) – the true (target) unitary, \(U \in \mathrm{U}(N)\).use_jax (
bool) – Use JAX for the normalized fidelity function (for optimizations)
- Returns:
A function that accepts
uhatthe estimated unitary (not necessarily unitary), \(\widehat{U}\) and returns the fidelity measurement.
- simphox.utils.random_tensor(size, is_complex=True)[source]¶
Generate a random complex normal tensor.
- Parameters:
size (
Union[int,Tuple]) – Number of inputs or shape.is_complex (
bool) – Return a complex vector
- Return type:
ndarray- Returns:
The random complex normal tensor.
- simphox.utils.random_unitary(n)[source]¶
Generate a random unitary matrix.
- Parameters:
n (
int) – Number of inputs and outputs- Return type:
ndarray- Returns:
The random complex normal vector.
- simphox.utils.random_vector(n, normed=False, is_complex=True)[source]¶
Generate a random complex normal tensor.
- Parameters:
n (
int) – Number of inputs.normed (
bool) – Whether to norm the random complex vector so that the norm of the vector is 1.is_complex (
bool) – Return a complex vector
- Returns:
The random complex normal vector.
simphox.viz module¶
- simphox.viz.get_extent_2d(shape, spacing=None)[source]¶
2D extent
- Parameters:
shape – shape of the elements to plot
spacing (
Optional[float]) – spacing between grid points (assumed to be isotropic)
- Returns:
The extent in 2D.
- simphox.viz.hv_field_2d(field, eps=None, spacing=None, cmap='RdBu', mat_cmap='gray', alpha=0.2, width=600)[source]¶
- simphox.viz.hv_power_2d(power, eps=None, spacing=None, cmap='hot', mat_cmap='gray', alpha=0.2, width=600)[source]¶
- simphox.viz.plot_eps_1d(ax, eps, spacing=None, color='blue', units='$\\\\mu$m', axis_label_rotation=90)[source]¶
Plot eps in 1D.
- Parameters:
ax – Matplotlib axis handle
eps (
Optional[ndarray]) – epsilon permittivity for overlaying field onto materialsspacing (
Optional[float]) – spacing between grid points (assumed to be isotropic)color (
str) – Color to plot the epsilonunits (
str) – Units for plotting (default microns)axis_label_rotation (
float) – Rotate the axis label in case a plot is made with shared axes.
- simphox.viz.plot_eps_2d(ax, eps, spacing=None, cmap='gray')[source]¶
Plot eps in 2D
- Parameters:
ax – Matplotlib axis handle
eps (
ndarray) – epsilon permittivityspacing (
Optional[float]) – spacing between grid points (assumed to be isotropic)cmap (
str) – colormap for field array (we highly recommend RdBu)
- simphox.viz.plot_eps_3d(plot, eps=None, spacing=1, color_range=None, alpha=100, samples=1200)[source]¶
- Parameters:
plot (Plot) – K3D plot handle (NOTE: this is for plotting in a Jupyter notebook)
eps (
Optional[ndarray]) – relative permittivityspacing (
float) – spacing between grid points (assumed to be isotropic)color_range (
Tuple[float,float]) – color range for visualization (if none, use half maximum value of field)alpha (
float) – alpha for k3d plotsamples (
float) – samples for k3d plot rendering
Returns:
- simphox.viz.plot_field_1d(ax, field, field_name, eps=None, spacing=None, color='red', eps_color='blue', units='$\\\\mu$m')[source]¶
Plot field in 1D
- Parameters:
ax – Matplotlib axis handle.
field (
ndarray) – Field to plot.field_name (
str) – Name of the field being plottedspacing (
Optional[float]) – spacing between grid points (assumed to be isotropic).color (
str) – Color to plot the epsilonunits (
str) – Units for plotting (default microns)
- simphox.viz.plot_field_2d(ax, field, eps=None, spacing=None, cmap='RdBu', mat_cmap='gray', alpha=0.8, vmax=None)[source]¶
Plot field in 2D
- Parameters:
ax – Matplotlib axis handle
field (
ndarray) – field to ploteps (
Optional[ndarray]) – epsilon permittivity for overlaying field onto materialsspacing (
Optional[float]) – spacing between grid points (assumed to be isotropic)cmap (
str) – colormap for field array (we highly recommend RdBu)mat_cmap (
str) – colormap for eps array (we recommend gray)alpha (
float) – transparency of the plots to visualize overlay
- simphox.viz.plot_field_3d(plot, field, eps=None, axis=1, imag=False, spacing=1, alpha=100, samples=1200, color_range=None)[source]¶
- Parameters:
plot (Plot) – K3D plot handle (NOTE: this is for plotting in a Jupyter notebook)
field (
ndarray) – field to ploteps (
Optional[ndarray]) – permittivity (if specified, plot with default options)axis (
int) – pick the correct axis for power in Poynting vector formimag (
bool) – whether to use the imaginary (instead of real) component of the fieldspacing (
float) – spacing between grid points (assumed to be isotropic)color_range (
Tuple[float,float]) – color range for visualization (if none, use half maximum value of field)alpha (
float) – alpha for k3d plotsamples (
float) – samples for k3d plot rendering
Returns:
- simphox.viz.plot_power_2d(ax, power, eps=None, spacing=None, cmap='hot', mat_cmap='gray', alpha=0.8, vmax=None)[source]¶
Plot the power (computed using Poynting) in 2D
- Parameters:
ax – Matplotlib axis handle
power (
ndarray) – power array of size (X, Y)eps (
Optional[ndarray]) – epsilon for overlay with materialsspacing (
Optional[float]) – spacing between grid points (assumed to be isotropic)cmap (
str) – colormap for power arraymat_cmap (
str) – colormap for eps array (we recommend gray)alpha (
float) – transparency of the plots to visualize overlay
- simphox.viz.plot_power_3d(plot, power, eps=None, axis=0, spacing=1, color_range=None, alpha=100, samples=1200)[source]¶
Plot the 3d power in a notebook given the fields \(E\) and \(H\).
- Parameters:
plot (Plot) – K3D plot handle (NOTE: this is for plotting in a Jupyter notebook)
power (
ndarray) – power (either Poynting field of size (3, X, Y, Z) or power of size (X, Y, Z))eps (
Optional[ndarray]) – permittivity (if specified, plot with default options)axis (
int) – pick the correct axis if inputting power in Poynting fieldspacing (
float) – spacing between grid points (assumed to be isotropic)color_range (
Tuple[float,float]) – color range for visualization (if none, use half maximum value of field)alpha (
float) – alpha for k3d plotsamples (
float) – samples for k3d plot rendering
Returns: