Setup¶
import os
import numpy as np
import matplotlib.pyplot as plt
import gdsfactory as gf
from gdsfactory.technology import LogicalLayer, LayerLevel, LayerStack
import luminescent as lumi
# coupler dims
w_wg = 1
gap = 0.25
# length: to be swept
dx = 15
dy = 5
wavelength = 1.55
bandwidth = 0.1
nwls = 11
wavelengths = np.linspace(wavelength - bandwidth / 2, wavelength + bandwidth / 2, nwls)
def setup(path, wavelength, wavelengths, length,gap, dx, dy, w_wg):
nres = 6
stop_decay = 3e-3
PML_decay = [0.001, 0.01, 0.1]
shot_every = 10
h_rib = 0.4
boundaries = ["PML", "PML", "PML"]
views = [lumi.view("Hz", x=0, z=h_rib / 2)]
# layer stack dims
h_slab = 0.2
margin = 1.5
source_offset = 2
sidewall_angle = 15
zmargin = 1.
zmin = -h_slab - zmargin
zmax = h_rib + zmargin
# anisotropic TFLN: X-cut along y
ne = 2.14
no = 2.21
materials = {
"LN": lumi.material(epsilon=[[no**2, 0, 0], [0, ne**2, 0], [0, 0, no**2]]),
"SiO2": lumi.material(1.44),
}
background = "SiO2"
# layers
WG = 1, 0
BBOX = 2, 0
layer_stack = LayerStack(
layers={
"rib": LayerLevel(
layer=LogicalLayer(layer=WG),
thickness=h_rib,
zmin=0,
material="LN",
mesh_order=0,
sidewall_angle=sidewall_angle,
),
"slab": LayerLevel(
layer=LogicalLayer(layer=BBOX),
thickness=h_slab,
zmin=-h_slab,
material="LN",
mesh_order=1,
),
}
)
# make component in gdsfactory. alternatively can import .gds into gdsfactory
c = gf.Component()
dut = c << gf.components.coupler(
gap=gap,
length=length,
dx=dx,
dy=dy,
cross_section=gf.cross_section.cross_section(width=w_wg),
)
s = c << gf.components.straight(length=source_offset, width=w_wg)
s.connect("o2", dut.ports["o1"])
c << gf.components.bbox(component=c, layer=BBOX, top=margin, bottom=margin)
for p in dut.ports:
c.add_port(p.name, port=p)
c.flatten()
c.plot()
bbox = c.bbox_np().tolist()
bbox[0].append(zmin)
bbox[1].append(zmax)
lx = w_wg + 2 * margin
frames = [
lumi.plane_frame(
"wg",
start=[-lx / 2, zmin],
stop=[lx / 2, zmax],
wls_mode_solver=[wavelength],
)
]
sources = [
lumi.gf_source(
"o1", c, layer_stack, source_offset,
frame="wg",
wl=wavelength,
bandwidth=max(max(wavelengths) - min(wavelengths), wavelength / 4),
)
]
monitors = [
lumi.gf_monitor("o1", c, layer_stack, frame="wg"),
lumi.gf_monitor("o3", c, layer_stack, frame="wg"),
lumi.gf_monitor("o4", c, layer_stack, frame="wg"),
]
lumi.mesh(path, c, layer_stack, materials, zmin, zmax)
lumi.setup(
path=path,
wl=wavelength,
wls=wavelengths,
materials=materials,
background=background,
boundaries=boundaries,
bbox=bbox,
frames=frames,
sources=sources,
monitors=monitors,
nres=nres,
stop_decay=stop_decay,
PML_decay=PML_decay,
views=views,
shot_every=shot_every,
device='gpu',
)
lumi backend: ~/Luminescent/bin/lumi
Sweep length¶
S31abs2_length = []
S41abs2_length = []
lengths = [7,8,9]
for length in lengths:
path = os.path.join("runs", f"TFLN_coupler_{length}")
setup(path, wavelength, wavelengths, length,gap, dx, dy, w_wg)
lumi.solve(path)
sol = lumi.load(path)
o1 = sol["monitors"]["o1"]
o3 = sol["monitors"]["o3"]
o4 = sol["monitors"]["o4"]
mid=nwls//2
S31 = o3["modes"][0]["+"] / o1["modes"][0]["-"]
S41 = o4["modes"][0]["+"] / o1["modes"][0]["-"]
S31abs2 = np.abs(S31[mid])**2
S41abs2 = np.abs(S41[mid])**2
print(f"length: {length} um, S31 power 1.55um: {S31abs2}, S41 power 1.55um: {S41abs2}")
S31abs2_length.append(S31abs2)
S41abs2_length.append(S41abs2)
Mesh is not watertight; plotting debug view
Mesh is not watertight; plotting debug view
Warning: boolean difference failed at index 1: Not all meshes are volumes!
Warning: boolean difference failed at index 2: Not all meshes are volumes!
showing modes for wavelength 1.55
mode Boundary conditions: 0000


