/
Brusselator.py
95 lines (88 loc) · 2.74 KB
/
Brusselator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
from ._TuringPattern import TuringPattern, ModelParameter
from scipy.ndimage import convolve
import numpy as np
from typing import Optional
class Brusselator(TuringPattern):
default_size = 200
default_dx = 1
default_dy = 1
default_dt = 0.01
default_contrast_limits=(0.3, 3.5)
A = ModelParameter(
name="A",
value=1.,
min=.1,
max=5.,
exponent=1,
description="Concentration of productor of x",
)
B = ModelParameter(
name="B",
value=3.,
min=.1,
max=5.,
exponent=1,
description="Concentration of productor of y (combined with x)",
)
mu_x = ModelParameter(
name="mu_x",
value=2.,
min=.1,
max=5,
exponent=1,
description="Diffusion coefficient of x",
)
mu_y = ModelParameter(
name="mu_y",
description="Diffusion coefficient of y (10^-1)",
value=2.,
min=0.01,
max=20,
exponent=1e-1,
)
nb_pos = ModelParameter(
name="nb_pos",
value=1,
min=1,
max=300,
exponent=1,
description="Number of random perturbations",
dtype=int
)
_necessary_parameters = [A, B, mu_x, mu_y, nb_pos]
_tunable_parameters = [A, B, mu_x, mu_y, nb_pos]
_concentration_names = ["X", "Y"]
def _reaction(self, c: str) -> np.ndarray:
if c == "X":
return self.A + self.X**2 * self.Y - self.B * self.X - self.X
elif c == "Y":
return self.B * self.X - self.X**2 * self.Y
def _diffusion(self, c: str) -> np.ndarray:
if c == "X":
arr = self.X
mu = self.mu_x
elif c == "Y":
arr = self.Y
mu = self.mu_y
to_cell = convolve(arr, self.kernel.value, mode="constant", cval=0)
from_cell = self.nb_neighbs * arr
out = mu * (to_cell - from_cell) / (self.dx * self.dy)
return out
def init_concentrations(self, C: Optional[str] = None) -> None:
pos = (np.random.random((2, self.nb_pos)) * self.size).astype(int)
values = np.random.random(self.nb_pos)
if C == "X" or C is None:
X = np.ones((self.size, self.size))*self.A
X[pos[0], pos[1]] += values
self["X"] = X
if C == "Y" or C is None:
Y = np.ones((self.size, self.size))*self.B/self.A
Y[pos[0], pos[1]] -= values
self["Y"] = Y
def __str__(self) -> str:
return (
"Equations (Brusselator model):\n"
" Concentration of two chemical components x and y\n"
" - dx/dt = mu_x * diffusion(x) + A + x^2*y - B * x - x\n"
" - dy/dt = mu_y * diffusion(i) + B * x - x^2*y"
)