Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,293 changes: 1,293 additions & 0 deletions docs/EXAMPLES.md

Large diffs are not rendered by default.

1,463 changes: 1,463 additions & 0 deletions docs/ROADMAP.md

Large diffs are not rendered by default.

68 changes: 45 additions & 23 deletions examples/dipole.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,52 @@ using CairoMakie

Khronos.choose_backend(Khronos.CUDADevice(), Float64)

# Place a z-polarized dipole with a wavelength 1μm at the center
sources = [
Khronos.UniformSource(
time_profile = Khronos.ContinuousWaveSource(fcen = 1.0),
component = Khronos.Ex(),
center = [0.0, 0.0, 0.0],
size = [0.0, 0.0, 0.0],
# we add a pi phase shift to force a sine wave, rather than a cosine.
amplitude = 1im,
),
]

# Build the simulation object, such that it spans a cube 10μm×10μm×10μm. Place PML 1μm thick.
sim = Khronos.Simulation(
cell_size = [4.0, 4.0, 4.0],
cell_center = [0.0, 0.0, 0.0],
resolution = 10,#40,
sources = sources,
boundaries = [[1.0, 1.0], [1.0, 1.0], [1.0, 1.0]],
)
function build_dipole_sim()
# Place a z-polarized dipole with a wavelength 1μm at the center
sources = [
Khronos.UniformSource(
time_profile = Khronos.ContinuousWaveSource(fcen = 1.0),
component = Khronos.Ex(),
center = [0.0, 0.0, 0.0],
size = [0.0, 0.0, 0.0],
# we add a pi phase shift to force a sine wave, rather than a cosine.
amplitude = 1im,
),
]

# Build the simulation object, such that it spans a cube 10μm×10μm×10μm. Place PML 1μm thick.
sim = Khronos.Simulation(
cell_size = [4.0, 4.0, 4.0],
cell_center = [0.0, 0.0, 0.0],
resolution = 10,#40,
sources = sources,
boundaries = [[1.0, 1.0], [1.0, 1.0], [1.0, 1.0]],
)
return sim
end

function run_dipole()
sim = build_dipole_sim()
t_end = 1.0#40.0;
Khronos.run(sim, until = t_end)
return sim
end

# --- Run 1: includes JIT compilation ---
println("=" ^ 60)
println("RUN 1 (cold — includes JIT compilation)")
println("=" ^ 60)
t1 = time()
sim = run_dipole()
println("Run 1 total wall time: $(round(time() - t1, digits=3))s\n")

# Run the simulation for 10 "time units"
t_end = 1.0#40.0;
Khronos.run(sim, until = t_end)
# --- Run 2: fresh sim, JIT already done ---
println("=" ^ 60)
println("RUN 2 (warm — JIT already compiled)")
println("=" ^ 60)
t2 = time()
sim = run_dipole()
println("Run 2 total wall time: $(round(time() - t2, digits=3))s\n")

