프로젝트

일반

사용자정보

통계
| 브랜치(Branch): | 개정판:

hytos / HYTOS / HYTOS / Shapes / EngineeringLoopItem.py @ d694c9e8

이력 | 보기 | 이력해설 | 다운로드 (64.4 KB)

1
# coding: utf-8
2
import os.path
3
import copy
4
import sys
5

    
6
try:
7
    from PyQt5.QtCore import Qt, QPointF, QRectF, pyqtSignal, QObject, QT_VERSION_STR, QRect
8
    from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QBrush, QPen, QTransform, QFont, QColor
9
    from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QFileDialog, QGraphicsItem, QAbstractGraphicsShapeItem, \
10
        QGraphicsTextItem, QGraphicsRectItem
11
except ImportError:
12
    try:
13
        from PyQt4.QtCore import Qt, QRectF, pyqtSignal, QRect, QObject, QT_VERSION_STR
14
        from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QFont, QColor
15
    except ImportError:
16
        raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.")
17

    
18
import math
19
from EngineeringAbstractItem import QEngineeringAbstractItem
20
from AppDocData import *
21

    
22

    
23
class QEngineeringLoopItem(QEngineeringAbstractItem):
24
    """ This is QEngineeringLoopItem class """
25

    
26
    def __init__(self, _items):
27
        """ constructor """
28
        import uuid
29

    
30
        QEngineeringAbstractItem.__init__(self)
31

    
32
        self._UID = None
33
        self._name = None
34
        self.items = _items
35

    
36
        self.units = {}
37
        self.pressures = {}
38
        self.pressure_drops = {}
39
        self.density_elevations = {}
40
        self.extras = {}
41

    
42
        self.total_device_loss = None
43
        self.suction_line_friction_loss = None
44
        self.discharge_line_friction_loss = None
45
        self.line_total_friction_loss = None
46
        self.suction_device_loss = None
47
        self.discharge_device_loss = None
48
        self.total_suction_loss = None
49
        self.total_discharge_loss = None
50

    
51
        self.fill_start = 0
52
        self.fill_end = None
53

    
54
    def __repr__(self):
55
        """ return string represent loop item """
56
        return '{}'.format(self.items)
57

    
58
    @property
59
    def name(self):
60
        return self._name
61

    
62
    @name.setter
63
    def name(self, value):
64
        self._name = value
65

    
66
    def calculate(self):
67
        """ calculate Pressure Drop (Static), Pressure @ Pipe end point of stream line """
68
        from AppDocData import AppDocData
69

    
70
        try:
71
            # (0) Units
72
            self.init_units()
73

    
74
            # (1) 기기들의 del.p, p, el을 넣음
75
            self.p_eq_input()
76

    
77
            # (3) 계산 시작
78
            self.discharge_cal()
79
            if not self.items[1] in self.pressures or not self.pressures[self.items[1]]:
80
                self.suction_cal()
81

    
82
            # Hole Calculation
83
            # cv와 pump가 다 없을때 (Hole Case)
84
            if self.fill_end - self.fill_start > 3:
85
                self.hole_calc(self.fill_start, self.fill_end)
86
                self.loss_input()
87
                self.cv_dp_cal()
88
                self.hole_recalc(self.fill_start, self.fill_end)
89
            else:
90
                self.loss_input()
91

    
92
            name = str(self.items[self.fill_start + 1])[:3]
93
            if name == 'CV_':
94
                self.pressure_drops[self.items[self.fill_start + 1]] = self.pressures[
95
                                                                           self.items[self.fill_start + 1]] - \
96
                                                                       self.pressures[
97
                                                                           self.items[self.fill_start + 2]]
98
            elif name == 'R_P' or name == 'L_P' or name == 'V_P' or name == 'R_K' or name == 'L_K':
99
                self.pressure_drops[self.items[self.fill_start + 1]] = self.pressures[
100
                                                                           self.items[self.fill_start + 2]] - \
101
                                                                       self.pressures[
102
                                                                           self.items[self.fill_start + 1]]
103
        except Exception as ex:
104
            from App import App
105
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
106
                                                           sys.exc_info()[-1].tb_lineno)
107
            App.mainWnd().addMessage.emit(MessageType.Error, message)
108

    
109
    def init_units(self):
110
        try:
111
            app_doc_data = AppDocData.instance()
112
            self.units = [attr[1] for attr in app_doc_data.activeDrawing.attrs if attr[0] == 'Units'][0]
113
        except Exception as ex:
114
            from App import App
115
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
116
                                                           sys.exc_info()[-1].tb_lineno)
117
            App.mainWnd().addMessage.emit(MessageType.Error, message)
118

    
119
    def hole_calc(self, hole_start, hole_end):
120
        try:
121
            self.pressures[self.items[hole_end - 2]] = self.pressures[self.items[hole_end - 1]]
122
            for i in range(hole_end - 3, hole_start + 2, -3):
123
                # (1) density 입력
124
                self.discharge_den(i)
125

    
126
                # (2) static P를 계산
127
                self.discharge_static_cal(i)
128

    
129
                # (3) pressure drop 계산
130
                if self.items[i].data.phase_type == 'Liquid' or self.items[i].data.phase_type == 'Mixed':
131
                    self.pressure_drops[self.items[i]] = self.items[i].data.pressure_drop_friction
132
                    res = self.hole_p_cal(i)
133
                    if res == 0:
134
                        break
135
                elif self.items[i].data.phase_type == 'Vapor':
136
                    self.discharge_vapor_factor_length(i)
137
                    res = self.hole_p_cal(i)
138
                    if res == 0:
139
                        break
140
        except Exception as ex:
141
            from App import App
142
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
143
                                                           sys.exc_info()[-1].tb_lineno)
144
            App.mainWnd().addMessage.emit(MessageType.Error, message)
145

    
146
    def hole_recalc(self, hole_start, hole_end):
147
        try:
148
            self.pressures[self.items[hole_end - 2]] = self.pressures[self.items[hole_end - 1]] + \
149
                                                       self.pressure_drops[self.items[hole_end - 2]]
150
            for i in range(hole_end - 3, hole_start + 2, -3):
151
                # (1) density 입력
152
                self.discharge_den(i)
153

    
154
                # (2) static P를 계산
155
                self.discharge_static_cal(i)
156

    
157
                # (3) pressure drop 계산
158
                if self.items[i].data.phase_type == 'Liquid' or self.items[i].data.phase_type == 'Mixed':
159
                    self.pressure_drops[self.items[i]] = self.items[i].data.pressure_drop_friction
160
                    res = self.hole_p_cal(i)
161
                    if res == 0:
162
                        break
163
                elif self.items[i].phase_type == 'Vapor':
164
                    self.discharge_vapor_factor_length(i)
165
                    res = self.hole_p_cal(i)
166
                    if res == 0:
167
                        break
168
        except Exception as ex:
169
            from App import App
170
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
171
                                                           sys.exc_info()[-1].tb_lineno)
172
            App.mainWnd().addMessage.emit(MessageType.Error, message)
173

    
174
    def get_control_valve_equation(self):
175
        app_doc_data = AppDocData.instance()
176
        equation = app_doc_data.getConfigs('Control Valve', 'Equation')
177

    
178
        if len(equation) == 1:
179
            return equation[0].value
180
        else:
181
            return 'bd'
182

    
183
    def cv_dp_cal(self):
184
        try:
185
            acv = 0
186
            for i in range(2, len(self.items) - 3, 3):
187
                if not self.items[i] in self.pressure_drops and str(self.items[i])[:3] == 'CV_':
188
                    acv = i
189
                    break
190

    
191
            if acv:
192
                pf = (self.total_device_loss if self.total_device_loss else 0) + \
193
                     (self.line_total_friction_loss if self.line_total_friction_loss else 0)
194
                method = self.get_control_valve_equation()
195
                if method == 'bd':
196
                    self.bd_cal(pf, acv)
197
                elif method == 'lummus':
198
                    pass
199
                elif method == 'mixed':
200
                    pass
201
                elif method == 'aramco':
202
                    pass
203
                else:
204
                    pass
205
        except Exception as ex:
206
            from App import App
207
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
208
                                                           sys.exc_info()[-1].tb_lineno)
209
            App.mainWnd().addMessage.emit(MessageType.Error, message)
210

    
211
    def bd_cal(self, pf, acv):
212
        from AppDocData import AppDocData
213

    
214
        try:
