turbo-design 1.1.3__py3-none-any.whl → 1.2.1__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.

@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.1
2
2
  Name: turbo-design
3
- Version: 1.1.3
3
+ Version: 1.2.1
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,7 +10,6 @@ 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
14
13
  Requires-Dist: cantera
15
14
  Requires-Dist: findiff
16
15
  Requires-Dist: matplotlib
@@ -1,11 +1,11 @@
1
1
  turbodesign/__init__.py,sha256=N8Nu0I1vrlEHYJZZ7yhhg-FtbNbLyrgjy7hoicygUqg,325
2
2
  turbodesign/arrayfuncs.py,sha256=GHIlTyLfeNsNCQQoh5m1aXK3iyvU6RjdYQipkqpU_ps,519
3
- turbodesign/bladerow.py,sha256=I0KYtw7c5cy32vxq1D54TrIkfsdbRlDWsnoCIADtCUA,24582
3
+ turbodesign/bladerow.py,sha256=M28spmHMwPc_3jVxzjzPwY-mbn4aeX5GrBEf4UomqYA,24857
4
4
  turbodesign/cantera_gas/co2.yaml,sha256=M2o_RzxV9B9rDkgkXJC-l3voKraFZguTZuKKt4F7S_c,887
5
5
  turbodesign/compressorspool.py,sha256=z8ZVczJ-EdZvIqqZArC6UdwC5MbU2SZh_MT2CGq5avY,2600
6
- turbodesign/coolant.py,sha256=nuj7ryUXuBhuOPt2jHjHwtEM_LVno7A8Wm14P0lJn-8,436
6
+ turbodesign/coolant.py,sha256=evDtUFOYhfZKTVAsDWzxRzUX20gTvfjj0uybaWg4CsI,427
7
7
  turbodesign/enums.py,sha256=T4aFrGMnx9fgZkrExMBIY2IbCueA0utqr_afk-TUe9Q,1188
8
- turbodesign/inlet.py,sha256=QeSvFi35JeOPevjQrz1TmAhoWkScXT9BRA_5oRTnDEE,6322
8
+ turbodesign/inlet.py,sha256=9vAI0rf8O03SV5iI2Kf154cktlPFzyuW-LR2Xy2hWz0,7365
9
9
  turbodesign/isentropic.py,sha256=YLTmNx69e_M5fTuLOmk_KvaQ6ABv0aZsityfBihJOmI,2003
10
10
  turbodesign/loss/__init__.py,sha256=ZJomzXa6ElduFruURukCrFwJQXMWS2aW8JSaVQ-M2r8,46
11
11
  turbodesign/loss/compressor/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
@@ -20,14 +20,14 @@ turbodesign/loss/turbine/kackerokapuu.py,sha256=hUmZdyA1hAhN3_xbwBhka2dyk0Aq9rqq
20
20
  turbodesign/loss/turbine/traupel.py,sha256=aZxFE9JDcCfi1gy-fqS1SxjjlhuDG-H-g3LPurty1M0,4164
21
21
  turbodesign/lossinterp.py,sha256=B2KEobp-nD9jwD6UINgBmTlH9kKyWg3UNvXxqfUsr-k,6198
22
22
  turbodesign/outlet.py,sha256=SwTwoL6XnWlsrE5A6wLxu3qXkydDDUsdKKeBbJm4mrQ,2069
23
- turbodesign/passage.py,sha256=a3DMc-QdlFEdjOEL1cockcTUFu_1iT1PSDrGo1qKN9s,9659
24
- turbodesign/radeq.py,sha256=RCsiQzcHvR5dozK6XG0eysAhXYewF0BY_qX0f1knURo,10091
23
+ turbodesign/passage.py,sha256=63ScNtLXd6T8flIre6dLsdSzjeS17PvH1atZhHdarEU,10788
24
+ turbodesign/radeq.py,sha256=gD-UYRuS1372GuxuOlhV13nEDqvFAVSf05fnZiF31Mo,10300
25
25
  turbodesign/rotor.py,sha256=tHl9o5H4aQ6Etd4gqa8Ime1UK7k0de4GLt5Yb1sJdGs,1376
26
- turbodesign/solve_radeq.py,sha256=2VGzFSVkyN0rTPFHaCQiD3v166cdEs39x7x7RuzLgmw,1886
27
- turbodesign/spool.py,sha256=h4m--HR5g8o01Kkhl4Mbvx7WORQez3YpncDE7XxbNaw,14172
26
+ turbodesign/solve_radeq.py,sha256=CK8uuvhs5jv0v0G90aUjKz0f_SOU16whnJWEiFCeUUA,1971
27
+ turbodesign/spool.py,sha256=kopByiu36urGuAfvDx9EI0DtMTt5leW3c2jUL3j4QhA,14216
28
28
  turbodesign/stage.py,sha256=UP45sDKDLsAkO_WfDWJ6kqXU7cYKh_4QO01QZnSN1oQ,166
29
- turbodesign/td_math.py,sha256=GjJdH9Mym1_vMSDT7lxilzSLVHBM5-Z5UE0wfsH2hr4,16153
30
- turbodesign/turbinespool.py,sha256=U_TMv5XNTlRWP9NJWTaaFWfNeTEGEuSVWt3HDi8QyFI,26124
31
- turbo_design-1.1.3.dist-info/METADATA,sha256=F1sI0aDeah1bWEhX57xeQTvt5aMMwHR9bkWyV7VFa-M,734
32
- turbo_design-1.1.3.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
33
- turbo_design-1.1.3.dist-info/RECORD,,
29
+ turbodesign/td_math.py,sha256=ZZmyCCAqha548bb5pkzqlhiGtvhtw8JO9qBAePNaleU,16098
30
+ turbodesign/turbinespool.py,sha256=xRqUmwyzNP5Hm5V9iLj_hcq8gWXpS_6-V90ev9VFZ5g,26619
31
+ turbo_design-1.2.1.dist-info/METADATA,sha256=ez_QBe7YfLBUE67nJZKrqVFpDnL-fDkB3dQ3Nxb_v_M,683
32
+ turbo_design-1.2.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
33
+ turbo_design-1.2.1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.0.1
2
+ Generator: poetry-core 1.9.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
turbodesign/bladerow.py CHANGED
@@ -26,7 +26,6 @@ class BladeRow:
26
26
  Cp: float = 1019 # Cp J/(Kg*K)
27
27
  Cv: float = 1019/1.14 # Cv J/(Kg*K)
28
28
  _coolant:Coolant = None # type: ignore # Coolant Fluid
29
- fluid: composite.Solution = Solution("air.yaml")
30
29
  mu:float = 0
