-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #13 from bblankrot/dev
Improved coverage and documentation
- Loading branch information
Showing
17 changed files
with
323 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,9 @@ os: | |
- osx | ||
julia: | ||
- 0.6 | ||
branches: | ||
except: | ||
- dev | ||
notifications: | ||
email: false | ||
env: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
julia 0.6 | ||
|
||
IterativeSolvers | ||
IterativeSolvers 0.5.0 | ||
LinearMaps | ||
Optim | ||
Optim 0.14.0 | ||
PyPlot | ||
DataFrames | ||
CSV | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
# Tutorial 3: Angle Optimization | ||
|
||
In this tutorial, we build upon the [previous tutorial]@(ref tutorial2) by | ||
optimizing the rotation angles of the particles (`φs`) to maximize the field | ||
intensity at a specific point. | ||
Depending on the scattering problem, wavelengths, and incident field, | ||
optimization can have a major or minor impact on the field. | ||
The simplest way to perform this optimization is by calling [`optimize_φ`](@ref), which | ||
in turn utilizes `Optim`, a Julia package for nonlinear optimization. The type of | ||
objective function handled here is given by | ||
|
||
```math | ||
f_{\mathrm{obj}} = \sum_{\mathbf{r} \in I} \| u(\mathbf{r})\|^2 | ||
``` | ||
|
||
where ``I`` is a set of points that lie outside all scattering discs | ||
and ``u`` is the ``z``-component of the electric field. This function can be | ||
minimized directly, or maximized by minimizing ``-f_{\mathrm{obj}}``. | ||
|
||
First we set up our scattering problem: | ||
|
||
```julia | ||
λ0 = 1 #doesn't matter since everything is normalized to λ0 | ||
k0 = 2π/λ0 | ||
kin = 0.5k0 | ||
θ_i = 0 #incident wave e^{i k_0 (1/sqrt{2},1/sqrt{2}) \cdot \mathbf{r}} | ||
M = 20 | ||
shapes = [rounded_star(0.35λ0, 0.1λ0, 4, 202)] | ||
P = 12 | ||
centers = rect_grid(2, div(M,2), λ0, λ0) #2xM/2 grid | ||
ids = ones(Int, M) | ||
φs0 = zeros(M) | ||
sp = ScatteringProblem(shapes, ids, centers, φs0) | ||
fmm_options = FMMoptions(true, acc = 6, dx = 2λ0) | ||
points = 0.05*λ0*[-1 0; 1 0; 0 1; 0 -1] | ||
``` | ||
|
||
where `φs0` is the starting point for the optimization method, and `points` are | ||
the locations at which we intend to maximize or minimize the field intensity. | ||
In this case, we want to optimize intensity at a small area around the origin. | ||
We now select the optimization method and select its options. | ||
In most cases, this combination of BFGS with a backtracking line search will | ||
yield accurate results in fast time; | ||
other line searches that require re-evaluation of the gradient will be | ||
significantly slower but may converge more accurately. The possible convergence | ||
criteria are set by the bounds `f_tol`, `g_tol`, and `x_tol`, for | ||
a relative change in the function, gradient norm, or variables, respectively. | ||
In addition, we can set a maximum number of `iterations`. Verbosity of the output | ||
is set with `show_trace` and `extended_trace`. | ||
|
||
```julia | ||
optim_options = Optim.Options(f_tol = 1e-6, iterations = 100, | ||
store_trace = true, show_trace = true) | ||
optim_method = Optim.BFGS(;linesearch = LineSearches.BackTracking()) | ||
``` | ||
|
||
We now run both minimization and maximization: | ||
|
||
```julia | ||
res_min = optimize_φ(φs0, points, P, θ_i, k0, kin, shapes, centers, ids, | ||
fmm_options, optim_options, optim_method; minimize = true) | ||
res_max = optimize_φ(φs0, points, P, θ_i, k0, kin, shapes, centers, ids, | ||
fmm_options, optim_options, optim_method; minimize = false) | ||
sp_min = ScatteringProblem(shapes, ids, centers, res_min.minimizer) | ||
sp_max = ScatteringProblem(shapes, ids, centers, res_max.minimizer) | ||
``` | ||
|
||
Once the optimization is done, we can visualize each `ScatteringProblem` | ||
separately with [`plot_near_field`](@ref) or compare them side by side with the | ||
following PyPlot code: | ||
|
||
```julia | ||
plts = Array{Any}(3) | ||
plts[1] = plot_near_field(k0, kin, P, sp, θ_i, x_points = 100, y_points = 300, | ||
opt = fmm_options, border = find_border(sp, points)) | ||
plts[2] = plot_near_field(k0, kin, P, sp_min, θ_i, x_points = 100, y_points = 300, | ||
opt = fmm_options, border = find_border(sp, points)) | ||
plts[3] = plot_near_field(k0, kin, P, sp_max, θ_i, x_points = 100, y_points = 300, | ||
opt = fmm_options, border = find_border(sp, points)) | ||
close("all") | ||
|
||
fig, axs = subplots(ncols=3); msh = 0 | ||
for (i, spi) in enumerate([sp;sp_min;sp_max]) | ||
msh = axs[i][:pcolormesh](plts[i][2][1], plts[i][2][2], abs.(plts[i][2][3]), | ||
vmin = 0, vmax = 3.4, cmap="viridis") | ||
draw_shapes(spi.shapes, spi.centers, spi.ids, spi.φs, axs[i]) | ||
axs[i][:set_aspect]("equal", adjustable = "box") | ||
axs[i][:set_xlim]([border[1];border[2]]) | ||
axs[i][:set_ylim]([border[3];border[4]]) | ||
axs[i][:set_xticks]([-1,0,1]) | ||
i > 1 && axs[i][:set_yticks]([]) | ||
end | ||
subplots_adjust(left=0.05, right=0.8, top=0.98, bottom = 0.05, wspace = 0.1) | ||
cbar_ax = fig[:add_axes]([0.85, 0.05, 0.05, 0.93]) | ||
fig[:colorbar](msh, cax=cbar_ax) | ||
``` | ||
```@raw html | ||
<div style="text-align:center"> | ||
<img alt=optim_angle src="./assets/optim_angle.png" style="width:80%; height:auto; margin:1%; max-width: 600px"> | ||
</div><p style="clear:both;"> | ||
``` | ||
|
||
From left to right, we see the electric field before optimization, after | ||
minimization, and after maximization. The field intensity at the origin is | ||
notably different in both optimization results, with minimization decreasing | ||
the intensity by 95%, and maximization increasing it by over 700%. The convergence | ||
of the optimization method for both examples can be plotted via: | ||
|
||
```julia | ||
iters = length(res_min.trace) | ||
fobj = [res_min.trace[i].value for i=1:iters] | ||
gobj = [res_min.trace[i].g_norm for i=1:iters] | ||
iters2 = length(res_max.trace) | ||
fobj2 = -[res_max.trace[i].value for i=1:iters2] | ||
gobj2 = [res_max.trace[i].g_norm for i=1:iters2] | ||
|
||
fig, axs = subplots(ncols=2, figsize=[7,5]) | ||
axs[1][:semilogy](0:iters-1, fobj, linewidth=2) | ||
axs[2][:semilogy](0:iters-1, gobj, linewidth=2) | ||
axs[1][:semilogy](0:iters2-1, fobj2, linewidth=2, "--") | ||
axs[2][:semilogy](0:iters2-1, gobj2, linewidth=2, "--") | ||
axs[1][:legend](["\$f_\\mathrm{obj}\$ (min)"; | ||
"\$f_\\mathrm{obj}\$ (max)"], loc="right") | ||
axs[2][:legend](["\$\\|\\mathbf{g}_\\mathrm{obj}\\|\$ (min)"; | ||
"\$\\|\\mathbf{g}_\\mathrm{obj}\\|\$ (max)"], loc="best") | ||
axs[1][:set_xlabel]("Iteration") | ||
axs[2][:set_xlabel]("Iteration") | ||
axs[1][:set_ylim](ymax=40) | ||
``` | ||
|
||
```@raw html | ||
<p style="text-align:center;"><img alt=optim_angle_conv src="./assets/optim_angle_conv.png" style="width:70%; height:auto; max-width:600px"></p> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
@testset "FMM" begin | ||
λ0 = 1 | ||
k0 = 2π/λ0 | ||
kin = 3k0 | ||
θ_i = π/4 #incident wave e^{i k_0 (1/sqrt{2},1/sqrt{2}) \cdot \mathbf{r}} | ||
N_squircle = 200 | ||
N_star = 210 | ||
P = 10 | ||
|
||
M = 10 | ||
shapes = [rounded_star(0.1λ0, 0.03λ0, 5, N_star); | ||
squircle(0.15λ0, N_squircle)] | ||
ids = rand(1:2, M^2) | ||
φs = 2π*rand(M^2) #random rotation angles | ||
dist = 2*maximum(shapes[i].R for i=1:2) | ||
try | ||
centers = randpoints(M^2, dist, 5λ0, 5λ0, [0.0 0.0], | ||
failures = 1_000) | ||
sp = ScatteringProblem(shapes, ids, centers, φs) | ||
@test verify_min_distance(sp, [0.0 0.0]) | ||
catch | ||
warn("Could not find random points (1)") | ||
end | ||
try | ||
centers = randpoints(M^2, dist, 5λ0, 5λ0, failures = 1_000) | ||
sp = ScatteringProblem(shapes, ids, centers, φs) | ||
@test verify_min_distance(sp) | ||
catch | ||
warn("Could not find random points (2)") | ||
end | ||
|
||
centers = rect_grid(M, M, 0.8λ0, λ0) | ||
sp = ScatteringProblem(shapes, ids, centers, φs) | ||
fmm_options = FMMoptions(true, acc = 6, nx = div(M,2)) | ||
|
||
groups,boxSize = divideSpace(centers, fmm_options; drawGroups = false) | ||
P2,Q = FMMtruncation(6, boxSize, k0) | ||
mFMM1 = FMMbuildMatrices(k0, P, P2, Q, groups, centers, boxSize; tri = false) | ||
mFMM2 = FMMbuildMatrices(k0, P, P2, Q, groups, centers, boxSize; tri = true) | ||
@test norm(mFMM1.Znear - mFMM2.Znear, Inf) == 0 | ||
|
||
points = [linspace(-λ0*M, λ0*M, 200) zeros(200)] | ||
u1 = calc_near_field(k0, kin, P, sp, points, θ_i; opt = fmm_options, | ||
verbose = false) | ||
u2 = calc_near_field(k0, kin, P, sp, points, θ_i; opt = fmm_options, | ||
verbose = true, use_multipole = false) | ||
@test norm(u1 - u2)/norm(u1) < 1e-6 | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
#based on the optimizing angle tutorial | ||
import Optim | ||
|
||
@testset "optimize angle" begin | ||
λ0 = 1 #doesn't matter since everything is normalized to λ0 | ||
k0 = 2π/λ0 | ||
kin = 0.5k0 | ||
θ_i = 0.0 | ||
M = 20 | ||
|
||
sfun(N) = rounded_star(0.35λ0, 0.1λ0, 4, N) | ||
# N, errN = minimumN(k0, kin, sfun; tol=1e-6, N_start = 200, N_min = 100, | ||
# N_max = 400) | ||
shapes = [sfun(202)] | ||
P = 12#P, errP = minimumP(k0, kin, shapes[1]; P_max = 30, tol = 1e-7) | ||
|
||
centers = rect_grid(2, div(M,2), λ0, λ0) #2xM/2 grid with distance λ0 | ||
ids = ones(Int, M) | ||
φs0 = zeros(M) | ||
sp = ScatteringProblem(shapes, ids, centers, φs0) | ||
|
||
points = [-0.05 0.0; 0.05 0.0; 0.0 0.05; 0.0 -0.05] | ||
assert(verify_min_distance(sp, points)) | ||
|
||
fmm_options = FMMoptions(true, acc = 6, dx = 2λ0) | ||
|
||
optim_options = Optim.Options(f_tol = 1e-6, iterations = 50, | ||
store_trace = true, show_trace = false) | ||
optim_method = Optim.BFGS(;linesearch = LineSearches.BackTracking()) | ||
res_min = optimize_φ(φs0, points, P, θ_i, k0, kin, shapes, centers, ids, fmm_options, | ||
optim_options, optim_method; minimize = true) | ||
@test res_min.f_converged | ||
res_max = optimize_φ(φs0, points, P, θ_i, k0, kin, shapes, centers, ids, fmm_options, | ||
optim_options, optim_method; minimize = false) | ||
@test res_max.f_converged | ||
sp_min = ScatteringProblem(shapes, ids, centers, res_min.minimizer) | ||
sp_max = ScatteringProblem(shapes, ids, centers, res_max.minimizer) | ||
|
||
u_bef = calc_near_field(k0, kin, P, sp, points, θ_i; opt = fmm_options, | ||
verbose = false) | ||
u_min = calc_near_field(k0, kin, P, sp_min, points, θ_i; opt = fmm_options, | ||
verbose = false) | ||
u_max = calc_near_field(k0, kin, P, sp_max, points, θ_i; opt = fmm_options, | ||
verbose = false) | ||
|
||
fobj0 = sum(abs2.(u_bef)) | ||
fobj_min = sum(abs2.(u_min)) | ||
fobj_max = sum(abs2.(u_max)) | ||
|
||
@test isapprox(res_min.trace[1].value, fobj0) | ||
@test isapprox(res_min.minimum, fobj_min) | ||
@test isapprox(-res_max.minimum, fobj_max) | ||
|
||
border = find_border(sp, points) | ||
end |
Oops, something went wrong.