215
            bdcvdp = [None, None, None]
216

    
217
            bdcvdp[0] = ((1.1135 * (
218
                    (self.extras[self.items[acv]] if self.extras[self.items[acv]] else 0) / 100 + 1)) ** 2 - 1) * pf
219
            bdcvdp[1] = pf / 3
220

    
221
            pressure_unit = self.units['Pressure']
222
            if pressure_unit == 'kg/cm2':
223
                bdcvdp[2] = 0.7
224
            elif pressure_unit == 'psi':
225
                bdcvdp[2] = 0.7 / 1.033 * 14.7
226
            elif pressure_unit == 'bar':
227
                bdcvdp[2] = 0.7 / 1.033 * 1.013
228
            elif pressure_unit == 'mmHg':
229
                bdcvdp[2] = 0.7 / 1.033 * 760
230
            elif pressure_unit == 'kPa':
231
                bdcvdp[2] = 0.7 / 1.033 * 101.325
232
            elif pressure_unit == 'MPa':
233
                bdcvdp[2] = 0.7 / 1.033 * 0.101325
234

    
235
            max_dp = max(bdcvdp[0], bdcvdp[1])
236
            if max_dp < bdcvdp[2]:
237
                max_dp = bdcvdp[2]
238

    
239
            self.pressure_drops[self.items[acv]] = max_dp
240
        except Exception as ex:
241
            from App import App
242
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
243
                                                           sys.exc_info()[-1].tb_lineno)
244
            App.mainWnd().addMessage.emit(MessageType.Error, message)
245

    
246
    def final_loss_input(self):
247
        pass
248

    
249
    def loss_input(self):
250
        try:
251
            hole_start, hole_end = self.fill_start, self.fill_end
252

    
253
            line_loss = 0
254
            # 라인(suc)
255
            for i in range(1, hole_start + 1, 3):
256
                line_loss = line_loss + self.pressure_drops[self.items[i]]
257
            self.suction_line_friction_loss = line_loss
258

    
259
            line_loss = 0
260
            for i in range(len(self.items) - 2, hole_start + 2, -3):
261
                if i == 3:
262
                    break
263
                if self.items[i] in self.pressure_drops and self.pressure_drops[self.items[i]]:
264
                    line_loss += self.pressure_drops[self.items[i]]
265
            self.discharge_line_friction_loss = line_loss
266

    
267
            line_loss = 0
268
            self.line_total_friction_loss = self.suction_line_friction_loss + self.discharge_line_friction_loss
269

    
270
            # 기기(suc)
271
            dev_loss = 0
272
            for i in range(2, hole_start - 1, 3):
273
                name = str(self.items[i])[:3]
274
                if name == 'R_P' or name == 'L_P' or name == 'V_P' or name == 'R_K' or name == 'L_K' or name == 'CV_':
275
                    pass
276
                else:
277
                    dev_loss += self.pressure_drops[self.items[i]]
278
            self.suction_device_loss = dev_loss
279

    
280
            # 기기(dis)
281
            dev_loss = 0
282
            for i in range(len(self.items) - 4, hole_start + 3, -3):
283
                name = str(self.items[i])[:3]
284
                if name == 'R_P' or name == 'L_P' or name == 'V_P' or name == 'R_K' or name == 'L_K' or name == 'CV_':
285
                    pass
286
                else:
287
                    dev_loss += self.pressure_drops[self.items[i]] if self.items[i] in self.pressure_drops else 0
288
            self.discharge_device_loss = dev_loss
289

    
290
            self.total_device_loss = self.discharge_device_loss + self.suction_device_loss
291

    
292
            # 스태틱(suc)
293
            stat_loss = 0
294
            for i in range(0, hole_start - 3, 3):
295
                stat_loss += self.pressure_drops[self.items[i]]
296
            self.total_suction_loss = stat_loss
297

    
298
            # 스태틱(dis)
299
            stat_loss = 0
300
            for i in range(len(self.items) - 3, hole_start, -3):
301
                stat_loss += self.pressure_drops[self.items[i]]
302
            self.total_discharge_loss = stat_loss
303
        except Exception as ex:
304
            from App import App
305
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
306
                                                           sys.exc_info()[-1].tb_lineno)
307
            App.mainWnd().addMessage.emit(MessageType.Error, message)
308

    
309
    def discharge_cal(self, calc_cnt=1):
310
        try:
311
            if len(self.items) == 3:
312
                # 장치 2개와 Line 1개로 구성된 경우
313
                self.discharge_den(1)  # (1) density 입력
314
                self.discharge_static_cal(1)  # (2) static P를 계산
315

    
316
                # (3) pressure drop 계산
317
                # liquid 인 경우 stream 시트로부터 del.P를 입력해줌.
318
                # vapor인 경우 압력강하를 계산해주고 넣어주는 모듈
319
                if self.items[1].data.phase_type == 'Liquid' or self.items[1].data.phase_type == 'Mixed':
320
                    self.pressure_drops[self.items[1]] = self.items[1].data.pressure_drop_friction
321
                    self.discharge_p_cal(1, calc_cnt)
322

    
323
                elif self.items[1].data.phase_type == 'Vapor':
324
                    self.discharge_vapor_factor_length(1)
325
                    self.discharge_p_cal(1, calc_cnt)
326

    
327
                self.fill_end = 3
328
            else:
329
                for i in range(len(self.items) - 2, 1, -3):  # backward
330
                    self.discharge_den(i)  # (1) density 입력
331
                    self.discharge_static_cal(i)  # (2) static P를 계산
332

    
333
                    # (3) pressure drop 계산
334
                    # liquid 인 경우 stream 시트로부터 del.P를 입력해줌.
335
                    # vapor인 경우 압력강하를 계산해주고 넣어주는 모듈
336
                    if self.items[i].data.phase_type == 'Liquid' or self.items[i].data.phase_type == 'Mixed':
337
                        self.pressure_drops[self.items[i]] = self.items[i].data.pressure_drop_friction
338
                        asd = self.discharge_p_cal(i, calc_cnt)
339
                        if asd == 0:
340
                            break
341
                    elif self.items[i].data.phase_type == 'Vapor':
342
                        self.discharge_vapor_factor_length(i)
343
                        asd = self.discharge_p_cal(i, calc_cnt)
344
                        if asd == 0:
345
                            break
346

    
347
                self.fill_end = i
348
        except Exception as ex:
349
            from App import App
350
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
351
                                                           sys.exc_info()[-1].tb_lineno)
352
            App.mainWnd().addMessage.emit(MessageType.Error, message)
353

    
354
    def discharge_vapor_factor_length(self, i):
355
        try:
356
            # '입력된 vapor의 압력과 밀도를 가지고 끊어서 계산하는 factor를 적용했을때 length가 얼마나 나오는지 판별하는 것.
357

    
358
            # pipe dia 가져오기
359
            ida = self.items[i].data.inside_pipe_size
360
            pipe_diameter_unit = self.units['Pipe_Diameter']
361
            if pipe_diameter_unit == 'in':
362
                ida = ida * 0.0254
363
            elif pipe_diameter_unit == 'mm':
364
                ida = ida / 1000
365

    
366
            # 'mass 가져오기 기준 kg/h
367
            mass = self.items[i].data.flowrate_mass
368
            flowrate_mass_unit = self.units['Flowrate_Mass']
369
            if flowrate_mass_unit == 'kg/h':
370
                mass = mass
371
            elif flowrate_mass_unit == 'g/min':
372
                mass = mass * 60 / 1000
373
            elif flowrate_mass_unit == 'lb/h':
374
                mass = mass * 0.453592
375
            elif flowrate_mass_unit == 't/h':
376
                mass = mass * 1000
377

    
378
            # 'g 구하기 (kg/m2/s)
379
            g = mass / 3600 / (3.1415 * ida ** 2 / 4)
380

    
381
            density2 = self.density_elevations[self.items[i]]
382
            # '속도 계산 (m/s)
383
            velocity = 4 * mass / density2 / 3.1415 / ida ** 2 / 3600
384

    
385
            # 'Mach Number 계산
386
            # 'k 가져오기
387
            k = self.items[i].data.specific_heat_ratio
388

    
389
            # temp 가져오기
390
            temp = self.items[i].data.temperature
391
            # 'temp를 kalvin으로 맞추기
392
            temp_unit = self.units['Temperature']
393
            if temp_unit == '':
394
                temp = temp + 273.15
395
            elif temp_unit == '':
