SCJ_Projekt/src/solver.jl

154 lines
4.1 KiB
Julia
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using DifferentialEquations
using Random
using .Constants
"""
fhn(du, u, p:FHNParams, t:)
Implements the spatial dynamics of FitzHugh-Nagumo (fhn). Designed to be
within a larger numerical solver of partial differential equations.
# Arguments
- `du`: output argument which stores the calculated derivatives
- `u`: input vector containing the current state of the system at time t
- `p`: holds all the fixed parameters of the FHN model
- `t`: current time
# Returns
- `du`: calculated derivatives put back into the du array
"""
function fhn!(du, u, p::FHNParams, t=0)
u_mat = reshape(u[1:p.N^2], p.N, p.N) # activation variable
v_mat = reshape(u[p.N^2+1:end], p.N, p.N) # deactivation variable
Δu = reshape(laplacian(u_mat, p.N, p.dx), p.N, p.N)
Δv = reshape(laplacian(v_mat, p.N, p.dx), p.N, p.N)
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
"""
run_simulation(tspan::Tuple{Float64,Float64}, N::Int)
solving the ODE and modelling it after FHN
# Arguments
- `tspan`: tuple of two Float64's representing start and end times for simulation
- `N`: size of the N×N grid
# Returns
- `sol`: solved differential equation (ODE)
"""
function run_simulation(tspan::Tuple{Float64,Float64}, N::Int)
# Turing-spot parameters
p = FHNParams(N=N, dx=1.0, Du=1e-5, Dv=1e-3, ϵ=0.01, a=0.1, b=0.5)
# Initial conditions (random noise)
Random.seed!(1234)
# Create two vectors with length N*N with numbers between 0.1 and 0.11
u0 = vec(0.1 .+ 0.01 .* rand(N, N))
v0 = vec(0.1 .+ 0.01 .* rand(N, N))
y0 = vcat(u0, v0)
prob = ODEProblem(fhn!, y0, tspan, p)
sol = solve(prob, BS3(), saveat=1.0) # You can try `Rosenbrock23()` too
return sol
end
# Laplacian with 5-point stencil
function laplacianA(A::Matrix{Float64}, N::Int, dx::Float64)
dx2 = dx^2
lap = zeros(N, N)
lap[2:end-1, 2:end-1] .= (
A[1:end-2, 2:end-1] .+ A[3:end, 2:end-1] # up/down
.+
A[2:end-1, 1:end-2] .+ A[2:end-1, 3:end] # left/right
.-
4 .* A[2:end-1, 2:end-1]
) ./ dx2
return lap
end
# Gray-Scott model: reaction + diffusion
function grayscott!(du, u, p::GSParams, t=0)
N = p.N
U = reshape(u[1:N^2], N, N)
V = reshape(u[N^2+1:end], N, N)
ΔU = laplacianA(U, N, p.dx)
ΔV = laplacianA(V, N, p.dx)
UVV = U .* V .* V
dU = p.Du * ΔU .- UVV .+ p.F .* (1 .- U)
dV = p.Dv * ΔV .+ UVV .- (p.F .+ p.k) .* V
du .= vcat(vec(dU), vec(dV))
end
# Run simulation
function run_simulationG(tspan::Tuple{Float64,Float64}, N::Int, GSP::GSParams)
# Replace this in run_simulation
p = GSP
# Initial conditions: U = 1, V = 0 everywhere
U = ones(N, N)
V = zeros(N, N)
# Seed a square in the center
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
y0 = vcat(vec(U), vec(V))
prob = ODEProblem(grayscott!, y0, tspan, p)
sol = solve(prob, BS3(), saveat=10.0) # or Rosenbrock23()
return sol
end
function run_simulationG_no_ode(tspan::Tuple{Float64,Float64}, N::Int, GSP::GSParams)
p = GSP
dx2 = p.dx^2
dt = 1.0 # fixed timestep
# Initialize U and V
U = ones(N, N)
V = zeros(N, N)
# Seed pattern in the center
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
# Store history for visualization (optional)
snapshots = []
for i in 1:tspan[2]
print("Running $i/$(tspan[2])\r")
lap_U = laplacianA(U, N, p.dx)
lap_V = laplacianA(V, N, p.dx)
UVV = U .* V .* V
dU = p.Du * lap_U .- UVV .+ p.F * (1 .- U)
dV = p.Dv * lap_V .+ UVV .- (p.F + p.k) .* V
U .+= dU * dt
V .+= dV * dt
if i % 100 == 0 # save every 100 steps
push!(snapshots, (copy(U), copy(V)))
end
end
return snapshots
end