Coverage for backend/pinch_service/OpenPinch/src/utils/heat_exchanger_eq.py: 5%
149 statements
« prev ^ index » next coverage.py v7.10.7, created at 2025-11-06 23:27 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2025-11-06 23:27 +0000
1import math
2from ..lib.enums import HeatExchangerTypes as HX
5def HX_Eff(Arrangement, Ntu, c, Passes=None, Rows=None, Cmin_Phase=None):
6 if Passes == None:
7 Passes = 1
9 Ntu = Ntu / Passes
10 if Ntu > 0 and c >= 0:
11 # Counter Flow - Single Pass Effectiveness
12 if Arrangement == HX.CF.value:
13 # test = c * math.exp(-Ntu * (1 - c))
14 if c != 1 and c * math.exp(-Ntu * (1 - c)) != 1:
15 eff = (1 - math.exp(-Ntu * (1 - c))) / (1 - c * math.exp(-Ntu * (1 - c)))
16 else:
17 eff = Ntu / (1 + Ntu)
18 # Parallel Flow - Single Pass Effectiveness
19 elif Arrangement == HX.PF.value:
20 eff = (1 - math.exp(-Ntu * (1 + c))) / (1 + c)
21 # Cross Flow - Both Streams Unmixed Effectiveness
22 elif Arrangement == HX.CrFUU:
23 if Rows == None or Cmin_Phase == None:
24 eff = CrossflowUnmixedEff1(Ntu, c)
25 else:
26 eff = CrossflowUnmixedEff2(Ntu, c, Rows, Cmin_Phase)
27 # Cross Flow - Both Streams Mixed Effectiveness
28 elif Arrangement == HX.CrFMM:
29 eff = (1 / (1 - math.exp(-Ntu)) + c / (1 - math.exp(-Ntu * c)) - 1 / Ntu) ** -1
30 # Cross Flow - Stream Cmax Unmixed Effectiveness
31 elif Arrangement == HX.CrFMUmax:
32 eff = 1 - math.exp(-1 / c * (1 - math.exp(-Ntu * c)))
33 # Cross Flow - Stream Cmin Unmixed Effectiveness
34 elif Arrangement == HX.CrFMUmin:
35 eff = 1 / c * (1 - math.exp(-c * (1 - math.exp(-Ntu))))
36 # Shell and Tube - One Shell Pass; 2,4,6, etc., Tube Passes Effectiveness
37 elif Arrangement == HX.ShellTube.value:
38 d = (1 + c ** 2) ** 0.5
39 eff = 2 / ((1 + c) + d ** 0.5 * Coth(Ntu * d / 2))
40 # Condensing or Evaporating of One Fluid
41 elif Arrangement == HX.CondEvap:
42 eff = 1 - math.exp(-Ntu)
43 else:
44 eff = HX_Eff(HX.CF.value, Ntu, c, 1)
45 else:
46 eff = 0
48 if Passes > 1:
49 Eff_p = eff
50 return MultiPassEff(Eff_p, c, Passes)
51 else:
52 return eff
55def HX_NTU(Arrangement, eff, c, Passes=None):
56 if Passes == None:
57 Passes = 1
59 if Passes > 1:
60 Eff_p = MultiPassNTU(eff, c, Passes)
61 eff = Eff_p
63 if eff > 0 and eff < 1:
64 # Counter Flow - Single Pass Effectiveness
65 if Arrangement == HX.CF.value:
66 if c != 1:
67 Ntu = 1 / (1 - c) * math.log((1 - eff * c) / (1 - eff))
68 else:
69 Ntu = eff / (1 - eff)
70 # Parallel Flow - Single Pass Effectiveness
71 elif Arrangement == HX.PF.value:
72 Ntu = -math.log(1 - eff * (1 + c)) / (1 + c)
73 # Cross Flow - Both Streams Unmixed NTU
74 elif Arrangement == HX.CrFUU:
75 Ntu = HX_NTU_Numerical(Arrangement, eff, c)
76 # Cross Flow - Both Streams Mixed NTU
77 elif Arrangement == HX.CrFMM:
78 Ntu = HX_NTU_Numerical(Arrangement, eff, c)
79 # Cross Flow - Stream Cmax Unmixed NTU
80 elif Arrangement == HX.CrFMUmax:
81 Ntu = -1 / c * math.log(1 + c * math.log(1 - eff))
82 # Cross Flow - Stream Cmin Unmixed NTU
83 elif Arrangement == HX.CrFMUmin:
84 Ntu = -math.log(1 + 1 / c * math.log(1 - eff * c))
85 # Shell and Tube - One Shell Pass; 2,4,6, etc., Tube Passes NTU
86 elif Arrangement == HX.ShellTube.value:
87 D1 = 1 + c - (1 + c ** 2) ** (1 / 4)
88 D2 = 1 + c + (1 + c ** 2) ** (1 / 4)
89 Ntu = (1 + c ** 2) ** -0.5 * math.log((2 - eff * D1) / (2 - eff * D2))
90 # Condensing or Evaporating of One Fluid
91 elif Arrangement == HX.CondEvap:
92 Ntu = -math.log(1 - eff)
93 else:
94 Ntu = -1
95 else:
96 Ntu = 0
98 return Ntu * Passes
101def CalcAreaUE(Arrangement, U, C_p, T_p1, T_p2, T_u1, T_u2, Passes):
102 Q = C_p * abs(T_p1 - T_p2)
103 C_u = Q / abs(T_u1 - T_u2)
104 if C_p < C_u:
105 eff = Q / C_p / abs(T_p1 - T_u1)
106 c = C_p / C_u
107 Ntu = HX_NTU(Arrangement, eff, c, Passes)
108 return Ntu * C_p / U
109 else:
110 eff = Q / C_u / abs(T_p1 - T_u1)
111 c = C_u / C_p
112 Ntu = HX_NTU(Arrangement, eff, c, Passes)
113 return Ntu * C_u / U
116def eNTU_slope_Numerical(Arrangement, Ntu, c, Passes):
117 dx = 1e-6
118 if Ntu > 0:
119 return (HX_Eff(Arrangement, Ntu + dx, c, Passes) - HX_Eff(Arrangement, Ntu, c, Passes)) / dx
122def Coth(R):
123 return (math.exp(2 * R) + 1) / (math.exp(2 * R) - 1)
126def MultiPassEff(eff, c, Passes):
127 if c != 1:
128 return (((1 - eff * c) / (1 - eff)) ** Passes - 1) / (((1 - eff * c) / (1 - eff)) ** Passes - c)
129 else:
130 return Passes * eff / (1 + eff * (Passes - 1))
133def MultiPassNTU(Eff_p, c, Passes):
134 if c != 1:
135 return (((1 - Eff_p * c) / (1 - Eff_p)) ** (1 / Passes) - 1) / (((1 - Eff_p * c) / (1 - Eff_p)) ** (1 / Passes) - c)
136 else:
137 return Eff_p / (Passes - Eff_p * (Passes - 1))
140def CrossflowUnmixedEff1(Ntu, c):
141 Sum_Pn = 0
142 for i in range(1, 21):
143 Pn = 0
144 for j in range(1, i):
145 Pn = Pn + c ** i / math.factorial(i + 1) * (i - j + 1) / math.factorial(j) * Ntu ** (i + j)
146 Sum_Pn = Sum_Pn + Pn
147 return 1 - math.exp(-Ntu) - math.exp(-(1 + c) * Ntu) * Sum_Pn
150def CrossflowUnmixedEff2(Ntu, c, Rows, Cmin_fluid):
151 # ESDU 86018
152 if Cmin_fluid == 'Air':
153 if Rows == 1:
154 eff = 1 / c * (1 - math.exp(-c * (1 - math.exp(-Ntu))))
155 elif Rows == 2:
156 k = 1 - math.exp(-Ntu / 2)
157 eff = 1 / c * (1 - math.exp(-2 * k * c) * (1 + c * k ** 2))
158 elif Rows == 3:
159 k = 1 - math.exp(-Ntu / 3)
160 eff = 1 / c * (1 - math.exp(-3 * k * c) * (1 + c * k ** 2 * (3 - k) + (3 * c ** 2 * k ** 4) / 2))
161 elif Rows == 4:
162 k = 1 - math.exp(-Ntu / 4)
163 eff = 1 / c * (1 - math.exp(-4 * k * c) * (1 + c * k ** 2 * (6 - 4 * k + k ** 2) + 4 * c ** 2 * k ** 4 * (2 - k) + (8 * c ** 3 * k ** 6) / 3))
164 elif Rows > 4:
165 eff = CrossflowUnmixedEff1(Ntu, c)
166 else:
167 if Rows == 1:
168 eff = 1 - math.exp(-1 / c * (1 - math.exp(-Ntu * c)))
169 elif Rows == 2:
170 k = 1 - math.exp(-Ntu * c / 2)
171 eff = 1 - math.exp(-2 * k / c) * (1 + (k ** 2) / c)
172 elif Rows == 3:
173 k = 1 - math.exp(-Ntu * c / 3)
174 eff = 1 - math.exp(-3 * k / c) * (1 + k ** 2 * (3 - k) / c + (3 * k ** 4) / (2 * c ** 2))
175 elif Rows == 4:
176 k = 1 - math.exp(-Ntu * c / 4)
177 eff = 1 - math.exp(-4 * k / c) * (1 + k ** 2 * (6 - 4 * k + k ** 2) / c + 4 * k ** 4 * (2 - k) / c ** 2 + (8 * k ** 6) / (3 * c ** 3))
178 elif Rows > 4:
179 eff = CrossflowUnmixedEff1(Ntu, c)
181 return eff
184def HX_NTU_Numerical(Arrangement, eff, c):
185 NTU1 = 0.001
186 NTU2 = 0.1
187 eps = 1e-5
188 f = 100.0
189 count = 1
190 F1 = eff - HX_Eff(Arrangement, NTU1, c)
191 F2 = eff - HX_Eff(Arrangement, NTU2, c)
192 while f > eps:
193 a = (F1 - F2) / (NTU1 - NTU2)
194 b = F1 - a * NTU1
195 NTU3 = -b / a
196 F3 = eff - HX_Eff(Arrangement, NTU3, c)
197 f = abs(F3)
198 NTU1 = NTU2
199 F1 = F2
200 NTU2 = NTU3
201 F2 = F3
202 count += 1
203 if count > 50:
204 raise ValueError('Solution does not converge')
206 return NTU3