In this lecture, we show how to perfectly inject a specific mode into a straight waveguide. This is helpful in decreasing computational cost, and having a clean simulation without unwanted electromagnetic interference in the computational domain.
- Describe how to use the eigenmode solver to solve for guided modes.
- Describe how to setup mode sources to selectively excite the target mode along a specific propagating direction.
- As a comparison, we also illustrate the field profile when excited by a dipole source.
In this tutorial, we illustrate the usage and the importance of mode sources in integrated photonics simulations.
# standard python imports
import numpy as np
import matplotlib.pyplot as plt
import tidy3d as td
from tidy3d.plugins.mode import ModeSolver
from tidy3d import web
We will do a simulation of a straight waveguide, using a silicon ridge waveguide on a silicon oxide substrate. We begin by defining some general parameters.
# Unit length is micron.
wg_height = 0.25
wg_width = 0.5
# Permittivity of waveguide and substrate
si_eps = 3.48**2
sio_eps = 1.45**2
# Free-space wavelength (in um) and frequency (in Hz)
lambda0 = 1.55
freq0 = td.C_0/lambda0
fwidth = freq0/10
# Simulation size inside the PML along propagation direction
sim_length = 20 #um
# space between waveguide and PML
spacing = 1.5 #um
# Simulation domain size and total run time
sim_size = [sim_length, wg_width + spacing * 2, wg_height + spacing * 2]
run_time = 20/fwidth
# Grid specification
grid_spec = td.GridSpec.auto(min_steps_per_wvl=20, wavelength=lambda0)
# monitor and modal plane size
sz_plane = 2 #um
# Modal source position (x coordinate)
src_pos = -sim_size[0]/2 + spacing
Now we set up almost everything (structures, monitors, simulation) to run the example. Sources will be set up in the next section.
First, we define the substrate and the waveguide. Note that they both need to be extended into the PML layers. In tidy3d
, the PML layers extend beyond the simulation domain (more details on setting up PML layers can be found here). So when defining the substrate and the waveguide, it is best to extend them well beyond the simulation domain size to make sure they truly extend into the PML layers.
# Waveguide and substrate materials
mat_wg = td.Medium(permittivity=si_eps, name='silicon')
mat_sub = td.Medium(permittivity=sio_eps, name='silica')
# Substrate
substrate = td.Structure(
geometry=td.Box(
center=[0, 0, -sim_size[2]],
size=[td.inf, td.inf, 2*sim_size[2]-wg_height],
),
medium=mat_sub,
name='substrate',
)
# Waveguide
waveguide = td.Structure(
geometry=td.Box(
center=[0, 0, 0],
size=[td.inf, wg_width, wg_height],
),
medium=mat_wg,
name='waveguide',
)
Next, we define two types of monitors:
FieldMonitor
to visualize the fields in xy plane at central frequency;FluxMonitor
to measure the flux as a function of distance away from the source.mnt_list = []
# xy-plane frequency-domain field monitor at central frequency
freq_mnt = td.FieldMonitor(
center=[0, 0, 0],
size=[np.inf, np.inf, 0],
freqs=[freq0],
name='field')
mnt_list.append(freq_mnt)
# A series of flux monitors
offset_from_source = 0.05 # the space between the 1st monitor and the source
pos_start = src_pos + offset_from_source # define the positions of the monitor
pos_end = sim_size[0]/2-spacing
num = 100
pos_list = np.linspace(pos_start,pos_end,num)
for i in range(num):
flux_mnt = td.FluxMonitor(
center= [pos_list[i], 0, 0],
size=[0, sz_plane, sz_plane],
freqs=[freq0],
name='flux'+str(i),
)
mnt_list.append(flux_mnt)
Now it is time to define the simulation object.
# Simulation
sim = td.Simulation(
size=sim_size,
grid_spec=grid_spec,
structures=[substrate, waveguide],
sources=[],
monitors=mnt_list,
run_time=run_time,
boundary_spec=td.BoundarySpec.all_sides(boundary=td.PML()))
Note: Tidy3D is warning us that our Simulation does not contain sources. In this case, since we are using the simulation as a demonstration and are not running any simulations, we may safely ignore this error.
In this waveguide example, we are interested in exciting a selected mode. This can be achieved with our in-built Mode Source
feature (Detals can be found here). The procedue is as follows,
n
, such that the modes that are fully below light-line (if any) should appear first.# position and size of source plane
src_plane = td.Box(center=[src_pos, 0, 0], size=[0, sz_plane, sz_plane])
# number of modes to compute
num_modes = 2
# setup and solve for modes
mode_spec = td.ModeSpec(num_modes=num_modes)
ms = ModeSolver(simulation=sim, plane=src_plane, mode_spec=mode_spec, freqs=[freq0])
modes = ms.solve()
print("Effective index of computed modes: ", np.array(modes.n_eff))
Effective index of computed modes: [[2.566749 2.0084913]]
fig, axs = plt.subplots(num_modes, 2, figsize=(10, 8), tight_layout=True)
for mode_ind in range(num_modes):
ms.plot_field("Ey", "real", f=freq0, mode_index=mode_ind, ax=axs[mode_ind, 0])
ms.plot_field("Ez", "real", f=freq0, mode_index=mode_ind, ax=axs[mode_ind, 1])
plt.show()
source_time = td.GaussianPulse(freq0=freq0, fwidth=fwidth)
mode_source = ms.to_source(mode_index=0, direction="+", source_time=source_time)
sim = sim.copy(update={'sources':[mode_source]})
As a comparison, here we setup another simulation whose source is simply a dipole source of the same polarization as the TE mode. We place the dipole source off the symmetry plane, since in general the waveguide might not have a symmetry plane.
point_source = td.PointDipole(
center=(src_pos, wg_width/4, wg_height/4),
source_time=source_time,
polarization='Ey',
name='point source',
)
sim_point = sim.copy(update={'sources':[point_source]})
Let's visualize the simulation with the modal source or the point source.
fig, ax = plt.subplots(1, 2, tight_layout=True, figsize=(8, 4))
sim.plot(x=src_pos, ax=ax[0]);
sim_point.plot(x=src_pos, ax=ax[1]);
plt.show()
We will submit the simulation to run as a new project.
sim_data = web.run(sim, task_name='lecture04_mode_source', path=f'data/data_mode.hdf5')
sim_point_data = web.run(sim_point, task_name='lecture04_point_source', path=f'data/data_point.hdf5')
Once the simulation has completed, we can download the results and load them into the simulation object.
Now, Let's visulize the field xy plane at the central frequency
fig, ax = plt.subplots(1,2,figsize=(12, 3), tight_layout=True)
sim_data.plot_field('field', 'Ey', z=0, f=freq0, val='real', ax = ax[0])
sim_point_data.plot_field('field', 'Ey', z=0, f=freq0, val='real', ax = ax[1])
ax[0].set_xlim([-10,0])
ax[1].set_xlim([-10,0])
plt.show()
The field excited by the modal source (left figure) shows sigle mode features; while the one by the point dipole (right figure) leaks to the free space. To quantatatively illustrate that, we plot the flux as a function of distance away from the source:
flux_list = np.zeros_like(pos_list)
flux_point_list = np.zeros_like(pos_list)
for i in range(num):
flux_list[i] = sim_data['flux'+str(i)].flux
flux_point_list[i] = sim_point_data['flux'+str(i)].flux
# normalize the dipole one
flux_point_list /= flux_point_list[0]
fig, ax = plt.subplots(1,figsize=(5, 4), tight_layout=True)
ax.plot(pos_list - src_pos, flux_list, '-r',label='Modal source')
ax.plot(pos_list - src_pos, flux_point_list, '--k', label='Point source')
ax.set_xlabel('Distance to the source')
ax.set_ylabel('Flux')
ax.legend()
plt.show()
FDTD 101: Lecture 4
This is another video for introduction to the finite difference time domain (FDTD) method. I'm Shanhui Fan from Flexcompute.
Today we're going to talk about using the FDTD method in the context of integrated photonics applications. This device is called the Mach-Zehnder interferometer. What you see here is a top view of the device. The red regions here correspond to a silicon waveguide sitting on a silicon dioxide substrate. The other side of the waveguide is air. This device is used as an optical switch. Suppose you change the refractive index of silicon a little bit in this region as indicated as phase shifter, you may switch input light to either the bottom or the top waveguide. This device operates as an optical switch. It is very important for a wide range of integrated photonic applications. For example, it is used both for quantum computing as well as for neuropathic optical computing. I'm going to show you some of the considerations in simulating this waveguide.
The first thing we’d like to talk about is to effectively inject the mode into the waveguide. We take a straight single waveguide as an example to illustrate the process. What we like to do is to inject a single mode into this waveguide. We would like to set up the simulation so that it excites a single mode that perfectly propagates down the waveguide.
Now for this purpose, we set up the computational cell as usual. We surround the waveguide with the perfectly matched layer boundary so that a wave propagation away from the computation domain is absorbed. To perfectly absorb a waveguide mode. It is important to extend both the waveguide and the substrate into the PML region.
The other important consideration is to use what's called the modal source. To get a clean simulation, it will be very advantageous to use an eigenmode source defined on the plane to inject the specific mode along the forward direction.
For a waveguide that looks like this you can use an eigen solver to solve for the guided mode of the waveguide. It has a fundamental mode with the electric field along the y direction and this is the mode that we would like to excite but it has other higher order modes as well. Using the modal source computed by the eigenmode solver, one can set the modal source in FDTD to selectively excite one of these modes. For example, to selectively excite the first order mode.
Here is a cross-sectional view through the center of the waveguide. The green line here corresponds to the position of the model source, and you can see that the use of modal source perfectly generates the key mode. One interesting aspect is that the modal source actually allows you to do directional excitation. You can see that the field is perfectly launched to the right of the source and there's zero field to the left of the source. Now you can contrast the behavior of the modal source with that of a dipole source. If you just put a dipole into the waveguide, well, you see quite a bit different in the field distribution. First of all, the dipole source is not directional launching. It launches waves in both directions. The second is that the polarization of the dipole is set to selectively excite a TE mode. But it takes some propagation distance before the mode settles into a perfect TE mode profile. During this process, there is radiation into the substrate.
To further illustrate the difference between the modal source and the point dipole source, we can perform a simulation where we compute the flux going through a flux plane perpendicular to the waveguide centered at the center of the waveguide. What we plot here is the flux as a function of distance of the flux point from the source. In the case of a modal source because we launch a single waveguide mode perfectly the flux basically remains the same as the propagation distance changes. Whereas if you put a point dipole source, the flux initially decays because the dipole is not perfectly matched with the mode. There is some radiation going out. And then after some propagation distance, the flux settles as the mode settles into the desired mode. In this process, there is radiation into the computational domain and that's a source of unwanted electromagnetic interference inside the computation domain. If you like to get a high-quality calculation of the behavior of the waveguide system, it would be better to use the modal source so that you don't have such radiation.
Let's come back to the simulation of a Mach-Zehnder. The movies that I'm playing here correspond to the case where the refractive index of the phase shifter is chosen so that the wave is perfectly launched or perfectly routed to the top waveguide. And in this case, you can see that a wave is very well confined in the waveguide. There's very little outside the waveguide. The field of the output retains essentially a perfectly single mode profile. This characteristic is the sign of the waveguide device that is very well designed. It is also a sign that the setup of the simulation is done correctly so that you don't have unwanted electromagnetic interference. Now to demonstrate a switch behavior, you can change the dielectric function of the phase shifter. As the wave goes through the device, it's perfectly routed but now to the bottom waveguide. The system will behave as an excellent optical switch.