31
30
 
32
31
  total_massflow:float = 0 # Massflow spool + all upstream cooling flow [kg/s]
@@ -437,7 +436,7 @@ class BladeRow:
437
436
  self._te_s = val
438
437
 
439
438
  def __repr__(self):
440
- return f"{self.row_type.name:0.2f}' P0:{np.mean(self.P0):0.2f} T0:{np.mean(self.T0):0.2f} P:{np.mean(self.P):0.2f} massflow:{self.total_massflow_no_coolant}:0.3f"
439
+ return f"{self.row_type.name} P0:{np.mean(self.P0):0.2f} T0:{np.mean(self.T0):0.2f} P:{np.mean(self.P):0.2f} massflow:{np.mean(self.total_massflow_no_coolant):0.3f}"
441
440
 
442
441
  def to_dict(self):
443
442
 
@@ -463,10 +462,10 @@ class BladeRow:
463
462
  "Vx":self.Vx.tolist(),
464
463
  "Vr":self.Vr.tolist(),
465
464
  "Vt":self.Vt.tolist(),
465
+ "U":self.U.tolist(),
466
466
  "V":self.V.tolist(),
467
467
  "M":self.M.tolist(),
468
468
  "M_rel":self.M_rel.tolist(),
469
- "U":self.U.tolist(),
470
469
  "W":self.W.tolist(),
471
470
  "Wt":self.Wt.tolist(),
472
471
  "omega":self.omega,
@@ -488,6 +487,10 @@ class BladeRow:
488
487
  "aspect_ratio":self.aspect_ratio,
489
488
  "num_blades":self.num_blades,
490
489
  "area": self.area,
490
+ "radius":self.r.tolist(),
491
+ "x":self.x.tolist(),
492
+ "dx":self.x[-1]-self.x[0],
493
+ "dr":self.r[-1]-self.r[0],
491
494
  "mprime":self.mprime[-1],
492
495
  "Reynolds":self.Reynolds,
493
496
  "axial_chord":self.axial_chord
@@ -605,21 +608,24 @@ def interpolate_quantities(q:npt.NDArray,r:npt.NDArray,r2:npt.NDArray):
605
608
  else:
606
609
  return interp1d(r,q,kind='linear')(r2)
607
610
 
608
- def compute_gas_constants(row:BladeRow):
609
- """Calculates all the gas constants for a row.
610
- This should be done if T or P change
611
+ def compute_gas_constants(row:BladeRow,fluid:Solution=None) -> None:
612
+ """Updates the Cp, Gamma, and density for a blade row. If fluid is not specified then only density and viscosity is updated.
613
+
614
+ Args:
615
+ row (BladeRow): _description_
616
+ fluid (Solution, optional): _description_. Defaults to None.
617
+
618
+ Returns:
619
+ (BladeRow): updated row
611
620
  """
612
- Tm = row.T.mean()
613
- Pm = row.P.mean()
614
- row.fluid.TP = Tm,Pm
615
- row.Cp = row.fluid.cp
616
- row.Cv = row.fluid.cv
617
- row.R = row.Cp-row.Cv
618
- row.gamma = row.Cp/row.Cv
619
- row.mu = sutherland(Tm) # type: ignore
620
- row.rho[:] = row.fluid.density
621
- # i = 0
622
- # for T,P in zip(row.T,row.P):
623
- # row.rho[i] = P/(T*row.R)
624
- # i+=1
625
- return row
621
+ if fluid:
622
+ Tm = row.T.mean()
623
+ Pm = row.P.mean()
624
+ fluid.TP = Tm,Pm
625
+ row.Cp = row.fluid.cp
626
+ row.Cv = row.fluid.cv
627
+ row.R = row.Cp-row.Cv
628
+ row.gamma = row.Cp/row.Cv
629
+ # Use Ideal Gas
630
+ row.rho = row.P/(row.T*row.R)
631
+ row.mu = sutherland(row.T) # type: ignore
turbodesign/coolant.py CHANGED
@@ -3,8 +3,8 @@ from cantera import Solution
3
3
 
4
4
  @dataclass
5
5
  class Coolant:
6
- fluid:Solution = field(default = Solution('air.yaml')) # cantera solution
7
6
  T0:float = field(default=900) # Kelvin
8
7
  P0:float = field(default=50*101325) # Pascal
9
- massflow_percentage:float = field(default=0.03) # Fraction of total massflow going through compressor
8
+ massflow_percentage:float = field(default=0.03) # Fraction of total massflow going through compressor
9
+ Cp:float = field(default=1000) # J/K
10
10
 
turbodesign/inlet.py CHANGED
@@ -16,50 +16,78 @@ class Inlet(BladeRow):
16
16
  (BladeRow): Defines the properties of the blade row
17
17
  """
18
18
  fun: interp1d
19
- def __init__(self,M:float,T0:Union[float,List[float]],P0:Union[float,List[float]],percent_radii:Union[float,List[float]],fluid:Solution,axial_location:float=0,beta:Union[float,List[float]]=[0]):
19
+
20
+ def __init__(self,M:float,T0:Union[float,List[float]],
21
+ P0:Union[float,List[float]],
22
+ axial_location:float=0,
23
+ beta:Union[float,List[float]]=[0],
24
+ percent_radii:Union[float,List[float]]=[0.5]):
20
25
  """Initializes the inlet station.
21
26
  Uses the beta and exit mach number to predict a value for Vm
22
27
 
23
28
  Args:
24
29
  M (float): Mach number at the inlet plane
25
- beta (Union[float,List[float]]): exit relative flow angle
26
30
  T0 (Union[float,List[float]]): Total Temperature Array
27
31
  P0 (Union[float,List[float]]): Total Pressure Array
28
32
  percent_radii (Union[float,List[float]]): Radius where total pressure and temperature are defined
29
- fluid (ct.Solution): Cantera mixture
30
33
  axial_location (float): Axial Location as a percentage of hub length
31
34
  beta (Union[float,List[float]], optional): Inlet flow angle in relative direction. Defaults to [].
35
+
32
36
  """
33
37
  super().__init__(row_type=RowType.Inlet,axial_location=axial_location,stage_id=-1)
34
- self.loss_function = None
35
38
  self.beta1 = convert_to_ndarray(beta)
36
39
  self.M = convert_to_ndarray(M)
37
40
  self.T0 = convert_to_ndarray(T0)
38
41
  self.P0 = convert_to_ndarray(P0)
39
42
  self.percent_hub_shroud = convert_to_ndarray(percent_radii)
