diff --git a/examples/3d_dipole_antenna/3d_quarter_wavelength_antenna_nres_16.mp4 b/examples/3d_dipole_antenna/3d_quarter_wavelength_antenna_nres_16.mp4 index 61624c5..68d80d5 100644 Binary files a/examples/3d_dipole_antenna/3d_quarter_wavelength_antenna_nres_16.mp4 and b/examples/3d_dipole_antenna/3d_quarter_wavelength_antenna_nres_16.mp4 differ diff --git a/examples/3d_dipole_antenna/[simulation]_3d_dipole_antenna.jl b/examples/3d_dipole_antenna/[simulation]_3d_dipole_antenna.jl index 361b2e6..fea1f62 100644 --- a/examples/3d_dipole_antenna/[simulation]_3d_dipole_antenna.jl +++ b/examples/3d_dipole_antenna/[simulation]_3d_dipole_antenna.jl @@ -8,6 +8,9 @@ dir = pwd() include("$(dir)/src/main.jl") include("$dir/../FDTDToolkit.jl/src/main.jl") +dogpu = true +# dogpu = false + name = "3d_quarter_wavelength_antenna" T = 8.0f0 # simulation duration in [periods] nx = 16 @@ -37,17 +40,26 @@ p = apply(geometry_splits; ϵ, μ, σ, σm) t = 0:dt:T u = [[similar.(a) for a = u0] for t = t] u[1] = u0 +if dogpu# && + using CUDA, Flux + @assert CUDA.functional() + u, p, t, field_padding, source_instances = gpu.((u, p, t, field_padding, source_instances)) +end + @showtime reduce( (u, (u1, t)) -> step!(u1, u, p, t, dx, dt, field_padding, source_instances), - zip(u[2:end], t[1:end-1]), - init=u0) -y = hcat([power.((m,), u) for m = monitor_instances]...) + zip(u[2:end], t[2:end]), + init=u[1]) +y = [power.((m,), u) for m = monitor_instances] +if dogpu# && + u, p, t, field_padding, source_instances = cpu.((u, p, t, field_padding, source_instances)) +end Ez = map(u) do u u[1][3] end dir = @__DIR__ -@showtime recordsim("$dir/$(name)_nres_$nx.mp4", Ez, y; +recordsim("$dir/$(name)_nres_$nx.mp4", collect.(Ez), collect.(y); dt, monitor_instances, source_instances, diff --git a/examples/3d_periodic_scattering/3d_periodic_scattering.jl b/examples/3d_periodic_scattering/3d_periodic_scattering.jl index 3e1965d..a27ced7 100644 --- a/examples/3d_periodic_scattering/3d_periodic_scattering.jl +++ b/examples/3d_periodic_scattering/3d_periodic_scattering.jl @@ -6,8 +6,11 @@ using UnPack, LinearAlgebra, GLMakie # using FDTDEngine,FDTDToolkit dir = pwd() include("$(dir)/src/main.jl") +include("$(dir)/scripts/startup.jl") include("$dir/../FDTDToolkit.jl/src/main.jl") +dogpu = true +# dogpu = false name = "3d_scattering" T = 8.0f0 # simulation duration in [periods] @@ -46,20 +49,34 @@ p = apply(geometry_splits; ϵ, μ, σ, σm) t = 0:dt:T u = [[similar.(a) for a = u0] for t = t] u[1] = u0 -@showtime reduce( - (u, (u1, t)) -> step!(u1, u, p, t, dx, dt, field_padding, source_instances), - zip(u[2:end], t[1:end-1]), + +if dogpu# && + using CUDA, Flux + @assert CUDA.functional() + u, u0, p, t, field_padding, source_instances = gpu.((u, u0, p, t, field_padding, source_instances)) +end + +# @showtime reduce( +# (u, (u1, t)) -> step!(u1, u, p, t, dx, dt, field_padding, source_instances), +# zip(u[2:end], t[1:end-1]), +# init=u[1]) +@showtime u = accumulate( + (u, t) -> step!(deepcopy(u), p, t, dx, dt, field_padding, source_instances), + t, init=u0) -y = hcat([power.((m,), u) for m = monitor_instances]...) +y = [power.((m,), u) for m = monitor_instances] # make movie +if dogpu# && + u, p, t, field_padding, source_instances = cpu.((u, p, t, field_padding, source_instances)) +end Ez = map(u) do u u[1][3] end ϵz = p[1][3] dir = @__DIR__ - -recordsim("$dir/$(name)_nres_$nx.mp4", Ez, y; +# error() +recordsim("$dir/$(name)_nres_$nx.mp4", collect.(Ez), collect.(y); dt, monitor_instances, source_instances, diff --git a/examples/3d_periodic_scattering/3d_scattering_nres_16.mp4 b/examples/3d_periodic_scattering/3d_scattering_nres_16.mp4 index ff88763..cc7b0ba 100644 Binary files a/examples/3d_periodic_scattering/3d_scattering_nres_16.mp4 and b/examples/3d_periodic_scattering/3d_scattering_nres_16.mp4 differ diff --git a/makedocs/inverse_design_3d_silicon_photonics_splitter/inverse_design_3d_silicon_photonics_splitter copy.jl b/makedocs/inverse_design_3d_silicon_photonics_splitter/inverse_design_3d_silicon_photonics_splitter copy.jl deleted file mode 100644 index 4a341f1..0000000 --- a/makedocs/inverse_design_3d_silicon_photonics_splitter/inverse_design_3d_silicon_photonics_splitter copy.jl +++ /dev/null @@ -1,237 +0,0 @@ -using UnPack, LinearAlgebra, Random, StatsBase, Interpolations, Zygote, Jello, Flux -using Flux: mae, Adam -using Zygote: withgradient, Buffer, bufferfrom -using BSON: @save, @load -using Optim: Options, minimizer -using Optim - -using GLMakie -dir = pwd() -include("$dir/src/main.jl") -include("$dir/../FDTDToolkit.jl/src/main.jl") -include("$dir/scripts/startup.jl") - -# dir = "FDTDEngine.jl" -# using FDTDEngine,FDTDToolkit - - - -F = Float32 -Random.seed!(1) - -"training params" -name = "silicon_photonics_splitter" -nx = 16 -T = 18.0f0 # simulation duration in [periods] -nbasis = 4 # complexity of design region -Courant = 1.5 * 0.7 / √3# Courant number -C = 1000 # scale loss -λ = 1.55f0 -λ2 = 1.3f0 -nepochs = 16 -ω2 = λ / λ2 - -"geometry" -# loads design layout -include("layout.jl") -@unpack wwg, hwg, lwg, ld, hclad, hbox, l, w, h, wm, c, base, sources, ports, designs, dx = layout -ϵbox = ϵclad = ϵslab = 2.25f0 -ϵcore = 12.25f0 - -ϵ = sandwich(base, round.(Int, [hbox, hwg, hclad] / dx), [ϵbox, ϵcore, ϵclad]) -sz0 = size(ϵ) - -"boundaries" -boundaries = [] # unspecified boundaries default to PML - -"monitors" -z = [hbox, hbox + hwg] -n = [1, 0, 0] -monitors = [Monitor([x, y, z], n) for (x, y) = ports] -ox, oy, = c -oz = hbox -append!(monitors, [ - Monitor([ox, [oy, oy + ld], [oz, oz + hwg]], [-1, 0, 0]), - Monitor([ox + ld, [oy, oy + ld], [oz, oz + hwg]], [1, 0, 0]), - Monitor([[ox, ox + ld], oy, [oz, oz + hwg]], [0, -1, 0]), - Monitor([[ox, ox + ld], oy + ld, [oz, oz + hwg]], [0, 1, 0]), - Monitor([[ox, ox + ld], [oy, oy + ld], oz], [0, 0, -1]), - Monitor([[ox, ox + ld], [oy, oy + ld], oz + hwg], [0, 0, 1]), -]) - -"sources" - -@load "$(@__DIR__)/mode.bson" mode -@unpack Ex, Ey, Ez, bounds = mode -f32(x::Real) = Float32(x) -f32(x::AbstractArray) = f32.(x) -bounds = f32(bounds) -bounds /= λ -_dx = mode.dx / λ -Ex, Ey, Ez = [Ex, Ey, Ez] / maximum(maximum.(abs, [Ex, Ey, Ez])) -sy, sz = size.((Ex,), (1, 2)) -y = range(F.(bounds[1])..., sy) -z = range(F.(bounds[2])..., sz) - -f1 = t -> cos(F(2π) * t) -f2 = t -> cos(F(2π) * t * λ / λ2) -gEx = LinearInterpolation((y, z), F.(Ez)) -gEy = LinearInterpolation((y, z), F.(Ex)) -gEz = LinearInterpolation((y, z), F.(Ey)) -c = [sources[1]..., hbox] -bounds = [0, bounds...] -sources = [ - Source(t -> f1(t) + f2(t), c, bounds; - Jx=(x, y, z) -> gEx(y, z), - Jy=(x, y, z) -> gEy(y, z), - Jz=(x, y, z) -> gEz(y, z), - ), -] - -configs = setup(boundaries, sources, monitors, dx, sz0; F, Courant, T) -@unpack μ, σ, σm, dt, geometry_padding, geometry_splits, field_padding, source_instances, monitor_instances, u0, power = configs - - - -function make_geometry(model, μ, σ, σm) - - b = place(base, model(), round.(Int, c / dx) .+ 1) - ϵ = sandwich(b, round.(Int, [hbox, hwg, hclad] / dx), [ϵbox, ϵcore, ϵclad]) - ϵ, μ, σ, σm = apply(geometry_padding; ϵ, μ, σ, σm) - p = apply(geometry_splits; ϵ, μ, σ, σm) -end - - -# run pre or post optimization simulation and save movie -function savesim(sol, p, name=name) - E = map(sol) do u - # sqrt(sum(u) do u u.^2 end) - # u[1] .^ 2 - u[1] - end - dir = @__DIR__ - recordsim(E, p[1][1], configs, "$dir/$(name)_nres_$nx.mp4", title="$name"; playback=1, bipolar=false) -end -function monitor_powers(model, T=T; bufferfrom=bufferfrom) - p = make_geometry(model, μ, σ, σm) - # run simulation - u = reduce((u, t) -> step!(u, p, t, dx, dt, field_padding, source_instances; bufferfrom), 0:dt:T-1, init=deepcopy(u0)) - reduce(((u, pow), t) -> (step!(u, p, t, dx, dt, field_padding, source_instances; bufferfrom), begin - y = power.(monitor_instances, (u,)) - pow + dt * vcat( - cispi(2t) * y, cispi(2t * ω2) * y) - end), - T-1+dt:dt:T, init=(u, zeros(ComplexF32, 2length(monitor_instances))))[2] -end - -function loss(p) - p = abs.(p) - dot([-1, 1, 1, -1, 1, 1, 1, 1], p[2:9]) + dot([1, -1, 1, -1, 1, 1, 1, 1], p[11:18]) -end - -"geometry generator model" -contrast = 10.0f0 -nbasis = 4 -model = Mask(round.(Int, (ld, ld) ./ dx), nbasis, contrast)#, symmetries=2) -model0 = deepcopy(model) - - -tp = abs(monitor_powers(model, 2)[1]) -p0 = make_geometry(model0, μ, σ, σm) -# volume(p0[3][1]) - -"Optim functions" -x0, re = destructure(model) -f_ = loss ∘ monitor_powers -f = f_ ∘ re -function g!(storage, x) - model = re(x) - g, = gradient(f_, model) - storage .= realvec(g.a) -end -function fg!(storage, x) - model = re(x) - l, (g,) = withgradient(f_, model) - storage .= realvec(g.a) - l -end -x = copy(x0) -@show f(x) -# @show x|>re|>monitor_powers -# train surrogate -Random.seed!(1) -runs = [] -function f!(x) - @time begin - model = re(x) - mp = monitor_powers(model) - l = loss(mp) - push!(runs, (x0, mp, l)) - l - end -end - -@showtime res = optimize(f!, x0, ParticleSwarm(; - n_particles=16), Optim.Options(f_tol=0, iterations=44, show_every=1, show_trace=true)) -xgf = minimizer(res) - -# error() -X = Base.stack(getindex.(runs, 1)) -Y = Base.stack(getindex.(runs, 2)) - -nl = leakyrelu -n = size(X, 1) -m, N = size(Y) -nn = Chain(Dense(n, 2n, nl), Dense(2n, 4n, nl), Dense(4n, m)) - -opt = Adam(0.1) -opt_state = Flux.setup(opt, nn) -n = 100 -for i = 1:n - l, (dldm,) = withgradient(nn -> Flux.mae(Y, nn(X)), nn) - Flux.update!(opt_state, nn, dldm) - (i % 25 == 0 || i == n) && println("$i $l") -end - -opt = Adam(0.1) -x = copy(xgf) -opt_state = Flux.setup(opt, x) -n = 100 -@show f(x) -for i = 1:n - l, (dldm,) = withgradient(x -> mae(nn(x), - [tp / 2, tp / 2, 0, -tp / 2, tp / 2, zeros(F, 4)..., - tp / 2, 0, tp / 2, -tp / 2, tp / 2, zeros(F, 4)...,]), x) - Flux.update!(opt_state, x, dldm) - (i % 25 == 0 || i == n) && println("$i $l") -end -@show loss(nn(x)) -@show f(x) -xsg = x -x = copy(xsg) - -# runsavesim(model0) -# loss(model) -# # volume(p[1][1]) - -# @showtime sol = accumulate((u, t) -> step(u, p, t, field_padding, source_instances), 0:dt:T, init=u0) - - -# od = OnceDifferentiable(f, g!, fg!, x0) -# @showtime res = optimize(od, x0, LBFGS(), Optim.Options(f_tol=0, iterations=1, show_every=1, show_trace=true)) -# x_adjoint = re(minimizer(res)) - -model = re(x) -p = make_geometry(model, μ, σ, σm) -t = 0:dt:T -sol = similar([u0], length(t)) -@showtime sol = accumulate!((u, t) -> step!(u, p, t, dx, dt, field_padding, source_instances), sol, t, init=u0) - -# make movie -Ez = map(sol) do u - u[3] -end -ϵz = p[1][3] -dir = @__DIR__ -° = π / 180 -recordsim(Ez, ϵz, configs, "$dir/$(name)_nres_$nx.mp4", title="$name"; elevation=60°, playback=1, bipolar=true) diff --git a/makedocs/inverse_design_3d_silicon_photonics_splitter/inverse_design_3d_silicon_photonics_splitter.jl b/makedocs/inverse_design_3d_silicon_photonics_splitter/inverse_design_3d_silicon_photonics_splitter.jl index 27841aa..003f553 100644 --- a/makedocs/inverse_design_3d_silicon_photonics_splitter/inverse_design_3d_silicon_photonics_splitter.jl +++ b/makedocs/inverse_design_3d_silicon_photonics_splitter/inverse_design_3d_silicon_photonics_splitter.jl @@ -15,19 +15,26 @@ include("$dir/scripts/startup.jl") # using FDTDEngine,FDTDToolkit F = Float32 +dogpu = true +# dogpu = false +if dogpu# && + using CUDA, Flux + @assert CUDA.functional() +end Random.seed!(1) "training params" name = "silicon_photonics_splitter" -nx = 16 +nx = 24 T = 18.0f0 # simulation duration in [periods] nbasis = 4 # complexity of design region -ϵmin = 1.5 +ϵmin = 2.26 λ = 1.55f0 # wavelength [um] # loads design layout @load "$(@__DIR__)/layout.bson" layout @unpack wwg, base, sources, ports, designs, dx, = layout +base = F.(base) hcore = 0.22f0 / λ hclad = hsub = 0.2f0 / λ ϵsub = ϵclad = 2.25f0 @@ -37,8 +44,7 @@ sz0 = size(ϵdummy) "geometry generator model" contrast = 10.0f0 -nbasis = 4 -model = Mask(round.(Int, designs[1].L / dx), nbasis, contrast) +model = Mask(round.(Int, designs[1].L / dx) .+ 1, nbasis, contrast) model0 = deepcopy(model) "boundaries" @@ -81,45 +87,48 @@ sources = [ configs = setup(boundaries, sources, monitors, dx, sz0; ϵmin, T) @unpack μ, σ, σm, dt, geometry_padding, geometry_splits, field_padding, source_instances, monitor_instances, u0, = configs nt = round(Int, 1 / dt) + +t = 0:dt:T +y0 = zeros(F, length(monitor_instances)) +if dogpu# && + u0, model, base, μ, σ, σm, t, field_padding, source_instances =#, monitor_instances = + gpu.((u0, model, base, μ, σ, σm, t, field_padding, source_instances))#, monitor_instances)) +end + function make_geometry(model, base, μ, σ, σm) - base = place!(F.(base), model(), round.(Int, designs[1].o / dx) .+ 1) - ϵ = sandwich(base, round.(Int, [hsub, hcore, hclad] / dx), [ϵsub, ϵcore, ϵclad]) + base_ = Buffer(base) + base_[:, :] = base + place!(base_, model(), round.(Int, designs[1].o / dx) .+ 1) + + ϵ = sandwich(copy(base_), round.(Int, [hsub, hcore, hclad] / dx), [ϵsub, ϵcore, ϵclad]) ϵ, μ, σ, σm = apply(geometry_padding; ϵ, μ, σ, σm) p = apply(geometry_splits; ϵ, μ, σ, σm) end -p0 = make_geometry(model0, base, μ, σ, σm) -# volume(p0[1][3]) -function metrics(model, T=T;) +function metrics(model;) p = make_geometry(model, base, μ, σ, σm) # run simulation - # u = reduce((u, t) -> step!(u, p, t, dx, dt, field_padding, source_instances;), 0:dt:T-1, init=deepcopy(u0)) - # y = reduce(((u, y), t) -> ( - # step!(u, p, t, dx, dt, field_padding, source_instances), - # y + dt * power.(monitor_instances, (u,)) - # ), - # T-1+dt:dt:T, - # init=(u, zeros(F, length(monitor_instances))))[2] - t = 0:dt:T - u = [i == 1 ? u0 : [similar.(a) for a = u0] for (i, t) = enumerate(t)] - reduce( - (u, (u1, t)) -> step!(u1, u, p, t, dx, dt, field_padding, source_instances), - zip(u[2:end], t[1:end-1]), - init=u0) - sum(u[end-nt+1:end]) do u - dt * power.(monitor_instances, (u,)) - end -end -tp = abs(metrics(model, 2)[1]) # total power + u = reduce((u, t) -> step(u, p, t, dx, dt, field_padding, source_instances;), 0:dt:T-1, init=u0) + y = reduce( + ((u, y), t) -> ( + step(u, p, t, dx, dt, field_padding, source_instances), + y + dt * power.(monitor_instances, (u,))), + T-1+dt:dt:T, + init=(u, y0))[2] +end function loss(y) dot([0, -1, -1, 1, -1, 1, 1, 1, 1], y) + abs(y[2] - y[3]) end +tp = abs(metrics(model)[1]) # total power +p0 = make_geometry(model0, base, μ, σ, σm) +# volume(p0[1][3]) + "Optim functions" x0, re = destructure(model) -f_ = loss ∘ metrics +f_ = m -> loss(metrics(m)) f = f_ ∘ re x = deepcopy(x0) @show f(x) @@ -128,30 +137,51 @@ x = deepcopy(x0) opt = Adam(0.2) m = re(x) opt_state = Flux.setup(opt, m) -n = 2 +n = 12 for i = 1:n - @time l, (dldm,) = withgradient(m -> loss(metrics(m;)), m) + @time l, (dldm,) = withgradient(m -> loss(metrics(m)), m) Flux.update!(opt_state, m, dldm) println("$i $l") end # x_adjoint = re(minimizer(res)) -function runsave(x) - model = re(x) - p = make_geometry(model, base, μ, σ, σm) - t = 0:dt:T - sol = similar([u0], length(t)) - @showtime sol = accumulate!((u, t) -> step!(u, p, t, dx, dt, field_padding, source_instances), sol, t, init=u0) +# move to cpu for plotting +if dogpu + u0, model, base, μ, σ, σm, t, field_padding, source_instances =#, monitor_instances = + cpu.((u0, model, base, μ, σ, σm, t, field_padding, source_instances))#, monitor_instances)) +end + +p = make_geometry(m, base, μ, σ, σm) +volume(cpu(p[1][3])) - # make movie - Ez = map(sol) do u +function runsave(x) + m = re(x) + p = make_geometry(m, base, μ, σ, σm) + @showtime u = accumulate((u, t) -> + step!(deepcopy(u), p, t, dx, dt, field_padding, source_instances), + t, init=u0) + + global source_instances + if dogpu + u, p, source_instances = cpu.((u, p, source_instances)) + end + Ez = map(u) do u u[1][3] end ϵz = p[1][3] dir = @__DIR__ - ° = π / 180 - recordsim(Ez, ϵz, configs, "$dir/$(name)_nres_$nx.mp4", title="$name"; elevation=60°, playback=1, bipolar=true) + # error() + recordsim("$dir/$(name)_nres_$nx.mp4", collect.(Ez), ; + dt, + monitor_instances, + source_instances, + geometry=ϵz, + elevation=30°, + playback=1, + axis1=(; title="$name\nEz"), + axis2=(; title="monitor powers"), + ) end -runsave(xgf) \ No newline at end of file +runsave(x) \ No newline at end of file diff --git a/makedocs/inverse_design_3d_silicon_photonics_splitter/layout.bson b/makedocs/inverse_design_3d_silicon_photonics_splitter/layout.bson index 3d7e446..58636f8 100644 Binary files a/makedocs/inverse_design_3d_silicon_photonics_splitter/layout.bson and b/makedocs/inverse_design_3d_silicon_photonics_splitter/layout.bson differ diff --git a/makedocs/inverse_design_3d_silicon_photonics_splitter/layout.jl b/makedocs/inverse_design_3d_silicon_photonics_splitter/layout.jl index 1065ae5..010e424 100644 --- a/makedocs/inverse_design_3d_silicon_photonics_splitter/layout.jl +++ b/makedocs/inverse_design_3d_silicon_photonics_splitter/layout.jl @@ -5,41 +5,41 @@ dir = "examples/utils" wwg = 0.5 hwg = 0.22 lwg = 1 -ld = 1 +ld = 1.5 hclad = hbox = 0.2 wm = 0.5wwg l = 2lwg + ld w = 2wm + ld h = hwg + hbox + hclad + +λ = 1.55f0 layout = (; wwg, hwg, lwg, ld, hclad, hbox, l, w, h, wm) -v = values(layout) +v = collect(values(layout)) / λ k = keys(layout) -λ = 1.55f0 -c = [lwg, wm] / λ -v = F.(v) ./ λ +c = [lwg, wm] +v = F.(v) n = [1, 0] ports = [ - (; c=[0.2f0, w / 2] / λ, n), - (; c=[l, w - wm - wwg / 2] / λ, n), - (; c=[l, wm + wwg / 2] / λ, n), + (; c=[0.2f0, w / 2], n), + (; c=[l, w - wm - wwg / 2], n), + (; c=[l, wm + wwg / 2], n), ] sources = [ - (; c=[0, w / 2] / λ) + (; c=[0, w / 2]) ] designs = [ - (; o=[lwg, wm] / λ, L=[ld, ld,] / λ, c=[lwg + ld / 2, wm + ld / 2] / λ) + (; o=[lwg, wm], L=[ld, ld,], c=[lwg + ld / 2, wm + ld / 2]) ] dx = 1.0f0 / nx wwg, hwg, lwg, ld, hclad, hbox, l, w, h, wm = round.(Int, v ./ dx) -base = zeros(Int, l, w) -base[1:lwg, (w-wwg)÷2+1:(w+wwg)÷2] .= 1 -base[end-lwg+1:end, wm+1:wm+wwg] .= 1 -base[end-lwg+1:end, end-wm-wwg+1:end-wm] .= 1 -# design = zeros(F, l, w) -# design[lwg:lwg+ld, wwg:wwg+ld] = 1 + +base = zeros(Int, l .+ 1, w .+ 1) +base[1:lwg.+1, (w-wwg)÷2+1:(w+wwg)÷2+1] .= 1 +base[end-lwg:end, wm+1:wm+wwg.+1] .= 1 +base[end-lwg:end, end-wm-wwg:end-wm] .= 1 layout = (; Pair.(k, v)..., base, sources, ports, designs, dx, nx) @save "$(@__DIR__)/layout.bson" layout \ No newline at end of file diff --git a/makedocs/inverse_design_3d_silicon_photonics_splitter/scratch.jl b/makedocs/inverse_design_3d_silicon_photonics_splitter/scratch.jl index d74457a..62358b0 100644 --- a/makedocs/inverse_design_3d_silicon_photonics_splitter/scratch.jl +++ b/makedocs/inverse_design_3d_silicon_photonics_splitter/scratch.jl @@ -1,66 +1,26 @@ -error() -# @show x|>re|>metrics +using VectorModesolver -# train surrogate -Random.seed!(1) -runs = [] -i = 1 -function f!(x) - @time begin - model = re(x) - mp = metrics(model) - l = loss(mp) - global i - # if i == 1 - push!(runs, [x, mp, l]) - # else - # runs[i] .= [x0, mp, l] - # end - # i +=1 - l - end -end - -iterations = 24 -f!(x) -# runs = similar(runs, iterations) +function (ε::εtype)(x::Float64, y::Float64) -@showtime res = optimize(f!, x0, ParticleSwarm(; - n_particles=16), Optim.Options(; f_tol=0, iterations, show_every=1, show_trace=true)) -xgf = minimizer(res) -x = deepcopy(xgf) + if (0.75 < x < 1.75) && (0.95 < y < 1.55) + return (4.0, 0.0, 0.0, 4.0, 4.0) + end -error() -X = Base.stack(getindex.(runs, 1)) -Y = Base.stack(getindex.(runs, 2)) + return (1.0, 0.0, 0.0, 1.0, 1.0) +end -nl = leakyrelu -n = size(X, 1) -m, N = size(Y) -nn = Chain(Dense(n, 2n, nl), Dense(2n, 4n, nl), Dense(4n, m)) +function main() + ε = εtype() + λ = 1.55 + x = [i for i in 0:0.03:2.5] + y = [i for i in 0:0.05:2.5] + neigs = 1 + tol = 1e-8 + boundary = (0, 0, 0, 0) + solver = VectorialModesolver(λ, x, y, boundary, ε) + modes = solve(solver, neigs, tol) -opt = Adam(0.1) -opt_state = Flux.setup(opt, nn) -n = 100 -for i = 1:n - l, (dldm,) = withgradient(nn -> Flux.mae(Y, nn(X)), nn) - Flux.update!(opt_state, nn, dldm) - (i % 25 == 0 || i == n) && println("$i $l") end -opt = Adam(0.1) -opt_state = Flux.setup(opt, x) -n = 100 -@show f(x) -for i = 1:n - l, (dldm,) = withgradient(x -> mae( - nn(x)[2:end], - [tp / 2, tp / 2, -tp, tp, zeros(F, 4)...] - ), x) - Flux.update!(opt_state, x, dldm) - (i % 25 == 0 || i == n) && println("$i $l") -end -@show loss(nn(x)) -@show f(x) -xsg = x -x = deepcopy(xsg) +modes = main() +plot_mode_fields(modes[1]) diff --git a/makedocs/inverse_design_3d_silicon_photonics_splitter/silicon_photonics_splitter_nres_16.mp4 b/makedocs/inverse_design_3d_silicon_photonics_splitter/silicon_photonics_splitter_nres_16.mp4 index ce5cbe8..508b399 100644 Binary files a/makedocs/inverse_design_3d_silicon_photonics_splitter/silicon_photonics_splitter_nres_16.mp4 and b/makedocs/inverse_design_3d_silicon_photonics_splitter/silicon_photonics_splitter_nres_16.mp4 differ diff --git a/makedocs/inverse_design_3d_silicon_photonics_splitter/silicon_photonics_splitter_nres_24.mp4 b/makedocs/inverse_design_3d_silicon_photonics_splitter/silicon_photonics_splitter_nres_24.mp4 new file mode 100644 index 0000000..162a5ff Binary files /dev/null and b/makedocs/inverse_design_3d_silicon_photonics_splitter/silicon_photonics_splitter_nres_24.mp4 differ diff --git a/scripts/setup.jl b/scripts/setup.jl new file mode 100644 index 0000000..ea9eb00 --- /dev/null +++ b/scripts/setup.jl @@ -0,0 +1,3 @@ +using Pkg +# ]add UnPack, BSON,DataStructures, StatsBase, Documenter,Interpolations, Zygote, Optim,ArrayPadding, Porcupine, Jello, GLMakie, Functors, Lazy,AbbreviatedStackTraces,ReverseStackTraces,CUDA,Flux +Pkg.add(url="https://github.com/paulxshen/ArrayPadding.jl") \ No newline at end of file diff --git a/scripts/startup.jl b/scripts/startup.jl index b80e534..0cd60da 100644 --- a/scripts/startup.jl +++ b/scripts/startup.jl @@ -1,16 +1,7 @@ -using AbbreviatedStackTraces, ReverseStackTraces, Pkg +using AbbreviatedStackTraces, Pkg +# using ReverseStackTraces # ENV["JULIA_PKG_PRECOMPILE_AUTO"] # ENV["JULIA_PKG_PRECOMPILE_AUTO"] = 0 Pkg.UPDATED_REGISTRY_THIS_SESSION[] = true # using -Base.round(x::AbstractFloat) = Base.round(Int, x) - -T = Float32 - -Base.getindex(s::Symbol, i) = Symbol(String(s)[i]) - - -f32(x::Real) = Float32(x) -f32(x::AbstractArray) = f32.(x) -° = π / 180 \ No newline at end of file diff --git a/src/boundaries.jl b/src/boundaries.jl index 6938ad5..23891f2 100644 --- a/src/boundaries.jl +++ b/src/boundaries.jl @@ -39,7 +39,7 @@ struct PML dims d::Real σ::Real - function PML(dims, d=0.125f0, σ=40.0f0) + function PML(dims, d=0.25f0, σ=10.0f0) new(dims, d, σ) end end @@ -54,11 +54,13 @@ struct InPad new(b, l, r, m) end end +@functor InPad (m,) struct OutPad b l r end +# @functor OutPad function apply!(p::AbstractVector{<:InPad}, a::AbstractArray) @@ -67,23 +69,34 @@ function apply!(p::AbstractVector{<:InPad}, a::AbstractArray) if isnothing(m) pad!(a, b, l, r;) else - a_ = bufferfrom(a) - a_[axes(a)...] = a .* m - a = copy(a_) + a .= a .* m end end a end +function apply(p::AbstractVector{<:InPad}, a::AbstractArray) + a_ = Buffer(a) + for p = p + @unpack l, r, b, m = p + if isnothing(m) + pad!(a_, b, l, r;) + else + a_[axes(a)...] = a .* m + end + end + + copy(a_) +end + function apply(p::AbstractVector{<:OutPad}, a) l = sum(getproperty.(p, :l)) r = sum(getproperty.(p, :r)) - # y = bufferfrom(ones(F, Tuple(l .+ r .+ size(a)))) y = Buffer(a, Tuple(l .+ r .+ size(a))) - place!(y, a, l .+ 1) + y = place!(y, a, l .+ 1) for p = p l -= p.l r -= p.r - pad!(y, p.b, p.l, p.r, l, r) + y = pad!(y, p.b, p.l, p.r, l, r) end copy(y) end diff --git a/src/fdtd.jl b/src/fdtd.jl index 41d0bfe..113c0c0 100644 --- a/src/fdtd.jl +++ b/src/fdtd.jl @@ -256,6 +256,8 @@ function setup(boundaries, sources, monitors, dx, sz0, polarization=nothing; ] end end + geometry_padding = NamedTuple(geometry_padding) + field_padding = NamedTuple(field_padding) (; μ, σ, σm, ϵ, geometry_padding, field_padding, geometry_splits, source_instances, monitor_instances, u0, save_info, fields, dx, dt, kw...) end function apply!(p; kw...) diff --git a/src/geometry.jl b/src/geometry.jl index 3b02e79..5f5a8b0 100644 --- a/src/geometry.jl +++ b/src/geometry.jl @@ -1,6 +1,7 @@ function sandwich(base, h, ϵ) - a = ones(F, size(base)) + # a = ones(F, size(base)) + a = 0 * base .+ 1 ϵbox, ϵcore, ϵclad, = ϵ # hbox, hwg, hclad = h cat(repeat.( diff --git a/src/main.jl b/src/main.jl index f2faa0a..e48661b 100644 --- a/src/main.jl +++ b/src/main.jl @@ -1,5 +1,6 @@ using UnPack, LinearAlgebra, Random, StatsBase, Interpolations, Functors, DataStructures -using Jello, ArrayPadding, Porcupine +using Porcupine +using Jello, ArrayPadding using Zygote: bufferfrom, Buffer using Zygote F = Float32 diff --git a/src/maxwell.jl b/src/maxwell.jl index dc49808..dd8c754 100644 --- a/src/maxwell.jl +++ b/src/maxwell.jl @@ -8,21 +8,18 @@ function step!(u1, u, p, t, dx, dt, field_padding, source_instances) ϵ, μ, σ, σm = p E, H = u E1, H1 = u1 - J = apply(source_instances, t; Jx=zeros(F, size(E[1])), Jy=zeros(F, size(E[2])), Jz=zeros(F, size(E[3]))) - # J = apply(source_instances, t; Jx=0, Jy=0, Jz=0) + # J = apply(source_instances, t; Jx=zeros(F, size(E[1])), Jy=zeros(F, size(E[2])), Jz=zeros(F, size(E[3]))) + J = apply(source_instances, t; Jx=0, Jy=0, Jz=0) # first update E Hx, Hy, Hz = H H = mark(field_padding; Hx, Hy, Hz) dEdt = (∇ × H - σ * E - J) / ϵ - E_ = bufferfrom.(E1) for i = 1:3 - E_[i][:, :, :] = E[i] + dEdt[i] * dt + E1[i][:, :, :] = E[i] + dEdt[i] * dt end - Ex, Ey, Ez = [copy(E_[1]), copy(E_[2]), copy(E_[3])] - # E .= E + dEdt * dt - + Ex, Ey, Ez = E1 apply!(field_padding; Ex, Ey, Ez) H = collect.(H) @@ -30,20 +27,82 @@ function step!(u1, u, p, t, dx, dt, field_padding, source_instances) E = mark(field_padding; Ex, Ey, Ez) dHdt = -(∇ × E .+ σm * H) / μ - H_ = bufferfrom.(H1) for i = 1:3 - H_[i][:, :, :] = H[i] + dHdt[i] * dt + H1[i][:, :, :] = H[i] + dHdt[i] * dt end - Hx, Hy, Hz = [copy(H_[1]), copy(H_[2]), copy(H_[3])] - # H .= H + dHdt * dt - + Hx, Hy, Hz = H1 apply!(field_padding; Hx, Hy, Hz) E = collect.(E) - H = [Hx, Hy, Hz] [E, H] # u1 end +step!(u, p, t, dx, dt, field_padding, source_instances) = step!(u, u, p, t, dx, dt, field_padding, source_instances) + +# function step!(u, p, t, dx, dt, field_padding, source_instances) +# ∇ = StaggeredDel([dx, dx, dx]) +# ϵ, μ, σ, σm = p +# E, H = u +# J = apply(source_instances, t; Jx=0, Jy=0, Jz=0) + +# # first update E +# Hx, Hy, Hz = H +# H = mark(field_padding; Hx, Hy, Hz) +# dEdt = (∇ × H - σ * E - J) / ϵ + +# E_ = bufferfrom.(E) +# for i = 1:3 +# E_[i][:, :, :] = E[i] + dEdt[i] * dt +# end +# Ex, Ey, Ez = [copy(E_[1]), copy(E_[2]), copy(E_[3])] +# # E .= E + dEdt * dt + +# apply!(field_padding; Ex, Ey, Ez) +# H = collect.(H) + +# # then update H +# E = mark(field_padding; Ex, Ey, Ez) +# dHdt = -(∇ × E .+ σm * H) / μ + +# H_ = bufferfrom.(H) +# for i = 1:3 +# H_[i][:, :, :] = H[i] + dHdt[i] * dt +# end +# Hx, Hy, Hz = [copy(H_[1]), copy(H_[2]), copy(H_[3])] +# # H .= H + dHdt * dt + +# apply!(field_padding; Hx, Hy, Hz) +# H = [Hx, Hy, Hz] +# E = collect.(E) + +# [E, H] +# end +function step(u, p, t, dx, dt, field_padding, source_instances) + ∇ = StaggeredDel([dx, dx, dx]) + ϵ, μ, σ, σm = p + E, H = u + J = apply(source_instances, t; Jx=0, Jy=0, Jz=0) + + # first update E + Hx, Hy, Hz = H + H = mark(field_padding; Hx, Hy, Hz) + dEdt = (∇ × H - σ * E - J) / ϵ + Ex, Ey, Ez = E + dEdt * dt + + Ex, Ey, Ez = apply(field_padding; Ex, Ey, Ez) + H = collect.(H) + + # then update H + E = mark(field_padding; Ex, Ey, Ez) + dHdt = -(∇ × E .+ σm * H) / μ + Hx, Hy, Hz = H + dHdt * dt + + H = apply(field_padding; Hx, Hy, Hz) + # H = [Hx, Hy, Hz] + E = collect.(E) + + [E, H] +end step3! = step! # Flux.trainable(m::PaddedArray) = (; a=m.a) diff --git a/src/monitors.jl b/src/monitors.jl index 6d71963..7a72e94 100644 --- a/src/monitors.jl +++ b/src/monitors.jl @@ -30,7 +30,7 @@ struct MonitorInstance A label end - +@functor MonitorInstance (n,) # power(m, u) = sum(sum(pf([u[m.idxs[k]...] for (u, k) = zip(u, fk)]) .* m.n)) """ diff --git a/src/sources.jl b/src/sources.jl index a51020c..ab859b6 100644 --- a/src/sources.jl +++ b/src/sources.jl @@ -17,7 +17,7 @@ struct PlaneWave new(f, fields, dims, label) end end - +@functor PlaneWave """ function GaussianBeam(f, σ, c, dims; fields...) @@ -39,6 +39,7 @@ struct GaussianBeam new(f, σ, fields, c, dims) end end +@functor GaussianBeam """ function Source(f, c, lb, ub, label=""; fields...) @@ -81,7 +82,7 @@ struct SourceInstance c label end - +@functor SourceInstance function SourceInstance(s::PlaneWave, dx, sizes, o, sz0) @unpack f, fields, dims, label = s d = length(first(sizes)) @@ -108,7 +109,7 @@ end function SourceInstance(s::Source, dx, sizes, o, stop) @unpack f, fields, c, lb, ub, label = s I = [a:dx:b for (a, b) = zip(lb, ub)] - g = Dict([k => [fields[k](v...) for v = Iterators.product(I...)] / dx^count(lb .== ub) for k = keys(fields)]) + g = Dict([k => [F.(fields[k](v...)) for v = Iterators.product(I...)] / dx^count(lb .== ub) for k = keys(fields)]) c = -1 .+ index(c, dx) .- round.(Int, (length.(I) .- 1) ./ 2) o = NamedTuple([k => o[k] .+ c for k = keys(o)]) _g = Dict([k => place(zeros(F, sizes[k]), g[k], o[k]) for k = keys(fields)]) @@ -121,13 +122,19 @@ end # # r = place(r, real(fields[k] * f(t) .* g), o) # a .+ real(f(t) .* _g) # end +_F(x::Real) = F(x) +_F(x::Complex) = ComplexF32(x) function apply(v::AbstractVector{<:SourceInstance}, t::Real; kw...) [ # sum([real(s.f(t) .* s._g[k]) for s = v if k in s.k], init=kw[k]) begin - a = [real(s.f(t) .* s._g[k]) for s = v if k in s.k] - kw[k] .+ (isempty(a) ? 0 : sum(a)) + a = [real(_F(s.f(t)) .* s._g[k]) for s = v if k in s.k] + if isempty(a) + kw[k] + else + kw[k] .+ sum(a) + end end for k = keys(kw) # end for (k, a) = pairs(kw) diff --git a/src/utils.jl b/src/utils.jl index 2b97024..363c4fe 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -7,32 +7,29 @@ Base.getindex(s::Symbol, i) = Symbol(String(s)[i]) index(v, dx) = round.(Int, v ./ dx .+ 1) reindex(i, ratio) = round.(Int, (i .- 1) .* ratio .+ 1) -Base.size(x::NamedTuple) = (length(x),) +Base.size(x::Union{NamedTuple,Tuple}) = (length(x),) T = Union{Tuple,AbstractArray,Number} Base.:-(x::T, y::T) = x .- y Base.:+(x::T, y::T) = x .+ y - -f32(x::Real) = Float32(x) -f32(x::AbstractArray) = f32.(x) - # __precompile__(false) (m::Number)(a...) = m gaussian(x; μ=0, σ=1) = exp(-((x - μ) / σ)^2) -function place(a, b, start; lazy=false) - a + pad(b, 0, Tuple(start) .- 1, size(a) .- size(b) .- Tuple(start) .+ 1) - # place!(buf, b, start) -end -function place!(a::AbstractArray, b, start) - buf = bufferfrom(a) - place!(buf, b, start) - copy(buf) +function place(a, b, o; lazy=false) + a + pad(b, 0, Tuple(o) .- 1, size(a) .- size(b) .- Tuple(o) .+ 1) + # place!(buf, b, o) end -function place!(a, b, start) - a[[i:j for (i, j) = zip(start, start .+ size(b) .- 1)]...] = b +# function place!(a::AbstractArray, b, o) +# buf = bufferfrom(a) +# buf = place!(buf, b, o) +# copy(buf) +# end +function place!(a, b, o) + a[[i:j for (i, j) = zip(o, o .+ size(b) .- 1)]...] = b + a end function place!(a, b; o) diff --git a/temp/0.0.png b/temp/0.0.png deleted file mode 100644 index 9feabe6..0000000 Binary files a/temp/0.0.png and /dev/null differ diff --git a/temp/0.2857142857142857.png b/temp/0.2857142857142857.png deleted file mode 100644 index 62c6b96..0000000 Binary files a/temp/0.2857142857142857.png and /dev/null differ diff --git a/temp/0.5714285714285714.png b/temp/0.5714285714285714.png deleted file mode 100644 index ef03463..0000000 Binary files a/temp/0.5714285714285714.png and /dev/null differ diff --git a/temp/0.8571428571428571.png b/temp/0.8571428571428571.png deleted file mode 100644 index edd9f89..0000000 Binary files a/temp/0.8571428571428571.png and /dev/null differ diff --git a/temp/1.1428571428571428.png b/temp/1.1428571428571428.png deleted file mode 100644 index c98d255..0000000 Binary files a/temp/1.1428571428571428.png and /dev/null differ diff --git a/temp/1.4285714285714286.png b/temp/1.4285714285714286.png deleted file mode 100644 index 888a64f..0000000 Binary files a/temp/1.4285714285714286.png and /dev/null differ diff --git a/temp/1.7142857142857142.png b/temp/1.7142857142857142.png deleted file mode 100644 index aa85db6..0000000 Binary files a/temp/1.7142857142857142.png and /dev/null differ diff --git a/temp/10.0.png b/temp/10.0.png deleted file mode 100644 index ab36e5b..0000000 Binary files a/temp/10.0.png and /dev/null differ diff --git a/temp/11.428571428571429.png b/temp/11.428571428571429.png deleted file mode 100644 index d2aaf14..0000000 Binary files a/temp/11.428571428571429.png and /dev/null differ diff --git a/temp/11.428572.png b/temp/11.428572.png deleted file mode 100644 index 4b05c6b..0000000 Binary files a/temp/11.428572.png and /dev/null differ diff --git a/temp/12.0.png b/temp/12.0.png deleted file mode 100644 index fa5e1dc..0000000 Binary files a/temp/12.0.png and /dev/null differ diff --git a/temp/13.714285714285714.png b/temp/13.714285714285714.png deleted file mode 100644 index c4264aa..0000000 Binary files a/temp/13.714285714285714.png and /dev/null differ diff --git a/temp/13.714286.png b/temp/13.714286.png deleted file mode 100644 index 8eb6dc4..0000000 Binary files a/temp/13.714286.png and /dev/null differ diff --git a/temp/14.0.png b/temp/14.0.png deleted file mode 100644 index ecdf5ab..0000000 Binary files a/temp/14.0.png and /dev/null differ diff --git a/temp/16.0.png b/temp/16.0.png deleted file mode 100644 index ce4cfa5..0000000 Binary files a/temp/16.0.png and /dev/null differ diff --git a/temp/2.0.png b/temp/2.0.png deleted file mode 100644 index 8ab5bf5..0000000 Binary files a/temp/2.0.png and /dev/null differ diff --git a/temp/2.2857142857142856.png b/temp/2.2857142857142856.png deleted file mode 100644 index 0a2f52b..0000000 Binary files a/temp/2.2857142857142856.png and /dev/null differ diff --git a/temp/2.2857144.png b/temp/2.2857144.png deleted file mode 100644 index 341b170..0000000 Binary files a/temp/2.2857144.png and /dev/null differ diff --git a/temp/3.4285714285714284.png b/temp/3.4285714285714284.png deleted file mode 100644 index e444e81..0000000 Binary files a/temp/3.4285714285714284.png and /dev/null differ diff --git a/temp/4.0.png b/temp/4.0.png deleted file mode 100644 index 4cd5f2b..0000000 Binary files a/temp/4.0.png and /dev/null differ diff --git a/temp/4.571428571428571.png b/temp/4.571428571428571.png deleted file mode 100644 index 66f4f4c..0000000 Binary files a/temp/4.571428571428571.png and /dev/null differ diff --git a/temp/4.571429.png b/temp/4.571429.png deleted file mode 100644 index 52488cb..0000000 Binary files a/temp/4.571429.png and /dev/null differ diff --git a/temp/5.714285714285714.png b/temp/5.714285714285714.png deleted file mode 100644 index 75b180c..0000000 Binary files a/temp/5.714285714285714.png and /dev/null differ diff --git a/temp/6.0.png b/temp/6.0.png deleted file mode 100644 index c173918..0000000 Binary files a/temp/6.0.png and /dev/null differ diff --git a/temp/6.857142857142857.png b/temp/6.857142857142857.png deleted file mode 100644 index 7c7f18c..0000000 Binary files a/temp/6.857142857142857.png and /dev/null differ diff --git a/temp/6.857143.png b/temp/6.857143.png deleted file mode 100644 index e52f02c..0000000 Binary files a/temp/6.857143.png and /dev/null differ diff --git a/temp/8.0.png b/temp/8.0.png deleted file mode 100644 index fdb97c5..0000000 Binary files a/temp/8.0.png and /dev/null differ diff --git a/temp/9.142857142857142.png b/temp/9.142857142857142.png deleted file mode 100644 index 6939267..0000000 Binary files a/temp/9.142857142857142.png and /dev/null differ diff --git a/temp/9.142858.png b/temp/9.142858.png deleted file mode 100644 index 9aaf0d0..0000000 Binary files a/temp/9.142858.png and /dev/null differ