Compare commits

...

47 Commits

Author SHA1 Message Date
Ruben Seitz 2dfdd7c08e Merge pull request 'constants no longer module' (#7) from feat/create_templates into main
Reviewed-on: #7
2025-06-17 21:46:50 +02:00
Nikola Sebastian Munder 152af2dfb5 constants no longer module 2025-06-17 21:22:37 +02:00
Nikola Sebastian Munder 3e6bf9b3a9 Merge pull request 'Templates + Styling' (#6) from feat/create_templates into main
Reviewed-on: #6
2025-06-17 21:20:37 +02:00
Nikola Sebastian Munder e5bc553e4c Merge branch 'feat/create_templates' of https://gitty.informatik.hs-mannheim.de/2212719/SCJ_Projekt into feat/create_templates 2025-06-17 19:28:25 +02:00
Nikola Sebastian Munder b129d9cec4 add scalar to single step button 2025-06-17 19:28:06 +02:00
2211567 1918c33770 removed unused function, adjusted color of btn_waves 2025-06-17 18:21:32 +02:00
2211567 a313cd7979 removed unused function, adjusted color of btn_waves 2025-06-17 18:21:08 +02:00
Nikola Sebastian Munder 53383487dc add explicit fhn solving 2025-06-17 17:49:33 +02:00
2211567 020da7c07a Merge branch 'main' into feat/create_templates 2025-06-17 16:06:41 +02:00
2211567 380d9aa228 implemented basic wave pattern instead of animal pattern 2025-06-17 16:04:03 +02:00
Ruben-FreddyLoafers 9ead776049 last pattern wip 2025-06-17 13:58:08 +02:00
Ruben Seitz efed0a47e0 Merge pull request 'Switch zwischen FHN und GrayScott einbauen' (#5) from feat/common_ui into main
Reviewed-on: #5
2025-06-17 09:56:58 +02:00
2211567 e146386895 removed redundant code 2025-06-16 22:16:33 +02:00
2211567 a9d440973c added captions 2025-06-16 22:14:18 +02:00
2211567 5bb3a912f0 Partial integration of feedbackl 2025-06-16 21:53:47 +02:00
2211567 5151adc995 possible to change heatmap colors too 2025-06-16 21:44:51 +02:00
2211567 792fd1b976 Merge branch 'feat/common_ui' into feat/create_templates 2025-06-16 21:16:36 +02:00
2211567 b189f1def7 Styled that shit 2025-06-16 21:13:31 +02:00
Nikola Sebastian Munder e994df0d65 parameter changes made from code during runtime are reflected in text boxes 2025-06-16 20:49:38 +02:00
Nikola Sebastian Munder ba7ef483c4 make slider not limit whole screen size and remove print 2025-06-16 20:44:47 +02:00
Nikola Sebastian Munder 29c1302191 add lift to actually update param values on ui change 2025-06-16 20:44:14 +02:00
2211567 f674ec4ab9 trying to style that shit 2025-06-16 19:44:39 +02:00
2211567 3913467108 removed redundant code 2025-06-16 15:41:37 +02:00
2211567 8ba1898656 Fixed Bugs and styling 2025-06-16 15:35:36 +02:00
2211567 f0991fdf56 End my suffering 2025-06-15 21:38:09 +02:00
2211567 74a0dbbecb IMplemented a working switch 2025-06-15 21:05:07 +02:00
2211567 53f7def2ca so close. I swear 2025-06-15 19:10:49 +02:00
2211567 08bb01fc85 so close. I swear 2025-06-15 19:10:40 +02:00
2211567 3aaef9fabe chicken jockey. Kill me 2025-06-15 17:46:35 +02:00
2211567 0e408df833 Merge branch 'main' into feat/common_ui 2025-06-15 11:44:53 +02:00
Ruben Seitz 8c07a4c969 Merge pull request 'FHN mit neuer UI kompatibel machen' (#4) from feat/fhn_expansion into main
Reviewed-on: #4
Reviewed-by: Nikola Sebastian Munder <2212719@stud.hs-mannheim.de>
2025-06-14 22:11:48 +02:00
2211567 e63fdfde65 Made universal laplacian function; removed redundant code 2025-06-14 22:09:57 +02:00
2211567 a52272f30d implemented first switching mechanisms 2025-06-14 21:47:25 +02:00
2211567 509417bc54 replaced solver with faster solution 2025-06-14 16:58:14 +02:00
2211567 a4f09dc79b Fixed bug in GS implentation 2025-06-14 14:48:48 +02:00
2211567 abc2a4997d adjusted project.toml 2025-06-14 14:42:01 +02:00
2211567 884e87383c compatibility of new UI with FHN implemented 2025-06-14 14:36:31 +02:00
2211567 d5ea440656 build_ui also more modular; adjusted includes and namespaces 2025-06-14 13:23:14 +02:00
2211567 b56033d4ba Merge branch 'main' into feat/fhn_expansion 2025-06-13 14:13:46 +02:00
Ruben Seitz bfcb410dab Merge pull request 'feat/diff_model' (#3) from feat/diff_model into main
Reviewed-on: #3
2025-06-13 14:09:32 +02:00
2211567 c98b5f0fca created utils file; rm two files 2025-06-13 14:08:05 +02:00
2211567 0dd6062c5d coral pattern kinda done 2025-06-11 18:13:12 +02:00
2211567 9223916f32 cheetah design more or less done 2025-06-11 15:31:55 +02:00
2211567 f5d3ebd0c2 cheetah conditions wip 2025-06-10 16:43:10 +02:00
2211567 ece09a29f5 Zebra provisorisch erstellt lol 2025-06-10 13:44:43 +02:00
2211567 2f498367e8 adding a squiggle on the matrix now possible 2025-06-10 12:07:13 +02:00
2211567 7b761e7ff9 FHN model WIP 2025-06-08 17:48:09 +02:00
13 changed files with 565 additions and 613 deletions

View File

@ -1,6 +1,6 @@
# This file is machine-generated - editing it directly is not advised
julia_version = "1.11.4"
julia_version = "1.11.5"
manifest_format = "2.0"
project_hash = "b5f5f0b50b1e0b7dd05bb93e0b1bb03fea235d53"
@ -194,9 +194,9 @@ version = "0.1.6"
[[deps.BoundaryValueDiffEq]]
deps = ["ADTypes", "BoundaryValueDiffEqAscher", "BoundaryValueDiffEqCore", "BoundaryValueDiffEqFIRK", "BoundaryValueDiffEqMIRK", "BoundaryValueDiffEqMIRKN", "BoundaryValueDiffEqShooting", "DiffEqBase", "FastClosures", "ForwardDiff", "LinearAlgebra", "Reexport", "SciMLBase"]
git-tree-sha1 = "6606f3f7d43b038a8c34ee4cdc31bbd93b447407"
git-tree-sha1 = "d6ec33e4516b2e790a64128afdb54f3b536667a7"
uuid = "764a87c0-6b3e-53db-9096-fe964310641d"
version = "5.17.0"
version = "5.18.0"
[deps.BoundaryValueDiffEq.extensions]
BoundaryValueDiffEqODEInterfaceExt = "ODEInterface"
@ -206,39 +206,39 @@ version = "5.17.0"
[[deps.BoundaryValueDiffEqAscher]]
deps = ["ADTypes", "AlmostBlockDiagonals", "BoundaryValueDiffEqCore", "ConcreteStructs", "DiffEqBase", "DifferentiationInterface", "FastClosures", "ForwardDiff", "LinearAlgebra", "PreallocationTools", "RecursiveArrayTools", "Reexport", "SciMLBase", "Setfield"]
git-tree-sha1 = "add7560694794f30eec7803b9c4036efb96bf493"
git-tree-sha1 = "64a777e06d995f677c86c7ddbb85f393074a0877"
uuid = "7227322d-7511-4e07-9247-ad6ff830280e"
version = "1.6.0"
version = "1.7.0"
[[deps.BoundaryValueDiffEqCore]]
deps = ["ADTypes", "Adapt", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "ForwardDiff", "LineSearch", "LinearAlgebra", "Logging", "NonlinearSolveFirstOrder", "PreallocationTools", "RecursiveArrayTools", "Reexport", "SciMLBase", "Setfield", "SparseArrays", "SparseConnectivityTracer", "SparseMatrixColorings"]
git-tree-sha1 = "1e97d81b6ea5e8e938c57a3c640a5cff1e181a2f"
git-tree-sha1 = "c83bf97da90dd379b1e3f4d9c6f3d0ae48eb0b29"
uuid = "56b672f2-a5fe-4263-ab2d-da677488eb3a"
version = "1.9.0"
version = "1.10.0"
[[deps.BoundaryValueDiffEqFIRK]]
deps = ["ADTypes", "ArrayInterface", "BandedMatrices", "BoundaryValueDiffEqCore", "ConcreteStructs", "DiffEqBase", "DifferentiationInterface", "FastAlmostBandedMatrices", "FastClosures", "ForwardDiff", "LinearAlgebra", "PreallocationTools", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "Setfield", "SparseArrays"]
git-tree-sha1 = "525c65da4b46271b4b5fc2178ccde16c99c21a41"
git-tree-sha1 = "e58ee9acfc6dce6dcc368fc0483952bec5625513"
uuid = "85d9eb09-370e-4000-bb32-543851f73618"
version = "1.7.0"
version = "1.8.1"
[[deps.BoundaryValueDiffEqMIRK]]
deps = ["ADTypes", "ArrayInterface", "BandedMatrices", "BoundaryValueDiffEqCore", "ConcreteStructs", "DiffEqBase", "DifferentiationInterface", "FastAlmostBandedMatrices", "FastClosures", "ForwardDiff", "LinearAlgebra", "PreallocationTools", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "Setfield", "SparseArrays"]
git-tree-sha1 = "f729bdedaedb537bf7883c9f71e7577e1c7a07f6"
git-tree-sha1 = "43debeee94167e2dc744f4a385213c4f0d16b4c3"
uuid = "1a22d4ce-7765-49ea-b6f2-13c8438986a6"
version = "1.7.0"
version = "1.8.1"
[[deps.BoundaryValueDiffEqMIRKN]]
deps = ["ADTypes", "ArrayInterface", "BandedMatrices", "BoundaryValueDiffEqCore", "ConcreteStructs", "DiffEqBase", "DifferentiationInterface", "FastAlmostBandedMatrices", "FastClosures", "ForwardDiff", "LinearAlgebra", "PreallocationTools", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "Setfield", "SparseArrays"]
git-tree-sha1 = "dfde7afe34137182a4bb8cd98f01d870772be999"
git-tree-sha1 = "1d92c9f7567b627514e143a3caf93af6d235c2db"
uuid = "9255f1d6-53bf-473e-b6bd-23f1ff009da4"
version = "1.6.0"
version = "1.7.1"
[[deps.BoundaryValueDiffEqShooting]]
deps = ["ADTypes", "ArrayInterface", "BandedMatrices", "BoundaryValueDiffEqCore", "ConcreteStructs", "DiffEqBase", "DifferentiationInterface", "FastAlmostBandedMatrices", "FastClosures", "ForwardDiff", "LinearAlgebra", "PreallocationTools", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "Setfield", "SparseArrays"]
git-tree-sha1 = "255c15c2d262ea8d3c5db1e0f130f829362c0fd4"
git-tree-sha1 = "1460c449c91c9bc4c8fb08fb5e878811ab38d667"
uuid = "ed55bfe0-3725-4db6-871e-a1dc9f42a757"
version = "1.7.0"
version = "1.8.1"
[[deps.BracketingNonlinearSolve]]
deps = ["CommonSolve", "ConcreteStructs", "NonlinearSolveBase", "PrecompileTools", "Reexport", "SciMLBase"]
@ -390,9 +390,9 @@ uuid = "2569d6c7-a4a2-43d3-a901-331e8e4be471"
version = "0.2.3"
[[deps.ConstructionBase]]
git-tree-sha1 = "76219f1ed5771adbb096743bff43fb5fdd4c1157"
git-tree-sha1 = "b4b092499347b18a015186eae3042f72267106cb"
uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
version = "1.5.8"
version = "1.6.0"
weakdeps = ["IntervalSets", "LinearAlgebra", "StaticArrays"]
[deps.ConstructionBase.extensions]
@ -457,9 +457,9 @@ version = "5.53.1"
[[deps.DiffEqBase]]
deps = ["ArrayInterface", "ConcreteStructs", "DataStructures", "DocStringExtensions", "EnumX", "EnzymeCore", "FastBroadcast", "FastClosures", "FastPower", "FunctionWrappers", "FunctionWrappersWrappers", "LinearAlgebra", "Logging", "Markdown", "MuladdMacro", "Parameters", "PrecompileTools", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "SciMLStructures", "Setfield", "Static", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "TruncatedStacktraces"]
git-tree-sha1 = "a0e5b5669df9465bc3dd32ea4a8ddeefbc0f7b5c"
git-tree-sha1 = "2d87d7bd165c1ca0d11923a9fabe90a9d71e88a6"
uuid = "2b5f629d-d688-5b77-993f-72d75c75574e"
version = "6.175.0"
version = "6.176.0"
[deps.DiffEqBase.extensions]
DiffEqBaseCUDAExt = "CUDA"
@ -533,9 +533,9 @@ version = "7.16.1"
[[deps.DifferentiationInterface]]
deps = ["ADTypes", "LinearAlgebra"]
git-tree-sha1 = "c8d85ecfcbaef899308706bebdd8b00107f3fb43"
git-tree-sha1 = "210933c93f39f832d92f9efbbe69a49c453db36d"
uuid = "a0c0ee7d-e4b9-4e03-894e-1c5f64a51d63"
version = "0.6.54"
version = "0.7.1"
[deps.DifferentiationInterface.extensions]
DifferentiationInterfaceChainRulesCoreExt = "ChainRulesCore"
@ -614,9 +614,9 @@ version = "0.25.120"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
[[deps.DocStringExtensions]]
git-tree-sha1 = "e7b7e6f178525d17c720ab9c081e4ef04429f860"
git-tree-sha1 = "7442a5dfe1ebb773c29cc2962a8980f47221d76c"
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
version = "0.9.4"
version = "0.9.5"
[[deps.Downloads]]
deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"]
@ -635,9 +635,9 @@ uuid = "4e289a0a-7415-4d19-859d-a7e5c4648b56"
version = "1.0.5"
[[deps.EnzymeCore]]
git-tree-sha1 = "1eb59f40a772d0fbd4cb75e00b3fa7f5f79c975a"
git-tree-sha1 = "8272a687bca7b5c601c0c24fc0c71bff10aafdfd"
uuid = "f151be2c-9106-41f4-ab19-57ee4f262869"
version = "0.8.9"
version = "0.8.12"
weakdeps = ["Adapt"]
[deps.EnzymeCore.extensions]
@ -694,9 +694,9 @@ version = "6.1.2+0"
[[deps.FFTW]]
deps = ["AbstractFFTs", "FFTW_jll", "LinearAlgebra", "MKL_jll", "Preferences", "Reexport"]
git-tree-sha1 = "7de7c78d681078f027389e067864a8d53bd7c3c9"
git-tree-sha1 = "797762812ed063b9b94f6cc7742bc8883bb5e69e"
uuid = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
version = "1.8.1"
version = "1.9.0"
[[deps.FFTW_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl"]
@ -852,9 +852,9 @@ version = "2.13.4+0"
[[deps.FreeTypeAbstraction]]
deps = ["BaseDirs", "ColorVectorSpace", "Colors", "FreeType", "GeometryBasics", "Mmap"]
git-tree-sha1 = "eaca92bac73aa42f68c57d1b8df1b746eeb2bdaa"
git-tree-sha1 = "4ebb930ef4a43817991ba35db6317a05e59abd11"
uuid = "663a7486-cb36-511b-a19d-713bb74d65c9"
version = "0.10.7"
version = "0.10.8"
[[deps.FriBidi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl"]
@ -898,9 +898,9 @@ version = "3.4.0+2"
[[deps.GLMakie]]
deps = ["ColorTypes", "Colors", "FileIO", "FixedPointNumbers", "FreeTypeAbstraction", "GLFW", "GeometryBasics", "LinearAlgebra", "Makie", "Markdown", "MeshIO", "ModernGL", "Observables", "PrecompileTools", "Printf", "ShaderAbstractions", "StaticArrays"]
git-tree-sha1 = "0650df73822ce8808dc473e3e1c7581bdb367083"
git-tree-sha1 = "aacae8d91f7da30979e189e8046c5bd655421687"
uuid = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
version = "0.11.8"
version = "0.12.0"
[[deps.GPUArraysCore]]
deps = ["Adapt"]
@ -956,10 +956,10 @@ uuid = "3b182d85-2403-5c21-9c21-1e1f0cc25472"
version = "1.3.15+0"
[[deps.Graphs]]
deps = ["ArnoldiMethod", "Compat", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"]
git-tree-sha1 = "3169fd3440a02f35e549728b0890904cfd4ae58a"
deps = ["ArnoldiMethod", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"]
git-tree-sha1 = "c5abfa0ae0aaee162a3fbb053c13ecda39be545b"
uuid = "86223c79-3864-5bf0-83f7-82e725a168b6"
version = "1.12.1"
version = "1.13.0"
[[deps.GridLayoutBase]]
deps = ["GeometryBasics", "InteractiveUtils", "Observables"]
@ -1145,9 +1145,9 @@ version = "3.1.1+0"
[[deps.JumpProcesses]]
deps = ["ArrayInterface", "DataStructures", "DiffEqBase", "DiffEqCallbacks", "DocStringExtensions", "FunctionWrappers", "Graphs", "LinearAlgebra", "Markdown", "PoissonRandom", "Random", "RandomNumbers", "RecursiveArrayTools", "Reexport", "SciMLBase", "Setfield", "StaticArrays", "SymbolicIndexingInterface", "UnPack"]
git-tree-sha1 = "216c196df09c8b80a40a2befcb95760eb979bcfd"
git-tree-sha1 = "fb7fd516de38db80f50fe15e57d44da2836365e7"
uuid = "ccbc3e58-028d-4f4c-8cd5-9ae44345cda5"
version = "9.15.0"
version = "9.16.0"
weakdeps = ["FastBroadcast"]
[[deps.KernelDensity]]
@ -1308,9 +1308,9 @@ weakdeps = ["LineSearches"]
[[deps.LineSearches]]
deps = ["LinearAlgebra", "NLSolversBase", "NaNMath", "Parameters", "Printf"]
git-tree-sha1 = "e4c3be53733db1051cc15ecf573b1042b3a712a1"
git-tree-sha1 = "4adee99b7262ad2a1a4bbbc59d993d24e55ea96f"
uuid = "d3d80556-e9d4-5f37-9878-2ab0fcc64255"
version = "7.3.0"
version = "7.4.0"
[[deps.LinearAlgebra]]
deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"]
@ -1319,9 +1319,9 @@ version = "1.11.0"
[[deps.LinearSolve]]
deps = ["ArrayInterface", "ChainRulesCore", "ConcreteStructs", "DocStringExtensions", "EnumX", "GPUArraysCore", "InteractiveUtils", "Krylov", "LazyArrays", "Libdl", "LinearAlgebra", "MKL_jll", "Markdown", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "Setfield", "StaticArraysCore", "UnPack"]
git-tree-sha1 = "c618a6a774d5712c6bf02dbcceb51b6dc6b9bb89"
git-tree-sha1 = "c0d1a91a50af6778863d320761f807f641f74935"
uuid = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae"
version = "3.16.0"
version = "3.17.0"
[deps.LinearSolve.extensions]
LinearSolveBandedMatricesExt = "BandedMatrices"
@ -1392,15 +1392,15 @@ version = "0.5.16"
[[deps.Makie]]
deps = ["Animations", "Base64", "CRC32c", "ColorBrewer", "ColorSchemes", "ColorTypes", "Colors", "Contour", "Dates", "DelaunayTriangulation", "Distributions", "DocStringExtensions", "Downloads", "FFMPEG_jll", "FileIO", "FilePaths", "FixedPointNumbers", "Format", "FreeType", "FreeTypeAbstraction", "GeometryBasics", "GridLayoutBase", "ImageBase", "ImageIO", "InteractiveUtils", "Interpolations", "IntervalSets", "InverseFunctions", "Isoband", "KernelDensity", "LaTeXStrings", "LinearAlgebra", "MacroTools", "MakieCore", "Markdown", "MathTeXEngine", "Observables", "OffsetArrays", "PNGFiles", "Packing", "PlotUtils", "PolygonOps", "PrecompileTools", "Printf", "REPL", "Random", "RelocatableFolders", "Scratch", "ShaderAbstractions", "Showoff", "SignedDistanceFields", "SparseArrays", "Statistics", "StatsBase", "StatsFuns", "StructArrays", "TriplotBase", "UnicodeFun", "Unitful"]
git-tree-sha1 = "968f03dc65c8144a728f988051a88c78fe625e26"
git-tree-sha1 = "29c5cf33287afa8c06711fec1b33d074f88dd354"
uuid = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
version = "0.22.7"
version = "0.23.0"
[[deps.MakieCore]]
deps = ["ColorTypes", "GeometryBasics", "IntervalSets", "Observables"]
git-tree-sha1 = "733d910c70805e7114c82508bae99c6cdf004466"
git-tree-sha1 = "6ec4aba99ce1a8c247822ce346b273d0d686e141"
uuid = "20f20a25-4f0e-4fdf-b5d1-57303727442b"
version = "0.9.3"
version = "0.10.0"
[[deps.ManualMemory]]
git-tree-sha1 = "bcaef4fc7a0cfe2cba636d84cda54b5e4e4ca3cd"
@ -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"]
@ -1493,9 +1493,9 @@ version = "0.2.4"
[[deps.NLSolversBase]]
deps = ["ADTypes", "DifferentiationInterface", "Distributed", "FiniteDiff", "ForwardDiff"]
git-tree-sha1 = "b14c7be6046e7d48e9063a0053f95ee0fc954176"
git-tree-sha1 = "25a6638571a902ecfb1ae2a18fc1575f86b1d4df"
uuid = "d41bc354-129a-5804-8e4c-c37616107c6c"
version = "7.9.1"
version = "7.10.0"
[[deps.NLsolve]]
deps = ["Distances", "LineSearches", "LinearAlgebra", "NLSolversBase", "Printf", "Reexport"]
@ -1639,7 +1639,7 @@ version = "3.2.4+0"
[[deps.OpenLibm_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "05823500-19ac-5b8b-9628-191a04bc5112"
version = "0.8.1+4"
version = "0.8.5+0"
[[deps.OpenSSL_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl"]
@ -1655,9 +1655,9 @@ version = "0.5.6+0"
[[deps.Optim]]
deps = ["Compat", "EnumX", "FillArrays", "ForwardDiff", "LineSearches", "LinearAlgebra", "NLSolversBase", "NaNMath", "PositiveFactorizations", "Printf", "SparseArrays", "StatsBase"]
git-tree-sha1 = "31b3b1b8e83ef9f1d50d74f1dd5f19a37a304a1f"
git-tree-sha1 = "61942645c38dd2b5b78e2082c9b51ab315315d10"
uuid = "429524aa-4258-5aef-a3af-852621145aeb"
version = "1.12.0"
version = "1.13.2"
[deps.Optim.extensions]
OptimMOIExt = "MathOptInterface"
@ -1690,15 +1690,15 @@ version = "1.2.0"
[[deps.OrdinaryDiffEqBDF]]
deps = ["ADTypes", "ArrayInterface", "DiffEqBase", "FastBroadcast", "LinearAlgebra", "MacroTools", "MuladdMacro", "OrdinaryDiffEqCore", "OrdinaryDiffEqDifferentiation", "OrdinaryDiffEqNonlinearSolve", "OrdinaryDiffEqSDIRK", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "StaticArrays", "TruncatedStacktraces"]
git-tree-sha1 = "42755bd13fe56e9d9ce1bc005f8b206a6b56b731"
git-tree-sha1 = "9124a686af119063bb4d3a8f87044a8f312fcad9"
uuid = "6ad6398a-0878-4a85-9266-38940aa047c8"
version = "1.5.1"
version = "1.6.0"
[[deps.OrdinaryDiffEqCore]]
deps = ["ADTypes", "Accessors", "Adapt", "ArrayInterface", "DataStructures", "DiffEqBase", "DocStringExtensions", "EnumX", "FastBroadcast", "FastClosures", "FastPower", "FillArrays", "FunctionWrappersWrappers", "InteractiveUtils", "LinearAlgebra", "Logging", "MacroTools", "MuladdMacro", "Polyester", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "SciMLStructures", "SimpleUnPack", "Static", "StaticArrayInterface", "StaticArraysCore", "SymbolicIndexingInterface", "TruncatedStacktraces"]
git-tree-sha1 = "d29adfeb720dd7c251b216d91c4bd4fe67c087df"
git-tree-sha1 = "08dac9c6672a4548439048089bac293759a897fd"
uuid = "bbf590c4-e513-4bbe-9b18-05decba2e5d8"
version = "1.26.0"
version = "1.26.1"
weakdeps = ["EnzymeCore"]
[deps.OrdinaryDiffEqCore.extensions]
@ -1712,9 +1712,9 @@ version = "1.4.0"
[[deps.OrdinaryDiffEqDifferentiation]]
deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "ConstructionBase", "DiffEqBase", "DifferentiationInterface", "FastBroadcast", "FiniteDiff", "ForwardDiff", "FunctionWrappersWrappers", "LinearAlgebra", "LinearSolve", "OrdinaryDiffEqCore", "SciMLBase", "SciMLOperators", "SparseArrays", "SparseMatrixColorings", "StaticArrayInterface", "StaticArrays"]
git-tree-sha1 = "c78060115fa4ea9d70ac47fa49496acbc630aefa"
git-tree-sha1 = "efecf0c4cc44e16251b0e718f08b0876b2a82b80"
uuid = "4302a76b-040a-498a-8c04-15b101fed76b"
version = "1.9.1"
version = "1.10.0"
[[deps.OrdinaryDiffEqExplicitRK]]
deps = ["DiffEqBase", "FastBroadcast", "LinearAlgebra", "MuladdMacro", "OrdinaryDiffEqCore", "RecursiveArrayTools", "Reexport", "TruncatedStacktraces"]
@ -1820,9 +1820,9 @@ version = "1.1.0"
[[deps.OrdinaryDiffEqRosenbrock]]
deps = ["ADTypes", "DiffEqBase", "DifferentiationInterface", "FastBroadcast", "FiniteDiff", "ForwardDiff", "LinearAlgebra", "LinearSolve", "MacroTools", "MuladdMacro", "OrdinaryDiffEqCore", "OrdinaryDiffEqDifferentiation", "Polyester", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "Static"]
git-tree-sha1 = "063e5ff1447b3869856ed264b6dcbb21e6e8bdb0"
git-tree-sha1 = "1ce0096d920e95773220e818f29bf4b37ea2bb78"
uuid = "43230ef6-c299-4910-a778-202eb28ce4ce"
version = "1.10.1"
version = "1.11.0"
[[deps.OrdinaryDiffEqSDIRK]]
deps = ["ADTypes", "DiffEqBase", "FastBroadcast", "LinearAlgebra", "MacroTools", "MuladdMacro", "OrdinaryDiffEqCore", "OrdinaryDiffEqDifferentiation", "OrdinaryDiffEqNonlinearSolve", "RecursiveArrayTools", "Reexport", "SciMLBase", "TruncatedStacktraces"]
@ -2169,9 +2169,9 @@ version = "0.1.0"
[[deps.SciMLBase]]
deps = ["ADTypes", "Accessors", "Adapt", "ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "EnumX", "FunctionWrappersWrappers", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "Markdown", "Moshi", "PrecompileTools", "Preferences", "Printf", "RecipesBase", "RecursiveArrayTools", "Reexport", "RuntimeGeneratedFunctions", "SciMLOperators", "SciMLStructures", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface"]
git-tree-sha1 = "ce947672206f6a3a2bee1017c690cfd5fd82d897"
git-tree-sha1 = "04bbcdc8d1f7d6f667f75fbcc68728231e21fabe"
uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
version = "2.96.0"
version = "2.101.0"
[deps.SciMLBase.extensions]
SciMLBaseChainRulesCoreExt = "ChainRulesCore"
@ -2202,9 +2202,9 @@ version = "0.1.6"
[[deps.SciMLOperators]]
deps = ["Accessors", "ArrayInterface", "DocStringExtensions", "LinearAlgebra", "MacroTools"]
git-tree-sha1 = "85608e4aaf758547ffc4030c908318b432114ec9"
git-tree-sha1 = "3249fe77f322fe539e935ecb388c8290cd38a3fc"
uuid = "c0aeaf25-5076-4817-a8d5-81caf7dfa961"
version = "1.3.0"
version = "1.3.1"
weakdeps = ["SparseArrays", "StaticArraysCore"]
[deps.SciMLOperators.extensions]
@ -2308,9 +2308,9 @@ version = "1.11.0"
[[deps.SparseConnectivityTracer]]
deps = ["ADTypes", "DocStringExtensions", "FillArrays", "LinearAlgebra", "Random", "SparseArrays"]
git-tree-sha1 = "fadb2d7010dd92912e5eb31a493613ad4b8c9583"
git-tree-sha1 = "affde0bfd920cfcaa0944d3c0eb3a573fa9c4d1e"
uuid = "9f842d2f-2579-4b1d-911e-f412cf18a3f5"
version = "0.6.18"
version = "0.6.20"
[deps.SparseConnectivityTracer.extensions]
SparseConnectivityTracerDataInterpolationsExt = "DataInterpolations"
@ -2517,9 +2517,9 @@ version = "1.0.1"
[[deps.Tables]]
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "OrderedCollections", "TableTraits"]
git-tree-sha1 = "598cd7c1f68d1e205689b1c2fe65a9f85846f297"
git-tree-sha1 = "f2c1efbc8f3a609aadf318094f8fc5204bdaf344"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.12.0"
version = "1.12.1"
[[deps.Tar]]
deps = ["ArgTools", "SHA"]
@ -2539,15 +2539,15 @@ version = "1.11.0"
[[deps.ThreadingUtilities]]
deps = ["ManualMemory"]
git-tree-sha1 = "2d529b6b22791f3e22e7ec5c60b9016e78f5f6bf"
git-tree-sha1 = "d969183d3d244b6c33796b5ed01ab97328f2db85"
uuid = "8290d209-cae3-49c0-8002-c8c24d57dab5"
version = "0.5.4"
version = "0.5.5"
[[deps.TiffImages]]
deps = ["ColorTypes", "DataStructures", "DocStringExtensions", "FileIO", "FixedPointNumbers", "IndirectArrays", "Inflate", "Mmap", "OffsetArrays", "PkgVersion", "ProgressMeter", "SIMD", "UUIDs"]
git-tree-sha1 = "f21231b166166bebc73b99cea236071eb047525b"
deps = ["ColorTypes", "DataStructures", "DocStringExtensions", "FileIO", "FixedPointNumbers", "IndirectArrays", "Inflate", "Mmap", "OffsetArrays", "PkgVersion", "PrecompileTools", "ProgressMeter", "SIMD", "UUIDs"]
git-tree-sha1 = "02aca429c9885d1109e58f400c333521c13d48a0"
uuid = "731e570b-9d59-4bfa-96dc-6df516fadf69"
version = "0.11.3"
version = "0.11.4"
[[deps.TimerOutputs]]
deps = ["ExprTools", "Printf"]
@ -2599,14 +2599,16 @@ version = "0.4.1"
[[deps.Unitful]]
deps = ["Dates", "LinearAlgebra", "Random"]
git-tree-sha1 = "d62610ec45e4efeabf7032d67de2ffdea8344bed"
git-tree-sha1 = "d2282232f8a4d71f79e85dc4dd45e5b12a6297fb"
uuid = "1986cc42-f94f-5a68-af5c-568840ba703d"
version = "1.22.1"
weakdeps = ["ConstructionBase", "InverseFunctions"]
version = "1.23.1"
weakdeps = ["ConstructionBase", "ForwardDiff", "InverseFunctions", "Printf"]
[deps.Unitful.extensions]
ConstructionBaseUnitfulExt = "ConstructionBase"
ForwardDiffExt = "ForwardDiff"
InverseFunctionsUnitfulExt = "InverseFunctions"
PrintfExt = "Printf"
[[deps.Wayland_jll]]
deps = ["Artifacts", "EpollShim_jll", "Expat_jll", "JLLWrappers", "Libdl", "Libffi_jll", "XML2_jll"]
@ -2615,10 +2617,10 @@ uuid = "a2964d1f-97da-50d4-b82a-358c7fce9d89"
version = "1.23.1+0"
[[deps.Wayland_protocols_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "5db3e9d307d32baba7067b13fc7b5aa6edd4a19a"
deps = ["Artifacts", "JLLWrappers", "Libdl"]
git-tree-sha1 = "54b8a029ac145ebe8299463447fd1590b2b1d92f"
uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91"
version = "1.36.0+0"
version = "1.44.0+0"
[[deps.WebP]]
deps = ["CEnum", "ColorTypes", "FileIO", "FixedPointNumbers", "ImageCore", "libwebp_jll"]
@ -2782,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"]

View File

@ -1,28 +1,34 @@
include("../src/gray_scott_solver.jl")
include("../src/visualization.jl")
include("../src/constants.jl")
include("../src/utils/constants.jl")
using Observables
using GLMakie
using .GrayScottSolver
using .Visualization
using .Constants
const N = 128
const dx = 1.0
Du, Dv = Observable(0.16), Observable(0.08)
F, k = Observable(0.060), Observable(0.062)
# GSParams AND FHNParams
N = 128
dx = 1.0
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)
)
params_obs = Observable(GSParams(N, dx, Du[], Dv[], F[], k[]))
lift(Du, Dv, F, k) do u, v, f, ki
params_obs[] = GSParams(N, dx, u, v, f, ki)
params_obs = Observable{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)
heat_obs = Observable(U)
fig = build_ui(U, V, Du, Dv, F, k, params_obs, heat_obs)
fig = build_ui(U, V, params, params_obs, heat_obs)
display(fig)

View File

@ -1,208 +0,0 @@
using GLMakie, Observables
include("../src/constants.jl")
using .Constants
include("../src/visualization.jl")
using .Visualization
# # Gray Scott Model Parameters
# Parameters and initial conditions
N = 128
dx = 1.0
# diffusion rates of substance 'u' and 'v'
Du, Dv = Observable(0.16), Observable(0.08)
# feed rate of 'u' and kill rate of 'v'
F, k = Observable(0.060), Observable(0.062)
dt = 1.0
params_obs = Observable(GSParams(N, dx, Du[], Dv[], F[], k[]))
# # GUI Parameters
run_label = Observable{String}("Run")
stepsize = Observable{Int}(30)
function update_params!(params_obs::Observable, u, v, feed, kill)
old = params_obs[]
params_obs[] = GSParams(old.N, old.dx, u, v, feed, kill)
end
# Whenever a value gets changed via the textbox, update params object to reflect changes in simulation
lift(Du, Dv, F, k) do u, v, F, k
update_params!(params_obs, u, v, F, k)
end
U = ones(N, N)
V = zeros(N, N)
center = N ÷ 2
radius = 10
# set a cube in the center with starting concentrations for 'u' and 'v'
U[center-radius:center+radius, center-radius:center+radius] .= 0.50
V[center-radius:center+radius, center-radius:center+radius] .= 0.25
# Observable holding current U for heatmap
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, params_obs::Observable)
lap_u = laplacian5(U)
lap_v = laplacian5(V)
diff_u = params_obs[].Du
diff_v = params_obs[].Dv
feed_u = params_obs[].F
kill_v = params_obs[].k
u = U[2:end-1, 2:end-1]
v = V[2:end-1, 2:end-1]
uvv = u .* v .* v
u_new = u .+ (diff_u .* lap_u .- uvv .+ feed_u .* (1 .- u))
v_new = v .+ (diff_v .* lap_v .+ uvv .- (feed_u .+ kill_v) .* v)
# 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
return U
end
function multi_step!(state, n_steps)
for _ in 1:n_steps
heat_obs[] = step!(state[1], state[2], params_obs)
end
end
# Build GUI
fig = Figure(size=(600, 600))
gh = GridLayout(fig[1, 1])
ax = Axis(gh[1, 1])
hm = Makie.heatmap!(ax, heat_obs, colormap=:viridis)
Makie.deactivate_interaction!(ax, :rectanglezoom)
ax.aspect = DataAspect()
spoint = select_point(ax.scene)
function coord_to_index(x, y, N)
ix = clamp(round(Int, x), 1, N)
iy = clamp(round(Int, y), 1, N)
return ix, iy
end
r = 5
on(spoint) do pt
if pt === nothing
return
end
x, y = pt
i, j = coord_to_index(x, y, N)
# get corners of square that will get filled with concentration
imin = max(i - r, 1)
imax = min(i + r, N)
jmin = max(j - r, 1)
jmax = min(j + r, N)
# set disbalanced concentration of U and V
U[imin:imax, jmin:jmax] .= 0.5
V[imin:imax, jmin:jmax] .= 0.25
heat_obs[] = copy(U)
end
# # 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)
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[]))
speed_slider = slidergrid.sliders[1].value
on(speed_slider) do s
try
stepsize[] = s
println("Changed stepsize to $s")
catch
@warn "Invalid input for $s"
end
end
gh[1, 2] = textboxgrid = GridLayout(ax.scene, tellwidth=false)
rowsize!(gh, 1, Relative(1.0))
function param_box!(row, labeltxt, observable)
Label(textboxgrid[row, 1], labeltxt)
box = Textbox(textboxgrid[row, 2], validator=Float64, width=50, placeholder=labeltxt, stored_string="$(observable[])")
on(box.stored_string) do s
try
observable[] = parse(Float64, s)
println("changed $labeltxt to $s")
catch
@warn "Invalid input for $labeltxt: $s"
end
end
end
param_box!(1, "Du", Du)
param_box!(2, "Dv", Dv)
param_box!(3, "Feed", F)
param_box!(4, "kill", k)
# Timer and state for animation
running = Observable(false)
function reset!(U, V, heat_obs)
U .= 1.0
V .= 0.0
center = size(U, 1) ÷ 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
heat_obs[] = copy(U)
end
on(running) do r
run_label[] = r ? "Pause" : "Run"
end
# Button Listeners
on(btn_step.clicks) do _
multi_step!((U, V), stepsize[])
end
on(btn_start.clicks) do _
running[] = !running[]
end
on(btn_start.clicks) do _
@async while running[]
multi_step!((U, V), stepsize[])
sleep(0.05) # ~20 FPS
end
end
on(btn_reset.clicks) do _
running[] = false
reset!(U, V, heat_obs)
end
display(fig)

View File

@ -1,21 +0,0 @@
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

View File

@ -1,30 +0,0 @@
module Constants
struct FHNParams
N::Int
dx::Float64 # grid spacing
Du::Float64
Dv::Float64
ϵ::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
N::Int # grid size
dx::Float64 # grid spacing
Du::Float64 # diffusion rate U
Dv::Float64 # diffusion rate V
F::Float64 # feed rate
k::Float64 # kill rate
end
export FHNParams, GSParams
end # module Constants

50
src/fhn_solver.jl 100644
View File

@ -0,0 +1,50 @@
module FHNSolver
include("utils/laplacian.jl")
using DifferentialEquations
using Random
using Observables
using .Laplacian
function step_fhn!(U, V, params_obs::Observable; dx=1, dt=0.01)
p = params_obs[]
N = p.N
# Compute Laplacians on the interior
Δu = laplacian(U, dx)
Δv = laplacian(V, dx)
# Extract interior
u_in = U[2:end-1, 2:end-1]
v_in = V[2:end-1, 2:end-1]
# Compute update using FHN reaction-diffusion terms
fu = p.Du .* Δu .+ u_in .- u_in .^ 3 ./ 3 .- v_in
fv = p.Dv .* Δv .+ p.ϵ .* (u_in .+ p.a .- p.b .* v_in)
# Euler update
u_new = u_in .+ dt .* fu
v_new = v_in .+ dt .* fv
# Write back interior updates
U[2:end-1, 2:end-1] .= u_new
V[2:end-1, 2:end-1] .= v_new
# Apply 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]
return U
end
end # Module end

View File

@ -1,39 +1,35 @@
module GrayScottSolver
include("utils/laplacian.jl")
using Observables
include("constants.jl")
using .Constants
export laplacian5, step!, multi_step!
using .Laplacian
function laplacian5(f, dx)
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_gray_scott!(U, V, params_obs::Observable; dx=1)
# Extract parameters
p = params_obs[]
Du, Dv = p.Du, p.Dv
F, k = p.F, p.k
function step!(U, V, params_obs::Observable; dx=1)
lap_u = laplacian5(U, dx)
lap_v = laplacian5(V, dx)
diff_u = params_obs[].Du
diff_v = params_obs[].Dv
feed_u = params_obs[].F
kill_v = params_obs[].k
# Compute Laplacians on the interior
lap_u = laplacian(U, dx) # shape (N-2, N-2)
lap_v = laplacian(V, dx)
# Extract interior values
u = U[2:end-1, 2:end-1]
v = V[2:end-1, 2:end-1]
# Gray-Scott update equations (Euler-style)
uvv = u .* v .* v
u_new = u .+ (diff_u .* lap_u .- uvv .+ feed_u .* (1 .- u))
v_new = v .+ (diff_v .* lap_v .+ uvv .- (feed_u .+ kill_v) .* v)
u_new = u .+ (Du .* lap_u .- uvv .+ F .* (1 .- u))
v_new = v .+ (Dv .* lap_v .+ uvv .- (F .+ k) .* v)
# Update with new values
# Update interior
U[2:end-1, 2:end-1] .= u_new
V[2:end-1, 2:end-1] .= v_new
# Periodic boundary conditions
# Apply periodic boundary conditions
U[1, :] .= U[end-1, :]
U[end, :] .= U[2, :]
U[:, 1] .= U[:, end-1]
@ -44,12 +40,7 @@ function step!(U, V, params_obs::Observable; dx=1)
V[:, 1] .= V[:, end-1]
V[:, end] .= V[:, 2]
# Update heatmap observable
return U
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
end # Module end

View File

@ -1,20 +0,0 @@
"""
laplacian(U::Matrix{Float64}, N::Int, h::Float64)
Computes the discrete 2D Laplacian of a matrix `U` using a 5-point stencil
and circular boundary conditions.
# Arguments
- `U::Matrix{Float64}`: The input 2D matrix representing the field or image.
- `N::Int`: Integer
- `h::Float64`: The spatial step size or grid spacing between points in the discretization.
# Returns
- `Vector{Float64}`: A flattened (vectorized) representation of the approximated Laplacian values for each element in `U`. The boundary conditions are handled circularly.
"""
function laplacian(U::Matrix{Float64}, N::Int, h::Float64)
# shifts matrices and sums them up
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

View File

@ -1,154 +0,0 @@
using DifferentialEquations
using Random
include("constants.jl")
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

View File

@ -0,0 +1,36 @@
abstract type PDEParams end
struct FHNParams <: PDEParams
N::Int
dx::Float64 # grid spacing
Du::Float64
Dv::Float64
ϵ::Float64
a::Float64
b::Float64
end
struct GSParams <: PDEParams
N::Int # grid size
dx::Float64 # grid spacing
Du::Float64 # diffusion rate U
Dv::Float64 # diffusion rate V
F::Float64 # feed rate
k::Float64 # kill rate
end
struct CombinedPDEParams <: PDEParams
N::Int
dx::Float64
Du::Float64
Dv::Float64
F::Float64
k::Float64
ϵ::Float64
a::Float64
b::Float64
end

View File

@ -0,0 +1,16 @@
module Laplacian
function laplacian(U::AbstractMatrix{<:Real}, dx::Real)
h2 = dx^2
center = U[2:end-1, 2:end-1]
up = U[1:end-2, 2:end-1]
down = U[3:end, 2:end-1]
left = U[2:end-1, 1:end-2]
right = U[2:end-1, 3:end]
return (up .+ down .+ left .+ right .- 4 .* center) ./ h2
end
export laplacian
end # module Laplacian

View File

@ -0,0 +1,185 @@
# helper functions for filling cells in specific places of the matrix
# Not all functions are used. Those are for experimenting and debugging purposes
module Templates
function blocks_ic(N)
u = fill(1.0, N, N)
v = fill(0.0, N, N)
p = div(N, 2)
function safe_block!(u, row_center, col_center)
row_start = max(row_center - 8, 1)
row_end = min(row_center + 7, N)
col_start = max(col_center - 8, 1)
col_end = min(col_center + 7, N)
u[row_start:row_end, col_start:col_end] .= -0.01
end
safe_block!(u, p, p)
return u, v
end
function column_ic(N)
u = fill(0.01, N, N)
v = fill(0.99, N, N)
col_center = div(N, 2)
col_width = 8 # You can adjust this
col_start = max(col_center - div(col_width, 2), 1)
col_end = min(col_center + div(col_width, 2) - 1, N)
u[col_start:col_end, :] .= -0.01
return u, v
end
function stripe_ic(N)
u = zeros(N, N)
v = zeros(N, N)
for i in 1:N
for j in 1:N
u[i, j] = 0.1 + 0.05 * sin(2π * j / 10) + 0.01 * randn()
end
end
return u, v
end
function two_rows_edge_distance_ic(N)
row_width = 8
distance_from_edge = 50
u = fill(0.01, N, N)
v = fill(0.99, N, N)
# --- Input Validation ---
if row_width <= 0 || distance_from_edge < 0
error("row_width must be positive and distance_from_edge must be non-negative.")
end
# Calculate column 1 (from the left edge)
col1_start = distance_from_edge + 1
col1_end = col1_start + row_width - 1
# Calculate column 2 (from the right edge)
col2_end = N - distance_from_edge
col2_start = col2_end - row_width + 1
# --- Further Validation for placement ---
if col1_end > N || col2_start < 1
error("Columns go out of bounds. Adjust N, row_width, or distance_from_edge.")
end
if col1_end >= col2_start # Check for overlap or touching
error("Columns overlap or touch. Adjust N, row_width, or distance_from_edge such that 2 * (distance_from_edge + row_width) <= N.")
end
# Apply the first column
u[:, col1_start:col1_end] .= -0.01
# Apply the second column
u[:, col2_start:col2_end] .= -0.01
return u, v
end
function center_band_ic(N)
u = fill(0.0, N, N)
v = fill(0.0, N, N)
band_width = div(N, 8)
row_start = div(N, 2) - div(band_width, 2)
row_end = div(N, 2) + div(band_width, 2)
u[row_start:row_end, :] .= 0.1 .+ 0.01 .* randn(band_width + 1, N)
v[row_start:row_end, :] .= 0.1 .+ 0.01 .* randn(band_width + 1, N)
return u, v
end
function circle_ic(N)
u = fill(0.01, N, N)
v = fill(0.99, N, N)
cx, cy = div(N, 2), div(N, 2) # center of matrix
radius = 0.125 * N # circle radius = 3/4 of N divided by 2
for i in 1:N, j in 1:N
if (i - cx)^2 + (j - cy)^2 radius^2
u[i, j] = -0.01
end
end
return u, v
end
function three_circles_random_ic(N)
u = fill(0.01, N, N)
v = fill(0.99, N, N)
radius = 0.125 * N
# Define the bounds for random centers to ensure the circle stays within the matrix
min_coord = ceil(Int, radius) + 1
max_coord = floor(Int, N - radius)
if min_coord > max_coord
error("Matrix size N is too small to place circles of this radius without overlap or going out of bounds.")
end
for _ in 1:5 # Place 3 circles
# Generate random center coordinates
cx = rand(min_coord:max_coord)
cy = rand(min_coord:max_coord)
# Apply the circle to the matrix
for i in 1:N, j in 1:N
if (i - cx)^2 + (j - cy)^2 radius^2
u[i, j] = -0.01
end
end
end
return u, v
end
function squiggle_ic(N, Lx=400.0, Ly=400.0)
uplus = 0.01
vplus = 0.99
uminus = -uplus
# Create coordinate grids
x = LinRange(0, Lx, N)
y = LinRange(0, Ly, N)
X = repeat(x', N, 1) # Transposed to align with meshgrid X
Y = repeat(y, 1, N) # Broadcasted to align with meshgrid Y
# Squiggle pattern
cos_term = 0.05 * Lx .* sin.(10 * 2π .* Y ./ Ly .+ π * 0.3)
exp_term = exp.(-((Y .- Ly / 2) ./ (0.1 * Ly)) .^ 2)
width = 0.05 * Lx
Z = exp.(-((X .- Lx / 2 .+ cos_term .* exp_term) ./ width) .^ 2)
u = fill(uplus, N, N)
v = fill(vplus, N, N)
# Apply squiggle
u[Z.>0.8] .= uminus
return u, v
end
function coral_ic(N)
u = ones(N, N)
v = zeros(N, N)
for _ in 1:150 # place 15 noisy seeds
i, j = rand(5:N-5), rand(5:N-5)
u[i-2:i+2, j-2:j+2] .= -0.534522 .+ 0.2 * rand(5, 5)
end
return u, v
end
export blocks_ic, column_ic, squiggle_ic, three_circles_random_ic, circle_ic, center_band_ic, two_rows_edge_distance_ic, coral_ic, stripe_ic
end

View File

@ -1,48 +1,39 @@
module Visualization
include("utils/templates.jl")
include("gray_scott_solver.jl")
using GLMakie, Observables, Makie
using .GrayScottSolver
"""
step_through_solution(sol::SolutionType, N::Int)
include("fhn_solver.jl")
Function for visualization for the output of run_simulation
using Observables, Makie, GLMakie
using .Templates
using .GrayScottSolver: step_gray_scott!
using .FHNSolver: step_fhn!
# Arguments
- `sol`: computed differential equation by run_simulation
- `N`: size of the N×N grid
const STEP_FUNCTIONS = Dict(
:gray_scott => GrayScottSolver.step_gray_scott!,
:fhn => FHNSolver.step_fhn!
)
# Returns
- ``: Displays created figure
"""
function step_through_solution(sol, N::Int)
fig = Figure(resolution=(600, 600))
ax = Axis(fig[1, 1])
slider = Slider(fig[2, 1], range=1:length(sol), startvalue=1)
textbox = Textbox(fig[1, 2], placeholder="Feed Rate", validator=Float64)
F = Observable(0.060)
# 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)
on(textbox.stored_string) do s
F[] = parse(Float64, s)
end
# 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
function coord_to_index(x, y, N)
ix = clamp(round(Int, x), 1, N)
iy = clamp(round(Int, y), 1, N)
return ix, iy
end
"""
reset(U, V, heat_obs)
Resets heatmap to original state by replacing each cell.
Currently only places a square in the center
# Arguments
- `U`: Matrix filled with ones
- `V`: Empty matrix filled with zeros
- `heat_obs`: Heatmap observable
# Returns
- ``: resetted heatmap observable
"""
function reset!(U, V, heat_obs)
U .= 1.0
V .= 0.0
@ -50,11 +41,15 @@ function reset!(U, V, heat_obs)
radius = 10
U[center-radius:center+radius, center-radius:center+radius] .= 0.50
V[center-radius:center+radius, center-radius:center+radius] .= 0.25
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)
@ -63,13 +58,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 build_ui(U, V, Du, Dv, F, k, params_obs, heat_obs)
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))
fig = Figure(size=(1300, 950))
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()
@ -77,26 +86,50 @@ function build_ui(U, V, Du, Dv, F, k, 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
# 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)
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:50, format="{}x", width=750, startvalue=stepsize[], tellwidth=false))
speed_slider = slidergrid.sliders[1].value
gh[1, 2] = templategrid = GridLayout(ax.scene, tellwidth=false)
templategrid[1, 1] = Label(fig, "Templates:")
btn_waves = Button(templategrid[1, 2], width=100, label="Wave Pattern")
btn_cow = Button(templategrid[1, 3], width=100, label="Cow Spots")
btn_cheetah = Button(templategrid[1, 4], width=100, label="Cheetah Spots")
gh[1, 2] = textboxgrid = GridLayout(ax.scene, tellwidth=false)
rowsize!(gh, 1, Relative(1.0))
# place all the parameter boxes
gh[2, 2] = textboxgrid = GridLayout(ax.scene, tellwidth=false)
# Create and assign column header labels
textboxgrid[1, 1] = Label(fig, "GrayScott:", halign=:center)
textboxgrid[1, 3] = Label(fig, "FHN:", halign=:center)
param_box!(textboxgrid, 1, "Du", Du)
param_box!(textboxgrid, 2, "Dv", Dv)
param_box!(textboxgrid, 3, "Feed", F)
param_box!(textboxgrid, 4, "kill", k)
# GrayScott column (col 1)
param_box!(textboxgrid, 2, "Du", param_obs_map.Du, col=1)
param_box!(textboxgrid, 3, "Dv", param_obs_map.Dv, col=1)
param_box!(textboxgrid, 4, "Feed", param_obs_map.F, col=1)
param_box!(textboxgrid, 5, "Kill", param_obs_map.k, col=1)
# FHN column (col 2)
param_box!(textboxgrid, 2, "Du", param_obs_map.Du, col=2)
param_box!(textboxgrid, 3, "Dv", param_obs_map.Dv, col=2)
param_box!(textboxgrid, 4, "ϵ", param_obs_map.ϵ, col=2)
param_box!(textboxgrid, 5, "a", param_obs_map.a, col=2)
param_box!(textboxgrid, 6, "b", param_obs_map.b, col=2)
rowsize!(gh, 1, Relative(0.2)) # small row for the menu
rowsize!(gh, 2, Relative(0.8))
for c in 1:4
colsize!(textboxgrid, c, Relative(0.1))
end
# ======== Events ========
# Timer and state for animation
running = Observable(false)
@ -111,9 +144,9 @@ function build_ui(U, V, Du, Dv, F, k, params_obs, heat_obs)
@warn "Invalid input for $s"
end
end
# Button Listeners
# Control Listeners
on(btn_step.clicks) do _
multi_step!((U, V), stepsize[], heat_obs, params_obs)
multi_step!((U, V), stepsize[] * 5, heat_obs, params_obs; step_method=step_method[])
end
on(btn_start.clicks) do _
@ -122,7 +155,7 @@ function build_ui(U, V, Du, Dv, F, k, 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
@ -132,13 +165,62 @@ function build_ui(U, V, Du, Dv, F, k, params_obs, heat_obs)
reset!(U, V, heat_obs)
end
# Template Control
on(btn_waves.clicks) do _
# add column to center of matrix
U, V = Templates.blocks_ic(params_obs[].N)
hm.colormap[] = :seismic
# change params
param_obs_map.Du[] = 0.0008
param_obs_map.Dv[] = 0.1
param_obs_map.ϵ[] = 0.01
param_obs_map.a[] = 0.5
param_obs_map.b[] = 0.15
heat_obs[] = copy(U)
end
# Template Control
on(btn_cow.clicks) do _
# fill matrix with random noise
U = 0.05 .* (2 .* rand(params_obs[].N, params_obs[].N) .- 1) # noise in [-0.05, 0.05]
V = 0.05 .* (2 .* rand(params_obs[].N, params_obs[].N) .- 1)
hm.colormap[] = :grayC
# change params
param_obs_map.Du[] = 1.0
param_obs_map.Dv[] = 10.0
param_obs_map.ϵ[] = 0.01
param_obs_map.a[] = -0.1
param_obs_map.b[] = 1.2
heat_obs[] = copy(U)
end
on(btn_cheetah.clicks) do _
# fill matrix with random noise
U = 0.05 .* (2 .* rand(params_obs[].N, params_obs[].N) .- 1) # noise in [-0.05, 0.05]
V = 0.05 .* (2 .* rand(params_obs[].N, params_obs[].N) .- 1)
hm.colormap[] = cgrad(:lajolla, rev=true)
# change params
param_obs_map.Du[] = 0.182
param_obs_map.Dv[] = 0.5
param_obs_map.ϵ[] = 0.05
param_obs_map.a[] = 0.2
param_obs_map.b[] = 2.0
heat_obs[] = copy(U)
end
on(spoint) do pt
r = 5
if pt === nothing
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
@ -153,9 +235,26 @@ function build_ui(U, V, Du, Dv, F, k, 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
export step_through_solution, build_ui
export build_ui
end