Bend Mode Solvers

The SiN bend of Bending: SiN solved with the bend in cylindrical coordinates (bend_method='cylindrical', grid coordinate transformation) and by transformation optics (bend_method='TO', material transformed by the bend’s conformal map), to compare how fast each converges. The FDM is solved on four grids and the FEM on six fixed meshes (fem_max_refinements=0), and each solve’s effective index and bend loss are compared against the finest FEM mesh.

The window and PMLs are optimized by convergence studies run separately. The bend radiates outward, so PMLs on the outer (east), top and bottom walls absorb the radiated light, and the guided mode’s imaginary index is its bend loss. The FEM’s PML absorbs fully in 500 nm, where the FDM’s needs 1 µm. max_effective_index sits just above the guided mode, so the one mode solved is the guided mode rather than a PML mode. A fine mesh in the core (the shape’s fem_resolution) lets the FEM resolve the mode even at 1 point per wavelength, so its first solve uses a 100 nm core mesh and the rest 50 nm.

The FEM is the best method all-around, but it requires EMode3D. Even its fastest solve is closer to the converged effective index than any FDM solve, so more points per wavelength mainly refine its bend loss, which converges much faster than the FDM’s. With EMode2D, the FDM with bend_method='TO' gives better effective index convergence than the FDM in cylindrical coordinates, but its error stops falling on the finest grids, and it does not give a reliable bend loss yet. The FDM in cylindrical coordinates converges slowest for the effective index, but its bend loss converges steadily, so use it when loss is important. With the FDM, choose a grid that puts the waveguide’s edges on grid lines, as every grid here does, or the effective index jumps from one grid spacing to the next. The FEM meshes the shapes’ edges and needs no such care.

This code example is licensed under the BSD 3-Clause License.

  • Python
import sys
import time
import numpy as np
import emodeconnection as emc
from matplotlib import pyplot as plt

## Set simulation parameters: the SiN bend of the 'Bending: SiN' example
wavelength = 980  # [nm] wavelength
w_core = 2000  # [nm] waveguide core width
w_trench = 1500  # [nm] waveguide side trench width
h_core = 200  # [nm] waveguide core height
h_clad = 2000  # [nm] waveguide top and bottom clad, above the PML
window_width = w_core + w_trench*2  # [nm]
window_height = h_core + h_clad*2  # [nm]
bend_radius = 20e3  # [nm] bend radius at the center of the core
x_off = 500  # [nm] core offset, so the bend radius is measured at the core

## The FDM grids all put the core's edges on grid lines (each divides 100 nm),
## and the FEM meshes are fixed (no refinement), from coarse to fine.
resolutions = [50, 25, 20, 10]  # [nm]
fem_meshes = [(1, 100), (1, 50), (2, 50), (3, 50), (4, 50), (6, 50)]  # FEM (points per wavelength, core mesh [nm])

em = emc.EMode(emode_cmd=sys.argv[1:], simulation_name='bend_solvers')


## Define common settings and the waveguide core
em.settings(
    wavelength=wavelength, window_width=window_width, window_height=window_height,
    num_modes=1, boundary_condition='00', background_material='SiO2',
    bend_radius=bend_radius + x_off,
    pml_NSEW_bool=[1, 1, 1, 0], pml_kappa_max=1, max_effective_index=1.67,
    tolerance=1e-6, fem_max_refinements=0, fem_min_angle=33)
em.shape(name='core', material='SiN', width=w_core, height=h_core,
         position=[-x_off, window_height/2], fem_resolution=50)


def solve(solver, method, resolution=20, points=4, core_mesh=50):
    ## The FEM's PML absorbs fully in 500 nm, the FDM's needs 1 um
    pml = 500 if solver == 'FEM' else 1000
    em.settings(solver=solver, bend_method=method,
                x_resolution=resolution, y_resolution=resolution,
                fem_points_per_wavelength=points, pml_thickness=[pml, pml, pml, 0])
    em.shape(name='core', fem_resolution=core_mesh)
    start = time.time()
    em.solve()
    elapsed = time.time() - start
    n_eff = float(np.asarray(em.get('effective_index'))[0])
    loss = float(np.asarray(em.get('loss_dB_per_m'))[0])
    return n_eff, loss, elapsed


## Run all resolutions and bend methods for FDM
rows = []
for method in ('cylindrical', 'TO'):
    for resolution in resolutions:
        n_eff, loss, elapsed = solve('FDM', method, resolution=resolution)
        rows.append(('FDM', method, f'{resolution} nm', n_eff, loss, elapsed))

