Switch zwischen FHN und GrayScott einbauen #5
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
julia_version = "1.11.5"
|
||||
manifest_format = "2.0"
|
||||
project_hash = "5fd84347cd356de5b819aa3ea793fa63c45180e4"
|
||||
project_hash = "b5f5f0b50b1e0b7dd05bb93e0b1bb03fea235d53"
|
||||
|
||||
[[deps.ADTypes]]
|
||||
git-tree-sha1 = "e2478490447631aedba0823d4d7a80b2cc8cdb32"
|
||||
|
|
@ -635,9 +635,9 @@ uuid = "4e289a0a-7415-4d19-859d-a7e5c4648b56"
|
|||
version = "1.0.5"
|
||||
|
||||
[[deps.EnzymeCore]]
|
||||
git-tree-sha1 = "7d7822a643c33bbff4eab9c87ca8459d7c688db0"
|
||||
git-tree-sha1 = "8272a687bca7b5c601c0c24fc0c71bff10aafdfd"
|
||||
uuid = "f151be2c-9106-41f4-ab19-57ee4f262869"
|
||||
version = "0.8.11"
|
||||
version = "0.8.12"
|
||||
weakdeps = ["Adapt"]
|
||||
|
||||
[deps.EnzymeCore.extensions]
|
||||
|
|
@ -1419,9 +1419,9 @@ version = "1.11.0"
|
|||
|
||||
[[deps.MathTeXEngine]]
|
||||
deps = ["AbstractTrees", "Automa", "DataStructures", "FreeTypeAbstraction", "GeometryBasics", "LaTeXStrings", "REPL", "RelocatableFolders", "UnicodeFun"]
|
||||
git-tree-sha1 = "31a99cb7537f812e1d6be893a71804c35979f1be"
|
||||
git-tree-sha1 = "6e64d2321257cc52f47e193407d0659ea1b2b431"
|
||||
uuid = "0a4f8689-d25c-4efe-a92b-7142dfc1aa53"
|
||||
version = "0.6.4"
|
||||
version = "0.6.5"
|
||||
|
||||
[[deps.MatrixFactorizations]]
|
||||
deps = ["ArrayLayouts", "LinearAlgebra", "Printf", "Random"]
|
||||
|
|
@ -2784,9 +2784,9 @@ version = "2.0.3+0"
|
|||
|
||||
[[deps.libpng_jll]]
|
||||
deps = ["Artifacts", "JLLWrappers", "Libdl", "Zlib_jll"]
|
||||
git-tree-sha1 = "002748401f7b520273e2b506f61cab95d4701ccf"
|
||||
git-tree-sha1 = "cd155272a3738da6db765745b89e466fa64d0830"
|
||||
uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f"
|
||||
version = "1.6.48+0"
|
||||
version = "1.6.49+0"
|
||||
|
||||
[[deps.libsixel_jll]]
|
||||
deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "Libdl", "libpng_jll"]
|
||||
|
|
|
|||
|
|
@ -1,58 +1,34 @@
|
|||
include("../src/utils/constants.jl")
|
||||
#include("../src/fhn_solver.jl")
|
||||
include("../src/gray_scott_solver.jl")
|
||||
include("../src/visualization.jl")
|
||||
|
||||
using Observables
|
||||
using GLMakie
|
||||
|
||||
using .Constants
|
||||
using .Visualization.Constants
|
||||
|
|
||||
using .Visualization
|
||||
|
||||
# GSParams
|
||||
# GSParams AND FHNParams
|
||||
N = 128
|
||||
dx = 1.0
|
||||
Du, Dv = Observable(0.16), Observable(0.08)
|
||||
F, k = Observable(0.060), Observable(0.062)
|
||||
|
||||
param_observables = (
|
||||
Du=Du,
|
||||
Dv=Dv,
|
||||
F=F,
|
||||
k=k,
|
||||
params = (
|
||||
N=Observable(128),
|
||||
dx=Observable(1.0),
|
||||
Du=Observable(0.16),
|
||||
Dv=Observable(0.08),
|
||||
F=Observable(0.060),
|
||||
k=Observable(0.062),
|
||||
ϵ=Observable(0.05),
|
||||
a=Observable(0.7),
|
||||
b=Observable(0.8)
|
||||
)
|
||||
|
||||
"""
|
||||
# FHNParams
|
||||
N = 128
|
||||
dx = 1.0
|
||||
Du, Dv = Observable(0.016), Observable(0.1)
|
||||
ϵ, a, b = Observable(0.1), Observable(0.5), Observable(0.9)
|
||||
param_observables = (
|
||||
Du=Du,
|
||||
Dv=Dv,
|
||||
ϵ=ϵ,
|
||||
a=a,
|
||||
b=b
|
||||
)
|
||||
"""
|
||||
params_obs = Observable(Constants.GSParams(N, dx, Du[], Dv[], F[], k[]))
|
||||
#params_obs = Observable(FHNParams(N=N, dx=dx, Du=Du[], Dv=Dv[], ϵ=ϵ[], a=a[], b=b[]))
|
||||
|
||||
|
||||
lift(Du, Dv, F, k) do u, v, f, ki
|
||||
params_obs[] = GSParams(N, dx, u, v, f, ki)
|
||||
params_obs = Observable{Constants.CombinedPDEParams}(CombinedPDEParams(N, dx, params.Du[], params.Dv[], params.F[], params.k[], params.ϵ[], params.a[], params.b[]))
|
||||
lift(params.N, params.dx, params.Du, params.Dv, params.F, params.k, params.ϵ, params.a, params.b) do N, dx, Du, Dv, F, k, ϵ, a, b
|
||||
params_obs[] = CombinedPDEParams(N, dx, Du, Dv, F, k, ϵ, a, b)
|
||||
end
|
||||
|
||||
"""
|
||||
lift(Du, Dv, ϵ, a, b) do d_u, d_v, eps, aa, bb
|
||||
params_obs[] = FHNParams(N=N, dx=dx, Du=d_u, Dv=d_v, ϵ=eps, a=aa, b=bb)
|
||||
end
|
||||
"""
|
||||
|
||||
U = ones(N, N)
|
||||
V = zeros(N, N)
|
||||
heat_obs = Observable(U)
|
||||
|
||||
fig = build_ui(U, V, param_observables, params_obs, heat_obs)
|
||||
fig = build_ui(U, V, params, params_obs, heat_obs)
|
||||
display(fig)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
module FHNSolver
|
||||
|
2212719
commented
Review
Für die beiden Module FHN und GrayScott, fänd ichs eig nicer, wenn wir multi dispatching implementieren könnten. Also dass wir einfach die step! Methode. Und je nachdem was für ein params_obs man reingibt, verhält sie sich anders. Also wenn es ein GSParams ist oder ein FHNParams. Für die beiden Module FHN und GrayScott, fänd ichs eig nicer, wenn wir multi dispatching implementieren könnten. Also dass wir einfach die step! Methode. Und je nachdem was für ein params_obs man reingibt, verhält sie sich anders. Also wenn es ein GSParams ist oder ein FHNParams.
step!(p::GSParams...)
step!(p::FHNParams...)
Wenn das aber zu schwierig ist, weil es diesen switch gibt, dann lassen wir es so. Wäre halt der more juliane way I guess
2211567
commented
Review
Ich setz mich mal dran Ich setz mich mal dran
|
||||
|
||||
include("utils/laplacian.jl")
|
||||
|
||||
using DifferentialEquations
|
||||
|
|
@ -45,7 +47,8 @@ function fhn!(du, u, p::FHNParams, t)
|
|||
du .= vcat(vec(fu_full), vec(fv_full))
|
||||
end
|
||||
|
||||
function step!(U, V, params_obs::Observable; dx=1)
|
||||
function step_fhn!(U, V, params_obs::Observable; dx=1)
|
||||
"""
|
||||
p = params_obs[]
|
||||
|
||||
# Flatten initial condition (activation u, recovery v)
|
||||
|
|
@ -65,11 +68,24 @@ function step!(U, V, params_obs::Observable; dx=1)
|
|||
U .= u_new
|
||||
V .= v_new
|
||||
|
||||
return U
|
||||
"""
|
||||
|
||||
params = params_obs[]
|
||||
|
||||
Δu = laplacian(U, params.dx)
|
||||
Δv = laplacian(V, params.dx)
|
||||
|
||||
u = U[2:end-1, 2:end-1]
|
||||
v = V[2:end-1, 2:end-1]
|
||||
|
||||
fu = params.Du .* Δu .+ u .- (u .^ 3) ./ 3 .- v
|
||||
fv = params.Dv .* Δv .+ params.ϵ .* (u .+ params.a .- params.b .* v)
|
||||
|
||||
U[2:end-1, 2:end-1] .+= 0.1 .* fu
|
||||
V[2:end-1, 2:end-1] .+= 0.1 .* fv
|
||||
|
||||
return U
|
||||
end
|
||||
|
||||
function multi_step!(state, n_steps, heat_obs::Observable, params_obs::Observable; dx=1)
|
||||
for _ in 1:n_steps
|
||||
heat_obs[] = step!(state[1], state[2], params_obs; dx=1)
|
||||
end
|
||||
end
|
||||
end # Module end
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
module GrayScottSolver
|
||||
|
||||
include("utils/constants.jl")
|
||||
include("utils/laplacian.jl")
|
||||
|
||||
|
|
@ -6,7 +8,7 @@ using Observables
|
|||
using .Constants
|
||||
using .Laplacian
|
||||
|
||||
function step!(U, V, params_obs::Observable; dx=1)
|
||||
function step_gray_scott!(U, V, params_obs::Observable; dx=1)
|
||||
# Extract parameters
|
||||
p = params_obs[]
|
||||
Du, Dv = p.Du, p.Dv
|
||||
|
|
@ -42,8 +44,5 @@ function step!(U, V, params_obs::Observable; dx=1)
|
|||
|
||||
return U # for visualization
|
||||
end
|
||||
function multi_step!(state, n_steps, heat_obs::Observable, params_obs::Observable; dx=1)
|
||||
for _ in 1:n_steps
|
||||
heat_obs[] = step!(state[1], state[2], params_obs; dx=1)
|
||||
end
|
||||
end
|
||||
|
||||
end # Module end
|
||||
|
|
@ -10,11 +10,6 @@ struct FHNParams <: PDEParams
|
|||
ϵ::Float64
|
||||
a::Float64
|
||||
b::Float64
|
||||
|
||||
# Inner constructor that takes keyword arguments
|
||||
# The semicolon ';' separates positional arguments from keyword arguments
|
||||
FHNParams(; N::Int, dx::Float64, Du::Float64, Dv::Float64, ϵ::Float64, a::Float64, b::Float64) =
|
||||
new(N, dx, Du, Dv, ϵ, a, b)
|
||||
end
|
||||
|
||||
struct GSParams <: PDEParams
|
||||
|
|
@ -27,6 +22,18 @@ struct GSParams <: PDEParams
|
|||
|
||||
end
|
||||
|
||||
export PDEParams, FHNParams, GSParams
|
||||
struct CombinedPDEParams <: PDEParams
|
||||
N::Int
|
||||
dx::Float64
|
||||
Du::Float64
|
||||
Dv::Float64
|
||||
F::Float64
|
||||
k::Float64
|
||||
ϵ::Float64
|
||||
a::Float64
|
||||
b::Float64
|
||||
end
|
||||
|
||||
export PDEParams, FHNParams, GSParams, CombinedPDEParams
|
||||
|
||||
end # module Constants
|
||||
|
|
|
|||
|
|
@ -1,8 +1,18 @@
|
|||
module Visualization
|
||||
include("gray_scott_solver.jl")
|
||||
#include("fhn_solver.jl")
|
||||
|
||||
using GLMakie, Observables, Makie
|
||||
include("../src/utils/constants.jl")
|
||||
include("gray_scott_solver.jl")
|
||||
include("fhn_solver.jl")
|
||||
|
||||
using Observables, Makie, GLMakie
|
||||
using .Constants
|
||||
using .GrayScottSolver: step_gray_scott!
|
||||
using .FHNSolver: step_fhn!
|
||||
|
||||
const STEP_FUNCTIONS = Dict(
|
||||
:gray_scott => GrayScottSolver.step_gray_scott!,
|
||||
:fhn => FHNSolver.step_fhn!
|
||||
)
|
||||
|
||||
function coord_to_index(x, y, N)
|
||||
ix = clamp(round(Int, x), 1, N)
|
||||
|
|
@ -34,9 +44,11 @@ function reset!(U, V, heat_obs)
|
|||
heat_obs[] = copy(U)
|
||||
end
|
||||
|
||||
function param_box!(grid, row, labeltxt, observable::Observable)
|
||||
Label(grid[row, 1], labeltxt)
|
||||
box = Textbox(grid[row, 2], validator=Float64, width=50, placeholder=labeltxt, stored_string="$(observable[])")
|
||||
function param_box!(grid, row, labeltxt, observable::Observable; col=1)
|
||||
label_cell = 2 * col - 1
|
||||
textbox_cell = 2 * col
|
||||
Label(grid[row, label_cell], labeltxt)
|
||||
box = Textbox(grid[row, textbox_cell], validator=Float64, width=50, placeholder=labeltxt, stored_string="$(observable[])")
|
||||
on(box.stored_string) do s
|
||||
try
|
||||
observable[] = parse(Float64, s)
|
||||
|
|
@ -45,13 +57,27 @@ function param_box!(grid, row, labeltxt, observable::Observable)
|
|||
@warn "Invalid input for $labeltxt: $s"
|
||||
end
|
||||
end
|
||||
on(observable) do val
|
||||
box.displayed_string[] = string(val)
|
||||
end
|
||||
end
|
||||
|
||||
function multi_step!(state, n_steps, heat_obs::Observable, params_obs::Observable; step_method=step_gray_scott!, dx=1)
|
||||
for _ in 1:n_steps
|
||||
heat_obs[] = step_method(state[1], state[2], params_obs; dx=1)
|
||||
end
|
||||
end
|
||||
|
||||
function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs)
|
||||
|
||||
reset!(U, V, heat_obs)
|
||||
fig = Figure(size=(800, 800))
|
||||
|
||||
gh = GridLayout(fig[1, 1])
|
||||
ax = Axis(gh[1, 1])
|
||||
dropdown = Menu(fig, options=collect(zip(["Gray-Scott", "FHN"], [:gray_scott, :fhn])))
|
||||
gh[1, 1] = dropdown
|
||||
ax = Axis(gh[2, 1])
|
||||
|
||||
hm = Makie.heatmap!(ax, heat_obs, colormap=:viridis)
|
||||
deactivate_interaction!(ax, :rectanglezoom)
|
||||
ax.aspect = DataAspect()
|
||||
|
|
@ -59,33 +85,39 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs)
|
|||
run_label = Observable{String}("Run")
|
||||
stepsize = Observable(30)
|
||||
spoint = select_point(ax.scene)
|
||||
step_method = Observable{Function}(step_gray_scott!)
|
||||
|
||||
# Controls
|
||||
fig[2, 1] = buttongrid = GridLayout(ax.scene, tellwidth=false)
|
||||
btn_step = Button(buttongrid[1, 1], width=50, label="Step")
|
||||
btn_start = Button(buttongrid[1, 2], width=50, label=run_label)
|
||||
|
2211567 marked this conversation as resolved
2212719
commented
Review
in Zeile 92 tellwidth=false dazu slidergrid = SliderGrid(fig[3, 1], (label="Speed", range=1:1:100, format="{}x", width=350, startvalue=stepsize[]), tellwidth=false)
in Zeile 92 tellwidth=false dazu
|
||||
btn_reset = Button(buttongrid[1, 3], width=50, label="Reset")
|
||||
slidergrid = SliderGrid(fig[3, 1], (label="Speed", range=1:1:100, format="{}x", width=350, startvalue=stepsize[]))
|
||||
slidergrid = SliderGrid(fig[3, 1], (label="Speed", range=1:1:100, format="{}x", width=350, startvalue=stepsize[]), tellwidth=false)
|
||||
|
||||
speed_slider = slidergrid.sliders[1].value
|
||||
|
||||
# place all the parameter boxes
|
||||
gh[2, 2] = textboxgrid = GridLayout(ax.scene, tellwidth=false)
|
||||
|
||||
gh[1, 2] = textboxgrid = GridLayout(ax.scene, tellwidth=false)
|
||||
rowsize!(gh, 1, Relative(1.0))
|
||||
param_box!(textboxgrid, 1, "Du", param_obs_map.Du, col=1)
|
||||
param_box!(textboxgrid, 2, "Dv", param_obs_map.Dv, col=1)
|
||||
param_box!(textboxgrid, 3, "Feed", param_obs_map.F, col=1)
|
||||
param_box!(textboxgrid, 4, "Kill", param_obs_map.k, col=1)
|
||||
|
||||
# FHN column (col 2)
|
||||
param_box!(textboxgrid, 1, "Du", param_obs_map.Du, col=2)
|
||||
param_box!(textboxgrid, 2, "Dv", param_obs_map.Dv, col=2)
|
||||
param_box!(textboxgrid, 3, "ϵ", param_obs_map.ϵ, col=2)
|
||||
param_box!(textboxgrid, 4, "a", param_obs_map.a, col=2)
|
||||
param_box!(textboxgrid, 5, "b", param_obs_map.b, col=2)
|
||||
|
||||
param_box!(textboxgrid, 1, "Du", param_obs_map.Du)
|
||||
param_box!(textboxgrid, 2, "Dv", param_obs_map.Dv)
|
||||
|
||||
if haskey(param_obs_map, :F)
|
||||
param_box!(textboxgrid, 3, "Feed", param_obs_map.F)
|
||||
param_box!(textboxgrid, 4, "kill", param_obs_map.k)
|
||||
elseif haskey(param_obs_map, :ϵ)
|
||||
param_box!(textboxgrid, 3, "ϵ", param_obs_map.ϵ)
|
||||
param_box!(textboxgrid, 4, "a", param_obs_map.a)
|
||||
param_box!(textboxgrid, 5, "b", param_obs_map.b)
|
||||
rowsize!(gh, 1, Fixed(50)) # small row for the menu
|
||||
rowsize!(gh, 2, Relative(1.0))
|
||||
for c in 1:4
|
||||
colsize!(textboxgrid, c, Relative(1.0 / 4.0))
|
||||
end
|
||||
|
||||
# Events ##############################################################
|
||||
# Timer and state for animation
|
||||
running = Observable(false)
|
||||
|
||||
|
|
@ -102,7 +134,7 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs)
|
|||
end
|
||||
# Button Listeners
|
||||
on(btn_step.clicks) do _
|
||||
multi_step!((U, V), stepsize[], heat_obs, params_obs)
|
||||
multi_step!((U, V), stepsize[], heat_obs, params_obs; step_method=step_method[])
|
||||
end
|
||||
|
||||
on(btn_start.clicks) do _
|
||||
|
|
@ -111,7 +143,7 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs)
|
|||
|
||||
on(btn_start.clicks) do _
|
||||
@async while running[]
|
||||
multi_step!((U, V), stepsize[], heat_obs, params_obs)
|
||||
multi_step!((U, V), stepsize[] * 5, heat_obs, params_obs; step_method=step_method[])
|
||||
sleep(0.0015) # ~20 FPS
|
||||
end
|
||||
end
|
||||
|
|
@ -127,7 +159,6 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs)
|
|||
return
|
||||
end
|
||||
x, y = pt
|
||||
println("params_obs[].N, ", params_obs[].N)
|
||||
i, j = coord_to_index(x, y, params_obs[].N)
|
||||
|
||||
# get corners of square that will get filled with concentration
|
||||
|
|
@ -142,6 +173,24 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs)
|
|||
|
||||
heat_obs[] = copy(U)
|
||||
end
|
||||
|
||||
on(dropdown.selection) do sel
|
||||
if sel isa Tuple
|
||||
label, selected_model = sel
|
||||
else
|
||||
selected_model = sel
|
||||
label = string(sel)
|
||||
end
|
||||
|
||||
@info "Selected model: $label → $selected_model"
|
||||
|
||||
if haskey(STEP_FUNCTIONS, selected_model)
|
||||
step_method[] = STEP_FUNCTIONS[selected_model]
|
||||
else
|
||||
@warn "Unknown model selected: $selected_model"
|
||||
end
|
||||
end
|
||||
|
||||
return fig
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
wieso hast du hier Visualization vor das Constants geschrieben? Macht es nicht mehr Sinn Constants selbst zu importieren? Oder bei Namenskonflikten explizit das Constants Modul anzugeben. Mit dem Doppelnamen sieht es nicht so schön aus finde ich
Weil Julia leider unterscheidet zwischen Main.Constants und Visualization.Constant