turbo-design 1.3.8__py3-none-any.whl → 1.3.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of turbo-design might be problematic. Click here for more details.

Files changed (48) hide show
  1. {turbo_design-1.3.8.dist-info → turbo_design-1.3.9.dist-info}/METADATA +2 -1
  2. turbo_design-1.3.9.dist-info/RECORD +46 -0
  3. {turbo_design-1.3.8.dist-info → turbo_design-1.3.9.dist-info}/WHEEL +1 -1
  4. turbodesign/__init__.py +57 -4
  5. turbodesign/agf.py +346 -0
  6. turbodesign/arrayfuncs.py +31 -1
  7. turbodesign/bladerow.py +237 -155
  8. turbodesign/compressor_math.py +374 -0
  9. turbodesign/compressor_spool.py +837 -0
  10. turbodesign/coolant.py +18 -6
  11. turbodesign/deviation/__init__.py +5 -0
  12. turbodesign/deviation/axial_compressor.py +3 -0
  13. turbodesign/deviation/carter_deviation.py +79 -0
  14. turbodesign/deviation/deviation_base.py +20 -0
  15. turbodesign/deviation/fixed_deviation.py +42 -0
  16. turbodesign/enums.py +5 -6
  17. turbodesign/flow_math.py +159 -0
  18. turbodesign/inlet.py +126 -56
  19. turbodesign/isentropic.py +59 -15
  20. turbodesign/loss/__init__.py +3 -1
  21. turbodesign/loss/compressor/OTAC_README.md +39 -0
  22. turbodesign/loss/compressor/__init__.py +54 -0
  23. turbodesign/loss/compressor/diffusion.py +61 -0
  24. turbodesign/loss/compressor/lieblein.py +1 -0
  25. turbodesign/loss/compressor/otac.py +799 -0
  26. turbodesign/loss/compressor/references/schobeiri-2012-shock-loss-model-for-transonic-and-supersonic-axial-compressors-with-curved-blades.pdf +0 -0
  27. turbodesign/loss/fixedpolytropic.py +27 -0
  28. turbodesign/loss/fixedpressureloss.py +30 -0
  29. turbodesign/loss/losstype.py +2 -30
  30. turbodesign/loss/turbine/TD2.py +25 -29
  31. turbodesign/loss/turbine/__init__.py +0 -1
  32. turbodesign/loss/turbine/ainleymathieson.py +6 -5
  33. turbodesign/loss/turbine/craigcox.py +6 -5
  34. turbodesign/loss/turbine/fixedefficiency.py +8 -7
  35. turbodesign/loss/turbine/kackerokapuu.py +7 -5
  36. turbodesign/loss/turbine/traupel.py +17 -16
  37. turbodesign/outlet.py +81 -22
  38. turbodesign/passage.py +98 -63
  39. turbodesign/row_factory.py +129 -0
  40. turbodesign/solve_radeq.py +9 -10
  41. turbodesign/{td_math.py → turbine_math.py} +126 -175
  42. turbodesign/turbine_spool.py +984 -0
  43. turbo_design-1.3.8.dist-info/RECORD +0 -33
  44. turbodesign/compressorspool.py +0 -60
  45. turbodesign/loss/turbine/fixedpressureloss.py +0 -25
  46. turbodesign/rotor.py +0 -38
  47. turbodesign/spool.py +0 -317
  48. turbodesign/turbinespool.py +0 -543
@@ -1,86 +1,17 @@
1
- from typing import List, Optional
1
+ from typing import List, Optional, Tuple
2
+ import warnings
2
3
  import numpy as np
3
4
  import numpy.typing as npt
5
+ from .isentropic import IsenP, IsenT
6
+ from turbodesign.loss import losstype
4
7
  from .bladerow import BladeRow, compute_gas_constants
5
8
  from .enums import RowType, LossType
9
+ from .outlet import OutletType
6
10
  from scipy.integrate import trapezoid
11
+ from scipy.optimize import minimize
7
12
  from .passage import Passage
8
13
  from .isentropic import IsenP
