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