## Run all resolutions for FEM
for points, core_mesh in fem_meshes:
    n_eff, loss, elapsed = solve('FEM', 'cylindrical', points=points, core_mesh=core_mesh)
    rows.append(('FEM', 'cylindrical', f'{points}/wl, {core_mesh} nm', n_eff, loss, elapsed))

## Plot the guided mode of the finest FEM mesh
em.plot(component='Ex', file_name='bend_FEM', file_type='png')

## Print each solve's error against the finest FEM mesh
reference = rows[-1][3]
print(f'\n{"solver":7s}{"method":13s}{"mesh":>14s}{"n_eff":>11s}{"error":>10s}{"dB/m":>8s}{"time (s)":>10s}')
for solver, method, mesh, n_eff, loss, elapsed in rows:
    print(f'{solver:7s}{method:13s}{mesh:>14s}{n_eff:>11.6f}{n_eff - reference:>10.1e}{loss:>8.4f}{elapsed:>10.1f}')

## Plot effective index and bend loss errors against solve time
loss_reference = rows[-1][4]
fig, axes = plt.subplots(1, 2, figsize=(10, 4))
for solver, method, marker in (('FDM', 'cylindrical', 'o'), ('FDM', 'TO', 's'), ('FEM', 'cylindrical', '^')):
    picked = [r for r in rows[:-1] if r[:2] == (solver, method)]
    times = [r[5] for r in picked]
    axes[0].loglog(times, [abs(r[3] - reference) for r in picked], marker=marker, label=f'{solver}, {method}')
    axes[1].loglog(times, [abs(r[4] - loss_reference) / loss_reference for r in picked], marker=marker, label=f'{solver}, {method}')
axes[0].set_ylabel('|n_eff error|')
axes[1].set_ylabel('|bend loss error| / bend loss')
for ax in axes:
    ax.set_xlabel('solve time (s)')
    ax.grid(True, which='both', alpha=0.3)
axes[0].legend()
fig.tight_layout()
fig.savefig('bend_solvers_convergence.png', dpi=300)

em.close()

Console output:

EMode3D 1.0.6 - email
Meshing completed in 0.2 sec
Solving modes completed in 0.8 sec
Meshing completed in 0.3 sec
Solving modes completed in 4.0 sec
Meshing completed in 0.4 sec
Solving modes completed in 6.8 sec
Meshing completed in 0.7 sec
Solving modes completed in 47.5 sec
Meshing completed in 0.3 sec
Solving modes completed in 0.8 sec
Meshing completed in 0.7 sec
Solving modes completed in 3.4 sec
Meshing completed in 1.0 sec
Solving modes completed in 6.0 sec
Meshing completed in 3.2 sec
Solving modes completed in 31.5 sec
Meshing completed in 0.4 sec
Solving modes completed in 1.3 sec
Meshing completed in 0.4 sec
Solving modes completed in 2.1 sec
Meshing completed in 0.4 sec
Solving modes completed in 3.1 sec
Meshing completed in 0.4 sec
Solving modes completed in 5.9 sec
Meshing completed in 0.4 sec
Solving modes completed in 10.1 sec
Meshing completed in 0.5 sec
Solving modes completed in 22.9 sec
Exited EMode

solver method                 mesh      n_eff     error    dB/m  time (s)
FDM    cylindrical           50 nm   1.663104  -2.9e-03  0.0248       1.0
FDM    cylindrical           25 nm   1.665276  -7.1e-04  0.0180       4.3
FDM    cylindrical           20 nm   1.665535  -4.6e-04  0.0174       7.3
FDM    cylindrical           10 nm   1.665877  -1.1e-04  0.0166      48.7
FDM    TO                    50 nm   1.665358  -6.3e-04  0.0000       1.2
FDM    TO                    25 nm   1.665919  -7.0e-05  0.0002       4.3
FDM    TO                    20 nm   1.665974  -1.6e-05  0.0003       7.2
FDM    TO                    10 nm   1.666021   3.1e-05  0.0003      35.8
FEM    cylindrical    1/wl, 100 nm   1.665985  -5.2e-06  0.0168       2.8
FEM    cylindrical     1/wl, 50 nm   1.665982  -7.5e-06  0.0166       3.4
FEM    cylindrical     2/wl, 50 nm   1.665982  -7.5e-06  0.0165       4.5
FEM    cylindrical     3/wl, 50 nm   1.665987  -3.3e-06  0.0164       8.2
FEM    cylindrical     4/wl, 50 nm   1.665987  -3.2e-06  0.0164      12.1
FEM    cylindrical     6/wl, 50 nm   1.665990   0.0e+00  0.0164      27.7

Figures:

../_images/bend_solvers_convergence.png
../_images/bend_FEM.png