9
-
10
- def T0_coolant_weighted_average(row:BladeRow) -> float:
11
- """Calculate the new weighted Total Temperature array considering coolant
12
-
13
- Args:
14
- coolant (Coolant): Coolant
15
- massflow (np.ndarray): massflow mainstream
16
-
17
- Returns:
18
- float: Total Temperature drop
19
- """
20
-
21
- massflow = row.massflow
22
- total_massflow_no_coolant = row.total_massflow_no_coolant
23
- Cp = row.Cp
24
-
25
- Cpc = row.coolant.Cp
26
- T0c = row.coolant.T0
27
- massflow_coolant = row.coolant.massflow_percentage*total_massflow_no_coolant*row.massflow[1:]/row.massflow[-1]
28
- if massflow_coolant.mean()>0:
29
- if row.row_type == RowType.Stator:
30
- T0= row.T0
31
- dT0 = T0.copy() * 0
32
- T0_new = (massflow[1:]*Cp*T0[1:] + massflow_coolant*Cpc*T0c) \
33
- /(massflow[1:]*Cp + massflow_coolant*Cpc)
34
- dT0[1:] = T0_new - row.T0[1:]
35
- dT0[0] = dT0[1]
36
- else:
37
- T0R = row.T0R
38
- T0R_new = T0R.copy()
39
- Cp = row.Cp
40
- T0R_new[1:] = (massflow[1:]*Cp*T0R[1:] + massflow_coolant*Cpc*T0c) \
41
- /(massflow[1:]*Cp + massflow_coolant*Cpc)
42
- T0R_new[0] = T0R_new[1]
43
-
44
- T = T0R_new - row.W**2/(2*Cp) # Dont change the velocity triangle but adjust the static temperature
45
- T0_new = T+row.V**2/(2*Cp) # Use new static temperature to calculate the total temperature
46
- dT0 = T0_new - row.T0
47
- return dT0
48
- else:
49
- return row.T0*0
50
-
51
- def compute_massflow(row:BladeRow) -> None:
52
- """Populates row.massflow and row.calculated_massflow
53
-
54
- Calculated_massflow is massflow[-1]
55
-
56
- Args:
57
- row (BladeRow): current blade row. All quantities are at exit
58
- upstream (BladeRow): upstream blade row. All quantities are at exit
59
- """
60
- massflow_fraction = np.linspace(0,1,len(row.percent_hub_shroud))
61
- massflow = row.percent_hub_shroud*0
62
- total_area = 0
63
- for j in range(1,len(row.percent_hub_shroud)):
64
- Vm = (row.Vm[j]+row.Vm[j-1])/2
65
- rho = (row.rho[j]+row.rho[j-1])/2
66
- if np.abs((row.x[j]-row.x[j-1]))<1E-5: # Axial Machines
67
- total_area += np.pi*(row.r[j]**2-row.r[j-1]**2)
68
- massflow[j] = Vm * rho * np.pi* (row.r[j]**2-row.r[j-1]**2) + massflow[j-1]
69
- else: # Radial Machines
70
- dx = row.x[j]-row.x[j-1]
71
- S = (row.r[j]-row.r[j-1])
72
- C = np.sqrt(1+((row.r[j]-row.r[j-1])/dx)**2)
73
- area = 2*np.pi*C*(S/2*dx**2+row.r[j-1]*dx)
74
- total_area += area
75
- massflow[j] = Vm * rho *area + massflow[j-1]
76
-
77
- row.total_massflow_no_coolant = massflow[-1]
78
- if row.coolant != None:
79
- massflow += massflow_fraction*row.coolant.massflow_percentage*row.total_massflow_no_coolant # Take into account the coolant massflow
80
- row.massflow = massflow
81
- row.calculated_massflow = massflow[-1]
82
- row.total_massflow = massflow[-1]
83
- row.area = total_area
14
+ from .flow_math import compute_massflow, compute_streamline_areas, compute_power
84
15
 
85
16
  def compute_reynolds(rows:List[BladeRow],passage:Passage):
