# Eigenmode Source

This example demonstrates using the `EigenModeSource`

to couple exclusively to a *single* waveguide mode. The structure, shown in the schematic below, is a 2d dielectric waveguide with ε=12, width =1 μm, and out-of-plane electric field E_{z}. The dispersion relation ω(k) for index-guided modes with *even* mirror symmetry in the y-direction is computed using MPB and shown in blue. The light cone which denotes radiative modes is the green section. Using this waveguide configuration, we will investigate two different frequency regimes: (1) single mode (normalized frequency of 0.15) and (2) multi mode (normalized frequency of 0.35), both shown as dotted lines in the figure. We will use the eigenmode source to excite a specific mode in each case — labeled **A** and **B** in the band diagram — and compare the results to using a constant-amplitude source for straight and rotated waveguides. Finally, we will demonstrate that a monitor plane in the y-direction is sufficient for computing the Poynting flux in a waveguide with arbitrary orientation.

The simulation script is in examples/oblique-source.py.

The simulation consists of two parts: (1) computing the flux, and (2) plotting the field profile. The field profile is generated via `compute_flux=False`

. For the single-mode case, a constant-amplitude current source (`eig_src=False`

) excites both the waveguide mode and radiating fields in both directions. This is shown in the main inset of the figure above. The `EigenModeSource`

excites only the right-going waveguide mode **A** as shown in the smaller inset. Exciting this mode requires setting `eig_src=True`

, `fsrc=0.15`

, `kx=0.4`

, and `bnum=1`

. Note that `EigenModeSource`

is a line centered at the origin extending the length of the entire cell. The constant-amplitude source is a line that is slightly larger than the waveguide width. The parameter `rot_angle`

specifies the rotation angle of the waveguide axis and is initially 0 (i.e., straight or horizontal orientation). This enables `eig_parity`

to include `EVEN_Y`

in addition to `ODD_Z`

and the cell to include a mirror symmetry plane in the y-direction.

For the multi-mode case, a constant-amplitude current source excites a superposition of the two waveguide modes in addition to the radiating field. This is again shown in the main inset of the figure above. The `EigenModeSource`

excites only a given mode: **A** (`fsrc=0.35`

, `kx=0.4`

, `bnum=2`

) or **B** (`fsrc=0.35`

, `kx=1.2`

, `bnum=1`

) as shown in the smaller insets.

```
import meep as mp
import numpy as np
resolution = 50 # pixels/μm
cell_size = mp.Vector3(14,14,0)
pml_layers = [mp.PML(thickness=2)]
rot_angle = np.radians(0) # rotation angle (in degrees) of waveguide, CCW around z-axis
geometry = [mp.Block(center=mp.Vector3(),
size=mp.Vector3(mp.inf,1,mp.inf),
e1=mp.Vector3(1,0,0).rotate(mp.Vector3(0,0,1), rot_angle),
e2=mp.Vector3(0,1,0).rotate(mp.Vector3(0,0,1), rot_angle),
material=mp.Medium(epsilon=12))]
fsrc = 0.15 # frequency of eigenmode or constant-amplitude source
kx = 0.4 # initial guess for wavevector in x-direction of eigenmode
bnum = 1 # band number of eigenmode
compute_flux = True # compute flux (True) or plot the field profile (False)
eig_src = True # eigenmode (True) or constant-amplitude (False) source
if eig_src:
sources = [mp.EigenModeSource(src=mp.GaussianSource(fsrc,fwidth=0.1*fsrc) if compute_flux else mp.ContinuousSource(fsrc),
center=mp.Vector3(),
size=mp.Vector3(y=14),
direction=mp.AUTOMATIC if rot_angle == 0 else mp.NO_DIRECTION,
eig_kpoint=mp.Vector3(kx,0,0).rotate(mp.Vector3(0,0,1), rot_angle),
eig_band=bnum,
eig_parity=mp.EVEN_Y+mp.ODD_Z if rot_angle == 0 else mp.ODD_Z,
eig_match_freq=True)]
else:
sources = [mp.Source(src=mp.GaussianSource(fsrc,fwidth=0.1*fsrc) if compute_flux else mp.ContinuousSource(fsrc),
center=mp.Vector3(),
size=mp.Vector3(y=2),
component=mp.Ez)]
sim = mp.Simulation(cell_size=cell_size,
resolution=resolution,
boundary_layers=pml_layers,
sources=sources,
geometry=geometry,
symmetries=[mp.Mirror(mp.Y)] if rot_angle == 0 else [])
if compute_flux:
tran = sim.add_flux(fsrc, 0, 1, mp.FluxRegion(center=mp.Vector3(x=5), size=mp.Vector3(y=14)))
sim.run(until_after_sources=50)
print("flux:, {:.6f}".format(mp.get_fluxes(tran)[0]))
else:
sim.run(until=100)
nonpml_vol = mp.Volume(center=mp.Vector3(), size=mp.Vector3(10,10,0))
eps_data = sim.get_array(vol=nonpml_vol, component=mp.Dielectric)
ez_data = sim.get_array(vol=nonpml_vol, component=mp.Ez)
import matplotlib.pyplot as plt
plt.figure()
plt.imshow(np.flipud(np.transpose(eps_data)), interpolation='spline36', cmap='binary')
plt.imshow(np.flipud(np.transpose(ez_data)), interpolation='spline36', cmap='RdBu', alpha=0.9)
plt.axis('off')
plt.show()
```

Note that in the eigenmode source, `direction`

must be set to `NO_DIRECTION`

for a non-zero `eig_kpoint`

which specifies the waveguide axis.

Additionally, we can demonstrate the eigenmode source for a rotated waveguide. The results are shown in the two figures below for the single- and multi-mode case. There is one subtlety: for mode **A** in the multi-mode case, the `bnum`

parameter is set to 3 rather than 2. This is because a non-zero rotation angle breaks the symmetry in the y-direction which therefore precludes the use of `EVEN_Y`

in `eig_parity`

. Without any parity specified for the y-direction, the second band corresponds to *odd* modes. This is why we must select the third band which contains even modes. An oblique waveguide also leads to a breakdown in the PML. A simple workaround for mitigating reflections from the boundary layers is to increase its length: the PML length has been doubled from 1 to 2.

There are numerical dispersion artifacts due to the FDTD spatial and temporal discretizations which create negligible backwards (leftward-propagating) wave artifacts by the eigenmode current source, carrying approximately 10^{-5} of the power of the desired rightward-propagating mode. These can be seen as artifacts in the field profiles.

Finally, we demonstrate that the power flux through a waveguide with an *arbitrary* orientation can be computed by a single flux plane oriented along the y direction: thanks to Poynting's theorem, the flux through any plane crossing a lossless waveguide is the same, regardless of whether the plane is oriented perpendicular to the waveguide. Furthermore, the eigenmode source is normalized in such a way as to produce the same power regardless of the waveguide orientation — in consequence, the flux values for mode **A** of the single-mode case for rotation angles of 0°, 20°, and 40° are 77.000266, 76.879339, and 76.817850, within 0.2% (discretization error) of one another.