ha-ha
[pde-python.git] / gui.py
blob71eaa459522e5bccca421ac072d2877bb26612dc
1 #-*- coding: utf-8
3 # Политика префиксов в именах
4 # QLineEdit - edit_
5 # QLabel - label_
6 # QPushButton - button_
9 import sys
11 from PyQt4.QtCore import *
12 from PyQt4.QtGui import *
14 import matplotlib
15 from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
16 from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar
17 from matplotlib.figure import Figure
19 import numpy as np
21 from grid import ExplicitSolver, ImplicitSolver, norm
22 try:
23 from waves import Exm, setParameters
24 except ImportError:
25 from third import Exm, setParameters
26 import const as co
29 def split_number(x):
30 return ('%g' % x).split('e')
32 def normal(x):
33 return np.float64('1e' + split_number(x)[1])
35 class Dummy(object):
36 pass
38 class AppForm(QMainWindow):
40 def __init__(self, parent=None):
41 QMainWindow.__init__(self, parent)
42 self.setWindowTitle(u'Курсовой проект')
44 self.create_main_frame()
45 self.setWindowState(Qt.WindowMaximized)
47 self.on_grid_change()
49 self.data = Dummy()
50 # self.test_graph()
52 def create_main_frame(self):
53 self.main_frame = QWidget()
54 self.init_work_frame()
55 self.init_param_frame()
57 self.splitter = QSplitter()
58 self.splitter.addWidget(self.param_frame)
60 self.splitter.addWidget(self.work_frame)
61 self.main_layout = QGridLayout(self.main_frame)
62 # self.main_layout.addWidget(self.param_frame, 0, 0)
63 # self.main_layout.addWidget(self.work_frame, 0, 1)
64 self.main_layout.addWidget(self.splitter)
65 self.setCentralWidget(self.main_frame)
67 def init_param_frame(self):
68 self.param_frame = QWidget()
69 param_group = QGroupBox(u"&Параметры")
70 param_layout = QGridLayout(self.param_frame)
71 param_layout.addWidget(param_group, 0, 0)
73 self.edit_LY = QLineEdit(str(co.LY))
74 self.edit_LY.setMinimumWidth(40)
75 self.edit_LZ = QLineEdit(str(co.LZ))
76 self.edit_LZ.setMinimumWidth(40)
77 self.edit_C = QLineEdit(str(co.C))
78 self.edit_C.setMinimumWidth(40)
79 self.edit_LAMBDA = QLineEdit(str(co.LAMBDA))
80 self.edit_LAMBDA.setMinimumWidth(40)
81 self.edit_T = QLineEdit('1e-14')
82 self.edit_dim_y = QLineEdit(str(50))
83 self.edit_dim_z = QLineEdit(str(50))
85 pg_layout = QFormLayout(param_group)
86 pg_layout.addRow(u'Ширина ly', self.edit_LY)
87 pg_layout.addRow(u'Высота lz', self.edit_LZ)
88 pg_layout.addRow(u'Скорость C', self.edit_C)
89 pg_layout.addRow(u'Волна λ', self.edit_LAMBDA)
90 pg_layout.addRow(u'Момент T', self.edit_T)
91 pg_layout.addRow(u'Размер по y (I)', self.edit_dim_y)
92 pg_layout.addRow(u'Размер по z (J)', self.edit_dim_z)
93 self.param_frame.setMaximumWidth(250)
95 self.connect(self.edit_LY, SIGNAL("returnPressed()"), self.on_grid_change)
96 self.connect(self.edit_LZ, SIGNAL("returnPressed()"), self.on_grid_change)
97 self.connect(self.edit_dim_y, SIGNAL("returnPressed()"), self.on_grid_change)
98 self.connect(self.edit_dim_z, SIGNAL("returnPressed()"), self.on_grid_change)
100 def _make_analytic(self):
101 a_group = QGroupBox(u"Аналитическое решение")
102 a_group.setCheckable(True)
103 a_layout = QFormLayout(a_group)
105 self.edit_length = QLineEdit(str(500))
106 a_layout.addRow(u"Элементов ряда", self.edit_length)
107 self.edit_length.setMaximumWidth(100)
109 return a_group
111 def _make_explicit(self):
112 e_group = QGroupBox(u"Явная схема")
113 e_group.setCheckable(True)
114 e_group.setChecked(False)
115 e_layout = QFormLayout(e_group)
116 self.edit_exp_step_t = QLineEdit()
117 e_layout.addRow(u"Шаг по t", self.edit_exp_step_t)
119 return e_group
121 def _make_implicit(self):
122 i_group = QGroupBox(u"Неявная схема")
123 i_group.setCheckable(True)
124 i_group.setChecked(False)
125 i_layout = QFormLayout(i_group)
126 self.edit_imp_step_t = QLineEdit()
127 i_layout.addRow(u"Шаг по t", self.edit_imp_step_t)
129 return i_group
131 def _make_norm_frame(self):
132 self.norm_frame = QWidget()
133 self.n_fig = Figure((5.0, 4.0), dpi = self.dpi)
134 self.n_canvas = FigureCanvas(self.n_fig)
135 self.n_canvas.setParent(self.main_frame)
136 self.n_axes = self.n_fig.add_subplot(111)
137 n_layout = QGridLayout(self.norm_frame)
138 n_layout.addWidget(self.n_canvas, 0, 0, 1, 3)
139 n_toolbar = NavigationToolbar(self.n_canvas, self.norm_frame)
140 n_layout.addWidget(n_toolbar, 1, 0, 1, 3)
142 ht_button = QPushButton("test ht")
143 self.connect(ht_button, SIGNAL("clicked()"), self.on_test_ht)
144 n_layout.addWidget(ht_button, 2, 0)
145 hy_button = QPushButton("test hy")
146 self.connect(hy_button, SIGNAL("clicked()"), self.on_test_hy)
147 n_layout.addWidget(hy_button, 2, 1)
148 hz_button = QPushButton("test hz")
149 self.connect(hz_button, SIGNAL("clicked()"), self.on_test_hz)
150 n_layout.addWidget(hz_button, 2, 2)
152 def init_work_frame(self):
153 self.work_frame = QTabWidget()
155 self.dpi = 100
156 self.z_fig = Figure((5.0, 4.0), dpi = self.dpi)
157 self.z_canvas = FigureCanvas(self.z_fig)
158 self.z_canvas.setParent(self.main_frame)
159 self.z_axes = self.z_fig.add_subplot(111)
161 self.graph_frame = QWidget()
162 graph_layout = QGridLayout(self.graph_frame)
163 graph_layout.addWidget(self.z_canvas, 0, 0, 1, 1)
165 self.mpl_toolbar = NavigationToolbar(self.z_canvas, self.graph_frame)
166 # self.mpl_toolbar.setOrientation(Qt.Vertical)
167 graph_layout.addWidget(self.mpl_toolbar, 1, 0, 1, 1)
169 scheme_frame = QWidget()
170 scheme_layout = QGridLayout(scheme_frame)
171 self.a_group = self._make_analytic()
172 self.exp_group = self._make_explicit()
173 self.imp_group = self._make_implicit()
174 scheme_layout.addWidget(self.a_group, 0, 0, 1, 1)
175 scheme_layout.addWidget(self.exp_group, 0, 1, 1, 1)
176 scheme_layout.addWidget(self.imp_group, 0, 2, 1, 1)
178 self.button_scheme_run = QPushButton(u'Пуск')
179 self.connect(self.button_scheme_run, SIGNAL("clicked()"), self.on_scheme_run)
180 self.button_scheme_run.setFocus(Qt.ActiveWindowFocusReason)
182 graph_layout.addWidget(scheme_frame, 2, 0)
183 graph_layout.addWidget(self.button_scheme_run, 3, 0)
185 self._make_norm_frame()
187 self.about_frame = QWidget()
189 self.work_frame.addTab(self.graph_frame, u"&Разностная схема")
190 self.work_frame.addTab(self.norm_frame, u"&Аппроксимация")
191 # self.work_frame.addTab(self.about_frame, u"&О программе")
193 def on_test_ht(self):
194 ly_str = unicode(self.edit_LY.text())
195 lz_str = unicode(self.edit_LZ.text())
196 ny_str = unicode(self.edit_dim_y.text())
197 nz_str = unicode(self.edit_dim_z.text())
198 time_str = unicode(self.edit_T.text())
200 M = 600
202 ly = np.float64(ly_str)
203 lz = np.float64(lz_str)
204 ny = int(ny_str)
205 nz = int(nz_str)
206 hy = (ly / ny)
207 hz = (lz / nz)
208 time = np.float64(time_str)
210 ht_exp = min(hy, hz) / (np.sqrt(2) * co.C)
211 ht = normal(ht_exp)
213 x_vals = []
214 y_vals = []
215 for n in xrange(1, 5):
216 print ht
217 x_vals.append(ht)
218 solver = ExplicitSolver(ny, nz, time, ht=ht)
219 u = solver.solve()
220 for i in xrange(u.shape[0]):
221 for j in xrange(u.shape[1]):
222 u[i, j] -= Exm(i * hy, j * hz, time, M)
223 y_vals.append(np.max(np.abs(u)))
224 ht /= 2
226 line, = self.n_axes.plot(x_vals, y_vals, 'o-')
228 self.n_axes.grid(True)
229 self.n_axes.set_xlabel('ht')
230 self.n_axes.set_ylabel('err')
231 self.n_canvas.draw()
233 def on_test_hy(self):
234 ly_str = unicode(self.edit_LY.text())
235 lz_str = unicode(self.edit_LZ.text())
236 ny_str = unicode(self.edit_dim_y.text())
237 nz_str = unicode(self.edit_dim_z.text())
238 time_str = unicode(self.edit_T.text())
240 M = 600
242 ly = np.float64(ly_str)
243 lz = np.float64(lz_str)
244 ny = int(ny_str)
245 nz = int(nz_str)
246 hy = (ly / ny)
247 hz = (lz / nz)
248 time = np.float64(time_str)
250 ht_exp = min(hy, hz) / (np.sqrt(2) * co.C)
251 ht = normal(ht_exp)
252 ht /= 2
254 x_vals = []
255 y_vals = []
256 hy_step = hy
257 for n in xrange(1, 11):
258 print hy
259 x_vals.append(hy)
260 solver = ExplicitSolver(ny, nz, time, ht=ht)
261 u = solver.solve()
262 for i in xrange(u.shape[0]):
263 for j in xrange(u.shape[1]):
264 u[i, j] -= Exm(i * hy, j * hz, time, M)
265 y_vals.append(np.max(np.abs(u)))
266 hy /= 2
267 ny *= 2
269 line, = self.n_axes.plot(x_vals, y_vals, 'o-')
271 self.n_axes.grid(True)
272 self.n_axes.set_xlabel('ht')
273 self.n_axes.set_ylabel('err')
274 self.n_canvas.draw()
276 def on_test_hz(self):
277 pass
279 def on_grid_change(self):
280 ly_str = unicode(self.edit_LY.text())
281 lz_str = unicode(self.edit_LZ.text())
282 ny_str = unicode(self.edit_dim_y.text())
283 nz_str = unicode(self.edit_dim_z.text())
285 ly = np.float64(ly_str)
286 lz = np.float64(lz_str)
287 ny = int(ny_str)
288 nz = int(nz_str)
289 hy = (ly / ny)
290 hz = (lz / nz)
291 h_exp = min(hy, hz) / (np.sqrt(2) * co.C)
292 h_imp = hy / co.C
293 exp_l = ("%g" % h_exp).split('e')
294 imp_l = ("%g" % h_imp).split('e')
295 ht_exp = '1e' + exp_l[1]
296 ht_imp = str(np.trunc(np.float64(imp_l[0]))) + 'e' + imp_l[1]
297 self.edit_exp_step_t.setText(ht_exp)
298 self.edit_imp_step_t.setText(ht_imp)
300 def clear_axes(self, axes):
301 axes.clear()
302 axes.grid(True)
303 axes.set_xlabel('z')
304 axes.set_ylabel('Ex')
306 def test_graph(self):
307 self.clear_axes(self.z_axes)
308 self.z_canvas.draw()
310 def _parse_a(self):
311 return int(unicode(self.edit_length.text()))
313 def _parse_grid(self):
314 I = int(unicode(self.edit_dim_y.text()))
315 J = int(unicode(self.edit_dim_z.text()))
316 return I, J
318 def _parse_exp(self):
319 s = unicode(self.edit_exp_step_t.text()).strip()
320 if s == '':
321 return None
322 return np.float64(s)
324 def _parse_imp(self):
325 s = unicode(self.edit_imp_step_t.text()).strip()
326 if s == '':
327 return None
328 return np.float64(s)
330 def _parse_args(self):
331 ly, lz, c, lambda_, t = [np.float64(unicode(p.text()).strip()) \
332 for p in [self.edit_LY, self.edit_LZ, self.edit_C, self.edit_LAMBDA, self.edit_T]]
333 return ly, lz, c, lambda_, t
335 def on_scheme_run(self):
336 is_analytic, is_explicit, is_implicit = [g.isChecked() \
337 for g in [self.a_group, self.exp_group, self.imp_group]]
339 if not (is_analytic or is_explicit or is_implicit):
340 return
342 I, J = self._parse_grid()
344 exp_ht, imp_ht = None, None
346 if is_analytic:
347 m = self._parse_a()
348 if is_explicit or is_implicit:
349 exp_ht = self._parse_exp()
350 imp_ht = self._parse_imp()
352 ly, lz, c, lambda_, t = self._parse_args()
354 if exp_ht is not None:
355 if not co.test_exp_stable(ly/I, lz/J, exp_ht):
356 warn = QMessageBox.warning(
357 self,
358 u'Явная схема',
359 u'С такими параметрами система может быть неустойчива!<br />Вы уверены, что хотите продолжить?',
360 QMessageBox.Yes | QMessageBox.No)
362 if imp_ht is not None:
363 if not co.test_imp_stable(ly/I, imp_ht):
364 warn = QMessageBox.warning(
365 self,
366 u'Неявная схема',
367 u'С такими параметрами система может быть неустойчива!<br />Вы уверены, что хотите продолжить?',
368 QMessageBox.Yes | QMessageBox.No)
371 self.data.z = np.linspace(0, lz, J + 1)
373 self.z_axes.clear()
374 lines = []
375 legs = []
376 if is_analytic:
377 setParameters(ly, lz, c, _lambda)
378 self.data.E_a = [Exm(ly / 2, z_, t, m) for z_ in self.data.z]
379 line, = self.z_axes.plot(self.data.z, self.data.E_a, color='red')
380 lines.append(line)
381 legs.append('Analytical')
382 if is_explicit:
383 solver = ExplicitSolver(I, J, t, exp_ht)
384 u = solver.solve()
385 self.data.E_exp = u[u.shape[0] / 2, :]
386 line, = self.z_axes.plot(self.data.z, self.data.E_exp, color='blue')
387 lines.append(line)
388 legs.append('Explicit scheme')
389 if is_implicit:
390 solver = ImplicitSolver(I, J, t, imp_ht)
391 u = solver.solve()
392 self.data.E_imp = u[u.shape[0] / 2, :]
393 line, = self.z_axes.plot(self.data.z, self.data.E_imp, color='green')
394 lines.append(line)
395 legs.append('Implicit scheme')
396 self.z_axes.grid(True)
397 self.z_axes.set_xlim(0, max(self.data.z))
398 emax = max(self.data.E_a)
399 self.z_axes.set_ylim(-1.5 * emax, 1.5 * emax)
400 self.z_axes.set_xlabel('z')
401 self.z_axes.set_ylabel('Ex')
402 self.z_axes.legend(lines, legs)
403 self.z_canvas.draw()
405 # def on_deviation_run(self):
406 # flags = (is_analytic, is_explicit, is_implicit) = [g.isChecked() \
407 # for g in [self.a_group, self.exp_group, self.imp_group]]
409 # if not (is_analytic or is_explicit or is_implicit):
410 # return
411 # if len(filter(None, flags)) < 2:
412 # return
414 # self.d_axes.clear()
415 # lines = []
416 # legs = []
417 # if (is_analytic and is_explicit):
418 # self.data.a_exp_dev = np.abs(self.data.E_a - self.data.E_exp)
419 # line, = self.d_axes.plot(self.data.z, self.data.a_exp_dev, color='blue')
420 # lines.append(line)
421 # legs.append('Analytical and explicit scheme')
422 # if (is_analytic and is_implicit):
423 # self.data.a_imp_dev = np.abs(self.data.E_a - self.data.E_imp)
424 # line, = self.d_axes.plot(self.data.z, self.data.a_imp_dev, color='green')
425 # lines.append(line)
426 # legs.append('Analytical and implicit scheme')
427 # if (is_explicit and is_implicit):
428 # self.data.exp_imp = np.abs(self.data.E_exp - self.data.E_imp)
429 # line, = self.d_axes.plot(self.data.z, self.data.exp_imp, color='black')
430 # lines.append(line)
431 # legs.append('Explicit and implicit schemes')
432 # self.d_axes.grid(True)
433 # self.d_axes.set_xlabel('z')
434 # self.d_axes.set_ylabel('e')
435 # emax = max(self.data.E_a)
436 # zmax = self.data.z[-1]
437 # self.d_axes.set_ylim(0, 2*emax)
438 # self.d_axes.set_xlim(0, zmax)
439 # self.d_axes.legend(lines, legs)
440 # self.d_canvas.draw()
443 class SolverWorker(QThread):
445 def __init__(self, parent=None):
446 QThread.__init__(self, parent)
447 self.exiting = False
448 self.u = None
450 def __del__(self):
451 self.exiting = True
452 self.wait()
454 def work(self, solver):
455 self.solver = solver()
456 self.start()
458 def run(self):
459 u = solver.solve()