generated from taichiCourse01/taichi_course_homework
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathdiffuse_explicit_profiling.py
More file actions
138 lines (117 loc) · 3.49 KB
/
diffuse_explicit_profiling.py
File metadata and controls
138 lines (117 loc) · 3.49 KB
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import taichi as ti
ti.init(arch = ti.cuda, kernel_profiler=True)
# control
paused = False
save_images = False
# problem setting
n = 256
scatter = 4
res = n * scatter
# physical parameters
# time-integration related
h = 1e-3 # time-step size
substep = 1 # number of substeps
dx = 1 # finite difference step size (in space)
# heat-source related
t_max = 300 # max temperature (in Celsius)
t_min = 0 # min temperature
heat_center = (n//2, n//2)
heat_radius = 5.1
k = 50.0 # rate of heat diffusion
# temperature now and temperature next_time
t_n = ti.field(ti.f32, shape = (n,n))
t_np1 = ti.field(ti.f32, shape = (n,n))
# visualization
pixels = ti.Vector.field(3, ti.f32, shape = (res, res))
# pixels = ti.Vector.field(3, ti.f32)
# ti.root.dense(ti.ij, n).dense(ti.ij, scatter).place(pixels)
@ti.kernel
def init():
for i,j in t_n:
if (float(i)-heat_center[0])**2 + (float(j)-heat_center[1])**2 <= heat_radius**2:
t_n[i, j] = t_max # source
t_np1[i, j] = t_max # source
else:
t_n[i, j] = t_min
t_np1[i, j] = t_min
@ti.kernel
def update_source():
for i,j in t_n:
if (float(i)-heat_center[0])**2 + (float(j)-heat_center[1])**2 <= heat_radius**2:
t_np1[i, j] = t_max
@ti.kernel
def diffuse(dt: ti.f32):
c = dt * k / dx**2
for i,j in t_n:
t_np1[i,j] = t_n[i,j]
if i-1 >= 0:
t_np1[i, j] += c * (t_n[i-1, j] - t_n[i, j])
if i+1 < n:
t_np1[i, j] += c * (t_n[i+1, j] - t_n[i, j])
if j-1 >= 0:
t_np1[i, j] += c * (t_n[i, j-1] - t_n[i, j])
if j+1 < n:
t_np1[i, j] += c * (t_n[i, j+1] - t_n[i, j])
def update_source_and_commit():
update_source()
t_n.copy_from(t_np1)
@ti.func
def get_color(v, vmin, vmax):
c = ti.Vector([1.0, 1.0, 1.0]) # white
if v < vmin:
v = vmin
if v > vmax:
v = vmax
dv = vmax - vmin
if v < (vmin + 0.25 * dv):
c[0] = 0
c[1] = 4 * (v-vmin) / dv
elif v < (vmin + 0.5 * dv):
c[0] = 0
c[2] = 1 + 4 * (vmin + 0.25*dv -v) / dv
elif v < (vmin + 0.75*dv):
c[0] = 4 * (v - vmin -0.5 * dv) / dv
c[2] = 0
else:
c[1] = 1 + 4 * (vmin + 0.75 * dv - v) / dv
c[2] = 0
return c
@ti.kernel
def temperature_to_color(t: ti.template(), color: ti.template(), tmin: ti.f32, tmax: ti.f32):
for i,j in t:
for k,l in ti.ndrange(scatter, scatter):
color[i*scatter+k,j*scatter+l] = get_color(t[i,j], tmin, tmax)
# GUI
my_gui = ti.GUI("Diffuse", (res, res))
init()
i = 0
# warm start the kernels
diffuse(0)
update_source_and_commit()
temperature_to_color(t_np1, pixels, t_min, t_max)
ti.clear_kernel_profile_info() # clear resutls
# while my_gui.running:
for debug_iter in range(100):
for e in my_gui.get_events(ti.GUI.PRESS):
if e.key == ti.GUI.ESCAPE:
exit()
elif e.key == ti.GUI.SPACE:
paused = not paused
elif e.key == 'i':
save_images = not save_images
print(f"Exporting images to images\output_{i:05}.png")
elif e.key == 'r':
init()
i = 0
if not paused:
for sub in range(substep):
diffuse(h/substep)
update_source_and_commit()
temperature_to_color(t_np1, pixels, t_min, t_max)
my_gui.set_image(pixels)
if save_images and not paused:
my_gui.show(f"images\output_{i:05}.png")
i += 1
else:
my_gui.show()
ti.print_kernel_profile_info('count')