Skip to content

Commit

Permalink
No commit message
Browse files Browse the repository at this point in the history
  • Loading branch information
paulxshen committed Jul 3, 2024
1 parent 5080fe0 commit 8343ab9
Show file tree
Hide file tree
Showing 26 changed files with 130 additions and 123 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
/*.mp4
/.vscode
docs/build/
/lumi_runs
/lumi/dist
8 changes: 4 additions & 4 deletions docs/luminescent.html
Original file line number Diff line number Diff line change
Expand Up @@ -7618,7 +7618,7 @@ <h2 id="Inverse-design-with-GCells">Inverse design with GCells<a class="anchor-l
<span class="kn">import</span> <span class="nn">luminescent</span> <span class="k">as</span> <span class="nn">lumi</span>

<span class="n">name</span> <span class="o">=</span> <span class="s2">"demux"</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">lumi</span><span class="o">.</span><span class="n">gcells</span><span class="o">.</span><span class="n">mimo</span><span class="p">(</span><span class="n">l</span><span class="o">=</span><span class="mf">4.0</span><span class="p">,</span> <span class="n">w</span><span class="o">=</span><span class="mf">4.0</span><span class="p">,</span> <span class="n">m</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">wwg</span><span class="o">=</span><span class="mf">.5</span><span class="p">)</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">lumi</span><span class="o">.</span><span class="n">gcells</span><span class="o">.</span><span class="n">mimo</span><span class="p">(</span><span class="n">l</span><span class="o">=</span><span class="mf">4.0</span><span class="p">,</span> <span class="n">w</span><span class="o">=</span><span class="mf">4.0</span><span class="p">,</span> <span class="n">nwest</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">neast</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">wwg</span><span class="o">=</span><span class="mf">.5</span><span class="p">)</span>
<span class="n">targets</span> <span class="o">=</span> <span class="p">{</span>
<span class="mf">1.55</span><span class="p">:</span> <span class="p">{</span>
<span class="s2">"2,1"</span><span class="p">:</span> <span class="mf">1.0</span>
Expand All @@ -7633,12 +7633,12 @@ <h2 id="Inverse-design-with-GCells">Inverse design with GCells<a class="anchor-l
<span class="n">lmin</span><span class="o">=</span><span class="mf">0.2</span><span class="p">,</span> <span class="n">dx</span><span class="o">=</span><span class="mf">0.05</span><span class="p">,</span> <span class="n">maxiters</span><span class="o">=</span><span class="mi">40</span><span class="p">,</span> <span class="n">eta</span><span class="o">=</span><span class="mf">10.</span><span class="p">,</span> <span class="n">approx_2D</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="n">sol</span> <span class="o">=</span> <span class="n">lumi</span><span class="o">.</span><span class="n">solve</span><span class="p">(</span><span class="n">prob</span><span class="p">)</span>

<span class="c1"># sol = lumi.load_solution()</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"post optim tparams:"</span><span class="p">)</span>
<span class="n">pprint</span><span class="p">(</span><span class="n">sol</span><span class="p">[</span><span class="s2">"after"</span><span class="p">][</span><span class="s2">"tparams"</span><span class="p">])</span>

<span class="n">c</span> <span class="o">=</span> <span class="n">sol</span><span class="p">[</span><span class="s2">"after"</span><span class="p">][</span><span class="s2">"component"</span><span class="p">]</span>
<span class="n">c</span><span class="o">.</span><span class="n">write_gds</span><span class="p">(</span><span class="sa">f</span><span class="s2">"optimal_</span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2">.gds"</span><span class="p">,</span> <span class="s2">""</span><span class="p">)</span>
<span class="n">c</span><span class="o">.</span><span class="n">plot</span><span class="p">()</span>
<span class="c1"># c = sol["after"]["component"]</span>
<span class="c1"># c.write_gds(f"optimal_{name}.gds", "")</span>
</pre></div>
</div>
</div>
Expand Down
Binary file modified lumi/dist/luminescent-0.1.4-py3-none-any.whl
Binary file not shown.
Binary file modified lumi/dist/luminescent-0.1.4.tar.gz
Binary file not shown.
8 changes: 4 additions & 4 deletions lumi/docs/luminescent.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
"import luminescent as lumi\n",
"\n",
"name = \"demux\"\n",
"c = lumi.gcells.mimo(l=4.0, w=4.0, m=1, n=2, wwg=.5)\n",
"c = lumi.gcells.mimo(l=4.0, w=4.0, nwest=1, neast=2, wwg=.5)\n",
"targets = {\n",
" 1.55: {\n",
" \"2,1\": 1.0\n",
Expand All @@ -130,12 +130,12 @@
" lmin=0.2, dx=0.05, maxiters=40, eta=10., approx_2D=True)\n",
"sol = lumi.solve(prob)\n",
"\n",
"# sol = lumi.load_solution()\n",
"print(\"post optim tparams:\")\n",
"pprint(sol[\"after\"][\"tparams\"])\n",
"\n",
"c = sol[\"after\"][\"component\"]\n",
"c.write_gds(f\"optimal_{name}.gds\", \"\")\n",
"c.plot()\n"
"# c = sol[\"after\"][\"component\"]\n",
"# c.write_gds(f\"optimal_{name}.gds\", \"\")\n"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion lumi/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "luminescent"
version = "0.1.4"
version = "0.1.7"
description = "Lumi FDTD by Luminescent AI is a GPU and automatic differentiation (AD) compatible FDTD package for simulation and inverse design in semiconductor photonics. Create layout in gdsfactory. Then use the Lumi Python plugin for calculating sparams or perform inverse design on Lumi's Julia backend."
authors = ["Paul Shen"]
license = "MIT"
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
43 changes: 22 additions & 21 deletions lumi/src/luminescent/gplugins/luminescent/gcells.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ def bend(r, wwg=.5, lwg=1, LAYER=LAYER, **kwargs):
return c


def mimo(l, w, wwg, m, n,
def mimo(l, w, wwg,
nwest=0, nnorth=0, neast=0, nsouth=0,
layer_wg=LAYER.WG, layer_wgclad=LAYER.WGCLAD, layer_box=LAYER.BOX, layer_design=LAYER.DESIGN,
**kwargs):
design = gf.Component()
Expand All @@ -64,26 +65,26 @@ def mimo(l, w, wwg, m, n,
design.add_polygon(p, layer=layer_design)
c.add_polygon(p, layer=layer_wg)

din = w/m
dout = w/n
yin = din/2
yout = dout/2
for i in range(m):
name = "o"+str(i+1)
design.add_port(name=name, center=(0, yin), width=wwg,
orientation=180, layer=layer_wg)
wg = c << gf.components.straight(length=lwg, width=wwg, layer=layer_wg)
wg.connect("o2", design.ports[name])
c.add_port(name=name, port=wg.ports["o1"])
yin += din
for i in range(n):
name = "o"+str(i+1+m)
design.add_port(name=name, center=(l, yout), width=wwg,
orientation=0, layer=layer_wg)
wg = c << gf.components.straight(length=lwg, width=wwg, layer=layer_wg)
wg.connect("o2", design.ports[name])
c.add_port(name=name, port=wg.ports["o1"])
yout += dout
j = 0
for (n, x, y, dx, dy, a) in zip(
[nwest, nnorth, neast, nsouth],
[0, 0, l, l],
[0, w, w, 0],
[0, l/max(1,nnorth), 0, -l/max(1,nsouth)],
[w/max(1,nwest), 0, -w/max(1,neast), 0],
[180, 90, 0, -90]
):
for i in range(n):

name = "o"+str(i+j+1)
design.add_port(name=name, center=(x+dx*(i+.5), y+dy*(i+.5)), width=wwg,
orientation=a, layer=layer_wg)
wg = c << gf.components.straight(
length=lwg, width=wwg, layer=layer_wg)
wg.connect("o2", design.ports[name])
c.add_port(name=name, port=wg.ports["o1"])
j += n

design = c << design
c = add_bbox(c, layers=[layer_wgclad, layer_box],
nonport_margin=XMARGIN)
Expand Down
32 changes: 17 additions & 15 deletions lumi/src/luminescent/gplugins/luminescent/run.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ verbose = false
#=
We load design layout which includes a 2d device of device waveguide geometry as well as variables with locations of ports, sources, design regions and material properties.
=#
@load PROB_PATH name runs ports λc dx components study mode_solutions eps_2D eps_3D mode_height zmin gpu_backend d
@load PROB_PATH name portsides runs ports λc dx components study mode_solutions eps_2D eps_3D mode_height zmin gpu_backend d
eps_2D = F(stack(stack.(eps_2D)))'
eps_3D = F(permutedims(stack(stack.(eps_3D)), (3, 2, 1)))
# heatmap(eps_2D) |> display
Expand All @@ -49,14 +49,17 @@ ports, = (ports,) .|> SortedDict
polarization = :TE

_dx = dx / λc
m = round(SOURCE_MARGIN / dx)
m = round(SOURCE_MARGIN / _dx)
source_margin = m * dx
n = round(PORT_SOURCE_OFFSET / dx)
n = round(PORT_SOURCE_OFFSET / _dx)
port_source_offset = n * dx
# device = pad(device, :replicate, n)
eps_2D = pad(eps_2D, :replicate, m + n)
eps_3D = pad(eps_3D, :replicate, (m + n, m + n, 0))
origin = components.device.bbox[1] - (m + n) * dx
xy = (m + n) * portsides
eps_2D = pad(eps_2D, :replicate, xy...)
origin = components.device.bbox[1] - dx * xy[1]
push!(xy[1], 0)
push!(xy[2], 0)
eps_3D = pad(eps_3D, :replicate, xy...)
# heatmap(eps_2D) |> display

if study == "inverse_design"
Expand Down Expand Up @@ -136,17 +139,15 @@ for ms = mode_solutions
mode = keepxy(mode)
global mode0 = deepcopy(mode)

if calibrate
if calibrate && d == 2
@unpack mode, power = calibrate_mode(mode, ϵmode, dx / λc)
# global mode /= sqrt(power)
# plot(abs.(mode.Ex)) |> display
# plot(abs.(mode0.Ex)) |> display
@unpack power, = calibrate_mode(mode, ϵmode, dx / λc;)
mode /= sqrt(power)
# @unpack power, = calibrate_mode(mode, ϵmode, dx / λc;)
# mode /= sqrt(power)

@unpack power, sol = calibrate_mode(mode, ϵmode, dx / λc; verbose=true)
MyMakie.save(joinpath(path, "calibration.png"), quickie(sol),)
@show power
# @unpack power, sol = calibrate_mode(mode, ϵmode, dx / λc; verbose=true)
# MyMakie.save(joinpath(path, "calibration.png"), quickie(sol),)
# @show power
# global mode2 = deepcopy(mode)
end

Expand All @@ -169,7 +170,8 @@ runs_sources = [
i = findfirst(mode_solutions) do v
isapprox(λ, v.wavelength) && string(port) in string.(v.ports)
end
mode = mode_solutions[i].calibrated_modes[mn+1]
ms = mode_solutions[i]
mode = ms.calibrated_modes[mn+1]
# sum(abs.(aa.source_instances[1].g.Jy))
# heatmap(abs.(bb.source_instances[1]._g.Jy))
n = -sig.normal
Expand Down
1 change: 1 addition & 0 deletions lumi/src/luminescent/gplugins/luminescent/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ def setup(c, study, center_wavelength, dx,

m = round(center_wavelength/2/dx)*dx
# prob["margins"] = [[m, m], [m, m]]
prob["portsides"] = portsides(c)
return prob


Expand Down
2 changes: 1 addition & 1 deletion lumi/src/luminescent/gplugins/luminescent/snapshot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ function _plot!(g, a, ; colorrange=nothing, title="", colormap=:seismic, algorit
end
if ndims(a) == 3
println("3D array: plotting middle slice")
title *= " (middle slice of 3D array)"
a = a[:, :, round(Int, size(a, 3) / 2)]
end
aspect = size(a, 1) / size(a, 2)
Expand All @@ -32,7 +33,6 @@ function _plot!(g, a, ; colorrange=nothing, title="", colormap=:seismic, algorit
Colorbar(g[1, 2], pl)
end
end

function quickie(sol; kw...)
@unpack fields, geometry = sol
fig = Figure()
Expand Down
6 changes: 2 additions & 4 deletions lumi/src/luminescent/gplugins/luminescent/src/constants.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@

margin_offset = 0.1
PORT_SOURCE_OFFSET = 0.6
PORT_SOURCE_OFFSET = 0.5
SOURCE_MARGIN = 0.1
MODE_MARGIN = 0.0
MODE_MARGIN = 0.2
34 changes: 14 additions & 20 deletions lumi/src/luminescent/gplugins/luminescent/src/photonics.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
function calibrate_mode(mode, ϵmode, dx, λ=1.55; F=Float32, verbose=false, name="", kwargs...)
mode, ϵmode, dx, λ = (mode, ϵmode, dx, λ) |> F
function calibrate_mode(mode, ϵmode, dx, ; F=Float32, verbose=false, name="", kwargs...)
# mode, ϵmode, dx, = (mode, ϵmode, dx,) |> F
d = ndims(ϵmode) + 1
n = sqrt(mean(ϵmode))

source_monitor_margin, source_boundary_margin, mode_margin = whole.((SOURCE_MONITOR_MARGIN, SOURCE_BOUNDARY_MARGIN, MODE_MARGIN), dx) / λ
l0 = 0.8
l = l0 + source_boundary_margin + source_monitor_margin
source_margin, port_source_offset, mode_margin = whole.((SOURCE_MARGIN, PORT_SOURCE_OFFSET, MODE_MARGIN), dx)
l0 = 2
l = l0 + port_source_offset + source_margin

# wm = wwg / 2
# w = 2wm + wwg
Expand All @@ -16,32 +16,26 @@ function calibrate_mode(mode, ϵmode, dx, λ=1.55; F=Float32, verbose=false, nam
ϵ = stack(fill(ϵmode, sz[1]))
if d == 2
ϵ = ϵ'
ϵ = pad(ϵ, :replicate, (0, round(mode_margin / dx)))
else
ϵ = permutedims(ϵ, (3, 1, 2))
end
# n = round(mode_margin / dx)
# ϵ = pad(ϵ, :replicate, (0, n), (0, n))
# ϵ |> heatmap |> display
# ϵ[1+round(wm / dx):end-round(wm / dx)] .= ϵ2
sz = size(ϵ)
l, w, = sz * dx

normal = [1, zeros(d - 1)...]
tangent = [0, -1, zeros(d - 2)...]
m = [ModalMonitor(mode, [x, (L / 2)...], normal, tangent, L) for x = range(0, l0, 3) + source_monitor_margin + source_boundary_margin]
s = ModalSource(t -> cispi(2t), mode, [source_monitor_margin, (L / 2)...], -normal, tangent, L;)
m = [ModalMonitor(mode, [x, w / 2], normal, tangent, L) for x = range(0, l0, 3) + source_margin + port_source_offset]
s = ModalSource(t -> cispi(2t), mode, [source_margin, w / 2], -normal, tangent, L;)

prob = setup([], [s], m, dx, sz; F, ϵ, verbose)
global aa = prob
sol = solve(prob; comprehensive=true, verbose=true,)
sol = solve(prob)

@unpack fields, modes, forward_mode_powers = sol
mode = modes[1][1]
# global a, b = modes, mode
power = forward_mode_powers[1][1][1]
@show forward_mode_powers
(; mode, power, sol)
# recordsim("$(@__DIR__)/$name.mp4", h, ;
# dt,
# field=:Hz,
# monitor_instances,
# source_instances,
# geometry=p.ϵ.ϵyy,
# )

end
9 changes: 5 additions & 4 deletions lumi/src/luminescent/gplugins/luminescent/src/sources.jl
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,13 @@ end

function SourceInstance(s::ModalSource, dx, sizes, common_left_pad_amount, fl, sz0; F=Float32)
@unpack f, center, lb, ub, normal, tangent, meta = s
fields = DefaultDict([0],)
C = complex(F)
J = dict([:Jx => [C(0)], :Jy => [C(0)], :Jz => [C(0)]])
for k = keys(s.mode)
fields[k] = s.mode[k]
J[k] = s.mode[k]
end
@unpack Jx, Jy, Jz = fields
J = values(J)

L = ub .- lb
sz = max.(1, round.(Int, L ./ dx)) |> Tuple
d = length(lb)
Expand All @@ -147,7 +149,6 @@ function SourceInstance(s::ModalSource, dx, sizes, common_left_pad_amount, fl, s
end

frame = [xaxis, yaxis, zaxis]
J = [Jx, Jy, Jz]
# J = resize.(J, (sz,))
J = reframe(frame, J)
if D == 2
Expand Down
5 changes: 3 additions & 2 deletions lumi/src/luminescent/gplugins/luminescent/src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ end
# Flux.gpu(d::T) where {T<:Dictlike} = dict(T, [k => Flux.gpu(d[k]) for k = keys(d)])
# Flux.cpu(d::T) where {T<:Dictlike} = dict(T, [k => Flux.cpu(d[k]) for k = keys(d)])

# Base.getproperty(d::AbstractDict, k::Symbol) = hasfield(d, k) ? getfield(d, k) : (haskey(d, k) ? d[k] : d[string(k)])
Base.getproperty(d::AbstractDict, k::Symbol) = hasproperty(d, k) ? getfield(d, k) : d[k]
# Base.Float16(x) = f16(x)
# Base.Float32(x) = f32(x)


footer = "Suppress this message by verbose=false\n2024 (c) Paul Shen at Luminescent AI\n<[email protected]>"
18 changes: 18 additions & 0 deletions lumi/src/luminescent/gplugins/luminescent/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,24 @@ def extend(endpoints, wm):
(endpoints[0]-wm*v).tolist(), (endpoints[1]+wm*v).tolist()]


def portsides(c):
res = [[False, False], [False, False]]
bbox = c.bbox_np()
xmin0, ymin0 = bbox[0]
xmax0, ymax0 = bbox[1]
for p in c.ports:
x, y = np.array(p.center)/1e3
if x == xmin0:
res[0][0] = True
if x == xmax0:
res[1][0] = True
if y == ymin0:
res[0][1] = True
if y == ymax0:
res[1][1] = True
return res


def add_bbox(c, layers, nonport_margin=0):
margin = nonport_margin
bbox = c.bbox_np()
Expand Down
2 changes: 1 addition & 1 deletion lumi/src/test_bend_sparams.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
# c.show()

sol = lumi.write_sparams(c, wavelengths=[1.55], keys=["2,1"],
dx=0.05, approx_2D=True, gpu=None,)
dx=0.05, approx_2D=False, gpu=None,)
# sol = lumi.load_solution()
pp.pprint(sol)
35 changes: 17 additions & 18 deletions lumi/src/test_demux_inverse_design.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,25 @@
import gdsfactory as gf
import luminescent as lumi

# name = "demux"
# c = lumi.gcells.mimo(l=4.0, w=4.0, m=1, n=2, wwg=.5)
# targets = {
# 1.55: {
# "2,1": 1.0
# },
# .85: {
# "3,1": 1.0
# }}
# c.show()
name = "demux"
c = lumi.gcells.mimo(l=4.0, w=4.0, nwest=1, neast=2, wwg=.5)
targets = {
1.55: {
"2,1": 1.0
},
.85: {
"3,1": 1.0
}}
c.show()

# prob = lumi.inverse_design_problem(
# c, tparam_targets=targets,
# lmin=0.2, dx=0.05, maxiters=40, eta=10., approx_2D=True)
# sol = lumi.solve(prob)
prob = lumi.inverse_design_problem(
c, tparam_targets=targets,
lmin=0.2, dx=0.05, maxiters=40, eta=10., approx_2D=True)
sol = lumi.solve(prob)

sol = lumi.load_solution()
# sol = lumi.load_solution()
print("post optim tparams:")
pprint(sol["after"]["tparams"])

c = sol["after"]["component"]
c.write_gds(f"optimal_{name}.gds", "")
c.plot()
# c = sol["after"]["component"]
# c.write_gds(f"optimal_{name}.gds", "")
Loading

0 comments on commit 8343ab9

Please sign in to comment.