86
17
  """Calculates the Reynolds Number
@@ -110,34 +41,6 @@ def compute_reynolds(rows:List[BladeRow],passage:Passage):
110
41
  row.axial_chord = max(c,1E-12) # Axial chord
111
42
  # row.num_blades = int(2*np.pi*row.r.mean() / row.pitch_to_chord * row.axial_chord)
112
43
 
113
- def compute_power(row:BladeRow,upstream:BladeRow) -> None:
114
- """Calculates the power
115
-
116
- Args:
117
- row (BladeRow): _description_
118
- upstream (BladeRow): _description_
119
- """
120
- if row.row_type == RowType.Stator:
121
- row.power = 0
122
- row.eta_static = 0
123
- row.eta_total = 0
124
- row.stage_loading = 0
125
- row.euler_power = 0
126
- row.T_is = 0 * row.T0
127
- row.T0_is = 0 * row.T0 # Make it an array
128
- else:
129
- P0_P = (upstream.P0/row.P).mean()
130
- row.T_is = upstream.T0 * (1/P0_P)**((row.gamma-1)/row.gamma)
131
- a = np.sqrt(row.gamma*row.R*row.T_is)
132
- row.T0_is = row.T_is * (1+(row.gamma-1)/2*(row.V/a)**2)
133
-
134
- row.power = row.massflow[-1] * (row.Cp * (upstream.T0 - row.T0)).mean()
135
- # row.power = sum(v * w for v, w in zip(row.power[1:], np.diff(row.massflow))) # Massflow weighted average
136
- row.eta_static = row.power/ (row.massflow[-1]*row.Cp*(upstream.T0.mean()-row.T_is.mean()))
137
- row.eta_total = (upstream.T0.mean() - row.T0.mean()) / (upstream.T0.mean() - row.T0_is.mean())
138
- row.stage_loading = row.Cp*(upstream.T0.mean() - row.T0.mean())/row.U.mean()**2
139
- row.euler_power = row.massflow[-1]* (upstream.U*upstream.Vt - row.U*row.Vt).mean()
140
-
141
44
  def compute_quantities(row:BladeRow,upstream:BladeRow):
142
45
  """Calculation of all quantites after radial equilibrium has been solved assuming we know the static pressure at the exit.
143
46
 
@@ -151,14 +54,14 @@ def compute_quantities(row:BladeRow,upstream:BladeRow):
151
54
  row (BladeRow): current blade row. All quantities are at exit
152
55
  upstream (BladeRow): upstream blade row. All quantities are at exit
153
56
  """
154
-
155
57
  if row.row_type == RowType.Rotor:
156
58
  Cp_avg = (row.Cp+upstream.Cp)/2
157
59
  # Factor any coolant added and changes in streamline radius
158
60
  row.T0R = upstream.T0R - T0_coolant_weighted_average(row) # - (upstream.U**2-row.U**2)/(2*Cp_avg)
159
61
  row.P = upstream.P0_stator_inlet/row.P0_P
160
-
161
- if row.loss_function.loss_type == LossType.Pressure:
62
+
63
+ loss_type = getattr(row.loss_function, "loss_type", None)
64
+ if loss_type == LossType.Pressure:
162
65
  # This affects the velocity triangle
163
66
  row.P0R = upstream.P0R - row.Yp*(upstream.P0R-row.P)
164
67
  row.T = (row.P/row.P0R)**((row.gamma-1)/row.gamma) * row.T0R
@@ -167,7 +70,7 @@ def compute_quantities(row:BladeRow,upstream:BladeRow):
167
70
  row.power = np.trapezoid(row.power_distribution,row.r-row.r[0])
168
71
  row.power_mean = row.massflow[-1] * row.Cp * (upstream.T0.mean()-row.T0.mean())
169
72
 
170
- elif row.loss_function.loss_type == LossType.Enthalpy:
73
+ elif loss_type == LossType.Enthalpy:
171
74
  ' For Enthalpy related loss, assume the static quantities do not change '
172
75
  row.T = (row.P/row.P0R)**((row.gamma-1)/row.gamma) * row.T0R
173
76
  row.T0 = (1+(row.gamma-1)/2 * row.M**2) * row.T
@@ -195,7 +98,8 @@ def compute_quantities(row:BladeRow,upstream:BladeRow):
195
98
 
196
99
  elif row.row_type == RowType.Stator:
197
100
  ' For the stator we already assume the upstream P0 already applied '
198
- if row.loss_function == LossType.Pressure:
101
+ loss_type = getattr(row.loss_function, "loss_type", None)
102
+ if loss_type == LossType.Pressure:
199
103
  row.P0 = upstream.P0 - row.Yp*(upstream.P0-row.P)
200
104
  else:
201
105
  row.P0 = upstream.P0
@@ -205,32 +109,45 @@ def compute_quantities(row:BladeRow,upstream:BladeRow):
205
109
  row.T0R = row.T + row.W**2 / (2*row.Cp)
206
110
  row.P0R = row.P*(row.T0R/row.T)**((row.gamma)/(row.gamma-1))
207
111
 
208
- def stator_calc(row:BladeRow,upstream:BladeRow,downstream:Optional[BladeRow]=None,calculate_vm:bool=True):
112
+ def stator_calc(row:BladeRow,upstream:BladeRow,downstream:Optional[BladeRow]=None,calculate_vm:bool=True, outlet_type:OutletType=OutletType.static_pressure):
209
113
  """Given P0, T0, P, alpha2 of stator calculate all other quantities