396
                temp = (temp - 32) / 1.8 + 273.15
397

    
398
            # 'MW 가져오기
399
            mw = self.items[i].data.molecular_weight
400

    
401
            mach = velocity / ((k * 9.80665 * 847.28 * temp / mw) ** 0.5)
402

    
403
            # '부피유량 계산
404
            volume = mass / density2
405

    
406
            # '현재 volume은 m3/h임. 부피유량 단위에 맞춰 뿌려줌
407
            flowrate_volume_unit = self.units['Flowrate_Volume']
408
            if flowrate_volume_unit == 'm3/h':
409
                self.items[i].data.flowrate_volume = round(volume, 3)
410
            elif flowrate_volume_unit == 'l/min':
411
                self.items[i].data.flowrate_volume = round(volume / 60 * 1000, 3)
412
            elif flowrate_volume_unit == 'ft3/h':
413
                self.items[i].data.flowrate_volume = round(volume * 35.3147, 3)
414
            elif flowrate_volume_unit == 'USgpm':
415
                self.items[i].data.flowrate_volume = round(volume * 4.40287, 3)
416
            elif flowrate_volume_unit == 'BPSD':
417
                self.items[i].data.flowrate_volume = round(volume * 150.955, 3)
418

    
419
            # ' viscosity 유닛 변환 (모두 kg/m.s로 바꿀것임)
420
            viscosity = self.items[i].data.viscosity
421
            viscosity_unit = self.units['Viscosity']
422
            if viscosity_unit == 'kg/m.sec':
423
                viscosity = viscosity
424
            elif viscosity_unit == 'cP':
425
                viscosity = viscosity * 0.001
426
            elif viscosity_unit == 'kg/m.h':
427
                viscosity = viscosity / 3600
428
            elif viscosity_unit == 'lb/ft.s':
429
                viscosity = viscosity * 1.48816
430

    
431
            # density case에 따라 re계산
432
            density_unit = self.units['Density']
433
            if density_unit == 'kg/m3':
434
                reynolds = ida * velocity * density2 / viscosity
435
            elif density_unit == 'lb/ft3':
436
                reynolds = ida * velocity * (density2 * 16.0185) / viscosity
437

    
438
            # roughness를 m로 바꿔줌
439
            rough = self.items[i].data.roughness
440
            roughness_unit = self.units['Roughness']
441
            if roughness_unit == 'm':
442
                rough = rough
443
            elif roughness_unit == 'ft':
444
                rough = rough * 0.3048
445
            elif roughness_unit == 'in':
446
                rough = rough * 0.0254
447
            elif roughness_unit == 'mm':
448
                rough = rough * 0.001
449

    
450
            # ' reynolds수에 따라 Fanning/Chen friction factor 계산
451
            if reynolds <= 2100:
452
                f = 4 * 16 / reynolds
453
            else:
454
                af = math.log(rough / ida / 3.7 + (6.7 / reynolds) ** 0.9) / math.log(10)
455
                f = (-2 * (math.log(rough / 3.7 / ida - 5.02 / reynolds * af) / math.log(10))) ** (-2)
456

    
457
            self.items[i].data.friction_factor = f
458

    
459
            # '속도와 mach 수 입력
460
            velocity_unit = self.units['Velocity']
461
            if velocity_unit == 'm/s':
462
                self.items[i].data.velocity = round(velocity, 3)
463
            elif velocity_unit == 'ft/s':
464
                self.items[i].data.velocity = round(velocity * 3.28084, 3)
465

    
466
            self.items[i].data.reynolds = round(mach, 5)
467

    
468
            Ref_baro = self.get_barometric_pressure()
469
            press2 = self.pressures[self.items[i + 1]]
470

    
471
            # 'pressure를 k.g.a로 맞춤
472
            pressure_unit = self.units['Pressure']
473
            if pressure_unit == 'kg/cm2':
474
                press2 = press2 + Ref_baro
475
            elif pressure_unit == 'psi':
476
                press2 = press2 / 14.7 * 1.033 + Ref_baro
477
            elif pressure_unit == 'atm':
478
                press2 = press2 * 1.033 + Ref_baro
479
            elif pressure_unit == 'bar':
480
                press2 = press2 / 1.013 * 1.033 + Ref_baro
481
            elif pressure_unit == 'mmHg':
482
                press2 = press2 / 760 * 1.033 + Ref_baro
483
            elif pressure_unit == 'kPa':
484
                press2 = press2 / 101.325 * 1.033 + Ref_baro
485
            elif pressure_unit == 'MPa':
486
                press2 = press2 / 0.101325 * 1.033 + Ref_baro
487

    
488
            press1est = press2 / 0.95  # HY_Calc_sht.Cells(2, 1)
489

    
490
            z = self.items[i].data.compress_factor
491
            density1est = press1est * mw / 0.08206 / temp / z / 1.033
492

    
493
            # ' 라인 길이 도출 (m)
494
            estlength = (((press1est ** 2 - press2 ** 2) * mw / g ** 2 / 0.08206 / 1.033 ** 2 / temp / z * 101325) - (
495
                    2 * math.log(density1est / density2))) * ida / f
496

    
497
            # '라인 길이를 유닛에 맞춰서 변환
498
            length_unit = self.units['Length']
499
            if length_unit == 'm':
500
                estlength = estlength
501
            elif length_unit == 'in':
502
                estlength = estlength * 39.3701
503
            elif length_unit == 'ft':
504
                estlength = estlength * 3.28084
505
            elif length_unit == 'yd':
506
                estlength = estlength * 1.09361
507
            elif length_unit == 'mile':
508
                estlength = estlength * 0.000621371
509
            elif length_unit == 'mm':
510
                estlength = estlength * 1000
511

    
512
            equivalent_length = self.get_equivalent_length(i)
513
            if estlength > equivalent_length:
514
                # '주어진 길이를 가지고 압력 강하를 계산하는 모듈이 들어가야함 (safe)
515
                # ' length 여유 있음. 한번에 isothermal 식으로 계산
516
                self.discharge_vap_dp_cal1(i, press2, g, mw, temp, f, z, ida)
517
            else:
518
                # '끊어서 계산하는 모듈이 들어가야함
519
                # 'length 여유 없음. 압력 재계산->밀도 재계산->re, f 재계산->압력 재계산 체계로 가야함
520
                self.discharge_vap_dp_cal2(i, press2, g, mw, temp, f, z, ida)
521

    
522
        except Exception as ex:
523
            from App import App
524
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
525
                                                           sys.exc_info()[-1].tb_lineno)
526
            App.mainWnd().addMessage.emit(MessageType.Error, message)
527

    
528
    def discharge_vap_dp_cal1(self, i, press2, g, mw, temp, f, z, ida):
529
        try:
530
            # 끊은 결과 length가 여유가 있음. 그래서 단순 계산하는 모듈
531
            length = self.get_equivalent_length(i)
532

    
533
            # length를 m로 변환
534
            length_unit = self.units['Length']
535
            if length_unit == 'm':
536
                length = length
537
            elif length_unit == 'in':
538
                length = length * 0.0254
539
            elif length_unit == 'ft':
540
                length = length * 0.3048
541
            elif length_unit == 'yd':
542
                length = length * 0.9144
543
            elif length_unit == 'mile':
544
                length = length * 1609.34
545
            elif length_unit == 'mm':
546
                length = length * 0.001
547

    
548
            # Newton's Rule에 따라
549
            press1 = self.Vap_Discharge_1(press2, g, mw, temp, f, z, ida, length)
550
            pressure_unit = self.units['Pressure']
551
            if pressure_unit == 'kg/cm2':
552
                self.pressure_drops[self.items[i]] = press1 - press2
553
            elif pressure_unit == 'psi':
554
                self.pressure_drops[self.items[i]] = (press1 - press2) / 1.033 * 14.7
555
            elif pressure_unit == 'atm':
556
                self.pressure_drops[self.items[i]] = (press1 - press2) / 1.033
557
            elif pressure_unit == 'bar':
558
                self.pressure_drops[self.items[i]] = (press1 - press2) / 1.033 * 1.033
559
            elif pressure_unit == 'mmHg':
560
                self.pressure_drops[self.items[i]] = (press1 - press2) / 1.033 * 760
561
            elif pressure_unit == 'kPa':
562
                self.pressure_drops[self.items[i]] = (press1 - press2) / 1.033 * 101.325
563
            elif pressure_unit == 'MPa':
