turbo-design 1.1.0__tar.gz → 1.1.2__tar.gz
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.
- {turbo_design-1.1.0 → turbo_design-1.1.2}/PKG-INFO +1 -1
- {turbo_design-1.1.0 → turbo_design-1.1.2}/pyproject.toml +1 -1
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/bladerow.py +11 -3
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/inlet.py +3 -3
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/passage.py +5 -3
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/td_math.py +31 -50
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/turbinespool.py +9 -5
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/__init__.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/arrayfuncs.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/cantera_gas/co2.yaml +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/compressorspool.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/coolant.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/enums.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/isentropic.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/loss/__init__.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/loss/compressor/__init__.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/loss/losstype.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/loss/turbine/TD2.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/loss/turbine/__init__.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/loss/turbine/ainleymathieson.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/loss/turbine/craigcox.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/loss/turbine/fixedefficiency.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/loss/turbine/fixedpressureloss.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/loss/turbine/kackerokapuu.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/loss/turbine/traupel.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/lossinterp.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/outlet.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/radeq.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/rotor.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/solve_radeq.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/spool.py +0 -0
- {turbo_design-1.1.0 → turbo_design-1.1.2}/turbodesign/stage.py +0 -0
|
@@ -97,6 +97,8 @@ class BladeRow:
|
|
|
97
97
|
phi:npt.NDArray = field(default_factory=lambda: np.array([0])) # Inclination angle x,r plane. AY td2.f
|
|
98
98
|
rm: npt.NDArray = field(default_factory=lambda: np.array([0])) # Curvature
|
|
99
99
|
incli_curve_radii: npt.NDArray = field(default_factory=lambda: np.array([0])) # radius at which curvature was evaluated
|
|
100
|
+
mprime:npt.NDArray = field(default_factory=lambda: np.array([0])) # Mprime distance
|
|
101
|
+
axial_chord:float = 0
|
|
100
102
|
|
|
101
103
|
Yp: float = 0 # Pressure loss
|
|
102
104
|
power:float = 0 # Watts
|
|
@@ -104,7 +106,8 @@ class BladeRow:
|
|
|
104
106
|
P0_P:float = 0 # Total to Static Pressure Ratio
|
|
105
107
|
Power_Type:PowerType
|
|
106
108
|
euler_power:float = 0
|
|
107
|
-
|
|
109
|
+
Reynolds:float = 0
|
|
110
|
+
|
|
108
111
|
# Used for loss calculations
|
|
109
112
|
_blade_to_blade_gap:float = 0.025 # Gap between blade in terms of percent chord.
|
|
110
113
|
|
|
@@ -118,7 +121,7 @@ class BladeRow:
|
|
|
118
121
|
_tip_clearance:float = 0 # Clearance as a percentage of span or blade height
|
|
119
122
|
|
|
120
123
|
_inlet_to_outlet_pratio = [0.06,0.95]
|
|
121
|
-
|
|
124
|
+
|
|
122
125
|
@property
|
|
123
126
|
def inlet_to_outlet_pratio(self) -> Tuple[float,float]:
|
|
124
127
|
"""This is what is varied by the optimization.
|
|
@@ -474,6 +477,7 @@ class BladeRow:
|
|
|
474
477
|
"P":self.P.tolist(),
|
|
475
478
|
"T":self.T.tolist(),
|
|
476
479
|
"rho":self.rho.tolist(),
|
|
480
|
+
"mu":self.mu,
|
|
477
481
|
"Yp":self.Yp,
|
|
478
482
|
"Power":self.power,
|
|
479
483
|
"P0_P": self.P0_P,
|
|
@@ -482,7 +486,11 @@ class BladeRow:
|
|
|
482
486
|
"euler_power":self.euler_power,
|
|
483
487
|
"axial_chord":self.axial_chord,
|
|
484
488
|
"aspect_ratio":self.aspect_ratio,
|
|
485
|
-
"
|
|
489
|
+
"num_blades":self.num_blades,
|
|
490
|
+
"area": self.area,
|
|
491
|
+
"mprime":self.mprime[-1],
|
|
492
|
+
"Reynolds":self.Reynolds,
|
|
493
|
+
"axial_chord":self.axial_chord
|
|
486
494
|
}
|
|
487
495
|
|
|
488
496
|
return data
|
|
@@ -54,7 +54,8 @@ class Inlet(BladeRow):
|
|
|
54
54
|
self.beta2_metal = [0]
|
|
55
55
|
self.P0_fun = interp1d(self.percent_hub_shroud,P0)
|
|
56
56
|
self.T0_fun = interp1d(self.percent_hub_shroud,T0)
|
|
57
|
-
|
|
57
|
+
self.mprime = [0]
|
|
58
|
+
|
|
58
59
|
|
|
59
60
|
def initialize_velocity(self,passage:Passage,num_streamlines:int):
|
|
60
61
|
"""Initialize velocity calculations. Assumes streamlines and inclination angles have been calculated
|
|
@@ -67,7 +68,6 @@ class Inlet(BladeRow):
|
|
|
67
68
|
|
|
68
69
|
cutline,_,_ = passage.get_cutting_line(self.axial_location)
|
|
69
70
|
self.x,self.r = cutline.get_point(np.linspace(0,1,num_streamlines))
|
|
70
|
-
|
|
71
71
|
for _ in range(10):
|
|
72
72
|
T0_T = (1+(self.gamma-1)/2 * self.M**2)
|
|
73
73
|
|
|
@@ -115,7 +115,7 @@ class Inlet(BladeRow):
|
|
|
115
115
|
Area += 2*np.pi*C*(S/2*dx**2+self.r[j-1]*dx)
|
|
116
116
|
|
|
117
117
|
self.calculated_massflow = self.rho.mean()*self.Vm.mean() * Area
|
|
118
|
-
|
|
118
|
+
|
|
119
119
|
|
|
120
120
|
def get_total_pressure(self,percent_hub_shroud:Union[float,npt.NDArray]):
|
|
121
121
|
"""Returns the static pressure at a certain percent hub_shroud
|
|
@@ -184,7 +184,7 @@ class Passage:
|
|
|
184
184
|
rshroud = self.rshroud(t_shroud)
|
|
185
185
|
return line2D([xhub,rhub],[xshroud,rshroud]), t_hub, t_shroud
|
|
186
186
|
|
|
187
|
-
def get_xr_slice(self,t_span:float,axial_location:float):
|
|
187
|
+
def get_xr_slice(self,t_span:float,axial_location:Tuple[float,float]):
|
|
188
188
|
"""Returns the xr coordinates of a streamline, a line that is parallel to both hub and shroud
|
|
189
189
|
|
|
190
190
|
Args:
|
|
@@ -194,7 +194,7 @@ class Passage:
|
|
|
194
194
|
Returns:
|
|
195
195
|
np.NDArray: _description_
|
|
196
196
|
"""
|
|
197
|
-
t_hub = np.linspace(0,axial_location,100)
|
|
197
|
+
t_hub = np.linspace(axial_location[0],axial_location[1],100)
|
|
198
198
|
|
|
199
199
|
shroud_pts_cyl = np.vstack([self.xshroud(t_hub),self.rshroud(t_hub)]).transpose()
|
|
200
200
|
hub_pts_cyl = np.vstack([self.xhub(t_hub),self.rhub(t_hub)]).transpose()
|
|
@@ -228,7 +228,9 @@ class Passage:
|
|
|
228
228
|
cut,_,_ = self.get_cutting_line(p)
|
|
229
229
|
x,r = cut.get_point(np.linspace(0,1,10))
|
|
230
230
|
plt.plot(x,r,label=f'{p}',linestyle='dashed')
|
|
231
|
-
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
plt.ylim([-self.rshroud_pts.max()*0.1, self.rshroud_pts.max()])
|
|
232
234
|
plt.legend()
|
|
233
235
|
plt.axis('scaled')
|
|
234
236
|
plt.show()
|
|
@@ -5,6 +5,7 @@ import numpy.typing as npt
|
|
|
5
5
|
from .bladerow import BladeRow, compute_gas_constants
|
|
6
6
|
from .enums import RowType, LossType
|
|
7
7
|
from scipy.integrate import trapezoid
|
|
8
|
+
from .passage import Passage
|
|
8
9
|
|
|
9
10
|
def T0_coolant_weighted_average(row:BladeRow) -> float:
|
|
10
11
|
"""Calculate the new weighted Total Temperature array considering coolant
|
|
@@ -78,6 +79,36 @@ def compute_massflow(row:BladeRow) -> None:
|
|
|
78
79
|
row.calculated_massflow = massflow[-1]
|
|
79
80
|
row.area = total_area
|
|
80
81
|
|
|
82
|
+
def compute_reynolds(rows:List[BladeRow],passage:Passage):
|
|
83
|
+
"""Calculates the Reynolds Number
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
rows (List[BladeRow]): Blade row to calculate the Reynolds number
|
|
87
|
+
passage (Passage): Passage
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
for i in range(1,len(rows)):
|
|
91
|
+
row = rows[i]
|
|
92
|
+
xr = passage.get_xr_slice(0.5,[rows[i-1].axial_location,row.axial_location])
|
|
93
|
+
dx = np.diff(xr[:,0])
|
|
94
|
+
dr = np.diff(xr[:,1])
|
|
95
|
+
c = np.sum(np.sqrt(dx**2+dr**2))
|
|
96
|
+
mp = [2/(xr[i,1]+xr[i-1,1])*np.sqrt(dr[i-1]**2 + dx[i-1]**2) for i in range(1,len(xr[:,1]))]
|
|
97
|
+
mp = np.hstack([[0],np.cumsum(mp)])
|
|
98
|
+
|
|
99
|
+
if row.row_type == RowType.Rotor:
|
|
100
|
+
V = row.W.mean()
|
|
101
|
+
else:
|
|
102
|
+
V = row.V.mean()
|
|
103
|
+
rho = row.rho.mean()
|
|
104
|
+
mu = row.mu
|
|
105
|
+
row.Reynolds = c*V*rho/mu
|
|
106
|
+
row.mprime = mp
|
|
107
|
+
row.axial_chord = max(c,1E-12) # Axial chord
|
|
108
|
+
# row.num_blades = int(2*np.pi*row.r.mean() / row.pitch_to_chord * row.axial_chord)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
|
|
81
112
|
def compute_power(row:BladeRow,upstream:BladeRow) -> None:
|
|
82
113
|
"""Calculates the power
|
|
83
114
|
|
|
@@ -169,56 +200,6 @@ def compute_quantities(row:BladeRow,upstream:BladeRow):
|
|
|
169
200
|
row.T0R = row.T + row.W**2 / (2*row.Cp)
|
|
170
201
|
row.P0R = row.P*(row.T0R/row.T)**((row.gamma)/(row.gamma-1))
|
|
171
202
|
|
|
172
|
-
def compute_quantities_power(row:BladeRow,upstream:BladeRow):
|
|
173
|
-
"""Calculation of all quantites after radial equilibrium has been solved assuming we know the power at the exit
|
|
174
|
-
|
|
175
|
-
Note:
|
|
176
|
-
Radial Equilibrium gives P0, T0, Vm. This code assumes the loss either enthalpy or pressure loss has already been calculated
|
|
177
|
-
|
|
178
|
-
compute_velocity has been called so we know W, Wt, V, Vt, U, M, M_rel
|
|
179
|
-
|
|
180
|
-
Static Pressure and Temperature should come from Total Temperature and Pressure + Velocity
|
|
181
|
-
|
|
182
|
-
Args:
|
|
183
|
-
row (BladeRow): current blade row. All quantities are at exit
|
|
184
|
-
upstream (BladeRow): upstream blade row. All quantities are at exit
|
|
185
|
-
|
|
186
|
-
"""
|
|
187
|
-
if row.row_type == RowType.Rotor:
|
|
188
|
-
Cp_avg = (row.Cp+upstream.Cp)/2
|
|
189
|
-
row.T0R = upstream.T0R - T0_coolant_weighted_average(row) - (upstream.U**2-row.U**2)/(2*Cp_avg)
|
|
190
|
-
|
|
191
|
-
# Factor in T0R_drop. Convert T0R drop to absolute terms
|
|
192
|
-
T_drop = (upstream.T0R - row.T0R) - row.W**2/(2*row.Cp) # row.T0R contains the drop
|
|
193
|
-
T0_drop = T_drop*(1+(row.gamma-1)/2*row.M**2)
|
|
194
|
-
|
|
195
|
-
# Adjust Total Temperature to match power
|
|
196
|
-
T0 = upstream.T0 - row.power/row.eta_total/(row.total_massflow*row.Cp) + T0_drop
|
|
197
|
-
|
|
198
|
-
if row.loss_function == LossType.Pressure:
|
|
199
|
-
row.P0R = upstream.P0R - row.Yp*(upstream.P0R-row.P)
|
|
200
|
-
row.T0 = T0
|
|
201
|
-
row.T = row.T0/(1+(row.gamma-1)/2*row.M**2)
|
|
202
|
-
row.P = row.P0R*(row.T/row.T0R)**(row.gamma/(row.gamma-1))
|
|
203
|
-
|
|
204
|
-
elif row.loss_function == LossType.Enthalpy:
|
|
205
|
-
row.P0 = row.P*(T0/row.T)**(row.gamma/(row.gamma-1))
|
|
206
|
-
row.T = T0 - row.W**2/(2*row.Cp) + T_drop
|
|
207
|
-
row.T0 = T0
|
|
208
|
-
row.P = row.P0*(row.T0/row.T)**(row.gamma/(row.gamma-1))
|
|
209
|
-
row.P0R = row.P * (row.T0R/row.T)**((row.gamma)/(row.gamma-1))
|
|
210
|
-
|
|
211
|
-
elif row.row_type == RowType.Stator:
|
|
212
|
-
row.T0 = upstream.T0 - T0_coolant_weighted_average(row)
|
|
213
|
-
if row.loss_function == LossType.Pressure:
|
|
214
|
-
row.P0 = upstream.P0 - row.Yp*(upstream.P0-row.P)
|
|
215
|
-
else:
|
|
216
|
-
row.P0 = upstream.P0
|
|
217
|
-
row.T = row.T0 * (1+(row.gamma-1)/2*row.M**2)
|
|
218
|
-
row.P = row.P0 * (row.T/row.T0)**((row.gamma)/(row.gamma-1))
|
|
219
|
-
row.T0R = row.T + row.W**2 / (2*row.Cp)
|
|
220
|
-
row.P0R = row.P*(row.T0R/row.T)**((row.gamma)/(row.gamma-1))
|
|
221
|
-
|
|
222
203
|
def stator_calc(row:BladeRow,upstream:BladeRow,downstream:BladeRow=None,calculate_vm:bool=True):
|
|
223
204
|
"""Given P0, T0, P, alpha2 of stator calculate all other quantities
|
|
224
205
|
|
|
@@ -8,7 +8,7 @@ from .passage import Passage
|
|
|
8
8
|
from scipy.interpolate import interp1d
|
|
9
9
|
import numpy as np
|
|
10
10
|
import numpy.typing as npt
|
|
11
|
-
from .td_math import inlet_calc,rotor_calc, stator_calc, compute_massflow, compute_power, compute_gas_constants
|
|
11
|
+
from .td_math import inlet_calc,rotor_calc, stator_calc, compute_massflow, compute_power, compute_gas_constants, compute_reynolds
|
|
12
12
|
from .solve_radeq import adjust_streamlines, radeq
|
|
13
13
|
from scipy.optimize import minimize_scalar, minimize, fmin_slsqp
|
|
14
14
|
from .inlet import Inlet
|
|
@@ -136,7 +136,7 @@ class TurbineSpool(Spool):
|
|
|
136
136
|
self.__match_massflow()
|
|
137
137
|
elif self.massflow_constraint == MassflowConstraint.BalanceMassFlow:
|
|
138
138
|
self.__balance_massflow()
|
|
139
|
-
|
|
139
|
+
|
|
140
140
|
|
|
141
141
|
def __match_massflow(self):
|
|
142
142
|
""" Matches the massflow between streamtubes by changing exit angles. Doesn't use radial equilibrium.
|
|
@@ -171,10 +171,11 @@ class TurbineSpool(Spool):
|
|
|
171
171
|
row.alpha2[0] = 1/(len(row.alpha2)-1)*row.alpha2[1:].sum()
|
|
172
172
|
upstream = compute_gas_constants(upstream)
|
|
173
173
|
row = compute_gas_constants(row)
|
|
174
|
-
|
|
174
|
+
|
|
175
175
|
|
|
176
176
|
# Step 3: Adjust streamlines to evenly divide massflow
|
|
177
177
|
adjust_streamlines(self.blade_rows,self.passage)
|
|
178
|
+
compute_reynolds(self.blade_rows,self.passage)
|
|
178
179
|
|
|
179
180
|
def __balance_massflow(self):
|
|
180
181
|
""" Balances the massflow between rows. Use radial equilibrium.
|
|
@@ -284,7 +285,10 @@ class TurbineSpool(Spool):
|
|
|
284
285
|
self.blade_rows[-1].P = self.blade_rows[-1].get_static_pressure(self.blade_rows[-1].percent_hub_shroud)
|
|
285
286
|
err = calculate_error(self.blade_rows[:-1])
|
|
286
287
|
print(f"Massflow convergenced error:{err}")
|
|
287
|
-
|
|
288
|
+
|
|
289
|
+
# calculate Reynolds number
|
|
290
|
+
compute_reynolds(self.blade_rows,self.passage)
|
|
291
|
+
|
|
288
292
|
# finetune = True
|
|
289
293
|
# if finetune:
|
|
290
294
|
# print('Finetune static pressure between stages')
|
|
@@ -453,7 +457,7 @@ def calculate_massflows(blade_rows:List[BladeRow],calculate_vm:bool=False):
|
|
|
453
457
|
row = compute_gas_constants(row)
|
|
454
458
|
compute_massflow(row)
|
|
455
459
|
compute_power(row,upstream)
|
|
456
|
-
|
|
460
|
+
|
|
457
461
|
def massflow_loss_function(exit_angle:float,index:int,row:BladeRow,upstream:BladeRow,downstream:BladeRow=None):
|
|
458
462
|
"""Finds the blade exit angles that balance the massflow throughout the stage
|
|
459
463
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|