Skip to content

Commit f9d02ca

Browse files
committed
reaction diffusion
1 parent 29ed055 commit f9d02ca

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed

src/ex65_reaction_diffusion.clj

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
;; https://www.karlsims.com/rd.html
2+
(ns ex65-reaction-diffusion
3+
(:require [fastmath.core :as m]
4+
[fastmath.random :as r]
5+
[clojure2d.core :as c2d]
6+
[clojure2d.color :as c]
7+
[fastmath.vector :as v])
8+
(:import [fastmath.java Array]))
9+
10+
(set! *warn-on-reflection* true)
11+
(set! *unchecked-math* :warn-on-boxed)
12+
13+
(def ^:const size 450)
14+
(def ^:const scale 2)
15+
(def ^:const csize (m/* scale size))
16+
(def ^:const size2 (m/* size size))
17+
(def rsize (range size))
18+
19+
(defn setup []
20+
(let [A (double-array size2 1.0)
21+
dA (double-array size2)
22+
23+
B (double-array size2 0.0)
24+
dB (double-array size2)]
25+
26+
(doseq [^long x (range 50 100)
27+
^long y (range 120 180)]
28+
(Array/set2d B size x y (r/drand))
29+
(Array/set2d B size y x (r/drand)))
30+
31+
(doseq [^long x (repeatedly 100 #(r/irand size))
32+
^long y (repeatedly 100 #(r/irand size))]
33+
(Array/set2d B size x y (r/drand))
34+
(Array/set2d B size y x (r/drand)))
35+
36+
{:A A :dA dA
37+
:B B :dB dB
38+
:Da 1.0 :Db m/THIRD
39+
:f 0.055 :k 0.062
40+
:dt 1.0
41+
:show-map? true}))
42+
43+
(defn diffuse! [^double d ^doubles source ^doubles target]
44+
(doseq [^long x rsize ^long y rsize
45+
:let [x- (m/mod (m/dec x) size)
46+
x+ (m/mod (m/inc x) size)
47+
y- (m/mod (m/dec y) size)
48+
y+ (m/mod (m/inc y) size)]]
49+
(Array/set2d target size x y (m/* d (m/- (m/+ (m/* 0.05 (m/+ (Array/get2d source size x- y-)
50+
(Array/get2d source size x+ y-)
51+
(Array/get2d source size x- y+)
52+
(Array/get2d source size x+ y+)))
53+
(m/* 0.2 (m/+ (Array/get2d source size x- y)
54+
(Array/get2d source size x+ y)
55+
(Array/get2d source size x y-)
56+
(Array/get2d source size x y+))))
57+
(Array/get2d source size x y))))))
58+
59+
(defn norm-f ^double [^double y] (m/mnorm y 0 size 0.15 0.001))
60+
(defn norm-k ^double [^double x] (m/mnorm x 0 size 0.041 0.085))
61+
62+
(defn step [{:keys [^doubles A ^doubles dA ^doubles B ^doubles dB ^double dt
63+
^double Da ^double Db ^double f ^double k show-map?] :as data}]
64+
(diffuse! Da A dA)
65+
(diffuse! Db B dB)
66+
(doseq [^long x rsize ^long y rsize
67+
:let [a (Array/get2d A size x y)
68+
b (Array/get2d B size x y)
69+
abb (m/* a b b)
70+
f (if show-map? (norm-f y) f)
71+
k (if show-map? (norm-k x) k)]]
72+
(Array/set2d A size x y (m/constrain (m/+ a (m/* dt (m/+ (Array/get2d dA size x y)
73+
(m/- (m/* f (m/- 1.0 a)) abb)))) 0.0 1.0))
74+
(Array/set2d B size x y (m/constrain (m/+ b (m/* dt (m/+ (Array/get2d dB size x y)
75+
(m/- abb (m/* (m/+ f k) b))))) 0.0 1.0)))
76+
data)
77+
78+
(defn draw
79+
[canvas window _ {:keys [^doubles A ^doubles B show-map? f k] :as curr}]
80+
(when (c2d/mouse-pressed? window)
81+
(let [[x y] (v/div (c2d/mouse-pos window) scale)]
82+
(dotimes [_ 20] (Array/set2d B size
83+
(m/mod (m/+ (r/irand -10 10) (int x)) size)
84+
(m/mod (m/+ (r/irand -10 10) (int y)) size) (r/drand)))))
85+
(let [[^double mx ^double my] (v/div (c2d/mouse-pos window) scale)
86+
curr (if (c2d/key-pressed? window)
87+
(condp = (c2d/key-code window)
88+
:space (let []
89+
(assoc curr
90+
:f (norm-f my)
91+
:k (norm-k mx)
92+
:show-map? false))
93+
:m (assoc curr :show-map? true)
94+
curr)
95+
curr)]
96+
97+
(c2d/set-background canvas (c/color 10 10 20) 100)
98+
(doseq [^long x rsize ^long y rsize
99+
:let [a (Array/get2d A size x y)
100+
b (Array/get2d B size x y)]]
101+
(c2d/set-color canvas (v/mult (v/vec3 (m/- 1.0 a) b (m/sqrt (m/* a b))) 255.0))
102+
(c2d/rect canvas (m/* x scale) (m/* y scale) scale scale))
103+
(let [f (m/approx (if show-map? (norm-f my) f) 6)
104+
k (m/approx (if show-map? (norm-k mx) k) 6)]
105+
(-> canvas
106+
(c2d/set-color :light-blue 200)
107+
(c2d/rect 8 9 80 38)
108+
(c2d/set-color :black)
109+
(c2d/set-font-attributes 12 :bold)
110+
(c2d/text (str "f=" f) 15 25)
111+
(c2d/text (str "k=" k) 15 40)))
112+
(step curr)))
113+
114+
(def window (c2d/show-window {:canvas (c2d/black-canvas csize csize :mid)
115+
:draw-fn draw
116+
:background :black
117+
:draw-state (step (setup))}))
118+

0 commit comments

Comments
 (0)