Noise floor of overlap integrals

Noise floor of overlap integrals#

The overlap integral between neighboring waveguides is one way to determine the coupling between neighboring waveguides. As the modes decay exponentially outside the core after a certain distance, the overlap integral also decays in good approximation exponentially. In order to see how good the estimation of the overlap integral is and to see at which distance the coupling is too weak to be estimated precisely using this methodology, we calculate the coupling as a function of the distance in the following.

For this example we chose two silicon nitride waveguides with a width of 1μm and a thickness of 0.3μm. Those waveguides are ontop of a silicon dioxide layer and air-clad.

Hide code cell source

using PyCall

all_distances = 1:1.0:30
distances = Float64[]
overlaps = Float64[]

mode_1 = nothing
mode_2 = nothing
Ω = nothing

for distance in all_distances
    println(distance)

    py"""
    import numpy as np
    import shapely
    import shapely.geometry
    import shapely.affinity
    from shapely.ops import clip_by_rect, unary_union
    from collections import OrderedDict
    from femwell.mesh import mesh_from_OrderedDict

    distance = $distance
    wg_width = 1
    wg_thickness = 0.3
    core = shapely.geometry.box(-wg_width / 2, 0, +wg_width / 2, wg_thickness)
    core1 = shapely.affinity.translate(core, xoff=distance/2)
    core2 = shapely.affinity.translate(core, xoff=-distance/2)
    env = unary_union([core1, core2]).buffer(max(5,distance), quad_segs = 2)

    polygons = OrderedDict(
        core1=core1,
        core2=core2,
        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 = {f"core{i}": {"resolution": 0.05, "distance": 1} for i in [1,2]}
    mesh = mesh_from_OrderedDict(
        polygons,
        resolutions,
        default_resolution_max = 1,
        filename = "mesh.msh"
    )
    """
    using Gridap
    using Gridap.Geometry
    using Gridap.Visualization
    using Gridap.ReferenceFEs
    using GridapGmsh
    using GridapMakie, CairoMakie

    using Femwell.Maxwell.Waveguide

    order = 1

    CairoMakie.inline!(true)

    model = GmshDiscreteModel("mesh.msh")
    Ω = Triangulation(model)
    labels = get_face_labeling(model)
    τ = CellField(get_face_tag(labels, num_cell_dims(model)), Ω)

    fig = plot(Ω)
    fig.axis.aspect = DataAspect()
    wireframe!(Ω, color = :black, linewidth = 1)
    display(fig)

    epsilons = ["core1" => 1.9963^2, "core2" => 1.444^2, "box" => 1.444^2, "clad" => 1.0^2]
    ε(tag) = Dict(get_tag_from_name(labels, u) => v for (u, v) in epsilons)[tag]
    @time modes_1 = calculate_modes(model, ε  τ, λ = 1.55, num = 1, order = order)
    println(n_eff(modes_1[1]))

    if length(distances) == 0
        push!(distances, 0)
        push!(overlaps, overlap(modes_1[1], modes_1[1]))
    end

    epsilons = ["core1" => 1.444^2, "core2" => 1.9963^2, "box" => 1.444^2, "clad" => 1.0^2]
    ε(tag) = Dict(get_tag_from_name(labels, u) => v for (u, v) in epsilons)[tag]
    modes_2 = calculate_modes(model, ε  τ, λ = 1.55, num = 1, order = order)
    println(n_eff(modes_2[1]))

    overlap_integral = overlap(modes_1[1], modes_2[1])
    println(overlap_integral)
    push!(distances, distance)
    push!(overlaps, abs(overlap_integral))

    if distance == last(all_distances)
        plot_mode(modes_1[1])
        plot_mode(modes_2[1])
    end
end

Hide code cell output

1.0
WARNING: Method definition (::Main.var"#ε#3"{labels})(Any) in module Main at In[1]:70 overwritten at In[1]:80.
InitError: could not load library "/home/runner/.julia/artifacts/b2e490a224990d92e99cc4463b8df48c8c454971/lib/libpangocairo-1.0.so"
/home/runner/.julia/artifacts/b2e490a224990d92e99cc4463b8df48c8c454971/lib/libpangoft2-1.0.so.0: undefined symbol: FcConfigSetDefaultSubstitute
during initialization of module Pango_jll

Stacktrace:
  [1] dlopen(s::String, flags::UInt32; throw_error::Bool)
    @ Base.Libc.Libdl ./libdl.jl:117
  [2] dlopen(s::String, flags::UInt32)
    @ Base.Libc.Libdl ./libdl.jl:116
  [3] macro expansion
    @ ~/.julia/packages/JLLWrappers/m2Pjh/src/products/library_generators.jl:63 [inlined]
  [4] __init__()
    @ Pango_jll ~/.julia/packages/Pango_jll/CWpUN/src/wrappers/x86_64-linux-gnu.jl:22
  [5] run_module_init(mod::Module, i::Int64)
    @ Base ./loading.jl:1134
  [6] register_restored_modules(sv::Core.SimpleVector, pkg::Base.PkgId, path::String)
    @ Base ./loading.jl:1122
  [7] _include_from_serialized(pkg::Base.PkgId, path::String, ocachepath::String, depmods::Vector{Any})
    @ Base ./loading.jl:1067
  [8] _tryrequire_from_serialized(modkey::Base.PkgId, path::String, ocachepath::String, sourcepath::String, depmods::Vector{})
    @ Base ./loading.jl:1481
  [9] _require_search_from_serialized(pkg::Base.PkgId, sourcepath::String, build_id::UInt128)
    @ Base ./loading.jl:1574
 [10] _require(pkg::Base.PkgId, env::String)
    @ Base ./loading.jl:1938
 [11] __require_prelocked(uuidkey::Base.PkgId, env::String)
    @ Base ./loading.jl:1812
 [12] #invoke_in_world#3
    @ ./essentials.jl:926 [inlined]
 [13] invoke_in_world
    @ ./essentials.jl:923 [inlined]
 [14] _require_prelocked(uuidkey::Base.PkgId, env::String)
    @ Base ./loading.jl:1803
 [15] macro expansion
    @ ./loading.jl:1790 [inlined]
 [16] macro expansion
    @ ./lock.jl:267 [inlined]
 [17] __require(into::Module, mod::Symbol)
    @ Base ./loading.jl:1753
 [18] #invoke_in_world#3
    @ ./essentials.jl:926 [inlined]
 [19] invoke_in_world
    @ ./essentials.jl:923 [inlined]
 [20] require(into::Module, mod::Symbol)
    @ Base ./loading.jl:1746
 [21] top-level scope
    @ ./In[1]:51

Hide code cell source

f = Figure()
ax = Axis(
    f[1, 1],
    title = "Overlap integral between neighboring waveguides",
    xlabel = "Distance / μm",
    ylabel = "Overlap integral / dB",
)
lines!(ax, distances, 10 * log10.(overlaps))
plot!(ax, distances, 10 * log10.(overlaps))
display(f)