210
114
 
211
115
  Usage:
212
116
  Set row.P0 = upstream.P0 - any pressure loss
213
117
  row.T0 = upstream.T0 - any cooling
214
- row.P = row.rp*(row.P0 - rotor.P) + rotor.P
215
- Set alpha2
216
-
118
+ row.P = row.rp*(row.P0 - rotor.P) + rotor.P
119
+ Set alpha2
120
+
217
121
  Args:
218
122
  row (BladeRow): Stator Row
219
- upstream (BladeRow): Stator or Rotor Row
123
+ upstream (BladeRow): Stator or Rotor Row
220
124
  downstream (BladeRow): Stator or Rotor Row. Defaults to None
221
-
125
+ calculate_vm (bool): True to calculate the meridional velocity. False, do not calculate this and let radeq calculate it
126
+ outlet_type (OutletType): OutletType.static_pressure if static conditions defined at outlet, OutletType.total_pressure if total conditions defined
222
127
  """
223
- ## degree of reaction (rp) is assumed
224
- # downstream.P = upstream.P0 * 1/downstream.P0_P
225
- # if downstream is not None:
226
- # # Use the upstream P0 value then later factor in the loss
227
- # row.P = downstream.rp*(upstream.P0 - downstream.P) + downstream.P
228
- # else:
229
- # row.P = upstream.P
230
-
231
- # Static Pressure is assumed
232
- row.P0 = upstream.P0 - row.Yp*(upstream.P0-row.P)
233
-
128
+
129
+ # Static Pressure is assumed
130
+ T0_coolant = 0
131
+ if row.coolant is not None:
132
+ T0_coolant = T0_coolant_weighted_average(row)
133
+ row.T0 = upstream.T0 - T0_coolant
134
+
135
+ loss_type = getattr(row.loss_function, "loss_type", None)
136
+ if loss_type == LossType.Pressure:
137
+ row.P0 = upstream.P0 - row.Yp*(upstream.P0-row.P) # When static conditions are defined, use it to calculate P0
138
+
139
+
140
+ elif loss_type == LossType.Enthalpy:
141
+ b = row.total_area * row.P0 / np.sqrt(row.T0) * np.sqrt(row.gamma/row.R)
142
+ solve_for_M = upstream.total_massflow / b
143
+ fun = lambda M : np.abs(solve_for_M - M*(1+(row.gamma-1)/2 * M**2) ** (-(row.gamma+1)/(2*(row.gamma-1))))
144
+ M_subsonic = minimize(fun,0.1, method='L-BFGS-B', bounds=[0,1])
145
+ M_supersonic = minimize(fun,1.5, method='L-BFGS-B', bounds=[1,5])
146
+ row.M = M_subsonic
147
+ row.T = row.T0/IsenT(M_subsonic,row.gamma)
148
+ a = np.sqrt(row.T*row.gamma*row.R)
149
+ row.P = row.total_massflow * row.R*row.T / (row.total_area * row.M * a) # Use the massflow to find static pressure
150
+
234
151
  if downstream is not None:
235
152
  row.P0_P = float((row.P0/downstream.P).mean())
236
153
  row.rp = ((row.P-downstream.P)/(upstream.P0-downstream.P)).mean()
@@ -239,7 +156,6 @@ def stator_calc(row:BladeRow,upstream:BladeRow,downstream:Optional[BladeRow]=Non
239
156
  row.M = ((row.P0/row.P)**((row.gamma-1)/row.gamma) - 1) * 2/(row.gamma-1)
240
157
  row.M = np.sqrt(row.M)
241
158
  T0_T = (1+(row.gamma-1)/2 * row.M**2)
242
- row.T0 = upstream.T0 - T0_coolant_weighted_average(row)
243
159
  row.T = row.T0/T0_T
244
160
  row.V = row.M*np.sqrt(row.gamma*row.R*row.T)
245
161
  row.Vm = row.V*np.cos(row.alpha2)
@@ -251,7 +167,6 @@ def stator_calc(row:BladeRow,upstream:BladeRow,downstream:Optional[BladeRow]=Non
251
167
  row.Vr = row.Vm*np.sin(row.phi)
252
168
  row.Vt = row.Vm*np.tan(row.alpha2)
253
169
  row.V = np.sqrt(row.Vx**2 + row.Vr**2 + row.Vt**2)
254
-
255
170
  row.T = row.P/(row.R*row.rho) # We know P, this is a guess
256
171
  row.M = row.V/np.sqrt(row.gamma*row.R*row.T)
257
172
 
@@ -263,12 +178,14 @@ def stator_calc(row:BladeRow,upstream:BladeRow,downstream:Optional[BladeRow]=Non
263
178
  row.Wt = row.Vt-row.U
264
179
  row.P0_stator_inlet = upstream.P0
265
180
 
266
- def rotor_calc(row:BladeRow,upstream:BladeRow,calculate_vm:bool=True):
267
- """Calculates quantities given beta2
181
+ def rotor_calc(row:BladeRow,upstream:BladeRow,calculate_vm:bool=True,outlet_type:OutletType=OutletType.static_pressure):
182
+ """Calculates quantities given beta2
268
183
 
269
184
  Args:
270
185
  row (BladeRow): Rotor Row
271
186
  upstream (BladeRow): Stator Row or Rotor Row
187
+ calculate_vm (bool): True to calculate the meridional velocity. False, do not calculate this and let radeq calculate it
188
+ outlet_type (OutletType): OutletType.static_pressure if static conditions defined at outlet, OutletType.total_pressure if total conditions defined
272
189
  """
