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
|
from OpenGL.GL import *
import numpy as np
import scipy.stats as stats
import scipy.constants as const
from scipy.optimize import minimize
import matplotlib
import matplotlib.pyplot as plt
from concurrent.futures import Future, ProcessPoolExecutor
def get_histogram(velocities, char_u):
maxwellian = stats.maxwell.fit(velocities)
plt.style.use('dark_background')
fig = plt.figure(figsize=(8,8))
ax = fig.add_axes([0.1, 0.06, 0.88, 0.92])
plt.ylim(0, 0.004)
plt.ylabel('Probability')
plt.xlim(0, 1.2*char_u)
plt.xlabel('Velocity magnitude [m/s]')
plt.hist(velocities, bins=50, density=True, alpha=0.5, label='Simulated velocities')
xs = np.linspace(0, 1.2*char_u, 100)
plt.plot(xs, stats.maxwell.pdf(xs, *maxwellian), label='Maxwell-Boltzmann distribution')
plt.legend(loc='upper right')
fig.canvas.draw()
buf = fig.canvas.tostring_rgb()
width, height = fig.canvas.get_width_height()
texture = np.frombuffer(buf, dtype=np.uint8).reshape(width, height, 3)
plt.close(fig)
return (texture, height, width)
class VelocityHistogram:
def __init__(self, gas, origin, extend):
self.gas = gas
self.origin = origin
self.extend = extend
self.steps = -1
self.pool = ProcessPoolExecutor(max_workers=1)
self.plotter = None
self.tick = False
self.mixing = 0.0
self.vertices = np.array([
self.origin[0] , self.origin[1] , 0., 1.,
self.origin[0] + self.extend[0], self.origin[1] , 1., 1.,
self.origin[0] , self.origin[1] + self.extend[1], 0., 0.,
self.origin[0] + self.extend[0], self.origin[1] + self.extend[1], 1., 0.
], dtype=np.float32)
def setup(self):
self.vao = glGenVertexArrays(1)
self.vbo = glGenBuffers(1)
glBindVertexArray(self.vao)
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
glBufferData(GL_ARRAY_BUFFER, self.vertices.tostring(), GL_STATIC_DRAW)
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4*np.dtype(np.float32).itemsize, ctypes.c_void_p(0))
glEnableVertexAttribArray(1)
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4*np.dtype(np.float32).itemsize, ctypes.c_void_p(2*np.dtype(np.float32).itemsize))
self.texture_id = glGenTextures(2)
glBindTexture(GL_TEXTURE_2D, self.texture_id[0])
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, self.texture_id[1])
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
def shutdown(self):
self.pool.shutdown()
def update(self):
self.steps = self.steps + 1
if self.steps % 50 == 0 and self.plotter == None:
self.plotter = self.pool.submit(get_histogram, self.gas.get_velocity_norms(), self.gas.char_u)
else:
if self.plotter != None and self.plotter.done():
texture, width, height = self.plotter.result()
if self.tick:
glBindTexture(GL_TEXTURE_2D, self.texture_id[0])
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture)
self.tick = False
self.mixing = 1.0
else:
glBindTexture(GL_TEXTURE_2D, self.texture_id[1])
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture)
self.tick = True
self.mixing = 0.0
self.plotter = None
def display_decoration(self, uniform):
pass
def display_window(self, uniform):
if self.tick:
self.mixing = min(self.mixing+0.05, 1.0);
else:
self.mixing = max(self.mixing-0.05, 0.0);
glBindTextures(self.texture_id[0], 2, self.texture_id)
glUniform1iv(uniform['picture'], len(self.texture_id), self.texture_id)
glUniform1f(uniform['mixing'], self.mixing)
glBindVertexArray(self.vao);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
glBindVertexArray(0)
|