Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

📚 The CoCalc Library - books, templates and other resources

132922 views
License: OTHER
1
import itertools
2
3
import numpy as np
4
import matplotlib.pyplot as plt
5
6
from Cell2D import Cell2D, Cell2DViewer
7
from scipy.signal import correlate2d
8
9
10
class SandPile(Cell2D):
11
"""Diffusion Cellular Automaton."""
12
13
kernel = np.array([[0, 1, 0],
14
[1,-4, 1],
15
[0, 1, 0]], dtype=np.int32)
16
17
def __init__(self, n, m=None, level=9):
18
"""Initializes the attributes.
19
20
n: number of rows
21
m: number of columns
22
level: starting value for all cells
23
"""
24
m = n if m is None else m
25
self.array = np.ones((n, m), dtype=np.int32) * level
26
self.reset()
27
28
def reset(self):
29
"""Start keeping track of the number of toppled cells.
30
"""
31
self.toppled_seq = []
32
33
def step(self, K=3):
34
"""Executes one time step.
35
36
returns: number of cells that toppled
37
"""
38
toppling = self.array > K
39
num_toppled = np.sum(toppling)
40
self.toppled_seq.append(num_toppled)
41
42
c = correlate2d(toppling, self.kernel, mode='same')
43
self.array += c
44
return num_toppled
45
46
def drop(self):
47
"""Increments a random cell."""
48
a = self.array
49
n, m = a.shape
50
index = np.random.randint(n), np.random.randint(m)
51
a[index] += 1
52
53
def run(self):
54
"""Runs until equilibrium.
55
56
returns: duration, total number of topplings
57
"""
58
total = 0
59
for i in itertools.count(1):
60
num_toppled = self.step()
61
total += num_toppled
62
if num_toppled == 0:
63
return i, total
64
65
def drop_and_run(self):
66
"""Drops a random grain and runs to equilibrium.
67
68
returns: duration, total_toppled
69
"""
70
self.drop()
71
duration, total_toppled = self.run()
72
return duration, total_toppled
73
74
75
class SandPileViewer(Cell2DViewer):
76
cmap = plt.get_cmap('YlOrRd')
77
options = dict(interpolation='nearest', alpha=0.8,
78
vmin=0, vmax=5)
79
80
def __init__(self, viewee, drop_flag=True):
81
"""Initializes the attributes.
82
83
drop_flag: determines whether `step` drops a grain
84
"""
85
Cell2DViewer.__init__(self, viewee)
86
self.drop_flag = drop_flag
87
88
def step(self):
89
"""Advances the viewee one step."""
90
if self.drop_flag:
91
self.viewee.drop_and_run()
92
else:
93
self.viewee.step()
94
95
96
def single_source(pile, height=1024):
97
"""Adds a tower to the center cell.
98
99
height: value assigned to the center cell
100
"""
101
a = pile.array
102
n, m = a.shape
103
a[:, :] = 0
104
a[n//2, m//2] = height
105
106
107
def main():
108
n = 101
109
pile = SandPile(n)
110
single_source(pile, height=2**14)
111
viewer = SandPileViewer(pile, drop_flag=False)
112
anim = viewer.animate(interval=0)
113
plt.subplots_adjust(left=0.01, right=0.99, bottom=0.01, top=0.99)
114
plt.show()
115
116
117
if __name__ == '__main__':
118
main()
119
120