564
                self.pressure_drops[self.items[i]] = (press1 - press2) / 10.33 * 0.101325
565

    
566
            self.discharge_p_cal(i)
567

    
568
        except Exception as ex:
569
            from App import App
570
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
571
                                                           sys.exc_info()[-1].tb_lineno)
572
            App.mainWnd().addMessage.emit(MessageType.Error, message)
573

    
574
    def discharge_vap_dp_cal2(self, i, press2, g, mw, temp, f, z, ida):
575
        try:
576
            # ' 끊은 결과 length 여유가 없음, 고로 물성치 (밀도) 를 재계산해주어야 함
577
            # ' 모든 물성들은 배열로 작성해야함
578
            # ' 좌표 추적/설정
579
            self.pressure_drops[self.items[i]] = 0
580
            pass
581
        except Exception as ex:
582
            from App import App
583
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
584
                                                           sys.exc_info()[-1].tb_lineno)
585
            App.mainWnd().addMessage.emit(MessageType.Error, message)
586

    
587
    def Vap_Discharge_1(self, p2, g, mw, temp, f, z, id, L_eq):
588
        try:
589
            R = 0.08206
590

    
591
            Tmp_Const = 101325 * mw / (1.033 ** 2 * (g ** 2) * R * temp * z)
592
            Tmp_Const2 = id / f
593
            pressure_unit = self.units['Pressure']
594
            if pressure_unit == 'kg/cm2':
595
                const_iteration = 5
596
            elif pressure_unit == 'psi':
597
                const_iteration = 75
598
            elif pressure_unit == 'atm':
599
                const_iteration = 5
600
            elif pressure_unit == 'bar':
601
                const_iteration = 5
602
            elif pressure_unit == 'mmHg':
603
                const_iteration = 3800
604
            elif pressure_unit == 'kPa':
605
                const_iteration = 506
606
            elif pressure_unit == 'MPa':
607
                const_iteration = 0.5
608

    
609
            x2 = p2 + const_iteration
610
            delta_x_past = 0
611

    
612
            loop = True
613
            while loop:
614
                X = x2
615
                f_x = (Tmp_Const2 * (Tmp_Const * (X ** 2 - p2 ** 2) - 2 * math.log(X / p2))) - L_eq
616
                df_x = 2 * Tmp_Const2 * (Tmp_Const * X - 1 / X)
617
                x2 = X - (f_x / df_x)
618
                delta_x = x2 - X
619
                if abs(delta_x_past) == abs(delta_x):
620
                    break
621

    
622
                delta_x_past = delta_x
623

    
624
                if delta_x == 0 or x2 < 0:
625
                    loop = False
626

    
627
            return x2
628

    
629
        except Exception as ex:
630
            from App import App
631
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
632
                                                           sys.exc_info()[-1].tb_lineno)
633
            App.mainWnd().addMessage.emit(MessageType.Error, message)
634

    
635
    def get_equivalent_length(self, i):
636
        try:
637
            if self.items[i].data.equivalent_length_input:
638
                return self.items[i].data.equivalent_length_input
639
            else:
640
                return self.items[i].data.equivalent_length_cal
641
        except Exception as ex:
642
            from App import App
643
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
644
                                                           sys.exc_info()[-1].tb_lineno)
645
            App.mainWnd().addMessage.emit(MessageType.Error, message)
646

    
647
    def suction_cal(self, calc_cnt=1):
648
        try:
649
            for i in range(1, len(self.items) - 1, 3):
650
                self.suction_find_line(i)
651
                self.suction_static_cal(i)  # static P를 계산해줌
652

    
653
                # 라인이 liquid 인지 vapor인지 판별
654
                if self.items[i].data.phase_type == 'Liquid' or self.items[i].data.phase_type == 'Mixed':
655
                    # liquid 인 경우 stream 데이타로부터 del.P를 입력해줌.
656
                    self.pressure_drops[self.items[i]] = self.items[i].data.pressure_drop_friction
657
                    res = self.suction_p_cal(i, calc_cnt)
658
                    if res == 0:
659
                        break
660
                elif self.items[i].data.phase_type == 'Vapor':
661
                    # vapor인 경우 압력강하를 계산해주고 넣어주는 모듈
662
                    self.suction_vapor_factor_length(i)
663
                    res = self.suction_p_cal(i, calc_cnt)
664
                    if res == 0:
665
                        break
666

    
667
            self.fill_start = i
668
        except Exception as ex:
669
            from App import App
670
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
671
                                                           sys.exc_info()[-1].tb_lineno)
672
            App.mainWnd().addMessage.emit(MessageType.Error, message)
673

    
674
    def suction_find_line(self, i):
675
        self.extras[self.items[i]] = self.items[i].data.phase_type
676
        if self.items[i].data.phase_type == 'Liquid' or self.items[i].data.phase_type == 'Mixed':
677
            self.density_elevations[self.items[i]] = self.items[i].data.density
678
        elif self.items[i].data.phase_type == 'Vapor':
679
            self.suction_vapor_density(i)
680
        else:
681
            raise ValueError('You have to input the properties of stream <{}>\nCalculation will be terminated !'.format(
682
                self.items[i].data.stream_no))
683

    
684
    def suction_vapor_density(self, i):
685
        try:
686

    
687
            Ref_baro = self.get_barometric_pressure()
688
            press2 = self.pressures[self.items[i - 1]]
689

    
690
            # '여기에 아래의 p를 이용하여 density를 넣는 항을 만들어줘야함 (완료)
691
            # 'pressure를 k.g.a로 맞춤
692
            pressure_unit = self.units['Pressure']
693
            if pressure_unit == 'kg/cm2':
694
                press2 = press2 + Ref_baro
695
            elif pressure_unit == 'psi':
696
                press2 = press2 / 14.7 * 1.033 + Ref_baro
697
            elif pressure_unit == 'atm':
698
                press2 = press2 * 1.033 + Ref_baro
699
            elif pressure_unit == 'bar':
700
                press2 = press2 / 1.013 * 1.033 + Ref_baro
701
            elif pressure_unit == 'mmHg':
702
                press2 = press2 / 760 * 1.033 + Ref_baro
703
            elif pressure_unit == 'kPa':
704
                press2 = press2 / 101.325 * 1.033 + Ref_baro
705
            elif pressure_unit == 'MPa':
706
                press2 = press2 / 0.101325 * 1.033 + Ref_baro
707

    
708
            # temp 가져오기
709
            temp = self.items[i].data.temperature
710
            # 'temp를 kalvin으로 맞추기
711
            temp_unit = self.units['Temperature']
712
            if temp_unit == '':
713
                temp = temp + 273.15
714
            elif temp_unit == '':
715
                temp = (temp - 32) / 1.8 + 273.15
716

    
717
            # 'MW 가져오기
718
            mw = self.items[i].data.molecular_weight
719

    
720
            # 'Z 가져오기
721
            z = self.items[i].data.compress_factor
722

    
723
            # 밀도 계산
724
            density2 = press2 * mw / 0.08206 / temp / z / 1.033
725

    
726
            # '밀도 입력
727
            density_unit = self.units['Density']
728
            if density_unit == 'kg/m3':
729
                density2 = density2
730
            elif density_unit == 'lb/ft3':
731
                density2 = density2 * 0.062428
732

    
733
            self.density_elevations[self.items[i]] = density2
734
        except Exception as ex:
735
            from App import App
736
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
737
                                                           sys.exc_info()[-1].tb_lineno)
738
            App.mainWnd().addMessage.emit(MessageType.Error, message)
739

    
740
    def suction_static_cal(self, i):
741
        try:
742
            if self.items[i].data.phase_type == 'Mixed':
743
                pass  # TODO:
744
            else:
745
                density_unit = self.units['Density']
746
                if density_unit == 'kg/m3':
747
                    density2 = self.density_elevations[self.items[i]]
748
                else:
749
                    density2 = self.density_elevations[self.items[i]] * 16.0185  # lb/ft3
750

    
751
                # 2 elevation 받음
752
                length_unit = self.units['Length']
753
                if length_unit == 'm':
754
                    el1 = self.density_elevations[self.items[i - 1]]
755
                    el2 = self.density_elevations[self.items[i + 1]]
756
                elif length_unit == 'in':
757
                    el1 = self.density_elevations[self.items[i - 1]] * 0.0254
758
                    el2 = self.density_elevations[self.items[i + 1]] * 0.0254
