Basics#
In this chapter, we’ll explore how to use femwell for more accurate waveguide modeling. Unlike simpler analytical models, FEMWELL allows us to solve Maxwell’s equations directly on the waveguide geometry.
Using femwell, you can mesh any component cross-section and solve PDEs with its powerful mode solver. Unlike other solvers that rely on predefined geometries, femwell works directly with the actual component geometry. You can compute the modes of a GDSFactory cross-section, which internally defines a “uz” mesh perpendicular to a straight component using the provided cross-section.
import all the necessary packages:
import doModels.RefractiveIndex as ri
from doModels import fem, PhotonicStack
import matplotlib.pyplot as plt
import numpy as np
Define photonic stack:
stack = PhotonicStack.create(
total_film_thickness=0.210,
etch_depth=0.210,
top_width=0.450,
side_wall_angle=0,
top_oxide_thickness=2.0,
bottom_oxide_thickness=2.0,
)
Mesh the geometry and visualize the stack
m = fem.mesh_waveguide(total_film_thickness=stack.total_film_thickness.target,
etch_depth=stack.etch_depth.target,
top_width=stack.top_width.target,
side_wall_angle=stack.side_wall_angle.target,
buffer_size=1.0,
core_resolution=0.04,
core_distance=1,
default_resolution_max=0.6,
show_plot=True)


Run the FEM
wavelength = 1.55
core_index = ri.silicon(wavelength)
box_index = ri.silica(wavelength)
clad_index = ri.silica(wavelength)
modes = fem.fem_waveguide(mesh=m, n_core=ri.silicon, n_clad=ri.silica, n_box=ri.silica, wavelength=wavelength, num_modes=4)
Visualize
for mode in modes:
tem = "TE" if mode.te_fraction > 0.5 else "TM"
if tem == "TE":
_, ax = plt.subplots(figsize=(5, 4))
mode.plot_intensity(ax=ax, normalize=False)
ax.set_title(f"neff={mode.n_eff.real:.4f} ({tem})")
ax.set_xlim(-1.5*stack.top_width.target, 1.5*stack.top_width.target)
ax.set_ylim(-1.5*stack.top_width.target, 1.5*stack.top_width.target)
else:
_, ax = plt.subplots(figsize=(5, 4))
mode.plot_intensity(ax=ax, normalize=False)
ax.set_title(f"neff={mode.n_eff.real:.4f} ({tem})")
ax.set_xlim(-1.5*stack.top_width.target, 1.5*stack.top_width.target)
ax.set_ylim(-1.5*stack.top_width.target, 1.5*stack.top_width.target)
plt.show()



