Quarter Wavelength Antenna
Complete file at examples folder
We simulate a quarter wavelength antenna above conductor ground plane and compute its nearfield radiation pattern
using UnPack, LinearAlgebra, GLMakie, CoordinateTransformations
using GLMakie: volume
using Luminescent, LuminescentVisualization
# if running directly without module # hide
# include("$(pwd())/src/main.jl") # hide
# include("$(pwd())/../LuminescentVisualization.jl/src/main.jl") # hide
name = "quarter_wavelength_antenna"
F = Float32
dogpu = false
T = 8.0 # simulation duration in [periods]
nx = 20
dx = 1.0 / nx # pixel resolution in [wavelengths]
l = 2 # simulation domain lxlxl box
sz = nx .* (l, l, l)
ϵ = ones(F, sz)
μ = ones(F, sz)
σ = zeros(F, sz)
m = zeros(F, sz)
Set Spherical monitor centered on ground. Portions outside domain eg bottom hemisphere are automatically discarded
boundaries = [PEC(-3)] # ground plane on -z, unspecified boundaries default to PML
monitors = [
# (center, radius)
SphereMonitor([l / 2, l / 2, 0], 1),
]
sources = [
# (signal, center, dimensions)
Source(t -> cos(2π * t), [l / 2, l / 2, 0.125], [0, 0, 0.25]; Jz=1),
]
prob = setup(boundaries, sources, monitors, dx, sz; F,)
@unpack dt, geometry_padvals, field_lims, field_boundvals, source_instances, monitor_instances, u0, = prob
p = apply(geometry_padvals; ϵ, μ, σ, m)
p = apply(field_lims, p)
# move to gpu
if dogpu
using Flux
# using CUDA
# @assert CUDA.functional()
u0, p, field_boundvals, source_instances = gpu.((u0, p, field_boundvals, source_instances))
end
We run simulation as an accumulate
loop. update!
applies Maxwells equations
as staggered time stepping on E, H. It's mutating so a copy is made in order to save sequence of
states
@showtime u = accumulate(0:dt:T, init=u0) do u, t
update!(deepcopy(u), p, t, dx, dt, field_boundvals, source_instances)
end
# move back to cpu for plotting
if dogpu
u, p, field_boundvals, source_instances = cpu.((u, p, field_boundvals, source_instances))
end
Plot nearfield Poynting flux thru our Spherical monitor integrated for 1 period
nt = round(Int, 1 / dt)
r = dt * sum(flux.(u[end-nt+1:end], (monitor_instances[1],),))
_, θ, ϕ = eachrow(sphcoords(monitors[1])[:, inbounds(monitor_instances[1])])
cfs = CartesianFromSpherical()
rvecs = cfs.(splat(Spherical).(zip(r, F.(θ), F.(ϕ))))
fig = Figure()
ax = Axis3(fig[1, 1])
plot!(ax, getindex.(rvecs, 1), getindex.(rvecs, 2), getindex.(rvecs, 3),)
display(fig)
save("antennapattern.png", fig)
Ready, set, action! We make movie,
Ez = field.(u, :Ez)
ϵEz = field(p, :ϵEz)
dir = @__DIR__
recordsim("$dir/$(name).mp4", Ez, ;
dt,
field=:Ez,
monitor_instances,
source_instances,
geometry=ϵEz,
elevation=30°,
playback=1,
axis1=(; title="$name Ez"),
# axis2=(; title="monitor powers"),
)