759
                elif length_unit == 'ft':
760
                    el1 = self.density_elevations[self.items[i - 1]] * 0.3048
761
                    el2 = self.density_elevations[self.items[i + 1]] * 0.3048
762
                elif length_unit == 'yd':
763
                    el1 = self.density_elevations[self.items[i - 1]] * 0.9144
764
                    el2 = self.density_elevations[self.items[i + 1]] * 0.9144
765
                elif length_unit == 'mm':
766
                    el1 = self.density_elevations[self.items[i - 1]] * 0.001
767
                    el2 = self.density_elevations[self.items[i + 1]] * 0.001
768
                else:  # mile
769
                    el1 = self.density_elevations[self.items[i - 1]] * 1609.34
770
                    el2 = self.density_elevations[self.items[i + 1]] * 1609.34
771

    
772
                # 3. static head 계산
773
                stat_dp = (el2 - el1) * density2 / 1000 * 9.80665 / 101.325  # atm으로 계산된 dp
774

    
775
                # 4. 압력 유닛에 맞춰 뿌리기
776
                pressure_unit = self.units['Pressure']
777
                if pressure_unit == 'kg/cm2':
778
                    self.pressure_drops[self.items[i - 1]] = stat_dp * 1.033
779
                elif pressure_unit == 'psi':
780
                    self.pressure_drops[self.items[i - 1]] = stat_dp * 14.7
781
                elif pressure_unit == 'atm':
782
                    self.pressure_drops[self.items[i - 1]] = stat_dp
783
                elif pressure_unit == 'bar':
784
                    self.pressure_drops[self.items[i - 1]] = stat_dp * 1.013
785
                elif pressure_unit == 'mmHg':
786
                    self.pressure_drops[self.items[i - 1]] = stat_dp * 760
787
                elif pressure_unit == 'kPa':
788
                    self.pressure_drops[self.items[i - 1]] = stat_dp * 101.325
789
                elif pressure_unit == 'MPa':
790
                    self.pressure_drops[self.items[i - 1]] = stat_dp * 0.101325
791
        except Exception as ex:
792
            from App import App
793
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
794
                                                           sys.exc_info()[-1].tb_lineno)
795
            App.mainWnd().addMessage.emit(MessageType.Error, message)
796

    
797
    def p_eq_input(self):
798
        try:
799
            # 시작, 끝 기기의 pressure와 elevation을 구한다
800
            self.pressures[self.items[0]] = self.items[0].data.pressure
801
            self.density_elevations[self.items[0]] = self.items[0].data.elevation
802
            self.pressures[self.items[-1]] = self.items[-1].data.pressure
803
            self.density_elevations[self.items[-1]] = self.items[-1].data.elevation
804

    
805
            if len(self.items) == 3:
806
                # 장치 2개와 Line 1개로 구성된 경우
807
                pass
808
            else:
809
                for i in range(2, len(self.items) - 3, 3):
810
                    dp_eq = str(self.items[i])[:3]
811
                    if dp_eq == 'HEX' or dp_eq == 'M_D' or dp_eq == 'M_R':
812
                        dp_eq = str(self.items[i])[:3]
813

    
814
                    # pressure drop
815
                    if self.items[i].data.pressure_drop is not None:
816
                        self.pressure_drops[self.items[i]] = self.items[i].data.pressure_drop
817
                    if not self.items[i].data.pressure_drop:
818
                        pass
819

    
820
                    # elevation
821
                    if dp_eq[:3] == 'M_R':
822
                        self.density_elevations[self.items[i]] = self.items[i].data.elevation
823
                        self.density_elevations[self.items[i + 1]] = self.items[i + 1].data.elevation
824
                    else:
825
                        self.density_elevations[self.items[i]] = self.items[i].data.elevation
826
                        self.density_elevations[self.items[i + 1]] = self.items[i + 1].data.elevation
827

    
828
                    if dp_eq[:3] == 'L_P' or dp_eq[:3] == 'R_P' or dp_eq[:3] == 'V_P' or dp_eq[:3] == 'R_K':
829
                        self.extras[self.items[i]] = self.items[i].data.over_design_cv \
830
                            if self.items[i].data.over_design_cv else 0
831
                    elif dp_eq[:3] == 'CV_':
832
                        self.extras[self.items[i]] = self.items[i].data.over_design_cv \
833
                            if self.items[i].data.over_design_cv else 0
834
                        self.extras[self.items[i + 1]] = None  # TODO:
835
        except Exception as ex:
836
            from App import App
837
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
838
                                                           sys.exc_info()[-1].tb_lineno)
839
            App.mainWnd().addMessage.emit(MessageType.Error, message)
840

    
841
    def discharge_den(self, i):
842
        try:
843
            self.extras[self.items[i]] = self.items[i].data.phase_type
844
            # 1. density 받음
845
            if self.items[i].data.phase_type == 'Liquid' or self.items[i].data.phase_type == 'Mixed':
846
                self.density_elevations[self.items[i]] = self.items[i].density
847
            elif self.items[i].data.phase_type == 'Vapor':
848
                self.discharge_vapor_density(i)
849
        except Exception as ex:
850
            from App import App
851
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
852
                                                           sys.exc_info()[-1].tb_lineno)
853
            App.mainWnd().addMessage.emit(MessageType.Error, message)
854

    
855
    def get_barometric_pressure(self):
856
        try:
857
            unit = self.units['Pressure']
858
            if unit == 'kg/cm2':
859
                barometric_pressure = 1.033
860
            elif unit == 'bar':
861
                barometric_pressure = 1.01325
862
            elif unit == 'psi':
863
                barometric_pressure = 14.7
864
            elif unit == 'mmHg':
865
                barometric_pressure = 760
866
            elif unit == 'kPa':
867
                barometric_pressure = 101.325
868
            elif unit == 'MPa':
869
                barometric_pressure = 0.101325
870

    
871
            return barometric_pressure
872
        except Exception as ex:
873
            from App import App
874
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
875
                                                           sys.exc_info()[-1].tb_lineno)
876
            App.mainWnd().addMessage.emit(MessageType.Error, message)
877

    
878
    def discharge_vapor_density(self, i):
879
        try:
880
            Ref_baro = self.get_barometric_pressure()
881
            press2 = self.pressures[self.items[i + 1]]
882

    
883
            # '여기에 아래의 p를 이용하여 density를 넣는 항을 만들어줘야함
884
            # 'pressure를 k.g.a로 맞춤
885
            pressure_unit = self.units['Pressure']
886
            if pressure_unit == 'kg/cm2':
887
                press2 = press2 + Ref_baro
888
            elif pressure_unit == 'psi':
889
                press2 = press2 / 14.7 * 1.033 + Ref_baro
890
            elif pressure_unit == 'atm':
891
                press2 = press2 * 1.033 + Ref_baro
892
            elif pressure_unit == 'bar':
893
                press2 = press2 / 1.013 * 1.033 + Ref_baro
894
            elif pressure_unit == 'mmHg':
895
                press2 = press2 / 760 * 1.033 + Ref_baro
896
            elif pressure_unit == 'kPa':
897
                press2 = press2 / 101.325 * 1.033 + Ref_baro
898
            elif pressure_unit == 'MPa':
899
                press2 = press2 / 0.101325 * 1.033 + Ref_baro
900

    
901
            # temp 가져오기
902
            temp = self.items[i].data.temperature
903
            # 'temp를 kalvin으로 맞추기
904
            temp_unit = self.units['Temperature']
905
            if temp_unit == '':
906
                temp = temp + 273.15
907
            elif temp_unit == '':
908
                temp = (temp - 32) / 1.8 + 273.15
909

    
910
            # 'MW 가져오기
911
            mw = self.items[i].data.molecular_weight
912

    
913
            # 'Z 가져오기
914
            z = self.items[i].data.compress_factor
915

    
916
            # 밀도 계산
917
            density2 = press2 * mw / 0.08206 / temp / z / 1.033
918

    
919
            # '밀도 입력
920
            density_unit = self.units['Density']
921
            if density_unit == 'kg/m3':
922
                density2 = density2
923
            elif density_unit == 'lb/ft3':
924
                density2 = density2 * 0.062428
925

    
926
            self.density_elevations[self.items[i]] = density2
927
        except Exception as ex:
928
            from App import App
929
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
930
                                                           sys.exc_info()[-1].tb_lineno)
931
            App.mainWnd().addMessage.emit(MessageType.Error, message)
