개정판 f1187004
issue #1060 : 계산식
Change-Id: Ic17bb7449542c39904972fa2039f847e74f654e6
HYTOS/HYTOS/Calculation.py | ||
---|---|---|
1 |
# coding: utf-8 |
|
2 |
""" |
|
3 |
This is calculation module |
|
4 |
""" |
|
5 |
import sys |
|
6 |
import os |
|
7 |
from AppDocData import * |
|
8 |
import math |
|
9 |
|
|
10 |
class Calculation: |
|
11 |
def __init__(self, hmb): |
|
12 |
self.initUnits() |
|
13 |
self._hmb = hmb |
|
14 |
|
|
15 |
if self._hmb.phase_type == 'Vapor': |
|
16 |
self.calculation_Vapor() |
|
17 |
elif self._hmb.phase_type == 'Liquid': |
|
18 |
self.calculation_Liquid() |
|
19 |
elif self._hmb.phase_type == 'Mixed': |
|
20 |
self.calculation_Mixed() |
|
21 |
|
|
22 |
def initUnits(self): |
|
23 |
activeDrawing = AppDocData.instance().activeDrawing |
|
24 |
|
|
25 |
for attr in activeDrawing.attrs: |
|
26 |
if attr[0] == 'Units': |
|
27 |
self.flowrate_mass_unit = attr[1]['Flowrate_Mass'] |
|
28 |
self.flowrate_volume_unit = attr[1]['Flowrate_Volume'] |
|
29 |
self.density_unit = attr[1]['Density'] |
|
30 |
self.viscosity_unit = attr[1]['Viscosity'] |
|
31 |
self.velocity_unit = attr[1]['Velocity'] |
|
32 |
self.pressure_unit = attr[1]['Pressure'] |
|
33 |
self.length_unit = attr[1]['Length'] |
|
34 |
self.pipe_diameter_unit = attr[1]['Pipe_Diameter'] |
|
35 |
self.roughness_unit = attr[1]['Roughness'] |
|
36 |
self.temperature_unit = attr[1]['Temperature'] |
|
37 |
|
|
38 |
def getBarometricPressure(self): |
|
39 |
barometric_pressure = None |
|
40 |
|
|
41 |
if self.pressure_unit == 'kg/cm2': |
|
42 |
barometric_pressure = 1.033 |
|
43 |
elif self.pressure_unit == 'bar': |
|
44 |
barometric_pressure = 1.01325 |
|
45 |
elif self.pressure_unit == 'psi': |
|
46 |
barometric_pressure = 14.7 |
|
47 |
elif self.pressure_unit == 'mmHg': |
|
48 |
barometric_pressure = 760 |
|
49 |
elif self.pressure_unit == 'kPa': |
|
50 |
barometric_pressure = 101.325 |
|
51 |
elif self.pressure_unit == 'MPa': |
|
52 |
barometric_pressure = 0.101325 |
|
53 |
|
|
54 |
return barometric_pressure |
|
55 |
|
|
56 |
def calculation_Vapor(self): |
|
57 |
|
|
58 |
|
|
59 |
# (1) density 입력 |
|
60 |
|
|
61 |
Ref_baro = self.getBarometricPressure() |
|
62 |
|
|
63 |
press2 = 100 # To쪽 Equipment의 Pressure |
|
64 |
|
|
65 |
if self.pressure_unit == 'kg/cm2': |
|
66 |
press2 = press2 + Ref_baro |
|
67 |
elif self.pressure_unit == 'psi': |
|
68 |
press2 = press2 / 14.7 * 1.033 + Ref_baro |
|
69 |
elif self.pressure_unit == 'atm': |
|
70 |
press2 = press2 * 1.033 + Ref_baro |
|
71 |
elif self.pressure_unit == 'bar': |
|
72 |
press2 = press2 / 1.013 * 1.033 + Ref_baro |
|
73 |
elif self.pressure_unit == 'mmHg': |
|
74 |
press2 = press2 / 760 * 1.033 + Ref_baro |
|
75 |
elif self.pressure_unit == 'kPa': |
|
76 |
press2 = press2 / 101.325 * 1.033 + Ref_baro |
|
77 |
elif self.pressure_unit == 'MPa': |
|
78 |
press2 = press2 / 0.101325 * 1.033 + Ref_baro |
|
79 |
|
|
80 |
temp = self._hmb.temperature |
|
81 |
# temp를 kalvin으로 맞추기 |
|
82 |
if self.temperature_unit == '℃': |
|
83 |
temp = temp + 273.15 |
|
84 |
elif self.temperature_unit == '℉': |
|
85 |
temp = (temp - 32) / 1.8 + 273.15 |
|
86 |
|
|
87 |
# 'MW 가져오기 |
|
88 |
mw = self._hmb.molecular_weight |
|
89 |
|
|
90 |
# 'Z 가져오기 |
|
91 |
z = self._hmb.compress_factor |
|
92 |
|
|
93 |
# 밀도 계산 |
|
94 |
density2 = press2 * mw / 0.08206 / temp / z / 1.033 |
|
95 |
|
|
96 |
# '밀도 입력 |
|
97 |
if self.density_unit == 'kg/m3': |
|
98 |
density2 = density2 |
|
99 |
elif self.density_unit == 'lb/ft3': |
|
100 |
density2 = density2 * 0.062428 |
|
101 |
|
|
102 |
|
|
103 |
|
|
104 |
# (2) static P를 계산 |
|
105 |
# 1. density 받음 |
|
106 |
if self.density_unit == 'kg/m3': |
|
107 |
density2 = density2 |
|
108 |
elif self.density_unit == 'lb/ft3': |
|
109 |
density2 = density2 * 16.0185 |
|
110 |
|
|
111 |
# 2. elevation 받음 |
|
112 |
el1 = 200 # From쪽 Equipment의 Elevation |
|
113 |
el2 = 100 # To쪽 Equipment의 Elevation |
|
114 |
if self.length_unit == 'm': |
|
115 |
el1 = el1 |
|
116 |
el2 = el2 |
|
117 |
elif self.length_unit == "in": |
|
118 |
el1 = el1 * 0.0254 |
|
119 |
el2 = el2 * 0.0254 |
|
120 |
elif self.length_unit == "ft": |
|
121 |
el1 = el1 * 0.3048 |
|
122 |
el2 = el2 * 0.3048 |
|
123 |
elif self.length_unit == "yd": |
|
124 |
el1 = el1 * 0.9144 |
|
125 |
el2 = el2 * 0.9144 |
|
126 |
elif self.length_unit == "mm": |
|
127 |
el1 = el1 * 0.001 |
|
128 |
el2 = el2 * 0.001 |
|
129 |
elif self.length_unit == 'mile': |
|
130 |
el1 = el1 * 1609.34 |
|
131 |
el2 = el2 * 1609.34 |
|
132 |
|
|
133 |
# 3. static head 계산 |
|
134 |
# 'atm으로 계산된 dp |
|
135 |
stat_dp = (el2 - el1) * density2 / 1000 * 9.80665 / 101.325 |
|
136 |
|
|
137 |
# 4. 압력 유닛에 맞춰 뿌리기 |
|
138 |
if self.pressure_unit == 'kg/cm2': |
|
139 |
stat_dp = stat_dp * 1.033 |
|
140 |
elif self.pressure_unit == 'psi': |
|
141 |
stat_dp = stat_dp * 14.7 |
|
142 |
elif self.pressure_unit == 'atm': |
|
143 |
stat_dp = stat_dp |
|
144 |
elif self.pressure_unit == 'bar': |
|
145 |
stat_dp = stat_dp * 1.013 |
|
146 |
elif self.pressure_unit == 'mmHg': |
|
147 |
stat_dp = stat_dp * 1.013 |
|
148 |
elif self.pressure_unit == 'kPa': |
|
149 |
stat_dp = stat_dp * 101.325 |
|
150 |
elif self.pressure_unit == 'MPa': |
|
151 |
stat_dp = stat_dp * 0.101325 |
|
152 |
|
|
153 |
|
|
154 |
# '(3) pressure drop 계산 |
|
155 |
# 'vapor인 경우 압력강하를 계산해주고 넣어주는 모듈 |
|
156 |
|
|
157 |
# '입력된 vapor의 압력과 밀도를 가지고 끊어서 계산하는 factor를 적용했을때 length가 얼마나 나오는지 판별하는 것. |
|
158 |
ida = self._hmb.inside_pipe_size |
|
159 |
if self.pipe_diameter_unit == 'in': |
|
160 |
ida = ida * 0.0254 |
|
161 |
elif self.pipe_diameter_unit == 'mm': |
|
162 |
ida = ida / 1000 |
|
163 |
|
|
164 |
# 'mass 가져오기 기준 kg/h |
|
165 |
mass = self._hmb.flowrate_mass |
|
166 |
if self.flowrate_mass_unit == 'kg/h': |
|
167 |
mass = mass |
|
168 |
elif self.flowrate_mass_unit == 'g/min': |
|
169 |
mass = mass * 60 / 1000 |
|
170 |
elif self.flowrate_mass_unit == 'lb/h': |
|
171 |
mass = mass * 0.453592 |
|
172 |
elif self.flowrate_mass_unit == 't/h': |
|
173 |
mass = mass * 1000 |
|
174 |
|
|
175 |
# 'g 구하기 (kg/m2/s) |
|
176 |
g = mass / 3600 / (3.1415 * ida ** 2 / 4) |
|
177 |
|
|
178 |
# '속도 계산 (m/s) |
|
179 |
velocity = 4 * mass / density2 / 3.1415 / ida ** 2 / 3600 |
|
180 |
|
|
181 |
# 'k 가져오기 |
|
182 |
k = self._hmb.specific_heat_ratio |
|
183 |
|
|
184 |
# 'Mach Number 계산 |
|
185 |
mach = velocity / ((k * 9.80665 * 847.28 * temp / mw) ** 0.5) |
|
186 |
|
|
187 |
# '부피유량 계산 |
|
188 |
volume = mass / density2 |
|
189 |
|
|
190 |
# '현재 volume은 m3/h임. 부피유량 단위에 맞춰 뿌려줌 |
|
191 |
if self.flowrate_volume_unit == 'm3/h': |
|
192 |
volume = round(volume, 3) |
|
193 |
elif self.flowrate_volume_unit == 'l/min': |
|
194 |
volume = round(volume / 60 * 1000, 3) |
|
195 |
elif self.flowrate_volume_unit == 'ft3/h': |
|
196 |
volume = round(volume * 35.3147, 3) |
|
197 |
elif self.flowrate_volume_unit == 'USgpm': |
|
198 |
volume = round(volume * 4.40287, 3) |
|
199 |
elif self.flowrate_volume_unit == 'BPSD': |
|
200 |
volume = round(volume * 150.955, 3) |
|
201 |
|
|
202 |
viscosity = self._hmb.viscosity |
|
203 |
# ' viscosity 유닛 변환 (모두 kg/m.s로 바꿀것임) |
|
204 |
if self.viscosity_unit == 'kg/m.sec': |
|
205 |
viscosity = viscosity |
|
206 |
elif self.viscosity_unit == 'cP': |
|
207 |
viscosity = viscosity * 0.001 |
|
208 |
elif self.viscosity_unit == 'kg/m.h': |
|
209 |
viscosity = viscosity / 3600 |
|
210 |
elif self.viscosity_unit == 'lb/ft.sec': |
|
211 |
viscosity = viscosity * 1.48816 |
|
212 |
|
|
213 |
# 'density case에 따라 re계산 |
|
214 |
if self.density_unit == 'kg/m3': |
|
215 |
reynolds = ida * velocity * density2 / viscosity |
|
216 |
elif self.density_unit == 'lb/ft3': |
|
217 |
reynolds = ida * velocity * (density2 * 16.0185) / viscosity |
|
218 |
|
|
219 |
rough = self._hmb.roughness |
|
220 |
# 'roughness 를 m로 바꿔줌 |
|
221 |
if self.roughness_unit == 'm': |
|
222 |
rough = rough |
|
223 |
elif self.roughness_unit == 'ft': |
|
224 |
rough = rough * 0.3048 |
|
225 |
elif self.roughness_unit == 'in': |
|
226 |
rough = rough * 0.0254 |
|
227 |
elif self.roughness_unit == 'mm': |
|
228 |
rough = rough * 0.001 |
|
229 |
|
|
230 |
# ' reynolds수에 따라 Fanning/Chen friction factor 계산 |
|
231 |
if reynolds <= 2100: |
|
232 |
f = 4 * 16 / reynolds |
|
233 |
else: |
|
234 |
af = math.log(rough / ida / 3.7 + (6.7 / reynolds) ** 0.9) / math.log(10) |
|
235 |
f = (-2 * (math.log(rough / 3.7 / ida - 5.02 / reynolds * af) / math.log(10))) ** (-2) |
|
236 |
|
|
237 |
# '속도와 마하 수 입력 |
|
238 |
if self.velocity_unit == 'm/s': |
|
239 |
self._hmb.velocity = round(velocity, 3) |
|
240 |
elif self.velocity_unit == 'ft/s': |
|
241 |
self._hmb.velocity = round(velocity * 3.28084, 3) |
|
242 |
|
|
243 |
self._hmb.reynolds = round(mach, 5) |
|
244 |
|
|
245 |
|
|
246 |
press1est = press2 / 0.95 #HY_Calc_sht.Cells(2, 1) |
|
247 |
density1est = press1est * mw / 0.08206 / temp / z / 1.033 |
|
248 |
|
|
249 |
# ' 라인 길이 도출 (m) |
|
250 |
estlength = (((press1est ** 2 - press2 ** 2) * mw / g ** 2 / 0.08206 / 1.033 ** 2 / temp / z * 101325) - (2 * math.log(density1est / density2))) * ida / f |
|
251 |
|
|
252 |
# '라인 길이를 유닛에 맞춰서 변환 |
|
253 |
if self.length_unit == 'm': |
|
254 |
estlength = estlength |
|
255 |
elif self.length_unit == 'in': |
|
256 |
estlength = estlength * 39.3701 |
|
257 |
elif self.length_unit == 'ft': |
|
258 |
estlength = estlength * 3.28084 |
|
259 |
elif self.length_unit == 'yd': |
|
260 |
estlength = estlength * 1.09361 |
|
261 |
elif self.length_unit == 'mile': |
|
262 |
estlength = estlength * 0.000621371 |
|
263 |
elif self.length_unit == 'mm': |
|
264 |
estlength = estlength * 1000 |
|
265 |
|
|
266 |
if estlength > self._hmb.equivalent_length: |
|
267 |
# '주어진 길이를 가지고 압력 강하를 계산하는 모듈이 들어가야함 (safe) |
|
268 |
# ' length 여유 있음. 한번에 isothermal 식으로 계산 |
|
269 |
|
|
270 |
|
|
271 |
# ' 끊은 결과 length가 여유가 있음. 그래서 단순 계산하는 모듈 |
|
272 |
length = self._hmb.equivalent_length |
|
273 |
|
|
274 |
# 'length 를 m로 변환 |
|
275 |
if self.length_unit == 'm': |
|
276 |
length = length |
|
277 |
elif self.length_unit == 'in': |
|
278 |
length = length * 0.0254 |
|
279 |
elif self.length_unit == 'ft': |
|
280 |
length = length * 0.3048 |
|
281 |
elif self.length_unit == 'yd': |
|
282 |
length = length * 0.9144 |
|
283 |
elif self.length_unit == 'mile': |
|
284 |
length = length * 1609.34 |
|
285 |
elif self.length_unit == 'mm': |
|
286 |
length = length * 0.001 |
|
287 |
|
|
288 |
# 'Newton's Rule에 따라 |
|
289 |
press1 = self.vap_discharge_1(press2, g, mw, temp, f, z, ida, length) |
|
290 |
|
|
291 |
line_drop_press = 0 |
|
292 |
if self.pressure_unit == 'kg/cm2': |
|
293 |
line_drop_press = press1 - press2 |
|
294 |
elif self.pressure_unit == 'psi': |
|
295 |
line_drop_press = (press1 - press2) / 1.033 * 14.7 |
|
296 |
elif self.pressure_unit == 'atm': |
|
297 |
line_drop_press = (press1 - press2) / 1.033 |
|
298 |
elif self.pressure_unit == 'bar': |
|
299 |
line_drop_press = (press1 - press2) / 1.033 * 1.013 |
|
300 |
elif self.pressure_unit == 'mmHg': |
|
301 |
line_drop_press = (press1 - press2) / 1.033 * 760 |
|
302 |
elif self.pressure_unit == 'kPa': |
|
303 |
line_drop_press = (press1 - press2) / 1.033 * 101.325 |
|
304 |
elif self.pressure_unit == 'MPa': |
|
305 |
line_drop_press = (press1 - press2) / 1.033 * 0.101325 |
|
306 |
|
|
307 |
|
|
308 |
# 'Hole Calculation |
|
309 |
# 'cv와 pump가 다 없을때 (Hole Case) |
|
310 |
|
|
311 |
|
|
312 |
|
|
313 |
|
|
314 |
else: |
|
315 |
# '끊어서 계산하는 모듈이 들어가야함 |
|
316 |
# 'length 여유 없음. 압력 재계산->밀도 재계산->re, f 재계산->압력 재계산 체계로 가야함 |
|
317 |
dev = 1 |
|
318 |
|
|
319 |
|
|
320 |
def vap_discharge_1(self, p2, g, mw, temp, f, z, id, L_eq): |
|
321 |
R = 0.08206 |
|
322 |
|
|
323 |
Tmp_Const = 101325 * mw / (1.033 ** 2 * (g ** 2) * R * temp * z) |
|
324 |
Tmp_Const2 = id / f |
|
325 |
|
|
326 |
if self.pressure_unit == 'kg/cm2': |
|
327 |
const_iteration = 5 |
|
328 |
elif self.pressure_unit == 'psi': |
|
329 |
const_iteration = 75 |
|
330 |
elif self.pressure_unit == 'atm': |
|
331 |
const_iteration = 5 |
|
332 |
elif self.pressure_unit == 'bar': |
|
333 |
const_iteration = 5 |
|
334 |
elif self.pressure_unit == 'mmHg': |
|
335 |
const_iteration = 3800 |
|
336 |
elif self.pressure_unit == 'kPa': |
|
337 |
const_iteration = 506 |
|
338 |
elif self.pressure_unit == 'MPa': |
|
339 |
const_iteration = 0.5 |
|
340 |
|
|
341 |
x2 = p2 + const_iteration |
|
342 |
delta_x_past = 0 |
|
343 |
|
|
344 |
loop = True |
|
345 |
while loop: |
|
346 |
X = x2 |
|
347 |
f_x = (Tmp_Const2 * (Tmp_Const * (X ** 2 - p2 ** 2) - 2 * math.log(X / p2))) - L_eq |
|
348 |
df_x = 2 * Tmp_Const2 * (Tmp_Const * X - 1 / X) |
|
349 |
x2 = X - (f_x / df_x) |
|
350 |
delta_x = x2 - X |
|
351 |
if abs(delta_x_past) == abs(delta_x): |
|
352 |
break |
|
353 |
|
|
354 |
delta_x_past = delta_x |
|
355 |
|
|
356 |
if delta_x == 0 or x2 < 0: |
|
357 |
loop = False |
|
358 |
|
|
359 |
''' |
|
360 |
Do |
|
361 |
X = x2 |
|
362 |
f_x = (Tmp_Const2 * (Tmp_Const * (X ^ 2 - p2 ^ 2) - 2 * Log(X / p2))) - L_eq |
|
363 |
df_x = 2 * Tmp_Const2 * (Tmp_Const * X - 1 / X) |
|
364 |
x2 = X - (f_x / df_x) |
|
365 |
delta_x = x2 - X |
|
366 |
If Abs(delta_x_past) = Abs(delta_x) Then Exit Do |
|
367 |
delta_x_past = delta_x |
|
368 |
Loop Until delta_x = 0 Or x2 < 0 |
|
369 |
''' |
|
370 |
|
|
371 |
return x2 |
|
372 |
|
|
373 |
def calculation_Liquid(self): |
|
374 |
self._hmb.velocity = 2.889 |
|
375 |
|
|
376 |
def calculation_Mixed(self): |
|
377 |
self._hmb.velocity = 2.889 |
HYTOS/HYTOS/MainWindow.py | ||
---|---|---|
108 | 108 |
self.actionClose.triggered.connect(self.close) |
109 | 109 |
self.actionNew.triggered.connect(self.new_drawing) |
110 | 110 |
self.actionSave.triggered.connect(self.actionSaveCliked) |
111 |
self.actionCalculation.triggered.connect(self.calculation) |
|
111 | 112 |
self.actionLine.triggered.connect(self.onPlaceLine) |
112 | 113 |
self.actionConfiguration.triggered.connect(self.configuration) |
113 | 114 |
self.actionInitialize.triggered.connect(self.onInitializeScene) |
... | ... | |
669 | 670 |
self.dlgOptions = QOptionsDialog(self) |
670 | 671 |
self.dlgOptions.exec_() |
671 | 672 |
|
673 |
def calculation(self): |
|
674 |
from AppDocData import AppDocData |
|
675 |
from Calculation import Calculation |
|
676 |
|
|
677 |
try: |
|
678 |
appDocData = AppDocData.instance() |
|
679 |
if appDocData.imgName is None or appDocData.activeDrawing is None: |
|
680 |
self.showImageSelectionMessageBox() |
|
681 |
return |
|
682 |
|
|
683 |
hmbs = appDocData.activeDrawing.hmbTable._hmbs |
|
684 |
if hmbs is not None: |
|
685 |
try: |
|
686 |
self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100, self) if not hasattr(self, 'progress') else self.progress |
|
687 |
self.progress.setWindowModality(Qt.WindowModal) |
|
688 |
self.progress.setAutoReset(True) |
|
689 |
self.progress.setAutoClose(True) |
|
690 |
self.progress.setMinimum(0) |
|
691 |
self.progress.resize(600,100) |
|
692 |
self.progress.setWindowTitle(self.tr("Calculate data...")) |
|
693 |
self.progress.show() |
|
694 |
|
|
695 |
maxValue = len(hmbs) |
|
696 |
self.progress.setMaximum(maxValue) |
|
697 |
|
|
698 |
for hmb in hmbs: |
|
699 |
self.progress.setValue(self.progress.value() + 1) |
|
700 |
|
|
701 |
if hmb.phase_type: |
|
702 |
Calculation(hmb) |
|
703 |
|
|
704 |
QApplication.processEvents() |
|
705 |
|
|
706 |
self.load_HMB() |
|
707 |
finally: |
|
708 |
self.progress.setValue(self.progress.maximum()) |
|
709 |
self.progress.hide() |
|
710 |
|
|
711 |
except Exception as ex: |
|
712 |
message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
713 |
self.addMessage.emit(MessageType.Error, message) |
|
672 | 714 |
''' |
673 | 715 |
@brief configuration |
674 | 716 |
''' |
내보내기 Unified diff