rework run script to enable stepping and simulating while watching
parent
3e283fb94e
commit
24d32768c5
|
|
@ -1,31 +1,131 @@
|
||||||
include("../src/AnimalFurFHN.jl") # this loads the module code
|
using GLMakie, Observables
|
||||||
using .AnimalFurFHN
|
using .AnimalFurFHN
|
||||||
# include optional visualizer only if needed:
|
|
||||||
include("../src/visualization.jl")
|
|
||||||
using .Visualization
|
|
||||||
|
|
||||||
N = 256
|
|
||||||
# tspan = (0.0, 1000.0)
|
|
||||||
|
|
||||||
# sol = AnimalFurFHN.run_simulation(tspan, N)
|
|
||||||
|
|
||||||
|
|
||||||
# Visualization.step_through_solution(sol, N)
|
# Parameters and initial conditions
|
||||||
|
N = 128
|
||||||
|
dx = 1.0
|
||||||
|
Du, Dv = Observable(0.16), Observable(0.08)
|
||||||
|
F, k = Observable(0.060), Observable(0.062)
|
||||||
|
dt = 1.0
|
||||||
|
params_obs = Observable(AnimalFurFHN.GSParams(N, dx, 0.16, 0.08, 0.08, 0.06))
|
||||||
|
|
||||||
using Plots
|
function update_params!(params_obs, u, v, feed, kill)
|
||||||
|
old = params_obs[]
|
||||||
function animate_gray_scott(sol, N; var=:U)
|
params_obs[] = AnimalFurFHN.GSParams(old.N, old.dx, u, v, feed, kill)
|
||||||
anim = @animate for t in 1:length(sol.t)
|
|
||||||
u = reshape(sol[t][1:N^2], N, N)
|
|
||||||
v = reshape(sol[t][N^2+1:end], N, N)
|
|
||||||
data = var == :U ? u : v
|
|
||||||
Plots.heatmap(data, c=:magma, title="$var at t=$(Int(sol.t[t]))", clims=(0, 1))
|
|
||||||
end
|
|
||||||
gif(anim, "gif/gray_scott.gif", fps=15)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# set time to more than 1000
|
lift(Du, Dv, F, k) do u, v, F, k
|
||||||
sol = AnimalFurFHN.run_simulationG((0.0, 10000.0), 256)
|
update_params!(params_obs, u, v, F, k)
|
||||||
|
end
|
||||||
|
U = ones(N, N)
|
||||||
|
V = zeros(N, N)
|
||||||
|
center = N ÷ 2
|
||||||
|
radius = 10
|
||||||
|
U[center-radius:center+radius, center-radius:center+radius] .= 0.50
|
||||||
|
V[center-radius:center+radius, center-radius:center+radius] .= 0.25
|
||||||
|
|
||||||
Visualization.step_through_solution(sol, N)
|
# Observable holding current U for heatmap
|
||||||
# animate_gray_scott(sol, 256, var=:U)
|
heat_obs = Observable(U)
|
||||||
|
|
||||||
|
function laplacian5(f)
|
||||||
|
h2 = dx^2
|
||||||
|
left = f[2:end-1, 1:end-2]
|
||||||
|
right = f[2:end-1, 3:end]
|
||||||
|
down = f[3:end, 2:end-1]
|
||||||
|
up = f[1:end-2, 2:end-1]
|
||||||
|
center = f[2:end-1, 2:end-1]
|
||||||
|
return (left .+ right .+ down .+ up .- 4 .* center) ./ h2
|
||||||
|
end
|
||||||
|
|
||||||
|
function step!(U, V)
|
||||||
|
lap_u = laplacian5(U)
|
||||||
|
lap_v = laplacian5(V)
|
||||||
|
|
||||||
|
u = U[2:end-1, 2:end-1]
|
||||||
|
v = V[2:end-1, 2:end-1]
|
||||||
|
|
||||||
|
uvv = u .* v .* v
|
||||||
|
u_new = u .+ (Du[] .* lap_u .- uvv .+ F[] .* (1 .- u)) .* dt
|
||||||
|
v_new = v .+ (Dv[] .* lap_v .+ uvv .- (F[] .+ k[]) .* v) .* dt
|
||||||
|
|
||||||
|
# Update with new values
|
||||||
|
U[2:end-1, 2:end-1] .= u_new
|
||||||
|
V[2:end-1, 2:end-1] .= v_new
|
||||||
|
|
||||||
|
# Periodic boundary conditions
|
||||||
|
U[1, :] .= U[end-1, :]
|
||||||
|
U[end, :] .= U[2, :]
|
||||||
|
U[:, 1] .= U[:, end-1]
|
||||||
|
U[:, end] .= U[:, 2]
|
||||||
|
|
||||||
|
V[1, :] .= V[end-1, :]
|
||||||
|
V[end, :] .= V[2, :]
|
||||||
|
V[:, 1] .= V[:, end-1]
|
||||||
|
V[:, end] .= V[:, 2]
|
||||||
|
|
||||||
|
# Update heatmap observable
|
||||||
|
heat_obs[] = copy(U)
|
||||||
|
end
|
||||||
|
function multi_step!(state, n_steps)
|
||||||
|
for _ in 1:n_steps
|
||||||
|
step!(state[1], state[2])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Build GUI
|
||||||
|
fig = Figure(size=(600, 600))
|
||||||
|
ax = Axis(fig[1, 1])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
hm = Makie.heatmap!(ax, heat_obs, colormap=:magma)
|
||||||
|
ax.aspect = DataAspect()
|
||||||
|
|
||||||
|
# # Controls
|
||||||
|
|
||||||
|
fig[2, 1] = buttongrid = GridLayout(tellwidth=false)
|
||||||
|
btn_step = Button(buttongrid[1, 1], label="Step")
|
||||||
|
btn_start = Button(buttongrid[1, 2], label="Start")
|
||||||
|
btn_stop = Button(buttongrid[1, 3], label="Stop")
|
||||||
|
|
||||||
|
|
||||||
|
fig[3, 1] = textboxgrid = GridLayout(tellwidth=false)
|
||||||
|
box_u = Textbox(textboxgrid[1, 1], validator=Float64, placeholder="word")
|
||||||
|
# box_v = Textbox(textboxgrid[1, 2], validator=Float64, placeholder="word")
|
||||||
|
# box_feed = Textbox(textboxgrid[1, 3], validator=Float64, placeholder="word")
|
||||||
|
# box_kill = Textbox(textboxgrid[1, 4], validator=Float64, placeholder="word")
|
||||||
|
# Timer and state for animation
|
||||||
|
running = Observable(false)
|
||||||
|
|
||||||
|
function animation_loop()
|
||||||
|
while running[]
|
||||||
|
# step!(U, V)
|
||||||
|
multi_step!((U, V), 30)
|
||||||
|
sleep(0.05) # ~20 FPS
|
||||||
|
end
|
||||||
|
end
|
||||||
|
on(box_u.stored_string) do s
|
||||||
|
try
|
||||||
|
Du[] = parse(Float64, s)
|
||||||
|
catch
|
||||||
|
@warn "Invalid input for Du: $s"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
on(btn_step.clicks) do _
|
||||||
|
multi_step!((U, V), 30)
|
||||||
|
end
|
||||||
|
|
||||||
|
on(btn_start.clicks) do _
|
||||||
|
if !running[]
|
||||||
|
running[] = true
|
||||||
|
@async animation_loop()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
on(btn_stop.clicks) do _
|
||||||
|
running[] = false
|
||||||
|
end
|
||||||
|
|
||||||
|
display(fig)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue