Lithium niobate phase-shifter#
Reproducing [1]
Show code cell source
using PyCall
py"""
from collections import OrderedDict
from shapely.geometry import box
from femwell.mesh import mesh_from_OrderedDict
core_width = 1.532
electrode_start_x = core_width / 2 + 2.629
electrode_width = 4.4
electrode_left = box(-electrode_start_x - electrode_width, 0.5, -electrode_start_x, 0.5 + 1.8)
electrode_right = box(electrode_start_x, 0.5, electrode_start_x + electrode_width, 0.5 + 1.8)
slab = box(-10, 0, 10, 0.5)
core = box(-core_width / 2, 0.5, core_width / 2, 0.8)
env = slab.buffer(20, resolution=8)
polygons = OrderedDict(
electrode_left=electrode_left,
electrode_right=electrode_right,
slab=slab,
core=core,
env=env,
)
resolutions = dict(
slab={"resolution": 0.1, "distance": 4},
core={"resolution": 0.1, "distance": 4},
)
mesh_from_OrderedDict(polygons, resolutions, filename="mesh.msh", default_resolution_max=3)
"""
using Gridap
using Gridap.Geometry
using GridapGmsh
using Femwell.Maxwell.Waveguide
using Femwell.Maxwell.Electrostatic
using GridapMakie, CairoMakie
model = GmshDiscreteModel("mesh.msh")
Ω = Triangulation(model)
labels = get_face_labeling(model)
τ = CellField(get_face_tag(labels, num_cell_dims(model)), Ω)
conductivity = [
"core" => 7.5,
"slab" => 28.4,
"electrode_left" => 3.9,
"electrode_right" => 3.9,
"env" => 3.9,
]
σ(tag) = Dict(get_tag_from_name(labels, u) => v for (u, v) in conductivity)[tag]
p0 = compute_potential(
σ ∘ τ,
Dict("electrode_left___slab" => 1.0, "electrode_right___slab" => 0.0),
order = 2,
)
plot_potential(p0)
fig, _, plt =
plot(get_triangulation(potential(p0)), (σ ∘ τ) * ∇(potential(p0)) ⋅ VectorValue(1, 0))
Colorbar(fig[1, 2], plt)
display(fig)
voltages = 0:10:100
voltages_neffs = []
for voltage in voltages
epsilons = [
"core" => 1.989,
"env" => 1.445,
"slab" => 2.211,
"electrode_left" => 1.445,
"electrode_right" => 1.445,
]
ε(tag) = Dict(get_tag_from_name(labels, u) => v for (u, v) in epsilons)[tag]
ε_perturbation =
0.5 * 2.211^3 * 31e-6 * ∇(potential(p0)) ⋅ VectorValue(-1, 0) *
voltage *
((tag -> get_tag_from_name(labels, "slab") == tag) ∘ τ)
modes = calculate_modes(
model,
(ε ∘ τ + ε_perturbation) * (ε ∘ τ + ε_perturbation),
λ = 1.55,
order = 0,
)
push!(voltages_neffs, n_eff(modes[1]))
end
The following 1 direct dependency failed to precompile:
GLMakie [e9467ef8-e4e7-5192-8a1a-b1aee30e663a]
Failed to precompile GLMakie [e9467ef8-e4e7-5192-8a1a-b1aee30e663a] to "/home/runner/.julia/compiled/v1.10/GLMakie/jl_pxbrUg".
┌ Warning: OpenGL/GLFW wasn't loaded correctly or couldn't be initialized.
│ This likely means, you're on a headless server without having OpenGL support setup correctly.
│ Have a look at the troubleshooting section in the readme:
│ https://github.com/MakieOrg/Makie.jl/tree/master/GLMakie#troubleshooting-opengl.
└ @ GLMakie ~/.julia/packages/GLMakie/TH3rf/src/gl_backend.jl:4
ERROR: LoadError: InitError: Exception[GLFW.GLFWError(65550, "X11: The DISPLAY environment variable is missing"), ErrorException("glfwInit failed")]
Stacktrace:
[1] __init__()
@ GLFW ~/.julia/packages/GLFW/wmoTL/src/GLFW.jl:35
[2] run_module_init(mod::Module, i::Int64)
@ Base ./loading.jl:1134
[3] register_restored_modules(sv::Core.SimpleVector, pkg::Base.PkgId, path::String)
@ Base ./loading.jl:1122
[4] _include_from_serialized(pkg::Base.PkgId, path::String, ocachepath::String, depmods::Vector{Any})
@ Base ./loading.jl:1067
[5] _require_search_from_serialized(pkg::Base.PkgId, sourcepath::String, build_id::UInt128)
@ Base ./loading.jl:1581
[6] _require(pkg::Base.PkgId, env::String)
@ Base ./loading.jl:1938
[7] __require_prelocked(uuidkey::Base.PkgId, env::String)
@ Base ./loading.jl:1812
[8] #invoke_in_world#3
@ ./essentials.jl:926 [inlined]
[9] invoke_in_world
@ ./essentials.jl:923 [inlined]
[10] _require_prelocked(uuidkey::Base.PkgId, env::String)
@ Base ./loading.jl:1803
[11] macro expansion
@ ./loading.jl:1790 [inlined]
[12] macro expansion
@ ./lock.jl:267 [inlined]
[13] __require(into::Module, mod::Symbol)
@ Base ./loading.jl:1753
[14] #invoke_in_world#3
@ ./essentials.jl:926 [inlined]
[15] invoke_in_world
@ ./essentials.jl:923 [inlined]
[16] require(into::Module, mod::Symbol)
@ Base ./loading.jl:1746
[17] top-level scope
@ ~/.julia/packages/GLMakie/TH3rf/src/gl_backend.jl:2
[18] include(mod::Module, _path::String)
@ Base ./Base.jl:495
[19] include(x::String)
@ GLMakie ~/.julia/packages/GLMakie/TH3rf/src/GLMakie.jl:1
[20] top-level scope
@ ~/.julia/packages/GLMakie/TH3rf/src/GLMakie.jl:87
[21] include
@ ./Base.jl:495 [inlined]
[22] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt128}}, source::Nothing)
@ Base ./loading.jl:2222
[23] top-level scope
@ stdin:3
during initialization of module GLFW
in expression starting at /home/runner/.julia/packages/GLMakie/TH3rf/src/gl_backend.jl:1
in expression starting at /home/runner/.julia/packages/GLMakie/TH3rf/src/GLMakie.jl:1
in expression starting at stdin:
Stacktrace:
[1] pkgerror(msg::String)
@ Pkg.Types /opt/hostedtoolcache/julia/1.10.3/x64/share/julia/stdlib/v1.10/Pkg/src/Types.jl:70
[2] precompile(ctx::Pkg.Types.Context, pkgs::Vector{Pkg.Types.PackageSpec}; internal_call::Bool, strict::Bool, warn_loaded::Bool, already_instantiated::Bool, timing::Bool, _from_loading::Bool, kwargs::@Kwargs{io::IJulia.IJuliaStdio{Base.PipeEndpoint}})
@ Pkg.API /opt/hostedtoolcache/julia/1.10.3/x64/share/julia/stdlib/v1.10/Pkg/src/API.jl:1659
[3] precompile(pkgs::Vector{Pkg.Types.PackageSpec}; io::IJulia.IJuliaStdio{Base.PipeEndpoint}, kwargs::@Kwargs{_from_loading::Bool})
@ Pkg.API /opt/hostedtoolcache/julia/1.10.3/x64/share/julia/stdlib/v1.10/Pkg/src/API.jl:159
[4] precompile
@ /opt/hostedtoolcache/julia/1.10.3/x64/share/julia/stdlib/v1.10/Pkg/src/API.jl:147 [inlined]
[5] #precompile#114
@ /opt/hostedtoolcache/julia/1.10.3/x64/share/julia/stdlib/v1.10/Pkg/src/API.jl:146 [inlined]
[6] #invokelatest#2
@ ./essentials.jl:894 [inlined]
[7] invokelatest
@ ./essentials.jl:889 [inlined]
[8] _require(pkg::Base.PkgId, env::String)
@ Base ./loading.jl:1963
[9] __require_prelocked(uuidkey::Base.PkgId, env::String)
@ Base ./loading.jl:1812
[10] #invoke_in_world#3
@ ./essentials.jl:926 [inlined]
[11] invoke_in_world
@ ./essentials.jl:923 [inlined]
[12] _require_prelocked(uuidkey::Base.PkgId, env::String)
@ Base ./loading.jl:1803
[13] macro expansion
@ ./loading.jl:1790 [inlined]
[14] macro expansion
@ ./lock.jl:267 [inlined]
[15] __require(into::Module, mod::Symbol)
@ Base ./loading.jl:1753
[16] #invoke_in_world#3
@ ./essentials.jl:926 [inlined]
[17] invoke_in_world
@ ./essentials.jl:923 [inlined]
[18] require(into::Module, mod::Symbol)
@ Base ./loading.jl:1746
Show code cell source
f = Figure()
ax = Axis(f[1, 1], xlabel = "Voltage / V", ylabel = "Effective refractive index")
lines!(ax, voltages, real(voltages_neffs))
plot!(ax, voltages, real(voltages_neffs))
display(f)
Bibliography#
[1]
Huangpu Han, Fan Yang, Chenghao Liu, Zhengfang Wang, Yunpeng Jiang, Guangyue Chai, Shuangchen Ruan, and Bingxi Xiang. High-performance electro-optical mach–zehnder modulators in a silicon nitride–lithium niobate thin-film hybrid platform. Photonics, 9(7):500, July 2022. URL: https://doi.org/10.3390/photonics9070500, doi:10.3390/photonics9070500.