From 509417bc54dd84063a4cacaec34414b1347ff06d Mon Sep 17 00:00:00 2001 From: 2211567 Date: Sat, 14 Jun 2025 16:58:14 +0200 Subject: [PATCH 01/13] replaced solver with faster solution --- src/fhn_solver.jl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/fhn_solver.jl b/src/fhn_solver.jl index 4118c01..8afee64 100644 --- a/src/fhn_solver.jl +++ b/src/fhn_solver.jl @@ -36,6 +36,7 @@ function fhn!(du, u, p::FHNParams, t) end function step!(U, V, params_obs::Observable; dx=1) + """ p = params_obs[] # Flatten initial condition (activation u, recovery v) @@ -55,6 +56,20 @@ function step!(U, V, params_obs::Observable; dx=1) U .= u_new V .= v_new + return U + """ + + params = params_obs[] + + Δu = reshape(Laplacian.laplacian(U, params.N, params.dx), params.N, params.N) + Δv = reshape(Laplacian.laplacian(V, params.N, params.dx), params.N, params.N) + + fu = params.Du * Δu .+ U .- (U .^ 3) ./ 3 .- V + fv = params.Dv * Δv .+ params.ϵ .* (U .+ params.a .- params.b .* V) + + U .+= 0.1 .* fu + V .+= 0.1 .* fv + return U end -- 2.43.0 From a52272f30d78eb7a487d948fa6829a6318add8c8 Mon Sep 17 00:00:00 2001 From: 2211567 Date: Sat, 14 Jun 2025 21:47:25 +0200 Subject: [PATCH 02/13] implemented first switching mechanisms --- scripts/main.jl | 50 +++++++++++++++++++++------------------- src/fhn_solver.jl | 4 ++-- src/gray_scott_solver.jl | 4 ++-- src/visualization.jl | 33 ++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 28 deletions(-) diff --git a/scripts/main.jl b/scripts/main.jl index 8c35b49..dd0a440 100644 --- a/scripts/main.jl +++ b/scripts/main.jl @@ -9,42 +9,44 @@ using GLMakie using .Constants using .Visualization -""" +model_type = Observable(:gray_scott) # or :fhn + # GSParams 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, +gray_params = ( + Du = Observable(0.16), + Dv = Observable(0.08), + F = Observable(0.060), + k = Observable(0.062) ) -""" # 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 +fhn_params = ( + Du = Observable(0.16), + Dv = Observable(0.08), + ϵ = Observable(0.05), + a = Observable(0.7), + b = Observable(0.8) ) -#params_obs = Observable(Constants.GSParams(N, dx, Du[], Dv[], F[], k[])) -params_obs = Observable(Constants.FHNParams(N=N, dx=dx, Du=Du[], Dv=Dv[], ϵ=ϵ[], a=a[], b=b[])) +params_obs = Observable(Constants.GSParams(N, dx, gray_params.Du[], gray_params.Dv[], gray_params.F[], gray_params.k[])) +#params_obs = Observable(Constants.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[] = Constants.GSParams(N, dx, u, v, f, ki) +# Rebuild when model or sliders change +function setup_param_binding!(model_type, gray_params, fhn_params, params_obs) + if model_type[] == :gray_scott + lift(gray_params.Du, gray_params.Dv, gray_params.F, gray_params.k) do Du, Dv, F, k + params_obs[] = GSParams(N, dx, Du, Dv, F, k) + end + else + lift(fhn_params.Du, fhn_params.Dv, fhn_params.ϵ, fhn_params.a, fhn_params.b) do Du, Dv, ϵ, a, b + params_obs[] = FHNParams(N, dx, Du, Dv, ϵ, a, b) + end + end end -""" lift(Du, Dv, ϵ, a, b) do d_u, d_v, eps, aa, bb params_obs[] = Constants.FHNParams(N=N, dx=dx, Du=d_u, Dv=d_v, ϵ=eps, a=aa, b=bb) diff --git a/src/fhn_solver.jl b/src/fhn_solver.jl index 8afee64..2dbc3cd 100644 --- a/src/fhn_solver.jl +++ b/src/fhn_solver.jl @@ -35,7 +35,7 @@ function fhn!(du, u, p::FHNParams, t) du .= vcat(vec(fu), vec(fv)) end -function step!(U, V, params_obs::Observable; dx=1) +function step_fhn!(U, V, params_obs::Observable; dx=1) """ p = params_obs[] @@ -75,6 +75,6 @@ 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) + heat_obs[] = step_fhn!(state[1], state[2], params_obs; dx=1) end end diff --git a/src/gray_scott_solver.jl b/src/gray_scott_solver.jl index eeb0ed8..8fcb29d 100644 --- a/src/gray_scott_solver.jl +++ b/src/gray_scott_solver.jl @@ -6,7 +6,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) lap_u = laplacian5(U, dx) lap_v = laplacian5(V, dx) diff_u = params_obs[].Du @@ -40,6 +40,6 @@ function step!(U, V, params_obs::Observable; dx=1) 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) + heat_obs[] = step_gray_scott!(state[1], state[2], params_obs; dx=1) end end diff --git a/src/visualization.jl b/src/visualization.jl index 792a87f..930f288 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -47,7 +47,33 @@ function param_box!(grid, row, labeltxt, observable::Observable) end end +function rebuild_param_boxes!(grid, model_type, gray_params, fhn_params) + empty!(grid) + + if model_type[] == :gray_scott + param_box!(grid, 1, "Du", gray_params.Du) + param_box!(grid, 2, "Dv", gray_params.Dv) + param_box!(grid, 3, "Feed", gray_params.F) + param_box!(grid, 4, "Kill", gray_params.k) + else + param_box!(grid, 1, "Du", fhn_params.Du) + param_box!(grid, 2, "Dv", fhn_params.Dv) + param_box!(grid, 3, "ϵ", fhn_params.ϵ) + param_box!(grid, 4, "a", fhn_params.a) + param_box!(grid, 5, "b", fhn_params.b) + end +end + +function step_model!(U, V, model_type, params_obs, heat_obs) + if model_type[] == :gray_scott + heat_obs[] = step_gray_scott!(U, V, params_obs) + else + heat_obs[] = step_fhn!(U, V, params_obs) + 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]) @@ -61,6 +87,7 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) spoint = select_point(ax.scene) # Controls + dropdown = Dropdown(fig[0, 1], options=["Gray-Scott" => :gray_scott, "FHN" => :fhn]) 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) @@ -142,6 +169,12 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) heat_obs[] = copy(U) end + + on(dropdown.selection) do sel + model_type[] = sel + setup_param_binding!(model_type, gray_params, fhn_params, params_obs) + rebuild_param_boxes!(param_grid, model_type, gray_params, fhn_params) + end return fig end -- 2.43.0 From 3aaef9fabe3bdeb8d236083385bff61ca47adc91 Mon Sep 17 00:00:00 2001 From: 2211567 Date: Sun, 15 Jun 2025 17:46:35 +0200 Subject: [PATCH 03/13] chicken jockey. Kill me --- Manifest.toml | 14 +++++----- scripts/main.jl | 24 +++++++++--------- src/fhn_solver.jl | 8 +++--- src/gray_scott_solver.jl | 9 +++---- src/utils/constants.jl | 5 ---- src/visualization.jl | 55 ++++++++++++++++++++++++++++++---------- 6 files changed, 68 insertions(+), 47 deletions(-) diff --git a/Manifest.toml b/Manifest.toml index 6c62bc0..718c6fb 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -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"] diff --git a/scripts/main.jl b/scripts/main.jl index b9f5213..7bf1f84 100644 --- a/scripts/main.jl +++ b/scripts/main.jl @@ -9,6 +9,16 @@ using GLMakie using .Constants using .Visualization + +# Rebuild when model or sliders change +function setup_param_binding!(model_type, gray_params, fhn_params, params_obs) + if model_type[] == :gray_scott + return gray_params + else + return fhn_params + end +end + model_type = Observable(:gray_scott) # or :fhn # GSParams @@ -35,19 +45,9 @@ fhn_params = ( params_obs = Observable(Constants.GSParams(N, dx, gray_params.Du[], gray_params.Dv[], gray_params.F[], gray_params.k[])) #params_obs = Observable(Constants.FHNParams(N=N, dx=dx, Du=Du[], Dv=Dv[], ϵ=ϵ[], a=a[], b=b[])) -# Rebuild when model or sliders change -function setup_param_binding!(model_type, gray_params, fhn_params, params_obs) - if model_type[] == :gray_scott - lift(gray_params.Du, gray_params.Dv, gray_params.F, gray_params.k) do Du, Dv, F, k - params_obs[] = GSParams(N, dx, Du, Dv, F, k) - end - else - lift(fhn_params.Du, fhn_params.Dv, fhn_params.ϵ, fhn_params.a, fhn_params.b) do Du, Dv, ϵ, a, b - params_obs[] = FHNParams(N, dx, Du, Dv, ϵ, a, b) - end - end -end +param_observables = setup_param_binding!(model_type, gray_params, fhn_params, params_obs) +""" 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 diff --git a/src/fhn_solver.jl b/src/fhn_solver.jl index cd412e7..835872f 100644 --- a/src/fhn_solver.jl +++ b/src/fhn_solver.jl @@ -1,3 +1,5 @@ +module FHNSolver + include("utils/laplacian.jl") using DifferentialEquations @@ -83,8 +85,4 @@ function step_fhn!(U, V, params_obs::Observable; dx=1) 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_fhn!(state[1], state[2], params_obs; dx=1) - end -end +end # Module end \ No newline at end of file diff --git a/src/gray_scott_solver.jl b/src/gray_scott_solver.jl index ffc7161..418015a 100644 --- a/src/gray_scott_solver.jl +++ b/src/gray_scott_solver.jl @@ -1,3 +1,5 @@ +module GrayScottSolver + include("utils/constants.jl") include("utils/laplacian.jl") @@ -42,8 +44,5 @@ function step_gray_scott!(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_gray_scott!(state[1], state[2], params_obs; dx=1) - end -end + +end # Module end \ No newline at end of file diff --git a/src/utils/constants.jl b/src/utils/constants.jl index a07f4f0..1908d86 100644 --- a/src/utils/constants.jl +++ b/src/utils/constants.jl @@ -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 diff --git a/src/visualization.jl b/src/visualization.jl index 751764a..a7c8f6e 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -1,8 +1,17 @@ module Visualization +include("../src/utils/constants.jl") include("gray_scott_solver.jl") -#include("fhn_solver.jl") +include("fhn_solver.jl") -using GLMakie, Observables, Makie +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) @@ -64,11 +73,21 @@ function rebuild_param_boxes!(grid, model_type, gray_params, fhn_params) end end -function step_model!(U, V, model_type, params_obs, heat_obs) +function setup_param_binding!(model_type, gray_params, fhn_params, params_obs) if model_type[] == :gray_scott - heat_obs[] = step_gray_scott!(U, V, params_obs) + lift(gray_params.Du, gray_params.Dv, gray_params.F, gray_params.k) do Du, Dv, F, k + params_obs[] = Constants.GSParams(N, dx, Du, Dv, F, k) + end else - heat_obs[] = step_fhn!(U, V, params_obs) + lift(fhn_params.Du, fhn_params.Dv, fhn_params.ϵ, fhn_params.a, fhn_params.b) do Du, Dv, ϵ, a, b + params_obs[] = Constants.FHNParams(N, dx, Du, Dv, ϵ, a, b) + end + 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 @@ -85,9 +104,10 @@ 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(step_gray_scott!) # Controls - dropdown = Dropdown(fig[0, 1], options=["Gray-Scott" => :gray_scott, "FHN" => :fhn]) + dropdown = Menu(fig, options = ["Gray-Scott" => :gray_scott, "FHN" => :fhn]) 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) @@ -96,7 +116,6 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) speed_slider = slidergrid.sliders[1].value - gh[1, 2] = textboxgrid = GridLayout(ax.scene, tellwidth=false) rowsize!(gh, 1, Relative(1.0)) @@ -129,7 +148,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 _ @@ -138,7 +157,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[], heat_obs, params_obs; step_method=step_method[]) sleep(0.0015) # ~20 FPS end end @@ -170,11 +189,21 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) heat_obs[] = copy(U) end - on(dropdown.selection) do sel - model_type[] = sel - setup_param_binding!(model_type, gray_params, fhn_params, params_obs) - rebuild_param_boxes!(param_grid, model_type, gray_params, fhn_params) + on(dropdown.selection) do sel_pair + selected_model = sel_pair[2] # get :gray_scott or :fhn from ("Gray-Scott" => :gray_scott) + + # Safely assign correct function to step_method + if haskey(STEP_FUNCTIONS, selected_model) + step_method[] = STEP_FUNCTIONS[selected_model] + else + @warn "Unknown model selected: $selected_model" + end + + # Update param bindings and input fields + setup_param_binding!(selected_model, gray_params, fhn_params, params_obs) + rebuild_param_boxes!(textboxgrid, selected_model, gray_params, fhn_params) end + return fig end -- 2.43.0 From 08bb01fc8555b039420d6001ad58abe6ff0a2686 Mon Sep 17 00:00:00 2001 From: 2211567 Date: Sun, 15 Jun 2025 19:10:40 +0200 Subject: [PATCH 04/13] so close. I swear --- scripts/main.jl | 53 +++++++++++------------------------------- src/utils/constants.jl | 14 ++++++++++- src/visualization.jl | 49 ++++++++++++++++++++------------------ 3 files changed, 53 insertions(+), 63 deletions(-) diff --git a/scripts/main.jl b/scripts/main.jl index 7bf1f84..394dc86 100644 --- a/scripts/main.jl +++ b/scripts/main.jl @@ -9,53 +9,26 @@ using GLMakie using .Constants using .Visualization - -# Rebuild when model or sliders change -function setup_param_binding!(model_type, gray_params, fhn_params, params_obs) - if model_type[] == :gray_scott - return gray_params - else - return fhn_params - end -end - -model_type = Observable(:gray_scott) # or :fhn - -# GSParams +# GSParams AND FHNParams N = 128 dx = 1.0 -gray_params = ( - Du = Observable(0.16), - Dv = Observable(0.08), - F = Observable(0.060), - k = Observable(0.062) +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 -fhn_params = ( - Du = Observable(0.16), - Dv = Observable(0.08), - ϵ = Observable(0.05), - a = Observable(0.7), - b = Observable(0.8) -) - -params_obs = Observable(Constants.GSParams(N, dx, gray_params.Du[], gray_params.Dv[], gray_params.F[], gray_params.k[])) -#params_obs = Observable(Constants.FHNParams(N=N, dx=dx, Du=Du[], Dv=Dv[], ϵ=ϵ[], a=a[], b=b[])) - -param_observables = setup_param_binding!(model_type, gray_params, fhn_params, params_obs) - -""" -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 -""" +params_obs = Observable{Constants.CombinedPDEParams}(CombinedPDEParams(N, dx, params.Du[], params.Dv[], params.F[], params.k[], params.ϵ[], params.a[], params.b[])) 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) diff --git a/src/utils/constants.jl b/src/utils/constants.jl index 1908d86..d3e37a0 100644 --- a/src/utils/constants.jl +++ b/src/utils/constants.jl @@ -22,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 diff --git a/src/visualization.jl b/src/visualization.jl index a7c8f6e..ecfe9e0 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -56,32 +56,35 @@ function param_box!(grid, row, labeltxt, observable::Observable) end end -function rebuild_param_boxes!(grid, model_type, gray_params, fhn_params) +function rebuild_param_boxes!(grid, model_type::Symbol, param_obs_map::NamedTuple) empty!(grid) - if model_type[] == :gray_scott - param_box!(grid, 1, "Du", gray_params.Du) - param_box!(grid, 2, "Dv", gray_params.Dv) - param_box!(grid, 3, "Feed", gray_params.F) - param_box!(grid, 4, "Kill", gray_params.k) + param_box!(grid, 1, "Du", param_obs_map.Du) + param_box!(grid, 2, "Dv", param_obs_map.Dv) + + if model_type == :gray_scott + param_box!(grid, 3, "Feed", param_obs_map.F) + param_box!(grid, 4, "Kill", param_obs_map.k) + elseif model_type == :fhn + param_box!(grid, 3, "ϵ", param_obs_map.ϵ) + param_box!(grid, 4, "a", param_obs_map.a) + param_box!(grid, 5, "b", param_obs_map.b) else - param_box!(grid, 1, "Du", fhn_params.Du) - param_box!(grid, 2, "Dv", fhn_params.Dv) - param_box!(grid, 3, "ϵ", fhn_params.ϵ) - param_box!(grid, 4, "a", fhn_params.a) - param_box!(grid, 5, "b", fhn_params.b) + @warn "Unknown model type in rebuild_param_boxes!: $model_type" end end -function setup_param_binding!(model_type, gray_params, fhn_params, params_obs) - if model_type[] == :gray_scott - lift(gray_params.Du, gray_params.Dv, gray_params.F, gray_params.k) do Du, Dv, F, k - params_obs[] = Constants.GSParams(N, dx, Du, Dv, F, k) +function setup_param_binding!(model_type::Symbol, param_obs_map::NamedTuple, params_obs::Observable) + if model_type == :gray_scott + lift(param_obs_map.N, param_obs_map.dx, param_obs_map.Du, param_obs_map.Dv, param_obs_map.F, param_obs_map.k) do N, dx, Du, Dv, F, k + params_obs[] = Constants.CombinedPDEParams(N, dx, Du, Dv, F, k) + end + elseif model_type == :fhn + lift(param_obs_map.N, param_obs_map.dx, param_obs_map.Du, param_obs_map.Dv, param_obs_map.F, param_obs_map.k, param_obs_map.ϵ, param_obs_map.a, param_obs_map.b) do N, dx, Du, Dv, F, k, ϵ, a, b + params_obs[] = Constants.CombinedPDEParams(N, dx, Du, Dv, F, k, ϵ, a, b) end else - lift(fhn_params.Du, fhn_params.Dv, fhn_params.ϵ, fhn_params.a, fhn_params.b) do Du, Dv, ϵ, a, b - params_obs[] = Constants.FHNParams(N, dx, Du, Dv, ϵ, a, b) - end + @warn "Unknown model type in setup_param_binding!: $model_type" end end @@ -104,10 +107,10 @@ 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(step_gray_scott!) + step_method = Observable{Function}(step_gray_scott!) # Controls - dropdown = Menu(fig, options = ["Gray-Scott" => :gray_scott, "FHN" => :fhn]) + dropdown = Menu(fig, options=["Gray-Scott" => :gray_scott, "FHN" => :fhn]) 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) @@ -200,8 +203,10 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) end # Update param bindings and input fields - setup_param_binding!(selected_model, gray_params, fhn_params, params_obs) - rebuild_param_boxes!(textboxgrid, selected_model, gray_params, fhn_params) + lift(param_obs_map.N, param_obs_map.dx, param_obs_map.Du, param_obs_map.Dv, param_obs_map.F, param_obs_map.k, param_obs_map.ϵ, param_obs_map.a, param_obs_map.b) do N, dx, Du, Dv, F, k, ϵ, a, b + params_obs[] = Constants.CombinedPDEParams(N, dx, Du, Dv, F, k, ϵ, a, b) + end + rebuild_param_boxes!(textboxgrid, selected_model, param_obs_map) end return fig -- 2.43.0 From 53f7def2ca826145538678f47d36c3dc879ac86c Mon Sep 17 00:00:00 2001 From: 2211567 Date: Sun, 15 Jun 2025 19:10:49 +0200 Subject: [PATCH 05/13] so close. I swear --- src/visualization.jl | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/visualization.jl b/src/visualization.jl index ecfe9e0..6dd6548 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -74,20 +74,6 @@ function rebuild_param_boxes!(grid, model_type::Symbol, param_obs_map::NamedTupl end end -function setup_param_binding!(model_type::Symbol, param_obs_map::NamedTuple, params_obs::Observable) - if model_type == :gray_scott - lift(param_obs_map.N, param_obs_map.dx, param_obs_map.Du, param_obs_map.Dv, param_obs_map.F, param_obs_map.k) do N, dx, Du, Dv, F, k - params_obs[] = Constants.CombinedPDEParams(N, dx, Du, Dv, F, k) - end - elseif model_type == :fhn - lift(param_obs_map.N, param_obs_map.dx, param_obs_map.Du, param_obs_map.Dv, param_obs_map.F, param_obs_map.k, param_obs_map.ϵ, param_obs_map.a, param_obs_map.b) do N, dx, Du, Dv, F, k, ϵ, a, b - params_obs[] = Constants.CombinedPDEParams(N, dx, Du, Dv, F, k, ϵ, a, b) - end - else - @warn "Unknown model type in setup_param_binding!: $model_type" - 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) -- 2.43.0 From 74a0dbbecbd118937e5b7c44008eb97d12b8c592 Mon Sep 17 00:00:00 2001 From: 2211567 Date: Sun, 15 Jun 2025 21:05:07 +0200 Subject: [PATCH 06/13] IMplemented a working switch --- scripts/main.jl | 5 +---- src/fhn_solver.jl | 15 +++++++++------ src/visualization.jl | 8 +++++++- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/scripts/main.jl b/scripts/main.jl index 394dc86..d4ec92f 100644 --- a/scripts/main.jl +++ b/scripts/main.jl @@ -1,12 +1,9 @@ -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 AND FHNParams diff --git a/src/fhn_solver.jl b/src/fhn_solver.jl index 835872f..31dbc87 100644 --- a/src/fhn_solver.jl +++ b/src/fhn_solver.jl @@ -73,14 +73,17 @@ function step_fhn!(U, V, params_obs::Observable; dx=1) params = params_obs[] - Δu = reshape(Laplacian.laplacian(U, params.N, params.dx), params.N, params.N) - Δv = reshape(Laplacian.laplacian(V, params.N, params.dx), params.N, params.N) + Δu = laplacian(U, params.dx) + Δv = laplacian(V, params.dx) - fu = params.Du * Δu .+ U .- (U .^ 3) ./ 3 .- V - fv = params.Dv * Δv .+ params.ϵ .* (U .+ params.a .- params.b .* V) + u = U[2:end-1, 2:end-1] + v = V[2:end-1, 2:end-1] - U .+= 0.1 .* fu - V .+= 0.1 .* fv + 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 diff --git a/src/visualization.jl b/src/visualization.jl index 6dd6548..5c73a69 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -1,4 +1,5 @@ module Visualization + include("../src/utils/constants.jl") include("gray_scott_solver.jl") include("fhn_solver.jl") @@ -57,7 +58,12 @@ function param_box!(grid, row, labeltxt, observable::Observable) end function rebuild_param_boxes!(grid, model_type::Symbol, param_obs_map::NamedTuple) - empty!(grid) + for pos in keys(grid.content) + if isa(pos, Tuple) && length(pos) == 2 + i, j = pos + grid[i, j] = nothing + end + end param_box!(grid, 1, "Du", param_obs_map.Du) param_box!(grid, 2, "Dv", param_obs_map.Dv) -- 2.43.0 From f0991fdf56389ba1341a120ab3c38e89f16e5cd9 Mon Sep 17 00:00:00 2001 From: 2211567 Date: Sun, 15 Jun 2025 21:38:09 +0200 Subject: [PATCH 07/13] End my suffering --- src/visualization.jl | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/visualization.jl b/src/visualization.jl index 5c73a69..a37b47d 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -113,19 +113,7 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) gh[1, 2] = textboxgrid = GridLayout(ax.scene, tellwidth=false) rowsize!(gh, 1, Relative(1.0)) - - - 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) - end + rebuild_param_boxes!(textboxgrid, :gray_scott, param_obs_map) # Timer and state for animation running = Observable(false) -- 2.43.0 From 8ba18986561d336bb4ac3f20396683a3b96aded2 Mon Sep 17 00:00:00 2001 From: 2211567 Date: Mon, 16 Jun 2025 15:35:36 +0200 Subject: [PATCH 08/13] Fixed Bugs and styling --- src/visualization.jl | 64 +++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/src/visualization.jl b/src/visualization.jl index a37b47d..0eaf12e 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -44,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) @@ -58,13 +60,6 @@ function param_box!(grid, row, labeltxt, observable::Observable) end function rebuild_param_boxes!(grid, model_type::Symbol, param_obs_map::NamedTuple) - for pos in keys(grid.content) - if isa(pos, Tuple) && length(pos) == 2 - i, j = pos - grid[i, j] = nothing - end - end - param_box!(grid, 1, "Du", param_obs_map.Du) param_box!(grid, 2, "Dv", param_obs_map.Dv) @@ -90,8 +85,12 @@ 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() @@ -102,7 +101,6 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) step_method = Observable{Function}(step_gray_scott!) # Controls - dropdown = Menu(fig, options=["Gray-Scott" => :gray_scott, "FHN" => :fhn]) 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) @@ -111,10 +109,28 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) speed_slider = slidergrid.sliders[1].value - gh[1, 2] = textboxgrid = GridLayout(ax.scene, tellwidth=false) - rowsize!(gh, 1, Relative(1.0)) - rebuild_param_boxes!(textboxgrid, :gray_scott, param_obs_map) + # place all the parameter boxes + gh[2, 2] = textboxgrid = GridLayout(ax.scene, tellwidth=false) + 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) + + 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) @@ -172,21 +188,21 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) heat_obs[] = copy(U) end - on(dropdown.selection) do sel_pair - selected_model = sel_pair[2] # get :gray_scott or :fhn from ("Gray-Scott" => :gray_scott) + 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" - # Safely assign correct function to step_method if haskey(STEP_FUNCTIONS, selected_model) step_method[] = STEP_FUNCTIONS[selected_model] else @warn "Unknown model selected: $selected_model" end - - # Update param bindings and input fields - lift(param_obs_map.N, param_obs_map.dx, param_obs_map.Du, param_obs_map.Dv, param_obs_map.F, param_obs_map.k, param_obs_map.ϵ, param_obs_map.a, param_obs_map.b) do N, dx, Du, Dv, F, k, ϵ, a, b - params_obs[] = Constants.CombinedPDEParams(N, dx, Du, Dv, F, k, ϵ, a, b) - end - rebuild_param_boxes!(textboxgrid, selected_model, param_obs_map) end return fig -- 2.43.0 From 391346710828e0db851c2761d8b8454351c8c2c6 Mon Sep 17 00:00:00 2001 From: 2211567 Date: Mon, 16 Jun 2025 15:41:37 +0200 Subject: [PATCH 09/13] removed redundant code --- src/visualization.jl | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/visualization.jl b/src/visualization.jl index 0eaf12e..b4ded0a 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -59,22 +59,6 @@ function param_box!(grid, row, labeltxt, observable::Observable; col=1) end end -function rebuild_param_boxes!(grid, model_type::Symbol, param_obs_map::NamedTuple) - param_box!(grid, 1, "Du", param_obs_map.Du) - param_box!(grid, 2, "Dv", param_obs_map.Dv) - - if model_type == :gray_scott - param_box!(grid, 3, "Feed", param_obs_map.F) - param_box!(grid, 4, "Kill", param_obs_map.k) - elseif model_type == :fhn - param_box!(grid, 3, "ϵ", param_obs_map.ϵ) - param_box!(grid, 4, "a", param_obs_map.a) - param_box!(grid, 5, "b", param_obs_map.b) - else - @warn "Unknown model type in rebuild_param_boxes!: $model_type" - 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) -- 2.43.0 From 29c13021914bd5baefbc99875f76c28efd20e094 Mon Sep 17 00:00:00 2001 From: Nikola <2212719@stud.hs-mannheim.de> Date: Mon, 16 Jun 2025 20:44:14 +0200 Subject: [PATCH 10/13] add lift to actually update param values on ui change --- scripts/main.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/main.jl b/scripts/main.jl index d4ec92f..45738d4 100644 --- a/scripts/main.jl +++ b/scripts/main.jl @@ -22,6 +22,9 @@ params = ( ) 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 U = ones(N, N) V = zeros(N, N) -- 2.43.0 From ba7ef483c48a3991b8b6db3ca187ba8e91358cf2 Mon Sep 17 00:00:00 2001 From: Nikola <2212719@stud.hs-mannheim.de> Date: Mon, 16 Jun 2025 20:44:47 +0200 Subject: [PATCH 11/13] make slider not limit whole screen size and remove print --- src/visualization.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/visualization.jl b/src/visualization.jl index b4ded0a..7efa50e 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -89,7 +89,7 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) btn_step = Button(buttongrid[1, 1], width=50, label="Step") btn_start = Button(buttongrid[1, 2], width=50, label=run_label) 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 @@ -156,7 +156,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 -- 2.43.0 From e994df0d65c1d9db82a808294549b355e8d77643 Mon Sep 17 00:00:00 2001 From: Nikola <2212719@stud.hs-mannheim.de> Date: Mon, 16 Jun 2025 20:49:38 +0200 Subject: [PATCH 12/13] parameter changes made from code during runtime are reflected in text boxes --- src/visualization.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/visualization.jl b/src/visualization.jl index 7efa50e..3f4c132 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -57,6 +57,9 @@ function param_box!(grid, row, labeltxt, observable::Observable; col=1) @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) -- 2.43.0 From 5bb3a912f0d7c706bacb9d82a3d6ffe2217f1f12 Mon Sep 17 00:00:00 2001 From: 2211567 Date: Mon, 16 Jun 2025 21:53:47 +0200 Subject: [PATCH 13/13] Partial integration of feedbackl --- src/visualization.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/visualization.jl b/src/visualization.jl index 3f4c132..257955c 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -143,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; step_method=step_method[]) + multi_step!((U, V), stepsize[] * 5, heat_obs, params_obs; step_method=step_method[]) sleep(0.0015) # ~20 FPS end end -- 2.43.0