932

    
933
    def discharge_static_cal(self, i):
934
        """ (2) static P를 계산 """
935

    
936
        try:
937
            if self.items[i].data.phase_type == 'Mixed':
938
                self.pressure_drops[self.items[i - 1]] = self.items[i].data.pressure_drop_static
939
            else:
940
                # 1. density 받음
941
                density_unit = self.units['Density']
942
                if density_unit == 'kg/m3':
943
                    density2 = self.density_elevations[self.items[i]]
944
                else:
945
                    density2 = self.density_elevations[self.items[i]] * 16.0185  # lb/ft3
946

    
947
                # 2 elevation 받음
948
                length_unit = self.units['Length']
949
                if length_unit == 'm':
950
                    el1 = self.density_elevations[self.items[i - 1]]
951
                    el2 = self.density_elevations[self.items[i + 1]]
952
                elif length_unit == 'in':
953
                    el1 = self.density_elevations[self.items[i - 1]] * 0.0254
954
                    el2 = self.density_elevations[self.items[i + 1]] * 0.0254
955
                elif length_unit == 'ft':
956
                    el1 = self.density_elevations[self.items[i - 1]] * 0.3048
957
                    el2 = self.density_elevations[self.items[i + 1]] * 0.3048
958
                elif length_unit == 'yd':
959
                    el1 = self.density_elevations[self.items[i - 1]] * 0.9144
960
                    el2 = self.density_elevations[self.items[i + 1]] * 0.9144
961
                elif length_unit == 'mm':
962
                    el1 = self.density_elevations[self.items[i - 1]] * 0.001
963
                    el2 = self.density_elevations[self.items[i + 1]] * 0.001
964
                else:  # mile
965
                    el1 = self.density_elevations[self.items[i - 1]] * 1609.34
966
                    el2 = self.density_elevations[self.items[i + 1]] * 1609.34
967

    
968
                # 3. static head 계산
969
                stat_dp = (el2 - el1) * density2 / 1000 * 9.80665 / 101.325  # atm으로 계산된 dp
970

    
971
                # 4. 압력 유닛에 맞춰 뿌리기
972
                pressure_unit = self.units['Pressure']
973
                if pressure_unit == 'kg/cm2':
974
                    self.pressure_drops[self.items[i - 1]] = stat_dp * 1.033
975
                elif pressure_unit == 'psi':
976
                    self.pressure_drops[self.items[i - 1]] = stat_dp * 14.7
977
                elif pressure_unit == 'atm':
978
                    self.pressure_drops[self.items[i - 1]] = stat_dp
979
                elif pressure_unit == 'bar':
980
                    self.pressure_drops[self.items[i - 1]] = stat_dp * 1.013
981
                elif pressure_unit == 'mmHg':
982
                    self.pressure_drops[self.items[i - 1]] = stat_dp * 760
983
                elif pressure_unit == 'kPa':
984
                    self.pressure_drops[self.items[i - 1]] = stat_dp * 101.325
985
                elif pressure_unit == 'MPa':
986
                    self.pressure_drops[self.items[i - 1]] = stat_dp * 0.101325
987
        except Exception as ex:
988
            from App import App
989
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
990
                                                           sys.exc_info()[-1].tb_lineno)
991
            App.mainWnd().addMessage.emit(MessageType.Error, message)
992

    
993
    def suction_vapor_factor_length(self, i):
994
        try:
995
            # '입력된 vapor의 압력과 밀도를 가지고 끊어서 계산하는 factor를 적용했을때 length가 얼마나 나오는지 판별하는 것.
996

    
997
            # pipe dia 가져오기
998
            ida = self.items[i].data.inside_pipe_size
999
            pipe_diameter_unit = self.units['Pipe_Diameter']
1000
            if pipe_diameter_unit == 'in':
1001
                ida = ida * 0.0254
1002
            elif pipe_diameter_unit == 'mm':
1003
                ida = ida / 1000
1004

    
1005
            # 'mass 가져오기 기준 kg/h
1006
            mass = self.items[i].data.flowrate_mass
1007
            flowrate_mass_unit = self.units['Flowrate_Mass']
1008
            if flowrate_mass_unit == 'kg/h':
1009
                mass = mass
1010
            elif flowrate_mass_unit == 'g/min':
1011
                mass = mass * 60 / 1000
1012
            elif flowrate_mass_unit == 'lb/h':
1013
                mass = mass * 0.453592
1014
            elif flowrate_mass_unit == 't/h':
1015
                mass = mass * 1000
1016

    
1017
            # 'g 구하기 (kg/m2/s)
1018
            g = mass / 3600 / (3.1415 * ida ** 2 / 4)
1019

    
1020
            density2 = self.density_elevations[self.items[i]]
1021
            # '속도 계산 (m/s)
1022
            velocity = 4 * mass / density2 / 3.1415 / ida ** 2 / 3600
1023

    
1024
            # 'Mach Number 계산
1025
            # 'k 가져오기
1026
            k = self.items[i].data.specific_heat_ratio
1027

    
1028
            # temp 가져오기
1029
            temp = self.items[i].data.temperature
1030
            # 'temp를 kalvin으로 맞추기
1031
            temp_unit = self.units['Temperature']
1032
            if temp_unit == '':
1033
                temp = temp + 273.15
1034
            elif temp_unit == '':
1035
                temp = (temp - 32) / 1.8 + 273.15
1036

    
1037
            # 'MW 가져오기
1038
            mw = self.items[i].data.molecular_weight
1039

    
1040
            mach = velocity / ((k * 9.80665 * 847.28 * temp / mw) ** 0.5)
1041

    
1042
            # '부피유량 계산
1043
            volume = mass / density2
1044

    
1045
            # '현재 volume은 m3/h임. 부피유량 단위에 맞춰 뿌려줌
1046
            flowrate_volume_unit = self.units['Flowrate_Volume']
1047
            if flowrate_volume_unit == 'm3/h':
1048
                self.items[i].data.flowrate_volume = round(volume, 3)
1049
            elif flowrate_volume_unit == 'l/min':
1050
                self.items[i].data.flowrate_volume = round(volume / 60 * 1000, 3)
1051
            elif flowrate_volume_unit == 'ft3/h':
1052
                self.items[i].data.flowrate_volume = round(volume * 35.3147, 3)
1053
            elif flowrate_volume_unit == 'USgpm':
1054
                self.items[i].data.flowrate_volume = round(volume * 4.40287, 3)
1055
            elif flowrate_volume_unit == 'BPSD':
1056
                self.items[i].data.flowrate_volume = round(volume * 150.955, 3)
1057

    
1058
            viscosity = self.items[i].data.viscosity
1059
            # ' viscosity 유닛 변환 (모두 kg/m.s로 바꿀것임)
1060
            viscosity_unit = self.units['Viscosity']
1061
            if viscosity_unit == 'kg/m.sec':
1062
                viscosity = viscosity
1063
            elif viscosity_unit == 'cP':
1064
                viscosity = viscosity * 0.001
1065
            elif viscosity_unit == 'kg/m.h':
1066
                viscosity = viscosity / 3600
1067
            elif viscosity_unit == 'lb/ft.s':
1068
                viscosity = viscosity * 1.48816
1069

    
1070
            # density case에 따라 re계산
1071
            density_unit = self.units['Density']
1072
            if density_unit == 'kg/m3':
1073
                reynolds = ida * velocity * density2 / viscosity
1074
            elif density_unit == 'lb/ft3':
1075
                reynolds = ida * velocity * (density2 * 16.0185) / viscosity
1076

    
1077
            # roughness를 m로 바꿔줌
1078
            rough = self.items[i].data.roughness
1079
            roughness_unit = self.units['Roughness']
1080
            if roughness_unit == 'm':
1081
                rough = rough
1082
            elif roughness_unit == 'ft':
1083
                rough = rough * 0.3048
1084
            elif roughness_unit == 'in':
1085
                rough = rough * 0.0254
1086
            elif roughness_unit == 'mm':
1087
                rough = rough * 0.001
1088

    
1089
            # ' reynolds수에 따라 Fanning/Chen friction factor 계산
1090
            if reynolds <= 2100:
1091
                f = 4 * 16 / reynolds
1092
            else:
1093
                af = math.log(rough / ida / 3.7 + (6.7 / reynolds) ** 0.9) / math.log(10)
1094
                f = (-2 * (math.log(rough / 3.7 / ida - 5.02 / reynolds * af) / math.log(10))) ** (-2)