43
+
44
+
45
+ def initialize_fluid(self,fluid:Solution=None,R:float=287.15,gamma:float=1.4,Cp:float=1024):
46
+ """Initialize the inlet using the fluid. This function should be called by a class that inherits from spool
47
+
48
+ Args:
49
+ fluid (Solution, optional): Cantera fluid object. Defaults to None.
50
+ R (float, optional): Ideal Gas Constant. Defaults to 287.15 J/(Kg K) for air
51
+ gamma (float, optional): _description_. Defaults to 1.4.
52
+ Cp (float, optional): _description_. Defaults to 1024 J/(Kg K).
53
+
54
+ """
55
+ self.loss_function = None
56
+
40
57
  # if it's inlet alpha and beta are the same, relative flow angle = absolute.
41
- self.beta2 = np.radians(convert_to_ndarray(beta))
42
- self.alpha1 = np.radians(convert_to_ndarray(beta))
43
- fluid.TP = self.T0.mean(),self.P0.mean()
44
- self.gamma = fluid.cp/fluid.cv
58
+ self.beta2 = np.radians(convert_to_ndarray(self.beta1))
59
+ self.alpha1 = np.radians(convert_to_ndarray(self.beta1))
45
60
 
46
- self.T = self.T0 * 1/(1 + (self.gamma-1) * self.M**2)
47
- self.P = self.P0 * 1/(1 + (self.gamma-1) * self.M**2)**(self.gamma/(self.gamma-1))
48
- fluid.TP = self.T.mean(),self.P.mean()
49
- self.rho = convert_to_ndarray([fluid.density])
50
- self.fluid = fluid
61
+ if fluid:
62
+ fluid.TP = self.T0.mean(),self.P0.mean()
63
+ self.gamma = fluid.cp/fluid.cv
64
+ self.T = self.T0 * 1/(1 + (self.gamma-1) * self.M**2)
65
+ self.P = self.P0 * 1/(1 + (self.gamma-1) * self.M**2)**(self.gamma/(self.gamma-1))
66
+ fluid.TP = self.T.mean(),self.P.mean()
67
+ self.rho = convert_to_ndarray([fluid.density])
68
+ else:
69
+ self.Cp = Cp
70
+ self.gamma = gamma
71
+ self.R = R
72
+ self.T = self.T0 * 1/(1 + (self.gamma-1) * self.M**2)
73
+ self.P = self.P0 * 1/(1 + (self.gamma-1) * self.M**2)**(self.gamma/(self.gamma-1))
74
+ self.rho = self.P/(self.R*self.T)
75
+
51
76
  self.rpm = 0
52
-
53
77
  self.beta1_metal = [0]
54
78
  self.beta2_metal = [0]
55
- self.P0_fun = interp1d(self.percent_hub_shroud,P0)
56
- self.T0_fun = interp1d(self.percent_hub_shroud,T0)
79
+ self.P0_fun = interp1d(self.percent_hub_shroud,self.P0)
80
+ self.T0_fun = interp1d(self.percent_hub_shroud,self.T0)
57
81
  self.mprime = [0]
58
-
59
82
 
60
83
  def initialize_velocity(self,passage:Passage,num_streamlines:int):
61
84
  """Initialize velocity calculations. Assumes streamlines and inclination angles have been calculated
62
-
85
+ Call this before performing calculations
86
+
87
+ Args:
88
+ passage (Passage): Passage object
89
+ num_streamlines (int): number of streamlines
90
+
63
91
  """
64
92
  # Perform Calculations on Velocity
65
93
  Vm_prev = 0; Vm_err = 0
@@ -84,7 +112,7 @@ class Inlet(BladeRow):
84
112
  self.V = np.sqrt(self.Vm**2 + self.Vt**2)
85
113
  self.Vr = self.Vm * np.sin(self.phi)
86
114
 
87
- self = compute_gas_constants(self)
115
+ compute_gas_constants(self)
88
116
  rho_mean = self.rho.mean()
89
117
  for i in range(len(self.massflow)-1):
90
118
  tube_massflow = self.massflow[i+1]-self.massflow[i]
turbodesign/passage.py CHANGED
@@ -1,22 +1,22 @@
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 interp1d
4
+ from scipy.interpolate import PchipInterpolator
5
5
  from pyturbo.helper import line2D
6
6
  from .enums import PassageType
7
7
  from scipy.optimize import minimize_scalar
8
8
  from findiff import FinDiff
9
- from pyturbo.helper import convert_to_ndarray
9
+ from pyturbo.helper import convert_to_ndarray,xr_to_mprime
10
10
  import matplotlib.pyplot as plt
11
11
 
12
12
  class Passage:
13
- xhub:interp1d
14
- rhub:interp1d
13
+ xhub:PchipInterpolator
14
+ rhub:PchipInterpolator
15
15
  xhub_pts:npt.NDArray
16
16
  rhub_pts:npt.NDArray
17
17
 
18
- xshroud:interp1d
19
- rshroud:interp1d
18
+ xshroud:PchipInterpolator
19
+ rshroud:PchipInterpolator
20
20
  xshroud_pts:npt.NDArray
21
21
  rshroud_pts:npt.NDArray
22
22
 
@@ -25,6 +25,7 @@ class Passage:
25
25
 
26
26
  x_streamlines:npt.NDArray
27
27
  r_streamlines:npt.NDArray
28
+ hub_arc_len:float
28
29
 
