initial commit with project structure
commit
de99d1360c
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,3 @@
|
|||
[deps]
|
||||
DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa"
|
||||
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
function fhn!(du, u, p::FHNParams, t)
|
||||
N, dx = p.N, p.dx
|
||||
|
||||
u_mat = reshape(u[1:N^2], N, N)
|
||||
v_mat = reshape(u[N^2+1:end], N, N)
|
||||
|
||||
Δu = laplacian(u_mat) / dx^2
|
||||
Δv = laplacian(v_mat) / dx^2
|
||||
|
||||
fu = p.Du * Δu .+ u_mat .- u_mat .^ 3 ./ 3 .- v_mat
|
||||
fv = p.Dv * Δv .+ p.ε * (u_mat .+ p.a .- p.b .* v_mat)
|
||||
|
||||
du .= vcat(vec(fu), vec(fv))
|
||||
end
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
include("../src/AnimalFurFHN.jl") # this loads the module code
|
||||
using .AnimalFurFHN
|
||||
# include optional visualizer only if needed:
|
||||
include("../src/visualization.jl")
|
||||
using .Visualization
|
||||
|
||||
N = 100
|
||||
tspan = (0.0, 100.0)
|
||||
|
||||
sol = run_simulation(N, tspan)
|
||||
|
||||
|
||||
Visualization.step_through_solution(sol, N)
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
using GLMakie
|
||||
include("../src/AnimalFurFHN.jl")
|
||||
using .AnimalFurFHN
|
||||
|
||||
# === Parameters ===
|
||||
N = 100
|
||||
tspan = (0.0, 100.0)
|
||||
frame_index = 1 # final time step
|
||||
|
||||
# === Run simulation ===
|
||||
sol = run_simulation(N, tspan)
|
||||
|
||||
# === Extract activator u ===
|
||||
u = sol.u[frame_index][1:N^2]
|
||||
u_mat = reshape(u, N, N)
|
||||
|
||||
# === Plot ===
|
||||
fig = Figure()
|
||||
ax = Axis(fig[1, 1])
|
||||
heatmap!(ax, u_mat, colormap=:viridis)
|
||||
fig
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
# src/AnimalFurFHN.jl
|
||||
module AnimalFurFHN
|
||||
|
||||
include("constants.jl")
|
||||
include("initial_conditions.jl")
|
||||
include("laplacian.jl")
|
||||
include("model_fhn.jl")
|
||||
include("solver.jl")
|
||||
|
||||
export run_simulation # Make sure this is here!
|
||||
end
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
struct FHNParams
|
||||
N::Int
|
||||
dx::Float64
|
||||
Du::Float64
|
||||
Dv::Float64
|
||||
ε::Float64
|
||||
a::Float64
|
||||
b::Float64
|
||||
end
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
function initial_conditions(N)
|
||||
Random.seed!(1234)
|
||||
u = 0.1 .+ 0.01 .* rand(N, N)
|
||||
v = 0.1 .+ 0.01 .* rand(N, N)
|
||||
return vec(u), vec(v)
|
||||
end
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
function laplacian(u, N, h)
|
||||
U = reshape(u, N, N)
|
||||
padded = circshift(U, (-1, 0)) .+ circshift(U, (1, 0)) .+
|
||||
circshift(U, (0, -1)) .+ circshift(U, (0, 1)) .- 4 .* U
|
||||
return vec(padded) ./ h^2
|
||||
end
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
function fhn!(du, u, p::FHNParams, t)
|
||||
N, dx = p.N, p.dx
|
||||
|
||||
u_mat = reshape(u[1:N^2], N, N)
|
||||
v_mat = reshape(u[N^2+1:end], N, N)
|
||||
|
||||
Δu = laplacian(u_mat) / dx^2
|
||||
Δv = laplacian(v_mat) / dx^2
|
||||
|
||||
fu = p.Du * Δu .+ u_mat .- u_mat .^ 3 ./ 3 .- v_mat
|
||||
fv = p.Dv * Δv .+ p.ε * (u_mat .+ p.a .- p.b .* v_mat)
|
||||
|
||||
du .= vcat(vec(fu), vec(fv))
|
||||
end
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
function run_simulation(N::Int, tspan::Tuple{Float64,Float64})
|
||||
# ✅ Turing pattern parameters — promotes stable spots
|
||||
a = 0.1
|
||||
b = 0.5
|
||||
ϵ = 0.01
|
||||
Du = 1e-5 # activator diffusion
|
||||
Dv = 1e-3 # inhibitor diffusion (>> Du)
|
||||
|
||||
# Laplacian setup (assumes ∆x = 1)
|
||||
dx = 1.0
|
||||
L = laplacian_matrix(N, dx)
|
||||
|
||||
# ✅ Local random noise around a constant for initial conditions
|
||||
u0, v0 = initial_conditions(N) # Should include a seeded RNG
|
||||
y0 = vcat(u0, v0)
|
||||
|
||||
# ODE system for Reaction-Diffusion with FitzHugh-Nagumo dynamics
|
||||
function f!(du, u, p, t)
|
||||
U = u[1:N^2]
|
||||
V = u[N^2+1:end]
|
||||
|
||||
ΔU = Du .* (L * U)
|
||||
ΔV = Dv .* (L * V)
|
||||
|
||||
du[1:N^2] = ΔU .+ (U .- (U .^ 3) ./ 3 .- V) ./ ϵ
|
||||
du[N^2+1:end] = ΔV .+ ϵ .* (U .+ a .- b .* V)
|
||||
end
|
||||
|
||||
# ✅ Use stiff solver for stability
|
||||
prob = ODEProblem(f!, y0, tspan)
|
||||
sol = solve(prob, Rosenbrock23(), saveat=1.0, reltol=1e-6, abstol=1e-6)
|
||||
|
||||
return sol
|
||||
end
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
module Visualization
|
||||
|
||||
using GLMakie
|
||||
|
||||
function step_through_solution(sol, N)
|
||||
fig = Figure(resolution=(600, 600))
|
||||
ax = Axis(fig[1, 1])
|
||||
slider = Slider(fig[2, 1], range=1:length(sol), startvalue=1)
|
||||
|
||||
# Initialize heatmap with first time step
|
||||
u0 = reshape(sol[1][1:N^2], N, N)
|
||||
heat_obs = Observable(u0)
|
||||
hmap = heatmap!(ax, heat_obs, colormap=:magma)
|
||||
|
||||
# Update heatmap on slider movement
|
||||
on(slider.value) do i
|
||||
u = reshape(sol[i][1:N^2], N, N)
|
||||
heat_obs[] = u
|
||||
end
|
||||
|
||||
display(fig)
|
||||
end
|
||||
|
||||
end
|
||||
Loading…
Reference in New Issue