1095

    
1096
            self.items[i].data.friction_factor = f
1097

    
1098
            # '속도와 mach 수 입력
1099
            velocity_unit = self.units['Velocity']
1100
            if velocity_unit == 'm/s':
1101
                self.items[i].data.velocity = round(velocity, 3)
1102
            elif velocity_unit == 'ft/s':
1103
                self.items[i].data.velocity = round(velocity * 3.28084, 3)
1104

    
1105
            self.items[i].data.reynolds = round(mach, 5)
1106

    
1107
            Ref_baro = self.get_barometric_pressure()
1108
            press2 = self.pressures[self.items[i - 1]]
1109

    
1110
            # pressure를 k.g.a로 맞춤
1111
            pressure_unit = self.units['Pressure']
1112
            if pressure_unit == 'kg/cm2':
1113
                press2 = press2 + Ref_baro
1114
            elif pressure_unit == 'psi':
1115
                press2 = press2 / 14.7 * 1.033 + Ref_baro
1116
            elif pressure_unit == 'atm':
1117
                press2 = press2 * 1.033 + Ref_baro
1118
            elif pressure_unit == 'bar':
1119
                press2 = press2 / 1.013 * 1.033 + Ref_baro
1120
            elif pressure_unit == 'mmHg':
1121
                press2 = press2 / 760 * 1.033 + Ref_baro
1122
            elif pressure_unit == 'kPa':
1123
                press2 = press2 / 101.325 * 1.033 + Ref_baro
1124
            elif pressure_unit == 'MPa':
1125
                press2 = press2 / 0.101325 * 1.033 + Ref_baro
1126

    
1127
            press1est = press2 * 0.95  # HY_Calc_sht.Cells(2, 1)
1128

    
1129
            z = self.items[i].data.compress_factor
1130
            density1est = press1est * mw / 0.08206 / temp / z / 1.033
1131

    
1132
            # ' 라인 길이 도출 (m)
1133
            estlength = abs(
1134
                (((press1est ** 2 - press2 ** 2) * mw / g ** 2 / 0.08206 / 1.033 ** 2 / temp / z * 101325) - (
1135
                        2 * math.log(density1est / density2))) * ida / f)
1136

    
1137
            # 라인 길이를 유닛에 맞춰서 변환
1138
            length_unit = self.units['Length']
1139
            if length_unit == 'm':
1140
                estlength = estlength
1141
            elif length_unit == 'in':
1142
                estlength = estlength * 39.3701
1143
            elif length_unit == 'ft':
1144
                estlength = estlength * 3.28084
1145
            elif length_unit == 'yd':
1146
                estlength = estlength * 1.09361
1147
            elif length_unit == 'mile':
1148
                estlength = estlength * 0.000621371
1149
            elif length_unit == 'mm':
1150
                estlength = estlength * 1000
1151

    
1152
            equivalent_length = self.get_equivalent_length(i)
1153
            if estlength > equivalent_length:
1154
                # '주어진 길이를 가지고 압력 강하를 계산하는 모듈이 들어가야함 (safe)
1155
                # ' length 여유 있음. 한번에 isothermal 식으로 계산
1156
                self.suction_vap_dp_cal1(i, press2, g, mw, temp, f, z, ida)
1157
            else:
1158
                # '끊어서 계산하는 모듈이 들어가야함
1159
                # 'length 여유 없음. 압력 재계산->밀도 재계산->re, f 재계산->압력 재계산 체계로 가야함
1160
                self.suction_vap_dp_cal2(i, press2, g, mw, temp, f, z, ida)
1161

    
1162
        except Exception as ex:
1163
            from App import App
1164
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1165
                                                           sys.exc_info()[-1].tb_lineno)
1166
            App.mainWnd().addMessage.emit(MessageType.Error, message)
1167

    
1168
    def suction_vap_dp_cal2(self, i, press2, g, mw, temp, f, z, ida):
1169
        # 끊은 결과 length 여유가 없음, 고로 물성치 (밀도) 를 재계산해주어야 함
1170

    
1171
        pass
1172

    
1173
    def suction_vap_dp_cal1(self, i, press2, g, mw, temp, f, z, ida):
1174
        try:
1175
            # 끊은 결과 length가 여유가 있음. 그래서 단순 계산하는 모듈
1176
            length = self.get_equivalent_length(i)
1177

    
1178
            # length를 m로 변환
1179
            length_unit = self.units['Length']
1180
            if length_unit == 'm':
1181
                length = length
1182
            elif length_unit == 'in':
1183
                length = length * 0.0254
1184
            elif length_unit == 'ft':
1185
                length = length * 0.3048
1186
            elif length_unit == 'yd':
1187
                length = length * 0.9144
1188
            elif length_unit == 'mile':
1189
                length = length * 1609.34
1190
            elif length_unit == 'mm':
1191
                length = length * 0.001
1192

    
1193
            # Newton's Rule에 따라
1194
            press1 = self.Vap_Suction_1(press2, g, mw, temp, f, z, ida, length)
1195
            pressure_unit = self.units['Pressure']
1196
            if pressure_unit == 'kg/cm2':
1197
                self.pressure_drops[self.items[i]] = press2 - press1
1198
            elif pressure_unit == 'psi':
1199
                self.pressure_drops[self.items[i]] = (press2 - press1) / 1.033 * 14.7
1200
            elif pressure_unit == 'atm':
1201
                self.pressure_drops[self.items[i]] = (press2 - press1) / 1.033
1202
            elif pressure_unit == 'bar':
1203
                self.pressure_drops[self.items[i]] = (press2 - press1) / 1.033 * 1.033
1204
            elif pressure_unit == 'mmHg':
1205
                self.pressure_drops[self.items[i]] = (press2 - press1) / 1.033 * 760
1206
            elif pressure_unit == 'kPa':
1207
                self.pressure_drops[self.items[i]] = (press2 - press1) / 1.033 * 101.325
1208
            elif pressure_unit == 'MPa':
1209
                self.pressure_drops[self.items[i]] = (press2 - press1) / 10.33 * 0.101325
1210

    
1211
            self.suction_p_cal(i)
1212
        except Exception as ex:
1213
            from App import App
1214
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1215
                                                           sys.exc_info()[-1].tb_lineno)
1216
            App.mainWnd().addMessage.emit(MessageType.Error, message)
1217

    
1218
    def Vap_Suction_1(self, p2, g, mw, temp, f, z, id, L_eq):
1219
        try:
1220
            R = 0.08206
1221

    
1222
            Tmp_Const = 101325 * mw / (1.033 ** 2 * (g ** 2) * R * temp * z)
1223
            Tmp_Const2 = id / f
1224

    
1225
            x2 = p2
1226
            delta_x_past = 0
1227

    
1228
            loop = True
1229
            while loop:
1230
                X = x2
1231
                f_x = (Tmp_Const2 * (Tmp_Const * (p2 ** 2 - X ** 2) - 2 * math.log(p2 / X))) - L_eq
1232
                df_x = 2 * Tmp_Const2 * (1 / X - Tmp_Const * X)
1233
                x2 = X - (f_x / df_x)
1234
                delta_x = x2 - X
1235
                if abs(delta_x_past) == abs(delta_x):
1236
                    break
1237

    
1238
                delta_x_past = delta_x
1239

    
1240
                if delta_x == 0 or x2 < 0:
1241
                    loop = False
1242

    
1243
            return x2
1244

    
1245
        except Exception as ex:
1246
            from App import App
1247
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1248
                                                           sys.exc_info()[-1].tb_lineno)
1249
            App.mainWnd().addMessage.emit(MessageType.Error, message)
1250

    
1251
    def suction_p_cal(self, i, calc_cnt=1):
1252
        res = 1
1253

    
1254
        try:
1255
            self.pressures[self.items[i]] = self.pressures[self.items[i - 1]] - self.pressure_drops[self.items[i - 1]]
1256

    
1257
            if self.pressures[self.items[i]] < 0:
1258
                pressure_unit = self.units['Pressure']
1259
                if pressure_unit == 'kg/cm2':
1260
                    pabsolute = self.pressures[self.items[i]] + 1.033
1261
                elif pressure_unit == 'psi':
1262
                    pabsolute = self.pressures[self.items[i]] + 14.7
1263
                elif pressure_unit == 'atm':
1264
                    pabsolute = self.pressures[self.items[i]] + 1