273
190
  def _log_rotor_failure(reason:str):
274
191
  def _fmt(val):
@@ -294,10 +211,7 @@ def rotor_calc(row:BladeRow,upstream:BladeRow,calculate_vm:bool=True):
294
211
  ## P0_P is assumed
295
212
  # row.P = row.P0_stator_inlet*1/row.P0_P
296
213
 
297
- # Static Pressure is assumed
298
- row.P0_P = (row.P0_stator_inlet/row.P).mean()
299
214
  upstream_radius = upstream.r
300
- row.U = row.omega*row.r
301
215
  # Upstream Relative Frame Calculations
302
216
  upstream.U = upstream.rpm*np.pi/30 * upstream_radius # rad/s
303
217
  upstream.Wt = upstream.Vt - upstream.U
@@ -306,17 +220,23 @@ def rotor_calc(row:BladeRow,upstream:BladeRow,calculate_vm:bool=True):
306
220
  upstream.T0R = upstream.T+upstream.W**2/(2*upstream.Cp)
307
221
  upstream.P0R = upstream.P * (upstream.T0R/upstream.T)**((upstream.gamma)/(upstream.gamma-1))
308
222
  upstream.M_rel = upstream.W/np.sqrt(upstream.gamma*upstream.R*upstream.T)
309
-
310
223
  upstream_rothalpy = upstream.T0R*upstream.Cp - 0.5*upstream.U**2 # H01R - 1/2 U1^2
224
+ row.U = row.omega*row.r
225
+
311
226
  if np.any(upstream_rothalpy < 0):
312
227
  print('U is too high, reduce RPM or radius')
228
+
313
229
  # Rotor Exit Calculations
314
230
  row.beta1 = upstream.beta2
315
231
  #row.Yp # Evaluated earlier
316
232
  row.P0R = upstream.P0R - row.Yp*(upstream.P0R-row.P)
317
-
233
+
234
+
318
235
  # Total Relative Temperature stays constant through the rotor. Adjust for change in radius from rotor inlet to exit
319
- row.T0R = upstream.T0R # (upstream_rothalpy + 0.5*row.U**2)/row.Cp # - T0_coolant_weighted_average(row)
236
+ T0_coolant = 0
237
+ if row.coolant is not None:
238
+ T0_coolant = T0_coolant_weighted_average(row)
239
+ row.T0R = upstream.T0R - T0_coolant # (upstream_rothalpy + 0.5*row.U**2)/row.Cp # - T0_coolant_weighted_average(row)
320
240
  P0R_P = row.P0R / row.P
