turbo-design 1.3.6__py3-none-any.whl → 1.3.8__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.
- {turbo_design-1.3.6.dist-info → turbo_design-1.3.8.dist-info}/METADATA +3 -2
- {turbo_design-1.3.6.dist-info → turbo_design-1.3.8.dist-info}/RECORD +13 -13
- {turbo_design-1.3.6.dist-info → turbo_design-1.3.8.dist-info}/WHEEL +1 -1
- turbodesign/bladerow.py +19 -13
- turbodesign/loss/__init__.py +1 -1
- turbodesign/loss/losstype.py +35 -5
- turbodesign/loss/turbine/ainleymathieson.py +6 -6
- turbodesign/loss/turbine/craigcox.py +21 -21
- turbodesign/loss/turbine/kackerokapuu.py +81 -44
- turbodesign/loss/turbine/traupel.py +15 -15
- turbodesign/radeq.py +3 -2
- turbodesign/td_math.py +33 -5
- turbodesign/turbinespool.py +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: turbo-design
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.8
|
|
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
|
|
@@ -11,6 +11,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.11
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
14
15
|
Requires-Dist: cantera
|
|
15
16
|
Requires-Dist: findiff
|
|
16
17
|
Requires-Dist: matplotlib
|
|
@@ -1,33 +1,33 @@
|
|
|
1
1
|
turbodesign/__init__.py,sha256=N8Nu0I1vrlEHYJZZ7yhhg-FtbNbLyrgjy7hoicygUqg,325
|
|
2
2
|
turbodesign/arrayfuncs.py,sha256=GHIlTyLfeNsNCQQoh5m1aXK3iyvU6RjdYQipkqpU_ps,519
|
|
3
|
-
turbodesign/bladerow.py,sha256=
|
|
3
|
+
turbodesign/bladerow.py,sha256=Uad3UUnaRqCaEQBV1mHD04eU_lkz-BWr4n1vjFsX-eA,25472
|
|
4
4
|
turbodesign/cantera_gas/co2.yaml,sha256=M2o_RzxV9B9rDkgkXJC-l3voKraFZguTZuKKt4F7S_c,887
|
|
5
5
|
turbodesign/compressorspool.py,sha256=z8ZVczJ-EdZvIqqZArC6UdwC5MbU2SZh_MT2CGq5avY,2600
|
|
6
6
|
turbodesign/coolant.py,sha256=evDtUFOYhfZKTVAsDWzxRzUX20gTvfjj0uybaWg4CsI,427
|
|
7
7
|
turbodesign/enums.py,sha256=WC6VPmHw3UF1zR1SLjj8z00gIWSNso66MShFGoYRY4U,1164
|
|
8
8
|
turbodesign/inlet.py,sha256=5uja906IA-_gca4FJykZvFLJ1he6HRy5pZDNQE1D2_g,7945
|
|
9
9
|
turbodesign/isentropic.py,sha256=YLTmNx69e_M5fTuLOmk_KvaQ6ABv0aZsityfBihJOmI,2003
|
|
10
|
-
turbodesign/loss/__init__.py,sha256=
|
|
10
|
+
turbodesign/loss/__init__.py,sha256=jltNIIbUntGKq2IfX3EKUNEajIcHdOB7pWuj5tLtmGw,66
|
|
11
11
|
turbodesign/loss/compressor/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
12
|
-
turbodesign/loss/losstype.py,sha256=
|
|
12
|
+
turbodesign/loss/losstype.py,sha256=ViUf1ue3DZ3qFAhLUP3ps2fyygNH6udekAr53vEzrY8,1776
|
|
13
13
|
turbodesign/loss/turbine/TD2.py,sha256=evyTG4K6s56NGdjxrZFD3G7zsB8_2lJTBOxT3Ju2uG8,5207
|
|
14
14
|
turbodesign/loss/turbine/__init__.py,sha256=d1UrbiIicO60FhDlOemo_irYW2asUaYoqlXUz-UG9zk,285
|
|
15
|
-
turbodesign/loss/turbine/ainleymathieson.py,sha256=
|
|
16
|
-
turbodesign/loss/turbine/craigcox.py,sha256=
|
|
15
|
+
turbodesign/loss/turbine/ainleymathieson.py,sha256=uTl1wXcJZmNjeerGTYDYCs0vJhyMPjG_0C9xlvSKYqY,5911
|
|
16
|
+
turbodesign/loss/turbine/craigcox.py,sha256=2dydHVvxTKhmJsRHO7Vf2JFKM6xaUSeT_CPxf8PCtWs,9942
|
|
17
17
|
turbodesign/loss/turbine/fixedefficiency.py,sha256=JJv4GUS5q9pvuf3akjBtlcHOykRYmRVFfDDrdWqH6S4,774
|
|
18
18
|
turbodesign/loss/turbine/fixedpressureloss.py,sha256=sgkm6uQwz6Qz2LDCEmir46aJRSPLAdCKpDyR1hNdgQ8,682
|
|
19
|
-
turbodesign/loss/turbine/kackerokapuu.py,sha256=
|
|
20
|
-
turbodesign/loss/turbine/traupel.py,sha256=
|
|
19
|
+
turbodesign/loss/turbine/kackerokapuu.py,sha256=TQkTKG6ZdpsdEp1-qJfacQR8EEZSQ1qjUmOTf3t7mws,7263
|
|
20
|
+
turbodesign/loss/turbine/traupel.py,sha256=8KDjalPgBW3GoZUL7jgsyPFoDwNfcQhzmeRNrsZA0XA,4369
|
|
21
21
|
turbodesign/lossinterp.py,sha256=B2KEobp-nD9jwD6UINgBmTlH9kKyWg3UNvXxqfUsr-k,6198
|
|
22
22
|
turbodesign/outlet.py,sha256=MaZJ-mDuLvh19AashnMQLx2XlR-Rk1r0HQS4kE0OxeI,2191
|
|
23
23
|
turbodesign/passage.py,sha256=RZ8giKMcpJI7EnO4SEnbGYcPFmKdGyzWC0UZTXHnS6g,12181
|
|
24
|
-
turbodesign/radeq.py,sha256=
|
|
24
|
+
turbodesign/radeq.py,sha256=LEqYxZZocCZyVPhY09MNFTnAkEXM740-SR6QxXW8Ssg,6522
|
|
25
25
|
turbodesign/rotor.py,sha256=tHl9o5H4aQ6Etd4gqa8Ime1UK7k0de4GLt5Yb1sJdGs,1376
|
|
26
26
|
turbodesign/solve_radeq.py,sha256=nLYlRtXElPgHaoUP9jwMulRmYKTJs_uQ1eCulk2V59I,1938
|
|
27
27
|
turbodesign/spool.py,sha256=81UFbBi5JKm0RJ_hjB40bKWeCXx0V2lt0b2VAwOtTDU,14376
|
|
28
28
|
turbodesign/stage.py,sha256=UP45sDKDLsAkO_WfDWJ6kqXU7cYKh_4QO01QZnSN1oQ,166
|
|
29
|
-
turbodesign/td_math.py,sha256=
|
|
30
|
-
turbodesign/turbinespool.py,sha256=
|
|
31
|
-
turbo_design-1.3.
|
|
32
|
-
turbo_design-1.3.
|
|
33
|
-
turbo_design-1.3.
|
|
29
|
+
turbodesign/td_math.py,sha256=aL5lbRl7nB8hQA6HyyFTtNpAbJ1ybn1s8iybXIfqiO8,17549
|
|
30
|
+
turbodesign/turbinespool.py,sha256=REA5QmpRE58o-3cf4dtVS1ChCoriCcQmzCOssv9CYvc,25259
|
|
31
|
+
turbo_design-1.3.8.dist-info/METADATA,sha256=9XmBcAOWQZPo5yR2zQVkL-rVxLK8YKjkOQI-CGtaFjU,785
|
|
32
|
+
turbo_design-1.3.8.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
33
|
+
turbo_design-1.3.8.dist-info/RECORD,,
|
turbodesign/bladerow.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from dataclasses import field, Field
|
|
2
|
-
from typing import Any, Callable, List, Optional, Tuple, Union
|
|
2
|
+
from typing import Any, Callable, List, Optional, Sequence, Tuple, Union
|
|
3
3
|
from .enums import RowType, PowerType
|
|
4
4
|
import numpy as np
|
|
5
5
|
import numpy.typing as npt
|
|
@@ -9,7 +9,7 @@ from cantera import Solution, composite
|
|
|
9
9
|
from .coolant import Coolant
|
|
10
10
|
from pyturbo.helper import line2D
|
|
11
11
|
from pyturbo.aero.airfoil2D import Airfoil2D
|
|
12
|
-
from .loss import LossBaseClass
|
|
12
|
+
from .loss import LossBaseClass, CompositeLossModel
|
|
13
13
|
from .passage import Passage
|
|
14
14
|
|
|
15
15
|
|
|
@@ -406,19 +406,25 @@ class BladeRow:
|
|
|
406
406
|
return self.loss_function
|
|
407
407
|
|
|
408
408
|
@loss_model.setter
|
|
409
|
-
def loss_model(self, model:
|
|
410
|
-
"""
|
|
409
|
+
def loss_model(self, model:Union[LossBaseClass, Sequence[LossBaseClass]]):
|
|
410
|
+
"""Assign one or more loss models that inherit :class:`LossBaseClass`.
|
|
411
411
|
|
|
412
412
|
Args:
|
|
413
|
-
model
|
|
414
|
-
|
|
415
|
-
Example:
|
|
416
|
-
|
|
417
|
-
def mylossfunction(row:BladeRow) -> float
|
|
418
|
-
code to do something with machine learning
|
|
419
|
-
return pressure loss
|
|
413
|
+
model: Either a single loss model or a sequence of models.
|
|
420
414
|
"""
|
|
421
|
-
|
|
415
|
+
if isinstance(model, LossBaseClass):
|
|
416
|
+
self.loss_function = model
|
|
417
|
+
return
|
|
418
|
+
|
|
419
|
+
if isinstance(model, Sequence):
|
|
420
|
+
if len(model) == 0:
|
|
421
|
+
raise ValueError("At least one loss model must be provided.")
|
|
422
|
+
if not all(isinstance(m, LossBaseClass) for m in model):
|
|
423
|
+
raise TypeError("All entries must inherit LossBaseClass.")
|
|
424
|
+
self.loss_function = CompositeLossModel(model)
|
|
425
|
+
return
|
|
426
|
+
|
|
427
|
+
raise TypeError("Loss models must inherit LossBaseClass.")
|
|
422
428
|
|
|
423
429
|
@property
|
|
424
430
|
def te_pitch(self):
|
|
@@ -631,4 +637,4 @@ def compute_gas_constants(row:BladeRow,fluid:Optional[Solution]=None) -> None:
|
|
|
631
637
|
row.gamma = row.Cp/row.Cv
|
|
632
638
|
# Use Ideal Gas
|
|
633
639
|
row.rho = row.P/(row.T*row.R)
|
|
634
|
-
row.mu = sutherland(row.T) # type: ignore
|
|
640
|
+
row.mu = sutherland(row.T) # type: ignore
|
turbodesign/loss/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
from .losstype import LossType, LossBaseClass
|
|
1
|
+
from .losstype import LossType, LossBaseClass, CompositeLossModel
|
turbodesign/loss/losstype.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
from
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Any, Dict, Iterable, Tuple
|
|
2
3
|
from ..lossinterp import LossInterp
|
|
3
4
|
import os
|
|
4
5
|
from ..enums import LossType
|
|
5
6
|
|
|
6
|
-
class LossBaseClass:
|
|
7
|
+
class LossBaseClass(ABC):
|
|
7
8
|
data: Dict[str,LossInterp]
|
|
8
9
|
_loss_type:LossType
|
|
9
10
|
|
|
@@ -15,11 +16,40 @@ class LossBaseClass:
|
|
|
15
16
|
|
|
16
17
|
self._loss_type = lossType
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def __call__(self, row:Any, upstream:Any) -> float:
|
|
21
|
+
"""Evaluate the loss for the supplied blade row."""
|
|
22
|
+
raise NotImplementedError
|
|
20
23
|
|
|
21
24
|
|
|
22
25
|
|
|
23
26
|
@property
|
|
24
27
|
def loss_type(self):
|
|
25
|
-
return self._loss_type
|
|
28
|
+
return self._loss_type
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class CompositeLossModel(LossBaseClass):
|
|
32
|
+
"""Combines multiple loss models of the same type."""
|
|
33
|
+
|
|
34
|
+
def __init__(self, models: Iterable[LossBaseClass]):
|
|
35
|
+
models_tuple: Tuple[LossBaseClass, ...] = tuple(models)
|
|
36
|
+
if not models_tuple:
|
|
37
|
+
raise ValueError("CompositeLossModel requires at least one loss model.")
|
|
38
|
+
|
|
39
|
+
loss_type = models_tuple[0].loss_type
|
|
40
|
+
for model in models_tuple[1:]:
|
|
41
|
+
if model.loss_type != loss_type:
|
|
42
|
+
raise ValueError("All loss models must share the same LossType.")
|
|
43
|
+
|
|
44
|
+
super().__init__(loss_type)
|
|
45
|
+
self._models: Tuple[LossBaseClass, ...] = models_tuple
|
|
46
|
+
|
|
47
|
+
def __call__(self, row: Any, upstream: Any) -> float:
|
|
48
|
+
total_loss = 0.0
|
|
49
|
+
for model in self._models:
|
|
50
|
+
total_loss += float(model(row, upstream))
|
|
51
|
+
return total_loss
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def models(self) -> Tuple[LossBaseClass, ...]:
|
|
55
|
+
return self._models
|
|
@@ -69,7 +69,7 @@ class AinleyMathieson(LossBaseClass):
|
|
|
69
69
|
beta1 = -np.abs(np.radians(row.beta1_metal))
|
|
70
70
|
alpha2 = np.abs(row.alpha2)
|
|
71
71
|
if row.M<0.5:
|
|
72
|
-
alpha2 = self.data['Fig05'](np.degrees(np.cos(row.throat/row.pitch)))
|
|
72
|
+
alpha2 = self.data['Fig05'](float(np.degrees(np.cos(row.throat/row.pitch))))
|
|
73
73
|
elif row.M<0.95:
|
|
74
74
|
X = 0.7
|
|
75
75
|
alpha2 = np.arctan(
|
|
@@ -88,7 +88,7 @@ class AinleyMathieson(LossBaseClass):
|
|
|
88
88
|
beta1 = np.abs(np.radians(row.beta1_metal))
|
|
89
89
|
alpha2 = -np.abs(row.beta2)
|
|
90
90
|
if row.M_rel<0.5:
|
|
91
|
-
alpha2 = self.data['Fig05'](np.degrees(np.cos(row.throat/row.pitch)))
|
|
91
|
+
alpha2 = self.data['Fig05'](float(np.degrees(np.cos(row.throat/row.pitch))))
|
|
92
92
|
elif row.M_rel<0.95:
|
|
93
93
|
X = 1.35 # Shrouded Blade
|
|
94
94
|
alpha2 = np.arctan(
|
|
@@ -106,18 +106,18 @@ class AinleyMathieson(LossBaseClass):
|
|
|
106
106
|
ID = (upstream.r[-1]+row.r[-1])/2; OD = (upstream.r[-1]+row.r[-1])/2
|
|
107
107
|
A1 = np.pi*(upstream.r[-1]**2 - upstream.r[0]**2)*np.cos(beta1)
|
|
108
108
|
A2 = np.pi*(row.r[-1]**2 - row.r[0]**2)*np.cos(alpha2)
|
|
109
|
-
lam = self.data['Fig08']((A2/A1)**2/(1+ID/OD)) # Eqn but using Figure 8
|
|
109
|
+
lam = self.data['Fig08'](float((A2/A1)**2/(1+ID/OD))) # Eqn but using Figure 8
|
|
110
110
|
alpha_m = np.arctan((np.tan(alpha1) - np.tan(alpha2))/2)
|
|
111
111
|
Cl_s_c = 2*(np.tan(alpha1)-np.tan(alpha2))*np.cos(alpha_m)
|
|
112
112
|
# calculated but not used
|
|
113
113
|
Y_secondary_clearance = (lam + B * k/h) * (Cl_s_c)**2 * (np.cos(alpha2)/np.cos(alpha_m)) # Eqn 6
|
|
114
114
|
|
|
115
115
|
|
|
116
|
-
Yp_beta0 = self.data['Fig04a'](s_c, np.degrees(alpha2))
|
|
117
|
-
Yp_beta1_eq_alpha2 = self.data['Fig04b'](s_c, np.degrees(alpha2))
|
|
116
|
+
Yp_beta0 = self.data['Fig04a'](float(s_c), float(np.degrees(alpha2)))
|
|
117
|
+
Yp_beta1_eq_alpha2 = self.data['Fig04b'](float(s_c), float(np.degrees(alpha2)))
|
|
118
118
|
|
|
119
119
|
Yp_i0 = (Yp_beta0 + (beta1/alpha2)**2 *(Yp_beta1_eq_alpha2 - Yp_beta0)) *(t_c/0.2)**(-beta1/alpha2) # Fig 4 and Eqn 5
|
|
120
120
|
|
|
121
121
|
Yt = Yp_i0 + Y_secondary_clearance
|
|
122
122
|
return Yt # Profile loss at zero incidence
|
|
123
|
-
|
|
123
|
+
|
|
@@ -116,58 +116,58 @@ class CraigCox(LossBaseClass):
|
|
|
116
116
|
|
|
117
117
|
asin_os = np.degrees(np.arcsin(currentRow.throat/currentRow.pitch))
|
|
118
118
|
|
|
119
|
-
N_pr = self.data['Fig03'](Re,0.05) # use a good finish for the geometry
|
|
119
|
+
N_pr = self.data['Fig03'](float(Re), 0.05) # use a good finish for the geometry
|
|
120
120
|
if (inlet_flow_angle-imin < 10):
|
|
121
121
|
Fl = 13
|
|
122
122
|
else:
|
|
123
|
-
Fl = self.data['Fig04'](outlet_flow_angle,inlet_flow_angle-imin)
|
|
123
|
+
Fl = self.data['Fig04'](float(outlet_flow_angle), float(inlet_flow_angle-imin))
|
|
124
124
|
|
|
125
125
|
x = 1-np.sin(np.radians(outlet_flow_angle))/np.sin(np.radians(inlet_flow_angle))
|
|
126
|
-
contraction_ratio = self.data['Fig07'](x,s_b) # contraction ratio
|
|
126
|
+
contraction_ratio = self.data['Fig07'](float(x), float(s_b)) # contraction ratio
|
|
127
127
|
|
|
128
|
-
X_pb = self.data['Fig05'](Fl*s_b,contraction_ratio)
|
|
129
|
-
delta_X_pt = self.data['Fig06_delta_Xpt'](currentRow.te_pitch)
|
|
130
|
-
N_pt = self.data['Fig06_Npt'](currentRow.te_pitch,outlet_flow_angle)
|
|
131
|
-
delta_Xpm = self.data['Fig08'](M_out,np.degrees(np.arcsin((currentRow.throat+te)/currentRow.pitch)))
|
|
132
|
-
delta_Xp_se = self.data['Fig09'](e_s,M_out)
|
|
128
|
+
X_pb = self.data['Fig05'](float(Fl*s_b), float(contraction_ratio))
|
|
129
|
+
delta_X_pt = self.data['Fig06_delta_Xpt'](float(currentRow.te_pitch))
|
|
130
|
+
N_pt = self.data['Fig06_Npt'](float(currentRow.te_pitch), float(outlet_flow_angle))
|
|
131
|
+
delta_Xpm = self.data['Fig08'](float(M_out), float(np.degrees(np.arcsin((currentRow.throat+te)/currentRow.pitch))))
|
|
132
|
+
delta_Xp_se = self.data['Fig09'](float(e_s), float(M_out))
|
|
133
133
|
|
|
134
|
-
Fi = self.data['Fig15'](blade_inlet_angle,s_b)
|
|
134
|
+
Fi = self.data['Fig15'](float(blade_inlet_angle), float(s_b))
|
|
135
135
|
# Incidence Effects
|
|
136
136
|
if currentRow.beta1_fixed:
|
|
137
137
|
if incidence_angle>0: # Positive incidence
|
|
138
|
-
stall_incidence_angle = self.data['Fig11'](currentRow.beta1.mean(),asin_os)
|
|
138
|
+
stall_incidence_angle = self.data['Fig11'](float(currentRow.beta1.mean()), float(asin_os))
|
|
139
139
|
|
|
140
140
|
incidence_ratio = (incidence_angle - imin)/(stall_incidence_angle-imin)
|
|
141
141
|
|
|
142
|
-
i_plus_istall_sb = self.data['Fig12_sb'](s_b,asin_os)
|
|
143
|
-
i_plus_istall_cor = self.data['Fig12_cr'](contraction_ratio,asin_os)
|
|
142
|
+
i_plus_istall_sb = self.data['Fig12_sb'](float(s_b), float(asin_os))
|
|
143
|
+
i_plus_istall_cor = self.data['Fig12_cr'](float(contraction_ratio), float(asin_os))
|
|
144
144
|
|
|
145
145
|
if blade_inlet_angle<=90:
|
|
146
|
-
i_plus_istall_basic = self.data['Fig11'](inlet_flow_angle,asin_os)
|
|
146
|
+
i_plus_istall_basic = self.data['Fig11'](float(inlet_flow_angle), float(asin_os))
|
|
147
147
|
i_plus_istall = i_plus_istall_basic + i_plus_istall_sb + i_plus_istall_cor # Eqn 5
|
|
148
148
|
else:
|
|
149
|
-
i_plus_istall_basic = self.data["Fig14_i+istall"](blade_inlet_angle,asin_os)
|
|
149
|
+
i_plus_istall_basic = self.data["Fig14_i+istall"](float(blade_inlet_angle), float(asin_os))
|
|
150
150
|
i_plus_istall = i_plus_istall_basic + (1-(blade_inlet_angle-90)/(90-asin_os))*(i_plus_istall_sb + i_plus_istall_cor) # Eqn 7
|
|
151
151
|
else:
|
|
152
|
-
i_minus_istall_sb = self.data['Fig13'](s_b,asin_os)
|
|
152
|
+
i_minus_istall_sb = self.data['Fig13'](float(s_b), float(asin_os))
|
|
153
153
|
|
|
154
154
|
if blade_inlet_angle<=90:
|
|
155
|
-
i_minus_istall_basic = self.data['Fig13_alpha1'](s_b,asin_os)
|
|
155
|
+
i_minus_istall_basic = self.data['Fig13_alpha1'](float(s_b), float(asin_os))
|
|
156
156
|
i_minus_istall = i_minus_istall_basic + i_minus_istall_sb # Eqn 6
|
|
157
157
|
else:
|
|
158
|
-
i_minus_istall_basic = self.data["Fig14_i-istall"](blade_inlet_angle,asin_os)
|
|
158
|
+
i_minus_istall_basic = self.data["Fig14_i-istall"](float(blade_inlet_angle), float(asin_os))
|
|
159
159
|
i_minus_istall = i_minus_istall_basic + (1-(blade_inlet_angle - 90)/(90-asin_os)) * i_minus_istall_sb # Eqn 8
|
|
160
160
|
|
|
161
161
|
imin = (i_plus_istall + Fi * (i_minus_istall))/(1+Fi) # type: ignore # Eqn 9
|
|
162
|
-
N_pi = self.data['Fig10'](imin,incidence_ratio)
|
|
162
|
+
N_pi = self.data['Fig10'](float(imin), float(incidence_ratio))
|
|
163
163
|
else:
|
|
164
164
|
N_pi = 1 # No effect
|
|
165
165
|
|
|
166
166
|
Xp = X_pb*N_pr*N_pi*N_pt + delta_X_pt + delta_Xp_se + delta_Xpm # Eqn 10
|
|
167
167
|
|
|
168
168
|
# Secondary Loss
|
|
169
|
-
Ns_hb = self.data['Fig17'](1/currentRow.aspect_ratio)
|
|
170
|
-
x_sb = self.data['Fig18']((V_inlet/V)**2,s_b*Fl)
|
|
169
|
+
Ns_hb = self.data['Fig17'](float(1/currentRow.aspect_ratio))
|
|
170
|
+
x_sb = self.data['Fig18'](float((V_inlet/V)**2), float(s_b*Fl))
|
|
171
171
|
|
|
172
172
|
Nsr = 1 # N_pr # I have no clue about this. Craig Cox doesn't describe. setting it to 1 for now.
|
|
173
173
|
Xs = Nsr*Ns_hb*x_sb
|
|
@@ -192,4 +192,4 @@ class CraigCox(LossBaseClass):
|
|
|
192
192
|
# According to Equation 3, Group 1 loss is an enthalpy loss Cp*T0. Need to convert to Pressure Loss
|
|
193
193
|
eta_total = (upstream.T0.mean() - row.T0.mean())/(upstream.T0.mean()-(row.T0.mean()-T0_Loss))
|
|
194
194
|
return eta_total
|
|
195
|
-
|
|
195
|
+
|
|
@@ -8,14 +8,22 @@ import pathlib
|
|
|
8
8
|
from ..losstype import LossBaseClass
|
|
9
9
|
import requests
|
|
10
10
|
|
|
11
|
-
class KackerOkapuu(LossBaseClass):
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
def _mean_value(value):
|
|
13
|
+
"""Return the mean of an array-like as a Python float."""
|
|
14
|
+
return float(np.asarray(value).mean())
|
|
15
|
+
|
|
16
|
+
class KackerOkapuu(LossBaseClass):
|
|
17
|
+
UseCFM:bool = False
|
|
18
|
+
def __init__(self,UseCFM:bool=False):
|
|
14
19
|
"""KackerOkapuu model is an improvement to the Ainley Mathieson model.
|
|
15
20
|
|
|
16
21
|
Limitations:
|
|
17
22
|
- Doesn't factor incidence loss
|
|
18
23
|
- For steam turbines and impulse turbines
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
UseCFM (bool): Factor in supersonic drag rise. Authors state in AMDC loss that this is not accurate. It's a multplier to pressure loss.
|
|
19
27
|
|
|
20
28
|
Reference:
|
|
21
29
|
Kacker, S. C., and U. Okapuu. "A mean line prediction method for axial flow turbine efficiency." (1982): 111-119.
|
|
@@ -33,7 +41,7 @@ class KackerOkapuu(LossBaseClass):
|
|
|
33
41
|
|
|
34
42
|
with open(path.absolute(),'rb') as f:
|
|
35
43
|
self.data = pickle.load(f) # type: ignore
|
|
36
|
-
|
|
44
|
+
self.UseCFM = UseCFM
|
|
37
45
|
|
|
38
46
|
|
|
39
47
|
def __call__(self,row:BladeRow, upstream:BladeRow) -> float:
|
|
@@ -52,71 +60,100 @@ class KackerOkapuu(LossBaseClass):
|
|
|
52
60
|
Returns:
|
|
53
61
|
float: Pressure Loss
|
|
54
62
|
"""
|
|
55
|
-
|
|
56
|
-
M1 = upstream.M
|
|
57
|
-
else:
|
|
58
|
-
M1 = upstream.M_rel
|
|
59
|
-
|
|
63
|
+
# Get the Inlet incoming mach number relative to the blade
|
|
60
64
|
c = row.chord
|
|
61
65
|
b = row.axial_chord
|
|
62
66
|
if row.row_type == RowType.Stator:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
beta1_rad = np.abs(_mean_value(np.radians(row.beta1_metal))) # Metal angle from fig 3
|
|
68
|
+
alpha1_rad = np.abs(_mean_value(row.alpha1)) # Flow angle
|
|
69
|
+
alpha2_rad = np.abs(_mean_value(row.alpha2)) # Flow angle at exit which is metal angle
|
|
70
|
+
beta2_rad = alpha2_rad
|
|
71
|
+
alpham_rad = (alpha1_rad + alpha2_rad)*0.5
|
|
72
|
+
M1 = _mean_value(upstream.M)
|
|
73
|
+
M2 = _mean_value(row.M)
|
|
67
74
|
h = 0
|
|
68
|
-
Rec = row.V*row.rho*row.chord / sutherland(row.T)
|
|
75
|
+
Rec = _mean_value(row.V*row.rho*row.chord / sutherland(row.T))
|
|
76
|
+
|
|
77
|
+
beta1_deg = np.abs(np.degrees(beta1_rad))
|
|
78
|
+
alpha2_deg = np.abs(np.degrees(alpha2_rad))
|
|
79
|
+
Yp_beta0 = self.data['Fig01_beta0'](float(row.pitch_to_chord), alpha2_deg) # when beta1 = 0
|
|
80
|
+
Yp_beta1_alpha2 = self.data['Fig02'](float(row.pitch_to_chord), alpha2_deg) # When beta1 = alpha2
|
|
81
|
+
t_max_c = self.data['Fig04'](beta1_deg+alpha2_deg)
|
|
69
82
|
else:
|
|
70
83
|
h = row.tip_clearance * (row.r[-1]-row.r[0])
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
84
|
+
alpha1_rad = np.abs(_mean_value(row.beta1))
|
|
85
|
+
beta1_rad = np.abs(_mean_value(np.radians(row.beta1_metal))) # metal angles are stored as degrees
|
|
86
|
+
beta2_rad = np.abs(_mean_value(np.radians(row.beta2_metal)))
|
|
87
|
+
alpha2_rad = np.abs(_mean_value(row.beta2))
|
|
88
|
+
alpham_rad = (beta1_rad + beta2_rad)*0.5
|
|
89
|
+
M1 = _mean_value(upstream.M_rel)
|
|
90
|
+
M2 = _mean_value(row.M_rel)
|
|
91
|
+
Rec = _mean_value(row.W*row.rho*row.chord / sutherland(row.T))
|
|
92
|
+
|
|
93
|
+
beta1_deg = np.abs(np.degrees(beta1_rad))
|
|
94
|
+
alpha2_deg = np.abs(np.degrees(beta2_rad))
|
|
95
|
+
Yp_beta0 = self.data['Fig01_beta0'](float(row.pitch_to_chord), alpha2_deg) # when beta1 = 0
|
|
96
|
+
Yp_beta1_alpha2 = self.data['Fig02'](float(row.pitch_to_chord), alpha2_deg) # When beta1 = alpha2
|
|
97
|
+
t_max_c = self.data['Fig04'](beta1_deg+alpha2_deg)
|
|
80
98
|
|
|
81
|
-
|
|
99
|
+
ratio = beta1_rad / alpha2_rad
|
|
100
|
+
Yp_amdc = (Yp_beta0 + np.abs(ratio) * ratio * (Yp_beta1_alpha2-Yp_beta0)) * ((t_max_c)/0.2)**(ratio) # Eqn 2, AMDC = Ainley Mathieson Dunham Came
|
|
82
101
|
|
|
83
102
|
# Shock Loss
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
103
|
+
if M1>=0.4: # You'll have imaginary numbers if M1<0.4
|
|
104
|
+
dP_q1_hub = 0.75*(M1-0.4)**1.75 # Eqn 4, this is at the hub
|
|
105
|
+
dP_q1_shock = row.r[-1]/row.r[0] * dP_q1_hub # Eqn 5
|
|
106
|
+
Y_shock = dP_q1_shock * upstream.P/row.P * (1-(1+(upstream.gamma-1)/2*M1**2))/(1-(1+(row.gamma-1)/2*M2**2)) # Eqn 6
|
|
107
|
+
Y_shock = _mean_value(Y_shock)
|
|
108
|
+
else:
|
|
109
|
+
Y_shock = 0
|
|
87
110
|
|
|
88
|
-
|
|
111
|
+
if M2 <= 0.2:
|
|
112
|
+
K1 = 1
|
|
113
|
+
else:
|
|
114
|
+
K1 = 1-1.25*(M2-0.2)
|
|
89
115
|
K2 = (M1/M2)**2
|
|
90
116
|
Kp = 1-K2*(1-K1)
|
|
91
117
|
|
|
92
|
-
|
|
118
|
+
if (M2>1) and (self.UseCFM is True):
|
|
119
|
+
CFM = 1+60*(M2-1)**2 # Eqn 9
|
|
120
|
+
else:
|
|
121
|
+
CFM = 1
|
|
93
122
|
|
|
94
|
-
Yp = 0.914 * (2/3*Yp_amdc
|
|
123
|
+
Yp = 0.914 * (2/3*Yp_amdc*Kp + Y_shock) # Eqn 8 Subsonic regime
|
|
95
124
|
if M2>1:
|
|
96
125
|
Yp = Yp*CFM
|
|
97
126
|
|
|
98
127
|
f_ar = (1-0.25*np.sqrt(2-h/c)) / (h/c) if h/c<=2 else 1/(h/c)
|
|
99
|
-
alpham = np.arctan(0.5*(np.tan(
|
|
100
|
-
Cl_sc = 2*(np.tan(
|
|
101
|
-
Ys_amdc = 0.0334 *f_ar *np.cos(
|
|
102
|
-
# Secondary Loss
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
128
|
+
alpham = np.arctan(0.5*(np.tan(alpha1_rad) - np.tan(alpha2_rad)))
|
|
129
|
+
Cl_sc = 2*(np.tan(alpha1_rad)+np.tan(alpha2_rad))*np.cos(alpham)
|
|
130
|
+
Ys_amdc = 0.0334 *f_ar *np.cos(alpha2_rad)/np.cos(beta1_rad) * (Cl_sc)**2 * np.cos(alpha2_rad)**2 / np.cos(alpham)**3
|
|
131
|
+
# Secondary Loss
|
|
132
|
+
if h>0: # h is calculated from tip clearance. When h is 0 there is no tip clearance
|
|
133
|
+
K3 = 1/(h/(b))**2 # Fig 13, it's actually bx in the picture which is the axial chord; h is 0 this causes nan
|
|
134
|
+
Ks = 1-K3*(1-Kp) # Eqn 15
|
|
135
|
+
Ys = 1.2*Ys_amdc*Ks # Eqn 16
|
|
136
|
+
else:
|
|
137
|
+
K3 = 0
|
|
138
|
+
Ks = 0
|
|
139
|
+
Ys = 0
|
|
106
140
|
|
|
107
141
|
# Trailing Edge
|
|
108
|
-
if np.abs(
|
|
109
|
-
delta_phi2 = self.data['Fig14_Impulse'](row.te_pitch*row.pitch / row.throat)
|
|
142
|
+
if np.abs(beta1_deg-np.degrees(beta2_rad))<5: # impulse turbine the inlet and exit angles are the same
|
|
143
|
+
delta_phi2 = self.data['Fig14_Impulse'](float(row.te_pitch*row.pitch / row.throat))
|
|
110
144
|
else:
|
|
111
|
-
delta_phi2 = self.data['Fig14_Axial_Entry'](row.te_pitch*row.pitch / row.throat)
|
|
145
|
+
delta_phi2 = self.data['Fig14_Axial_Entry'](float(row.te_pitch*row.pitch / row.throat))
|
|
112
146
|
|
|
113
|
-
Ytet = (1-(row.gamma-1)/2
|
|
147
|
+
Ytet = (1-(row.gamma-1)/2 * M2**2 * (1/(1-delta_phi2)-1)) **(-row.gamma/(row.gamma-1)) - 1 # Equation 18
|
|
114
148
|
Ytet = Ytet / (1-(1+(row.gamma-1)/2*M2**2)**(-row.gamma/(row.gamma-1)))
|
|
115
149
|
|
|
116
150
|
# Tip Clearance
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
151
|
+
if h > 0:
|
|
152
|
+
kprime = row.tip_clearance/(3)**0.42 # Number of seals
|
|
153
|
+
Ytc = 0.37*c/h * (kprime/c)**0.78 * Cl_sc**2 * np.cos(alpha2_rad)**2 / np.cos(alpham)**3
|
|
154
|
+
else:
|
|
155
|
+
Ytc = 0
|
|
156
|
+
|
|
120
157
|
if Rec <= 2E5:
|
|
121
158
|
f_re = (Rec/2E5)**-0.4
|
|
122
159
|
elif Rec<1E6:
|
|
@@ -126,4 +163,4 @@ class KackerOkapuu(LossBaseClass):
|
|
|
126
163
|
|
|
127
164
|
Yt = Yp*f_re + Ys + Ytet + Ytc
|
|
128
165
|
return Yt
|
|
129
|
-
|
|
166
|
+
|
|
@@ -45,21 +45,21 @@ class Traupel(LossBaseClass):
|
|
|
45
45
|
|
|
46
46
|
if row.row_type == RowType.Rotor:
|
|
47
47
|
turning = np.abs(np.degrees(upstream.beta2-row.beta2).mean())
|
|
48
|
-
F = self.data['Fig06']((upstream.W/row.W).mean(),turning) # Inlet velocity
|
|
48
|
+
F = self.data['Fig06'](float((upstream.W/row.W).mean()), float(turning)) # Inlet velocity
|
|
49
49
|
else:
|
|
50
50
|
turning = np.abs(np.degrees(upstream.alpha2-row.alpha2).mean())
|
|
51
|
-
F = self.data['Fig06']((upstream.V/row.V).mean(),turning) # Inlet velocity
|
|
51
|
+
F = self.data['Fig06'](float((upstream.V/row.V).mean()), float(turning)) # Inlet velocity
|
|
52
52
|
|
|
53
|
-
H = self.data['Fig07'](alpha1-beta2,alpha2-beta3)
|
|
53
|
+
H = self.data['Fig07'](float(alpha1-beta2), float(alpha2-beta3))
|
|
54
54
|
|
|
55
55
|
zeta_s = F*g/h_stator # (h1-h1s)/(0.5*c1s**2) # no idea what h1s or h2s is
|
|
56
56
|
zeta_r = F*g/h_rotor # (h2-h2s)/(0.5*w2s**2)
|
|
57
|
-
x_p_stator = self.data['Fig01'](alpha1,alpha2) # not sure if this is the right figure
|
|
58
|
-
x_p_rotor = self.data['Fig01'](beta2,beta3) # not sure if this is the right figure
|
|
59
|
-
zeta_p_stator = self.data['Fig02'](alpha1,alpha2)
|
|
60
|
-
x_m_stator = self.data['Fig03_0'](upstream.M)
|
|
61
|
-
zeta_p_rotor = self.data['Fig02'](beta2,beta3)
|
|
62
|
-
x_m_rotor = self.data['Fig03_0'](row.M_rel)
|
|
57
|
+
x_p_stator = self.data['Fig01'](float(alpha1), float(alpha2)) # not sure if this is the right figure
|
|
58
|
+
x_p_rotor = self.data['Fig01'](float(beta2), float(beta3)) # not sure if this is the right figure
|
|
59
|
+
zeta_p_stator = self.data['Fig02'](float(alpha1), float(alpha2))
|
|
60
|
+
x_m_stator = self.data['Fig03_0'](float(np.mean(upstream.M)))
|
|
61
|
+
zeta_p_rotor = self.data['Fig02'](float(beta2), float(beta3))
|
|
62
|
+
x_m_rotor = self.data['Fig03_0'](float(np.mean(row.M_rel)))
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
e_te = upstream.te_pitch * g
|
|
@@ -67,10 +67,10 @@ class Traupel(LossBaseClass):
|
|
|
67
67
|
ssen_alpha2 = e_te/o # Thickness of Trailing edge divide by throat
|
|
68
68
|
ssen_beta2 = row.te_pitch*g / row.throat
|
|
69
69
|
|
|
70
|
-
x_delta_stator = self.data['Fig05'](ssen_alpha2,alpha2)
|
|
71
|
-
zeta_delta_stator = self.data['Fig04'](ssen_alpha2,alpha2)
|
|
72
|
-
x_delta_rotor = self.data['Fig05'](ssen_beta2,beta3)
|
|
73
|
-
zeta_delta_rotor = self.data['Fig04'](ssen_beta2,beta3)
|
|
70
|
+
x_delta_stator = self.data['Fig05'](float(ssen_alpha2), float(alpha2))
|
|
71
|
+
zeta_delta_stator = self.data['Fig04'](float(ssen_alpha2), float(alpha2))
|
|
72
|
+
x_delta_rotor = self.data['Fig05'](float(ssen_beta2), float(beta3))
|
|
73
|
+
zeta_delta_rotor = self.data['Fig04'](float(ssen_beta2), float(beta3))
|
|
74
74
|
|
|
75
75
|
Dm = 2* (upstream.r[-1] + upstream.r[0])/2 # Is this the mean diameter? I dont know
|
|
76
76
|
zeta_f = 0.5 * (h_stator/Dm)**2
|
|
@@ -85,7 +85,7 @@ class Traupel(LossBaseClass):
|
|
|
85
85
|
if row.row_type == RowType.Stator:
|
|
86
86
|
zeta_cl = 0
|
|
87
87
|
else:
|
|
88
|
-
zeta_cl = self.data['Fig08'](row.tip_clearance) # For simplicity assume unshrouded blade
|
|
88
|
+
zeta_cl = self.data['Fig08'](float(row.tip_clearance)) # For simplicity assume unshrouded blade
|
|
89
89
|
|
|
90
90
|
zeta_z = 0 # Do not factor this in, a bit complicated
|
|
91
91
|
# 1 - (internal) - (external)
|
|
@@ -97,4 +97,4 @@ class Traupel(LossBaseClass):
|
|
|
97
97
|
|
|
98
98
|
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
|
turbodesign/radeq.py
CHANGED
|
@@ -70,12 +70,13 @@ def radeq(row:BladeRow,upstream:BladeRow,downstream:Optional[BladeRow]=None) ->
|
|
|
70
70
|
down_Vm = interp1d(row_radius, downstream.Vm)(r)
|
|
71
71
|
else:
|
|
72
72
|
down_Vm = Vm
|
|
73
|
+
|
|
74
|
+
row_m = interp1d(row_radius, row.m)(r)
|
|
73
75
|
up_m = interp1d(row_radius, upstream.m)(r)
|
|
74
76
|
|
|
75
|
-
# Get a rough guess of dVm/
|
|
77
|
+
# Get a rough guess of dVm/dmv
|
|
76
78
|
if downstream!=None:
|
|
77
79
|
down_m = interp1d(row_radius, downstream.m)(r)
|
|
78
|
-
row_m = interp1d(row_radius, row.m)(r)
|
|
79
80
|
if down_m != row_m:
|
|
80
81
|
func_Vm_m = PchipInterpolator([up_m, row_m, down_m],[up_Vm, Vm, down_Vm])
|
|
81
82
|
else:
|
turbodesign/td_math.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
from typing import List, Optional
|
|
1
|
+
from typing import List, Optional
|
|
2
2
|
import numpy as np
|
|
3
|
-
import math
|
|
4
3
|
import numpy.typing as npt
|
|
5
4
|
from .bladerow import BladeRow, compute_gas_constants
|
|
6
5
|
from .enums import RowType, LossType
|
|
@@ -271,6 +270,26 @@ def rotor_calc(row:BladeRow,upstream:BladeRow,calculate_vm:bool=True):
|
|
|
271
270
|
row (BladeRow): Rotor Row
|
|
272
271
|
upstream (BladeRow): Stator Row or Rotor Row
|
|
273
272
|
"""
|
|
273
|
+
def _log_rotor_failure(reason:str):
|
|
274
|
+
def _fmt(val):
|
|
275
|
+
try:
|
|
276
|
+
return np.array2string(np.asarray(val), precision=5)
|
|
277
|
+
except Exception:
|
|
278
|
+
return str(val)
|
|
279
|
+
|
|
280
|
+
print(f"[RotorCalc] Failure detected: {reason}")
|
|
281
|
+
print(f" row.T0R: {_fmt(row.T0R)}")
|
|
282
|
+
print(f" row.T: {_fmt(row.T)}")
|
|
283
|
+
print(f" row.W: {_fmt(row.W)}")
|
|
284
|
+
print(f" row.M: {_fmt(getattr(row,'M', np.nan))}")
|
|
285
|
+
print(f" row.M_rel: {_fmt(getattr(row,'M_rel', np.nan))}")
|
|
286
|
+
print(f" row.Yp: {_fmt(getattr(row,'Yp', np.nan))}")
|
|
287
|
+
if np.any(row.T >= row.T0R):
|
|
288
|
+
print(" Note: T should be less than T0R.")
|
|
289
|
+
yp_val = getattr(row,'Yp', None)
|
|
290
|
+
if yp_val is not None and np.any(yp_val > 0.3):
|
|
291
|
+
print(" Note: row.Yp exceeded 0.3 which may indicate an issue with the design or loss model.")
|
|
292
|
+
|
|
274
293
|
row.P0_stator_inlet = upstream.P0_stator_inlet
|
|
275
294
|
## P0_P is assumed
|
|
276
295
|
# row.P = row.P0_stator_inlet*1/row.P0_P
|
|
@@ -303,9 +322,18 @@ def rotor_calc(row:BladeRow,upstream:BladeRow,calculate_vm:bool=True):
|
|
|
303
322
|
row.T = (row.T0R/T0R_T) # Exit static temperature
|
|
304
323
|
if calculate_vm: # Calculates the T0 at the exit
|
|
305
324
|
row.W = np.sqrt(2*row.Cp*(row.T0R-row.T)) #! nan popups here a lot for radial machines
|
|
306
|
-
|
|
325
|
+
nan_in_velocity = np.isnan(np.sum(row.W))
|
|
326
|
+
temp_issue = np.any(row.T >= row.T0R)
|
|
327
|
+
high_loss = np.any(getattr(row,'Yp',0) > 0.3)
|
|
328
|
+
if nan_in_velocity:
|
|
307
329
|
# Need to adjust T
|
|
308
|
-
|
|
330
|
+
reason = "nan detected in relative velocity"
|
|
331
|
+
if temp_issue:
|
|
332
|
+
reason += "; T >= T0R shouldn't happen because of T-s diagram'"
|
|
333
|
+
if high_loss:
|
|
334
|
+
reason += "; Yp > 0.3 This could be a problem with the loss model;"
|
|
335
|
+
_log_rotor_failure(reason)
|
|
336
|
+
raise ValueError(f'nan detected')
|
|
309
337
|
row.Vr = row.W*np.sin(row.phi)
|
|
310
338
|
row.Vm = row.W*np.cos(row.beta2)
|
|
311
339
|
row.Wt = row.W*np.sin(row.beta2)
|
|
@@ -378,4 +406,4 @@ def inlet_calc(row:BladeRow):
|
|
|
378
406
|
raise ValueError(f"High inlet mach can lead to errors iter:{iter} Mach:{avg_mach}")
|
|
379
407
|
|
|
380
408
|
if np.mean(row.M)<0.01:
|
|
381
|
-
print(f"Unusually slow flow:{iter} Mach:{avg_mach}")
|
|
409
|
+
print(f"Unusually slow flow:{iter} Mach:{avg_mach}")
|
turbodesign/turbinespool.py
CHANGED
|
@@ -449,9 +449,9 @@ def calculate_massflows(blade_rows:List[BladeRow],calculate_vm:bool=False,fluid:
|
|
|
449
449
|
row.Yp = 0
|
|
450
450
|
stator_calc(row,upstream,downstream,calculate_vm=True)
|
|
451
451
|
row = radeq(row,upstream)
|
|
452
|
-
|
|
452
|
+
compute_gas_constants(row,fluid)
|
|
453
453
|
stator_calc(row,upstream,downstream,calculate_vm=False)
|
|
454
|
-
|
|
454
|
+
compute_gas_constants(row,fluid)
|
|
455
455
|
compute_massflow(row)
|
|
456
456
|
compute_power(row,upstream)
|
|
457
457
|
|