1265
                elif pressure_unit == 'bar':
1266
                    pabsolute = self.pressures[self.items[i]] + 1.013
1267
                elif pressure_unit == 'mmHg':
1268
                    pabsolute = self.pressures[self.items[i]] + 760
1269
                elif pressure_unit == 'kPa':
1270
                    pabsolute = self.pressures[self.items[i]] + 101.325
1271
                elif pressure_unit == 'MPa':
1272
                    pabsolute = self.pressures[self.items[i]] + 0.101325
1273

    
1274
                if pabsolute < 0:
1275
                    raise ValueError('The absolute pressure of {} is below 0.'.format(self.items[i]))
1276

    
1277
            if i < len(self.items) - 2:
1278
                self.pressures[self.items[i + 1]] = self.pressures[self.items[i]] - self.pressure_drops[self.items[i]]
1279
                if self.pressures[self.items[i + 1]] < 0:
1280
                    pressure_unit = self.units['Pressure']
1281
                    if pressure_unit == 'kg/cm2':
1282
                        pabsolute = self.pressures[self.items[i + 1]] + 1.033
1283
                    elif pressure_unit == 'psi':
1284
                        pabsolute = self.pressures[self.items[i + 1]] + 14.7
1285
                    elif pressure_unit == 'atm':
1286
                        pabsolute = self.pressures[self.items[i + 1]] + 1
1287
                    elif pressure_unit == 'bar':
1288
                        pabsolute = self.pressures[self.items[i + 1]] + 1.013
1289
                    elif pressure_unit == 'mmHg':
1290
                        pabsolute = self.pressures[self.items[i + 1]] + 760
1291
                    elif pressure_unit == 'kPa':
1292
                        pabsolute = self.pressures[self.items[i + 1]] + 101.325
1293
                    elif pressure_unit == 'MPa':
1294
                        pabsolute = self.pressures[self.items[i + 1]] + 0.101325
1295

    
1296
                    if pabsolute < 0:
1297
                        raise ValueError('The absolute pressure of {} is below 0.'.format(self.items[i + 1]))
1298

    
1299
                if calc_cnt == 1:
1300
                    if self.items[i + 1] in self.pressure_drops and self.pressure_drops[self.items[i + 1]] is not None:
1301
                        name = str(self.items[i + 1])[:3]
1302
                        if name == 'L_P' or name == 'R_P' or name == 'V_P' or name == 'R_K' or name == 'L_K':
1303
                            self.pressures[self.items[i + 2]] = self.pressures[self.items[i + 1]] + \
1304
                                                                self.pressure_drops[self.items[i + 1]]
1305
                        else:
1306
                            self.pressures[self.items[i + 2]] = self.pressures[self.items[i + 1]] - \
1307
                                                                self.pressure_drops[self.items[i + 1]]
1308
                    else:
1309
                        res = 0
1310
                elif calc_cnt == 2:
1311
                    if self.items[i + 1] in self.pressure_drops and self.pressure_drops[self.items[i + 1]] is not None:
1312
                        name = str(self.items[i + 1])[:3]
1313
                        if name == 'CV_':
1314
                            res = 0
1315
                        elif name == 'L_P' or name == 'R_P' or name == 'V_P' or name == 'R_K' or name == 'L_K':
1316
                            self.pressures[self.items[i + 2]] = self.pressures[self.items[i + 1]] + \
1317
                                                                self.pressure_drops[self.items[i + 1]]
1318
                        else:
1319
                            self.pressures[self.items[i + 2]] = self.pressures[self.items[i + 1]] - \
1320
                                                                self.pressure_drops[self.items[i + 1]]
1321
                    else:
1322
                        res = 0
1323
        except Exception as ex:
1324
            from App import App
1325
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
1326
                                                           sys.exc_info()[-1].tb_lineno)
1327
            App.mainWnd().addMessage.emit(MessageType.Error, message)
1328

    
1329
        return res
1330

    
1331
    def hole_p_cal(self, i):
1332
        res = 1
1333

    
1334
        try:
1335
            self.pressures[self.items[i]] = self.pressures[self.items[i + 1]] + self.pressure_drops[self.items[i]] \
1336
                if not self.pressure_drops[self.items[i]] is None else 0
1337

    
1338
            index = str(self.items[i - 2])[:3]
1339
            if i > 0:
1340
                self.pressures[self.items[i - 1]] = self.pressures[self.items[i]] + self.pressure_drops[
1341
                    self.items[i - 1]]
1342

    
1343
                if self.items[i - 2] in self.pressure_drops and self.pressure_drops[self.items[i - 2]] is not None:
1344
                    if index == 'L_P' or index == 'R_P' or index == 'V_P' or index == 'R_K' or index == 'L_K':
1345
                        self.pressures[self.items[i - 2]] = self.pressures[self.items[i - 1]] - \
1346
                                                            self.pressure_drops[self.items[i - 2]]
1347
                    else:
1348
                        self.pressures[self.items[i - 2]] = self.pressures[self.items[i - 1]] + \
1349
                                                            self.pressure_drops[self.items[i - 2]]
1350
                else:
1351
                    # 여기에 그 루프는 그만 하는 로직을 넣어줘야함
1352
                    res = 0
1353
        except Exception as ex:
1354
            from App import App
1355
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
1356
                                                           sys.exc_info()[-1].tb_lineno)
1357
            App.mainWnd().addMessage.emit(MessageType.Error, message)
1358

    
1359
        return res
1360

    
1361
    def discharge_p_cal(self, i, calc_cnt=1):
1362
        res = 1
1363

    
1364
        try:
1365
            pressure = 0 if self.pressures[self.items[i + 1]] is None else self.pressures[self.items[i + 1]]
1366
            pressure_drop = 0 if self.pressure_drops[self.items[i]] is None else self.pressure_drops[self.items[i]]
1367

    
1368
            self.pressures[self.items[i]] = pressure + pressure_drop
1369
            name = str(self.items[i - 2])[:3]
1370
            if i > 1:
1371
                self.pressures[self.items[i - 1]] = self.pressures[self.items[i]] + \
1372
                                                    self.pressure_drops[self.items[i - 1]]
1373

    
1374
                if calc_cnt == 1:
1375
                    if self.items[i - 2] in self.pressure_drops and self.pressure_drops[self.items[i - 2]] is not None:
1376
                        if name == 'L_P' or name == 'R_P' or name == 'V_P' or name == 'R_K' or name == 'L_K':
1377
                            self.pressures[self.items[i - 2]] = self.pressures[self.items[i - 1]] - self.pressure_drops[
1378
                                self.items[i - 2]]
1379
                        else:
1380
                            self.pressures[self.items[i - 2]] = self.pressures[self.items[i - 1]] + self.pressure_drops[
1381
                                self.items[i - 2]]
1382
                    else:
1383
                        # 여기에 그 루프는 그만 하는 로직을 넣어줘야함
1384
                        res = 0
1385
                elif calc_cnt == 2:
1386
                    if self.items[i - 2] in self.pressure_drops and self.pressure_drops[self.items[i - 2]] is not None:
1387
                        if name == 'CV_':
1388
                            self.pressure_drops[self.items[i - 2]] = self.pressures[self.items[i - 2]] - \
1389
                                                                     self.pressures[self.items[i - 1]]
1390
                            res = 0
1391
                        elif name == 'L_P' or name == 'R_P' or name == 'V_P' or name == 'R_K' or name == 'L_K':
1392
                            self.pressures[self.items[i - 2]] = self.pressures[self.items[i - 1]] - self.pressure_drops[
1393
                                self.items[i - 2]]
1394
                        else:
1395
                            self.pressures[self.items[i - 2]] = self.pressures[self.items[i - 1]] + self.pressure_drops[
1396
                                self.items[i - 2]]
1397
                    else:
1398
                        # 여기에 그 루프는 그만 하는 로직을 넣어줘야함
1399
                        res = 0
1400
        except Exception as ex:
1401
            from App import App
1402
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
1403
                                                           sys.exc_info()[-1].tb_lineno)
1404
            App.mainWnd().addMessage.emit(MessageType.Error, message)
1405

    
1406
        return res
1407

    
1408

    
1409
class Transfer(QObject):
1410
    onRemoved = pyqtSignal(QGraphicsItem)
1411

    
1412
    def __init__(self, parent=None):
1413
        QObject.__init__(self, parent)
클립보드 이미지 추가 (최대 크기: 500 MB)