wg/1.55 mode 0 (neff=1.910+0.000j)
saving mode to runs/TFLN_coupler_7/modes/wg/1.55/0.npz
using simulation folder runs/TFLN_coupler_7
========================================
backend using simulation folder runs/TFLN_coupler_7
========================================
setting up simulation...
processing geometry bodies...
generating voxels...
subpixel smoothing: 6.544695 seconds (146.12 M allocations: 6.440 GiB, 9.28% gc time, 155.56% compilation time)
making sources o1 ...
making monitors o1 o3 o4 ...
========================================
run: runs/TFLN_coupler_7
processor: CPU
cpu threads: 16
nres: 6.0
courant: 0.95
subpixel_smoothing: 1
boundaries: [:PML :PML; :PML :PML; :PML :PML]
sources
o1: -17, -1.87, 0
monitors
o1: -15, -1.88, 0
o3: 22, 3.12, 0
o4: 22, -1.88, 0
original size: (331, 83, 18)
padded size: (361, 103, 26)
cell count: 966,758
step size: 28.0 steps/period
source duration: 3.93 periods
max time: 1000.0 periods
max steps: 28,000
max load: 27,069,224,000 cell-steps
energy decay threshold: 0.003
========================================
running simulation...
accumulating dft field...
period 10, decay: 0.97, 1.71 seconds/period
period 20, decay: 0.96, 0.3 seconds/period
period 30.0, decay: 0.96, 0.311 seconds/period
period 40, decay: 0.95, 0.279 seconds/period
period 50.0, decay: 0.95, 0.258 seconds/period
period 60.0, decay: 0.91, 0.255 seconds/period
period 70, decay: 0.129, 0.281 seconds/period
period 80, decay: 0.003, 0.309 seconds/period
period 82.29 stop on energy decay
simulation completed.
loading solution from runs/TFLN_coupler_7
may take a minute if simulation folder is remotely mounted
length: 7 um, S31 power 1.55um: 0.3983535419784426, S41 power 1.55um: 0.5719360890469225
Mesh is not watertight; plotting debug view
Mesh is not watertight; plotting debug view
Warning: boolean difference failed at index 1: Not all meshes are volumes!
Warning: boolean difference failed at index 2: Not all meshes are volumes!
showing modes for wavelength 1.55
mode Boundary conditions: 0000



