Inverse design of grating coupler on SOI for angled fiber. (inverse design not available in free version)
Config¶
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
from scipy.spatial import ConvexHull
path = os.path.join("runs", "GC_invd")
wl = 1.55
bandwidth = 0.01
nwls = 3
wls = np.linspace(wl - bandwidth / 2, wl + bandwidth / 2, nwls)
# simulation parameters
nres = 10
boundaries = ["PML", ["PEC", "PML"], "PML"]
# PML_decay = [0.01, 0.3, 0.01]
PML_decay = [0.001, 0.1, 0.001]
courant = 0.95
# shutoff=.001
shutoff=None
# horizontal dimensions
D = 10.4 # mode field diameter, SMF-28
R = 1.5 * D/2 # beam frame half width
# flare = 25 # waveguide flare full angle (deg)
# W = 3 * D
# L = W
# L = W/2/np.tan(flare/2/180*np.pi)
# elliptical grating coupler whose outline is the design contour
n_periods = 16
period = 0.635
fill_factor = 0.5
taper_length = 15.0
taper_angle = 40.0
w_wg = 0.5
# l_wg =1
l_wg = 2
l_flare = .5
# margin = .5
margin = 1
# nox=1.44
nox = 1.444
# vertical dimensions
# theta = 7 * np.pi / 180 # beam angle
theta = 6.9 * np.pi / 180 # beam angle
h_wg = 0.22
# h_etch = 0.08
h_etch = 0.10
h_slab = h_wg-h_etch
# h_box = 2.0 # buried oxide
h_box = (1 + .5) *wl / (2 * nox * np.cos( theta))
# h_sub = 0.3 # substrate thickness in domain
# zmargin = .6
zmargin = 1
# port_offset = 0.3
port_offset = zmargin
# source_offset = 0.3
source_offset = 0.25
z_port = h_wg + port_offset
# zmin = -h_box - h_sub
# zmin = -h_box
zmin = -zmargin
zmax = h_wg + port_offset + source_offset
# movie parameters
shot_every = 10
views = [
lumi.view("Ey", y=0, z=h_slab+h_etch/2,mirrors = ["y-"]),
]
# materials
core = "Si"
clad = "SiO2"
materials = {
# "Si": lumi.material(3.45),
# "SiO2": lumi.material(1.44),
"Si": lumi.material(3.478),
"SiO2": lumi.material(nox),
}
n_core = materials[core]["n"]
n_clad = materials[clad]["n"]
lambda_core = wl / n_core
lambda_clad = wl / n_clad
dx = lambda_core / nres
background = clad
materials["design"] = lumi.placeholder_material(n_core)
# layer stack. lower mesh order layers override higher mesh order layers.
WG = (1, 0)
CLAD = (2, 0)
SLAB = (102, 0)
DESIGN = (1001, 0)
CONTOUR=(1002,0)
layers = {
"design": LayerLevel(
layer=LogicalLayer(layer=DESIGN),
zmin=h_slab,
thickness=h_etch,
material="design",
mesh_order=1,
),
"rib": LayerLevel(
# layer=LogicalLayer(layer=SLAB),
layer=LogicalLayer(layer=CONTOUR),
zmin=h_slab,
thickness=h_etch,
material=core,
mesh_order=101,
),
"slab": LayerLevel(
layer=LogicalLayer(layer=SLAB),
zmin=0,
thickness=h_slab,
material=core,
mesh_order=102,
),
"core": LayerLevel(
layer=LogicalLayer(layer=WG),
zmin=0,
thickness=h_wg,
material=core,
mesh_order=200,
),
# "substrate": LayerLevel(
# layer=LogicalLayer(layer=CLAD),
# zmin=zmin,
# thickness=h_sub,
# material=core,
# mesh_order=300,
# ),
}
layer_stack = LayerStack(layers=layers)
optimizer = lumi.optimizer(
stoploss=0.1,
lowloss=0.5,
# iters=20,
iters=40,
contrast=0,
momentum=0.7,
)
targets = [
lumi.target(src="o2@0-", dst="o1@0+", target=1, weight=1 / nwls, wl=wl)
for wl in wls
]
lmin=.1Geometry¶
# Build the gdsfactory component to be optimized (upper half, mirrored about y=0).
# design contour: outline of elliptical grating coupler, grating center at x=0 under beam
gc = gf.components.grating_coupler_elliptical_uniform(
n_periods=n_periods,
period=period,
fill_factor=fill_factor,
taper_length=taper_length,
taper_angle=taper_angle,
wavelength=wl,
fiber_angle=np.degrees(theta),
nclad=nox,
# layer_slab=None,
layer_slab=SLAB,
cross_section=gf.cross_section.cross_section(width=w_wg, layer=WG),
)
q = np.vstack([np.array(p) for ps in gc.get_polygons_points(layers=[WG]).values() for p in ps])
q = q[ConvexHull(q).vertices] - [gc.ports["o2"].x, 0]
p = np.c_[q[:, 0], np.maximum(q[:, 1], 0)] # upper half
x_design, L, W = p[:, 0].min(), np.ptp(p[:, 0]), 2 * p[:, 1].max()
# x_design = -L + R
# x_flare = ox_design - l_flare
# x_wg = x_flare - l_wg
c = gf.Component()
for layer in (DESIGN, ):
rect = c << gf.components.rectangle(size=(L, W / 2), layer=layer)
rect.movex(x_design)
# w_flare = w_wg / 2 + l_flare * np.tan(np.radians(flare / 2))
x_wg=x_design-l_wg
# p=[(x_design,0),(x_design,w_wg/2),(x_design+L,W/2),(x_design+L,0)]
c.add_polygon([(x_wg, 0), (x_wg, w_wg / 2), (x_design, w_wg / 2), (x_design,0)], layer=WG)
c.add_polygon(p, layer=CONTOUR)
c.add_polygon(p, layer=SLAB)
for ps in gc.get_polygons_points(layers=[SLAB]).values(): # slab overhang, as in GC
for s in ps:
s = np.array(s) - [gc.ports["o2"].x, 0]
c.add_polygon(np.c_[s[:, 0], np.maximum(s[:, 1], 0)], layer=SLAB)
# c << gf.components.bbox(component=c, layer=CLAD, top=margin, right=margin)
# c << gf.components.bbox( # also enclose beam frame
# component=c,
# layer=CLAD,
# top=max(margin, R + margin - W / 2),
# right=max(margin, R + margin - x_design - L),
# )
x_fiber = np.sin(theta) * (port_offset + source_offset)
c << gf.components.bbox( # enclose beam frame, as in GC
component=c,
layer=CLAD,
top=margin,
right=max(0, x_fiber + R - c.xmax),
)
c.add_port("o1", center=(x_wg, 0), width=w_wg / 2, orientation=180, layer=WG)
c.plot()
frames = [
lumi.plane_frame(
"wg",
start=[-w_wg / 2 - margin, -zmargin],
stop=[0, h_wg+zmargin],
boundaries=[("PML", "PEC"), "PML"],
wls_mode_solver=[wl],
),
lumi.plane_frame(
"beam",
modes=[
[
lumi.gaussian_mode(
D,
n_clad,
dx=dx,
theta=theta,
wl=wl,
half="y+",
Dlim=2*R,
)
]
],
start=[-R, 0],
stop=[R, R],
),
]
# origin = [
# np.sin(theta) * (source_offset + port_offset),
# 0,
# h_wg + port_offset + source_offset,
# ]
origin = [x_fiber, 0, h_wg + port_offset] # source and beam monitor at same point, as in GC
basis = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
sources = [
lumi.source(
"o2",
origin,
basis,
wl=wl,
bandwidth=max(max(wls) - min(wls), wl / 8),
frame="beam",
)
]
# origin = [np.sin(theta) * (port_offset), 0, h_wg + port_offset]
monitors = [
lumi.gf_monitor("o1", c, layer_stack, frame="wg"),
lumi.monitor("o2", origin, basis, frame="beam"),
]
designs = [
lumi.design(
name="design",
lmin =lmin,
layer=DESIGN,
contour_layer=CONTOUR,
fill_material=core,
void_material=clad,
component=c,
layer_stack=layer_stack,
materials=materials,
repdims=[3],
anchordims=[],
)
]
tmax = 1./ wl * (
(port_offset + source_offset + 2 * h_box) / np.cos(theta) * n_clad
+ (L + W / 2 + R + l_wg) * n_core
) + sources[0]["duration"]
bbox = c.bbox_np().tolist()
bbox[0].append(zmin)
bbox[1].append(zmax)Solve¶
lumi.mesh(path, c, layer_stack, materials, zmin, zmax)
lumi.setup(
path=path,
wl=wl,
wls=wls,
frames=frames,
monitors=monitors,
sources=sources,
boundaries=boundaries,
bbox=bbox,
materials=materials,
background=background,
nres=nres,
tmax=tmax,
PML_decay=PML_decay,
courant=courant,
shutoff=shutoff,
shot_every=shot_every,
views=views,
designs=designs,
targets=targets,
optimizer=optimizer,
# load_designs=['design']
)Warning: boolean difference failed at index 1: Difference only defined over two meshes.

