Mode solving

Contents

Mode solving#

Caution

This example is under construction As Julia-Dicts are not ordered, the mesh might become incorrect when adjusted (for now, better do the meshing in python)

using PyCall
np = pyimport("numpy")
shapely = pyimport("shapely")
shapely.affinity = pyimport("shapely.affinity")
clip_by_rect = pyimport("shapely.ops").clip_by_rect
OrderedDict = pyimport("collections").OrderedDict
mesh_from_OrderedDict = pyimport("femwell.mesh").mesh_from_OrderedDict

wg_width = 0.5
wg_thickness = 0.22
slab_width = 3
slab_thickness = 0.11
core = shapely.geometry.box(-wg_width / 2, 0, wg_width / 2, wg_thickness)
slab = shapely.geometry.box(slab_width / 2, 0, slab_width / 2, slab_thickness)
env = shapely.affinity.scale(core.buffer(3, resolution = 8), xfact = 0.5)

polygons = OrderedDict(
    core = core,
    slab = slab,
    box = clip_by_rect(env, -np.inf, -np.inf, np.inf, 0),
    clad = clip_by_rect(env, -np.inf, 0, np.inf, np.inf),
)

resolutions = Dict(
    "core" => Dict("resolution" => 0.03, "distance" => 0.5),
    "slab" => Dict("resolution" => 0.03, "distance" => 0.5),
)

mesh = mesh_from_OrderedDict(
    polygons,
    resolutions,
    default_resolution_max = 1,
    filename = "mesh.msh",
)
Hide code cell output
PyObject <meshio mesh object>
  Number of points: 632
  Number of cells:
    vertex: 1
    vertex: 1
    line: 4
    line: 17
    line: 8
    line: 17
    line: 8
    line: 6
    line: 8
    line: 3
    triangle: 344
    triangle: 352
    triangle: 528
  Cell sets: slab_points, slab, core___box, core___clad, box___clad, core, box, clad, gmsh:bounding_entities
  Point data: gmsh:dim_tags
  Cell data: gmsh:physical, gmsh:geometrical
  Field data: slab_points, slab, core___box, core___clad, box___clad, core, box, clad
using Gridap
using Gridap.Geometry
using Gridap.Visualization
using Gridap.ReferenceFEs
using GridapGmsh
using GridapMakie, CairoMakie

using Femwell.Maxwell.Waveguide

CairoMakie.inline!(true)
model = GmshDiscreteModel("mesh.msh")
Ω = Triangulation(model)
#fig = plot(Ω)
#fig.axis.aspect=DataAspect()
#wireframe!(Ω, color=:black, linewidth=1)
#display(fig)

labels = get_face_labeling(model)

epsilons = ["core" => 3.5^2, "slab" => 1.44^2, "box" => 1.444^2, "clad" => 1.44^2]
ε(tag) = Dict(get_tag_from_name(labels, u) => v for (u, v) in epsilons)[tag]


#dΩ = Measure(Ω, 1)
τ = CellField(get_face_tag(labels, num_cell_dims(model)), Ω)

modes = calculate_modes(model, ε  τ, λ = 1.55, num = 1, order = 1)
println(n_eff(modes[1]))
# write_mode_to_vtk("mode", modes[2])

plot_mode(modes[1])
#plot_mode(modes[2])
modes
Info    : Reading 'mesh.msh'...
Info    : 89 entities
Info    : 632 nodes
Info    : 1297 elements
Info    : Done reading 'mesh.msh'
2.470478488488765 + 0.0im
../_images/1b590a68546855aed59151394497cdf63af5539ebf766e31fcc94ae8b5d37e9b.png
1-element Vector{Mode}:
 Mode(k=10.0144994455328 + 0.0im, n_eff=2.470478488488765 + 0.0im)

Perturbations#

Let’s add a minor perturbation and calculate the effective refractive index using perturbation theory:

epsilons_p = ["core" => -0.1im, "box" => -0.0im, "slab" => -0.0im, "clad" => -0.0im]
ε_p(tag) = Dict(get_tag_from_name(labels, u) => v for (u, v) in epsilons_p)[tag]

println(perturbed_neff(modes[1], ε_p  τ))
2.470478488488765 - 0.015304012592707257im

For comparison, we also calculate directly the effective refractive index:

modes_p = calculate_modes(model, ε  τ + ε_p  τ, λ = 1.55, num = 2, order = 1)
println(n_eff(modes_p[1]))
plot_mode(modes_p[1])
2.4704936829557957 - 0.015304178613236508im
../_images/2e8a6f3655546c05ac9a3290b27f15ab7ab4ee709c1cfc6f908479071bab8ed5.png