321
241
  T0R_T = P0R_P**((row.gamma-1)/row.gamma)
322
242
  row.T = (row.T0R/T0R_T) # Exit static temperature
@@ -343,7 +263,6 @@ def rotor_calc(row:BladeRow,upstream:BladeRow,calculate_vm:bool=True):
343
263
  row.M = row.V/np.sqrt(row.gamma*row.R*row.T)
344
264
  row.Vm = np.sqrt(row.Vx**2+row.Vr**2)
345
265
  row.T0 = row.T + row.V**2/(2*row.Cp)
346
- row.P0 = row.P*(row.T0/row.T)**(row.gamma/(row.gamma-1))
347
266
  row.alpha2 = np.arctan2(row.Vt,row.Vm)
348
267
  else: # We know Vm, P0, T0
349
268
  row.Vr = row.Vm*np.sin(row.phi)
@@ -352,15 +271,16 @@ def rotor_calc(row:BladeRow,upstream:BladeRow,calculate_vm:bool=True):
352
271
  row.W = np.sqrt(2*row.Cp*(row.T0R-row.T))
353
272
  row.Wt = row.W*np.sin(row.beta2)
354
273
  row.U = row.omega * row.r
355
- row.Vt = row.Wt+row.U
274
+ row.Vt = row.Wt + row.U
356
275
 
357
276
  row.alpha2 = np.arctan2(row.Vt,row.Vm)
358
277
  row.V = np.sqrt(row.Vm**2*(1+np.tan(row.alpha2)**2))
359
278
 
360
279
  row.M = row.V/np.sqrt(row.gamma*row.R*row.T)
361
- T0_T = (1+(row.gamma-1)/2 * row.M**2)
362
- row.P0 = row.P * T0_T**(row.gamma/(row.gamma-1))
363
-
280
+ T0_T = (1+(row.gamma-1)/2 * row.M**2)
281
+ row.P0 = row.P * T0_T**(row.gamma/(row.gamma-1))
282
+ row.P0_P = (row.P0_stator_inlet/row.P).mean()
283
+
364
284
  row.M_rel = row.W/np.sqrt(row.gamma*row.R*row.T)
365
285
  row.T0 = row.T+row.V**2/(2*row.Cp)
366
286
 
@@ -370,40 +290,71 @@ def inlet_calc(row:BladeRow):
370
290
  Args:
371
291
  row (BladeRow): _description_
