3 # Политика префиксов в именах
6 # QPushButton - button_
11 from PyQt4
.QtCore
import *
12 from PyQt4
.QtGui
import *
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
21 from grid
import ExplicitSolver
, ImplicitSolver
, norm
23 from waves
import Exm
, setParameters
25 from third
import Exm
, setParameters
29 ABOUT_IMAGE
= 'about.jpg'
33 ABOUT_TEXT
= u
'Курсовую работу выполнили:<br />студенты группы 6407<br /><b>Каранашев Мухамед</b><br /><b>Гайдель Андрей</b>'
34 ABOUT_TEXT_WIDTH
= 300
38 return ('%g' % x
).split('e')
41 return np
.float64('1e' + split_number(x
)[1])
46 class AppForm(QMainWindow
):
48 def __init__(self
, parent
=None):
49 QMainWindow
.__init
__(self
, parent
)
50 self
.setWindowTitle(u
'Курсовой проект')
53 self
.data
.counter_sol
= self
.data
.counter_res
= 1
55 self
.create_main_frame()
56 self
.setWindowState(Qt
.WindowMaximized
)
62 def create_main_frame(self
):
63 self
.main_frame
= QWidget()
64 self
.init_work_frame()
65 self
.init_param_frame()
67 self
.splitter
= QSplitter()
68 self
.splitter
.addWidget(self
.param_frame
)
70 self
.splitter
.addWidget(self
.work_frame
)
71 self
.main_layout
= QGridLayout(self
.main_frame
)
72 # self.main_layout.addWidget(self.param_frame, 0, 0)
73 # self.main_layout.addWidget(self.work_frame, 0, 1)
74 self
.main_layout
.addWidget(self
.splitter
)
75 self
.setCentralWidget(self
.main_frame
)
77 def init_param_frame(self
):
78 self
.param_frame
= QWidget()
79 param_group
= QGroupBox(u
"&Параметры")
80 param_layout
= QGridLayout(self
.param_frame
)
81 param_layout
.addWidget(param_group
, 0, 0)
83 self
.edit_LY
= QLineEdit(str(co
.LY
))
84 self
.edit_LY
.setMinimumWidth(40)
85 self
.edit_LZ
= QLineEdit(str(co
.LZ
))
86 self
.edit_LZ
.setMinimumWidth(40)
87 self
.edit_C
= QLineEdit(str(co
.C
))
88 self
.edit_C
.setMinimumWidth(40)
89 self
.edit_LAMBDA
= QLineEdit(str(co
.LAMBDA
))
90 self
.edit_LAMBDA
.setMinimumWidth(40)
91 self
.edit_T
= QLineEdit('1e-14')
92 self
.edit_dim_y
= QLineEdit(str(50))
93 self
.edit_dim_z
= QLineEdit(str(50))
95 pg_layout
= QFormLayout(param_group
)
96 pg_layout
.addRow(u
'Ширина ly', self
.edit_LY
)
97 pg_layout
.addRow(u
'Высота lz', self
.edit_LZ
)
98 pg_layout
.addRow(u
'Скорость C', self
.edit_C
)
99 pg_layout
.addRow(u
'Волна λ', self
.edit_LAMBDA
)
100 pg_layout
.addRow(u
'Момент T', self
.edit_T
)
101 pg_layout
.addRow(u
'Размер по y (I)', self
.edit_dim_y
)
102 pg_layout
.addRow(u
'Размер по z (J)', self
.edit_dim_z
)
103 self
.param_frame
.setMaximumWidth(250)
105 self
.connect(self
.edit_LY
, SIGNAL("returnPressed()"), self
.on_grid_change
)
106 self
.connect(self
.edit_LZ
, SIGNAL("returnPressed()"), self
.on_grid_change
)
107 self
.connect(self
.edit_dim_y
, SIGNAL("returnPressed()"), self
.on_grid_change
)
108 self
.connect(self
.edit_dim_z
, SIGNAL("returnPressed()"), self
.on_grid_change
)
111 bu_layout
= QVBoxLayout(bu_group
)
112 save_solution
= QPushButton("Save solution")
113 save_research
= QPushButton("Save research")
114 self
.connect(save_solution
, SIGNAL("clicked()"), self
.save_solution
)
115 self
.connect(save_research
, SIGNAL("clicked()"), self
.save_research
)
116 bu_layout
.addWidget(save_solution
)
117 bu_layout
.addWidget(save_research
)
118 param_layout
.addWidget(bu_group
, 3, 0)
120 def save_solution(self
):
121 base
= os
.path
.join('graph', 'solution', str(self
.data
.counter_sol
))
122 self
.z_fig
.savefig(base
+ '.png')
123 print 'saved', base
+ '.png'
124 self
.z_fig
.savefig(base
+ '.eps')
125 print 'saved', base
+ '.eps'
126 self
.data
.counter_sol
+= 1
128 def save_research(self
):
129 base
= os
.path
.join('graph', 'research', str(self
.data
.counter_res
))
130 self
.n_fig
.savefig(path
+ '.png')
131 print 'saved', base
+ '.png'
132 self
.n_fig
.savegif(path
+ '.eps')
133 print 'saved', base
+ '.eps'
134 self
.data
.counter_res
+= 1
136 def _make_analytic(self
):
137 a_group
= QGroupBox(u
"Аналитическое решение")
138 a_group
.setCheckable(True)
139 a_layout
= QFormLayout(a_group
)
141 self
.edit_length
= QLineEdit(str(500))
142 a_layout
.addRow(u
"Элементов ряда", self
.edit_length
)
143 self
.edit_length
.setMaximumWidth(100)
147 def _make_explicit(self
):
148 e_group
= QGroupBox(u
"Явная схема")
149 e_group
.setCheckable(True)
150 e_group
.setChecked(False)
151 e_layout
= QFormLayout(e_group
)
152 self
.edit_exp_step_t
= QLineEdit()
153 e_layout
.addRow(u
"Шаг по t", self
.edit_exp_step_t
)
157 def _make_implicit(self
):
158 i_group
= QGroupBox(u
"Неявная схема")
159 i_group
.setCheckable(True)
160 i_group
.setChecked(False)
161 i_layout
= QFormLayout(i_group
)
162 self
.edit_imp_step_t
= QLineEdit()
163 i_layout
.addRow(u
"Шаг по t", self
.edit_imp_step_t
)
167 def _make_t_norm(self
):
168 t_group
= QGroupBox(u
'Ось T')
169 t_layout
= QFormLayout(t_group
)
171 self
.edit_k_start
= QLineEdit(str(10))
172 self
.edit_k_end
= QLineEdit(str(100))
173 self
.edit_k_step
= QLineEdit(str(10))
174 self
.edit_k_M
= QLineEdit(str(600))
175 self
.t_norm_button
= QPushButton(u
'Пуск')
176 self
.connect(self
.t_norm_button
, SIGNAL("clicked()"), self
.on_test_ht
)
177 t_layout
.addRow(u
'Мин. узлов', self
.edit_k_start
)
178 t_layout
.addRow(u
'Макс. узлов', self
.edit_k_end
)
179 t_layout
.addRow(u
'Шаг', self
.edit_k_step
)
180 t_layout
.addRow(u
'Ряд', self
.edit_k_M
)
181 t_layout
.addRow(self
.t_norm_button
)
186 def _make_y_norm(self
):
187 y_group
= QGroupBox(u
"Ось Y")
188 y_layout
= QFormLayout(y_group
)
190 self
.edit_y_start
= QLineEdit('10')
191 self
.edit_y_end
= QLineEdit('100')
192 self
.edit_y_step
= QLineEdit('10')
193 self
.edit_y_ht
= QLineEdit('1e-16')
194 self
.edit_y_M
= QLineEdit(str(600))
195 self
.y_norm_button
= QPushButton(u
'Пуск')
196 self
.connect(self
.y_norm_button
, SIGNAL("clicked()"), self
.on_test_hy
)
197 y_layout
.addRow(u
'Мин. узлов', self
.edit_y_start
)
198 y_layout
.addRow(u
'Макс. узлов', self
.edit_y_end
)
199 y_layout
.addRow(u
'Шаг', self
.edit_y_step
)
200 y_layout
.addRow(u
'ht', self
.edit_y_ht
)
201 y_layout
.addRow(u
'Ряд', self
.edit_y_M
)
202 y_layout
.addRow(self
.y_norm_button
)
206 def _make_z_norm(self
):
207 z_group
= QGroupBox(u
"Ось Z")
208 z_layout
= QFormLayout(z_group
)
210 self
.edit_z_start
= QLineEdit('10')
211 self
.edit_z_end
= QLineEdit('100')
212 self
.edit_z_step
= QLineEdit('10')
213 self
.edit_z_ht
= QLineEdit('1e-16')
214 self
.edit_z_M
= QLineEdit(str(600))
215 self
.z_norm_button
= QPushButton(u
'Пуск')
216 self
.connect(self
.z_norm_button
, SIGNAL("clicked()"), self
.on_test_hz
)
217 z_layout
.addRow(u
'Мин. узлов', self
.edit_z_start
)
218 z_layout
.addRow(u
'Макс. узлов', self
.edit_z_end
)
219 z_layout
.addRow(u
'Шаг', self
.edit_z_step
)
220 z_layout
.addRow(u
'ht', self
.edit_z_ht
)
221 z_layout
.addRow(u
'Ряд', self
.edit_z_M
)
222 z_layout
.addRow(self
.z_norm_button
)
226 def _set_solver(self
, t
):
228 self
.Solver
= ExplicitSolver
230 self
.Solver
= ImplicitSolver
233 def _make_norm_frame(self
):
234 self
.norm_frame
= QWidget()
235 self
.n_fig
= Figure((5.0, 5.0), dpi
= self
.dpi
)
236 self
.n_canvas
= FigureCanvas(self
.n_fig
)
237 self
.n_canvas
.setParent(self
.main_frame
)
238 self
.n_axes
= self
.n_fig
.add_axes([.1, .1, .8, .8])
239 n_layout
= QGridLayout(self
.norm_frame
)
240 n_layout
.addWidget(self
.n_canvas
, 0, 0)
241 n_toolbar
= NavigationToolbar(self
.n_canvas
, self
.norm_frame
)
242 n_layout
.addWidget(n_toolbar
, 1, 0)
244 scheme_type_frame
= QWidget()
245 scheme_type_layout
= QGridLayout(scheme_type_frame
)
246 self
.exp_radio_button
= QRadioButton(u
'Явная схема', scheme_type_frame
)
247 self
.imp_radio_button
= QRadioButton(u
'Неявная схема', scheme_type_frame
)
248 self
.connect(self
.exp_radio_button
, SIGNAL("toggled(bool)"), self
._set
_solver
)
249 self
.exp_radio_button
.setChecked(True)
250 scheme_type_layout
.addWidget(self
.exp_radio_button
, 0, 0)
251 scheme_type_layout
.addWidget(self
.imp_radio_button
, 0, 1)
253 n_layout
.addWidget(scheme_type_frame
, 2, 0)
255 n_param_frame
= QWidget()
256 n_param_layout
= QGridLayout(n_param_frame
)
257 n_param_layout
.addWidget(self
._make
_t
_norm
(), 0, 0)
258 n_param_layout
.addWidget(self
._make
_y
_norm
(), 0, 1)
259 n_param_layout
.addWidget(self
._make
_z
_norm
(), 0, 2)
260 n_layout
.addWidget(n_param_frame
, 3, 0)
262 def _make_about_frame(self
):
263 about_frame
= QWidget()
264 lay
= QHBoxLayout(about_frame
)
265 about_image
= QImage(ABOUT_IMAGE
)
266 image_label
= QLabel()
267 image_label
.setPixmap(QPixmap
.fromImage(about_image
))
268 about_label
= QLabel(ABOUT_TEXT
)
269 about_label
.setMinimumWidth(ABOUT_TEXT_WIDTH
)
270 lay
.addWidget(image_label
)
271 lay
.addWidget(about_label
)
275 def init_work_frame(self
):
276 self
.work_frame
= QTabWidget()
279 self
.z_fig
= Figure((5.0, 5.0), dpi
= self
.dpi
)
280 self
.z_canvas
= FigureCanvas(self
.z_fig
)
281 self
.z_canvas
.setParent(self
.main_frame
)
282 self
.z_axes
= self
.z_fig
.add_axes([.1, .1, .8, .8])
284 self
.graph_frame
= QWidget()
285 graph_layout
= QGridLayout(self
.graph_frame
)
286 graph_layout
.addWidget(self
.z_canvas
, 0, 0, 1, 1)
288 self
.mpl_toolbar
= NavigationToolbar(self
.z_canvas
, self
.graph_frame
)
289 # self.mpl_toolbar.setOrientation(Qt.Vertical)
290 graph_layout
.addWidget(self
.mpl_toolbar
, 1, 0, 1, 1)
292 scheme_frame
= QWidget()
293 scheme_layout
= QGridLayout(scheme_frame
)
294 self
.a_group
= self
._make
_analytic
()
295 self
.exp_group
= self
._make
_explicit
()
296 self
.imp_group
= self
._make
_implicit
()
297 scheme_layout
.addWidget(self
.a_group
, 0, 0, 1, 1)
298 scheme_layout
.addWidget(self
.exp_group
, 0, 1, 1, 1)
299 scheme_layout
.addWidget(self
.imp_group
, 0, 2, 1, 1)
301 self
.button_scheme_run
= QPushButton(u
'Пуск')
302 self
.connect(self
.button_scheme_run
, SIGNAL("clicked()"), self
.on_scheme_run
)
303 self
.button_scheme_run
.setFocus(Qt
.ActiveWindowFocusReason
)
305 graph_layout
.addWidget(scheme_frame
, 2, 0)
306 graph_layout
.addWidget(self
.button_scheme_run
, 3, 0)
308 self
._make
_norm
_frame
()
310 self
.about_frame
= self
._make
_about
_frame
()
312 self
.work_frame
.addTab(self
.graph_frame
, u
"&Разностная схема")
313 self
.work_frame
.addTab(self
.norm_frame
, u
"&Исследование аппроксимации")
314 self
.work_frame
.addTab(self
.about_frame
, u
"&О программе")
316 def on_test_ht(self
):
320 ly
, lz
, c
, lambda_
, t
= self
._parse
_args
()
321 I
, J
= self
._parse
_grid
()
322 k_min
= int(str(self
.edit_k_start
.text()))
323 k_max
= int(str(self
.edit_k_end
.text()))
324 k_step
= int(str(self
.edit_k_step
.text()))
325 M
= int(str(self
.edit_k_M
.text()))
327 QMessageBox
.critical(
330 u
'Параметры введены в неверном формате.<br />Пожалуйста, исправьте их и повторите.')
338 if not co
.test_exp_stable(ly
/I
, lz
/J
, t
/ k_min
):
339 warn
= QMessageBox
.warning(
342 u
'С такими параметрами система может быть неустойчива!<br />Вы уверены, что хотите продолжить?',
343 QMessageBox
.Yes | QMessageBox
.No
)
344 if (warn
== QMessageBox
.No
):
347 for k_cur
in xrange(k_min
, k_max
+ 1, k_step
):
351 solver
= self
.Solver(I
, J
, t
, ht
, ly
=ly
, lz
=lz
, lambda_
=lambda_
, C
=c
)
353 for i
in xrange(u
.shape
[0]):
354 for j
in xrange(u
.shape
[1]):
355 u
[i
, j
] -= Exm(i
* hy
, j
* hz
, t
, M
)
356 y_vals
.append(np
.max(np
.abs(u
)))
359 line
, = self
.n_axes
.plot(x_vals
, y_vals
, '.-')
361 self
.n_axes
.grid(True)
362 self
.n_axes
.set_xlabel(u
'ht')
363 self
.n_axes
.set_ylabel(u
'err')
366 def on_test_hy(self
):
368 ly
, lz
, c
, lambda_
, t
= self
._parse
_args
()
369 I
, J
= self
._parse
_grid
()
370 i_min
= int(str(self
.edit_y_start
.text()))
371 i_max
= int(str(self
.edit_y_end
.text()))
372 i_step
= int(str(self
.edit_y_step
.text()))
373 ht
= np
.float64(str(self
.edit_y_ht
.text()))
374 M
= int(str(self
.edit_y_M
.text()))
376 QMessageBox
.critical(
379 u
'Параметры введены в неверном формате.<br />Пожалуйста, исправьте их и повторите.')
386 if not co
.test_exp_stable(ly
/i_max
, lz
/J
, ht
):
387 warn
= QMessageBox
.warning(
390 u
'С такими параметрами система может быть неустойчива!<br />Вы уверены, что хотите продолжить?',
391 QMessageBox
.Yes | QMessageBox
.No
)
392 if (warn
== QMessageBox
.No
):
395 for i_cur
in xrange(i_min
, i_max
+ 1, i_step
):
399 solver
= self
.Solver(i_cur
, J
, t
, ht
, ly
=ly
, lz
=lz
, lambda_
=lambda_
, C
=c
)
401 for i
in xrange(u
.shape
[0]):
402 for j
in xrange(u
.shape
[1]):
403 u
[i
, j
] -= Exm(i
* hy
, j
* hz
, t
, M
)
404 y_vals
.append(np
.max(np
.abs(u
)))
407 line
, = self
.n_axes
.plot(x_vals
, y_vals
, '.-')
409 self
.n_axes
.grid(True)
410 self
.n_axes
.set_xlabel(u
'hy')
411 self
.n_axes
.set_ylabel(u
'err')
414 def on_test_hz(self
):
416 ly
, lz
, c
, lambda_
, t
= self
._parse
_args
()
417 I
, J
= self
._parse
_grid
()
418 j_min
= int(str(self
.edit_z_start
.text()))
419 j_max
= int(str(self
.edit_z_end
.text()))
420 j_step
= int(str(self
.edit_z_step
.text()))
421 ht
= np
.float64(str(self
.edit_z_ht
.text()))
422 M
= int(str(self
.edit_z_M
.text()))
424 QMessageBox
.critical(
427 u
'Параметры введены в неверном формате.<br />Пожалуйста, исправьте их и повторите.')
434 if not co
.test_exp_stable(ly
/I
, lz
/j_max
, ht
):
435 warn
= QMessageBox
.warning(
438 u
'С такими параметрами система может быть неустойчива!<br />Вы уверены, что хотите продолжить?',
439 QMessageBox
.Yes | QMessageBox
.No
)
440 if (warn
== QMessageBox
.No
):
443 for j_cur
in xrange(j_min
, j_max
+ 1, j_step
):
447 solver
= self
.Solver(I
, j_cur
, t
, ht
, ly
=ly
, lz
=lz
, lambda_
=lambda_
, C
=c
)
449 for i
in xrange(u
.shape
[0]):
450 for j
in xrange(u
.shape
[1]):
451 u
[i
, j
] -= Exm(i
* hy
, j
* hz
, t
, M
)
452 y_vals
.append(np
.max(np
.abs(u
)))
455 line
, = self
.n_axes
.plot(x_vals
, y_vals
, '.-')
457 self
.n_axes
.grid(True)
458 self
.n_axes
.set_xlabel(u
'hz')
459 self
.n_axes
.set_ylabel(u
'err')
462 def on_grid_change(self
):
463 ly_str
= unicode(self
.edit_LY
.text())
464 lz_str
= unicode(self
.edit_LZ
.text())
465 ny_str
= unicode(self
.edit_dim_y
.text())
466 nz_str
= unicode(self
.edit_dim_z
.text())
468 ly
= np
.float64(ly_str
)
469 lz
= np
.float64(lz_str
)
474 h_exp
= min(hy
, hz
) / (np
.sqrt(2) * co
.C
)
476 exp_l
= ("%g" % h_exp
).split('e')
477 imp_l
= ("%g" % h_imp
).split('e')
478 ht_exp
= '1e' + exp_l
[1]
479 ht_imp
= str(np
.trunc(np
.float64(imp_l
[0]))) + 'e' + imp_l
[1]
480 self
.edit_exp_step_t
.setText(ht_exp
)
481 self
.edit_imp_step_t
.setText(ht_imp
)
483 def clear_axes(self
, axes
):
487 axes
.set_ylabel('Ex')
489 def test_graph(self
):
490 self
.clear_axes(self
.z_axes
)
494 return int(unicode(self
.edit_length
.text()))
496 def _parse_grid(self
):
497 I
= int(unicode(self
.edit_dim_y
.text()))
498 J
= int(unicode(self
.edit_dim_z
.text()))
501 def _parse_exp(self
):
502 s
= unicode(self
.edit_exp_step_t
.text()).strip()
507 def _parse_imp(self
):
508 s
= unicode(self
.edit_imp_step_t
.text()).strip()
513 def _parse_args(self
):
514 ly
, lz
, c
, lambda_
, t
= [np
.float64(unicode(p
.text()).strip()) \
515 for p
in [self
.edit_LY
, self
.edit_LZ
, self
.edit_C
, self
.edit_LAMBDA
, self
.edit_T
]]
516 return ly
, lz
, c
, lambda_
, t
518 def on_scheme_run(self
):
519 is_analytic
, is_explicit
, is_implicit
= [g
.isChecked() \
520 for g
in [self
.a_group
, self
.exp_group
, self
.imp_group
]]
522 if not (is_analytic
or is_explicit
or is_implicit
):
533 exp_ht
, imp_ht
= None, None
538 if is_explicit
or is_implicit
:
539 exp_ht
= self
._parse
_exp
()
540 imp_ht
= self
._parse
_imp
()
542 QMessageBox
.critical(
545 u
'Параметры введены в неверном формате.<br />Пожалуйста, исправьте их и повторите.')
549 ly
, lz
, c
, lambda_
, t
= self
._parse
_args
()
550 I
, J
= self
._parse
_grid
()
552 QMessageBox
.critical(
555 u
'Параметры введены в неверном формате.<br />Пожалуйста, исправьте их и повторите.')
558 if exp_ht
is not None:
559 if not co
.test_exp_stable(ly
/I
, lz
/J
, exp_ht
):
560 warn
= QMessageBox
.warning(
563 u
'С такими параметрами система может быть неустойчива!<br />Вы уверены, что хотите продолжить?',
564 QMessageBox
.Yes | QMessageBox
.No
)
565 if (warn
== QMessageBox
.No
):
568 if imp_ht
is not None:
569 if not co
.test_imp_stable(ly
/I
, imp_ht
):
570 warn
= QMessageBox
.warning(
573 u
'С такими параметрами система может быть неустойчива!<br />Вы уверены, что хотите продолжить?',
574 QMessageBox
.Yes | QMessageBox
.No
)
575 if (warn
== QMessageBox
.No
):
578 self
.data
.z
= np
.linspace(0, lz
, J
+ 1)
584 setParameters(ly
, lz
, c
, lambda_
)
585 self
.data
.E_a
= [Exm(ly
/ 2, z_
, t
, m
) for z_
in self
.data
.z
]
586 line
, = self
.z_axes
.plot(self
.data
.z
, self
.data
.E_a
, color
='red')
588 legs
.append('Analytical')
590 solver
= ExplicitSolver(I
, J
, t
, exp_ht
, ly
=ly
, lz
=lz
, lambda_
=lambda_
, C
=c
)
592 self
.data
.E_exp
= u
[u
.shape
[0] / 2, :]
593 line
, = self
.z_axes
.plot(self
.data
.z
, self
.data
.E_exp
, color
='blue')
595 legs
.append('Explicit scheme')
597 solver
= ImplicitSolver(I
, J
, t
, imp_ht
, ly
=ly
, lz
=lz
, lambda_
=lambda_
, C
=c
)
599 self
.data
.E_imp
= u
[u
.shape
[0] / 2, :]
600 line
, = self
.z_axes
.plot(self
.data
.z
, self
.data
.E_imp
, color
='green')
602 legs
.append('Implicit scheme')
603 self
.z_axes
.grid(True)
604 self
.z_axes
.set_xlim(0, max(self
.data
.z
))
605 emax
= max(self
.data
.E_a
)
606 self
.z_axes
.set_ylim(-1.5 * emax
, 1.5 * emax
)
607 self
.z_axes
.set_xlabel('z')
608 self
.z_axes
.set_ylabel('Ex')
609 self
.z_axes
.legend(lines
, legs
, loc
='upper center', bbox_to_anchor
=(0.5, 1.13), ncol
=cols
)