Calculate Kirchhoff-Fresnel diffraction integrals with visualization. Explanation: https://lewinb.net/posts/diffraction/ - example: http://borgac.net/~lbo/doc/kirchhoff.pdf
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
### A Pluto.jl notebook ### | |
# v0.14.3 | |
using Markdown | |
using InteractiveUtils | |
# ╔═╡ 6d796395-5024-4129-a250-df2401327711 | |
using Setfield | |
# ╔═╡ 87c80fda-9eda-11eb-2ac5-b7b5006b19b7 | |
import CairoMakie as CM | |
# ╔═╡ 836ad30f-20cd-4f1b-9142-e47bc6e90aa0 | |
import FileIO | |
# ╔═╡ 27295f24-fd52-4608-865b-8d77a02762f7 | |
CM.activate!(type="png") | |
# ╔═╡ b6a6faa5-684d-4d77-82a1-ae5e1618b12f | |
md"""**Utility functions...**""" | |
# ╔═╡ af3b9d5e-385f-4b22-b140-468f094e1424 | |
# Make this use cos() if your angles are not very small. | |
function fastcos(x) | |
1 - x^2/2 | |
end | |
# ╔═╡ f218f7bf-b88b-4f30-91b3-51aa4e3eb373 | |
function fastatan(x) | |
x-x^3/3 | |
end | |
# ╔═╡ 6574c144-ef7e-467f-ba52-2b6beb7672fd | |
md"""# Kirchhoff-Fresnel diffraction integral""" | |
# ╔═╡ c81b24c9-9f7b-48a1-bb2e-28fd314ee0d7 | |
md"""## Aperture functions | |
Shape function for apertures. You can test the different functions at the end of this section. | |
Shape functions are used in the Setup struct; kwargs can be given as a dictionary.""" | |
# ╔═╡ fe40f98f-7344-497a-b965-436ea0380efd | |
function circular(x, y; radius=1000e-6)::Float16 | |
(x^2+y^2) <= radius^2 ? 1 : 0 | |
end | |
# ╔═╡ db008850-db81-4c85-a46d-04fea3f04837 | |
function double_circle(x, y; radius=1000e-6, dist=1000e-6)::Float16 | |
d = dist/2 | |
rsq = radius^2 | |
ysq = y^2 | |
(((x-d)^2+ysq) <= rsq || ((x+d)^2+ysq) <= rsq) ? 1 : 0 | |
end | |
# ╔═╡ 54feae63-2bce-4e22-b41e-461bf3056275 | |
function quadratic(x, y; side=1000e-6)::Float16 | |
(-side <= x && x <= side && -side <= y && y <= side) ? 1 : 0 | |
end | |
# ╔═╡ ea0d82b8-b040-4aa3-a8e1-fad9eec948e2 | |
function slit(x, y; width=800e-6, height=1000) | |
(-width/2 <= x && x <= width/2 && -height <= y && y <= height) ? 1 : 0 | |
end | |
# ╔═╡ 12afa06a-4893-40ac-8692-1366ae8dcdda | |
function double_slit(x, y; width=800e-6, off=1000e-6, height=1000) | |
(-width/2-off <= x && x <= width/2-off && -height <= y && y <= height) || (-width/2+off <= x && x <= width/2+off && -height <= y && y <= height) ? 1 : 0 | |
end | |
# ╔═╡ 126adaa2-a420-4d58-b121-0c97a9eca83a | |
function smallgrate(x, y; width=100e-6, off=200e-6, height=1000) | |
s = abs(rem(x, off+width)) | |
((x < 0 && s <= width) || (x >= 0 && s >= off)) ? 1 : 0 | |
end | |
# ╔═╡ b76a6f05-dd85-4c64-9ab7-fe17d7e11774 | |
function cross(x, y; width=300e6) | |
(abs(x) <= width/2 || abs(y) <= width/2) ? 0 : 1 | |
end | |
# ╔═╡ 5b7646f9-7935-4aa8-8d81-b236dfdc5c9a | |
function spikes(x, y; width=100e-6, radius=1000e-6) | |
circular(x, y, radius=radius) == 1 && cross(x, y, width=width) == 1 | |
end | |
# ╔═╡ 1b974614-3748-43b2-bd28-9933aec8d860 | |
#circular_fft = convert.(Float16, FileIO.load("circle.png")) | |
# ╔═╡ d2b812f6-cbd7-407e-a0e4-eea53a73dd76 | |
function from_raster(shape, maxdim) | |
maxix = size(shape, 1) | |
off = convert(Int, trunc((maxix)/2)) | |
return function(x,y) | |
i, j = convert(Int, trunc(maxix*x/maxdim)), convert(Int, trunc(maxix*y/maxdim)) | |
shape[min(i+off+1, maxix), min(j+off+1, maxix)] | |
end | |
end | |
# ╔═╡ 40f819d3-4a86-4b2c-9b18-b9b4143e3a96 | |
function grating2d(x, y; width=100e-6, off=200e-6) | |
s = abs(rem(x, off+width)) | |
a = ((x < 0 && s <= width) || (x >= 0 && s >= off)) | |
t = abs(rem(y, off+width)) | |
b = ((y < 0 && t <= width) || (y >= 0 && t >= off)) | |
a && b | |
end | |
# ╔═╡ 64bad78e-e34a-4562-9168-d7e27ecd3158 | |
function invertshape(s) | |
if s <= 0.1 | |
1 | |
else | |
0 | |
end | |
end | |
# ╔═╡ 06ffee0e-1189-4645-bab2-9e938db0620d | |
begin | |
# These constants are just used for testing the aperture functions. | |
const OUTER_DIM = .002 | |
const SCREEN_DIM = 0.3 | |
end | |
# ╔═╡ 5b11a45e-4430-4db7-8909-cd08c8bd142f | |
function sample_shape(f; dim=OUTER_DIM, res=100)::Tuple{LinRange{Float64}, Matrix{Float16}} | |
field = zeros(Float16, res, res) | |
xs = ys = LinRange(-dim/2, dim/2, res) | |
for (i, x) = enumerate(xs) | |
for (j, y) = enumerate(ys) | |
field[i,j] = f(x, y) | |
end | |
end | |
xs, field | |
end | |
# ╔═╡ 1488f2ee-1741-4676-9e14-93dd4e22fbb4 | |
function show_shape(f; dim=OUTER_DIM, scan=OUTER_DIM/10) | |
xs, field = sample_shape(f, dim=dim, res=convert(Int, div(dim,scan))) | |
fig = CM.Figure(resolution=(440,400)) | |
CM.Axis(fig[1,1]) | |
CM.heatmap!(xs, xs, field) | |
fig | |
end | |
# ╔═╡ a23a6d00-4d4e-4868-86a7-fa8c638ee8ea | |
show_shape((x,y) -> grating2d(x, y), dim=OUTER_DIM, scan=OUTER_DIM/200) | |
# ╔═╡ a22f16ca-14a9-4a69-bf0f-c84fba39a836 | |
md"""## Integral calculation | |
We integrate across the aperture, sampling both aperture and screen area. | |
Before doing that, we add some structs for configuring our calculations.""" | |
# ╔═╡ 0765cbcc-f0f1-4dfd-94e2-14358e6e6b28 | |
Base.@kwdef struct Source | |
x::Float64 = 0 | |
y::Float64 = 0 | |
z::Float64 | |
end | |
# ╔═╡ 0839fb51-ba56-4f70-8e69-bbb41685c2b2 | |
struct Setup | |
# (negative) position of source, left of aperture | |
source::Vector{Source} | |
# aperture shape function | |
aperture::Function | |
# aperture config | |
aperture_kwargs::Dict{Symbol, Float64} | |
# distance to screen | |
screen_pos::Float64 | |
# wavelength | |
lambda::Float64 | |
end | |
# ╔═╡ c0393e2b-28fd-4d9b-869d-ffeb0fdb8d24 | |
# Distance of source, shape function, shape parameters, distance to screen, wavelength | |
default_setup = Setup([Source(z=-30, y=-.0)], | |
double_slit, Dict(), | |
30, 500e-9) | |
# ╔═╡ 65cd7931-4dcf-4644-94d7-149effce4cce | |
struct ScanParam | |
aperture_size::Float64 | |
aperture::Float64 | |
screen_size::Float64 | |
screen::Float64 | |
end | |
# ╔═╡ 1ccd1e55-fe40-4683-af90-8b15617d63b1 | |
default_scan_param = ScanParam( | |
# Aperture scan size and scan step, in m, depends on aperture function | |
0.005, .005/100, | |
# Screen size and scan step in m. | |
.04, .04/50) | |
# ╔═╡ d2a3d02f-7eb3-42d6-9765-16e5bbc99d8b | |
md"""### Point source to screen | |
`calculate_integral()` assumes one or more point sources and a screen orthogonal to the (geometric) beam. It calculates the image on the screen, which is shown below.""" | |
# ╔═╡ 1c3bfcfd-1332-49d4-9b98-ceecc8c2926a | |
function calculate_integral(setup::Setup; scan_param::ScanParam=default_scan_param) | |
screendim = convert(Int, div(scan_param.screen_size, scan_param.screen)) | |
apdim = convert(Int, div(scan_param.aperture_size, scan_param.aperture)) | |
screen = zeros(Complex{Float64}, screendim, screendim) | |
delta = scan_param.aperture_size / apdim | |
all_aperture_coords = ((x,y) | |
for x = LinRange( | |
-scan_param.aperture_size/2, scan_param.aperture_size/2, apdim) | |
, y = LinRange( | |
-scan_param.aperture_size/2, scan_param.aperture_size/2, apdim)) | |
all_screen_coords = ((i, x, j, y) | |
for (i, x) = enumerate(LinRange( | |
-scan_param.screen_size/2, scan_param.screen_size/2, screendim)) | |
, (j, y) = enumerate(LinRange( | |
-scan_param.screen_size/2, scan_param.screen_size/2, screendim))) | |
k = 2pi/setup.lambda | |
all_screen_coords = collect(all_screen_coords) | |
count = 0 | |
@time begin for (apx, apy) = all_aperture_coords | |
weight = setup.aperture(apx, apy; setup.aperture_kwargs...) | |
if weight == 0 | |
continue | |
end | |
count += length(all_screen_coords) | |
cdist = sqrt(apx^2+apy^2) | |
dists = ((atan(sum(((s.x, s.y) .- (apx, apy)).^2)/abs(s.z)), | |
sqrt(sum(((apx,apy,0) .- (s.x, s.y, s.z)).^2))) | |
for s = setup.source) | |
sourceterms = [(fastcos(alpha), exp(-im * k * R)/R) for (alpha, R) = dists] | |
Threads.@threads for (i, scx, j, scy) = all_screen_coords | |
pointdist = sqrt((apx-scx)^2 + (apy-scy)^2) | |
r = sqrt(pointdist^2 + setup.screen_pos^2) | |
beta = fastatan(pointdist / abs(setup.screen_pos)) | |
fcb = fastcos(beta) | |
term = exp(-im*k*r)/r * sum( | |
((fcb+fca)/2 * t | |
for (fca, t) = sourceterms)) | |
screen[i, j] += weight * term * delta^2/(im*setup.lambda) | |
end | |
end | |
end | |
println("calculate_integral: $count iterations") | |
abs.(screen).^2, LinRange(-scan_param.screen_size/2, scan_param.screen_size/2, screendim) | |
end | |
# ╔═╡ e0abeb58-afd8-42d9-b0fc-fb55cc383323 | |
md"""**Check the actual aperture used:**""" | |
# ╔═╡ 6c0b1f38-f692-4b3e-ac08-c0f71734ed05 | |
show_shape((x,y) -> default_setup.aperture(x, y; default_setup.aperture_kwargs...), dim=default_scan_param.aperture_size, scan=default_scan_param.aperture) | |
# ╔═╡ 92147968-94e2-41d1-ad15-857eb5f06f60 | |
function plot_diffraction() | |
screen, coords = calculate_integral(default_setup, scan_param=default_scan_param); | |
fig = CM.Figure(resolution=(1300, 650)) | |
CM.Axis(fig[1,1]) | |
CM.heatmap!(coords, coords, (screen)) | |
axh = CM.Axis(fig[1, 2]) | |
axv = CM.Axis(fig[1,2], xaxisposition=:top, yaxisposition=:right) | |
mid = div(size(screen)[1], 2) | |
CM.lines!(axh, coords, view(screen, :, mid)/maximum(view(screen, :, mid)), | |
color=:green) | |
CM.lines!(axv, view(screen, mid, :)/maximum(view(screen, mid, :)), coords, | |
color=:red) | |
fig | |
end | |
# ╔═╡ 1f538236-9883-4c44-a3ab-5cf5a4b01ee1 | |
md"""**Show diffraction image as a heatmap with a crosssection (by default: along the middle, in x-orientation)**""" | |
# ╔═╡ 1aada718-2e07-48fa-b794-708e2ea23d8b | |
plot_diffraction() | |
# ╔═╡ 1b0e2b99-a65d-441d-b038-159ccc48e6f0 | |
md"""## Fraunhofer Integral""" | |
# ╔═╡ e134d03f-3771-4056-acd7-d4a8d74f2cf7 | |
function calculate_fraunhofer_integral(setup::Setup; scan_param::ScanParam=default_scan_param) | |
screendim = convert(Int, div(scan_param.screen_size, scan_param.screen)) | |
apdim = convert(Int, div(scan_param.aperture_size, scan_param.aperture)) | |
screen = zeros(Complex{Float64}, screendim, screendim) | |
delta = scan_param.aperture_size / apdim | |
all_aperture_coords = ((x,y) | |
for x = LinRange( | |
-scan_param.aperture_size/2, scan_param.aperture_size/2, apdim) | |
, y = LinRange( | |
-scan_param.aperture_size/2, scan_param.aperture_size/2, apdim)) | |
all_screen_coords = ((i, x, j, y) | |
for (i, x) = enumerate(LinRange( | |
-scan_param.screen_size/2, scan_param.screen_size/2, screendim)) | |
, (j, y) = enumerate(LinRange( | |
-scan_param.screen_size/2, scan_param.screen_size/2, screendim))) | |
k = 2pi/setup.lambda | |
all_screen_coords = collect(all_screen_coords) | |
count = 0 | |
@time begin for (apx, apy) = all_aperture_coords | |
if setup.aperture(apx, apy; setup.aperture_kwargs...) < 0.1 | |
continue | |
end | |
count += length(all_screen_coords) | |
Threads.@threads for (i, scx, j, scy) = all_screen_coords | |
#l, m = (sin(fastatan((scx-apx)/setup.screen_pos)), | |
# sin(fastatan((scy-apy)/setup.screen_pos))) | |
l, m = scx/setup.screen_pos, scy/setup.screen_pos | |
term = exp(-im*k*(l*apx + m*apy)) | |
screen[i, j] += term * delta^2 | |
end | |
end | |
end | |
println("calculate_fraunhofer_integral: $count iterations") | |
abs.(screen).^2, LinRange(-scan_param.screen_size/2, scan_param.screen_size/2, screendim) | |
end | |
# ╔═╡ 04f4e258-749c-4ac4-8fad-f1c15370a1d7 | |
function plot_fraunhofer_diffraction() | |
screen, coords = calculate_fraunhofer_integral(default_setup, | |
scan_param=default_scan_param); | |
fig = CM.Figure(resolution=(1300, 650)) | |
CM.Axis(fig[1,1]) | |
CM.heatmap!(coords, coords, (screen)) | |
axh = CM.Axis(fig[1, 2]) | |
axv = CM.Axis(fig[1,2], xaxisposition=:top, yaxisposition=:right) | |
mid = div(size(screen)[1], 2) | |
CM.lines!(axh, coords, view(screen, :, mid)/maximum(view(screen, :, mid)), | |
color=:green) | |
CM.lines!(axv, view(screen, mid, :)/maximum(view(screen, mid, :)), coords, | |
color=:red) | |
fig | |
end | |
# ╔═╡ 8502868f-c309-4391-9ef5-a83d5979ac77 | |
plot_fraunhofer_diffraction() | |
# ╔═╡ c83fc930-87c3-4b99-b947-6d06ac516429 | |
md"""### Diffraction pattern on plane | |
Here we calculate the intensities along a plane containing the (geometric) beam as it travels towards the screen. | |
The plane is configured in the `Plane` struct, which determines the rotation angle of the plane around the geometric beam axis, as well as the width and length of the plane. | |
Below we link these values with the aperture and screen settings used above, so that we always see the pattern on the way to the screen. | |
""" | |
# ╔═╡ 114b3dc2-39e3-4d97-b9f1-af60419bd0a8 | |
struct Plane | |
# 0 degrees = x plane | |
angle::Float64 | |
width::Float64 | |
wscan::Float64 | |
length::Float64 | |
lscan::Float64 | |
end | |
# ╔═╡ fdfc21ca-ea64-4726-9533-8694a27d40df | |
function calculate_plane_integral(setup::Setup, plane::Plane; | |
scan_param::ScanParam=default_scan_param) | |
screendim = (round(Int, div(plane.width, plane.wscan)), | |
round(Int, div(plane.length, plane.lscan))) | |
apdim = convert(Int, div(scan_param.aperture_size, scan_param.aperture)) | |
screen = zeros(Complex{Float64}, screendim) | |
delta = scan_param.aperture_size / apdim | |
k = 2pi / setup.lambda | |
all_aperture_coords = ((x,y) | |
for x = LinRange( | |
-scan_param.aperture_size/2, scan_param.aperture_size/2, apdim) | |
, y = LinRange( | |
-scan_param.aperture_size/2, scan_param.aperture_size/2, apdim)) | |
# For stepping, it is important to have a very slight angle at the least. | |
ang = plane.angle != 0 ? plane.angle : 0.1 | |
plane_n, plane_l_n = screendim | |
cosine = cos(ang/180*pi) | |
sine = sin(ang/180*pi) | |
all_trans_coords = enumerate(zip( | |
LinRange(-cosine*plane.width/2, cosine*plane.width/2, plane_n), | |
LinRange(-sine*plane.width/2, sine*plane.width/2, plane_n))) | |
all_plane_coords = ((i, x, y, j, z) | |
for (i, (x, y)) = all_trans_coords | |
for (j, z) = enumerate(LinRange(0, plane.length, plane_l_n)) | |
if i < plane_n && j < plane_l_n) | |
all_plane_coords = collect(all_plane_coords) | |
count = 0 | |
@time begin for (apx, apy) = all_aperture_coords | |
if setup.aperture(apx, apy; setup.aperture_kwargs...) < 0.1 | |
continue | |
end | |
count += length(all_plane_coords) | |
cdist = sqrt(apx^2+apy^2) | |
dists = [(fastatan(sum(((s.x, s.y) .- (apx, apy)).^2)/abs(s.z)), | |
sqrt(sum(((apx,apy,0) .- (s.x, s.y, s.z)).^2))) | |
for s = setup.source] | |
sourceterms = [(alpha, exp(-im * k * R)/R) for (alpha, R) = dists] | |
Threads.@threads for (i, x, y, j, z) = all_plane_coords | |
pointdist = sqrt((apx-x)^2 + (apy-y)^2) | |
r = sqrt(pointdist^2 + z^2) | |
beta = atan(pointdist / abs(setup.screen_pos)) | |
term = exp(-im*k*r)/r * sum( | |
((fastcos(beta)+fastcos(alpha))/2 * t | |
for (alpha, t) = sourceterms)) | |
# cos terms are only sometimes required | |
K = 1/(im*setup.lambda) | |
screen[i, j] += K * term * delta^2 | |
end | |
end | |
end | |
println("calculate_plane_integral: $count iterations") | |
(abs.(screen).^2, | |
LinRange(-plane.width/2, plane.width/2, plane_n), | |
LinRange(0, plane.length, plane_l_n)) | |
end | |
# ╔═╡ 79480cf1-834d-4458-80a6-c5bb246ec39d | |
begin | |
#plane = Plane(0, 0.025, 0.025/200, 20, 20/100) | |
plane = Plane(90, default_scan_param.screen_size, default_scan_param.screen/2, | |
default_setup.screen_pos, default_setup.screen_pos/100) | |
end | |
# ╔═╡ 1efe51d4-1edf-4772-b91a-ca04475e31c5 | |
function plot_diffraction_on_plane() | |
screen, wcoords, lcoords = calculate_plane_integral(default_setup, plane); | |
fig = CM.Figure(resolution=(1300, 1300)) | |
CM.Axis(fig[1,1]) | |
CM.heatmap!(wcoords, lcoords, log.(screen)) | |
CM.Axis(fig[1, 2]) | |
mid = div(size(screen)[1], 2) | |
CM.lines!(-log.(screen[mid, :]), lcoords) | |
fig | |
end | |
# ╔═╡ 5308c06f-c14b-4d3c-8283-a833a008a532 | |
plot_diffraction_on_plane() | |
# ╔═╡ a9d05389-9d58-4d7c-a3ed-3ea7a1c5ab38 | |
md"""### Babinet's principle | |
[Babinet's Principle](https://en.wikipedia.org/wiki/Babinet%27s_principle) | |
Show diffraction for inverted aperture. | |
Consider that the used aperture is square and usually of very limited length: Major artifacts will stem from that fact. | |
""" | |
# ╔═╡ 2de1ca1a-8741-4364-ae91-4819e6447927 | |
function plot_inverse_diffraction() | |
setup = default_setup | |
aperture = setup.aperture | |
setup = @set setup.aperture = (x, y; kwargs...) -> (invertshape(aperture(x, y; kwargs...))) | |
screen, coords = calculate_integral(setup); | |
fig = CM.Figure(resolution=(1300, 650)) | |
CM.Axis(fig[1,1]) | |
CM.heatmap!(coords, coords, (screen)) | |
axh = CM.Axis(fig[1, 2]) | |
axv = CM.Axis(fig[1,2], xaxisposition=:top, yaxisposition=:right) | |
mid = div(size(screen)[1], 2) | |
CM.lines!(axh, coords, view(screen, :, mid)/maximum(view(screen, :, mid)), | |
color=:green) | |
CM.lines!(axv, view(screen, mid, :)/maximum(view(screen, mid, :)), coords, | |
color=:red) | |
fig | |
end | |
# ╔═╡ b7e30300-1bd3-4eab-a0d6-93d4902e9b9d | |
plot_inverse_diffraction() | |
# ╔═╡ db083fe4-b5ba-4502-8258-2aceb84e6e42 | |
md"""### Plane Wave diffraction | |
In the limit of far distance of the point source to the screen, we get plane waves. | |
By directly assuming plane waves, we can calculate faster. D different setup and scan configurations are used here, too. However, they are linked to the configuration above by default to allow a 1:1 comparison of point source images to plane wave images. | |
""" | |
# ╔═╡ 202e0940-2fd2-4f6e-983a-83d7025c91de | |
begin | |
# Distance of source, shape function, shape parameters, | |
# distance to screen, wavelength | |
plane_setup = Setup([Source(z=-80)], double_slit, Dict(), 20, 500e-9) | |
plane_setup = default_setup | |
end | |
# ╔═╡ 1ff2be95-ecc6-4a90-9205-f425535039d7 | |
begin | |
plane_scan_param = ScanParam( | |
# Aperture scan size and scan step, in m, depends on aperture function | |
0.005, .005/100, | |
# Screen size and scan step in m. | |
.025, .025/100) | |
# Override: use identical plane as above | |
plane_scan_param = default_scan_param | |
end | |
# ╔═╡ 352c281e-11d7-4158-9528-e05a4717cf7d | |
function calculate_integral_planewave(setup::Setup; | |
scan_param::ScanParam=plane_scan_param) | |
screendim = convert(Int, div(scan_param.screen_size, scan_param.screen)) | |
apdim = convert(Int, div(scan_param.aperture_size, scan_param.aperture)) | |
screen = zeros(Complex{Float64}, screendim, screendim) | |
delta = scan_param.aperture_size / apdim | |
all_aperture_coords = ((x,y) | |
for x = LinRange( | |
-scan_param.aperture_size/2, scan_param.aperture_size/2, apdim) | |
for y = LinRange( | |
-scan_param.aperture_size/2, scan_param.aperture_size/2, apdim)) | |
all_screen_coords = ((i, x, j, y) | |
for (i, x) = enumerate(LinRange( | |
-scan_param.screen_size/2, scan_param.screen_size/2, screendim)) | |
for (j, y) = enumerate(LinRange( | |
-scan_param.screen_size/2, scan_param.screen_size/2, screendim))) | |
all_screen_coords = collect(all_screen_coords) | |
k = 2pi/setup.lambda | |
count = 0 | |
@time begin for (apx, apy) = all_aperture_coords | |
if setup.aperture(apx, apy; setup.aperture_kwargs...) < 0.1 | |
continue | |
end | |
count += length(all_screen_coords) | |
alpha = 0 | |
Threads.@threads for (i, scx, j, scy) = all_screen_coords | |
pointdist = sqrt((apx-scx)^2 + (apy-scy)^2) | |
r = sqrt(pointdist^2 + setup.screen_pos^2) | |
beta = atan(pointdist / abs(setup.screen_pos)) | |
term = exp(-im*(k*r))/(r) | |
K = 1/(im*setup.lambda) * (fastcos(alpha)+fastcos(beta))/2 | |
screen[i, j] += K * term * delta^2 | |
end | |
end | |
end | |
println("calculate_integral_planewave: $count iterations") | |
(abs.(screen).^2, | |
LinRange(-scan_param.screen_size/2, scan_param.screen_size/2, screendim)) | |
end | |
# ╔═╡ 5488a918-315f-4b0d-bf0b-d26d873583fe | |
function plot_diffraction_planewave() | |
screen, coords = calculate_integral_planewave(plane_setup); | |
fig = CM.Figure(resolution=(1300, 650)) | |
CM.Axis(fig[1,1]) | |
CM.heatmap!(coords, coords, (screen)) | |
axh = CM.Axis(fig[1, 2]) | |
axv = CM.Axis(fig[1,2], xaxisposition=:top, yaxisposition=:right) | |
mid = div(size(screen)[1], 2) | |
CM.lines!(axh, coords, view(screen, :, mid)/maximum(view(screen, :, mid)), | |
color=:green) | |
CM.lines!(axv, view(screen, mid, :)/maximum(view(screen, :, mid)), coords, | |
color=:red) | |
fig | |
end | |
# ╔═╡ b3cd8248-2e5c-4730-ba9c-fe99d2c79e78 | |
plot_diffraction_planewave() | |
# ╔═╡ Cell order: | |
# ╠═87c80fda-9eda-11eb-2ac5-b7b5006b19b7 | |
# ╠═836ad30f-20cd-4f1b-9142-e47bc6e90aa0 | |
# ╠═27295f24-fd52-4608-865b-8d77a02762f7 | |
# ╠═b6a6faa5-684d-4d77-82a1-ae5e1618b12f | |
# ╠═af3b9d5e-385f-4b22-b140-468f094e1424 | |
# ╠═f218f7bf-b88b-4f30-91b3-51aa4e3eb373 | |
# ╠═6574c144-ef7e-467f-ba52-2b6beb7672fd | |
# ╠═c81b24c9-9f7b-48a1-bb2e-28fd314ee0d7 | |
# ╠═fe40f98f-7344-497a-b965-436ea0380efd | |
# ╠═db008850-db81-4c85-a46d-04fea3f04837 | |
# ╠═54feae63-2bce-4e22-b41e-461bf3056275 | |
# ╠═ea0d82b8-b040-4aa3-a8e1-fad9eec948e2 | |
# ╠═12afa06a-4893-40ac-8692-1366ae8dcdda | |
# ╠═126adaa2-a420-4d58-b121-0c97a9eca83a | |
# ╠═b76a6f05-dd85-4c64-9ab7-fe17d7e11774 | |
# ╠═5b7646f9-7935-4aa8-8d81-b236dfdc5c9a | |
# ╠═1b974614-3748-43b2-bd28-9933aec8d860 | |
# ╠═d2b812f6-cbd7-407e-a0e4-eea53a73dd76 | |
# ╠═40f819d3-4a86-4b2c-9b18-b9b4143e3a96 | |
# ╠═64bad78e-e34a-4562-9168-d7e27ecd3158 | |
# ╠═5b11a45e-4430-4db7-8909-cd08c8bd142f | |
# ╠═1488f2ee-1741-4676-9e14-93dd4e22fbb4 | |
# ╠═06ffee0e-1189-4645-bab2-9e938db0620d | |
# ╠═a23a6d00-4d4e-4868-86a7-fa8c638ee8ea | |
# ╠═a22f16ca-14a9-4a69-bf0f-c84fba39a836 | |
# ╠═0765cbcc-f0f1-4dfd-94e2-14358e6e6b28 | |
# ╠═0839fb51-ba56-4f70-8e69-bbb41685c2b2 | |
# ╠═c0393e2b-28fd-4d9b-869d-ffeb0fdb8d24 | |
# ╠═65cd7931-4dcf-4644-94d7-149effce4cce | |
# ╠═1ccd1e55-fe40-4683-af90-8b15617d63b1 | |
# ╠═d2a3d02f-7eb3-42d6-9765-16e5bbc99d8b | |
# ╠═1c3bfcfd-1332-49d4-9b98-ceecc8c2926a | |
# ╠═e0abeb58-afd8-42d9-b0fc-fb55cc383323 | |
# ╠═6c0b1f38-f692-4b3e-ac08-c0f71734ed05 | |
# ╠═92147968-94e2-41d1-ad15-857eb5f06f60 | |
# ╠═1f538236-9883-4c44-a3ab-5cf5a4b01ee1 | |
# ╠═1aada718-2e07-48fa-b794-708e2ea23d8b | |
# ╠═1b0e2b99-a65d-441d-b038-159ccc48e6f0 | |
# ╠═e134d03f-3771-4056-acd7-d4a8d74f2cf7 | |
# ╠═04f4e258-749c-4ac4-8fad-f1c15370a1d7 | |
# ╠═8502868f-c309-4391-9ef5-a83d5979ac77 | |
# ╠═c83fc930-87c3-4b99-b947-6d06ac516429 | |
# ╠═114b3dc2-39e3-4d97-b9f1-af60419bd0a8 | |
# ╠═fdfc21ca-ea64-4726-9533-8694a27d40df | |
# ╠═79480cf1-834d-4458-80a6-c5bb246ec39d | |
# ╠═1efe51d4-1edf-4772-b91a-ca04475e31c5 | |
# ╠═5308c06f-c14b-4d3c-8283-a833a008a532 | |
# ╠═a9d05389-9d58-4d7c-a3ed-3ea7a1c5ab38 | |
# ╠═6d796395-5024-4129-a250-df2401327711 | |
# ╠═2de1ca1a-8741-4364-ae91-4819e6447927 | |
# ╠═b7e30300-1bd3-4eab-a0d6-93d4902e9b9d | |
# ╠═db083fe4-b5ba-4502-8258-2aceb84e6e42 | |
# ╠═352c281e-11d7-4158-9528-e05a4717cf7d | |
# ╠═5488a918-315f-4b0d-bf0b-d26d873583fe | |
# ╠═202e0940-2fd2-4f6e-983a-83d7025c91de | |
# ╠═1ff2be95-ecc6-4a90-9205-f425535039d7 | |
# ╠═b3cd8248-2e5c-4730-ba9c-fe99d2c79e78 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment