2019-09-05 22:38:29 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from typing import Dict, List, Tuple
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import numpy
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import scipy.sparse as sparse
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-05 00:20:06 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from .. import vec, unvec, dx_lists_t, vfield_t, field_t
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from . import operators, waveguide, functional
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-05 00:20:06 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from ..eigensolvers import signed_eigensolve, rayleigh_quotient_iteration
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-09-05 22:38:29 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								def vsolve_waveguide_mode_2d(mode_number: int,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             omega: complex,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             dxes: dx_lists_t,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             epsilon: vfield_t,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             mu: vfield_t = None,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             mode_margin: int = 2,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             ) -> Tuple[vfield_t, complex]:
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    """
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Given a 2d region, attempts to solve for the eigenmode with the specified mode number.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2017-09-24 22:28:08 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    :param mode_number: Number of the mode, 0-indexed.
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param omega: Angular frequency of the simulation
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-04 13:48:41 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    :param dxes: Grid parameters [dx_e, dx_h] as described in meanas.types
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param epsilon: Dielectric constant
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param mu: Magnetic permeability (default 1 everywhere)
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-26 00:25:36 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    :param mode_margin: The eigensolver will actually solve for (mode_number + mode_margin)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        modes, but only return the target mode. Increasing this value can improve the solver's
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ability to find the correct mode. Default 2.
							 | 
						
					
						
							
								
									
										
										
										
											2019-09-05 22:38:29 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    :return: (e_xy, wavenumber)
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    """
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Solve for the largest-magnitude eigenvalue of the real operator
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    dxes_real = [[numpy.real(dx) for dx in dxi] for dxi in dxes]
							 | 
						
					
						
							
								
									
										
										
										
											2019-09-05 22:38:29 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    A_r = waveguide.operator_e(numpy.real(omega), dxes_real, numpy.real(epsilon), numpy.real(mu))
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-26 00:25:36 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    eigvals, eigvecs = signed_eigensolve(A_r, mode_number + mode_margin)
							 | 
						
					
						
							
								
									
										
										
										
											2019-09-05 22:38:29 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    e_xy = eigvecs[:, -(mode_number + 1)]
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Now solve for the eigenvector of the full operator, using the real operator's
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								     eigenvector as an initial guess for Rayleigh quotient iteration.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							
								
									
										
										
										
											2019-09-05 22:38:29 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    A = waveguide.operator_e(omega, dxes, epsilon, mu)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    eigval, e_xy = rayleigh_quotient_iteration(A, e_xy)
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # Calculate the wave-vector (force the real part to be positive)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    wavenumber = numpy.sqrt(eigval)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    wavenumber *= numpy.sign(numpy.real(wavenumber))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-09-05 22:38:29 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    return e_xy, wavenumber
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								def solve_waveguide_mode(mode_number: int,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         omega: complex,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         dxes: dx_lists_t,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         axis: int,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         polarity: int,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         slices: List[slice],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         epsilon: field_t,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         mu: field_t = None,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         ) -> Dict[str, complex or numpy.ndarray]:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    """
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Given a 3D grid, selects a slice from the grid and attempts to
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								     solve for an eigenmode propagating through that slice.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param mode_number: Number of the mode, 0-indexed
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param omega: Angular frequency of the simulation
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-04 13:48:41 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    :param dxes: Grid parameters [dx_e, dx_h] as described in meanas.types
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param axis: Propagation axis (0=x, 1=y, 2=z)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param polarity: Propagation direction (+1 for +ve, -1 for -ve)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param slices: epsilon[tuple(slices)] is used to select the portion of the grid to use
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        as the waveguide cross-section. slices[axis] should select only one
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param epsilon: Dielectric constant
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param mu: Magnetic permeability (default 1 everywhere)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :return: {'E': List[numpy.ndarray], 'H': List[numpy.ndarray], 'wavenumber': complex}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    """
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    if mu is None:
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-01 23:48:25 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        mu = numpy.ones_like(epsilon)
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-07-09 20:11:32 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    slices = tuple(slices)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Solve the 2D problem in the specified plane
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # Define rotation to set z as propagation direction
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    order = numpy.roll(range(3), 2 - axis)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    reverse_order = numpy.roll(range(3), axis - 2)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-07 01:00:21 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # Find dx in propagation direction
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    dxab_forward = numpy.array([dx[order[2]][slices[order[2]]] for dx in dxes])
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    dx_prop = 0.5 * sum(dxab_forward)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # Reduce to 2D and solve the 2D problem
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    args_2d = {
							 | 
						
					
						
							
								
									
										
										
										
											2019-09-05 22:38:29 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        'omega': omega,
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        'dxes': [[dx[i][slices[i]] for i in order[:2]] for dx in dxes],
							 | 
						
					
						
							
								
									
										
										
										
											2019-09-05 22:38:29 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        'epsilon': vec([epsilon[i][slices].transpose(order) for i in order]),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        'mu': vec([mu[i][slices].transpose(order) for i in order]),
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    }
							 | 
						
					
						
							
								
									
										
										
										
											2019-09-05 22:38:29 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    e_xy, wavenumber_2d = vsolve_waveguide_mode_2d(mode_number, **args_2d)
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Apply corrections and expand to 3D
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-26 00:26:54 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # Correct wavenumber to account for numerical dispersion.
							 | 
						
					
						
							
								
									
										
										
										
											2019-09-05 22:38:29 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    wavenumber = 2/dx_prop * numpy.arcsin(wavenumber_2d * dx_prop/2)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    print(wavenumber_2d / wavenumber)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    shape = [d.size for d in args_2d['dxes'][0]]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ve, vh = waveguide.normalized_fields_e(e_xy, wavenumber=wavenumber_2d, **args_2d, prop_phase=dx_prop * wavenumber)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    e = unvec(ve, shape)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    h = unvec(vh, shape)
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-26 00:26:54 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # Adjust for propagation direction
							 | 
						
					
						
							
								
									
										
										
										
											2019-09-05 22:38:29 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    h *= polarity
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # Apply phase shift to H-field
							 | 
						
					
						
							
								
									
										
										
										
											2019-09-05 22:38:29 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    h[:2] *= numpy.exp(-1j * polarity * 0.5 * wavenumber * dx_prop)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    e[2]  *= numpy.exp(-1j * polarity * 0.5 * wavenumber * dx_prop)
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # Expand E, H to full epsilon space we were given
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-01 23:48:25 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    E = numpy.zeros_like(epsilon, dtype=complex)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    H = numpy.zeros_like(epsilon, dtype=complex)
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    for a, o in enumerate(reverse_order):
							 | 
						
					
						
							
								
									
										
										
										
											2019-09-05 22:38:29 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        E[(a, *slices)] = e[o][:, :, None].transpose(reverse_order)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        H[(a, *slices)] = h[o][:, :, None].transpose(reverse_order)
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    results = {
							 | 
						
					
						
							
								
									
										
										
										
											2019-09-05 22:38:29 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        'wavenumber': wavenumber,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        'wavenumber_2d': wavenumber_2d,
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        'H': H,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        'E': E,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    return results
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								def compute_source(E: field_t,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                   wavenumber: complex,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                   omega: complex,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                   dxes: dx_lists_t,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                   axis: int,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                   polarity: int,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                   slices: List[slice],
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-26 01:03:13 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                   epsilon: field_t,
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                   mu: field_t = None,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                   ) -> field_t:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    """
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Given an eigenmode obtained by solve_waveguide_mode, returns the current source distribution
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    necessary to position a unidirectional source at the slice location.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param E: E-field of the mode
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param wavenumber: Wavenumber of the mode
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param omega: Angular frequency of the simulation
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-04 13:48:41 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    :param dxes: Grid parameters [dx_e, dx_h] as described in meanas.types
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param axis: Propagation axis (0=x, 1=y, 2=z)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param polarity: Propagation direction (+1 for +ve, -1 for -ve)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param slices: epsilon[tuple(slices)] is used to select the portion of the grid to use
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        as the waveguide cross-section. slices[axis] should select only one
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param mu: Magnetic permeability (default 1 everywhere)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :return: J distribution for the unidirectional source
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    """
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-26 01:03:13 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    E_expanded = expand_wgmode_e(E=E, dxes=dxes, wavenumber=wavenumber, axis=axis,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                 polarity=polarity, slices=slices)
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-07 01:01:55 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-26 01:03:13 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    smask = [slice(None)] * 4
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    if polarity > 0:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        smask[axis + 1] = slice(slices[axis].start, None)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        smask[axis + 1] = slice(None, slices[axis].stop)
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-26 01:03:13 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    mask = numpy.zeros_like(E_expanded, dtype=int)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    mask[tuple(smask)] = 1
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-26 01:03:13 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    masked_e2j = operators.e_boundary_source(mask=vec(mask), omega=omega, dxes=dxes, epsilon=vec(epsilon), mu=vec(mu))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    J = unvec(masked_e2j @ vec(E_expanded), E.shape[1:])
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    return J
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								def compute_overlap_e(E: field_t,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                      wavenumber: complex,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                      dxes: dx_lists_t,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                      axis: int,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                      polarity: int,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                      slices: List[slice],
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-30 22:03:54 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                      ) -> field_t:                 # TODO DOCS
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    """
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Given an eigenmode obtained by solve_waveguide_mode, calculates overlap_e for the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    mode orthogonality relation Integrate(((E x H_mode) + (E_mode x H)) dot dn)
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-30 22:03:54 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    [assumes reflection symmetry].i
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    overlap_e makes use of the e2h operator to collapse the above expression into
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								     (vec(E) @ vec(overlap_e)), allowing for simple calculation of the mode overlap.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param E: E-field of the mode
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param H: H-field of the mode (advanced by half of a Yee cell from E)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param wavenumber: Wavenumber of the mode
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param omega: Angular frequency of the simulation
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-04 13:48:41 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    :param dxes: Grid parameters [dx_e, dx_h] as described in meanas.types
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param axis: Propagation axis (0=x, 1=y, 2=z)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param polarity: Propagation direction (+1 for +ve, -1 for -ve)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param slices: epsilon[tuple(slices)] is used to select the portion of the grid to use
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        as the waveguide cross-section. slices[axis] should select only one
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param mu: Magnetic permeability (default 1 everywhere)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :return: overlap_e for calculating the mode overlap
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    """
							 | 
						
					
						
							
								
									
										
										
										
											2019-07-09 20:12:03 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    slices = tuple(slices)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-30 22:03:54 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Ee = expand_wgmode_e(E=E, wavenumber=wavenumber, dxes=dxes,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         axis=axis, polarity=polarity, slices=slices)
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-30 22:03:54 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    start, stop = sorted((slices[axis].start, slices[axis].start - 2 * polarity))
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-30 22:03:54 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    slices2 = list(slices)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    slices2[axis] = slice(start, stop)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    slices2 = (slice(None), *slices2)
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-30 22:03:54 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Etgt = numpy.zeros_like(Ee)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Etgt[slices2] = Ee[slices2]
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-30 22:30:45 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-30 22:03:54 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Etgt /= (Etgt.conj() * Etgt).sum()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    return Etgt.conj()
							 | 
						
					
						
							
								
									
										
										
										
											2017-09-24 22:28:39 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								def solve_waveguide_mode_cylindrical(mode_number: int,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                     omega: complex,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                     dxes: dx_lists_t,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                     epsilon: vfield_t,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                     r0: float,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                     ) -> Dict[str, complex or field_t]:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    """
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-05 00:20:06 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    TODO: fixup
							 | 
						
					
						
							
								
									
										
										
										
											2017-09-24 22:28:39 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Given a 2d (r, y) slice of epsilon, attempts to solve for the eigenmode
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								     of the bent waveguide with the specified mode number.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param mode_number: Number of the mode, 0-indexed
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param omega: Angular frequency of the simulation
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-04 13:48:41 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    :param dxes: Grid parameters [dx_e, dx_h] as described in meanas.types.
							 | 
						
					
						
							
								
									
										
										
										
											2017-09-24 22:28:39 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        The first coordinate is assumed to be r, the second is y.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param epsilon: Dielectric constant
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :param r0: Radius of curvature for the simulation. This should be the minimum value of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        r within the simulation domain.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    :return: {'E': List[numpy.ndarray], 'H': List[numpy.ndarray], 'wavenumber': complex}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    """
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Solve for the largest-magnitude eigenvalue of the real operator
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    dxes_real = [[numpy.real(dx) for dx in dxi] for dxi in dxes]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    A_r = waveguide.cylindrical_operator(numpy.real(omega), dxes_real, numpy.real(epsilon), r0)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    eigvals, eigvecs = signed_eigensolve(A_r, mode_number + 3)
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-27 00:40:49 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    e_xy = eigvecs[:, -(mode_number+1)]
							 | 
						
					
						
							
								
									
										
										
										
											2017-09-24 22:28:39 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Now solve for the eigenvector of the full operator, using the real operator's
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								     eigenvector as an initial guess for Rayleigh quotient iteration.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    A = waveguide.cylindrical_operator(omega, dxes, epsilon, r0)
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-27 00:40:49 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    eigval, e_xy = rayleigh_quotient_iteration(A, e_xy)
							 | 
						
					
						
							
								
									
										
										
										
											2017-09-24 22:28:39 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # Calculate the wave-vector (force the real part to be positive)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    wavenumber = numpy.sqrt(eigval)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    wavenumber *= numpy.sign(numpy.real(wavenumber))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-05 00:20:06 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # TODO: Perform correction on wavenumber to account for numerical dispersion.
							 | 
						
					
						
							
								
									
										
										
										
											2017-09-24 22:28:39 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    shape = [d.size for d in dxes[0]]
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-27 00:40:49 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    e_xy = numpy.hstack((e_xy, numpy.zeros(shape[0] * shape[1])))
							 | 
						
					
						
							
								
									
										
										
										
											2017-09-24 22:28:39 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    fields = {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        'wavenumber': wavenumber,
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-27 00:40:49 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        'E': unvec(e_xy, shape),
							 | 
						
					
						
							
								
									
										
										
										
											2017-09-24 22:28:39 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								#        'E': unvec(e, shape),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#        'H': unvec(h, shape),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    return fields
							 | 
						
					
						
							
								
									
										
										
										
											2019-07-09 20:13:31 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								def expand_wgmode_e(E: field_t,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    wavenumber: complex,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    dxes: dx_lists_t,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    axis: int,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    polarity: int,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    slices: List[slice],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    ) -> field_t:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    slices = tuple(slices)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # Determine phase factors for parallel slices
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    a_shape = numpy.roll([1, -1, 1, 1], axis)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    a_E = numpy.real(dxes[0][axis]).cumsum()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    r_E = a_E - a_E[slices[axis]]
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-26 00:28:19 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    iphi = polarity * -1j * wavenumber
							 | 
						
					
						
							
								
									
										
										
										
											2019-07-09 20:13:31 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    phase_E = numpy.exp(iphi * r_E).reshape(a_shape)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # Expand our slice to the entire grid using the phase factors
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-07 01:00:57 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    E_expanded = numpy.zeros_like(E)
							 | 
						
					
						
							
								
									
										
										
										
											2019-07-09 20:13:31 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    slices_exp = list(slices)
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-01 23:48:25 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    slices_exp[axis] = slice(E.shape[axis + 1])
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    slices_exp = (slice(None), *slices_exp)
							 | 
						
					
						
							
								
									
										
										
										
											2019-07-09 20:13:31 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-07 01:00:57 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    slices_in = (slice(None), *slices)
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-01 23:17:13 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-07 01:00:57 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    E_expanded[slices_exp] = phase_E * numpy.array(E)[slices_in]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    return E_expanded
							 | 
						
					
						
							
								
									
										
										
										
											2019-07-09 20:13:31 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 |