# Plot cross sections of the result
scene = Khronos.plot2D(
Expand Down
38 changes: 23 additions & 15 deletions examples/gaussian_beam.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ function build_simulation(λ, waist_radius, resolution)
return sim
end

function run_simulation!(sim::Khronos.SimulationData)
function run_gaussian_beam()
λ = 1.0
waist_radius = 0.75
resolution = 20.0
sim = build_simulation(λ, waist_radius, resolution)
Khronos.run(
sim,
until_after_sources = Khronos.stop_when_dft_decayed(
Expand All @@ -62,27 +66,31 @@ function run_simulation!(sim::Khronos.SimulationData)
maximum_runtime = 300.0,
),
)
return sim
end

function plot_source_profile!(sim::Khronos.SimulationData)
Khronos.prepare_simulation!(sim)
Ex = sum(sim.source_data[1].amplitude_data, dims = 3)[:, :, 1]
heatmap(Ex)
end

# --- Run 1: includes JIT compilation ---
println("=" ^ 60)
println("RUN 1 (cold — includes JIT compilation)")
println("=" ^ 60)
t1 = time()
sim = run_gaussian_beam()
println("Run 1 total wall time: $(round(time() - t1, digits=3))s\n")

# --- Run 2: fresh sim, JIT already done ---
println("=" ^ 60)
println("RUN 2 (warm — JIT already compiled)")
println("=" ^ 60)
t2 = time()
sim = run_gaussian_beam()
println("Run 2 total wall time: $(round(time() - t2, digits=3))s\n")

# Visualize the source profile
λ = 1.0
waist_radius = 0.75
resolution = 20.0

sim = build_simulation(λ, waist_radius, resolution)

# Visualize the source profile in the time and frequency domains
frequencies = 0.75:0.005:1.25
scene = Khronos.plot_timesource(sim, sim.sources[1], frequencies)
save("sources.png", scene)

run_simulation!(sim)

# Visualize the response of the monitor
scene = Khronos.plot_monitor(sim.monitors[1], 1)
save("gaussian_beam.png", scene)
67 changes: 39 additions & 28 deletions examples/periodic_slab.jl
Original file line number Diff line number Diff line change
Expand Up @@ -105,39 +105,50 @@ function compute_power(sim::Khronos.SimulationData)
return sum(abs.(sim.monitors[1].monitor_data.fields) .^ 2, dims = [1, 2])[1, 1, 1, :]
end

function main()
# Arbitrary simulation parameters that produce at least two maxima
d = 0.5
n = 3.5
λ = range(1.0, 2.0, length = 100)
resolution = 50

sim = build_simulation(d, n, λ, resolution; plot_geometry = false)
# Arbitrary simulation parameters that produce at least two maxima
d = 0.5
n = 3.5
λ = range(1.0, 2.0, length = 100)
resolution = 50

function run_periodic_slab(d, n, λ, resolution)
# Run a normalization simulation
run_simulation!(sim)

# Compute the total power to normalize the actual simulation
baseline = compute_power(sim)
sim_norm = build_simulation(d, n, λ, resolution; plot_geometry = false)
run_simulation!(sim_norm)
baseline = compute_power(sim_norm)

# Run the actual simulation
sim = build_simulation(d, n, λ, resolution; plot_geometry = true)
run_simulation!(sim)
slab = compute_power(sim)
sim_slab = build_simulation(d, n, λ, resolution; plot_geometry = true)
run_simulation!(sim_slab)
slab = compute_power(sim_slab)

# Normalize the transmission response
T_Khronos = slab ./ baseline

# Compute the analytic response for comparison
T = slab_analytical(d, n, λ)

# Plot the comparison
f = Figure()
ax = Axis(f[1, 1], xlabel = "λ (μm)", ylabel = "T (a.u.)")
line1 = scatterlines!(ax, λ, Array(T))
line2 = scatterlines!(ax, λ, Array(T_Khronos))
legend = Legend(f[1, 2], [line1, line2], ["Analytic", "Khronos"])
save("periodic_slab.png", f)
return T_Khronos
end

main()
# --- Run 1: includes JIT compilation ---
println("=" ^ 60)
println("RUN 1 (cold — includes JIT compilation)")
println("=" ^ 60)
t1 = time()
T_Khronos = run_periodic_slab(d, n, λ, resolution)
println("Run 1 total wall time: $(round(time() - t1, digits=3))s\n")

# --- Run 2: fresh sim, JIT already done ---
println("=" ^ 60)
println("RUN 2 (warm — JIT already compiled)")
println("=" ^ 60)
t2 = time()
T_Khronos = run_periodic_slab(d, n, λ, resolution)
println("Run 2 total wall time: $(round(time() - t2, digits=3))s\n")

# Compute the analytic response for comparison
T = slab_analytical(d, n, λ)

# Plot the comparison
f = Figure()
ax = Axis(f[1, 1], xlabel = "λ (μm)", ylabel = "T (a.u.)")
line1 = scatterlines!(ax, λ, Array(T))
line2 = scatterlines!(ax, λ, Array(T_Khronos))
legend = Legend(f[1, 2], [line1, line2], ["Analytic", "Khronos"])
save("periodic_slab.png", f)
27 changes: 23 additions & 4 deletions examples/planewave.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,30 @@ function build_simulation(λ, resolution)
return sim
end

λ = 1.0
resolution = 40.0
function run_planewave()
λ = 1.0
resolution = 40.0
sim = build_simulation(λ, resolution)
Khronos.run(sim, until = 60)
return sim
end

# --- Run 1: includes JIT compilation ---
println("=" ^ 60)
println("RUN 1 (cold — includes JIT compilation)")
println("=" ^ 60)
t1 = time()
sim = run_planewave()
println("Run 1 total wall time: $(round(time() - t1, digits=3))s\n")

# --- Run 2: fresh sim, JIT already done ---
println("=" ^ 60)
println("RUN 2 (warm — JIT already compiled)")
println("=" ^ 60)
t2 = time()
sim = run_planewave()
println("Run 2 total wall time: $(round(time() - t2, digits=3))s\n")

sim = build_simulation(λ, resolution)
Khronos.run(sim, until = 60)
scene = Khronos.plot2D(
sim,
Khronos.Ex(),
Expand Down
25 changes: 21 additions & 4 deletions examples/sphere.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,28 @@ function build_sphere_sim(resolution, radius; include_loss = false)
return sim, s_xyz
end

sim, s_xyz = build_sphere_sim(20.0, 1.0; include_loss = true)
function run_sphere()
sim, s_xyz = build_sphere_sim(20.0, 1.0; include_loss = true)
t_end = 10.0;
Khronos.run(sim, until = t_end)
return sim, s_xyz
end

# --- Run 1: includes JIT compilation ---
println("=" ^ 60)
println("RUN 1 (cold — includes JIT compilation)")
println("=" ^ 60)
t1 = time()
sim, s_xyz = run_sphere()
println("Run 1 total wall time: $(round(time() - t1, digits=3))s\n")

# Run the simulation until steady state
t_end = 10.0;
Khronos.run(sim, until = t_end)
# --- Run 2: fresh sim, JIT already done ---
println("=" ^ 60)
println("RUN 2 (warm — JIT already compiled)")
println("=" ^ 60)
t2 = time()
sim, s_xyz = run_sphere()
println("Run 2 total wall time: $(round(time() - t2, digits=3))s\n")

# Visualize the fields
scene = Khronos.plot2D(
Expand Down
35 changes: 21 additions & 14 deletions examples/waveguide.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,22 +46,29 @@ function build_waveguide_simulation(λ::Number)
return sim
end

λ = 1.55
sim = build_waveguide_simulation(λ)

# scene = Khronos.plot2D(
# sim,
# nothing,
# Khronos.Volume([0.0, 0.0, 0.0], [6.0, 2.0, 2.0]);
# plot_geometry=true,
# )

function run_waveguide()
λ = 1.55
sim = build_waveguide_simulation(λ)
t_end = 40.0;
Khronos.run(sim, until = t_end)
return sim
end

# scene = Khronos.plot_source(sim, sim.sources[1])
# save("waveguide_source.png", scene)
# --- Run 1: includes JIT compilation ---
println("=" ^ 60)
println("RUN 1 (cold — includes JIT compilation)")
println("=" ^ 60)
t1 = time()
sim = run_waveguide()
println("Run 1 total wall time: $(round(time() - t1, digits=3))s\n")

t_end = 40.0;
Khronos.run(sim, until = t_end)
# --- Run 2: fresh sim, JIT already done ---
println("=" ^ 60)
println("RUN 2 (warm — JIT already compiled)")
println("=" ^ 60)
t2 = time()
sim = run_waveguide()
println("Run 2 total wall time: $(round(time() - t2, digits=3))s\n")

scene = Khronos.plot2D(
sim,
Expand Down
Loading
Loading