wg/1.55 mode 0 (neff=1.910+0.000j)
saving mode to runs/TFLN_coupler_8/modes/wg/1.55/0.npz
using simulation folder runs/TFLN_coupler_8
========================================
backend using simulation folder runs/TFLN_coupler_8
========================================
setting up simulation...
processing geometry bodies...
generating voxels...
subpixel smoothing: 7.044815 seconds (149.60 M allocations: 6.599 GiB, 9.05% gc time, 162.70% compilation time)
making sources o1 ...
making monitors o1 o3 o4 ...
========================================
run: runs/TFLN_coupler_8
processor: CPU
cpu threads: 16
nres: 6.0
courant: 0.95
subpixel_smoothing: 1
boundaries: [:PML :PML; :PML :PML; :PML :PML]
sources
o1: -17, -1.87, 0
monitors
o1: -15, -1.88, 0
o3: 23, 3.12, 0
o4: 23, -1.88, 0
original size: (339, 83, 18)
padded size: (369, 103, 26)
cell count: 988,182
step size: 28.0 steps/period
source duration: 3.93 periods
max time: 1000.0 periods
max steps: 28,000
max load: 27,669,096,000 cell-steps
energy decay threshold: 0.003
========================================
running simulation...
accumulating dft field...
period 10, decay: 0.97, 1.68 seconds/period
period 20, decay: 0.96, 0.312 seconds/period
period 30.0, decay: 0.96, 0.327 seconds/period
period 40, decay: 0.95, 0.289 seconds/period
period 50.0, decay: 0.95, 0.293 seconds/period
period 60.0, decay: 0.93, 0.281 seconds/period
period 70, decay: 0.248, 0.286 seconds/period
period 80, decay: 0.006, 0.294 seconds/period
period 82.29 stop on energy decay
simulation completed.
loading solution from runs/TFLN_coupler_8
may take a minute if simulation folder is remotely mounted
length: 8 um, S31 power 1.55um: 0.44944616902040524, S41 power 1.55um: 0.5214126593446475
Mesh is not watertight; plotting debug view
Mesh is not watertight; plotting debug view
Warning: boolean difference failed at index 1: Not all meshes are volumes!
Warning: boolean difference failed at index 2: Not all meshes are volumes!
showing modes for wavelength 1.55
mode Boundary conditions: 0000



wg/1.55 mode 0 (neff=1.910+0.000j)
saving mode to runs/TFLN_coupler_9/modes/wg/1.55/0.npz
using simulation folder runs/TFLN_coupler_9
========================================
backend using simulation folder runs/TFLN_coupler_9
========================================
setting up simulation...
processing geometry bodies...
generating voxels...
subpixel smoothing: 7.671235 seconds (153.27 M allocations: 6.757 GiB, 10.05% gc time, 161.06% compilation time)
making sources o1 ...
making monitors o1 o3 o4 ...
========================================
run: runs/TFLN_coupler_9
processor: CPU
cpu threads: 16
nres: 6.0
courant: 0.95
subpixel_smoothing: 1
boundaries: [:PML :PML; :PML :PML; :PML :PML]
sources
o1: -17, -1.87, 0
monitors
o1: -15, -1.88, 0
o3: 24, 3.12, 0
o4: 24, -1.88, 0
original size: (348, 83, 18)
padded size: (378, 103, 26)
cell count: 1,012,284
step size: 28.0 steps/period
source duration: 3.93 periods
max time: 1000.0 periods
max steps: 28,000
max load: 28,343,952,000 cell-steps
energy decay threshold: 0.003
========================================
running simulation...
accumulating dft field...
period 10, decay: 0.97, 1.73 seconds/period
period 20, decay: 0.96, 0.349 seconds/period
period 30.0, decay: 0.96, 0.35 seconds/period
period 40, decay: 0.95, 0.314 seconds/period
period 50.0, decay: 0.95, 0.307 seconds/period
period 60.0, decay: 0.93, 0.311 seconds/period
period 70, decay: 0.419, 0.324 seconds/period
period 80, decay: 0.013, 0.345 seconds/period
period 82.29 stop on energy decay
simulation completed.
loading solution from runs/TFLN_coupler_9
may take a minute if simulation folder is remotely mounted
length: 9 um, S31 power 1.55um: 0.4967570038605854, S41 power 1.55um: 0.4679700268921563

plt.plot(lengths, S31abs2_length, label="S31 power")
plt.plot(lengths, S41abs2_length, label="S41 power")
plt.xlabel("coupling length [um]")
plt.legend()
plt.show()
Movie¶
lumi.movie(path)Loading...