Finite-element mode solver#

You can mesh any waveguide cross-section and solve for the optical modes using femwell.

This example defines a simple strip waveguide geometry using shapely, meshes it with femwell, and computes and visualizes the guided modes.

from collections import OrderedDict

import numpy as np
from femwell.maxwell.waveguide import compute_modes
from femwell.mesh import mesh_from_OrderedDict
from shapely.geometry import box
from shapely.ops import clip_by_rect
from skfem import Basis, ElementTriP0
from skfem.io.meshio import from_meshio

Define waveguide geometry#

We describe the cross-section geometry using shapely. A strip waveguide is a rectangular core sitting on a box (substrate), surrounded by cladding.

wavelength = 1.55
wg_width = 1.0
wg_thickness = 0.22

core_index = 3.45
clad_index = 1.444
box_index = 1.444

core = box(-wg_width / 2, 0, wg_width / 2, wg_thickness)
polygons = OrderedDict(
    core=core,
    box=clip_by_rect(core.buffer(3.0, resolution=4), -np.inf, -np.inf, np.inf, 0),
    clad=clip_by_rect(core.buffer(3.0, resolution=4), -np.inf, 0, np.inf, np.inf),
)

resolutions = {"core": {"resolution": 0.02, "distance": 2}}

Generate mesh#

mesh = from_meshio(
    mesh_from_OrderedDict(
        polygons, resolutions, default_resolution_max=0.5, filename="mesh.msh"
    )
)
mesh.draw().show()
../_images/a74d6c5dc133a81cfa49ab8d430b4f4a6f882523f578f4c1da91eb42fe34a890.png

Assign material values#

basis0 = Basis(mesh, ElementTriP0())
epsilon = basis0.zeros()
for subdomain, n in {"core": core_index, "box": box_index, "clad": clad_index}.items():
    epsilon[basis0.get_dofs(elements=subdomain)] = n**2
basis0.plot(epsilon, colorbar=True).show()
../_images/e502e7cacc01ef87edd2eaa7ea411cfa2f1aaab3a54ca915704b6f5fdfa3efec.png

Solve for modes#

modes = compute_modes(basis0, epsilon, wavelength=wavelength, num_modes=2, order=1)

Inspect modes#

You can use these as inputs to other femwell mode solver functions to inspect or analyze the modes.

print(f"Mode 0 TE fraction: {modes[0].te_fraction:.4f}")
print(f"Mode 1 TE fraction: {modes[1].te_fraction:.4f}")
Mode 0 TE fraction: 0.9978
Mode 1 TE fraction: 0.9874

Plot electric field#

modes[0].show("E", part="real")
../_images/0111e9ae24c21dd48f28bdaf3fc89877383a500d3ac31dcd2436dc91029140a4.png
modes[0].plot_component("E", component="x", part="real", colorbar=True)
<Axes: title={'center': 'Ex (real. part)'}>
../_images/1bccb3ccfebe36895dd5feda2e6e3f6014f9f9944ec4e4458c8f4358bc2959fd.png
modes[1].plot_component("E", component="x", part="real", colorbar=True)
<Axes: title={'center': 'Ex (real. part)'}>
../_images/bfb5408b4b23756953e68187e58bc1873e94b9d36dd409c56b3b465adabfb748.png
modes[1].show("E", part="real")
../_images/c35d4fb112bedd8bcc0f85ed62250729ac211f0accea7f194425c49db3e410e3.png