turbo-design 1.2.1__tar.gz → 1.3.0__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.
Potentially problematic release.
This version of turbo-design might be problematic. Click here for more details.
- {turbo_design-1.2.1 → turbo_design-1.3.0}/PKG-INFO +3 -2
- {turbo_design-1.2.1 → turbo_design-1.3.0}/pyproject.toml +1 -1
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/bladerow.py +9 -7
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/inlet.py +4 -4
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/outlet.py +2 -1
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/passage.py +39 -7
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/radeq.py +32 -8
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/solve_radeq.py +5 -5
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/spool.py +12 -10
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/td_math.py +5 -5
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/turbinespool.py +84 -100
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/__init__.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/arrayfuncs.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/cantera_gas/co2.yaml +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/compressorspool.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/coolant.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/enums.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/isentropic.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/loss/__init__.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/loss/compressor/__init__.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/loss/losstype.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/loss/turbine/TD2.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/loss/turbine/__init__.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/loss/turbine/ainleymathieson.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/loss/turbine/craigcox.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/loss/turbine/fixedefficiency.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/loss/turbine/fixedpressureloss.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/loss/turbine/kackerokapuu.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/loss/turbine/traupel.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/lossinterp.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/rotor.py +0 -0
- {turbo_design-1.2.1 → turbo_design-1.3.0}/turbodesign/stage.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: turbo-design
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: TurboDesign is a library used to design turbines and compressors using radial equilibrium.
|
|
5
5
|
Author: Paht Juangphanich
|
|
6
6
|
Author-email: paht.juangphanich@nasa.gov
|
|
@@ -10,6 +10,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.10
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.11
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
14
|
Requires-Dist: cantera
|
|
14
15
|
Requires-Dist: findiff
|
|
15
16
|
Requires-Dist: matplotlib
|
|
@@ -34,10 +34,11 @@ class BladeRow:
|
|
|
34
34
|
# ----------------------------------
|
|
35
35
|
|
|
36
36
|
# Streamline Properties
|
|
37
|
-
|
|
37
|
+
percent_hub:float = 0 # Where blade row is defined along the hub.
|
|
38
38
|
percent_hub_shroud: npt.NDArray = field(default_factory=lambda: np.array([0])) # Percent streamline length from hub to shroud.
|
|
39
39
|
x: npt.NDArray = field(default_factory=lambda: np.array([0])) # x - coordinates (useful for computing axial chord)
|
|
40
40
|
r: npt.NDArray = field(default_factory=lambda: np.array([0])) # Radius - coordinates
|
|
41
|
+
m: npt.NDArray = field(default_factory=lambda: np.array([0])) # meridional
|
|
41
42
|
area:float = 0
|
|
42
43
|
# Calculated massflow is the massflow computed after radial eq solver
|
|
43
44
|
calculated_massflow: float = 0
|
|
@@ -120,6 +121,7 @@ class BladeRow:
|
|
|
120
121
|
_tip_clearance:float = 0 # Clearance as a percentage of span or blade height
|
|
121
122
|
|
|
122
123
|
_inlet_to_outlet_pratio = [0.06,0.95]
|
|
124
|
+
location:float = 0 # Percent along hub where bladerow is defined
|
|
123
125
|
|
|
124
126
|
@property
|
|
125
127
|
def inlet_to_outlet_pratio(self) -> Tuple[float,float]:
|
|
@@ -327,18 +329,18 @@ class BladeRow:
|
|
|
327
329
|
"""
|
|
328
330
|
self._tip_clearance = val
|
|
329
331
|
|
|
330
|
-
def __init__(self,
|
|
332
|
+
def __init__(self,location:float,row_type:RowType=RowType.Stator,stage_id:int = 0):
|
|
331
333
|
"""Initializes the blade row to be a particular type
|
|
332
334
|
|
|
333
335
|
Args:
|
|
334
|
-
|
|
336
|
+
location (float): Location of the blade row as a percentage of hub length
|
|
335
337
|
row_type (RowType): Specifies the Type. Defaults to RowType.Stator
|
|
336
338
|
power (float, optional): power . Defaults to 0.
|
|
337
339
|
P0_P (float, optional): Total to Static Pressure Ratio
|
|
338
340
|
stage_id (int, optional): ID of the stage so if you have 9 stages, the id could be 9. It's used to separate the stages. Each stage will have it's own unique degree of reaction
|
|
339
341
|
"""
|
|
340
342
|
self.row_type = row_type
|
|
341
|
-
self.
|
|
343
|
+
self.location = location
|
|
342
344
|
self.Yp = 0 # Loss
|
|
343
345
|
self.stage_id = stage_id
|
|
344
346
|
|
|
@@ -511,7 +513,7 @@ def interpolate_streamline_radii(row:BladeRow,passage:Passage,num_streamlines:in
|
|
|
511
513
|
Returns:
|
|
512
514
|
(BladeRow): new row object with quantities interpolated
|
|
513
515
|
"""
|
|
514
|
-
row.cutting_line,_,_ = passage.get_cutting_line(row.
|
|
516
|
+
row.cutting_line,_,_ = passage.get_cutting_line(row.location)
|
|
515
517
|
row.x,row.r = row.cutting_line.get_point(np.linspace(0,1,num_streamlines))
|
|
516
518
|
streamline_percent_length = np.sqrt((row.r-row.r[0])**2+(row.x-row.x[0])**2)/row.cutting_line.length
|
|
517
519
|
|
|
@@ -622,8 +624,8 @@ def compute_gas_constants(row:BladeRow,fluid:Solution=None) -> None:
|
|
|
622
624
|
Tm = row.T.mean()
|
|
623
625
|
Pm = row.P.mean()
|
|
624
626
|
fluid.TP = Tm,Pm
|
|
625
|
-
row.Cp =
|
|
626
|
-
row.Cv =
|
|
627
|
+
row.Cp = fluid.cp
|
|
628
|
+
row.Cv = fluid.cv
|
|
627
629
|
row.R = row.Cp-row.Cv
|
|
628
630
|
row.gamma = row.Cp/row.Cv
|
|
629
631
|
# Use Ideal Gas
|
|
@@ -19,7 +19,7 @@ class Inlet(BladeRow):
|
|
|
19
19
|
|
|
20
20
|
def __init__(self,M:float,T0:Union[float,List[float]],
|
|
21
21
|
P0:Union[float,List[float]],
|
|
22
|
-
|
|
22
|
+
location:float=0,
|
|
23
23
|
beta:Union[float,List[float]]=[0],
|
|
24
24
|
percent_radii:Union[float,List[float]]=[0.5]):
|
|
25
25
|
"""Initializes the inlet station.
|
|
@@ -30,11 +30,11 @@ class Inlet(BladeRow):
|
|
|
30
30
|
T0 (Union[float,List[float]]): Total Temperature Array
|
|
31
31
|
P0 (Union[float,List[float]]): Total Pressure Array
|
|
32
32
|
percent_radii (Union[float,List[float]]): Radius where total pressure and temperature are defined
|
|
33
|
-
|
|
33
|
+
location (float): Location as a percentage of hub length
|
|
34
34
|
beta (Union[float,List[float]], optional): Inlet flow angle in relative direction. Defaults to [].
|
|
35
35
|
|
|
36
36
|
"""
|
|
37
|
-
super().__init__(row_type=RowType.Inlet,
|
|
37
|
+
super().__init__(row_type=RowType.Inlet,location=location,stage_id=-1)
|
|
38
38
|
self.beta1 = convert_to_ndarray(beta)
|
|
39
39
|
self.M = convert_to_ndarray(M)
|
|
40
40
|
self.T0 = convert_to_ndarray(T0)
|
|
@@ -94,7 +94,7 @@ class Inlet(BladeRow):
|
|
|
94
94
|
t,x,radius = passage.get_streamline(self.percent_hub_shroud)
|
|
95
95
|
radius = radius[0]
|
|
96
96
|
|
|
97
|
-
cutline,_,_ = passage.get_cutting_line(self.
|
|
97
|
+
cutline,_,_ = passage.get_cutting_line(self.location)
|
|
98
98
|
self.x,self.r = cutline.get_point(np.linspace(0,1,num_streamlines))
|
|
99
99
|
for _ in range(10):
|
|
100
100
|
T0_T = (1+(self.gamma-1)/2 * self.M**2)
|
|
@@ -12,7 +12,7 @@ from scipy.interpolate import interp1d
|
|
|
12
12
|
class Outlet(BladeRow):
|
|
13
13
|
P_fun:interp1d
|
|
14
14
|
|
|
15
|
-
def __init__(self,P:Union[float,List[float]],percent_radii:List[float],num_streamlines:int=3):
|
|
15
|
+
def __init__(self,P:Union[float,List[float]],percent_radii:List[float],num_streamlines:int=3,location:float=1):
|
|
16
16
|
"""Initialize the outlet
|
|
17
17
|
|
|
18
18
|
Args:
|
|
@@ -26,6 +26,7 @@ class Outlet(BladeRow):
|
|
|
26
26
|
self.P_fun = interp1d(self.percent_hub_shroud,self.P)
|
|
27
27
|
self.row_type = RowType.Outlet
|
|
28
28
|
self.loss_function = None
|
|
29
|
+
self.location = location
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
def transfer_quantities(self,upstream:BladeRow):
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import List, Tuple
|
|
2
2
|
import numpy as np
|
|
3
3
|
import numpy.typing as npt
|
|
4
|
-
from scipy.interpolate import PchipInterpolator
|
|
4
|
+
from scipy.interpolate import PchipInterpolator, interp1d
|
|
5
5
|
from pyturbo.helper import line2D
|
|
6
6
|
from .enums import PassageType
|
|
7
7
|
from scipy.optimize import minimize_scalar
|
|
@@ -141,7 +141,7 @@ class Passage:
|
|
|
141
141
|
r = r_streamline
|
|
142
142
|
|
|
143
143
|
return phi, rm, r
|
|
144
|
-
|
|
144
|
+
|
|
145
145
|
def get_area(self,t_hub:float) -> float:
|
|
146
146
|
"""Get Area
|
|
147
147
|
|
|
@@ -166,7 +166,7 @@ class Passage:
|
|
|
166
166
|
total_area += area
|
|
167
167
|
return total_area
|
|
168
168
|
|
|
169
|
-
def get_cutting_line(self, t_hub:float) -> line2D:
|
|
169
|
+
def get_cutting_line(self, t_hub:float) -> Tuple[line2D,float,float]:
|
|
170
170
|
"""Gets the cutting line perpendicular to hub and shroud
|
|
171
171
|
|
|
172
172
|
Args:
|
|
@@ -212,17 +212,18 @@ class Passage:
|
|
|
212
212
|
rshroud = self.rshroud(t_shroud)
|
|
213
213
|
return line2D([xhub,rhub],[xshroud,rshroud]), t_hub, t_shroud
|
|
214
214
|
|
|
215
|
-
def get_xr_slice(self,t_span:float,
|
|
215
|
+
def get_xr_slice(self,t_span:float,percent_hub:Tuple[float,float],resolution:int=100):
|
|
216
216
|
"""Returns the xr coordinates of a streamline, a line that is parallel to both hub and shroud
|
|
217
217
|
|
|
218
218
|
Args:
|
|
219
219
|
t_span (float): _description_
|
|
220
|
-
|
|
220
|
+
meridional_location (float): _description_
|
|
221
|
+
resolution (int): number of points to resolve
|
|
221
222
|
|
|
222
223
|
Returns:
|
|
223
224
|
np.NDArray: _description_
|
|
224
225
|
"""
|
|
225
|
-
t_hub = np.linspace(
|
|
226
|
+
t_hub = np.linspace(percent_hub[0],percent_hub[1],resolution)
|
|
226
227
|
t_hub = convert_to_ndarray(t_hub)*self.hub_length
|
|
227
228
|
|
|
228
229
|
shroud_pts_cyl = np.vstack([self.xshroud(t_hub),self.rshroud(t_hub)]).transpose()
|
|
@@ -233,8 +234,39 @@ class Passage:
|
|
|
233
234
|
for j in range(n):
|
|
234
235
|
l = line2D(hub_pts_cyl[j,:],shroud_pts_cyl[j,:])
|
|
235
236
|
xr[j,0],xr[j,1] = l.get_point(t_span)
|
|
237
|
+
|
|
236
238
|
return xr
|
|
237
|
-
|
|
239
|
+
|
|
240
|
+
def get_m(self,t_span:float,resolution:int=100) -> npt.NDArray:
|
|
241
|
+
"""Meridional cooridnates
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
t_span (float): _description_
|
|
245
|
+
resolution (int, optional): _description_. Defaults to 100.
|
|
246
|
+
|
|
247
|
+
Returns:
|
|
248
|
+
npt.NDArray: _description_
|
|
249
|
+
"""
|
|
250
|
+
xr = self.get_xr_slice(t_span,(0,1),resolution)
|
|
251
|
+
dx = np.diff(xr[:,0])
|
|
252
|
+
dr = np.diff(xr[:,1])
|
|
253
|
+
m = np.concat([[0],np.cumsum(np.sqrt(dx**2 + dr**2))])
|
|
254
|
+
return m
|
|
255
|
+
|
|
256
|
+
def get_dm(self,t_span:float,location:float,resolution:int=1000) -> float:
|
|
257
|
+
"""return the derivative in the meridional direction at a particular point
|
|
258
|
+
|
|
259
|
+
Args:
|
|
260
|
+
t_span (float): percent span
|
|
261
|
+
location (float): hub location of the blade
|
|
262
|
+
resolution (int, optional): number of points to represent the hub curve. Defaults to 1000.
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
(float) : returns the derivative
|
|
266
|
+
"""
|
|
267
|
+
m = self.get_m(t_span,resolution)
|
|
268
|
+
return PchipInterpolator(np.linspace(0,1,resolution),np.diff(m))(location)
|
|
269
|
+
|
|
238
270
|
@property
|
|
239
271
|
def hub_length(self):
|
|
240
272
|
"""returns the computed length of the hub
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
from scipy.interpolate import interp1d
|
|
1
|
+
from scipy.interpolate import interp1d,PchipInterpolator
|
|
2
2
|
from scipy.integrate import odeint
|
|
3
|
-
import numpy as np
|
|
3
|
+
import numpy as np
|
|
4
|
+
import numdifftools as nd
|
|
4
5
|
from .bladerow import BladeRow
|
|
5
6
|
from .enums import RowType
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
def radeq(row:BladeRow,upstream:BladeRow) -> BladeRow:
|
|
9
|
+
def radeq(row:BladeRow,upstream:BladeRow,downstream:BladeRow=None) -> BladeRow:
|
|
9
10
|
"""Solves the radial equilibrium equation for axial machines and returns the convergence.
|
|
10
11
|
|
|
11
12
|
Note:
|
|
@@ -14,7 +15,8 @@ def radeq(row:BladeRow,upstream:BladeRow) -> BladeRow:
|
|
|
14
15
|
Args:
|
|
15
16
|
row (BladeRow): Current row
|
|
16
17
|
upstream (BladeRow): Previous row
|
|
17
|
-
|
|
18
|
+
downstream (BladeRow): Next row
|
|
19
|
+
|
|
18
20
|
Returns:
|
|
19
21
|
BladeRow: current row with T0, P0, and Vm calculated
|
|
20
22
|
"""
|
|
@@ -57,8 +59,30 @@ def radeq(row:BladeRow,upstream:BladeRow) -> BladeRow:
|
|
|
57
59
|
# Estimations
|
|
58
60
|
dVm_dr = float(interp1d(row_radius, np.gradient(row.Vm, row_radius))(r))
|
|
59
61
|
dVt_dr = dVm_dr*np.tan(alpha)
|
|
60
|
-
dVr_dr = dVm_dr*np.sin(phi)
|
|
61
|
-
|
|
62
|
+
# dVr_dr = dVm_dr*np.sin(phi)
|
|
63
|
+
|
|
64
|
+
up_Vm = interp1d(row_radius, upstream.Vm)(r)
|
|
65
|
+
if downstream:
|
|
66
|
+
if downstream.row_type == RowType.Outlet:
|
|
67
|
+
down_Vm = Vm
|
|
68
|
+
else:
|
|
69
|
+
down_Vm = interp1d(row_radius, downstream.Vm)(r)
|
|
70
|
+
else:
|
|
71
|
+
down_Vm = Vm
|
|
72
|
+
up_m = interp1d(row_radius, upstream.m)(r)
|
|
73
|
+
|
|
74
|
+
# Get a rough guess of dVm/dm
|
|
75
|
+
if downstream!=None:
|
|
76
|
+
down_m = interp1d(row_radius, downstream.m)(r)
|
|
77
|
+
row_m = interp1d(row_radius, row.m)(r)
|
|
78
|
+
if down_m != row_m:
|
|
79
|
+
func_Vm_m = PchipInterpolator([up_m, row_m, down_m],[up_Vm, Vm, down_Vm])
|
|
80
|
+
else:
|
|
81
|
+
func_Vm_m = PchipInterpolator([up_m, row_m],[up_Vm, Vm])
|
|
82
|
+
else:
|
|
83
|
+
func_Vm_m = PchipInterpolator([up_m, row_m],[up_Vm, Vm])
|
|
84
|
+
dVm_dm = func_Vm_m.derivative()(row_m)
|
|
85
|
+
|
|
62
86
|
# Upstream
|
|
63
87
|
dT0up_dr = float(interp1d(upstream.percent_hub_shroud, np.gradient(upstream.T0,up_radius))((r-row_radius[0])/(row_radius[-1]-row_radius[0]))) # use percentage to get the T0 upstream value
|
|
64
88
|
dP0up_dr = float(interp1d(upstream.percent_hub_shroud, np.gradient(upstream.P0,up_radius))((r-row_radius[0])/(row_radius[-1]-row_radius[0]))) # use percentage to get the T0 upstream value
|
|
@@ -82,9 +106,9 @@ def radeq(row:BladeRow,upstream:BladeRow) -> BladeRow:
|
|
|
82
106
|
|
|
83
107
|
epsilon = 1e-10 # or another small threshold
|
|
84
108
|
if abs(rm) > epsilon:
|
|
85
|
-
dVm_dr =
|
|
109
|
+
dVm_dr = Cp*T0/(Vm*A*(1+np.tan(alpha)**2)) * (rho*(Vt**2/r + Vm**2/rm * np.cos(phi) - Vr*dVm_dm) - B*dP0_dr) + Vm/(2*T0) *dT0_dr # Eqn 6
|
|
86
110
|
else:
|
|
87
|
-
dVm_dr =
|
|
111
|
+
dVm_dr = Cp*T0/(Vm*A*(1+np.tan(alpha)**2)) * (rho*(Vt**2/r - Vr*dVm_dm) - B*dP0_dr) + Vm/(2*T0) *dT0_dr # Eqn 6
|
|
88
112
|
|
|
89
113
|
ydot = np.array([dP0_dr,dT0_dr,dVm_dr])
|
|
90
114
|
|
|
@@ -27,13 +27,13 @@ def adjust_streamlines(blade_rows:List[BladeRow],passage:Passage):
|
|
|
27
27
|
new_percent_streamline = interp1d(row.massflow,row.percent_hub_shroud)(ideal_massflow_fraction[1:-1])
|
|
28
28
|
row.percent_hub_shroud[1:-1] = new_percent_streamline
|
|
29
29
|
|
|
30
|
-
cut_line, thub,_ = passage.get_cutting_line(row.
|
|
30
|
+
cut_line, thub,_ = passage.get_cutting_line(row.percent_hub)
|
|
31
31
|
row.x,row.r = cut_line.get_point(row.percent_hub_shroud)
|
|
32
32
|
# Radii may have shifted, recompute Ay and rm
|
|
33
33
|
for i,tr in enumerate(row.percent_hub_shroud):
|
|
34
34
|
t_streamline, x_streamline, r_streamline = passage.get_streamline(tr)
|
|
35
35
|
phi, rm, r = passage.streamline_curvature(x_streamline,r_streamline)
|
|
36
|
-
row.phi[i] = float(interp1d(t_streamline,phi)(row.
|
|
37
|
-
row.rm[i] = float(interp1d(t_streamline,rm)(row.
|
|
38
|
-
row.r[i] = float(interp1d(t_streamline,r)(row.
|
|
39
|
-
row.x[i] = float(interp1d(t_streamline,x_streamline)(row.
|
|
36
|
+
row.phi[i] = float(interp1d(t_streamline,phi)(row.percent_hub))
|
|
37
|
+
row.rm[i] = float(interp1d(t_streamline,rm)(row.percent_hub))
|
|
38
|
+
row.r[i] = float(interp1d(t_streamline,r)(row.percent_hub))
|
|
39
|
+
row.x[i] = float(interp1d(t_streamline,x_streamline)(row.percent_hub))
|
|
@@ -34,7 +34,7 @@ class Spool:
|
|
|
34
34
|
def __init__(self,passage:Passage,
|
|
35
35
|
massflow:float,rows=List[BladeRow],
|
|
36
36
|
num_streamlines:int=3,
|
|
37
|
-
fluid:Solution=
|
|
37
|
+
fluid:Solution=None,
|
|
38
38
|
rpm:float=-1,
|
|
39
39
|
massflow_constraint:MassflowConstraint=MassflowConstraint.MatchMassFlow):
|
|
40
40
|
"""Initializes a Spool
|
|
@@ -50,7 +50,7 @@ class Spool:
|
|
|
50
50
|
massflow (float): massflow at spool inlet
|
|
51
51
|
rows (List[BladeRow], optional): List of blade rows. Defaults to List[BladeRow].
|
|
52
52
|
num_streamlines (int, optional): number of streamlines. Defaults to 3.
|
|
53
|
-
|
|
53
|
+
fluid (ct.Solution, optional): cantera gas solution. Defaults to None, fluid is set by bladerow cp
|
|
54
54
|
rpm (float, optional): RPM for the entire spool Optional, you can also set rpm of the blade rows individually. Defaults to -1.
|
|
55
55
|
massflow_constraint (MassflowConstraint, optional): MatchMassflow - Matches the massflow defined in the spool. BalanceMassflow - Balances the massflow between BladeRows, matches the lowest massflow.
|
|
56
56
|
"""
|
|
@@ -71,7 +71,7 @@ class Spool:
|
|
|
71
71
|
'''
|
|
72
72
|
if (type(self.blade_rows[i]) != Inlet) and (type(self.blade_rows[i]) != Outlet):
|
|
73
73
|
self.blade_rows[i].rpm = rpm
|
|
74
|
-
self.blade_rows[i].axial_chord = self.blade_rows[i].
|
|
74
|
+
self.blade_rows[i].axial_chord = self.blade_rows[i].location * self.passage.hub_length
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
@property
|
|
@@ -158,10 +158,11 @@ class Spool:
|
|
|
158
158
|
row.phi = np.zeros((self.num_streamlines,))
|
|
159
159
|
row.rm = np.zeros((self.num_streamlines,))
|
|
160
160
|
row.r = np.zeros((self.num_streamlines,))
|
|
161
|
+
row.m = np.zeros((self.num_streamlines,))
|
|
161
162
|
|
|
162
163
|
t_radial = np.linspace(0,1,self.num_streamlines)
|
|
163
164
|
self.calculate_streamline_curvature(row,t_radial)
|
|
164
|
-
|
|
165
|
+
|
|
165
166
|
# Set the loss function if it's not set
|
|
166
167
|
if (type(row)!= Inlet and type(row) != Outlet):
|
|
167
168
|
if row.loss_function == None:
|
|
@@ -177,9 +178,10 @@ class Spool:
|
|
|
177
178
|
for i,tr in enumerate(t_radial):
|
|
178
179
|
t_streamline, x_streamline, r_streamline = self.passage.get_streamline(tr)
|
|
179
180
|
phi, rm, r = self.passage.streamline_curvature(x_streamline,r_streamline)
|
|
180
|
-
row.phi[i] = float(interp1d(t_streamline,phi)(row.
|
|
181
|
-
row.rm[i] = float(interp1d(t_streamline,rm)(row.
|
|
182
|
-
row.r[i] = float(interp1d(t_streamline,r)(row.
|
|
181
|
+
row.phi[i] = float(interp1d(t_streamline,phi)(row.location))
|
|
182
|
+
row.rm[i] = float(interp1d(t_streamline,rm)(row.location))
|
|
183
|
+
row.r[i] = float(interp1d(t_streamline,r)(row.location))
|
|
184
|
+
row.m[i] = float(interp1d(t_streamline,self.passage.get_m(tr,resolution=len(t_streamline)))(row.location))
|
|
183
185
|
|
|
184
186
|
def solve(self):
|
|
185
187
|
raise NotImplementedError('Solve is not implemented')
|
|
@@ -214,10 +216,10 @@ class Spool:
|
|
|
214
216
|
else: # i>0
|
|
215
217
|
upstream = self.blade_rows[i-1]
|
|
216
218
|
if upstream.row_type== RowType.Inlet:
|
|
217
|
-
cut_line1,_,_ = self.passage.get_cutting_line((row.
|
|
219
|
+
cut_line1,_,_ = self.passage.get_cutting_line((row.location*hub_length +(0.5*row.blade_to_blade_gap*row.axial_chord) - row.axial_chord)/hub_length)
|
|
218
220
|
else:
|
|
219
|
-
cut_line1,_,_ = self.passage.get_cutting_line((upstream.
|
|
220
|
-
cut_line2,_,_ = self.passage.get_cutting_line((row.
|
|
221
|
+
cut_line1,_,_ = self.passage.get_cutting_line((upstream.location*hub_length)/hub_length)
|
|
222
|
+
cut_line2,_,_ = self.passage.get_cutting_line((row.location*hub_length-(0.5*row.blade_to_blade_gap*row.axial_chord))/hub_length)
|
|
221
223
|
|
|
222
224
|
if self.blade_rows[i].row_type == RowType.Stator:
|
|
223
225
|
x1,r1 = cut_line1.get_point(np.linspace(0,1,10))
|
|
@@ -93,7 +93,7 @@ def compute_reynolds(rows:List[BladeRow],passage:Passage):
|
|
|
93
93
|
|
|
94
94
|
for i in range(1,len(rows)):
|
|
95
95
|
row = rows[i]
|
|
96
|
-
xr = passage.get_xr_slice(0.5,[rows[i-1].
|
|
96
|
+
xr = passage.get_xr_slice(0.5,[rows[i-1].location,row.percent_hub])
|
|
97
97
|
dx = np.diff(xr[:,0])
|
|
98
98
|
dr = np.diff(xr[:,1])
|
|
99
99
|
c = np.sum(np.sqrt(dx**2+dr**2))
|
|
@@ -111,8 +111,6 @@ def compute_reynolds(rows:List[BladeRow],passage:Passage):
|
|
|
111
111
|
row.axial_chord = max(c,1E-12) # Axial chord
|
|
112
112
|
# row.num_blades = int(2*np.pi*row.r.mean() / row.pitch_to_chord * row.axial_chord)
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
|
|
116
114
|
def compute_power(row:BladeRow,upstream:BladeRow) -> None:
|
|
117
115
|
"""Calculates the power
|
|
118
116
|
|
|
@@ -232,8 +230,9 @@ def stator_calc(row:BladeRow,upstream:BladeRow,downstream:BladeRow=None,calculat
|
|
|
232
230
|
|
|
233
231
|
# Static Pressure is assumed
|
|
234
232
|
row.P0 = upstream.P0 - row.Yp*(upstream.P0-row.P)
|
|
235
|
-
|
|
233
|
+
|
|
236
234
|
if downstream is not None:
|
|
235
|
+
row.P0_P = row.P0/downstream.P
|
|
237
236
|
row.rp = (row.P-downstream.P)/(upstream.P0-downstream.P)
|
|
238
237
|
|
|
239
238
|
if calculate_vm:
|
|
@@ -261,6 +260,7 @@ def stator_calc(row:BladeRow,upstream:BladeRow,downstream:BladeRow=None,calculat
|
|
|
261
260
|
row.beta1 = upstream.beta2
|
|
262
261
|
row.rho = row.P/(row.R*row.T)
|
|
263
262
|
row.U = row.omega*row.r
|
|
263
|
+
row.Wt = row.Vt-row.U
|
|
264
264
|
row.P0_stator_inlet = upstream.P0
|
|
265
265
|
|
|
266
266
|
def rotor_calc(row:BladeRow,upstream:BladeRow,calculate_vm:bool=True):
|
|
@@ -296,7 +296,7 @@ def rotor_calc(row:BladeRow,upstream:BladeRow,calculate_vm:bool=True):
|
|
|
296
296
|
row.P0R = upstream.P0R - row.Yp*(upstream.P0R-row.P)
|
|
297
297
|
|
|
298
298
|
# Total Relative Temperature stays constant through the rotor. Adjust for change in radius from rotor inlet to exit
|
|
299
|
-
row.T0R =
|
|
299
|
+
row.T0R = (upstream_rothalpy + 0.5*row.U**2)/row.Cp - T0_coolant_weighted_average(row)
|
|
300
300
|
P0R_P = row.P0R / row.P
|
|
301
301
|
T0R_T = P0R_P**((row.gamma-1)/row.gamma)
|
|
302
302
|
row.T = (row.T0R/T0R_T) # Exit static temperature
|
|
@@ -53,15 +53,15 @@ class TurbineSpool(Spool):
|
|
|
53
53
|
gamma=self.blade_rows[1].gamma,
|
|
54
54
|
Cp=self.blade_rows[1].Cp)
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
inlet.total_massflow = W0
|
|
57
|
+
inlet.total_massflow_no_coolant = W0
|
|
58
|
+
inlet.massflow = np.linspace(0,1,self.num_streamlines)*W0
|
|
59
|
+
|
|
60
|
+
inlet.initialize_velocity(self.passage,self.num_streamlines)
|
|
61
|
+
interpolate_streamline_radii(inlet,self.passage,self.num_streamlines)
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
compute_gas_constants(inlet,self.fluid)
|
|
64
|
+
inlet_calc(inlet)
|
|
65
65
|
|
|
66
66
|
for row in self.blade_rows:
|
|
67
67
|
interpolate_streamline_radii(row,self.passage,self.num_streamlines)
|
|
@@ -122,10 +122,12 @@ class TurbineSpool(Spool):
|
|
|
122
122
|
|
|
123
123
|
if row.row_type == RowType.Stator:
|
|
124
124
|
stator_calc(row,upstream,downstream)
|
|
125
|
+
compute_massflow(row)
|
|
125
126
|
elif row.row_type == RowType.Rotor:
|
|
126
127
|
rotor_calc(row,upstream)
|
|
127
128
|
compute_massflow(row)
|
|
128
129
|
compute_power(row,upstream)
|
|
130
|
+
|
|
129
131
|
|
|
130
132
|
def solve(self):
|
|
131
133
|
"""
|
|
@@ -163,7 +165,7 @@ class TurbineSpool(Spool):
|
|
|
163
165
|
bounds = [-80,0]
|
|
164
166
|
if row.row_type != RowType.Inlet:
|
|
165
167
|
for j in range(1,self.num_streamlines):
|
|
166
|
-
res = minimize_scalar(massflow_loss_function, bounds=bounds,args=(j,row,upstream,downstream),tol=1E-
|
|
168
|
+
res = minimize_scalar(massflow_loss_function, bounds=bounds,args=(j,row,upstream,downstream),tol=1E-3)
|
|
167
169
|
if row.row_type == RowType.Rotor:
|
|
168
170
|
row.beta2[j] = np.radians(res.x)
|
|
169
171
|
# Initialize the value at the hub to not upset the mean
|
|
@@ -178,7 +180,34 @@ class TurbineSpool(Spool):
|
|
|
178
180
|
# Step 3: Adjust streamlines to evenly divide massflow
|
|
179
181
|
adjust_streamlines(self.blade_rows,self.passage)
|
|
180
182
|
compute_reynolds(self.blade_rows,self.passage)
|
|
181
|
-
|
|
183
|
+
|
|
184
|
+
@staticmethod # Private static method
|
|
185
|
+
def __massflow_std__(blade_rows:List[BladeRow]):
|
|
186
|
+
"""Returns the standard deviation of the massflow
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
blade_rows (List[BladeRow]): List of blade rows
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
_type_: _description_
|
|
193
|
+
"""
|
|
194
|
+
total_massflow = list(); s = 0; massflow_stage = list()
|
|
195
|
+
stage_ids = list(set([row.stage_id for row in blade_rows if row.stage_id>=0]))
|
|
196
|
+
for row in blade_rows[1:-1]: # Ignore inlet and outlet
|
|
197
|
+
total_massflow.append(row.total_massflow_no_coolant)
|
|
198
|
+
sign = 1
|
|
199
|
+
for s in stage_ids:
|
|
200
|
+
for row in blade_rows:
|
|
201
|
+
if row.stage_id == s and row.row_type == RowType.Rotor:
|
|
202
|
+
massflow_stage.append(sign*row.total_massflow_no_coolant)
|
|
203
|
+
sign*=-1
|
|
204
|
+
if len(stage_ids) % 2 == 1:
|
|
205
|
+
massflow_stage.append(massflow_stage[-1]*sign)
|
|
206
|
+
deviation = np.std(total_massflow)*2
|
|
207
|
+
if deviation>1.0:
|
|
208
|
+
print("high massflow deviation detected")
|
|
209
|
+
return np.std(total_massflow)*2 # + abs(sum(massflow_stage)) # Equation 28
|
|
210
|
+
|
|
182
211
|
def __balance_massflow(self):
|
|
183
212
|
""" Balances the massflow between rows. Use radial equilibrium.
|
|
184
213
|
|
|
@@ -195,24 +224,7 @@ class TurbineSpool(Spool):
|
|
|
195
224
|
3. Adjust the streamlines for each blade row to balance the massflow
|
|
196
225
|
"""
|
|
197
226
|
|
|
198
|
-
|
|
199
|
-
total_massflow = list(); s = 0; massflow_stage = list()
|
|
200
|
-
stage_ids = list(set([row.stage_id for row in self.blade_rows if row.stage_id>=0]))
|
|
201
|
-
for row in blade_rows[1:]:
|
|
202
|
-
total_massflow.append(row.total_massflow_no_coolant)
|
|
203
|
-
|
|
204
|
-
sign = 1
|
|
205
|
-
for s in stage_ids:
|
|
206
|
-
for row in blade_rows:
|
|
207
|
-
if row.stage_id == s and row.row_type == RowType.Rotor:
|
|
208
|
-
massflow_stage.append(sign*row.total_massflow_no_coolant)
|
|
209
|
-
sign*=-1
|
|
210
|
-
if len(stage_ids) % 2 == 1:
|
|
211
|
-
massflow_stage.append(massflow_stage[-1]*sign)
|
|
212
|
-
deviation = np.std(total_massflow)*2
|
|
213
|
-
if deviation>1.0:
|
|
214
|
-
print("high massflow deviation detected")
|
|
215
|
-
return np.std(total_massflow)*2 # + abs(sum(massflow_stage)) # Equation 28
|
|
227
|
+
|
|
216
228
|
|
|
217
229
|
# Balance the massflow between Stages
|
|
218
230
|
def balance_massflows(x0:List[float],blade_rows:List[List[BladeRow]],P0:npt.NDArray,P:npt.NDArray,balance_mean_pressure:bool=True):
|
|
@@ -239,27 +251,24 @@ class TurbineSpool(Spool):
|
|
|
239
251
|
if balance_mean_pressure:
|
|
240
252
|
for j in range(self.num_streamlines):
|
|
241
253
|
Ps_range = outlet_pressure(x0,P0[j],P[j])
|
|
242
|
-
for i in range(1,len(blade_rows)-
|
|
254
|
+
for i in range(1,len(blade_rows)-2):
|
|
243
255
|
blade_rows[i].P[j] = Ps_range[i-1]
|
|
244
|
-
blade_rows[-
|
|
256
|
+
blade_rows[-2].P = P
|
|
245
257
|
else:
|
|
246
258
|
for i in range(1,len(blade_rows)-1):
|
|
247
259
|
for j in range(self.num_streamlines):
|
|
248
260
|
blade_rows[i].P[j] = P[j]*x0[(i-1)*self.num_streamlines+j] # x0 size = num_streamlines -1
|
|
249
|
-
try:
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
except:
|
|
254
|
-
|
|
255
|
-
|
|
261
|
+
# try:
|
|
262
|
+
calculate_massflows(blade_rows,True,self.fluid)
|
|
263
|
+
print(x0)
|
|
264
|
+
return self.__massflow_std__(blade_rows)
|
|
265
|
+
# except Exception as e:
|
|
266
|
+
# print(e)
|
|
267
|
+
# finally:
|
|
268
|
+
# blade_rows = blade_rows_backup
|
|
269
|
+
# return np.inf # Return a high error
|
|
256
270
|
|
|
257
|
-
|
|
258
|
-
# for i in range(1,len(blade_rows)-1):
|
|
259
|
-
# for j in range(self.num_streamlines):
|
|
260
|
-
# blade_rows[i].P[j] = P[j]
|
|
261
|
-
# calculate_massflows(blade_rows,True)
|
|
262
|
-
# return 10
|
|
271
|
+
|
|
263
272
|
# Break apart the rows to stages
|
|
264
273
|
outlet_P=list(); outlet_P_guess = list() # Outlet P is the bounds, outlet_p_guess is the guessed values
|
|
265
274
|
|
|
@@ -267,63 +276,38 @@ class TurbineSpool(Spool):
|
|
|
267
276
|
outlet_P.append(self.blade_rows[i].inlet_to_outlet_pratio)
|
|
268
277
|
outlet_P_guess.append(np.mean(self.blade_rows[i].inlet_to_outlet_pratio))
|
|
269
278
|
|
|
270
|
-
print(
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
279
|
+
print(f"Looping to converge massflow")
|
|
280
|
+
past_err = -100; loop_iter = 0; err = 0.001
|
|
281
|
+
while np.abs((err-past_err)/err)>0.05:
|
|
282
|
+
if len(outlet_P) == 1:
|
|
283
|
+
# x = balance_massflows(0.658,self.blade_rows[:-1],self.blade_rows[0].P0,self.blade_rows[-1].P)
|
|
284
|
+
res = minimize_scalar(fun=balance_massflows,args=(self.blade_rows,self.blade_rows[0].P0,self.blade_rows[-1].P),bounds=outlet_P[0],tol=0.001,options={'disp': True},method='bounded')
|
|
285
|
+
x = res.x
|
|
286
|
+
print(x)
|
|
287
|
+
else:
|
|
288
|
+
x = fmin_slsqp(func=balance_massflows,args=(self.blade_rows,self.blade_rows[0].P0,self.blade_rows[-1].P),
|
|
289
|
+
bounds=outlet_P, x0=outlet_P_guess,epsilon=0.001,iter=100) # ,tol=0.001,options={'disp': True})
|
|
290
|
+
outlet_P_guess = x
|
|
280
291
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
292
|
+
# Adjust the inlet: Set the massflow
|
|
293
|
+
self.blade_rows[0].massflow = np.linspace(0,1,self.num_streamlines)*self.blade_rows[1].total_massflow_no_coolant
|
|
294
|
+
self.blade_rows[0].total_massflow_no_coolant = self.blade_rows[1].total_massflow_no_coolant
|
|
295
|
+
self.blade_rows[0].total_massflow = np.linspace(0,1,self.num_streamlines)*self.blade_rows[1].total_massflow_no_coolant
|
|
296
|
+
self.blade_rows[0].calculated_massflow = self.blade_rows[0].total_massflow_no_coolant
|
|
297
|
+
inlet_calc(self.blade_rows[0]) # adjust the inlet to match massflow
|
|
286
298
|
|
|
287
|
-
|
|
288
|
-
for _ in range(2):
|
|
299
|
+
if self.adjust_streamlines:
|
|
289
300
|
adjust_streamlines(self.blade_rows[:-1],self.passage)
|
|
290
|
-
|
|
291
|
-
self.blade_rows[-1].P = self.blade_rows[-1].get_static_pressure(self.blade_rows[-1].percent_hub_shroud)
|
|
292
|
-
balance_massflows(x,self.blade_rows[:-1],self.blade_rows[0].P0,self.blade_rows[-1].P)
|
|
293
|
-
else:
|
|
301
|
+
|
|
294
302
|
self.blade_rows[-1].transfer_quantities(self.blade_rows[-2])
|
|
295
303
|
self.blade_rows[-1].P = self.blade_rows[-1].get_static_pressure(self.blade_rows[-1].percent_hub_shroud)
|
|
296
|
-
|
|
297
|
-
|
|
304
|
+
|
|
305
|
+
err = self.__massflow_std__(self.blade_rows)
|
|
306
|
+
print(f"Loop {loop_iter} massflow convergenced error:{err}")
|
|
298
307
|
|
|
299
308
|
# calculate Reynolds number
|
|
300
309
|
compute_reynolds(self.blade_rows,self.passage)
|
|
301
310
|
|
|
302
|
-
# finetune = True
|
|
303
|
-
# if finetune:
|
|
304
|
-
# print('Finetune static pressure between stages')
|
|
305
|
-
# self.blade_rows[-1].transfer_quantities(self.blade_rows[-2])
|
|
306
|
-
# self.blade_rows[-1].P = self.blade_rows[-1].get_static_pressure(self.blade_rows[-1].percent_hub_shroud)
|
|
307
|
-
# P = [row.P for row in self.blade_rows] # Average static pressures
|
|
308
|
-
# bounds = []; guess = []
|
|
309
|
-
# for i in range(1,len(self.blade_rows)-1): # set the bounds
|
|
310
|
-
# for j in range(self.num_streamlines):
|
|
311
|
-
# bounds.append([0.8,1.2]) # vary by +- 20%
|
|
312
|
-
# guess.append(1)
|
|
313
|
-
|
|
314
|
-
# x = fmin_slsqp(func=balance_massflows,args=(self.blade_rows[:-1],self.blade_rows[0].P0,P,False),
|
|
315
|
-
# bounds=bounds, x0=guess,epsilon=0.001,iter=200)
|
|
316
|
-
# P = [row.P for row in self.blade_rows] # Average static pressures
|
|
317
|
-
|
|
318
|
-
# for _ in range(2):
|
|
319
|
-
# adjust_streamlines(self.blade_rows[:-1],self.passage)
|
|
320
|
-
# self.blade_rows[-1].transfer_quantities(self.blade_rows[-2])
|
|
321
|
-
# self.blade_rows[-1].P = self.blade_rows[-1].get_static_pressure(self.blade_rows[-1].percent_hub_shroud)
|
|
322
|
-
# balance_massflows(x,self.blade_rows[:-1],self.blade_rows[0].P0,P,False)
|
|
323
|
-
|
|
324
|
-
# err = calculate_error(self.blade_rows[:-1])
|
|
325
|
-
# print(f"Massflow convergenced error after finetuning:{err}")
|
|
326
|
-
|
|
327
311
|
|
|
328
312
|
def export_properties(self,filename:str="turbine_spool.json"):
|
|
329
313
|
"""Export the spool object to json
|
|
@@ -337,7 +321,7 @@ class TurbineSpool(Spool):
|
|
|
337
321
|
total_static_efficiency = list()
|
|
338
322
|
stage_loading = list()
|
|
339
323
|
euler_power = list()
|
|
340
|
-
|
|
324
|
+
enthalpy_power = list()
|
|
341
325
|
x_streamline = np.zeros((self.num_streamlines,len(self.blade_rows)))
|
|
342
326
|
r_streamline = np.zeros((self.num_streamlines,len(self.blade_rows)))
|
|
343
327
|
massflow = list()
|
|
@@ -352,14 +336,14 @@ class TurbineSpool(Spool):
|
|
|
352
336
|
|
|
353
337
|
stage_loading.append(row.stage_loading)
|
|
354
338
|
euler_power.append(row.euler_power)
|
|
355
|
-
|
|
339
|
+
enthalpy_power.append(row.power)
|
|
356
340
|
if row.row_type!=RowType.Inlet and row.row_type!=RowType.Outlet:
|
|
357
341
|
massflow.append(row.massflow[-1])
|
|
358
342
|
|
|
359
343
|
for j,p in enumerate(row.percent_hub_shroud):
|
|
360
344
|
t,x,r = self.passage.get_streamline(p)
|
|
361
|
-
x_streamline[j,indx] = float(interp1d(t,x)(row.
|
|
362
|
-
r_streamline[j,indx] = float(interp1d(t,r)(row.
|
|
345
|
+
x_streamline[j,indx] = float(interp1d(t,x)(row.percent_hub))
|
|
346
|
+
r_streamline[j,indx] = float(interp1d(t,r)(row.percent_hub))
|
|
363
347
|
|
|
364
348
|
Pratio_Total_Total = np.mean(self.blade_rows[0].P0 / self.blade_rows[-2].P0)
|
|
365
349
|
Pratio_Total_Static = np.mean(self.blade_rows[0].P0 / self.blade_rows[-2].P)
|
|
@@ -378,6 +362,8 @@ class TurbineSpool(Spool):
|
|
|
378
362
|
"xhub":self.passage.xhub_pts.tolist(),
|
|
379
363
|
"xshroud":self.passage.xshroud_pts.tolist(),
|
|
380
364
|
"num_streamlines":self.num_streamlines,
|
|
365
|
+
"euler_power": euler_power,
|
|
366
|
+
"enthalpy_power":enthalpy_power,
|
|
381
367
|
"total-total_efficiency":total_total_efficiency,
|
|
382
368
|
"total-static_efficiency":total_static_efficiency,
|
|
383
369
|
"stage_loading":stage_loading,
|
|
@@ -408,7 +394,7 @@ def calculate_massflows(blade_rows:List[BladeRow],calculate_vm:bool=False,fluid:
|
|
|
408
394
|
calculate_vm (bool, optional): _description_. Defaults to False.
|
|
409
395
|
"""
|
|
410
396
|
for p in range(3):
|
|
411
|
-
for i in range(1,len(blade_rows)):
|
|
397
|
+
for i in range(1,len(blade_rows)-1):
|
|
412
398
|
row = blade_rows[i]
|
|
413
399
|
# Upstream Row
|
|
414
400
|
if i == 0:
|
|
@@ -417,8 +403,6 @@ def calculate_massflows(blade_rows:List[BladeRow],calculate_vm:bool=False,fluid:
|
|
|
417
403
|
upstream = blade_rows[i-1]
|
|
418
404
|
if i<len(blade_rows)-1:
|
|
419
405
|
downstream = blade_rows[i+1]
|
|
420
|
-
else:
|
|
421
|
-
downstream = None
|
|
422
406
|
|
|
423
407
|
# Pressure loss = shift in entropy which affects the total pressure of the row
|
|
424
408
|
if row.row_type == RowType.Inlet:
|
|
@@ -430,13 +414,13 @@ def calculate_massflows(blade_rows:List[BladeRow],calculate_vm:bool=False,fluid:
|
|
|
430
414
|
if row.row_type == RowType.Rotor:
|
|
431
415
|
rotor_calc(row,upstream,calculate_vm=True)
|
|
432
416
|
# Finds Equilibrium between Vm, P0, T0
|
|
433
|
-
row = radeq(row,upstream)
|
|
417
|
+
row = radeq(row,upstream,downstream)
|
|
434
418
|
compute_gas_constants(row,fluid)
|
|
435
419
|
rotor_calc(row,upstream,calculate_vm=False)
|
|
436
420
|
elif row.row_type == RowType.Stator:
|
|
437
421
|
stator_calc(row,upstream,downstream,calculate_vm=True)
|
|
438
422
|
# Finds Equilibrium between Vm, P0, T0
|
|
439
|
-
row = radeq(row,upstream)
|
|
423
|
+
row = radeq(row,upstream,downstream)
|
|
440
424
|
compute_gas_constants(row,fluid)
|
|
441
425
|
stator_calc(row,upstream,downstream,calculate_vm=False)
|
|
442
426
|
compute_gas_constants(row,fluid)
|
|
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
|