372
292
  """
373
-
374
- area = row.Vm.copy()*0
375
293
  # Estimate the density
376
- row.T = row.T0
377
- row.P = row.P0
378
- row.rho = row.P/(row.T*row.R)
379
- total_area = 0
380
- for iter in range(5): # Lets converge the Mach and Total and Static pressures
381
- for j in range(1,len(row.percent_hub_shroud)):
382
- rho = row.rho[j]
383
- tube_massflow = row.massflow[j]-row.massflow[j-1]
384
- if np.abs((row.x[j]-row.x[j-1]))<1E-6: # Axial Machines
385
- total_area += np.pi*(row.r[j]**2-row.r[j-1]**2)
386
- row.Vm[j] = tube_massflow/(rho*np.pi*(row.r[j]**2-row.r[j-1]**2))
387
- else: # Radial Machines
388
- dx = row.x[j]-row.x[j-1]
389
- S = (row.r[j]-row.r[j-1])
390
- C = np.sqrt(1+((row.r[j]-row.r[j-1])/dx)**2)
391
- area[j] = 2*np.pi*C*(S/2*dx**2+row.r[j-1]*dx)
392
- total_area += area[j]
393
- row.Vm[j] = tube_massflow/(rho*area[j])
394
- avg_mach = np.mean(row.M)
395
- row.Vm[0] = 1/(len(row.Vm)-1)*row.Vm[1:].sum() # Initialize the value at the hub to not upset the mean
396
- row.Vr = row.Vm*np.sin(row.phi)
397
- row.Vt = row.Vm*np.tan(row.alpha2)
398
- row.V = np.sqrt(row.Vt**2+row.Vm**2)
399
- # Fine tune the Temperature and Pressure and density
400
- row.M = row.V/np.sqrt(row.gamma*row.R*row.T)
401
- row.T = row.T0 * 1/(1+(row.gamma-1)/2*row.M**2)
402
- row.P = row.P0 * (row.T/row.T0)**(row.gamma/(row.gamma-1))
403
- compute_gas_constants(row)
294
+ row.T = row.T0 * 1/(1+(row.gamma-1)/2*row.M**2)
295
+ row.P = row.P0 * (row.T/row.T0)**(row.gamma/(row.gamma-1))
296
+ compute_gas_constants(row)
404
297
 
405
- if np.mean(row.M)>0.5:
406
- raise ValueError(f"High inlet mach can lead to errors iter:{iter} Mach:{avg_mach}")
298
+ total_area, streamline_area = compute_streamline_areas(row)
299
+ row.total_area = total_area
300
+ row.area = streamline_area
301
+ Vm_tube = np.zeros(len(row.percent_hub_shroud)-1)
302
+
303
+ Vm_mean = row.total_massflow / (row.rho.mean()*row.total_area)
304
+ for j in range(1,len(row.percent_hub_shroud)):
305
+ rho = row.rho[j]
306
+ Vm_tube[j-1] = (row.massflow[j]-row.massflow[j-1])/(rho*row.area[j])
307
+
308
+ # Recover per-streamline Vm from tube-averaged Vm_tube assuming piecewise linear variation
309
+ row.Vm[0] = Vm_tube[0] if len(Vm_tube) else Vm_mean
310
+ for j in range(1, len(row.percent_hub_shroud)):
311
+ rho_bar = 0.5 * (row.rho[j] + row.rho[j-1])
312
+ Vm_tube_j = (row.massflow[j] - row.massflow[j-1]) / (rho_bar * row.area[j] + 1e-12)
313
+ row.Vm[j] = 2 * Vm_tube_j - row.Vm[j-1]
314
+
315
+ row.Vr = row.Vm*np.sin(row.phi)
316
+ row.V = row.M*np.sqrt(row.gamma*row.R*row.T)
317
+ row.Vt = row.V*np.sin(row.alpha2)
318
+ row.Vx = row.Vm*np.cos(row.phi)
319
+
320
+
321
+ def T0_coolant_weighted_average(row:BladeRow) -> npt.NDArray:
322
+ """Calculate the new weighted Total Temperature array considering coolant
323
+
324
+ Args:
325
+ row (BladeRow): Coolant
326
+ massflow (np.ndarray): massflow mainstream
327
+
328
+ Returns:
329
+ float: Total Temperature drop
330
+ """
331
+
332
+ massflow = row.massflow
333
+ total_massflow_no_coolant = row.total_massflow_no_coolant
334
+ Cp = row.Cp
407
335
 
408
- if np.mean(row.M)<0.01:
409
- print(f"Unusually slow flow:{iter} Mach:{avg_mach}")
336
+ Cpc = row.coolant.Cp
337
+ T0c = row.coolant.T0
338
+ massflow_coolant = row.coolant.massflow_percentage*total_massflow_no_coolant*row.massflow[1:]/row.massflow[-1]
339
+ if massflow_coolant.mean()>0:
340
+ if row.row_type == RowType.Stator:
341
+ T0= row.T0
342
+ dT0 = T0.copy() * 0
343
+ T0_new = (massflow[1:]*Cp*T0[1:] + massflow_coolant*Cpc*T0c) \
344
+ /(massflow[1:]*Cp + massflow_coolant*Cpc)
345
+ dT0[1:] = T0_new - row.T0[1:]
346
+ dT0[0] = dT0[1]
347
+ else: # Rotor use relative total temperature
348
+ T0R = row.T0R
349
+ T0R_new = T0R.copy()
350
+ Cp = row.Cp
351
+ T0R_new[1:] = (massflow[1:]*Cp*T0R[1:] + massflow_coolant*Cpc*T0c) \
352
+ /(massflow[1:]*Cp + massflow_coolant*Cpc)
353
+ T0R_new[0] = T0R_new[1]
354
+
355
+ T = T0R_new - row.W**2/(2*Cp) # Dont change the velocity triangle but adjust the static temperature
356
+ T0_new = T+row.V**2/(2*Cp) # Use new static temperature to calculate the total temperature
357
+ dT0 = T0_new - row.T0
358
+ return dT0
359
+ else:
360
+ return row.T0*0