using simulation folder runs/GC_invd
lumi.solve(path)========================================
backend using simulation folder runs/GC_invd
========================================
setting up simulation...
processing geometry bodies...
generating voxels...
voxelation: 41.634453 seconds (3.34 G allocations: 129.393 GiB, 26.82% gc time, 50.22% compilation time)
Yee mode λ=1.0: neff 2.4592
making sources o2 ...
making monitors o1 o2 ...
making designs design ...
========================================
run: runs/GC_invd
processor: GPU
cpu threads: 48
nres: 10.0
courant: 0.95
subpixel_smoothing: 1
boundaries: [:PML :PML; :PEC :PML; :PML :PML]
sources
o2: 0.15, 0, 1.22
monitors
o1: -21.85, 0, 0
o2: 0.15, 0, 1.22
original size: (644, 219, 46)
padded size: (669, 224, 70)
cell count: 10,489,920
step size: 52.0 steps/period
source duration: 3.94 periods
max time: 131.08 periods
max steps: 6,816
max load: 66,957,159,360 cell-steps
starting optimization... first iter will be slow due to adjoint compilation.
[1]
saving designs to runs/GC_invd/designs...
========================================
running simulation...
applying design region: design
grad ckpt at 568
simulation completed.
- o2@0-->o1@0+ λ=1.5450000000000002 target=1 value=0.007410095209840333 loss=0.33086331145721465
- o2@0-->o1@0+ λ=1.55 target=1 value=0.0074051009168767164 loss=0.3308649762215855
- o2@0-->o1@0+ λ=1.555 target=1 value=0.007389885359062612 loss=0.33087004807434134
loss: 0.9925983357531416
gradient: 287.4 s
122
design regions change fracs: Any[0.031101296f0]
memory usage: 16.52 GB / 189.91 GB (8.7%)
GPU memory usage: 46.02 GB / 101.98 GB (45.1%)
losses: Any[0.9925983357531416]
[2]
saving designs to runs/GC_invd/designs...
========================================
running simulation...
applying design region: design
grad ckpt at 568
simulation completed.
- o2@0-->o1@0+ λ=1.5450000000000002 target=1 value=0.22203296913667384 loss=0.2593223513495168
- o2@0-->o1@0+ λ=1.55 target=1 value=0.16833435627792298 loss=0.2772218895025482
- o2@0-->o1@0+ λ=1.555 target=1 value=0.12327298728738414 loss=0.2922423462803723
loss: 0.8287865871324374
gradient: 88.4 s
0
design regions change fracs: Any[0.07527309f0, 0.031101296f0]
memory usage: 16.8 GB / 189.91 GB (8.8%)
GPU memory usage: 62.7 GB / 101.98 GB (61.5%)
losses: Any[0.8287865871324374, 0.9925983357531416]
[3]
saving designs to runs/GC_invd/designs...
========================================
running simulation...
applying design region: design
grad ckpt at 568
simulation completed.
- o2@0-->o1@0+ λ=1.5450000000000002 target=1 value=0.006324775446843299 loss=0.3312250847223287
- o2@0-->o1@0+ λ=1.55 target=1 value=0.0021602148490916075 loss=0.3326132716296171
- o2@0-->o1@0+ λ=1.555 target=1 value=0.00467279179498208 loss=0.33177574595602677
loss: 0.9956141023079726
gradient: 86.9 s
0
design regions change fracs: Any[0.0160665f0, 0.07527309f0, 0.031101296f0]
memory usage: 16.8 GB / 189.91 GB (8.8%)
GPU memory usage: 62.7 GB / 101.98 GB (61.5%)
losses: Any[0.9956141023079726, 0.8287865871324374, 0.9925983357531416]
[4]
saving designs to runs/GC_invd/designs...
========================================
running simulation...
applying design region: design
grad ckpt at 568
simulation completed.
- o2@0-->o1@0+ λ=1.5450000000000002 target=1 value=0.007553675276326484 loss=0.3308154514336263
- o2@0-->o1@0+ λ=1.55 target=1 value=0.0182919647819539 loss=0.3272360214917418
- o2@0-->o1@0+ λ=1.555 target=1 value=0.036983045750057716 loss=0.3210056609833613
loss: 0.9790571339087295
gradient: 88.5 s
0
design regions change fracs: Any[0.0075287675f0, 0.0160665f0, 0.07527309f0, 0.031101296f0]
memory usage: 17.09 GB / 189.91 GB (9.0%)
GPU memory usage: 62.7 GB / 101.98 GB (61.5%)
losses: Any[0.9790571339087295, 0.9956141023079726, 0.8287865871324374, 0.9925983357531416]
[5]
saving designs to runs/GC_invd/designs...
========================================
running simulation...
applying design region: design
grad ckpt at 568
simulation completed.
- o2@0-->o1@0+ λ=1.5450000000000002 target=1 value=0.025431909790867055 loss=0.3248560397511751
- o2@0-->o1@0+ λ=1.55 target=1 value=0.05029233472626766 loss=0.31656923119240876
- o2@0-->o1@0+ λ=1.555 target=1 value=0.07589517523512194 loss=0.30803495076844933
loss: 0.9494602217120333
gradient: 88.1 s
0
design regions change fracs: Any[0.008995501f0, 0.0075287675f0, 0.0160665f0, 0.07527309f0, 0.031101296f0]
memory usage: 17.01 GB / 189.91 GB (9.0%)
GPU memory usage: 62.7 GB / 101.98 GB (61.5%)
losses: Any[0.9494602217120333, 0.9790571339087295, 0.9956141023079726, 0.8287865871324374, 0.9925983357531416]
[6]
saving designs to runs/GC_invd/designs...
========================================
running simulation...
applying design region: design
grad ckpt at 568
simulation completed.
- o2@0-->o1@0+ λ=1.5450000000000002 target=1 value=0.07287276686719767 loss=0.309042420254449
- o2@0-->o1@0+ λ=1.55 target=1 value=0.11070054827106993 loss=0.29643315941070636
- o2@0-->o1@0+ λ=1.555 target=1 value=0.13449131313399604 loss=0.28850290422005764
loss: 0.8939784838852131
gradient: 88.3 s
0
design regions change fracs: Any[0.013277924f0, 0.008995501f0, 0.0075287675f0, 0.0160665f0, 0.07527309f0, 0.031101296f0]
memory usage: 17.0 GB / 189.91 GB (9.0%)
GPU memory usage: 62.7 GB / 101.98 GB (61.5%)
losses: Any[0.8939784838852131, 0.9494602217120333, 0.9790571339087295, 0.9956141023079726, 0.8287865871324374, 0.9925983357531416]
[7]
saving designs to runs/GC_invd/designs...
========================================
running simulation...
applying design region: design
grad ckpt at 568
simulation completed.
- o2@0-->o1@0+ λ=1.5450000000000002 target=1 value=0.17841433158514153 loss=0.2738618976333398
- o2@0-->o1@0+ λ=1.55 target=1 value=0.20622742810668607 loss=0.26459086518319336
- o2@0-->o1@0+ λ=1.555 target=1 value=0.20216734330090608 loss=0.2659442268254533
loss: 0.8043969896419865
gradient: 88.3 s
0
design regions change fracs: Any[0.018912883f0, 0.013277924f0, 0.008995501f0, 0.0075287675f0, 0.0160665f0, 0.07527309f0, 0.031101296f0]
memory usage: 17.36 GB / 189.91 GB (9.1%)
GPU memory usage: 62.7 GB / 101.98 GB (61.5%)
losses: Any[0.8043969896419865, 0.8939784838852131, 0.9494602217120333, 0.9790571339087295, 0.9956141023079726, 0.8287865871324374, 0.9925983357531416]
[8]
saving designs to runs/GC_invd/designs...
========================================
running simulation...
applying design region: design
grad ckpt at 568
simulation completed.
- o2@0-->o1@0+ λ=1.5450000000000002 target=1 value=0.33150990218552157 loss=0.22283003924567862
- o2@0-->o1@0+ λ=1.55 target=1 value=0.3215183398196239 loss=0.2261605601335684
- o2@0-->o1@0+ λ=1.555 target=1 value=0.2806468736260093 loss=0.23978438260412818
loss: 0.6887749819833752
gradient: 87.9 s
0
design regions change fracs: Any[0.017943926f0, 0.018912883f0, 0.013277924f0, 0.008995501f0, 0.0075287675f0, 0.0160665f0, 0.07527309f0, 0.031101296f0]
memory usage: 17.37 GB / 189.91 GB (9.1%)
GPU memory usage: 62.7 GB / 101.98 GB (61.5%)
losses: Any[0.6887749819833752, 0.8043969896419865, 0.8939784838852131, 0.9494602217120333, 0.9790571339087295, 0.9956141023079726, 0.8287865871324374, 0.9925983357531416]
[9]
saving designs to runs/GC_invd/designs...
========================================
running simulation...
applying design region: design
grad ckpt at 568
simulation completed.
- o2@0-->o1@0+ λ=1.5450000000000002 target=1 value=0.37035222514659233 loss=0.20988259787279123
- o2@0-->o1@0+ λ=1.55 target=1 value=0.33998340398345156 loss=0.22000553856219196
- o2@0-->o1@0+ λ=1.555 target=1 value=0.2959790784243939 loss=0.23467364751902153
loss: 0.6645617839540048
gradient: 87.9 s
0
design regions change fracs: Any[0.011753262f0, 0.017943926f0, 0.018912883f0, 0.013277924f0, 0.008995501f0, 0.0075287675f0, 0.0160665f0, 0.07527309f0, 0.031101296f0]
memory usage: 17.11 GB / 189.91 GB (9.0%)
GPU memory usage: 62.7 GB / 101.98 GB (61.5%)
losses: Any[0.6645617839540048, 0.6887749819833752, 0.8043969896419865, 0.8939784838852131, 0.9494602217120333, 0.9790571339087295, 0.9956141023079726, 0.8287865871324374, 0.9925983357531416]
[10]
saving designs to runs/GC_invd/designs...
========================================
running simulation...
applying design region: design
grad ckpt at 568
simulation completed.
- o2@0-->o1@0+ λ=1.5450000000000002 target=1 value=0.43177251721774396 loss=0.18940916657225154
- o2@0-->o1@0+ λ=1.55 target=1 value=0.40031868629541467 loss=0.1998937771921604
- o2@0-->o1@0+ λ=1.555 target=1 value=0.36256305082924134 loss=0.2124789893892867
loss: 0.6017819331536987
gradient: 88.1 s
0
design regions change fracs: Any[0.008445494f0, 0.011753262f0, 0.017943926f0, 0.018912883f0, 0.013277924f0, 0.008995501f0, 0.0075287675f0, 0.0160665f0, 0.07527309f0, 0.031101296f0]
memory usage: 17.0 GB / 189.91 GB (9.0%)
GPU memory usage: 62.7 GB / 101.98 GB (61.5%)
losses: Any[0.6017819331536987, 0.6645617839540048, 0.6887749819833752, 0.8043969896419865, 0.8939784838852131, 0.9494602217120333, 0.9790571339087295, 0.9956141023079726, 0.8287865871324374, 0.9925983357531416]
[11]
saving designs to runs/GC_invd/designs...
========================================
running simulation...
applying design region: design
grad ckpt at 568
simulation completed.
- o2@0-->o1@0+ λ=1.5450000000000002 target=1 value=0.46582465226074077 loss=0.17805845455297506
- o2@0-->o1@0+ λ=1.55 target=1 value=0.4432099904743567 loss=0.18559667537309288
- o2@0-->o1@0+ λ=1.555 target=1 value=0.41178579310660457 loss=0.19607140814118162
loss: 0.5597265380672496
gradient: 87.6 s
0
design regions change fracs: Any[0.0069551356f0, 0.008445494f0, 0.011753262f0, 0.017943926f0, 0.018912883f0, 0.013277924f0, 0.008995501f0, 0.0075287675f0, 0.0160665f0, 0.07527309f0, 0.031101296f0]
memory usage: 17.31 GB / 189.91 GB (9.1%)
GPU memory usage: 62.7 GB / 101.98 GB (61.5%)
losses: Any[0.5597265380672496, 0.6017819331536987, 0.6645617839540048, 0.6887749819833752, 0.8043969896419865, 0.8939784838852131, 0.9494602217120333, 0.9790571339087295, 0.9956141023079726, 0.8287865871324374, 0.9925983357531416]
[12]
saving designs to runs/GC_invd/designs...
========================================
running simulation...
applying design region: design
grad ckpt at 568
simulation completed.
- o2@0-->o1@0+ λ=1.5450000000000002 target=1 value=0.5199442295207402 loss=0.1600185949286789
- o2@0-->o1@0+ λ=1.55 target=1 value=0.5064896892791368 loss=0.16450344180953885
- o2@0-->o1@0+ λ=1.555 target=1 value=0.4771887559705765 loss=0.17427041987013758
loss: 0.49879245660835536
gradient: 88.5 s
0
design regions change fracs: Any[0.0064944597f0, 0.0069551356f0, 0.008445494f0, 0.011753262f0, 0.017943926f0, 0.018912883f0, 0.013277924f0, 0.008995501f0, 0.0075287675f0, 0.0160665f0, 0.07527309f0, 0.031101296f0]
memory usage: 17.33 GB / 189.91 GB (9.1%)
GPU memory usage: 62.7 GB / 101.98 GB (61.5%)
losses: Any[0.49879245660835536, 0.5597265380672496, 0.6017819331536987, 0.6645617839540048, 0.6887749819833752, 0.8043969896419865, 0.8939784838852131, 0.9494602217120333, 0.9790571339087295, 0.9956141023079726, 0.8287865871324374, 0.9925983357531416]
[13]
saving designs to runs/GC_invd/designs...
========================================
running simulation...
applying design region: design
grad ckpt at 568
simulation completed.
- o2@0-->o1@0+ λ=1.5450000000000002 target=1 value=0.600840846543404 loss=0.1330530551174886
- o2@0-->o1@0+ λ=1.55 target=1 value=0.5863243815380769 loss=0.1378918769301391
- o2@0-->o1@0+ λ=1.555 target=1 value=0.5443747601869448 loss=0.15187508446391518
loss: 0.4228200165115429
gradient: 87.9 s
0
design regions change fracs: Any[0.0063520023f0, 0.0064944597f0, 0.0069551356f0, 0.008445494f0, 0.011753262f0, 0.017943926f0, 0.018912883f0, 0.013277924f0, 0.008995501f0, 0.0075287675f0, 0.0160665f0, 0.07527309f0, 0.031101296f0]
memory usage: 17.15 GB / 189.91 GB (9.0%)
GPU memory usage: 62.7 GB / 101.98 GB (61.5%)
losses: Any[0.4228200165115429, 0.49879245660835536, 0.5597265380672496, 0.6017819331536987, 0.6645617839540048, 0.6887749819833752, 0.8043969896419865, 0.8939784838852131, 0.9494602217120333, 0.9790571339087295, 0.9956141023079726, 0.8287865871324374, 0.9925983357531416]
[14]
saving designs to runs/GC_invd/designs...
========================================
running simulation...
applying design region: design
grad ckpt at 568
simulation completed.
- o2@0-->o1@0+ λ=1.5450000000000002 target=1 value=0.6634782352325986 loss=0.11217392493217716
- o2@0-->o1@0+ λ=1.55 target=1 value=0.637108531619806 loss=0.12096382639840085
- o2@0-->o1@0+ λ=1.555 target=1 value=0.5766205581595777 loss=0.14112648481937098
loss: 0.37426423614994897
gradient: 88.6 s
saving masks to runs/GC_invd/designs...
Movie¶
lumi.movie(path)Loading...