29
30
  def __init__(self,xhub:List[float],rhub:List[float],
30
31
  xshroud:List[float],rshroud:List[float],
@@ -41,12 +42,15 @@ class Passage:
41
42
  assert len(xhub) == len(xshroud), "xHub and xShroud should be the same length"
42
43
  assert len(rhub) == len(rshroud), "rHub and rShroud should be the same length"
43
44
 
45
+ hub_arc_len = xr_to_mprime(np.vstack([xhub,rhub]).transpose())[1]
46
+ self.hub_arc_len = hub_arc_len[-1]
47
+
48
+ self.xhub = PchipInterpolator(hub_arc_len/hub_arc_len[-1],xhub) # Get the xhub,rhub in terms of the hub arc len
49
+ self.rhub = PchipInterpolator(hub_arc_len/hub_arc_len[-1],rhub)
50
+ self.xshroud = PchipInterpolator(hub_arc_len/hub_arc_len[-1],xshroud)
51
+ self.rshroud = PchipInterpolator(hub_arc_len/hub_arc_len[-1],rshroud)
52
+
44
53
  self.n = len(xhub)
45
- t_streamline = np.linspace(0,1,len(xhub))
46
- self.xhub = interp1d(t_streamline,xhub)
47
- self.rhub = interp1d(t_streamline,rhub)
48
- self.xshroud = interp1d(t_streamline,xshroud)
49
- self.rshroud = interp1d(t_streamline,rshroud)
50
54
 
51
55
  self.xhub_pts = convert_to_ndarray(xhub)
52
56
  self.rhub_pts = convert_to_ndarray(rhub)
@@ -137,6 +141,30 @@ class Passage:
137
141
  r = r_streamline
138
142
 
139
143
  return phi, rm, r
144
+
145
+ def get_area(self,t_hub:float) -> float:
146
+ """Get Area
147
+
148
+ Args:
149
+ t_hub (float): Percent arc length along the hub
150
+
151
+ Returns:
152
+ float: Area
153
+ """
154
+ n = 100
155
+ line = self.get_cutting_line(t_hub)[0]
156
+ x,r = line.get_point(np.linspace(0,1,n))
157
+ total_area = 0
158
+ for j in range(1,n):
159
+ if np.abs((x[-1]-x[0]))<1E-12: # Axial Machines
160
+ total_area += np.pi*(r[j]**2-r[j-1]**2)
161
+ else: # Radial Machines
162
+ dx = x[j]-x[j-1]
163
+ S = (r[j]-r[j-1])
164
+ C = np.sqrt(1+((r[j]-r[j-1])/dx)**2)
165
+ area = 2*np.pi*C*(S/2*dx**2+r[j-1]*dx)
166
+ total_area += area
167
+ return total_area
140
168
 
141
169
  def get_cutting_line(self, t_hub:float) -> line2D:
142
170
  """Gets the cutting line perpendicular to hub and shroud
@@ -148,7 +176,7 @@ class Passage:
148
176
  (Tuple) containing:
149
177
 
150
178
  cut (line2D): line from hub to shroud
151
- t_hub (float): t corresponding to xhub location
179
+ t_hub (float): Percentage along hub arc length
152
180
  t_shroud (float): t corresponding to intersection of bisector of hub
153
181
 
154
182
  """
@@ -195,6 +223,7 @@ class Passage:
195
223
  np.NDArray: _description_
196
224
  """
197
225
  t_hub = np.linspace(axial_location[0],axial_location[1],100)
226
+ t_hub = convert_to_ndarray(t_hub)*self.hub_length
198
227
 
199
228
  shroud_pts_cyl = np.vstack([self.xshroud(t_hub),self.rshroud(t_hub)]).transpose()
200
229
  hub_pts_cyl = np.vstack([self.xhub(t_hub),self.rhub(t_hub)]).transpose()
turbodesign/radeq.py CHANGED
@@ -79,7 +79,12 @@ def radeq(row:BladeRow,upstream:BladeRow) -> BladeRow:
79
79
  raise Exception("Invalid value of C {C}, change reduce alpha or Vm")
80
80
  B = (1-C)**(gamma/(gamma-1))
81
81
  A = P0 * gamma/(gamma-1) * (1-C)**(1/(gamma-1))
82
- dVm_dr = 1/(2*Vm*A) * (rho*(Vt/r - Vm**2/rm * np.cos(phi) - Vr*dVr_dr) - dP0_dr*B) + 1/(2*T0) *dT0_dr # Eqn 6
82
+
83
+ epsilon = 1e-10 # or another small threshold
84
+ if abs(rm) > epsilon:
85
+ dVm_dr = 1/(2*Vm*A) * (rho*(Vt/r - Vm**2/rm * np.cos(phi) - Vr*dVr_dr) - dP0_dr*B) + 1/(2*T0) *dT0_dr # Eqn 6
86
+ else:
87
+ dVm_dr = 1/(2*Vm*A) * (rho*(Vt/r - Vr*dVr_dr) - dP0_dr*B) + 1/(2*T0) *dT0_dr # Eqn 6
83
88
 
84
89
  ydot = np.array([dP0_dr,dT0_dr,dVm_dr])
85
90
 
@@ -18,7 +18,8 @@ def adjust_streamlines(blade_rows:List[BladeRow],passage:Passage):
18
18
  passage (Passage): passage object describing the hub and shroud
19
19
 
20
20
  """
21
- for _,row in enumerate(blade_rows):
21
+ for row_index,row in enumerate(blade_rows):
22
+ print(f"Adjusting Streamlines to balance massflow Row: {row_index}")
22
23
  massflow_fraction = np.linspace(0,1,len(row.percent_hub_shroud))
23
24
  row.total_massflow = row.massflow[-1]
24
25
  ideal_massflow_fraction = row.massflow[-1] * massflow_fraction
turbodesign/spool.py CHANGED
@@ -1,7 +1,7 @@
1
1
  # type: ignore[arg-type, reportUnknownArgumentType]
2
2
  from dataclasses import field
3
3
  import json
4
- from typing import Dict, List, Union
4
+ from typing import Dict, List, Union, Optional
5
5
  import matplotlib.pyplot as plt
6
6
  from .bladerow import BladeRow
7
7
  import numpy as np
@@ -70,13 +70,12 @@ class Spool:
70
70
  2. Counter Rotation: We either use the RPM already persecribed for each blade row.
71
71
  '''
72
72
  if (type(self.blade_rows[i]) != Inlet) and (type(self.blade_rows[i]) != Outlet):
73
- self.blade_rows[i].fluid = self.fluid
74
73
  self.blade_rows[i].rpm = rpm
75
74
  self.blade_rows[i].axial_chord = self.blade_rows[i].axial_location * self.passage.hub_length
76
75
 
77
76
 
78
77
  @property
79
- def fluid(self):
78
+ def fluid(self) -> Optional[Solution]:
80
79
  return self._fluid
81
80
 
82
81
  @fluid.setter
@@ -164,8 +163,9 @@ class Spool:
164
163
  self.calculate_streamline_curvature(row,t_radial)
165
164
 
166
165
  # Set the loss function if it's not set
167
- if (row.loss_function == None):
168
- row.loss_function = TD2()
166
+ if (type(row)!= Inlet and type(row) != Outlet):
167
+ if row.loss_function == None:
168
+ row.loss_function = TD2()
169
169
 
170
170
  def calculate_streamline_curvature(self,row:BladeRow,t_radial:Union[List[float],npt.NDArray]):
171
171
  """Called to calculate new streamline curvature
turbodesign/td_math.py CHANGED
@@ -6,6 +6,7 @@ from .bladerow import BladeRow, compute_gas_constants
6
6
  from .enums import RowType, LossType
7
7
  from scipy.integrate import trapezoid
8
8
  from .passage import Passage
9
+ from .isentropic import IsenP
9
10
 
10
11
  def T0_coolant_weighted_average(row:BladeRow) -> float:
11
12
  """Calculate the new weighted Total Temperature array considering coolant
@@ -17,11 +18,12 @@ def T0_coolant_weighted_average(row:BladeRow) -> float:
17
18
  Returns:
18
19
  float: Total Temperature drop
19
20
  """
20
- row.coolant.fluid.TP = row.coolant.T0, row.coolant.P0
21
+
21
22
  massflow = row.massflow
22
23
  total_massflow_no_coolant = row.total_massflow_no_coolant
23
24
  Cp = row.Cp
24
- Cpc = row.coolant.fluid.cp
25
+
26
+ Cpc = row.coolant.Cp
25
27
  T0c = row.coolant.T0
26
28
  massflow_coolant = row.coolant.massflow_percentage*total_massflow_no_coolant*row.massflow[1:]/row.massflow[-1]
27
29
  if massflow_coolant.mean()>0:
@@ -35,8 +37,9 @@ def T0_coolant_weighted_average(row:BladeRow) -> float:
35
37
  else:
36
38
  T0R = row.T0R
37
39
  T0R_new = T0R.copy()
40
+ Cp = row.Cp
38
41
  T0R_new[1:] = (massflow[1:]*Cp*T0R[1:] + massflow_coolant*Cpc*T0c) \
39
- /(massflow[1:]*row.fluid.cp + massflow_coolant*Cpc)
42
+ /(massflow[1:]*Cp + massflow_coolant*Cpc)
40
43
  T0R_new[0] = T0R_new[1]
41
44
 
42
45
  T = T0R_new - row.W**2/(2*Cp) # Dont change the velocity triangle but adjust the static temperature
@@ -61,7 +64,7 @@ def compute_massflow(row:BladeRow) -> None:
61
64
  for j in range(1,len(row.percent_hub_shroud)):
62
65
  Vm = (row.Vm[j]+row.Vm[j-1])/2
63
66
  rho = (row.rho[j]+row.rho[j-1])/2
64
- if np.abs((row.x[j]-row.x[j-1]))<1E-12: # Axial Machines
67
+ if np.abs((row.x[j]-row.x[j-1]))<1E-5: # Axial Machines
65
68
  total_area += np.pi*(row.r[j]**2-row.r[j-1]**2)
66
69
  massflow[j] = Vm * rho * np.pi* (row.r[j]**2-row.r[j-1]**2) + massflow[j-1]
67
70
  else: # Radial Machines
@@ -77,6 +80,7 @@ def compute_massflow(row:BladeRow) -> None:
77
80
  massflow += massflow_fraction*row.coolant.massflow_percentage*row.total_massflow_no_coolant # Take into account the coolant massflow
78
81
  row.massflow = massflow
79
82
  row.calculated_massflow = massflow[-1]
83
+ row.total_massflow = massflow[-1]
80
84
  row.area = total_area
81
85
 
82
86
  def compute_reynolds(rows:List[BladeRow],passage:Passage):
@@ -125,11 +129,14 @@ def compute_power(row:BladeRow,upstream:BladeRow) -> None:
125
129
  row.T_is = 0
126
130
  row.T0_is = 0
127
131
  else:
128
- row.T_is = row.T0R*(row.P/upstream.P0R)**((row.gamma-1)/row.gamma)
129
- row.T0_is = row.T_is*(1+(row.gamma-1)/2*row.M**2)
132
+ P0_P = (upstream.P0/row.P).mean()
133
+ row.T_is = upstream.T0 * (1/P0_P)**((row.gamma-1)/row.gamma)
134
+ a = np.sqrt(row.gamma*row.R*row.T_is)
135
+ row.T0_is = row.T_is * (1+(row.gamma-1)/2*(row.V/a)**2)
136
+
130
137
  row.power = row.massflow[-1] * row.Cp * (upstream.T0.mean() - row.T0.mean())
131
- row.eta_static = row.power/ (row.massflow[-1]*row.Cp*(upstream.T0.mean()-row.T0_is.mean()))
132
- row.eta_total = row.power / (row.massflow[-1]*row.Cp * (upstream.T0.mean()-row.T0_is.mean()))
138
+ row.eta_static = row.power/ (row.massflow[-1]*row.Cp*(upstream.T0.mean()-row.T_is.mean()))
139
+ row.eta_total = (upstream.T0.mean() - row.T0.mean()) / (upstream.T0.mean() - row.T0_is.mean())
133
140
  row.stage_loading = row.Cp*(upstream.T0.mean() - row.T0.mean())/row.U.mean()**2
134
141
  row.euler_power = row.massflow[-1]* (upstream.U*upstream.Vt - row.U*row.Vt).mean()
135
142
 
@@ -150,7 +157,7 @@ def compute_quantities(row:BladeRow,upstream:BladeRow):
150
157
  if row.row_type == RowType.Rotor:
151
158
  Cp_avg = (row.Cp+upstream.Cp)/2
152
159
  # Factor any coolant added and changes in streamline radius
153
- row.T0R = upstream.T0R - T0_coolant_weighted_average(row) - (upstream.U**2-row.U**2)/(2*Cp_avg)
160
+ row.T0R = upstream.T0R - T0_coolant_weighted_average(row) # - (upstream.U**2-row.U**2)/(2*Cp_avg)
154
161
  row.P = upstream.P0_stator_inlet/row.P0_P
155
162
 
156
163
  if row.loss_function.loss_type == LossType.Pressure:
@@ -232,13 +239,13 @@ def stator_calc(row:BladeRow,upstream:BladeRow,downstream:BladeRow=None,calculat
232
239
  if calculate_vm:
233
240
  row.M = ((row.P0/row.P)**((row.gamma-1)/row.gamma) - 1) * 2/(row.gamma-1)
234
241
  row.M = np.sqrt(row.M)
235
- T0_T = (1+(row.gamma-1)/2 * row.M.mean()**2)
242
+ T0_T = (1+(row.gamma-1)/2 * row.M**2)
236
243
  row.T0 = upstream.T0 - T0_coolant_weighted_average(row)
237
244
  row.T = row.T0/T0_T
238
245
  row.V = row.M*np.sqrt(row.gamma*row.R*row.T)
246
+ row.Vm = row.V*np.cos(row.alpha2)
239
247
  row.Vx = row.Vm*np.cos(row.phi)
240
- row.Vr = row.V*np.sin(row.phi)
241
- row.Vm = np.sqrt(row.Vx**2+row.Vr**2)
248
+ row.Vr = row.Vm*np.sin(row.phi)
242
249
  row.Vt = row.Vm*np.tan(row.alpha2)
243
250
  else: # We know Vm, P0, T0, P
244
251
  row.Vx = row.Vm*np.cos(row.phi)
@@ -289,7 +296,7 @@ def rotor_calc(row:BladeRow,upstream:BladeRow,calculate_vm:bool=True):
289
296
  row.P0R = upstream.P0R - row.Yp*(upstream.P0R-row.P)
290
297
 
291
298
  # Total Relative Temperature stays constant through the rotor. Adjust for change in radius from rotor inlet to exit
292
- row.T0R = (upstream_rothalpy + 0.5*row.U**2)/row.Cp - T0_coolant_weighted_average(row)
299
+ row.T0R =upstream.T0R - T0_coolant_weighted_average(row) # (upstream_rothalpy + 0.5*row.U**2)/row.Cp - T0_coolant_weighted_average(row)
293
300
  P0R_P = row.P0R / row.P
294
301
  T0R_T = P0R_P**((row.gamma-1)/row.gamma)
295
302
  row.T = (row.T0R/T0R_T) # Exit static temperature
@@ -297,7 +304,7 @@ def rotor_calc(row:BladeRow,upstream:BladeRow,calculate_vm:bool=True):
297
304
  row.W = np.sqrt(2*row.Cp*(row.T0R-row.T)) #! nan popups here a lot for radial machines
298
305
  if np.isnan(np.sum(row.W)):
299
306
  # Need to adjust T
300
- print(f'nan detected: check flow path. Turbine inlet cut should be horizontal')
307
+ raise ValueError(f'nan detected: check flow path. Turbine inlet cut should be horizontal')
301
308
  row.Vr = row.W*np.sin(row.phi)
302
309
  row.Vm = row.W*np.cos(row.beta2)
303
310
  row.Wt = row.W*np.sin(row.beta2)
@@ -327,11 +334,6 @@ def rotor_calc(row:BladeRow,upstream:BladeRow,calculate_vm:bool=True):
327
334
 
328
335
  row.M_rel = row.W/np.sqrt(row.gamma*row.R*row.T)
329
336
  row.T0 = row.T+row.V**2/(2*row.Cp)
330
-
331
- T3_is = upstream.T0 * (1/row.P0_P)**((row.gamma-1)/row.gamma)
332
- a = np.sqrt(row.gamma*row.R*T3_is)
333
- T03_is = T3_is * (1+(row.gamma-1)/2*(row.V/a)**2)
334
- row.eta_total = (upstream.T0.mean() - row.T0.mean())/(upstream.T0.mean()-T03_is.mean())
335
337
 
336
338
  def inlet_calc(row:BladeRow):
337
339
  """Calculates the conditions for the Inlet
@@ -339,12 +341,13 @@ def inlet_calc(row:BladeRow):
339
341
  Args:
340
342
  row (BladeRow): _description_
341
343
  """
344
+
342
345
  area = row.Vm.copy()*0
343
346
  # Estimate the density
344
347
  row.T = row.T0
345
- row.P = row.P0
348
+ row.P = row.P0
346
349
  row.rho = row.P/(row.T*row.R)
347
- total_area = 0
350
+ total_area = 0
348
351
  for iter in range(5): # Lets converge the Mach and Total and Static pressures
349
352
  for j in range(1,len(row.percent_hub_shroud)):
350
353
  rho = row.rho[j]
@@ -361,9 +364,9 @@ def inlet_calc(row:BladeRow):
361
364
  row.Vm[j] = tube_massflow/(rho*area[j])
362
365
  avg_mach = np.mean(row.M)
363
366
  if np.mean(row.M)>0.5:
364
- print(f"High inlet mach can lead to errors iter:{iter} Mach:{avg_mach}")
367
+ raise ValueError(f"High inlet mach can lead to errors iter:{iter} Mach:{avg_mach}")
365
368
  if np.mean(row.M)<0.01:
366
- print(f"Unusually slow flow:{iter} Mach:{avg_mach}")
369
+ raise ValueError(f"Unusually slow flow:{iter} Mach:{avg_mach}")
367
370
  row.Vm[0] = 1/(len(row.Vm)-1)*row.Vm[1:].sum() # Initialize the value at the hub to not upset the mean
368
371
  row.Vr = row.Vm*np.sin(row.phi)
369
372
  row.Vt = row.Vm*np.cos(row.phi)*np.tan(row.alpha2)
@@ -10,17 +10,18 @@ import numpy as np
10
10
  import numpy.typing as npt
11
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
- from scipy.optimize import minimize_scalar, minimize, fmin_slsqp
13
+ from scipy.optimize import minimize_scalar, differential_evolution, fmin_slsqp
14
14
  from .inlet import Inlet
15
15
  from .outlet import Outlet
16
16
 
17
17
  class TurbineSpool(Spool):
18
+
18
19
  def __init__(self,passage:Passage,
19
20
  massflow:float,rows:List[BladeRow],
20
21
  num_streamlines:int=3,
21
22
  fluid:Solution=Solution('air.yaml'),
22
23
  rpm:float=-1,
23
- massflow_constraint:MassflowConstraint=MassflowConstraint.MatchMassFlow):
24
+ massflow_constraint:MassflowConstraint=MassflowConstraint.MatchMassFlow):
24
25
  """Initializes a Turbine Spool
25
26
 
26
27
  Args:
@@ -45,21 +46,22 @@ class TurbineSpool(Spool):
45
46
  # Inlet
46
47
  W0 = self.massflow
47
48
  inlet = self.blade_rows[0]
48
- if self.blade_rows[0].row_type == RowType.Inlet:
49
- self.blade_rows[0].massflow = np.linspace(0,1,self.num_streamlines)*W0
50
- self.blade_rows[0].total_massflow = W0
51
- self.blade_rows[0].total_massflow_no_coolant = W0
49
+ if self.fluid:
50
+ inlet.initialize_fluid(self.fluid)
51
+ else:
52
+ inlet.initialize_fluid(R=self.blade_rows[1].R,
53
+ gamma=self.blade_rows[1].gamma,
54
+ Cp=self.blade_rows[1].Cp)
55
+
56
+ inlet.total_massflow = W0
57
+ inlet.total_massflow_no_coolant = W0
58
+ inlet.massflow = np.linspace(0,1,self.num_streamlines)*W0
52
59
 
53
- interpolate_streamline_radii(self.blade_rows[0],self.passage,self.num_streamlines)
60
+ inlet.initialize_velocity(self.passage,self.num_streamlines)
61
+ interpolate_streamline_radii(inlet,self.passage,self.num_streamlines)
54
62
 
55
- # Set the gas to total values for now
56
- self.blade_rows[0].fluid.TP = self.blade_rows[0].T0.mean(), self.blade_rows[0].P0.mean()
57
- self.blade_rows[0].Cp = self.blade_rows[0].fluid.cp
58
- self.blade_rows[0].Cv = self.blade_rows[0].fluid.cv
59
- self.blade_rows[0].R = self.blade_rows[0].Cp-self.blade_rows[0].Cv
60
- self.blade_rows[0].gamma = self.blade_rows[0].Cp/self.blade_rows[0].Cv
61
- self.blade_rows[0].rho[:] = self.blade_rows[0].fluid.density
62
- inlet_calc(self.blade_rows[0])
63
+ compute_gas_constants(inlet,self.fluid)
64
+ inlet_calc(inlet)
63
65
 
64
66
  for row in self.blade_rows:
65
67
  interpolate_streamline_radii(row,self.passage,self.num_streamlines)
@@ -83,10 +85,10 @@ class TurbineSpool(Spool):
83
85
 
84
86
  row = self.blade_rows[i]
85
87
  if (row.coolant is not None):
86
- T0c = self.blade_rows[i].coolant.fluid.T
87
- P0c = self.blade_rows[i].coolant.fluid.P
88
+ T0c = self.blade_rows[i].coolant.T0
89
+ P0c = self.blade_rows[i].coolant.P0
88
90
  W0c = self.blade_rows[i].coolant.massflow_percentage * self.massflow
89
- Cpc = self.blade_rows[i].coolant.fluid.cp
91
+ Cpc = self.blade_rows[i].coolant.Cp
90
92
  else:
91
93
  T0c = 100
92
94
  P0c = 0
@@ -133,9 +135,9 @@ class TurbineSpool(Spool):
133
135
  self.initialize_quantities()
134
136
 
135
137
  if self.massflow_constraint ==MassflowConstraint.MatchMassFlow:
136
- self.__match_massflow()
138
+ self.__match_massflow() # Matches massflow by changing turning angle
137
139
  elif self.massflow_constraint == MassflowConstraint.BalanceMassFlow:
138
- self.__balance_massflow()
140
+ self.__balance_massflow() # Balances massflow by changing row exit static pressure
139
141
 
140
142
 
141
143
  def __match_massflow(self):
@@ -169,8 +171,8 @@ class TurbineSpool(Spool):
169
171
  elif row.row_type == RowType.Stator:
170
172
  row.alpha2[j] = np.radians(res.x)
171
173
  row.alpha2[0] = 1/(len(row.alpha2)-1)*row.alpha2[1:].sum()
172
- upstream = compute_gas_constants(upstream)
173
- row = compute_gas_constants(row)
174
+ compute_gas_constants(upstream,self.fluid)
175
+ compute_gas_constants(row,self.fluid)
174
176
 
175
177
 
176
178
  # Step 3: Adjust streamlines to evenly divide massflow
@@ -198,7 +200,7 @@ class TurbineSpool(Spool):
198
200
  stage_ids = list(set([row.stage_id for row in self.blade_rows if row.stage_id>=0]))
199
201
  for row in blade_rows[1:]:
200
202
  total_massflow.append(row.total_massflow_no_coolant)
201
-
203
+
202
204
  sign = 1
203
205
  for s in stage_ids:
204
206
  for row in blade_rows:
@@ -232,9 +234,10 @@ class TurbineSpool(Spool):
232
234
  Returns:
233
235
  _type_: _description_
234
236
  """
237
+ blade_rows_backup = copy.deepcopy(blade_rows)
235
238
  # try:
236
239
  if balance_mean_pressure:
237
- for j in range(self.num_streamlines):
240
+ for j in range(self.num_streamlines):
238
241
  Ps_range = outlet_pressure(x0,P0[j],P[j])
239
242
  for i in range(1,len(blade_rows)-1):
240
243
  blade_rows[i].P[j] = Ps_range[i-1]
@@ -243,10 +246,14 @@ class TurbineSpool(Spool):
243
246
  for i in range(1,len(blade_rows)-1):
244
247
  for j in range(self.num_streamlines):
245
248
  blade_rows[i].P[j] = P[j]*x0[(i-1)*self.num_streamlines+j] # x0 size = num_streamlines -1
246
-
247
- calculate_massflows(blade_rows,True)
248
- print(x0)
249
- return calculate_error(blade_rows)
249
+ try:
250
+ calculate_massflows(blade_rows,True)
251
+ print(x0)
252
+ return calculate_error(blade_rows)
253
+ except:
254
+ blade_rows = blade_rows_backup
255
+ return np.inf # Return a high error
256
+
250
257
  # except:
251
258
  # for i in range(1,len(blade_rows)-1):
252
259
  # for j in range(self.num_streamlines):
@@ -262,9 +269,10 @@ class TurbineSpool(Spool):
262
269
 
263
270
  print('Find average P in between stages')
264
271
  if len(outlet_P) == 1:
265
- res = minimize_scalar(fun=balance_massflows,args=(self.blade_rows[:-1],self.blade_rows[0].P0,self.blade_rows[-1].P),
266
- bounds=outlet_P[0],tol=0.0001,options={'disp': True})
272
+ # x = balance_massflows(0.658,self.blade_rows[:-1],self.blade_rows[0].P0,self.blade_rows[-1].P)
273
+ res = minimize_scalar(fun=balance_massflows,args=(self.blade_rows[:-1],self.blade_rows[0].P0,self.blade_rows[-1].P),bounds=outlet_P[0],tol=0.0001,options={'disp': True},method='bounded')
267
274
  x = res.x
275
+ print(x)
268
276
  else:
269
277
  x = fmin_slsqp(func=balance_massflows,args=(self.blade_rows[:-1],self.blade_rows[0].P0,self.blade_rows[-1].P),
270
278
  bounds=outlet_P, x0=outlet_P_guess,epsilon=0.001,iter=100) # ,tol=0.001,options={'disp': True})
@@ -272,6 +280,8 @@ class TurbineSpool(Spool):
272
280
 
273
281
  # Adjust the inlet: Set the massflow
274
282
  self.blade_rows[0].massflow = np.linspace(0,1,self.num_streamlines)*self.blade_rows[1].total_massflow_no_coolant
283
+ self.blade_rows[0].total_massflow_no_coolant = self.blade_rows[1].total_massflow_no_coolant
284
+ self.blade_rows[0].total_massflow = np.linspace(0,1,self.num_streamlines)*self.blade_rows[1].total_massflow_no_coolant
275
285
  inlet_calc(self.blade_rows[0]) # adjust the inlet to match massflow
276
286
 
277
287
  if self.adjust_streamlines:
@@ -389,7 +399,7 @@ class TurbineSpool(Spool):
389
399
  json.dump(data, f, indent=4,cls=NumpyEncoder)
390
400
 
391
401
 
392
- def calculate_massflows(blade_rows:List[BladeRow],calculate_vm:bool=False):
402
+ def calculate_massflows(blade_rows:List[BladeRow],calculate_vm:bool=False,fluid:Solution=None):
393
403
  """Calculates the massflow
394
404
 
395
405
  Args:
@@ -421,15 +431,15 @@ def calculate_massflows(blade_rows:List[BladeRow],calculate_vm:bool=False):
421
431
  rotor_calc(row,upstream,calculate_vm=True)
422
432
  # Finds Equilibrium between Vm, P0, T0
423
433
  row = radeq(row,upstream)
424
- row = compute_gas_constants(row)
434
+ compute_gas_constants(row,fluid)
425
435
  rotor_calc(row,upstream,calculate_vm=False)
426
436
  elif row.row_type == RowType.Stator:
427
437
  stator_calc(row,upstream,downstream,calculate_vm=True)
428
438
  # Finds Equilibrium between Vm, P0, T0
429
439
  row = radeq(row,upstream)
430
- row = compute_gas_constants(row)
440
+ compute_gas_constants(row,fluid)
431
441
  stator_calc(row,upstream,downstream,calculate_vm=False)
432
- row = compute_gas_constants(row)
442
+ compute_gas_constants(row,fluid)
433
443
  compute_massflow(row)
434
444
  compute_power(row,upstream)
435
445
 
@@ -442,7 +452,7 @@ def calculate_massflows(blade_rows:List[BladeRow],calculate_vm:bool=False):
442
452
  row.Yp = Yp
443
453
  rotor_calc(row,upstream,calculate_vm=True)
444
454
  row = radeq(row,upstream)
445
- row = compute_gas_constants(row)
455
+ compute_gas_constants(row,fluid)
446
456
  rotor_calc(row,upstream,calculate_vm=False)
447
457
  return abs(row.eta_total - eta_total)
448
458
 
@@ -452,13 +462,13 @@ def calculate_massflows(blade_rows:List[BladeRow],calculate_vm:bool=False):
452
462
  row.Yp = 0
453
463
  stator_calc(row,upstream,downstream,calculate_vm=True)
454
464
  row = radeq(row,upstream)
455
- row = compute_gas_constants(row)
465
+ row = compute_gas_constants(row,fluid)
456
466
  stator_calc(row,upstream,downstream,calculate_vm=False)
457
- row = compute_gas_constants(row)
467
+ row = compute_gas_constants(row,fluid)
458
468
  compute_massflow(row)
459
469
  compute_power(row,upstream)
460
470
 
461
- def massflow_loss_function(exit_angle:float,index:int,row:BladeRow,upstream:BladeRow,downstream:BladeRow=None):
471
+ def massflow_loss_function(exit_angle:float,index:int,row:BladeRow,upstream:BladeRow,downstream:BladeRow=None,fluid:Solution=None):
462
472
  """Finds the blade exit angles that balance the massflow throughout the stage
463
473
 
464
474
  Args:
@@ -483,8 +493,8 @@ def massflow_loss_function(exit_angle:float,index:int,row:BladeRow,upstream:Blad
483
493
  elif row.row_type == RowType.Stator:
484
494
  row.alpha2[index] = np.radians(exit_angle)
485
495
  stator_calc(row,upstream,downstream)
486
- upstream = compute_gas_constants(upstream)
487
- row = compute_gas_constants(row)
496
+ upstream = compute_gas_constants(upstream,fluid)
497
+ row = compute_gas_constants(row,fluid)
488
498
  elif row.loss_function.loss_type == LossType.Enthalpy:
489
499
  # Search for pressure loss that results in the correct total temperature drop
490
500
  if row.row_type == RowType.Rotor:
@@ -496,8 +506,8 @@ def massflow_loss_function(exit_angle:float,index:int,row:BladeRow,upstream:Blad
496
506
  def find_yp(Yp):
497
507
  row.Yp = Yp
498
508
  rotor_calc(row,upstream)
499
- upstream = compute_gas_constants(upstream)
500
- row = compute_gas_constants(row)
509
+ upstream = compute_gas_constants(upstream,fluid)
510
+ row = compute_gas_constants(row,fluid)
501
511
  return abs(row.T0.mean() - T0_target)
502
512
  res = minimize_scalar(find_yp,bounds=[0,0.6])
503
513
  row.Yp = res.x
@@ -505,8 +515,8 @@ def massflow_loss_function(exit_angle:float,index:int,row:BladeRow,upstream:Blad
505
515
  row.Yp = 0
506
516
  row.alpha2[index] = np.radians(exit_angle)
507
517
  stator_calc(row,upstream,downstream)
508
- upstream = compute_gas_constants(upstream)
509
- row = compute_gas_constants(row)
518
+ upstream = compute_gas_constants(upstream,fluid)
519
+ row = compute_gas_constants(row,fluid)
510
520
 
511
521
 
512
522
  # if use_radeq:
@@ -516,12 +526,12 @@ def massflow_loss_function(exit_angle:float,index:int,row:BladeRow,upstream:Blad
516
526
  compute_power(row,upstream)
517
527
 
518
528
  if row.row_type!=RowType.Inlet:
519
- if row.row_type == RowType.Rotor:
520
- T3_is = upstream.T0 * (1/row.P0_P)**((row.gamma-1)/row.gamma)
521
- else:
522
- T3_is = upstream.T0 * (row.P0/row.P)**((row.gamma-1)/row.gamma)
529
+ # if row.row_type == RowType.Rotor:
530
+ T3_is = upstream.T0 * (1/row.P0_P)**((row.gamma-1)/row.gamma)
531
+ # else:
532
+ # T3_is = upstream.T0 * (row.P0/row.P)**((row.gamma-1)/row.gamma)
523
533
  a = np.sqrt(row.gamma*row.R*T3_is)
524
- T03_is = T3_is * (1+(row.gamma-1)/2*(row.Vm/a)**2)
534
+ T03_is = T3_is * (1+(row.gamma-1)/2*(row.V/a)**2)
525
535
  row.eta_total = (upstream.T0.mean() - row.T0.mean())/(upstream.T0.mean()-T03_is.mean())
526
536
 
527
537
  return np.abs(row.total_massflow*index/(len(row.massflow)-1) - row.massflow[index])